pax_global_header00006660000000000000000000000064150362404750014520gustar00rootroot0000000000000052 comment=f867a08fd279548a953b9f0b631842ae83a351e9 qatlib-25.08.0/000077500000000000000000000000001503624047500131505ustar00rootroot00000000000000qatlib-25.08.0/.github/000077500000000000000000000000001503624047500145105ustar00rootroot00000000000000qatlib-25.08.0/.github/dependabot.yml000066400000000000000000000001501503624047500173340ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "" directory: "/" schedule: interval: "weekly" qatlib-25.08.0/.github/workflows/000077500000000000000000000000001503624047500165455ustar00rootroot00000000000000qatlib-25.08.0/.github/workflows/codeql.yml000066400000000000000000000022701503624047500205400ustar00rootroot00000000000000name: "CodeQL" on: push: branches: [ "main" ] pull_request: branches: [ "main" ] permissions: contents: read jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ 'cpp' ] steps: - name: Checkout repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@b8efe4dc6ab6d31abe3ec159420d2a4916880800 with: languages: ${{ matrix.language }} # Install dependencies and build - name: Install dependencies run: sudo apt install -y automake libtool pkg-config libssl-dev libz-dev nasm libnuma-dev autoconf-archive - name: autogen run: ACLOCAL_PATH=/usr/share/aclocal ./autogen.sh - name: configure run: ./configure - name: make run: make -j - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@b8efe4dc6ab6d31abe3ec159420d2a4916880800 with: category: "/language:${{matrix.language}}" qatlib-25.08.0/.github/workflows/linux_build_gcc.yml000066400000000000000000000012001503624047500224130ustar00rootroot00000000000000name: Linux Build gcc on: push: branches: [ "main" ] pull_request: branches: [ "main" ] permissions: contents: read jobs: build: runs-on: ubuntu-latest steps: - run: sudo apt install -y automake libtool pkg-config libssl-dev libz-dev nasm libnuma-dev autoconf-archive - name: Checkout repository using checkout action v4.1.7 uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 with: repository: intel/qatlib - name: autogen run: ACLOCAL_PATH=/usr/share/aclocal ./autogen.sh - name: configure run: ./configure - name: make run: make -j qatlib-25.08.0/.github/workflows/scorecards.yml000066400000000000000000000020551503624047500214220ustar00rootroot00000000000000name: "OSSF Scorecard" on: branch_protection_rule: push: branches: [ "main" ] permissions: read-all jobs: analysis: name: Scorecards analysis runs-on: ubuntu-latest permissions: security-events: write id-token: write steps: - name: "Checkout code" uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false - name: "Run analysis" uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 with: results_file: results.sarif results_format: sarif publish_results: true - name: "Upload artifact" uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: SARIF file path: results.sarif retention-days: 5 - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0 with: sarif_file: results.sarif qatlib-25.08.0/.gitignore000066400000000000000000000015431503624047500151430ustar00rootroot00000000000000/aclocal.m4 /autom4te.cache/ /config.log /Makefile /Makefile.in /config.h /config.h.in /config.status /config.guess /config.sub /configure /install-sh /missing /libtool /m4 /ar-lib /compile /depcomp /ltmain.sh **/.deps **/.dirstamp /quickassist/utilities/service/qat.service /stamp-h1 /.libs *.la *.lo *.o *.m4 *.pc build /alg_chaining_sample /ccm_sample /chaining_sample /cipher_sample /cpa_sample_code /dc_dp_sample /dc_sample_event_notif /diffie_hellman_sample /gcm_sample /hash_file_sample /hash_sample /ipsec_sample /prime_sample /qatmgr /ssl_sample /stateful_sample /stateless_multi_op_checksum_sample /stateless_sample /symdp_sample /update_sample /algchaining_sample /dc_stateless_multi_op_sample /dc_stateless_sample /dh_sample /ec_montedwds_sample /eddsa_sample /hkdf_sample /qatlib.spec quickassist/utilities/service/qat_init.sh /sym_dp_sample /zuc_sample qatlib-25.08.0/INSTALL000066400000000000000000001136131503624047500142060ustar00rootroot00000000000000=============================================================================== =============================================================================== Reference ========= - Intel® Communications Chipset 4xxx/4xxxx Series Software for Linux* Getting Started Guide =============================================================================== Overview ========= Intel® QuickAssist Technology provides security and compression acceleration capabilities used to improve performance and efficiency across the data center. Previously existing build system has been replaced by Autotools solution in order to provide with the widely known and easy to use tool to build and install source packages. =============================================================================== Licensing ========= This product is released under the BSD-3-Clause License. Files within this project have various inbound licenses, listed below: - Dual BSD/GPLv2 License - BSD License This package also links against files with the following licenses: - OpenSSL License - ZLIB License For BSD-3-Clause license, please see the file LICENSE contained in the top level folder. For Dual BSD/GPLv2 please see the file headers of the relevant files. =============================================================================== QATlib User's Guide =================== Web-based documentation for QATlib and related components is available at: https://intel.github.io/quickassist/qatlib/index.html Using the QATlib package ======================== Note: The build instructions provided are for RPM-based Linux distributions such as Fedora, Red Hat Enterprise Linux (RHEL), CentOS, and Rocky Linux. For Debian-based distributions like Debian and Ubuntu, refer to the installation guide at: https://intel.github.io/quickassist/qatlib/install.html#installing-from-sources These instructions assume operation as a non-root user with sudo privileges. Users on other distributions may need to adapt the command-lines accordingly. Check System Prerequisites ========================== There are some prerequisites to running the software in this package. If running from a distro many of these are taken care of, if not here they are: * platform must have an Intel® Communications device installed. Supported devices: --------------------------- Driver Name | PFid | VFid --------------------------- 4xxx | 4940 | 4941 401xx | 4942 | 4943 402xx | 4944 | 4945 420xx | 4946 | 4947 --------------------------- Examples in this doc are for the 4940 device. See https://intel.github.io/quickassist/qatlib/requirements.html#supported-devices for more details of other devices. * check there's a PF device present lspci -d 8086: will return the list of devices installed, e.g. "lspci -d 8086:4940" Note: Later, after "systemctl start qat" or "make install" steps, the corresponding Virtual Function devices will also be visible and bound to the vfio-pci driver. lspci -d 8086: will list VF devices which have been created, e.g. "lspci -d 8086:4941" * firmware must be available Check that these files exist: /lib/firmware/qat_4xxx.bin or /lib/firmware/qat_4xxx.bin.xz /lib/firmware/qat_4xxx_mmp.bin or /lib/firmware/qat_4xxx_mmp.bin.xz If not, download the firmware images from linux-firmware and copy them to /lib/firmware: wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/qat_4xxx.bin wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/qat_4xxx_mmp.bin sudo mv qat_4xxx.bin /lib/firmware sudo mv qat_4xxx_mmp.bin /lib/firmware See Supported Devices table linked above for firmware filenames for other devices. If firmware is not present on linux-firmware please contact qat-linux@intel.com On updating any firmware files run "sudo dracut --force" to update initramfs. * kernel driver must be running Use "lsmod | grep qat" to check that these kernel modules are running: intel_qat qat_4xxx (See Supported Devices table for other qat module names) They should load by default if using any of the following: * A recent Linux kernel (see https://intel.github.io/quickassist/qatlib/requirements.html#kernel-firmware-requirements ) * Fedora 36+ (39+ for 420xx) * RHEL 8.4+ (for compression use 9.0+) * each PF device must be bound to a qat kernel module Use ls to show the BDFs of each bound PF, e.g. "cd /sys/bus/pci/drivers; ls 4xxx;" * BIOS settings Intel VT-d and SR-IOV must be enabled in the platform BIOS. Consult your platform guide on how to do this. If using an Intel BKC these usually default to on, you can verify by rebooting, entering F2 on the console to get to the BIOS menus and checking these are enabled: EDKII Menu -> Socket Configuration -> IIO Configuration -> Intel VT for Directed I/O (VT-d) -> Intel VT for Directed I/O EDKII Menu -> Platform Configuration -> Miscellaneous Configuration -> SR-IOV Support * GRUB Configuration Updates - Step 1: Edit the GRUB configuration file. * Open the file with a text editor, for example, `sudo vi /etc/default/grub`. - Step 2: Add the necessary parameters to the `GRUB_CMDLINE_LINUX` entry. * Enable Intel IOMMU by adding "intel_iommu=on". The line should look like: `GRUB_CMDLINE_LINUX="... intel_iommu=on"`. * Add VFIO-PCI device IDs. For a device with the ID 8086:4941, add "vfio-pci.ids=8086:4941". The line should look like: `GRUB_CMDLINE_LINUX="... vfio-pci.ids=8086:4941"`. * Refer to the list of supported devices at https://intel.github.io/quickassist/qatlib/requirements.html#supported-devices for other device IDs. - Step 3: Update the GRUB configuration and reboot the system. * Generate a new GRUB configuration file: `sudo grub2-mkconfig -o /etc/grub2-efi.cfg`. * Reboot the system to apply the changes: `sudo shutdown -r now`. =============================================================================== Compilation and installation - quickstart instructions ====================================================== Note, more detailed instructions in following section. --------------------------------------------------------------------------- Summary if running from Fedora 34+: # Install qatlib sudo dnf install -y qatlib # Add your user to qat group and re-login to make the change effective sudo usermod -a -G qat `whoami` sudo su -l $USER # Enable qat service and make persistent after reboot sudo systemctl enable qat sudo systemctl start qat # The library is now ready to use with your application # You can also follow these steps to try out a pre-built sample # application: # Install qatlib-tests rpm sudo dnf install -y qatlib-tests # cpa_sample_code requires a minimum of 500MB to run its compression demo # To increase amount of locked memory for your user to 500MB: sudo cp /etc/security/limits.conf /etc/security/limits.conf.qatlib_bak echo `whoami` - memlock 500000 | sudo tee -a /etc/security/limits.conf > /dev/null # Re-login in order to make the change effective sudo su -l $USER # Run it! (takes several minutes to complete) cpa_sample_code ---------------------------------------------------------------------------- Summary if building from sources. # Install dependencies sudo dnf install -y gcc systemd-devel automake autoconf autoconf-archive libtool sudo dnf install -y pkg-config openssl-devel zlib-devel nasm numactl-devel # Clone QATlib into ~/qatlib, i.e. in your home dir cd ~ git clone https://github.com/intel/qatlib.git # If instead you upgrade an earlier clone, follow the steps in # "Remove the libraries and cleanup" before fetching. # Build and install library cd qatlib ./autogen.sh ./configure --enable-service make -j sudo make install # Add your user to the "qat" group which was automatically # created by --enable-service. Then re-login to make the change # effective, this will also move you back into your home directory sudo usermod -a -G qat `whoami` sudo su -l $USER # The library is now ready to use with your application # You can also follow these steps to try out a sample application: # cpa_sample_code requires a minimum of 500MB to run its compression demo # To increase the amount of locked memory for your user to 500MB: sudo cp /etc/security/limits.conf /etc/security/limits.conf.qatlib_bak echo `whoami` - memlock 500000 | sudo tee -a /etc/security/limits.conf > /dev/null # Re-login in order to make the change effective sudo su -l $USER # Compression sample code expects to find data files at a known location, # so call the samples-install target to put them there cd qatlib sudo make samples-install # Run it! (takes several minutes to complete) cpa_sample_code # No need to leave the samples installed, so cleanup sudo make samples-uninstall =============================================================================== Compilation and installation - detailed instructions ==================================================== 1) Install compilation dependencies If running from a distro most or all of QATlib depends are taken care of, if not use your OS-specific commands to install the following: tools: gcc make autotools (automake, autoconf, autoconf-archive, libtool) pkg-config systemd-devel nasm Note: If nasm compiler is unavailable see --disable-fast-crc-in-assembler option in Configuration section below libraries: openssl-devel zlib-devel numactl-devel ---------------------------------------------------------------------------- 2) Download package and configure it To generate configure script - call: ./autogen.sh To setup the default build configuration - call: ./configure Full list of configuration options can be found under "Configuration options" section below or by calling: ./configure --help To run in Managed Mode, enable qat service. This can be done automatically during installation by calling: ./configure --enable-service In some case, e.g. containers, it may be preferable to build without the qat service, to avoid a dependency on systemd. This is referred to as Standalone Mode. In this case use: ./configure --enable-systemd=no See also the "Configuration and tuning section" below. ---------------------------------------------------------------------------- 3) Configure the system Create the "qat" group. qat.service requires "qat" group This is automatically created by configure --enable-service so this step can be skipped. To manually create the group: sudo groupadd qat Add your user to "qat" group. To be able to use QATlib functionalities as non root user, user must be part of the qat group. To add your user to the qat group sudo usermod -a -G qat Set maximum amount of locked memory for your user. The maximum amount of locked memory should be set correctly by defining memlock limit which is 16MB per VF plus whatever the application requires. For cpa_sample_code running crypto at least 200MB are required, if running compression set at least 500MB. To set 500MB add a line like this - memlock 500000 in the file /etc/security/limits.conf. After making user changes it's necessary to re-login for them to take effect sudo su -l $USER ---------------------------------------------------------------------------- 4) Compile and install the library Build and install: make -j sudo make install If the service was not configured to start automatically, by using --enable-service then it will need to be started. To start it and make persistent after reboot: systemctl enable qat systemctl start qat ---------------------------------------------------------------------------- 5) Run sample application Sample code is built by default. Information on running the performance sample-code is at ./quickassist/lookaside/access_layer/src/sample_code/README.txt Examples: Compression sample code expects to find data files at a known location, so call the samples-install target to put them there: sudo make samples-install Run all performance tests: ./cpa_sample_code Symmetric crypto tests only: ./cpa_sample_code runTests=1 Asymmetric crypto RSA tests only: ./cpa_sample_code runTests=2 Compression tests only: ./cpa_sample_code runTests=32 Examples of other samples for a specific functionality: Run just one symmetric cipher operation: ./cipher_sample Run just one compress/decompress operation: ./dc_stateless_sample Run just one chaining hash then compress operation: ./chaining_sample ---------------------------------------------------------------------------- 6) Remove the libraries and cleanup Note: These make commands should be run using the Makefiles that were generated by the original call to the configure script. I.e. there is no need to call ./configure again. If it is ever called again it must be called with exactly the same options as were originally used so whatever was installed can be correctly cleaned up. Uninstall: sudo make samples-uninstall #if samples installed sudo systemctl stop qat sudo make uninstall Clean up: make clean make distclean ---------------------------------------------------------------------------- 7) Configuration and tuning There are parameters which can be tweaked to optimize for an application's workload which might work in two modes: managed (when qat service is enabled) and standalone (without service) MANAGED MODE In Managed mode, qatmgr manages allocation of the VF resources to each process on process startup. A sample config file can be found in quickassist/utilities/service/qat. it can be copied to /etc/sysconfig/qat and used to set the following parameters: POLICY Indicates how many VFs will be assigned to each process. POLICY=0 or not set (Default) One VF from each PF will be assigned to each process. POLICY=N N VFs will be assigned to each process. ServicesEnabled Tells the kernel driver which Services to enable on PFs. All VFs on a PF have the same service. Unset (Default) Every even-numbered PF has sym;asym, every odd-numbered PF has dc. I.e. PF0, PF2 ... support crypto and PF1, PF3 ... support data compression. ServicesEnabled=sym All PFs, and so all VFs, have sym only. ServicesEnabled=asym All PFs, and so all VFs, have asym only. ServicesEnabled=sym;asym All PFs, and so all VFs, have sym;asym only. ServicesEnabled=dc All PFs, and so all VFs, have dc only. ServicesEnabled=sym;dc All PFs, and so all VFs, have sym;dc only. ServicesEnabled=asym;dc All PFs, and so all VFs, have asym;dc only. ServicesEnabled=dcc All PFs, and so all VFs, have dc instances enabled for chaining operations (hash then compress) only. Note: Throughput is lower than dc. Only use this setting when chaining is needed. The following examples are based on a one-socket QAT 4xxx platform with 4 PFs, each PF has 16 VFs. Each VF enabled for sym, asym, dc has 4 instances. Each VF enabled for mixed services like sym;asym, sym;dc, asym;dc has 2 instances of each type, so sym;asym has 2 cy instances (note that cy instance is and sym and asym together), sym;dc has 2 sym instances and 2 dc instances, asym;dc has 2 asym instances and 2 dc instances. An instance is an abstraction used on the APIs to identify a unique path to the hardware. In a multi-threaded process, typically at least one instance is needed per thread. Usage Flexibility On default configuration, with neither param set, each process will be allocated one VF from each PF, so 4 VFs. It will have 2 sym;asym VFs, so 4 sym instances and 4 asym instances and 2 dc VFs, so 8 dc instances. The maximum number of processes is 16. With N sockets, the maximum number of processes is still 16, each will have instances as above * N. Scalability and flexibility POLICY=2. ServicesEnabled unset. Each process will be allocated 2 VFs, 1 with sym;asym, 1 with dc. So each will have 2 sym instances, 2 asym instance and 4 dc instances. The maximum number of processes is 32. 16 VFs * 4 PFs / POLICY. N sockets will have 32 * N. Scalability and flexibility for crypto symmetric or asymmetric plus compression. POLICY=1. ServicesEnabled sym;dc or asym;dc. Each process will be allocated 1 VF, with sym;dc or asym;dc. So each will have 2 sym or asym instances and 2 dc instances. The maximum number of processes is 64. 16 VFs * 4 PFs / POLICY. N sockets will have 64 * N. Crypto-only scalability POLICY=1. ServicesEnabled=sym;asym. All VFs have sym;asym. Each process will be allocated 1 VF so will have 2 sym instances and 2 asym instances. The maximum number of processes is 64. 16 VFs * 4 PFs. N sockets will have 64 * N. Note: This configuration also provides optimized-throughput for asym. Crypto-only optimized-throughput POLICY=0. ServicesEnabled=sym;asym. All VFs have sym;asym. Each process will be allocated 1 VF per PF which will have 2 sym instances and 2 asym instances, so each process will have (2 * number of PFs) of each instance type. The maximum number of processes is 16. Sym-only optimized-throughput POLICY=0. ServicesEnabled=sym. All VFs have sym. Each process will be allocated 1 VF per PF which will have 4 sym instances, so each process will have (4 * number of PFs) instances. The maximum number of processes is 16. Compression-only scalability POLICY=1. ServicesEnabled=dc. All VFs have dc. Each process will be allocated 1 VF so will have 4 dc instances. The maximum number of processes is 64. 16 VFs * 4 PFs. N sockets will have 64 * N. Compression-only optimized-throughput POLICY=0. ServicesEnabled=dc. All VFs have dc. Each process will be allocated 1 VF per PF which will have 4 dc instances, so each process will have (4 * number of PFs) instances. The maximum number of processes is 16. Compression chaining scalability: POLICY=1. ServicesEnabled=dcc. All VFs have dc with sym capabilities but only for chaining operations. Each process will be allocated 1 VF so will have 4 dc instances. The maximum number of processes is 64. 16 VFs * 4 PFs. N sockets will have 64 * N. STANDALONE MODE In standalone mode, there is no qat service running. This is the preferred way to run on containers where a subset of VFs are explicitly passed through and so no qatmgr managed resource mgr is needed. Each standalone process assumes VF devices which it can't open are in use by another process and looks for unopened VFs. In standalone mode /quickassist/utilities/service/qat_init.sh can be called on the host to bind VFs to vfio-pci and to enable services based on the ServicesEnabled param. In this mode the POLICY parameter should not be set in /etc/sysconfig/qat, if it is set it will be ignored, instead an environment variable QAT_POLICY can be set. Please note that the QAT_POLICY=0 is not a valid setting in standalone mode. The valid setting range starts from 1 and goes up to max PFs * 16. Note1: The ServicesEnabled configuration requires Linux kernel v6.0 or later and applies to all PFs on the platform. The script below can be used to view the PF/VF service config. Config can also be set per PF, follow the instructions provided in the following link: https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-driver-qat. If an alternative config is set per PF following those instructions, then neither ServicesEnabled nor POLICY should be set in /etc/sysconfig/qat, else it will not be deterministic which instances a process receives. RUNNING IN A VIRTUAL MACHINE / GUEST When passing VFs to a guest, the BDFs on the guest should facilitate qatlib recognizing whether VFs are from the same PF or not. So the libvirt XML file should specify that VFs from the same host (same domain + bus) are assigned to a common (domain + bus) on the guest, which is different to the (domain + bus) used for VFs from other PFs. e.g. if VF on host 0000:6b:00.1 maps to :00.1 on guest then 0000:6b:00.6 should map to :00.6 and 0000:7a:00.3 should map to :00.3 The first VF, mapped to function='0x0', should also set multifunction='on'. Sufficient VFs should be passed from the host to the guest to satisfy the type of services and number of processes needed by the guest. See here for more information on host configuration: https://intel.github.io/quickassist/qatlib/configuration.html# If using the default kernel configuration, at least 2 VFs are needed per process so that the process has both CY and DC instances. Set either POLICY=0 or POLICY=2 (or 4, 6, ...) in /etc/sysconfig/qat on the guest and restart qatmgr. SCRIPT TO VIEW QAT PF/VF SERVICE CONFIG ------------------------------------------------------------------------ #!/bin/bash printf "%-13s | %-5s | %-12s | %-12s | %-10s\n" "VFIO GROUP" "NODE" \ "PF BDF" "VF BDF" "SERVICES" echo "--------------------------------------------------------------" for vfio_group in /dev/vfio/*; do if [ $vfio_group = "/dev/vfio/vfio" ]; then continue fi group=${vfio_group##*/} # assume one bdf per iommu group bdf=$(ls /sys/kernel/iommu_groups/$group/devices/) vendor=$(cat /sys/kernel/iommu_groups/$group/devices/$bdf/vendor) node=$(cat /sys/kernel/iommu_groups/$group/devices/$bdf/numa_node) did=$(cat /sys/kernel/iommu_groups/$group/devices/$bdf/device) if [ "$vendor" != "0x8086" ]; then continue fi if [ "$did" != "0x4941" ] && [ "$did" != "0x4943" ] && [ "$did" != "0x4945" ] && [ "$did" != "0x4947" ]; then continue fi regex='([a-z0-9]+):([a-z0-9]+):.*' [[ $bdf =~ $regex ]] pf_domain=${BASH_REMATCH[1]} pf_bus=${BASH_REMATCH[2]} pf_bdf="$pf_domain:$pf_bus:00.0" printf "%-15s %-7s %-14s %-14s %-10s\n" "$vfio_group" "$node" \ "$pf_bdf" "$bdf" \ "$(cat /sys/bus/pci/devices/$pf_bdf/qat/cfg_services)" done ------------------------------------------------------------------------ Note2: As the library assumes that all VFs from the same PF have the same services, take care when passing VFs through to a VM that all VFs from the same Host PF are passed through with a common Domain/Bus. =============================================================================== Full list of Configuration options ================================== Typical examples of how to update configuration options are as follows: ./configure ICP_ANY_FLAG=value or ./configure --enable-something If it is required to use more than one flag at once: ./configure ICP_ANY_PATH=path ICP_ANY_NAME=name --enable-something Features flags: Enables or disables the additional features supported by the package --disable-option-checking Ignores unrecognized configure options when run along with it. --disable-FEATURE Does not include FEATURE (same as --enable-FEATURE=no). --enable-FEATURE[=ARG] Includes FEATURE [ARG=yes]. --enable-silent-rules Less verbose build output (undo: "make V=1"). --disable-silent-rules Verbose build output (undo: "make V=0"). --enable-dependency-tracking Does not reject slow dependency extractors. --disable-dependency-tracking Speeds up one-time build --enable-icp-debug Enables debugging. --disable-param-check Disables parameters checking in the top-level APIs (Use for performance optimization). --disable-stats Disables statistic collection (Use for performance optimization). --disable-fast-crc-in-assembler Force use of C code instead of faster assembler implementation of CRC for DC integrityCrc feature. Not recommended unless nasm assembler compiler is unavailable. --enable-icp-log-syslog Enables debugging messages to be outputted to the system log instead of standard output. --enable-icp-trace Enables tracing for the Cryptography API. --enable-dc-error-simulation Enables Data Compression Error Simulation. --enable-hb-error-simulation Enables Heartbeat Error Simulation. --enable-legacy-lib-names Enables legacy names for libraries. --enable-systemd  Enable systemd support. Set to No to remove dependency on systemd [default=yes] Note: --enable-service should not be used in this case. --enable-service Automatically creates "qat" group and enables systemd service during installation. --enable-legacy-algorithms Enable deprecated legacy crypto algorithms. See the README.md for the list of algorithms which are deprecated by default. --enable-icp-thread-specific-usdm USDM allocates and handles memory specific to threads. (For multi-thread apps, allocated memory information will be maintained separately for each thread; employs thread local storage feature i.e. TLS. It avoids locking that was needed when a global data structure being used in non thread-specific implementation). NOTE: Any memory allocated by a thread must be freed by the same thread. If it passes the memory to other threads for use, it's responsible for any synchronisation between those threads. The thread which did the allocation must live until after all threads using the memory are finished with it, as any thread memory not yet freed may be cleaned up on termination of the thread. --enable-icp-without-qp-submission-lock This allows for the removal of Queue Pair (QP) submission locks and is designed to optimize performance in environments where QPs assigned to one thread are not shared by another thread. In these scenarios, the frequent invocation of mutex_lock/unlock during hardware request submissions is unnecessary and can affect performance. By enabling this flag, the locks around QP submissions are eliminated, thus reducing the cost of offload. As QPs are assigned to instances, only enable this if instances are not shared across threads, else undefined behaviour could occur. --enable-treat-crc-from-comp-engine-as-error When the device calculates a CRC over the uncompressed data, it usually uses the decompression engine to do the CRC calculation. In compression operation cases where the stored block is returned e.g. due to input data being incompressible, the returned CRC is calculated using the compression engine, which should give exactly the same CRC as the decompression engine would. Enabling this option causes any case where the CRC is calculated by the compression engine to be reported as a CPA_DC_E2E_NO_DECOMPRESSION error, rather than as a successful operation. Please see below link for firmware needed to support this feature. https://intel.github.io/quickassist/RN/In-Tree/in_tree_firmware_RN.html#qat-2-0-in-tree-kernel-requirements MAX_MR Number of Miller Rabin rounds for prime operations. Setting this to a smaller value reduces the memory usage required by the driver. Type: value Default value: 50 =============================================================================== Common issues ============= Additional details are available at: https://intel.github.io/quickassist/qatlib/index.html Issue: errors like these are seen in system logs: * 4xxx 0000:6b:00.0: IOMMU should be enabled for SR-IOV to work * vfio-pci: probe of 0000:6b:00.1 failed with error -22 Likely cause: Check VT-d, SR-IOV and intel_iommu settings are correct as described above. One way to check that is to run: dmesg | grep "Virtualization Technology" If you get output similar to below, everything is ready, otherwise there is something misconfigured. "[57.503644] DMAR: Intel(R) Virtualization Technology for Directed I/O" Issue: On running sample code: qaeMemInit started Open failed on /dev/vfio/15 No device found ADF_UIO_PROXY err: icp_adf_userProcessToStart: Failed to start SSL... Likely cause: Incorrect permissions. Use "id " to verify the user is in the qat group and logout/login to the shell to ensure group changes take effect. Issue: On running sample code: qaeMemInit started No device found ADF_UIO_PROXY err: icp_adf_userProcessToStart: Failed to start SSL... Likely cause: (1) No PF driver available. Check that PFs are available and bound to qat_4xxx: (See Supported Devices table for other devices) sudo lspci -vvd:4940 | grep "Kernel driver in use". Upgrade to a recent Linux Kernel. (2) No VFs available. Check VFs are available and bound to vfio-pci sudo lspci -vvd:4941 | grep "Kernel driver in use" Issue: On running ./autogen.sh following warning appears: aclocal: warning: couldn't open directory 'm4': No such file or dir... Likely cause: This warning can be ignored, as is resolved subsequently Issue: After upgrading to new version following error may be received: This qatlib v21.8 received response from incompatible qatmgr v0.0 Likely cause: if qat service was already running during upgrade, it won't be restarted automatically. After upgrading ensure that qat service is restarted. Issue: "DC Instances are not present" error when trying to run compression operations, e.g. using "cpa_sample_code runTests=32" Likely cause: QAT driver in Linux kernel before v5.17 doesn't support compression service. Upgrade to a later kernel. Issue: "Could not open corpus file: /usr/local/share/qat/calgary" seen when running compression sample code. Likely cause: sample code data files not installed at the expected location Run: sudo make samples-install Issue: Error "memFreeNUMA:1313 Address to be freed cannot be NULL" seen when running cpa_sample_code. Also dmesg | grep MEMLOCK shows messages like this: "hvfio_pin_pages_remote: RLIMIT_MEMLOCK (204800000) exceeded" Likely cause: Not enough locked memory. Increase the amount of locked memory for your user – see instructions above. After updating re-login so the changes take effect: sudo su -l $USER Issue: error on make install or on systemctl start qat "Job for qat.service failed because the control process exited with error code" System logs (dmesg) show QAT kernel module failed with error like: "4xxx 0000:6b:00.0: enabling device (0140 -> 0142) QAT: authentication error (FCU_STATUS = 0x3),retry = 0 4xxx 0000:6b:00.0: Failed to load MMP 4xxx 0000:6b:00.0: Failed to load acceleration FW 4xxx 0000:6b:00.0: Resetting device qat_dev0 4xxx: probe of 0000:6b:00.0 failed with error -14" Likely cause: firmware files not present in initramfs on module loading early in boot process. Fix: First make sure you have the firmware installed in /lib/firmware, see pre-requisites section above. In order to load the firmware, the driver must be reloaded, i.e. for 4xxx driver run: "sudo rmmod qat_4xxx; sudo modprobe qat_4xxx; sudo systemctl start qat". For a persistent change (on future reboots) run "sudo dracut --force". See Supported Devices table for other driver names. Issue: X kernel taint flag seen on SUSE from SLES15-SP4 onwards "intel_qat: externally supported module,setting X kernel taint flag." "qat_4xxx: externally supported module,setting X kernel taint flag." Likely cause: This is normal on load of the kernel driver in a SUSE distro. See explanation for X flag here: https://www.suse.com/support/kb/doc/?id=000016321 It indicates that the modules are supported by external parties, in this case Intel. Fix: None necessary, qatlib can be used as normal despite this message. Issue: make: *** No rule to make target 'sample-uninstall'. Stop. Likely cause: There was a name change between 21.11 and 22.07, note the extra 's'. Sorry if it causes confusion. Fix: sudo make samples-uninstall Issue: on Ubuntu on make install, this error may be seen: “Failed to start qat.service: Unit qat.service not found.” Likely cause: The qat.service file is not installed by Ubuntu in the expected directory Fix: Explicitly configure the systemd path to where Ubuntu has installed the qat.service, e.g. ./configure --enable-service systemdsystemunitdir=/lib/systemd/system/ =============================================================================== Legal/Disclaimers =================== INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL(R) PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER, AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT. Intel products are not intended for use in medical, life saving, life sustaining, critical control or safety systems, or in nuclear facility applications. Intel may make changes to specifications and product descriptions at any time, without notice. (C) Intel Corporation 2022 * Other names and brands may be claimed as the property of others. =============================================================================== qatlib-25.08.0/LICENSE000066400000000000000000000031041503624047500141530ustar00rootroot00000000000000 SPDX-License-Identifier: BSD-3-Clause Copyright(c) 2007-2025 Intel Corporation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. qatlib-25.08.0/Makefile.am000066400000000000000000000526221503624047500152130ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2022 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ ACLOCAL_AMFLAGS = -Im4 noinst_LTLIBRARIES = libosal.la libosal_la_SOURCES = \ quickassist/utilities/osal/src/linux/user_space/OsalSemaphore.c \ quickassist/utilities/osal/src/linux/user_space/OsalThread.c \ quickassist/utilities/osal/src/linux/user_space/OsalMutex.c \ quickassist/utilities/osal/src/linux/user_space/OsalSpinLock.c \ quickassist/utilities/osal/src/linux/user_space/OsalAtomic.c \ quickassist/utilities/osal/src/linux/user_space/OsalServices.c \ quickassist/utilities/osal/src/linux/user_space/OsalUsrKrnProxy.c \ quickassist/utilities/osal/src/linux/user_space/OsalCryptoInterface.c libosal_la_CFLAGS = -I$(srcdir)/quickassist/utilities/osal/src/linux/user_space \ -I$(srcdir)/quickassist/utilities/osal/src/linux/user_space/include \ -I$(srcdir)/quickassist/utilities/osal/include \ -DOSAL_ENSURE_ON \ -Wno-deprecated-declarations \ $(COMMON_FLAGS) noinst_LTLIBRARIES += libadf.la libadf_la_SOURCES = \ quickassist/lookaside/access_layer/src/qat_direct/io/adf_process_proxy.c \ quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_cfg.c \ quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_device.c \ quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_ETring_mgr_dp.c \ quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_init.c \ quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_ring.c \ quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_transport_ctrl.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_cfg.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_ring.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_user_bundles.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_user_proxy.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr_client.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr_lib.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_log.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_lib.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_proto.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_vf_msg.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_vfio_pf.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_mgr_lib.c libadf_la_CFLAGS = -I$(srcdir)/quickassist/utilities/libusdm_drv \ -I$(srcdir)/quickassist/utilities/osal/include \ -I$(srcdir)/quickassist/utilities/osal/src/linux/user_space/include \ -I$(srcdir)/quickassist/include \ -I$(srcdir)/quickassist/include/lac \ -I$(srcdir)/quickassist/qat/drivers/crypto/qat/qat_common \ -I$(srcdir)/quickassist/lookaside/access_layer/src/common/include \ -I$(srcdir)/quickassist/lookaside/access_layer/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio \ -D USER_SPACE \ $(COMMON_FLAGS) sbin_PROGRAMS = qatmgr qatmgr_SOURCES = \ quickassist/utilities/qat_mgr/qat_mgr.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr_lib.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_mgr_lib.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_log.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_proto.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_vf_msg.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_lib.c \ quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_vfio_pf.c qatmgr_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio \ -I$(srcdir)/quickassist/lookaside/access_layer/include \ -I$(srcdir)/quickassist/include \ -I$(srcdir)/quickassist/utilities/osal/include \ -I$(srcdir)/quickassist/utilities/osal/src/linux/user_space/include \ -I$(srcdir)/quickassist/qat/drivers/crypto/qat/qat_common \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include \ -D USER_SPACE \ $(COMMON_FLAGS) qatmgr_LDADD = $(PTHREAD_LIBS) -lnuma lib_LTLIBRARIES = lib@LIBUSDMNAME@.la lib@LIBUSDMNAME@_la_SOURCES = \ quickassist/utilities/libusdm_drv/user_space/vfio/qae_mem_utils_vfio.c \ quickassist/utilities/libusdm_drv/user_space/qae_mem_utils_common.c \ quickassist/utilities/libusdm_drv/user_space/vfio/qae_mem_hugepage_utils_vfio.c if ICP_THREAD_SPECIFIC_USDM_AC lib@LIBUSDMNAME@_la_SOURCES += \ quickassist/utilities/libusdm_drv/user_space/qae_mem_multi_thread_utils.c else lib@LIBUSDMNAME@_la_SOURCES += \ quickassist/utilities/libusdm_drv/user_space/qae_mem_common.c endif lib@LIBUSDMNAME@_la_CFLAGS = -I$(srcdir)/quickassist/utilities/libusdm_drv \ -I$(srcdir)/quickassist/utilities/libusdm_drv/include \ -I$(srcdir)/quickassist/utilities/libusdm_drv/user_space \ $(COMMON_FLAGS) lib@LIBUSDMNAME@_la_LDFLAGS = -version-info $(LIBUSDM_VERSION) \ $(COMMON_LDFLAGS) \ -export-symbols-regex '^(qae)' if !USE_CCODE_CRC # Creating CRC libs from asm files using nasm with automake-like output libcrc_SOURCES_DIR = quickassist/lookaside/access_layer/src/common/compression/ %.lo: @echo " CCAS $(libcrc_SOURCES_DIR)$@" @$(LIBTOOL) --mode=compile --quiet \ nasm -f elf64 -D LINUX -X gnu $(top_srcdir)/$(libcrc_SOURCES_DIR)$(@:.lo=.S) -I$(top_srcdir)/$(libcrc_SOURCES_DIR) -o $@ -prefer-non-pic endif lib_LTLIBRARIES += lib@LIBQATNAME@.la lib@LIBQATNAME@_la_SOURCES = \ quickassist/lookaside/access_layer/src/common/compression/dc_capabilities.c \ quickassist/lookaside/access_layer/src/common/compression/dc_buffers.c \ quickassist/lookaside/access_layer/src/common/compression/dc_chain.c \ quickassist/lookaside/access_layer/src/common/compression/dc_datapath.c \ quickassist/lookaside/access_layer/src/common/compression/dc_dictionary.c \ quickassist/lookaside/access_layer/src/common/compression/dc_dp.c \ quickassist/lookaside/access_layer/src/common/compression/dc_header_footer.c \ quickassist/lookaside/access_layer/src/common/compression/dc_header_footer_lz4.c \ quickassist/lookaside/access_layer/src/common/compression/dc_session.c \ quickassist/lookaside/access_layer/src/common/compression/dc_stats.c \ quickassist/lookaside/access_layer/src/common/compression/dc_err_sim.c \ quickassist/lookaside/access_layer/src/common/compression/dc_ns_datapath.c \ quickassist/lookaside/access_layer/src/common/compression/dc_ns_header_footer.c \ quickassist/lookaside/access_layer/src/common/compression/dc_crc32.c \ quickassist/lookaside/access_layer/src/common/compression/dc_crc64.c \ quickassist/lookaside/access_layer/src/common/compression/dc_xxhash32.c \ quickassist/lookaside/access_layer/src/common/compression/icp_sal_dc_err_sim.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_control_path.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_data_path.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_interface_check.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_stats.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/dsa/lac_dsa.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/dsa/lac_dsa_interface_check.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_common.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_montedwds.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_nist_curves.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecdh.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecdsa.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecsm2.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_kpt_ecdsa.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/large_number/lac_ln.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/large_number/lac_ln_interface_check.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_mmp.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_qat_comms.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_utils.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/prime/lac_prime.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/prime/lac_prime_interface_check.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_control_path.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_decrypt.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_encrypt.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_interface_check.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_keygen.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_stats.c \ quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_kpt_rsa_decrypt.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/drbg/lac_sym_drbg_api.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/key/lac_sym_key.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_alg_chain.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_api.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_auth_enc.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_cb.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_cipher.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_compile_check.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_dp.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_hash.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_partial.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_queue.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_stats.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/nrbg/lac_sym_nrbg_api.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_cipher.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_constants_table.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_hash.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_key.c \ quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_hash_sw_precomputes.c \ quickassist/lookaside/access_layer/src/common/crypto/kpt/provision/lac_kpt_provision.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_compression.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_compression_capabilities.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_create_services.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_ctrl_services.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_list.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_rl_stubs.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_crypto.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_dc_chain.c \ quickassist/lookaside/access_layer/src/common/ctrl/sal_instances.c \ quickassist/lookaside/access_layer/src/common/qat_comms/sal_qat_cmn_msg.c \ quickassist/lookaside/access_layer/src/common/utils/lac_buffer_desc.c \ quickassist/lookaside/access_layer/src/common/utils/lac_log_message.c \ quickassist/lookaside/access_layer/src/common/utils/lac_mem.c \ quickassist/lookaside/access_layer/src/common/utils/lac_mem_pools.c \ quickassist/lookaside/access_layer/src/common/utils/lac_sw_responses.c \ quickassist/lookaside/access_layer/src/common/utils/lac_sync.c \ quickassist/lookaside/access_layer/src/common/utils/sal_service_state.c \ quickassist/lookaside/access_layer/src/common/utils/sal_statistics.c \ quickassist/lookaside/access_layer/src/common/utils/sal_misc_error_stats.c \ quickassist/lookaside/access_layer/src/common/utils/sal_string_parse.c \ quickassist/lookaside/access_layer/src/common/utils/sal_user_process.c \ quickassist/lookaside/access_layer/src/common/utils/sal_versions.c \ quickassist/lookaside/access_layer/src/common/device/sal_dev_info.c \ quickassist/lookaside/access_layer/src/user/sal_user.c \ quickassist/lookaside/access_layer/src/user/sal_user_congestion_mgmt.c \ quickassist/lookaside/access_layer/src/user/sal_user_dyn_instance.c if USE_CCODE_CRC lib@LIBQATNAME@_la_SOURCES += \ quickassist/lookaside/access_layer/src/common/compression/dc_crc_base.c endif lib@LIBQATNAME@_la_CFLAGS = -I$(srcdir)/quickassist/utilities/libusdm_drv \ -I$(srcdir)/quickassist/utilities/osal/include \ -I$(srcdir)/quickassist/utilities/osal/src/linux/user_space/include \ -I$(srcdir)/quickassist/include \ -I$(srcdir)/quickassist/include/lac \ -I$(srcdir)/quickassist/include/dc \ -I$(srcdir)/quickassist/include/rl \ -I$(srcdir)/quickassist/qat/drivers/crypto/qat/qat_common \ -I$(srcdir)/quickassist/lookaside/access_layer/src/common/compression/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/common/crypto/sym/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/common/crypto/asym/include \ -I$(srcdir)/quickassist/lookaside/firmware/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/common/include \ -I$(srcdir)/quickassist/lookaside/access_layer/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio \ -D USER_SPACE \ -D LAC_BYTE_ORDER=__LITTLE_ENDIAN \ $(COMMON_FLAGS) lib@LIBQATNAME@_la_LIBADD = libosal.la libadf.la lib@LIBUSDMNAME@.la -lcrypto -lnuma if !USE_CCODE_CRC lib@LIBQATNAME@_la_LIBADD += crc32_gzip_refl_by8.lo crc64_ecma_norm_by8.lo endif lib@LIBQATNAME@_la_LDFLAGS = -version-info $(LIBQAT_VERSION) \ $(COMMON_LDFLAGS) \ -export-symbols-regex '^(cpa|icp_sal)' pkgincludedir = $(includedir)/qat pkginclude_HEADERS = \ quickassist/include/cpa.h \ quickassist/include/cpa_dev.h \ quickassist/include/cpa_types.h \ quickassist/include/lac/cpa_cy_common.h \ quickassist/include/lac/cpa_cy_dh.h \ quickassist/include/lac/cpa_cy_drbg.h \ quickassist/include/lac/cpa_cy_dsa.h \ quickassist/include/lac/cpa_cy_ecdh.h \ quickassist/include/lac/cpa_cy_ecdsa.h \ quickassist/include/lac/cpa_cy_ecsm2.h \ quickassist/include/lac/cpa_cy_ec.h \ quickassist/include/lac/cpa_cy_im.h \ quickassist/include/lac/cpa_cy_key.h \ quickassist/include/lac/cpa_cy_kpt.h \ quickassist/include/lac/cpa_cy_ln.h \ quickassist/include/lac/cpa_cy_nrbg.h \ quickassist/include/lac/cpa_cy_prime.h \ quickassist/include/lac/cpa_cy_rsa.h \ quickassist/include/lac/cpa_cy_sym_dp.h \ quickassist/include/lac/cpa_cy_sym.h \ quickassist/include/dc/cpa_dc.h \ quickassist/include/dc/cpa_dc_dp.h \ quickassist/include/dc/cpa_dc_chain.h \ quickassist/include/dc/cpa_dc_capabilities.h \ quickassist/include/rl/cpa_rl.h \ quickassist/lookaside/access_layer/include/icp_sal_congestion_mgmt.h \ quickassist/lookaside/access_layer/include/icp_sal_poll.h \ quickassist/lookaside/access_layer/include/icp_sal_user.h \ quickassist/lookaside/access_layer/include/icp_sal.h \ quickassist/lookaside/access_layer/include/icp_sal_versions.h \ quickassist/utilities/libusdm_drv/qae_mem.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = qatlib.pc libqat.pc libusdm.pc if HAVE_SYSTEMD systemdsystemunit_DATA = quickassist/utilities/service/qat.service endif systemd_scriptsdir = $(sbindir) dist_systemd_scripts_SCRIPTS = quickassist/utilities/service/qat_init.sh install-data-hook: if SERVICE_AC @if [ "$(shell id -u)" == 0 ]; then \ /usr/sbin/groupadd qat 2> /dev/null || :; \ systemctl daemon-reload; \ systemctl start qat; \ systemctl enable qat; \ fi endif uninstall-hook: if SERVICE_AC @if [ "$(shell id -u)" == 0 ]; then \ systemctl daemon-reload; \ pidof qatmgr > /dev/null && kill `pidof qatmgr`; \ rm -rf /run/qat; \ systemctl disable qat; \ fi endif dist_man_MANS = qat_init.sh.8 qatmgr.8 cpa_sample_code.7 EXTRA_DIST = INSTALL README.md SECURITY.md LICENSE \ filelist \ versionfile \ autogen.sh \ quickassist/lookaside/firmware/include \ quickassist/include \ quickassist/lookaside/access_layer/src/common \ quickassist/lookaside/access_layer/include \ quickassist/lookaside/access_layer/src/qat_direct \ quickassist/utilities/osal \ quickassist/utilities/libusdm_drv/include \ quickassist/utilities/libusdm_drv/user_space \ quickassist/utilities/service/qat \ quickassist/lookaside/access_layer/src/sample_code DISTCHECK_CONFIGURE_FLAGS = \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) ###################### # Build parameters # ###################### COMMON_LDFLAGS = -pie -z relro -z now -z noexecstack AM_LDFLAGS = $(COMMON_LDFLAGS) COMMON_FLAGS = -Wformat \ -Wformat-security \ -Werror=format-security \ -D_FORTIFY_SOURCE=2 \ -fstack-protector-strong \ -fPIE \ -fPIC \ -fno-strict-overflow \ -fno-delete-null-pointer-checks \ -fwrapv \ -D MAX_MR_ROUND=$(MAX_MR) \ -D _FILE_OFFSET_BITS=64 \ $(NO_UNUSED_CMDLINE_ARG_CFLAGS) \ $(MCX16_CFLAGS) \ $(PTHREAD_CFLAGS) if USE_GCC COMMON_FLAGS += -Wformat-truncation=2 endif if USE_ICC COMMON_FLAGS += -Wno-unknown-warning-option endif if ICP_DEBUG_AC ICP_DEBUG = 1 COMMON_FLAGS += -DICP_DEBUG endif if ICP_PARAM_CHECK_AC ICP_PARAM_CHECK = y COMMON_FLAGS += -DICP_PARAM_CHECK endif if DISABLE_STATS_AC DISABLE_STATS = 1 COMMON_FLAGS += -DDISABLE_STATS endif if ICP_LOG_SYSLOG_AC ICP_LOG_SYSLOG = 1 COMMON_FLAGS += -DICP_LOG_SYSLOG endif if ICP_TRACE_AC ICP_TRACE = 1 COMMON_FLAGS += -DICP_TRACE endif if ICP_DC_ERROR_SIMULATION_AC ICP_DC_ERROR_SIMULATION = 1 COMMON_FLAGS += -DICP_DC_ERROR_SIMULATION endif if ICP_HB_ERROR_SIMULATION_AC ICP_HB_FAIL_SIM = 1 COMMON_FLAGS += -DICP_HB_FAIL_SIM endif if USE_CCODE_CRC COMMON_FLAGS += -DUSE_CCODE_CRC endif if QAT_LEGACY_ALGORITHMS_AC QAT_LEGACY_ALGORITHMS = y COMMON_FLAGS += -DQAT_LEGACY_ALGORITHMS else QAT_LEGACY_ALGORITHMS = n endif if ICP_THREAD_SPECIFIC_USDM_AC ICP_THREAD_SPECIFIC_USDM = 1 COMMON_FLAGS += -DICP_THREAD_SPECIFIC_USDM endif if ICP_WITHOUT_QP_SUBMISSION_LOCK_AC ICP_WITHOUT_QP_SUBMISSION_LOCK = 1 COMMON_FLAGS += -DICP_WITHOUT_QP_SUBMISSION_LOCK endif if TREAT_CRC_FROM_COMP_ENGINE_AS_ERROR_AC TREAT_CRC_FROM_COMP_ENGINE_AS_ERROR = 1 COMMON_FLAGS += -DTREAT_CRC_FROM_COMP_ENGINE_AS_ERROR endif include Samples.am ######################## # RPM package building # ######################## rpm: clean dist qatlib.spec @mkdir -p rpmbuild/BUILD rpmbuild/RPMS rpmbuild/SOURCES rpmbuild/SPECS rpmbuild/SRPMS @cp $(PACKAGE)-$(VERSION).tar.gz rpmbuild/SOURCES/ @cp qatlib.spec rpmbuild/SPECS/ @rpmbuild --define "_topdir $(abs_srcdir)/rpmbuild" -ba rpmbuild/SPECS/qatlib.spec rpmclean: @rm -fr rpmbuild .PHONY: rpm rpmclean qatlib-25.08.0/README.md000066400000000000000000001050631503624047500144340ustar00rootroot00000000000000![Linux build with gcc](https://github.com/intel/qatlib/actions/workflows/linux_build_gcc.yml/badge.svg) ![CodeQL scan](https://github.com/intel/qatlib/actions/workflows/codeql.yml/badge.svg) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/intel/qatlib/badge)](https://api.securityscorecards.dev/projects/github.com/intel/qatlib) # Intel® QuickAssist Technology Library (QATlib) ## Table of Contents - [Revision History](#revision-history) - [Overview](#overview) - [Features](#features) - [Insecure Algorithms](#insecure-algorithms) - [Deprecated Features & Planned Deprecations](#deprecated-features--planned-deprecations) - [Setup](#setup) - [Supported Devices](#supported-devices) - [Limitations](#limitations) - [Environmental Assumptions](#environmental-assumptions) - [Examples](#examples) - [Open Issues](#open-issues) - [Resolved Issues](#resolved-issues) - [Licensing](#licensing) - [Legal](#legal) - [Terminology](#terminology) ## Revision History | Date | Doc Revision | Version | Details | |----------|:-------------:|------:|:------| | July 2025 | 016 | 25.08 | - Added support for Hugepages.
- Added No-IOMMU support for vfio.
- Added support for programmable CRCs to the DC Service
- Added a new API to query compression capabilities and marked the old API for deprecation.
- Enabled treating a CRC generated by the compression engine as an error. (See --enable-treat-crc-from-comp-engine-as-error).
- Enabled a performance optimization in the case where Queue Pairs are not shared across threads. (See --enable-icp-without-qp-submission-lock).
- Aligned with CPA API v5.6
- Bug Fixes. See [Resolved Issues](#resolved-issues). | | November 2024 | 015 | 24.09 | - Doc update only. Add QAT20-38022 information to [Open Issues](#open-issues) section. | | September 2024 | 014 | 24.09 | - Improved performance scaling in multi-thread applications (--enable-icp-thread-specific-usdm).
- Bug Fixes. See [Resolved Issues](#resolved-issues).
- Set core affinity mapping based on NUMA node to improve performance (near-linear scaling) on multi-socket platforms. | | July 2024 | 013 | 24.02 | - Doc update only. Updated this table to say that support for the GEN4 402xx device was added in the 24.02 release. Added link to more details in Supported Devices section. | | February 2024 | 012 | 24.02 | - Added Heartbeat support.
- Added support for QAT GEN 5 devices, including support for a range of crypto wireless algorithms.
- RAS - Device error reset and recovery handling.
- Bug Fixes. See [Resolved Issues](#resolved-issues). | | November 2023 | 011 | 23.11 | - Support DC NS (NoSession) APIs.
- Support DC compressBound APIs.
- Support Symmetric Crypto SM3 & SM4.
- Support Asymmetric Crypto SM2.
- Bug Fixes. See [Resolved Issues](#resolved-issues). | | August 2023 | 010 | 23.08 | - Removal of following insecure algorithms: Diffie-Hellman and Elliptic curves less than 256-bits.
- Additional configuration profiles, including sym which facilitates improved symmetric crypto performance.
- DC Chaining (Hash then compress)
- Bug Fixes. See [Resolved Issues](#resolved-issues).
- The shared object version is changed from 3->4. | | February 2023 | 009 | 23.02 | - Added configuration option --enable-legacy-algorithms to use these insecure crypto algorithms and disabled them by default (AES-ECB, SHA-1, SHA2-224, SHA3-224, RSA512/1024/1536, DSA)
- Refactored code in quickassist/utilities/libusdm_drv
- Bugfixes
- Updated documentation with configuration and tuning information | | November 2022 | 008 | 22.07.2 | - Changed from yasm to nasm for assembly compilation
- Added configuration option to use C implementation of soft CRC implementation instead of asm
- Added support for pkg-config
- Added missing lock around accesses to some global data in qatmgr | | October 2022 | 007 | 22.07.1 | - Fix for QATE-86605 | | July 2022 | 006 | 22.07 | - Added support for lz4/lz4s compression algorithms
- Added support for Compression End-to-end (E2E) integrity check
- Added support for PKE generic point multiply
- Updated QAT APIs (as a result the shared object version changed from 2->3).
- Enabled CPM2.0b
- Split rpm package | | November 2021 | 005 | 21.11 | - Added qatlib-tests rpm package
- Added option to configure script to skip building sample code | | August 2021 | 004 | 21.08 | - Added support for deflate compression - Compress and Verify (CnV) and Compress and Verify and Recover (CnVnR)
- Added Physical Function to Virtual Function (PFVF) communication support | | May 2021 | 003 | 21.05 | - Added support for AES-CCM 192/265
- Added support for SHA3-224/384/512 (no partials support)
- Added support for ChaCha20-Poly1305
- Added support for PKE 8K (RSA, DH, ModExp, ModInv)
- Fixed device enumeration on different nodes
- Fixed pci_vfio_set_command for 32 bit builds | | November 2020 | 002 | 20.10 | - Fixed service stopping during uninstallation
- Fixed "Cannot open /sys/kernel/iommu_groups/vfio/devices/" error
- Fixes based on static code analysis
- Fixes based on secure code reviews
- Refactored logging mechanism
- Updated library versioning scheme
- Improvements to make install target
- Fix so service file installed in /usr/lib64 can be properly detected
- Remove execute permissions from non-executable files
- Clarified documentation of licensing
- Removed libudev dependency from the package
- Removed OpenSSL/libcrypto extracts, instead link against system OpenSSL/libcrypto | | August 2020 | 001 | 20.08 | - Initial Release | ## Overview Intel(R) QuickAssist Technology (Intel(R) QAT) provides hardware acceleration for offloading security, authentication and compression services from the CPU, thus significantly increasing the performance and efficiency of standard platform solutions. Its services include symmetric encryption and authentication, asymmetric encryption, digital signatures, RSA, DH and ECC, and lossless data compression. This package provides user space libraries that allow access to Intel(R) QuickAssist devices and expose the Intel(R) QuickAssist APIs and sample codes. ## Features The following services are available in qatlib via the QuickAssist API: * Symmetric (Bulk) Cryptography * Ciphers ([AES-ECB](#insecure-algorithms), AES-CBC, AES-CTR (no partials support), AES-XTS (no partials support), AES-GCM, AES-CCM (192/256), [SM4-ECB](#insecure-algorithms), SM4-CBC, SM4-CTR) * Message digest/hash ([SHA1](#insecure-algorithms), SHA2 ([224](#insecure-algorithms)/256/384/512), SHA3 ([224](#insecure-algorithms)/256/384/512) (no partials support), SM3) and authentication (AES-CBC-MAC, AES-XCBC-MAC, AES-CMAC-128) * Algorithm chaining (one cipher and one hash in a single operation) * Authenticated encryption (CCM-128 (no partials support), GCM (128/192/256) (no partials support), GMAC (no partials support) and ChaCha20-Poly1305) * KeyGen * TLS1.2 * TLS1.3 * HKDF * MGF1 * Asymmetric (Public Key) Cryptography * Modular exponentiation and modular inversion up to 8192 bits * [Diffie-Hellman (DH)](#insecure-algorithms) key generation phase 1 and 2 up to 8192 bits * [RSA](#insecure-algorithms) key generation, encryption/decryption and digital signature generation/verification up to 8192 bits * [DSA](#insecure-algorithms) parameter generation and digital signature generation/verification * Elliptic Curve Cryptography: ECDSA, ECDHE, Edwards Montgomery curves * Generic point multiply * SM2 * Compression * Deflate * lz4/lz4s * Compress and Verify (CnV) * Compress and Verify and Recover (CnVnR) * End-to-end (E2E) integrity check * DC compressBound APIs * DC NS (No Session) APIs * Compression Chaining (Deflate only) * Hash then compress * Wireless Algorithms (supported on QAT GEN 5 devices) * Ciphers (SNOW3G-UEA2, ZUC-128, AES-F8) * Message digest/hash (SNOW3G-UIA2, ZUC-128) and authentication (AES-CMAC-128, AES-CMAC-192, AES-CMAC-256) This package includes: * libqat: user space library for QAT devices exposed via the vfio kernel driver * libusdm: user space library for memory management * qatmgr: user space daemon for device management * Sample codes: applications to demo usage of the libs ## Insecure Algorithms The following algorithms are considered insecure and are disabled by default. * AES-ECB * SHA-1 * SHA2-224 * SHA3-224 * RSA512/1024/1536 * DSA * Diffie-Helman * Elliptic Curve Cryptography algorithms with less 256 bits * SM4-ECB To enable these algorithms, use the following configuration option: * `--enable-legacy-algorithms` ## Deprecated Features & Planned Deprecations * The following configuration option will be deprecated after 2023: * `--enable-legacy-lib-names` ## Setup Please refer to [INSTALL](INSTALL) for details on installing the library. ## Supported Devices * 4xxx, 401xx and 402xx (QAT GEN 4 devices) * 420xx (QAT GEN 5 devices) Earlier generations of QAT devices (e.g. c6xx, dh895xxcc, etc.) are not supported. Please refer to [QATlib User’s Guide](https://intel.github.io/quickassist/qatlib/requirements.html#supported-devices) for more information on supported devices. ## Limitations * For simplicity, only one configuration file is used by qatlib. For guidance on how to use this to allocate resources for processes, please refer to Configuration and Tuning section in [QATlib User’s Guide](https://intel.github.io/quickassist/qatlib/index.html). The following features are not currently supported: * Dynamic instances * Intel® Key Protection Technology (KPT) * Event driven polling * More than 16 processes per end point (16 is the maximum) * accumulateXXHash when combined with autoSelectBestHuffmanTree * accumulateXXHash in Decompression or Combined sessions * Only 2MB Hugepages are supported. A client can not allocate more than 2MB in a single allocation with hugepages enabled. ## Environmental Assumptions The following assumptions are made concerning the deployment environment: * Users within the same processing domain must be trusted, i.e.: on the same host or within the same virtual machine, users must trust each other. * The library can be used by unprivileged users if those users are included in the 'qat' group. * DRAM is considered to be inside the trust boundary. The typical memory protection schemes provided by the Intel architecture processor and memory controller, and by the operating system, prevent unauthorized access to these memory regions. * A QuickAssist kernel driver for the supported device is installed, which has discovered and initialized the device, exposing the VFs. This driver is included in the Linux kernel, see [QATlib User’s Guide](https://intel.github.io/quickassist/RN/In-Tree/in_tree_firmware_RN.html#qat-kernel-driver-releases-features) for information about which kernel to use. ## Examples Example applications that showcase usage of the QAT APIs are included in the package (quickassist/lookaside/access_layer/src/sample_code). Please refer to [Intel® QuickAssist Technology API Programmer's Guide](https://www.intel.com/content/www/us/en/content-details/709196/intel-quickassist-technology-api-programmer-s-guide.html). ## Open Issues Known issues relating to the Intel® QAT software are described in this section. Additional Errata Information While this section covers known issues related to QATlib, users seeking information on errata items specific to QAT kernel drivers and firmware can refer to the Intel QuickAssist Technology documentation. This additional resource provides insights and updates that may be relevant to your use of Intel QuickAssist Technology: [Known Errata - Linux Firmware & Kernel Modules](https://intel.github.io/quickassist/RN/In-Tree/in_tree_firmware_RN.html#known-errata-linux-firmware-kernel-modules) Issue titles follow the pattern: [Stepping] - Description of issue where: \ is one of the following: * CY - Cryptographic * DC - Compression * EP - Endpoint * GEN - General * SYM DP - Symmetric Cryptography on Data Plane * SR-IOV - Single Root I/O Virtualization * FW - Firmware * PERF - Performance [Stepping] is an optional qualifier that identifies if the errata applies to a specific device stepping | Issue ID | Description | |-------------|------------| | QATE-106085 | [GEN - A QATlib process fails to start a 4xxx device on kernel v6.1 LTS](#qate-106085) | | QAT20-40469 | [DC - Incorrect Reporting of Programmable CRC Capability.](#qat20-40469) | | QATE-106040 | [CY – using AES-CCM authenticated encryption without Additional Auth Data can cause undefined behaviour.](#qate-106040) | | QATE-102747 | [GEN - Intel QAT Concurrent Initialization Failure in Standalone Mode.](#qate-102747) | | QATE-102390 | [GEN - [error] validateConcurrRequest() - : Invalid numConcurrRequests](#qate-102390) | | QATE-3241 | [CY - cpaCySymPerformOp when used with parameter checking may reveal the amount of padding.](#qate-3241) | | QATE-76073 | [GEN - If PF device configuration is modified without restarting qatmgr, undefined behavior may occur.](#qate-76073) | ## QATE-106085 | Title | GEN - A QATlib process fails to start a 4xxx device on kernel v6.1 LTS | |----------|:-------------| | Reference # | QATE-106085 | | Description | The process fails to start with an error "Failed to get enabled services" | | Implication | The process fails to run. | | Resolution | Use any later LTS kernel or use a different version of qatlib | | Affected OS | Linux - only applies to v6.1 LTS | | Driver/Module | QATlib – Only applies to v24.09 and v25.08. On v24.09 compression services fail to run, while on v25.08 both Crypto and Compression services fail to run. Only applies to 4xxx devices as support for other devices was only introduced in later kernels. | ## QAT20-40469 | Title | DC - Incorrect Reporting of Programmable CRC Capability | |----------|:-------------| | Reference # | QAT20-40469 | | Description | The API `cpaDcQueryCapabilityByType` incorrectly indicates that programmable CRC capability is only supported in the compression direction. | | Implication | Users may incorrectly assume that programmable CRCs are not supported in the decompression direction, potentially limiting the use of this feature. | | Resolution | Customers can ignore the unsupported status returned by this API for decompression. Programmable CRCs are supported in both compression and decompression directions. | | Affected OS | Linux | | Driver/Module | CPM-IA – Data Compression. | ## QATE-106040 | Title | CY – using AES-CCM authenticated encryption without Additional Auth Data can cause undefined behaviour. | |----------|:-------------| | Reference # | QATE-106040 | | Description | If CpaCySymHashAuthModeSetupData.aadLenInBytes is 0 and the AAD buffer passed in CpaCySymOpData.pAdditionalAuthData is less than 32 bytes, then the lib will overwrite bytes after the buffer. The API description is open to interpretation on the buffer size required, but is clear that it must be at least 16 bytes. However, bytes from byte 16..31 may be overwritten if aadLenInBytes = 0. | | Implication | This may result in undefined behaviour if the application had data stored after the buffer. | | Resolution | For CCM case the minimum AAD buffer size must be 32 bytes. | | Affected OS | Linux | | Driver/Module | CPM-IA – Crypto | ## QATE-102747 | Title | GEN - Intel QAT Concurrent Initialization Failure in Standalone Mode | |----------|:-------------| | Reference # | QATE-102747 | | Description | Concurrent initialization of the qatlib process in standalone mode may fail with an error message like: “err: Open vfio file /dev/vfio/481 failed!” This issue arises due to resource contention, particularly involving systemd-journald, which can hold the mutex required for VFIO operations. | | Implication | Users may experience failures during the initialization of the qatlib process, leading to unsuccessful attempts to utilize QAT resources. This can affect applications relying on QAT for cryptographic or data compression operations, potentially causing delays or requiring manual intervention. | | Resolution | The following may help to mititgate this issue: (1) Use kernel v6.14.5+, as this doesn't acquire the device mutex in journald or disable systemd-journald dev-log and restart it. (2) In standalone mode, instantiate QATlib processes sequentially to avoid contention. | | Affected OS | Linux | | Driver/Module | QATlib | ## QATE-102390 | Title | GEN – [error] validateConcurrRequest() - : Invalid numConcurrRequests | |---------------|:-------------------------------------------------------------------| | Reference # | QATE-102390 | | Description | An error occurs in a virtualized environment after VF resources are detached from a running VM (guest) and then re-attached. Following this, the qat service is restarted on the guest to ensure the correct VF resources are used. In rare instances, this leads to a failure in process initialisation with the error: "[error] validateConcurrRequest() - : Invalid numConcurrRequests". | | Implication | Processes within the guest fail to start. | | Resolution | To resolve the issue, restart the qatmgr on the guest using "sudo systemctl restart qat". If in standalone mode, restart the process manually. | | Affected OS | Linux | | Driver/Module | CPM-IA – Only on the 420xx QAT GEN 5 device. | ## QATE-3241 | Title | CY - cpaCySymPerformOp when used with parameter checking may reveal the amount of padding. | |----------|:-------------| | Reference # | QATE-3241 | | Description | When Performing a CBC Decryption as a chained request using cpaCySymPerformOp it is necessary to pass a length of the data to MAC (messageLenToHashInBytes). With ICP_PARAM_CHECK enabled, this checks the length of data to MAC is valid and, if not, it aborts the whole operation and outputs an error on stderr. | | Implication | The length of the data to MAC is based on the amount of padding. This should remain private and not be revealed. The issue is not observed when the length is checked in constant time before passing the value to the API. This is done by OpenSSL. | | Resolution | 1. Build without ICP_PARAM_CHECK, but this opens the risk of buffer overrun.
2. Validate the length before using the API. | | Affected OS | Linux | | Driver/Module | CPM-IA - Crypto | ## QATE-76073 | Title | GEN - If PF device configuration is modified without restarting qatmgr, undefined behavior may occur. | |----------|:-------------| | Reference # | QATE-76073 | | Description | When qatmgr is initialized, it reads the current configuration of the PF device. If the PF device configuration is modified without restarting the qatmgr, the updated device configuration is not comprehended by qatmgr. | | Implication | Undefined behavior may occur. | | Resolution | If PF device is reconfigured and reloaded, ensure to stop and start the qatmgr. | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## Resolved Issues Resolved issues relating to the Intel® QAT software are described in this section. | Issue ID | Description | |-------------|------------| | QAT20-38022 | [CY - Edwards and Montgomery curves not supported in PKE operations.](#qat20-38022) | | QAT20-40016 | [CY - ZUC-256 (EIA and EEA) on QAT GEN5 is no longer spec compliant.](#qat20-40016) | | QATE-76698 | [GEN - Multi-process applications running in guest will fail when running with default Policy settings.](#qate-76698) | | QATE-99637 | [GEN - QAT instances on PCI domains other than 0000 are inaccessible.](#qate-99637) | | QATE-99638 | [GEN - Incompatible service to ring configuration with non in-tree QAT kernel modules.](#qate-99638) | | QATE-98551 | [GEN - On a multi-socket platform, there can be a performance degradation on the remote sockets.](#qate-98551) | | QATE-41707 | [CY - Incorrect digest returned when performing a plain hash operation on input data of size 4GB or larger.](#qate-41707) | | QATE-97977 | [DC - 'Unable to get the physical address of Data Integrity buffer' error may be observed when using user-provided address translation functions.](#qate-97977) | | QATE-94369 | [GEN - SELinux Preventing QAT Service Startup.](#qate-94369) | | QATE-94286 | [GEN - Compression services not detected when crypto-capable VFs are added to VM.](#qate-94286) | | QATE-95905 | [GEN - Fix build when building outside of main directory, issue #56](#qate-95905) | | QATE-93844 | [DC - cpaDcLZ4SCompressBound is not returning correct value, which could lead to a buffer overflow.](#qate-93844) | | QATE-93278 | [GEN - sample_code potential seg-fault, issue #46](#qate-93278) | | QATE-90845 | [GEN - QAT service fails to start, issue #38](#qate-90845) | | QATE-78459 | [DC - cpaDcDeflateCompressBound API returns incorrect output buffer size when input size exceeds 477218588 bytes.](#qate-78459) | | QATE-76846 | [GEN - Forking and re-initializing use-cases do not work](#qate-76846) | | QATE-12241 | [CY - TLS1.2 with secret key lengths greater than 64 are not supported.](#qate-12241) | ## QAT20-38022 | Title | CY – Edwards and Montgomery curves not supported in PKE operations | |----------|:-------------| | Reference # | QAT20-38022 | | Description | On some platforms the function cpaCyQueryCapabilities() will report the ecEdMontSupported capability as FALSE and operations using those curves will fail. This case can arise when qatlib is running in a guest and the QAT kernel driver on the host is not a standard Linux in-tree kernel driver. For example, it can occur with some Linux out-of-tree, VMware® ESXi and Windows® QAT kernel drivers. | | Implication | PKE operations using those elliptic curves will fail. | | Resolution | Fixed in 25.08 | | Affected OS | Linux, VMware®, Windows® | | Driver/Module | CPM-IA – Only applies to QAT GEN4 devices. | ## QAT20-40016 | Title | CY - ZUC-256 (EIA and EEA) on QAT GEN5 is no longer spec compliant. | |----------|:-------------| | Reference # | QAT20-40016 | | Description | The Intel implementation of QAT ZUC-256 EEA (Encryption Algorithm) and EIA (Integrity Algorithm) does not align with the 2022 public specification. The initial ZUC-256 specification featured a different initialization scheme, which has since been updated to conform to cryptographic standards and 5G specifications. | | Implication | Applications attempting to utilize QAT for ZUC-256 EEA and EIA may encounter incorrect values, potentially affecting data integrity and security. | | Resolution | Issue closed: From QATlib 25.08+ support for ZUC-256 EEA and EIA is no longer provided for QAT GEN5 devices. | | Affected OS | ALL | | Driver/Module | CPM-IA - Crypto - Only applies to QAT GEN5 devices. | ## QATE-76698 | Title | GEN - Multi-process applications running in guest will fail when running with default Policy settings. | |----------|:-------------| | Reference # | QATE-76698 | | Description | The default Policy setting results in the first process receiving all available VFs allocated to a guest operating system if the BDFs on the guest do not facilitate qatlib recognising which VFs are from the same PF. In the case of a multi-process application, failures will be observed if all available QAT resources are consumed by the first process. | | Implication | Multi-process applications running in guest OS may fail with default Policy settings. | | Resolution | Issue closed: The issue won't arise if the guidance [here](https://intel.github.io/quickassist/qatlib/running_in_vm.html#qat-virtual-function) for specifying guest BDFs is followed. | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-99637 | Title | QAT instances on PCI domains other than 0000 are inaccessible. | |----------|:-------------| | Reference # | QATE-99637 | | Description | On multi-domain systems, QuickAssist Technology (QAT) devices that are assigned to PCI domains with identifiers other than the default '0000' are not recognized by the system. Consequently, the QAT instances associated with these devices do not appear available for use or configuration. | | Implication | The inability to access QAT instances on non-default PCI domains prevents the utilization of QAT devices in those domains. This limitation restricts the deployment of QAT in environments with complex PCI topologies and can lead to under utilization of available hardware acceleration resources. | | Resolution | Fixed in 24.09 | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-99638 | Title | Incompatible service to ring configuration with non in-tree QAT kernel modules. | |----------|:-------------| | Reference # | QATE-99638 | | Description | QATlib assumes a ring layout corresponding to ring configuration defaults used by the in-tree QAT kernel driver. This assumption is invalid if qatlib is running on a guest and the host has some other QAT kernel driver, e.g. an out-of-tree driver or ESXi driver, which may use different ring configurations. This affects configurations such as ASYM;DC and SYM;DC. All kernel drivers provide ring2service information via pfvfcomms, qatlib should query this rather than rely on an assumed ring layout. | | Implication | Crypto or compression operations will fail if sent to a ring which doesn’t handle that service. | | Resolution | Fixed in 24.09 | | Affected OS | Linux OOT, ESXi, Windows Server | | Driver/Module | CPM-IA - General | ## QATE-98551 | Title | GEN - On a multi-socket platform, there can be a performance degradation on the remote sockets. | |----------|:-------------| | Reference # | QATE-98551 | | Description | On a multi-socket platform, there can be a performance degradation on remote sockets. This can arise when either the threads are not affinitised to the core on the socket the device is on and/or the memory is not allocated on the appropriate NUMA node. | | Implication | Performance on socket 0 is as expected, but does not scale proportionally on remote sockets. | | Resolution | Fixed in 24.09 | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-41707 | Title | CY - Incorrect digest returned when performing a plain hash operation on input data of size 4GB or larger. | |----------|:-------------| | Reference # | QATE-41707 | | Description | When performing a plain hash operation on input data size of 4GB or larger, incorrect digest is returned. | | Implication | Incorrect digest is returned from a plain hash operation. | | Resolution | Issue closed: From QATlib 24.09+ hash operations on input size of 4GB or greater will be rejected, to prevent hitting this error. | | Affected OS | Linux | | Driver/Module | CPM-IA - Crypto | ## QATE-97977 | Title | DC - 'Unable to get the physical address of Data Integrity buffer' error may be observed when using user-provided address translation functions. | |----------|:-------------| | Reference # | QATE-97977 | | Description | When using Integrity CRC feature (integrityCrcCheck in CpaDcOpData) and also user provided address translation functions (cpaDcSetAddressTranslation) the above error may be observed. | | Implication | Compression request operations may fail in this scenario. | | Resolution | Fixed in 24.02 | | Affected OS | Linux | | Driver/Module | CPM-IA - Data Compression | ## QATE-94369 | Title | GEN - SELinux Preventing QAT Service Startup | |----------|:-------------| | Reference # | QATE-94369 | | Description | The qat service fails to start due to SELinux preventing the qat_init.sh script and qatmgr from accessing resources. The issue occurs when the system is running with SELinux enabled, causing insufficient permissions for the qat_init.sh script and qatmgr to function correctly. | | Implication | This issue affects the proper functioning of the qat service on systems with SELinux enabled, potentially preventing QAT virtual functions (VFs) from functioning. | | Resolution | The fix is not in the scope of qatlib. Instead there are three possible methods to handle this issue:
1) Update selinux-policy as seen in https://github.com/fedora-selinux/selinux-policy/pull/1992
2) Disable SElinux
3) Update mode to SElinux mode to permissive using following commands:
semanage permissive -a qatlib_exec_t
semanage permissive -a qatlib_t
The audit warnings may be generated, but qatlib will be allowed access to vfio devices. | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-94286 | Title | GEN - Compression services not detected when crypto-capable VFs are also added to VM. | |----------|:-------------| | Reference # | QATE-94286 | | Description | When configuring a system with different services on different QAT end-points, e.g. asym;sym on one and dc on another, and exposing only one of those Virtual Function (VF) types to the Virtual Machine (VM), the application works as expected. However, when VFs of more than one type are passed to the same VM, the application may only recognize one service-type, e.g. it may detect crypto instances, but not compression instances. There is an assumption that all VFs provide the same services if they come from the same PF. However, detecting which PF they come from is based on domain+bus, which is not always a valid assumption on a VM. | | Implication | This issue prevents the detection of compression services in a virtualized environment when the default kernel configuration is used, and crypto and dc VFs are passed to the VM, potentially impacting the proper functioning of the system. | | Resolution | Fixed in 23.11 | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-95905 | Title | GEN - Fix build when building outside of main directory, issue #56 | |----------|:-------------| | Reference # | QATE-95905 | | Description | Fix build when building outside of main directory. Added changes to autoconfig to be able to build outside main directory. See [issue 56](https://github.com/intel/qatlib/issues/56). | | Implication | A fatal error occurs when trying to build outside main directory. | | Resolution | Fixed in 23.11. | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-93844 | Title | DC - cpaDcLZ4SCompressBound is not returning correct value, which could lead to a buffer overflow. | |----------|:-------------| | Reference # | QATE-93844 | | Description | CompressBound API (cpaDcLZ4SCompressBound()) is intended to return the maximum size of the output buffer. However, this API is not returning the correct value, which can lead to a lz4s buffer overflow. | | Implication | Applications may experience buffer overflows even when using the output of compressBound API to allocate output buffers. | | Resolution | Fixed in 23.11 | | Affected OS | Linux | | Driver/Module | QAT IA - Compression | ## QATE-93278 | Title | GEN - sample_code potential seg-fault, issue #46 | |----------|:-------------| | Reference # | QATE-93278 | | Description | cpa_dc_stateless_multi_op_checksum_sample.c missed checking the return value of a memory allocation. See [issue 46](https://github.com/intel/qatlib/issues/46). | | Implication | In a low memory system, if the memory allocation fails, the process could crash. | | Resolution | Fixed in qatlib 23.08. | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-90845 | Title | GEN - QAT service fails to start, issue #38 | |----------|:-------------| | Reference # | QATE-90845 | | Description | QAT service fails to start. The qat service may fail if the kernel driver's initialization is not fully finished when the service starts. See [issue 38](https://github.com/intel/qatlib/issues/38). | | Implication | The qatmgr may not detect any or all of the vfio devices. | | Resolution | Fixed in 23.08. The service waits until the kernel driver has completed initialization of all PFs before starting the service. | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-78459 | Title | DC - cpaDcDeflateCompressBound API returns incorrect output buffer size when input size exceeds 477218588 bytes. | |----------|:-------------| | Reference # | QATE-74786 | | Description | When cpaDcDeflateCompressBound API is called with input size > 477218588 bytes incorrect buffer size is returned. For any buffer input size, the API should not produce output buffer size greater than the max limit (4 GB). | | Implication | Incorrect output buffer size is returned instead of error. | | Resolution | The issue is not present in qatlib. | | Affected OS | Linux | | Driver/Module | CPM-IA - Data Compression | ## QATE-76846 | Title | GEN - Forking and re-initializing use-cases do not work | |----------|:-------------| | Reference # | QATE-76846 | | Description | Forking and re-initializing use-cases do not work:
-icp_sal_userStart()/icp_sal_userStop()/icp_sal_userStart() in single process
-icp_sal_userStart()/fork()/icp_sal_userStart() in child.
This is the use case in openssh + QAT_Engine. | | Implication | The process will have undefined behavior in these use-cases. | | Resolution | Fixed in 21.08. If using release prior to this release and using these flows, call qaeMemDestroy() immediately after icp_sal_userStop() to prevent this issue. | | Affected OS | Linux | | Driver/Module | CPM-IA - General | ## QATE-12241 | Title | CY - TLS1.2 with secret key lengths greater than 64 are not supported | |----------|:-------------| | Reference # | QATE-12241 | | Description | Algorithms, as with Diffie-Hellman using 8K parameters that can use a secret key length greater than 64 bytes is not supported.| | Implication | Key generation would fail for TLS1.2 algorithms that use more than 64 bytes secret length keys. | | Resolution | Fixed in 22.07. | | Affected OS | Linux | | Driver/Module | CPM-IA - Crypto | ## Licensing * This product is released under the BSD-3-Clause. ## Legal Intel, Intel Atom, and Xeon are trademarks of Intel Corporation in the U.S. and/or other countries. \*Other names and brands may be claimed as the property of others. Copyright © 2016-2022, Intel Corporation. All rights reserved. ## Terminology | Term | Description | |----------|:-------------:| | API | Application Programming Interface | | BIOS | Basic Input/Output System | | BSD | Berkeley Standard Distribution | | CY | Cryptographic | | CnV | Compress and Verify | | CnVnR | Compress and Verify and Recover | | DC | Compression | | DMA | Direct Memory Access | | EFI | Extensible Firmware Interface | | FW | Firmware | | GPL | General Public License | | HKDF | HMAC-based Extract-and-Expand Key Derivation Function | | Intel® QAT | Intel® QuickAssist Technology | | OS | Operating System | | SR-IOV | Single-root Input/Output Virtualization | | TLS | Transport Layer Security | | VFs | Virtual Functions | qatlib-25.08.0/SECURITY.md000066400000000000000000000006331503624047500147430ustar00rootroot00000000000000# Security Policy Intel® is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. ## Reporting a Vulnerability Please report any security vulnerabilities in this project utilizing the guidelines [here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). qatlib-25.08.0/Samples.am000066400000000000000000000667311503624047500151100ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2022 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ ################### # QAT Sample Code # ################### if SAMPLES COMMON_SAMPLE_CFLAGS = -D USER_SPACE \ -D_GNU_SOURCE \ -DSC_ENABLE_DYNAMIC_COMPRESSION \ -DSC_SM2_ENABLED \ -DWITH_CMDRV \ -DSC_WITH_QAT20_UPSTREAM \ -DDO_CRYPTO \ -DINCLUDE_COMPRESSION \ -DSC_CHAINING_ENABLED \ -Wno-deprecated-declarations COMMON_SAMPLE_INCLUDES = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/framework \ -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/user_space \ -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/compression \ -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/common \ -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ -I$(srcdir)/quickassist/utilities/libusdm_drv \ -I$(srcdir)/quickassist/lookaside/access_layer/include \ -I$(srcdir)/quickassist/include \ -I$(srcdir)/quickassist/include/lac \ -I$(srcdir)/quickassist/include/dc \ -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/busy_loop \ -I$(srcdir)/quickassist/lookaside/access_layer/src/common/include \ -I$(srcdir)/quickassist/lookaside/access_layer/src/common/compression/include COMMON_SAMPLE_LDFLAGS = $(PTHREAD_LIBS) -lcrypto -lz -lc lib@LIBUSDMNAME@.la lib@LIBQATNAME@.la noinst_PROGRAMS = cpa_sample_code cpa_sample_code_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/user_space/cpa_sample_code_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/framework/cpa_sample_code_framework.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_sleeptime.c \ quickassist/lookaside/access_layer/src/sample_code/performance/cpa_sample_code_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_crypto_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_perf_dp.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_rsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_dsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ecdsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_dh_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update_common.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update_dp.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ike_rsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_kpt2_common.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_rsa_kpt2_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ecdsa_kpt2_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_sign_verify.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_Keyex_P1_P2.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_kdf_hash.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_enc_dec.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_buffer_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_dp.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_e2e.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_zlib.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_chaining_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_latency.c \ quickassist/lookaside/access_layer/src/sample_code/busy_loop/busy_loop.c cpa_sample_code_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance \ -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/ \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) \ -DSAMPLE_CODE_CORPUS_PATH="\"$(datadir)/qat/\"" cpa_sample_code_LDADD = $(COMMON_SAMPLE_LDFLAGS) noinst_LTLIBRARIES += libcpa_sample_code_s.la libcpa_sample_code_s_la_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/user_space/cpa_sample_code_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/framework/cpa_sample_code_framework.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_sleeptime.c \ quickassist/lookaside/access_layer/src/sample_code/performance/cpa_sample_code_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_crypto_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_perf_dp.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_rsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_dsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ecdsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_dh_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update_common.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update_dp.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ike_rsa_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_kpt2_common.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_rsa_kpt2_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ecdsa_kpt2_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_perf.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_sign_verify.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_Keyex_P1_P2.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_kdf_hash.c \ quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_enc_dec.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_buffer_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_dp.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_utils.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_e2e.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_zlib.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_chaining_main.c \ quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_latency.c \ quickassist/lookaside/access_layer/src/sample_code/busy_loop/busy_loop.c libcpa_sample_code_s_la_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance \ -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/ \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) \ -DSAMPLE_CODE_CORPUS_PATH="\"$(datadir)/qat/\"" noinst_PROGRAMS += dc_dp_sample dc_dp_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/dc_dp_sample/cpa_dc_dp_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/dc_dp_sample/cpa_dc_dp_sample_user.c dc_dp_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) dc_dp_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += dc_stateless_sample dc_stateless_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/cpa_dc_stateless_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/cpa_dc_sample_user.c dc_stateless_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) dc_stateless_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += chaining_sample chaining_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/cpa_chaining_sample_user.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/cpa_chaining_sample.c chaining_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) chaining_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += dc_stateless_multi_op_sample dc_stateless_multi_op_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_multi_op_checksum_sample/cpa_dc_stateless_multi_op_checksum_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/cpa_dc_sample_user.c dc_stateless_multi_op_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) dc_stateless_multi_op_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += algchaining_sample algchaining_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/alg_chaining_sample/cpa_algchaining_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/alg_chaining_sample/cpa_algchaining_sample_user.c algchaining_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) algchaining_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += ccm_sample ccm_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/ccm_sample/cpa_ccm_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/ccm_sample/cpa_ccm_sample_user.c ccm_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) ccm_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += cipher_sample cipher_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/cipher_sample/cpa_cipher_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/cipher_sample/cpa_cipher_sample_user.c cipher_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) cipher_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += gcm_sample gcm_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/gcm_sample/cpa_gcm_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/gcm_sample/cpa_gcm_sample_user.c gcm_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) gcm_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += hash_file_sample hash_file_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_file_sample/cpa_hash_file_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_file_sample/cpa_hash_file_sample_user.c hash_file_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) hash_file_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += hash_sample hash_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_sample/cpa_hash_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_sample/cpa_hash_sample_user.c hash_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) hash_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += ipsec_sample ipsec_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/ipsec_sample/cpa_ipsec_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/ipsec_sample/cpa_ipsec_sample_user.c ipsec_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) ipsec_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += ssl_sample ssl_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/cpa_ssl_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/cpa_sample_decrypt_user.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/cpa_ssl_sample_user.c ssl_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) ssl_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += sym_dp_sample sym_dp_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/symdp_sample/cpa_sym_dp_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/symdp_sample/cpa_sym_dp_sample_user.c sym_dp_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) sym_dp_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += dh_sample dh_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/diffie_hellman_sample/cpa_dh_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/diffie_hellman_sample/cpa_dh_sample_user.c dh_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) dh_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += eddsa_sample eddsa_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_eddsa_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_eddsa_sample_user.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_big_num.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_ed_point_operations.c eddsa_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ -I$(srcdir)/quickassist/utilities/osal/include \ -I$(srcdir)/quickassist/utilities/osal/src/linux/user_space/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) eddsa_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la libosal.la noinst_PROGRAMS += prime_sample prime_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/prime_sample/cpa_prime_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/prime_sample/cpa_prime_sample_user.c prime_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) prime_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += hkdf_sample hkdf_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/cpa_hkdf_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/cpa_hkdf_sample_user.c hkdf_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) hkdf_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += ec_montedwds_sample ec_montedwds_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/ec_montedwds_sample/cpa_ec_montedwds_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/asym/ec_montedwds_sample/cpa_ec_montedwds_sample_user.c ec_montedwds_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) ec_montedwds_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += zuc_sample zuc_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/zuc_sample/cpa_zuc_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/zuc_sample/cpa_zuc_sample_user.c zuc_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) zuc_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la noinst_PROGRAMS += update_sample update_sample_SOURCES = \ quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/update_sample/cpa_sym_dp_update_sample.c \ quickassist/lookaside/access_layer/src/sample_code/functional/sym/update_sample/cpa_sym_dp_update_sample_user.c update_sample_CFLAGS = -I$(srcdir)/quickassist/lookaside/access_layer/src/sample_code/functional/include \ $(COMMON_SAMPLE_INCLUDES) \ $(COMMON_SAMPLE_CFLAGS) \ $(COMMON_FLAGS) update_sample_LDADD = $(COMMON_SAMPLE_LDFLAGS) libcpa_sample_code_s.la samples: $(lib_LTLIBRARIES) cpa_sample_code dc_dp_sample dc_stateless_sample \ dc_stateless_multi_op_sample algchaining_sample ccm_sample \ cipher_sample gcm_sample hash_file_sample hash_sample ipsec_sample \ ssl_sample sym_dp_sample dh_sample prime_sample hkdf_sample \ ec_montedwds_sample eddsa_sample chaining_sample zuc_sample update_sample samples-install: samples @install -D -m 755 $(srcdir)/.libs/cpa_sample_code $(DESTDIR)$(bindir)/cpa_sample_code @install -D -m 755 $(srcdir)/.libs/dc_dp_sample $(DESTDIR)$(bindir)/dc_dp_sample @install -D -m 755 $(srcdir)/.libs/dc_stateless_sample $(DESTDIR)$(bindir)/dc_stateless_sample @install -D -m 755 $(srcdir)/.libs/chaining_sample $(DESTDIR)$(bindir)/chaining_sample @install -D -m 755 $(srcdir)/.libs/dc_stateless_multi_op_sample $(DESTDIR)$(bindir)/dc_stateless_multi_op_sample @install -D -m 755 $(srcdir)/.libs/algchaining_sample $(DESTDIR)$(bindir)/algchaining_sample @install -D -m 755 $(srcdir)/.libs/ccm_sample $(DESTDIR)$(bindir)/ccm_sample @install -D -m 755 $(srcdir)/.libs/cipher_sample $(DESTDIR)$(bindir)/cipher_sample @install -D -m 755 $(srcdir)/.libs/gcm_sample $(DESTDIR)$(bindir)/gcm_sample @install -D -m 755 $(srcdir)/.libs/hash_file_sample $(DESTDIR)$(bindir)/hash_file_sample @install -D -m 755 $(srcdir)/.libs/hash_sample $(DESTDIR)$(bindir)/hash_sample @install -D -m 755 $(srcdir)/.libs/ipsec_sample $(DESTDIR)$(bindir)/ipsec_sample @install -D -m 755 $(srcdir)/.libs/ssl_sample $(DESTDIR)$(bindir)/ssl_sample @install -D -m 755 $(srcdir)/.libs/sym_dp_sample $(DESTDIR)$(bindir)/sym_dp_sample @install -D -m 755 $(srcdir)/.libs/dh_sample $(DESTDIR)$(bindir)/dh_sample @install -D -m 755 $(srcdir)/.libs/eddsa_sample $(DESTDIR)$(bindir)/eddsa_sample @install -D -m 755 $(srcdir)/.libs/prime_sample $(DESTDIR)$(bindir)/prime_sample @install -D -m 755 $(srcdir)/.libs/hkdf_sample $(DESTDIR)$(bindir)/hkdf_sample @install -D -m 755 $(srcdir)/.libs/ec_montedwds_sample $(DESTDIR)$(bindir)/ec_montedwds_sample @install -D -m 755 $(srcdir)/.libs/zuc_sample $(DESTDIR)$(bindir)/zuc_sample @install -D -m 755 $(srcdir)/.libs/update_sample $(DESTDIR)$(bindir)/update_sample @install -D -m 644 $(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/compression/calgary $(DESTDIR)$(datadir)/qat/calgary @install -D -m 644 $(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/compression/calgary32 $(DESTDIR)$(datadir)/qat/calgary32 @install -D -m 644 $(srcdir)/quickassist/lookaside/access_layer/src/sample_code/performance/compression/canterbury $(DESTDIR)$(datadir)/qat/canterbury @echo "" @echo "*******************************************************" @echo "* cpa_sample_code installed under $(DESTDIR)$(bindir) *" @echo "*******************************************************" @echo "" samples-uninstall: @rm -rf $(DESTDIR)$(bindir)/cpa_sample_code @rm -rf $(DESTDIR)$(bindir)/dc_dp_sample @rm -rf $(DESTDIR)$(bindir)/dc_stateless_sample @rm -rf $(DESTDIR)$(bindir)/chaining_sample @rm -rf $(DESTDIR)$(bindir)/dc_stateless_multi_op_sample @rm -rf $(DESTDIR)$(bindir)/algchaining_sample @rm -rf $(DESTDIR)$(bindir)/ccm_sample @rm -rf $(DESTDIR)$(bindir)/cipher_sample @rm -rf $(DESTDIR)$(bindir)/gcm_sample @rm -rf $(DESTDIR)$(bindir)/hash_file_sample @rm -rf $(DESTDIR)$(bindir)/hash_sample @rm -rf $(DESTDIR)$(bindir)/ipsec_sample @rm -rf $(DESTDIR)$(bindir)/ssl_sample @rm -rf $(DESTDIR)$(bindir)/sym_dp_sample @rm -rf $(DESTDIR)$(bindir)/dh_sample @rm -rf $(DESTDIR)$(bindir)/eddsa_sample @rm -rf $(DESTDIR)$(bindir)/prime_sample @rm -rf $(DESTDIR)$(bindir)/hkdf_sample @rm -rf $(DESTDIR)$(bindir)/ec_montedwds_sample @rm -rf $(DESTDIR)$(bindir)/zuc_sample @rm -rf $(DESTDIR)$(bindir)/update_sample @rm -rf $(DESTDIR)$(datadir)/qat/calgary @rm -rf $(DESTDIR)$(datadir)/qat/calgary32 @rm -rf $(DESTDIR)$(datadir)/qat/canterbury @if test -d $(DESTDIR)$(datadir)/qat; then rmdir --ignore-fail-on-non-empty $(DESTDIR)$(datadir)/qat; fi endif .PHONY: samples samples-install samples-uninstall qatlib-25.08.0/autogen.sh000077500000000000000000000034401503624047500151520ustar00rootroot00000000000000################################################################# # # BSD LICENSE # # Copyright(c) 2007-2022 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################# #!/bin/sh autoreconf -if qatlib-25.08.0/configure.ac000066400000000000000000000271121503624047500154410ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([qatlib], [25.08.0], [qat-linux@intel.com]) AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign subdir-objects tar-pax]) AM_SILENT_RULES([yes]) AC_USE_SYSTEM_EXTENSIONS AC_CONFIG_MACRO_DIRS([m4]) AC_CONFIG_HEADERS([config.h]) AC_SUBST([LIBQAT_VERSION], [8:0:4]) AC_SUBST([LIBUSDM_VERSION], [1:2:1]) # Checks for programs. AC_PROG_AWK AC_PROG_CC AC_PROG_LN_S AC_PROG_MAKE_SET AM_PROG_AR AC_PATH_TOOL(PKGCONFIG, pkg-config) LT_PREREQ([2.4]) LT_INIT # Check for pthreads m4_ifdef([AX_PTHREAD], [], [ m4_fatal([AX_PTHREAD not found. Please install autoconf-archive or place ax_pthread.m4 in m4/]) ]) AX_PTHREAD AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_LIBS]) # Checks for libraries. AC_CHECK_LIB([crypto], [AES_decrypt]) # Checks for header files. AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h utmpx.h]) # Checks for typedefs, structures, and compiler characteristics. AC_CHECK_HEADER_STDBOOL AC_TYPE_UID_T AC_C_INLINE AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_INT8_T AC_TYPE_PID_T AC_C_RESTRICT AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T # Checks for library functions. AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_MMAP AC_FUNC_STRNLEN AC_CHECK_FUNCS([alarm clock_gettime getpagesize gettimeofday memmove memset munmap select socket strerror strstr strtoul strtoull]) # Check for openssl header AC_CHECK_HEADERS([openssl/md5.h], [], [AC_MSG_ERROR([openssl/md5.h not found])] ) # Check for numa header AC_CHECK_HEADERS([numa.h], [], [AC_MSG_ERROR([numa.h not found])] ) # Check if compiler supports mcx16 saved_cflags="$CFLAGS" CFLAGS=-mcx16 AC_MSG_CHECKING([whether $CC supports -mcx16]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [if $GREP "warning" conftest.err >/dev/null; then AC_MSG_RESULT([no]); else MCX16_CFLAGS="-mcx16"; AC_MSG_RESULT([yes]); fi], [AC_MSG_RESULT([no])]) CFLAGS="$saved_cflags" AC_SUBST(MCX16_CFLAGS) # Reset both values before checking AC_SUBST([USE_GCC], [0]) AC_SUBST([USE_ICC], [0]) # Detect the compiler from CC AC_MSG_CHECKING([which compiler is being used]) case "$CC" in *gcc*) AC_MSG_RESULT([GCC detected]) AC_SUBST([USE_GCC], [1]) AC_SUBST([USE_ICC], [0]) ;; *icx*|*icc*) AC_MSG_RESULT([ICC detected]) AC_SUBST([USE_ICC], [1]) AC_SUBST([USE_GCC], [0]) ;; *) AC_MSG_RESULT([Unknown compiler]) ;; esac # Store the results for automake AM_CONDITIONAL([USE_GCC], [test "$USE_GCC" = "1"]) AM_CONDITIONAL([USE_ICC], [test "$USE_ICC" = "1"]) # Check if compiler supports -Wno-unused-command-line-argument saved_cflags="$CFLAGS" CFLAGS=-Wno-unused-command-line-argument AC_MSG_CHECKING([whether $CC supports -Wno-unused-command-line-argument]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [if $GREP "warning" conftest.err >/dev/null; then AC_MSG_RESULT([no]); else NO_UNUSED_CMDLINE_ARG_CFLAGS="-Wno-unused-command-line-argument"; AC_MSG_RESULT([yes]); fi], [AC_MSG_RESULT([no])]) CFLAGS="$saved_cflags" AC_SUBST(NO_UNUSED_CMDLINE_ARG_CFLAGS) # Check for pkgconfig AC_MSG_CHECKING([for pkg-config]) AS_IF([test "x${PKGCONFIG}" = "x"], [ AC_MSG_RESULT(no) have_pkgconfig="no" ], [ AC_MSG_RESULT(yes) have_pkgconfig="yes" ] ) # Check for systemd. AS_IF([test "x${have_pkgconfig}" = "xyes"], [ AC_MSG_CHECKING(for systemd pkg-config support) AS_IF([$PKGCONFIG --exists systemd], [ AC_MSG_RESULT(yes); have_systemd="yes" ], [ AC_MSG_RESULT(no); have_systemd="no" ]) ], [] ) AC_ARG_ENABLE(systemd, AS_HELP_STRING([--enable-systemd], [Enable systemd support]), [enable_systemd=${enableval}], [enable_systemd="yes"]) if (test "${have_systemd}" = "no"); then if (test "${enable_systemd}" != "no" ); then AC_MSG_ERROR(systemd not found) fi else AC_MSG_CHECKING(whether to use systemd) AC_MSG_RESULT(${enable_systemd}) fi AC_CHECK_PROG(NASM_BINARY, nasm, yes , no) AC_ARG_ENABLE(fast-crc-in-assembler, AS_HELP_STRING([--disable-fast-crc-in-assembler], [Force use of C code instead of faster assembler implementation of CRC for DC integrityCrc feature. Not recommended unless assembler compiler unavailable.]), [disable_fast_crc_in_assembler="yes"], [disable_fast_crc_in_assembler="no"]) AC_MSG_CHECKING(force disable fast crc in assembler) AC_MSG_RESULT(${disable_fast_crc_in_assembler}) AM_CONDITIONAL(USE_CCODE_CRC, test "$disable_fast_crc_in_assembler" = "yes" ) if ( test "$disable_fast_crc_in_assembler" = "no" ); then if (test "${NASM_BINARY}" = "no"); then AC_MSG_ERROR(Nasm not found) fi fi # Check location of systemd unit files AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), [], [AS_IF([test "${have_pkgconfig}" = "yes"], [with_systemdsystemunitdir=$($PKGCONFIG --variable=systemdsystemunitdir systemd) AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])], []) ]) AM_CONDITIONAL(HAVE_SYSTEMD, test "${enable_systemd}" != "no") AS_IF([test "${enable_systemd}" != "no"], [AC_MSG_CHECKING(systemd unit directory); AC_MSG_RESULT(${systemdsystemunitdir})], []) # SAMPLES AC_ARG_ENABLE(samples, AS_HELP_STRING([--enable-samples], [Create sample programs]), [enable_samples=${enableval}], [enable_samples="yes"]) AC_MSG_CHECKING(whether to build samples) AC_MSG_RESULT(${enable_samples}) AM_CONDITIONAL(SAMPLES, test "${enable_samples}" != "no") # MAX_MR AC_ARG_VAR(MAX_MR, [Number of Miller Rabin rounds for prime operations. Setting this to a smaller value reduces the memory usage required by the driver (default: 50).]) if ! test "$MAX_MR"; then MAX_MR=50 fi # ICP_DEBUG AC_ARG_ENABLE(icp-debug, AS_HELP_STRING([--enable-icp-debug], [Enables debugging.]), [icp_debug=true], [icp_debug=false] ) AM_CONDITIONAL([ICP_DEBUG_AC], [test x$icp_debug = xtrue]) #ICP_PARAM_CHECK AC_ARG_ENABLE([param-check], [AS_HELP_STRING([--disable-param-check], [Disables parameters checking in the top-level APIs. (Use for performance optimization.)])], [case "${enableval}" in yes) disable_param_check=false;; no) disable_param_check=true;; *) disable_param_check=false;; esac], [disable_param_check=false] ) AM_CONDITIONAL([ICP_PARAM_CHECK_AC], [test x$disable_param_check = xfalse]) # DISABLE_STATS AC_ARG_ENABLE(stats, AS_HELP_STRING([--disable-stats], [Disables statistic collection (Use for performance optimization).]), [disable_stats=true], [disable_stats=false] ) AM_CONDITIONAL([DISABLE_STATS_AC], [test x$disable_stats = xtrue]) # ICP_LOG_SYSLOG AC_ARG_ENABLE(icp-log-syslog, AS_HELP_STRING([--enable-icp-log-syslog], [Enables debugging messages to be outputted to the system log instead of standard output.]), [icp_log_syslog=true], [icp_log_syslog=false] ) AM_CONDITIONAL([ICP_LOG_SYSLOG_AC], [test x$icp_log_syslog = xtrue]) # ICP_TRACE AC_ARG_ENABLE(icp-trace, AS_HELP_STRING([--enable-icp-trace], [Enables tracing for the Cryptography API.]), [icp_trace=true], [icp_trace=false] ) AM_CONDITIONAL([ICP_TRACE_AC], [test x$icp_trace = xtrue]) # ICP_DC_ERROR_SIMULATION AC_ARG_ENABLE(dc-error-simulation, AS_HELP_STRING([--enable-dc-error-simulation], [Enables Data Compression Error Simulation.]), [dc_error_simulation=true], [dc_error_simulation=false] ) AM_CONDITIONAL([ICP_DC_ERROR_SIMULATION_AC], [test x$dc_error_simulation = xtrue]) # ICP_HB_ERROR_SIMULATION AC_ARG_ENABLE(hb-error-simulation, AS_HELP_STRING([--enable-hb-error-simulation], [Enables Heartbeat Error Simulation.]), [hb_error_simulation=true], [hb_error_simulation=false] ) AM_CONDITIONAL([ICP_HB_ERROR_SIMULATION_AC], [test x$hb_error_simulation = xtrue]) # ICP_THREAD_SPECIFIC_USDM AC_ARG_ENABLE(icp-thread-specific-usdm, AS_HELP_STRING([--enable-icp-thread-specific-usdm], [USDM allocates and handles memory specific to threads (For multi-thread apps, allocated memory information will be maintained separately for each thread). @<:@default=no@:>@ ]), [icp_thread_specific_usdm=true], [icp_thread_specific_usdm=false] ) AM_CONDITIONAL([ICP_THREAD_SPECIFIC_USDM_AC], [test x$icp_thread_specific_usdm = xtrue]) AC_ARG_ENABLE(legacy-lib-names, AS_HELP_STRING([--enable-legacy-lib-names], [Enables legacy names for libraries.]), [ AC_SUBST([LIBQATNAME], "qat_s") AC_SUBST([LIBUSDMNAME], "usdm_drv_s") ], [ AC_SUBST([LIBQATNAME], "qat") AC_SUBST([LIBUSDMNAME], "usdm") ]) AC_ARG_ENABLE(service, AS_HELP_STRING([--enable-service], [Automatically enables systemd service during installation.]), [service=true], [service=false] ) AM_CONDITIONAL([SERVICE_AC], [test x$service = xtrue -a x$enable_systemd != xno ]) AC_ARG_ENABLE(legacy-algorithms, AS_HELP_STRING([--enable-legacy-algorithms], [Enable legacy crypto algorithms.]), [enable_legacy_algorithms="yes"], [enable_legacy_algorithms="no"]) AM_CONDITIONAL(QAT_LEGACY_ALGORITHMS_AC, test "$enable_legacy_algorithms" = "yes" ) # ICP_WITHOUT_QP_SUBMISSION_LOCK AC_ARG_ENABLE(icp-without-qp-submission-lock, AS_HELP_STRING([--enable-icp-without-qp-submission-lock], [This allows for the removal of Queue Pair (QP) submission locks and is designed to optimize performance in environments where QPs assigned to one thread are not shared by another thread. In these scenarios, the frequent invocation of mutex_lock/unlock during hardware request submissions is unnecessary and can affect performance. By enabling this flag, the locks around QP submissions are eliminated, thus reducing the cost of offload. As QPs are assigned to instances, only enable this if instances are not shared across threads, else undefined behaviour could occur.]), [icp_without_qp_submission_lock=true], [icp_without_qp_submission_lock=false] ) AM_CONDITIONAL([ICP_WITHOUT_QP_SUBMISSION_LOCK_AC], [test x$icp_without_qp_submission_lock = xtrue]) # TREAT_CRC_FROM_COMP_ENGINE_AS_ERROR AC_ARG_ENABLE(treat-crc-from-comp-engine-as-error, AS_HELP_STRING([--enable-treat-crc-from-comp-engine-as-error], [When the device calculates a CRC over the uncompressed data, it usually uses the decompression engine to do the CRC calculation. In compression operation cases where the stored block is returned e.g. due to input data being incompressible, the returned CRC is calculated using the compression engine, which should give exactly the same CRC as the decompression engine would. Enabling this option causes any case where the CRC is calculated by the compression engine to be reported as a CPA_DC_E2E_NO_DECOMPRESSION error, rather than as a successful operation. Please see below link for firmware needed to support this feature. https://intel.github.io/quickassist/RN/In-Tree/in_tree_firmware_RN.html#qat-2-0-in-tree-kernel-requirements]), [treat_crc_from_comp_engine_as_error=true], [treat_crc_from_comp_engine_as_error=false] ) AM_CONDITIONAL([TREAT_CRC_FROM_COMP_ENGINE_AS_ERROR_AC], [test x$treat_crc_from_comp_engine_as_error = xtrue]) # Config files. AC_CONFIG_FILES([Makefile qatlib.spec qatlib.pc libqat.pc libusdm.pc]) if test x$enable_systemd != xno then AC_CONFIG_FILES([quickassist/utilities/service/qat.service quickassist/utilities/service/qat_init.sh]) fi # Substitutions in spec file AC_SUBST([PACKAGE]) AC_SUBST([VERSION]) AC_OUTPUT qatlib-25.08.0/cpa_sample_code.7000066400000000000000000000075771503624047500163560ustar00rootroot00000000000000.\" Copyright(c) 2025 Intel Corporation. All rights reserved. .\" All rights reserved. .\" .\" %%%LICENSE_START(BSD_3_CLAUSE) .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" * Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" * Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in .\" the documentation and/or other materials provided with the .\" distribution. .\" * Neither the name of Intel Corporation nor the names of its .\" contributors may be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR .\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT .\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, .\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT .\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" %%%LICENSE_END .\" .\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH CPA_SAMPLE_CODE 7 "August 12, 2024" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .nr TW 0 .SH NAME cpa_sample_code \- showcase of Intel QuickAssist device functionality and performance .SH SYNOPSIS cpa_sample_code [ signOfLife=1 | getOffloadCost=1 | getLatency=1 ] [ runTests=mask ] .SH DESCRIPTION This example tool showcases the functionality and performance of Intel QuickAssist devices. .SH OPTIONS .LP mask for runTests: .TS l l. runTests=1 Run symmetric crypto tests. runTests=2 Run RSA test. runTests=4 Run DSA test. runTests=8 Run ECDSA test. runTests=16 Run DH test runTests=32 Run Stateless Compression test. runTests=63 Run all above tests. (default) runTests=1024 Run SM2 test. runTests=2048 Run SM3&4 test. .TE .SH EXAMPLES .LP run the full suite of symmetric cryptography, asymmetric cryptography and data compression operations: .IP \f[CR]cpa_sample_code\f[] .LP run a small number of each operation type: .IP \f[CR]cpa_sample_code signOfLife=1\f[] .LP run only RSA operations: .IP \f[CR]cpa_sample_code runTests=2\f[] .br .SH FURTHER INFORMATION https://intel.github.io/quickassist/qatlib/sample_code.html .br https://github.com/intel/qatlib/blob/main/quickassist/lookaside/access_layer/src/sample_code/README.txt qatlib-25.08.0/filelist000066400000000000000000001012031503624047500147030ustar00rootroot00000000000000INSTALL LICENSE Makefile.am README.md SECURITY.md Samples.am autogen.sh configure.ac cpa_sample_code.7 filelist libqat.pc.in libusdm.pc.in qat_init.sh.8 qatlib.pc.in qatlib.spec.in qatmgr.8 quickassist/include/cpa.h quickassist/include/cpa_dev.h quickassist/include/cpa_types.h quickassist/include/dc/cpa_dc.h quickassist/include/dc/cpa_dc_capabilities.h quickassist/include/dc/cpa_dc_chain.h quickassist/include/dc/cpa_dc_dp.h quickassist/include/lac/cpa_cy_common.h quickassist/include/lac/cpa_cy_dh.h quickassist/include/lac/cpa_cy_drbg.h quickassist/include/lac/cpa_cy_dsa.h quickassist/include/lac/cpa_cy_ec.h quickassist/include/lac/cpa_cy_ecdh.h quickassist/include/lac/cpa_cy_ecdsa.h quickassist/include/lac/cpa_cy_ecsm2.h quickassist/include/lac/cpa_cy_im.h quickassist/include/lac/cpa_cy_key.h quickassist/include/lac/cpa_cy_kpt.h quickassist/include/lac/cpa_cy_ln.h quickassist/include/lac/cpa_cy_nrbg.h quickassist/include/lac/cpa_cy_prime.h quickassist/include/lac/cpa_cy_rsa.h quickassist/include/lac/cpa_cy_sym.h quickassist/include/lac/cpa_cy_sym_dp.h quickassist/include/rl/cpa_rl.h quickassist/lookaside/access_layer/include/adf_kernel_types.h quickassist/lookaside/access_layer/include/icp_accel_devices.h quickassist/lookaside/access_layer/include/icp_adf_accel_mgr.h quickassist/lookaside/access_layer/include/icp_adf_cfg.h quickassist/lookaside/access_layer/include/icp_adf_debug.h quickassist/lookaside/access_layer/include/icp_adf_init.h quickassist/lookaside/access_layer/include/icp_adf_poll.h quickassist/lookaside/access_layer/include/icp_adf_transport.h quickassist/lookaside/access_layer/include/icp_adf_transport_dp.h quickassist/lookaside/access_layer/include/icp_adf_user_proxy.h quickassist/lookaside/access_layer/include/icp_buffer_desc.h quickassist/lookaside/access_layer/include/icp_sal.h quickassist/lookaside/access_layer/include/icp_sal_congestion_mgmt.h quickassist/lookaside/access_layer/include/icp_sal_iommu.h quickassist/lookaside/access_layer/include/icp_sal_poll.h quickassist/lookaside/access_layer/include/icp_sal_user.h quickassist/lookaside/access_layer/include/icp_sal_versions.h quickassist/lookaside/access_layer/src/common/compression/crc32_gzip_refl_by8.S quickassist/lookaside/access_layer/src/common/compression/crc64_ecma_norm_by8.S quickassist/lookaside/access_layer/src/common/compression/dc_buffers.c quickassist/lookaside/access_layer/src/common/compression/dc_capabilities.c quickassist/lookaside/access_layer/src/common/compression/dc_chain.c quickassist/lookaside/access_layer/src/common/compression/dc_crc32.c quickassist/lookaside/access_layer/src/common/compression/dc_crc64.c quickassist/lookaside/access_layer/src/common/compression/dc_crc_base.c quickassist/lookaside/access_layer/src/common/compression/dc_datapath.c quickassist/lookaside/access_layer/src/common/compression/dc_dictionary.c quickassist/lookaside/access_layer/src/common/compression/dc_dp.c quickassist/lookaside/access_layer/src/common/compression/dc_err_sim.c quickassist/lookaside/access_layer/src/common/compression/dc_header_footer.c quickassist/lookaside/access_layer/src/common/compression/dc_header_footer_lz4.c quickassist/lookaside/access_layer/src/common/compression/dc_ns_datapath.c quickassist/lookaside/access_layer/src/common/compression/dc_ns_header_footer.c quickassist/lookaside/access_layer/src/common/compression/dc_session.c quickassist/lookaside/access_layer/src/common/compression/dc_stats.c quickassist/lookaside/access_layer/src/common/compression/dc_xxhash32.c quickassist/lookaside/access_layer/src/common/compression/icp_sal_dc_err_sim.c quickassist/lookaside/access_layer/src/common/compression/include/dc_capabilities.h quickassist/lookaside/access_layer/src/common/compression/include/dc_chain.h quickassist/lookaside/access_layer/src/common/compression/include/dc_crc32.h quickassist/lookaside/access_layer/src/common/compression/include/dc_crc64.h quickassist/lookaside/access_layer/src/common/compression/include/dc_datapath.h quickassist/lookaside/access_layer/src/common/compression/include/dc_err_sim.h quickassist/lookaside/access_layer/src/common/compression/include/dc_error_counter.h quickassist/lookaside/access_layer/src/common/compression/include/dc_header_footer.h quickassist/lookaside/access_layer/src/common/compression/include/dc_header_footer_lz4.h quickassist/lookaside/access_layer/src/common/compression/include/dc_ns_datapath.h quickassist/lookaside/access_layer/src/common/compression/include/dc_session.h quickassist/lookaside/access_layer/src/common/compression/include/dc_stats.h quickassist/lookaside/access_layer/src/common/compression/include/dc_xxhash32.h quickassist/lookaside/access_layer/src/common/compression/reg_sizes.asm quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_control_path.c quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_data_path.c quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_interface_check.c quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_stats.c quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/lac_dh_stats_p.h quickassist/lookaside/access_layer/src/common/crypto/asym/dsa/lac_dsa.c quickassist/lookaside/access_layer/src/common/crypto/asym/dsa/lac_dsa_interface_check.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_common.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_montedwds.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_nist_curves.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecdh.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecdsa.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecsm2.c quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_kpt_ecdsa.c quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_dsa.h quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_ec.h quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_ec_nist_curves.h quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_ln.h quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_pke_mmp.h quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_pke_qat_comms.h quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_pke_utils.h quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_prime.h quickassist/lookaside/access_layer/src/common/crypto/asym/large_number/lac_ln.c quickassist/lookaside/access_layer/src/common/crypto/asym/large_number/lac_ln_interface_check.c quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_mmp.c quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_qat_comms.c quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_utils.c quickassist/lookaside/access_layer/src/common/crypto/asym/prime/lac_prime.c quickassist/lookaside/access_layer/src/common/crypto/asym/prime/lac_prime_interface_check.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_kpt_rsa_decrypt.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_control_path.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_decrypt.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_encrypt.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_interface_check.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_keygen.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_p.h quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_stats.c quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_stats_p.h quickassist/lookaside/access_layer/src/common/crypto/kpt/provision/lac_kpt_provision.c quickassist/lookaside/access_layer/src/common/crypto/sym/drbg/lac_sym_drbg_api.c quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_session.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_alg_chain.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_auth_enc.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_cb.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_cipher.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_cipher_defs.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_hash.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_hash_defs.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_hash_precomputes.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_key.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_partial.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_cipher.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_constants_table.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_hash.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_key.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_queue.h quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_stats.h quickassist/lookaside/access_layer/src/common/crypto/sym/key/lac_sym_key.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_alg_chain.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_api.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_auth_enc.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_cb.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_cipher.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_compile_check.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_dp.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_hash.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_hash_hw_precomputes.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_hash_sw_precomputes.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_partial.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_queue.c quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_stats.c quickassist/lookaside/access_layer/src/common/crypto/sym/nrbg/lac_sym_nrbg_api.c quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat.c quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_cipher.c quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_constants_table.c quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_hash.c quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_key.c quickassist/lookaside/access_layer/src/common/ctrl/sal_compression.c quickassist/lookaside/access_layer/src/common/ctrl/sal_compression_capabilities.c quickassist/lookaside/access_layer/src/common/ctrl/sal_create_services.c quickassist/lookaside/access_layer/src/common/ctrl/sal_crypto.c quickassist/lookaside/access_layer/src/common/ctrl/sal_ctrl_services.c quickassist/lookaside/access_layer/src/common/ctrl/sal_dc_chain.c quickassist/lookaside/access_layer/src/common/ctrl/sal_instances.c quickassist/lookaside/access_layer/src/common/ctrl/sal_list.c quickassist/lookaside/access_layer/src/common/ctrl/sal_rl_stubs.c quickassist/lookaside/access_layer/src/common/device/sal_dev_info.c quickassist/lookaside/access_layer/src/common/include/lac_buffer_desc.h quickassist/lookaside/access_layer/src/common/include/lac_common.h quickassist/lookaside/access_layer/src/common/include/lac_hooks.h quickassist/lookaside/access_layer/src/common/include/lac_list.h quickassist/lookaside/access_layer/src/common/include/lac_log.h quickassist/lookaside/access_layer/src/common/include/lac_mem.h quickassist/lookaside/access_layer/src/common/include/lac_mem_pools.h quickassist/lookaside/access_layer/src/common/include/lac_sal.h quickassist/lookaside/access_layer/src/common/include/lac_sal_ctrl.h quickassist/lookaside/access_layer/src/common/include/lac_sal_types.h quickassist/lookaside/access_layer/src/common/include/lac_sal_types_crypto.h quickassist/lookaside/access_layer/src/common/include/lac_sw_responses.h quickassist/lookaside/access_layer/src/common/include/lac_sync.h quickassist/lookaside/access_layer/src/common/include/sal_instances.h quickassist/lookaside/access_layer/src/common/include/sal_misc_error_stats.h quickassist/lookaside/access_layer/src/common/include/sal_qat_cmn_msg.h quickassist/lookaside/access_layer/src/common/include/sal_service_state.h quickassist/lookaside/access_layer/src/common/include/sal_statistics.h quickassist/lookaside/access_layer/src/common/include/sal_string_parse.h quickassist/lookaside/access_layer/src/common/include/sal_types_compression.h quickassist/lookaside/access_layer/src/common/qat_comms/sal_qat_cmn_msg.c quickassist/lookaside/access_layer/src/common/utils/lac_buffer_desc.c quickassist/lookaside/access_layer/src/common/utils/lac_lock_free_stack.h quickassist/lookaside/access_layer/src/common/utils/lac_log_message.c quickassist/lookaside/access_layer/src/common/utils/lac_mem.c quickassist/lookaside/access_layer/src/common/utils/lac_mem_pools.c quickassist/lookaside/access_layer/src/common/utils/lac_sw_responses.c quickassist/lookaside/access_layer/src/common/utils/lac_sync.c quickassist/lookaside/access_layer/src/common/utils/sal_misc_error_stats.c quickassist/lookaside/access_layer/src/common/utils/sal_service_state.c quickassist/lookaside/access_layer/src/common/utils/sal_statistics.c quickassist/lookaside/access_layer/src/common/utils/sal_string_parse.c quickassist/lookaside/access_layer/src/common/utils/sal_user_process.c quickassist/lookaside/access_layer/src/common/utils/sal_versions.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_bundles.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_cfg.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_ring.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_user_proxy.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_cfg.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_ring.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_user_bundles.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_user_proxy.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_msg.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_proto.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_proto.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_vf_msg.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_vf_msg.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_vfio_pf.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_vfio_pf.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_log.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_log.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr_client.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr_lib.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_lib.c quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_lib.h quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_mgr_lib.c quickassist/lookaside/access_layer/src/qat_direct/include/adf_dev_ring_ctl.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_devmgr.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_init.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_platform.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_platform_acceldev_common.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_platform_acceldev_gen4.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_platform_common.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_user.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_arbiter.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_cfg.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_init.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_ring.h quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_transport.h quickassist/lookaside/access_layer/src/qat_direct/include/icp_platform.h quickassist/lookaside/access_layer/src/qat_direct/include/icp_platform_user.h quickassist/lookaside/access_layer/src/qat_direct/io/adf_process_proxy.c quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_ETring_mgr_dp.c quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_cfg.c quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_device.c quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_init.c quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_ring.c quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_transport_ctrl.c quickassist/lookaside/access_layer/src/sample_code/README.txt quickassist/lookaside/access_layer/src/sample_code/busy_loop/busy_loop.c quickassist/lookaside/access_layer/src/sample_code/busy_loop/busy_loop.h quickassist/lookaside/access_layer/src/sample_code/functional/asym/diffie_hellman_sample/cpa_dh_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/diffie_hellman_sample/cpa_dh_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/ec_montedwds_sample/cpa_ec_montedwds_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/ec_montedwds_sample/cpa_ec_montedwds_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_big_num.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_big_num.h quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_ed_point_operations.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_ed_point_operations.h quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_eddsa_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_eddsa_sample.h quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/cpa_eddsa_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/prime_sample/cpa_prime_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/asym/prime_sample/cpa_prime_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/common/cpa_sample_utils.c quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/cpa_chaining_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/cpa_chaining_sample_input.h quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/cpa_chaining_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/dc/dc_dp_sample/cpa_dc_dp_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/dc/dc_dp_sample/cpa_dc_dp_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_multi_op_checksum_sample/cpa_dc_stateless_multi_op_checksum_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/cpa_dc_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/cpa_dc_stateless_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/include/cpa_sample_cnv_utils.h quickassist/lookaside/access_layer/src/sample_code/functional/include/cpa_sample_utils.h quickassist/lookaside/access_layer/src/sample_code/functional/sym/alg_chaining_sample/cpa_algchaining_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/alg_chaining_sample/cpa_algchaining_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/ccm_sample/cpa_ccm_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/ccm_sample/cpa_ccm_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/cipher_sample/cpa_cipher_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/cipher_sample/cpa_cipher_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/gcm_sample/cpa_gcm_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/gcm_sample/cpa_gcm_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_file_sample/cpa_hash_file_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_file_sample/cpa_hash_file_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_sample/cpa_hash_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_sample/cpa_hash_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/cpa_hkdf_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/cpa_hkdf_sample_linux_kernel_module.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/cpa_hkdf_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/ipsec_sample/cpa_ipsec_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/ipsec_sample/cpa_ipsec_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/cpa_sample_decrypt_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/cpa_ssl_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/cpa_ssl_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/symdp_sample/cpa_sym_dp_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/symdp_sample/cpa_sym_dp_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/update_sample/cpa_sym_dp_update_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/update_sample/cpa_sym_dp_update_sample_user.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/zuc_sample/cpa_zuc_sample.c quickassist/lookaside/access_layer/src/sample_code/functional/sym/zuc_sample/cpa_zuc_sample_user.c quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_buffer_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_buffer_utils.h quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_cycles.h quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_latency.c quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_latency.h quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_sleeptime.c quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_sleeptime.h quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/common/qat_perf_utils.h quickassist/lookaside/access_layer/src/sample_code/performance/compression/calgary quickassist/lookaside/access_layer/src/sample_code/performance/compression/calgary32 quickassist/lookaside/access_layer/src/sample_code/performance/compression/canterbury quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_dp.c quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_dp.h quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_perf.h quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_dc_utils.h quickassist/lookaside/access_layer/src/sample_code/performance/compression/cpa_sample_code_zlib.c quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_chaining_main.c quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_cnv_utils.h quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_e2e.c quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_e2e.h quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_main.c quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_main.h quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/compression/qat_compression_zlib.h quickassist/lookaside/access_layer/src/sample_code/performance/cpa_sample_code_main.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_cipher_perf2.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_crypto_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_crypto_utils.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_dh_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_drbg_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_drbg_perf.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_dsa_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ec_curves.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ec_montedwds_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ec_montedwds_vectors.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ec_montedwds_vectors.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ecdsa_kpt2_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ecdsa_kpt2_perf.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ecdsa_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ike_dsa_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_ike_rsa_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_kpt2_common.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_kpt2_common.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_nrbg_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_nrbg_perf.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_rsa_kpt2_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_rsa_kpt2_perf.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_rsa_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_Keyex_P1_P2.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_enc_dec.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_kdf_hash.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_perf.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sm2_sign_verify.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_perf.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_perf_dp.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_perf_dp.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update_common.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update_common.h quickassist/lookaside/access_layer/src/sample_code/performance/crypto/cpa_sample_code_sym_update_dp.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_main.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_utils.h quickassist/lookaside/access_layer/src/sample_code/performance/framework/cpa_sample_code_framework.c quickassist/lookaside/access_layer/src/sample_code/performance/framework/cpa_sample_code_framework.h quickassist/lookaside/access_layer/src/sample_code/performance/framework/cpa_sample_code_utils_common.h quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/user_space/cpa_sample_code_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/user_space/cpa_sample_code_utils.h quickassist/lookaside/access_layer/src/sample_code/performance/qae/linux/kernel_space/qae_mem_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/qae/linux/user_space/qae_mem_utils.c quickassist/lookaside/access_layer/src/sample_code/performance/qae/qae_mem.h quickassist/lookaside/access_layer/src/sample_code/performance/qae/qae_mem_utils.h quickassist/lookaside/access_layer/src/user/sal_user.c quickassist/lookaside/access_layer/src/user/sal_user_congestion_mgmt.c quickassist/lookaside/access_layer/src/user/sal_user_dyn_instance.c quickassist/lookaside/firmware/include/icp_qat_fw.h quickassist/lookaside/firmware/include/icp_qat_fw_comp.h quickassist/lookaside/firmware/include/icp_qat_fw_dc_chain.h quickassist/lookaside/firmware/include/icp_qat_fw_init_admin.h quickassist/lookaside/firmware/include/icp_qat_fw_la.h quickassist/lookaside/firmware/include/icp_qat_fw_mmp.h quickassist/lookaside/firmware/include/icp_qat_fw_mmp_ids.h quickassist/lookaside/firmware/include/icp_qat_fw_pke.h quickassist/lookaside/firmware/include/icp_qat_hw.h quickassist/lookaside/firmware/include/icp_qat_hw_20_comp.h quickassist/lookaside/firmware/include/icp_qat_hw_20_comp_defs.h quickassist/utilities/libusdm_drv/include/qae_mem_utils.h quickassist/utilities/libusdm_drv/qae_mem.h quickassist/utilities/libusdm_drv/user_space/qae_mem_common.c quickassist/utilities/libusdm_drv/user_space/qae_mem_hugepage_utils.h quickassist/utilities/libusdm_drv/user_space/qae_mem_lib_utils.h quickassist/utilities/libusdm_drv/user_space/qae_mem_multi_thread.h quickassist/utilities/libusdm_drv/user_space/qae_mem_multi_thread_utils.c quickassist/utilities/libusdm_drv/user_space/qae_mem_user_utils.h quickassist/utilities/libusdm_drv/user_space/qae_mem_utils_common.c quickassist/utilities/libusdm_drv/user_space/qae_mem_utils_common.h quickassist/utilities/libusdm_drv/user_space/qae_page_table_common.h quickassist/utilities/libusdm_drv/user_space/qae_page_table_defs.h quickassist/utilities/libusdm_drv/user_space/vfio/qae_mem_hugepage_utils_vfio.c quickassist/utilities/libusdm_drv/user_space/vfio/qae_mem_utils_vfio.c quickassist/utilities/osal/include/Osal.h quickassist/utilities/osal/include/OsalDevDrvCommon.h quickassist/utilities/osal/include/OsalTypes.h quickassist/utilities/osal/src/linux/user_space/OsalAtomic.c quickassist/utilities/osal/src/linux/user_space/OsalCryptoInterface.c quickassist/utilities/osal/src/linux/user_space/OsalMutex.c quickassist/utilities/osal/src/linux/user_space/OsalSemaphore.c quickassist/utilities/osal/src/linux/user_space/OsalServices.c quickassist/utilities/osal/src/linux/user_space/OsalSpinLock.c quickassist/utilities/osal/src/linux/user_space/OsalThread.c quickassist/utilities/osal/src/linux/user_space/OsalUsrKrnProxy.c quickassist/utilities/osal/src/linux/user_space/include/OsalDevDrv.h quickassist/utilities/osal/src/linux/user_space/include/OsalOsTypes.h quickassist/utilities/qat_mgr/qat_mgr.c quickassist/utilities/service/qat quickassist/utilities/service/qat.service.in quickassist/utilities/service/qat_init.sh.in versionfile qatlib-25.08.0/libqat.pc.in000066400000000000000000000004201503624047500153510ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libqat Description: User space library that allows to access Intel QAT devices Version: @VERSION@ Libs: -L${libdir} -l@LIBQATNAME@ Cflags: -I${includedir} Requires: libusdm libcrypto qatlib-25.08.0/libusdm.pc.in000066400000000000000000000003441503624047500155410ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libusdm Description: User space library for memory management Version: @VERSION@ Libs: -L${libdir} -l@LIBUSDMNAME@ Cflags: -I${includedir} qatlib-25.08.0/qat_init.sh.8000066400000000000000000000053311503624047500154640ustar00rootroot00000000000000.\" Copyright(c) 2007-2019 Intel Corporation. All rights reserved. .\" All rights reserved. .\" .\" %%%LICENSE_START(BSD_3_CLAUSE) .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" * Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" * Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in .\" the documentation and/or other materials provided with the .\" distribution. .\" * Neither the name of Intel Corporation nor the names of its .\" contributors may be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR .\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT .\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, .\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT .\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" %%%LICENSE_END .TH qat_init.sh 8 "30 Oct 2019" qat_init.sh man page .SH NAME qat_init.sh \- QAT resource initializer .SY qat_init.sh .SH SYNOPSIS .B qat_init.sh .SH DESCRIPTION .B qat_init.sh initializes the Intel\(co Quick Assist Technology (Intel\(co QAT) devices in preparation for use by the user space library (qatlib). .PP When run on a host system with physical function (PF) QAT devices visible and bound to the QAT device driver, the qat_init.sh script will enable sriov on each of the PF devices. This enables the virtual function (VF) devices. .PP For each of the QAT VF devices, the qat_init.sh binds the device to the vfio-pci device driver, making it available for applications using the qatlib user space library. .SH ENVIRONMENT VARIABLES \fBLKCF_LIST\fR if set, gives a list of VF devices that should be used for accelerating operations from the Linux crypto framework instead of being available for user space applications. .PP Example: .EX LKCF_LIST="0000:3d:01.0 0000:3f:01.0 0000:da:01.0" .EE .SH SEE ALSO qatmgr(8) .SH AUTHOR Conor McLoughlin qatlib-25.08.0/qatlib.pc.in000066400000000000000000000004151503624047500153550ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: qatlib Description: Provides access to Intel QAT hardware accelerated cryptography and compression URL: https://github.com/intel/qatlib Version: @VERSION@ Requires: libqat libusdm qatlib-25.08.0/qatlib.spec.in000066400000000000000000000177301503624047500157150ustar00rootroot00000000000000# SPDX-License-Identifier: MIT %global libqat_soversion 4 %global libusdm_soversion 0 Name: @PACKAGE@ Version: @VERSION@ Release: 1%{?dist} Summary: Intel QuickAssist user space library # The entire source code is released under BSD. # For a breakdown of inbound licenses see the INSTALL file. License: BSD-3-Clause AND ( BSD-3-Clause OR GPL-2.0-only ) URL: https://github.com/intel/%{name} Source0: https://github.com/intel/%{name}/archive/%{version}/%{name}-%{version}.tar.gz BuildRequires: systemd gcc make autoconf autoconf-archive automake libtool systemd-devel openssl-devel zlib-devel nasm numactl-devel Recommends: qatlib-service # https://bugzilla.redhat.com/show_bug.cgi?id=1897661 ExcludeArch: %{arm} aarch64 %{power64} s390x i686 %description Intel QuickAssist Technology (Intel QAT) provides hardware acceleration for offloading security, authentication and compression services from the CPU, thus significantly increasing the performance and efficiency of standard platform solutions. Its services include symmetric encryption and authentication, asymmetric encryption, digital signatures, RSA, DH and ECC, and lossless data compression. This package provides user space libraries that allow access to Intel QuickAssist devices and expose the Intel QuickAssist APIs. %package devel Summary: Headers and libraries to build applications that use qatlib Requires: %{name}%{?_isa} = %{version}-%{release} %description devel This package contains headers and libraries required to build applications that use the Intel QuickAssist APIs. %package tests Summary: Sample applications that use qatlib Requires: %{name}%{?_isa} = %{version}-%{release} %description tests This package contains sample applications that use the Intel QuickAssists APIs. %package service Summary: A daemon for qatlib resources management Requires: %{name}%{?_isa} = %{version}-%{release} %{?systemd_requires} %description service This package contains a daemon that manages QAT resources for the Intel QuickAssist Technology user space library (qatlib). %prep %autosetup -p1 # Create a sysusers.d config file cat >qatlib.sysusers.conf < - 25.08.0-1 - Update to qatlib 25.08.0 * Thu Jan 23 2025 Giovanni Cabiddu - 24.09.0-6 - Add patch to remove hardcoded installation path to fix the build on F42 * Sat Jan 18 2025 Fedora Release Engineering - 24.09.0-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild * Tue Oct 01 2024 Vladis Dronov - 24.09.0-4 - Update to qatlib 24.09.0 @ 36fb0903 * Mon Sep 16 2024 Giovanni Cabiddu - 24.09.0-3 - Move pciutils as a dependency of the qat-service subpackage * Mon Sep 16 2024 Giovanni Cabiddu - 24.09.0-2 - Add pciutils as a dependency as required by qatlib * Thu Sep 05 2024 Berenike Bronikowska - 24.09.0-1 - Add dependency on numactl-devel. - Update to qatlib 24.09.0 * Thu Feb 08 2024 Xinghong Chen - 24.02.0-1 - Add the zuc_sample to tests package. - Update to qatlib 24.02.0 * Thu Feb 08 2024 Vladis Dronov - 23.11.0-2 - Use proper SPDX license identifiers * Fri Oct 27 2023 Michal Ferenc - 23.11.0-1 - Update to qatlib 23.11.0 * Fri Aug 18 2023 Michal Ferenc - 23.08.0-1 - Add the chaining_sample to tests package. - Update to qatlib 23.08.0 * Mon Jan 23 2023 Fiona Trahe - 23.02.0-1 - Update to qatlib 23.02.0 * Thu Nov 03 2022 Fiona Trahe - 22.07.2-1 - Update to qatlib 22.07.2 * Tue Nov 01 2022 Giovanni Cabiddu - 22.07.1-2 - Add support for pkgconfig * Tue Oct 04 2022 Michal Ferenc - 22.07.1-1 - Update to qatlib 22.07.1 * Fri Jul 22 2022 Fedora Release Engineering - 22.07.0-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild * Fri Jul 22 2022 Giovanni Cabiddu - 22.07.0-1 - Update to qatlib 22.07 - Removed patches as fixes are present in qatlib 22.07 - Moved qat.service to separate rpm * Tue Mar 22 2022 Vladis Dronov - 21.11.0-3 - Fix small issues in qatlib-tests package - Update documentation from the upstream * Fri Jan 21 2022 Fedora Release Engineering - 21.11.0-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild * Fri Oct 15 2021 Marcin Malinowski - 21.11-0-1 - Update to qatlib 21.11 - Add qatlib-tests package * Tue Sep 14 2021 Sahana Prasad - 21.08.0-2 - Rebuilt with OpenSSL 3.0.0 * Wed Aug 11 2021 Mateusz Polrola - 21.08-0-1 - Update to qatlib 21.08 * Wed Apr 14 2021 Giovanni Cabiddu - 21.05.0-1 - Update to qatlib 21.05 * Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 20.10.0-4 - Rebuilt for updated systemd-rpm-macros See https://pagure.io/fesco/issue/2583. * Wed Jan 27 2021 Fedora Release Engineering - 20.10.0-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild * Mon Dec 14 2020 Giovanni Cabiddu - 20.10.0-2 - Add ExcludeArch i686 * Mon Nov 16 2020 Giovanni Cabiddu - 20.10.0-1 - Update to qatlib 20.10 - Fixes to spec to address comments from Fedora review * Mon Aug 10 2020 Mateusz Polrola - 20.08.0-1 - Initial version of the package qatlib-25.08.0/qatmgr.8000066400000000000000000000055251503624047500145430ustar00rootroot00000000000000.\" Copyright(c) 2007-2019 Intel Corporation. All rights reserved. .\" All rights reserved. .\" .\" %%%LICENSE_START(BSD_3_CLAUSE) .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" * Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" * Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in .\" the documentation and/or other materials provided with the .\" distribution. .\" * Neither the name of Intel Corporation nor the names of its .\" contributors may be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR .\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT .\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, .\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT .\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" %%%LICENSE_END .TH qatmgr 8 "30 Oct 2019" qatmgr man page .SH NAME qatmgr \- QAT resource manager .SY qatmgr .SH SYNOPSIS .B qatmgr [option]... .SH DESCRIPTION .B qatmgr is a daemon that manages QAT resources for the Intel\(co Quick Assist Technology (Intel\(co QAT) user space library (qatlib). .SH OPTIONS .TP \fB\-d\fR, \fB\-\-debug=LEVEL\fR set debug level, default 0 for no debug. Higher debug level produces more output. .TP \fB\-f\fR, \fB\-\-foreground\fR run in the foreground. By default, the qatmgr runs as a daemon in the background. .TP \fB\-h\fR, \fB\-\-help\fR display help page .TP \fB\-p\fR, \fB\-\-policy=POLICY\fR selects the QAT manager policy. This determines how resources should be allocated to each process using the qatlib library. The default POLICY 0 allocates one virtual function (VF) from each physical function (PF) endpoint to each process. This should be selected for best performance. A POLICY of 1 allocates a single VF to each process. This should be selected for maximum scalability. Any other POLICY value allocates that number of VFs to each process. .SH SEE ALSO qat_init.sh(8) .SH FILES /run/qat/qatmgr.pid /tmp/qat.sock .SH AUTHOR Conor McLoughlin qatlib-25.08.0/quickassist/000077500000000000000000000000001503624047500155135ustar00rootroot00000000000000qatlib-25.08.0/quickassist/include/000077500000000000000000000000001503624047500171365ustar00rootroot00000000000000qatlib-25.08.0/quickassist/include/cpa.h000066400000000000000000001207141503624047500200570ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa.h * * @defgroup cpa CPA API * * @description * This is the top level API definition for Intel(R) QuickAssist * Technology. It contains structures, data types and definitions that are * common across the interface. * *****************************************************************************/ /** ***************************************************************************** * @defgroup cpa_BaseDataTypes Base Data Types * @file cpa.h * * @ingroup cpa * * @description * The base data types for the Intel CPA API. * *****************************************************************************/ #ifndef CPA_H #define CPA_H #ifdef __cplusplus extern "C" { #endif #include "cpa_types.h" /** ****************************************************************************** * @ingroup cpa * CPA Version Number * @description * The CPA API version. This has major and minor definitions and the * combination of those represent the complete version number for this * interface. It will be incremented on code changes in the C headers in * the top-level directory and its subdirectories. Helper macros are * provided to simplify version number comparisons for "at least" and * "less than" cases. * @note * The CPA API version supersedes the DC and CY versions already existing * which represent subsets of this interface. The CPA version will start * at v5.0 and the CY and DC versions will move to the same version and * be kept in line with it in future. * @note * Applications which are intended to be compiled against both this version * and earlier versions of the API which did not include this CPA version * should never use the macros with values less than 5.0 and should use the * following pattern to avoid compilation issues: * #ifdef CPA_API_VERSION_AT_LEAST * #if CPA_API_VERSION_AT_LEAST(5,2) * < call APIs that only exist in v5.2 > * #endif * #endif * *****************************************************************************/ /** ****************************************************************************** * @ingroup cpa * CPA Major Version Number * @description * The CPA API major version number. This number will be incremented * when significant changes to the API have occurred. * *****************************************************************************/ #define CPA_API_VERSION_NUM_MAJOR (5) /** ***************************************************************************** * @ingroup cpa * CPA Minor Version Number * @description * The CPA API minor version number. This number will be incremented * when minor changes to the API have occurred. * *****************************************************************************/ #define CPA_API_VERSION_NUM_MINOR (6) /** ***************************************************************************** * @ingroup cpa * CPA API version at least * @description * The minimal supported CPA API version. Allow to check if the API * version is equal or above some version to avoid compilation issues * with an older API version. * *****************************************************************************/ #define CPA_API_VERSION_AT_LEAST(major, minor) \ (CPA_API_VERSION_NUM_MAJOR > major || \ (CPA_API_VERSION_NUM_MAJOR == major && \ CPA_API_VERSION_NUM_MINOR >= minor)) /** ***************************************************************************** * @ingroup cpa * CPA API version less than * @description * The maximum supported CPA API version. Allow to check if the API * version is below some version to avoid compilation issues with a newer * API version. * *****************************************************************************/ #define CPA_API_VERSION_LESS_THAN(major, minor) \ (CPA_API_VERSION_NUM_MAJOR < major || \ (CPA_API_VERSION_NUM_MAJOR == major && \ CPA_API_VERSION_NUM_MINOR < minor)) /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Instance handle type. * * @description * Handle used to uniquely identify an instance. * * @note * Where only a single instantiation exists this field may be set to * @ref CPA_INSTANCE_HANDLE_SINGLE. * *****************************************************************************/ typedef void *CpaInstanceHandle; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Default instantiation handle value where there is only a single instance * * @description * Used as an instance handle value where only one instance exists. * *****************************************************************************/ #define CPA_INSTANCE_HANDLE_SINGLE ((CpaInstanceHandle)0) /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Physical memory address. * @description * Type for physical memory addresses. *****************************************************************************/ typedef Cpa64U CpaPhysicalAddr; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Virtual to physical address conversion routine. * * @description * This function is used to convert virtual addresses to physical * addresses. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] pVirtualAddr Virtual address to be converted. * * @return * Returns the corresponding physical address. * On error, the value NULL is returned. * * @post * None * @see * None * *****************************************************************************/ typedef CpaPhysicalAddr (*CpaVirtualToPhysical)(void *pVirtualAddr); /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Flat buffer structure containing a pointer and length member. * * @description * A flat buffer structure. The data pointer, pData, is a virtual address. * An API instance may require the actual data to be in contiguous * physical memory as determined by @ref CpaInstanceInfo2. * *****************************************************************************/ typedef struct _CpaFlatBuffer { Cpa32U dataLenInBytes; /**< Data length specified in bytes. * When used as an input parameter to a function, the length specifies * the current length of the buffer. * When used as an output parameter to a function, the length passed in * specifies the maximum length of the buffer on return (i.e. the allocated * length). The implementation will not write past this length. On return, * the length is always unchanged. */ Cpa8U *pData; /**< The data pointer is a virtual address, however the actual data pointed * to is required to be in contiguous physical memory unless the field requiresPhysicallyContiguousMemory in CpaInstanceInfo2 is false. */ } CpaFlatBuffer; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Scatter/Gather buffer list containing an array of flat buffers. * * @description * A scatter/gather buffer list structure. This buffer structure is * typically used to represent a region of memory which is not * physically contiguous, by describing it as a collection of * buffers, each of which is physically contiguous. * * @note * The memory for the pPrivateMetaData member must be allocated * by the client as physically contiguous memory. When allocating * memory for pPrivateMetaData, a call to the corresponding * BufferListGetMetaSize function (e.g. cpaCyBufferListGetMetaSize) * MUST be made to determine the size of the Meta Data Buffer. The * returned size (in bytes) may then be passed in a memory allocation * routine to allocate the pPrivateMetaData memory. *****************************************************************************/ typedef struct _CpaBufferList { Cpa32U numBuffers; /**< Number of buffers in the list */ CpaFlatBuffer *pBuffers; /**< Pointer to an unbounded array containing the number of CpaFlatBuffers * defined by numBuffers */ void *pUserData; /**< This is an opaque field that is not read or modified internally. */ void *pPrivateMetaData; /**< Private representation of this buffer list. The memory for this * buffer needs to be allocated by the client as contiguous data. * The amount of memory required is returned with a call to * the corresponding BufferListGetMetaSize function. If that function * returns a size of zero then no memory needs to be allocated, and this * parameter can be NULL. */ } CpaBufferList; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Flat buffer structure with physical address. * * @description * Functions taking this structure do not need to do any virtual to * physical address translation before writing the buffer to hardware. *****************************************************************************/ typedef struct _CpaPhysFlatBuffer { Cpa32U dataLenInBytes; /**< Data length specified in bytes. * When used as an input parameter to a function, the length specifies * the current length of the buffer. * When used as an output parameter to a function, the length passed in * specifies the maximum length of the buffer on return (i.e. the allocated * length). The implementation will not write past this length. On return, * the length is always unchanged. */ Cpa32U reserved; /**< Reserved for alignment */ CpaPhysicalAddr bufferPhysAddr; /**< The physical address at which the data resides. The data pointed * to is required to be in contiguous physical memory. */ } CpaPhysFlatBuffer; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Scatter/gather list containing an array of flat buffers with * physical addresses. * * @description * Similar to @ref CpaBufferList, this buffer structure is typically * used to represent a region of memory which is not physically * contiguous, by describing it as a collection of buffers, each of * which is physically contiguous. The difference is that, in this * case, the individual "flat" buffers are represented using * physical, rather than virtual, addresses. *****************************************************************************/ typedef struct _CpaPhysBufferList { Cpa64U reserved0; /**< Reserved for internal usage */ Cpa32U numBuffers; /**< Number of buffers in the list */ Cpa32U reserved1; /**< Reserved for alignment */ CpaPhysFlatBuffer flatBuffers[]; /**< Array of flat buffer structures, of size numBuffers */ } CpaPhysBufferList; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Crc Control data structure for programmable CRC engine. * @description * This structure specifies CRC algorithm parameters which are used * to configure a programmable CRC engine. It can be used to specify a * CRC algorithm, other than those natively supported by the API. * ****************************************************************************/ typedef struct _CpaCrcControlData { Cpa64U polynomial; /**< Polynomial used for CRC64 calculation.*/ Cpa64U initialValue; /**< Initial value to be used for seeding the CRC. */ CpaBoolean reflectIn; /**< Reflect bit order before CRC calculation. */ CpaBoolean reflectOut; /**< Reflect bit order after CRC calculation. */ Cpa64U xorOut; /**< XOR pattern to XOR with the final CRC residue after any output * reflection */ } CpaCrcControlData; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Special value which can be taken by length fields on some of the * "data plane" APIs to indicate that the buffer in question is of * type CpaPhysBufferList, rather than simply an array of bytes. ****************************************************************************/ #define CPA_DP_BUFLIST ((Cpa32U)0xFFFFFFFF) /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * API status value type definition * * @description * This type definition is used for the return values used in all the * API functions. Common values are defined, for example see * @ref CPA_STATUS_SUCCESS, @ref CPA_STATUS_FAIL, etc. *****************************************************************************/ typedef Cpa32S CpaStatus; #define CPA_STATUS_SUCCESS (0) /**< * @ingroup cpa_BaseDataTypes * Success status value. */ #define CPA_STATUS_FAIL (-1) /**< * @ingroup cpa_BaseDataTypes * Fail status value. */ #define CPA_STATUS_RETRY (-2) /**< * @ingroup cpa_BaseDataTypes * Retry status value. */ #define CPA_STATUS_RESOURCE (-3) /**< * @ingroup cpa_BaseDataTypes * The resource that has been requested is unavailable. Refer * to relevant sections of the API for specifics on what the suggested * course of action is. */ #define CPA_STATUS_INVALID_PARAM (-4) /**< * @ingroup cpa_BaseDataTypes * Invalid parameter has been passed in. */ #define CPA_STATUS_FATAL (-5) /**< * @ingroup cpa_BaseDataTypes * A serious error has occurred. Recommended course of action * is to shutdown and restart the component. */ #define CPA_STATUS_UNSUPPORTED (-6) /**< * @ingroup cpa_BaseDataTypes * The function is not supported, at least not with the specific * parameters supplied. This may be because a particular * capability is not supported by the current implementation. */ #define CPA_STATUS_RESTARTING (-7) /**< * @ingroup cpa_BaseDataTypes * The API implementation is restarting. This may be reported if, for example, * a hardware implementation is undergoing a reset. Recommended course of * action is to retry the request. */ /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * API status string type definition * @description * This type definition is used for the generic status text strings * provided by cpaXxGetStatusText API functions. Common values are * defined, for example see @ref CPA_STATUS_STR_SUCCESS, * @ref CPA_STATUS_FAIL, etc., as well as the maximum size * @ref CPA_STATUS_MAX_STR_LENGTH_IN_BYTES. *****************************************************************************/ #define CPA_STATUS_MAX_STR_LENGTH_IN_BYTES (255) /**< * @ingroup cpa_BaseDataTypes * Maximum length of the Overall Status String (including generic and specific * strings returned by calls to cpaXxGetStatusText) */ #define CPA_STATUS_STR_SUCCESS ("Operation was successful:") /**< * @ingroup cpa_BaseDataTypes * Status string for @ref CPA_STATUS_SUCCESS. */ #define CPA_STATUS_STR_FAIL ("General or unspecified error occurred:") /**< * @ingroup cpa_BaseDataTypes * Status string for @ref CPA_STATUS_FAIL. */ #define CPA_STATUS_STR_RETRY ("Recoverable error occurred:") /**< * @ingroup cpa_BaseDataTypes * Status string for @ref CPA_STATUS_RETRY. */ #define CPA_STATUS_STR_RESOURCE ("Required resource unavailable:") /**< * @ingroup cpa_BaseDataTypes * Status string for @ref CPA_STATUS_RESOURCE. */ #define CPA_STATUS_STR_INVALID_PARAM ("Invalid parameter supplied:") /**< * @ingroup cpa_BaseDataTypes * Status string for @ref CPA_STATUS_INVALID_PARAM. */ #define CPA_STATUS_STR_FATAL ("Fatal error has occurred:") /**< * @ingroup cpa_BaseDataTypes * Status string for @ref CPA_STATUS_FATAL. */ #define CPA_STATUS_STR_UNSUPPORTED ("Operation not supported:") /**< * @ingroup cpa_BaseDataTypes * Status string for @ref CPA_STATUS_UNSUPPORTED. */ /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Instance Types * * @deprecated * As of v1.3 of the Crypto API, this enum has been deprecated, * replaced by @ref CpaAccelerationServiceType. * * @description * Enumeration of the different instance types. * *****************************************************************************/ typedef enum _CpaInstanceType { CPA_INSTANCE_TYPE_CRYPTO = 0, /**< Cryptographic instance type */ CPA_INSTANCE_TYPE_DATA_COMPRESSION, /**< Data compression instance type */ CPA_INSTANCE_TYPE_RAID, /**< RAID instance type */ CPA_INSTANCE_TYPE_XML, /**< XML instance type */ CPA_INSTANCE_TYPE_REGEX /**< Regular Expression instance type */ } CpaInstanceType CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Service Type * @description * Enumeration of the different service types. * *****************************************************************************/ typedef enum _CpaAccelerationServiceType { CPA_ACC_SVC_TYPE_CRYPTO = CPA_INSTANCE_TYPE_CRYPTO, /**< Cryptography */ CPA_ACC_SVC_TYPE_DATA_COMPRESSION = CPA_INSTANCE_TYPE_DATA_COMPRESSION, /**< Data Compression */ CPA_ACC_SVC_TYPE_PATTERN_MATCH = CPA_INSTANCE_TYPE_REGEX, /**< Pattern Match */ CPA_ACC_SVC_TYPE_RAID = CPA_INSTANCE_TYPE_RAID, /**< RAID */ CPA_ACC_SVC_TYPE_XML = CPA_INSTANCE_TYPE_XML, /**< XML */ CPA_ACC_SVC_TYPE_VIDEO_ANALYTICS = 4, /**< Video Analytics */ CPA_ACC_SVC_TYPE_CRYPTO_ASYM = 5, /**< Cryptography - Asymmetric service */ CPA_ACC_SVC_TYPE_CRYPTO_SYM = 6, /**< Cryptography - Symmetric service */ CPA_ACC_SVC_TYPE_DATA_DECOMPRESSION = 7 /**< Data Decompression service */ } CpaAccelerationServiceType; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Instance State * * @deprecated * As of v1.3 of the Crypto API, this enum has been deprecated, * replaced by @ref CpaOperationalState. * * @description * Enumeration of the different instance states that are possible. * *****************************************************************************/ typedef enum _CpaInstanceState { CPA_INSTANCE_STATE_INITIALISED = 0, /**< Instance is in the initialized state and ready for use. */ CPA_INSTANCE_STATE_SHUTDOWN /**< Instance is in the shutdown state and not available for use. */ } CpaInstanceState CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Instance operational state * @description * Enumeration of the different operational states that are possible. * *****************************************************************************/ typedef enum _CpaOperationalState { CPA_OPER_STATE_DOWN = 0, /**< Instance is not available for use. May not yet be initialized, * or stopped. */ CPA_OPER_STATE_UP /**< Instance is available for use. Has been initialized and started. */ } CpaOperationalState; #define CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES 64 /**< * @ingroup cpa_BaseDataTypes * Maximum instance info name string length in bytes */ #define CPA_INSTANCE_MAX_ID_SIZE_IN_BYTES 128 /**< * @ingroup cpa_BaseDataTypes * Maximum instance info id string length in bytes */ #define CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES 64 /**< * @ingroup cpa_BaseDataTypes * Maximum instance info version string length in bytes */ /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Instance Info Structure * * @deprecated * As of v1.3 of the Crypto API, this structure has been deprecated, * replaced by CpaInstanceInfo2. * * @description * Structure that contains the information to describe the instance. * *****************************************************************************/ typedef struct _CpaInstanceInfo { enum _CpaInstanceType type; /**< Type definition for this instance. */ enum _CpaInstanceState state; /**< Operational state of the instance. */ Cpa8U name[CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES]; /**< Simple text string identifier for the instance. */ Cpa8U version[CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES]; /**< Version string. There may be multiple versions of the same type of * instance accessible through a particular library. */ } CpaInstanceInfo CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Physical Instance ID * @description * Identifies the physical instance of an accelerator execution * engine. * * Accelerators grouped into "packages". Each accelerator can in * turn contain one or more execution engines. Implementations of * this API will define the packageId, acceleratorId, * executionEngineId and busAddress as appropriate for the * implementation. For example, for hardware-based accelerators, * the packageId might identify the chip, which might contain * multiple accelerators, each of which might contain multiple * execution engines. The combination of packageId, acceleratorId * and executionEngineId uniquely identifies the instance. * * Hardware based accelerators implementing this API may also provide * information on the location of the accelerator in the busAddress * field. This field will be defined as appropriate for the * implementation. For example, for PCIe attached accelerators, * the busAddress may contain the PCIe bus, device and function * number of the accelerators. * *****************************************************************************/ typedef struct _CpaPhysicalInstanceId { Cpa16U packageId; /**< Identifies the package within which the accelerator is * contained. */ Cpa16U acceleratorId; /**< Identifies the specific accelerator within the package. */ Cpa16U executionEngineId; /**< Identifies the specific execution engine within the * accelerator. */ Cpa16U busAddress; /**< Identifies the bus address associated with the accelerator * execution engine. */ Cpa32U kptAcHandle; /**< Identifies the achandle of the accelerator. */ } CpaPhysicalInstanceId; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Instance Info Structure, version 2 * @description * Structure that contains the information to describe the instance. * *****************************************************************************/ typedef struct _CpaInstanceInfo2 { CpaAccelerationServiceType accelerationServiceType; /**< Type of service provided by this instance. */ #define CPA_INST_VENDOR_NAME_SIZE CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES /**< Maximum length of the vendor name. */ Cpa8U vendorName[CPA_INST_VENDOR_NAME_SIZE]; /**< String identifying the vendor of the accelerator. */ #define CPA_INST_PART_NAME_SIZE CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES /**< Maximum length of the part name. */ Cpa8U partName[CPA_INST_PART_NAME_SIZE]; /**< String identifying the part (name and/or number). */ #define CPA_INST_SW_VERSION_SIZE CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES /**< Maximum length of the software version string. */ Cpa8U swVersion[CPA_INST_SW_VERSION_SIZE]; /**< String identifying the version of the software associated with * the instance. For hardware-based implementations of the API, * this should be the driver version. For software-based * implementations of the API, this should be the version of the * library. * * Note that this should NOT be used to store the version of the * API, nor should it be used to report the hardware revision * (which can be captured as part of the @ref partName, if required). */ #define CPA_INST_NAME_SIZE CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES /**< Maximum length of the instance name. */ Cpa8U instName[CPA_INST_NAME_SIZE]; /**< String identifying the name of the instance. */ #define CPA_INST_ID_SIZE CPA_INSTANCE_MAX_ID_SIZE_IN_BYTES Cpa8U instID[CPA_INST_ID_SIZE]; /**< String containing a unique identifier for the instance */ CpaPhysicalInstanceId physInstId; /**< Identifies the "physical instance" of the accelerator. */ #define CPA_MAX_CORES 4096 /**< Maximum number of cores to support in the coreAffinity bitmap. */ CPA_BITMAP(coreAffinity, CPA_MAX_CORES); /**< A bitmap identifying the core or cores to which the instance * is affinitized in an SMP operating system. * * The term core here is used to mean a "logical" core - for example, * in a dual-processor, quad-core system with hyperthreading (two * threads per core), there would be 16 such cores (2 processors x * 4 cores/processor x 2 threads/core). The numbering of these cores * and the corresponding bit positions is OS-specific. Note that Linux * refers to this as "processor affinity" or "CPU affinity", and refers * to the bitmap as a "cpumask". * * The term "affinity" is used to mean that this is the core on which * the callback function will be invoked when using the asynchronous * mode of the API. In a hardware-based implementation of the API, * this might be the core to which the interrupt is affinitized. * In a software-based implementation, this might be the core to which * the process running the algorithm is affinitized. Where there is * no affinity, the bitmap can be set to all zeroes. * * This bitmap should be manipulated using the macros @ref * CPA_BITMAP_BIT_SET, @ref CPA_BITMAP_BIT_CLEAR and @ref * CPA_BITMAP_BIT_TEST. */ Cpa32U nodeAffinity; /**< Identifies the processor complex, or node, to which the accelerator * is physically connected, to help identify locality in NUMA systems. * * The values taken by this attribute will typically be in the range * 0..n-1, where n is the number of nodes (processor complexes) in the * system. For example, in a dual-processor configuration, n=2. The * precise values and their interpretation are OS-specific. */ CpaOperationalState operState; /**< Operational state of the instance. */ CpaBoolean requiresPhysicallyContiguousMemory; /**< Specifies whether the data pointed to by flat buffers * (CpaFlatBuffer::pData) supplied to this instance must be in * physically contiguous memory. */ CpaBoolean isPolled; /**< Specifies whether the instance must be polled, or is event driven. * For hardware accelerators, the alternative to polling would be * interrupts. */ CpaBoolean isOffloaded; /**< Identifies whether the instance uses hardware offload, or is a * software-only implementation. */ } CpaInstanceInfo2; /** ***************************************************************************** * @ingroup cpa_BaseDataTypes * Instance Events * @description * Enumeration of the different events that will cause the registered * Instance notification callback function to be invoked. * *****************************************************************************/ typedef enum _CpaInstanceEvent { CPA_INSTANCE_EVENT_RESTARTING = 0, /**< Event type that triggers the registered instance notification callback * function when and instance is restarting. The reason why an instance is * restarting is implementation specific. For example a hardware * implementation may send this event if the hardware device is about to * be reset. */ CPA_INSTANCE_EVENT_RESTARTED, /**< Event type that triggers the registered instance notification callback * function when and instance has restarted. The reason why an instance has * restarted is implementation specific. For example a hardware * implementation may send this event after the hardware device has * been reset. */ CPA_INSTANCE_EVENT_FATAL_ERROR /**< Event type that triggers the registered instance notification callback * function when an error has been detected that requires the device * to be reset. * This event will be sent by all instances using the device, both on the * host and guests. */ } CpaInstanceEvent; /*****************************************************************************/ /* CPA Instance Management Functions */ /*****************************************************************************/ /** ***************************************************************************** * @file cpa.h * @ingroup cpa * Get the number of Acceleration Service instances that are supported by * the API implementation. * * @description * This function will get the number of instances that are supported * for the required Acceleration Service by an implementation of the CPA * API. This number is then used to determine the size of the array that * must be passed to @ref cpaGetInstances(). * * @context * This function MUST NOT be called from an interrupt context as it MAY * sleep. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] accelerationServiceType Acceleration Service required * @param[out] pNumInstances Pointer to where the number of * instances will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated * * @see * cpaGetInstances * *****************************************************************************/ CpaStatus cpaGetNumInstances( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *pNumInstances); /** ***************************************************************************** * @file cpa.h * @ingroup cpa * Get the handles to the required Acceleration Service instances that are * supported by the API implementation. * * @description * This function will return handles to the required Acceleration Service * instances that are supported by an implementation of the CPA API. These * instance handles can then be used as input parameters with other * API functions. * * This function will populate an array that has been allocated by the * caller. The size of this array will have been determined by the * cpaGetNumInstances() function. * * @context * This function MUST NOT be called from an interrupt context as it MAY * sleep. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] accelerationServiceType Acceleration Service requested * @param[in] numInstances Size of the array. If the value is * greater than the number of instances * supported, then an error (@ref * CPA_STATUS_INVALID_PARAM) is returned. * @param[in,out] cpaInstances Pointer to where the instance * handles will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated * * @see * cpaGetNumInstances * *****************************************************************************/ CpaStatus cpaGetInstances( const CpaAccelerationServiceType accelerationServiceType, Cpa16U numInstances, CpaInstanceHandle *cpaInstances); /** ***************************************************************************** * @ingroup cpa * Instance Allocation Policies * @description * Enumeration of the possible instance allocation policies that may be * used for allocating instances using the cpaAllocInstance() API. * *****************************************************************************/ typedef enum _CpaInstanceAllocPolicy { CPA_INST_ALLOC_NONE = 0, /**< No policy specified. The implementation will choose a default * allocation scheme which may be device dependent. */ CPA_INST_ALLOC_PREFER_EXISTING, /**< Allocate new instances from the same underlying hardware devices that * are already in use by the same process that is requesting the new * allocation. If no instances are available, a new device, if available, * will be used. * Note, “already in use” means in use for any service, not specifically * for the service type requested. The service type requested is only used * to determine which of the available underlying devices can support the * service, not to group instance allocations based on service type. */ CPA_INST_ALLOC_PREFER_NEW, /**< Allocate new instances from a device that is not currently in use. If * no unused devices are available, existing devices used by the process * requesting the allocation may be used. */ } CpaInstanceAllocPolicy; /** ***************************************************************************** * @ingroup cpa * Allocate a service instance. * * @description * This function is used to allocate a service instance. * If there are multiple devices with free instances, the allocation * policy is used to influence which device the instance will be * allocated from. * If multiple instances are required, this function must be called * multiple times to allocate each instance. * * When this function is called in user space, the implementation may only * be able to allocate from the devices that are visible to the user space * process context from which the function is called. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] serviceType Type of acceleration service instance * to allocate. * @param[in] policy Allocation policy * @param[out] pInstanceHandle Allocated instance or NULL if the * allocation failed and no instance was * allocated. * * @retval CPA_STATUS_SUCCESS An instance was successfully allocated. * @retval CPA_STATUS_FAIL Function failed to allocate an instance. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus cpaAllocInstance(const CpaAccelerationServiceType serviceType, const CpaInstanceAllocPolicy policy, CpaInstanceHandle *pInstanceHandle); /** ***************************************************************************** * @ingroup cpa * Free a service instance. * * @description * This function is used to free a service instance. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance to free. * * @retval CPA_STATUS_SUCCESS An instance was successfully freed. * @retval CPA_STATUS_FAIL Function failed to free an instance. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus cpaFreeInstance(CpaInstanceHandle instanceHandle); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_H */ qatlib-25.08.0/quickassist/include/cpa_dev.h000066400000000000000000000144501503624047500207140ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_dev.h * * @defgroup cpaDev Device API * * @ingroup cpa * * @description * These functions specify the API for device level operation. * * @remarks * * *****************************************************************************/ #ifndef CPA_DEV_H #define CPA_DEV_H #ifdef __cplusplus extern "C" { #endif #ifndef CPA_H #include "cpa.h" #endif /***************************************************************************** * @ingroup cpaDev * Returns device information * * @description * This data structure contains the device information. The device * information are available to both Physical and Virtual Functions. * Depending on the resource partitioning configuration, the services * available may changes. This configuration will impact the size of the * Security Association Database (SADB). Other properties such device SKU * and device ID are also reported. * *****************************************************************************/ typedef struct _CpaDeviceInfo { Cpa32U sku; /**< Identifies the SKU of the device. */ Cpa16U bdf; /**< Identifies the Bus Device Function of the device. * Format is reported as follow: * - bits<2:0> represent the function number. * - bits<7:3> represent the device * - bits<15:8> represent the bus */ Cpa32U deviceId; /**< Returns the device ID. */ Cpa32U numaNode; /**< Return the local NUMA node mapped to the device. */ CpaBoolean isVf; /**< Return whether the device is currently used in a virtual function * or not. */ CpaBoolean dcEnabled; /**< Compression service enabled */ CpaBoolean cySymEnabled; /**< Symmetric crypto service enabled */ CpaBoolean cyAsymEnabled; /**< Asymmetric crypto service enabled */ CpaBoolean inlineEnabled; /**< Inline service enabled */ Cpa32U deviceMemorySizeAvailable; /**< Return the size of the device memory available. This device memory * section could be used for the intermediate buffers in the * compression service. */ } CpaDeviceInfo; /***************************************************************************** * @ingroup cpaDev * Returns number devices. * * @description * This API returns the number of devices available to the application. * If used on the host, it will return the number of physical devices. * If used on the guest, it will return the number of function mapped * to the virtual machine. * *****************************************************************************/ CpaStatus cpaGetNumDevices(Cpa16U *numDevices); /***************************************************************************** * @ingroup cpaDev * Returns device information for a given device index. * * @description * Returns device information for a given device index. This API must * be used with cpaGetNumDevices(). *****************************************************************************/ CpaStatus cpaGetDeviceInfo(Cpa16U device, CpaDeviceInfo *deviceInfo); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_DEV_H */ qatlib-25.08.0/quickassist/include/cpa_types.h000066400000000000000000000212361503624047500213020ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_types.h * * @defgroup cpa_Types CPA Type Definition * * @ingroup cpa * * @description * This is the CPA Type Definitions. * *****************************************************************************/ #ifndef CPA_TYPES_H #define CPA_TYPES_H #ifdef __cplusplus extern "C" { #endif #if defined(__linux__) && defined(__KERNEL__) /* Linux kernel mode */ #include #include #elif defined(__FreeBSD__) && defined(_KERNEL) /* FreeBSD kernel mode */ #include #include #include #elif defined(_WIN64) && defined(KERNEL_SPACE) /* Windows kernel mode */ #include #include #include #include #elif defined(__linux__) || defined(__FreeBSD__) || defined(WIN32) || \ defined(_WIN64) /* Linux, FreeBSD, or Windows user mode */ #include #include #include #elif defined(_WRS_KERNEL) /* Wind River VxWorks kernel mode */ #include #else #error Unsupported operating system #endif /* OS and mode */ #if defined(WIN32) || defined(_WIN64) /* nonstandard extension used : zero-sized array in struct/union */ #pragma warning(disable : 4200) #endif typedef uint8_t Cpa8U; /**< * @file cpa_types.h * @ingroup cpa_Types * Unsigned byte base type. */ typedef int8_t Cpa8S; /**< * @file cpa_types.h * @ingroup cpa_Types * Signed byte base type. */ typedef uint16_t Cpa16U; /**< * @file cpa_types.h * @ingroup cpa_Types * Unsigned double-byte base type. */ typedef int16_t Cpa16S; /**< * @file cpa_types.h * @ingroup cpa_Types * Signed double-byte base type. */ typedef uint32_t Cpa32U; /**< * @file cpa_types.h * @ingroup cpa_Types * Unsigned quad-byte base type. */ typedef int32_t Cpa32S; /**< * @file cpa_types.h * @ingroup cpa_Types * Signed quad-byte base type. */ typedef uint64_t Cpa64U; /**< * @file cpa_types.h * @ingroup cpa_Types * Unsigned double-quad-byte base type. */ typedef int64_t Cpa64S; /**< * @file cpa_types.h * @ingroup cpa_Types * Signed double-quad-byte base type. */ /***************************************************************************** * Generic Base Data Type definitions *****************************************************************************/ #ifndef NULL #define NULL (0) /**< * @file cpa_types.h * @ingroup cpa_Types * NULL definition. */ #endif /** ***************************************************************************** * @ingroup cpa_Types * Boolean type. * * @description * Functions in this API use this type for Boolean variables that take * true or false values. * *****************************************************************************/ typedef enum _CpaBoolean { CPA_FALSE = (0 == 1), /**< False value */ CPA_TRUE = (1 == 1) /**< True value */ } CpaBoolean; /** ***************************************************************************** * @ingroup cpa_Types * Declare a bitmap of specified size (in bits). * * @description * This macro is used to declare a bitmap of arbitrary size. * * To test whether a bit in the bitmap is set, use @ref * CPA_BITMAP_BIT_TEST. * * While most uses of bitmaps on the API are read-only, macros are also * provided to set (see @ref CPA_BITMAP_BIT_SET) and clear (see @ref * CPA_BITMAP_BIT_CLEAR) bits in the bitmap. *****************************************************************************/ #define CPA_BITMAP(name, sizeInBits) Cpa32U name[((sizeInBits) + 31) / 32] #define CPA_BITMAP_BIT_TEST(bitmask, bit) \ ((bitmask[(bit) / 32]) & (0x1 << ((bit) % 32))) /**< * @ingroup cpa_Types * Test a specified bit in the specified bitmap. The bitmap may have been * declared using @ref CPA_BITMAP. Returns a Boolean (true if the bit is * set, false otherwise). */ #define CPA_BITMAP_BIT_SET(bitmask, bit) \ (bitmask[(bit) / 32] |= (0x1 << ((bit) % 32))) /**< * @file cpa_types.h * @ingroup cpa_Types * Set a specified bit in the specified bitmap. The bitmap may have been * declared using @ref CPA_BITMAP. */ #define CPA_BITMAP_BIT_CLEAR(bitmask, bit) \ (bitmask[(bit) / 32] &= ~(0x1 << ((bit) % 32))) /**< * @ingroup cpa_Types * Clear a specified bit in the specified bitmap. The bitmap may have been * declared using @ref CPA_BITMAP. */ /** ********************************************************************** * * @ingroup cpa_Types * * @description * Declare a function or type and mark it as deprecated so that * usages get flagged with a warning. * ********************************************************************** */ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(_WIN64) /* * gcc and icc support the __attribute__ ((deprecated)) syntax for marking * functions and other constructs as deprecated. */ /* * Uncomment the deprecated macro if you need to see which structs are * deprecated */ #define CPA_DEPRECATED /*#define CPA_DEPRECATED __attribute__ ((deprecated)) */ #else /* * for all other compilers, define deprecated to do nothing * */ /* #define CPA_DEPRECATED_FUNC(func) func; #pragma deprecated(func) */ #pragma message( \ "WARNING: You need to implement the CPA_DEPRECATED macro for this compiler") #define CPA_DEPRECATED #endif #define CPA_BITMASK(bit) (1UL << (bit)) #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_TYPES_H */ qatlib-25.08.0/quickassist/include/dc/000077500000000000000000000000001503624047500175245ustar00rootroot00000000000000qatlib-25.08.0/quickassist/include/dc/cpa_dc.h000066400000000000000000004471141503624047500211210ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_dc.h * * @defgroup cpaDc Data Compression API * * @ingroup cpa * * @description * These functions specify the API for Data Compression operations. * * The Data Compression API has the following: * 1) Session based API functions * These functions require a session to be created before performing any * DC operations. Subsequent DC API functions make use of the returned * Session Handle within their structures or function prototypes. * 2) Session-less or No-Session (Ns) based API functions. * These functions do not require a session to be initialized before * performing DC operations. They are "one-shot" API function calls * that submit DC requests directly using the supplied parameters. * * @remarks * * *****************************************************************************/ #ifndef CPA_DC_H #define CPA_DC_H #ifdef __cplusplus extern "C" { #endif #ifndef CPA_H #include "cpa.h" #endif /** ***************************************************************************** * @ingroup cpaDc * CPA Dc Major Version Number * @deprecated * As of v5.0 of the Compression API, this define has been deprecated, * replaced by @ref CPA_API_VERSION_NUM_MAJOR. * @description * The CPA_DC API major version number. This number will be incremented * when significant churn to the API has occurred. The combination of the * major and minor number definitions represent the complete version number * for this interface. * *****************************************************************************/ #define CPA_DC_API_VERSION_NUM_MAJOR (CPA_API_VERSION_NUM_MAJOR) /** ***************************************************************************** * @ingroup cpaDc * CPA DC Minor Version Number * @deprecated * As of v5.0 of the Compression API, this define has been deprecated, * replaced by @ref CPA_API_VERSION_NUM_MINOR. * @description * The CPA_DC API minor version number. This number will be incremented * when minor changes to the API has occurred. The combination of the major * and minor number definitions represent the complete version number for * this interface. * *****************************************************************************/ #define CPA_DC_API_VERSION_NUM_MINOR (CPA_API_VERSION_NUM_MINOR) /** ***************************************************************************** * @file cpa_dc.h * @ingroup cpaDc * CPA DC API version at least * @description * The minimal supported CPA_DC API version. Allow to check if the API * version is equal or above some version to avoid compilation issues * with an older API version. * *****************************************************************************/ #define CPA_DC_API_VERSION_AT_LEAST(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR > major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR >= minor)) /** ***************************************************************************** * @file cpa_dc.h * @ingroup cpaDc * CPA DC API version less than * @description * The maximum supported CPA_DC API version. Allow to check if the API * version is below some version to avoid compilation issues with a newer * API version. * *****************************************************************************/ #define CPA_DC_API_VERSION_LESS_THAN(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR < major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR < minor)) /** ***************************************************************************** * @ingroup cpaDc * Size of bitmap needed for compression chaining capabilities. * * @description * Defines the number of bits in the bitmap to represent supported * chaining capabilities @ref dcChainCapInfo. Should be set to * at least one greater than the largest value in the enumerated type * @ref CpaDcChainOperations, so that the value of the enum constant * can also be used as the bit position in the bitmap. * * A larger value was chosen to allow for extensibility without the need * to change the size of the bitmap (to ease backwards compatibility in * future versions of the API). * *****************************************************************************/ #define CPA_DC_CHAIN_CAP_BITMAP_SIZE (32) /** ***************************************************************************** * @ingroup cpaDc * Compression API session handle type * * @description * Handle used to uniquely identify a Compression API session handle. This * handle is established upon registration with the API using * cpaDcInitSession(). * * * *****************************************************************************/ typedef void *CpaDcSessionHandle; /** ***************************************************************************** * @ingroup cpaDc * Supported flush flags * * @description * This enumerated list identifies the types of flush that can be * specified for stateful and stateless cpaDcCompressData and * cpaDcDecompressData functions. * *****************************************************************************/ typedef enum _CpaDcFlush { CPA_DC_FLUSH_NONE = 0, /**< No flush request. */ CPA_DC_FLUSH_FINAL, /**< Indicates that the input buffer contains all of the data for the compression session allowing any buffered data to be released. For Deflate, BFINAL is set in the compression header.*/ CPA_DC_FLUSH_SYNC, /**< Used for stateful deflate compression to indicate that all pending output is flushed, byte aligned, to the output buffer. The session state is not reset.*/ CPA_DC_FLUSH_FULL /**< Used for deflate compression to indicate that all pending output is flushed to the output buffer and the session state is reset.*/ } CpaDcFlush; /** ***************************************************************************** * @ingroup cpaDc * Supported Huffman Tree types * * @description * This enumeration lists support for Huffman Tree types. * Selecting Static Huffman trees generates compressed blocks with an RFC * 1951 header specifying "compressed with fixed Huffman trees". * * Selecting Full Dynamic Huffman trees generates compressed blocks with * an RFC 1951 header specifying "compressed with dynamic Huffman codes". * The headers are calculated on the data being compressed, requiring two * passes. * * Selecting Precompiled Huffman Trees generates blocks with RFC 1951 * dynamic headers. The headers are pre-calculated and are specified by * the file type. * *****************************************************************************/ typedef enum _CpaDcHuffType { CPA_DC_HT_STATIC = 0, /**< Static Huffman Trees */ CPA_DC_HT_PRECOMP, /**< Precompiled Huffman Trees */ CPA_DC_HT_FULL_DYNAMIC /**< Full Dynamic Huffman Trees */ } CpaDcHuffType; /** ***************************************************************************** * @ingroup cpaDc * Supported compression types * * @description * This enumeration lists the supported data compression algorithms. * In combination with CpaDcChecksum it is used to decide on the file * header and footer format. * *****************************************************************************/ typedef enum _CpaDcCompType { CPA_DC_DEFLATE = 3, /**< Deflate Compression */ CPA_DC_LZ4, /**< LZ4 Compression */ CPA_DC_LZ4S /**< LZ4S Compression */ } CpaDcCompType; /** ***************************************************************************** * @ingroup cpaDc * Support for defined algorithm window sizes * * @description * This enumerated list defines the valid window sizes that can be * used with the supported algorithms *****************************************************************************/ typedef enum _CpaDcCompWindowSize { CPA_DC_WINSIZE_4K = 0, /**< Window size of 4KB */ CPA_DC_WINSIZE_8K, /**< Window size of 8KB */ CPA_DC_WINSIZE_16K, /**< Window size of 16KB */ CPA_DC_WINSIZE_32K /**< Window size of 32KB */ } CpaDcCompWindowSize; /** ***************************************************************************** * @ingroup cpaDc * Min match size in bytes * @description * This is the min match size that will be used for the search algorithm. * It is only configurable for LZ4S. *****************************************************************************/ typedef enum _CpaDcCompMinMatch { CPA_DC_MIN_3_BYTE_MATCH = 0, /**< Min Match of 3 bytes */ CPA_DC_MIN_4_BYTE_MATCH /**< Min Match of 4 bytes */ } CpaDcCompMinMatch; /** ***************************************************************************** * @ingroup cpaDc * Maximum LZ4 output block size * @description * Maximum LZ4 output block size *****************************************************************************/ typedef enum _CpaDcCompLZ4BlockMaxSize { CPA_DC_LZ4_MAX_BLOCK_SIZE_64K = 0, /**< Maximum block size 64K */ CPA_DC_LZ4_MAX_BLOCK_SIZE_256K, /**< Maximum block size 256K */ CPA_DC_LZ4_MAX_BLOCK_SIZE_1M, /**< Maximum block size 1M */ CPA_DC_LZ4_MAX_BLOCK_SIZE_4M, /**< Maximum block size 4M */ } CpaDcCompLZ4BlockMaxSize; /** ***************************************************************************** * @ingroup cpaDc * Bitmask definition for block size * @description * This enumeration defines the bitmasks for the supported block size. *****************************************************************************/ typedef enum _CpaDcBlockSizeBitmask { CPA_DC_BLOCK_SIZE_64K_BITMASK = CPA_BITMASK(0), /**< Block size 64K */ CPA_DC_BLOCK_SIZE_256K_BITMASK = CPA_BITMASK(1), /**< Block size 256K */ CPA_DC_BLOCK_SIZE_1M_BITMASK = CPA_BITMASK(2), /**< Block size 1M */ CPA_DC_BLOCK_SIZE_4M_BITMASK = CPA_BITMASK(3), /**< Block size 4M */ } CpaDcBlockSizeBitmask; /** ***************************************************************************** * @ingroup cpaDc * Supported checksum algorithms * * @description * This enumeration lists the supported checksum algorithms * Used to decide on file header and footer specifics. * *****************************************************************************/ typedef enum _CpaDcChecksum { CPA_DC_NONE = 0, /**< No checksum required */ CPA_DC_CRC32, /**< Application requires a CRC32 checksum */ CPA_DC_ADLER32, /**< Application requires Adler-32 checksum */ CPA_DC_CRC32_ADLER32, /**< Application requires both CRC32 and Adler-32 checksums */ CPA_DC_XXHASH32, /**< Application requires xxHash-32 checksum */ } CpaDcChecksum; /** ***************************************************************************** * @ingroup cpaDc * Supported session directions * * @description * This enumerated list identifies the direction of a session. * A session can be compress, decompress or both. * *****************************************************************************/ typedef enum _CpaDcSessionDir { CPA_DC_DIR_COMPRESS = 0, /**< Session will be used for compression */ CPA_DC_DIR_DECOMPRESS, /**< Session will be used for decompression */ CPA_DC_DIR_COMBINED /**< Session will be used for both compression and decompression */ } CpaDcSessionDir; typedef CpaDcSessionDir CpaDcDir; /** ***************************************************************************** * @ingroup cpaDc * Supported session state settings * * @description * This enumerated list identifies the stateful setting of a session. * A session can be either stateful or stateless. * * Stateful sessions are limited to have only one in-flight message per * session. This means a compress or decompress request must be complete * before a new request can be started. This applies equally to sessions * that are uni-directional in nature and sessions that are combined * compress and decompress. Completion occurs when the synchronous function * returns, or when the asynchronous callback function has completed. * *****************************************************************************/ typedef enum _CpaDcSessionState { CPA_DC_STATEFUL = 0, /**< Session will be stateful, implying that state may need to be saved in some situations */ CPA_DC_STATELESS /**< Session will be stateless, implying no state will be stored*/ } CpaDcSessionState; typedef CpaDcSessionState CpaDcState; /** ***************************************************************************** * @ingroup cpaDc * Supported compression levels * * @description * This enumerated lists the supported compressed levels. * Lower values will result in less compressibility in less time. * * *****************************************************************************/ typedef enum _CpaDcCompLvl { CPA_DC_L1 = 1, /**< Compression level 1 */ CPA_DC_L2, /**< Compression level 2 */ CPA_DC_L3, /**< Compression level 3 */ CPA_DC_L4, /**< Compression level 4 */ CPA_DC_L5, /**< Compression level 5 */ CPA_DC_L6, /**< Compression level 6 */ CPA_DC_L7, /**< Compression level 7 */ CPA_DC_L8, /**< Compression level 8 */ CPA_DC_L9, /**< Compression level 9 */ CPA_DC_L10, /**< Compression level 10 */ CPA_DC_L11, /**< Compression level 11 */ CPA_DC_L12 /**< Compression level 12 */ } CpaDcCompLvl; /** ***************************************************************************** * @ingroup cpaDc * Supported additional details from accelerator * * @description * This enumeration lists the supported additional details from the * accelerator. These may be useful in determining the best way to * recover from a failure. * * *****************************************************************************/ typedef enum _CpaDcReqStatus { CPA_DC_OK = 0, /**< No error detected by compression slice */ CPA_DC_INVALID_BLOCK_TYPE = -1, /**< Invalid block type (type == 3) */ CPA_DC_BAD_STORED_BLOCK_LEN = -2, /**< Stored block length did not match one's complement */ CPA_DC_TOO_MANY_CODES = -3, /**< Too many length or distance codes */ CPA_DC_INCOMPLETE_CODE_LENS = -4, /**< Code length codes incomplete */ CPA_DC_REPEATED_LENS = -5, /**< Repeated lengths with no first length */ CPA_DC_MORE_REPEAT = -6, /**< Repeat more than specified lengths */ CPA_DC_BAD_LITLEN_CODES = -7, /**< Invalid literal/length code lengths */ CPA_DC_BAD_DIST_CODES = -8, /**< Invalid distance code lengths */ CPA_DC_INVALID_CODE = -9, /**< Invalid literal/length or distance code in fixed or dynamic block */ CPA_DC_INVALID_DIST = -10, /**< Distance is too far back in fixed or dynamic block */ CPA_DC_OVERFLOW = -11, /**< Overflow detected. This is an indication that output buffer has * overflowed. For stateful sessions, this is a warning (the input can be * adjusted and resubmitted). For stateless sessions this is an error * condition */ CPA_DC_SOFTERR = -12, /**< Other non-fatal detected */ CPA_DC_FATALERR = -13, /**< Fatal error detected */ CPA_DC_MAX_RESUBITERR = -14, /**< On an error being detected, the firmware attempted to correct and * resubmitted the * request, however, the maximum resubmit value was exceeded */ CPA_DC_INCOMPLETE_FILE_ERR = -15, /**< The input file is incomplete. Note this is an indication that the * request was submitted with a CPA_DC_FLUSH_FINAL, however, a BFINAL bit * was not found in the request */ CPA_DC_WDOG_TIMER_ERR = -16, /**< The request was not completed as a watchdog timer hardware event occurred */ CPA_DC_EP_HARDWARE_ERR = -17, /**< Request was not completed as an end point hardware error occurred (for * example, a parity error) */ CPA_DC_VERIFY_ERROR = -18, /**< Error detected during "compress and verify" operation */ CPA_DC_EMPTY_DYM_BLK = -19, /**< Decompression request contained an empty dynamic stored block * (not supported) */ CPA_DC_CRC_INTEG_ERR = -20, /**< A data integrity CRC error was detected */ CPA_DC_REGION_OUT_OF_BOUNDS = -21, /**< Error returned when decompression ends before the specified partial * decompression region was produced */ CPA_DC_LZ4_INVALID_COMP_LEN = -24, /**< LZ4 invalid request length */ CPA_DC_INVALID_DICT_BUFF = -28, /**< Dictionary buffer list addresses are not 16-byte aligned * and/or size of flat buffers is not a multiple of 16-byte * except the last flat buffer in the list which can be of any size */ CPA_DC_LZ4_MULTIBLOCK_WITHOUT_HEADER = -29, /**< LZ4 block drop when using LZ4 without header mode */ CPA_DC_LZ4_MAX_BLOCK_SIZE_EXCEEDED = -93, /**< LZ4 max block size exceeded */ CPA_DC_LZ4_BLOCK_OVERFLOW_ERR = -95, /**< LZ4 Block Overflow Error */ CPA_DC_LZ4_TOKEN_IS_ZERO_ERR = -98, /**< LZ4 Decoded token offset or token length is zero */ CPA_DC_LZ4_DISTANCE_OUT_OF_RANGE_ERR = -100, /**< LZ4 Distance out of range for len/distance pair */ CPA_DC_E2E_NO_DECOMPRESSION = -101, /**< Integrity input CRC computed by compression accelerator OR * CnVnR or ASB resulted in uncompressed data */ } CpaDcReqStatus; /** ***************************************************************************** * @ingroup cpaDc * Supported modes for automatically selecting the best compression type. * * @description * This enumeration lists the supported modes for automatically selecting * the best encoding which would lead to the best compression results. * * When CPA_DC_ASB_ENABLED is used the output will be a format compliant * block, whether the data is compressed or not. * * The following values are deprecated and should not be used. They * will be removed in a future version of this file. * - CPA_DC_ASB_STATIC_DYNAMIC * - CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS * - CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS * *****************************************************************************/ typedef enum _CpaDcAutoSelectBest { CPA_DC_ASB_DISABLED = 0, /**< Auto select best mode is disabled */ CPA_DC_ASB_STATIC_DYNAMIC = 1, /**< Auto select between static and dynamic compression */ CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS = 2, /**< Auto select between uncompressed, static and dynamic compression, * using stored block deflate headers if uncompressed is selected */ CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS = 3, /**< Auto select between uncompressed, static and dynamic compression, * using no deflate headers if uncompressed is selected */ CPA_DC_ASB_ENABLED = 4, /**< Auto select best mode is enabled */ } CpaDcAutoSelectBest; /** ***************************************************************************** * @ingroup cpaDc * Supported modes for skipping regions of input or output buffers. * * @description * This enumeration lists the supported modes for skipping regions of * input or output buffers. * *****************************************************************************/ typedef enum _CpaDcSkipMode { CPA_DC_SKIP_DISABLED = 0, /**< Skip mode is disabled */ CPA_DC_SKIP_AT_START = 1, /**< Skip region is at the start of the buffer. */ CPA_DC_SKIP_AT_END = 2, /**< Skip region is at the end of the buffer. */ CPA_DC_SKIP_STRIDE = 3 /**< Skip region occurs at regular intervals within the buffer. CpaDcSkipData.strideLength specifies the number of bytes between each skip region. */ } CpaDcSkipMode; /** ***************************************************************************** * @ingroup cpaDc * Supported dictionary formats * * @description * This enumeration lists the supported dictionary formats for * cpaDcCompressDataWithDict() and cpaDcDecompressDataWithDict() APIs. * *****************************************************************************/ typedef enum _CpaDcDictType { CPA_DC_UNCOMPRESSED_DICT = 0, /**< Uncompressed dictionary format */ CPA_DC_COMPRESSED_DICT = 1 /**< Compressed dictionary format */ } CpaDcDictType; /** ***************************************************************************** * @ingroup cpaDc * Supported modes for LZ4 compressed output and corresponding CRCs. * * @description * This enumeration lists the supported modes for LZ4 compressed output and * corresponding CRCs. * *****************************************************************************/ typedef enum _CpaDcLZ4OutputFormat { CPA_DC_LZ4_OUTPUT_WITH_HEADER = 0, /**< When this mode is selected, the destination buffer contains LZ4 data * with the LZ4 header and LZ4 compressed data block. The oCRC field in * CpaIntegrityCrc or CpaIntegrityCrc64 is calculated over both the LZ4 * header and LZ4 compressed data. */ CPA_DC_LZ4_OUTPUT_WITHOUT_HEADER = 1 /**< When this mode is selected, the destination buffer contains only the * LZ4 compressed data block. The oCRC field in CpaIntegrityCrc or * CpaIntegrityCrc64 is calculated over the LZ4 compressed data without the * header. */ } CpaDcLZ4OutputFormat; /** ***************************************************************************** * @ingroup cpaDc * Service specific return codes * * @description * Compression specific return codes * * *****************************************************************************/ #define CPA_DC_BAD_DATA (-100) /**consumed arg. * -# The implementation communicates the amount of data in the * destination buffer list via pResults->produced arg. * * Source Buffer Setup Rules * -# The buffer list must have the correct number of flat buffers. This * is specified by the numBuffers element of the CpaBufferList. * -# Each flat buffer must have a pointer to contiguous memory that has * been allocated by the calling application. The * number of octets to be compressed or decompressed must be stored * in the dataLenInBytes element of the flat buffer. * -# It is permissible to have one or more flat buffers with a zero length * data store. This function will process all flat buffers until the * destination buffer is full or all source data has been processed. * If a buffer has zero length, then no data will be processed from * that buffer. * * Source Buffer Processing Rules. * -# The buffer list is processed in index order - SrcBuff->pBuffers[0] * will be completely processed before SrcBuff->pBuffers[1] begins to * be processed. * -# The application must drain the destination buffers. * If the source data was not completely consumed, the application * must resubmit the request. * -# On return, the pResults->consumed will indicate the number of bytes * consumed from the input buffers. * * Destination Buffer Setup Rules * -# The destination buffer list must have storage for processed data. * This implies at least one flat buffer must exist in the buffer list. * -# For each flat buffer in the buffer list, the dataLenInBytes element * must be set to the size of the buffer space. * -# It is permissible to have one or more flat buffers with a zero length * data store. * If a buffer has zero length, then no data will be added to * that buffer. * * Destination Buffer Processing Rules. * -# The buffer list is processed in index order - DestBuff->pBuffers[0] * will be completely processed before DestBuff->pBuffers[1] begins to * be processed. * -# On return, the pResults->produced will indicate the number of bytes * written to the output buffers. * -# If processing has not been completed, the application must drain the * destination buffers and resubmit the request. The application must * reset the dataLenInBytes for each flat buffer in the destination * buffer list. * * Checksum rules. * If a checksum is specified in the session setup data, then: * -# For the first request for a particular data segment the checksum * is initialised internally by the implementation. * -# The checksum is maintained by the implementation between calls * until the flushFlag is set to CPA_DC_FLUSH_FINAL indicating the * end of a particular data segment. * -# Intermediate checksum values are returned to the application, * via the CpaDcRqResults structure, in response to each request. * However these checksum values are not guaranteed to the valid * until the call with flushFlag set to CPA_DC_FLUSH_FINAL * completes successfully. * * The application should set flushFlag to * CPA_DC_FLUSH_FINAL to indicate processing a particular data segment * is complete. It should be noted that this function may have to be * called more than once to process data after the flushFlag parameter has * been set to CPA_DC_FLUSH_FINAL if the destination buffer fills. Refer * to buffer processing rules. * * For stateful operations, when the function is invoked with flushFlag * set to CPA_DC_FLUSH_NONE or CPA_DC_FLUSH_SYNC, indicating more data * is yet to come, the function may or may not retain data. When the * function is invoked with flushFlag set to CPA_DC_FLUSH_FULL or * CPA_DC_FLUSH_FINAL, the function will process all buffered data. * * For stateless operations, CPA_DC_FLUSH_FINAL will cause the BFINAL * bit to be set for deflate compression. The initial checksum for the * stateless operation should be set to 0. CPA_DC_FLUSH_NONE and * CPA_DC_FLUSH_SYNC should not be used for stateless operations. * * It is possible to maintain checksum and length information across * cpaDcCompressData() calls with a stateless session without maintaining * the full history state that is maintained by a stateful session. * In this mode of operation, an initial checksum value of * 0 is passed into the first cpaDcCompressData() call with the flush flag set * to CPA_DC_FLUSH_FULL. This feature is supported when the * CPA_DC_CAP_BOOL_STATEFUL_LITE capability is true. On subsequent calls to * cpaDcCompressData() for this session, the checksum passed to * cpadccompressdata should be set to the checksum value produced by the * previous call to cpaDcCompressData(). When the last block of input data is * passed to cpaDcCompressData(), the flush flag should be set to * CPA_DC_FLUSH_FINAL. This will cause the BFINAL bit to be set in a deflate * stream. It is the responsibility of the calling application to maintain * overall lengths across the stateless requests and to pass the checksum * produced by one request into the next request. * * When an instance supports compressAndVerifyAndRecover, it is enabled by * default when using cpaDcCompressData(). If this feature needs to be * disabled, cpaDcCompressData2() must be used. * * Synchronous or Asynchronous operation of the API is determined by * the value of the callbackFn parameter passed to cpaDcInitSession() * when the sessionHandle was setup. If a non-NULL value was specified * then the supplied callback function will be invoked asynchronously * with the response of this request. * * Response ordering: * For each session, the implementation must maintain the order of * responses. That is, if in asynchronous mode, the order of the callback * functions must match the order of jobs submitted by this function. * In a simple synchronous mode implementation, the practice of submitting * a request and blocking on its completion ensure ordering is preserved. * * This limitation does not apply if the application employs multiple * threads to service a single session. * * If this API is invoked asynchronous, the return code represents * the success or not of asynchronously scheduling the request. * The results of the operation, along with the amount of data consumed * and produced become available when the callback function is invoked. * As such, pResults->consumed and pResults->produced are available * only when the operation is complete. * * The application must not use either the source or destination buffers * until the callback has completed. * * @see * None * *****************************************************************************/ CpaStatus cpaDcCompressData(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Submit a request to compress a buffer of data. * * @description * This API consumes data from the input buffer and generates compressed * data in the output buffer. This API is very similar to * cpaDcCompressData() except it provides a CpaDcOpData structure for * passing additional input parameters not covered in cpaDcCompressData(). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to data buffer for compression. * @param[in] pDestBuff Pointer to buffer space for data after * compression. * @param[in,out] pOpData Additional parameters. * @param[in,out] pResults Pointer to results structure * @param[in] callbackTag User supplied value to help correlate * the callback with its associated * request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_DC_BAD_DATA The input data was not properly formed. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * pSessionHandle has been setup using cpaDcInitSession() * @post * pSessionHandle has session related state information * @note * This function passes control to the compression service for processing * * @see * cpaDcCompressData() * *****************************************************************************/ CpaStatus cpaDcCompressData2(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Submit a request to compress a buffer of data without requiring a * session to be created. This is a No-Session (Ns) variant of the * cpaDcCompressData function. * * @description * This API consumes data from the input buffer and generates compressed * data in the output buffer. Unlike the other compression APIs this * does not use a previously created session. This is a "one-shot" API * that requests can be directly submitted to. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in] pSetupData Configuration structure for compression. * @param[in] pSrcBuff Pointer to data buffer for compression. * @param[in] pDestBuff Pointer to buffer space for data after * compression. * @param[in] pOpData Additional input parameters. * @param[in,out] pResults Pointer to results structure * @param[in] callbackFn For synchronous operation this callback * shall be a null pointer. * @param[in] callbackTag User supplied value to help correlate * the callback with its associated * request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * None * @post * None * @note * This function passes control to the compression service for processing * * Checksum rules. * The checksum rules are the same as those for the session based APIs * (cpaDcCompressData or cpaDcCompressData2) with the following exception. * -# If the algorithm specified is CPA_DC_LZ4 or CPA_DC_LZ4S the xxHash32 * checksum will not be maintained across calls to the API. The * implication is that the xxHash32 value will only be valid for the * output of a single request, no state will be saved. If an LZ4 frame is * required, even in recoverable error scenarios such as CPA_DC_OVERFLOW, * the checksum will not be continued. If that is required the session * based API must be used. * * @see * None * *****************************************************************************/ CpaStatus cpaDcNsCompressData(CpaInstanceHandle dcInstance, CpaDcNsSetupData *pSetupData, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, CpaDcCallbackFn callbackFn, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Submit a request to compress a buffer of data using a dictionary. * * @description * This API consumes data from the input buffer and generates compressed * data in the output buffer. This API makes use of a dictionary that * is supplied as a separate CpaBufferList within the * pDictionaryData parameter. * The application is responsible for creating the dictionary. * The dictionary used to compress data must be identical both in content * and in size to the dictionary used during decompression. * Apart from supporting dictionary functionality, this API is very * similar to cpaDcCompressData2(). See descriptions of both * cpaDcCompressData() and cpaDcCompressData2() for more information. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to data buffer for compression. * @param[in] pDestBuff Pointer to buffer space for data after * compression. * @param[in,out] pDictionaryData Pointer to dictionary data to be used. * during the compression request. * @param[in,out] pOpData Additional parameters. * @param[in,out] pResults Pointer to results structure * @param[in] callbackTag User supplied value to help correlate * the callback with its associated * request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * pSessionHandle has been setup using cpaDcInitSession() * @post * pSessionHandle has session related state information * @note * This function passes control to the compression service for processing * * @see * cpaDcCompressData() * cpaDcCompressData2() * *****************************************************************************/ CpaStatus cpaDcCompressDataWithDict(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcDictionaryData *pDictionaryData, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Submit a request to decompress a buffer of data. * * @description * This API consumes compressed data from the input buffer and generates * uncompressed data in the output buffer. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to data buffer for compression. * @param[in] pDestBuff Pointer to buffer space for data * after decompression. * @param[in,out] pResults Pointer to results structure * @param[in] flushFlag When set to CPA_DC_FLUSH_FINAL, * indicates that the input buffer contains * all of the data for the compression * session, allowing the function to * release history data. * @param[in] callbackTag User supplied value to help correlate * the callback with its associated * request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_DC_BAD_DATA The input data was not properly formed. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * pSessionHandle has been setup using cpaDcInitSession() * @post * pSessionHandle has session related state information * @note * This function passes control to the compression service for * decompression. The function returns the status from the service. * * This function may be called repetitively with input until all of the * input has been provided and all the output has been consumed. * * This function has identical buffer processing rules as * cpaDcCompressData(). * * This function has identical checksum processing rules as * cpaDcCompressData(). * * The application should set flushFlag to * CPA_DC_FLUSH_FINAL to indicate processing a particular compressed * data segment is complete. It should be noted that this function may * have to be called more than once to process data after flushFlag * has been set if the destination buffer fills. Refer to * buffer processing rules in cpaDcCompressData(). * * Synchronous or Asynchronous operation of the API is determined by * the value of the callbackFn parameter passed to cpaDcInitSession() * when the sessionHandle was setup. If a non-NULL value was specified * then the supplied callback function will be invoked asynchronously * with the response of this request, along with the callbackTag * specified in the function. * * The same response ordering constraints identified in the * cpaDcCompressData API apply to this function. * * @see * cpaDcCompressData() * *****************************************************************************/ CpaStatus cpaDcDecompressData(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Submit a request to decompress a buffer of data. * * @description * This API consumes compressed data from the input buffer and generates * uncompressed data in the output buffer. This API is very similar to * cpaDcDecompressData() except it provides a CpaDcOpData structure for * passing additional input parameters not covered in * cpaDcDecompressData(). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to data buffer for compression. * @param[in] pDestBuff Pointer to buffer space for data * after decompression. * @param[in] pOpData Additional input parameters. * @param[in,out] pResults Pointer to results structure * @param[in] callbackTag User supplied value to help correlate * the callback with its associated * request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_DC_BAD_DATA The input data was not properly formed. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * pSessionHandle has been setup using cpaDcInitSession() * @post * pSessionHandle has session related state information * @note * This function passes control to the compression service for * decompression. The function returns the status from the service. * * @see * cpaDcDecompressData() * cpaDcCompressData2() * cpaDcCompressData() * *****************************************************************************/ CpaStatus cpaDcDecompressData2(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Submit a request to decompress a buffer of data without requiring a * session to be created. This is a No-Session (Ns) variant of the * cpaDcDecompressData function. * * @description * This API consumes data from the input buffer and generates decompressed * data in the output buffer. Unlike the other decompression APIs this * does not use a previously created session. This is a "one-shot" API * that requests can be directly submitted to. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in] pSetupData Configuration structure for * decompression. * @param[in] pSrcBuff Pointer to data buffer for * decompression. * @param[in] pDestBuff Pointer to buffer space for data * after decompression. * @param[in] pOpData Additional input parameters. * @param[in,out] pResults Pointer to results structure * @param[in] callbackFn For synchronous operation this callback * shall be a null pointer. * @param[in] callbackTag User supplied value to help correlate * the callback with its associated * request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * None * @post * None * @note * This function passes control to the decompression service. The function * returns the status from the service. * * @see * cpaDcDecompressData() * cpaDcCompressData2() * cpaDcCompressData() * *****************************************************************************/ CpaStatus cpaDcNsDecompressData(CpaInstanceHandle dcInstance, CpaDcNsSetupData *pSetupData, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, CpaDcCallbackFn callbackFn, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Submit a request to decompress a buffer of data using a dictionary. * * @description * This API consumes data from the input buffer and generates * decompressed data in the output buffer. This API makes use of a * dictionary that is supplied as a separate CpaBufferList pointer. * In order to successfully decompress data with a dictionary, the same * dictionary that was used during the compression operation must be * reused. Apart from supporting dictionary functionality, this API is * very similar to cpaDcDecompressData2(). See descriptions of both * cpaDcDecompressData() and cpaDcDecompressData2() for more information. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to data buffer to decompress. * @param[in] pDestBuff Pointer to buffer space for data after * decompression. * @param[in,out] pDictionaryData Pointer to dictionary data to be used * during the compression request. * The dictionary buffer list addresses must * be 16-byte aligned. * The size of the flat buffers must be multiple * of 16-byte with the exception of the last flat buffer * in the buffer list which can be of any size. * @param[in,out] pOpData Additional parameters. * @param[in,out] pResults Pointer to results structure * @param[in] callbackTag User supplied value to help correlate * the callback with its associated * request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * pSessionHandle has been setup using cpaDcInitSession() * @post * pSessionHandle has session related state information * @note * This function passes control to the compression service for processing * * @see * cpaDcDecompressData() * cpaDcDecompressData2() * *****************************************************************************/ CpaStatus cpaDcDecompressDataWithDict(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcDictionaryData *pDictionaryData, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDc * Generate compression header. * * @description * This function generates the gzip header, zlib header or LZ4 frame * header and stores it in the destination buffer. The type of header * created is determined using the compression algorithm selected using * CpaDcSessionSetupData.compType, for the session associated with the * session handle. * * @context * This function may be call from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] pSessionHandle Session handle. * @param[in] pDestBuff Pointer to data buffer where the * compression header will go. * @param[out] count Pointer to counter filled in with * header size. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * pSessionHandle has been setup using cpaDcInitSession() * * @note * When the deflate compression algorithm is used, this function can output * a 10 byte gzip header or 2 byte zlib header to the destination buffer. * The session properties are used to determine the header type. To * output a Gzip or a Zlib header the session must have been initialized * with CpaDcCompType CPA_DC_DEFLATE. * To output a gzip header the session must have been initialized with * CpaDcChecksum CPA_DC_CRC32. To output a zlib header the session must * have been initialized with CpaDcChecksum CPA_DC_ADLER32. * For CpaDcChecksum CPA_DC_NONE no header is output. * * If the compression requires a gzip header, then this header requires * at a minimum the following fields, defined in RFC1952: * ID1: 0x1f * ID2: 0x8b * CM: Compression method = 8 for deflate * * The zlib header is defined in RFC1950 and this function must implement * as a minimum: * CM: four bit compression method - 8 is deflate with window size to * 32k * CINFO: four bit window size (see RFC1950 for details), 7 is 32k * window * FLG: defined as: * - Bits 0 - 4: check bits for CM, CINFO and FLG (see RFC1950) * - Bit 5: FDICT 0 = default, 1 is preset dictionary * - Bits 6 - 7: FLEVEL, compression level (see RFC 1950) * * When LZ4 algorithm is used, this function can output a 7 byte frame * header. This function will set the LZ4 frame header with: * - Magic number 0x184D2204 * - The LZ4 max block size defined in the CpaDcSessionSetupData * - Flag byte as: * * Version = 1 * * Block independence = 0 * * Block checksum = 0 * * Content size present = 0 * * Content checksum present = 1 * * Dictionary ID present = 0 * - Content size = 0 * - Dictionary ID = 0 * - Header checksum = 1 byte representing the second byte of the * XXH32 of the frame descriptor field. * * The counter parameter will be set to the number of bytes added to the * buffer. The pData will be not be changed. * * For any of the compression algorithms used, the application is * responsible to offset the pData pointer in CpaBufferList by the length * of the header before calling the CpaDcCompressData() or * CpaDcCompressData2() functions. * @see * None * *****************************************************************************/ CpaStatus cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle, CpaFlatBuffer *pDestBuff, Cpa32U *count); /** ***************************************************************************** * @ingroup cpaDc * Generate compression footer. * * @description * This function generates the footer for gzip, zlib or LZ4. * The generated footer is stored it in the destination buffer. * The type of footer created is determined using the compression * algorithm selected for the session associated with the session handle. * * @context * This function may be call from any context. * @assumptions * None * @sideEffects * All session variables are reset * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in,out] pSessionHandle Session handle. * @param[in] pDestBuff Pointer to data buffer where the * compression footer will go. * @param[in,out] pResults Pointer to results structure filled by * CpaDcCompressData. Updated with the * results of this API call * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * pSessionHandle has been setup using cpaDcInitSession() * pResults structure has been filled by CpaDcCompressData(). * * @note * Depending on the session variables, this function can add the * alder32 footer to the zlib compressed data as defined in RFC1950. * If required, it can also add the gzip footer, which is the crc32 of the * uncompressed data and the length of the uncompressed data. * This section is defined in RFC1952. The session variables used to * determine the header type are CpaDcCompType and CpaDcChecksum, see * cpaDcGenerateHeader for more details. * * For LZ4 compression, this function adds the LZ4 frame footer * using XXH32 algorithm of the uncompressed data. The XXH32 checksum is * added after the end mark. This section is defined in the documentation * of the LZ4 frame format at: * https://github.com/lz4/lz4/blob/dev/doc/lz4_Frame_format.md * * An artifact of invoking this function for writing the footer data is * that all opaque session specific data is re-initialized. If the * compression level and file types are consistent, the upper level * application can continue processing compression requests using the * same session handle. * * The produced element of the pResults structure will be incremented by * the numbers bytes added to the buffer. The pointer to the buffer will * not be modified. It is necessary for the application to ensure that * there is always sufficient memory in the destination buffer to append * the footer. In the event that the destination buffer would be too small * to accept the footer, overflow will not be reported. * * @see * None * *****************************************************************************/ CpaStatus cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle, CpaFlatBuffer *pDestBuff, CpaDcRqResults *pResults); /** ***************************************************************************** * @ingroup cpaDc * Generate compression header without requiring a session to be created. * This is a No-Session (Ns) variant of the cpaDcGenerateHeader function. * * @description * This API generates the required compression format header and stores it * in the output buffer. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] pSetupData Pointer to Ns Configuration structure. * @param[in] pDestBuff Pointer to data buffer where the * compression header will go. * @param[out] count Pointer to counter filled in with * header size. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * * @note * This function outputs the required compression format header to * the destination buffer. The CpaDcNsSetupData structure fields are used * to determine the header type. * * To output an LZ4 header the structure must have been initialized with * with CpaDcCompType CPA_DC_LZ4. * To output a gzip or zlib header the structure must have been initialized * with CpaDcCompType CPA_DC_DEFLATE. * To output a gzip header the structure must have been initialized with * CpaDcChecksum CPA_DC_CRC32. * To output a zlib header the structure must have been initialized with * CpaDcChecksum CPA_DC_ADLER32. * For CpaDcChecksum CPA_DC_NONE no header is output. * * The counter parameter will be set to the number of bytes added to the * buffer. * * @see * cpaDcGenerateHeader * *****************************************************************************/ CpaStatus cpaDcNsGenerateHeader(CpaDcNsSetupData *pSetupData, CpaFlatBuffer *pDestBuff, Cpa32U *count); /** ***************************************************************************** * @ingroup cpaDc * Generate compression footer without requiring a session to be created. * This is a No-Session (Ns) variant of the cpaDcGenerateFooter function. * * @description * This API generates the footer for the required format and stores it in * the destination buffer. * @context * This function may be call from any context. * @assumptions * None * @sideEffects * All session variables are reset * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] pSetupData Pointer to Ns Configuration structure. * @param[in] totalLength Total accumulated length of input data * processed. See description for formats * that make use of this parameter. * @param[in] pDestBuff Pointer to data buffer where the * compression footer will go. * @param[in,out] pResults Pointer to results structure filled by * CpaDcNsCompressData. Updated with the * results of this API call * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * pResults structure has been filled by CpaDcNsCompressData(). * * @note * This function outputs the required compression format footer to * the destination buffer. The CpaDcNsSetupData structure fields are used * to determine the footer type created. * * To output an LZ4 footer the structure must have been initialized with * with CpaDcCompType CPA_DC_LZ4. * To output a gzip or zlib footer the structure must have been initialized * with CpaDcCompType CPA_DC_DEFLATE. * To output a gzip footer the structure must have been initialized with * CpaDcChecksum CPA_DC_CRC32 and the totalLength parameter initialized to * the total accumulated length of data processed. * To output a zlib footer the structure must have been initialized with * CpaDcChecksum CPA_DC_ADLER32. * For CpaDcChecksum CPA_DC_NONE no footer is output. * * The produced element of the pResults structure will be incremented by * the number of bytes added to the buffer. The pointer to the buffer will * not be modified. * * @see * CpaDcNsSetupData * cpaDcNsGenerateHeader * cpaDcGenerateFooter * *****************************************************************************/ CpaStatus cpaDcNsGenerateFooter(CpaDcNsSetupData *pSetupData, Cpa64U totalLength, CpaFlatBuffer *pDestBuff, CpaDcRqResults *pResults); /** ***************************************************************************** * @ingroup cpaDc * Retrieve statistics * * @description * This API retrieves the current statistics for a compression instance. * * @context * This function may be call from any context. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Instance handle. * @param[out] pStatistics Pointer to statistics structure. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * * @see * None * *****************************************************************************/ CpaStatus cpaDcGetStats(CpaInstanceHandle dcInstance, CpaDcStats *pStatistics); /*****************************************************************************/ /* Instance Discovery Functions */ /** ***************************************************************************** * @ingroup cpaDc * Get the number of device instances that are supported by the API * implementation. * * @description * * This function will get the number of device instances that are supported * by an implementation of the compression API. This number is then used to * determine the size of the array that must be passed to * cpaDcGetInstances(). * * @context * This function MUST NOT be called from an interrupt context as it MAY * sleep. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[out] pNumInstances Pointer to where the number of * instances will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated * * @see * cpaDcGetInstances * *****************************************************************************/ CpaStatus cpaDcGetNumInstances(Cpa16U *pNumInstances); /** ***************************************************************************** * @ingroup cpaDc * Get the handles to the device instances that are supported by the * API implementation. * * @description * * This function will return handles to the device instances that are * supported by an implementation of the compression API. These instance * handles can then be used as input parameters with other compression API * functions. * * This function will populate an array that has been allocated by the * caller. The size of this API is determined by the * cpaDcGetNumInstances() function. * * @context * This function MUST NOT be called from an interrupt context as it MAY * sleep. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] numInstances Size of the array. * @param[out] dcInstances Pointer to where the instance * handles will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated * * @see * cpaDcGetInstances * *****************************************************************************/ CpaStatus cpaDcGetInstances(Cpa16U numInstances, CpaInstanceHandle *dcInstances); /** ***************************************************************************** * @ingroup cpaDc * Compression Component utility function to determine the number of * intermediate buffers required by an implementation. * * @description * This function will determine the number of intermediate buffer lists * required by an implementation for a compression instance. These buffers * should then be allocated and provided when calling @ref * cpaDcStartInstance() to start a compression instance that will use * dynamic compression. * * @context * This function may sleep, and MUST NOT be called in interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * @param[in,out] instanceHandle Handle to an instance of this API to be * initialized. * @param[out] pNumBuffers When the function returns, this will * specify the number of buffer lists that * should be used as intermediate buffers * when calling cpaDcStartInstance(). * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. Suggested course of action * is to shutdown and restart. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * * @see * cpaDcStartInstance() * *****************************************************************************/ CpaStatus cpaDcGetNumIntermediateBuffers(CpaInstanceHandle instanceHandle, Cpa16U *pNumBuffers); /** ***************************************************************************** * @ingroup cpaDc * Compression Component Initialization and Start function. * * @description * This function will initialize and start the compression component. * It MUST be called before any other compress function is called. This * function SHOULD be called only once (either for the very first time, * or after an cpaDcStopInstance call which succeeded) per instance. * Subsequent calls will have no effect. * * If required by an implementation, this function can be provided with * instance specific intermediate buffers. The intent is to provide an * instance specific location to store intermediate results during dynamic * instance Huffman tree compression requests. The memory should be * accessible by the compression engine. The buffers are to support * deflate compression with dynamic Huffman Trees. Each buffer list * should be similar in size to twice the destination buffer size passed * to the compress API. The number of intermediate buffer lists may vary * between implementations and so @ref cpaDcGetNumIntermediateBuffers() * should be called first to determine the number of intermediate * buffers required by the implementation. * * If not required, this parameter can be passed in as NULL. * * @context * This function may sleep, and MUST NOT be called in interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * @param[in,out] instanceHandle Handle to an instance of this API to be * initialized. * @param[in] numBuffers Number of buffer lists represented by * the pIntermediateBuffers parameter. * Note: @ref * cpaDcGetNumIntermediateBuffers() can * be used to determine the number of * intermediate buffers that an * implementation requires. * @param[in] pIntermediateBuffers Optional pointer to Instance specific * DRAM buffer. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. Suggested course of action * is to shutdown and restart. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * * @see * cpaDcStopInstance() * cpaDcGetNumIntermediateBuffers() * *****************************************************************************/ CpaStatus cpaDcStartInstance(CpaInstanceHandle instanceHandle, Cpa16U numBuffers, CpaBufferList **pIntermediateBuffers); /** ***************************************************************************** * @ingroup cpaDc * Compress Component Stop function. * * @description * This function will stop the Compression component and free * all system resources associated with it. The client MUST ensure that * all outstanding operations have completed before calling this function. * The recommended approach to ensure this is to deregister all session or * callback handles before calling this function. If outstanding * operations still exist when this function is invoked, the callback * function for each of those operations will NOT be invoked and the * shutdown will continue. If the component is to be restarted, then a * call to cpaDcStartInstance is required. * * @context * This function may sleep, and so MUST NOT be called in interrupt * context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * @param[in] instanceHandle Handle to an instance of this API to be * shutdown. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. Suggested course of action * is to ensure requests are not still being * submitted and that all sessions are * deregistered. If this does not help, then * forcefully remove the component from the * system. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaDcStartInstance * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * * @see * cpaDcStartInstance() * *****************************************************************************/ CpaStatus cpaDcStopInstance(CpaInstanceHandle instanceHandle); /** ***************************************************************************** * @ingroup cpaDc * Function to get information on a particular instance. * * @description * This function will provide instance specific information through a * @ref CpaInstanceInfo2 structure. * * @context * This function will be executed in a context that requires that sleeping * MUST NOT be permitted. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API to be * initialized. * @param[out] pInstanceInfo2 Pointer to the memory location allocated by * the client into which the CpaInstanceInfo2 * structure will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The client has retrieved an instanceHandle from successive calls to * @ref cpaDcGetNumInstances and @ref cpaDcGetInstances. * @post * None * @note * None * @see * cpaDcGetNumInstances, * cpaDcGetInstances, * CpaInstanceInfo2 * *****************************************************************************/ CpaStatus cpaDcInstanceGetInfo2(const CpaInstanceHandle instanceHandle, CpaInstanceInfo2 *pInstanceInfo2); /*****************************************************************************/ /* Instance Notification Functions */ /*****************************************************************************/ /** ***************************************************************************** * @ingroup cpaDc * Callback function for instance notification support. * * @description * This is the prototype for the instance notification callback function. * The callback function is passed in as a parameter to the * @ref cpaDcInstanceSetNotificationCb function. * * @context * This function will be executed in a context that requires that sleeping * MUST NOT be permitted. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCallbackTag Opaque value provided by user while making * individual function calls. * @param[in] instanceEvent The event that will trigger this function to * get invoked. * * @retval * None * @pre * Component has been initialized and the notification function has been * set via the cpaDcInstanceSetNotificationCb function. * @post * None * @note * None * @see * cpaDcInstanceSetNotificationCb(), * *****************************************************************************/ typedef void (*CpaDcInstanceNotificationCbFunc)( const CpaInstanceHandle instanceHandle, void *pCallbackTag, const CpaInstanceEvent instanceEvent); /** ***************************************************************************** * @ingroup cpaDc * Subscribe for instance notifications. * * @description * Clients of the CpaDc interface can subscribe for instance notifications * by registering a @ref CpaDcInstanceNotificationCbFunc function. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pInstanceNotificationCb Instance notification callback * function pointer. * @param[in] pCallbackTag Opaque value provided by user while * making individual function calls. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Instance has been initialized. * @post * None * @note * None * @see * CpaDcInstanceNotificationCbFunc * *****************************************************************************/ CpaStatus cpaDcInstanceSetNotificationCb( const CpaInstanceHandle instanceHandle, const CpaDcInstanceNotificationCbFunc pInstanceNotificationCb, void *pCallbackTag); /** ***************************************************************************** * @ingroup cpaDc * Get the size of the memory required to hold the session information. * * @description * * The client of the Data Compression API is responsible for * allocating sufficient memory to hold session information and the context * data. This function provides a means for determining the size of the * session information and the size of the context data. * * @context * No restrictions * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Instance handle. * @param[in] pSessionData Pointer to a user instantiated structure * containing session data. * @param[out] pSessionSize On return, this parameter will be the size * of the memory that will be * required by cpaDcInitSession() for session * data. * @param[out] pContextSize On return, this parameter will be the size * of the memory that will be required * for context data. Context data is * save/restore data including history and * any implementation specific data that is * required for a save/restore operation. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * Only a synchronous version of this function is provided. * * It is expected that context data is comprised of the history and * any data stores that are specific to the history such as linked * lists or hash tables. * For stateless sessions the context size returned from this function * will be zero. For stateful sessions the context size returned will * depend on the session setup data and may be zero. * * Session data is expected to include interim checksum values, various * counters and other session related data that needs to persist * between invocations. * For a given implementation of this API, it is safe to assume that * cpaDcGetSessionSize() will always return the same session size and * that the size will not be different for different setup data * parameters. However, it should be noted that the size may change: * (1) between different implementations of the API (e.g. between software * and hardware implementations or between different hardware * implementations) * (2) between different releases of the same API implementation. * * @see * cpaDcInitSession() * *****************************************************************************/ CpaStatus cpaDcGetSessionSize(CpaInstanceHandle dcInstance, CpaDcSessionSetupData *pSessionData, Cpa32U *pSessionSize, Cpa32U *pContextSize); /** ***************************************************************************** * @ingroup cpaDc * Function to return the size of the memory which must be allocated for * the pPrivateMetaData member of CpaBufferList. * * @description * This function is used to obtain the size (in bytes) required to allocate * a buffer descriptor for the pPrivateMetaData member in the * CpaBufferList structure. * Should the function return zero then no meta data is required for the * buffer list. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[in] numBuffers The number of pointers in the CpaBufferList. * This is the maximum number of CpaFlatBuffers * which may be contained in this CpaBufferList. * @param[out] pSizeInBytes Pointer to the size in bytes of memory to be * allocated when the client wishes to allocate * a cpaFlatBuffer. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * None * @see * cpaDcGetInstances() * *****************************************************************************/ CpaStatus cpaDcBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, Cpa32U numBuffers, Cpa32U *pSizeInBytes); /** ***************************************************************************** * @ingroup cpaDc * Function to return the size of the memory which must be allocated for * the pPrivateMetaData member of the source CpaBufferList used with * dictionary compression. * * @description * This function is used to obtain the size (in bytes) required to * allocate a buffer descriptor for the pPrivateMetaData member in the * CpaBufferList structure of the source buffer list used in the API's * cpaDcCompressDataWithDict() and cpaDcDecompressDataWithDict(). * In contrast the size in bytes to allocate the descriptor of the * destination buffer list must not use this API, and needs to be * determined using the API cpaDcBufferListGetMetaSize(). * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[in] numDictBuffers The number of CpaFlatBuffers contained in * the dictionary buffer CpaBufferList. * This number must not be exceeded during use. * @param[in] numSourceBuffers The number of CpaFlatBuffers contained in * the source buffer CpaBufferList. * This number must not be exceeded during use. * @param[out] pSizeInBytes Pointer to the size in bytes of memory to be * allocated as metadata to be assigned to the * pPrivateMetaData member of the source * buffer CpaBufferList. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * None * @see * cpaDcGetInstances() * *****************************************************************************/ CpaStatus cpaDcGetMetaSizeForSrcBuffWithDict( const CpaInstanceHandle instanceHandle, Cpa32U numDictBuffers, Cpa32U numSourceBuffers, Cpa32U *pSizeInBytes); /** ***************************************************************************** * @ingroup cpaDc * Function to return a string indicating the specific error that occurred * within the system. * * @description * When a function returns any error including CPA_STATUS_SUCCESS, the * client can invoke this function to get a string which describes the * general error condition, and if available additional information on * the specific error. * The Client MUST allocate CPA_STATUS_MAX_STR_LENGTH_IN_BYTES bytes for * the buffer string. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Handle to an instance of this API. * @param[in] errStatus The error condition that occurred. * @param[in,out] pStatusText Pointer to the string buffer that will * be updated with the status text. The invoking * application MUST allocate this buffer to be * exactly CPA_STATUS_MAX_STR_LENGTH_IN_BYTES. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. Note, in this scenario * it is INVALID to call this function a * second time. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * None * @see * CpaStatus * *****************************************************************************/ CpaStatus cpaDcGetStatusText(const CpaInstanceHandle dcInstance, const CpaStatus errStatus, Cpa8S *pStatusText); /** ***************************************************************************** * @ingroup cpaDc * Set Address Translation function * * @description * This function is used to set the virtual to physical address * translation routine for the instance. The specified routine * is used by the instance to perform any required translation of * a virtual address to a physical address. If the application * does not invoke this function, then the instance will use its * default method, such as virt2phys, for address translation. * * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Data Compression API instance handle. * @param[in] virtual2Physical Routine that performs virtual to * physical address translation. * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus cpaDcSetAddressTranslation(const CpaInstanceHandle instanceHandle, CpaVirtualToPhysical virtual2Physical); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_DC_H */ qatlib-25.08.0/quickassist/include/dc/cpa_dc_capabilities.h000066400000000000000000000311741503624047500236250ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_dc_capabilities.h * * @defgroup cpaDcCap Capability APIs for Data Compression * * @ingroup cpaDc * * @description * This file specifies the API for Data Compression capability queries. * * @remarks * * *****************************************************************************/ #ifndef CPA_DC_CAPABILITIES_H #define CPA_DC_CAPABILITIES_H #ifdef __cplusplus extern "C" { #endif #include "cpa.h" #include "cpa_dc.h" /** ***************************************************************************** * @ingroup cpaDcCap * Capability IDs * * @description * This enumeration lists the capabilities that can be queried * using cpaDcQueryCapabilityByType() API. * *****************************************************************************/ typedef enum _CpaDcCapabilityId { CPA_DC_CAP_BOOL_STATELESS = 0, /**< Support for specified algorithm for a stateless session */ CPA_DC_CAP_BOOL_STATEFUL = 1, /**< Support for specified algorithm for a stateful session */ CPA_DC_CAP_BOOL_STATEFUL_LITE = 2, /**< Check if stateful lite is supported */ CPA_DC_CAP_BOOL_WINDOW_SIZE_4K = 3, /**< Support for 4K window size */ CPA_DC_CAP_BOOL_WINDOW_SIZE_8K = 4, /**< Support for 8K window size */ CPA_DC_CAP_BOOL_WINDOW_SIZE_16K = 5, /**< Support for 16K window size */ CPA_DC_CAP_BOOL_WINDOW_SIZE_32K = 6, /**< Support for 32K window size */ CPA_DC_CAP_BOOL_WINDOW_SIZE_64K = 7, /**< Support for 64K window size */ CPA_DC_CAP_U32_DEFAULT_WINDOW_SIZE = 8, /**< Fetch the default supported window size */ CPA_DC_CAP_BOOL_DYNAMIC_HUFFMAN = 9, /**< Support for Dynamic Huffman Tree Deflate algorithm */ CPA_DC_CAP_BOOL_STATIC_HUFFMAN = 10, /**< Support for Static Huffman Tree Deflate algorithm */ CPA_DC_CAP_BOOL_BLOCK_CHECKSUM = 11, /**< Support for block checksum generation */ CPA_DC_CAP_BOOL_ACCUMULATE_XXHASH = 12, /**< Check if algorithm can accumulate xxHash */ CPA_DC_CAP_BOOL_BLOCK_SIZE_64K = 13, /**< Check if algorithm supports 64K block size */ CPA_DC_CAP_BOOL_BLOCK_SIZE_256K = 14, /**< Check if algorithm supports 256K block size */ CPA_DC_CAP_BOOL_BLOCK_SIZE_1M = 15, /**< Check if algorithm supports 1M block size */ CPA_DC_CAP_BOOL_BLOCK_SIZE_4M = 16, /**< Check if algorithm supports 4M block size */ CPA_DC_CAP_U32_BLOCK_SIZE_BITMASK = 17, /**< Bitmask of supported block sizes, enum CpaDcBlockSizeBitmask */ CPA_DC_CAP_BOOL_CHECKSUM_CRC32 = 18, /**< Check if CRC32 checksum is supported */ CPA_DC_CAP_BOOL_CHECKSUM_ADLER32 = 19, /**< Check if Adler32 checksum is supported */ CPA_DC_CAP_BOOL_CHECKSUM_XXHASH32 = 20, /**< Check if XXHash32 checksum is supported */ CPA_DC_CAP_BOOL_CHECKSUM_XXHASH64 = 21, /**< Check if XXHash64 checksum is supported */ CPA_DC_CAP_BOOL_ASB = 22, /**< Check if Auto Select Best is supported. * Compression direction only */ CPA_DC_CAP_BOOL_ASB_THRESHOLD = 23, /**< Check if Auto Select Best with threshold is supported. * Compression direction only */ CPA_DC_CAP_BOOL_ASB_RATIO = 24, /**< Check if Auto Select Best with ratio is supported. * Compression direction only */ CPA_DC_CAP_BOOL_ASB_ENABLE_PREFERRED = 25, /**< Check if it is preferred to keep ASB enabled for the requested compression algorithm */ CPA_DC_CAP_BOOL_DETERMINISM = 26, /**< Check if Determinism is supported with compression operation */ CPA_DC_CAP_BOOL_OVERFLOW_RESUBMIT = 27, /**< Check if resubmission of (un)compressed data is supported */ CPA_DC_CAP_BOOL_COMPRESS_N_VERIFY = 28, /**< Check if "compress and verify" error reporting is supported */ CPA_DC_CAP_BOOL_COMPRESS_N_VERIFY_N_RECOVER = 29, /**< Check if instance can produce an uncompressed block in the event of "compress and verify" error. */ CPA_DC_CAP_BOOL_INTEGRITY_CRC32 = 30, /**< Check if integrity CRC32 checksum is supported */ CPA_DC_CAP_BOOL_INTEGRITY_CRC64 = 31, /**< Check if integrity CRC64 checksum is supported */ CPA_DC_CAP_BOOL_CHAIN_HASH_THEN_COMPRESS = 32, /**< Check if chain hash then compress is supported */ CPA_DC_CAP_BOOL_CHAIN_COMPRESS_THEN_AEAD = 33, /**< Check if chain compress then aead is supported */ CPA_DC_CAP_BOOL_CHAIN_AEAD_THEN_DECOMPRESS = 34, /**< Check if chain aead then decompress is supported */ CPA_DC_CAP_BOOL_UNCOMPRESSED_DICT = 35, /**< Check if the algorithm supports compression or decompression using an uncompressed dictionary */ CPA_DC_CAP_BOOL_COMPRESSED_DICT = 36, /**< Check if the algorithm supports compression or decompression using a compressed dictionary */ CPA_DC_CAP_BOOL_ZERO_LENGTH_REQ = 37, /**< Check if submission of zero length requests is supported */ CPA_DC_CAP_BOOL_PROGRAMMABLE_CRC64 = 38, /**< Check if programmable CRC64 is supported */ CPA_DC_CAP_BOOL_CHAIN_PROGRAMMABLE_CRC64 = 39, /**< Check if programmable CRC64 with chaining is supported */ CPA_DC_CAP_BOOL_E2E_CRC_OVER_COMP_BLOCK = 40, /**< Check if E2E CRC is supported over compressed block. This capability is only applicable in compression direction. */ CPA_DC_CAP_BOOL_DICT_ID = 41, /**< Support for dictionary ID */ } CpaDcCapabilityId; /** ***************************************************************************** * @ingroup cpaDcCap * Implementation of the Capability Request structure * @description * This structure lists the parameters required for querying capabilities * @note * All parameters must be set unless otherwise stated in the * CpaDcCapabilityId capId comment * ****************************************************************************/ typedef struct _CpaDcCapabilityReq { CpaDcCompType algo; /**< Algorithm ID from CpaDcCompType being queried */ CpaDcDir dir; /**< Algorithm direction from CpaDcDir being queried. * Only COMPRESS and DECOMPRESS directions are supported. */ CpaDcCapabilityId capId; /**< Capability ID from CpaDcCapabilityId being queried */ } CpaDcCapabilityReq; /** ***************************************************************************** * @ingroup cpaDcCap * Implementation of the Capability Response parameter * @description * This union lists the various response types that are supported by the * cpaDcQueryCapabilityByType() API. * ****************************************************************************/ typedef union _CpaDcCapabilityResp { CpaBoolean boolStatus; /**< A boolean value in response to a capability query with capId name * CPA_DC_CAP_BOOL_XXX */ Cpa32U u32Status; /**< A 32bit value in response to a capability query with capId name * CPA_DC_CAP_U32_XXX */ Cpa64U u64Status; /**< A 64bit value in response to a capability query with capId name * CPA_DC_CAP_U64_XXX */ } CpaDcCapabilityResp; /** ***************************************************************************** * @ingroup cpaDcCap * Query capabilities for a data compression instance * * @description * This function is used to query the capabilities supported by a * compression instance. * * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Data compression instance handle * @param[in] capabilityReq Request parameter of the type * CpaDcCapabilityReq that will identify the * capability that is being queried. * @param[in,out] pCapabilityResp Pointer to a CpaDcCapabilityResp structure. * On return the result of the query will be * stored here. * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED The function is not supported, or a field * in the request is above the top range of its * enum. This API may be extended to include * additional capability IDs or other * algorithms. This return value should be * understood as the capability is unknown, * rather than that the capability is * unsupported as the library cannot answer * whether it has the capability or not. * * @pre * None * @post * None * @note * This API will accept the capability request parameter that will identify * the capability ID and the algorithm and the algorithm direction that is * being queried. These parameters are used to fetch the instance * capability. The value returned in CpaDcCapabilityResp should be * interpreted based on the name of the capId, e.g. CPA_DC_CAP_BOOL_XXX * will return boolStatus. * @see * None * *****************************************************************************/ CpaStatus cpaDcQueryCapabilityByType(CpaInstanceHandle dcInstance, CpaDcCapabilityReq capabilityReq, CpaDcCapabilityResp *pCapabilityResp); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_DC_CAPABILITIES_H */ qatlib-25.08.0/quickassist/include/dc/cpa_dc_chain.h000066400000000000000000001160311503624047500222520ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_dc_chain.h * * @defgroup cpaDcChain Data Compression Chaining API * * @ingroup cpaDc * * @description * These functions specify the API for Data Compression Chaining * operations. * * @remarks * * *****************************************************************************/ #ifndef CPA_DC_CHAIN_H #define CPA_DC_CHAIN_H #ifdef __cplusplus extern "C" { #endif #include "cpa_dc.h" #include "cpa_cy_sym.h" /** ***************************************************************************** * @ingroup cpaDcChain * Supported operations for compression chaining * * @description * This enumeration lists the supported operations for compression chaining * *****************************************************************************/ typedef enum _CpaDcChainOperations { CPA_DC_CHAIN_COMPRESS_THEN_HASH = 0, /**< 2 operations for chaining: * 1st operation is to perform compression on plain text * 2nd operation is to perform hash on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for compression setup data * 2nd entry is for hash setup data */ CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT = 1, /**< 2 operations for chaining: * 1st operation is to perform compression on plain text * 2nd operation is to perform encryption on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for compression setup data * 2nd entry is for encryption setup data */ CPA_DC_CHAIN_COMPRESS_THEN_HASH_ENCRYPT = 2, /**< 2 operations for chaining: * 1st operation is to perform compression on plain text * 2nd operation is to perform hash on compressed text and * encryption on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for compression setup data * 2nd entry is for hash and encryption setup data */ CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT_HASH = 3, /**< 2 operations for chaining: * 1st operation is to perform compression on plain text * 2nd operation is to perform encryption on compressed text and * hash on compressed & encrypted text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for compression setup data * 2nd entry is for encryption and hash setup data */ CPA_DC_CHAIN_COMPRESS_THEN_AEAD = 4, /**< 2 operations for chaining: * 1st operation is to perform compression on plain text * 2nd operation is to perform AEAD encryption on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for compression setup data * 2nd entry is for AEAD encryption setup data */ CPA_DC_CHAIN_HASH_THEN_COMPRESS = 5, /**< 2 operations for chaining: * 1st operation is to perform hash on plain text * 2nd operation is to perform compression on plain text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for hash setup data * 2nd entry is for compression setup data */ CPA_DC_CHAIN_HASH_VERIFY_THEN_DECOMPRESS = 6, /**< 2 operations for chaining: * 1st operation is to perform hash verify on compressed text * 2nd operation is to perform decompression on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for hash setup data * 2nd entry is for decompression setup data */ CPA_DC_CHAIN_DECRYPT_THEN_DECOMPRESS = 7, /**< 2 operations for chaining: * 1st operation is to perform decryption on compressed & encrypted text * 2nd operation is to perform decompression on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for decryption setup data * 2nd entry is for decompression setup data */ CPA_DC_CHAIN_HASH_VERIFY_DECRYPT_THEN_DECOMPRESS = 8, /**< 2 operations for chaining: * 1st operation is to perform hash verify on compressed & encrypted text * and decryption on compressed & encrypted text * 2nd operation is to perform decompression on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for hash and decryption setup data * 2nd entry is for decompression setup data */ CPA_DC_CHAIN_DECRYPT_HASH_VERIFY_THEN_DECOMPRESS = 9, /**< 2 operations for chaining: * 1st operation is to perform decryption on compressed & encrypted text * and hash verify on compressed text * 2nd operation is to perform decompression on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for decryption and hash setup data * 2nd entry is for decompression setup data */ CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS = 10, /**< 2 operations for chaining: * 1st operation is to perform AEAD decryption on compressed & encrypted * text * 2nd operation is to perform decompression on compressed text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for AEAD decryption setup data * 2nd entry is for decompression setup data */ CPA_DC_CHAIN_DECOMPRESS_THEN_HASH_VERIFY = 11, /**< 2 operations for chaining: * 1st operation is to perform decompression on compressed text * 2nd operation is to perform hash verify on plain text * 2 entries in CpaDcChainSessionSetupData array: * 1st entry is for decompression setup data * 2nd entry is for hash setup data */ CPA_DC_CHAIN_COMPRESS_THEN_AEAD_THEN_HASH = 12, /**< 3 operations for chaining: * 1st operation is to perform compression on plain text * 2nd operation is to perform AEAD encryption on compressed text * 3rd operation is to perform hash on compressed & encrypted text * 3 entries in CpaDcChainSessionSetupData array: * 1st entry is for compression setup data * 2nd entry is for AEAD encryption setup data * 3rd entry is for hash setup data */ } CpaDcChainOperations; /** ***************************************************************************** * @ingroup cpaDcChain * Supported session types for data compression chaining. * * @description * This enumeration lists the supported session types * for data compression chaining. *****************************************************************************/ typedef enum _CpaDcChainSessionType { CPA_DC_CHAIN_COMPRESS_DECOMPRESS = 0, /**< Indicate the session is for compression or decompression */ CPA_DC_CHAIN_SYMMETRIC_CRYPTO /**< Indicate the session is for symmetric crypto */ } CpaDcChainSessionType; /** ***************************************************************************** * @ingroup cpaDcChain * Chaining Session Setup Data. * @description * This structure contains data relating to the setup of a chaining * session. * This structure can comprise either compression or crypto session data * determined by the sessType. * The client needs to complete the information in this structure in order * to setup a chaining session. * This structure contains settings for use with the * cpaDcChainInitSession API. * ****************************************************************************/ typedef struct _CpaDcChainSessionSetupData { CpaDcChainSessionType sessType; /**< Indicate the type for this session */ union { CpaDcSessionSetupData *pDcSetupData; /**< Pointer to compression session setup data */ CpaCySymSessionSetupData *pCySetupData; /**< Pointer to symmetric crypto session setup data */ }; } CpaDcChainSessionSetupData; /** ***************************************************************************** * @ingroup cpaDcChain * Compression chaining request input parameters. * @description * This structure contains the request information to use with * compression chaining operations. * This structure contains settings for use with the * cpaDcChainPerformOp API. * ****************************************************************************/ typedef struct _CpaDcChainOpData { CpaDcChainSessionType opType; /**< Indicate the type for this operation */ union { CpaDcOpData *pDcOp; /**< Pointer to compression operation data */ CpaCySymOpData *pCySymOp; /**< Pointer to symmetric crypto operation data with * append crc64 option */ }; } CpaDcChainOpData; /** ***************************************************************************** * @ingroup cpaDcChain * Compression chaining request input parameters. * @description * This structure contains the request information to use with * compression chaining sub-request operations. * This structure contains settings for use with the * cpaDcChainPerformOp2 API. * ****************************************************************************/ typedef struct _CpaDcChainSubOpData2 { CpaDcChainSessionType opType; /**< Indicate the type for this operation */ union { CpaDcOpData2 *pDcOp2; /**< Pointer to compression operation data */ CpaCySymOpData2 *pCySymOp2; /**< Pointer to symmetric crypto operation data with * additional options. */ }; } CpaDcChainSubOpData2; /** ***************************************************************************** * @ingroup cpaDcChain * Chaining request result data * @description * This structure contains the request results. * This result structure is used with the cpaDcChainPerformOp API. * ****************************************************************************/ typedef struct _CpaDcChainRqResults { CpaDcReqStatus dcStatus; /**< Additional status details from compression accelerator */ CpaStatus cyStatus; /**< Additional status details from symmetric crypto accelerator */ CpaBoolean verifyResult; /**< This parameter is valid when the verifyDigest option is set in the * CpaCySymSessionSetupData structure. A value of CPA_TRUE indicates * that the compare succeeded. A value of CPA_FALSE indicates that the * compare failed */ Cpa32U produced; /**< Octets produced to the output buffer */ Cpa32U consumed; /**< Octets consumed from the input buffer */ Cpa32U crc32; /**< Crc32 checksum produced by chaining operations */ Cpa32U adler32; /**< Adler32 checksum produced by chaining operations */ } CpaDcChainRqResults; /** ***************************************************************************** * @ingroup cpaDcChain * Chaining request result data for chained operations with optional * verification step. * @description * This structure contains the request results. * This result structure is used with the cpaDcChainPerformOp2 API. * ****************************************************************************/ typedef struct _CpaDcChainRqVResults { CpaDcChainRqResults chainRqResults; /**< Chain result structure. */ Cpa64U ctxCrc64; /**< Crc64 of context structure. * Applicable to store2 flow. */ Cpa64U iDcCrc64; /**< Input crc of DC operation */ Cpa64U oDcCrc64; /**< Output crc of DC operation */ Cpa64U storedCrc64; /**< Crc64 that was appended to compressed data. * Only valid if decrypt and decompress operations * were performed successfully and appendCrc was requested. */ CpaBoolean reserved1; /**< Reserved for future use */ CpaStatus chainStatus; /**< Status of chain command. In the event the request is invalid, * a value of CPA_STATUS_INVALID_PARAM or CPA_STATUS_UNSUPPORTED may * be returned. If the request has been successfully sent to the * accelerator and has been processed, this value will be set to * CPA_STATUS_SUCCESS. To verify the success of the entire chain * operation, the return status of each operation must be examined. */ } CpaDcChainRqVResults; /** ***************************************************************************** * @ingroup cpaDcChain * Chaining request data for chained operations with optional * verification step. * @description * This structure contains arguments for the cpaDcChainPerformOp2 API. * ****************************************************************************/ typedef struct _CpaDcChainOpData2 { CpaBoolean testIntegrity; /**< True if integrity check is required */ CpaDcChainOperations operation; /**< Description of operations */ Cpa8U numOpDatas; /**< Number of elements in pChainOpData, which define the chain * operation. */ CpaDcChainSubOpData2 *pChainOpData; /**< Array of operations for chaining */ } CpaDcChainOpData2; /** ***************************************************************************** * @ingroup cpaDcChain * Get the size of the memory required to hold the chaining session * information. * * @description * The client of the Data Compression API is responsible for * allocating sufficient memory to hold chaining session information. * This function provides a way for determining the size of a chaining * session. * * @context * No restrictions * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Instance handle. * @param[in] operation The operation for chaining * @param[in] numSessions Number of sessions for the chaining * @param[in] pSessionData Pointer to an array of * CpaDcChainSessionSetupData structures. * There should be numSessions entries in * the array. * @param[out] pSessionSize On return, this parameter will be the size * of the memory that will be required * to be allocated for the session handle. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * dcInstance has been started using cpaDcStartInstance. * @post * pSessionSize will contain the size in bytes to be allocated for the * session handle. * @note * Only a synchronous version of this function is provided. * * @see * cpaDcChainInitSession() * *****************************************************************************/ CpaStatus cpaDcChainGetSessionSize(CpaInstanceHandle dcInstance, CpaDcChainOperations operation, Cpa8U numSessions, CpaDcChainSessionSetupData *pSessionData, Cpa32U *pSessionSize); /** ***************************************************************************** * @ingroup cpaDcChain * Initialize data compression chaining session * * @description * This function is used to initialize a compression/decompression * chaining session. * This function returns a unique session handle each time this function * is invoked. * If the session has been configured with a callback function, then * the order of the callbacks are guaranteed to be in the same order the * compression or decompression requests were submitted for each session, * so long as a single thread of execution is used for job submission. * For data integrity computations the default CRC algorithm parameters * are used. * * @context * This is a synchronous function and it cannot sleep. It can be executed * in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Instance handle derived from discovery * functions. * @param[in,out] pSessionHandle Pointer to a session handle. * @param[in] operation The operations for chaining * @param[in] numSessions Number of sessions for chaining * @param[in,out] pSessionData Pointer to an array of * CpaDcChainSessionSetupData structures. * There should be numSessions entries in * the array. * @param[in] callbackFn For synchronous operation this callback * shall be a null pointer. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * dcInstance has been started using cpaDcStartInstance. * Before the session is initialized with this function, * cpaDcChainGetSessionSize() function should be used to determine the * size of the session handle. Memory needs to be allocated of the * required size and passed in as the pSessionHandle. * @post * Internal state and session parameters will be stored within the * session handle. * @note * Only a synchronous version of this function is provided. * * pSessionData Setup Rules * -# Each element in CpaDcChainSessionSetupData structure array provides * (de)compression or a symmetric crypto session setup data. * * -# The supported chaining operations are listed in CpaDcChainOperations. * This enum indicates the number of operations in a chain and the order * in which they are performed. * * -# The order of entries in pSessionData[] should be consistent with the * CpaDcChainOperations perform order. * As an example, for CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT, pSessionData[0] * holds the compression setup data and pSessionData[1] holds the * encryption setup data.. * * -# The numSessions for each chaining operation are provided in * the documentation of enum CpaDcChainOperations. * * -# For a (de)compression session, the corresponding * pSessionData[]->sessType should be set to * CPA_DC_CHAIN_COMPRESS_DECOMPRESS and pSessionData[]->pDcSetupData * should point to a CpaDcSessionSetupData structure. * * -# For a symmetric crypto session, the corresponding * pSessionData[]->sessType should be set to CPA_DC_CHAIN_SYMMETRIC_CRYPTO * and pSessionData[]->pCySetupData should point to a * CpaCySymSessionSetupData structure. * * -# Combined compression sessions are not supported for chaining. * * -# Stateful compression/decompression is not supported for chaining. * * -# Simultaneous CRC32 and Adler32 over the input data are supported for * chaining. * * @see * None * *****************************************************************************/ CpaStatus cpaDcChainInitSession(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcChainOperations operation, Cpa8U numSessions, CpaDcChainSessionSetupData *pSessionData, CpaDcCallbackFn callbackFn); /** ***************************************************************************** * @ingroup cpaDcChain * Initialize CRC parameters for a DC Chaining session * * @description * This function is used to initialize E2E programmable CRC parameters. * * @context * This is a synchronous function and it cannot sleep. It can be executed * in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Instance handle derived from discovery * functions. * @param[in,out] pSessionHandle Pointer to a session handle. * @param[in] pCrcControlData Pointer to a user instantiated structure * containing the CRC parameters. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_FAIL Operation failed. * @retval CPA_STATUS_UNSUPPORTED Unsupported feature. * * @pre * dcInstance has been started using cpaDcStartInstance. * cpaDcInitSession has been called to initialize session parameters. * @post * None * @note * Only a synchronous version of this function is provided. * * @see * None * *****************************************************************************/ CpaStatus cpaDcChainSetCrcControlData(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaCrcControlData *pCrcControlData); /** ***************************************************************************** * @ingroup cpaDcChain * Reset a compression chaining session. * * @description * This function will reset a previously initialized session handle. * Reset will return CPA_STATUS_RETRY if outstanding calls still exist * for the initialized session handle. In that case the client needs to * retry the reset function at a later time. * * @context * This is a synchronous function that cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Instance handle. * @param[in,out] pSessionHandle Session handle. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaDcStartInstance function. * The session has been initialized via cpaDcChainInitSession. * This function will work with either standard or extended chained * requests. * @post * Internal state within the chained session will be cleared allowing * the session to be reused again without calling either * cpaDcChainRemoveSession or cpaDcChainInitSession. * @note * This is a synchronous function and has no completion callback * associated with it. * cpaDcChainResetSession() API will have the capability to reset a * session previously initialized with cpaDcChainInitSession(). * * @see * cpaDcChainInitSession() * *****************************************************************************/ CpaStatus cpaDcChainResetSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle); /** ***************************************************************************** * @ingroup cpaDcChain * Remove a compression chaining session. * * @description * This function will remove a previously initialized session handle * and the installed callback handler function. Removal will fail if * outstanding calls still exist for the initialized session handle. * The client needs to retry the remove function at a later time. * The memory for the session handle MUST not be freed until this call * has completed successfully. * * @context * This is a synchronous function that cannot sleep. It can be executed * in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Instance handle. * @param[in,out] pSessionHandle Session handle. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaDcStartInstance function. * pSessionHandle has been setup using cpaDcChainInitSession(). * This function will work with either standard or extended chained * requests. * @post * Following a retval of CPA_STATUS_SUCCESS it is safe to free the * memory allocated for the session handle. * @note * This is a synchronous function and has no completion callback * associated with it. * cpaDcChainRemoveSession() API will have the capability to remove a * session initialized with cpaDcChainInitSession(). * * @see * cpaDcChainInitSession() * *****************************************************************************/ CpaStatus cpaDcChainRemoveSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle); /** ***************************************************************************** * @ingroup cpaDcChain * Submit a request to perform chaining operations. * * @description * This function is used to perform chaining operations over data from * the source buffer. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to input data buffer. * @param[out] pDestBuff Pointer to output data buffer. * @param[in] operation Operation for the chaining request * @param[in] numOpData The number of CpaDcChainOpData array items * @param[in] pChainOpData Pointer to an array of CpaDcChainOpData * structures. There should be numOpData * items in the array. * @param[in,out] pResults Pointer to CpaDcChainRqResults * @param[in] callbackTag User supplied value to help correlate * the callback with its associated request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_DC_BAD_DATA The input data was not properly formed. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * pSessionHandle has been setup using cpaDcChainInitSession() * @post * Following synchronous operation: * The pSessionHandle will contain updated session related state * information. * The pDestBuff will contain processed data following the chained * operation. * The pResults will contain the status/checksums/additional outputs * from the completed chained operation. * Following asynchronous operation: * The call has been submitted and the data dependent structures will * only be safe to use once the asynchronous callback is called. * @note * This function passes control to the compression service for chaining * processing, the supported chaining operations are described in * CpaDcChainOperations. * This function does not support the additional integrity checking * chaining features supported in cpaDcChainPerformOp2() and should only * be used if these features are not required. * * pChainOpData Setup Rules * -# Each element in CpaDcChainOpData structure array holds either a * (de)compression or a symmetric crypto operation data. * * -# The order of entries in pChainOpData[] must be consistent with the * order of operations described for the chaining operation in * CpaDcChainOperations. * As an example, for CPA_DC_CHAIN_HASH_THEN_COMPRESS, pChainOpData[0] * must contain the hash operation data and pChainOpData[1] must * contain the compress operation data. * * -# The numOpData for each chaining operation are specified in the * documentation for the operation in CpaDcChainOperations. * * -# For a (de)compression operation, the corresponding * pChainOpData[]->opType should be set to * CPA_DC_CHAIN_COMPRESS_DECOMPRESS and pChainOpData[]->pDcOp should * point to a CpaDcOpData structure. * * -# For a symmetric crypto operation, the corresponding * pChainOpData[]->opType should be set to * CPA_DC_CHAIN_SYMMETRIC_CRYPTO and pChainOpData[]->pCySymOp should * point to a CpaCySymOpData structure. * * -# Partial packet processing is not supported. * * This function has identical buffer processing rules as * cpaDcCompressData(). * * This function has identical checksum processing rules as * cpaDcCompressData(), except: * -# pResults->crc32 is available to the application if * CpaDcSessionSetupData->checksum is set to CPA_DC_CRC32 * and will contain a crc32 checksum. * * -# pResults->adler32 is available to the application if * CpaDcSessionSetupData->checksum is set to CPA_DC_ADLER32 * and will contain an adler32 checksum. * * -# pResults->adler32 is available to the application if * CpaDcSessionSetupData->checksum is set to CPA_DC_XXHASH32 * and will contain an xxhash32 checksum. * * -# Both pResults->crc32 and pResults->adler32 are available if * CpaDcSessionSetupData->checksum is set to CPA_DC_CRC32_ADLER32 * and will contain crc32 and adler32 checksums respectively. * * Synchronous or asynchronous operation of the API is determined by * the value of the callbackFn parameter passed to cpaDcChainInitSession() * when the sessionHandle was setup. If a non-NULL value was specified * then the supplied callback function will be invoked asynchronously * with the response of this request. * * This function has identical response ordering rules as * cpaDcCompressData(). * * @see * cpaDcCompressData * *****************************************************************************/ CpaStatus cpaDcChainPerformOp(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcChainOperations operation, Cpa8U numOpData, CpaDcChainOpData *pChainOpData, CpaDcChainRqResults *pResults, void *callbackTag); /** ***************************************************************************** * @ingroup cpaDcChain * Submit a request to perform chaining with integrity operations. * * @description * This function is used to perform chaining operations over data from * the source buffer with optional integrity checking. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to input data buffer. * @param[out] pDestBuff Pointer to output data buffer. * @param[in] pInterBuff Pointer to intermediate buffer to be used * as internal staging area for chaining * operations. * @param[in] opData User supplied CpaDcChainOpData2 * structure. * @param[in,out] pResults Pointer to CpaDcChainRqVResults * structure. * @param[in] callbackTag User supplied value to help correlate * the callback with its associated request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_DC_BAD_DATA The input data was not properly formed. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * pSessionHandle has been setup using cpaDcChainInitSession() * @post * Following synchronous operation: * The pSessionHandle will contain updated session related state * information. * The pDestBuff will contain processed data following the chained * operation. * The pResults will contain the status/checksums/additional outputs * from the completed chained operation. * Following asynchronous operation: * The call has been submitted only and the data structures above will * only be safe to use once the asynchronous callback is called. * @note * This function passes control to the compression service for chaining * processing, the supported chaining operations are described in * CpaDcChainOperations. * This function is a replacement for cpaDcChainPerformOp() supporting * additional integrity chaining features and should be used if these * additional features are required. * * User supplied opData contains pChainOpData * -# Refer to cpaDcChainPerformOp for pChainOpData Setup Rules * * This function has identical buffer processing rules as * cpaDcCompressData(). * * Synchronous or asynchronous operation of the API is determined by * the value of the callbackFn parameter passed to cpaDcChainInitSession() * when the sessionHandle was setup. If a non-NULL value was specified * then the supplied callback function will be invoked asynchronously * with the response of this request. * * This function has identical response ordering rules as * cpaDcCompressData(). * * @see * cpaDcCompressData * *****************************************************************************/ CpaStatus cpaDcChainPerformOp2(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaBufferList *pInterBuff, CpaDcChainOpData2 opData, CpaDcChainRqVResults *pResults, void *callbackTag); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_DC_CHAIN_H */ qatlib-25.08.0/quickassist/include/dc/cpa_dc_dp.h000066400000000000000000001410501503624047500215720ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_dc_dp.h * * @defgroup cpaDcDp Data Compression Data Plane API * * @ingroup cpaDc * * @description * These data structures and functions specify the Data Plane API * for compression and decompression operations. * * This API is recommended for data plane applications, in which the * cost of offload - that is, the cycles consumed by the driver in * sending requests to the hardware, and processing responses - needs * to be minimized. In particular, use of this API is recommended * if the following constraints are acceptable to your application: * * - Thread safety is not guaranteed. Each software thread should * have access to its own unique instance (CpaInstanceHandle) to * avoid contention. * - Polling is used, rather than interrupts (which are expensive). * Implementations of this API will provide a function (not * defined as part of this API) to read responses from the hardware * response queue and dispatch callback functions, as specified on * this API. * - Buffers and buffer lists are passed using physical addresses, * to avoid virtual to physical address translation costs. * - The ability to enqueue one or more requests without submitting * them to the hardware allows for certain costs to be amortized * across multiple requests. * - Only asynchronous invocation is supported. * - There is no support for partial packets. * - Implementations may provide certain features as optional at * build time, such as atomic counters. * - There is no support for stateful operations. * - The "default" instance (CPA_INSTANCE_HANDLE_SINGLE) is not * supported on this API. The specific handle should be obtained * using the instance discovery functions (@ref cpaDcGetNumInstances, * @ref cpaDcGetInstances). * *****************************************************************************/ #ifndef CPA_DC_DP_H #define CPA_DC_DP_H #ifdef __cplusplus extern "C" { #endif #include "cpa_dc.h" /** ***************************************************************************** * @ingroup cpaDcDp * Decompression partial read data. * @description * This structure contains configuration related to requesting * specific chunk of decompression data. * ****************************************************************************/ typedef struct _CpaDcDpPartialReadData { Cpa32U bufferOffset; /**< Number of bytes to skip in the destination buffer (or buffers list) * before writing. At this point only zero is supported. */ Cpa32U dataOffset; /**< The offset in the decompressed data of the first byte written to * the destination buffer. The data offset length should be an integer * multiple of 4KB in order to achieve the best performance. */ Cpa32U length; /**< Size in bytes of requested decompressed data chunk. The length should be * an integer multiple of 4KB in order to achieve the best performance. */ } CpaDcDpPartialReadData; /** ***************************************************************************** * @ingroup cpaDcDp * Operation Data for compression data plane API. * * @description * This structure contains data relating to a request to perform * compression processing on one or more data buffers. * * The physical memory to which this structure points should be * at least 8-byte aligned. * * All reserved fields SHOULD NOT be written or read by the * calling code. * * @see * cpaDcDpEnqueueOp, cpaDcDpEnqueueOpBatch ****************************************************************************/ typedef struct _CpaDcDpOpData { Cpa64U reserved0; /**< Reserved for internal use. Source code should not read or write * this field. */ Cpa32U bufferLenToCompress; /**< The number of bytes from the source buffer to compress. This must be * less than, or more typically equal to, the total size of the source * buffer (or buffer list). */ Cpa32U bufferLenForData; /**< The maximum number of bytes that should be written to the destination * buffer. This must be less than, or more typically equal to, the total * size of the destination buffer (or buffer list). */ Cpa64U reserved1; /**< Reserved for internal use. Source code should not read or write */ Cpa64U reserved2; /**< Reserved for internal use. Source code should not read or write */ Cpa64U reserved3; /**< Reserved for internal use. Source code should not read or write */ CpaDcRqResults results; /**< Results of the operation. Contents are valid upon completion. */ CpaInstanceHandle dcInstance; /**< Instance to which the request is to be enqueued */ CpaDcSessionHandle pSessionHandle; /**< DC Session associated with the stream of requests. * This field is only valid when using the session based API functions. * This field must be set to NULL if the application wishes to use * the No-Session (Ns) API. */ CpaPhysicalAddr srcBuffer; /**< Physical address of the source buffer on which to operate. * This is either the location of the data, of length srcBufferLen; or, * if srcBufferLen has the special value @ref CPA_DP_BUFLIST, then * srcBuffer contains the location where a @ref CpaPhysBufferList is * stored. */ Cpa32U srcBufferLen; /**< If the source buffer is a "flat buffer", then this field * specifies the size of the buffer, in bytes. If the source buffer * is a "buffer list" (of type @ref CpaPhysBufferList), then this field * should be set to the value @ref CPA_DP_BUFLIST. */ CpaPhysicalAddr destBuffer; /**< Physical address of the destination buffer on which to operate. * This is either the location of the data, of length destBufferLen; or, * if destBufferLen has the special value @ref CPA_DP_BUFLIST, then * destBuffer contains the location where a @ref CpaPhysBufferList is * stored. */ Cpa32U destBufferLen; /**< If the destination buffer is a "flat buffer", then this field * specifies the size of the buffer, in bytes. If the destination buffer * is a "buffer list" (of type @ref CpaPhysBufferList), then this field * should be set to the value @ref CPA_DP_BUFLIST. */ CpaDcSessionDir sessDirection; /**pSessionHandle was setup using * @ref cpaDcDpInitSession OR pOpData->pSetupData data structure was * initialized for No-Session (Ns) usage. * The instance identified by pOpData->dcInstance has had a * callback function registered via @ref cpaDcDpRegCbFunc. * * @post * None * * @note * A callback of type @ref CpaDcDpCallbackFn is generated in * response to this function call. Any errors generated during * processing are reported as part of the callback status code. * * @see * @ref cpaDcDpPerformOpNow *****************************************************************************/ CpaStatus cpaDcDpEnqueueOp(CpaDcDpOpData *pOpData, const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaDcDp * Enqueue a single decompression request with partial read configuration. * See @CpaDcDpPartialReadData for more details. * * @description * This function enqueues a single request to perform a decompression * operation and allows to specify particular region of decompressed * data to be placed in the destination buffer (or buffer list). * * The function is asynchronous. The control is returned to the user once * the request has been submitted. On completion of the request, the * application may poll for responses, which will cause a callback * function (registered via @ref cpaDcDpRegCbFunc) to be invoked. * Callbacks within a session are guaranteed to be in the same order * in which they were submitted. * * The following restrictions apply to the pOpData parameter: * * - The memory MUST be aligned on an 8-byte boundary. * - The reserved fields of the structure MUST NOT be written to * or read from. * - The structure MUST reside in physically contiguous memory. * * @context * This function will not sleep, and hence can be executed in a context * that does not permit sleeping. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in,out] pOpData See @ref cpaDcDpEnqueueOp pOpData description. * * @param[in] pPartReadData Pointer to a structure containing the partial * read configuration parameters. * See @CpaDcDpPartialReadData for more details. * * @param[in] performOpNow See @ref cpaDcDpEnqueueOp performOpNow input * parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The session identified by pOpData->pSessionHandle was setup using * @ref cpaDcDpInitSession. The instance identified by pOpData->dcInstance * has had a callback function registered via @ref cpaDcDpRegCbFunc. * * @post * None * * @note * A callback of type @ref CpaDcDpCallbackFn is generated in * response to this function call. Any errors generated during * processing are reported as part of the callback status code. * * @see * @ref cpaDcDpPerformOpNow *****************************************************************************/ CpaStatus cpaDcDpEnqueueOpWithPartRead(CpaDcDpOpData *pOpData, CpaDcDpPartialReadData *pPartReadData, const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaDcDp * Enqueue a single compression request with an option set to zero-fill * data after the compression output in the leftover bytes. * * @description * This function enqueues a single request to perform a compression * operation with zero-filling leftover bytes with 4KB alignment * in the destination buffer (or buffer list). * * The function is asynchronous. The control is returned to the user once * the request has been submitted. On completion of the request, the * application may poll for responses, which will cause a callback * function (registered via @ref cpaDcDpRegCbFunc) to be invoked. * Callbacks within a session are guaranteed to be in the same order * in which they were submitted. * * The following restrictions apply to the pOpData parameter: * * - The memory MUST be aligned on an 8-byte boundary. * - The reserved fields of the structure MUST NOT be written to * or read from. * - The structure MUST reside in physically contiguous memory. * * @context * This function will not sleep, and hence can be executed in a context * that does not permit sleeping. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in,out] pOpData See @ref cpaDcDpEnqueueOp pOpData description. * * @param[in] performOpNow See @ref cpaDcDpEnqueueOp performOpNow input * parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The session identified by pOpData->pSessionHandle was setup using * @ref cpaDcDpInitSession. The instance identified by pOpData->dcInstance * has had a callback function registered via @ref cpaDcDpRegCbFunc. * * @post * None * * @note * A callback of type @ref CpaDcDpCallbackFn is generated in * response to this function call. Any errors generated during * processing are reported as part of the callback status code. * * @see * @ref cpaDcDpPerformOpNow *****************************************************************************/ CpaStatus cpaDcDpEnqueueOpWithZeroPad(CpaDcDpOpData *pOpData, const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaDcDp * Enqueue multiple requests to the compression data plane API. * * @description * This function enqueues multiple requests to perform compression or * decompression operations. * * The function is asynchronous; control is returned to the user once * the request has been submitted. On completion of the request, the * application may poll for responses, which will cause a callback * function (registered via @ref cpaDcDpRegCbFunc) to be invoked. * Separate callbacks will be invoked for each request. * Callbacks within a session and at the same priority are guaranteed * to be in the same order in which they were submitted. * * The following restrictions apply to each element of the pOpData * array: * * - The memory MUST be aligned on an 8-byte boundary. * - The reserved fields of the structure MUST be set to zero. * - The structure MUST reside in physically contiguous memory. * * @context * This function will not sleep, and hence can be executed in a context * that does not permit sleeping. * * @assumptions * Client MUST allocate the request parameters to 8 byte alignment. * Reserved elements of the CpaDcDpOpData structure MUST not used * The CpaDcDpOpData structure MUST reside in physically * contiguous memory. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] numberRequests The number of requests in the array of * CpaDcDpOpData structures. * @param[in] pOpData An array of pointers to CpaDcDpOpData * structures. Each CpaDcDpOpData * structure contains the request parameters for * that request. The client code allocates the * memory for this structure. This component takes * ownership of the memory until it is returned in * the callback, which was registered on the * instance via @ref cpaDcDpRegCbFunc. * See the above Description for some restrictions * that apply to this parameter. * @param[in] performOpNow Flag to indicate whether the operation should be * performed immediately (CPA_TRUE), or simply * enqueued to be performed later (CPA_FALSE). * In the latter case, the request is submitted * to be performed either by calling this function * again with this flag set to CPA_TRUE, or by * invoking the function @ref * cpaDcDpPerformOpNow. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The session identified by pOpData[i]->pSessionHandle was setup using * @ref cpaDcDpInitSession OR pOpData[i]->pSetupData data structure was * initialized for No-Session (Ns) usage. * The instance identified by pOpData[i]->dcInstance has had a * callback function registered via @ref cpaDcDpRegCbFunc. * * @post * None * * @note * Multiple callbacks of type @ref CpaDcDpCallbackFn are generated in * response to this function call (one per request). Any errors * generated during processing are reported as part of the callback * status code. * * @see * cpaDcDpEnqueueOp *****************************************************************************/ CpaStatus cpaDcDpEnqueueOpBatch(const Cpa32U numberRequests, CpaDcDpOpData *pOpData[], const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaDcDp * Enqueue multiple decompression request with partial read configuration. * See @CpaDcDpPartialReadData for more details. * * @description * This function enqueues multiple requests to perform decompression * operations and allows to specify particular region of decompressed * data to be placed in the destination buffer (or buffer list) for * each individual request. * * The function is asynchronous. The control is returned to the user once * the request has been submitted. On completion of the request, the * application may poll for responses, which will cause a callback * function (registered via @ref cpaDcDpRegCbFunc) to be invoked. * Separate callbacks will be invoked for each request. * Callbacks within a session and at the same priority are guaranteed * to be in the same order in which they were submitted. * * The following restrictions apply to each element of the pOpData * array: * * - The memory MUST be aligned on an 8-byte boundary. * - The reserved fields of the structure MUST be set to zero. * - The structure MUST reside in physically contiguous memory. * * @context * See @ref cpaDcDpEnqueueOpBatch context. * * @assumptions * See @ref cpaDcDpEnqueueOpBatch assumptions. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] numberRequests The number of requests in the array of * CpaDcDpOpData structures. * * @param[in,out] pOpData See @ref cpaDcDpEnqueueOpBatch pOpData for more * details. * * @param[in] pPartReadData An array of pointers to a structures containing * the partial read configuration parameters. * See @CpaDcDpPartialReadData for more details. * * @param[in] performOpNow See @ref cpaDcDpEnqueueOpBatch performOpNow * input parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * * @pre * The session identified by pOpData[i]->pSessionHandle was setup using * @ref cpaDcDpInitSession. The instance identified by * pOpData[i]->dcInstance has had a callback function registered via * @ref cpaDcDpRegCbFunc. * * @post * None * * @note * Multiple callbacks of type @ref CpaDcDpCallbackFn are generated in * response to this function call (one per request). Any errors * generated during processing are reported as part of the callback * status code. * * @see * @ref cpaDcDpEnqueueOp *****************************************************************************/ CpaStatus cpaDcDpEnqueueOpWithPartReadBatch( const Cpa32U numberRequests, CpaDcDpOpData *pOpData[], CpaDcDpPartialReadData *pPartReadData[], const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaDcDp * Enqueue multiple compression requests with an option set to zero-fill * data after the compression output in the leftover bytes. * * @description * This function enqueues multiple requests to perform compression * operations with an option set to zero-fill leftover bytes in the * destination buffer (of buffer list) for each individual request. * Please note that optional zero-filling leftover output buffer bytes * is aligned to 4KB. * * The function is asynchronous. The control is returned to the user once * the request has been submitted. On completion of the request, the * application may poll for responses, which will cause a callback * function (registered via @ref cpaDcDpRegCbFunc) to be invoked. * Separate callbacks will be invoked for each request. * Callbacks within a session and at the same priority are guaranteed * to be in the same order in which they were submitted. * * The following restrictions apply to each element of the pOpData * array: * * - The memory MUST be aligned on an 8-byte boundary. * - The reserved fields of the structure MUST be set to zero. * - The structure MUST reside in physically contiguous memory. * * @context * See @ref cpaDcDpEnqueueOpBatch context. * * @assumptions * See @ref cpaDcDpEnqueueOpBatch assumptions. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] numberRequests The number of requests in the array of * CpaDcDpOpData structures. * * @param[in,out] pOpData See @ref cpaDcDpEnqueueOpBatch pOpData for more * details. * * @param[in] performOpNow See @ref cpaDcDpEnqueueOpBatch performOpNow * input parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * * @pre * The session identified by pOpData[i]->pSessionHandle was setup using * @ref cpaDcDpInitSession. The instance identified by * pOpData[i]->dcInstance has had a callback function registered via * @ref cpaDcDpRegCbFunc. * * @post * None * * @note * Multiple callbacks of type @ref CpaDcDpCallbackFn are generated in * response to this function call (one per request). Any errors * generated during processing are reported as part of the callback * status code. * * @see * @ref cpaDcDpEnqueueOp *****************************************************************************/ CpaStatus cpaDcDpEnqueueOpWithZeroPadBatch(const Cpa32U numberRequests, CpaDcDpOpData *pOpData[], const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaDcDp * Submit any previously enqueued requests to be performed now on the * compression data plane API. * * @description * This function triggers processing of previously enqueued requests on the * referenced instance. * * * @context * Will not sleep. It can be executed in a context that does not * permit sleeping. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] dcInstance Instance to which the requests will be * submitted. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via @ref cpaDcStartInstance function. * A compression session has been previously setup using the * @ref cpaDcDpInitSession function call. * * @post * None * * @see * cpaDcDpEnqueueOp, cpaDcDpEnqueueOpBatch *****************************************************************************/ CpaStatus cpaDcDpPerformOpNow(CpaInstanceHandle dcInstance); /** ***************************************************************************** * @ingroup cpaDc * Function to return the "partial read" feature support. * * @description * This function is used to determine if given instance supports * "partial read" feature. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[out] pFlag Pointer to boolean flag which indicates * whether a feature is supported. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * None * @see * cpaDcQueryCapabilities() * *****************************************************************************/ CpaStatus cpaDcDpIsPartReadSupported(const CpaInstanceHandle instanceHandle, CpaBoolean *pFlag); /** ***************************************************************************** * @ingroup cpaDc * Function to return the "zero pad" feature support. * * @description * This function is used to determine if given instance supports * "zero pad" feature. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[out] pFlag Pointer to boolean flag which indicates * whether a feature is supported. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * None * @see * cpaDcQueryCapabilities() * *****************************************************************************/ CpaStatus cpaDcDpIsZeroPadSupported(const CpaInstanceHandle instanceHandle, CpaBoolean *pFlag); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_DC_DP_H */ qatlib-25.08.0/quickassist/include/lac/000077500000000000000000000000001503624047500176755ustar00rootroot00000000000000qatlib-25.08.0/quickassist/include/lac/cpa_cy_common.h000066400000000000000000000613331503624047500226620ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_common.h * * @defgroup cpaCy Cryptographic API * * @ingroup cpa * * @description * These functions specify the Cryptographic API. * *****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_common.h * @defgroup cpaCyCommon Cryptographic Common API * * @ingroup cpaCy * * @description * This file specifies items which are common for both the asymmetric * (public key cryptography) and the symmetric operations for the * Cryptographic API. * *****************************************************************************/ #ifndef CPA_CY_COMMON_H #define CPA_CY_COMMON_H #ifdef __cplusplus extern "C" { #endif #include "cpa.h" /** ***************************************************************************** * @ingroup cpa_cyCommon * CPA CY Major Version Number * @deprecated * As of v5.0 of the Crypto API, this define has been deprecated, * replaced by @ref CPA_API_VERSION_NUM_MAJOR. * @description * The CPA_CY API major version number. This number will be incremented * when significant churn to the API has occurred. The combination of the * major and minor number definitions represent the complete version number * for this interface. * *****************************************************************************/ #define CPA_CY_API_VERSION_NUM_MAJOR (CPA_API_VERSION_NUM_MAJOR) /** ***************************************************************************** * @ingroup cpa_cyCommon * CPA CY Minor Version Number * @deprecated * As of v5.0 of the Crypto API, this define has been deprecated, * replaced by @ref CPA_API_VERSION_NUM_MINOR. * @description * The CPA_CY API minor version number. This number will be incremented * when minor changes to the API has occurred. The combination of the major * and minor number definitions represent the complete version number for * this interface. * *****************************************************************************/ #define CPA_CY_API_VERSION_NUM_MINOR (CPA_API_VERSION_NUM_MINOR) /** ***************************************************************************** * @file cpa_cy_common.h * @ingroup cpa_cyCommon * CPA CY API version at least * @description * The minimal supported CPA_CY API version. Allow to check if the API * version is equal or above some version to avoid compilation issues * with an older API version. * *****************************************************************************/ #define CPA_CY_API_VERSION_AT_LEAST(major, minor) \ (CPA_CY_API_VERSION_NUM_MAJOR > major || \ (CPA_CY_API_VERSION_NUM_MAJOR == major && \ CPA_CY_API_VERSION_NUM_MINOR >= minor)) /** ***************************************************************************** * @file cpa_cy_common.h * @ingroup cpa_cyCommon * CPA CY API version less than * @description * The maximum supported CPA_CY API version. Allow to check if the API * version is below some version to avoid compilation issues with a newer * API version. * *****************************************************************************/ #define CPA_CY_API_VERSION_LESS_THAN(major, minor) \ (CPA_CY_API_VERSION_NUM_MAJOR < major || \ (CPA_CY_API_VERSION_NUM_MAJOR == major && \ CPA_CY_API_VERSION_NUM_MINOR < minor)) /** ***************************************************************************** * @file cpa_cy_common.h * @ingroup cpaCyCommon * Request priority * @description * Enumeration of priority of the request to be given to the API. * Currently two levels - HIGH and NORMAL are supported. HIGH priority * requests will be prioritized on a "best-effort" basis over requests * that are marked with a NORMAL priority. * *****************************************************************************/ typedef enum _CpaCyPriority { CPA_CY_PRIORITY_NORMAL = 1, /**< Normal priority */ CPA_CY_PRIORITY_HIGH /**< High priority */ } CpaCyPriority; /*****************************************************************************/ /* Callback Definitions */ /*****************************************************************************/ /** ***************************************************************************** * @ingroup cpaCyCommon * Definition of the crypto generic callback function * * @description * This data structure specifies the prototype for a generic callback * function * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag Opaque value provided by user while making individual * function call. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Opaque Pointer to the operation data that was * submitted in the request * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyKeyGenSsl() * *****************************************************************************/ typedef void (*CpaCyGenericCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData); /** ***************************************************************************** * @ingroup cpaCyCommon * Definition of generic callback function with an additional output * CpaFlatBuffer parameter. * * @description * This data structure specifies the prototype for a generic callback * function which provides an output buffer (of type CpaFlatBuffer). * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag Opaque value provided by user while making individual * function call. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Opaque Pointer to the operation data that was * submitted in the request * @param[in] pOut Pointer to the output buffer provided in the request * invoking this callback. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * None * *****************************************************************************/ typedef void (*CpaCyGenFlatBufCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaFlatBuffer *pOut); /** ***************************************************************************** * @ingroup cpaCyCommon * Function to return the size of the memory which must be allocated for * the pPrivateMetaData member of CpaBufferList. * * @description * This function is used obtain the size (in bytes) required to allocate * a buffer descriptor for the pPrivateMetaData member in the * CpaBufferList the structure. * Should the function return zero then no meta data is required for the * buffer list. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[in] numBuffers The number of pointers in the CpaBufferList. * this is the maximum number of CpaFlatBuffers * which may be contained in this CpaBufferList. * @param[out] pSizeInBytes Pointer to the size in bytes of memory to be * allocated when the client wishes to allocate * a cpaFlatBuffer * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None. * @post * None * @note * None * @see * cpaCyGetInstances() * *****************************************************************************/ CpaStatus cpaCyBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, Cpa32U numBuffers, Cpa32U *pSizeInBytes); /** ***************************************************************************** * @ingroup cpaCyCommon * Function to return a string indicating the specific error that occurred * for a particular instance. * * @description * When a function invocation on a particular instance returns an error, * the client can invoke this function to query the instance for a null * terminated string which describes the general error condition, and if * available additional text on the specific error. * The Client MUST allocate CPA_STATUS_MAX_STR_LENGTH_IN_BYTES bytes for * the buffer string. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[in] errStatus The error condition that occurred * @param[out] pStatusText Pointer to the string buffer that will be * updated with a null terminated status text * string. * The invoking application MUST allocate this * buffer to be CPA_STATUS_MAX_STR_LENGTH_IN_BYTES. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. Note, In this scenario it * is INVALID to call this function a further * time. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None. * @post * None * @note * None * @see * CpaStatus * *****************************************************************************/ CpaStatus cpaCyGetStatusText(const CpaInstanceHandle instanceHandle, CpaStatus errStatus, Cpa8S *pStatusText); /*****************************************************************************/ /* Instance Discovery Functions */ /*****************************************************************************/ /** ***************************************************************************** * @ingroup cpaCyCommon * Get the number of instances that are supported by the API * implementation. * * @description * This function will get the number of instances that are supported * by an implementation of the Cryptographic API. This number is then * used to determine the size of the array that must be passed to * @ref cpaCyGetInstances(). * * @context * This function MUST NOT be called from an interrupt context as it MAY * sleep. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[out] pNumInstances Pointer to where the number of * instances will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated * * @see * cpaCyGetInstances * *****************************************************************************/ CpaStatus cpaCyGetNumInstances(Cpa16U *pNumInstances); /** ***************************************************************************** * @ingroup cpaCyCommon * Get the handles to the instances that are supported by the * API implementation. * * @description * This function will return handles to the instances that are * supported by an implementation of the Cryptographic API. These * instance handles can then be used as input parameters with other * Cryptographic API functions. * * This function will populate an array that has been allocated by the * caller. The size of this API will have been determined by the * cpaCyGetNumInstances() function. * * @context * This function MUST NOT be called from an interrupt context as it MAY * sleep. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] numInstances Size of the array. If the value is not * the same as the number of instances * supported, then an error (@ref * CPA_STATUS_INVALID_PARAM) is returned. * @param[in,out] cyInstances Pointer to where the instance * handles will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated * * @see * cpaCyGetNumInstances * *****************************************************************************/ CpaStatus cpaCyGetInstances(Cpa16U numInstances, CpaInstanceHandle *cyInstances); /** ***************************************************************************** * @ingroup cpaCyCommon * Function to get information on a particular instance. * * @deprecated * As of v1.3 of the Crypto API, this function has been deprecated, * replaced by @ref cpaCyInstanceGetInfo2. * * @description * This function will provide instance specific information through a * @ref CpaInstanceInfo structure. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API to be * initialized. * @param[out] pInstanceInfo Pointer to the memory location allocated by * the client into which the CpaInstanceInfo * structure will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The client has retrieved an instanceHandle from successive calls to * @ref cpaCyGetNumInstances and @ref cpaCyGetInstances. * @post * None * @note * None * @see * cpaCyGetNumInstances, * cpaCyGetInstances, * CpaInstanceInfo * *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCyInstanceGetInfo(const CpaInstanceHandle instanceHandle, struct _CpaInstanceInfo *pInstanceInfo); /** ***************************************************************************** * @ingroup cpaCyCommon * Function to get information on a particular instance. * * @description * This function will provide instance specific information through a * @ref CpaInstanceInfo2 structure. * Supersedes @ref cpaCyInstanceGetInfo. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API to be * initialized. * @param[out] pInstanceInfo2 Pointer to the memory location allocated by * the client into which the CpaInstanceInfo2 * structure will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The client has retrieved an instanceHandle from successive calls to * @ref cpaCyGetNumInstances and @ref cpaCyGetInstances. * @post * None * @note * None * @see * cpaCyGetNumInstances, * cpaCyGetInstances, * CpaInstanceInfo * *****************************************************************************/ CpaStatus cpaCyInstanceGetInfo2(const CpaInstanceHandle instanceHandle, CpaInstanceInfo2 *pInstanceInfo2); /*****************************************************************************/ /* Instance Notification Functions */ /*****************************************************************************/ /** ***************************************************************************** * @ingroup cpaCyCommon * Callback function for instance notification support. * * @description * This is the prototype for the instance notification callback function. * The callback function is passed in as a parameter to the * @ref cpaCyInstanceSetNotificationCb function. * * @context * This function will be executed in a context that requires that sleeping * MUST NOT be permitted. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCallbackTag Opaque value provided by user while making * individual function calls. * @param[in] instanceEvent The event that will trigger this function to * get invoked. * * @retval * None * @pre * Component has been initialized and the notification function has been * set via the cpaCyInstanceSetNotificationCb function. * @post * None * @note * None * @see * cpaCyInstanceSetNotificationCb(), * *****************************************************************************/ typedef void (*CpaCyInstanceNotificationCbFunc)( const CpaInstanceHandle instanceHandle, void *pCallbackTag, const CpaInstanceEvent instanceEvent); /** ***************************************************************************** * @ingroup cpaCyCommon * Subscribe for instance notifications. * * @description * Clients of the CpaCy interface can subscribe for instance notifications * by registering a @ref CpaCyInstanceNotificationCbFunc function. * * @context * This function may be called from any context. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pInstanceNotificationCb Instance notification callback * function pointer. * @param[in] pCallbackTag Opaque value provided by user while * making individual function calls. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Instance has been initialized. * @post * None * @note * None * @see * CpaCyInstanceNotificationCbFunc * *****************************************************************************/ CpaStatus cpaCyInstanceSetNotificationCb( const CpaInstanceHandle instanceHandle, const CpaCyInstanceNotificationCbFunc pInstanceNotificationCb, void *pCallbackTag); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_COMMON_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_dh.h000066400000000000000000000572071503624047500217720ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_dh.h * * @defgroup cpaCyDh Diffie-Hellman (DH) API * * @ingroup cpaCy * * @description * These functions specify the API for Public Key Encryption * (Cryptography) operations for use with Diffie-Hellman algorithm. * * @note * Large numbers are represented on the QuickAssist API as described * in the Large Number API (@ref cpaCyLn). *****************************************************************************/ #ifndef CPA_CY_DH_H #define CPA_CY_DH_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyDh * Diffie-Hellman Phase 1 Key Generation Data. * @description * This structure lists the different items that are required in the * cpaCyDhKeyGenPhase1 function. The client MUST allocate the memory for * this structure. When the structure is passed into the function, * ownership of the memory passes to the function. Ownership of the memory * returns to the client when this structure is returned with the * CpaCyDhPhase1KeyGenOpData structure. * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyDhKeyGenPhase1 function, and * before it has been returned in the callback, undefined behavior will * result. * All values in this structure are required to be in Most Significant Byte * first order, e.g. primeP.pData[0] = MSB. * *****************************************************************************/ typedef struct _CpaCyDhPhase1KeyGenOpData { CpaFlatBuffer primeP; /**< Flat buffer containing a pointer to the random odd prime number (p). * The bit-length of this number may be one of 768, 1024, 1536, 2048, * 3072, 4096 or 8192. */ CpaFlatBuffer baseG; /**< Flat buffer containing a pointer to base (g). This MUST comply with * the following: * 0 < g < p. */ CpaFlatBuffer privateValueX; /**< Flat buffer containing a pointer to the private value (x). This is a * random value which MUST satisfy the following condition: * 0 < PrivateValueX < (PrimeP - 1) * * Refer to PKCS #3: Diffie-Hellman Key-Agreement Standard for details. * The client creating this data MUST ensure the compliance of this value * with the standard. Note: This value is also needed to complete local * phase 2 Diffie-Hellman operation.*/ } CpaCyDhPhase1KeyGenOpData; /** ***************************************************************************** * @ingroup cpaCyDh * Diffie-Hellman Phase 2 Secret Key Generation Data. * @description * This structure lists the different items that required in the * cpaCyDhKeyGenPhase2Secret function. The client MUST allocate the * memory for this structure. When the structure is passed into the * function, ownership of the memory passes to the function. Ownership of * the memory returns to the client when this structure is returned with * the callback. * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyDhKeyGenPhase2Secret * function, and before it has been returned in the callback, undefined * behavior will result. * All values in this structure are required to be in Most Significant Byte * first order, e.g. primeP.pData[0] = MSB. * *****************************************************************************/ typedef struct _CpaCyDhPhase2SecretKeyGenOpData { CpaFlatBuffer primeP; /**< Flat buffer containing a pointer to the random odd prime number (p). * The bit-length of this number may be one of 768, 1024, 1536, 2048, * 3072, 4096 or 8192. * This SHOULD be same prime number as was used in the phase 1 key * generation operation. */ CpaFlatBuffer remoteOctetStringPV; /**< Flat buffer containing a pointer to the remote entity * octet string Public Value (PV). */ CpaFlatBuffer privateValueX; /**< Flat buffer containing a pointer to the private value (x). This * value may have been used in a call to the cpaCyDhKeyGenPhase1 function. * This is a random value which MUST satisfy the following condition: * 0 < privateValueX < (primeP - 1). */ } CpaCyDhPhase2SecretKeyGenOpData; /** ***************************************************************************** * @ingroup cpaCyDh * Diffie-Hellman Statistics. * @deprecated * As of v1.3 of the Crypto API, this structure has been deprecated, * replaced by @ref CpaCyDhStats64. * @description * This structure contains statistics on the Diffie-Hellman operations. * Statistics are set to zero when the component is initialized, and are * collected per instance. ****************************************************************************/ typedef struct _CpaCyDhStats { Cpa32U numDhPhase1KeyGenRequests; /**< Total number of successful Diffie-Hellman phase 1 key * generation requests. */ Cpa32U numDhPhase1KeyGenRequestErrors; /**< Total number of Diffie-Hellman phase 1 key generation requests * that had an error and could not be processed. */ Cpa32U numDhPhase1KeyGenCompleted; /**< Total number of Diffie-Hellman phase 1 key generation operations * that completed successfully. */ Cpa32U numDhPhase1KeyGenCompletedErrors; /**< Total number of Diffie-Hellman phase 1 key generation operations * that could not be completed successfully due to errors. */ Cpa32U numDhPhase2KeyGenRequests; /**< Total number of successful Diffie-Hellman phase 2 key * generation requests. */ Cpa32U numDhPhase2KeyGenRequestErrors; /**< Total number of Diffie-Hellman phase 2 key generation requests * that had an error and could not be processed. */ Cpa32U numDhPhase2KeyGenCompleted; /**< Total number of Diffie-Hellman phase 2 key generation operations * that completed successfully. */ Cpa32U numDhPhase2KeyGenCompletedErrors; /**< Total number of Diffie-Hellman phase 2 key generation operations * that could not be completed successfully due to errors. */ } CpaCyDhStats CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCyDh * Diffie-Hellman Statistics (64-bit version). * @description * This structure contains the 64-bit version of the statistics on the * Diffie-Hellman operations. * Statistics are set to zero when the component is initialized, and are * collected per instance. ****************************************************************************/ typedef struct _CpaCyDhStats64 { Cpa64U numDhPhase1KeyGenRequests; /**< Total number of successful Diffie-Hellman phase 1 key * generation requests. */ Cpa64U numDhPhase1KeyGenRequestErrors; /**< Total number of Diffie-Hellman phase 1 key generation requests * that had an error and could not be processed. */ Cpa64U numDhPhase1KeyGenCompleted; /**< Total number of Diffie-Hellman phase 1 key generation operations * that completed successfully. */ Cpa64U numDhPhase1KeyGenCompletedErrors; /**< Total number of Diffie-Hellman phase 1 key generation operations * that could not be completed successfully due to errors. */ Cpa64U numDhPhase2KeyGenRequests; /**< Total number of successful Diffie-Hellman phase 2 key * generation requests. */ Cpa64U numDhPhase2KeyGenRequestErrors; /**< Total number of Diffie-Hellman phase 2 key generation requests * that had an error and could not be processed. */ Cpa64U numDhPhase2KeyGenCompleted; /**< Total number of Diffie-Hellman phase 2 key generation operations * that completed successfully. */ Cpa64U numDhPhase2KeyGenCompletedErrors; /**< Total number of Diffie-Hellman phase 2 key generation operations * that could not be completed successfully due to errors. */ } CpaCyDhStats64; /** ***************************************************************************** * @ingroup cpaCyDh * Function to implement Diffie-Hellman phase 1 operations. * * @description * This function may be used to implement the Diffie-Hellman phase 1 * operations as defined in the PKCS #3 standard. It may be used to * generate the the (local) octet string public value (PV) key. * The prime number sizes specified in RFC 2409, 4306, and part of * RFC 3526 are supported (bit size 6144 from RFC 3536 is not * supported). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pDhPhase1Cb Pointer to a callback function to be invoked * when the operation is complete. If the * pointer is set to a NULL value the function * will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback * @param[in] pPhase1KeyGenData Structure containing all the data needed * to perform the DH Phase 1 key generation * operation. The client code allocates the * memory for this structure. This component * takes ownership of the memory until it is * returned in the callback. * @param[out] pLocalOctetStringPV Pointer to memory allocated by the client * into which the (local) octet string Public * Value (PV) will be written. This value * needs to be sent to the remote entity with * which Diffie-Hellman is negotiating. * The size of this buffer in bytes (as * represented by the dataLenInBytes field) * MUST be at least big enough to store * the public value, which may have a bit * length up to that of pPrimeP. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pDhPhase1Cb is non-NULL an asynchronous callback of type * CpaCyGenFlatBufCbFunc is generated in response to this function * call. Any errors generated during processing are reported in the * structure returned in the callback. * * @see * CpaCyGenFlatBufCbFunc, * CpaCyDhPhase1KeyGenOpData * *****************************************************************************/ CpaStatus cpaCyDhKeyGenPhase1( const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pDhPhase1Cb, void *pCallbackTag, const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, CpaFlatBuffer *pLocalOctetStringPV); /** ***************************************************************************** * @ingroup cpaCyDh * Function to implement Diffie-Hellman phase 2 operations. * * @description * This function may be used to implement the Diffie-Hellman phase 2 * operation as defined in the PKCS #3 standard. It may be used to * generate the Diffie-Hellman shared secret key. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pDhPhase2Cb Pointer to a callback function to be * invoked when the operation is complete. * If the pointer is set to a NULL value * the function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in * the callback. * @param[in] pPhase2SecretKeyGenData Structure containing all the data * needed to perform the DH Phase 2 * secret key generation operation. The * client code allocates the memory for * this structure. This component takes * ownership of the memory until it is * returned in the callback. * @param[out] pOctetStringSecretKey Pointer to memory allocated by the * client into which the octet string * secret key will be written. * The size of this buffer in bytes (as * represented by the dataLenInBytes field) * MUST be at least big enough to store * the public value, which may have a bit * length up to that of pPrimeP. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pDhPhase2Cb is non-NULL an asynchronous callback of type * CpaCyGenFlatBufCbFunc is generated in response to this function * call. Any errors generated during processing are reported in the * structure returned in the callback. * * @see * CpaCyGenFlatBufCbFunc, * CpaCyDhPhase2SecretKeyGenOpData * *****************************************************************************/ CpaStatus cpaCyDhKeyGenPhase2Secret( const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pDhPhase2Cb, void *pCallbackTag, const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, CpaFlatBuffer *pOctetStringSecretKey); /** ***************************************************************************** * @ingroup cpaCyDh * Query statistics for Diffie-Hellman operations * * @deprecated * As of v1.3 of the Crypto API, this function has been deprecated, * replaced by @ref cpaCyDhQueryStats64(). * * @description * This function will query a specific Instance handle for Diffie- * Hellman statistics. The user MUST allocate the CpaCyDhStats * structure and pass the reference to that structure into this function * call. This function writes the statistic results into the passed in * CpaCyDhStats structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pDhStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyDhStats *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCyDhQueryStats(const CpaInstanceHandle instanceHandle, struct _CpaCyDhStats *pDhStats); /** ***************************************************************************** * @ingroup cpaCyDh * Query statistics (64-bit version) for Diffie-Hellman operations * * @description * This function will query a specific Instance handle for the 64-bit * version of the Diffie-Hellman statistics. The user MUST allocate the * CpaCyDhStats64 structure and pass the reference to that structure into * this function call. This function writes the statistic results into * the passed in CpaCyDhStats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pDhStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyDhStats64 *****************************************************************************/ CpaStatus cpaCyDhQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyDhStats64 *pDhStats); /*****************************************************************************/ #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_DH_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_drbg.h000066400000000000000000000642531503624047500223140ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_drbg.h * * @defgroup cpaCyDrbg Deterministic Random Bit Generation API * * @ingroup cpaCy * * @description * These functions specify the API for a Deterministic Random Bit * Generation (DRBG), compliant with NIST SP 800-90, March 2007, * "Recommendation for Random Number Generation Using Deterministic * Random Bit Generators (Revised)". * * The functions @ref cpaCyDrbgInitSession, @ref * cpaCyDrbgGen, @ref cpaCyDrbgReseed and @ref * cpaCyDrbgRemoveSession are used to instantiate, generate, * reseed and uninstantiate a DRBG mechanism. * * @note * These functions supersede the random number generation functions * in API group @ref cpaCyRand, which are now deprecated. * *****************************************************************************/ #ifndef CPA_CY_DRBG_H #define CPA_CY_DRBG_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyDrbg * Security Strength * @description * This enum defines the security strength. NIST SP 800-90 defines * security strength as "A number associated with the amount of work * (that is, the number of operations) that is required to break a * cryptographic algorithm or system; a security strength is specified * in bits and is a specific value from the set (112, 128, 192, 256) * for this Recommendation. The amount of work needed is * 2^(security_strength)." ****************************************************************************/ typedef enum _CpaCyDrbgSecStrength { CPA_CY_RBG_SEC_STRENGTH_112 = 1, CPA_CY_RBG_SEC_STRENGTH_128, CPA_CY_RBG_SEC_STRENGTH_192, CPA_CY_RBG_SEC_STRENGTH_256 } CpaCyDrbgSecStrength; /** ***************************************************************************** * @ingroup cpaCyDrbg * DRBG Session (Instance) Setup Data * @description * This structure contains data relating to instantiation of a * DRBG session, or instance. *****************************************************************************/ typedef struct _CpaCyDrbgSessionSetupData { CpaCyDrbgSecStrength secStrength; /**< Requested security strength */ CpaBoolean predictionResistanceRequired; /**< Prediction resistance flag. * Indicates whether or not prediction resistance may be required by the * consuming application during one or more requests for pseudorandom * bits. */ CpaFlatBuffer personalizationString; /**< Personalization string. * String that should be used to derive the seed. */ } CpaCyDrbgSessionSetupData; /** ***************************************************************************** * @ingroup cpaCyDrbg * Handle to a DRBG session (or instance). * @description * This is what NIST SP 800-90 refers to as the "state_handle". * That document also refers to the process of creating such a handle * as "instantiation", or instance creation. On this API, we use the * term "session" to refer to such an instance, to avoid confusion with * the crypto instance handle, and for consistency with the similar * concept of sessions in symmetric crypto (see @ref cpaCySym) and * elsewhere on the API. * * Note that there can be multiple sessions, or DRBG instances, created * within a single instance of a CpaInstanceHandle. * * @note * The memory for this handle is allocated by the client. The size * of the memory that the client needs to allocate is determined * by a call to the @ref cpaCyDrbgSessionGetSize function. The * session memory is initialized with a call to the @ref * cpaCyDrbgInitSession function. This memory MUST not be * freed until a call to @ref cpaCyDrbgRemoveSession has * completed successfully. *****************************************************************************/ typedef void *CpaCyDrbgSessionHandle; /** ***************************************************************************** * @ingroup cpaCyDrbg * DRBG Data Generation Operation Data * @description * This structure contains data relating to generation of random bits * using a DRBG. * @see * cpaCyDrbgGen() * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the @ref cpaCyDrbgGen() function, and * before it has been returned in the callback, undefined behavior will * result. *****************************************************************************/ typedef struct _CpaCyDrbgGenOpData { CpaCyDrbgSessionHandle sessionHandle; /**< Session handle, also known as the state handle or instance handle */ Cpa32U lengthInBytes; /**< Requested number of bytes to be generated */ CpaCyDrbgSecStrength secStrength; /**< Requested security strength */ CpaBoolean predictionResistanceRequired; /**< Requested prediction resistance flag. * Indicates whether or not prediction resistance is to be * provided prior to the generation of the requested pseudorandom * bits to be generated. */ CpaFlatBuffer additionalInput; /**< Additional input */ } CpaCyDrbgGenOpData; /** ***************************************************************************** * @ingroup cpaCyDrbg * DRBG Reseed Operation Data * @description * This structure contains data relating to reseeding a DRBG session, * or instance. * @see * cpaCyDrbgReseed() * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the @ref cpaCyDrbgReseed() function, * and before it has been returned in the callback, undefined behavior will * result. *****************************************************************************/ typedef struct _CpaCyDrbgReseedOpData { CpaCyDrbgSessionHandle sessionHandle; /**< Session handle, also known as a state handle or instance handle. */ CpaFlatBuffer additionalInput; /**< An "optional" input to the reseeding. The length should be * less than or equal to the seed length, which is returned by the * function @ref cpaCyDrbgInitSession(). A length of 0 can be * specified to indicate no additional input. */ } CpaCyDrbgReseedOpData; /** ***************************************************************************** * @ingroup cpaCyDrbg * DRBG Statistics * @description * This structure contains statistics (counters) related to the * random bit generation API. * @see * CpaCyDrbgQueryStats64() *****************************************************************************/ typedef struct _CpaCyDrbgStats64 { Cpa64U numSessionsInitialized; /**< Number of session initialized */ Cpa64U numSessionsRemoved; /**< Number of sessions removed */ Cpa64U numSessionErrors; /**< Total number of errors returned when initializing and removing * sessions */ Cpa64U numGenRequests; /**< Number of successful calls to @ref cpaCyDrbgGen. */ Cpa64U numGenRequestErrors; /**< Number of calls to @ref cpaCyDrbgGen that returned an error and * could not be processed. */ Cpa64U numGenCompleted; /**< Number of calls to @ref cpaCyDrbgGen that completed * successfully. */ Cpa64U numGenCompletedErrors; /**< Number of calls to @ref cpaCyDrbgGen that completed with an error * status. */ Cpa64U numReseedRequests; /**< Number of successful calls to @ref cpaCyDrbgReseed. * * Note that this does NOT include implicit reseeds due to calls to @ref * cpaCyDrbgGen with prediction resistance, or due to seed * lifetime expiry. */ Cpa64U numReseedRequestErrors; /**< Number of calls to @ref cpaCyDrbgReseed that returned an error and * could not be processed. */ Cpa64U numReseedCompleted; /**< Number of calls to @ref cpaCyDrbgReseed that completed * successfully. */ Cpa64U numReseedCompletedErrors; /**< Number of calls to @ref cpaCyDrbgReseed that completed with an * error status. */ } CpaCyDrbgStats64; /** ***************************************************************************** * @ingroup cpaCyDrbg * Returns the size (in bytes) of a DRBG session handle. * * @description * This function is used by the client to determine the size of the memory * it must allocate in order to store the DRBG session. This MUST be * called before the client allocates the memory for the session * and before the client calls the @ref cpaCyDrbgInitSession function. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pSetupData Pointer to session setup data which * contains parameters which are static * for a given DRBG session, such * as security strength, etc. * @param[out] pSize The amount of memory in bytes required * to hold the session. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via the @ref cpaCyStartInstance * function. * @post * None *****************************************************************************/ CpaStatus cpaCyDrbgSessionGetSize(const CpaInstanceHandle instanceHandle, const CpaCyDrbgSessionSetupData *pSetupData, Cpa32U *pSize); /** ***************************************************************************** * @ingroup cpaCyDrbg * Instantiates and seeds a DRBG session, or instance. * * @description * This function is used by the client to initialize a DRBG session, * or instance. * @note * On some implementations, the client may have to register an entropy * source, nonce source, and/or a function which specifies whether a * derivation function is required. See the Programmer's Guide for your * implementation for more details. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pGenCb Pointer to callback function to be * registered. This is the function that will * be called back to indicate completion of * the asynchronous @ref cpaCyDrbgGen * function. Set this field to NULL if this * function is to operate in a synchronous * manner. * @param[in] pReseedCb Pointer to callback function to be * registered. This is the function that will * be called back to indicate completion of * the asynchronous @ref cpaCyDrbgReseed * function. Set this field to NULL if this * function is to operate in a synchronous * manner. * @param[in] pSetupData Pointer to setup data. * @param[out] sessionHandle Pointer to the memory allocated by the * client to store the instance handle. This * will be initialized with this function. This * handle needs to be passed to subsequent * processing calls. * @param[out] pSeedLen Seed length for the supported DRBG * mechanism and security strength. * The value of this is dependent on the * DRBG mechanism implemented by the * instance, which is implementation-dependent. * This seed length may be used by * the client when reseeding. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via the @ref cpaCyStartInstance * function. * @post * None *****************************************************************************/ CpaStatus cpaCyDrbgInitSession(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pGenCb, const CpaCyGenericCbFunc pReseedCb, const CpaCyDrbgSessionSetupData *pSetupData, CpaCyDrbgSessionHandle sessionHandle, Cpa32U *pSeedLen); /** ***************************************************************************** * @ingroup cpaCyDrbg * Reseeds a DRBG session, or instance. * * @description * Reseeding inserts additional entropy into the generation of * pseudorandom bits. * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback. * @param[in] pOpData Structure containing all the data needed * to perform the operation. The client code * allocates the memory for this structure. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via the @ref cpaCyStartInstance * function. * @post * None ******************************************************************************/ CpaStatus cpaCyDrbgReseed(const CpaInstanceHandle instanceHandle, void *pCallbackTag, CpaCyDrbgReseedOpData *pOpData); /** ***************************************************************************** * @ingroup cpaCyDrbg * Generates pseudorandom bits. * * @description * This function is used to request the generation of random bits. * The generated data and the length of the data will be * returned to the caller in an asynchronous callback function. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback. * @param[in] pOpData Structure containing all the data needed * to perform the operation. The client code * allocates the memory for this structure. * This component takes ownership of the * memory until it is returned in the * callback. * @param[out] pPseudoRandomBits Pointer to the memory allocated by the * client where the random data will be written * to. For optimal performance, the data * pointed to SHOULD be 8-byte aligned. * There is no endianness associated with the * random data. On invocation the callback * function will contain this parameter in its * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. One * reason may be for an entropy test failing. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via the @ref cpaCyStartInstance * function. * The DRBG session, or instance, has been initialized via the @ref * cpaCyDrbgInitSession function. * @post * None ******************************************************************************/ CpaStatus cpaCyDrbgGen(const CpaInstanceHandle instanceHandle, void *pCallbackTag, CpaCyDrbgGenOpData *pOpData, CpaFlatBuffer *pPseudoRandomBits); /** ***************************************************************************** * @ingroup cpaCyDrbg * Removes a previously instantiated DRBG session, or instance. * * @description * This function will remove a previously initialized DRBG session, * or instance, and the installed callback handler function. * Removal will fail if outstanding calls still exist for the * initialized session. In this case, the client needs to retry * the remove function at a later time. The memory for the session * handle MUST not be freed until this call has completed successfully. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] sessionHandle DRBG session handle to be removed. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via the @ref cpaCyStartInstance * function. * The DRBG session, or instance, has been initialized via the @ref * cpaCyDrbgInitSession function. * @post * None *****************************************************************************/ CpaStatus cpaCyDrbgRemoveSession(const CpaInstanceHandle instanceHandle, CpaCyDrbgSessionHandle sessionHandle); /** ***************************************************************************** * @ingroup cpaCyDrbg * Returns statistics specific to a session, or instance, of the * RBG API. * * @description * This function will query a specific session for RBG statistics. * The user MUST allocate the CpaCyDrbgStats64 structure and pass the * reference to that into this function call. This function writes * the statistic results into the passed in CpaCyDrbgStats64 structure. * * Note: statistics returned by this function do not interrupt current * data processing and as such can be slightly out of sync with * operations that are in progress during the statistics retrieval * process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pStats Pointer to memory into which the *statistics will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None *****************************************************************************/ CpaStatus cpaCyDrbgQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyDrbgStats64 *pStats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_DRBG_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_dsa.h000066400000000000000000001656361503624047500221540ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_dsa.h * * @defgroup cpaCyDsa Digital Signature Algorithm (DSA) API * * @ingroup cpaCy * * @description * These functions specify the API for Public Key Encryption * (Cryptography) Digital Signature Algorithm (DSA) operations. * * Support is provided for FIPS PUB 186-2 with Change Notice 1 * specification, and optionally for FIPS PUB 186-3. If an * implementation does not support FIPS PUB 186-3, then the * corresponding functions may return a status of @ref * CPA_STATUS_FAIL. * * Support for FIPS PUB 186-2 with Change Notice 1 implies supporting * the following choice for the pair L and N: * - L = 1024, N = 160 * * Support for FIPS PUB 186-3 implies supporting the following choices * for the pair L and N: * * - L = 1024, N = 160 * - L = 2048, N = 224 * - L = 2048, N = 256 * - L = 3072, N = 256 * * Only the modular math aspects of DSA parameter generation and message * signature generation and verification are implemented here. For full * DSA support, this DSA API SHOULD be used in conjunction with other * parts of this overall Cryptographic API. In particular the Symmetric * functions (for hashing), the Random Number Generation functions, and * the Prime Number Test functions will be required. * * @note * Large numbers are represented on the QuickAssist API as described * in the Large Number API (@ref cpaCyLn). *****************************************************************************/ #ifndef CPA_CY_DSA_H #define CPA_CY_DSA_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyDsa * DSA P Parameter Generation Operation Data. * @description * This structure contains the operation data for the cpaCyDsaGenPParam * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. X.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyDsaGenPParam * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyDsaGenPParam() * *****************************************************************************/ typedef struct _CpaCyDsaPParamGenOpData { CpaFlatBuffer X; /**< 2^(L-1) <= X < 2^L (from FIPS 186-3) */ CpaFlatBuffer Q; /**< DSA group parameter q */ } CpaCyDsaPParamGenOpData; /** ***************************************************************************** * @ingroup cpaCyDsa * DSA G Parameter Generation Operation Data. * @description * This structure contains the operation data for the cpaCyDsaGenGParam * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. P.pData[0] = MSB. * * All numbers MUST be stored in big-endian order. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyDsaGenGParam * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyDsaGenGParam() * *****************************************************************************/ typedef struct _CpaCyDsaGParamGenOpData { CpaFlatBuffer P; /**< DSA group parameter p */ CpaFlatBuffer Q; /**< DSA group parameter q */ CpaFlatBuffer H; /**< any integer with 1 < h < p - 1 */ } CpaCyDsaGParamGenOpData; /** ***************************************************************************** * @ingroup cpaCyDsa * DSA Y Parameter Generation Operation Data. * @description * This structure contains the operation data for the cpaCyDsaGenYParam * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. P.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyDsaGenYParam * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyDsaGenYParam() * *****************************************************************************/ typedef struct _CpaCyDsaYParamGenOpData { CpaFlatBuffer P; /**< DSA group parameter p */ CpaFlatBuffer G; /**< DSA group parameter g */ CpaFlatBuffer X; /**< DSA private key x */ } CpaCyDsaYParamGenOpData; /** ***************************************************************************** * @ingroup cpaCyDsa * DSA R Sign Operation Data. * @description * This structure contains the operation data for the cpaCyDsaSignR * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. P.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyDsaSignR * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyDsaSignR() * *****************************************************************************/ typedef struct _CpaCyDsaRSignOpData { CpaFlatBuffer P; /**< DSA group parameter p */ CpaFlatBuffer Q; /**< DSA group parameter q */ CpaFlatBuffer G; /**< DSA group parameter g */ CpaFlatBuffer K; /**< DSA secret parameter k for signing */ } CpaCyDsaRSignOpData; /** ***************************************************************************** * @ingroup cpaCyDsa * DSA S Sign Operation Data. * @description * This structure contains the operation data for the cpaCyDsaSignS * function. The client MUST allocate the memory for this structure and * the items pointed to by this structure. When the structure is passed * into the function, ownership of the memory passes to the function. * Ownership of the memory returns to the client when this structure is * returned in the callback function. * * For optimal performance all data SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. Q.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyDsaSignS * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyDsaSignS() * *****************************************************************************/ typedef struct _CpaCyDsaSSignOpData { CpaFlatBuffer Q; /**< DSA group parameter q */ CpaFlatBuffer X; /**< DSA private key x */ CpaFlatBuffer K; /**< DSA secret parameter k for signing */ CpaFlatBuffer R; /**< DSA message signature r */ CpaFlatBuffer Z; /**< The leftmost min(N, outlen) bits of Hash(M), where: * - N is the bit length of q * - outlen is the bit length of the hash function output block * - M is the message to be signed */ } CpaCyDsaSSignOpData; /** ***************************************************************************** * @ingroup cpaCyDsa * DSA R & S Sign Operation Data. * @description * This structure contains the operation data for the cpaCyDsaSignRS * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. P.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyDsaSignRS * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyDsaSignRS() * *****************************************************************************/ typedef struct _CpaCyDsaRSSignOpData { CpaFlatBuffer P; /**< DSA group parameter p */ CpaFlatBuffer Q; /**< DSA group parameter q */ CpaFlatBuffer G; /**< DSA group parameter g */ CpaFlatBuffer X; /**< DSA private key x */ CpaFlatBuffer K; /**< DSA secret parameter k for signing */ CpaFlatBuffer Z; /**< The leftmost min(N, outlen) bits of Hash(M), where: * - N is the bit length of q * - outlen is the bit length of the hash function output block * - M is the message to be signed */ } CpaCyDsaRSSignOpData; /** ***************************************************************************** * @ingroup cpaCyDsa * DSA Verify Operation Data. * @description * This structure contains the operation data for the cpaCyDsaVerify * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. P.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyDsaVerify * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyDsaVerify() * *****************************************************************************/ typedef struct _CpaCyDsaVerifyOpData { CpaFlatBuffer P; /**< DSA group parameter p */ CpaFlatBuffer Q; /**< DSA group parameter q */ CpaFlatBuffer G; /**< DSA group parameter g */ CpaFlatBuffer Y; /**< DSA public key y */ CpaFlatBuffer Z; /**< The leftmost min(N, outlen) bits of Hash(M'), where: * - N is the bit length of q * - outlen is the bit length of the hash function output block * - M is the message to be signed */ CpaFlatBuffer R; /**< DSA message signature r */ CpaFlatBuffer S; /**< DSA message signature s */ } CpaCyDsaVerifyOpData; /** ***************************************************************************** * @ingroup cpaCyDsa * Cryptographic DSA Statistics. * @deprecated * As of v1.3 of the Crypto API, this structure has been deprecated, * replaced by @ref CpaCyDsaStats64. * @description * This structure contains statistics on the Cryptographic DSA * operations. Statistics are set to zero when the component is * initialized, and are collected per instance. ****************************************************************************/ typedef struct _CpaCyDsaStats { Cpa32U numDsaPParamGenRequests; /**< Total number of successful DSA P parameter generation requests. */ Cpa32U numDsaPParamGenRequestErrors; /**< Total number of DSA P parameter generation requests that had an * error and could not be processed. */ Cpa32U numDsaPParamGenCompleted; /**< Total number of DSA P parameter generation operations that * completed successfully. */ Cpa32U numDsaPParamGenCompletedErrors; /**< Total number of DSA P parameter generation operations that could * not be completed successfully due to errors. */ Cpa32U numDsaGParamGenRequests; /**< Total number of successful DSA G parameter generation requests. */ Cpa32U numDsaGParamGenRequestErrors; /**< Total number of DSA G parameter generation requests that had an * error and could not be processed. */ Cpa32U numDsaGParamGenCompleted; /**< Total number of DSA G parameter generation operations that * completed successfully. */ Cpa32U numDsaGParamGenCompletedErrors; /**< Total number of DSA G parameter generation operations that could * not be completed successfully due to errors. */ Cpa32U numDsaYParamGenRequests; /**< Total number of successful DSA Y parameter generation requests. */ Cpa32U numDsaYParamGenRequestErrors; /**< Total number of DSA Y parameter generation requests that had an * error and could not be processed. */ Cpa32U numDsaYParamGenCompleted; /**< Total number of DSA Y parameter generation operations that * completed successfully. */ Cpa32U numDsaYParamGenCompletedErrors; /**< Total number of DSA Y parameter generation operations that could * not be completed successfully due to errors. */ Cpa32U numDsaRSignRequests; /**< Total number of successful DSA R sign generation requests. */ Cpa32U numDsaRSignRequestErrors; /**< Total number of DSA R sign requests that had an error and could * not be processed. */ Cpa32U numDsaRSignCompleted; /**< Total number of DSA R sign operations that completed * successfully. */ Cpa32U numDsaRSignCompletedErrors; /**< Total number of DSA R sign operations that could not be completed * successfully due to errors. */ Cpa32U numDsaSSignRequests; /**< Total number of successful DSA S sign generation requests. */ Cpa32U numDsaSSignRequestErrors; /**< Total number of DSA S sign requests that had an error and could * not be processed. */ Cpa32U numDsaSSignCompleted; /**< Total number of DSA S sign operations that completed * successfully. */ Cpa32U numDsaSSignCompletedErrors; /**< Total number of DSA S sign operations that could not be completed * successfully due to errors. */ Cpa32U numDsaRSSignRequests; /**< Total number of successful DSA RS sign generation requests. */ Cpa32U numDsaRSSignRequestErrors; /**< Total number of DSA RS sign requests that had an error and could * not be processed. */ Cpa32U numDsaRSSignCompleted; /**< Total number of DSA RS sign operations that completed * successfully. */ Cpa32U numDsaRSSignCompletedErrors; /**< Total number of DSA RS sign operations that could not be completed * successfully due to errors. */ Cpa32U numDsaVerifyRequests; /**< Total number of successful DSA verify generation requests. */ Cpa32U numDsaVerifyRequestErrors; /**< Total number of DSA verify requests that had an error and could * not be processed. */ Cpa32U numDsaVerifyCompleted; /**< Total number of DSA verify operations that completed * successfully. */ Cpa32U numDsaVerifyCompletedErrors; /**< Total number of DSA verify operations that could not be completed * successfully due to errors. */ Cpa32U numDsaVerifyFailures; /**< Total number of DSA verify operations that executed successfully * but the outcome of the test was that the verification failed. * Note that this does not indicate an error. */ } CpaCyDsaStats CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCyDsa * Cryptographic DSA Statistics (64-bit version). * @description * This structure contains 64-bit version of the statistics on the * Cryptographic DSA operations. * Statistics are set to zero when the component is * initialized, and are collected per instance. ****************************************************************************/ typedef struct _CpaCyDsaStats64 { Cpa64U numDsaPParamGenRequests; /**< Total number of successful DSA P parameter generation requests. */ Cpa64U numDsaPParamGenRequestErrors; /**< Total number of DSA P parameter generation requests that had an * error and could not be processed. */ Cpa64U numDsaPParamGenCompleted; /**< Total number of DSA P parameter generation operations that * completed successfully. */ Cpa64U numDsaPParamGenCompletedErrors; /**< Total number of DSA P parameter generation operations that could * not be completed successfully due to errors. */ Cpa64U numDsaGParamGenRequests; /**< Total number of successful DSA G parameter generation requests. */ Cpa64U numDsaGParamGenRequestErrors; /**< Total number of DSA G parameter generation requests that had an * error and could not be processed. */ Cpa64U numDsaGParamGenCompleted; /**< Total number of DSA G parameter generation operations that * completed successfully. */ Cpa64U numDsaGParamGenCompletedErrors; /**< Total number of DSA G parameter generation operations that could * not be completed successfully due to errors. */ Cpa64U numDsaYParamGenRequests; /**< Total number of successful DSA Y parameter generation requests. */ Cpa64U numDsaYParamGenRequestErrors; /**< Total number of DSA Y parameter generation requests that had an * error and could not be processed. */ Cpa64U numDsaYParamGenCompleted; /**< Total number of DSA Y parameter generation operations that * completed successfully. */ Cpa64U numDsaYParamGenCompletedErrors; /**< Total number of DSA Y parameter generation operations that could * not be completed successfully due to errors. */ Cpa64U numDsaRSignRequests; /**< Total number of successful DSA R sign generation requests. */ Cpa64U numDsaRSignRequestErrors; /**< Total number of DSA R sign requests that had an error and could * not be processed. */ Cpa64U numDsaRSignCompleted; /**< Total number of DSA R sign operations that completed * successfully. */ Cpa64U numDsaRSignCompletedErrors; /**< Total number of DSA R sign operations that could not be completed * successfully due to errors. */ Cpa64U numDsaSSignRequests; /**< Total number of successful DSA S sign generation requests. */ Cpa64U numDsaSSignRequestErrors; /**< Total number of DSA S sign requests that had an error and could * not be processed. */ Cpa64U numDsaSSignCompleted; /**< Total number of DSA S sign operations that completed * successfully. */ Cpa64U numDsaSSignCompletedErrors; /**< Total number of DSA S sign operations that could not be completed * successfully due to errors. */ Cpa64U numDsaRSSignRequests; /**< Total number of successful DSA RS sign generation requests. */ Cpa64U numDsaRSSignRequestErrors; /**< Total number of DSA RS sign requests that had an error and could * not be processed. */ Cpa64U numDsaRSSignCompleted; /**< Total number of DSA RS sign operations that completed * successfully. */ Cpa64U numDsaRSSignCompletedErrors; /**< Total number of DSA RS sign operations that could not be completed * successfully due to errors. */ Cpa64U numDsaVerifyRequests; /**< Total number of successful DSA verify generation requests. */ Cpa64U numDsaVerifyRequestErrors; /**< Total number of DSA verify requests that had an error and could * not be processed. */ Cpa64U numDsaVerifyCompleted; /**< Total number of DSA verify operations that completed * successfully. */ Cpa64U numDsaVerifyCompletedErrors; /**< Total number of DSA verify operations that could not be completed * successfully due to errors. */ Cpa64U numDsaVerifyFailures; /**< Total number of DSA verify operations that executed successfully * but the outcome of the test was that the verification failed. * Note that this does not indicate an error. */ } CpaCyDsaStats64; /** ***************************************************************************** * @ingroup cpaCyDsa * Definition of a generic callback function invoked for a number of the * DSA API functions.. * * @description * This is the prototype for the cpaCyDsaGenCbFunc callback function. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Opaque pointer to Operation data supplied in * request. * @param[in] protocolStatus The result passes/fails the DSA protocol * related checks. * @param[in] pOut Output data from the request. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyDsaGenPParam() * cpaCyDsaGenGParam() * cpaCyDsaSignR() * cpaCyDsaSignS() * *****************************************************************************/ typedef void (*CpaCyDsaGenCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean protocolStatus, CpaFlatBuffer *pOut); /** ***************************************************************************** * @ingroup cpaCyDsa * Definition of callback function invoked for cpaCyDsaSignRS * requests. * * @description * This is the prototype for the cpaCyDsaSignRS callback function, which * will provide the DSA message signature r and s parameters. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Operation data pointer supplied in request. * @param[in] protocolStatus The result passes/fails the DSA protocol * related checks. * @param[in] pR DSA message signature r. * @param[in] pS DSA message signature s. * * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyDsaSignRS() * *****************************************************************************/ typedef void (*CpaCyDsaRSSignCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean protocolStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** ***************************************************************************** * @ingroup cpaCyDsa * Definition of callback function invoked for cpaCyDsaVerify * requests. * * @description * This is the prototype for the cpaCyDsaVerify callback function. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Operation data pointer supplied in request. * @param[in] verifyStatus The verification passed or failed. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyDsaVerify() * *****************************************************************************/ typedef void (*CpaCyDsaVerifyCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus); /** ***************************************************************************** * @ingroup cpaCyDsa * Generate DSA P Parameter. * * @description * * This function performs FIPS 186-3 Appendix A.1.1.2 steps 11.4 and 11.5, * and part of step 11.7: * * 11.4. c = X mod 2q. * 11.5. p = X - (c - 1). * 11.7. Test whether or not p is prime as specified in Appendix C.3. * [Note that a GCD test against ~1400 small primes is performed * on p to eliminate ~94% of composites - this is NOT a "robust" * primality test, as specified in Appendix C.3.] * * The protocol status, returned in the callback function as parameter * protocolStatus (or, in the case of synchronous invocation, in the * parameter *pProtocolStatus) is used to indicate whether the value p is * in the right range and has passed the limited primality test. * * Specifically, (protocolStatus == CPA_TRUE) means p is in the right range * and SHOULD be subjected to a robust primality test as specified in * FIPS 186-3 Appendix C.3 (for example, 40 rounds of Miller-Rabin). * Meanwhile, (protocolStatus == CPA_FALSE) means p is either composite, * or p < 2^(L-1), in which case the value of p gets set to zero. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is * set to a NULL value the function will * operate synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pProtocolStatus The result passes/fails the DSA protocol * related checks. * @param[out] pP Candidate for DSA parameter p, p odd and * 2^(L-1) < p < X * On invocation the callback function will * contain this parameter in the pOut parameter. * * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyDsaPParamGenCbFunc is generated in response to this * function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyDsaPParamGenOpData, * CpaCyDsaGenCbFunc * *****************************************************************************/ CpaStatus cpaCyDsaGenPParam(const CpaInstanceHandle instanceHandle, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaPParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pP); /** ***************************************************************************** * @ingroup cpaCyDsa * Generate DSA G Parameter. * * @description * This function performs FIPS 186-3 Appendix A.2.1, steps 1 and 3, * and part of step 4: * * 1. e = (p - 1)/q. * 3. Set g = h^e mod p. * 4. If (g = 1), then go to step 2. * Here, the implementation will check for g == 1, and return * status accordingly. * * * The protocol status, returned in the callback function as parameter * protocolStatus (or, in the case of synchronous invocation, in the * parameter *pProtocolStatus) is used to indicate whether the value g is * acceptable. * * Specifically, (protocolStatus == CPA_TRUE) means g is acceptable. * Meanwhile, (protocolStatus == CPA_FALSE) means g == 1, so a * different value of h SHOULD be used to generate another value of g. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pProtocolStatus The result passes/fails the DSA protocol * related checks. * @param[out] pG g = h^((p-1)/q) mod p. * On invocation the callback function will * contain this parameter in the pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyDsaGParamGenCbFunc is generated in response to this * function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyDsaGParamGenOpData, * CpaCyDsaGenCbFunc * *****************************************************************************/ CpaStatus cpaCyDsaGenGParam(const CpaInstanceHandle instanceHandle, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaGParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pG); /** ***************************************************************************** * @ingroup cpaCyDsa * Generate DSA Y Parameter. * * @description * * This function performs modular exponentiation to generate y as * described in FIPS 186-3 section 4.1: * y = g^x mod p * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pProtocolStatus The result passes/fails the DSA protocol * related checks. * @param[out] pY y = g^x mod p* * On invocation the callback function will * contain this parameter in the pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyDsaYParamGenCbFunc is generated in response to this * function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyDsaYParamGenOpData, * CpaCyDsaGenCbFunc * *****************************************************************************/ CpaStatus cpaCyDsaGenYParam(const CpaInstanceHandle instanceHandle, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaYParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pY); /** ***************************************************************************** * @ingroup cpaCyDsa * Generate DSA R Signature. * * @description * This function generates the DSA R signature as described in FIPS 186-3 * Section 4.6: * r = (g^k mod p) mod q * * The protocol status, returned in the callback function as parameter * protocolStatus (or, in the case of synchronous invocation, in the * parameter *pProtocolStatus) is used to indicate whether the value r == 0. * * Specifically, (protocolStatus == CPA_TRUE) means r != 0, while * (protocolStatus == CPA_FALSE) means r == 0. * * Generation of signature r does not depend on the content of the message * being signed, so this operation can be done in advance for different * values of k. Then once each message becomes available only the * signature s needs to be generated. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pProtocolStatus The result passes/fails the DSA protocol * related checks. * @param[out] pR DSA message signature r. * On invocation the callback function will * contain this parameter in the pOut parameter. * * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyDsaRSignCbFunc is generated in response to this function * call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyDsaRSignOpData, * CpaCyDsaGenCbFunc, * cpaCyDsaSignS(), * cpaCyDsaSignRS() * *****************************************************************************/ CpaStatus cpaCyDsaSignR(const CpaInstanceHandle instanceHandle, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaRSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR); /** ***************************************************************************** * @ingroup cpaCyDsa * Generate DSA S Signature. * * @description * This function generates the DSA S signature as described in FIPS 186-3 * Section 4.6: * s = (k^-1(z + xr)) mod q * * Here, z = the leftmost min(N, outlen) bits of Hash(M). This function * does not perform the SHA digest; z is computed by the caller and * passed as a parameter in the pOpData field. * * The protocol status, returned in the callback function as parameter * protocolStatus (or, in the case of synchronous invocation, in the * parameter *pProtocolStatus) is used to indicate whether the value s == 0. * * Specifically, (protocolStatus == CPA_TRUE) means s != 0, while * (protocolStatus == CPA_FALSE) means s == 0. * * If signature r has been generated in advance, then this function can be * used to generate the signature s once the message becomes available. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pProtocolStatus The result passes/fails the DSA protocol * related checks. * @param[out] pS DSA message signature s. * On invocation the callback function will * contain this parameter in the pOut parameter. * * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyDsaSSignCbFunc is generated in response to this function * call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyDsaSSignOpData, * CpaCyDsaGenCbFunc, * cpaCyDsaSignR(), * cpaCyDsaSignRS() * *****************************************************************************/ CpaStatus cpaCyDsaSignS(const CpaInstanceHandle instanceHandle, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pS); /** ***************************************************************************** * @ingroup cpaCyDsa * Generate DSA R and S Signatures. * * @description * This function generates the DSA R and S signatures as described in * FIPS 186-3 Section 4.6: * * r = (g^k mod p) mod q * s = (k^-1(z + xr)) mod q * * Here, z = the leftmost min(N, outlen) bits of Hash(M). This function * does not perform the SHA digest; z is computed by the caller and * passed as a parameter in the pOpData field. * * The protocol status, returned in the callback function as parameter * protocolStatus (or, in the case of synchronous invocation, in the * parameter *pProtocolStatus) is used to indicate whether either of * the values r or s are zero. * * Specifically, (protocolStatus == CPA_TRUE) means neither is zero (i.e. * (r != 0) && (s != 0)), while (protocolStatus == CPA_FALSE) means that at * least one of r or s is zero (i.e. (r == 0) || (s == 0)). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pProtocolStatus The result passes/fails the DSA protocol * related checks. * @param[out] pR DSA message signature r. * @param[out] pS DSA message signature s. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyDsaRSSignCbFunc is generated in response to this function * call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyDsaRSSignOpData, * CpaCyDsaRSSignCbFunc, * cpaCyDsaSignR(), * cpaCyDsaSignS() * *****************************************************************************/ CpaStatus cpaCyDsaSignRS(const CpaInstanceHandle instanceHandle, const CpaCyDsaRSSignCbFunc pCb, void *pCallbackTag, const CpaCyDsaRSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** ***************************************************************************** * @ingroup cpaCyDsa * Verify DSA R and S signatures. * * @description * This function performs FIPS 186-3 Section 4.7: * w = (s')^-1 mod q * u1 = (zw) mod q * u2 = ((r')w) mod q * v = (((g)^u1 (y)^u2) mod p) mod q * * Here, z = the leftmost min(N, outlen) bits of Hash(M'). This function * does not perform the SHA digest; z is computed by the caller and * passed as a parameter in the pOpData field. * * A response status of ok (verifyStatus == CPA_TRUE) means v = r'. * A response status of not ok (verifyStatus == CPA_FALSE) means v != r'. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pVerifyStatus The verification passed or failed. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyDsaVerifyCbFunc is generated in response to this function * call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyDsaVerifyOpData, * CpaCyDsaVerifyCbFunc * *****************************************************************************/ CpaStatus cpaCyDsaVerify(const CpaInstanceHandle instanceHandle, const CpaCyDsaVerifyCbFunc pCb, void *pCallbackTag, const CpaCyDsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus); /** ***************************************************************************** * @ingroup cpaCyDsa * Query statistics for a specific DSA instance. * * @deprecated * As of v1.3 of the Crypto API, this function has been deprecated, * replaced by @ref cpaCyDsaQueryStats64(). * * @description * This function will query a specific instance of the DSA implementation * for statistics. The user MUST allocate the CpaCyDsaStats structure * and pass the reference to that structure into this function call. This * function writes the statistic results into the passed in * CpaCyDsaStats structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pDsaStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyDsaStats *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCyDsaQueryStats(const CpaInstanceHandle instanceHandle, struct _CpaCyDsaStats *pDsaStats); /** ***************************************************************************** * @ingroup cpaCyDsa * Query 64-bit statistics for a specific DSA instance. * * @description * This function will query a specific instance of the DSA implementation * for 64-bit statistics. The user MUST allocate the CpaCyDsaStats64 * structure and pass the reference to that structure into this function. * This function writes the statistic results into the passed in * CpaCyDsaStats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pDsaStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyDsaStats *****************************************************************************/ CpaStatus cpaCyDsaQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyDsaStats64 *pDsaStats); /*****************************************************************************/ #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_DSA_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_ec.h000066400000000000000000001417571503624047500217720ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_ec.h * * @defgroup cpaCyEc Elliptic Curve (EC) API * * @ingroup cpaCy * * @description * These functions specify the API for Public Key Encryption * (Cryptography) Elliptic Curve (EC) operations. * * All implementations will support at least the following: * * - "NIST RECOMMENDED ELLIPTIC CURVES FOR FEDERAL GOVERNMENT USE" * as defined by * http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf * * - Random curves where the max(log2(q), log2(n) + log2(h)) <= 512 * where q is the modulus, n is the order of the curve and h is the * cofactor * * For Montgomery and Edwards 25519 and 448 elliptic curves, * the following operations are supported: * 1. Montgomery 25519 Curve | scalar point Multiplication * Input: Montgomery affine coordinate X of point P * Scalar k * Output: Montgomery affine coordinate X of point [k]P * Decode: Scalar k always decoded by implementation * * 2. Montgomery 25519 Curve | generator point Multiplication * Input: Scalar k * Output: Montgomery affine coordinate X of point [k]G * Decode: Scalar k always decoded by implementation * * 3. Twisted Edwards 25519 Curve | scalar point Multiplication * Input: Twisted Edwards affine coordinate X of point P * Twisted Edwards affine coordinate Y of point P * Scalar k * Output: Twisted Edwards affine coordinate X of point [k]P * Twisted Edwards affine coordinate Y of point [k]P * Decode: Caller must supply parameters in MSB order, the * implementation will not explicitly decode according * to RFC#7748 Section 5 * * 4. Twisted Edwards 25519 Curve | generator point Multiplication * Input: Scalar k * Output: Twisted Edwards affine coordinate X of point [k]G * Twisted Edwards affine coordinate Y of point [k]G * Decode: Caller must supply parameters in MSB order, the * implementation will not explicitly decode according * to RFC#7748 Section 5 * * 5. Montgomery 448 Curve | scalar point Multiplication * Input: Montgomery affine coordinate X of point P * Scalar k * Output: Montgomery affine coordinate X of point [k]P * Decode: Scalar k always decoded by implementation * * 6. Montgomery 448 Curve | generator point Multiplication * Input: Scalar k * Output: Montgomery affine coordinate X of point [k]G * Decode: Scalar k always decoded by implementation * * 7. Edwards 448 Curve | scalar point Multiplication * Input: Edwards affine coordinate X of point P * Edwards affine coordinate Y of point P * Scalar k * Output: Edwards affine coordinate X of point [k]P * Edwards affine coordinate Y of point [k]P * Decode: Caller must supply parameters in MSB order, the * implementation will not explicitly decode according * to RFC#7748 Section 5 * * 8. Edwards 448 Curve | generator point Multiplication * Input: Scalar k * Output: Edwards affine coordinate X of point [k]G * Edwards affine coordinate Y of point [k]G * Decode: Caller must supply parameters in MSB order, the * implementation will not explicitly decode according * to RFC#7748 Section 5 * * @note * Large numbers are represented on the QuickAssist API as described * in the Large Number API (@ref cpaCyLn). * * In addition, the bit length of large numbers passed to the API * MUST NOT exceed 576 bits for Elliptic Curve operations. *****************************************************************************/ #ifndef CPA_CY_EC_H_ #define CPA_CY_EC_H_ #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyEc * Field types for Elliptic Curve * @description * As defined by FIPS-186-3, for each cryptovariable length, there are * two kinds of fields. *
    *
  • A prime field is the field GF(p) which contains a prime number * p of elements. The elements of this field are the integers modulo * p, and the field arithmetic is implemented in terms of the * arithmetic of integers modulo p.
  • * *
  • A binary field is the field GF(2^m) which contains 2^m elements * for some m (called the degree of the field). The elements of * this field are the bit strings of length m, and the field * arithmetic is implemented in terms of operations on the bits.
  • *
*****************************************************************************/ typedef enum _CpaCyEcFieldType { CPA_CY_EC_FIELD_TYPE_PRIME = 1, /**< A prime field, GF(p) */ CPA_CY_EC_FIELD_TYPE_BINARY, /**< A binary field, GF(2^m) */ } CpaCyEcFieldType; /** ***************************************************************************** * @ingroup cpaCyEc * Enumeration listing curve types to use with generic multiplication * and verification routines. * * @description * This structure contains a list of different elliptic curve types. * EC Point multiplication and other operations depend on the type of * the curve. * * @see * cpaCyEcGenericPointMultiply() * cpaCyEcGenericPointVerify() * *****************************************************************************/ typedef enum _CpaCyEcCurveType { CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_PRIME = 1, /**< A Weierstrass curve with arithmetic in terms of the * arithmetic of integers modulo p over a prime field. */ CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_BINARY, /**< A Weierstrass curve with arithmetic in terms of operations on bits * over a binary field. */ CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_KOBLITZ_BINARY, /**< A Weierstrass-koblitz curve with arithmetic in terms of operations on * the bits over a binary field. */ } CpaCyEcCurveType; /** ***************************************************************************** * @ingroup cpaCyEc * Curve types for Elliptic Curves defined in RFC#7748 * @description * As defined by RFC 7748, there are four elliptic curves in this * group. The Montgomery curves are denoted curve25519 and curve448, * and the birationally equivalent Twisted Edwards curves are denoted * edwards25519 and edwards448 * *****************************************************************************/ typedef enum _CpaCyEcMontEdwdsCurveType { CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE = 1, /**< Montgomery 25519 curve */ CPA_CY_EC_MONTEDWDS_ED25519_TYPE, /**< Edwards 25519 curve */ CPA_CY_EC_MONTEDWDS_CURVE448_TYPE, /**< Montgomery 448 curve */ CPA_CY_EC_MONTEDWDS_ED448_TYPE, /**< Edwards 448 curve */ } CpaCyEcMontEdwdsCurveType; /** ***************************************************************************** * @ingroup cpaCyEc * Curve parameters for a Weierstrass type curve. * * @description * This structure contains curve parameters for Weierstrass type * curve: y^2 = x^3 + ax + b * The client MUST allocate the memory for this structure * When the structure is passed into the function, ownership of the memory * passes to the function. Ownership of the memory returns to the client * when this structure is returned in the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * The legend used in this structure is borrowed from RFC7748 * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the function, and before it * has been returned in the callback, undefined behavior will result. * * @see * CpaCyEcCurveParameters * CpaCyEcFieldType * *****************************************************************************/ typedef struct _CpaCyEcCurveParametersWeierstrass { CpaCyEcFieldType fieldType; /**< Prime or Binary */ CpaFlatBuffer p; /**< Prime modulus or irreducible polynomial over GF(2^m) */ CpaFlatBuffer a; /**< a coefficient */ CpaFlatBuffer b; /**< b coefficient */ CpaFlatBuffer h; /**< Cofactor */ } CpaCyEcCurveParametersWeierstrass; /** ***************************************************************************** * @ingroup cpaCyEc * Union characterised by a specific curve. * * @description * This union allows for the characterisation of different curve types * encapsulated in one data type. The intention is that new curve types * will be added in the future. * * @note * * @see * CpaCyEcCurveParametersWeierstrass * *****************************************************************************/ typedef union _CpaCyEcCurveParameters { CpaCyEcCurveParametersWeierstrass weierstrassParameters; } CpaCyEcCurveParameters; /** ***************************************************************************** * @ingroup cpaCyEc * Unified curve parameters. * * @description * This structure provides a single data type that can describe a number * of different curve types. The intention is to add further * curve types in the future, thus the union field will allow for that * expansion. * * The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the function, and before it * has been returned in the callback, undefined behavior will result. * * @see * CpaCyEcCurveParameters * cpaCyEcGenericPointMultiply * cpaCyEcGenericPointVerify * *****************************************************************************/ typedef struct _CpaCyEcCurve { CpaCyEcCurveType curveType; CpaCyEcCurveParameters parameters; } CpaCyEcCurve; /** ***************************************************************************** * @ingroup cpaCyEc * EC Point Multiplication Operation Data. * * @description * This structure contains the operation data for the cpaCyEcPointMultiply * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcPointMultiply * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcPointMultiply() * *****************************************************************************/ typedef struct _CpaCyEcPointMultiplyOpData { CpaFlatBuffer k; /**< scalar multiplier (k > 0 and k < n) */ CpaFlatBuffer xg; /**< x coordinate of curve point */ CpaFlatBuffer yg; /**< y coordinate of curve point */ CpaFlatBuffer a; /**< a elliptic curve coefficient */ CpaFlatBuffer b; /**< b elliptic curve coefficient */ CpaFlatBuffer q; /**< prime modulus or irreducible polynomial over GF(2^m)*/ CpaFlatBuffer h; /**< cofactor of the operation. * If the cofactor is NOT required then set the cofactor to 1 or the * data pointer of the Flat Buffer to NULL. */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcPointMultiplyOpData CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCyEc * Generic EC Point Multiplication Operation Data. * * @description * This structure contains a generic EC point and a multiplier for use with * cpaCyEcGenericPointMultiply. This is common for representing all EC * points, irrespective of curve type: Weierstrass, Montgomery and Twisted * Edwards (at this time only Weierstrass are supported). The same * point + multiplier format can be used when performing generator * multiplication, in which case the xP, yP supplied in this structure will * be ignored by QAT API library & a generator point will be inserted in * their place. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcGenericPointMultiply * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcGenericPointMultiply() * *****************************************************************************/ typedef struct _CpaCyEcGenericPointMultiplyOpData { CpaFlatBuffer k; /** 0 and k < n) */ CpaFlatBuffer xP; /** pair specified in the structure * lies on the curve indicated in the cpaCyEcGenericPointVerify API. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcGenericPointVerify * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcGenericPointVerify() * *****************************************************************************/ typedef struct _CpaCyEcGenericPointVerifyOpData { CpaFlatBuffer xP; /** 0 and k < n) */ CpaFlatBuffer xg; /**< x coordinate of curve point */ CpaFlatBuffer yg; /**< y coordinate of curve point */ CpaFlatBuffer a; /**< a equation coefficient */ CpaFlatBuffer b; /**< b equation coefficient */ CpaFlatBuffer q; /**< prime modulus or irreducible polynomial over GF(2^r) */ CpaFlatBuffer h; /**< cofactor of the operation. * If the cofactor is NOT required then set the cofactor to 1 or the * data pointer of the Flat Buffer to NULL. * There are some restrictions on the value of the cofactor. * Implementations of this API will support at least the following: *
    *
  • NIST standard curves and their cofactors (1, 2 and 4)
  • * *
  • Random curves where max(log2(p), log2(n)+log2(h)) <= 512, where * p is the modulus, n is the order of the curve and h is the cofactor *
  • *
*/ CpaCyEcFieldType fieldType; /**< field type for the operation */ CpaBoolean pointVerify; /**< set to CPA_TRUE to do a verification before the multiplication */ } CpaCyEcdhPointMultiplyOpData; /** ***************************************************************************** * @ingroup cpaCyEcdh * Cryptographic ECDH Statistics. * @description * This structure contains statistics on the Cryptographic ECDH * operations. Statistics are set to zero when the component is * initialized, and are collected per instance. * ****************************************************************************/ typedef struct _CpaCyEcdhStats64 { Cpa64U numEcdhPointMultiplyRequests; /**< Total number of ECDH Point Multiplication operation requests. */ Cpa64U numEcdhPointMultiplyRequestErrors; /**< Total number of ECDH Point Multiplication operation requests that had * an error and could not be processed. */ Cpa64U numEcdhPointMultiplyCompleted; /**< Total number of ECDH Point Multiplication operation requests that * completed successfully. */ Cpa64U numEcdhPointMultiplyCompletedError; /**< Total number of ECDH Point Multiplication operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcdhRequestCompletedOutputInvalid; /**< Total number of ECDH Point Multiplication or Point Verify operation * requests that could not be completed successfully due to an invalid * output. * Note that this does not indicate an error. */ } CpaCyEcdhStats64; /** ***************************************************************************** * @ingroup cpaCyEcdh * Definition of callback function invoked for cpaCyEcdhPointMultiply * requests. * * @description * This is the prototype for the CpaCyEcdhPointMultiplyCbFunc callback * function * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Opaque pointer to Operation data supplied in * request. * @param[in] pXk Output x coordinate from the request. * @param[in] pYk Output y coordinate from the request. * @param[in] multiplyStatus Status of the point multiplication and the * verification when the pointVerify bit is set * in the CpaCyEcdhPointMultiplyOpData structure. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyEcdhPointMultiply() * *****************************************************************************/ typedef void (*CpaCyEcdhPointMultiplyCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk); /** ***************************************************************************** * @ingroup cpaCyEcdh * ECDH Point Multiplication. * * @description * This function performs ECDH Point Multiplication as defined in * ANSI X9.63 2001 section 5.4 * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pMultiplyStatus In synchronous mode, the status of the point * multiplication and the verification when the * pointVerify bit is set in the * CpaCyEcdhPointMultiplyOpData structure. Set to * CPA_FALSE if the point is NOT on the curve or * at infinity. Set to CPA_TRUE if the point is * on the curve. * @param[out] pXk Pointer to x coordinate flat buffer. * @param[out] pYk Pointer to y coordinate flat buffer. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyEcdhPointMultiplyCbFunc is generated in response to this function * call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcdhPointMultiplyOpData, * CpaCyEcdhPointMultiplyCbFunc * *****************************************************************************/ CpaStatus cpaCyEcdhPointMultiply(const CpaInstanceHandle instanceHandle, const CpaCyEcdhPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcdhPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk); /** ***************************************************************************** * @ingroup cpaCyEcdh * Query statistics for a specific ECDH instance. * * @description * This function will query a specific instance of the ECDH implementation * for statistics. The user MUST allocate the CpaCyEcdhStats64 structure * and pass the reference to that structure into this function call. This * function writes the statistic results into the passed in * CpaCyEcdhStats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pEcdhStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyEcdhStats64 *****************************************************************************/ CpaStatus cpaCyEcdhQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyEcdhStats64 *pEcdhStats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /*CPA_CY_ECDH_H_*/ qatlib-25.08.0/quickassist/include/lac/cpa_cy_ecdsa.h000066400000000000000000001130251503624047500224450ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_ecdsa.h * * @defgroup cpaCyEcdsa Elliptic Curve Digital Signature Algorithm (ECDSA) API * * @ingroup cpaCy * * @description * These functions specify the API for Public Key Encryption * (Cryptography) Elliptic Curve Digital Signature Algorithm (ECDSA) * operations. * * @note * Large numbers are represented on the QuickAssist API as described * in the Large Number API (@ref cpaCyLn). * * In addition, the bit length of large numbers passed to the API * MUST NOT exceed 576 bits for Elliptic Curve operations. *****************************************************************************/ #ifndef CPA_CY_ECDSA_H_ #define CPA_CY_ECDSA_H_ #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" #include "cpa_cy_ec.h" /** ***************************************************************************** * @ingroup cpaCyEcdsa * ECDSA Sign R Operation Data. * @description * This structure contains the operation data for the cpaCyEcdsaSignR * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcdsaSignR * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcdsaSignR() * *****************************************************************************/ typedef struct _CpaCyEcdsaSignROpData { CpaFlatBuffer xg; /**< x coordinate of base point G */ CpaFlatBuffer yg; /**< y coordinate of base point G */ CpaFlatBuffer n; /**< order of the base point G, which shall be prime */ CpaFlatBuffer q; /**< prime modulus or irreducible polynomial over GF(2^r) */ CpaFlatBuffer a; /**< a elliptic curve coefficient */ CpaFlatBuffer b; /**< b elliptic curve coefficient */ CpaFlatBuffer k; /**< random value (k > 0 and k < n) */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcdsaSignROpData; /** ***************************************************************************** * @ingroup cpaCyEcdsa * ECDSA Sign S Operation Data. * @description * This structure contains the operation data for the cpaCyEcdsaSignS * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcdsaSignS * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcdsaSignS() * *****************************************************************************/ typedef struct _CpaCyEcdsaSignSOpData { CpaFlatBuffer m; /**< digest of the message to be signed */ CpaFlatBuffer d; /**< private key */ CpaFlatBuffer r; /**< Ecdsa r signature value */ CpaFlatBuffer k; /**< random value (k > 0 and k < n) */ CpaFlatBuffer n; /**< order of the base point G, which shall be prime */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcdsaSignSOpData; /** ***************************************************************************** * @ingroup cpaCyEcdsa * ECDSA Sign R & S Operation Data. * @description * This structure contains the operation data for the cpaCyEcdsaSignRS * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcdsaSignRS * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcdsaSignRS() * *****************************************************************************/ typedef struct _CpaCyEcdsaSignRSOpData { CpaFlatBuffer xg; /**< x coordinate of base point G */ CpaFlatBuffer yg; /**< y coordinate of base point G */ CpaFlatBuffer n; /**< order of the base point G, which shall be prime */ CpaFlatBuffer q; /**< prime modulus or irreducible polynomial over GF(2^r) */ CpaFlatBuffer a; /**< a elliptic curve coefficient */ CpaFlatBuffer b; /**< b elliptic curve coefficient */ CpaFlatBuffer k; /**< random value (k > 0 and k < n) */ CpaFlatBuffer m; /**< digest of the message to be signed */ CpaFlatBuffer d; /**< private key */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcdsaSignRSOpData; /** ***************************************************************************** * @ingroup cpaCyEcdsa * ECDSA Verify Operation Data, for Public Key. * @description * This structure contains the operation data for the CpaCyEcdsaVerify * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcdsaVerify * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * CpaCyEcdsaVerify() * *****************************************************************************/ typedef struct _CpaCyEcdsaVerifyOpData { CpaFlatBuffer xg; /**< x coordinate of base point G */ CpaFlatBuffer yg; /**< y coordinate of base point G */ CpaFlatBuffer n; /**< order of the base point G, which shall be prime */ CpaFlatBuffer q; /**< prime modulus or irreducible polynomial over GF(2^r) */ CpaFlatBuffer a; /**< a elliptic curve coefficient */ CpaFlatBuffer b; /**< b elliptic curve coefficient */ CpaFlatBuffer m; /**< digest of the message to be signed */ CpaFlatBuffer r; /**< ECDSA r signature value (r > 0 and r < n) */ CpaFlatBuffer s; /**< ECDSA s signature value (s > 0 and s < n) */ CpaFlatBuffer xp; /**< x coordinate of point P (public key) */ CpaFlatBuffer yp; /**< y coordinate of point P (public key) */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcdsaVerifyOpData; /** ***************************************************************************** * @ingroup cpaCyEcdsa * Cryptographic ECDSA Statistics. * @description * This structure contains statistics on the Cryptographic ECDSA * operations. Statistics are set to zero when the component is * initialized, and are collected per instance. * ****************************************************************************/ typedef struct _CpaCyEcdsaStats64 { Cpa64U numEcdsaSignRRequests; /**< Total number of ECDSA Sign R operation requests. */ Cpa64U numEcdsaSignRRequestErrors; /**< Total number of ECDSA Sign R operation requests that had an error and * could not be processed. */ Cpa64U numEcdsaSignRCompleted; /**< Total number of ECDSA Sign R operation requests that completed * successfully. */ Cpa64U numEcdsaSignRCompletedErrors; /**< Total number of ECDSA Sign R operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcdsaSignRCompletedOutputInvalid; /**< Total number of ECDSA Sign R operation requests could not be completed * successfully due to an invalid output. * Note that this does not indicate an error. */ Cpa64U numEcdsaSignSRequests; /**< Total number of ECDSA Sign S operation requests. */ Cpa64U numEcdsaSignSRequestErrors; /**< Total number of ECDSA Sign S operation requests that had an error and * could not be processed. */ Cpa64U numEcdsaSignSCompleted; /**< Total number of ECDSA Sign S operation requests that completed * successfully. */ Cpa64U numEcdsaSignSCompletedErrors; /**< Total number of ECDSA Sign S operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcdsaSignSCompletedOutputInvalid; /**< Total number of ECDSA Sign S operation requests could not be completed * successfully due to an invalid output. * Note that this does not indicate an error. */ Cpa64U numEcdsaSignRSRequests; /**< Total number of ECDSA Sign R & S operation requests. */ Cpa64U numEcdsaSignRSRequestErrors; /**< Total number of ECDSA Sign R & S operation requests that had an * error and could not be processed. */ Cpa64U numEcdsaSignRSCompleted; /**< Total number of ECDSA Sign R & S operation requests that completed * successfully. */ Cpa64U numEcdsaSignRSCompletedErrors; /**< Total number of ECDSA Sign R & S operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcdsaSignRSCompletedOutputInvalid; /**< Total number of ECDSA Sign R & S operation requests could not be * completed successfully due to an invalid output. * Note that this does not indicate an error. */ Cpa64U numEcdsaVerifyRequests; /**< Total number of ECDSA Verification operation requests. */ Cpa64U numEcdsaVerifyRequestErrors; /**< Total number of ECDSA Verification operation requests that had an * error and could not be processed. */ Cpa64U numEcdsaVerifyCompleted; /**< Total number of ECDSA Verification operation requests that completed * successfully. */ Cpa64U numEcdsaVerifyCompletedErrors; /**< Total number of ECDSA Verification operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcdsaVerifyCompletedOutputInvalid; /**< Total number of ECDSA Verification operation requests that resulted * in an invalid output. * Note that this does not indicate an error. */ Cpa64U numKptEcdsaSignRSCompletedOutputInvalid; /**< Total number of KPT ECDSA Sign R & S operation requests could not be * completed successfully due to an invalid output. * Note that this does not indicate an error. */ Cpa64U numKptEcdsaSignRSCompleted; /**< Total number of KPT ECDSA Sign R & S operation requests that completed * successfully. */ Cpa64U numKptEcdsaSignRSRequests; /**< Total number of KPT ECDSA Sign R & S operation requests. */ Cpa64U numKptEcdsaSignRSRequestErrors; /**< Total number of KPT ECDSA Sign R & S operation requests that had an * error and could not be processed. */ Cpa64U numKptEcdsaSignRSCompletedErrors; /**< Total number of KPT ECDSA Sign R & S operation requests that could * not be completed successfully due to errors. */ } CpaCyEcdsaStats64; /** ***************************************************************************** * @ingroup cpaCyEcdsa * Definition of a generic callback function invoked for a number of the * ECDSA Sign API functions. * * @description * This is the prototype for the CpaCyEcdsaGenSignCbFunc callback function. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Opaque pointer to Operation data supplied in * request. * @param[in] multiplyStatus Status of the point multiplication. * @param[in] pOut Output data from the request. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyEcdsaSignR() * cpaCyEcdsaSignS() * *****************************************************************************/ typedef void (*CpaCyEcdsaGenSignCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pOut); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Definition of callback function invoked for cpaCyEcdsaSignRS * requests. * * @description * This is the prototype for the CpaCyEcdsaSignRSCbFunc callback function, * which will provide the ECDSA message signature r and s parameters. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Operation data pointer supplied in request. * @param[in] multiplyStatus Status of the point multiplication. * @param[in] pR Ecdsa message signature r. * @param[in] pS Ecdsa message signature s. * * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyEcdsaSignRS() * *****************************************************************************/ typedef void (*CpaCyEcdsaSignRSCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Definition of callback function invoked for cpaCyEcdsaVerify requests. * * @description * This is the prototype for the CpaCyEcdsaVerifyCbFunc callback function. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Operation data pointer supplied in request. * @param[in] verifyStatus The verification status. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyEcdsaVerify() * *****************************************************************************/ typedef void (*CpaCyEcdsaVerifyCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Generate ECDSA Signature R. * * @description * This function generates ECDSA Signature R as per ANSI X9.62 2005 * section 7.3. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pSignStatus In synchronous mode, the multiply output is * valid (CPA_TRUE) or the output is invalid * (CPA_FALSE). * @param[out] pR ECDSA message signature r. * * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback is generated in response * to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * None *****************************************************************************/ CpaStatus cpaCyEcdsaSignR(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaGenSignCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignROpData *pOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Generate ECDSA Signature S. * * @description * This function generates ECDSA Signature S as per ANSI X9.62 2005 * section 7.3. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pSignStatus In synchronous mode, the multiply output is * valid (CPA_TRUE) or the output is invalid * (CPA_FALSE). * @param[out] pS ECDSA message signature s. * * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback is generated in response * to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * None *****************************************************************************/ CpaStatus cpaCyEcdsaSignS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaGenSignCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignSOpData *pOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pS); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Generate ECDSA Signature R & S. * * @description * This function generates ECDSA Signature R & S as per ANSI X9.62 2005 * section 7.3. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pSignStatus In synchronous mode, the multiply output is * valid (CPA_TRUE) or the output is invalid * (CPA_FALSE). * @param[out] pR ECDSA message signature r. * @param[out] pS ECDSA message signature s. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback is generated in response * to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * None *****************************************************************************/ CpaStatus cpaCyEcdsaSignRS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Differential Power Analysis (DPA) Resistant Generation of ECDSA * Signature R & S. This is a variation of the cpaCyEcdsaSignRS() API. * * @description * This function generates ECDSA Signature R & S in a DPA resistant * way as per ANSI X9.62 2005 section 7.3. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[in] pRandom Pointer to buffer containing cryptographically * secure random data. * @param[in] createRandomData Control parameter to delegate the random * data generation to QAT. If set to CPA_TRUE, * input parameter pRandom is ignored. * @param[out] pSignStatus In synchronous mode, the multiply output is * valid (CPA_TRUE) or the output is invalid * (CPA_FALSE). * @param[out] pR ECDSA message signature r. * @param[out] pS ECDSA message signature s. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback is generated in response * to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * None *****************************************************************************/ CpaStatus cpaCyEcdsaDpaSignRS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, const CpaFlatBuffer *pRandom, const CpaBoolean createRandomData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Verify ECDSA Public Key. * * @description * This function performs ECDSA Verify as per ANSI X9.62 2005 section 7.4. * * A response status of ok (verifyStatus == CPA_TRUE) means that the * signature was verified * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pVerifyStatus In synchronous mode, set to CPA_FALSE if the * point is NOT on the curve or at infinity. Set * to CPA_TRUE if the point is on the curve. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyEcdsaVerifyCbFunc is generated in response to this function * call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcdsaVerifyOpData, * CpaCyEcdsaVerifyCbFunc * *****************************************************************************/ CpaStatus cpaCyEcdsaVerify(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaVerifyCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus); /** ***************************************************************************** * @ingroup cpaCyEcdsa * Query statistics for a specific ECDSA instance. * * @description * This function will query a specific instance of the ECDSA implementation * for statistics. The user MUST allocate the CpaCyEcdsaStats64 structure * and pass the reference to that structure into this function call. This * function writes the statistic results into the passed in * CpaCyEcdsaStats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pEcdsaStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyEcdsaStats64 *****************************************************************************/ CpaStatus cpaCyEcdsaQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyEcdsaStats64 *pEcdsaStats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /*CPA_CY_ECDSA_H_*/ qatlib-25.08.0/quickassist/include/lac/cpa_cy_ecsm2.h000066400000000000000000001671671503624047500224170ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_ecsm2.h * * @defgroup cpaCyEcsm2 Elliptic Curve SM2 (ECSM2) API * * @ingroup cpaCy * * @description * These functions specify the API for Public Key Encryption * (Cryptography) SM2 operations. * * Chinese Public Key Algorithm based on Elliptic Curve Theory * * @note * The naming, terms, and reference on SM2 elliptic curve, and their * flow of algorithms inside this API header file are from the link * below, please kindly refer to it for details. * https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 * *****************************************************************************/ #ifndef CPA_CY_ECSM2_H_ #define CPA_CY_ECSM2_H_ #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" #include "cpa_cy_ec.h" /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Encryption Operation Data. * * @description * This structure contains the operation data for the cpaCyEcsm2Encrypt * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2Encrypt * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2Encrypt() * *****************************************************************************/ typedef struct _CpaCyEcsm2EncryptOpData { CpaFlatBuffer k; /**< scalar multiplier (k > 0 and k < n) */ CpaFlatBuffer xP; /**< x coordinate of public key */ CpaFlatBuffer yP; /**< y coordinate of public key */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2EncryptOpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Decryption Operation Data. * * @description * This structure contains the operation data for the cpaCyEcsm2Decrypt * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2Decrypt * function, and before it has been returned in the callback, undefined * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2Decrypt * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2Decrypt() * *****************************************************************************/ typedef struct _CpaCyEcsm2DecryptOpData { CpaFlatBuffer d; /**< private key (d > 0 and d < n) */ CpaFlatBuffer x1; /**< x coordinate of [k]G */ CpaFlatBuffer y1; /**< y coordinate of [k]G */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2DecryptOpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Point Multiplication Operation Data. * * @description * This structure contains the operation data for the * cpaCyEcsm2PointMultiply function. The client MUST allocate the memory * for this structure and the items pointed to by this structure. When the * structure is passed into the function, ownership of the memory passes to * the function. Ownership of the memory returns to the client when this * structure is returned in the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2PointMultiply * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2PointMultiply() * *****************************************************************************/ typedef struct _CpaCyEcsm2PointMultiplyOpData { CpaFlatBuffer k; /**< scalar multiplier (k > 0 and k < n) */ CpaFlatBuffer x; /**< x coordinate of a point on the curve */ CpaFlatBuffer y; /**< y coordinate of a point on the curve */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2PointMultiplyOpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Generator Multiplication Operation Data. * * @description * This structure contains the operation data for the * cpaCyEcsm2GeneratorMultiply function. The client MUST allocate the * memory for this structure and the items pointed to by this structure. * When the structure is passed into the function, ownership of the * memory passes to the function. Ownership of the memory returns to the * client when this structure is returned in the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2GeneratorMultiply * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2GeneratorMultiply() * *****************************************************************************/ typedef struct _CpaCyEcsm2GeneratorMultiplyOpData { CpaFlatBuffer k; /**< scalar multiplier (k > 0 and k < n) */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2GeneratorMultiplyOpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Point Verify Operation Data. * * @description * This structure contains the operation data for the cpaCyEcsm2PointVerify * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2PointVerify * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2PointVerify() * *****************************************************************************/ typedef struct _CpaCyEcsm2PointVerifyOpData { CpaFlatBuffer x; /**< x coordinate of a point on the curve */ CpaFlatBuffer y; /**< y coordinate of a point on the curve */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2PointVerifyOpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Signature Operation Data. * * @description * This structure contains the operation data for the cpaCyEcsm2Sign * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2Sign * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2Sign() * *****************************************************************************/ typedef struct _CpaCyEcsm2SignOpData { CpaFlatBuffer k; /**< scalar multiplier (k > 0 and k < n) */ CpaFlatBuffer e; /**< digest of the message */ CpaFlatBuffer d; /**< private key (d > 0 and d < n) */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2SignOpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Signature Verify Operation Data. * * @description * This structure contains the operation data for the cpaCyEcsm2Verify * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2Verify * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2Verify() * *****************************************************************************/ typedef struct _CpaCyEcsm2VerifyOpData { CpaFlatBuffer e; /**< digest of the message */ CpaFlatBuffer r; /**< signature r */ CpaFlatBuffer s; /**< signature s */ CpaFlatBuffer xP; /**< x coordinate of public key */ CpaFlatBuffer yP; /**< y coordinate of public key */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2VerifyOpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Key Exchange Phase 1 Operation Data. * * @description * This structure contains the operation data for the cpaCyEcsm2KeyExPhase1 * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2KeyExPhase1 * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2KeyExPhase1() * *****************************************************************************/ typedef struct _CpaCyEcsm2KeyExPhase1OpData { CpaFlatBuffer r; /**< scalar multiplier (r > 0 and r < n) */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2KeyExPhase1OpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Key Exchange Phase 2 Operation Data. * * @description * This structure contains the operation data for the cpaCyEcsm2KeyExPhase2 * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. a.pData[0] = MSB. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyEcsm2KeyExPhase2 * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcsm2KeyExPhase2() * *****************************************************************************/ typedef struct _CpaCyEcsm2KeyExPhase2OpData { CpaFlatBuffer r; /**< scalar multiplier (r > 0 and r < n) */ CpaFlatBuffer d; /**< private key (d > 0 and d < n) */ CpaFlatBuffer x1; /**< x coordinate of a point on the curve from other side */ CpaFlatBuffer x2; /**< x coordinate of a point on the curve from phase 1 */ CpaFlatBuffer y2; /**< y coordinate of a point on the curve from phase 1 */ CpaFlatBuffer xP; /**< x coordinate of public key from other side */ CpaFlatBuffer yP; /**< y coordinate of public key from other side */ CpaCyEcFieldType fieldType; /**< field type for the operation */ } CpaCyEcsm2KeyExPhase2OpData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Encryption Output Data. * * @description * This structure contains the output data of the cpaCyEcsm2Encrypt * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * @see * cpaCyEcsm2Encrypt() * *****************************************************************************/ typedef struct _CpaCyEcsm2EncryptOutputData { CpaFlatBuffer x1; /**< x coordinate of [k]G */ CpaFlatBuffer y1; /**< y coordinate of [k]G */ CpaFlatBuffer x2; /**< x coordinate of [k]Pb */ CpaFlatBuffer y2; /**< y coordinate of [k]Pb */ } CpaCyEcsm2EncryptOutputData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Decryption Output Data. * * @description * This structure contains the output data of the cpaCyEcsm2Decrypt * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * @see * cpaCyEcsm2Decrypt() * *****************************************************************************/ typedef struct _CpaCyEcsm2DecryptOutputData { CpaFlatBuffer x2; /**< x coordinate of [k]Pb */ CpaFlatBuffer y2; /**< y coordinate of [k]Pb */ } CpaCyEcsm2DecryptOutputData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * SM2 Key Exchange (Phase 1 & Phase 2) Output Data. * * @description * This structure contains the output data of the key exchange(phase 1 & 2) * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * @see * cpaCyEcsm2KeyExPhase1(),cpaCyEcsm2KeyExPhase2() * *****************************************************************************/ typedef struct _CpaCyEcsm2KeyExOutputData { CpaFlatBuffer x; /**< x coordinate of a point on the curve */ CpaFlatBuffer y; /**< y coordinate of a point on the curve */ } CpaCyEcsm2KeyExOutputData; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * Cryptographic ECSM2 Statistics. * @description * This structure contains statistics on the Cryptographic ECSM2 * operations. Statistics are set to zero when the component is * initialized, and are collected per instance. * ****************************************************************************/ typedef struct _CpaCyEcsm2Stats64 { Cpa64U numEcsm2PointMultiplyRequests; /**< Total number of ECSM2 Point Multiplication operation requests. */ Cpa64U numEcsm2PointMultiplyRequestErrors; /**< Total number of ECSM2 Point Multiplication operation requests that * had an error and could not be processed. */ Cpa64U numEcsm2PointMultiplyCompleted; /**< Total number of ECSM2 Point Multiplication operation requests that * completed successfully. */ Cpa64U numEcsm2PointMultiplyCompletedError; /**< Total number of ECSM2 Point Multiplication operation requests that * could not be completed successfully due to errors. */ Cpa64U numEcsm2PointMultiplyCompletedOutputInvalid; /**< Total number of ECSM2 Point Multiplication or Point Verify operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ Cpa64U numEcsm2GeneratorMultiplyRequests; /**< Total number of ECSM2 Generator Multiplication operation requests. */ Cpa64U numEcsm2GeneratorMultiplyRequestErrors; /**< Total number of ECSM2 Generator Multiplication operation requests that * had an error and could not be processed. */ Cpa64U numEcsm2GeneratorMultiplyCompleted; /**< Total number of ECSM2 Generator Multiplication operation requests that * completed successfully. */ Cpa64U numEcsm2GeneratorMultiplyCompletedError; /**< Total number of ECSM2 Generator Multiplication operation requests that * could not be completed successfully due to errors. */ Cpa64U numEcsm2GeneratorMultiplyCompletedOutputInvalid; /**< Total number of ECSM2 Generator Multiplication or Point Verify * operation requests that could not be completed successfully due to an * invalid output. Note that this does not indicate an error. */ Cpa64U numEcsm2PointVerifyRequests; /**< Total number of ECSM2 Point Verify operation requests. */ Cpa64U numEcsm2PointVerifyRequestErrors; /**< Total number of ECSM2 Point Verify operation requests that had * an error and could not be processed. */ Cpa64U numEcsm2PointVerifyCompleted; /**< Total number of ECSM2 Point Verify operation requests that * completed successfully. */ Cpa64U numEcsm2PointVerifyCompletedError; /**< Total number of ECSM2 Point Verify operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcsm2PointVerifyCompletedOutputInvalid; /**< Total number of ECSM2 Point Verify operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ Cpa64U numEcsm2SignRequests; /**< Total number of ECSM2 Sign operation requests. */ Cpa64U numEcsm2SignRequestErrors; /**< Total number of ECSM2 Sign operation requests that had an error * and could not be processed. */ Cpa64U numEcsm2SignCompleted; /**< Total number of ECSM2 Sign operation requests that completed * successfully. */ Cpa64U numEcsm2SignCompletedError; /**< Total number of ECSM2 Sign operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcsm2SignCompletedOutputInvalid; /**< Total number of ECSM2 Sign operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ Cpa64U numEcsm2VerifyRequests; /**< Total number of ECSM2 Verify operation requests. */ Cpa64U numEcsm2VerifyRequestErrors; /**< Total number of ECSM2 Verify operation requests that had an error * and could not be processed. */ Cpa64U numEcsm2VerifyCompleted; /**< Total number of ECSM2 Verify operation requests that completed * successfully. */ Cpa64U numEcsm2VerifyCompletedError; /**< Total number of ECSM2 Verify operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcsm2VerifyCompletedOutputInvalid; /**< Total number of ECSM2 Verify operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ Cpa64U numEcsm2EncryptRequests; /**< Total number of ECSM2 Encryption requests. */ Cpa64U numEcsm2EncryptRequestErrors; /**< Total number of ECSM2 Point Encryption requests that had * an error and could not be processed. */ Cpa64U numEcsm2EncryptCompleted; /**< Total number of ECSM2 Encryption operation requests that * completed successfully. */ Cpa64U numEcsm2EncryptCompletedError; /**< Total number of ECSM2 Encryption operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcsm2EncryptCompletedOutputInvalid; /**< Total number of ECSM2 Encryption operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ Cpa64U numEcsm2DecryptRequests; /**< Total number of ECSM2 Decryption operation requests. */ Cpa64U numEcsm2DecryptRequestErrors; /**< Total number of ECSM2 Point Decryption requests that had * an error and could not be processed. */ Cpa64U numEcsm2DecryptCompleted; /**< Total number of ECSM2 Decryption operation requests that * completed successfully. */ Cpa64U numEcsm2DecryptCompletedError; /**< Total number of ECSM2 Decryption operation requests that could * not be completed successfully due to errors. */ Cpa64U numEcsm2DecryptCompletedOutputInvalid; /**< Total number of ECSM2 Decryption operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ Cpa64U numEcsm2KeyExPhase1Requests; /**< Total number of ECSM2 Key Exchange Phase1 operation requests. */ Cpa64U numEcsm2KeyExPhase1RequestErrors; /**< Total number of ECSM2 Key Exchange Phase1 operation requests that * had an error and could not be processed. */ Cpa64U numEcsm2KeyExPhase1Completed; /**< Total number of ECSM2 Key Exchange Phase1 operation requests that * completed successfully. */ Cpa64U numEcsm2KeyExPhase1CompletedError; /**< Total number of ECSM2 Key Exchange Phase1 operation requests that * could not be completed successfully due to errors. */ Cpa64U numEcsm2KeyExPhase1CompletedOutputInvalid; /**< Total number of ECSM2 Key Exchange Phase1 operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ Cpa64U numEcsm2KeyExPhase2Requests; /**< Total number of ECSM2 Key Exchange Phase2 operation requests. */ Cpa64U numEcsm2KeyExPhase2RequestErrors; /**< Total number of ECSM2 Key Exchange Phase2 operation requests that * had an error and could not be processed. */ Cpa64U numEcsm2KeyExPhase2Completed; /**< Total number of ECSM2 Key Exchange Phase2 operation requests that * completed successfully. */ Cpa64U numEcsm2KeyExPhase2CompletedError; /**< Total number of ECSM2 Key Exchange Phase2 operation requests that * could not be completed successfully due to errors. */ Cpa64U numEcsm2KeyExPhase2CompletedOutputInvalid; /**< Total number of ECSM2 Key Exchange Phase2 operation * requests that could not be completed successfully due to an invalid * output. Note that this does not indicate an error. */ } CpaCyEcsm2Stats64; /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * Definition of callback function invoked for cpaCyEcsm2Sign * requests. * * @description * This is the callback function for: * cpaCyEcsm2Sign * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS and CPA_STATUS_FAIL. * @param[in] pOpData A pointer to Operation data supplied in * request. * @param[in] pass Indicate whether pOut is valid or not. * CPA_TRUE == pass, pOut is valid * CPA_FALSE == pass, pOut is invalid * @param[in] pR Ecsm2 message signature r. * @param[in] pS Ecsm2 message signature s. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyEcsm2GeneratorMultiply() * *****************************************************************************/ typedef void (*CpaCyEcsm2SignCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean pass, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * Definition of callback function invoked for cpaCyEcsm2Verify requests. * * @description * This is the prototype for the CpaCyEcsm2VerifyCbFunc callback function. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS and CPA_STATUS_FAIL. * @param[in] pOpData Operation data pointer supplied in request. * @param[in] verifyStatus The verification status. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyEcsm2Verify() * *****************************************************************************/ typedef void (*CpaCyEcsm2VerifyCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus); /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * Perform SM2 Point Multiplication. * * @description * This function performs SM2 Point Multiplication, multiply * a point (P) by k (scalar) ([k]P). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pMultiplyStatus Multiply status * CPA_TRUE == pOutputData is valid * CPA_FALSE == pOutputData is invalid * @param[out] pXk x coordinate of the resulting point * multiplication * @param[out] pYk y coordinate of the resulting point * multiplication * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyEcsm2PointMultiplyCbFunc is generated in response to this function * call. For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2PointMultiplyOpData, * CpaCyEcPointMultiplyCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2PointMultiply(const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2PointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk); /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * Perform SM2 Generator Multiplication. * * @description * This function performs SM2 Generator Multiplication, multiply the * generator point (G) by k (scalar) ([k]G). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pMultiplyStatus Multiply status * CPA_TRUE == pOutputData is valid * CPA_FALSE == pOutputData is invalid * @param[out] pXk x coordinate of the resulting point * multiplication * @param[out] pYk y coordinate of the resulting point * multiplication * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyEcPointMultiplyCbFunc is generated in response to this function * call. For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2GeneratorMultiplyOpData, * CpaCyEcPointMultiplyCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2GeneratorMultiply( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2GeneratorMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk); /** ***************************************************************************** * @file cpa_cy_ec.h * @ingroup cpaCyEcsm2 * Perform SM2 Point Verify. * * @description * This function performs SM2 Point Verify, to check if the input point * on the curve or not. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pVerifyStatus Verification status * CPA_TRUE == verify pass * CPA_FALSE == verify fail * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyEcsm2VerifyCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2PointVerifyOpData, * CpaCyEcPointVerifyCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2PointVerify(const CpaInstanceHandle instanceHandle, const CpaCyEcPointVerifyCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2PointVerifyOpData *pOpData, CpaBoolean *pVerifyStatus); /** ***************************************************************************** * @file cpa_cy_ec.h * @ingroup cpaCyEcsm2 * Perform SM2 Signature (Step A4 to A7). * * @description * This function implements step A4 to A7 (in Section 5.2 in "Generation * of Signature" Part 1). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pSignStatus Signature status * CPA_TRUE = pOutputData is valid * CPA_FALSE = pOutputData is invalid * @param[out] pR R output of the resulting signature operation * @param[out] pS S output of the resulting signature operation * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyEcsm2SignCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2SignOpData, * CpaCyEcsm2SignCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2Sign(const CpaInstanceHandle instanceHandle, const CpaCyEcsm2SignCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2SignOpData *pOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** ***************************************************************************** * @file cpa_cy_ec.h * @ingroup cpaCyEcsm2 * Perform SM2 Signature Verify (Step B5 to B7). * * @description * This function implements step B5 to B7 (in Section 5.3 in "Verification * of Signature" Part 1). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pVerifyStatus Status of the signature verification * CPA_TRUE == verify pass * CPA_FALSE == verify fail * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyEcsm2VerifyCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2VerifyOpData, * CpaCyEcsm2VerifyCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2Verify(const CpaInstanceHandle instanceHandle, const CpaCyEcsm2VerifyCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2VerifyOpData *pOpData, CpaBoolean *pVerifyStatus); /** ***************************************************************************** * @file cpa_cy_ec.h * @ingroup cpaCyEcsm2 * Perform SM2 Encryption (Step A2 to A4). * * @description * This function implements step A2 to A4 (in Section 7.2 in * "Algorithm for Encryption and the Flow Chart" Part 1). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pOutputData Ecrypted message * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyGenFlatBufCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2EncryptOpData, * CpaCyEcsm2EncryptOutputData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2Encrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2EncryptOpData *pOpData, CpaCyEcsm2EncryptOutputData *pOutputData); /** ***************************************************************************** * @file cpa_cy_ec.h * @ingroup cpaCyEcsm2 * Perform SM2 Decryption (Step B1 to B3). * * @description * This function implements step B1 to B3 (in Section 7.3 in "Algorithm * for Decryption and the Flow Chart" Part 1). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pOutputData Decrypted message * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyGenFlatBufCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2DecryptOpData, * CpaCyEcsm2DecryptOutputData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2Decrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2DecryptOpData *pOpData, CpaCyEcsm2DecryptOutputData *pOutputData); /** ***************************************************************************** * @file cpa_cy_ec.h * @ingroup cpaCyEcsm2 * Perform SM2 Key Exchange Phase 1 (Step A2/B2). * * @description * This function implements step A2 (User A) or B2 (User B) * (in Section 6.2 in "Key Exchange Protocol and the Flow Chart" Part 1). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pOutputData Output of key exchange phase 1 ([r]G) * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyGenFlatBufCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2KeyExPhase1OpData, * CpaCyEcsm2KeyExOutputData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2KeyExPhase1(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2KeyExPhase1OpData *pOpData, CpaCyEcsm2KeyExOutputData *pOutputData); /** ***************************************************************************** * @file cpa_cy_ec.h * @ingroup cpaCyEcsm2 * Perform SM2 Key Exchange Phase 2 (Step A4 to A7, B3 to B6). * * @description * This function implements steps A4 to A7(User A) or B3 to B6(User B) * (in Section 6.2 in "Key Exchange Protocol and the Flow Chart" Part 1). * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pOutputData Output of key exchange phase2. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyGenFlatBufCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyEcsm2KeyExPhase2OpData, * CpaCyEcsm2KeyExOutputData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyEcsm2KeyExPhase2(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pCb, void *pCallbackTag, const CpaCyEcsm2KeyExPhase2OpData *pOpData, CpaCyEcsm2KeyExOutputData *pOutputData); /** ***************************************************************************** * @file cpa_cy_ecsm2.h * @ingroup cpaCyEcsm2 * Query statistics for a specific ECSM2 instance. * * @description * This function will query a specific instance of the ECSM2 implementation * for statistics. The user MUST allocate the CpaCyEcsm2Stats64 structure * and pass the reference to that structure into this function call. This * function writes the statistic results into the passed in * CpaCyEcsm2Stats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pEcsm2Stats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyEcsm2Stats64 *****************************************************************************/ CpaStatus cpaCyEcsm2QueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyEcsm2Stats64 *pEcsm2Stats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /*CPA_CY_ECSM2_H_*/ qatlib-25.08.0/quickassist/include/lac/cpa_cy_im.h000066400000000000000000000333071503624047500217770ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_im.h * * @defgroup cpaCyInstMaint Cryptographic Instance Management API * * @ingroup cpaCy * * @description * These functions specify the Instance Management API for available * Cryptographic Instances. It is expected that these functions will only * be called via a single system maintenance entity, rather than individual * clients. * *****************************************************************************/ #ifndef CPA_CY_IM_H_ #define CPA_CY_IM_H_ #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyInstMaint * Cryptographic Component Initialization and Start function. * * @description * This function will initialize and start the Cryptographic component. * It MUST be called before any other crypto function is called. This * function SHOULD be called only once (either for the very first time, * or after an cpaCyStopInstance call which succeeded) per instance. * Subsequent calls will have no effect. * * @context * This function may sleep, and MUST NOT be called in interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * @param[out] instanceHandle Handle to an instance of this API to be * initialized. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. Suggested course of action * is to shutdown and restart. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None. * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * * @see * cpaCyStopInstance() * *****************************************************************************/ CpaStatus cpaCyStartInstance(CpaInstanceHandle instanceHandle); /** ***************************************************************************** * @ingroup cpaCyInstMaint * Cryptographic Component Stop function. * * @description * This function will stop the Cryptographic component and free * all system resources associated with it. The client MUST ensure that * all outstanding operations have completed before calling this function. * The recommended approach to ensure this is to deregister all session or * callback handles before calling this function. If outstanding * operations still exist when this function is invoked, the callback * function for each of those operations will NOT be invoked and the * shutdown will continue. If the component is to be restarted, then a * call to cpaCyStartInstance is required. * * @context * This function may sleep, and so MUST NOT be called in interrupt * context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * @param[in] instanceHandle Handle to an instance of this API to be * shutdown. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. Suggested course of action * is to ensure requests are not still being * submitted and that all sessions are * deregistered. If this does not help, then * forcefully remove the component from the * system. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance. * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * * @see * cpaCyStartInstance() * *****************************************************************************/ CpaStatus cpaCyStopInstance(CpaInstanceHandle instanceHandle); /** ***************************************************************************** * @ingroup cpaCyInstMaint * Cryptographic Capabilities Info * * @description * This structure contains the capabilities that vary across API * implementations. This structure is used in conjunction with * @ref cpaCyQueryCapabilities() to determine the capabilities supported * by a particular API implementation. * * The client MUST allocate memory for this structure and any members * that require memory. When the structure is passed into the function * ownership of the memory passes to the function. Ownership of the * memory returns to the client when the function returns. *****************************************************************************/ typedef struct _CpaCyCapabilitiesInfo { CpaBoolean symSupported; /**< CPA_TRUE if instance supports the symmetric cryptography API. * See @ref cpaCySym. */ CpaBoolean symDpSupported; /**< CPA_TRUE if instance supports the symmetric cryptography * data plane API. * See @ref cpaCySymDp. */ CpaBoolean dhSupported; /**< CPA_TRUE if instance supports the Diffie Hellman API. * See @ref cpaCyDh. */ CpaBoolean dsaSupported; /**< CPA_TRUE if instance supports the DSA API. * See @ref cpaCyDsa. */ CpaBoolean rsaSupported; /**< CPA_TRUE if instance supports the RSA API. * See @ref cpaCyRsa. */ CpaBoolean ecSupported; /**< CPA_TRUE if instance supports the Elliptic Curve API. * See @ref cpaCyEc. */ CpaBoolean ecdhSupported; /**< CPA_TRUE if instance supports the Elliptic Curve Diffie Hellman API. * See @ref cpaCyEcdh. */ CpaBoolean ecdsaSupported; /**< CPA_TRUE if instance supports the Elliptic Curve DSA API. * See @ref cpaCyEcdsa. */ CpaBoolean keySupported; /**< CPA_TRUE if instance supports the Key Generation API. * See @ref cpaCyKeyGen. */ CpaBoolean lnSupported; /**< CPA_TRUE if instance supports the Large Number API. * See @ref cpaCyLn. */ CpaBoolean primeSupported; /**< CPA_TRUE if instance supports the prime number testing API. * See @ref cpaCyPrime. */ CpaBoolean drbgSupported; /**< CPA_TRUE if instance supports the DRBG API. * See @ref cpaCyDrbg. */ CpaBoolean nrbgSupported; /**< CPA_TRUE if instance supports the NRBG API. * See @ref cpaCyNrbg. */ CpaBoolean randSupported; /**< CPA_TRUE if instance supports the random bit/number generation API. * See @ref cpaCyRand. */ CpaBoolean kptSupported; /**< CPA_TRUE if instance supports the Intel(R) KPT Cryptographic API. * See @ref cpaCyKpt. */ CpaBoolean hkdfSupported; /**< CPA_TRUE if instance supports the HKDF components of the KeyGen API. * See @ref cpaCyKeyGen. */ CpaBoolean extAlgchainSupported; /**< CPA_TRUE if instance supports algorithm chaining for certain * wireless algorithms. Please refer to implementation for details. * See @ref cpaCySym. */ CpaBoolean ecEdMontSupported; /**< CPA_TRUE if instance supports the Edwards and Montgomery elliptic * curves of the EC API. * See @ref cpaCyEc */ CpaBoolean ecSm2Supported; /**< CPA_TRUE if instance supports the EcSM2 API. * See @ref cpaCyEcsm2. */ } CpaCyCapabilitiesInfo; /** ***************************************************************************** * @ingroup cpaCyInstMaint * Returns capabilities of a Cryptographic API instance * * @description * This function is used to query the instance capabilities. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[out] pCapInfo Pointer to capabilities info structure. * All fields in the structure * are populated by the API instance. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The instance has been initialized via the @ref cpaCyStartInstance * function. * @post * None *****************************************************************************/ CpaStatus cpaCyQueryCapabilities(const CpaInstanceHandle instanceHandle, CpaCyCapabilitiesInfo *pCapInfo); /** ***************************************************************************** * @ingroup cpaCyInstMaint * Sets the address translation function * * @description * This function is used to set the virtual to physical address * translation routine for the instance. The specified routine * is used by the instance to perform any required translation of * a virtual address to a physical address. If the application * does not invoke this function, then the instance will use its * default method, such as virt2phys, for address translation. * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[in] virtual2Physical Routine that performs virtual to * physical address translation. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus cpaCySetAddressTranslation(const CpaInstanceHandle instanceHandle, CpaVirtualToPhysical virtual2Physical); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /*CPA_CY_IM_H_*/ qatlib-25.08.0/quickassist/include/lac/cpa_cy_key.h000066400000000000000000001535461503624047500221720ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_key.h * * @defgroup cpaCyKeyGen Cryptographic Key and Mask Generation API * * @ingroup cpaCy * * @description * These functions specify the API for key and mask generation * operations. * *****************************************************************************/ #ifndef CPA_CY_KEY_H #define CPA_CY_KEY_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" #include "cpa_cy_sym.h" /* needed for hash algorithm, for MGF */ /** ***************************************************************************** * @ingroup cpaCyKeyGen * SSL or TLS key generation random number length. * * @description * Defines the permitted SSL or TLS random number length in bytes that * may be used with the functions @ref cpaCyKeyGenSsl and @ref * cpaCyKeyGenTls. This is the length of the client or server random * number values. *****************************************************************************/ #define CPA_CY_KEY_GEN_SSL_TLS_RANDOM_LEN_IN_BYTES (32) /** ***************************************************************************** * @ingroup cpaCyKeyGen * SSL Operation Types * @description * Enumeration of the different SSL operations that can be specified in * the struct @ref CpaCyKeyGenSslOpData. It identifies the label. *****************************************************************************/ typedef enum _CpaCyKeySslOp { CPA_CY_KEY_SSL_OP_MASTER_SECRET_DERIVE = 1, /**< Derive the master secret */ CPA_CY_KEY_SSL_OP_KEY_MATERIAL_DERIVE, /**< Derive the key material */ CPA_CY_KEY_SSL_OP_USER_DEFINED /**< User Defined Operation for custom labels*/ } CpaCyKeySslOp; /** ***************************************************************************** * @ingroup cpaCyKeyGen * SSL data for key generation functions * @description * This structure contains data for use in key generation operations for * SSL. For specific SSL key generation operations, the structure fields * MUST be set as follows: * * @par SSL Master-Secret Derivation: *
sslOp = CPA_CY_KEY_SSL_OP_MASTER_SECRET_DERIVE *
secret = pre-master secret key *
seed = client_random + server_random *
userLabel = NULL * * @par SSL Key-Material Derivation: *
sslOp = CPA_CY_KEY_SSL_OP_KEY_MATERIAL_DERIVE *
secret = master secret key *
seed = server_random + client_random *
userLabel = NULL * *
Note that the client/server random order is reversed from that * used for master-secret derivation. * * @note Each of the client and server random numbers need to be of * length CPA_CY_KEY_GEN_SSL_TLS_RANDOM_LEN_IN_BYTES. * * @note In each of the above descriptions, + indicates concatenation. * * @note The label used is predetermined by the SSL operation in line * with the SSL 3.0 specification, and can be overridden by using * a user defined operation CPA_CY_KEY_SSL_OP_USER_DEFINED and * associated userLabel. * ****************************************************************************/ typedef struct _CpaCyKeyGenSslOpData { CpaCyKeySslOp sslOp; /**< Indicate the SSL operation to be performed */ CpaFlatBuffer secret; /**< Flat buffer containing a pointer to either the master or pre-master * secret key. The length field indicates the length of the secret key in * bytes. Implementation-specific limits may apply to this length. */ CpaFlatBuffer seed; /**< Flat buffer containing a pointer to the seed data. * Implementation-specific limits may apply to this length. */ CpaFlatBuffer info; /**< Flat buffer containing a pointer to the info data. * Implementation-specific limits may apply to this length. */ Cpa32U generatedKeyLenInBytes; /**< The requested length of the generated key in bytes. * Implementation-specific limits may apply to this length. */ CpaFlatBuffer userLabel; /**< Optional flat buffer containing a pointer to a user defined label. * The length field indicates the length of the label in bytes. To use this * field, the sslOp must be CPA_CY_KEY_SSL_OP_USER_DEFINED, * or otherwise it is ignored and can be set to NULL. * Implementation-specific limits may apply to this length. */ } CpaCyKeyGenSslOpData; /** ***************************************************************************** * @ingroup cpaCyKeyGen * TLS Operation Types * @description * Enumeration of the different TLS operations that can be specified in * the CpaCyKeyGenTlsOpData. It identifies the label. * * The functions @ref cpaCyKeyGenTls and @ref cpaCyKeyGenTls2 * accelerate the TLS PRF, which is defined as part of RFC2246 (TLS * v1.0), RFC4346 (TLS v1.1), and RFC5246 (TLS v1.2). * One of the inputs to each of these functions is a label. * This enumerated type defines values that correspond to some of * the required labels. * However, for some of the operations/labels required by these RFCs, * no values are specified. * * In such cases, a user-defined value must be provided. The client * should use the enum value @ref CPA_CY_KEY_TLS_OP_USER_DEFINED, and * pass the label using the userLabel field of the @ref * CpaCyKeyGenTlsOpData data structure. * *****************************************************************************/ typedef enum _CpaCyKeyTlsOp { CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE = 1, /**< Derive the master secret using the TLS PRF. * Corresponds to RFC2246/5246 section 8.1, operation "Computing the * master secret", label "master secret". */ CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE, /**< Derive the key material using the TLS PRF. * Corresponds to RFC2246/5246 section 6.3, operation "Derive the key * material", label "key expansion". */ CPA_CY_KEY_TLS_OP_CLIENT_FINISHED_DERIVE, /**< Derive the client finished tag using the TLS PRF. * Corresponds to RFC2246/5246 section 7.4.9, operation "Client finished", * label "client finished". */ CPA_CY_KEY_TLS_OP_SERVER_FINISHED_DERIVE, /**< Derive the server finished tag using the TLS PRF. * Corresponds to RFC2246/5246 section 7.4.9, operation "Server finished", * label "server finished". */ CPA_CY_KEY_TLS_OP_USER_DEFINED /**< User Defined Operation for custom labels. */ } CpaCyKeyTlsOp; /** ***************************************************************************** * @file cpa_cy_key.h * @ingroup cpaCyKeyGen * TLS Operation Types * @description * Enumeration of the different TLS operations that can be specified in * the CpaCyKeyGenHKDFOpData. * * The function @ref cpaCyKeyGenTls3 * accelerates the TLS HKDF, which is defined as part of RFC5869 (HKDF) * and RFC8446 (TLS v1.3). * * This enumerated type defines the support HKDF operations for * extraction and expansion of keying material. * *****************************************************************************/ typedef enum _CpaCyKeyHKDFOp { CPA_CY_HKDF_KEY_EXTRACT = 12, /**< HKDF Extract operation * Corresponds to RFC5869 section 2.2, step 1 "Extract" */ CPA_CY_HKDF_KEY_EXPAND, /**< HKDF Expand operation * Corresponds to RFC5869 section 2.3, step 2 "Expand" */ CPA_CY_HKDF_KEY_EXTRACT_EXPAND, /**< HKDF operation * This performs HKDF_EXTRACT and HKDF_EXPAND in a single * API invocation. */ CPA_CY_HKDF_KEY_EXPAND_LABEL, /**< HKDF Expand label operation for TLS 1.3 * Corresponds to RFC8446 section 7.1 Key Schedule definition for * HKDF-Expand-Label, which refers to HKDF-Expand defined in RFC5869. */ CPA_CY_HKDF_KEY_EXTRACT_EXPAND_LABEL /**< HKDF Extract plus Expand label operation for TLS 1.3 * Corresponds to RFC5869 section 2.2, step 1 "Extract" followed by * RFC8446 section 7.1 Key Schedule definition for * HKDF-Expand-Label, which refers to HKDF-Expand defined in RFC5869. */ } CpaCyKeyHKDFOp; /** ***************************************************************************** * @file cpa_cy_key.h * @ingroup cpaCyKeyGen * TLS Operation Types * @description * Enumeration of the different cipher suites that may be used in a TLS * v1.3 operation. This value is used to infer the sizes of the key * and iv sublabel. * * The function @ref cpaCyKeyGenTls3 * accelerates the TLS HKDF, which is defined as part of RFC5869 (HKDF) * and RFC8446 (TLS v1.3). * * This enumerated type defines the supported cipher suites in the * TLS operation that require HKDF key operations. * *****************************************************************************/ typedef enum _CpaCyKeyHKDFCipherSuite { CPA_CY_HKDF_TLS_AES_128_GCM_SHA256 = 1, CPA_CY_HKDF_TLS_AES_256_GCM_SHA384, CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256, CPA_CY_HKDF_TLS_AES_128_CCM_SHA256, CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256 } CpaCyKeyHKDFCipherSuite; /** ***************************************************************************** * @file cpa_cy_key.h * @ingroup cpaCyKeyGen * TLS Operation Types * @description * Bitwise constants for HKDF sublabels * * These definitions provide bit settings for sublabels for * HKDF-ExpandLabel operations. * *
key sublabel to generate "key" keying material *
iv sublabel to generate "iv" keying material *
resumption sublabel to generate "resumption" keying material *
finished sublabel to generate "finished" keying material * *****************************************************************************/ #define CPA_CY_HKDF_SUBLABEL_KEY ((Cpa16U)0x0001) /**< Bit for creation of key material for 'key' sublabel */ #define CPA_CY_HKDF_SUBLABEL_IV ((Cpa16U)0x0002) /**< Bit for creation of key material for 'iv' sublabel */ #define CPA_CY_HKDF_SUBLABEL_RESUMPTION ((Cpa16U)0x0004) /**< Bit for creation of key material for 'resumption' sublabel */ #define CPA_CY_HKDF_SUBLABEL_FINISHED ((Cpa16U)0x0008) /**< Bit for creation of key material for 'finished' sublabel */ #define CPA_CY_HKDF_KEY_MAX_SECRET_SZ ((Cpa8U)80) /** space in bytes PSK or (EC)DH */ #define CPA_CY_HKDF_KEY_MAX_HMAC_SZ ((Cpa8U)48) /** space in bytes of CPA_CY_SYM_HASH_SHA384 result */ #define CPA_CY_HKDF_KEY_MAX_INFO_SZ ((Cpa8U)80) /** space in bytes of largest info needed for TLS 1.3, * rounded up to multiple of 8 */ #define CPA_CY_HKDF_KEY_MAX_LABEL_SZ ((Cpa8U)78) /** space in bytes of largest label for TLS 1.3 */ #define CPA_CY_HKDF_KEY_MAX_LABEL_COUNT ((Cpa8U)4) /** Maximum number of labels in op structure */ /** ***************************************************************************** * @file cpa_cy_key.h * @ingroup cpaCyKeyGen * TLS data for key generation functions * @description * This structure contains data for describing label for the * HKDF Extract Label function * * @par Extract Label Function *
labelLen = length of the label field *
contextLen = length of the context field *
sublabelFlag = Mask of sub labels required for this label. *
label = label as defined in RFC8446 *
context = context as defined in RFC8446 * ****************************************************************************/ typedef struct _CpaCyKeyGenHKDFExpandLabel { Cpa8U label[CPA_CY_HKDF_KEY_MAX_LABEL_SZ]; /**< HKDFLabel field as defined in RFC8446 sec 7.1. */ Cpa8U labelLen; /**< The length, in bytes of the label */ Cpa8U sublabelFlag; /**< mask of sublabels to be generated. * This flag is composed of zero or more of: * CPA_CY_HKDF_SUBLABEL_KEY * CPA_CY_HKDF_SUBLABEL_IV * CPA_CY_HKDF_SUBLABEL_RESUMPTION * CPA_CY_HKDF_SUBLABEL_FINISHED */ } CpaCyKeyGenHKDFExpandLabel; /** ***************************************************************************** * @ingroup cpaCyKeyGen * TLS data for key generation functions * @description * This structure contains data for all HKDF operations: *
HKDF Extract *
HKDF Expand *
HKDF Expand Label *
HKDF Extract and Expand *
HKDF Extract and Expand Label * * @par HKDF Map Structure Elements *
secret - IKM value for extract operations or PRK for expand * or expand operations. *
seed - contains the salt for extract * operations *
info - contains the info data for extract operations *
labels - See notes above * ****************************************************************************/ typedef struct _CpaCyKeyGenHKDFOpData { CpaCyKeyHKDFOp hkdfKeyOp; /**< Keying operation to be performed. */ Cpa8U secretLen; /**< Length of secret field */ Cpa16U seedLen; /**< Length of seed field */ Cpa16U infoLen; /**< Length of info field */ Cpa16U numLabels; /**< Number of filled CpaCyKeyGenHKDFExpandLabel elements */ Cpa8U secret[CPA_CY_HKDF_KEY_MAX_SECRET_SZ]; /**< Input Key Material or PRK */ Cpa8U seed[CPA_CY_HKDF_KEY_MAX_HMAC_SZ]; /**< Input salt */ Cpa8U info[CPA_CY_HKDF_KEY_MAX_INFO_SZ]; /**< info field */ CpaCyKeyGenHKDFExpandLabel label[CPA_CY_HKDF_KEY_MAX_LABEL_COUNT]; /**< array of Expand Label structures */ } CpaCyKeyGenHKDFOpData; /** ***************************************************************************** * @ingroup cpaCyKeyGen * TLS data for key generation functions * @description * This structure contains data for use in key generation operations for * TLS. For specific TLS key generation operations, the structure fields * MUST be set as follows: * * @par TLS Master-Secret Derivation: *
tlsOp = CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE *
secret = pre-master secret key *
seed = client_random + server_random *
userLabel = NULL * * @par TLS Key-Material Derivation: *
tlsOp = CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE *
secret = master secret key *
seed = server_random + client_random *
userLabel = NULL * *
Note that the client/server random order is reversed from * that used for Master-Secret Derivation. * * @par TLS Client finished/Server finished tag Derivation: *
tlsOp = CPA_CY_KEY_TLS_OP_CLIENT_FINISHED_DERIVE (client) *
or CPA_CY_KEY_TLS_OP_SERVER_FINISHED_DERIVE (server) *
secret = master secret key *
seed = MD5(handshake_messages) + SHA-1(handshake_messages) *
userLabel = NULL * * @note Each of the client and server random seeds need to be of * length CPA_CY_KEY_GEN_SSL_TLS_RANDOM_LEN_IN_BYTES. * @note In each of the above descriptions, + indicates concatenation. * @note The label used is predetermined by the TLS operation in line * with the TLS specifications, and can be overridden by using * a user defined operation CPA_CY_KEY_TLS_OP_USER_DEFINED * and associated userLabel. * ****************************************************************************/ typedef struct _CpaCyKeyGenTlsOpData { CpaCyKeyTlsOp tlsOp; /**< TLS operation to be performed */ CpaFlatBuffer secret; /**< Flat buffer containing a pointer to either the master or pre-master * secret key. The length field indicates the length of the secret in * bytes. */ CpaFlatBuffer seed; /**< Flat buffer containing a pointer to the seed data. * Implementation-specific limits may apply to this length. */ Cpa32U generatedKeyLenInBytes; /**< The requested length of the generated key in bytes. * Implementation-specific limits may apply to this length. */ CpaFlatBuffer userLabel; /**< Optional flat buffer containing a pointer to a user defined label. * The length field indicates the length of the label in bytes. To use this * field, the tlsOp must be CPA_CY_KEY_TLS_OP_USER_DEFINED. * Implementation-specific limits may apply to this length. */ } CpaCyKeyGenTlsOpData; /** ***************************************************************************** * @ingroup cpaCyKeyGen * Key Generation Mask Generation Function (MGF) Data * @description * This structure contains data relating to Mask Generation Function * key generation operations. * * @note The default hash algorithm used by the MGF is SHA-1. If a * different hash algorithm is preferred, then see the extended * version of this structure, @ref CpaCyKeyGenMgfOpDataExt. * @see * cpaCyKeyGenMgf ****************************************************************************/ typedef struct _CpaCyKeyGenMgfOpData { CpaFlatBuffer seedBuffer; /**< Caller MUST allocate a buffer and populate with the input seed * data. For optimal performance the start of the seed SHOULD be allocated * on an 8-byte boundary. The length field represents the seed length in * bytes. Implementation-specific limits may apply to this length. */ Cpa32U maskLenInBytes; /**< The requested length of the generated mask in bytes. * Implementation-specific limits may apply to this length. */ } CpaCyKeyGenMgfOpData; /** ***************************************************************************** * @ingroup cpaCyKeyGen * Extension to the original Key Generation Mask Generation Function * (MGF) Data * @description * This structure is an extension to the original MGF data structure. * The extension allows the hash function to be specified. * @note * This structure is separate from the base @ref CpaCyKeyGenMgfOpData * structure in order to retain backwards compatibility with the * original version of the API. * @see * cpaCyKeyGenMgfExt ****************************************************************************/ typedef struct _CpaCyKeyGenMgfOpDataExt { CpaCyKeyGenMgfOpData baseOpData; /**< "Base" operational data for MGF generation */ CpaCySymHashAlgorithm hashAlgorithm; /**< Specifies the hash algorithm to be used by the Mask Generation * Function */ } CpaCyKeyGenMgfOpDataExt; /** ***************************************************************************** * @ingroup cpaCyKeyGen * Key Generation Statistics. * @deprecated * As of v1.3 of the Crypto API, this structure has been deprecated, * replaced by @ref CpaCyKeyGenStats64. * @description * This structure contains statistics on the key and mask generation * operations. Statistics are set to zero when the component is * initialized, and are collected per instance. * ****************************************************************************/ typedef struct _CpaCyKeyGenStats { Cpa32U numSslKeyGenRequests; /**< Total number of successful SSL key generation requests. */ Cpa32U numSslKeyGenRequestErrors; /**< Total number of SSL key generation requests that had an error and * could not be processed. */ Cpa32U numSslKeyGenCompleted; /**< Total number of SSL key generation operations that completed * successfully. */ Cpa32U numSslKeyGenCompletedErrors; /**< Total number of SSL key generation operations that could not be * completed successfully due to errors. */ Cpa32U numTlsKeyGenRequests; /**< Total number of successful TLS key generation requests. */ Cpa32U numTlsKeyGenRequestErrors; /**< Total number of TLS key generation requests that had an error and * could not be processed. */ Cpa32U numTlsKeyGenCompleted; /**< Total number of TLS key generation operations that completed * successfully. */ Cpa32U numTlsKeyGenCompletedErrors; /**< Total number of TLS key generation operations that could not be * completed successfully due to errors. */ Cpa32U numMgfKeyGenRequests; /**< Total number of successful MGF key generation requests (including * "extended" MGF requests). */ Cpa32U numMgfKeyGenRequestErrors; /**< Total number of MGF key generation requests that had an error and * could not be processed. */ Cpa32U numMgfKeyGenCompleted; /**< Total number of MGF key generation operations that completed * successfully. */ Cpa32U numMgfKeyGenCompletedErrors; /**< Total number of MGF key generation operations that could not be * completed successfully due to errors. */ } CpaCyKeyGenStats CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCyKeyGen * Key Generation Statistics (64-bit version). * @description * This structure contains the 64-bit version of the statistics * on the key and mask generation operations. * Statistics are set to zero when the component is * initialized, and are collected per instance. * ****************************************************************************/ typedef struct _CpaCyKeyGenStats64 { Cpa64U numSslKeyGenRequests; /**< Total number of successful SSL key generation requests. */ Cpa64U numSslKeyGenRequestErrors; /**< Total number of SSL key generation requests that had an error and * could not be processed. */ Cpa64U numSslKeyGenCompleted; /**< Total number of SSL key generation operations that completed * successfully. */ Cpa64U numSslKeyGenCompletedErrors; /**< Total number of SSL key generation operations that could not be * completed successfully due to errors. */ Cpa64U numTlsKeyGenRequests; /**< Total number of successful TLS key generation requests. */ Cpa64U numTlsKeyGenRequestErrors; /**< Total number of TLS key generation requests that had an error and * could not be processed. */ Cpa64U numTlsKeyGenCompleted; /**< Total number of TLS key generation operations that completed * successfully. */ Cpa64U numTlsKeyGenCompletedErrors; /**< Total number of TLS key generation operations that could not be * completed successfully due to errors. */ Cpa64U numMgfKeyGenRequests; /**< Total number of successful MGF key generation requests (including * "extended" MGF requests). */ Cpa64U numMgfKeyGenRequestErrors; /**< Total number of MGF key generation requests that had an error and * could not be processed. */ Cpa64U numMgfKeyGenCompleted; /**< Total number of MGF key generation operations that completed * successfully. */ Cpa64U numMgfKeyGenCompletedErrors; /**< Total number of MGF key generation operations that could not be * completed successfully due to errors. */ } CpaCyKeyGenStats64; /** ***************************************************************************** * @ingroup cpaCyKeyGen * SSL Key Generation Function. * @description * This function is used for SSL key generation. It implements the key * generation function defined in section 6.2.2 of the SSL 3.0 * specification as described in * http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt. * * The input seed is taken as a flat buffer and the generated key is * returned to caller in a flat destination data buffer. * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenSslOpData Structure containing all the data * needed to perform the SSL key * generation operation. The client code * allocates the memory for this * structure. This component takes * ownership of the memory until it is * returned in the callback. * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @see * CpaCyKeyGenSslOpData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyKeyGenSsl(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenSslOpData *pKeyGenSslOpData, CpaFlatBuffer *pGeneratedKeyBuffer); /** ***************************************************************************** * @ingroup cpaCyKeyGen * TLS Key Generation Function. * @description * This function is used for TLS key generation. It implements the * TLS PRF (Pseudo Random Function) as defined by RFC2246 (TLS v1.0) * and RFC4346 (TLS v1.1). * * The input seed is taken as a flat buffer and the generated key is * returned to caller in a flat destination data buffer. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenTlsOpData Structure containing all the data * needed to perform the TLS key * generation operation. The client code * allocates the memory for this * structure. This component takes * ownership of the memory until it is * returned in the callback. * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @see * CpaCyKeyGenTlsOpData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyKeyGenTls(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, CpaFlatBuffer *pGeneratedKeyBuffer); /** ***************************************************************************** * @ingroup cpaCyKeyGen * TLS Key Generation Function version 2. * @description * This function is used for TLS key generation. It implements the * TLS PRF (Pseudo Random Function) as defined by RFC5246 (TLS v1.2). * * The input seed is taken as a flat buffer and the generated key is * returned to caller in a flat destination data buffer. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenTlsOpData Structure containing all the data * needed to perform the TLS key * generation operation. The client code * allocates the memory for this * structure. This component takes * ownership of the memory until it is * returned in the callback. * @param[in] hashAlgorithm Specifies the hash algorithm to use. * According to RFC5246, this should be * "SHA-256 or a stronger standard hash * function." * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @see * CpaCyKeyGenTlsOpData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyKeyGenTls2(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, CpaCySymHashAlgorithm hashAlgorithm, CpaFlatBuffer *pGeneratedKeyBuffer); /** ***************************************************************************** * @ingroup cpaCyKeyGen * TLS Key Generation Function version 3. * @description * This function is used for TLS key generation. It implements the * TLS HKDF (HMAC Key Derivation Function) as defined by * RFC5689 (HKDF) and RFC8446 (TLS 1.3). * * The input seed is taken as a flat buffer and the generated key is * returned to caller in a flat destination data buffer. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenTlsOpData Structure containing all the data * needed to perform the TLS key * generation operation. The client code * allocates the memory for this * structure. This component takes * ownership of the memory until it is * returned in the callback. The memory * must be pinned and contiguous, suitable * for DMA operations. * @param[in] hashAlgorithm Specifies the hash algorithm to use. * According to RFC5246, this should be * "SHA-256 or a stronger standard hash * function." * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @see * CpaCyGenFlatBufCbFunc * CpaCyKeyGenHKDFOpData * *****************************************************************************/ CpaStatus cpaCyKeyGenTls3(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, CpaCyKeyHKDFCipherSuite cipherSuite, CpaFlatBuffer *pGeneratedKeyBuffer); /** ***************************************************************************** * @ingroup cpaCyKeyGen * Mask Generation Function. * @description * This function implements the mask generation function MGF1 as * defined by PKCS#1 v2.1, and RFC3447. The input seed is taken * as a flat buffer and the generated mask is returned to caller in a * flat destination data buffer. * * @note The default hash algorithm used by the MGF is SHA-1. If a * different hash algorithm is preferred, then see the "extended" * version of this function, @ref cpaCyKeyGenMgfExt. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the * callback. * @param[in] pKeyGenMgfOpData Structure containing all the data needed * to perform the MGF key generation * operation. The client code allocates the * memory for this structure. This * component takes ownership of the memory * until it is returned in the callback. * @param[out] pGeneratedMaskBuffer Caller MUST allocate a sufficient buffer * to hold the generated mask. The data * pointer SHOULD be aligned on an 8-byte * boundary. The length field passed in * represents the size of the buffer in * bytes. The value that is returned is the * size of the generated mask in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @see * CpaCyKeyGenMgfOpData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyKeyGenMgf(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, CpaFlatBuffer *pGeneratedMaskBuffer); /** ***************************************************************************** * @ingroup cpaCyKeyGen * Extended Mask Generation Function. * @description * This function is used for mask generation. It differs from the "base" * version of the function (@ref cpaCyKeyGenMgf) in that it allows * the hash function used by the Mask Generation Function to be * specified. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the * callback. * @param[in] pKeyGenMgfOpDataExt Structure containing all the data needed * to perform the extended MGF key generation * operation. The client code allocates the * memory for this structure. This * component takes ownership of the memory * until it is returned in the callback. * @param[out] pGeneratedMaskBuffer Caller MUST allocate a sufficient buffer * to hold the generated mask. The data * pointer SHOULD be aligned on an 8-byte * boundary. The length field passed in * represents the size of the buffer in * bytes. The value that is returned is the * size of the generated mask in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * This function is only used to generate a mask keys from seed * material. * @see * CpaCyKeyGenMgfOpData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyKeyGenMgfExt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenMgfOpDataExt *pKeyGenMgfOpDataExt, CpaFlatBuffer *pGeneratedMaskBuffer); /** ***************************************************************************** * @ingroup cpaCyKeyGen * Queries the Key and Mask generation statistics specific to * an instance. * * @deprecated * As of v1.3 of the Crypto API, this function has been deprecated, * replaced by @ref cpaCyKeyGenQueryStats64(). * * @description * This function will query a specific instance for key and mask * generation statistics. The user MUST allocate the CpaCyKeyGenStats * structure and pass the reference to that into this function call. This * function will write the statistic results into the passed in * CpaCyKeyGenStats structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pKeyGenStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * * @see * CpaCyKeyGenStats * *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCyKeyGenQueryStats(const CpaInstanceHandle instanceHandle, struct _CpaCyKeyGenStats *pKeyGenStats); /** ***************************************************************************** * @ingroup cpaCyKeyGen * Queries the Key and Mask generation statistics (64-bit version) * specific to an instance. * * @description * This function will query a specific instance for key and mask * generation statistics. The user MUST allocate the CpaCyKeyGenStats64 * structure and pass the reference to that into this function call. This * function will write the statistic results into the passed in * CpaCyKeyGenStats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pKeyGenStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * * @see * CpaCyKeyGenStats64 *****************************************************************************/ CpaStatus cpaCyKeyGenQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyKeyGenStats64 *pKeyGenStats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_KEY_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_kpt.h000066400000000000000000001111071503624047500221630ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_kpt.h * * @defgroup cpaCyKpt Intel(R) Key Protection Technology (KPT) Cryptographic API * * @ingroup cpaCy * * @description * These functions specify the APIs for Key Protection Technology (KPT) * Cryptographic services. * * @note * These functions implement the KPT Cryptographic API. * This API is experimental and subject to change. * *****************************************************************************/ #ifndef __CPA_CY_KPT_H__ #define __CPA_CY_KPT_H__ #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" #include "cpa_cy_rsa.h" #include "cpa_cy_ecdsa.h" #include "cpa_cy_ec.h" /** ***************************************************************************** * @ingroup cpaCyKpt * KPT wrapping key handle * * @description * Handle to a unique wrapping key in wrapping key table. Application * creates it in KPT key transfer phase and maintains it for KPT Crypto * service. For each KPT Crypto service API invocation, this handle will * be used to get a SWK(Symmetric Wrapping Key) to unwrap * WPK(Wrapped Private Key) before performing the requested crypto * service. * *****************************************************************************/ typedef Cpa64U CpaCyKptHandle; /** ***************************************************************************** * @ingroup cpaCyKpt * Return Status * @description * This enumeration lists all the possible return status after completing * KPT APIs. * *****************************************************************************/ typedef enum CpaCyKptKeyManagementStatus_t { CPA_CY_KPT_SUCCESS = 0, /**< Generic success status for all KPT wrapping key handling functions */ CPA_CY_KPT_LOADKEY_FAIL_QUOTA_EXCEEDED_PER_VFID, /**< SWK count exceeds the configured maximum value per VFID */ CPA_CY_KPT_LOADKEY_FAIL_QUOTA_EXCEEDED_PER_PASID, /**< SWK count exceeds the configured maximum value per PASID */ CPA_CY_KPT_LOADKEY_FAIL_QUOTA_EXCEEDED, /**< SWK count exceeds the configured maximum value when not scoped to * VFID or PASID */ CPA_CY_KPT_SWK_FAIL_NOT_FOUND, /**< Unable to find SWK entry by handle */ CPA_CY_KPT_FAILED, } CpaCyKptKeyManagementStatus; /** ***************************************************************************** * @ingroup cpaCyKpt * PKCS#1 v2.2 RSA-3K signature output length in bytes. * @see CpaCyKptValidationKey * *****************************************************************************/ #define CPA_CY_RSA3K_SIG_SIZE_INBYTES 384 /** ***************************************************************************** * @ingroup cpaCyKpt * KPT device credentials key certificate * @description * This structure defines the key format for use with KPT. * @see * cpaCyKptQueryDeviceCredentials * *****************************************************************************/ typedef struct CpaCyKptValidationKey_t { CpaCyRsaPublicKey publicKey; /**< Key */ Cpa8U signature[CPA_CY_RSA3K_SIG_SIZE_INBYTES]; /**< Signature of key */ } CpaCyKptValidationKey; /** ***************************************************************************** * @ingroup cpaCyKpt * Cipher algorithms used to generate a wrapped private key (WPK) from * the clear private key. * * @description * This enumeration lists supported cipher algorithms and modes. * *****************************************************************************/ typedef enum CpaCyKptWrappingKeyType_t { CPA_CY_KPT_WRAPPING_KEY_TYPE_AES256_GCM = 0 } CpaCyKptWrappingKeyType; /** ***************************************************************************** * @ingroup cpaCyKpt * KPT Loading key format specification. * @description * This structure defines the format of the symmetric wrapping key to be * loaded into KPT. Application sets these parameters through the * cpaCyKptLoadKey calls. * *****************************************************************************/ typedef struct CpaCyKptLoadKey_t { CpaFlatBuffer eSWK; /**< Encrypted SWK */ CpaCyKptWrappingKeyType wrappingAlgorithm; /**< Symmetric wrapping algorithm */ } CpaCyKptLoadKey; /** ***************************************************************************** * @ingroup cpaCyKpt * Max length of initialization vector * @description * Defines the permitted max iv length in bytes that may be used in * private key wrapping/unwrapping.For AEC-GCM, iv length is 12 bytes. * *@see cpaCyKptUnwrapContext * *****************************************************************************/ #define CPA_CY_KPT_MAX_IV_LENGTH (12) /** ***************************************************************************** * @ingroup cpaCyKpt * Max length of Additional Authenticated Data * @description * Defines the permitted max aad length in bytes that may be used in * private key wrapping/unwrapping. * *@see cpaCyKptUnwrapContext * *****************************************************************************/ #define CPA_CY_KPT_MAX_AAD_LENGTH (16) /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * Structure of KPT unwrapping context. * @description * This structure is a parameter of KPT crypto APIs, it contains data * relating to KPT WPK unwrapping, the application needs to fill in this * information. * *****************************************************************************/ typedef struct CpaCyKptUnwrapContext_t { CpaCyKptHandle kptHandle; /**< This is application's unique handle that identifies its * (symmetric) wrapping key*/ Cpa8U iv[CPA_CY_KPT_MAX_IV_LENGTH]; /**< Initialization Vector - which must be a nonce */ Cpa8U additionalAuthData[CPA_CY_KPT_MAX_AAD_LENGTH]; /**< A buffer holding the Additional Authenticated Data.*/ Cpa32U aadLenInBytes; /**< Number of bytes representing the size of AAD within additionalAuthData * buffer. */ } CpaCyKptUnwrapContext; /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * RSA Private Key Structure For Representation 1. * @description * This structure contains the first representation that can be used for * describing the RSA private key, represented by the tuple of the * modulus (N) and the private exponent (D). * The representation is encrypted as follows: * Encrypt - AES-256-GCM (Key, AAD, Input) * "||" - denotes concatenation * Key = SWK * AAD = DER(OID) * IV = nonce * Input = (D || N) * Encrypt (SWK, AAD, IV, (D || N)) * Output (AuthTag, (D || N)') * EncryptedRSAKey = (D || N)' * * privateKey = (EncryptedRSAKey || AuthTag) * * OID's that shall be supported by KPT implementation: * OID DER(OID) * 1.2.840.113549.1.1 06 08 2A 86 48 86 F7 0D 01 01 * * Permitted lengths for N and D are: * - 512 bits (64 bytes), * - 1024 bits (128 bytes), * - 1536 bits (192 bytes), * - 2048 bits (256 bytes), * - 3072 bits (384 bytes), * - 4096 bits (512 bytes), or * - 8192 bits (1024 bytes). * * AuthTag is 128 bits (16 bytes) * * @note It is important that the value D is big enough. It is STRONGLY * recommended that this value is at least half the length of the modulus * N to protect against the Wiener attack. * It is critical a unique nonce is used for each SWK encrypt operation. * *****************************************************************************/ typedef struct CpaCyKptRsaPrivateKeyRep1_t { CpaFlatBuffer privateKey; /**< The EncryptedRSAKey concatenated with AuthTag */ } CpaCyKptRsaPrivateKeyRep1; /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * KPT RSA Private Key Structure For Representation 2. * @description * This structure contains the second representation that can be used for * describing the RSA private key. The quintuple of p, q, dP, dQ, and qInv * (explained below and in the spec) are required for the second * representation. For KPT the parameters are Encrypted * with the associated SWK as follows: * Encrypt - AES-256-GCM (Key, AAD, Input) * "||" - denotes concatenation * Key = SWK * IV = nonce * AAD = DER(OID) * Input = (P || Q || dP || dQ || Qinv || publicExponentE) * Expanded Description: * Encrypt (SWK, AAD, IV, * (P || Q || dP || dQ || Qinv || publicExponentE)) * EncryptedRSAKey = (P || Q || dP || dQ || Qinv || publicExponentE)' * Output (AuthTag, EncryptedRSAKey) * * privateKey = EncryptedRSAKey || AuthTag * * OID's that shall be supported by KPT implementation: * OID DER(OID) * 1.2.840.113549.1.1 06 08 2A 86 48 86 F7 0D 01 01 * * All of the encrypted parameters will be of equal size. The length of * each will be equal to keySize in bytes/2. * For example for a key size of 256 Bytes (2048 bits), the length of * P, Q, dP, dQ, and Qinv are all 128 Bytes, plus the * publicExponentE of 256 Bytes, giving a total size for * EncryptedRSAKey of 896 Bytes. * * AuthTag is 128 bits (16 bytes) * * Permitted Key Sizes are: * - 512 bits (64 bytes), * - 1024 bits (128 bytes), * - 1536 bits (192 bytes), * - 2048 bits (256 bytes), * - 3072 bits (384 bytes), * - 4096 bits (512 bytes), or * - 8192 bits (1024 bytes). * * @note It is critical a unique nonce is used for each SWK encrypt operation. * *****************************************************************************/ typedef struct CpaCyKptRsaPrivateKeyRep2_t { CpaFlatBuffer privateKey; /**< RSA private key representation 2 is built up from the * tuple of p, q, dP, dQ, qInv, publicExponentE and AuthTag. */ } CpaCyKptRsaPrivateKeyRep2; /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * RSA Private Key Structure. * @description * This structure contains the two representations that can be used for * describing the RSA private key. The privateKeyRepType will be used to * identify which representation is to be used. Typically, using the * second representation results in faster decryption operations. * *****************************************************************************/ typedef struct CpaCyKptRsaPrivateKey_t { CpaCyRsaVersion version; /**< Indicates the version of the PKCS #1 specification that is * supported. * Note that this applies to both representations. */ CpaCyRsaPrivateKeyRepType privateKeyRepType; /**< This value is used to identify which of the private key * representation types in this structure is relevant. * When performing key generation operations for Type 2 representations, * memory must also be allocated for the type 1 representations, and values * for both will be returned. */ CpaCyKptRsaPrivateKeyRep1 privateKeyRep1; /**< This is the first representation of the RSA private key as * defined in the PKCS #1 V2.2 specification. */ CpaCyKptRsaPrivateKeyRep2 privateKeyRep2; /**< This is the second representation of the RSA private key as * defined in the PKCS #1 V2.2 specification. */ } CpaCyKptRsaPrivateKey; /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * KPT RSA Decryption Primitive Operation Data * @description * This structure lists the different items that are required in the * cpaCyKptRsaDecrypt function. As the RSA decryption primitive and * signature primitive operations are mathematically identical this * structure may also be used to perform an RSA signature primitive * operation. * When performing an RSA decryption primitive operation, the input data * is the cipher text and the output data is the message text. * When performing an RSA signature primitive operation, the input data * is the message and the output data is the signature. * The client MUST allocate the memory for this structure. When the * structure is passed into the function, ownership of the memory passes * to he function. Ownership of the memory returns to the client when * this structure is returned in the CpaCyGenFlatBufCbFunc * callback function. * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyKptRsaDecrypt function, and * before it has been returned in the callback, undefined behavior will * result. * All values in this structure are required to be in Most Significant Byte * first order, e.g. inputData.pData[0] = MSB. * *****************************************************************************/ typedef struct CpaCyKptRsaDecryptOpData_t { CpaCyKptRsaPrivateKey *pRecipientPrivateKey; /**< Pointer to the recipient's RSA private key. */ CpaFlatBuffer inputData; /**< The input data that the RSA decryption primitive operation is * performed on. The data pointed to is an integer that MUST be in big- * endian order. The value MUST be between 0 and the modulus n - 1. */ } CpaCyKptRsaDecryptOpData; /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * KPT ECDSA Sign R & S Operation Data. * * @description * This structure contains the operation data for the cpaCyKptEcdsaSignRS * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * This key structure is encrypted when passed into cpaCyKptEcdsaSignRS * Encrypt - AES-256-GCM (Key, AAD, Input) * "||" - denotes concatenation * * Key = SWK * AAD = DER(OID) * IV = nonce * Input = (d) * Encrypt (SWK, AAD, IV, (d)) * Output (AuthTag, EncryptedECKey) * * privatekey == EncryptedECKey || AuthTag * * OID's that shall be supported by KPT implementation: * Curve OID DER(OID) * secp256r1 1.2.840.10045.3.1.7 06 08 2A 86 48 CE 3D 03 01 07 * secp384r1 1.3.132.0.34 06 05 2B 81 04 00 22 * secp521r1 1.3.132.0.35 06 05 2B 81 04 00 23 * * Expected private key (d) sizes: * secp256r1 256 bits * secp384r1 384 bits * secp521r1 576 bits (rounded up to a multiple of 64-bit quadword) * * AuthTag is 128 bits (16 bytes) * * For optimal performance all data buffers SHOULD be 8-byte aligned. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyKptEcdsaSignRS * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyEcdsaSignRS() * *****************************************************************************/ typedef struct CpaCyKptEcdsaSignRSOpData_t { CpaFlatBuffer privateKey; /**< Encrypted private key data of the form * EncryptECKey || AuthTag */ CpaFlatBuffer m; /**< digest of the message to be signed */ } CpaCyKptEcdsaSignRSOpData; /** ***************************************************************************** * Discovery and Provisioning APIs for KPT * *****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * Query KPT's issuing public key(R_Pu) and signature from QAT driver. * @description * This function is to query the RSA3K issuing key and its * PKCS#1 v2.2 SHA-384 signature from the QAT driver. * @context * This function may sleep, and MUST NOT be called in interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @param[in] instanceHandle Instance handle. * @param[out] pIssueCert KPT-2.0 Issuing certificate in PEM format as defined in RFC#7468 * @param[out] pKptStatus One of the status codes denoted in the * enumerate type CpaCyKptKeyManagementStatus * CPA_CY_KPT_SUCCESS: Issuing key retrieved successfully * CPA_CY_KPT_FAILED: Operation failed * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_FAIL Function failed. Suggested course of action * is to shutdown and restart. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * @see * *****************************************************************************/ CpaStatus cpaCyKptQueryIssuingKeys(const CpaInstanceHandle instanceHandle, CpaFlatBuffer *pPublicX509IssueCert, CpaCyKptKeyManagementStatus *pKptStatus); /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * Query KPT's Per-Part public key(I_pu) and signature from QAT * device * @description * This function is to query RSA3K Per-Part public key and its * PKCS#1 v2.2 SHA-384 signature from the QAT device. * @context * This function may sleep, and MUST NOT be called in interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @param[in] instanceHandle Instance handle. * @param[out] pDevCredential Device Per-Part public key * @param[out] pKptStatus One of the status codes denoted in the * enumerate type CpaCyKptKeyManagementStatus * CPA_CY_KPT_SUCCESS: Device credentials * retrieved successfully * CPA_CY_KPT_FAILED: Operation failed * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_FAIL Function failed. Suggested course of action * is to shutdown and restart. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * @see * *****************************************************************************/ CpaStatus cpaCyKptQueryDeviceCredentials( const CpaInstanceHandle instanceHandle, CpaCyKptValidationKey *pDevCredential, CpaCyKptKeyManagementStatus *pKptStatus); /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * Perform KPT key loading function. * * @description * This function is invoked by a QAT application to load an encrypted * symmetric wrapping key. * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle QAT service instance handle. * @param[in] pSWK Encrypted SWK * @param[out] keyHandle A 64-bit handle value created by KPT * @param[out] pKptStatus One of the status codes denoted in the * enumerate type CpaCyKptKeyManagementStatus * CPA_CY_KPT_SUCCESS: * Key Loaded successfully * CPA_CY_KPT_LOADKEY_FAIL_QUOTA_EXCEEDED_PER_VFID: * SWK count exceeds the configured maximum * value per VFID * CPA_CY_KPT_LOADKEY_FAIL_QUOTA_EXCEEDED_PER_PASID: * SWK count exceeds the configured maximum * value per PASID * CPA_CY_KPT_LOADKEY_FAIL_QUOTA_EXCEEDED: SWK * count exceeds the configured maximum value * when not scoped to VFID or * PASID CPA_CY_KPT_FAILED: Operation failed due * to unspecified reason * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * @retval CPA_STATUS_UNSUPPORTED KPT-2.0 is not supported. * * @pre * Component has been initialized. * @post * None * @note * None * @see * None *****************************************************************************/ CpaStatus cpaCyKptLoadKey(CpaInstanceHandle instanceHandle, CpaCyKptLoadKey *pSWK, CpaCyKptHandle *keyHandle, CpaCyKptKeyManagementStatus *pKptStatus); /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * Perform KPT delete keys function according to key handle * * @description * Before closing a QAT session(instance), an application that has * previously stored its wrapping key in a QAT device using the KPT * framework executes this call to delete its wrapping key in the QAT * device. * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle QAT service instance handle. * @param[in] keyHandle A 64-bit handle value * @param[out] pkptstatus One of the status codes denoted in the * enumerate type CpaCyKptKeyManagementStatus * CPA_CY_KPT_SUCCESS: Key Deleted successfully * CPA_CY_KPT_SWK_FAIL_NOT_FOUND: For any * reason the input handle cannot be found. * CPA_CY_KPT_FAILED: Operation failed due to * unspecified reason * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * @pre * Component has been initialized. * @post * None * @note * None * @see * None *****************************************************************************/ CpaStatus cpaCyKptDeleteKey(CpaInstanceHandle instanceHandle, CpaCyKptHandle keyHandle, CpaCyKptKeyManagementStatus *pKptStatus); /** ***************************************************************************** * Usage APIs for KPT * *****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_kpt.h * @ingroup cpaCyKpt * Perform KPT-2.0 mode RSA decrypt primitive operation on the input data. * * @description * This function is a variant of cpaCyRsaDecrypt, which will perform * an RSA decryption primitive operation on the input data using the * specified RSA private key which are encrypted. As the RSA decryption * primitive and signing primitive operations are mathematically * identical this function may also be used to perform an RSA signing * primitive operation. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pRsaDecryptCb Pointer to callback function to be invoked * when the operation is complete. If this is * set to a NULL value the function will operate * synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback. * @param[in] pDecryptOpData Structure containing all the data needed to * perform the RSA decrypt operation. The * client code allocates the memory for this * structure. This component takes ownership * of the memory until it is returned in the * callback. * @param[out] pOutputData Pointer to structure into which the result of * the RSA decryption primitive is written. The * client MUST allocate this memory. The data * pointed to is an integer in big-endian order. * The value will be between 0 and the modulus * n - 1. * On invocation the callback function will * contain this parameter in the pOut parameter. * @param[in] pKptUnwrapContext Pointer of structure into which the content * of KptUnwrapContext is kept. The client MUST * allocate this memory and copy structure * KptUnwrapContext into this flat buffer. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting.Resubmit * the request. * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * By virtue of invoking cpaSyKptRsaDecrypt, the implementation understands * that pDecryptOpData contains an encrypted private key that requires * unwrapping. KptUnwrapContext contains a 'KptHandle' field that points * to the unwrapping key in the WKT. * When pRsaDecryptCb is non-NULL an asynchronous callback is generated in * response to this function call. * Any errors generated during processing are reported as part of the * callback status code. For optimal performance, data pointers SHOULD be * 8-byte aligned. * In KPT release, private key field in CpaCyKptRsaDecryptOpData is a * concatenation of cipher text and hash tag. * For optimal performance, data pointers SHOULD be 8-byte aligned. * @see * CpaCyKptRsaDecryptOpData, * CpaCyGenFlatBufCbFunc, * *****************************************************************************/ CpaStatus cpaCyKptRsaDecrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyKptRsaDecryptOpData *pDecryptOpData, CpaFlatBuffer *pOutputData, CpaCyKptUnwrapContext *pKptUnwrapContext); /** ***************************************************************************** * @ingroup cpaCyKpt * Generate ECDSA Signature R & S. * @description * This function is a variant of cpaCyEcdsaSignRS, it generates ECDSA * signature R & S as per ANSI X9.62 2005 section 7.3. * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pSignStatus In synchronous mode, the multiply output is * valid (CPA_TRUE) or the output is invalid * (CPA_FALSE). * @param[out] pR ECDSA message signature r. * @param[out] pS ECDSA message signature s. * @param[in] pKptUnwrapContext Pointer of structure into which the content * of KptUnwrapContext is kept,The client MUST * allocate this memory and copy structure * KptUnwrapContext into this flat buffer. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * By virtue of invoking the cpaCyKptEcdsaSignRS, the implementation * understands CpaCyEcdsaSignRSOpData contains an encrypted private key * that requires unwrapping. KptUnwrapContext contains a 'KptHandle' field * that points to the unwrapping key in the WKT. When pCb is non-NULL an * asynchronous callback of type CpaCyEcdsaSignRSCbFunc generated in * response to this function call. * In KPT release, private key field in CpaCyEcdsaSignRSOpData is a * concatenation of cipher text and hash tag. * @see * None *****************************************************************************/ CpaStatus cpaCyKptEcdsaSignRS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyKptEcdsaSignRSOpData *pOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS, CpaCyKptUnwrapContext *pKptUnwrapContext); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif qatlib-25.08.0/quickassist/include/lac/cpa_cy_ln.h000066400000000000000000000557751503624047500220200ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_ln.h * * @defgroup cpaCyLn Cryptographic Large Number API * * @ingroup cpaCy * * @description * These functions specify the Cryptographic API for Large Number * Operations. * * @note * Large numbers are represented on the QuickAssist API using octet * strings, stored in structures of type @ref CpaFlatBuffer. These * octet strings are encoded as described by PKCS#1 v2.1, section 4, * which is consistent with ASN.1 syntax. The following text * summarizes this. Any exceptions to this encoding are specified * on the specific data structure or function to which the exception * applies. * * An n-bit number, N, has a value in the range 2^(n-1) through 2^(n)-1. * In other words, its most significant bit, bit n-1 (where bit-counting * starts from zero) MUST be set to 1. We can also state that the * bit-length n of a number N is defined by n = floor(log2(N))+1. * * The buffer, b, in which an n-bit number N is stored, must be "large * enough". In other words, b.dataLenInBytes must be at least * minLenInBytes = ceiling(n/8). * * The number is stored in a "big endian" format. This means that the * least significant byte (LSB) is b[b.dataLenInBytes-1], while the * most significant byte (MSB) is b[b.dataLenInBytes-minLenInBytes]. * In the case where the buffer is "exactly" the right size, then the * MSB is b[0]. Otherwise, all bytes from b[0] up to the MSB MUST be * set to 0x00. * * The largest bit-length we support today is 8192 bits. In other * words, we can deal with numbers up to a value of (2^8192)-1. * *****************************************************************************/ #ifndef CPA_CY_LN_H #define CPA_CY_LN_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyLn * Modular Exponentiation Function Operation Data. * @description * This structure lists the different items that are required in the * cpaCyLnModExp function. The client MUST allocate the memory for * this structure. When the structure is passed into the function, * ownership of the memory passes to the function. Ownership of the memory * returns to the client when this structure is returned in the callback. * The operation size in bits is equal to the size of whichever of the * following is largest: the modulus, the base or the exponent. * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyLnModExp function, and * before it has been returned in the callback, undefined behavior will * result. * The values of the base, the exponent and the modulus MUST all be less * than 2^8192, and the modulus must not be equal to zero. *****************************************************************************/ typedef struct _CpaCyLnModExpOpData { CpaFlatBuffer modulus; /**< Flat buffer containing a pointer to the modulus. * This number may be up to 8192 bits in length, and MUST be greater * than zero. */ CpaFlatBuffer base; /**< Flat buffer containing a pointer to the base. * This number may be up to 8192 bits in length. */ CpaFlatBuffer exponent; /**< Flat buffer containing a pointer to the exponent. * This number may be up to 8192 bits in length. */ } CpaCyLnModExpOpData; /** ***************************************************************************** * @ingroup cpaCyLn * Modular Inversion Function Operation Data. * @description * This structure lists the different items that are required in the * function @ref cpaCyLnModInv. The client MUST allocate the memory for * this structure. When the structure is passed into the function, * ownership of the memory passes to the function. Ownership of the * memory returns to the client when this structure is returned in the * callback. * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyLnModInv function, and * before it has been returned in the callback, undefined behavior will * result. * * Note that the values of A and B MUST NOT both be even numbers, and * both MUST be less than 2^8192. *****************************************************************************/ typedef struct _CpaCyLnModInvOpData { CpaFlatBuffer A; /**< Flat buffer containing a pointer to the value that will be * inverted. * This number may be up to 8192 bits in length, it MUST NOT be zero, * and it MUST be co-prime with B. */ CpaFlatBuffer B; /**< Flat buffer containing a pointer to the value that will be used as * the modulus. * This number may be up to 8192 bits in length, it MUST NOT be zero, * and it MUST be co-prime with A. */ } CpaCyLnModInvOpData; /** ***************************************************************************** * @ingroup cpaCyLn * Look Aside Cryptographic large number Statistics. * @deprecated * As of v1.3 of the Crypto API, this structure has been deprecated, * replaced by @ref CpaCyLnStats64. * @description * This structure contains statistics on the Look Aside Cryptographic * large number operations. Statistics are set to zero when the component * is initialized, and are collected per instance. * ****************************************************************************/ typedef struct _CpaCyLnStats { Cpa32U numLnModExpRequests; /**< Total number of successful large number modular exponentiation * requests.*/ Cpa32U numLnModExpRequestErrors; /**< Total number of large number modular exponentiation requests that * had an error and could not be processed. */ Cpa32U numLnModExpCompleted; /**< Total number of large number modular exponentiation operations * that completed successfully. */ Cpa32U numLnModExpCompletedErrors; /**< Total number of large number modular exponentiation operations * that could not be completed successfully due to errors. */ Cpa32U numLnModInvRequests; /**< Total number of successful large number modular inversion * requests.*/ Cpa32U numLnModInvRequestErrors; /**< Total number of large number modular inversion requests that * had an error and could not be processed. */ Cpa32U numLnModInvCompleted; /**< Total number of large number modular inversion operations * that completed successfully. */ Cpa32U numLnModInvCompletedErrors; /**< Total number of large number modular inversion operations * that could not be completed successfully due to errors. */ } CpaCyLnStats CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCyLn * Look Aside Cryptographic large number Statistics. * @description * This structure contains statistics on the Look Aside Cryptographic * large number operations. Statistics are set to zero when the component * is initialized, and are collected per instance. * ****************************************************************************/ typedef struct _CpaCyLnStats64 { Cpa64U numLnModExpRequests; /**< Total number of successful large number modular exponentiation * requests.*/ Cpa64U numLnModExpRequestErrors; /**< Total number of large number modular exponentiation requests that * had an error and could not be processed. */ Cpa64U numLnModExpCompleted; /**< Total number of large number modular exponentiation operations * that completed successfully. */ Cpa64U numLnModExpCompletedErrors; /**< Total number of large number modular exponentiation operations * that could not be completed successfully due to errors. */ Cpa64U numLnModInvRequests; /**< Total number of successful large number modular inversion * requests.*/ Cpa64U numLnModInvRequestErrors; /**< Total number of large number modular inversion requests that * had an error and could not be processed. */ Cpa64U numLnModInvCompleted; /**< Total number of large number modular inversion operations * that completed successfully. */ Cpa64U numLnModInvCompletedErrors; /**< Total number of large number modular inversion operations * that could not be completed successfully due to errors. */ } CpaCyLnStats64; /** ***************************************************************************** * @ingroup cpaCyLn * Perform modular exponentiation operation. * * @description * This function performs modular exponentiation. It computes the * following result based on the inputs: * * result = (base ^ exponent) mod modulus * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pLnModExpCb Pointer to callback function to be * invoked when the operation is complete. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback. * @param[in] pLnModExpOpData Structure containing all the data needed * to perform the LN modular exponentiation * operation. The client code allocates * the memory for this structure. This * component takes ownership of the memory * until it is returned in the callback. * @param[out] pResult Pointer to a flat buffer containing a * pointer to memory allocated by the client * into which the result will be written. * The size of the memory required MUST be * larger than or equal to the size * required to store the modulus. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * @post * None * @note * When pLnModExpCb is non null, an asynchronous callback of type * CpaCyLnModExpCbFunc is generated in response to this function call. * Any errors generated during processing are reported in the structure * returned in the callback. * * @see * CpaCyLnModExpOpData, CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyLnModExp(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pLnModExpCb, void *pCallbackTag, const CpaCyLnModExpOpData *pLnModExpOpData, CpaFlatBuffer *pResult); /** ***************************************************************************** * @ingroup cpaCyLn * Perform modular inversion operation. * * @description * This function performs modular inversion. It computes the following * result based on the inputs: * * result = (1/A) mod B. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pLnModInvCb Pointer to callback function to be * invoked when the operation is complete. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the * callback. * @param[in] pLnModInvOpData Structure containing all the data * needed to perform the LN modular * inversion operation. The client code * allocates the memory for this structure. * This component takes ownership of the * memory until it is returned in the * callback. * @param[out] pResult Pointer to a flat buffer containing a * pointer to memory allocated by the client * into which the result will be written. * The size of the memory required MUST be * larger than or equal to the size * required to store the modulus. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * @post * None * @note * When pLnModInvCb is non null, an asynchronous callback of type * CpaCyLnModInvCbFunc is generated in response to this function call. * Any errors generated during processing are reported in the structure * returned in the callback. * * @see * CpaCyLnModInvOpData, * CpaCyGenFlatBufCbFunc * *****************************************************************************/ CpaStatus cpaCyLnModInv(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pLnModInvCb, void *pCallbackTag, const CpaCyLnModInvOpData *pLnModInvOpData, CpaFlatBuffer *pResult); /** ***************************************************************************** * @ingroup cpaCyLn * Query statistics for large number operations * * @deprecated * As of v1.3 of the Crypto API, this function has been deprecated, * replaced by @ref cpaCyLnStatsQuery64(). * * @description * This function will query a specific instance handle for large number * statistics. The user MUST allocate the CpaCyLnStats structure and pass * the reference to that structure into this function call. This function * writes the statistic results into the passed in CpaCyLnStats structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pLnStats Pointer to memory into which the * statistics will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Acceleration Services unit has been initialized. * * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * * @see * CpaCyLnStats * *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCyLnStatsQuery(const CpaInstanceHandle instanceHandle, struct _CpaCyLnStats *pLnStats); /** ***************************************************************************** * @ingroup cpaCyLn * Query statistics (64-bit version) for large number operations * * @description * This function will query a specific instance handle for the 64-bit * version of the large number statistics. * The user MUST allocate the CpaCyLnStats64 structure and pass * the reference to that structure into this function call. This function * writes the statistic results into the passed in CpaCyLnStats64 * structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pLnStats Pointer to memory into which the * statistics will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. * Resubmit the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Acceleration Services unit has been initialized. * * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * * @see * CpaCyLnStats *****************************************************************************/ CpaStatus cpaCyLnStatsQuery64(const CpaInstanceHandle instanceHandle, CpaCyLnStats64 *pLnStats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_LN_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_nrbg.h000066400000000000000000000202321503624047500223130ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_nrbg.h * * @defgroup cpaCyNrbg Non-Deterministic Random Bit Generation API * * @ingroup cpaCy * * @description * These functions specify the API for Non-Deterministic Random Bit * Generation (NRBG). This is used to provide entropy to a * Deterministic RBG (DRBG). * * @note * These functions supersede the random number generation functions * in API group @ref cpaCyRand, which are now deprecated. * *****************************************************************************/ #ifndef CPA_CY_NRBG_H #define CPA_CY_NRBG_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyNrbg * NRBG Get Entropy Operation Data * @description * This structure contains data relating to generation of entropy * using an NRBG. * @see * cpaCyNrbgGetEntropy() * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the @ref cpaCyNrbgGetEntropy() function, * and before it has been returned in the callback, undefined behavior will * result. *****************************************************************************/ typedef struct _CpaCyNrbgOpData { Cpa32U lengthInBytes; /**< Requested number of bytes to be generated. On calls to @ref * cpaCyNrbgGetEntropy, this value must be greater than zero (>0). */ } CpaCyNrbgOpData; /** ***************************************************************************** * @ingroup cpaCyNrbg * Gets entropy from the NRBG. * * @description * This function returns a string of bits of specified length. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback. * @param[in] pOpData Structure containing all the data needed * to perform the operation. The client code * allocates the memory for this structure. * This component takes ownership of the * memory until it is returned in the * callback. * @param[out] pEntropy Pointer to memory allocated by the client * to which the entropy will be written. For * optimal performance, the data pointed to * SHOULD be 8-byte aligned. There is no * endianness associated with the entropy. * On invocation the callback function will * contain this parameter in its pOut *parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via the @ref cpaCyStartInstance * function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type @ref * CpaCyGenFlatBufCbFunc is generated in response to this function call. * Any errors generated during processing are reported as part of the * callback status code. For optimal performance, data pointers SHOULD be * 8-byte aligned. *****************************************************************************/ CpaStatus cpaCyNrbgGetEntropy(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pCb, void *pCallbackTag, const CpaCyNrbgOpData *pOpData, CpaFlatBuffer *pEntropy); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_NRBG_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_prime.h000066400000000000000000000457461503624047500225200ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_prime.h * * @defgroup cpaCyPrime Prime Number Test API * * @ingroup cpaCy * * @description * These functions specify the API for the prime number test operations. * * For prime number generation, this API SHOULD be used in conjunction * with the Deterministic Random Bit Generation API (@ref cpaCyDrbg). * * @note * Large numbers are represented on the QuickAssist API as described * in the Large Number API (@ref cpaCyLn). * * In addition, the bit length of large numbers passed to the API * MUST NOT exceed 576 bits for Elliptic Curve operations. *****************************************************************************/ #ifndef CPA_CY_PRIME_H #define CPA_CY_PRIME_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyPrime * Prime Test Operation Data. * @description * This structure contains the operation data for the cpaCyPrimeTest * function. The client MUST allocate the memory for this structure and the * items pointed to by this structure. When the structure is passed into * the function, ownership of the memory passes to the function. Ownership * of the memory returns to the client when this structure is returned in * the callback function. * * All values in this structure are required to be in Most Significant Byte * first order, e.g. primeCandidate.pData[0] = MSB. * * All numbers MUST be stored in big-endian order. * * @note * If the client modifies or frees the memory referenced in this * structure after it has been submitted to the cpaCyPrimeTest * function, and before it has been returned in the callback, undefined * behavior will result. * * @see * cpaCyPrimeTest() * *****************************************************************************/ typedef struct _CpaCyPrimeTestOpData { CpaFlatBuffer primeCandidate; /**< The prime number candidate to test */ CpaBoolean performGcdTest; /**< A value of CPA_TRUE means perform a GCD Primality Test */ CpaBoolean performFermatTest; /**< A value of CPA_TRUE means perform a Fermat Primality Test */ Cpa32U numMillerRabinRounds; /**< Number of Miller Rabin Primality Test rounds. Set to 0 to perform * zero Miller Rabin tests. The maximum number of rounds supported is 50. */ CpaFlatBuffer millerRabinRandomInput; /**< Flat buffer containing a pointer to an array of n random numbers * for Miller Rabin Primality Tests. The size of the buffer MUST be * * n * (MAX(64,x)) * * where: * * - n is the requested number of rounds. * - x is the minimum number of bytes required to represent the prime * candidate, i.e. x = ceiling((ceiling(log2(p)))/8). * * Each random number MUST be greater than 1 and less than the prime * candidate - 1, with leading zeroes as necessary. */ CpaBoolean performLucasTest; /**< An CPA_TRUE value means perform a Lucas Primality Test */ } CpaCyPrimeTestOpData; /** ***************************************************************************** * @ingroup cpaCyPrime * Prime Number Test Statistics. * @deprecated * As of v1.3 of the Crypto API, this structure has been deprecated, * replaced by @ref CpaCyPrimeStats64. * @description * This structure contains statistics on the prime number test operations. * Statistics are set to zero when the component is initialized, and are * collected per instance. * ****************************************************************************/ typedef struct _CpaCyPrimeStats { Cpa32U numPrimeTestRequests; /**< Total number of successful prime number test requests.*/ Cpa32U numPrimeTestRequestErrors; /**< Total number of prime number test requests that had an * error and could not be processed. */ Cpa32U numPrimeTestCompleted; /**< Total number of prime number test operations that completed * successfully. */ Cpa32U numPrimeTestCompletedErrors; /**< Total number of prime number test operations that could not be * completed successfully due to errors. */ Cpa32U numPrimeTestFailures; /**< Total number of prime number test operations that executed * successfully but the outcome of the test was that the number was not * prime. */ } CpaCyPrimeStats CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCyPrime * Prime Number Test Statistics (64-bit version). * @description * This structure contains a 64-bit version of the statistics on the * prime number test operations. * Statistics are set to zero when the component is initialized, and are * collected per instance. ****************************************************************************/ typedef struct _CpaCyPrimeStats64 { Cpa64U numPrimeTestRequests; /**< Total number of successful prime number test requests.*/ Cpa64U numPrimeTestRequestErrors; /**< Total number of prime number test requests that had an * error and could not be processed. */ Cpa64U numPrimeTestCompleted; /**< Total number of prime number test operations that completed * successfully. */ Cpa64U numPrimeTestCompletedErrors; /**< Total number of prime number test operations that could not be * completed successfully due to errors. */ Cpa64U numPrimeTestFailures; /**< Total number of prime number test operations that executed * successfully but the outcome of the test was that the number was not * prime. */ } CpaCyPrimeStats64; /** ***************************************************************************** * @ingroup cpaCyPrime * Definition of callback function invoked for cpaCyPrimeTest * requests. * * @description * This is the prototype for the cpaCyPrimeTest callback function. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pOpData Opaque pointer to the Operation data pointer * supplied in request. * @param[in] testPassed A value of CPA_TRUE means the prime candidate * is probably prime. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCyPrimeTest() * *****************************************************************************/ typedef void (*CpaCyPrimeTestCbFunc)(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean testPassed); /** ***************************************************************************** * @ingroup cpaCyPrime * Prime Number Test Function. * * @description * This function will test probabilistically if a number is prime. Refer * to ANSI X9.80 2005 for details. The primality result will be returned * in the asynchronous callback. * * The following combination of GCD, Fermat, Miller-Rabin, and Lucas * testing is supported: * (up to 1x GCD) + (up to 1x Fermat) + (up to 50x Miller-Rabin rounds) + * (up to 1x Lucas) * For example: * (1x GCD) + (25x Miller-Rabin) + (1x Lucas); * (1x GCD) + (1x Fermat); * (50x Miller-rabin); * * Tests are always performed in order of increasing complexity, for * example GCD first, then Fermat, then Miller-Rabin, and finally Lucas. * * For all of the primality tests, the following prime number "sizes" * (length in bits) are supported: all sizes up to and including 512 * bits, as well as sizes 768, 1024, 1536, 2048, 3072 and 4096. * * Candidate prime numbers MUST match these sizes accordingly, with * leading zeroes present where necessary. * * When this prime number test is used in conjunction with combined * Miller-Rabin and Lucas tests, it may be used as a means of performing * a self test operation on the random data generator. * * A response status of ok (pass == CPA_TRUE) means all requested * primality tests passed, and the prime candidate is probably prime * (the exact probability depends on the primality tests requested). * A response status of not ok (pass == CPA_FALSE) means one of the * requested primality tests failed (the prime candidate has been found * to be composite). * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pTestPassed A value of CPA_TRUE means the prime candidate * is probably prime. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pCb is non-NULL an asynchronous callback of type * CpaCyPrimeTestCbFunc is generated in response to this function call. * For optimal performance, data pointers SHOULD be 8-byte aligned. * * @see * CpaCyPrimeTestOpData, CpaCyPrimeTestCbFunc * *****************************************************************************/ CpaStatus cpaCyPrimeTest(const CpaInstanceHandle instanceHandle, const CpaCyPrimeTestCbFunc pCb, void *pCallbackTag, const CpaCyPrimeTestOpData *pOpData, CpaBoolean *pTestPassed); /****************************************************************************** * @ingroup cpaCyPrime * Query prime number statistics specific to an instance. * * @deprecated * As of v1.3 of the Crypto API, this function has been deprecated, * replaced by @ref cpaCyPrimeQueryStats64(). * * @description * This function will query a specific instance for prime number * statistics. The user MUST allocate the CpaCyPrimeStats structure * and pass the reference to that into this function call. This function * will write the statistic results into the passed in * CpaCyPrimeStats structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pPrimeStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCyPrimeQueryStats(const CpaInstanceHandle instanceHandle, struct _CpaCyPrimeStats *pPrimeStats); /****************************************************************************** * @ingroup cpaCyPrime * Query prime number statistics specific to an instance. * * @description * This function will query a specific instance for the 64-bit * version of the prime number statistics. * The user MUST allocate the CpaCyPrimeStats64 structure * and pass the reference to that into this function call. This function * will write the statistic results into the passed in * CpaCyPrimeStats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pPrimeStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. *****************************************************************************/ CpaStatus cpaCyPrimeQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyPrimeStats64 *pPrimeStats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_PRIME_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_rsa.h000066400000000000000000001345671503624047500221710ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_rsa.h * * @defgroup cpaCyRsa RSA API * * @ingroup cpaCy * * @description * These functions specify the API for Public Key Encryption * (Cryptography) RSA operations. The PKCS #1 V2.1 specification is * supported, however the support is limited to "two-prime" mode. RSA * multi-prime is not supported. * * @note * These functions implement RSA cryptographic primitives. RSA padding * schemes are not implemented. For padding schemes that require the mgf * function see @ref cpaCyKeyGen. * * @note * Large numbers are represented on the QuickAssist API as described * in the Large Number API (@ref cpaCyLn). *****************************************************************************/ #ifndef CPA_CY_RSA_H #define CPA_CY_RSA_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Version. * @description * This enumeration lists the version identifier for the PKCS #1 V2.1 * standard. * @note * Multi-prime (more than two primes) is not supported. * *****************************************************************************/ typedef enum _CpaCyRsaVersion { CPA_CY_RSA_VERSION_TWO_PRIME = 1 /**< The version supported is "two-prime". */ } CpaCyRsaVersion; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Public Key Structure. * @description * This structure contains the two components which comprise the RSA * public key as defined in the PKCS #1 V2.1 standard. * All values in this structure are required to be in Most Significant Byte * first order, e.g. modulusN.pData[0] = MSB. * *****************************************************************************/ typedef struct _CpaCyRsaPublicKey { CpaFlatBuffer modulusN; /**< The modulus (n). * For key generation operations, the client MUST allocate the memory * for this parameter; its value is generated. * For encrypt operations this parameter is an input. */ CpaFlatBuffer publicExponentE; /**< The public exponent (e). * For key generation operations, this field is unused. It is NOT * generated by the interface; it is the responsibility of the client * to set this to the same value as the corresponding parameter on * the CpaCyRsaKeyGenOpData structure before using the key for * encryption. * For encrypt operations this parameter is an input. */ } CpaCyRsaPublicKey; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Private Key Structure For Representation 1. * @description * This structure contains the first representation that can be used for * describing the RSA private key, represented by the tuple of the * modulus (n) and the private exponent (d). * All values in this structure are required to be in Most Significant Byte * first order, e.g. modulusN.pData[0] = MSB. * *****************************************************************************/ typedef struct _CpaCyRsaPrivateKeyRep1 { CpaFlatBuffer modulusN; /**< The modulus (n). For key generation operations the memory MUST * be allocated by the client and the value is generated. For other * operations this is an input. Permitted lengths are: * * - 512 bits (64 bytes), * - 1024 bits (128 bytes), * - 1536 bits (192 bytes), * - 2048 bits (256 bytes), * - 3072 bits (384 bytes), * - 4096 bits (512 bytes), or * - 8192 bits (1024 bytes). */ CpaFlatBuffer privateExponentD; /**< The private exponent (d). For key generation operations the * memory MUST be allocated by the client and the value is generated. For * other operations this is an input. * NOTE: It is important that the value D is big enough. It is STRONGLY * recommended that this value is at least half the length of the modulus * N to protect against the Wiener attack. */ } CpaCyRsaPrivateKeyRep1; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Private Key Structure For Representation 2. * @description * This structure contains the second representation that can be used for * describing the RSA private key. The quintuple of p, q, dP, dQ, and qInv * (explained below and in the spec) are required for the second * representation. The optional sequence of triplets are not included. * All values in this structure are required to be in Most Significant Byte * first order, e.g. prime1P.pData[0] = MSB. * *****************************************************************************/ typedef struct _CpaCyRsaPrivateKeyRep2 { CpaFlatBuffer prime1P; /**< The first large prime (p). * For key generation operations, this field is unused. */ CpaFlatBuffer prime2Q; /**< The second large prime (q). * For key generation operations, this field is unused. */ CpaFlatBuffer exponent1Dp; /**< The first factor CRT exponent (dP). d mod (p-1). */ CpaFlatBuffer exponent2Dq; /**< The second factor CRT exponent (dQ). d mod (q-1). */ CpaFlatBuffer coefficientQInv; /**< The (first) Chinese Remainder Theorem (CRT) coefficient (qInv). * (inverse of q) mod p. */ } CpaCyRsaPrivateKeyRep2; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA DPA Opdata. * @description * This structure contains data needed to perform RSA DPA decrypt. * *****************************************************************************/ typedef struct _CpaCyRsaDpaOpData { CpaFlatBuffer *pRsaPrimeP; /**< Pointer to RSA prime P data buffer. */ CpaFlatBuffer *pRsaPrimeQ; /**< Pointer to RSA prime Q data buffer. */ CpaFlatBuffer *pRsaPublicE; /**< Pointer to an RSA Public key exponent. */ CpaFlatBuffer *pRandom; /**< Pointer to buffer containing cryptographically secure random data. */ CpaBoolean createRandomData; /**< Control parameter to delegate the random data generation to QAT. If * set to CPA_TRUE, input parameter pRandom is ignored. */ } CpaCyRsaDpaOpData; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA private key representation type. * @description * This enumeration lists which PKCS V2.1 representation of the private * key is being used. * *****************************************************************************/ typedef enum _CpaCyRsaPrivateKeyRepType { CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 = 1, /**< The first representation of the RSA private key. */ CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2 /**< The second representation of the RSA private key. */ } CpaCyRsaPrivateKeyRepType; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Private Key Structure. * @description * This structure contains the two representations that can be used for * describing the RSA private key. The privateKeyRepType will be used to * identify which representation is to be used. Typically, using the * second representation results in faster decryption operations. * *****************************************************************************/ typedef struct _CpaCyRsaPrivateKey { CpaCyRsaVersion version; /**< Indicates the version of the PKCS #1 specification that is * supported. * Note that this applies to both representations. */ CpaCyRsaPrivateKeyRepType privateKeyRepType; /**< This value is used to identify which of the private key * representation types in this structure is relevant. * When performing key generation operations for Type 2 representations, * memory must also be allocated for the type 1 representations, and values * for both will be returned. */ CpaCyRsaPrivateKeyRep1 privateKeyRep1; /**< This is the first representation of the RSA private key as * defined in the PKCS #1 V2.1 specification. For key generation operations * the memory for this structure is allocated by the client and the * specific values are generated. For other operations this is an input * parameter. */ CpaCyRsaPrivateKeyRep2 privateKeyRep2; /**< This is the second representation of the RSA private key as * defined in the PKCS #1 V2.1 specification. For key generation operations * the memory for this structure is allocated by the client and the * specific values are generated. For other operations this is an input * parameter. */ } CpaCyRsaPrivateKey; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Key Generation Data. * @description * This structure lists the different items that are required in the * cpaCyRsaGenKey function. The client MUST allocate the memory for this * structure. When the structure is passed into the function, ownership of * the memory passes to the function. Ownership of the memory returns to * the client when this structure is returned in the * CpaCyRsaKeyGenCbFunc callback function. * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyRsaGenKey function, and * before it has been returned in the callback, undefined behavior will * result. * All values in this structure are required to be in Most Significant Byte * first order, e.g. prime1P.pData[0] = MSB. * * The following limitations on the permutations of the supported bit * lengths of p, q and n (written as {p, q, n}) apply: * * - {256, 256, 512} or * - {512, 512, 1024} or * - {768, 768, 1536} or * - {1024, 1024, 2048} or * - {1536, 1536, 3072} or * - {2048, 2048, 4096}. * *****************************************************************************/ typedef struct _CpaCyRsaKeyGenOpData { CpaFlatBuffer prime1P; /**< A large random prime number (p). This MUST be created by the * client. Permitted bit lengths are: 256, 512, 768, 1024, 1536 or 2048. * Limitations apply - refer to the description above for details. */ CpaFlatBuffer prime2Q; /**< A large random prime number (q). This MUST be created by the * client. Permitted bit lengths are: 256, 512, 768, 1024, 1536 or 2048. * Limitations apply - refer to the description above for details. If the * private key representation type is 2, then this pointer will be assigned * to the relevant structure member of the representation 2 private key. */ Cpa32U modulusLenInBytes; /**< The bit length of the modulus (n). This is the modulus length for * both the private and public keys. The length of the modulus N parameter * for the private key representation 1 structure and the public key * structures will be assigned to this value. References to the strength of * RSA actually refer to this bit length. Recommended minimum is 1024 bits. * Permitted lengths are: * - 512 bits (64 bytes), * - 1024 bits (128 bytes), * - 1536 bits (192 bytes), * - 2048 bits (256 bytes), * - 3072 bits (384 bytes), or * - 4096 bits (512 bytes). * Limitations apply - refer to description above for details. */ CpaCyRsaVersion version; /**< Indicates the version of the PKCS #1 specification that is * supported. * Note that this applies to both representations. */ CpaCyRsaPrivateKeyRepType privateKeyRepType; /**< This value is used to identify which of the private key * representation types is required to be generated. */ CpaFlatBuffer publicExponentE; /**< The public exponent (e). */ } CpaCyRsaKeyGenOpData; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Encryption Primitive Operation Data * @description * This structure lists the different items that are required in the * cpaCyRsaEncrypt function. As the RSA encryption primitive and * verification primitive operations are mathematically identical this * structure may also be used to perform an RSA verification primitive * operation. * When performing an RSA encryption primitive operation, the input data * is the message and the output data is the cipher text. * When performing an RSA verification primitive operation, the input data * is the signature and the output data is the message. * The client MUST allocate the memory for this structure. When the * structure is passed into the function, ownership of the memory passes * to the function. Ownership of the memory returns to the client when * this structure is returned in the CpaCyRsaEncryptCbFunc * callback function. * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyRsaEncrypt function, and * before it has been returned in the callback, undefined behavior will * result. * All values in this structure are required to be in Most Significant Byte * first order, e.g. inputData.pData[0] = MSB. * *****************************************************************************/ typedef struct _CpaCyRsaEncryptOpData { CpaCyRsaPublicKey *pPublicKey; /**< Pointer to the public key. */ CpaFlatBuffer inputData; /**< The input data that the RSA encryption primitive operation is * performed on. The data pointed to is an integer that MUST be in big- * endian order. The value MUST be between 0 and the modulus n - 1. */ } CpaCyRsaEncryptOpData; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Decryption Primitive Operation Data * @description * This structure lists the different items that are required in the * cpaCyRsaDecrypt function. As the RSA decryption primitive and * signature primitive operations are mathematically identical this * structure may also be used to perform an RSA signature primitive * operation. * When performing an RSA decryption primitive operation, the input data * is the cipher text and the output data is the message text. * When performing an RSA signature primitive operation, the input data * is the message and the output data is the signature. * The client MUST allocate the memory for this structure. When the * structure is passed into the function, ownership of the memory passes * to he function. Ownership of the memory returns to the client when * this structure is returned in the CpaCyRsaDecryptCbFunc * callback function. * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCyRsaDecrypt function, and * before it has been returned in the callback, undefined behavior will * result. * All values in this structure are required to be in Most Significant Byte * first order, e.g. inputData.pData[0] = MSB. * *****************************************************************************/ typedef struct _CpaCyRsaDecryptOpData { CpaCyRsaPrivateKey *pRecipientPrivateKey; /**< Pointer to the recipient's RSA private key. */ CpaFlatBuffer inputData; /**< The input data that the RSA decryption primitive operation is * performed on. The data pointed to is an integer that MUST be in big- * endian order. The value MUST be between 0 and the modulus n - 1. */ } CpaCyRsaDecryptOpData; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Statistics. * @deprecated * As of v1.3 of the Crypto API, this structure has been deprecated, * replaced by @ref CpaCyRsaStats64. * @description * This structure contains statistics on the RSA operations. * Statistics are set to zero when the component is initialized, and are * collected per instance. ****************************************************************************/ typedef struct _CpaCyRsaStats { Cpa32U numRsaKeyGenRequests; /**< Total number of successful RSA key generation requests. */ Cpa32U numRsaKeyGenRequestErrors; /**< Total number of RSA key generation requests that had an error and * could not be processed. */ Cpa32U numRsaKeyGenCompleted; /**< Total number of RSA key generation operations that completed * successfully. */ Cpa32U numRsaKeyGenCompletedErrors; /**< Total number of RSA key generation operations that could not be * completed successfully due to errors. */ Cpa32U numRsaEncryptRequests; /**< Total number of successful RSA encrypt operation requests. */ Cpa32U numRsaEncryptRequestErrors; /**< Total number of RSA encrypt requests that had an error and could * not be processed. */ Cpa32U numRsaEncryptCompleted; /**< Total number of RSA encrypt operations that completed * successfully. */ Cpa32U numRsaEncryptCompletedErrors; /**< Total number of RSA encrypt operations that could not be * completed successfully due to errors. */ Cpa32U numRsaDecryptRequests; /**< Total number of successful RSA decrypt operation requests. */ Cpa32U numRsaDecryptRequestErrors; /**< Total number of RSA decrypt requests that had an error and could * not be processed. */ Cpa32U numRsaDecryptCompleted; /**< Total number of RSA decrypt operations that completed * successfully. */ Cpa32U numRsaDecryptCompletedErrors; /**< Total number of RSA decrypt operations that could not be * completed successfully due to errors. */ } CpaCyRsaStats CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCyRsa * RSA Statistics (64-bit version). * @description * This structure contains 64-bit version of the statistics on the RSA * operations. * Statistics are set to zero when the component is initialized, and are * collected per instance. ****************************************************************************/ typedef struct _CpaCyRsaStats64 { Cpa64U numRsaKeyGenRequests; /**< Total number of successful RSA key generation requests. */ Cpa64U numRsaKeyGenRequestErrors; /**< Total number of RSA key generation requests that had an error and * could not be processed. */ Cpa64U numRsaKeyGenCompleted; /**< Total number of RSA key generation operations that completed * successfully. */ Cpa64U numRsaKeyGenCompletedErrors; /**< Total number of RSA key generation operations that could not be * completed successfully due to errors. */ Cpa64U numRsaEncryptRequests; /**< Total number of successful RSA encrypt operation requests. */ Cpa64U numRsaEncryptRequestErrors; /**< Total number of RSA encrypt requests that had an error and could * not be processed. */ Cpa64U numRsaEncryptCompleted; /**< Total number of RSA encrypt operations that completed * successfully. */ Cpa64U numRsaEncryptCompletedErrors; /**< Total number of RSA encrypt operations that could not be * completed successfully due to errors. */ Cpa64U numRsaDecryptRequests; /**< Total number of successful RSA decrypt operation requests. */ Cpa64U numRsaDecryptRequestErrors; /**< Total number of RSA decrypt requests that had an error and could * not be processed. */ Cpa64U numRsaDecryptCompleted; /**< Total number of RSA decrypt operations that completed * successfully. */ Cpa64U numRsaDecryptCompletedErrors; /**< Total number of RSA decrypt operations that could not be * completed successfully due to errors. */ Cpa64U numKptRsaDecryptRequests; /**< Total number of successful KPT RSA decrypt operation requests. */ Cpa64U numKptRsaDecryptRequestErrors; /**< Total number of KPT RSA decrypt requests that had an error and could * not be processed. */ Cpa64U numKptRsaDecryptCompleted; /**< Total number of KPT RSA decrypt operations that completed * successfully. */ Cpa64U numKptRsaDecryptCompletedErrors; /**< Total number of KPT RSA decrypt operations that could not be * completed successfully due to errors. */ } CpaCyRsaStats64; /** ***************************************************************************** * @ingroup cpaCyRsa * Definition of the RSA key generation callback function. * * @description * This is the prototype for the RSA key generation callback function. The * callback function pointer is passed in as a parameter to the * cpaCyRsaGenKey function. It will be invoked once the request has * completed. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag Opaque value provided by user while making * individual function calls. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] pKeyGenOpData Structure with output params for callback. * @param[in] pPrivateKey Structure which contains pointers to the memory * into which the generated private key will be * written. * @param[in] pPublicKey Structure which contains pointers to the memory * into which the generated public key will be * written. The pointer to the public exponent (e) * that is returned in this structure is equal to * the input public exponent. * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * CpaCyRsaPrivateKey, * CpaCyRsaPublicKey, * cpaCyRsaGenKey() * *****************************************************************************/ typedef void (*CpaCyRsaKeyGenCbFunc)(void *pCallbackTag, CpaStatus status, void *pKeyGenOpData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey); /** ***************************************************************************** * @ingroup cpaCyRsa * Generate RSA keys. * * @description * This function will generate private and public keys for RSA as specified * in the PKCS #1 V2.1 standard. Both representation types of the private * key may be generated. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pRsaKeyGenCb Pointer to the callback function to be invoked * when the operation is complete. If this is * set to a NULL value the function will operate * synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. Will * be returned unchanged in the callback. * @param[in] pKeyGenOpData Structure containing all the data needed to * perform the RSA key generation operation. The * client code allocates the memory for this * structure. This component takes ownership of * the memory until it is returned in the * callback. * @param[out] pPrivateKey Structure which contains pointers to the memory * into which the generated private key will be * written. The client MUST allocate memory * for this structure, and for the pointers * within it, recursively; on return, these will * be populated. * @param[out] pPublicKey Structure which contains pointers to the memory * into which the generated public key will be * written. The memory for this structure and * for the modulusN parameter MUST be allocated * by the client, and will be populated on return * from the call. The field publicExponentE * is not modified or touched in any way; it is * the responsibility of the client to set this * to the same value as the corresponding * parameter on the CpaCyRsaKeyGenOpData * structure before using the key for encryption. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pRsaKeyGenCb is non-NULL, an asynchronous callback of type is * generated in response to this function call. * Any errors generated during processing are reported as part of the * callback status code. For optimal performance, data pointers SHOULD be * 8-byte aligned. * @see * CpaCyRsaKeyGenOpData, * CpaCyRsaKeyGenCbFunc, * cpaCyRsaEncrypt(), * cpaCyRsaDecrypt() * *****************************************************************************/ CpaStatus cpaCyRsaGenKey(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, void *pCallbackTag, const CpaCyRsaKeyGenOpData *pKeyGenOpData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey); /** ***************************************************************************** * @ingroup cpaCyRsa * Perform the RSA encrypt (or verify) primitive operation on the input * data. * * @description * This function will perform an RSA encryption primitive operation on the * input data using the specified RSA public key. As the RSA encryption * primitive and verification primitive operations are mathematically * identical this function may also be used to perform an RSA verification * primitive operation. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pRsaEncryptCb Pointer to callback function to be invoked * when the operation is complete. If this is * set to a NULL value the function will operate * synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. Will * be returned unchanged in the callback. * @param[in] pEncryptOpData Structure containing all the data needed to * perform the RSA encryption operation. The * client code allocates the memory for this * structure. This component takes ownership of * the memory until it is returned in the * callback. * @param[out] pOutputData Pointer to structure into which the result of * the RSA encryption primitive is written. The * client MUST allocate this memory. The data * pointed to is an integer in big-endian order. * The value will be between 0 and the modulus * n - 1. * On invocation the callback function will * contain this parameter in the pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pRsaEncryptCb is non-NULL an asynchronous callback of type is * generated in response to this function call. * Any errors generated during processing are reported as part of the * callback status code. For optimal performance, data pointers SHOULD be * 8-byte aligned. * @see * CpaCyGenFlatBufCbFunc * CpaCyRsaEncryptOpData * cpaCyRsaGenKey() * cpaCyRsaDecrypt() * *****************************************************************************/ CpaStatus cpaCyRsaEncrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaEncryptCb, void *pCallbackTag, const CpaCyRsaEncryptOpData *pEncryptOpData, CpaFlatBuffer *pOutputData); /** ***************************************************************************** * @ingroup cpaCyRsa * Perform the RSA decrypt (or sign) primitive operation on the input * data. * * @description * This function will perform an RSA decryption primitive operation on the * input data using the specified RSA private key. As the RSA decryption * primitive and signing primitive operations are mathematically identical * this function may also be used to perform an RSA signing primitive * operation. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pRsaDecryptCb Pointer to callback function to be invoked * when the operation is complete. If this is * set to a NULL value the function will operate * synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback. * @param[in] pDecryptOpData Structure containing all the data needed to * perform the RSA decrypt operation. The * client code allocates the memory for this * structure. This component takes ownership * of the memory until it is returned in the * callback. * @param[out] pOutputData Pointer to structure into which the result of * the RSA decryption primitive is written. The * client MUST allocate this memory. The data * pointed to is an integer in big-endian order. * The value will be between 0 and the modulus * n - 1. * On invocation the callback function will * contain this parameter in the pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pRsaDecryptCb is non-NULL an asynchronous callback is generated in * response to this function call. * Any errors generated during processing are reported as part of the * callback status code. For optimal performance, data pointers SHOULD be * 8-byte aligned. * @see * CpaCyRsaDecryptOpData, * CpaCyGenFlatBufCbFunc, * cpaCyRsaGenKey(), * cpaCyRsaEncrypt() * *****************************************************************************/ CpaStatus cpaCyRsaDecrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptOpData, CpaFlatBuffer *pOutputData); /** ***************************************************************************** * @ingroup cpaCyRsa * Perform Differential Power Analysis (DPA) resistant RSA decrypt * (or sign) primitive operation on the input data. This is the DPA * variation of cpaCyRsaDecrypt() API. * * @description * This function will perform an RSA decryption primitive operation on the * input data using the specified RSA private key. As the RSA decryption * primitive and signing primitive operations are mathematically identical * this function may also be used to perform an RSA signing primitive * operation. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pRsaDecryptCb Pointer to callback function to be invoked * when the operation is complete. If this is * set to a NULL value the function will operate * synchronously. * @param[in] pCallbackTag Opaque User Data for this specific call. * Will be returned unchanged in the callback. * @param[in] pDecryptOpData Structure containing all the data needed to * perform the RSA decrypt operation. The * client code allocates the memory for this * structure. This component takes ownership * of the memory until it is returned in the * callback. * @param[in] pDpaOpData Structure containing the additional * configuration settings to make the RSA decrypt * operations DPA resilient. * @param[out] pOutputData Pointer to structure into which the result of * the RSA decryption primitive is written. The * client MUST allocate this memory. The data * pointed to is an integer in big-endian order. * The value will be between 0 and the modulus * n - 1. * On invocation the callback function will * contain this parameter in the pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * When pRsaDecryptCb is non-NULL an asynchronous callback is generated in * response to this function call. * Any errors generated during processing are reported as part of the * callback status code. For optimal performance, data pointers SHOULD be * 8-byte aligned. * @see * CpaCyRsaDecryptOpData, * CpaCyGenFlatBufCbFunc, * cpaCyRsaGenKey(), * cpaCyRsaEncrypt() * *****************************************************************************/ CpaStatus cpaCyRsaDpaDecrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptOpData, const CpaCyRsaDpaOpData *pDpaOpData, CpaFlatBuffer *pOutputData); /** ***************************************************************************** * @ingroup cpaCyRsa * Query statistics for a specific RSA instance. * * @deprecated * As of v1.3 of the Crypto API, this function has been deprecated, * replaced by @ref cpaCyRsaQueryStats64(). * * @description * This function will query a specific instance for RSA statistics. The * user MUST allocate the CpaCyRsaStats structure and pass the * reference to that into this function call. This function will write the * statistic results into the passed in CpaCyRsaStats structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pRsaStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyRsaStats * *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCyRsaQueryStats(const CpaInstanceHandle instanceHandle, struct _CpaCyRsaStats *pRsaStats); /** ***************************************************************************** * @ingroup cpaCyRsa * Query statistics (64-bit version) for a specific RSA instance. * * @description * This function will query a specific instance for RSA statistics. The * user MUST allocate the CpaCyRsaStats64 structure and pass the * reference to that into this function call. This function will write the * statistic results into the passed in CpaCyRsaStats64 structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pRsaStats Pointer to memory into which the statistics * will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner and no asynchronous * callback will be generated. * @see * CpaCyRsaStats64 *****************************************************************************/ CpaStatus cpaCyRsaQueryStats64(const CpaInstanceHandle instanceHandle, CpaCyRsaStats64 *pRsaStats); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_RSA_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_sym.h000066400000000000000000002472471503624047500222140ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_sym.h * * @defgroup cpaCySym Symmetric Cipher and Hash Cryptographic API * * @ingroup cpaCy * * @description * These functions specify the Cryptographic API for symmetric cipher, * hash, and combined cipher and hash operations. * *****************************************************************************/ #ifndef CPA_CY_SYM_H #define CPA_CY_SYM_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" /** ***************************************************************************** * @ingroup cpaCySym * Cryptographic component symmetric session context handle. * @description * Handle to a cryptographic session context. The memory for this handle * is allocated by the client. The size of the memory that the client needs * to allocate is determined by a call to the @ref * cpaCySymSessionCtxGetSize or @ref cpaCySymSessionCtxGetDynamicSize * functions. The session context memory is initialized with a call to * the @ref cpaCySymInitSession function. * This memory MUST not be freed until a call to @ref * cpaCySymRemoveSession has completed successfully. * *****************************************************************************/ typedef void *CpaCySymSessionCtx; /** ***************************************************************************** * @ingroup cpaCySym * Packet type for the cpaCySymPerformOp function * * @description * Enumeration which is used to indicate to the symmetric cryptographic * perform function on which type of packet the operation is required to * be invoked. Multi-part cipher and hash operations are useful when * processing needs to be performed on a message which is available to * the client in multiple parts (for example due to network fragmentation * of the packet). * * @note * There are some restrictions regarding the operations on which * partial packet processing is supported. For details, see the * function @ref cpaCySymPerformOp. * * @see * cpaCySymPerformOp() * *****************************************************************************/ typedef enum _CpaCySymPacketType { CPA_CY_SYM_PACKET_TYPE_FULL = 1, /**< Perform an operation on a full packet*/ CPA_CY_SYM_PACKET_TYPE_PARTIAL, /**< Perform a partial operation and maintain the state of the partial * operation within the session. This is used for either the first or * subsequent packets within a partial packet flow. */ CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL /**< Complete the last part of a multi-part operation */ } CpaCySymPacketType; /** ***************************************************************************** * @ingroup cpaCySym * Types of operations supported by the cpaCySymPerformOp function. * @description * This enumeration lists different types of operations supported by the * cpaCySymPerformOp function. The operation type is defined during * session registration and cannot be changed for a session once it has * been setup. * @see * cpaCySymPerformOp *****************************************************************************/ typedef enum _CpaCySymOp { CPA_CY_SYM_OP_NONE = 0, /**< No operation */ CPA_CY_SYM_OP_CIPHER, /**< Cipher only operation on the data */ CPA_CY_SYM_OP_HASH, /**< Hash only operation on the data */ CPA_CY_SYM_OP_ALGORITHM_CHAINING /**< Chain any cipher with any hash operation. The order depends on * the value in the CpaCySymAlgChainOrder enum. * * This value is also used for authenticated ciphers (GCM and CCM), in * which case the cipherAlgorithm should take one of the values @ref * CPA_CY_SYM_CIPHER_AES_CCM or @ref CPA_CY_SYM_CIPHER_AES_GCM, while the * hashAlgorithm should take the corresponding value @ref * CPA_CY_SYM_HASH_AES_CCM or @ref CPA_CY_SYM_HASH_AES_GCM. */ } CpaCySymOp; /** ***************************************************************************** * @ingroup cpaCySym * Cipher algorithms. * @description * This enumeration lists supported cipher algorithms and modes. * *****************************************************************************/ typedef enum _CpaCySymCipherAlgorithm { CPA_CY_SYM_CIPHER_NULL = 1, /**< NULL cipher algorithm. No mode applies to the NULL algorithm. */ CPA_CY_SYM_CIPHER_ARC4 = 2, /**< (A)RC4 cipher algorithm */ CPA_CY_SYM_CIPHER_AES_ECB = 3, /**< AES algorithm in ECB mode */ CPA_CY_SYM_CIPHER_AES_CBC = 4, /**< AES algorithm in CBC mode */ CPA_CY_SYM_CIPHER_AES_CTR = 5, /**< AES algorithm in Counter mode */ CPA_CY_SYM_CIPHER_AES_CCM = 6, /**< AES algorithm in CCM mode. This authenticated cipher is only supported * when the hash mode is also set to CPA_CY_SYM_HASH_MODE_AUTH. When this * cipher algorithm is used the CPA_CY_SYM_HASH_AES_CCM element of the * CpaCySymHashAlgorithm enum MUST be used to set up the related * CpaCySymHashSetupData structure in the session context. */ CPA_CY_SYM_CIPHER_AES_GCM = 7, /**< AES algorithm in GCM mode. This authenticated cipher is only supported * when the hash mode is also set to CPA_CY_SYM_HASH_MODE_AUTH. When this * cipher algorithm is used the CPA_CY_SYM_HASH_AES_GCM element of the * CpaCySymHashAlgorithm enum MUST be used to set up the related * CpaCySymHashSetupData structure in the session context. */ CPA_CY_SYM_CIPHER_DES_ECB = 8, /**< DES algorithm in ECB mode */ CPA_CY_SYM_CIPHER_DES_CBC = 9, /**< DES algorithm in CBC mode */ CPA_CY_SYM_CIPHER_3DES_ECB = 10, /**< Triple DES algorithm in ECB mode */ CPA_CY_SYM_CIPHER_3DES_CBC = 11, /**< Triple DES algorithm in CBC mode */ CPA_CY_SYM_CIPHER_3DES_CTR = 12, /**< Triple DES algorithm in CTR mode */ CPA_CY_SYM_CIPHER_KASUMI_F8 = 13, /**< Kasumi algorithm in F8 mode */ CPA_CY_SYM_CIPHER_SNOW3G_UEA2 = 14, /**< SNOW3G algorithm in UEA2 mode */ CPA_CY_SYM_CIPHER_AES_F8 = 15, /**< AES algorithm in F8 mode */ CPA_CY_SYM_CIPHER_AES_XTS = 16, /**< AES algorithm in XTS mode */ CPA_CY_SYM_CIPHER_ZUC_EEA3 = 17, /**< ZUC algorithm in EEA3 mode */ CPA_CY_SYM_CIPHER_CHACHA = 18, /**< ChaCha20 Cipher Algorithm. This cipher is only supported for * algorithm chaining. When selected, the hash algorithm must be set to * CPA_CY_SYM_HASH_POLY and the hash mode must be set to * CPA_CY_SYM_HASH_MODE_AUTH. */ CPA_CY_SYM_CIPHER_SM4_ECB = 19, /**< SM4 algorithm in ECB mode This cipher supports 128 bit keys only and * does not support partial processing. */ CPA_CY_SYM_CIPHER_SM4_CBC = 20, /**< SM4 algorithm in CBC mode This cipher supports 128 bit keys only and * does not support partial processing. */ CPA_CY_SYM_CIPHER_SM4_CTR = 21 /**< SM4 algorithm in CTR mode This cipher supports 128 bit keys only and * does not support partial processing. */ } CpaCySymCipherAlgorithm; /** * @ingroup cpaCySym * Size of bitmap needed for cipher "capabilities" type. * * @description * Defines the number of bits in the bitmap to represent supported * ciphers in the type @ref CpaCySymCapabilitiesInfo. Should be set to * at least one greater than the largest value in the enumerated type * @ref CpaCySymCipherAlgorithm, so that the value of the enum constant * can also be used as the bit position in the bitmap. * * A larger value was chosen to allow for extensibility without the need * to change the size of the bitmap (to ease backwards compatibility in * future versions of the API). */ #define CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE (32) /** ***************************************************************************** * @ingroup cpaCySym * Symmetric Cipher Direction * @description * This enum indicates the cipher direction (encryption or decryption). * *****************************************************************************/ typedef enum _CpaCySymCipherDirection { CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT = 1, /**< Encrypt Data */ CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT /**< Decrypt Data */ } CpaCySymCipherDirection; /** ***************************************************************************** * @file cpa_cy_sym.h * @ingroup cpaCySym * Symmetric Cipher Op Data for key derivation * @description * This structure contains the cipher key or the data to derive * the cipher key in addition to other cipher related data. * *****************************************************************************/ typedef struct _CpaCySymDeriveOpData { Cpa8U *pContext; /**< Pointer to Context structure */ Cpa16U contextLen; /**< The number of octets of context */ } CpaCySymDeriveOpData; /** ***************************************************************************** * @ingroup cpaCySym * Symmetric Cipher Setup Data. * @description * This structure contains data relating to Cipher (Encryption and * Decryption) to setup a session. * *****************************************************************************/ typedef struct _CpaCySymCipherSetupData { CpaCySymCipherAlgorithm cipherAlgorithm; /**< Cipher algorithm and mode */ Cpa32U cipherKeyLenInBytes; /**< Cipher key length in bytes. For AES it can be 128 bits (16 bytes), * 192 bits (24 bytes) or 256 bits (32 bytes). * For the CCM mode of operation, the only supported key length is 128 bits * (16 bytes). * For the CPA_CY_SYM_CIPHER_AES_F8 mode of operation, cipherKeyLenInBytes * should be set to the combined length of the encryption key and the * keymask. Since the keymask and the encryption key are the same size, * cipherKeyLenInBytes should be set to 2 x the AES encryption key length. * For the AES-XTS mode of operation: * - Two keys must be provided and cipherKeyLenInBytes refers to total * length of the two keys. * - Each key can be either 128 bits (16 bytes) or 256 bits (32 bytes). * - Both keys must have the same size. */ Cpa8U *pCipherKey; /**< Cipher key * For the CPA_CY_SYM_CIPHER_AES_F8 mode of operation, pCipherKey will * point to a concatenation of the AES encryption key followed by a * keymask. As per RFC3711, the keymask should be padded with trailing * bytes to match the length of the encryption key used. * For AES-XTS mode of operation, two keys must be provided and pCipherKey * must point to the two keys concatenated together (Key1 || Key2). * cipherKeyLenInBytes will contain the total size of both keys. * These fields are set to NULL if key derivation will be used. */ CpaCySymCipherDirection cipherDirection; /**< This parameter determines if the cipher operation is an encrypt or * a decrypt operation. * For the RC4 algorithm and the F8/CTR modes, only encrypt operations * are valid. */ } CpaCySymCipherSetupData; /** ***************************************************************************** * @ingroup cpaCySym * Symmetric Hash mode * @description * This enum indicates the Hash Mode. * *****************************************************************************/ typedef enum _CpaCySymHashMode { CPA_CY_SYM_HASH_MODE_PLAIN = 1, /**< Plain hash. Can be specified for MD5 and the SHA family of * hash algorithms. */ CPA_CY_SYM_HASH_MODE_AUTH, /**< Authenticated hash. This mode may be used in conjunction with the * MD5 and SHA family of algorithms to specify HMAC. It MUST also be * specified with all of the remaining algorithms, all of which are in * fact authentication algorithms. */ CPA_CY_SYM_HASH_MODE_NESTED /**< Nested hash. Can be specified for MD5 and the SHA family of * hash algorithms. */ } CpaCySymHashMode; /** ***************************************************************************** * @ingroup cpaCySym * Hash algorithms. * @description * This enumeration lists supported hash algorithms. * *****************************************************************************/ typedef enum _CpaCySymHashAlgorithm { CPA_CY_SYM_HASH_NONE = 0, /**< No hash algorithm. */ CPA_CY_SYM_HASH_MD5 = 1, /**< MD5 algorithm. Supported in all 3 hash modes */ CPA_CY_SYM_HASH_SHA1 = 2, /**< 128 bit SHA algorithm. Supported in all 3 hash modes */ CPA_CY_SYM_HASH_SHA224 = 3, /**< 224 bit SHA algorithm. Supported in all 3 hash modes */ CPA_CY_SYM_HASH_SHA256 = 4, /**< 256 bit SHA algorithm. Supported in all 3 hash modes */ CPA_CY_SYM_HASH_SHA384 = 5, /**< 384 bit SHA algorithm. Supported in all 3 hash modes */ CPA_CY_SYM_HASH_SHA512 = 6, /**< 512 bit SHA algorithm. Supported in all 3 hash modes */ CPA_CY_SYM_HASH_AES_XCBC = 7, /**< AES XCBC algorithm. This is only supported in the hash mode * CPA_CY_SYM_HASH_MODE_AUTH. */ CPA_CY_SYM_HASH_AES_CCM = 8, /**< AES algorithm in CCM mode. This authenticated cipher requires that the * hash mode is set to CPA_CY_SYM_HASH_MODE_AUTH. When this hash algorithm * is used, the CPA_CY_SYM_CIPHER_AES_CCM element of the * CpaCySymCipherAlgorithm enum MUST be used to set up the related * CpaCySymCipherSetupData structure in the session context. */ CPA_CY_SYM_HASH_AES_GCM = 9, /**< AES algorithm in GCM mode. This authenticated cipher requires that the * hash mode is set to CPA_CY_SYM_HASH_MODE_AUTH. When this hash algorithm * is used, the CPA_CY_SYM_CIPHER_AES_GCM element of the * CpaCySymCipherAlgorithm enum MUST be used to set up the related * CpaCySymCipherSetupData structure in the session context. */ CPA_CY_SYM_HASH_KASUMI_F9 = 10, /**< Kasumi algorithm in F9 mode. This is only supported in the hash * mode CPA_CY_SYM_HASH_MODE_AUTH. */ CPA_CY_SYM_HASH_SNOW3G_UIA2 = 11, /**< SNOW3G algorithm in UIA2 mode. This is only supported in the hash * mode CPA_CY_SYM_HASH_MODE_AUTH. */ CPA_CY_SYM_HASH_AES_CMAC = 12, /**< AES CMAC algorithm. This is only supported in the hash mode * CPA_CY_SYM_HASH_MODE_AUTH. */ CPA_CY_SYM_HASH_AES_GMAC = 13, /**< AES GMAC algorithm. This is only supported in the hash mode * CPA_CY_SYM_HASH_MODE_AUTH. When this hash algorithm * is used, the CPA_CY_SYM_CIPHER_AES_GCM element of the * CpaCySymCipherAlgorithm enum MUST be used to set up the related * CpaCySymCipherSetupData structure in the session context. */ CPA_CY_SYM_HASH_AES_CBC_MAC = 14, /**< AES-CBC-MAC algorithm. This is only supported in the hash mode * CPA_CY_SYM_HASH_MODE_AUTH. Only 128-bit keys are supported. */ CPA_CY_SYM_HASH_ZUC_EIA3 = 15, /**< ZUC algorithm in EIA3 mode */ CPA_CY_SYM_HASH_SHA3_256 = 16, /**< 256 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. * Partial requests are not supported, that is, only requests * of CPA_CY_SYM_PACKET_TYPE_FULL are supported. */ CPA_CY_SYM_HASH_SHA3_224 = 17, /**< 224 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. */ CPA_CY_SYM_HASH_SHA3_384 = 18, /**< 384 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. * Partial requests are not supported, that is, only requests * of CPA_CY_SYM_PACKET_TYPE_FULL are supported. */ CPA_CY_SYM_HASH_SHA3_512 = 19, /**< 512 bit SHA-3 algorithm. Only CPA_CY_SYM_HASH_MODE_PLAIN and * CPA_CY_SYM_HASH_MODE_AUTH are supported, that is, the hash * mode CPA_CY_SYM_HASH_MODE_NESTED is not supported for this algorithm. * Partial requests are not supported, that is, only requests * of CPA_CY_SYM_PACKET_TYPE_FULL are supported. */ CPA_CY_SYM_HASH_SHAKE_128 = 20, /**< 128 bit SHAKE algorithm. This is only supported in the hash * mode CPA_CY_SYM_HASH_MODE_PLAIN. Partial requests are not * supported, that is, only requests of CPA_CY_SYM_PACKET_TYPE_FULL * are supported. */ CPA_CY_SYM_HASH_SHAKE_256 = 21, /**< 256 bit SHAKE algorithm. This is only supported in the hash * mode CPA_CY_SYM_HASH_MODE_PLAIN. Partial requests are not * supported, that is, only requests of CPA_CY_SYM_PACKET_TYPE_FULL * are supported. */ CPA_CY_SYM_HASH_POLY = 22, /**< Poly1305 hash algorithm. This is only supported in the hash mode * CPA_CY_SYM_HASH_MODE_AUTH. This hash algorithm is only supported * as part of an algorithm chain with AES_CY_SYM_CIPHER_CHACHA to * implement the ChaCha20-Poly1305 AEAD algorithm. */ CPA_CY_SYM_HASH_SM3 = 23 /**< SM3 hash algorithm. Supported in all 3 hash modes. */ } CpaCySymHashAlgorithm; /** * @ingroup cpaCySym * Size of bitmap needed for hash "capabilities" type. * * @description * Defines the number of bits in the bitmap to represent supported * hashes in the type @ref CpaCySymCapabilitiesInfo. Should be set to * at least one greater than the largest value in the enumerated type * @ref CpaCySymHashAlgorithm, so that the value of the enum constant * can also be used as the bit position in the bitmap. * * A larger value was chosen to allow for extensibility without the need * to change the size of the bitmap (to ease backwards compatibility in * future versions of the API). */ #define CPA_CY_SYM_HASH_CAP_BITMAP_SIZE (32) /** ***************************************************************************** * @ingroup cpaCySym * Hash Mode Nested Setup Data. * @description * This structure contains data relating to a hash session in * CPA_CY_SYM_HASH_MODE_NESTED mode. * *****************************************************************************/ typedef struct _CpaCySymHashNestedModeSetupData { Cpa8U *pInnerPrefixData; /**< A pointer to a buffer holding the Inner Prefix data. For optimal * performance the prefix data SHOULD be 8-byte aligned. This data is * prepended to the data being hashed before the inner hash operation is * performed. */ Cpa32U innerPrefixLenInBytes; /**< The inner prefix length in bytes. The maximum size the prefix data * can be is 255 bytes. */ CpaCySymHashAlgorithm outerHashAlgorithm; /**< The hash algorithm used for the outer hash. Note: The inner hash * algorithm is provided in the hash context. */ Cpa8U *pOuterPrefixData; /**< A pointer to a buffer holding the Outer Prefix data. For optimal * performance the prefix data SHOULD be 8-byte aligned. This data is * prepended to the output from the inner hash operation before the outer * hash operation is performed.*/ Cpa32U outerPrefixLenInBytes; /**< The outer prefix length in bytes. The maximum size the prefix data * can be is 255 bytes. */ } CpaCySymHashNestedModeSetupData; /** ***************************************************************************** * @ingroup cpaCySym * Hash Auth Mode Setup Data. * @description * This structure contains data relating to a hash session in * CPA_CY_SYM_HASH_MODE_AUTH mode. * *****************************************************************************/ typedef struct _CpaCySymHashAuthModeSetupData { Cpa8U *authKey; /**< Authentication key pointer. * For the GCM (@ref CPA_CY_SYM_HASH_AES_GCM) and CCM (@ref * CPA_CY_SYM_HASH_AES_CCM) modes of operation, this field is ignored; * the authentication key is the same as the cipher key (see * the field pCipherKey in struct @ref CpaCySymCipherSetupData). */ Cpa32U authKeyLenInBytes; /**< Length of the authentication key in bytes. The key length MUST be * less than or equal to the block size of the algorithm. It is the client's * responsibility to ensure that the key length is compliant with the * standard being used (for example RFC 2104, FIPS 198a). * * For the GCM (@ref CPA_CY_SYM_HASH_AES_GCM) and CCM (@ref * CPA_CY_SYM_HASH_AES_CCM) modes of operation, this field is ignored; * the authentication key is the same as the cipher key, and so is its * length (see the field cipherKeyLenInBytes in struct @ref * CpaCySymCipherSetupData). */ Cpa32U aadLenInBytes; /**< The length of the additional authenticated data (AAD) in bytes. * The maximum permitted value is 240 bytes, unless otherwise * specified below. * * This field must be specified when the hash algorithm is one of the * following: * - For SNOW3G (@ref CPA_CY_SYM_HASH_SNOW3G_UIA2), this is the * length of the IV (which should be 16). * - For GCM (@ref CPA_CY_SYM_HASH_AES_GCM). In this case, this is the * length of the Additional Authenticated Data (called A, in NIST * SP800-38D). * - For CCM (@ref CPA_CY_SYM_HASH_AES_CCM). In this case, this is the * length of the associated data (called A, in NIST SP800-38C). * Note that this does NOT include the length of any padding, or the * 18 bytes reserved at the start of the above field to store the * block B0 and the encoded length. The maximum permitted value in * this case is 222 bytes. * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of operation * this field is not used and should be set to 0. Instead the length * of the AAD data is specified in the messageLenToHashInBytes field of * the CpaCySymOpData structure. */ } CpaCySymHashAuthModeSetupData; /** ***************************************************************************** * @ingroup cpaCySym * Hash Setup Data. * @description * This structure contains data relating to a hash session. The fields * hashAlgorithm, hashMode and digestResultLenInBytes are common to all * three hash modes and MUST be set for each mode. * *****************************************************************************/ typedef struct _CpaCySymHashSetupData { CpaCySymHashAlgorithm hashAlgorithm; /**< Hash algorithm. For mode CPA_CY_SYM_MODE_HASH_NESTED, this is the * inner hash algorithm. */ CpaCySymHashMode hashMode; /**< Mode of the hash operation. Valid options include plain, auth or * nested hash mode. */ Cpa32U digestResultLenInBytes; /**< Length of the digest to be returned. If the verify option is set, * this specifies the length of the digest to be compared for the * session. * * For CCM (@ref CPA_CY_SYM_HASH_AES_CCM), this is the octet length * of the MAC, which can be one of 4, 6, 8, 10, 12, 14 or 16. * * For GCM (@ref CPA_CY_SYM_HASH_AES_GCM), this is the length in bytes * of the authentication tag. * * If the value is less than the maximum length allowed by the hash, * the result shall be truncated. If the value is greater than the * maximum length allowed by the hash, an error (@ref * CPA_STATUS_INVALID_PARAM) is returned from the function @ref * cpaCySymInitSession. * * In the case of nested hash, it is the outer hash which determines * the maximum length allowed. */ CpaCySymHashAuthModeSetupData authModeSetupData; /**< Authentication Mode Setup Data. * Only valid for mode CPA_CY_SYM_MODE_HASH_AUTH */ CpaCySymHashNestedModeSetupData nestedModeSetupData; /**< Nested Hash Mode Setup Data * Only valid for mode CPA_CY_SYM_MODE_HASH_NESTED */ } CpaCySymHashSetupData; /** ***************************************************************************** * @ingroup cpaCySym * Algorithm Chaining Operation Ordering * @description * This enum defines the ordering of operations for algorithm chaining. * ****************************************************************************/ typedef enum _CpaCySymAlgChainOrder { CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER = 1, /**< Perform the hash operation followed by the cipher operation. If it is * required that the result of the hash (i.e. the digest) is going to be * included in the data to be ciphered, then: * *
    *
  • The digest MUST be placed in the destination buffer at the * location corresponding to the end of the data region to be hashed * (hashStartSrcOffsetInBytes + messageLenToHashInBytes), * i.e. there must be no gaps between the start of the digest and the * end of the data region to be hashed.
  • *
  • The messageLenToCipherInBytes member of the CpaCySymOpData * structure must be equal to the overall length of the plain text, * the digest length and any (optional) trailing data that is to be * included.
  • *
  • The messageLenToCipherInBytes must be a multiple to the block * size if a block cipher is being used.
  • *
* * The following is an example of the layout of the buffer before the * operation, after the hash, and after the cipher: @verbatim +-------------------------+---------------+ | Plaintext | Tail | +-------------------------+---------------+ <-messageLenToHashInBytes-> +-------------------------+--------+------+ | Plaintext | Digest | Tail | +-------------------------+--------+------+ <--------messageLenToCipherInBytes--------> +-----------------------------------------+ | Cipher Text | +-----------------------------------------+ @endverbatim */ CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH /**< Perform the cipher operation followed by the hash operation. * The hash operation will be performed on the ciphertext resulting from * the cipher operation. * * The following is an example of the layout of the buffer before the * operation, after the cipher, and after the hash: @verbatim +--------+---------------------------+---------------+ | Head | Plaintext | Tail | +--------+---------------------------+---------------+ <-messageLenToCipherInBytes-> +--------+---------------------------+---------------+ | Head | Ciphertext | Tail | +--------+---------------------------+---------------+ <------messageLenToHashInBytes-------> +--------+---------------------------+--------+------+ | Head | Ciphertext | Digest | Tail | +--------+---------------------------+--------+------+ @endverbatim * */ } CpaCySymAlgChainOrder; /** ***************************************************************************** * @ingroup cpaCySym * Session Setup Data. * @description * This structure contains data relating to setting up a session. The * client needs to complete the information in this structure in order to * setup a session. * ****************************************************************************/ typedef struct _CpaCySymSessionSetupData { CpaCyPriority sessionPriority; /**< Priority of this session */ CpaCySymOp symOperation; /**< Operation to perform */ CpaCySymCipherSetupData cipherSetupData; /**< Cipher Setup Data for the session. This member is ignored for the * CPA_CY_SYM_OP_HASH operation. */ CpaCySymHashSetupData hashSetupData; /**< Hash Setup Data for a session. This member is ignored for the * CPA_CY_SYM_OP_CIPHER operation. */ CpaCySymAlgChainOrder algChainOrder; /**< If this operation data structure relates to an algorithm chaining * session then this parameter determines the order in which the chained * operations are performed. If this structure does not relate to an * algorithm chaining session then this parameter will be ignored. * * @note In the case of authenticated ciphers (GCM and CCM), which are * also presented as "algorithm chaining", this value is also ignored. * The chaining order is defined by the authenticated cipher, in those * cases. */ CpaBoolean digestIsAppended; /**< Flag indicating whether the digest is appended immediately following * the region over which the digest is computed. This is true for both * IPsec packets and SSL/TLS records. * * If this flag is set, then the value of the pDigestResult field of * the structure @ref CpaCySymOpData is ignored. * * @note The value of this field is ignored for the authenticated cipher * AES_CCM as the digest must be appended in this case. * * @note Setting digestIsAppended for hash only operations when * verifyDigest is also set is not supported. For hash only operations * when verifyDigest is set, digestIsAppended should be set to CPA_FALSE. */ CpaBoolean verifyDigest; /**< This flag is relevant only for operations which generate a message * digest. If set to true, the computed digest will not be written back * to the buffer location specified by other parameters, but instead will * be verified (i.e. compared to the value passed in at that location). * The number of bytes to be written or compared is indicated by the * digest output length for the session. * @note This option is only valid for full packets and for final * partial packets when using partials without algorithm chaining. * @note The value of this field is ignored for the authenticated ciphers * (AES_CCM and AES_GCM). Digest verification is always done for these * (when the direction is decrypt) and unless the DP API is used, * the message buffer will be zeroed if verification fails. When using the * DP API, it is the API clients responsibility to clear the message * buffer when digest verification fails. */ CpaBoolean partialsNotRequired; /**< This flag indicates if partial packet processing is required for this * session. If set to true, partial packet processing will not be enabled * for this session and any calls to cpaCySymPerformOp() with the * packetType parameter set to a value other than * CPA_CY_SYM_PACKET_TYPE_FULL will fail. */ } CpaCySymSessionSetupData; /** ***************************************************************************** * @ingroup cpaCySym * Session Update Data. * @description * This structure contains data relating to resetting a session. ****************************************************************************/ typedef struct _CpaCySymSessionUpdateData { Cpa32U flags; /**< Flags indicating which fields to update. * All bits should be set to 0 except those fields to be updated. */ #define CPA_CY_SYM_SESUPD_CIPHER_KEY 1 << 0 #define CPA_CY_SYM_SESUPD_CIPHER_DIR 1 << 1 #define CPA_CY_SYM_SESUPD_AUTH_KEY 1 << 2 Cpa8U *pCipherKey; /**< Cipher key. * The same restrictions apply as described in the corresponding field * of the data structure @ref CpaCySymCipherSetupData. */ CpaCySymCipherDirection cipherDirection; /**< This parameter determines if the cipher operation is an encrypt or * a decrypt operation. * The same restrictions apply as described in the corresponding field * of the data structure @ref CpaCySymCipherSetupData. */ Cpa8U *authKey; /**< Authentication key pointer. * The same restrictions apply as described in the corresponding field * of the data structure @ref CpaCySymHashAuthModeSetupData. */ } CpaCySymSessionUpdateData; /** ***************************************************************************** * @ingroup cpaCySym * Cryptographic Component Operation Data. * @description * This structure contains data relating to performing cryptographic * processing on a data buffer. This request is used with * cpaCySymPerformOp() call for performing cipher, hash, auth cipher * or a combined hash and cipher operation. * * @see * CpaCySymPacketType * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the cpaCySymPerformOp function, and * before it has been returned in the callback, undefined behavior will * result. ****************************************************************************/ typedef struct _CpaCySymOpData { CpaCySymSessionCtx sessionCtx; /**< Handle for the initialized session context */ CpaCySymPacketType packetType; /**< Selects the packet type */ Cpa8U *pIv; /**< Initialization Vector or Counter. * * - For block ciphers in CBC or F8 mode, or for Kasumi in F8 mode, or for * SNOW3G in UEA2 mode, this is the Initialization Vector (IV) * value. * - For block ciphers in CTR mode, this is the counter. * - For GCM mode, this is either the IV (if the length is 96 bits) or J0 * (for other sizes), where J0 is as defined by NIST SP800-38D. * Regardless of the IV length, a full 16 bytes needs to be allocated. * - For CCM mode, the first byte is reserved, and the nonce should be * written starting at &pIv[1] (to allow space for the implementation * to write in the flags in the first byte). Note that a full 16 bytes * should be allocated, even though the ivLenInBytes field will have * a value less than this. * The macro @ref CPA_CY_SYM_CCM_SET_NONCE may be used here. * - For AES-XTS, this is the 128bit tweak, i, from IEEE Std 1619-2007. * * For optimum performance, the data pointed to SHOULD be 8-byte * aligned. * * The IV/Counter will be updated after every partial cryptographic * operation. */ Cpa32U ivLenInBytes; /**< Length of valid IV data pointed to by the pIv parameter. * * - For block ciphers in CBC or F8 mode, or for Kasumi in F8 mode, or for * SNOW3G in UEA2 mode, this is the length of the IV (which * must be the same as the block length of the cipher). * - For block ciphers in CTR mode, this is the length of the counter * (which must be the same as the block length of the cipher). * - For GCM mode, this is either 12 (for 96-bit IVs) or 16, in which * case pIv points to J0. * - For CCM mode, this is the length of the nonce, which can be in the * range 7 to 13 inclusive. */ Cpa32U cryptoStartSrcOffsetInBytes; /**< Starting point for cipher processing, specified as number of bytes * from start of data in the source buffer. The result of the cipher * operation will be written back into the output buffer starting * at this location. */ Cpa32U messageLenToCipherInBytes; /**< The message length, in bytes, of the source buffer on which the * cryptographic operation will be computed. This must be a multiple of * the block size if a block cipher is being used. This is also the same * as the result length. * * @note In the case of CCM (@ref CPA_CY_SYM_HASH_AES_CCM), this value * should not include the length of the padding or the length of the * MAC; the driver will compute the actual number of bytes over which * the encryption will occur, which will include these values. * * @note There are limitations on this length for partial * operations. Refer to the cpaCySymPerformOp function description for * details. * * @note On some implementations, this length may be limited to a 16-bit * value (65535 bytes). * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC), this field * should be set to 0. */ Cpa32U hashStartSrcOffsetInBytes; /**< Starting point for hash processing, specified as number of bytes * from start of packet in source buffer. * * @note For CCM and GCM modes of operation, this field is ignored. * The field @ref pAdditionalAuthData field should be set instead. * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of * operation, this field specifies the start of the AAD data in * the source buffer. */ Cpa32U messageLenToHashInBytes; /**< The message length, in bytes, of the source buffer that the hash * will be computed on. * * @note There are limitations on this length for partial operations. * Refer to the @ref cpaCySymPerformOp function description for details. * * @note For CCM and GCM modes of operation, this field is ignored. * The field @ref pAdditionalAuthData field should be set instead. * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of * operation, this field specifies the length of the AAD data in the * source buffer. The maximum length supported for AAD data for AES-GMAC * is 16383 bytes. * * @note On some implementations, this length may be limited to a 16-bit * value (65535 bytes). */ Cpa8U *pDigestResult; /**< If the digestIsAppended member of the @ref CpaCySymSessionSetupData * structure is NOT set then this is a pointer to the location where the * digest result should be inserted (in the case of digest generation) * or where the purported digest exists (in the case of digest * verification). * * At session registration time, the client specified the digest result * length with the digestResultLenInBytes member of the @ref * CpaCySymHashSetupData structure. The client must allocate at least * digestResultLenInBytes of physically contiguous memory at this location. * * For partial packet processing without algorithm chaining, this pointer * will be ignored for all but the final partial operation. * * For digest generation, the digest result will overwrite any data * at this location. * * @note For GCM (@ref CPA_CY_SYM_HASH_AES_GCM), for "digest result" * read "authentication tag T". * * If the digestIsAppended member of the @ref CpaCySymSessionSetupData * structure is set then this value is ignored and the digest result * is understood to be in the destination buffer for digest generation, * and in the source buffer for digest verification. The location of the * digest result in this case is immediately following the region over * which the digest is computed. * */ Cpa8U *pAdditionalAuthData; /**< Pointer to Additional Authenticated Data (AAD) needed for * authenticated cipher mechanisms (CCM and GCM), and to the IV for * SNOW3G authentication (@ref CPA_CY_SYM_HASH_SNOW3G_UIA2). * For other authentication mechanisms this pointer is ignored. * * The length of the data pointed to by this field is set up for * the session in the @ref CpaCySymHashAuthModeSetupData structure * as part of the @ref cpaCySymInitSession function call. This length * must not exceed 240 bytes. * * Specifically for CCM (@ref CPA_CY_SYM_HASH_AES_CCM), the caller * should setup this field as follows: * * - the nonce should be written starting at an offset of one byte * into the array, leaving room for the implementation to write in * the flags to the first byte. For example, *
* memcpy(&pOpData->pAdditionalAuthData[1], pNonce, nonceLen); *
* The macro @ref CPA_CY_SYM_CCM_SET_NONCE may be used here. * * - the additional authentication data itself should be written * starting at an offset of 18 bytes into the array, leaving room for * the length encoding in the first two bytes of the second block. * For example, *
* memcpy(&pOpData->pAdditionalAuthData[18], pAad, aadLen); *
* The macro @ref CPA_CY_SYM_CCM_SET_AAD may be used here. * * - the array should be big enough to hold the above fields, plus * any padding to round this up to the nearest multiple of the * block size (16 bytes). Padding will be added by the * implementation. * * Finally, for GCM (@ref CPA_CY_SYM_HASH_AES_GCM), the caller * should setup this field as follows: * * - the AAD is written in starting at byte 0 * - the array must be big enough to hold the AAD, plus any padding * to round this up to the nearest multiple of the block size (16 * bytes). Padding will be added by the implementation. * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of * operation, this field is not used and should be set to 0. Instead * the AAD data should be placed in the source buffer. */ } CpaCySymOpData; /** ***************************************************************************** * @ingroup cpaCySym * Cryptographic Component Operation Data with additional arguments * @description * This structure contains data relating to performing cryptographic * processing on a data buffer. This request is used with * cpaCySymPerformOp() call for performing cipher, hash, auth cipher * or a combined hash and cipher operation. * It includes a structure to support a NIST 800-108 key derivation. * This data structure is currently only used in chained usecases. * * If the deriveCtxData structure contains non-NULL entries for the * context structure, this indicates the cipher key and initialization * vector will be either supplied in, or derived from, that context * structure. In this case, the pointers to and the lengths of the cipher * key and iv in the symOpData structure must be NULL and zero * respectively. * * Additionally, if the cipher key is provided in the symOpData then * the deriveCtxData fields must be set to NULL and zero. * * @see * CpaCySymPacketType * * @note * If the client modifies or frees the memory referenced in this structure * after it has been submitted to the CPA level function, and * before it has been returned in the callback, undefined behavior will * result. ****************************************************************************/ typedef struct _CpaCySymOpData2 { CpaCySymOpData symOpData; /**< Symmetric opdata. */ CpaCySymDeriveOpData deriveCtxData; /**< Key derivation specific opdata. */ } CpaCySymOpData2; /** ***************************************************************************** * @ingroup cpaCySym * Setup the nonce for CCM. * @description * This macro sets the nonce in the appropriate locations of the * @ref CpaCySymOpData struct for the authenticated encryption * algorithm @ref CPA_CY_SYM_HASH_AES_CCM. ****************************************************************************/ #define CPA_CY_SYM_CCM_SET_NONCE(pOpData, pNonce, nonceLen) \ do \ { \ memcpy(&pOpData->pIv[1], pNonce, nonceLen); \ memcpy(&pOpData->pAdditionalAuthData[1], pNonce, nonceLen); \ } while (0) /** ***************************************************************************** * @ingroup cpaCySym * Setup the additional authentication data for CCM. * @description * This macro sets the additional authentication data in the * appropriate location of the@ref CpaCySymOpData struct for the * authenticated encryption algorithm @ref CPA_CY_SYM_HASH_AES_CCM. ****************************************************************************/ #define CPA_CY_SYM_CCM_SET_AAD(pOpData, pAad, aadLen) \ do \ { \ memcpy(&pOpData->pAdditionalAuthData[18], pAad, aadLen); \ } while (0) /** ***************************************************************************** * @ingroup cpaCySym * Cryptographic Component Statistics. * @deprecated * As of v1.3 of the cryptographic API, this structure has been * deprecated, replaced by @ref CpaCySymStats64. * @description * This structure contains statistics on the Symmetric Cryptographic * operations. Statistics are set to zero when the component is * initialized. ****************************************************************************/ typedef struct _CpaCySymStats { Cpa32U numSessionsInitialized; /**< Number of session initialized */ Cpa32U numSessionsRemoved; /**< Number of sessions removed */ Cpa32U numSessionErrors; /**< Number of session initialized and removed errors. */ Cpa32U numSymOpRequests; /**< Number of successful symmetric operation requests. */ Cpa32U numSymOpRequestErrors; /**< Number of operation requests that had an error and could * not be processed. */ Cpa32U numSymOpCompleted; /**< Number of operations that completed successfully. */ Cpa32U numSymOpCompletedErrors; /**< Number of operations that could not be completed * successfully due to errors. */ Cpa32U numSymOpVerifyFailures; /**< Number of operations that completed successfully, but the * result of the digest verification test was that it failed. * Note that this does not indicate an error condition. */ } CpaCySymStats CPA_DEPRECATED; /** ***************************************************************************** * @ingroup cpaCySym * Cryptographic Component Statistics (64-bit version). * @description * This structure contains a 64-bit version of the statistics on * the Symmetric Cryptographic operations. * Statistics are set to zero when the component is initialized. ****************************************************************************/ typedef struct _CpaCySymStats64 { Cpa64U numSessionsInitialized; /**< Number of session initialized */ Cpa64U numSessionsRemoved; /**< Number of sessions removed */ Cpa64U numSessionErrors; /**< Number of session initialized and removed errors. */ Cpa64U numSymOpRequests; /**< Number of successful symmetric operation requests. */ Cpa64U numSymOpRequestErrors; /**< Number of operation requests that had an error and could * not be processed. */ Cpa64U numSymOpCompleted; /**< Number of operations that completed successfully. */ Cpa64U numSymOpCompletedErrors; /**< Number of operations that could not be completed * successfully due to errors. */ Cpa64U numSymOpVerifyFailures; /**< Number of operations that completed successfully, but the * result of the digest verification test was that it failed. * Note that this does not indicate an error condition. */ } CpaCySymStats64; /** ***************************************************************************** * @ingroup cpaCySym * Definition of callback function * * @description * This is the callback function prototype. The callback function is * registered by the application using the cpaCySymInitSession() * function call. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pCallbackTag Opaque value provided by user while making * individual function call. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] operationType Identifies the operation type that was * requested in the cpaCySymPerformOp function. * @param[in] pOpData Pointer to structure with input parameters. * @param[in] pDstBuffer Caller MUST allocate a sufficiently sized * destination buffer to hold the data output. For * out-of-place processing the data outside the * cryptographic regions in the source buffer are * copied into the destination buffer. To perform * "in-place" processing set the pDstBuffer * parameter in cpaCySymPerformOp function to point * at the same location as pSrcBuffer. For optimum * performance, the data pointed to SHOULD be * 8-byte aligned. * @param[in] verifyResult This parameter is valid when the verifyDigest * option is set in the CpaCySymSessionSetupData * structure. A value of CPA_TRUE indicates that * the compare succeeded. A value of CPA_FALSE * indicates that the compare failed for an * unspecified reason. * * @retval * None * @pre * Component has been initialized. * @post * None * @note * None * @see * cpaCySymInitSession(), * cpaCySymRemoveSession() * *****************************************************************************/ typedef void (*CpaCySymCbFunc)(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult); /** ***************************************************************************** * @ingroup cpaCySym * Gets the size required to store a session context. * * @description * This function is used by the client to determine the size of the memory * it must allocate in order to store the session context. This MUST be * called before the client allocates the memory for the session context * and before the client calls the @ref cpaCySymInitSession function. * * For a given implementation of this API, it is safe to assume that * cpaCySymSessionCtxGetSize() will always return the same size and that * the size will not be different for different setup data parameters. * However, it should be noted that the size may change: * (1) between different implementations of the API (e.g. between * software and hardware implementations or between different * hardware implementations) * (2) between different releases of the same API implementation. * * The size returned by this function is the smallest size needed to * support all possible combinations of setup data parameters. Some * setup data parameter combinations may fit within a smaller session * context size. The alternate cpaCySymSessionCtxGetDynamicSize() * function will return the smallest size needed to fit the * provided setup data parameters. * * @context * This is a synchronous function that cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pSessionSetupData Pointer to session setup data which * contains parameters which are static * for a given cryptographic session such * as operation type, mechanisms, and keys * for cipher and/or hash operations. * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required * to hold the Session Context. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * This is a synchronous function and has no completion callback * associated with it. * @see * CpaCySymSessionSetupData * cpaCySymInitSession() * cpaCySymSessionCtxGetDynamicSize() * cpaCySymPerformOp() * *****************************************************************************/ CpaStatus cpaCySymSessionCtxGetSize( const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes); /** ***************************************************************************** * @ingroup cpaCySym * Gets the minimum size required to store a session context. * * @description * This function is used by the client to determine the smallest size of * the memory it must allocate in order to store the session context. * This MUST be called before the client allocates the memory for the * session context and before the client calls the @ref cpaCySymInitSession * function. * * This function is an alternate to cpaCySymSessionGetSize(). * cpaCySymSessionCtxGetSize() will return a fixed size which is the * minimum memory size needed to support all possible setup data parameter * combinations. cpaCySymSessionCtxGetDynamicSize() will return the * minimum memory size needed to support the specific session setup * data parameters provided. This size may be different for different setup * data parameters. * * @context * This is a synchronous function that cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pSessionSetupData Pointer to session setup data which * contains parameters which are static * for a given cryptographic session such * as operation type, mechanisms, and keys * for cipher and/or hash operations. * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required * to hold the Session Context. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * This is a synchronous function and has no completion callback * associated with it. * @see * CpaCySymSessionSetupData * cpaCySymInitSession() * cpaCySymSessionCtxGetSize() * cpaCySymPerformOp() * *****************************************************************************/ CpaStatus cpaCySymSessionCtxGetDynamicSize( const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes); /** ***************************************************************************** * @ingroup cpaCySym * Initialize a session for symmetric cryptographic API. * * @description * This function is used by the client to initialize an asynchronous * completion callback function for the symmetric cryptographic * operations. Clients MAY register multiple callback functions using * this function. * The callback function is identified by the combination of userContext, * pSymCb and session context (sessionCtx). The session context is the * handle to the session and needs to be passed when processing calls. * Callbacks on completion of operations within a session are guaranteed * to be in the same order they were submitted in. * * @context * This is a synchronous function and it cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pSymCb Pointer to callback function to be * registered. Set to NULL if the * cpaCySymPerformOp function is required to * work in a synchronous manner. * @param[in] pSessionSetupData Pointer to session setup data which contains * parameters which are static for a given * cryptographic session such as operation * type, mechanisms, and keys for cipher and/or * hash operations. * @param[out] sessionCtx Pointer to the memory allocated by the * client to store the session context. This * will be initialized with this function. This * value needs to be passed to subsequent * processing calls. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * This is a synchronous function and has no completion callback * associated with it. * @see * CpaCySymSessionCtx, * CpaCySymCbFunc, * CpaCySymSessionSetupData, * cpaCySymRemoveSession(), * cpaCySymPerformOp() * *****************************************************************************/ CpaStatus cpaCySymInitSession(const CpaInstanceHandle instanceHandle, const CpaCySymCbFunc pSymCb, const CpaCySymSessionSetupData *pSessionSetupData, CpaCySymSessionCtx sessionCtx); /** ***************************************************************************** * @ingroup cpaCySym * Remove (delete) a symmetric cryptographic session. * * @description * This function will remove a previously initialized session context * and the installed callback handler function. Removal will fail if * outstanding calls still exist for the initialized session handle. * The client needs to retry the remove function at a later time. * The memory for the session context MUST not be freed until this call * has completed successfully. * * @context * This is a synchronous function that cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in,out] pSessionCtx Session context to be removed. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * * @see * CpaCySymSessionCtx, * cpaCySymInitSession() * *****************************************************************************/ CpaStatus cpaCySymRemoveSession(const CpaInstanceHandle instanceHandle, CpaCySymSessionCtx pSessionCtx); /** ***************************************************************************** * @ingroup cpaCySym * Update a session. * * @description * This function is used to update certain parameters of a session, as * specified by the CpaCySymSessionUpdateData data structure. * * It can be used on sessions created with either the so-called * Traditional API (@ref cpaCySymInitSession) or the Data Plane API * (@ref cpaCySymDpInitSession). * * In order for this function to operate correctly, two criteria must * be met: * * - In the case of sessions created with the Traditional API, the * session must be stateless, i.e. the field partialsNotRequired of * the CpaCySymSessionSetupData data structure must be FALSE. * (Sessions created using the Data Plane API are always stateless.) * * - There must be no outstanding requests in flight for the session. * The application can call the function @ref cpaCySymSessionInUse * to test for this. * * Note that in the case of multi-threaded applications (which are * supported using the Traditional API only), this function may fail * even if a previous invocation of the function @ref * cpaCySymSessionInUse indicated that there were no outstanding * requests. * * @param[in] sessionCtx Identifies the session to be reset. * @param[in] pSessionUpdateData Pointer to session data which contains * the parameters to be updated. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * @post * None * @note * This is a synchronous function and has no completion callback * associated with it. *****************************************************************************/ CpaStatus cpaCySymUpdateSession( CpaCySymSessionCtx sessionCtx, const CpaCySymSessionUpdateData *pSessionUpdateData); /** ***************************************************************************** * @ingroup cpaCySym * Indicates whether there are outstanding requests on a given * session. * * @description * This function is used to test whether there are outstanding * requests in flight for a specified session. This may be used * before resetting session parameters using the function @ref * cpaCySymResetSession. See some additional notes on * multi-threaded applications described on that function. * * @param[in] sessionCtx Identifies the session to be reset. * @param[out] pSessionInUse Returns CPA_TRUE if there are * outstanding requests on the session, * or CPA_FALSE otherwise. *****************************************************************************/ CpaStatus cpaCySymSessionInUse(CpaCySymSessionCtx sessionCtx, CpaBoolean *pSessionInUse); /** ***************************************************************************** * @ingroup cpaCySym * Perform a symmetric cryptographic operation on an existing session. * * @description * Performs a cipher, hash or combined (cipher and hash) operation on * the source data buffer using supported symmetric key algorithms and * modes. * * This function maintains cryptographic state between calls for * partial cryptographic operations. If a partial cryptographic * operation is being performed, then on a per-session basis, the next * part of the multi-part message can be submitted prior to previous * parts being completed, the only limitation being that all parts * must be performed in sequential order. * * If for any reason a client wishes to terminate the partial packet * processing on the session (for example if a packet fragment was lost) * then the client MUST remove the session. * * When using partial packet processing with algorithm chaining, only * the cipher state is maintained between calls. The hash state is * not be maintained between calls. Instead the hash digest will be * generated/verified for each call. If both the cipher state and * hash state need to be maintained between calls, algorithm chaining * cannot be used. * The following restrictions apply to the length: * * - When performing block based operations on a partial packet * (excluding the final partial packet), the data that is to be * operated on MUST be a multiple of the block size of the algorithm * being used. This restriction only applies to the cipher state * when using partial packets with algorithm chaining. * * - The final block must not be of length zero (0) if the operation * being performed is the authentication algorithm @ref * CPA_CY_SYM_HASH_AES_XCBC. This is because this algorithm requires * that the final block be XORed with another value internally. * If the length is zero, then the return code @ref * CPA_STATUS_INVALID_PARAM will be returned. * * - The length of the final block must be greater than or equal to * 16 bytes when using the @ref CPA_CY_SYM_CIPHER_AES_XTS cipher * algorithm. * * Partial packet processing is supported only when the following * conditions are true: * * - The cipher, hash or authentication operation is "in place" (that is, * pDstBuffer == pSrcBuffer) * * - The cipher or hash algorithm is NOT one of Kasumi or SNOW3G * * - The cipher mode is NOT F8 mode. * * - The hash algorithm is NOT SHAKE * * - The cipher algorithm is not SM4 * * - The cipher algorithm is not CPA_CY_SYM_CIPHER_CHACHA and the hash * algorithm is not CPA_CY_SYM_HASH_POLY. * * - The cipher algorithm is not CPA_CY_SYM_CIPHER_AES_GCM and the hash * algorithm is not CPA_CY_SYM_HASH_AES_GCM. * * - The instance/implementation supports partial packets as one of * its capabilities (see @ref CpaCySymCapabilitiesInfo). * * The term "in-place" means that the result of the cryptographic * operation is written into the source buffer. The term "out-of-place" * means that the result of the cryptographic operation is written into * the destination buffer. To perform "in-place" processing, set the * pDstBuffer parameter to point at the same location as the pSrcBuffer * parameter. * * @context * When called as an asynchronous function it cannot sleep. It can be * executed in a context that does not permit sleeping. * When called as a synchronous function it may sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes when configured to operate in synchronous mode. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pCallbackTag Opaque data that will be returned to the client * in the callback. * @param[in] pOpData Pointer to a structure containing request * parameters. The client code allocates the memory * for this structure. This component takes * ownership of the memory until it is returned in * the callback. * @param[in] pSrcBuffer The source buffer. The caller MUST allocate * the source buffer and populate it * with data. For optimum performance, the data * pointed to SHOULD be 8-byte aligned. For * block ciphers, the data passed in MUST be * a multiple of the relevant block size. * i.e. padding WILL NOT be applied to the data. * For optimum performance, the buffer should * only contain the data region that the * cryptographic operation(s) must be performed on. * Any additional data in the source buffer may be * copied to the destination buffer and this copy * may degrade performance. * @param[out] pDstBuffer The destination buffer. The caller MUST * allocate a sufficiently sized destination * buffer to hold the data output (including * the authentication tag in the case of CCM). * Furthermore, the destination buffer must be the * same size as the source buffer (i.e. the sum of * lengths of the buffers in the buffer list must * be the same). This effectively means that the * source buffer must in fact be big enough to hold * the output data, too. This is because, * for out-of-place processing, the data outside * the regions in the source buffer on which * cryptographic operations are performed are * copied into the destination buffer. To perform * "in-place" processing set the pDstBuffer * parameter in cpaCySymPerformOp function to point * at the same location as pSrcBuffer. For optimum * performance, the data pointed to SHOULD be * 8-byte aligned. * @param[out] pVerifyResult In synchronous mode, this parameter is returned * when the verifyDigest option is set in the * CpaCySymSessionSetupData structure. A value of * CPA_TRUE indicates that the compare succeeded. A * value of CPA_FALSE indicates that the compare * failed for an unspecified reason. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resource. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized via cpaCyStartInstance function. * A Cryptographic session has been previously setup using the * @ref cpaCySymInitSession function call. * @post * None * * @note * When in asynchronous mode, a callback of type CpaCySymCbFunc is * generated in response to this function call. Any errors generated during * processing are reported as part of the callback status code. * * @see * CpaCySymOpData, * cpaCySymInitSession(), * cpaCySymRemoveSession() *****************************************************************************/ CpaStatus cpaCySymPerformOp(const CpaInstanceHandle instanceHandle, void *pCallbackTag, const CpaCySymOpData *pOpData, const CpaBufferList *pSrcBuffer, CpaBufferList *pDstBuffer, CpaBoolean *pVerifyResult); /** ***************************************************************************** * @ingroup cpaCySym * Query symmetric cryptographic statistics for a specific instance. * * @deprecated * As of v1.3 of the cryptographic API, this function has been * deprecated, replaced by @ref cpaCySymQueryStats64(). * * @description * This function will query a specific instance for statistics. The * user MUST allocate the CpaCySymStats structure and pass the * reference to that into this function call. This function will write * the statistic results into the passed in CpaCySymStats * structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pSymStats Pointer to memory into which the * statistics will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner, i.e. no asynchronous * callback will be generated. * @see * CpaCySymStats *****************************************************************************/ CpaStatus CPA_DEPRECATED cpaCySymQueryStats(const CpaInstanceHandle instanceHandle, struct _CpaCySymStats *pSymStats); /** ***************************************************************************** * @ingroup cpaCySym * Query symmetric cryptographic statistics (64-bit version) for a * specific instance. * * @description * This function will query a specific instance for statistics. The * user MUST allocate the CpaCySymStats64 structure and pass the * reference to that into this function call. This function will write * the statistic results into the passed in CpaCySymStats64 * structure. * * Note: statistics returned by this function do not interrupt current data * processing and as such can be slightly out of sync with operations that * are in progress during the statistics retrieval process. * * @context * This is a synchronous function and it can sleep. It MUST NOT be * executed in a context that DOES NOT permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[out] pSymStats Pointer to memory into which the * statistics will be written. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * This function operates in a synchronous manner, i.e. no asynchronous * callback will be generated. * @see * CpaCySymStats64 *****************************************************************************/ CpaStatus cpaCySymQueryStats64(const CpaInstanceHandle instanceHandle, CpaCySymStats64 *pSymStats); /** ***************************************************************************** * @ingroup cpaCySym * Symmetric Capabilities Info * * @description * This structure contains the capabilities that vary across * implementations of the symmetric sub-API of the cryptographic API. * This structure is used in conjunction with @ref * cpaCySymQueryCapabilities() to determine the capabilities supported * by a particular API implementation. * * For example, to see if an implementation supports cipher * @ref CPA_CY_SYM_CIPHER_AES_CBC, use the code * * @code if (CPA_BITMAP_BIT_TEST(capInfo.ciphers, CPA_CY_SYM_CIPHER_AES_CBC)) { // algo is supported } else { // algo is not supported } * @endcode * * The client MUST allocate memory for this structure and any members * that require memory. When the structure is passed into the function * ownership of the memory passes to the function. Ownership of the * memory returns to the client when the function returns. *****************************************************************************/ typedef struct _CpaCySymCapabilitiesInfo { CPA_BITMAP(ciphers, CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE); /**< Bitmap representing which cipher algorithms (and modes) are * supported by the instance. * Bits can be tested using the macro @ref CPA_BITMAP_BIT_TEST. * The bit positions are those specified in the enumerated type * @ref CpaCySymCipherAlgorithm. */ CPA_BITMAP(hashes, CPA_CY_SYM_HASH_CAP_BITMAP_SIZE); /**< Bitmap representing which hash/authentication algorithms are * supported by the instance. * Bits can be tested using the macro @ref CPA_BITMAP_BIT_TEST. * The bit positions are those specified in the enumerated type * @ref CpaCySymHashAlgorithm. */ CpaBoolean partialPacketSupported; /**< CPA_TRUE if instance supports partial packets. * See @ref CpaCySymPacketType. */ } CpaCySymCapabilitiesInfo; /** ***************************************************************************** * @ingroup cpaCySym * Returns capabilities of the symmetric API group of a Cryptographic * API instance. * * @description * This function is used to determine which specific capabilities are * supported within the symmetric sub-group of the Cryptographic API. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Handle to an instance of this API. * @param[out] pCapInfo Pointer to capabilities info structure. * All fields in the structure * are populated by the API instance. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The instance has been initialized via the @ref cpaCyStartInstance * function. * @post * None *****************************************************************************/ CpaStatus cpaCySymQueryCapabilities(const CpaInstanceHandle instanceHandle, CpaCySymCapabilitiesInfo *pCapInfo); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_SYM_H */ qatlib-25.08.0/quickassist/include/lac/cpa_cy_sym_dp.h000066400000000000000000001247411503624047500226700ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_cy_sym_dp.h * * @defgroup cpaCySymDp Symmetric cryptographic Data Plane API * * @ingroup cpaCySym * * @description * These data structures and functions specify the Data Plane API * for symmetric cipher, hash, and combined cipher and hash * operations. * * This API is recommended for data plane applications, in which the * cost of offload - that is, the cycles consumed by the driver in * sending requests to the hardware, and processing responses - needs * to be minimized. In particular, use of this API is recommended * if the following constraints are acceptable to your application: * * - Thread safety is not guaranteed. Each software thread should * have access to its own unique instance (CpaInstanceHandle) to * avoid contention. * - Polling is used, rather than interrupts (which are expensive). * Implementations of this API will provide a function (not * defined as part of this API) to read responses from the hardware * response queue and dispatch callback functions, as specified on * this API. * - Buffers and buffer lists are passed using physical addresses, * to avoid virtual to physical address translation costs. * - For GCM and CCM modes of AES, when performing decryption and * verification, if verification fails, then the message buffer * will NOT be zeroed. (This is a consequence of using physical * addresses for the buffers.) * - The ability to enqueue one or more requests without submitting * them to the hardware allows for certain costs to be amortized * across multiple requests. * - Only asynchronous invocation is supported. * - There is no support for partial packets. * - Implementations may provide certain features as optional at * build time, such as atomic counters. * - The "default" instance (@ref CPA_INSTANCE_HANDLE_SINGLE) is not * supported on this API. The specific handle should be obtained * using the instance discovery functions (@ref cpaCyGetNumInstances, * @ref cpaCyGetInstances). * * @note Performance Trade-Offs * Different implementations of this API may have different performance * trade-offs; please refer to the documentation for your implementation * for details. However, the following concepts informed the definition * of this API. * * The API distinguishes between enqueuing a request and actually * submitting that request to the cryptographic acceleration * engine to be performed. This allows multiple requests to be enqueued * (either individually or in batch), and then for all enqueued requests * to be submitted in a single operation. The rationale is that in some * (especially hardware-based) implementations, the submit operation * is expensive; for example, it may incur an MMIO instruction. The * API allows this cost to be amortized over a number of requests. The * precise number of such requests can be tuned for optimal * performance. * * Specifically: * * - The function @ref cpaCySymDpEnqueueOp allows one request to be * enqueued, and optionally for that request (and all previously * enqueued requests) to be submitted. * - The function @ref cpaCySymDpEnqueueOpBatch allows multiple * requests to be enqueued, and optionally for those requests (and all * previously enqueued requests) to be submitted. * - The function @ref cpaCySymDpPerformOpNow enqueues no requests, but * submits all previously enqueued requests. *****************************************************************************/ #ifndef CPA_CY_SYM_DP_H #define CPA_CY_SYM_DP_H #ifdef __cplusplus extern "C" { #endif #include "cpa_cy_common.h" #include "cpa_cy_sym.h" /** ***************************************************************************** * @ingroup cpaCySymDp * Cryptographic component symmetric session context handle for the * data plane API. * @description * Handle to a cryptographic data plane session context. The memory for * this handle is allocated by the client. The size of the memory that * the client needs to allocate is determined by a call to the @ref * cpaCySymDpSessionCtxGetSize or @ref cpaCySymDpSessionCtxGetDynamicSize * functions. The session context memory is initialized with a call to * the @ref cpaCySymInitSession function. * This memory MUST not be freed until a call to @ref * cpaCySymDpRemoveSession has completed successfully. * *****************************************************************************/ typedef void *CpaCySymDpSessionCtx; /** ***************************************************************************** * @ingroup cpaCySymDp * Operation Data for cryptographic data plane API. * * @description * This structure contains data relating to a request to perform * symmetric cryptographic processing on one or more data buffers. * * The physical memory to which this structure points needs to be * at least 8-byte aligned. * * All reserved fields SHOULD NOT be written or read by the * calling code. * * @see * cpaCySymDpEnqueueOp, cpaCySymDpEnqueueOpBatch ****************************************************************************/ typedef struct _CpaCySymDpOpData { Cpa64U reserved0; /**< Reserved for internal usage. */ Cpa32U cryptoStartSrcOffsetInBytes; /**< Starting point for cipher processing, specified as number of bytes * from start of data in the source buffer. The result of the cipher * operation will be written back into the buffer starting at this * location in the destination buffer. */ Cpa32U messageLenToCipherInBytes; /**< The message length, in bytes, of the source buffer on which the * cryptographic operation will be computed. This must be a multiple of * the block size if a block cipher is being used. This is also the * same as the result length. * * @note In the case of CCM (@ref CPA_CY_SYM_HASH_AES_CCM), this value * should not include the length of the padding or the length of the * MAC; the driver will compute the actual number of bytes over which * the encryption will occur, which will include these values. * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC), this field * should be set to 0. * * @note On some implementations, this length may be limited to a 16-bit * value (65535 bytes). */ CpaPhysicalAddr iv; /**< Initialization Vector or Counter. Specifically, this is the * physical address of one of the following: * * - For block ciphers in CBC mode, or for Kasumi in F8 mode, or for * SNOW3G in UEA2 mode, this is the Initialization Vector (IV) * value. * - For ARC4, this is reserved for internal usage. * - For block ciphers in CTR mode, this is the counter. * - For GCM mode, this is either the IV (if the length is 96 bits) or J0 * (for other sizes), where J0 is as defined by NIST SP800-38D. * Regardless of the IV length, a full 16 bytes needs to be allocated. * - For CCM mode, the first byte is reserved, and the nonce should be * written starting at &pIv[1] (to allow space for the implementation * to write in the flags in the first byte). Note that a full 16 bytes * should be allocated, even though the ivLenInBytes field will have * a value less than this. * The macro @ref CPA_CY_SYM_CCM_SET_NONCE may be used here. */ Cpa64U reserved1; /**< Reserved for internal usage. */ Cpa32U hashStartSrcOffsetInBytes; /**< Starting point for hash processing, specified as number of bytes * from start of packet in source buffer. * * @note For CCM and GCM modes of operation, this value in this field * is ignored, and the field is reserved for internal usage. * The fields @ref additionalAuthData and @ref pAdditionalAuthData * should be set instead. * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of * operation, this field specifies the start of the AAD data in * the source buffer. */ Cpa32U messageLenToHashInBytes; /**< The message length, in bytes, of the source buffer that the hash * will be computed on. * * @note For CCM and GCM modes of operation, this value in this field * is ignored, and the field is reserved for internal usage. * The fields @ref additionalAuthData and @ref pAdditionalAuthData * should be set instead. * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of * operation, this field specifies the length of the AAD data in the * source buffer. * * @note On some implementations, this length may be limited to a 16-bit * value (65535 bytes). */ CpaPhysicalAddr additionalAuthData; /**< Physical address of the Additional Authenticated Data (AAD), * which is needed for authenticated cipher mechanisms (CCM and * GCM), and to the IV for SNOW3G authentication (@ref * CPA_CY_SYM_HASH_SNOW3G_UIA2). For other authentication * mechanisms, this value is ignored, and the field is reserved for * internal usage. * * The length of the data pointed to by this field is set up for * the session in the @ref CpaCySymHashAuthModeSetupData structure * as part of the @ref cpaCySymDpInitSession function call. This length * must not exceed 240 bytes. * If AAD is not used, this address must be set to zero. * * Specifically for CCM (@ref CPA_CY_SYM_HASH_AES_CCM) and GCM (@ref * CPA_CY_SYM_HASH_AES_GCM), the caller should be setup as described in * the same way as the corresponding field, pAdditionalAuthData, on the * "traditional" API (see the @ref CpaCySymOpData). * * @note For AES-GMAC (@ref CPA_CY_SYM_HASH_AES_GMAC) mode of * operation, this field is not used and should be set to 0. Instead * the AAD data should be placed in the source buffer. * */ CpaPhysicalAddr digestResult; /**< If the digestIsAppended member of the @ref CpaCySymSessionSetupData * structure is NOT set then this is the physical address of the location * where the digest result should be inserted (in the case of digest * generation) or where the purported digest exists (in the case of digest * verification). * * At session registration time, the client specified the digest result * length with the digestResultLenInBytes member of the @ref * CpaCySymHashSetupData structure. The client must allocate at least * digestResultLenInBytes of physically contiguous memory at this location. * * For digest generation, the digest result will overwrite any data * at this location. * * @note For GCM (@ref CPA_CY_SYM_HASH_AES_GCM), for "digest result" * read "authentication tag T". * * If the digestIsAppended member of the @ref CpaCySymSessionSetupData * structure is set then this value is ignored and the digest result * is understood to be in the destination buffer for digest generation, * and in the source buffer for digest verification. The location of the * digest result in this case is immediately following the region over * which the digest is computed. */ CpaInstanceHandle instanceHandle; /**< Instance to which the request is to be enqueued. * @note A callback function must have been registered on the instance * using @ref cpaCySymDpRegCbFunc. */ CpaCySymDpSessionCtx sessionCtx; /**< Session context specifying the cryptographic parameters for this * request. * @note The session must have been created using @ref * cpaCySymDpInitSession. */ Cpa32U ivLenInBytes; /**< Length of valid IV data pointed to by the pIv parameter. * * - For block ciphers in CBC mode, or for Kasumi in F8 mode, or for * SNOW3G in UEA2 mode, this is the length of the IV (which * must be the same as the block length of the cipher). * - For block ciphers in CTR mode, this is the length of the counter * (which must be the same as the block length of the cipher). * - For GCM mode, this is either 12 (for 96-bit IVs) or 16, in which * case pIv points to J0. * - For CCM mode, this is the length of the nonce, which can be in the * range 7 to 13 inclusive. */ CpaPhysicalAddr srcBuffer; /**< Physical address of the source buffer on which to operate. * This is either: * * - The location of the data, of length srcBufferLen; or, * - If srcBufferLen has the special value @ref CPA_DP_BUFLIST, then * srcBuffer contains the location where a @ref CpaPhysBufferList is * stored. In this case, the CpaPhysBufferList MUST be aligned * on an 8-byte boundary. * - For optimum performance, the buffer should only contain the data * region that the cryptographic operation(s) must be performed on. * Any additional data in the source buffer may be copied to the * destination buffer and this copy may degrade performance. */ Cpa32U srcBufferLen; /**< Length of source buffer, or @ref CPA_DP_BUFLIST. */ CpaPhysicalAddr dstBuffer; /**< Physical address of the destination buffer on which to operate. * This is either: * * - The location of the data, of length srcBufferLen; or, * - If srcBufferLen has the special value @ref CPA_DP_BUFLIST, then * srcBuffer contains the location where a @ref CpaPhysBufferList is * stored. In this case, the CpaPhysBufferList MUST be aligned * on an 8-byte boundary. * * For "in-place" operation, the dstBuffer may be identical to the * srcBuffer. */ Cpa32U dstBufferLen; /**< Length of destination buffer, or @ref CPA_DP_BUFLIST. */ CpaPhysicalAddr thisPhys; /**< Physical address of this data structure */ Cpa8U *pIv; /**< Pointer to (and therefore, the virtual address of) the IV field * above. * Needed here because the driver in some cases writes to this field, * in addition to sending it to the accelerator. */ Cpa8U *pAdditionalAuthData; /**< Pointer to (and therefore, the virtual address of) the * additionalAuthData field above. * Needed here because the driver in some cases writes to this field, * in addition to sending it to the accelerator. */ void *pCallbackTag; /**< Opaque data that will be returned to the client in the function * completion callback. * * This opaque data is not used by the implementation of the API, * but is simply returned as part of the asynchronous response. * It may be used to store information that might be useful when * processing the response later. */ } CpaCySymDpOpData; /** ***************************************************************************** * @ingroup cpaCySymDp * Definition of callback function for cryptographic data plane API. * * @description * This is the callback function prototype. The callback function is * registered by the application using the @ref cpaCySymDpRegCbFunc * function call, and called back on completion of asynchronous * requests made via calls to @ref cpaCySymDpEnqueueOp or @ref * cpaCySymDpEnqueueOpBatch. * * @context * This callback function can be executed in a context that DOES NOT * permit sleeping to occur. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] pOpData Pointer to the CpaCySymDpOpData object which * was supplied as part of the original request. * @param[in] status Status of the operation. Valid values are * CPA_STATUS_SUCCESS, CPA_STATUS_FAIL and * CPA_STATUS_UNSUPPORTED. * @param[in] verifyResult This parameter is valid when the verifyDigest * option is set in the CpaCySymSessionSetupData * structure. A value of CPA_TRUE indicates that * the compare succeeded. A value of CPA_FALSE * indicates that the compare failed. * * @return * None * @pre * Component has been initialized. * Callback has been registered with @ref cpaCySymDpRegCbFunc. * @post * None * @note * None * @see * cpaCySymDpRegCbFunc *****************************************************************************/ typedef void (*CpaCySymDpCbFunc)(CpaCySymDpOpData *pOpData, CpaStatus status, CpaBoolean verifyResult); /** ***************************************************************************** * @ingroup cpaCySymDp * Registration of the operation completion callback function. * * @description * This function allows a completion callback function to be registered. * The registered callback function is invoked on completion of * asynchronous requests made via calls to @ref cpaCySymDpEnqueueOp * or @ref cpaCySymDpEnqueueOpBatch. * * If a callback function was previously registered, it is overwritten. * * @context * This is a synchronous function and it cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] instanceHandle Instance on which the callback function is to be * registered. * @param[in] pSymNewCb Callback function for this instance. * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * Component has been initialized. * @post * None * @note * None * @see * CpaCySymDpCbFunc *****************************************************************************/ CpaStatus cpaCySymDpRegCbFunc(const CpaInstanceHandle instanceHandle, const CpaCySymDpCbFunc pSymNewCb); /** ***************************************************************************** * @ingroup cpaCySymDp * Gets the size required to store a session context for the data plane * API. * * @description * This function is used by the client to determine the size of the memory * it must allocate in order to store the session context. This MUST be * called before the client allocates the memory for the session context * and before the client calls the @ref cpaCySymDpInitSession function. * * For a given implementation of this API, it is safe to assume that * cpaCySymDpSessionCtxGetSize() will always return the same size and that * the size will not be different for different setup data parameters. * However, it should be noted that the size may change: * (1) between different implementations of the API (e.g. between * software and hardware implementations or between different * hardware implementations) * (2) between different releases of the same API implementation. * * The size returned by this function is the smallest size needed to * support all possible combinations of setup data parameters. Some * setup data parameter combinations may fit within a smaller session * context size. The alternate cpaCySymDpSessionCtxGetDynamicSize() * function will return the smallest size needed to fit the * provided setup data parameters. * * @context * This is a synchronous function that cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pSessionSetupData Pointer to session setup data which * contains parameters which are static * for a given cryptographic session such * as operation type, mechanisms, and keys * for cipher and/or hash operations. * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required * to hold the Session Context. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * @post * None * @note * This is a synchronous function and has no completion callback * associated with it. * @see * CpaCySymSessionSetupData * cpaCySymDpSessionCtxGetDynamicSize() * cpaCySymDpInitSession() *****************************************************************************/ CpaStatus cpaCySymDpSessionCtxGetSize( const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes); /** ***************************************************************************** * @ingroup cpaCySymDp * Gets the minimum size required to store a session context for the data * plane API. * * @description * This function is used by the client to determine the smallest size of * the memory it must allocate in order to store the session context. * This MUST be called before the client allocates the memory for the * session context and before the client calls the * @ref cpaCySymDpInitSession function. * * This function is an alternate to cpaCySymDpSessionGetSize(). * cpaCySymDpSessionCtxGetSize() will return a fixed size which is the * minimum memory size needed to support all possible setup data parameter * combinations. cpaCySymDpSessionCtxGetDynamicSize() will return the * minimum memory size needed to support the specific session setup * data parameters provided. This size may be different for different setup * data parameters. * * @context * This is a synchronous function that cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] pSessionSetupData Pointer to session setup data which * contains parameters which are static * for a given cryptographic session such * as operation type, mechanisms, and keys * for cipher and/or hash operations. * @param[out] pSessionCtxSizeInBytes The amount of memory in bytes required * to hold the Session Context. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * @post * None * @note * This is a synchronous function and has no completion callback * associated with it. * @see * CpaCySymSessionSetupData * cpaCySymDpSessionCtxGetSize() * cpaCySymDpInitSession() *****************************************************************************/ CpaStatus cpaCySymDpSessionCtxGetDynamicSize( const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes); /** ***************************************************************************** * @ingroup cpaCySymDp * Initialize a session for the symmetric cryptographic data plane API. * * @description * This function is used by the client to initialize an asynchronous * session context for symmetric cryptographic data plane operations. * The returned session context is the handle to the session and needs to * be passed when requesting cryptographic operations to be performed. * * Only sessions created using this function may be used when * invoking functions on this API * * The session can be removed using @ref cpaCySymDpRemoveSession. * * @context * This is a synchronous function and it cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] instanceHandle Instance to which the requests will be * submitted. * @param[in] pSessionSetupData Pointer to session setup data which * contains parameters that are static * for a given cryptographic session such * as operation type, algorithm, and keys * for cipher and/or hash operations. * @param[out] sessionCtx Pointer to the memory allocated by the * client to store the session context. This * memory must be physically contiguous, and * its length (in bytes) must be at least as * big as specified by a call to @ref * cpaCySymDpSessionCtxGetSize. This memory * will be initialized with this function. This * value needs to be passed to subsequent * processing calls. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * @post * None * @note * This is a synchronous function and has no completion callback * associated with it. * @see * cpaCySymDpSessionCtxGetSize, cpaCySymDpRemoveSession *****************************************************************************/ CpaStatus cpaCySymDpInitSession( CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, CpaCySymDpSessionCtx sessionCtx); /** ***************************************************************************** * @ingroup cpaCySymDp * Remove (delete) a symmetric cryptographic session for the data plane * API. * * @description * This function will remove a previously initialized session context * and the installed callback handler function. Removal will fail if * outstanding calls still exist for the initialized session handle. * The client needs to retry the remove function at a later time. * The memory for the session context MUST not be freed until this call * has completed successfully. * * @context * This is a synchronous function that cannot sleep. It can be * executed in a context that does not permit sleeping. * @assumptions * None * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] instanceHandle Instance handle. * @param[in,out] sessionCtx Session context to be removed. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * @post * None * @note * Note that this is a synchronous function and has no completion callback * associated with it. * * @see * CpaCySymDpSessionCtx, * cpaCySymDpInitSession() * *****************************************************************************/ CpaStatus cpaCySymDpRemoveSession(const CpaInstanceHandle instanceHandle, CpaCySymDpSessionCtx sessionCtx); /** ***************************************************************************** * @ingroup cpaCySymDp * Enqueue a single symmetric cryptographic request. * * @description * This function enqueues a single request to perform a cipher, * hash or combined (cipher and hash) operation. Optionally, the * request is also submitted to the cryptographic engine to be * performed. * * See note about performance trade-offs on the @ref cpaCySymDp API. * * The function is asynchronous; control is returned to the user once * the request has been submitted. On completion of the request, the * application may poll for responses, which will cause a callback * function (registered via @ref cpaCySymDpRegCbFunc) to be invoked. * Callbacks within a session are guaranteed to be in the same order * in which they were submitted. * * The following restrictions apply to the pOpData parameter: * * - The memory MUST be aligned on an 8-byte boundary. * - The structure MUST reside in physically contiguous memory. * - The reserved fields of the structure SHOULD NOT be written * or read by the calling code. * * @context * This function will not sleep, and hence can be executed in a context * that does not permit sleeping. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] pOpData Pointer to a structure containing the * request parameters. The client code allocates * the memory for this structure. This component * takes ownership of the memory until it is * returned in the callback, which was registered * on the instance via @ref cpaCySymDpRegCbFunc. * See the above Description for restrictions * that apply to this parameter. * @param[in] performOpNow Flag to specify whether the operation should be * performed immediately (CPA_TRUE), or simply * enqueued to be performed later (CPA_FALSE). * In the latter case, the request is submitted * to be performed either by calling this * function again with this flag set to CPA_TRUE, * or by invoking the function *@ref cpaCySymDpPerformOpNow. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The session identified by pOpData->sessionCtx was setup using * @ref cpaCySymDpInitSession. * The instance identified by pOpData->instanceHandle has had a * callback function registered via @ref cpaCySymDpRegCbFunc. * * @post * None * * @note * A callback of type @ref CpaCySymDpCbFunc is generated in response to * this function call. Any errors generated during processing are * reported as part of the callback status code. * * @see * cpaCySymDpInitSession, * cpaCySymDpPerformOpNow *****************************************************************************/ CpaStatus cpaCySymDpEnqueueOp(CpaCySymDpOpData *pOpData, const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaCySymDp * Enqueue multiple requests to the symmetric cryptographic data plane * API. * * @description * This function enqueues multiple requests to perform cipher, hash * or combined (cipher and hash) operations. * See note about performance trade-offs on the @ref cpaCySymDp API. * * The function is asynchronous; control is returned to the user once * the request has been submitted. On completion of the request, the * application may poll for responses, which will cause a callback * function (registered via @ref cpaCySymDpRegCbFunc) to be invoked. * Separate callbacks will be invoked for each request. * Callbacks within a session are guaranteed to be in the same order * in which they were submitted. * * The following restrictions apply to each element of the pOpData * array: * * - The memory MUST be aligned on an 8-byte boundary. * - The structure MUST reside in physically contiguous memory. * - The reserved fields of the structure SHOULD NOT be * written or read by the calling code. * * @context * This function will not sleep, and hence can be executed in a context * that does not permit sleeping. * * @assumptions * Client MUST allocate the request parameters to 8 byte alignment. * Reserved elements of the CpaCySymDpOpData structure MUST be 0. * The CpaCySymDpOpData structure MUST reside in physically * contiguous memory. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] numberRequests The number of requests in the array of * CpaCySymDpOpData structures. * @param[in] pOpData An array of pointers to CpaCySymDpOpData * structures. Each of the CpaCySymDpOpData * structure contains the request parameters for * that request. The client code allocates the * memory for this structure. This component takes * ownership of the memory until it is returned in * the callback, which was registered on the * instance via @ref cpaCySymDpRegCbFunc. * See the above Description for restrictions * that apply to this parameter. * @param[in] performOpNow Flag to specify whether the operation should be * performed immediately (CPA_TRUE), or simply * enqueued to be performed later (CPA_FALSE). * In the latter case, the request is submitted * to be performed either by calling this function * again with this flag set to CPA_TRUE, or by * invoking the function @ref * cpaCySymDpPerformOpNow. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The session identified by pOpData[i]->sessionCtx was setup using * @ref cpaCySymDpInitSession. * The instance identified by pOpData->instanceHandle[i] has had a * callback function registered via @ref cpaCySymDpRegCbFunc. * * @post * None * * @note * Multiple callbacks of type @ref CpaCySymDpCbFunc are generated in * response to this function call (one per request). Any errors * generated during processing are reported as part of the callback * status code. * * @see * cpaCySymDpInitSession, * cpaCySymDpEnqueueOp *****************************************************************************/ CpaStatus cpaCySymDpEnqueueOpBatch(const Cpa32U numberRequests, CpaCySymDpOpData *pOpData[], const CpaBoolean performOpNow); /** ***************************************************************************** * @ingroup cpaCySymDp * Submit any previously enqueued requests to be performed now on the * symmetric cryptographic data plane API. * * @description * If any requests/operations were enqueued via calls to @ref * cpaCySymDpEnqueueOp and/or @ref cpaCySymDpEnqueueOpBatch, but with * the flag performOpNow set to @ref CPA_FALSE, then these operations * will now be submitted to the accelerator to be performed. * * See note about performance trade-offs on the @ref cpaCySymDp API. * * @context * Will not sleep. It can be executed in a context that does not * permit sleeping. * * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * No * * @param[in] instanceHandle Instance to which the requests will be * submitted. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * * @pre * The component has been initialized. * A cryptographic session has been previously setup using the * @ref cpaCySymDpInitSession function call. * * @post * None * * @see * cpaCySymDpEnqueueOp, cpaCySymDpEnqueueOpBatch *****************************************************************************/ CpaStatus cpaCySymDpPerformOpNow(CpaInstanceHandle instanceHandle); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_CY_SYM_DP_H */ qatlib-25.08.0/quickassist/include/rl/000077500000000000000000000000001503624047500175535ustar00rootroot00000000000000qatlib-25.08.0/quickassist/include/rl/cpa_rl.h000066400000000000000000001042321503624047500211660ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_rl.h * * @defgroup cpaRl Rate Limiting API * * @ingroup cpa * * * @description * Rate limiting feature is a feature designed in QAT software to enforce * Service Level Agreements (SLA), which allocate a specified amount of * acceleration capacity for a specified service at a ring-pair or * queue-pair (QP) granularity. * * A single queue-pair or a bundle of queue-pairs can be assigned to * guest virtual machines or to the host. However, rate limits can only * be allocated by the host. * * These functions specify the API for setting and querying the rate * limits with respect to device, instance and queue-pair. * * Terminology: * CIR - Committed Information Rate. A value used to specify the committed * rate for a QP. A given QP should always be able to use the * acceleration bandwidth up to its CIR value * PIR - Peak Information Rate. A value used to specify the peak rate for * a QP. A given QP cannot use acceleration bandwidth beyond its PIR * value. The PIR value is always >= CIR value. * * @remarks * *****************************************************************************/ #ifndef CPA_RL_H #define CPA_RL_H #ifdef __cplusplus extern "C" { #endif #ifndef CPA_H #include "cpa.h" #endif /** ***************************************************************************** * @ingroup cpaRl * Supported additional details from accelerator * * @description * This enumeration lists the supported additional details about rate * limiting requests status from accelerator. * *****************************************************************************/ typedef enum _CpaRlError { CPA_STATUS_RL_FAIL = -1, /**< Failure not covered in the other cases */ CPA_STATUS_RL_FAIL_IO = -2, /**< Failed to send request to hardware */ CPA_STATUS_RL_NOT_ENABLED = -3, /* Rate limiting is not enabled */ CPA_STATUS_RL_INVALID_CIR_PIR = -4, /* CIR or PIR is beyond the parent node capacity */ CPA_STATUS_RL_SLA_NOT_CONFIGURED = -5, /* For SLA delete, SLA is not configured on the QP */ } CpaRlError; /** ***************************************************************************** * @ingroup cpaRl * Rate limiting handle type. * * @description * Handle used to uniquely identify a QP to configure sla. * *****************************************************************************/ typedef void *CpaRlQpHandle; /** ***************************************************************************** * @ingroup cpaRl * Rate limiting property handle type. * * @description * Handle used to identify a specific device's rate limiting properties * for a specific service. The properties includes available and remaining * number of interfaces for SLA configuration, PIR and CIR. * *****************************************************************************/ typedef void *CpaRlPropertiesHandle; /** ***************************************************************************** * @ingroup cpa * User SLA Info Structure * * @description * Structure that contains the CIR, PIR and service type for a handle. * The value of cir and pir are absolute value in Mbps or Kops. The unit * is dependent on the service type as following: * Sym and Dc: Mbps * Asym: Kops * *****************************************************************************/ typedef struct _CpaUserSla { CpaAccelerationServiceType svcType; /**< Service type associated with the cpaQpHandle. * Supported service types are CPA_ACC_SVC_TYPE_DATA_COMPRESSION, * CPA_ACC_SVC_TYPE_CRYPTO_ASYM and CPA_ACC_SVC_TYPE_CRYPTO_SYM. * This parameter is only for checking, and not a setter param. */ Cpa32U cir; /**< Committed Information Rate for the associated cpaQpHandle. * With a correctly provisioned configuration, a QP should always be able * to use acceleration bandwidth up to its CIR. */ Cpa32U pir; /**< Peak Information Rate for the associated cpaQpHandle. * The handle's rate must not exceed this. PIR is always >= CIR. */ } CpaUserSla; /** ***************************************************************************** * @ingroup cpaRl * Get the rate limiting properties handle associated with a device for * the service type. * * @description * This function gets the rate limiting properties handle associated with * a device for the given service type. * * This function is called for a user application to discover rate limiting * properties on a device of specific service type. Error code is returned * if incorrect device ID or service type is called. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] devIdx Device index from which to fetch the rate * limiting handle. * @param[in] svcType The service type that the rate limiting * handle is associated with. * @param[out] handle Pointer to rate limiting handle or NULL if * failed to fetch, incorrect device index * or/and incorrect service type. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS A handle was successfully retrieved. * @retval CPA_STATUS_FAIL Function failed to fetch a handle. * @retval CPA_STATUS_INVALID_PARAM Invalid device index or invalid service * type. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaGetDevRlPropertiesHandle(Cpa16U devIdx, const CpaAccelerationServiceType svcType, CpaRlPropertiesHandle *handle, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Get the number of interfaces that can be assigned an SLA with respect * to a rate limiting handle. * * @description * This function is used to query total number of interfaces for this * service that can be assigned and the number of interfaces that are * currently unassigned. * * The value of total interfaces and remaining interfaces on a physical * device are HW dependent. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Rate limiting handle * @param[out] totalSlaInterfaces Total number of interfaces that can be as- * signed an SLA on a device with a service * that a rate limiting handle represents. * @param[out] remSlaInterfaces Number of unassigned interfaces for SLA on * a device with a service that a rate * limiting handle represents. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS Query the total number of interfaces and * unassigned interfaces successfully. * @retval CPA_STATUS_FAIL Function failed to query total interfaces * and unassigned interfaces for SLA. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaRlPropGetNumInterfaces(const CpaRlPropertiesHandle handle, Cpa32U *totalSlaInterfaces, Cpa32U *remSlaInterfaces, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Get the current CIR values with respect to rate limiting handle * * @description * This function is used to query total CIR and remaining CIR for the * service represented on a specific QAT device represented by the handle. * * The returned value of CIRs are absolute value in Mbps or Kops. The unit * is dependent on the service type as following: * Sym and Dc: Mbps * Asym: Kops * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Rate limiting handle specifies a service * on a specific QAT device. * @param[out] totalCir Total CIR on a device with a service that * a rate limiting handle represents. * @param[out] remCir Remaining CIR on a device with a service * that a rate limiting handle represents. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS CIR query on a handle successfully * @retval CPA_STATUS_FAIL Function failed to query CIR on that rate * limiting handle. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaGetDevRlPropSlaCir(const CpaRlPropertiesHandle handle, Cpa32U *totalCir, Cpa32U *remCir, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Get the current PIR values with respect to rate limiting handle * * @description * This function is used to query total PIR and total assigned PIR for * the service represented on a specific QAT device represented by the * handle. * * The returned value of PIR are absolute value in Mbps or Kops. The unit * is dependent on the service type as following: * Sym and Dc: Mbps * Asym: Kops * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Rate limiting handle specifies a service * on a specific QAT device. * @param[out] totalPir Total PIR on a device with a service that * a rate limiting handle represents. * @param[out] totalAssignedPir Total assigned PIR to QPs on a device * with a service that a rate limiting handle * represents. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS PIR queries on a handle successfully * @retval CPA_STATUS_FAIL Function failed to query PIR on that rate * limiting handle. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaGetDevRlPropSlaPir(const CpaRlPropertiesHandle handle, Cpa32U *totalPir, Cpa32U *totalAssignedPir, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Get PIR setting on current instance handle. * * @description * This function is used to query the PIR of an instance. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle An instance handle. * @param[out] pirSetting PIR value set on selected instance. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS PIR queries on an instance successfully. * @retval CPA_STATUS_FAIL Function failed to query PIR on that * instance. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * None * @post * None * @see * None * @note * This API can only be inside the partition where the instance is assigned * *****************************************************************************/ CpaStatus cpaGetInstanceRlSlaPir(const CpaInstanceHandle handle, Cpa32U *pirSetting, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Get CIR setting on current instance handle. * * @description * This function is used to query the CIR of an instance. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle An instance handle. * @param[out] cirSetting CIR value set on selected instance. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS CIR queries on an instance successfully * @retval CPA_STATUS_FAIL Function failed to query CIR on that * instance. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * None * @post * None * @see * None * @note * This API can only be inside the partition where the instance is assigned * *****************************************************************************/ CpaStatus cpaGetInstanceRlSlaCir(const CpaInstanceHandle handle, Cpa32U *cirSetting, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Get the number of handles associated with a device for * the service type. * * @description * This function gets the number of handles associated with * a device for the given service type. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] devIdx Device id to fetch the number of * handles from. * @param[in] svcType Service type of the handles. * @param[out] numHandles Number of handles associated * with the service type. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS Number of handles fetched successfully. * @retval CPA_STATUS_FAIL Failed to get the number of handles * associated with the device for the given * service type. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaRlGetQpNumHandles(Cpa32U devIdx, CpaAccelerationServiceType svcType, Cpa8U *numHandles, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Get the handles associated with a device for the given service type. * * @description * This function gets the handles associated with a device for the given * service type. These handles can then be used as input parameters with * other Rate limiting API. * * This function will populate an array that has been allocated by the * caller. The size of this array is determined by the * cpaGetQpNumHandles() function. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] devIdx Device id to fetch the handles from. * @param[in] svcType Service type of the handles to fetch. * @param[in/out] handles Pointer to where the handles will be * written. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS Handles fetched successfully. * @retval CPA_STATUS_FAIL Function failed to fetch handles from * the device of that service type. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaRlGetQpHandles(Cpa32U devIdx, CpaAccelerationServiceType svcType, CpaRlQpHandle *handles, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Set the SLA information on the given QP handle. * * @description * This function sets the SLA information on the given QP handle. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Handle to the QP. * @param[in] sla SLA information to be set. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * CPA_STATUS_RL_INVALID_CIR_PIR if CIR or * PIR requested exceeds device available * capacity. * CPA_STATUS_RL_FAIL_IO if failed to send * request to hardware. * @retval CPA_STATUS_SUCCESS SLA is created successfully. * @retval CPA_STATUS_FAIL Function failed to set SLA on the given * handle. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * @retVal CPA_STATUS_RESOURCE Error related to system resources. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaSetRlSla(CpaRlQpHandle handle, CpaUserSla *sla, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Delete the SLA information associated with the handle. * * @description * This function deletes the SLA information associated with the handle. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Handle to the QP. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * CPA_STATUS_RL_SLA_NOT_CONFIGURED if SLA is * not configured on this QP. * CPA_STATUS_RL_FAIL_IO if failed to send * request to hardware. * @retval CPA_STATUS_SUCCESS SLA is deleted successfully. * @retval CPA_STATUS_FAIL Function failed to delete SLA on that * handle. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * @retVal CPA_STATUS_RESOURCE Error related to system resources. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaDeleteRlSla(CpaRlQpHandle handle, CpaRlError *rlStatus); /** ***************************************************************************** * @ingroup cpaRl * Get the SLA information associated with the handle. * * @description * This function gets the SLA information associated with the handle. * * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Handle to the QP. * @param[out] sla SLA information. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_NOT_ENABLED if rate limiting * is not enabled. * @retval CPA_STATUS_SUCCESS SLA information is fetched successfully. * @retval CPA_STATUS_FAIL Function failed to query SLA information * on that instance. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * * @pre * Rate limiting has been enabled via cpaEnableRateLimiting() function. * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaGetRlSla(const CpaRlQpHandle handle, CpaUserSla *sla, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Enable Rate limiting. * * @description * This function enables rate limiting if it is not already enabled. * If the rate limiting is already enabled, then the function would * return successfully. * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] devIdx Device index to enable rate limiting. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_FAIL_IO if failed to send * request to hardware. * @retval CPA_STATUS_SUCCESS Enabled rate limiting successfully. * @retval CPA_STATUS_FAIL Failed to enable rate limiting. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * @retVal CPA_STATUS_RESOURCE Error related to system resources. * * @pre * None * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaEnableRateLimiting(Cpa32U devIdx, CpaRlError *rlError); /** ***************************************************************************** * @ingroup cpaRl * Disable Rate limiting. * * @description * This function disables rate limiting if it is already enabled. * If the rate limiting is already disabled, then the function would * return successfully. * @context * The function shall not be called in an interrupt context. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] devIdx Device index to disable rate limiting. * @param[out] rlError Error status of rate limiting query. This * parameter is only valid if CPA_STATUS_FAIL * is returned. * CPA_STATUS_RL_FAIL_IO if failed to send * request to hardware. * @retval CPA_STATUS_SUCCESS Disabled rate limiting successfully. * @retval CPA_STATUS_FAIL Failed to disable rate limiting. * @retval CPA_STATUS_UNSUPPORTED Feature is not supported. * @retVal CPA_STATUS_RESOURCE Error related to system resources. * * @pre * None * @post * None * @see * None * @note * This function can only be called from the partition that has the * physical function (PF) device mapped. * *****************************************************************************/ CpaStatus cpaDisableRateLimiting(Cpa32U devIdx, CpaRlError *rlError); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* CPA_RL_H */ qatlib-25.08.0/quickassist/lookaside/000077500000000000000000000000001503624047500174655ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/000077500000000000000000000000001503624047500221225ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/include/000077500000000000000000000000001503624047500235455ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/include/adf_kernel_types.h000066400000000000000000000064361503624047500272450ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef ADF_KERNEL_TYPES_H #define ADF_KERNEL_TYPES_H #ifdef USER_SPACE #include #define u64 uint64_t #define u32 uint32_t #define u16 uint16_t #define u8 uint8_t #define s64 int64_t #define s32 int32_t #define s16 int16_t #define s8 int8_t #ifndef __packed #define __packed __attribute__((__packed__)) #endif #ifndef __aligned #define __aligned(x) __attribute__((aligned(x))) #endif #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_accel_devices.h000066400000000000000000000266261503624047500273360ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /***************************************************************************** * @file icp_accel_devices.h * * @defgroup Acceleration Driver Framework * * @ingroup icp_Adf * * @description * This is the top level header file that contains the layout of the ADF * icp_accel_dev_t structure and related macros/definitions. * It can be used to dereference the icp_accel_dev_t *passed into upper * layers. * *****************************************************************************/ #ifndef ICP_ACCEL_DEVICES_H_ #define ICP_ACCEL_DEVICES_H_ #include "cpa.h" #include "Osal.h" #define ADF_CFG_MAX_STR_LEN 128 #define MAX_DEVICE_NAME_SIZE 32 #define ADF_DEVICE_NAME_LENGTH 32 #define ADF_CFG_MAX_STR_LEN 128 #define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN #define ADF_CFG_MAX_VAL_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN #define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN #define ADF_MAX_DEVICES (32 * 32) /* Max PFs = num sockets x num PFs per socket */ #define ADF_MAX_PF_DEVICES 32 enum dev_sku_info { DEV_SKU_1 = 0, DEV_SKU_2, DEV_SKU_3, DEV_SKU_4, DEV_SKU_VF, DEV_SKU_UNKNOWN, }; enum adf_event { ADF_EVENT_INIT = 0, ADF_EVENT_START, ADF_EVENT_STOP, ADF_EVENT_SHUTDOWN, ADF_EVENT_RESTARTING, ADF_EVENT_RESTARTED, ADF_EVENT_ERROR, }; #define ADF_CFG_NO_INSTANCE 0xFFFFFFFF #define ADF_CTL_DEVICE_NAME "/dev/qat_adf_ctl" #define ADF_DEVICE_TYPE_LENGTH 16 #define BIT(n) (1 << n) /** ***************************************************************************** * @ingroup icp_AdfAccelHandle * * @description * Accelerator capabilities * *****************************************************************************/ typedef enum { ICP_ACCEL_CAPABILITIES_NULL = 0, ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC = 0x01, ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC = 0x02, ICP_ACCEL_CAPABILITIES_CIPHER = 0x04, ICP_ACCEL_CAPABILITIES_AUTHENTICATION = 0x08, ICP_ACCEL_CAPABILITIES_COMPRESSION = 0x20, ICP_ACCEL_CAPABILITIES_DEPRECATED = 0x40, ICP_ACCEL_CAPABILITIES_5G = 0x80, ICP_ACCEL_CAPABILITIES_CRYPTO_ZUC = 0x100, ICP_ACCEL_CAPABILITIES_CRYPTO_SHA3 = 0x200, ICP_ACCEL_CAPABILITIES_RESERVED = 0x400, ICP_ACCEL_CAPABILITIES_RL = 0x800, ICP_ACCEL_CAPABILITIES_HKDF = 0x1000, ICP_ACCEL_CAPABILITIES_ECEDMONT = 0x2000, ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN = 0x4000, ICP_ACCEL_CAPABILITIES_SHA3_EXT = 0x8000, ICP_ACCEL_CAPABILITIES_AESGCM_SPC = 0x10000, ICP_ACCEL_CAPABILITIES_CHACHA_POLY = 0x20000, ICP_ACCEL_CAPABILITIES_SM2 = 0x40000, ICP_ACCEL_CAPABILITIES_SM3 = 0x80000, ICP_ACCEL_CAPABILITIES_SM4 = 0x100000, ICP_ACCEL_CAPABILITIES_INLINE = 0x200000, ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY = 0x400000, ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY64 = 0x800000, ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION = 0x1000000, ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION = 0x2000000, ICP_ACCEL_CAPABILITIES_AES_V2 = 0x4000000, ICP_ACCEL_CAPABILITIES_KPT = 0x8000000, /* Reserved capability for CIPHER_CRC */ ICP_ACCEL_CAPABILITIES_ZUC_256 = 0x20000000, ICP_ACCEL_CAPABILITIES_WIRELESS_CRYPTO_EXT = 0x40000000, } icp_accel_capabilities_t; enum serv_type { SERV_TYPE_DC = BIT(0), SERV_TYPE_SYM = BIT(1), SERV_TYPE_ASYM = BIT(2), SERV_TYPE_DECOMP = BIT(4), SERV_TYPE_CY = (SERV_TYPE_SYM + SERV_TYPE_ASYM), SERV_TYPE_SYM_DC = (SERV_TYPE_SYM + SERV_TYPE_DC), SERV_TYPE_ASYM_DC = (SERV_TYPE_ASYM + SERV_TYPE_DC), SERV_TYPE_DC_DECOMP = (SERV_TYPE_DC + SERV_TYPE_DECOMP), SERV_TYPE_SYM_DECOMP = (SERV_TYPE_SYM + SERV_TYPE_DECOMP), SERV_TYPE_ASYM_DECOMP = (SERV_TYPE_ASYM + SERV_TYPE_DECOMP), SERV_TYPE_CY_DC = (SERV_TYPE_SYM + SERV_TYPE_ASYM + SERV_TYPE_DC), SERV_TYPE_CY_DECOMP = (SERV_TYPE_SYM + SERV_TYPE_ASYM + SERV_TYPE_DECOMP), SERV_TYPE_SYM_DC_DECOMP = (SERV_TYPE_SYM + SERV_TYPE_DC + SERV_TYPE_DECOMP), SERV_TYPE_ASYM_DC_DECOMP = (SERV_TYPE_ASYM + SERV_TYPE_DC + SERV_TYPE_DECOMP), }; /** ***************************************************************************** * @ingroup icp_AdfAccelHandle * * @description * Device Configuration Data Structure * *****************************************************************************/ typedef enum device_type_e { DEVICE_UNKNOWN = 0, DEVICE_DH895XCC, DEVICE_DH895XCCVF, DEVICE_C62X, DEVICE_C62XVF, DEVICE_C3XXX, DEVICE_C3XXXVF, DEVICE_D15XX, DEVICE_D15XXVF, DEVICE_200XX, DEVICE_200XXVF, DEVICE_C4XXX, DEVICE_C4XXXVF, DEVICE_4XXX, DEVICE_4XXXVF, DEVICE_420XX, DEVICE_420XXVF, } device_type_t; #define QAT_GEN4_STR "4xxx" /* * Macro for checking if given device_type_t enum value * belongs to QAT_GEN2 generation. */ #ifdef IS_QAT_GEN2 #undef IS_QAT_GEN2 #endif #define IS_QAT_GEN2(dev_type) \ ({ \ int _dt = dev_type; \ _dt == DEVICE_C62X || _dt == DEVICE_C62XVF || _dt == DEVICE_C3XXX || \ _dt == DEVICE_C3XXXVF || _dt == DEVICE_D15XX || \ _dt == DEVICE_D15XXVF; \ }) /* * Macro for checking if given device_type_t enum value * belongs to QAT 4 generation. */ #ifdef IS_QAT_GEN4 #undef IS_QAT_GEN4 #endif #define IS_QAT_GEN4(dev_type) \ ({ \ int _dt = dev_type; \ _dt == DEVICE_4XXX || _dt == DEVICE_4XXXVF || _dt == DEVICE_420XX || \ _dt == DEVICE_420XXVF; \ }) #ifdef IS_QAT_GEN4_2 #undef IS_QAT_GEN4_2 #endif #define IS_QAT_GEN4_2(dev_type) \ ({ \ int _dt = dev_type; \ _dt == DEVICE_420XX || _dt == DEVICE_420XXVF; \ }) /* * Enumeration on Service Type */ typedef enum adf_service_type_s { ADF_SERVICE_CRYPTO, ADF_SERVICE_COMPRESS, ADF_SERVICE_MAX /* this is always the last one */ } adf_service_type_t; struct fw_caps_accel { uint16_t comp_algos; uint16_t cksum_algos; uint32_t deflate_caps; uint16_t lz4_caps; uint16_t lz4s_caps; uint8_t is_fw_caps; }; /* Enumeration on Ring Queue modes */ typedef enum adf_ring_queue_mode { ADF_RING_WQ_MODE = 0, } adf_ring_queue_mode_t; typedef struct accel_dev_s { /* Some generic information */ Cpa32U accelId; device_type_t deviceType; /* Device Type */ char deviceName[ADF_DEVICE_TYPE_LENGTH + 1]; /* Device name for SAL */ Cpa16U services; Cpa32U accelCapabilitiesMask; /* Accelerator's capabilities mask */ Cpa32U cipherCapabilitiesMask; /* Cipher algorithms capabilities mask */ Cpa32U hashCapabilitiesMask; /* Hash algorithms capabilities mask */ Cpa32U asymCapabilitiesMask; /* Asym algorithms capabilities mask */ Cpa32U dcExtendedFeatures; /* bit field of features */ struct fw_caps_accel fw_caps; OsalAtomic usageCounter; /* Prevents shutting down the dev if not 0 */ void *pSalHandle; /* For SAL */ void *pQatStats; /* For QATAL/SAL stats */ void *ringInfoCallBack; /* Callback for user space ring enabling */ Cpa32U adfSubsystemStatus; /* Status of ADF and registered subsystems */ Cpa32S numa_node; /* Physical processor to which the dev is connected */ enum dev_sku_info sku; Cpa32U arb_mask; void *accel; Cpa32U maxNumBanks; Cpa32U maxNumRingsPerBank; void *banks; /* banks information */ #ifdef KERNEL_SPACE const Cpa8U *pAccelName; /* Name given to accelerator */ struct adf_accel_dev *accel_dev; struct accel_dev_s *pPrev; struct accel_dev_s *pNext; #endif Cpa32U deviceMemAvail; /* Device memory for intermediate buffers */ Cpa32U pciDevId; CpaBoolean isVf; /* Device runs on a virtual function */ void *ioPriv; adf_ring_queue_mode_t ringMode; } icp_accel_dev_t; /* * This structure must be identical to CpaPfInfo which * defined in "icp_sal_user.h" */ typedef struct accel_pf_info_s { Cpa32U pkg_id; Cpa16U domain; Cpa16U bdf; char device_gen[ADF_DEVICE_TYPE_LENGTH + 1]; } icp_accel_pf_info_t; #endif /* ICP_ACCEL_HANDLE_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_accel_mgr.h000066400000000000000000000204301503624047500272760ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /***************************************************************************** * @file icp_adf_accel_mgr.h * * @description * This file contains the function prototype for accel * instances management * *****************************************************************************/ #ifndef ICP_ADF_ACCEL_MGR_H #define ICP_ADF_ACCEL_MGR_H #include "cpa.h" #include "icp_accel_devices.h" /* * Device reset mode type. * If device reset is triggered from atomic context * it needs to be in ICP_ADF_DEV_RESET_ASYNC mode. * Otherwise can be either. */ typedef enum icp_adf_dev_reset_mode_e { ICP_ADF_DEV_RESET_ASYNC = 0, ICP_ADF_DEV_RESET_SYNC } icp_adf_dev_reset_mode_t; /* * icp_adf_resetDev * * Description: * Function resets the given device. * If device reset is triggered from atomic context * it needs to be in ICP_ADF_DEV_RESET_ASYNC mode. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_resetDev(icp_accel_dev_t *accel_dev, icp_adf_dev_reset_mode_t mode); /* * icp_adf_isDevInError * * Description: * Check if device is in error state. * * Returns: * CPA_TRUE device is in error state * CPA_FALSE device is not in error state */ CpaBoolean icp_adf_isDevInError(icp_accel_dev_t *accel_dev); /* * icp_adf_isDevInRestarting * * Description: * Check if device is in restarting state. * * Returns: * CPA_TRUE device is in restarting state * CPA_FALSE device is not in restarting state */ CpaBoolean icp_adf_isDevInRestarting(icp_accel_dev_t *accel_dev); /* * icp_adf_getNumInstances * * Description: * Returns number of accel instances in the system. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_getNumInstances(Cpa16U *pNumInstances); /* * icp_adf_getInstances * * Description: * Returns table of accel instances in the system. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_getInstances(Cpa16U numInstances, icp_accel_dev_t **pAccel_devs); /* * icp_adf_getAccelDevByCapabilities * * Description: * Returns a started accel device that implements the capabilities * specified in capabilitiesMask. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_getAccelDevByCapabilities(Cpa32U capabilitiesMask, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances); /* * icp_adf_getAllAccelDevByCapabilities * * Description: * Returns table of accel devices that are started and implement * the capabilities specified in capabilitiesMask. * * Returns: * CPA_STATUS_SUCCESS on success */ CpaStatus icp_adf_getAllAccelDevByCapabilities(Cpa32U capabilitiesMask, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances); /* * icp_adf_getAllAccelDevByServices * * Description: * Returns table of accel devices that are started and implement * the capabilities specified in configuration services. * * Returns: * CPA_STATUS_SUCCESS on success */ CpaStatus icp_adf_getAllAccelDevByServices(Cpa16U servType, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances); /* * icp_adf_getAllAccelDevByEachCapability * * Description: * Returns table of accel devices that are started and implement * each of the capability specified in capabilitiesMask. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_getAllAccelDevByEachCapability(Cpa32U capabilitiesMask, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances); /* * icp_adf_getAccelDevCapabilities * Returns accel devices capabilities specified in capabilitiesMask. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_getAccelDevCapabilities(icp_accel_dev_t *accel_dev, Cpa32U *pCapabilitiesMask); /* * icp_adf_qaDevGet * * Description: * Function increments the device usage counter. * * Returns: void */ void icp_adf_qaDevGet(icp_accel_dev_t *pDev); /* * icp_adf_qaDevPut * * Description: * Function decrements the device usage counter. * * Returns: void */ void icp_adf_qaDevPut(icp_accel_dev_t *pDev); /* * icp_adf_getAccelDevByAccelId * * Description: * Gets the accel_dev structure based on accelId * * Returns: a pointer to the accelerator structure or NULL if not found. */ icp_accel_dev_t *icp_adf_getAccelDevByAccelId(Cpa32U accelId); /* * icp_adf_getNumDevices * * Description: * This function is used to determine the number of acceleration devices. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_getNumDevices(Cpa32U *num_dev); /* * icp_adf_checkDevId * * Description: * This function checks the validity of a device id * * Returns: * CPA_TRUE if the dev_id provided is valid * CPA_FALSE if the dev_id is invalid */ CpaBoolean icp_adf_isDevIdValid(Cpa32U dev_id); #endif /* ICP_ADF_ACCEL_MGR_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_cfg.h000066400000000000000000000127351503624047500261320ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /****************************************************************************** * @file icp_adf_cfg.h * * @defgroup icp_AdfCfg Acceleration Driver Framework Configuration Interface. * * @ingroup icp_Adf * * @description * This is the top level header file for the run-time system configuration * parameters. This interface may be used by components of this API to * access the supported run-time configuration parameters. * *****************************************************************************/ #ifndef ICP_ADF_CFG_H #define ICP_ADF_CFG_H #include "cpa.h" #include "icp_accel_devices.h" /****************************************************************************** * Section for #define's & typedef's ******************************************************************************/ /* MMP firmware version */ #ifndef ADF_MMP_VER_KEY #define ADF_MMP_VER_KEY ("Firmware_MmpVer") #endif /* UOF firmware version */ #ifndef ADF_UOF_VER_KEY #define ADF_UOF_VER_KEY ("Firmware_UofVer") #endif /* Hardware rev id */ #ifndef ADF_HW_REV_ID_KEY #define ADF_HW_REV_ID_KEY ("HW_RevId") #endif /* Lowest Compatible Driver Version */ #define ICP_CFG_LO_COMPATIBLE_DRV_KEY ("Lowest_Compat_Drv_Ver") /* Device node id, tells to which die the device is connected to */ #define ADF_DEV_NODE_ID ("Device_NodeId") /* Device package id, this is accel_dev id */ #define ADF_DEV_PKG_ID ("Device_PkgId") /* * icp_adf_cfgGetParamValue * * Description: * This function is used to determine the value for a given parameter name. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_cfgGetParamValue(icp_accel_dev_t *accel_dev, const char *section, const char *param_name, char *param_value); /* * icp_adf_cfgGetRingNumber * * Description: * Function returns ring number configured for the service. * NOTE: this function will only be used by QATAL in kernelspace. * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_cfgGetRingNumber(icp_accel_dev_t *accel_dev, const char *section_name, const Cpa32U accel_num, const Cpa32U bank_num, const char *pServiceName, Cpa32U *pRingNum); /* * icp_adf_getBusAddress * Gets the B.D.F. of the accelerator device. */ Cpa16U icp_adf_getBusAddress(Cpa16U accelId); #endif /* ICP_ADF_CFG_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_debug.h000066400000000000000000000130511503624047500264510ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /****************************************************************************** * @file icp_adf_debug.h * * @description * This header file that contains the prototypes and definitions required * for ADF debug feature. * *****************************************************************************/ #ifndef ICP_ADF_DEBUG_H #define ICP_ADF_DEBUG_H /* * adf_proc_type_t * Type of proc file. Simple for files where read funct * prints less than page size (4kB) and seq type for files * where read function needs to print more that page size. */ typedef enum adf_proc_type_e { ADF_PROC_SIMPLE = 1, ADF_PROC_SEQ } adf_proc_type_t; /* * debug_dir_info_t * Struct which is used to hold information about a debug directory * under the proc filesystem. * Client should only set name and parent fields. */ typedef struct debug_dir_info_s { char *name; struct debug_dir_info_s *parent; /* The below fields are used internally by the driver */ struct debug_dir_info_s *dirChildListHead; struct debug_dir_info_s *dirChildListTail; struct debug_dir_info_s *pNext; struct debug_dir_info_s *pPrev; struct debug_file_info_s *fileListHead; struct debug_file_info_s *fileListTail; void *proc_entry; } debug_dir_info_t; /* * Read handle type for simple proc file * Function is called only once and can print up to 4kB (size) * Function should return number of bytes printed. */ typedef int (*file_read)(void *private_data, char *buff, int size); /* * Read handle type for sequential proc file * Function can be called more than once. It will be called until the * return value is not 0. offset should be used to mark the starting * point for next step. In one go function can print up to 4kB (size). * Function should return 0 (zero) if all info is printed or * offset from where to start in next step. */ typedef int (*file_read_seq)(void *private_data, char *buff, int size, int offset); /* * debug_file_info_t * Struct which is used to hold information about a debug file * under the proc filesystem. * Client should only set name, type, private_data, parent fields, * and read or seq_read pointers depending on type used. */ typedef struct debug_file_info_s { char *name; struct debug_dir_info_s *parent; adf_proc_type_t type; file_read read; file_read_seq seq_read; void *private_data; /* The below fields are used internally by the driver */ struct debug_file_info_s *pNext; struct debug_file_info_s *pPrev; void *page; Cpa32U offset; void *proc_entry; } debug_file_info_t; #endif /* ICP_ADF_DEBUG_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_init.h000066400000000000000000000167301503624047500263350ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /***************************************************************************** * @file icp_adf_init.h * * @description * This file contains the function prototype used to register a subsystem * into the Acceleration Driver Framework (ADF). * *****************************************************************************/ #ifndef ICP_ADF_INIT_H #define ICP_ADF_INIT_H #include "icp_accel_devices.h" #include "adf_kernel_types.h" /* * Ring info operation used to enable or disable ring polling by ME */ typedef enum icp_adf_ringInfoOperation_e { ICP_ADF_RING_ENABLE = 0, ICP_ADF_RING_DISABLE } icp_adf_ringInfoOperation_t; /* * Ring generic service info private data */ typedef enum icp_adf_ringInfoService_e { ICP_ADF_RING_SERVICE_0 = 0, ICP_ADF_RING_SERVICE_1, ICP_ADF_RING_SERVICE_2, ICP_ADF_RING_SERVICE_3, ICP_ADF_RING_SERVICE_4, ICP_ADF_RING_SERVICE_5, ICP_ADF_RING_SERVICE_6, ICP_ADF_RING_SERVICE_7, ICP_ADF_RING_SERVICE_8, ICP_ADF_RING_SERVICE_9, ICP_ADF_RING_SERVICE_10, } icp_adf_ringInfoService_t; /* * Ring info callback. Function is used to send operation and ring info * to enable or disable ring polling by ME */ typedef CpaStatus (*ringInfoCb)(icp_accel_dev_t *accel_dev, Cpa32U ringNumber, icp_adf_ringInfoOperation_t operation, icp_adf_ringInfoService_t info); /* * Registration handle structure * Each subservice has to have an instance of it. */ typedef struct subservice_registation_handle_s { CpaStatus (*subserviceEventHandler)(icp_accel_dev_t *accel_dev, enum adf_event event, void *param); struct { Cpa32U subsystemInitBit : 1; Cpa32U subsystemStartBit : 1; Cpa32U subsystemFailedBit : 1; } subsystemStatus[ADF_MAX_DEVICES]; char *subsystem_name; struct subservice_registation_handle_s *pNext; struct subservice_registation_handle_s *pPrev; } subservice_registation_handle_t; /* * icp_adf_subsystemRegister * * Description: * Function used by subsystem to register within ADF * Should be called during insertion of a subsystem * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_subsystemRegister(subservice_registation_handle_t *handle); /* * icp_adf_subsystemUnregister * * Description: * Function used by subsystem to unregister from ADF * Should be called while subsystem in removed * If the subsystem is initialised and/or started * it will be stopped and shutdown by this function * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_subsystemUnregister(subservice_registation_handle_t *handle); /* * icp_adf_isSubsystemStarted * * Description: * Function returns true if the service is started on a device * * Returns: * CPA_TRUE if subsystem is started * CPA_FALSE if subsystem is not started */ CpaBoolean icp_adf_isSubsystemStarted( subservice_registation_handle_t *subsystem_hdl); /* * icp_adf_isDevStarted * * Description: * Function returns true if the device is started * Returns: * CPA_TRUE if dev is started * CPA_FALSE if dev is not started */ CpaBoolean icp_adf_isDevStarted(icp_accel_dev_t *accel_dev); /* * adf_subsystemRestarting * * Description: * Function sends restarting event to all subsystems. * This function should be used by error handling funct. only * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus adf_subsystemRestarting(icp_accel_dev_t *accel_dev); /* * adf_subsystemRestarted * * Description: * Function sends restarted event to all subsystems. * This function should be used by error handling funct. only * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus adf_subsystemRestarted(icp_accel_dev_t *accel_dev); /* * adf_subsystemError * * Description: * Function sends error event to all subsystems. * This function should be used by error handling funct. only * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus adf_subsystemError(icp_accel_dev_t *accel_dev); /* * icp_adf_resetSubsystemTable * * Description: * Function to reset subsystem table head, the pointer * to the head of the list and lock. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_resetSubsystemTable(void); #endif /* ICP_ADF_INIT_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_poll.h000066400000000000000000000123461503624047500263370ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /***************************************************************************** * @file icp_adf_poll.h * * @description * File contains Public API Definitions for the polling method. * *****************************************************************************/ #ifndef ICP_ADF_POLL_H #define ICP_ADF_POLL_H #include "cpa.h" /* * icp_adf_pollInstance * * Description: * Poll an instance. In order to poll an instance * sal will pass in a table of trans handles from which * the ring to be polled can be obtained and subsequently * polled. * * Returns: * CPA_STATUS_SUCCESS on polling a ring with data * CPA_STATUS_FAIL on failure * CPA_STATUS_RETRY if ring has no data on it * or ring is already being polled. */ CpaStatus icp_adf_pollInstance(icp_comms_trans_handle *trans_hnd, Cpa32U num_transHandles, Cpa32U response_quota); /* * icp_adf_check_RespInstance * * Description: * Check whether an instance is empty or has remaining responses on it. In * order to check an instance for the remaining responses, sal will pass in * a table of trans handles from which the instance to be checked can be * obtained and subsequently checked. * * Returns: * CPA_STATUS_SUCCESS if response ring is empty * CPA_STATUS_FAIL on failure * CPA_STATUS_RETRY if response ring is not empty * CPA_STATUS_INVALID_PARAM Invalid parameter passed in */ CpaStatus icp_adf_check_RespInstance(icp_comms_trans_handle *trans_hnd, Cpa32U num_transHandles); /* * This function allows the user to check ring error bit status */ CpaStatus icp_adf_checkRingError(icp_comms_trans_handle *trans_hnd, Cpa32U num_transHandles); /* * This function polls the rings on the given bank to determine * if any of the rings contain messages to be read. The * response quota is per ring. */ CpaStatus icp_adf_pollBank(Cpa32U accelId, Cpa32U bank_number, Cpa32U response_quota); /* * This function polls the rings on all banks to determine * if any of the rings contain messages to be read. The * response quota is per ring. */ CpaStatus icp_adf_pollAllBanks(Cpa32U accelId, Cpa32U response_quota); #endif /* ICP_ADF_POLL_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_transport.h000066400000000000000000000230361503624047500274230ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /***************************************************************************** * @file icp_adf_transport.h * * @description * File contains Public API Definitions for ADF transport. * *****************************************************************************/ #ifndef ICP_ADF_TRANSPORT_H #define ICP_ADF_TRANSPORT_H #include "cpa.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" /* Invalid sequence number. */ #define ICP_ADF_INVALID_SEND_SEQ ((Cpa64U)~0) /* * Enumeration on Transport Types exposed */ typedef enum icp_transport_type_e { ICP_TRANS_TYPE_NONE = 0, ICP_TRANS_TYPE_ETR, ICP_TRANS_TYPE_DP_ETR, ICP_TRANS_TYPE_DELIMIT } icp_transport_type; /* * Enumeration on response delivery method */ typedef enum icp_resp_deliv_method_e { ICP_RESP_TYPE_NONE = 0, ICP_RESP_TYPE_IRQ, ICP_RESP_TYPE_POLL, ICP_RESP_TYPE_DELIMIT } icp_resp_deliv_method; /* * Unique identifier of a transport handle */ typedef Cpa32U icp_trans_identifier; /* * Opaque Transport Handle */ typedef void *icp_comms_trans_handle; /* * Function Pointer invoked when a set of messages is received for the given * transport handle */ typedef void (*icp_trans_callback)(void *pMsg); /* * icp_adf_transGetFdForHandle * * Description: * Get a file descriptor for a particular transaction handle. * If more than one transaction handler * are ever present, this will need to be refactored to * return the appropriate fd of the appropriate bank. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * * */ CpaStatus icp_adf_transGetFdForHandle(icp_comms_trans_handle trans_hnd, int *fd); /* * icp_adf_transCreateHandle * * Description: * Create a transport handle * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * * The message size is variable: requests can be 64 or 128 bytes, responses * can be 16, 32 or 64 bytes. * Supported num_msgs: * 32, 64, 128, 256, 512, 1024, 2048 number of messages. * */ CpaStatus icp_adf_transCreateHandle(icp_accel_dev_t *accel_dev, icp_transport_type trans_type, const char *section, const Cpa32U accel_nr, const Cpa32U bank_nr, const char *service_name, const icp_adf_ringInfoService_t info, icp_trans_callback callback, icp_resp_deliv_method resp, const Cpa32U num_msgs, const Cpa32U msg_size, icp_comms_trans_handle *trans_handle); /* * icp_adf_transReinitHandle * * Description: * Reinitialize a transport handle * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * * The message size is variable: requests can be 64 or 128 bytes, responses * can be 16, 32 or 64 bytes. * Supported num_msgs: * 32, 64, 128, 256, 512, 1024, 2048 number of messages. * */ CpaStatus icp_adf_transReinitHandle(icp_accel_dev_t *accel_dev, icp_transport_type trans_type, const char *section, const Cpa32U accel_nr, const Cpa32U bank_nr, const char *service_name, const icp_adf_ringInfoService_t info, icp_trans_callback callback, icp_resp_deliv_method resp, const Cpa32U num_msgs, const Cpa32U msg_size, icp_comms_trans_handle *trans_handle); /* * icp_adf_transGetHandle * * Description: * Gets a pointer to a previously created transport handle * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * */ CpaStatus icp_adf_transGetHandle(icp_accel_dev_t *accel_dev, icp_transport_type trans_type, const char *section, const Cpa32U accel_nr, const Cpa32U bank_nr, const char *service_name, icp_comms_trans_handle *trans_handle); /* * icp_adf_transReleaseHandle * * Description: * Release a transport handle * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_transReleaseHandle(icp_comms_trans_handle trans_handle); /* * icp_adf_transResetHandle * * Description: * Reset a transport handle * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_transResetHandle(icp_comms_trans_handle trans_handle); /* * icp_adf_transPutMsg * * Description: * Put Message onto the transport handle * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_transPutMsg(icp_comms_trans_handle trans_handle, Cpa32U *inBufs, Cpa32U bufLen, Cpa64U *seq_num); /* * icp_adf_getInflightRequests * * Description: * Retrieves in-flight and max in-flight request counts * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * CPA_STATUS_INVALID_PARAM invalid parameter */ CpaStatus icp_adf_getInflightRequests(icp_comms_trans_handle trans_handle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests); /* * icp_adf_transPutMsgSync * * Description: * Put Message onto the transport handle and waits for a response. * Note: Not all transports support method. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_transPutMsgSync(icp_comms_trans_handle trans_handle, Cpa32U *inBuf, Cpa32U *outBuf, Cpa32U bufsLen); /* * icp_adf_transGetRingNum * * Description: * Function Returns ring number of the given trans_handle * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_transGetRingNum(icp_comms_trans_handle trans_handle, Cpa32U *ringNum); #endif /* ICP_ADF_TRANSPORT_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_transport_dp.h000066400000000000000000000127271503624047500301130ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /***************************************************************************** * @file icp_adf_transport_dp.h * * @description * File contains Public API definitions for ADF transport for data plane. * *****************************************************************************/ #ifndef ICP_ADF_TRANSPORT_DP_H #define ICP_ADF_TRANSPORT_DP_H #include "cpa.h" #include "icp_adf_transport.h" /* * icp_adf_getQueueMemory * Data plane support function - returns the pointer to next message on the ring * or NULL if there is not enough space. */ extern void icp_adf_getQueueMemory(icp_comms_trans_handle trans_handle, Cpa32U numberRequests, void **pCurrentQatMsg); /* * icp_adf_getSingleQueueAddr * Data plane support function - returns the pointer to next message on the ring * or NULL if there is not enough space - it also updates the shadow tail copy. */ extern void icp_adf_getSingleQueueAddr(icp_comms_trans_handle trans_handle, void **pCurrentQatMsg); /* * icp_adf_getQueueNext * Data plane support function - increments the tail pointer and returns * the pointer to next message on the ring. */ extern void icp_adf_getQueueNext(icp_comms_trans_handle trans_handle, void **pCurrentQatMsg); /* * icp_adf_updateQueueTail * Data plane support function - Writes the tail shadow copy to the device. */ extern CpaStatus icp_adf_updateQueueTail(icp_comms_trans_handle trans_handle); /* * icp_adf_isRingEmpty * Data plane support function - check if the ring is empty */ extern CpaBoolean icp_adf_isRingEmpty(icp_comms_trans_handle trans_handle); /* * icp_adf_pollQueue * Data plane support function - Poll messages from the queue. */ extern CpaStatus icp_adf_pollQueue(icp_comms_trans_handle trans_handle, Cpa32U response_quota); /* * icp_adf_queueDataToSend * LAC lite support function - Indicates if there is data on the ring to be * send. This should only be called on request rings. If the function returns * true then it is ok to call icp_adf_updateQueueTail() function on this ring. */ extern CpaBoolean icp_adf_queueDataToSend(icp_comms_trans_handle trans_hnd); /* * icp_adf_getDpInflightRequests * Retrieves in-flight and max in-flight request counts */ extern void icp_adf_getDpInflightRequests(icp_comms_trans_handle trans_handle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests); #endif /* ICP_ADF_TRANSPORT_DP_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_adf_user_proxy.h000066400000000000000000000175651503624047500276200ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /***************************************************************************** * @file icp_adf_user_proxy.h * * @description * This file contains the function prototype to initialize ADF proxy * in user space. * *****************************************************************************/ #ifndef ICP_ADF_USER_PROXY_H #define ICP_ADF_USER_PROXY_H #include "cpa.h" #include "icp_accel_devices.h" /* * icp_adf_userProcessToStart * * Description: * This function checks if a user space process with a given name has * already been started. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_userProcessToStart(const char *const name_tml, char *name); /* * icp_adf_userProxyInit * * Description: * This function is used to initialize the ADF proxy in user space. * It takes a process name as a parameter. Caller should check if * such process name is not already started using * icp_adf_userProcessStarted function. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_userProxyInit(const char *const name); /* * icp_adf_userProxyShutdown * * Description: * This function is used to shutdown the ADF proxy in user space. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_userProxyShutdown(void); /* * icp_adf_userProcessStop * * Description: * This function closes the processes info file. * It should be called before a process exits if icp_adf_userProcessToStart() * has been used to obtain unique user process name. * * Returns: void */ void icp_adf_userProcessStop(void); /* * icp_adf_userFindNewDevices * * Description: * Function tries to connect to devices. * This function is used in threadless mode in user space. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_userFindNewDevices(void); /* * icp_adf_pollDeviceEvents * * Description: * Function polls new device events. * This function is used in threadless mode in user space. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_pollDeviceEvents(void); /* * icp_adf_userGetNumPfs * * Description: * Returns the number of PFs in the system, only returned if the process has * privileges to access the QAT debugfs/sysfs entries. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_userGetNumPfs(Cpa16U *pNumPFs); /* * icp_adf_userGetPfInfo * * Description: * Populates a pre-allocated list of PF info. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_userGetPfInfo(icp_accel_pf_info_t *pPfInfo); /* * icp_adf_userCheckDevice * * Description: * Function checks the status of the firmware/hardware for a given device. * This function is used as part of the heartbeat functionality. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * CPA_STATUS_UNSUPPORTED on unsupported */ CpaStatus icp_adf_userCheckDevice(Cpa32U packageId); /* * icp_adf_userCheckAllDevices * * Description: * Function checks the status of the firmware/hardware for all devices. * This function is used as part of the heartbeat functionality. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * CPA_STATUS_UNSUPPORTED on unsupported */ CpaStatus icp_adf_userCheckAllDevices(void); #ifdef ICP_HB_FAIL_SIM /* * icp_adf_heartbeatSimulateFailure * * Description: * Function simulates a heartbeat failure. * If icp_adf_userCheckDevice is used along with this call, a heartbeat * failure will be detected * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_heartbeatSimulateFailure(Cpa32U packageId); #endif /* * icp_adf_resetDevice * * Description: * reset device - calls the IOCTL in * the driver which resets the device based on accelId * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure * CPA_STATUS_UNSUPPORTED on unsupported */ CpaStatus icp_adf_resetDevice(Cpa32U accelId); /* * icp_adf_mmap_misc_counter * * Description: * Function mmap miscellaneous counter. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_mmap_misc_counter(Cpa64U **miscCounter); /* * icp_adf_unmap_misc_counter * * Description: * Function unmap miscellaneous counter. * * Returns: * CPA_STATUS_SUCCESS on success * CPA_STATUS_FAIL on failure */ CpaStatus icp_adf_unmap_misc_counter(Cpa64U *miscCounter); /* * icp_adf_isDeviceAvailable * * Description: * check if there are available devices * * Returns: * CPA_TRUE on success - found available device * CPA_FALSE on failure */ CpaBoolean icp_adf_isDeviceAvailable(void); #endif /* ICP_ADF_USER_PROXY_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_buffer_desc.h000066400000000000000000000126671503624047500270340ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file icp_buffer_desc.h * * @defgroup icp_BufferDesc Buffer descriptor for LAC * * @ingroup LacCommon * * @description * This file contains details of the hardware buffer descriptors used to * communicate with the QAT. * *****************************************************************************/ #ifndef ICP_BUFFER_DESC_H #define ICP_BUFFER_DESC_H #include "cpa.h" typedef Cpa64U icp_qat_addr_width_t; /* Alignment constraint of the buffer list. */ #define ICP_DESCRIPTOR_ALIGNMENT_BYTES 8 /** ***************************************************************************** * @ingroup icp_BufferDesc * Buffer descriptors for FlatBuffers - used in communications with * the QAT. * * @description * A QAT friendly buffer descriptor. * All buffer descriptor described in this structure are physical * and are 64 bit wide. * * Updates in the CpaFlatBuffer should be also reflected in this * structure * *****************************************************************************/ typedef struct icp_flat_buffer_desc_s { Cpa32U dataLenInBytes; Cpa32U reserved; icp_qat_addr_width_t phyBuffer; /**< The client will allocate memory for this using API function calls * and the access layer will fill it and the QAT will read it. */ } icp_flat_buffer_desc_t; /** ***************************************************************************** * @ingroup icp_BufferDesc * Buffer descriptors for BuffersLists - used in communications with * the QAT. * * @description * A QAT friendly buffer descriptor. * All buffer descriptor described in this structure are physical * and are 64 bit wide. * * Updates in the CpaBufferList should be also reflected in this structure * *****************************************************************************/ typedef struct icp_buffer_list_desc_s { Cpa64U resrvd; Cpa32U numBuffers; Cpa32U reserved; icp_flat_buffer_desc_t phyBuffers[]; /**< Unbounded array of physical buffer pointers, these point to the * FlatBufferDescs. The client will allocate memory for this using * API function calls and the access layer will fill it and the QAT * will read it. */ } icp_buffer_list_desc_t; #endif /* ICP_BUFFER_DESC_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_sal.h000066400000000000000000000111061503624047500253270ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file icp_sal.h * * @ingroup SalCommon * * Functions for both user space and kernel space. * ***************************************************************************/ #ifndef ICP_SAL_H #define ICP_SAL_H #ifdef __cplusplus extern "C" { #endif /* * icp_sal_dc_simulate_error * * @description: * This function injects a simulated compression error for a defined * number of compression requests * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] numErrors Num DC Errors * 0 - No Error injection * 1-0xFE - Num Errors to Inject * 0xFF - Always inject Error * @param[in] dcError DC Error Type * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed */ CpaStatus icp_sal_dc_simulate_error(Cpa8U numErrors, Cpa8S dcError); /* * icp_sal_get_dc_error * * @description: * This function returns the occurrences of compression errors specified * in the input parameter * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * @param[in] dcError DC Error Type * * returns Number of failing requests of type dcError */ Cpa64U icp_sal_get_dc_error(Cpa8S dcError); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_sal_congestion_mgmt.h000066400000000000000000000142601503624047500306070ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* *************************************************************************** * @file icp_sal_congestion_mgmt.h * * @ingroup SalUserCongsMgmt * * This file contains function prototypes for Congestion Management APIs. * ***************************************************************************/ #ifndef ICP_SAL_CONGESTION_MGMT_H #define ICP_SAL_CONGESTION_MGMT_H #include "icp_sal.h" /* ***************************************************************************** * @ingroup SalUserCongsMgmt * Symmetric get in-flight requests * * @description * This function is used to fetch in-flight and max in-flight request * counts for the given symmetric instance handle. * * @param[in] instanceHandle Symmetric instance handle * @param[out] maxInflightRequests Max in-flight request count * @param[out] numInflightRequests Current in-flight request count * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed * @retval CPA_STATUS_INVALID_PARAM Invalid parameter * *****************************************************************************/ CpaStatus icp_sal_SymGetInflightRequests(CpaInstanceHandle instanceHandle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests); /* ***************************************************************************** * @ingroup SalUserCongsMgmt * Asymmetric get in-flight requests * * @description * This function is used to fetch in-flight and max in-flight request * counts for the given asymmetric instance handle. * * @param[in] instanceHandle Asymmetric instance handle * @param[out] maxInflightRequests Max in-flight request count * @param[out] numInflightRequests Current in-flight request count * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed * @retval CPA_STATUS_INVALID_PARAM Invalid parameter * *****************************************************************************/ CpaStatus icp_sal_AsymGetInflightRequests(CpaInstanceHandle instanceHandle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests); /* ***************************************************************************** * @ingroup SalUserCongsMgmt * Symmetric data plane get in-flight requests * * @description * Data plane API to fetch in-flight and max in-flight request counts * for the given symmetric instance handle. * * @param[in] instanceHandle Symmetric instance handle * @param[out] maxInflightRequests Max in-flight request count * @param[out] numInflightRequests Current in-flight request count * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed * @retval CPA_STATUS_INVALID_PARAM Invalid parameter * *****************************************************************************/ CpaStatus icp_sal_dp_SymGetInflightRequests(CpaInstanceHandle instanceHandle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_sal_iommu.h000066400000000000000000000117721503624047500265460ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file icp_sal_iommu.h * * @ingroup SalUser * * Sal iommu wrapper functions. * ***************************************************************************/ #ifndef ICP_SAL_IOMMU_H #define ICP_SAL_IOMMU_H /************************************************************************* * @ingroup Sal * @description * Function returns page_size rounded size for iommu remapping * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] size Minimum required size. * * @retval page_size rounded size for iommu remapping. * *************************************************************************/ size_t icp_sal_iommu_get_remap_size(size_t size); /************************************************************************* * @ingroup Sal * @description * Function adds an entry into iommu remapping table * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] phaddr Host physical address. * @param[in] iova Guest physical address. * @param[in] size Size of the remapped region. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * *************************************************************************/ CpaStatus icp_sal_iommu_map(Cpa64U phaddr, Cpa64U iova, size_t size); /************************************************************************* * @ingroup Sal * @description * Function removes an entry from iommu remapping table * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] iova Guest physical address to be removed. * @param[in] size Size of the remapped region. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * *************************************************************************/ CpaStatus icp_sal_iommu_unmap(Cpa64U iova, size_t size); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_sal_poll.h000066400000000000000000000513101503624047500263560ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file icp_sal_poll.h * * @defgroup SalPoll * * @ingroup SalPoll * * @description * Polling APIs for instance polling. * These functions retrieve requests on appropriate response rings and * dispatch the associated callbacks. Callbacks are called in the * context of the polling function itself. * * ***************************************************************************/ #ifndef ICP_SAL_POLL_H #define ICP_SAL_POLL_H #ifdef __cplusplus extern "C" { #endif /************************************************************************* * @ingroup SalPoll * @description * Poll a Cy logical instance to retrieve requests that are on the * response rings associated with that instance and dispatch the * associated callbacks. * * @context * This functions is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There are no responses on the rings * associated with this instance * @retval CPA_STATUS_FAIL Indicates a failure * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_RESOURCE Error related to system resources * @retval CPA_STATUS_FATAL A serious error has occurred. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. *************************************************************************/ CpaStatus icp_sal_CyPollInstance(CpaInstanceHandle instanceHandle, Cpa32U response_quota); /************************************************************************* * @ingroup SalPoll * @description * Poll the symmetric logical instance to retrieve requests that are on * the response rings associated with that instance and dispatch the * associated callbacks. * * @context * This functions is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There are no responses on the rings * associated with this instance * @retval CPA_STATUS_FAIL Indicates a failure * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_RESTARTING Device restarting. Resubmit the * request *************************************************************************/ CpaStatus icp_sal_CyPollSymRing(CpaInstanceHandle instanceHandle, Cpa32U response_quota); /************************************************************************* * @ingroup SalPoll * @description * Poll the asymmetric logical instance to retrieve requests that are on * the response rings associated with that instance and dispatch the * associated callbacks. * * @context * This functions is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There are no responses on the rings * associated with this instance * @retval CPA_STATUS_FAIL Indicates a failure * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_RESOURCE Error related to system resources * @retval CPA_STATUS_FATAL A serious error has occurred. * @retval CPA_STATUS_RESTARTING Device restarting. Resubmit the * request *************************************************************************/ CpaStatus icp_sal_CyPollAsymRing(CpaInstanceHandle instanceHandle, Cpa32U response_quota); /************************************************************************* * @ingroup SalPoll * @description * Poll the high priority symmetric response ring associated with a Cy * logical instance to retrieve requests and dispatch the * associated callbacks. * * This API is recommended for data plane applications, in which the * cost of offload - that is, the cycles consumed by the driver in * sending requests to the hardware, and processing responses - needs * to be minimized. In particular, use of this API is recommended * if the following constraints are acceptable to your application: * * - Thread safety is not guaranteed. Each software thread should * have access to its own unique instance (CpaInstanceHandle) to * avoid contention. * - The "default" instance (@ref CPA_INSTANCE_HANDLE_SINGLE) is not * supported on this API. The specific handle should be obtained * using the instance discovery functions (@ref cpaCyGetNumInstances, * @ref cpaCyGetInstances). * * This polling function should be used with the functions described * in cpa_cy_sym_dp.h * * @context * This functions is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] instanceHandle Instance handle. * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There are no responses on the ring * associated with this instance * @retval CPA_STATUS_FAIL Indicates a failure *************************************************************************/ CpaStatus icp_sal_CyPollDpInstance(const CpaInstanceHandle instanceHandle, const Cpa32U response_quota); /************************************************************************* * @ingroup SalPoll * @description * Poll a Dc logical instance to retrieve requests that are on the * response ring associated with that instance and dispatch the * associated callbacks. * * @context * This function is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] instanceHandle Instance handle. * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There are no responses on the ring * associated with this instance * @retval CPA_STATUS_FAIL Indicates a failure *************************************************************************/ CpaStatus icp_sal_DcPollInstance(CpaInstanceHandle instanceHandle, Cpa32U response_quota); /************************************************************************* * @ingroup SalPoll * @description * Poll the response ring associated with a Dc logical instance to * retrieve requests and dispatch the associated callbacks. * * This API is recommended for data plane applications, in which the * cost of offload - that is, the cycles consumed by the driver in * sending requests to the hardware, and processing responses - needs * to be minimized. In particular, use of this API is recommended * if the following constraints are acceptable to your application: * * - Thread safety is not guaranteed. Each software thread should * have access to its own unique instance (CpaInstanceHandle) to * avoid contention. * - The "default" instance (@ref CPA_INSTANCE_HANDLE_SINGLE) is not * supported on this API. The specific handle should be obtained * using the instance discovery functions (@ref cpaDcGetNumInstances, * @ref cpaDcGetInstances). * * This polling function should be used with the functions described * in cpa_dc_dp.h * * @context * This functions is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] instanceHandle Instance handle. * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There are no responses on the ring * associated with this instance * @retval CPA_STATUS_FAIL Indicates a failure *************************************************************************/ CpaStatus icp_sal_DcPollDpInstance(CpaInstanceHandle dcInstance, Cpa32U responseQuota); /************************************************************************* * @ingroup SalPoll * @description * This function polls the rings on the given bank to determine * if any of the rings contain messages to be read. The * response quota is per ring. * * @context * This functions is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] accelId Acceleration device Id, also known as * packageId. This can be obtained using * instance info functions ( * @ref cpaCyInstanceGetInfo2 * and @ref cpaDcInstanceGetInfo2) * * @param[in] bank_number Bank number * * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There is no data on any ring on the bank * or the bank is already being polled * @retval CPA_STATUS_FAIL Indicates a failure *************************************************************************/ CpaStatus icp_sal_pollBank(Cpa32U accelId, Cpa32U bank_number, Cpa32U response_quota); /************************************************************************* * @ingroup SalPoll * @description * This function polls the rings on all banks to determine * if any of the rings contain messages to be read. The * response quota is per ring. * * @context * This functions is called from both the user and kernel context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] accelId Acceleration device Id, also known as * packageId. This can be obtained using * instance info functions ( * @ref cpaCyInstanceGetInfo2 * and @ref cpaDcInstanceGetInfo2) * * @param[in] response_quota The maximum number of messages that * will be read in one polling. Setting * the response quota to zero means that * all messages on the ring will be read. * * @retval CPA_STATUS_SUCCESS Successfully polled a ring with data * @retval CPA_STATUS_RETRY There is no data on any ring on any bank * or the banks are already being polled * @retval CPA_STATUS_FAIL Indicates a failure *************************************************************************/ CpaStatus icp_sal_pollAllBanks(Cpa32U accelId, Cpa32U response_quota); /** ***************************************************************************** * @ingroup cpaDc * Get file descriptor for an instance * * @description * This function is used to get a file descriptor for a particular * instance. The fd will be set only in case of success and be kept * unchanged otherwise. * * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Data Compression API instance handle. * @param[in] fd File descriptor address to be set. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_UNSUPPORTED Instance not in EPOLL mode. * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus icp_sal_DcGetFileDescriptor(CpaInstanceHandle instanceHandle, int *fd); /** ***************************************************************************** * @ingroup SalCtrl * Get file descriptor for an instance * * @description * This function is used to get a file descriptor for a particular * instance. The fd will be set only in case of success and be kept * unchanged otherwise. * * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Crypto Compression API instance handle. * @param[in] fd File descriptor address to be set. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_UNSUPPORTED Instance not in EPOLL mode. * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus icp_sal_CyGetFileDescriptor(CpaInstanceHandle instanceHandle, int *fd); /** ***************************************************************************** * @ingroup cpaDc * Put file descriptor for an instance * * @description * This function exists for compatibility reasons. * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Data Compression API instance handle. * @param[in] fd File descriptor. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_UNSUPPORTED Instance not in EPOLL mode. * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus icp_sal_DcPutFileDescriptor(CpaInstanceHandle instanceHandle, int fd); /** ***************************************************************************** * @ingroup cpaDc * Put file descriptor for an instance * * @description * This function exists for compatibility reasons. * * @assumptions * None * @sideEffects * None * @blocking * This function is synchronous and blocking. * @reentrant * No * @threadSafe * Yes * * @param[in] handle Data Compression API instance handle. * @param[in] fd File descriptor. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_UNSUPPORTED Instance not in EPOLL mode. * @pre * None * @post * None * @see * None * *****************************************************************************/ CpaStatus icp_sal_CyPutFileDescriptor(CpaInstanceHandle instanceHandle, int fd); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_sal_user.h000066400000000000000000000640571503624047500264020ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file icp_sal_user.h * * @ingroup SalUser * * User space process init and shutdown functions. * ***************************************************************************/ #ifndef ICP_SAL_USER_H #define ICP_SAL_USER_H #include "icp_sal.h" #include "cpa_dc.h" #ifdef __cplusplus extern "C" { #endif /************************************************************************* * @ingroup SalUser * @description * This function initialises and starts user space service access layer * (SAL) - it registers SAL with ADF and initialises the ADF proxy. * This function must only be called once per user space process. * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] pProcessName Process address space name described in * the config file for this device * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * *************************************************************************/ CpaStatus icp_sal_userStart(const char *pProcessName); /************************************************************************* * @ingroup SalUser * @description * Simple wrapper for the icp_sal_userStart() function * * This function is only for backwards compatibility. * New users should use icp_sal_userStart function directly. * *************************************************************************/ CpaStatus icp_sal_userStartMultiProcess(const char *pProcessName, CpaBoolean limitDevAccess); /************************************************************************* * @ingroup SalUser * @description * This function stops and shuts down user space SAL * - it deregisters SAL with ADF and shuts down ADF proxy * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * ************************************************************************/ CpaStatus icp_sal_userStop(void); #ifndef ICP_DC_ONLY /************************************************************************* * @ingroup SalUser * @description * This function gets the number of the available dynamic allocated * crypto instances. * * @context * This function is called from the user process context. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userCyGetAvailableNumDynInstances(Cpa32U *pNumCyInstances); #endif /************************************************************************* * @ingroup SalUser * @description * This function gets the number of the available dynamic allocated * compression instances * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userDcGetAvailableNumDynInstances(Cpa32U *pNumDcInstances); #ifndef ICP_DC_ONLY /************************************************************************* * @ingroup SalUser * @description * This function gets the number of the available dynamic allocated * crypto instances which are from the specific device package. * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * ************************************************************************/ CpaStatus icp_sal_userCyGetAvailableNumDynInstancesByDevPkg( Cpa32U *pNumCyInstances, Cpa32U devPkgID); /************************************************************************* * @ingroup SalUser * @description * This function gets the number of the available dynamic allocated * crypto instances which are from the specific device package and specific * accelerator. * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userCyGetAvailableNumDynInstancesByPkgAccel( Cpa32U *pNumCyInstances, Cpa32U devPkgID, Cpa32U accelerator_number); #endif /************************************************************************* * @ingroup SalUser * @description * This function gets the number of the available dynamic allocated * compression instances which are from the specific device package. * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userDcGetAvailableNumDynInstancesByDevPkg( Cpa32U *pNumDcInstances, Cpa32U devPkgID); #ifndef ICP_DC_ONLY /************************************************************************* * @ingroup SalUser * @description * This function allocates crypto instances * from dynamic crypto instance pool * - it adds new allocated instances into crypto_services * - it initializes new allocated instances * - it starts new allocated instances * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userCyInstancesAlloc(Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances); /************************************************************************* * @ingroup SalUser * @description * This function allocates crypto instances * from dynamic crypto instance pool * which are from the specific device package. * - it adds new allocated instances into crypto_services * - it initializes new allocated instances * - it starts new allocated instances * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userCyInstancesAllocByDevPkg(Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances, Cpa32U devPkgID); /************************************************************************* * @ingroup SalUser * @description * This function allocates crypto instances * from dynamic crypto instance pool * which are from the specific device package and specific accelerator * - it adds new allocated instances into crypto_services * - it initializes new allocated instances * - it starts new allocated instances * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userCyInstancesAllocByPkgAccel( Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances, Cpa32U devPkgID, Cpa32U accelerator_number); /************************************************************************* * @ingroup SalUser * @description * This function frees crypto instances allocated * from dynamic crypto instance pool * - it stops the instances * - it shutdowns the instances * - it removes the instances from crypto_services * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userCyFreeInstances(Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances); #endif /************************************************************************* * @ingroup SalUser * @description * This function allocates compression instances * from dynamic compression instance pool * - it adds new allocated instances into compression_services * - it initializes new allocated instances * - it starts new allocated instances * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userDcInstancesAlloc(Cpa32U numDcInstances, CpaInstanceHandle *pDcInstances); /************************************************************************* * @ingroup SalUser * @description * This function allocates compression instances * from dynamic compression instance pool * which are from the specific device package. * - it adds new allocated instances into compression_services * - it initializes new allocated instances * - it starts new allocated instances * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userDcInstancesAllocByDevPkg(Cpa32U numDcInstances, CpaInstanceHandle *pDcInstances, Cpa32U devPkgID); /************************************************************************* * @ingroup SalUser * @description * This function frees compression instances allocated * from dynamic compression instance pool * - it stops the instances * - it shutdowns the instances * - it removes the instances from compression_services * * @context * This function is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_userDcFreeInstances(Cpa32U numDcInstances, CpaInstanceHandle *pDcInstances); /************************************************************************* * @ingroup SalUser * @description * This function checks if new devices have been started and if so * starts to use them. * * @context * This function is called from the user process context * in threadless mode * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Deprecated function * ************************************************************************/ CpaStatus icp_sal_find_new_devices(void); /************************************************************************* * @ingroup SalUser * @description * This function polls device events. * * @context * This function is called from the user process context * in threadless mode * * @assumptions * None * @sideEffects * In case a device has been stopped or restarted the application * will get restarting/stop/shutdown events * @reentrant * No * @threadSafe * No * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * ************************************************************************/ CpaStatus icp_sal_poll_device_events(void); /* * icp_sal_check_device * * @description: * This function checks the status of the device and also if it supports * heartbeat or not. * This function is used as part of the heartbeat functionality. * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * In case a device is unresponsive the device will * be restarted. * @reentrant * No * @threadSafe * Yes * * @param[in] packageId The package Id can be found by calling * cpaCyInstanceGetInfo2() or * cpaDcInstanceGetInfo2(). * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Unsupported feature */ CpaStatus icp_sal_check_device(Cpa32U packageId); /* * icp_sal_check_all_devices * * @description: * This function checks the status of the device and also if it supports * heartbeat or not. * This function is used as part of the heartbeat functionality. * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * In case a device is unresponsive the device will * be restarted. * @reentrant * No * @threadSafe * Yes * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed * @retval CPA_STATUS_UNSUPPORTED Unsupported feature */ CpaStatus icp_sal_check_all_devices(void); /* * icp_sal_heartbeat_simulate_failure * * @description: * This function simulates a heartbeat failure * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * This along with a icp_sal_check call will notify the heartbeat * error to user space * @reentrant * No * @threadSafe * Yes * * @param[in] packageId The package Id can be found by calling * cpaCyInstanceGetInfo2() or * cpaDcInstanceGetInfo2(). * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed */ CpaStatus icp_sal_heartbeat_simulate_failure(Cpa32U packageId); #define CPA_DEVICE_GEN_LEN 16 typedef struct _CpaPfInfo { Cpa32U pkg_id; Cpa16U domain; Cpa16U bdf; char device_gen[CPA_DEVICE_GEN_LEN + 1]; } CpaPfInfo; /* * icp_sal_get_num_pfs * * @description: * Returns the number of PFs in the system, only returned if the process has * privileges to access the QAT debugfs/sysfs entries. * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[out] pNumPFs The number of PFs in the system. * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed */ CpaStatus icp_sal_get_num_pfs(Cpa16U *pNumPFs); /* * icp_sal_get_pf_info * * @description: * This function populates a pre-allocated list of PF info, only returned * if the process has privileges to access the QAT debugfs/sysfs entries. * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[out] pPfInfo Pre-allocated list of PF info, the size of * this should match the number of PFs on * the platform. * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_FAIL Operation failed */ CpaStatus icp_sal_get_pf_info(CpaPfInfo *pPf_info); /* * @ingroup icp_sal_user * @description * This is a stub function to send messages to VF * * @context * None * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * */ CpaStatus icp_sal_userSendMsgToVf(Cpa32U accelId, Cpa32U vfNum, Cpa32U message); /* * @ingroup icp_sal_user * @description * This is a stub function to send messages to PF * * @context * None * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * */ CpaStatus icp_sal_userSendMsgToPf(Cpa32U accelId, Cpa32U message); /* * @ingroup icp_sal_user * @description * This is a stub function to get messages from VF * * @context * None * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * */ CpaStatus icp_sal_userGetMsgFromVf(Cpa32U accelId, Cpa32U vfNum, Cpa32U *message, Cpa32U *messageCounter); /* * @ingroup icp_sal_user * @description * This is a stub function to get messages from PF * * @context * None * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * */ CpaStatus icp_sal_userGetMsgFromPf(Cpa32U accelId, Cpa32U *message, Cpa32U *messageCounter); /* * @ingroup icp_sal_user * @description * This is a stub function to get pfvf comms status * * @context * None * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * */ CpaStatus icp_sal_userGetPfVfcommsStatus(CpaBoolean *unreadMessage); /* * @ingroup icp_sal_user * @description * This is a stub function to reset the device * * @context * None * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * */ CpaStatus icp_sal_reset_device(Cpa32U accelId); /* * icp_sal_userIsQatAvailable * * @description: * This function returns CPA_TRUE if a QAT device is present in the * system and available to qatlib * * @context * This function is called from the user process context * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @retval CPA_TRUE QAT device available * @retval CPA_FALSE QAT device not available * */ CpaBoolean icp_sal_userIsQatAvailable(void); /* * icp_sal_cnv_simulate_error * * @description: * This function enables the CnVError injection for the * session passed in. All Compression requests sent within * the session are injected with CnV errors. This error injection * is for the duration of the session. Resetting the session * results in setting being cleared. * CnV error injection does not apply to Data Plane API. * * @note Only applies when compressAndVerify is on and * compressAndVerifyAndRecover is off. * * @context * This function is called from the user process context * @assumptions * The session has been initialized via cpaDcInitSession function * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] dcInstance Instance Handle * @param[in] pSessionHandle Session Handle * * @retval CPA_STATUS_UNSUPPORTED Unsupported feature * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_SUCCESS No error * */ CpaStatus icp_sal_cnv_simulate_error(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle); /* * icp_sal_ns_cnv_simulate_error * * @description: * This function enables the CnVError injection for the * No-Session case. All Compression requests sent * to the dcInstance that is passed in as a parameter, * are injected with CnV errors. This CnV error injection * does not apply to Data Plane API. * This function is for GEN4 devices. * @context * This function is called from the user process context * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] dcInstance Instance Handle * * @retval CPA_STATUS_UNSUPPORTED Unsupported feature * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_SUCCESS No error * */ CpaStatus icp_sal_ns_cnv_simulate_error(CpaInstanceHandle dcInstance); /* * icp_sal_ns_cnv_reset_error * * @description: * This function resets the CnVError injection for the * specific dcInstance that is passed in as a parameter * for the No-Session operations. * @context * This function is called from the user process context * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] dcInstance Instance Handle * * @retval CPA_STATUS_UNSUPPORTED Unsupported feature * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_SUCCESS No error * */ CpaStatus icp_sal_ns_cnv_reset_error(CpaInstanceHandle dcInstance); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/include/icp_sal_versions.h000066400000000000000000000221121503624047500272560ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file icp_sal_versions.h * * @defgroup SalVersions * * @ingroup SalVersions * * API and structures definition for obtaining software and hardware versions * ***************************************************************************/ #ifndef _ICP_SAL_VERSIONS_H_ #define _ICP_SAL_VERSIONS_H_ #ifdef __cplusplus extern "C" { #endif /** ***************************************************************************** * ICP API version history * v1.0: Base version * v1.1: addition of icp_sal_get_num_pfs() and icp_sal_get_num_pfs() *****************************************************************************/ /** ***************************************************************************** * @ingroup SalVersions * ICP Major Version Number * * @description * The ICP API major version number. This number will be incremented * when significant changes to the API have occurred. The combination of the * major and minor number definitions represents the complete version number * for this interface. * *****************************************************************************/ #define ICP_API_VERSION_NUM_MAJOR (1) /** ***************************************************************************** * @ingroup SalVersions * ICP Minor Version Number * * @description * The ICP API minor version number. This number will be incremented * when minor changes to the API have occurred. The combination of the major * and minor number definitions represents the complete version number for * this interface. * *****************************************************************************/ #define ICP_API_VERSION_NUM_MINOR (1) /**< Check for ICP API version (at least) */ #define ICP_API_VERSION_AT_LEAST(major, minor) \ (ICP_API_VERSION_NUM_MAJOR > major || \ (ICP_API_VERSION_NUM_MAJOR == major && \ ICP_API_VERSION_NUM_MINOR >= minor)) /**< Check for ICP API version (less than) */ #define ICP_API_VERSION_LESS_THAN(major, minor) \ (ICP_API_VERSION_NUM_MAJOR < major || \ (ICP_API_VERSION_NUM_MAJOR == major && \ ICP_API_VERSION_NUM_MINOR < minor)) /** ******************************************************************************* * SAL software, firmware and hardware versions *****************************************************************************/ #define ICP_SAL_VERSIONS_FW_VERSION_SIZE 16 /**< Max length of firmware version string */ #define ICP_SAL_VERSIONS_SW_VERSION_SIZE 16 /**< Max length of software version string */ #define ICP_SAL_VERSIONS_MMP_VERSION_SIZE 16 /**< Max length of MMP binary version string */ #define ICP_SAL_VERSIONS_HW_VERSION_SIZE 4 /**< Max length of hardware version string */ /* Part name and number of the accelerator device */ #define SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER 25 #define SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER 8 #define SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER 0 #define SAL_INFO2_DRIVER_SW_VERSION_TYPE "in-tree" #define VERSION_STRING(ver) #ver #define VERSION_CONCAT(ver, ...) VERSION_STRING(ver) #__VA_ARGS__ #define QAT_SW_VERSION(s1, s2, s3, s4) s1 s2 s3 s4 static const char *__attribute__((used)) qat_sw_version = QAT_SW_VERSION(VERSION_CONCAT(QAT_SOFTWARE_VERSION, =), VERSION_CONCAT(SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, .), VERSION_CONCAT(SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, .), VERSION_CONCAT(SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER)); /** ******************************************************************************* * @ingroup SalVersions * Structure holding versions information * * @description * This structure stores information about versions of software * and hardware being run on a particular device. *****************************************************************************/ typedef struct icp_sal_dev_version_info_s { Cpa32U devId; /**< Number of acceleration device for which this structure holds version * information */ Cpa8U firmwareVersion[ICP_SAL_VERSIONS_FW_VERSION_SIZE]; /**< String identifying the version of the firmware associated with * the device. */ Cpa8U mmpVersion[ICP_SAL_VERSIONS_MMP_VERSION_SIZE]; /**< String identifying the version of the MMP binary associated with * the device. */ Cpa8U softwareVersion[ICP_SAL_VERSIONS_SW_VERSION_SIZE]; /**< String identifying the version of the software associated with * the device. */ Cpa8U hardwareVersion[ICP_SAL_VERSIONS_HW_VERSION_SIZE]; /**< String identifying the version of the hardware (stepping and * revision ID) associated with the device. */ } icp_sal_dev_version_info_t; /** ******************************************************************************* * @ingroup SalVersions * Obtains the version information for a given device * @description * This function obtains hardware and software version information * associated with a given device. * * @param[in] accelId ID of the acceleration device for which version * information is to be obtained. * @param[out] pVerInfo Pointer to a structure that will hold version * information * * @context * This function might sleep. It cannot be executed in a context that * does not permit sleeping. * @assumptions * The system has been started * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @return CPA_STATUS_SUCCESS Operation finished successfully * @return CPA_STATUS_INVALID_PARAM Invalid parameter passed to the function * @return CPA_STATUS_RESOURCE System resources problem * @return CPA_STATUS_FAIL Operation failed * *****************************************************************************/ CpaStatus icp_sal_getDevVersionInfo(Cpa32U accelId, icp_sal_dev_version_info_t *pVerInfo); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/000077500000000000000000000000001503624047500227115ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/000077500000000000000000000000001503624047500242015ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/000077500000000000000000000000001503624047500265425ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/crc32_gzip_refl_by8.S000066400000000000000000000440041503624047500324270ustar00rootroot00000000000000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Copyright(c) 2011-2022 Intel Corporation All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in ; the documentation and/or other materials provided with the ; distribution. ; * Neither the name of Intel Corporation nor the names of its ; contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Function API: ; UINT32 crc32_gzip_refl_by8( ; UINT32 init_crc, //initial CRC value, 32 bits ; const unsigned char *buf, //buffer pointer to calculate CRC on ; UINT64 len //buffer length in bytes (64-bit data) ; ); ; ; Authors: ; Erdinc Ozturk ; Vinodh Gopal ; James Guilford ; ; Reference paper titled "Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction" ; URL: http://download.intel.com/design/intarch/papers/323102.pdf ; ; ; sample yasm command line: ; yasm -f x64 -f elf64 -X gnu -g dwarf2 crc32_gzip_refl_by8 ; ; As explained here: ; http://docs.oracle.com/javase/7/docs/api/java/util/zip/package-summary.html ; CRC-32 checksum is described in RFC 1952 ; Implementing RFC 1952 CRC: ; http://www.ietf.org/rfc/rfc1952.txt %include "reg_sizes.asm" %define fetch_dist 1024 [bits 64] default rel section .text %ifidn __OUTPUT_FORMAT__, win64 %xdefine arg1 rcx %xdefine arg2 rdx %xdefine arg3 r8 %xdefine arg1_low32 ecx %else %xdefine arg1 rdi %xdefine arg2 rsi %xdefine arg3 rdx %xdefine arg1_low32 edi %endif %define TMP 16*0 %ifidn __OUTPUT_FORMAT__, win64 %define XMM_SAVE 16*2 %define VARIABLE_OFFSET 16*10+8 %else %define VARIABLE_OFFSET 16*2+8 %endif align 16 mk_global crc32_gzip_refl_by8, function crc32_gzip_refl_by8: endbranch ; unsigned long c = crc ^ 0xffffffffL; not arg1_low32 ; sub rsp, VARIABLE_OFFSET %ifidn __OUTPUT_FORMAT__, win64 ; push the xmm registers into the stack to maintain movdqa [rsp + XMM_SAVE + 16*0], xmm6 movdqa [rsp + XMM_SAVE + 16*1], xmm7 movdqa [rsp + XMM_SAVE + 16*2], xmm8 movdqa [rsp + XMM_SAVE + 16*3], xmm9 movdqa [rsp + XMM_SAVE + 16*4], xmm10 movdqa [rsp + XMM_SAVE + 16*5], xmm11 movdqa [rsp + XMM_SAVE + 16*6], xmm12 movdqa [rsp + XMM_SAVE + 16*7], xmm13 %endif ; check if smaller than 256B cmp arg3, 256 ; for sizes less than 256, we can't fold 128B at a time... jl _less_than_256 ; load the initial crc value movd xmm10, arg1_low32 ; initial crc ; receive the initial 64B data, xor the initial crc value movdqu xmm0, [arg2+16*0] movdqu xmm1, [arg2+16*1] movdqu xmm2, [arg2+16*2] movdqu xmm3, [arg2+16*3] movdqu xmm4, [arg2+16*4] movdqu xmm5, [arg2+16*5] movdqu xmm6, [arg2+16*6] movdqu xmm7, [arg2+16*7] ; XOR the initial_crc value pxor xmm0, xmm10 movdqa xmm10, [rk3] ;xmm10 has rk3 and rk4 ;imm value of pclmulqdq instruction will determine which constant to use ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; we subtract 256 instead of 128 to save one instruction from the loop sub arg3, 256 ; at this section of the code, there is 128*x+y (0<=y<128) bytes of buffer. The _fold_128_B_loop ; loop will fold 128B at a time until we have 128+y Bytes of buffer ; fold 128B at a time. This section of the code folds 8 xmm registers in parallel _fold_128_B_loop: ; update the buffer pointer add arg2, 128 prefetchnta [arg2+fetch_dist+0] movdqu xmm9, [arg2+16*0] movdqu xmm12, [arg2+16*1] movdqa xmm8, xmm0 movdqa xmm13, xmm1 pclmulqdq xmm0, xmm10, 0x10 pclmulqdq xmm8, xmm10 , 0x1 pclmulqdq xmm1, xmm10, 0x10 pclmulqdq xmm13, xmm10 , 0x1 pxor xmm0, xmm9 xorps xmm0, xmm8 pxor xmm1, xmm12 xorps xmm1, xmm13 prefetchnta [arg2+fetch_dist+32] movdqu xmm9, [arg2+16*2] movdqu xmm12, [arg2+16*3] movdqa xmm8, xmm2 movdqa xmm13, xmm3 pclmulqdq xmm2, xmm10, 0x10 pclmulqdq xmm8, xmm10 , 0x1 pclmulqdq xmm3, xmm10, 0x10 pclmulqdq xmm13, xmm10 , 0x1 pxor xmm2, xmm9 xorps xmm2, xmm8 pxor xmm3, xmm12 xorps xmm3, xmm13 prefetchnta [arg2+fetch_dist+64] movdqu xmm9, [arg2+16*4] movdqu xmm12, [arg2+16*5] movdqa xmm8, xmm4 movdqa xmm13, xmm5 pclmulqdq xmm4, xmm10, 0x10 pclmulqdq xmm8, xmm10 , 0x1 pclmulqdq xmm5, xmm10, 0x10 pclmulqdq xmm13, xmm10 , 0x1 pxor xmm4, xmm9 xorps xmm4, xmm8 pxor xmm5, xmm12 xorps xmm5, xmm13 prefetchnta [arg2+fetch_dist+96] movdqu xmm9, [arg2+16*6] movdqu xmm12, [arg2+16*7] movdqa xmm8, xmm6 movdqa xmm13, xmm7 pclmulqdq xmm6, xmm10, 0x10 pclmulqdq xmm8, xmm10 , 0x1 pclmulqdq xmm7, xmm10, 0x10 pclmulqdq xmm13, xmm10 , 0x1 pxor xmm6, xmm9 xorps xmm6, xmm8 pxor xmm7, xmm12 xorps xmm7, xmm13 sub arg3, 128 ; check if there is another 128B in the buffer to be able to fold jge _fold_128_B_loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; add arg2, 128 ; at this point, the buffer pointer is pointing at the last y Bytes of the buffer, where 0 <= y < 128 ; the 128B of folded data is in 8 of the xmm registers: xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 ; fold the 8 xmm registers to 1 xmm register with different constants movdqa xmm10, [rk9] movdqa xmm8, xmm0 pclmulqdq xmm0, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 xorps xmm7, xmm0 movdqa xmm10, [rk11] movdqa xmm8, xmm1 pclmulqdq xmm1, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 xorps xmm7, xmm1 movdqa xmm10, [rk13] movdqa xmm8, xmm2 pclmulqdq xmm2, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 pxor xmm7, xmm2 movdqa xmm10, [rk15] movdqa xmm8, xmm3 pclmulqdq xmm3, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 xorps xmm7, xmm3 movdqa xmm10, [rk17] movdqa xmm8, xmm4 pclmulqdq xmm4, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 pxor xmm7, xmm4 movdqa xmm10, [rk19] movdqa xmm8, xmm5 pclmulqdq xmm5, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 xorps xmm7, xmm5 movdqa xmm10, [rk1] movdqa xmm8, xmm6 pclmulqdq xmm6, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 pxor xmm7, xmm6 ; instead of 128, we add 128-16 to the loop counter to save 1 instruction from the loop ; instead of a cmp instruction, we use the negative flag with the jl instruction add arg3, 128-16 jl _final_reduction_for_128 ; now we have 16+y bytes left to reduce. 16 Bytes is in register xmm7 and the rest is in memory ; we can fold 16 bytes at a time if y>=16 ; continue folding 16B at a time _16B_reduction_loop: movdqa xmm8, xmm7 pclmulqdq xmm7, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 movdqu xmm0, [arg2] pxor xmm7, xmm0 add arg2, 16 sub arg3, 16 ; instead of a cmp instruction, we utilize the flags with the jge instruction ; equivalent of: cmp arg3, 16-16 ; check if there is any more 16B in the buffer to be able to fold jge _16B_reduction_loop ;now we have 16+z bytes left to reduce, where 0<= z < 16. ;first, we reduce the data in the xmm7 register _final_reduction_for_128: add arg3, 16 je _128_done ; here we are getting data that is less than 16 bytes. ; since we know that there was data before the pointer, we can offset the input pointer before the actual point, to receive exactly 16 bytes. ; after that the registers need to be adjusted. _get_last_two_xmms: movdqa xmm2, xmm7 movdqu xmm1, [arg2 - 16 + arg3] ; get rid of the extra data that was loaded before ; load the shift constant lea rax, [pshufb_shf_table] add rax, arg3 movdqu xmm0, [rax] pshufb xmm7, xmm0 pxor xmm0, [mask3] pshufb xmm2, xmm0 pblendvb xmm2, xmm1 ;xmm0 is implicit ;;;;;;;;;; movdqa xmm8, xmm7 pclmulqdq xmm7, xmm10, 0x1 pclmulqdq xmm8, xmm10, 0x10 pxor xmm7, xmm8 pxor xmm7, xmm2 _128_done: ; compute crc of a 128-bit value movdqa xmm10, [rk5] movdqa xmm0, xmm7 ;64b fold pclmulqdq xmm7, xmm10, 0 psrldq xmm0, 8 pxor xmm7, xmm0 ;32b fold movdqa xmm0, xmm7 pslldq xmm7, 4 pclmulqdq xmm7, xmm10, 0x10 pxor xmm7, xmm0 ;barrett reduction _barrett: pand xmm7, [mask2] movdqa xmm1, xmm7 movdqa xmm2, xmm7 movdqa xmm10, [rk7] pclmulqdq xmm7, xmm10, 0 pxor xmm7, xmm2 pand xmm7, [mask] movdqa xmm2, xmm7 pclmulqdq xmm7, xmm10, 0x10 pxor xmm7, xmm2 pxor xmm7, xmm1 pextrd eax, xmm7, 2 _cleanup: ; return c ^ 0xffffffffL; not eax %ifidn __OUTPUT_FORMAT__, win64 movdqa xmm6, [rsp + XMM_SAVE + 16*0] movdqa xmm7, [rsp + XMM_SAVE + 16*1] movdqa xmm8, [rsp + XMM_SAVE + 16*2] movdqa xmm9, [rsp + XMM_SAVE + 16*3] movdqa xmm10, [rsp + XMM_SAVE + 16*4] movdqa xmm11, [rsp + XMM_SAVE + 16*5] movdqa xmm12, [rsp + XMM_SAVE + 16*6] movdqa xmm13, [rsp + XMM_SAVE + 16*7] %endif add rsp, VARIABLE_OFFSET ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align 16 _less_than_256: ; check if there is enough buffer to be able to fold 16B at a time cmp arg3, 32 jl _less_than_32 ; if there is, load the constants movdqa xmm10, [rk1] ; rk1 and rk2 in xmm10 movd xmm0, arg1_low32 ; get the initial crc value movdqu xmm7, [arg2] ; load the plaintext pxor xmm7, xmm0 ; update the buffer pointer add arg2, 16 ; update the counter. subtract 32 instead of 16 to save one instruction from the loop sub arg3, 32 jmp _16B_reduction_loop align 16 _less_than_32: ; mov initial crc to the return value. this is necessary for zero-length buffers. mov eax, arg1_low32 test arg3, arg3 je _cleanup movd xmm0, arg1_low32 ; get the initial crc value cmp arg3, 16 je _exact_16_left jl _less_than_16_left movdqu xmm7, [arg2] ; load the plaintext pxor xmm7, xmm0 ; xor the initial crc value add arg2, 16 sub arg3, 16 movdqa xmm10, [rk1] ; rk1 and rk2 in xmm10 jmp _get_last_two_xmms align 16 _less_than_16_left: ; use stack space to load data less than 16 bytes, zero-out the 16B in memory first. pxor xmm1, xmm1 mov r11, rsp movdqa [r11], xmm1 cmp arg3, 4 jl _only_less_than_4 ; backup the counter value mov r9, arg3 cmp arg3, 8 jl _less_than_8_left ; load 8 Bytes mov rax, [arg2] mov [r11], rax add r11, 8 sub arg3, 8 add arg2, 8 _less_than_8_left: cmp arg3, 4 jl _less_than_4_left ; load 4 Bytes mov eax, [arg2] mov [r11], eax add r11, 4 sub arg3, 4 add arg2, 4 _less_than_4_left: cmp arg3, 2 jl _less_than_2_left ; load 2 Bytes mov ax, [arg2] mov [r11], ax add r11, 2 sub arg3, 2 add arg2, 2 _less_than_2_left: cmp arg3, 1 jl _zero_left ; load 1 Byte mov al, [arg2] mov [r11], al _zero_left: movdqa xmm7, [rsp] pxor xmm7, xmm0 ; xor the initial crc value lea rax,[pshufb_shf_table] movdqu xmm0, [rax + r9] pshufb xmm7,xmm0 jmp _128_done align 16 _exact_16_left: movdqu xmm7, [arg2] pxor xmm7, xmm0 ; xor the initial crc value jmp _128_done _only_less_than_4: cmp arg3, 3 jl _only_less_than_3 ; load 3 Bytes mov al, [arg2] mov [r11], al mov al, [arg2+1] mov [r11+1], al mov al, [arg2+2] mov [r11+2], al movdqa xmm7, [rsp] pxor xmm7, xmm0 ; xor the initial crc value pslldq xmm7, 5 jmp _barrett _only_less_than_3: cmp arg3, 2 jl _only_less_than_2 ; load 2 Bytes mov al, [arg2] mov [r11], al mov al, [arg2+1] mov [r11+1], al movdqa xmm7, [rsp] pxor xmm7, xmm0 ; xor the initial crc value pslldq xmm7, 6 jmp _barrett _only_less_than_2: ; load 1 Byte mov al, [arg2] mov [r11], al movdqa xmm7, [rsp] pxor xmm7, xmm0 ; xor the initial crc value pslldq xmm7, 7 jmp _barrett section .data ; precomputed constants align 16 rk1 : DQ 0x00000000ccaa009e rk2 : DQ 0x00000001751997d0 rk3 : DQ 0x000000014a7fe880 rk4 : DQ 0x00000001e88ef372 rk5 : DQ 0x00000000ccaa009e rk6 : DQ 0x0000000163cd6124 rk7 : DQ 0x00000001f7011640 rk8 : DQ 0x00000001db710640 rk9 : DQ 0x00000001d7cfc6ac rk10 : DQ 0x00000001ea89367e rk11 : DQ 0x000000018cb44e58 rk12 : DQ 0x00000000df068dc2 rk13 : DQ 0x00000000ae0b5394 rk14 : DQ 0x00000001c7569e54 rk15 : DQ 0x00000001c6e41596 rk16 : DQ 0x0000000154442bd4 rk17 : DQ 0x0000000174359406 rk18 : DQ 0x000000003db1ecdc rk19 : DQ 0x000000015a546366 rk20 : DQ 0x00000000f1da05aa mask: dq 0xFFFFFFFFFFFFFFFF, 0x0000000000000000 mask2: dq 0xFFFFFFFF00000000, 0xFFFFFFFFFFFFFFFF mask3: dq 0x8080808080808080, 0x8080808080808080 pshufb_shf_table: ; use these values for shift constants for the pshufb instruction ; different alignments result in values as shown: ; dq 0x8887868584838281, 0x008f8e8d8c8b8a89 ; shl 15 (16-1) / shr1 ; dq 0x8988878685848382, 0x01008f8e8d8c8b8a ; shl 14 (16-3) / shr2 ; dq 0x8a89888786858483, 0x0201008f8e8d8c8b ; shl 13 (16-4) / shr3 ; dq 0x8b8a898887868584, 0x030201008f8e8d8c ; shl 12 (16-4) / shr4 ; dq 0x8c8b8a8988878685, 0x04030201008f8e8d ; shl 11 (16-5) / shr5 ; dq 0x8d8c8b8a89888786, 0x0504030201008f8e ; shl 10 (16-6) / shr6 ; dq 0x8e8d8c8b8a898887, 0x060504030201008f ; shl 9 (16-7) / shr7 ; dq 0x8f8e8d8c8b8a8988, 0x0706050403020100 ; shl 8 (16-8) / shr8 ; dq 0x008f8e8d8c8b8a89, 0x0807060504030201 ; shl 7 (16-9) / shr9 ; dq 0x01008f8e8d8c8b8a, 0x0908070605040302 ; shl 6 (16-10) / shr10 ; dq 0x0201008f8e8d8c8b, 0x0a09080706050403 ; shl 5 (16-11) / shr11 ; dq 0x030201008f8e8d8c, 0x0b0a090807060504 ; shl 4 (16-12) / shr12 ; dq 0x04030201008f8e8d, 0x0c0b0a0908070605 ; shl 3 (16-13) / shr13 ; dq 0x0504030201008f8e, 0x0d0c0b0a09080706 ; shl 2 (16-14) / shr14 ; dq 0x060504030201008f, 0x0e0d0c0b0a090807 ; shl 1 (16-15) / shr15 dq 0x8786858483828100, 0x8f8e8d8c8b8a8988 dq 0x0706050403020100, 0x000e0d0c0b0a0908 qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/crc64_ecma_norm_by8.S000066400000000000000000000357611503624047500324250ustar00rootroot00000000000000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Copyright(c) 2011-2022 Intel Corporation All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in ; the documentation and/or other materials provided with the ; distribution. ; * Neither the name of Intel Corporation nor the names of its ; contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Function API: ; uint64_t crc64_ecma_norm_by8( ; uint64_t init_crc, //initial CRC value, 64 bits ; const unsigned char *buf, //buffer pointer to calculate CRC on ; uint64_t len //buffer length in bytes (64-bit data) ; ); ; ; yasm -f x64 -f elf64 -X gnu -g dwarf2 crc64_ecma_norm_by8 %include "reg_sizes.asm" %define fetch_dist 1024 [bits 64] default rel section .text %ifidn __OUTPUT_FORMAT__, win64 %xdefine arg1 rcx %xdefine arg2 rdx %xdefine arg3 r8 %else %xdefine arg1 rdi %xdefine arg2 rsi %xdefine arg3 rdx %endif %define TMP 16*0 %ifidn __OUTPUT_FORMAT__, win64 %define XMM_SAVE 16*2 %define VARIABLE_OFFSET 16*10+8 %else %define VARIABLE_OFFSET 16*2+8 %endif align 16 mk_global crc64_ecma_norm_by8, function crc64_ecma_norm_by8: endbranch ; commented out for CPM gen4 HW compatibility ;not arg1 ;~init_crc sub rsp,VARIABLE_OFFSET %ifidn __OUTPUT_FORMAT__, win64 ; push the xmm registers into the stack to maintain movdqa [rsp + XMM_SAVE + 16*0], xmm6 movdqa [rsp + XMM_SAVE + 16*1], xmm7 movdqa [rsp + XMM_SAVE + 16*2], xmm8 movdqa [rsp + XMM_SAVE + 16*3], xmm9 movdqa [rsp + XMM_SAVE + 16*4], xmm10 movdqa [rsp + XMM_SAVE + 16*5], xmm11 movdqa [rsp + XMM_SAVE + 16*6], xmm12 movdqa [rsp + XMM_SAVE + 16*7], xmm13 %endif ; check if smaller than 256 cmp arg3, 256 ; for sizes less than 256, we can't fold 128B at a time... jl _less_than_256 ; load the initial crc value movq xmm10, arg1 ; initial crc ; crc value does not need to be byte-reflected, but it needs to be moved to the high part of the register. ; because data will be byte-reflected and will align with initial crc at correct place. pslldq xmm10, 8 movdqa xmm11, [SHUF_MASK] ; receive the initial 128B data, xor the initial crc value movdqu xmm0, [arg2+16*0] movdqu xmm1, [arg2+16*1] movdqu xmm2, [arg2+16*2] movdqu xmm3, [arg2+16*3] movdqu xmm4, [arg2+16*4] movdqu xmm5, [arg2+16*5] movdqu xmm6, [arg2+16*6] movdqu xmm7, [arg2+16*7] pshufb xmm0, xmm11 ; XOR the initial_crc value pxor xmm0, xmm10 pshufb xmm1, xmm11 pshufb xmm2, xmm11 pshufb xmm3, xmm11 pshufb xmm4, xmm11 pshufb xmm5, xmm11 pshufb xmm6, xmm11 pshufb xmm7, xmm11 movdqa xmm10, [rk3] ;xmm10 has rk3 and rk4 ;imm value of pclmulqdq instruction will determine which constant to use ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; we subtract 256 instead of 128 to save one instruction from the loop sub arg3, 256 ; at this section of the code, there is 128*x+y (0<=y<128) bytes of buffer. The _fold_128_B_loop ; loop will fold 128B at a time until we have 128+y Bytes of buffer ; fold 128B at a time. This section of the code folds 8 xmm registers in parallel _fold_128_B_loop: ; update the buffer pointer add arg2, 128 ; buf += 128; prefetchnta [arg2+fetch_dist+0] movdqu xmm9, [arg2+16*0] movdqu xmm12, [arg2+16*1] pshufb xmm9, xmm11 pshufb xmm12, xmm11 movdqa xmm8, xmm0 movdqa xmm13, xmm1 pclmulqdq xmm0, xmm10, 0x0 pclmulqdq xmm8, xmm10 , 0x11 pclmulqdq xmm1, xmm10, 0x0 pclmulqdq xmm13, xmm10 , 0x11 pxor xmm0, xmm9 xorps xmm0, xmm8 pxor xmm1, xmm12 xorps xmm1, xmm13 prefetchnta [arg2+fetch_dist+32] movdqu xmm9, [arg2+16*2] movdqu xmm12, [arg2+16*3] pshufb xmm9, xmm11 pshufb xmm12, xmm11 movdqa xmm8, xmm2 movdqa xmm13, xmm3 pclmulqdq xmm2, xmm10, 0x0 pclmulqdq xmm8, xmm10 , 0x11 pclmulqdq xmm3, xmm10, 0x0 pclmulqdq xmm13, xmm10 , 0x11 pxor xmm2, xmm9 xorps xmm2, xmm8 pxor xmm3, xmm12 xorps xmm3, xmm13 prefetchnta [arg2+fetch_dist+64] movdqu xmm9, [arg2+16*4] movdqu xmm12, [arg2+16*5] pshufb xmm9, xmm11 pshufb xmm12, xmm11 movdqa xmm8, xmm4 movdqa xmm13, xmm5 pclmulqdq xmm4, xmm10, 0x0 pclmulqdq xmm8, xmm10 , 0x11 pclmulqdq xmm5, xmm10, 0x0 pclmulqdq xmm13, xmm10 , 0x11 pxor xmm4, xmm9 xorps xmm4, xmm8 pxor xmm5, xmm12 xorps xmm5, xmm13 prefetchnta [arg2+fetch_dist+96] movdqu xmm9, [arg2+16*6] movdqu xmm12, [arg2+16*7] pshufb xmm9, xmm11 pshufb xmm12, xmm11 movdqa xmm8, xmm6 movdqa xmm13, xmm7 pclmulqdq xmm6, xmm10, 0x0 pclmulqdq xmm8, xmm10 , 0x11 pclmulqdq xmm7, xmm10, 0x0 pclmulqdq xmm13, xmm10 , 0x11 pxor xmm6, xmm9 xorps xmm6, xmm8 pxor xmm7, xmm12 xorps xmm7, xmm13 sub arg3, 128 ; check if there is another 128B in the buffer to be able to fold jge _fold_128_B_loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; add arg2, 128 ; at this point, the buffer pointer is pointing at the last y Bytes of the buffer, where 0 <= y < 128 ; the 128B of folded data is in 8 of the xmm registers: xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 ; fold the 8 xmm registers to 1 xmm register with different constants movdqa xmm10, [rk9] movdqa xmm8, xmm0 pclmulqdq xmm0, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 xorps xmm7, xmm0 movdqa xmm10, [rk11] movdqa xmm8, xmm1 pclmulqdq xmm1, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 xorps xmm7, xmm1 movdqa xmm10, [rk13] movdqa xmm8, xmm2 pclmulqdq xmm2, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 pxor xmm7, xmm2 movdqa xmm10, [rk15] movdqa xmm8, xmm3 pclmulqdq xmm3, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 xorps xmm7, xmm3 movdqa xmm10, [rk17] movdqa xmm8, xmm4 pclmulqdq xmm4, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 pxor xmm7, xmm4 movdqa xmm10, [rk19] movdqa xmm8, xmm5 pclmulqdq xmm5, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 xorps xmm7, xmm5 movdqa xmm10, [rk1] ;xmm10 has rk1 and rk2 movdqa xmm8, xmm6 pclmulqdq xmm6, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 pxor xmm7, xmm6 ; instead of 128, we add 112 to the loop counter to save 1 instruction from the loop ; instead of a cmp instruction, we use the negative flag with the jl instruction add arg3, 128-16 jl _final_reduction_for_128 ; now we have 16+y bytes left to reduce. 16 Bytes is in register xmm7 and the rest is in memory ; we can fold 16 bytes at a time if y>=16 ; continue folding 16B at a time _16B_reduction_loop: movdqa xmm8, xmm7 pclmulqdq xmm7, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 movdqu xmm0, [arg2] pshufb xmm0, xmm11 pxor xmm7, xmm0 add arg2, 16 sub arg3, 16 ; instead of a cmp instruction, we utilize the flags with the jge instruction ; equivalent of: cmp arg3, 16-16 ; check if there is any more 16B in the buffer to be able to fold jge _16B_reduction_loop ;now we have 16+z bytes left to reduce, where 0<= z < 16. ;first, we reduce the data in the xmm7 register _final_reduction_for_128: ; check if any more data to fold. If not, compute the CRC of the final 128 bits add arg3, 16 je _128_done ; here we are getting data that is less than 16 bytes. ; since we know that there was data before the pointer, we can offset the input pointer before the actual point, to receive exactly 16 bytes. ; after that the registers need to be adjusted. _get_last_two_xmms: movdqa xmm2, xmm7 movdqu xmm1, [arg2 - 16 + arg3] pshufb xmm1, xmm11 ; get rid of the extra data that was loaded before ; load the shift constant lea rax, [pshufb_shf_table + 16] sub rax, arg3 movdqu xmm0, [rax] ; shift xmm2 to the left by arg3 bytes pshufb xmm2, xmm0 ; shift xmm7 to the right by 16-arg3 bytes pxor xmm0, [mask1] pshufb xmm7, xmm0 pblendvb xmm1, xmm2 ;xmm0 is implicit ; fold 16 Bytes movdqa xmm2, xmm1 movdqa xmm8, xmm7 pclmulqdq xmm7, xmm10, 0x11 pclmulqdq xmm8, xmm10, 0x0 pxor xmm7, xmm8 pxor xmm7, xmm2 _128_done: ; compute crc of a 128-bit value movdqa xmm10, [rk5] ; rk5 and rk6 in xmm10 movdqa xmm0, xmm7 ;64b fold pclmulqdq xmm7, xmm10, 0x01 ; H*L pslldq xmm0, 8 pxor xmm7, xmm0 ;barrett reduction _barrett: movdqa xmm10, [rk7] ; rk7 and rk8 in xmm10 movdqa xmm0, xmm7 movdqa xmm1, xmm7 pand xmm1, [mask3] pclmulqdq xmm7, xmm10, 0x01 pxor xmm7, xmm1 pclmulqdq xmm7, xmm10, 0x11 pxor xmm7, xmm0 pextrq rax, xmm7, 0 _cleanup: ; commented out for CPM gen4 HW compatibility ;not rax %ifidn __OUTPUT_FORMAT__, win64 movdqa xmm6, [rsp + XMM_SAVE + 16*0] movdqa xmm7, [rsp + XMM_SAVE + 16*1] movdqa xmm8, [rsp + XMM_SAVE + 16*2] movdqa xmm9, [rsp + XMM_SAVE + 16*3] movdqa xmm10, [rsp + XMM_SAVE + 16*4] movdqa xmm11, [rsp + XMM_SAVE + 16*5] movdqa xmm12, [rsp + XMM_SAVE + 16*6] movdqa xmm13, [rsp + XMM_SAVE + 16*7] %endif add rsp, VARIABLE_OFFSET ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align 16 _less_than_256: ; check if there is enough buffer to be able to fold 16B at a time cmp arg3, 32 jl _less_than_32 movdqa xmm11, [SHUF_MASK] ; if there is, load the constants movdqa xmm10, [rk1] ; rk1 and rk2 in xmm10 movq xmm0, arg1 ; get the initial crc value pslldq xmm0, 8 ; align it to its correct place movdqu xmm7, [arg2] ; load the plaintext pshufb xmm7, xmm11 ; byte-reflect the plaintext pxor xmm7, xmm0 ; update the buffer pointer add arg2, 16 ; update the counter. subtract 32 instead of 16 to save one instruction from the loop sub arg3, 32 jmp _16B_reduction_loop align 16 _less_than_32: ; mov initial crc to the return value. this is necessary for zero-length buffers. mov rax, arg1 test arg3, arg3 je _cleanup movdqa xmm11, [SHUF_MASK] movq xmm0, arg1 ; get the initial crc value pslldq xmm0, 8 ; align it to its correct place cmp arg3, 16 je _exact_16_left jl _less_than_16_left movdqu xmm7, [arg2] ; load the plaintext pshufb xmm7, xmm11 ; byte-reflect the plaintext pxor xmm7, xmm0 ; xor the initial crc value add arg2, 16 sub arg3, 16 movdqa xmm10, [rk1] ; rk1 and rk2 in xmm10 jmp _get_last_two_xmms align 16 _less_than_16_left: ; use stack space to load data less than 16 bytes, zero-out the 16B in memory first. pxor xmm1, xmm1 mov r11, rsp movdqa [r11], xmm1 ; backup the counter value mov r9, arg3 cmp arg3, 8 jl _less_than_8_left ; load 8 Bytes mov rax, [arg2] mov [r11], rax add r11, 8 sub arg3, 8 add arg2, 8 _less_than_8_left: cmp arg3, 4 jl _less_than_4_left ; load 4 Bytes mov eax, [arg2] mov [r11], eax add r11, 4 sub arg3, 4 add arg2, 4 _less_than_4_left: cmp arg3, 2 jl _less_than_2_left ; load 2 Bytes mov ax, [arg2] mov [r11], ax add r11, 2 sub arg3, 2 add arg2, 2 _less_than_2_left: cmp arg3, 1 jl _zero_left ; load 1 Byte mov al, [arg2] mov [r11], al _zero_left: movdqa xmm7, [rsp] pshufb xmm7, xmm11 pxor xmm7, xmm0 ; xor the initial crc value ; shl r9, 4 lea rax, [pshufb_shf_table + 16] sub rax, r9 cmp r9, 8 jl _end_1to7 _end_8to15: movdqu xmm0, [rax] pxor xmm0, [mask1] pshufb xmm7, xmm0 jmp _128_done _end_1to7: ; Right shift (8-length) bytes in XMM add rax, 8 movdqu xmm0, [rax] pshufb xmm7,xmm0 jmp _barrett align 16 _exact_16_left: movdqu xmm7, [arg2] pshufb xmm7, xmm11 pxor xmm7, xmm0 ; xor the initial crc value jmp _128_done section .data ; precomputed constants align 16 rk1 : DQ 0x5f5c3c7eb52fab6 rk2 : DQ 0x4eb938a7d257740e rk3 : DQ 0x5cf79dea9ac37d6 rk4 : DQ 0x001067e571d7d5c2 rk5 : DQ 0x5f5c3c7eb52fab6 rk6 : DQ 0x0000000000000000 rk7 : DQ 0x578d29d06cc4f872 rk8 : DQ 0x42f0e1eba9ea3693 rk9 : DQ 0xe464f4df5fb60ac1 rk10 : DQ 0xb649c5b35a759cf2 rk11 : DQ 0x9af04e1eff82d0dd rk12 : DQ 0x6e82e609297f8fe8 rk13 : DQ 0x97c516e98bd2e73 rk14 : DQ 0xb76477b31e22e7b rk15 : DQ 0x5f6843ca540df020 rk16 : DQ 0xddf4b6981205b83f rk17 : DQ 0x54819d8713758b2c rk18 : DQ 0x4a6b90073eb0af5a rk19 : DQ 0x571bee0a227ef92b rk20 : DQ 0x44bef2a201b5200c mask1: dq 0x8080808080808080, 0x8080808080808080 mask2: dq 0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFF mask3: dq 0x0000000000000000, 0xFFFFFFFFFFFFFFFF SHUF_MASK: dq 0x08090A0B0C0D0E0F, 0x0001020304050607 pshufb_shf_table: ; use these values for shift constants for the pshufb instruction ; different alignments result in values as shown: ; dq 0x8887868584838281, 0x008f8e8d8c8b8a89 ; shl 15 (16-1) / shr1 ; dq 0x8988878685848382, 0x01008f8e8d8c8b8a ; shl 14 (16-3) / shr2 ; dq 0x8a89888786858483, 0x0201008f8e8d8c8b ; shl 13 (16-4) / shr3 ; dq 0x8b8a898887868584, 0x030201008f8e8d8c ; shl 12 (16-4) / shr4 ; dq 0x8c8b8a8988878685, 0x04030201008f8e8d ; shl 11 (16-5) / shr5 ; dq 0x8d8c8b8a89888786, 0x0504030201008f8e ; shl 10 (16-6) / shr6 ; dq 0x8e8d8c8b8a898887, 0x060504030201008f ; shl 9 (16-7) / shr7 ; dq 0x8f8e8d8c8b8a8988, 0x0706050403020100 ; shl 8 (16-8) / shr8 ; dq 0x008f8e8d8c8b8a89, 0x0807060504030201 ; shl 7 (16-9) / shr9 ; dq 0x01008f8e8d8c8b8a, 0x0908070605040302 ; shl 6 (16-10) / shr10 ; dq 0x0201008f8e8d8c8b, 0x0a09080706050403 ; shl 5 (16-11) / shr11 ; dq 0x030201008f8e8d8c, 0x0b0a090807060504 ; shl 4 (16-12) / shr12 ; dq 0x04030201008f8e8d, 0x0c0b0a0908070605 ; shl 3 (16-13) / shr13 ; dq 0x0504030201008f8e, 0x0d0c0b0a09080706 ; shl 2 (16-14) / shr14 ; dq 0x060504030201008f, 0x0e0d0c0b0a090807 ; shl 1 (16-15) / shr15 dq 0x8786858483828100, 0x8f8e8d8c8b8a8988 dq 0x0706050403020100, 0x0f0e0d0c0b0a0908 dq 0x8080808080808080, 0x0f0e0d0c0b0a0908 dq 0x8080808080808080, 0x8080808080808080 qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_buffers.c000066400000000000000000000371751503624047500310250ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_buffers.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of the buffer management operations for * Data Compression service. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" #include "sal_types_compression.h" #include "icp_qat_fw_comp.h" #define CPA_DC_CEIL_DIV(x, y) (((x) + (y)-1) / (y)) #define DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 (55) #define DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_STATIC (1029) #define DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_DYN (512) #define DC_DEST_BUFF_EXTRA_LZ4_GEN4 (1024) #define DC_DEST_BUFF_EXTRA_LZ4S_GEN4 (1024) #define DC_DEST_BUFF_MIN_EXTRA_BYTES(x) ((x < 8) ? (8 - x) : 0) #define DC_BUF_MAX_SIZE (0xFFFFFFFF) /* To determine an overflow on a 32 unsigned value */ #define UINT_OVERFLOW (0xFFFFFFFF00000000UL) #define DC_NUM_EXTRA_BUFFERS (1) #define DC_NUM_DICT_BUFFERS (1) CpaStatus cpaDcBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, Cpa32U numBuffers, Cpa32U *pSizeInBytes) { CpaInstanceHandle insHandle = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { insHandle = dcGetFirstHandle(); } else { insHandle = instanceHandle; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(insHandle); LAC_CHECK_NULL_PARAM(pSizeInBytes); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); if (0 == numBuffers) { LAC_INVALID_PARAM_LOG("Number of Buffers"); return CPA_STATUS_INVALID_PARAM; } #endif *pSizeInBytes = (sizeof(icp_buffer_list_desc_t) + (sizeof(icp_flat_buffer_desc_t) * (numBuffers + DC_NUM_EXTRA_BUFFERS)) + ICP_DESCRIPTOR_ALIGNMENT_BYTES); #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, %d, 0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle, numBuffers, (LAC_ARCH_UINT)pSizeInBytes, *pSizeInBytes); #endif return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup cpaDc * Function to return the size of the memory which must be allocated for * the pPrivateMetaData member of the CpaBufferList used with dictionary * compression. * * @description * This function is used to obtain the size (in bytes) required to * allocate a buffer descriptor for the pPrivateMetaData member in the * CpaBufferList structure of the source buffer list used in the API's * cpaDcCompressDataWithDict() and cpaDcDecompressDataWithDict(). * In contrast the size in bytes to allocate the descriptor of the * destination buffer list must not use this API, and needs to be * determined using the API cpaDcBufferListGetMetaSize(). * * @param[in] instanceHandle Handle to an instance of this API. * @param[in] numDictBuffers The number of CpaFlatBuffers contained in * the dictionary buffer CpaBufferList. * This number must not be exceeded during use. * @param[in] numSourceBuffers The number of CpaFlatBuffers contained in * the source buffer CpaBufferList. * This number must not be exceeded during use. * @param[out] pSizeInBytes Pointer to the size in bytes of memory to be * allocated as metadata to be assigned within * the source buffer CpaBufferList. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * *****************************************************************************/ CpaStatus cpaDcGetMetaSizeForSrcBuffWithDict( const CpaInstanceHandle instanceHandle, Cpa32U numDictBuffers, Cpa32U numSourceBuffers, Cpa32U *pSizeInBytes) { return CPA_STATUS_UNSUPPORTED; } CpaStatus dcDeflateBoundGen2(void *pService, CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize) { Cpa64U inBufferSize = inputSize; Cpa64U outBufferSize = 0; /* Formula for GEN2 deflate: * ceil(9 * Total input bytes / 8) + 55 bytes. * 55 bytes is the skid pad value for GEN2 devices. * Adding extra bytes = `DC_DEST_BUFF_MIN_EXTRA_BYTES(inputSize)` * when calculated value from `CPA_DC_CEIL_DIV(9 * inputSize, 8) + * DC_DEST_BUFF_EXTRA_DEFLATE_GEN2` is less than 64 bytes to * achieve a safer output buffer size of 64 bytes. */ outBufferSize = CPA_DC_CEIL_DIV(9 * inBufferSize, 8) + DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 + DC_DEST_BUFF_MIN_EXTRA_BYTES(inputSize); if (outBufferSize > DC_BUF_MAX_SIZE) *outputSize = DC_BUF_MAX_SIZE; else *outputSize = (Cpa32U)outBufferSize; return CPA_STATUS_SUCCESS; } CpaStatus dcDeflateBoundGen4(void *pServiceType, CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize) { Cpa64U outputSizeLong; Cpa64U inputSizeLong = (Cpa64U)inputSize; sal_compression_service_t *pService = NULL; pService = (sal_compression_service_t *)pServiceType; switch (huffType) { case CPA_DC_HT_STATIC: /* Formula for GEN4 static deflate: * ceil((9*sourceLen)/8) + 5 + 1024. */ outputSizeLong = CPA_DC_CEIL_DIV(9 * inputSizeLong, 8) + DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_STATIC; break; case CPA_DC_HT_FULL_DYNAMIC: outputSizeLong = DC_DEST_BUFF_EXTRA_DEFLATE_GEN4_DYN; outputSizeLong += CPA_DC_CEIL_DIV(9 * inputSizeLong, 8); if (pService->generic_service_info.isGen4_2) { /* Formula for GEN4_2 dynamic deflate: * Ceil ((9*sourceLen)/8) + * ((((8/7) * sourceLen)/ 4KB) * (150+5)) + 512 */ outputSizeLong += ((8 * inputSizeLong * 155) / 7) / (4 * 1024); } else { /* Formula for GEN4 dynamic deflate: * Ceil ((9*sourceLen)/8) + * ((((8/7) * sourceLen)/ 16KB) * (150+5)) + 512 */ outputSizeLong += ((8 * inputSizeLong * 155) / 7) / (16 * 1024); } break; default: return CPA_STATUS_INVALID_PARAM; } /* Avoid output size overflow */ if (outputSizeLong & UINT_OVERFLOW) return CPA_STATUS_INVALID_PARAM; *outputSize = (Cpa32U)outputSizeLong; return CPA_STATUS_SUCCESS; } CpaStatus cpaDcDeflateCompressBound(const CpaInstanceHandle dcInstance, CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize) { sal_compression_service_t *pService; CpaInstanceHandle insHandle = NULL; dc_capabilities_t *pDcCapabilities = NULL; #ifdef ICP_PARAM_CHECK CpaBoolean dynHuffmanSupported = CPA_FALSE; #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(insHandle); LAC_CHECK_NULL_PARAM(outputSize); /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif pService = (sal_compression_service_t *)insHandle; /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; #ifdef ICP_PARAM_CHECK dynHuffmanSupported = DC_CAPS_DEFLATE_TYPE_SUPPORT_GET(pDcCapabilities->deflate.typeSupport, DC_CAPS_DEFLATE_TYPE_DYNAMIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); if (!inputSize) { LAC_INVALID_PARAM_LOG("The input size needs to be greater than zero"); return CPA_STATUS_INVALID_PARAM; } if ((CPA_DC_HT_STATIC != huffType) && (CPA_DC_HT_FULL_DYNAMIC != huffType)) { LAC_INVALID_PARAM_LOG("Invalid huffType value"); return CPA_STATUS_INVALID_PARAM; } if ((CPA_FALSE == dynHuffmanSupported) && (CPA_DC_HT_FULL_DYNAMIC == huffType)) { LAC_INVALID_PARAM_LOG("Invalid huffType value"); return CPA_STATUS_INVALID_PARAM; } #endif return (pDcCapabilities->dcDeflateBound)( (void *)pService, huffType, inputSize, outputSize); } CpaStatus dcLZ4BoundGen4(Cpa32U inputSize, Cpa32U *outputSize) { Cpa64U outputSizeLong; Cpa64U inputSizeLong = (Cpa64U)inputSize; /* Formula for GEN4 LZ4: * sourceLen + Ceil(sourceLen/1520) * 13 + 1024 */ outputSizeLong = inputSizeLong + DC_DEST_BUFF_EXTRA_LZ4_GEN4; outputSizeLong += CPA_DC_CEIL_DIV(inputSizeLong, 1520) * 13; /* Avoid output size overflow */ if (outputSizeLong & UINT_OVERFLOW) return CPA_STATUS_INVALID_PARAM; *outputSize = (Cpa32U)outputSizeLong; return CPA_STATUS_SUCCESS; } CpaStatus dcLZ4SBoundGen4(Cpa32U inputSize, Cpa32U *outputSize) { Cpa64U outputSizeLong; Cpa64U inputSizeLong = (Cpa64U)inputSize; /* Formula for GEN4 LZ4S: * sourceLen + Ceil(sourceLen/2000) * 11 + 1024 */ outputSizeLong = inputSizeLong + DC_DEST_BUFF_EXTRA_LZ4S_GEN4; outputSizeLong += CPA_DC_CEIL_DIV(inputSizeLong, 2000) * 11; /* Avoid output size overflow */ if (outputSizeLong & UINT_OVERFLOW) return CPA_STATUS_INVALID_PARAM; *outputSize = (Cpa32U)outputSizeLong; return CPA_STATUS_SUCCESS; } CpaStatus cpaDcLZ4CompressBound(const CpaInstanceHandle dcInstance, Cpa32U inputSize, Cpa32U *outputSize) { sal_compression_service_t *pService = NULL; CpaInstanceHandle insHandle = NULL; dc_capabilities_t *pDcCapabilities = NULL; CpaBoolean lz4Supported = CPA_FALSE; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(insHandle); LAC_CHECK_NULL_PARAM(outputSize); /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); if (!inputSize) { return CPA_STATUS_INVALID_PARAM; } #endif pService = (sal_compression_service_t *)insHandle; /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; lz4Supported = pDcCapabilities->lz4.supported; if (CPA_FALSE == lz4Supported) { return CPA_STATUS_UNSUPPORTED; } if (pDcCapabilities->dcLZ4Bound) { return (pDcCapabilities->dcLZ4Bound)(inputSize, outputSize); } else { return CPA_STATUS_UNSUPPORTED; } } CpaStatus cpaDcLZ4SCompressBound(const CpaInstanceHandle dcInstance, Cpa32U inputSize, Cpa32U *outputSize) { sal_compression_service_t *pService = NULL; CpaInstanceHandle insHandle = NULL; dc_capabilities_t *pDcCapabilities = NULL; CpaBoolean lz4sSupported = CPA_FALSE; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(insHandle); LAC_CHECK_NULL_PARAM(outputSize); /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); if (!inputSize) { return CPA_STATUS_INVALID_PARAM; } #endif pService = (sal_compression_service_t *)insHandle; /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; lz4sSupported = pDcCapabilities->lz4s.supported; if (CPA_FALSE == lz4sSupported) { return CPA_STATUS_UNSUPPORTED; } if (pDcCapabilities->dcLZ4SBound) { return (pDcCapabilities->dcLZ4SBound)(inputSize, outputSize); } else { return CPA_STATUS_UNSUPPORTED; } } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_capabilities.c000066400000000000000000001032041503624047500320050ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_capabilities.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Gets capabilities on the current instance * *****************************************************************************/ /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "sal_types_compression.h" /* DEBUG */ #ifdef ICP_DEBUG #undef STATIC /* When DEBUG is set, STATIC and INLINE evaluates to nothing. */ #define STATIC #define INLINE #else /* otherwise they evaluate to the static and inline keywords, * respectively. */ #define STATIC static #define INLINE inline #endif CpaStatus dcGetAsbEnablePrefCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus) { *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if (pDcCapabilities->deflate.asbEnablePref) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if (pDcCapabilities->lz4.asbEnablePref) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4S: if (pDcCapabilities->lz4s.asbEnablePref) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } STATIC INLINE CpaStatus dcGetAlgoWindowSizeForCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U capId, Cpa32U dir, Cpa32U algo, CpaBoolean *pCapStatus) { Cpa16U validBitMask = 0; Cpa16U windowSizeMask = 0; *pCapStatus = CPA_FALSE; switch (dir) { case CPA_DC_DIR_COMPRESS: case CPA_DC_DIR_DECOMPRESS: break; case CPA_DC_DIR_COMBINED: LAC_LOG_ERROR("Combined direction is not supported\n"); return CPA_STATUS_INVALID_PARAM; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm direction is not supported\n"); return CPA_STATUS_UNSUPPORTED; } switch (capId) { case CPA_DC_CAP_BOOL_WINDOW_SIZE_4K: validBitMask = DC_4K_WINDOW_MASK; break; case CPA_DC_CAP_BOOL_WINDOW_SIZE_8K: validBitMask = DC_8K_WINDOW_MASK; break; case CPA_DC_CAP_BOOL_WINDOW_SIZE_16K: validBitMask = DC_16K_WINDOW_MASK; break; case CPA_DC_CAP_BOOL_WINDOW_SIZE_32K: validBitMask = DC_32K_WINDOW_MASK; break; default: LAC_UNSUPPORTED_PARAM_LOG("Window size is not supported\n"); return CPA_STATUS_UNSUPPORTED; } switch (algo) { case CPA_DC_DEFLATE: if (dir == CPA_DC_DIR_COMPRESS) { windowSizeMask = pDcCapabilities->deflate.validWindowSizeMaskCompression; } else { windowSizeMask = pDcCapabilities->deflate.validWindowSizeMaskDecompression; } break; case CPA_DC_LZ4: if (dir == CPA_DC_DIR_COMPRESS) { windowSizeMask = pDcCapabilities->lz4.validWindowSizeMaskCompression; } else { windowSizeMask = pDcCapabilities->lz4.validWindowSizeMaskDecompression; } break; case CPA_DC_LZ4S: if (dir == CPA_DC_DIR_COMPRESS) { windowSizeMask = pDcCapabilities->lz4s.validWindowSizeMaskCompression; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } if (windowSizeMask & validBitMask) { *pCapStatus = CPA_TRUE; } return CPA_STATUS_SUCCESS; } STATIC INLINE CpaStatus dcGetAlgoWindowSizeCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U dir, Cpa32U algo, Cpa32U *pU32Status) { *pU32Status = 0; switch (dir) { case CPA_DC_DIR_COMPRESS: case CPA_DC_DIR_DECOMPRESS: break; case CPA_DC_DIR_COMBINED: LAC_LOG_ERROR("Combined direction is not supported\n"); return CPA_STATUS_INVALID_PARAM; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm direction is not supported\n"); return CPA_STATUS_UNSUPPORTED; } switch (algo) { case CPA_DC_DEFLATE: *pU32Status = pDcCapabilities->deflate.historyBufferSize; break; case CPA_DC_LZ4: *pU32Status = pDcCapabilities->lz4.historyBufferSize; break; case CPA_DC_LZ4S: *pU32Status = pDcCapabilities->lz4s.historyBufferSize; break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } STATIC INLINE CpaStatus dcGetMaxBlockSizeForBitmaskCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa8U lz4BlockSize, Cpa32U algo, CpaBoolean *pCapStatus) { *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_LZ4: if (pDcCapabilities->lz4.maxBlockSize & lz4BlockSize) { *pCapStatus = CPA_TRUE; } else { *pCapStatus = CPA_FALSE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } STATIC INLINE CpaStatus dcGetCompDictSupportCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, Cpa32U dirMask, CpaBoolean *pCapStatus) { *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if ((pDcCapabilities->deflate.supported) && (pDcCapabilities->deflate.dictCompSupported) && ((pDcCapabilities->deflate.dirMask & dirMask) == dirMask) && (pDcCapabilities->deflate.dictCap & DC_CAPS_COMPRESSED_DICT)) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if ((pDcCapabilities->lz4.supported) && (pDcCapabilities->lz4.dictCompSupported) && ((pDcCapabilities->lz4.dirMask & dirMask) == dirMask) && (pDcCapabilities->lz4.dictCap & DC_CAPS_COMPRESSED_DICT)) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4S: if ((pDcCapabilities->lz4s.supported) && (pDcCapabilities->lz4s.dictCompSupported) && ((pDcCapabilities->lz4s.dirMask & dirMask) == dirMask) && (pDcCapabilities->lz4s.dictCap & DC_CAPS_COMPRESSED_DICT)) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } STATIC INLINE CpaStatus dcChainGetPcrc64CapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus) { *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if (pDcCapabilities->deflate.programmableCrc64) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if (pDcCapabilities->lz4.programmableCrc64) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } STATIC INLINE CpaStatus dcGetDirMaskFromApiDir(Cpa32U dir, Cpa32U *pDirMask) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDirMask); #endif switch (dir) { case CPA_DC_DIR_COMPRESS: *pDirMask = DC_CAPS_COMPRESSION; break; case CPA_DC_DIR_DECOMPRESS: *pDirMask = DC_CAPS_DECOMPRESSION; break; case CPA_DC_DIR_COMBINED: *pDirMask = (DC_CAPS_COMPRESSION | DC_CAPS_DECOMPRESSION); break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm direction is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } STATIC INLINE CpaStatus dcGetDirCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U capabilitiesMask, Cpa32U algo, Cpa32U dirMask, CpaBoolean *pCapStatus) { *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if ((pDcCapabilities->deflate.supported) && ((pDcCapabilities->deflate.dirMask & dirMask) == dirMask)) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if ((pDcCapabilities->lz4.supported) && (capabilitiesMask & ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION) && ((pDcCapabilities->lz4.dirMask & dirMask) == dirMask)) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4S: if ((pDcCapabilities->lz4s.supported) && (capabilitiesMask & ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION) && ((pDcCapabilities->lz4s.dirMask & dirMask) == dirMask)) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } STATIC CpaStatus dcGetCrcOverBlockCapabilityStatus( dc_extd_ftrs_t* pExtendedFtrs, Cpa32U algo, CpaBoolean* pCapStatus) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pCapStatus); #endif * pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_LZ4: if (pExtendedFtrs->is_e2e_comp_crc_over_block) { *pCapStatus = CPA_TRUE; } break; default: LAC_LOG_ERROR("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcQueryCapabilityByType(CpaInstanceHandle dcInstance, CpaDcCapabilityReq capabilityReq, CpaDcCapabilityResp *pCapabilityResp) { CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; Cpa32U capabilitiesMask = 0, dirMask = 0; dc_capabilities_t *pDcCapabilities = NULL; dc_extd_ftrs_t *pExtendedFtrs = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); LAC_CHECK_NULL_PARAM(pCapabilityResp); #endif pService = (sal_compression_service_t *)insHandle; capabilitiesMask = pService->generic_service_info.capabilitiesMask; pDcCapabilities = &pService->dc_capabilities; pExtendedFtrs = (dc_extd_ftrs_t *)&(((sal_service_t *)insHandle)->dcExtendedFeatures); osalMemSet(pCapabilityResp, 0, sizeof(CpaDcCapabilityResp)); switch (capabilityReq.algo) { case CPA_DC_DEFLATE: case CPA_DC_LZ4: case CPA_DC_LZ4S: break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm not supported\n"); return CPA_STATUS_UNSUPPORTED; } switch (capabilityReq.dir) { case CPA_DC_DIR_COMPRESS: dirMask = DC_CAPS_COMPRESSION; break; case CPA_DC_DIR_DECOMPRESS: dirMask = DC_CAPS_DECOMPRESSION; break; case CPA_DC_DIR_COMBINED: LAC_LOG_ERROR("Invalid Algorithm Direction not supported\n"); return CPA_STATUS_INVALID_PARAM; break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm direction is not supported\n"); return CPA_STATUS_UNSUPPORTED; } switch (capabilityReq.capId) { case CPA_DC_CAP_BOOL_STATEFUL: case CPA_DC_CAP_BOOL_STATELESS: if ((CPA_DC_CAP_BOOL_STATEFUL == capabilityReq.capId) && !(pDcCapabilities->sessState & DC_CAPS_STATEFUL)) { pCapabilityResp->boolStatus = CPA_FALSE; break; } if ((CPA_DC_CAP_BOOL_STATELESS == capabilityReq.capId) && !(pDcCapabilities->sessState & DC_CAPS_STATELESS)) { pCapabilityResp->boolStatus = CPA_FALSE; break; } dcGetDirCapabilityStatus(pDcCapabilities, capabilitiesMask, capabilityReq.algo, dirMask, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_BOOL_WINDOW_SIZE_4K: case CPA_DC_CAP_BOOL_WINDOW_SIZE_8K: case CPA_DC_CAP_BOOL_WINDOW_SIZE_16K: case CPA_DC_CAP_BOOL_WINDOW_SIZE_32K: case CPA_DC_CAP_BOOL_WINDOW_SIZE_64K: dcGetAlgoWindowSizeForCapabilityStatus( pDcCapabilities, capabilityReq.capId, capabilityReq.dir, capabilityReq.algo, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_U32_DEFAULT_WINDOW_SIZE: dcGetAlgoWindowSizeCapabilityStatus(pDcCapabilities, capabilityReq.dir, capabilityReq.algo, &pCapabilityResp->u32Status); break; case CPA_DC_CAP_BOOL_DYNAMIC_HUFFMAN: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = DC_CAPS_DEFLATE_TYPE_SUPPORT_GET( pDcCapabilities->deflate.typeSupport, DC_CAPS_DEFLATE_TYPE_DYNAMIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); } break; case CPA_DC_CAP_BOOL_STATIC_HUFFMAN: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = DC_CAPS_DEFLATE_TYPE_SUPPORT_GET( pDcCapabilities->deflate.typeSupport, DC_CAPS_DEFLATE_TYPE_STATIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); } break; case CPA_DC_CAP_BOOL_BLOCK_CHECKSUM: if (capabilityReq.algo == CPA_DC_LZ4 && capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = pDcCapabilities->lz4.blockChecksum; } break; case CPA_DC_CAP_BOOL_ACCUMULATE_XXHASH: if (capabilityReq.algo == CPA_DC_LZ4 && capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = pDcCapabilities->lz4.accumulateXXHash; } break; case CPA_DC_CAP_BOOL_BLOCK_SIZE_64K: dcGetMaxBlockSizeForBitmaskCapabilityStatus( pDcCapabilities, DC_CAPS_LZ4_64K, capabilityReq.algo, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_BOOL_BLOCK_SIZE_256K: dcGetMaxBlockSizeForBitmaskCapabilityStatus( pDcCapabilities, DC_CAPS_LZ4_256K, capabilityReq.algo, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_BOOL_BLOCK_SIZE_1M: dcGetMaxBlockSizeForBitmaskCapabilityStatus( pDcCapabilities, DC_CAPS_LZ4_1M, capabilityReq.algo, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_BOOL_BLOCK_SIZE_4M: dcGetMaxBlockSizeForBitmaskCapabilityStatus( pDcCapabilities, DC_CAPS_LZ4_4M, capabilityReq.algo, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_U32_BLOCK_SIZE_BITMASK: if (capabilityReq.algo == CPA_DC_LZ4) { pCapabilityResp->u32Status = pDcCapabilities->lz4.maxBlockSize; } break; case CPA_DC_CAP_BOOL_CHECKSUM_CRC32: if (pDcCapabilities->checksum & DC_CAPS_CRC32 && capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = CPA_TRUE; } break; case CPA_DC_CAP_BOOL_CHECKSUM_ADLER32: if (pDcCapabilities->checksum & DC_CAPS_ADLER32 && capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = CPA_TRUE; } break; case CPA_DC_CAP_BOOL_CHECKSUM_XXHASH32: if (pDcCapabilities->checksum & DC_CAPS_XXHASH32 && capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = CPA_TRUE; } break; case CPA_DC_CAP_BOOL_CHECKSUM_XXHASH64: if (pDcCapabilities->checksum & DC_CAPS_XXHASH64 && capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = CPA_TRUE; } break; case CPA_DC_CAP_BOOL_ASB: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS && capabilityReq.algo != CPA_DC_LZ4S) { pCapabilityResp->boolStatus = pDcCapabilities->asb.supported; } break; case CPA_DC_CAP_BOOL_ASB_THRESHOLD: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS && capabilityReq.algo != CPA_DC_LZ4S) { pCapabilityResp->boolStatus = pDcCapabilities->asb.asbTshSupported; } break; case CPA_DC_CAP_BOOL_ASB_RATIO: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS && capabilityReq.algo != CPA_DC_LZ4S) { pCapabilityResp->boolStatus = pDcCapabilities->asb.asbRatioSupported; } break; case CPA_DC_CAP_BOOL_DETERMINISM: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = pDcCapabilities->determinism; } break; case CPA_DC_CAP_BOOL_OVERFLOW_RESUBMIT: pCapabilityResp->boolStatus = !pDcCapabilities->overflowResubmitUnsupported; break; case CPA_DC_CAP_BOOL_COMPRESS_N_VERIFY: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = (CpaBoolean)pExtendedFtrs->is_cnv; } break; case CPA_DC_CAP_BOOL_COMPRESS_N_VERIFY_N_RECOVER: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { pCapabilityResp->boolStatus = (CpaBoolean)pExtendedFtrs->is_cnvnr; } break; case CPA_DC_CAP_BOOL_INTEGRITY_CRC32: if (capabilitiesMask & ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY) { pCapabilityResp->boolStatus = CPA_TRUE; } break; case CPA_DC_CAP_BOOL_INTEGRITY_CRC64: if (capabilitiesMask & ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY64) { pCapabilityResp->boolStatus = CPA_TRUE; } break; case CPA_DC_CAP_BOOL_CHAIN_HASH_THEN_COMPRESS: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS && capabilityReq.algo != CPA_DC_LZ4S) { dcGetHashChainingCapabilityStatus(pDcCapabilities, capabilityReq.algo, &pCapabilityResp->boolStatus); } break; case CPA_DC_CAP_BOOL_CHAIN_COMPRESS_THEN_AEAD: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS && capabilityReq.algo != CPA_DC_LZ4S) { dcGetCompAeadChainingCapabilityStatus( pDcCapabilities, capabilityReq.algo, &pCapabilityResp->boolStatus); } break; case CPA_DC_CAP_BOOL_CHAIN_AEAD_THEN_DECOMPRESS: if (capabilityReq.dir == CPA_DC_DIR_DECOMPRESS && capabilityReq.algo != CPA_DC_LZ4S) { dcGetAeadDecompChainingCapabilityStatus( pDcCapabilities, capabilityReq.algo, &pCapabilityResp->boolStatus); } break; case CPA_DC_CAP_BOOL_STATEFUL_LITE: if (capabilityReq.algo == CPA_DC_DEFLATE) { pCapabilityResp->boolStatus = !pDcCapabilities->statefulLiteUnsupported; } break; case CPA_DC_CAP_BOOL_UNCOMPRESSED_DICT: dcGetUncompDictSupportCapabilityStatus( pDcCapabilities, capabilityReq.algo, dirMask, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_BOOL_COMPRESSED_DICT: dcGetCompDictSupportCapabilityStatus(pDcCapabilities, capabilityReq.algo, dirMask, &pCapabilityResp->boolStatus); break; case CPA_DC_CAP_BOOL_ZERO_LENGTH_REQ: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { dcGetZeroLengthReqCapabilityStatus( pDcCapabilities, capabilityReq.algo, &pCapabilityResp->boolStatus); } break; case CPA_DC_CAP_BOOL_PROGRAMMABLE_CRC64: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { dcGetPcrc64CapabilityStatus(pDcCapabilities, capabilityReq.algo, &pCapabilityResp->boolStatus); } break; case CPA_DC_CAP_BOOL_ASB_ENABLE_PREFERRED: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { dcGetAsbEnablePrefCapabilityStatus( pDcCapabilities, capabilityReq.algo, &pCapabilityResp->boolStatus); } break; case CPA_DC_CAP_BOOL_CHAIN_PROGRAMMABLE_CRC64: if (capabilityReq.dir == CPA_DC_DIR_COMPRESS) { dcChainGetPcrc64CapabilityStatus(pDcCapabilities, capabilityReq.algo, &pCapabilityResp->boolStatus); } break; case CPA_DC_CAP_BOOL_E2E_CRC_OVER_COMP_BLOCK: dcGetCrcOverBlockCapabilityStatus(pExtendedFtrs, capabilityReq.algo, &pCapabilityResp->boolStatus); break; default: LAC_UNSUPPORTED_PARAM_LOG("Capability is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } inline CpaStatus dcGetUncompDictSupportCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, Cpa32U dirMask, CpaBoolean *pCapStatus) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDcCapabilities); LAC_CHECK_NULL_PARAM(pCapStatus); #endif *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if ((pDcCapabilities->deflate.supported) && (pDcCapabilities->deflate.dictCompSupported) && ((pDcCapabilities->deflate.dirMask & dirMask) == dirMask) && (pDcCapabilities->deflate.dictCap & DC_CAPS_UNCOMPRESSED_DICT)) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if ((pDcCapabilities->lz4.supported) && (pDcCapabilities->lz4.dictCompSupported) && ((pDcCapabilities->lz4.dirMask & dirMask) == dirMask) && (pDcCapabilities->lz4.dictCap & DC_CAPS_UNCOMPRESSED_DICT)) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4S: if ((pDcCapabilities->lz4s.supported) && (pDcCapabilities->lz4s.dictCompSupported) && ((pDcCapabilities->lz4s.dirMask & dirMask) == dirMask) && (pDcCapabilities->lz4s.dictCap & DC_CAPS_UNCOMPRESSED_DICT)) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } inline CpaStatus dcGetZeroLengthReqCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDcCapabilities); LAC_CHECK_NULL_PARAM(pCapStatus); #endif *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if (pDcCapabilities->deflate.zerolengthRequests) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if (pDcCapabilities->lz4.zerolengthRequests) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4S: if (pDcCapabilities->lz4s.zerolengthRequests) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } inline CpaStatus dcGetPcrc64CapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDcCapabilities); LAC_CHECK_NULL_PARAM(pCapStatus); #endif *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if (pDcCapabilities->deflate.programmableCrc64) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if (pDcCapabilities->lz4.programmableCrc64) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4S: if (pDcCapabilities->lz4s.programmableCrc64) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } inline CpaStatus dcGetHashChainingCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDcCapabilities); LAC_CHECK_NULL_PARAM(pCapStatus); #endif *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if (pDcCapabilities->deflate.hashThenCompressSupported) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if (pDcCapabilities->lz4.hashThenCompressSupported) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } inline CpaStatus dcGetCompAeadChainingCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDcCapabilities); LAC_CHECK_NULL_PARAM(pCapStatus); #endif *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if (pDcCapabilities->deflate.compressThenAeadSupported) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if (pDcCapabilities->lz4.compressThenAeadSupported) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } inline CpaStatus dcGetAeadDecompChainingCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDcCapabilities); LAC_CHECK_NULL_PARAM(pCapStatus); #endif *pCapStatus = CPA_FALSE; switch (algo) { case CPA_DC_DEFLATE: if (pDcCapabilities->deflate.aeadThenDecompressSupported) { *pCapStatus = CPA_TRUE; } break; case CPA_DC_LZ4: if (pDcCapabilities->lz4.aeadThenDecompressSupported) { *pCapStatus = CPA_TRUE; } break; default: LAC_UNSUPPORTED_PARAM_LOG("Algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_chain.c000066400000000000000000002366301503624047500304500ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_chain.c * * @ingroup Dc_Chaining * * @description * Implementation of the chaining session operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #ifndef ICP_DC_ONLY #include "cpa.h" #include "icp_qat_fw.h" #include "icp_qat_fw_comp.h" #include "icp_qat_hw.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_chain.h" #include "dc_capabilities.h" #include "dc_datapath.h" #include "dc_stats.h" #include "lac_mem_pools.h" #include "lac_buffer_desc.h" #include "sal_service_state.h" #include "sal_qat_cmn_msg.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "sal_string_parse.h" #include "lac_sym.h" #include "lac_session.h" #include "lac_sym_qat.h" #include "lac_sym_hash.h" #include "lac_sym_alg_chain.h" #include "lac_sym_auth_enc.h" #include "dc_session.h" #include "dc_crc64.h" #define DC_CHAIN_COMPUTE_KEY(huffType, dcDir, sessType) \ ((huffType << 8) | (dcDir << 4) | sessType) #define CY_CHAIN_COMPUTE_KEY(cyOpType, cyDir, sessType) \ ((cyOpType << 8) | (cyDir << 4) | sessType) static const dc_chain_cmd_tbl_t dc_chain_cmd_table[] = { /* link0: additional=2(hash)|dir=0(rsvd)|type=1(crypto) * link1: additional=0(static)|dir=0(compression)|type=0(comp) */ { 0x201, 0x0, 0x0, ICP_QAT_FW_CHAINING_CMD_HASH_STATIC_COMP, ICP_QAT_FW_CHAINING_20_CMD_HASH_COMPRESS }, /* link0: additional=2(hash)|dir=0(rsvd)|type=1(crypto) * link1: additional=2(dynamic )|dir=0(compression)|type=0(comp) */ { 0x201, 0x200, 0x0, ICP_QAT_FW_CHAINING_CMD_HASH_DYNAMIC_COMP, ICP_QAT_FW_CHAINING_20_CMD_HASH_COMPRESS }, /* link0: additional=2(dynamic)|dir=0(compression)|type=0(comp) * link1: additional=3(algChain)|dir=1(encrypt)|type=1(crypto) */ { 0x200, 0x311, 0x0, ICP_QAT_FW_NO_CHAINING, ICP_QAT_FW_CHAINING_20_CMD_COMPRESS_ENCRYPT }, /* link0: additional=3(algChain)|dir=2(decrypt)|type=1(crypto) * link1: additional=0(rsvd)|dir=1(decomp)|type=0(comp) */ { 0x321, 0x10, 0x0, ICP_QAT_FW_NO_CHAINING, ICP_QAT_FW_CHAINING_20_CMD_DECRYPT_DECOMPRESS }, }; #ifdef ICP_PARAM_CHECK #define NUM_OF_SESSION_SUPPORT 2 /** ***************************************************************************** * @ingroup Dc_Chaining * Check that chaining HASH setup data is valid * * @description * Check that chaining HASH setup data in the CpaCySymHashSetupData is * valid * * @param[in] pHashSetupData Pointer to an CpaCySymHashSetupData * structures. * @param[in] hw_gen Hardware generation * @param[in] operation Chaining operation type * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ STATIC CpaStatus dcChainSession_CheckHashSetupData(const CpaCySymHashSetupData *pHashSetupData, dc_hw_gen_types_t hw_gen, CpaDcChainOperations operation) { LAC_CHECK_NULL_PARAM(pHashSetupData); { /* Support SHA1, SHA224 and SHA256 */ LAC_CHECK_STATEMENT_LOG( pHashSetupData->hashAlgorithm != CPA_CY_SYM_HASH_SHA1 && pHashSetupData->hashAlgorithm != CPA_CY_SYM_HASH_SHA224 && pHashSetupData->hashAlgorithm != CPA_CY_SYM_HASH_SHA256, "%s", "Only algorithms SHA1, SHA224, SHA256 are " "supported"); LAC_CHECK_STATEMENT_LOG( (CPA_CY_SYM_HASH_MODE_PLAIN != pHashSetupData->hashMode), "Invalid CY hashMode=0x%x", pHashSetupData->hashMode); } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup Dc_Chaining * Check that chaining session data is valid * * @description * Check that all the parameters defined in the pSessionData are valid * * @param[in] operation Chaining operation type * @param[in] numSessions Number of chaining sessions * @param[in] pSessionData Pointer to an array of * CpaDcChainSessionSetupData * structures.There should be numSessions * entries in the array. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_UNSUPPORTED Unsupported operation passed in * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ STATIC CpaStatus dcChainSession_CheckSessionData(CpaInstanceHandle dcInstance, CpaDcChainOperations operation, Cpa8U numSessions, const CpaDcChainSessionSetupData *pSessionData) { dc_capabilities_t *pDcCapabilities = NULL; sal_compression_service_t *pService = (sal_compression_service_t *)dcInstance; CpaCySymSessionSetupData *pCySetupData = NULL; CpaDcSessionSetupData *pDcSetupData = NULL; CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean capSupport = CPA_FALSE; pDcCapabilities = &pService->dc_capabilities; /* Currently all supported chaining operations have * exactly 2 sessions. This is defined by NUM_OF_SESSION_SUPPORT */ LAC_CHECK_STATEMENT_LOG(numSessions != NUM_OF_SESSION_SUPPORT, "%s", "Wrong number of sessions " "for a chaining operation"); switch (operation) { case CPA_DC_CHAIN_HASH_THEN_COMPRESS: pCySetupData = pSessionData[0].pCySetupData; pDcSetupData = pSessionData[1].pDcSetupData; LAC_CHECK_NULL_PARAM(pCySetupData); LAC_CHECK_NULL_PARAM(pDcSetupData); /* Check for valid/supported DC chaining parameters */ LAC_CHECK_STATEMENT_LOG( (pSessionData[0].sessType != CPA_DC_CHAIN_SYMMETRIC_CRYPTO), "Invalid chaining cySessType=0x%x for HASH_THEN_COMPRESS", pSessionData[0].sessType); LAC_CHECK_STATEMENT_LOG( (pSessionData[1].sessType != CPA_DC_CHAIN_COMPRESS_DECOMPRESS), "Invalid chaining dcSessType=0x%x for HASH_THEN_COMPRESS", pSessionData[1].sessType); status = dcGetHashChainingCapabilityStatus( pDcCapabilities, pDcSetupData->compType, &capSupport); LAC_CHECK_STATUS(status); if (capSupport != CPA_TRUE) { LAC_INVALID_PARAM_LOG1("Unsupported DC compType=0x%x for " "HASH_THEN_COMPRESS chaining", pDcSetupData->compType); return CPA_STATUS_UNSUPPORTED; } /* Check for valid/supported Symmetric Crypto parameters */ LAC_CHECK_STATEMENT_LOG( (pCySetupData->symOperation != CPA_CY_SYM_OP_HASH), "Invalid CY symOperation=0x%x for HASH_THEN_COMPRESS chaining", pCySetupData->symOperation); LAC_CHECK_STATEMENT_LOG( (pCySetupData->digestIsAppended == CPA_TRUE), "Invalid CY digestIsAppended=0x%x for HASH_THEN_COMPRESS " "chaining", pCySetupData->digestIsAppended); /* Check for valid/supported DC parameters */ LAC_CHECK_STATEMENT_LOG( (pDcSetupData->sessDirection != CPA_DC_DIR_COMPRESS), "Invalid DC sessDirection=0x%x for HASH_THEN_COMPRESS chaining", pDcSetupData->sessDirection); LAC_CHECK_STATEMENT_LOG( (pDcSetupData->huffType == CPA_DC_HT_PRECOMP), "Invalid DC huffType=0x%x for HASH_THEN_COMPRESS chaining", pDcSetupData->huffType); if (pDcSetupData->sessState != CPA_DC_STATELESS) { LAC_INVALID_PARAM_LOG2( "Invalid DC sessState=0x%x for %d chaining operation", pDcSetupData->sessState, operation); return CPA_STATUS_INVALID_PARAM; } /* Check for supported hash parameters */ status = dcChainSession_CheckHashSetupData( &pCySetupData->hashSetupData, pDcCapabilities->deviceData.hw_gen, operation); LAC_CHECK_STATUS(status); break; case CPA_DC_CHAIN_COMPRESS_THEN_AEAD: case CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS: case CPA_DC_CHAIN_COMPRESS_THEN_HASH: case CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT: case CPA_DC_CHAIN_COMPRESS_THEN_HASH_ENCRYPT: case CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT_HASH: case CPA_DC_CHAIN_HASH_VERIFY_THEN_DECOMPRESS: case CPA_DC_CHAIN_DECRYPT_THEN_DECOMPRESS: case CPA_DC_CHAIN_HASH_VERIFY_DECRYPT_THEN_DECOMPRESS: case CPA_DC_CHAIN_DECRYPT_HASH_VERIFY_THEN_DECOMPRESS: case CPA_DC_CHAIN_DECOMPRESS_THEN_HASH_VERIFY: case CPA_DC_CHAIN_COMPRESS_THEN_AEAD_THEN_HASH: LAC_LOG_ERROR1("Chaining operation 0x%x not supported", operation); return CPA_STATUS_UNSUPPORTED; default: LAC_INVALID_PARAM_LOG1("Invalid operation 0x%x\n", operation); return CPA_STATUS_INVALID_PARAM; } return status; } /** ***************************************************************************** * @ingroup Dc_Chaining * Initialization for chaining sessions * * @description * Check for supported Sym Crypto operations as part of DC Chain * * @param[in] pCySessDesc Session descriptor for Sym Crypto * operation. * @param[in] operation Chaining operation type * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid Sym Crypto parameter * *****************************************************************************/ STATIC CpaStatus dcChainSession_CheckCySessDesc(const lac_session_desc_t *pCySessDesc, CpaDcChainOperations operation) { LAC_CHECK_NULL_PARAM(pCySessDesc); /* Restrict DC Chain Sym Crypto operations to supported/validated * combinations when used as part of a chain operation */ switch (operation) { case CPA_DC_CHAIN_HASH_THEN_COMPRESS: LAC_CHECK_STATEMENT_LOG( (CPA_CY_SYM_OP_HASH != pCySessDesc->symOperation), "Invalid CY symOperation=0x%x for HASH_THEN_COMPRESS chaining", pCySessDesc->symOperation); LAC_CHECK_STATEMENT_LOG( ((CPA_CY_SYM_HASH_MODE_PLAIN != pCySessDesc->hashMode) && (CPA_CY_SYM_HASH_MODE_AUTH != pCySessDesc->hashMode)), "Invalid CY hashMode=0x%x for HASH_THEN_COMPRESS chaining", pCySessDesc->hashMode); LAC_CHECK_STATEMENT_LOG((CPA_FALSE != pCySessDesc->isAuthEncryptOp), "Invalid CY isAuthEncryptOp=0x%x for " "HASH_THEN_COMPRESS chaining", pCySessDesc->isAuthEncryptOp); LAC_CHECK_STATEMENT_LOG( (CPA_FALSE != pCySessDesc->isCipher), "Invalid CY isCipher=0x%x for HASH_THEN_COMPRESS chaining", pCySessDesc->isCipher); LAC_CHECK_STATEMENT_LOG( (CPA_TRUE != pCySessDesc->isAuth), "Invalid CY isAuth=0x%x for HASH_THEN_COMPRESS chaining", pCySessDesc->isAuth); break; default: LAC_INVALID_PARAM_LOG1("Unsupported DC chaining operation=0x%x", operation); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup Dc_Chaining * Initialization for chaining sessions * * @description * Check for supported compression operations as part of DC Chain * * @param[in] pDcSessDesc Session descriptor for compression * operation. * @param[in] operation Chaining operation type * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid compression parameter * *****************************************************************************/ STATIC CpaStatus dcChainSession_CheckDcSessDesc(const dc_session_desc_t *pDcSessDesc, CpaDcChainOperations operation, dc_capabilities_t *pDcCapabilities) { CpaBoolean staticSupported = CPA_FALSE; LAC_CHECK_NULL_PARAM(pDcSessDesc); if ((CPA_DC_DEFLATE == pDcSessDesc->compType) && (CPA_DC_HT_STATIC == pDcSessDesc->huffType)) { staticSupported = DC_CAPS_DEFLATE_TYPE_SUPPORT_GET( pDcCapabilities->deflate.typeSupport, DC_CAPS_DEFLATE_TYPE_STATIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); if (CPA_FALSE == staticSupported) { LAC_UNSUPPORTED_PARAM_LOG( "Static huffman encoding is not supported " "on current instance"); return CPA_STATUS_UNSUPPORTED; } } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup Dc_Chaining * Initialization for chaining sessions * * @description * Check for supported compression operations as part of DC Chain * * @param[in] pChainSessDesc Session descriptor for DC Chain * requests. * @param[in] dcInstance Instance handle * @param[in] operation Chaining operation type * @param[in] numSessions Number of sessions in the chain operation * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid compression parameter * *****************************************************************************/ STATIC CpaStatus dcChainSession_CheckChainSessDesc(const dc_chain_session_head_t *pChainSessDesc, const CpaInstanceHandle dcInstance, const CpaDcChainOperations operation, const Cpa8U numSessions) { sal_compression_service_t *pDcService = (sal_compression_service_t *)dcInstance; Cpa8U *pTemp; LAC_CHECK_NULL_PARAM(pChainSessDesc); LAC_CHECK_STATEMENT_LOG(numSessions != NUM_OF_SESSION_SUPPORT, "%s", "Wrong number of sessions " "for a chaining operation"); pTemp = (Cpa8U *)pChainSessDesc + sizeof(dc_chain_session_head_t); /* Restrict DC chaining operations to supported combinations */ switch (operation) { case CPA_DC_CHAIN_HASH_THEN_COMPRESS: if (!(pDcService->generic_service_info.dcExtendedFeatures & DC_CHAIN_HASH_THEN_COMPRESS_EXTENDED_CAPABILITY)) { LAC_INVALID_PARAM_LOG( "HW does not support chaining operation hash and compress"); return CPA_STATUS_UNSUPPORTED; } LAC_CHECK_STATEMENT_LOG( (DC_CHAIN_TYPE_GET(pTemp) != CPA_DC_CHAIN_SYMMETRIC_CRYPTO), "Invalid chaining cySessType=0x%x for HASH_THEN_COMPRESS", DC_CHAIN_TYPE_GET(pTemp)); /* Move to the next session data */ pTemp += (LAC_SYM_SESSION_SIZE + sizeof(CpaDcChainSessionType)); LAC_CHECK_STATEMENT_LOG( (DC_CHAIN_TYPE_GET(pTemp) != CPA_DC_CHAIN_COMPRESS_DECOMPRESS), "Invalid chaining dcSessType=0x%x for HASH_THEN_COMPRESS", DC_CHAIN_TYPE_GET(pTemp)); break; default: LAC_INVALID_PARAM_LOG1("Invalid chaining operation %x", operation); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif /** ***************************************************************************** * @ingroup Dc_Chaining * Get the size for chaining sessions * * @description * Get the size for chaining sessions, it counts how many bytes are needed * for one chaining request, and it is called by cpaDcChainGetSessionSize * * @param[in] dcInstance Instance handle * @param[in] pSessionData Pointer to an array of * CpaDcChainSessionSetupData * structures. There should be numSessions * entries in the array. * @param[in] numSessions Number of chaining sessions * @param[out] pSessionSize On return, this parameter will be the size * of the memory that will be required by * cpaDcChainInitSession() for session data. * * @retval CPA_STATUS_SUCCESS Function executed successfully * *****************************************************************************/ STATIC CpaStatus dcChainGetSessionSize(CpaInstanceHandle dcInstance, CpaDcChainSessionSetupData *pSessionData, Cpa8U numSessions, Cpa32U *pSessionSize) { Cpa32U sessSize; Cpa32U i; sessSize = sizeof(dc_chain_session_head_t); for (i = 0; i < numSessions; i++) { sessSize += sizeof(CpaDcChainSessionType) + LAC_64BYTE_ALIGNMENT + sizeof(LAC_ARCH_UINT); if (pSessionData[i].sessType == CPA_DC_CHAIN_COMPRESS_DECOMPRESS) sessSize += sizeof(dc_session_desc_t); else sessSize += sizeof(lac_session_desc_t); } *pSessionSize = sessSize; return CPA_STATUS_SUCCESS; } CpaStatus cpaDcChainGetSessionSize(CpaInstanceHandle dcInstance, CpaDcChainOperations operation, Cpa8U numSessions, CpaDcChainSessionSetupData *pSessionData, Cpa32U *pSessionSize) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionData); LAC_CHECK_NULL_PARAM(pSessionSize); LAC_CHECK_STATEMENT_LOG(numSessions != NUM_OF_SESSION_SUPPORT, "%s", "Invalid number of sessions"); #endif return dcChainGetSessionSize( dcInstance, pSessionData, numSessions, pSessionSize); } /** ***************************************************************************** * @ingroup Dc_Chaining * Generate command ID * * @description * Generate command ID from session data and number of sessions * * @param[in] pSessionData Pointer to an array of * CpaDcChainSessionSetupData * structures. * @param[in] numSessions Number of chaining sessions * @param[in] cmd Command ID * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ STATIC CpaStatus dcChainSession_GenerateCmd(CpaInstanceHandle dcInstance, CpaDcChainSessionSetupData *pSessionData, Cpa8U numSessions, icp_qat_comp_chain_cmd_id_t *cmd) { Cpa16U key[DC_CHAIN_MAX_LINK] = {0}; CpaDcChainSessionType sessType; CpaCySymCipherSetupData const *pCipherSetupData = NULL; CpaDcSessionDir dcDir = CPA_DC_DIR_COMPRESS; CpaCySymCipherDirection cyDir = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; CpaDcHuffType huffType; CpaCySymOp cyOpType = CPA_CY_SYM_OP_NONE; Cpa32U i, numOfCmds; for (i = 0; i < numSessions; i++) { sessType = pSessionData[i].sessType; if (CPA_DC_CHAIN_COMPRESS_DECOMPRESS == sessType) { dcDir = pSessionData[i].pDcSetupData->sessDirection; if (dcDir == CPA_DC_DIR_COMPRESS) huffType = pSessionData[i].pDcSetupData->huffType; else huffType = CPA_DC_HT_STATIC; key[i] = DC_CHAIN_COMPUTE_KEY(huffType, dcDir, sessType); } else { cyOpType = pSessionData[i].pCySetupData->symOperation; pCipherSetupData = &(pSessionData[i].pCySetupData->cipherSetupData); cyDir = pCipherSetupData->cipherDirection; if (CPA_CY_SYM_OP_HASH == cyOpType) { cyDir = NOT_APPLICABLE; } key[i] = CY_CHAIN_COMPUTE_KEY(cyOpType, cyDir, sessType); } } numOfCmds = sizeof(dc_chain_cmd_table) / sizeof(dc_chain_cmd_tbl_t); for (i = 0; i < numOfCmds; i++) { if ((key[0] == dc_chain_cmd_table[i].link0_key) && (key[1] == dc_chain_cmd_table[i].link1_key) && (key[2] == dc_chain_cmd_table[i].link2_key)) { *cmd = (icp_qat_comp_chain_cmd_id_t)dc_chain_cmd_table[i] .cmd_20_id; /* Check if chaining is supported for the found operation */ if (ICP_QAT_FW_NO_CHAINING == *cmd) { return CPA_STATUS_FAIL; } else { return CPA_STATUS_SUCCESS; } } } return CPA_STATUS_FAIL; } /** ***************************************************************************** * @ingroup Dc_Chaining * Initialization for chaining sessions * * @description * Initialization for chaining sessions, it is called by * cpaDcChainInitSession * * @param[in] dcInstance Instance handle derived from discovery * functions. * @param[in,out] pSessionHandle Pointer to a session handle. * @param[in,out] pSessionData Pointer to an array of * CpaDcChainSessionSetupData structures. * There should be numSessions entries in the * array. * @param[in] numSessions Number of sessions for the chaining * @param[in] callbackFn For synchronous operation this callback * shall be a null pointer. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ STATIC CpaStatus dcChainInitSessions(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcChainSessionSetupData *pSessionData, Cpa8U numSessions, CpaDcCallbackFn callbackFn) { CpaStatus status = CPA_STATUS_SUCCESS; dc_chain_session_head_t *pSessHead; icp_qat_comp_chain_cmd_id_t chainCmd; Cpa8U *pTemp; Cpa32U i; CpaBoolean cyInitialized = CPA_FALSE; CpaBoolean dcInitialized = CPA_FALSE; lac_session_desc_t *pCySessDesc = NULL; pSessHead = (dc_chain_session_head_t *)pSessionHandle; pTemp = (Cpa8U *)pSessionHandle + sizeof(dc_chain_session_head_t); for (i = 0; i < numSessions; i++) { if (pSessionData[i].sessType == CPA_DC_CHAIN_COMPRESS_DECOMPRESS) { *(CpaDcChainSessionType *)pTemp = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; pTemp += sizeof(CpaDcChainSessionType); status = dcInitSession( dcInstance, (CpaDcSessionHandle)pTemp, (CpaDcSessionSetupData *)pSessionData[i].pDcSetupData, NULL, NULL); if (CPA_STATUS_SUCCESS != status) { if (CPA_TRUE == cyInitialized) { /* For crypto, destroy spinlock and mutex */ pCySessDesc = pSessHead->pCySessionDesc; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pCySessDesc); #endif LAC_SPINLOCK_DESTROY(&pCySessDesc->requestQueueLock); osalAtomicSet(0, &pCySessDesc->accessLock); } LAC_LOG_ERROR("Init compression session failure\n"); return status; } pSessHead->pDcSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pTemp); LAC_CHECK_NULL_PARAM(pSessHead->pDcSessionDesc); pTemp += DC_COMP_SESSION_SIZE; dcInitialized = CPA_TRUE; } else { *(CpaDcChainSessionType *)pTemp = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; pTemp += sizeof(CpaDcChainSessionType); status = LacSym_InitSession( dcInstance, NULL, (CpaCySymSessionSetupData *)pSessionData[i].pCySetupData, CPA_FALSE, (CpaCySymSessionCtx)pTemp); if (CPA_STATUS_SUCCESS != status) { if (CPA_TRUE == dcInitialized) { /* For DC, destroy spinlock */ LAC_SPINLOCK_DESTROY( &(pSessHead->pDcSessionDesc->updateLock)); } LAC_LOG_ERROR("Init symmetric session failure\n"); return status; } pSessHead->pCySessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pTemp); pTemp += LAC_SYM_SESSION_SIZE; cyInitialized = CPA_TRUE; } } pSessHead->pdcChainCb = ((void *)NULL != (void *)callbackFn) ? callbackFn : LacSync_GenWakeupSyncCaller; osalAtomicSet(0, &pSessHead->pendingChainCbCount); /*Fill the pre-build header*/ status = dcChainSession_GenerateCmd( dcInstance, pSessionData, numSessions, &chainCmd); if (CPA_STATUS_SUCCESS != status) { status = cpaDcChainRemoveSession(dcInstance, pSessionHandle); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("cpaDcChainRemoveSession returned %d status", status); } LAC_LOG_ERROR("generate chained command failure\n"); return CPA_STATUS_FAIL; } /* Store number of links in the chain */ pSessHead->numLinks = numSessions; /* Fill chaining request descriptor header */ pSessHead->hdr.comn_hdr2.service_cmd_id = chainCmd; pSessHead->hdr.comn_hdr2.service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_COMP_CHAIN; pSessHead->hdr.comn_hdr2.hdr_flags = ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET); pSessHead->hdr.comn_hdr2.resrvd1 = 0; pSessHead->hdr.comn_hdr2.serv_specif_flags = ICP_QAT_FW_COMP_CHAIN_REQ_FLAGS_BUILD( ICP_QAT_FW_COMP_CHAIN_NO_APPEND_CRC, ICP_QAT_FW_COMP_CHAIN_NO_VERIFY, ICP_QAT_FW_COMP_CHAIN_NO_DERIVE_KEY, ICP_QAT_FW_COMP_CHAIN_NO_CRC64_CTX); pSessHead->hdr.comn_hdr2.comn_req_flags = ICP_QAT_FW_COMN_FLAGS_BUILD( DC_DEFAULT_QAT_PTR_TYPE, QAT_COMN_CD_FLD_TYPE_16BYTE_DATA); pSessHead->hdr.comn_hdr2.extended_serv_specif_flags = 0; return status; } CpaStatus cpaDcChainInitSession(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcChainOperations operation, Cpa8U numSessions, CpaDcChainSessionSetupData *pSessionData, CpaDcCallbackFn callbackFn) { CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(insHandle); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); LAC_CHECK_NULL_PARAM(pSessionData); LAC_CHECK_NULL_PARAM(pSessionHandle); SAL_RUNNING_CHECK(pService); if (dcChainSession_CheckSessionData( insHandle, operation, numSessions, pSessionData) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (NULL == pService->pDcChainService) { return CPA_STATUS_UNSUPPORTED; } #endif return dcChainInitSessions( insHandle, pSessionHandle, pSessionData, numSessions, callbackFn); } CpaStatus cpaDcChainRemoveSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle insHandle = NULL; dc_chain_session_head_t *pSessHead = NULL; Cpa64U numPendingRequest = 0; sal_compression_service_t *pService = NULL; lac_session_desc_t *pCySessDesc = NULL; dc_session_desc_t *pSessionDesc = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); #endif pSessHead = (dc_chain_session_head_t *)pSessionHandle; pSessionDesc = pSessHead->pDcSessionDesc; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif pService = (sal_compression_service_t *)insHandle; if (NULL == pService->pDcChainService) { return CPA_STATUS_UNSUPPORTED; } /* Check if SAL is running otherwise return an error */ SAL_RUNNING_CHECK(insHandle); numPendingRequest = osalAtomicGet(&(pSessHead->pendingChainCbCount)); /* Check if there are pending requests */ if (0 != numPendingRequest) { LAC_LOG_ERROR1("There are %llu chaining requests pending", numPendingRequest); status = CPA_STATUS_RETRY; } /* For crypto, destroy spinlock and mutex */ pCySessDesc = pSessHead->pCySessionDesc; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pCySessDesc); #endif LAC_SPINLOCK_DESTROY(&pCySessDesc->requestQueueLock); osalAtomicSet(0, &pCySessDesc->accessLock); if (CPA_DC_STATELESS == pSessHead->pDcSessionDesc->sessState) { LAC_SPINLOCK_DESTROY(&(pSessHead->pDcSessionDesc->updateLock)); } /* Free the CRC lookup table if one was allocated */ if (NULL != pSessionDesc->crcConfig.pCrcLookupTable) { LAC_OS_FREE(pSessionDesc->crcConfig.pCrcLookupTable); } return status; } CpaStatus cpaDcChainResetSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle insHandle = NULL; dc_session_desc_t *pDcDescriptor = NULL; dc_chain_session_head_t *pSessHead = NULL; Cpa64U numPendingRequest = 0; Cpa8U *pTemp; Cpa32U i; sal_compression_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); #endif pSessHead = (dc_chain_session_head_t *)pSessionHandle; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif pService = (sal_compression_service_t *)insHandle; if (NULL == pService->pDcChainService) { return CPA_STATUS_UNSUPPORTED; } /* Check if SAL is running otherwise return an error */ SAL_RUNNING_CHECK(insHandle); numPendingRequest = osalAtomicGet(&(pSessHead->pendingChainCbCount)); /* Check if there are stateless pending requests */ if (0 != numPendingRequest) { LAC_LOG_ERROR1("There are %llu chaining requests pending", numPendingRequest); return CPA_STATUS_RETRY; } pTemp = (Cpa8U *)pSessionHandle + sizeof(dc_chain_session_head_t); for (i = 0; i < pSessHead->numLinks; i++) { if (DC_CHAIN_TYPE_GET(pTemp) == CPA_DC_CHAIN_SYMMETRIC_CRYPTO) { pTemp += sizeof(CpaDcChainSessionType); pTemp += LAC_SYM_SESSION_SIZE; } else { pTemp += sizeof(CpaDcChainSessionType); pDcDescriptor = DC_SESSION_DESC_FROM_CTX_GET(pTemp); break; } } LAC_CHECK_NULL_PARAM(pDcDescriptor); /* Reset chaining session descriptor */ pDcDescriptor->requestType = DC_REQUEST_FIRST; pDcDescriptor->cumulativeConsumedBytes = 0; return status; } /** * ************************************************************************ * @ingroup Dc_Chaining * Create compression request and link it to chaining request * * @param[in] dcInstance Compression instance handle * @param[out] pChainCookie Chaining cookie * @param[in] operation Chaining operation type * @param[in] pSessionHandle Compression session handle * @param[in] pDcOpDataExt Pointer to compression operation data * @param[in] pDcCookie Compression cookie * @param[in] pSrcBuff Source buffer for compression * @param[in] pDestBuff Destination buffer for comprssion * @param[in] pResults Chaining result * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_UNSUPPORTED Action not support * * *************************************************************************/ STATIC CpaStatus dcChainPrepare_CompRequest(CpaInstanceHandle dcInstance, dc_chain_cookie_t *pChainCookie, CpaDcChainOperations operation, Cpa8U *pSessionHandle, dc_opdata_ext_t *pDcOpDataExt, dc_compression_cookie_t *pDcCookie, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcChainRqResults *pResults) { CpaStatus status = CPA_STATUS_SUCCESS; dc_session_desc_t *pDcSessDesc = NULL; sal_compression_service_t *pDcService = (sal_compression_service_t *)dcInstance; sal_dc_chain_service_t *pChainService = pDcService->pDcChainService; CpaDcOpData *pDcOpData = NULL; dc_request_dir_t compDecomp; CpaDcRqResults dcResults = {0}; Cpa64U rspDescPhyAddr = 0; dc_cnv_mode_t cnvMode; void *pDcLinkRsp = NULL; icp_qat_fw_chain_stor2_req_t *pChainStor2Req = NULL; icp_qat_fw_comp_req_t *pMsg = NULL; dc_capabilities_t *pDcCapabilities = NULL; CpaBoolean statefulLiteUnsupported = CPA_FALSE; pDcSessDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); LAC_CHECK_NULL_PARAM(pDcSessDesc); pDcCapabilities = &pDcService->dc_capabilities; statefulLiteUnsupported = pDcCapabilities->statefulLiteUnsupported; /* Legacy CpaDcOpData. DC OpData extensions are not supported. */ if (DC_OPDATA_TYPE0 == pDcOpDataExt->opDataType) { pDcOpData = (CpaDcOpData *)pDcOpDataExt->pOpData; } else { pDcOpData = &((CpaDcOpData2 *)pDcOpDataExt->pOpData)->dcOpData; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDcOpData); LAC_CHECK_STATEMENT_LOG( pDcOpData->flushFlag == CPA_DC_FLUSH_SYNC, "%s", "CPA_DC_FLUSH_SYNC not supported for compression.\n"); LAC_CHECK_STATEMENT_LOG( pDcOpData->flushFlag == CPA_DC_FLUSH_NONE, "%s", "CPA_DC_FLUSH_NONE flag not supported for compression.\n"); if (CPA_STATUS_SUCCESS != dcChainSession_CheckDcSessDesc(pDcSessDesc, operation, pDcCapabilities)) { return CPA_STATUS_INVALID_PARAM; } #endif if (pDcOpData->compressAndVerifyAndRecover && pDcCapabilities->cnv.recovery) cnvMode = DC_CNVNR; else if (pDcOpData->compressAndVerify && pDcCapabilities->cnv.supported) cnvMode = DC_CNV; else cnvMode = DC_NO_CNV; if (CPA_DC_DIR_COMPRESS == pDcSessDesc->sessDirection) compDecomp = DC_COMPRESSION_REQUEST; else compDecomp = DC_DECOMPRESSION_REQUEST; if (CPA_FALSE == pDcOpData->compressAndVerify) { LAC_UNSUPPORTED_PARAM_LOG( "Data compression without verification not allowed"); return CPA_STATUS_UNSUPPORTED; } /* Add DC Chaining info to the compression cookie */ pDcCookie->dcChain.isDcChaining = CPA_TRUE; /* This is the common DC function to create the requests for * compression or decompression. It creates the DC request * message but does not send it. */ status = dcCreateRequest(pDcCookie, pDcService, pDcSessDesc, pSessionHandle, pSrcBuff, pDestBuff, &dcResults, pDcOpData->flushFlag, pDcOpData, NULL, compDecomp, cnvMode, NULL); pDcCookie->pResults = NULL; /* If this is not a DC_REQUEST_FIRST then for DC Chaining we must * re-seed both adler32 and crc32 with the previous checksums */ pMsg = (icp_qat_fw_comp_req_t *)&pDcCookie->request; if ((DC_REQUEST_FIRST != pDcSessDesc->requestType) && (CPA_DC_STATELESS == pDcSessDesc->sessState) && (CPA_TRUE != statefulLiteUnsupported)) { pMsg->comp_pars.crc.legacy.initial_adler = pResults->adler32; pMsg->comp_pars.crc.legacy.initial_crc32 = pResults->crc32; } LAC_CHECK_STATUS(status); pDcLinkRsp = Lac_MemPoolEntryAlloc(pChainService->dc_chain_serv_resp_pool); if (NULL == pDcLinkRsp) { return CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pDcLinkRsp) { return CPA_STATUS_RETRY; } rspDescPhyAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( pDcService->generic_service_info, pDcLinkRsp); pChainCookie->pDcRspAddr = pDcLinkRsp; pChainCookie->pDcCookieAddr = pDcCookie; pChainStor2Req = (icp_qat_fw_chain_stor2_req_t *)&pChainCookie->request; pChainStor2Req->compReqAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( pDcService->generic_service_info, &pDcCookie->request); pChainStor2Req->compRespAddr = rspDescPhyAddr; return status; } /** * ************************************************************************ * @ingroup Dc_Chaining * Create symmetric crypto request for chaining request * and link crypto request address to chaining request, * FW will parse chaining request on ring to get crypto * request address. * * @param[in] dcInstance Chaining Instance handle * @param[in,out] pChainCookie Chaining cookie * @param[in] operation Chaining operation type * @param[in] pSessionHandle Chaining session handle * @param[in] pCyCookie Symmetric crypto cookie * @param[in] pCySymOpExt Symmetric crypto operation data * @param[in] pSrcBuffer Source buffer for crypto * @param[in] pDestBuffer Destination buffer for crypto * @param[in,out] pResults Chaining response result * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_RESOURCE Error related to system resources * @retval CPA_STATUS_RETRY Need to try it again * * *************************************************************************/ STATIC CpaStatus dcChainPrepare_SymRequest(CpaInstanceHandle dcInstance, dc_chain_cookie_t *pChainCookie, CpaDcChainOperations operation, Cpa8U *pSessionHandle, lac_sym_bulk_cookie_t *pCyCookie, cy_opdata_ext_t *pCySymOpExt, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcChainRqResults *pResults) { CpaStatus status = CPA_STATUS_SUCCESS; /* Compression service and chain service */ sal_compression_service_t *pDcService = (sal_compression_service_t *)dcInstance; sal_dc_chain_service_t *pChainService = pDcService->pDcChainService; lac_session_desc_t *pCySessDesc = NULL; void *pCyLinkRsp = NULL; Cpa64U rspDescPhyAddr = 0; icp_qat_fw_chain_stor2_req_t *pChainStor2Req = NULL; CpaCySymOpData *pCySymOp = NULL; pCySessDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionHandle); /* Legacy CpaCySymOpData. CY OpData extensions are not supported. */ if (CY_OPDATA_TYPE0 == pCySymOpExt->opDataType) { pCySymOp = (CpaCySymOpData *)pCySymOpExt->pOpData; } else { pCySymOp = &((CpaCySymOpData2 *)pCySymOpExt->pOpData)->symOpData; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pCySymOp); LAC_CHECK_NULL_PARAM(pResults); LAC_CHECK_STATEMENT_LOG( (pCySymOp->packetType == CPA_CY_SYM_PACKET_TYPE_PARTIAL || pCySymOp->packetType == CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL), "%s", "Symmetric crypto partial packet are not supported in dc-chain " "operation.\n"); if ((!pCySessDesc->digestIsAppended) && ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == pCySessDesc->symOperation) || (CPA_CY_SYM_OP_HASH == pCySessDesc->symOperation))) { /* Check that pDigestResult is not NULL */ LAC_CHECK_NULL_PARAM(pCySymOp->pDigestResult); } if (CPA_STATUS_SUCCESS != dcChainSession_CheckCySessDesc(pCySessDesc, operation)) { return CPA_STATUS_INVALID_PARAM; } #endif pCySymOp->sessionCtx = pSessionHandle; if (CPA_STATUS_SUCCESS == status) { /* Add DC Chaining info to the CY cookie */ pCyCookie->dcChain.isDcChaining = CPA_TRUE; /* This is the common CY function to create the requests for * crypto operations. It creates the crypto request * message but does not send it for DC chained requests. */ status = LacAlgChain_Perform(dcInstance, pCySessDesc, NULL, pCySymOp, pCyCookie, pSrcBuff, pDestBuff, &pResults->verifyResult); } LAC_CHECK_STATUS(status); pCyLinkRsp = Lac_MemPoolEntryAlloc(pChainService->dc_chain_serv_resp_pool); if (NULL == pCyLinkRsp) { return CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pCyLinkRsp) { return CPA_STATUS_RETRY; } rspDescPhyAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( pDcService->generic_service_info, pCyLinkRsp); pChainCookie->pCyRspAddr = pCyLinkRsp; pChainCookie->pCyCookieAddr = pCyCookie; pChainStor2Req = (icp_qat_fw_chain_stor2_req_t *)&pChainCookie->request; pChainStor2Req->symCryptoReqAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( pDcService->generic_service_info, &pCyCookie->qatMsg); pChainStor2Req->symCryptoRespAddr = rspDescPhyAddr; return status; } /* Free memory */ STATIC void dcChainOp_MemPoolEntryFree(void *pEntry) { if ((void *)CPA_STATUS_RETRY == pEntry) return; if (NULL != pEntry) Lac_MemPoolEntryFree(pEntry); return; } /** ***************************************************************************** * @ingroup Dc_Chaining * Chaining perform operation * * @description * Chaining perform operation, it is called at cpaDcChainPerformOp, * which is used to perform chaining requests. * * @param[in] dcInstance Instance handle derived from discovery * functions. * @param[in] pSessionHandle Pointer to a session handle. * @param[in] pSrcBuff Source buffer * @param[in] pDestBuff Destination buffer * @param[in] pInterBuff Pointer to intermediate buffer to be * used as internal staging area for * chaining operations. * @param[in] operation Chaining operation type * @param[in] numOperations Number of operations for the chaining * @param[in] pChainOpDataExt Extensible chaining operation data * @param[in,out] pResultsExt Extensible chaining response result * @param[in] callbackTag For synchronous operation this callback * shall be a null pointer. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_RESOURCE Failed to allocate required resources * @retval CPA_STATUS_RETRY Request re-submission needed * *****************************************************************************/ CpaStatus dcChainPerformOp(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaBufferList *pInterBuff, CpaDcChainOperations operation, Cpa8U numOperations, dc_chain_opdata_ext_t *pChainOpDataExt, dc_chain_results_ext_t *pResultsExt, void *callbackTag) { CpaInstanceHandle insHandle = NULL; /* Compression service and chain service */ sal_compression_service_t *pDcService = NULL; ; sal_dc_chain_service_t *pChainService; /* Session descriptor for compression and crypto */ dc_session_desc_t *pDcSessDesc = NULL; dc_chain_session_head_t *pSessHead = NULL; /* Cookies for chaining (compression + crypto) */ dc_chain_cookie_t *pChainCookie = NULL; dc_compression_cookie_t *pDcCookie = NULL; lac_sym_bulk_cookie_t *pCyCookie = NULL; /* Request for chaining (compression + crypto) */ icp_qat_fw_chain_stor2_req_t *pChainStor2Req = NULL; CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pTemp; Cpa32U i; CpaBufferList *pChainSrcBuff = NULL; CpaBufferList *pChainDestBuff = NULL; CpaDcChainOpData *pChainSubOpData = NULL; CpaDcChainSubOpData2 *pChainSubOpData2 = NULL; dc_opdata_ext_t dcOpDataExt = { 0 }; cy_opdata_ext_t cyOpDataExt = { 0 }; CpaDcChainRqResults *pResults = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pSrcBuff); LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pResultsExt); LAC_CHECK_NULL_PARAM(pChainOpDataExt); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); if (CPA_STATUS_SUCCESS != dcChainSession_CheckChainSessDesc( (dc_chain_session_head_t *)pSessionHandle, insHandle, operation, numOperations)) { return CPA_STATUS_INVALID_PARAM; } #endif pDcService = (sal_compression_service_t *)insHandle; /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); pChainService = pDcService->pDcChainService; pSessHead = (dc_chain_session_head_t *)pSessionHandle; /* Allocate chaining cookie */ pChainCookie = (dc_chain_cookie_t *)Lac_MemPoolEntryAlloc( pChainService->dc_chain_cookie_pool); if (NULL == pChainCookie) { return CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pChainCookie) { return CPA_STATUS_RETRY; } if (DC_CHAIN_OPDATA_TYPE0 == pChainOpDataExt->opDataType) { pChainSubOpData = (CpaDcChainOpData *)pChainOpDataExt->pOpData; } else { pChainSubOpData2 = ((CpaDcChainOpData2 *)pChainOpDataExt->pOpData)->pChainOpData; } if (DC_CHAIN_RESULTS_TYPE0 == pResultsExt->resultsType) { pResults = (CpaDcChainRqResults *)pResultsExt->pResults; } else { pResults = &((CpaDcChainRqVResults *)pResultsExt->pResults)->chainRqResults; } /* Populate chaining cookie */ LAC_OS_BZERO(pChainCookie, sizeof(dc_chain_cookie_t)); pChainCookie->dcInstance = insHandle; pChainCookie->pSessionHandle = pSessionHandle; pChainCookie->extResults = *pResultsExt; pChainCookie->callbackTag = callbackTag; /* Build chaining common header */ pChainStor2Req = (icp_qat_fw_chain_stor2_req_t *)&pChainCookie->request; LAC_OS_BZERO(pChainStor2Req, sizeof(icp_qat_fw_chain_stor2_req_t)); /* Populates the QAT common request header part of the message * (LW 0 to 1) */ osalMemCopy((void *)(&pChainStor2Req->comn_hdr), (void *)(&pSessHead->hdr.comn_hdr2), sizeof(icp_qat_fw_comn_req_hdr_t)); osalAtomicInc(&(pSessHead->pendingChainCbCount)); pTemp = (Cpa8U *)pSessionHandle + sizeof(dc_chain_session_head_t); for (i = 0; i < numOperations; i++) { /* Use chaining intermediate buffer if provided. */ if (NULL == pInterBuff) { pChainSrcBuff = pSrcBuff; pChainDestBuff = pDestBuff; } else { /* First chain operation */ if (FIRST_DC_CHAIN_ITEM == i) { /* First chain operation is from pSrcBuff => pInterBuff */ pChainSrcBuff = pSrcBuff; pChainDestBuff = pInterBuff; } else { /* Next chain operation is from pInterBuff => pDestBuff */ pChainSrcBuff = pInterBuff; pChainDestBuff = pDestBuff; } } if (DC_CHAIN_TYPE_GET(pTemp) == CPA_DC_CHAIN_COMPRESS_DECOMPRESS) { pTemp += sizeof(CpaDcChainSessionType); pDcSessDesc = DC_SESSION_DESC_FROM_CTX_GET(pTemp); pDcCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc( pDcService->compression_mem_pool); if (NULL == pDcCookie) { status = CPA_STATUS_RESOURCE; goto out_err; } else if ((void *)CPA_STATUS_RETRY == pDcCookie) { status = CPA_STATUS_RETRY; goto out_err; } pDcCookie->srcTotalDataLenInBytes = 0; if (DC_CHAIN_OPDATA_TYPE0 == pChainOpDataExt->opDataType) { dcOpDataExt.opDataType = DC_OPDATA_TYPE0; dcOpDataExt.pOpData = pChainSubOpData[i].pDcOp; /* For Decrypt/Decompress operations, we get the number of bytes * to 'decompress' from the preceding 'decrypt' operation. */ if (CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS == operation) { if (NULL != pChainSubOpData[0].pCySymOp) { /* Buffer length is the output from the * cipher operation */ pDcCookie->srcTotalDataLenInBytes = pChainSubOpData[0] .pCySymOp->messageLenToCipherInBytes; } else { LAC_LOG_ERROR("pCySymOp is NULL\n"); status = CPA_STATUS_INVALID_PARAM; goto out_err; } } } else { dcOpDataExt.opDataType = DC_OPDATA_TYPE1; dcOpDataExt.pOpData = pChainSubOpData2[i].pDcOp2; /* For Decrypt/Decompress operations, we get the number of bytes * to 'decompress' from the preceding 'decrypt' operation. */ if (CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS == operation) { if (NULL != pChainSubOpData2[0].pCySymOp2) { /* Buffer length is the output from the * cipher operation */ pDcCookie->srcTotalDataLenInBytes = pChainSubOpData2[0] .pCySymOp2->symOpData.messageLenToCipherInBytes; } else { LAC_LOG_ERROR("pCySymOp2 is NULL\n"); status = CPA_STATUS_INVALID_PARAM; goto out_err; } } } status = dcChainPrepare_CompRequest(insHandle, pChainCookie, operation, pTemp, &dcOpDataExt, pDcCookie, pChainSrcBuff, pChainDestBuff, pResults); if (CPA_STATUS_SUCCESS != status) goto out_err; pTemp += DC_COMP_SESSION_SIZE; } else { pTemp += sizeof(CpaDcChainSessionType); pCyCookie = (lac_sym_bulk_cookie_t *)Lac_MemPoolEntryAlloc( pChainService->lac_sym_cookie_pool); if (NULL == pCyCookie) { LAC_LOG_ERROR("Cannot get symmetric crypto mem pool entry\n"); status = CPA_STATUS_RESOURCE; goto out_err; } else if ((void *)CPA_STATUS_RETRY == pCyCookie) { status = CPA_STATUS_RETRY; goto out_err; } if (DC_CHAIN_OPDATA_TYPE0 == pChainOpDataExt->opDataType) { cyOpDataExt.opDataType = CY_OPDATA_TYPE0; cyOpDataExt.pOpData = pChainSubOpData[i].pCySymOp; } else { cyOpDataExt.opDataType = CY_OPDATA_TYPE1; cyOpDataExt.pOpData = pChainSubOpData2[i].pCySymOp2; } status = dcChainPrepare_SymRequest(insHandle, pChainCookie, operation, pTemp, pCyCookie, &cyOpDataExt, pChainSrcBuff, pChainDestBuff, pResults); if (CPA_STATUS_SUCCESS != status) goto out_err; pTemp += LAC_SYM_SESSION_SIZE; } } if (NULL == pDcSessDesc) { LAC_LOG_ERROR("No compression request on Chaining\n"); status = CPA_STATUS_INVALID_PARAM; goto out_err; } /* Populates the QAT common request middle part of the message * (LW 6 to 13). * Note: arg 3 (buffer type) should be a flat buffer type, as there * is a strict check for this condition in Gen6 firmware. This parameter * was ignored in previous generation. */ SalQatMsg_CmnMidWrite( (icp_qat_fw_la_bulk_req_t *)&pChainCookie->request, pChainCookie, QAT_COMN_PTR_TYPE_FLAT, (Cpa64U)NULL, (Cpa64U)NULL, 0, 0); /*Put message on the ring*/ status = SalQatMsg_transPutMsg(pDcService->trans_handle_compression_tx, (void *)&pChainCookie->request, LAC_QAT_DC_REQ_SZ_LW, LAC_LOG_MSG_DC, NULL); /*update stats*/ if (CPA_STATUS_SUCCESS == status) { if (pDcSessDesc->sessDirection == CPA_DC_DIR_COMPRESS) { COMPRESSION_STAT_INC(numCompRequests, pDcService); } else { COMPRESSION_STAT_INC(numDecompRequests, pDcService); } } else { if (pDcSessDesc->sessDirection == CPA_DC_DIR_COMPRESS) { COMPRESSION_STAT_INC(numCompRequestsErrors, pDcService); } else { COMPRESSION_STAT_INC(numDecompRequestsErrors, pDcService); } goto out_err; } return CPA_STATUS_SUCCESS; out_err: osalAtomicDec(&(pSessHead->pendingChainCbCount)); dcChainOp_MemPoolEntryFree(pDcCookie); dcChainOp_MemPoolEntryFree(pCyCookie); dcChainOp_MemPoolEntryFree(pChainCookie->pDcRspAddr); dcChainOp_MemPoolEntryFree(pChainCookie->pCyRspAddr); dcChainOp_MemPoolEntryFree(pChainCookie); return status; } CpaStatus cpaDcChainPerformOp(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcChainOperations operation, Cpa8U numOpDatas, CpaDcChainOpData *pChainOpData, CpaDcChainRqResults *pResults, void *callbackTag) { dc_chain_opdata_ext_t chainOpDataExt = { 0 }; dc_chain_results_ext_t chainResultsExt = { 0 }; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pChainOpData); #endif chainOpDataExt.opDataType = DC_CHAIN_OPDATA_TYPE0; chainOpDataExt.pOpData = pChainOpData; chainResultsExt.resultsType = DC_CHAIN_RESULTS_TYPE0; chainResultsExt.pResults = pResults; return dcChainPerformOp(dcInstance, pSessionHandle, pSrcBuff, pDestBuff, NULL, operation, numOpDatas, &chainOpDataExt, &chainResultsExt, callbackTag); } /** ***************************************************************************** * @ingroup cpaDcChain * Submit a request to perform chaining with integrity operations. * * @description * This function is used to perform chaining operations over data from * the source buffer with optional integrity checking. * * @param[in] dcInstance Target service instance. * @param[in,out] pSessionHandle Session handle. * @param[in] pSrcBuff Pointer to input data buffer. * @param[out] pDestBuff Pointer to output data buffer. * @param[in] pInterBuff Pointer to intermediate buffer to be used * as internal staging area for chaining * operations. * @param[in] opData User supplied CpaDcChainOpData2 * structure. * @param[in,out] pResults Pointer to CpaDcChainRqVResults * structure. * @param[in] callbackTag User supplied value to help correlate * the callback with its associated request. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_DC_BAD_DATA The input data was not properly formed. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Function is not supported. * *****************************************************************************/ CpaStatus cpaDcChainPerformOp2(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaBufferList *pInterBuff, CpaDcChainOpData2 opData, CpaDcChainRqVResults *pResults, void *callbackTag) { return CPA_STATUS_UNSUPPORTED; } /** ************************************************************************ * @ingroup Dc_Chaining * Process symmetric crypto response message for chaining * * @param[in] pCyCookie Symmetric crypto cookie * @param[in] pCySessionDesc Symmetric crypto session description * @param[in] pCyRespMsg Symmetric crypto response message * * @param[out] pResults Chaining request result * * @retval void * **************************************************************************/ STATIC void dcChainCallback_ProcessSymCrypto(lac_sym_bulk_cookie_t *pCyCookie, lac_session_desc_t *pCySessionDesc, icp_qat_fw_la_resp_t *pCyRespMsg, CpaDcChainRqResults *pResults) { Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; Cpa8U comnErr = ERR_CODE_NO_ERROR; opStatus = pCyRespMsg->comn_resp.comn_status; comnErr = pCyRespMsg->comn_resp.comn_error.s.comn_err_code; /* Log the slice hang, ssm parity and endpoint push/pullerror inside the * response */ if (ERR_CODE_SSM_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR("Slice hang detected on CPM cipher or auth slice. "); } else if (ERR_CODE_SSM_PARITY_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR("Operation resulted in a parity error in one or more " "accelerators."); } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR( "The PCIe End Point Push/Pull or TI/RI Parity error detected."); } pResults->cyStatus = CPA_STATUS_FAIL; pResults->verifyResult = CPA_FALSE; if (ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(opStatus)) { pResults->cyStatus = CPA_STATUS_SUCCESS; if (CPA_TRUE == pCySessionDesc->digestVerify) pResults->verifyResult = CPA_TRUE; } return; } /** ************************************************************************ * @ingroup Dc_Chaining * Process data compression response message for chaining * * @param[in] pDcCookie Data compression cookie * @param[in] pDcSessionDesc Data compression session description * @param[in] pCompRespMsg Data compression response message * * @param[out] pResults Chaining request result * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * **************************************************************************/ STATIC CpaStatus dcChainCallback_ProcessComp(dc_compression_cookie_t *pDcCookie, dc_session_desc_t *pDcSessionDesc, icp_qat_fw_comp_resp_t *pCompRespMsg, CpaDcChainRqResults *pResults) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean cmpPass = CPA_TRUE, xlatPass = CPA_TRUE; #ifndef ICP_DC_DYN_NOT_SUPPORTED Cpa8U xlatErr = ERR_CODE_NO_ERROR; #endif Cpa8U cmpErr = ERR_CODE_NO_ERROR; dc_request_dir_t compDecomp = DC_COMPRESSION_REQUEST; Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; sal_compression_service_t *pService = NULL; Cpa8U hdrFlags = 0; opStatus = pCompRespMsg->comn_resp.comn_status; hdrFlags = pCompRespMsg->comn_resp.hdr_flags; /* Check compression response status */ cmpPass = (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(opStatus)); pService = (sal_compression_service_t *)(pDcCookie->dcInstance); /* Get the cmp error code */ cmpErr = pCompRespMsg->comn_resp.comn_error.s1.cmp_err_code; compDecomp = pDcCookie->compDecomp; if ((CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr) || (CPA_DC_BAD_STORED_BLOCK_LEN == (Cpa8S)cmpErr)) { cmpPass = CPA_TRUE; cmpErr = ERR_CODE_NO_ERROR; } /* Log the slice hang, ssm parity and endpoint push/pull error inside the * response */ if (ERR_CODE_SSM_ERROR == (Cpa8S)cmpErr) { LAC_LOG_ERROR("The slice hang is detected on the compression slice"); } else if (ERR_CODE_SSM_PARITY_ERROR == (Cpa8S)cmpErr) { LAC_LOG_ERROR("Operation resulted in a parity error in one or more " "accelerators."); } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)cmpErr) { LAC_LOG_ERROR( "The PCIe End Point Push/Pull or TI/RI Parity error detected."); } pResults->dcStatus = (Cpa8S)cmpErr; #ifndef ICP_DC_DYN_NOT_SUPPORTED /* Check the translator status */ if ((DC_COMPRESSION_REQUEST == compDecomp) && (CPA_DC_HT_FULL_DYNAMIC == pDcSessionDesc->huffType)) { /* Check translator response status */ xlatPass = (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(opStatus)); /* Get the translator error code */ xlatErr = pCompRespMsg->comn_resp.comn_error.s1.xlat_err_code; /* Return a fatal error or a potential error in the translator slice * if the compression slice did not return any error */ if ((CPA_DC_OK == pResults->dcStatus) || (CPA_DC_FATALERR == (Cpa8S)xlatErr)) { pResults->dcStatus = (Cpa8S)xlatErr; } } #endif status = pResults->dcStatus; /* In case of any error for an end of packet request, we need to update * the request type for the following request. */ if (CPA_DC_FLUSH_FINAL == pDcCookie->flushFlag && cmpPass && xlatPass) { pDcSessionDesc->requestType = DC_REQUEST_FIRST; } else { pDcSessionDesc->requestType = DC_REQUEST_SUBSEQUENT; } if ((CPA_DC_STATEFUL == pDcSessionDesc->sessState) || ((CPA_DC_STATELESS == pDcSessionDesc->sessState) && (DC_COMPRESSION_REQUEST == compDecomp))) { /* Overflow is a valid use case for Traditional API only. * Stateful Overflow is supported in both compression and * decompression direction. * Stateless Overflow is supported only in compression direction. */ if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) { cmpPass = CPA_TRUE; } #ifndef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) { xlatPass = CPA_TRUE; } #endif } if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) { /* Extract the response from the firmware */ pResults->consumed = pCompRespMsg->comp_resp_pars.input_byte_counter; pResults->produced = pCompRespMsg->comp_resp_pars.output_byte_counter; pDcSessionDesc->cumulativeConsumedBytes = pResults->consumed; pResults->crc32 = pCompRespMsg->comp_resp_pars.crc.legacy.curr_crc32; pResults->adler32 = pCompRespMsg->comp_resp_pars.crc.legacy.curr_adler_32; if (NULL != pService) { if (DC_COMPRESSION_REQUEST == compDecomp) COMPRESSION_STAT_INC(numCompCompleted, pService); else COMPRESSION_STAT_INC(numDecompCompleted, pService); /* Check if a CNV recovery happened and * increase stats counter */ if ((DC_COMPRESSION_REQUEST == compDecomp) && ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdrFlags) && ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdrFlags)) { COMPRESSION_STAT_INC(numCompCnvErrorsRecovered, pService); } } status = CPA_STATUS_SUCCESS; } else { #ifdef ICP_DC_RETURN_COUNTERS_ON_ERROR /* Extract the response from the firmware */ pResults->consumed = pCompRespMsg->comp_resp_pars.input_byte_counter; pResults->produced = pCompRespMsg->comp_resp_pars.output_byte_counter; pDcSessionDesc->cumulativeConsumedBytes = pResults->consumed; #else pResults->consumed = 0; pResults->produced = 0; #endif if (CPA_DC_OVERFLOW == pResults->dcStatus && CPA_DC_STATELESS == pDcSessionDesc->sessState) { /* This error message will be returned only in stateless * decompression direction */ LAC_LOG_ERROR( "Unrecoverable error: stateless overflow. You may " "need to increase the size of your destination buffer"); } if (NULL != pService) { if (DC_COMPRESSION_REQUEST == compDecomp) COMPRESSION_STAT_INC(numCompCompletedErrors, pService); else COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } } return status; } STATIC void dcChainHandleChecksums(dc_compression_cookie_t *pDcCookie, CpaCrcData *crc_external, icp_qat_comp_chain_20_cmd_id_t chain_id, CpaDcChainRqResults *pResults) { CpaDcRqResults pTempDcResults = { 0 }; dc_session_desc_t *pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pDcCookie->pSessionHandle); if (!pDcCookie->pDcOpData->integrityCrcCheck) return; pTempDcResults.status = pResults->dcStatus; pTempDcResults.produced = pResults->produced; pTempDcResults.consumed = pResults->consumed; dcHandleIntegrityChecksums(pDcCookie, crc_external, &pTempDcResults, pSessionDesc->huffType, pSessionDesc->compType, pSessionDesc->checksumType, CPA_FALSE, chain_id); pResults->dcStatus = pTempDcResults.status; } /** ***************************************************************************** * @ingroup Dc_Chaining * Process chaining result * * @description * Process chaining result, it is called at dcCompression_ProcessCallback * when response type is chaining * * @param[in,out] pRespMsg Pointer to firmware response message * * @retval void * *****************************************************************************/ void dcChainProcessResults(void *pRespMsg) { CpaStatus status = CPA_STATUS_FAIL; dc_chain_cookie_t *pChainCookie = NULL; dc_chain_session_head_t *pSessHead = NULL; icp_qat_fw_comp_chain_resp_t *pChainRespMsg = NULL; Cpa64U *pReqData = NULL; void *callbackTag = NULL; CpaDcChainRqResults *pResults = NULL; dc_chain_results_ext_t *pResultsExt = NULL; CpaDcCallbackFn pCbFunc = NULL; icp_qat_comp_chain_20_cmd_id_t cmd_id = ICP_QAT_FW_NO_CHAINING_20; icp_qat_fw_comp_resp_t *pCompRespMsg = NULL; dc_session_desc_t *pDcSessionDesc = NULL; dc_compression_cookie_t *pDcCookie = NULL; icp_qat_fw_la_resp_t *pCyRespMsg = NULL; lac_session_desc_t *pCySessionDesc = NULL; lac_sym_bulk_cookie_t *pCyCookie = NULL; Cpa8U respStatus = 0; pChainRespMsg = (icp_qat_fw_comp_chain_resp_t *)pRespMsg; LAC_MEM_SHARED_READ_TO_PTR(pChainRespMsg->opaque_data, pReqData); #ifdef ICP_PARAM_CHECK LAC_ASSERT_NOT_NULL(pReqData); #endif pChainCookie = (dc_chain_cookie_t *)pReqData; pSessHead = (dc_chain_session_head_t *)pChainCookie->pSessionHandle; callbackTag = pChainCookie->callbackTag; pDcSessionDesc = pSessHead->pDcSessionDesc; pCySessionDesc = pSessHead->pCySessionDesc; pCbFunc = pSessHead->pdcChainCb; pCompRespMsg = (icp_qat_fw_comp_resp_t *)((Cpa8U *)pChainCookie->pDcRspAddr); pCyRespMsg = (icp_qat_fw_la_resp_t *)((Cpa8U *)pChainCookie->pCyRspAddr); pResultsExt = &pChainCookie->extResults; if (DC_CHAIN_RESULTS_TYPE0 == pResultsExt->resultsType) { pResults = (CpaDcChainRqResults *)pResultsExt->pResults; } else { pResults = &((CpaDcChainRqVResults *)pResultsExt->pResults)->chainRqResults; } pDcCookie = (dc_compression_cookie_t *)((Cpa8U *)pChainCookie->pDcCookieAddr); pCyCookie = (lac_sym_bulk_cookie_t *)((Cpa8U *)pChainCookie->pCyCookieAddr); /* Check for unsupported request */ respStatus = pChainRespMsg->rspStatus; if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(respStatus)) { if (DC_CHAIN_RESULTS_TYPE0 != pResultsExt->resultsType) { ((CpaDcChainRqVResults *)pResultsExt->pResults)->chainStatus = CPA_STATUS_FAIL; } } else { /* Check for crypto or compression errors */ if (ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(respStatus) || ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(respStatus)) { if (DC_CHAIN_RESULTS_TYPE0 != pResultsExt->resultsType) { ((CpaDcChainRqVResults *)pResultsExt->pResults)->chainStatus = CPA_STATUS_FAIL; } } /* Process crypto response result */ dcChainCallback_ProcessSymCrypto( pCyCookie, pCySessionDesc, pCyRespMsg, pResults); if (CPA_STATUS_SUCCESS == pResults->cyStatus) { /* Process compression response */ status = dcChainCallback_ProcessComp( pDcCookie, pDcSessionDesc, pCompRespMsg, pResults); if (CPA_DC_OK != pResults->dcStatus && (CPA_STATUS_SUCCESS == status)) { status = CPA_STATUS_FAIL; } } } cmd_id = pChainCookie->request.hdr.service_cmd_id; dcChainHandleChecksums( pDcCookie, pDcCookie->pDcOpData->pCrcData, cmd_id, pResults); Lac_MemPoolEntryFree(pChainCookie->pDcRspAddr); Lac_MemPoolEntryFree(pChainCookie->pCyRspAddr); Lac_MemPoolEntryFree(pDcCookie); Lac_MemPoolEntryFree(pCyCookie); Lac_MemPoolEntryFree(pChainCookie); osalAtomicDec(&(pSessHead->pendingChainCbCount)); /*pCbFunc can never be NULL, its default is LacSync_GenWakeupSyncCaller*/ pCbFunc(callbackTag, status); } #endif CpaStatus cpaDcChainSetCrcControlData(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaCrcControlData *pCrcControlData) { #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pCrcControlData); #endif return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_crc32.c000066400000000000000000000123261503624047500302740ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_crc32.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of the CRC-32 operations. * *****************************************************************************/ #include "dc_crc32.h" /** * @description * Calculates CRC-32 checksum for given Buffer List * * Function loop through all of the flat buffers in the buffer list. * CRC is calculated for each flat buffer, but output CRC from * buffer[0] is used as input seed for buffer[1] CRC calculation * (and so on until looped through all flat buffers). * Resulting CRC is final CRC for all buffers in the buffer list struct * * @param[in] bufferList Pointer to data byte array to calculate CRC on * @param[in] consumedBytes Total number of bytes to calculate CRC on * (for all buffer in buffer list) * @param[in] seedChecksums Input checksum from where the calculation will * start from. * * @retval Cpa32U 32bit long CRC checksum for given buffer list */ Cpa32U dcCalculateCrc32(CpaBufferList *pBufferList, Cpa32U consumedBytes, const Cpa32U seedChecksum) { Cpa32U i = 0; Cpa64U computeLength = 0; Cpa32U flatBufferLength = 0; Cpa32U currentCrc = seedChecksum; CpaFlatBuffer *pBuffer = NULL; LAC_ENSURE_NOT_NULL(pBufferList); pBuffer = &pBufferList->pBuffers[0]; for (i = 0; i < pBufferList->numBuffers; i++) { flatBufferLength = pBuffer->dataLenInBytes; /* Get number of bytes based on remaining data (consumedBytes) and * max buffer length, then calculate CRC on them */ if (consumedBytes > flatBufferLength) { computeLength = flatBufferLength; consumedBytes -= flatBufferLength; } else { computeLength = consumedBytes; consumedBytes = 0; } #ifdef USE_CCODE_CRC currentCrc = crc32_gzip_refl_base(currentCrc, pBuffer->pData, computeLength); #else currentCrc = crc32_gzip_refl_by8(currentCrc, pBuffer->pData, computeLength); #endif pBuffer++; } return currentCrc; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_crc64.c000066400000000000000000000336631503624047500303100ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_crc64.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of the CRC-64 operations. * *****************************************************************************/ #include "dc_crc64.h" /* Number of bits in a byte */ #define NUM_BITS_PER_BYTE 8 /* Number of bits in a 64bit parameter */ #define NUM_BITS_PER_64BIT 64 /* Mask for a byte */ #define BYTE_MASK 0xFF /* Mask for the most significant bit in a 8bit parameter */ #define MOST_SIGNIFICANT_8BIT_MASK 0x80 /* Mask for the most significant bit in a 64bit parameter */ #define MOST_SIGNIFICANT_64BIT_MASK 0x8000000000000000ULL /* Bit index (zero based) of the most significant byte in a 64bit parameter */ #define MOST_SIGNIFICANT_BYTE_BIT_INDEX 56 /* Maximum number of possible byte values */ #define MAX_NUM_BYTE_VALUES 256 /* CRC lookup table is 256 * 64bit entries */ #define CRC_LOOKUP_TABLE_SIZE_IN_BYTES MAX_NUM_BYTE_VALUES * sizeof(Cpa64U) /** * @description * Calculates CRC-64 checksum for given Buffer List * * Function loop through all of the flat buffers in the buffer list. * CRC is calculated for each flat buffer, but output CRC from * buffer[0] is used as input seed for buffer[1] CRC calculation * (and so on until looped through all flat buffers). * Resulting CRC is final CRC for all buffers in the buffer list struct * * @param[in] bufferList Pointer to data byte array to calculate CRC on * @param[in] consumedBytes Total number of bytes to calculate CRC on * (for all buffer in buffer list) * @param[in] seedChecksums Input checksum from where the calculation will * start from. * * @retval Cpa64U 64bit long CRC checksum for given buffer list */ Cpa64U dcCalculateCrc64(const CpaBufferList *pBufferList, Cpa32U consumedBytes, Cpa64U seedChecksum) { Cpa32U i = 0; Cpa64U computeLength = 0; Cpa32U flatBufferLength = 0; Cpa64U currentCrc = seedChecksum; CpaFlatBuffer *pBuffer = &pBufferList->pBuffers[0]; for (i = 0; i < pBufferList->numBuffers; i++) { flatBufferLength = pBuffer->dataLenInBytes; /* Get number of bytes based on remaining data (consumedBytes) and * max buffer length, then calculate CRC on them */ if (consumedBytes > flatBufferLength) { computeLength = flatBufferLength; consumedBytes -= flatBufferLength; } else { computeLength = consumedBytes; consumedBytes = 0; } #ifdef USE_CCODE_CRC currentCrc = crc64_ecma_norm_base(currentCrc, pBuffer->pData, computeLength); #else currentCrc = crc64_ecma_norm_by8(currentCrc, pBuffer->pData, computeLength); #endif pBuffer++; } return currentCrc; } /** * @description * Reflects the 8bit input parameter. * * CRC support function to reflect the 8bit input parameter. * * Example - 8bit input parameter: 0xBE * (10111110) * Becomes: * 8bit reflected parameter: 0x7D * (01111101) * * @param[in] value 8bit input parameter to reflect. * @param[out] reflectVal 8bit reflected output. */ STATIC Cpa8U dcSwReflect8(Cpa8U value) { Cpa8U inputVal = value; Cpa8U reflectVal = 0; Cpa32U i = 0; for (i = 0; i < NUM_BITS_PER_BYTE; i++) { reflectVal = (reflectVal << 1) | (inputVal & 1); inputVal >>= 1; } return reflectVal; } /** * @description * Reflects the 64bit input parameter. * * CRC support function to reflect the 64bit input parameter. * * Example - 64bit input parameter: 0xBBE4A6466F216080 * (1011101111100100101001100100011001101111001000010110000010000000) * Becomes: * 64bit reflected parameter: 0x010684F6626527DD * (0000000100000110100001001111011001100010011001010010011111011101) * * @param[in] value 64bit input parameter to reflect. * @param[out] reflectVal 64bit reflected output. */ STATIC Cpa64U dcSwReflect64(Cpa64U value) { Cpa32U i = 0; Cpa64U inputVal = value; Cpa64U reflectVal = 0; for (i = 0; i < NUM_BITS_PER_64BIT; i++) { reflectVal = (reflectVal << 1) | (inputVal & 1); inputVal >>= 1; } return reflectVal; } /** * @description * Creates a lookup table for CRC64 calculation * * Function creates a lookup table for a given polynomial. This table is * used to speed up CRC64 calculation at runtime. * * @param[in] crc64Polynomial CRC64 polynomial used for generating the CRC * lookup table. * @param[out] ppCrcLookupTable Address of pointer to the CRC lookup table * created. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_RESOURCE Memory allocation error * */ CpaStatus dcGenerateLookupTable(Cpa64U crc64Polynomial, Cpa64U **ppCrcLookupTable) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(ppCrcLookupTable); #endif Cpa32U j = 0; Cpa64U i = 0; Cpa64U tableEntry = 0; /* Allocate the CRC64 lookup table */ *ppCrcLookupTable = NULL; if (CPA_STATUS_SUCCESS != LAC_OS_MALLOC(ppCrcLookupTable, CRC_LOOKUP_TABLE_SIZE_IN_BYTES)) { LAC_LOG_ERROR("Unable to allocate memory for CRC lookup table"); return CPA_STATUS_RESOURCE; } /* Loop through all possible byte values */ for (i = 0; i < MAX_NUM_BYTE_VALUES; i++) { /* Move to most significant byte of 64bit */ tableEntry = (i << MOST_SIGNIFICANT_BYTE_BIT_INDEX); /* For each bit in the byte */ for (j = 0; j < NUM_BITS_PER_BYTE; j++) { /* Check if the most significant bit is set */ if (tableEntry & MOST_SIGNIFICANT_64BIT_MASK) { /* XOR with polynomial if set */ tableEntry = (tableEntry << 1) ^ crc64Polynomial; } else { tableEntry = tableEntry << 1; } } /* Store result in the lookup table */ (*ppCrcLookupTable)[i] = tableEntry; } return CPA_STATUS_SUCCESS; } /** * @description * Calculates CRC-64 checksum for the given flat buffer length * * Function calculates the 64bit CRC on the given flat buffer for the * requested length. * * @param[in] pCrcConfig Pointer to the CRC configuration used for * calculating the checksum. * @param[in] pCrcLookupTable Pointer to the CRC lookup table used for * calculating the checksum. * @param[in] pData Pointer to data byte array to calculate CRC * on. * @param[in] computeLength Total number of bytes to calculate CRC on. * @param[out] pCurrentCrc Pointer to 64bit long CRC checksum for the * given flat buffer length. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in */ STATIC CpaStatus dcBufferCalculateCrc64(const CpaCrcControlData *pCrcConfig, const Cpa64U *pCrcLookupTable, const Cpa8U *pData, Cpa64U computeLength, Cpa64U *pCurrentCrc) { Cpa8U nextByte = 0; Cpa8U position = 0; Cpa64U i = 0; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pCrcConfig); LAC_CHECK_NULL_PARAM(pData); LAC_CHECK_NULL_PARAM(pCurrentCrc); LAC_CHECK_NULL_PARAM(pCrcLookupTable); #endif *pCurrentCrc = pCrcConfig->initialValue; for (i = 0; i < computeLength; i++) { nextByte = pData[i]; if (pCrcConfig->reflectIn) { /* Get the byte reflected value */ nextByte = dcSwReflect8(nextByte); } /* Calculate the position in the lookup table */ position = ((*pCurrentCrc >> MOST_SIGNIFICANT_BYTE_BIT_INDEX) ^ nextByte) & BYTE_MASK; /* Generate the CRC using the lookup table position */ *pCurrentCrc = (*pCurrentCrc << NUM_BITS_PER_BYTE) ^ pCrcLookupTable[position]; } return CPA_STATUS_SUCCESS; } /** * @description * Calculates programmable CRC-64 checksum for given Buffer List * * Function loops through all of the flat buffers in the buffer list. * CRC is calculated for each flat buffer, but output CRC from * buffer[0] is used as input seed for buffer[1] CRC calculation * (and so on until looped through all flat buffers). * Resulting CRC is final CRC for all buffers in the buffer list struct * * @param[in] pCrcConfig Pointer to the CRC configuration used for * calculating the checksum. * @param[in] pCrcLookupTable Pointer to the CRC lookup table used for * calculating the checksum. * @param[in] bufferList Pointer to data byte array to calculate CRC * on. * @param[in] consumedBytes Total number of bytes to calculate CRC on * (for all buffers in buffer list) * @param[out] pSwCrc Pointer to 64bit long CRC checksum for the * given buffer list. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in */ CpaStatus dcCalculateProgCrc64(const CpaCrcControlData *pCrcConfig, Cpa64U *pCrcLookupTable, const CpaBufferList *pBufferList, Cpa32U consumedBytes, Cpa64U *pSwCrc) { Cpa64U i = 0; Cpa64U computeLength = 0; Cpa32U flatBufferLength = 0; CpaFlatBuffer *pBuffer = &pBufferList->pBuffers[0]; CpaStatus status = CPA_STATUS_SUCCESS; for (i = 0; i < pBufferList->numBuffers; i++) { flatBufferLength = pBuffer->dataLenInBytes; /* Get number of bytes based on remaining data (consumedBytes) and * max buffer length, then calculate CRC on them */ if (consumedBytes > flatBufferLength) { computeLength = flatBufferLength; consumedBytes -= flatBufferLength; } else { computeLength = consumedBytes; consumedBytes = 0; } status = dcBufferCalculateCrc64( pCrcConfig, pCrcLookupTable, pBuffer->pData, computeLength, pSwCrc); if (CPA_STATUS_SUCCESS != status) { return status; } pBuffer++; } if (pCrcConfig->reflectOut) { /* Reflect the 64bit CRC */ *pSwCrc = dcSwReflect64(*pSwCrc); } *pSwCrc = *pSwCrc ^ pCrcConfig->xorOut; return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_crc_base.c000066400000000000000000000276501503624047500311270ustar00rootroot00000000000000/********************************************************************** Copyright(c) 2011-2022 Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **********************************************************************/ /** ***************************************************************************** * @file dc_crc_base.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of the CRC-32 and CRC-64 operations in C. * Implementation derived from ISA-L * ISA-L : Intel(R) Intelligent Storage Acceleration Library * *****************************************************************************/ #include static const uint32_t crc32_table_gzip_refl[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; static const uint64_t crc64_ecma_norm_table[256] = { 0x0000000000000000ULL, 0x42f0e1eba9ea3693ULL, 0x85e1c3d753d46d26ULL, 0xc711223cfa3e5bb5ULL, 0x493366450e42ecdfULL, 0x0bc387aea7a8da4cULL, 0xccd2a5925d9681f9ULL, 0x8e224479f47cb76aULL, 0x9266cc8a1c85d9beULL, 0xd0962d61b56fef2dULL, 0x17870f5d4f51b498ULL, 0x5577eeb6e6bb820bULL, 0xdb55aacf12c73561ULL, 0x99a54b24bb2d03f2ULL, 0x5eb4691841135847ULL, 0x1c4488f3e8f96ed4ULL, 0x663d78ff90e185efULL, 0x24cd9914390bb37cULL, 0xe3dcbb28c335e8c9ULL, 0xa12c5ac36adfde5aULL, 0x2f0e1eba9ea36930ULL, 0x6dfeff5137495fa3ULL, 0xaaefdd6dcd770416ULL, 0xe81f3c86649d3285ULL, 0xf45bb4758c645c51ULL, 0xb6ab559e258e6ac2ULL, 0x71ba77a2dfb03177ULL, 0x334a9649765a07e4ULL, 0xbd68d2308226b08eULL, 0xff9833db2bcc861dULL, 0x388911e7d1f2dda8ULL, 0x7a79f00c7818eb3bULL, 0xcc7af1ff21c30bdeULL, 0x8e8a101488293d4dULL, 0x499b3228721766f8ULL, 0x0b6bd3c3dbfd506bULL, 0x854997ba2f81e701ULL, 0xc7b97651866bd192ULL, 0x00a8546d7c558a27ULL, 0x4258b586d5bfbcb4ULL, 0x5e1c3d753d46d260ULL, 0x1cecdc9e94ace4f3ULL, 0xdbfdfea26e92bf46ULL, 0x990d1f49c77889d5ULL, 0x172f5b3033043ebfULL, 0x55dfbadb9aee082cULL, 0x92ce98e760d05399ULL, 0xd03e790cc93a650aULL, 0xaa478900b1228e31ULL, 0xe8b768eb18c8b8a2ULL, 0x2fa64ad7e2f6e317ULL, 0x6d56ab3c4b1cd584ULL, 0xe374ef45bf6062eeULL, 0xa1840eae168a547dULL, 0x66952c92ecb40fc8ULL, 0x2465cd79455e395bULL, 0x3821458aada7578fULL, 0x7ad1a461044d611cULL, 0xbdc0865dfe733aa9ULL, 0xff3067b657990c3aULL, 0x711223cfa3e5bb50ULL, 0x33e2c2240a0f8dc3ULL, 0xf4f3e018f031d676ULL, 0xb60301f359dbe0e5ULL, 0xda050215ea6c212fULL, 0x98f5e3fe438617bcULL, 0x5fe4c1c2b9b84c09ULL, 0x1d14202910527a9aULL, 0x93366450e42ecdf0ULL, 0xd1c685bb4dc4fb63ULL, 0x16d7a787b7faa0d6ULL, 0x5427466c1e109645ULL, 0x4863ce9ff6e9f891ULL, 0x0a932f745f03ce02ULL, 0xcd820d48a53d95b7ULL, 0x8f72eca30cd7a324ULL, 0x0150a8daf8ab144eULL, 0x43a04931514122ddULL, 0x84b16b0dab7f7968ULL, 0xc6418ae602954ffbULL, 0xbc387aea7a8da4c0ULL, 0xfec89b01d3679253ULL, 0x39d9b93d2959c9e6ULL, 0x7b2958d680b3ff75ULL, 0xf50b1caf74cf481fULL, 0xb7fbfd44dd257e8cULL, 0x70eadf78271b2539ULL, 0x321a3e938ef113aaULL, 0x2e5eb66066087d7eULL, 0x6cae578bcfe24bedULL, 0xabbf75b735dc1058ULL, 0xe94f945c9c3626cbULL, 0x676dd025684a91a1ULL, 0x259d31cec1a0a732ULL, 0xe28c13f23b9efc87ULL, 0xa07cf2199274ca14ULL, 0x167ff3eacbaf2af1ULL, 0x548f120162451c62ULL, 0x939e303d987b47d7ULL, 0xd16ed1d631917144ULL, 0x5f4c95afc5edc62eULL, 0x1dbc74446c07f0bdULL, 0xdaad56789639ab08ULL, 0x985db7933fd39d9bULL, 0x84193f60d72af34fULL, 0xc6e9de8b7ec0c5dcULL, 0x01f8fcb784fe9e69ULL, 0x43081d5c2d14a8faULL, 0xcd2a5925d9681f90ULL, 0x8fdab8ce70822903ULL, 0x48cb9af28abc72b6ULL, 0x0a3b7b1923564425ULL, 0x70428b155b4eaf1eULL, 0x32b26afef2a4998dULL, 0xf5a348c2089ac238ULL, 0xb753a929a170f4abULL, 0x3971ed50550c43c1ULL, 0x7b810cbbfce67552ULL, 0xbc902e8706d82ee7ULL, 0xfe60cf6caf321874ULL, 0xe224479f47cb76a0ULL, 0xa0d4a674ee214033ULL, 0x67c58448141f1b86ULL, 0x253565a3bdf52d15ULL, 0xab1721da49899a7fULL, 0xe9e7c031e063acecULL, 0x2ef6e20d1a5df759ULL, 0x6c0603e6b3b7c1caULL, 0xf6fae5c07d3274cdULL, 0xb40a042bd4d8425eULL, 0x731b26172ee619ebULL, 0x31ebc7fc870c2f78ULL, 0xbfc9838573709812ULL, 0xfd39626eda9aae81ULL, 0x3a28405220a4f534ULL, 0x78d8a1b9894ec3a7ULL, 0x649c294a61b7ad73ULL, 0x266cc8a1c85d9be0ULL, 0xe17dea9d3263c055ULL, 0xa38d0b769b89f6c6ULL, 0x2daf4f0f6ff541acULL, 0x6f5faee4c61f773fULL, 0xa84e8cd83c212c8aULL, 0xeabe6d3395cb1a19ULL, 0x90c79d3fedd3f122ULL, 0xd2377cd44439c7b1ULL, 0x15265ee8be079c04ULL, 0x57d6bf0317edaa97ULL, 0xd9f4fb7ae3911dfdULL, 0x9b041a914a7b2b6eULL, 0x5c1538adb04570dbULL, 0x1ee5d94619af4648ULL, 0x02a151b5f156289cULL, 0x4051b05e58bc1e0fULL, 0x87409262a28245baULL, 0xc5b073890b687329ULL, 0x4b9237f0ff14c443ULL, 0x0962d61b56fef2d0ULL, 0xce73f427acc0a965ULL, 0x8c8315cc052a9ff6ULL, 0x3a80143f5cf17f13ULL, 0x7870f5d4f51b4980ULL, 0xbf61d7e80f251235ULL, 0xfd913603a6cf24a6ULL, 0x73b3727a52b393ccULL, 0x31439391fb59a55fULL, 0xf652b1ad0167feeaULL, 0xb4a25046a88dc879ULL, 0xa8e6d8b54074a6adULL, 0xea16395ee99e903eULL, 0x2d071b6213a0cb8bULL, 0x6ff7fa89ba4afd18ULL, 0xe1d5bef04e364a72ULL, 0xa3255f1be7dc7ce1ULL, 0x64347d271de22754ULL, 0x26c49cccb40811c7ULL, 0x5cbd6cc0cc10fafcULL, 0x1e4d8d2b65facc6fULL, 0xd95caf179fc497daULL, 0x9bac4efc362ea149ULL, 0x158e0a85c2521623ULL, 0x577eeb6e6bb820b0ULL, 0x906fc95291867b05ULL, 0xd29f28b9386c4d96ULL, 0xcedba04ad0952342ULL, 0x8c2b41a1797f15d1ULL, 0x4b3a639d83414e64ULL, 0x09ca82762aab78f7ULL, 0x87e8c60fded7cf9dULL, 0xc51827e4773df90eULL, 0x020905d88d03a2bbULL, 0x40f9e43324e99428ULL, 0x2cffe7d5975e55e2ULL, 0x6e0f063e3eb46371ULL, 0xa91e2402c48a38c4ULL, 0xebeec5e96d600e57ULL, 0x65cc8190991cb93dULL, 0x273c607b30f68faeULL, 0xe02d4247cac8d41bULL, 0xa2dda3ac6322e288ULL, 0xbe992b5f8bdb8c5cULL, 0xfc69cab42231bacfULL, 0x3b78e888d80fe17aULL, 0x7988096371e5d7e9ULL, 0xf7aa4d1a85996083ULL, 0xb55aacf12c735610ULL, 0x724b8ecdd64d0da5ULL, 0x30bb6f267fa73b36ULL, 0x4ac29f2a07bfd00dULL, 0x08327ec1ae55e69eULL, 0xcf235cfd546bbd2bULL, 0x8dd3bd16fd818bb8ULL, 0x03f1f96f09fd3cd2ULL, 0x41011884a0170a41ULL, 0x86103ab85a2951f4ULL, 0xc4e0db53f3c36767ULL, 0xd8a453a01b3a09b3ULL, 0x9a54b24bb2d03f20ULL, 0x5d45907748ee6495ULL, 0x1fb5719ce1045206ULL, 0x919735e51578e56cULL, 0xd367d40ebc92d3ffULL, 0x1476f63246ac884aULL, 0x568617d9ef46bed9ULL, 0xe085162ab69d5e3cULL, 0xa275f7c11f7768afULL, 0x6564d5fde549331aULL, 0x279434164ca30589ULL, 0xa9b6706fb8dfb2e3ULL, 0xeb46918411358470ULL, 0x2c57b3b8eb0bdfc5ULL, 0x6ea7525342e1e956ULL, 0x72e3daa0aa188782ULL, 0x30133b4b03f2b111ULL, 0xf7021977f9cceaa4ULL, 0xb5f2f89c5026dc37ULL, 0x3bd0bce5a45a6b5dULL, 0x79205d0e0db05dceULL, 0xbe317f32f78e067bULL, 0xfcc19ed95e6430e8ULL, 0x86b86ed5267cdbd3ULL, 0xc4488f3e8f96ed40ULL, 0x0359ad0275a8b6f5ULL, 0x41a94ce9dc428066ULL, 0xcf8b0890283e370cULL, 0x8d7be97b81d4019fULL, 0x4a6acb477bea5a2aULL, 0x089a2aacd2006cb9ULL, 0x14dea25f3af9026dULL, 0x562e43b4931334feULL, 0x913f6188692d6f4bULL, 0xd3cf8063c0c759d8ULL, 0x5dedc41a34bbeeb2ULL, 0x1f1d25f19d51d821ULL, 0xd80c07cd676f8394ULL, 0x9afce626ce85b507ULL }; uint32_t crc32_gzip_refl_base(uint32_t seed, uint8_t * buf, uint64_t len) { unsigned int crc; unsigned char *p_buf; unsigned char *p_end = buf + len; p_buf = (unsigned char *)buf; crc = ~seed; while (p_buf < p_end) { crc = (crc >> 8) ^ crc32_table_gzip_refl[(crc & 0x000000FF) ^ *p_buf++]; } return ~crc; } uint64_t crc64_ecma_norm_base(uint64_t seed, const uint8_t * buf, uint64_t len) { uint64_t i; /* Original ISA-L has crc = ~seed; Changed for CPM gen4 HW compatibility */ uint64_t crc = seed; for (i = 0; i < len; i++) { uint8_t byte = buf[i]; crc = crc64_ecma_norm_table[((crc >> 56) ^ byte) & 0xff] ^ (crc << 8); } /* Original ISA-L has return ~crc; Changed for CPM gen4 HW compatibility */ return crc; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_datapath.c000066400000000000000000003417011503624047500311500ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_datapath.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of the Data Compression datapath operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc_dp.h" #ifndef ICP_DC_ONLY #include "dc_chain.h" #endif #include "icp_qat_hw_20_comp.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_datapath.h" #include "dc_ns_datapath.h" #include "sal_statistics.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_log.h" #include "dc_stats.h" #include "lac_buffer_desc.h" #include "lac_sal.h" #include "lac_sync.h" #include "sal_service_state.h" #include "sal_qat_cmn_msg.h" #ifdef ICP_DC_ERROR_SIMULATION #include "dc_err_sim.h" #endif #include "dc_error_counter.h" #ifndef KERNEL_SPACE #include #include "dc_crc32.h" #include "dc_crc64.h" #endif #include "sal_misc_error_stats.h" #define DC_COMP_MAX_BUFF_SIZE (1024 * 64) STATIC OsalAtomic dcErrorCount[MAX_DC_ERROR_TYPE]; void dcErrorLog(CpaDcReqStatus dcError) { Cpa32U absError = 0; absError = abs(dcError); if ((dcError < CPA_DC_OK) && (absError < MAX_DC_ERROR_TYPE)) { osalAtomicInc(&(dcErrorCount[absError])); } } /* Reset xxhash state */ STATIC void dcResetXxhashState(dc_session_desc_t *pSessionDesc, dc_compression_cookie_t *pCookie) { if ((NULL == pSessionDesc) || (NULL == pCookie)) return; if ((CPA_DC_LZ4 == pSessionDesc->compType) && (CPA_DC_XXHASH32 == pSessionDesc->checksumType) && (CPA_DC_FLUSH_FINAL == pCookie->flushFlag)) { dcXxhash32SetState(pSessionDesc, 0); } } Cpa64U getDcErrorCounter(CpaDcReqStatus dcError) { Cpa32U absError = 0; absError = abs(dcError); if (!(dcError >= CPA_DC_OK || dcError < CPA_DC_EMPTY_DYM_BLK)) { return (Cpa64U)osalAtomicGet(&dcErrorCount[absError]); } return 0; } #ifndef KERNEL_SPACE STATIC void dcUpdateCompStateCrc(dc_compression_cookie_t *pCookie, const Cpa32U offset, const Cpa32U newCrcValue) { Cpa8U *pStateAddr = NULL; Cpa8U i = 0; dc_session_desc_t *pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle); /* Update state register with new CRC32 value */ pStateAddr = &pSessionDesc->stateRegistersComp[offset]; for (i = 0; i < DC_CHECKSUM_SIZE_IN_BYTES; i++) { *(pStateAddr++) = (newCrcValue >> (i * DC_8_BIT_SHIFT_POS)) & DC_8_BIT_MASK; } } void dcHandleIntegrityChecksumsLegacy(dc_compression_cookie_t *pCookie, CpaCrcData *crc_external, CpaDcRqResults *pDcResults, CpaDcHuffType huffType, CpaDcChecksum checksumType, CpaDcSessionState sessState, CpaDcSessionDir sessDirection, CpaBoolean isDcNs) { dc_integrity_crc_fw_t *crc_internal = &pCookie->dataIntegrityCrcs; CpaBoolean integrityErrorOccurred = CPA_FALSE; dc_request_dir_t compDecomp = pCookie->compDecomp; Cpa32U swCrcI = DC_DEFAULT_CRC, swCrcO = DC_DEFAULT_CRC; CpaBoolean verifyHwIntegrityCrcs = pCookie->pDcOpData->verifyHwIntegrityCrcs; dc_sw_checksums_t seedSwCrc; seedSwCrc.swCrc32I = DC_DEFAULT_CRC; seedSwCrc.swCrc32O = DC_DEFAULT_CRC; if ((CPA_DC_STATEFUL == sessState) && (CPA_FALSE == isDcNs)) { seedSwCrc.swCrc32I = crc_external->integrityCrc.iCrc; seedSwCrc.swCrc32O = crc_external->integrityCrc.oCrc; } /* Move results from internal firmware buffer (opaque to user) * into structure fields visible to user */ crc_external->crc32 = crc_internal->crc32; crc_external->adler32 = crc_internal->adler32; /* Copy compression input CRC to iCrc field of * CpaIntegrityCrc structure */ crc_external->integrityCrc.iCrc = crc_internal->iCrc32Cpr; if ((CPA_TRUE == verifyHwIntegrityCrcs) || (DC_CLEARTEXT_TYPE == (dc_block_type_t)crc_internal->deflateBlockType)) { /* Calculate checksum on input data */ swCrcI = dcCalculateCrc32( pCookie->pUserSrcBuff, pDcResults->consumed, seedSwCrc.swCrc32I); /* Calculate checksum on output data */ swCrcO = dcCalculateCrc32( pCookie->pUserDestBuff, pDcResults->produced, seedSwCrc.swCrc32O); } if (DC_STATIC_TYPE == (dc_block_type_t)crc_internal->deflateBlockType || CPA_DC_DIR_DECOMPRESS == sessDirection) { crc_external->integrityCrc.oCrc = crc_internal->oCrc32Cpr; } else if (DC_DYNAMIC_TYPE == (dc_block_type_t)crc_internal->deflateBlockType) { /* Copy translator output CRC to oCrc field of * CpaIntegrityCrc structure */ crc_external->integrityCrc.oCrc = crc_internal->oCrc32Xlt; /* Verify data integrity between compression and translator slices. */ if (crc_internal->oCrc32Cpr != crc_internal->iCrc32Xlt) { integrityErrorOccurred = CPA_TRUE; } } else if (DC_CLEARTEXT_TYPE == (dc_block_type_t)crc_internal->deflateBlockType) { crc_external->integrityCrc.iCrc = swCrcI; crc_external->integrityCrc.oCrc = swCrcO; if (CPA_FALSE == isDcNs) { /* Update State register 5 "CRC32" */ dcUpdateCompStateCrc(pCookie, DC_STATE_CRC32_OFFSET, swCrcI); /* Update State register 6 "Input CRC32" */ dcUpdateCompStateCrc(pCookie, DC_STATE_INPUT_CRC32_OFFSET, swCrcI); /* Update State register 6 "Input CRC32" */ dcUpdateCompStateCrc(pCookie, DC_STATE_OUTPUT_CRC32_OFFSET, swCrcO); } } /* Compare H/W CRCs against software ones if required */ if (CPA_TRUE == verifyHwIntegrityCrcs) { if (crc_external->integrityCrc.iCrc != swCrcI || crc_external->integrityCrc.oCrc != swCrcO) { integrityErrorOccurred = CPA_TRUE; } } if (CPA_TRUE == integrityErrorOccurred) { LAC_LOG_ERROR("CRC Data integrity failure detected."); LAC_LOG_ERROR1("\tsoftware input buffer CRC = 0x%08x", swCrcI); LAC_LOG_ERROR1("\tsoftware output buffer CRC = 0x%08x", swCrcO); LAC_LOG_ERROR1("\tinternal compression input CRC = 0x%08x", crc_internal->iCrc32Cpr); LAC_LOG_ERROR1("\tinternal compression output CRC = 0x%08x", crc_internal->oCrc32Cpr); /* Report extra CRCs for dynamic compression */ if (CPA_DC_HT_FULL_DYNAMIC == huffType) { LAC_LOG_ERROR1("\tinternal translator input CRC = 0x%08x", crc_internal->iCrc32Xlt); LAC_LOG_ERROR1("\tinternal translator output CRC = 0x%08x", crc_internal->oCrc32Xlt); } /* IA should indicate CRC integrity error, but does not * override hardware error code if one was already set */ if (CPA_DC_OK == pDcResults->status || CPA_DC_OVERFLOW == pDcResults->status) { pDcResults->status = CPA_DC_CRC_INTEG_ERR; } } else if ((DC_DYNAMIC_TYPE == (dc_block_type_t)crc_internal->deflateBlockType) && (CPA_FALSE == isDcNs)) { /* Update the state registers in case of Stateful compression */ if (DC_COMPRESSION_REQUEST == compDecomp) { /* Update State register 6 "Output CRC32" */ dcUpdateCompStateCrc(pCookie, DC_STATE_OUTPUT_CRC32_OFFSET, crc_external->integrityCrc.oCrc); } } else if ((DC_STATIC_TYPE == (dc_block_type_t)crc_internal->deflateBlockType) && (CPA_FALSE == isDcNs)) { if (DC_COMPRESSION_REQUEST == compDecomp) { /* Update State register 6 "Output CRC32" */ dcUpdateCompStateCrc(pCookie, DC_STATE_OUTPUT_CRC32_OFFSET, crc_external->integrityCrc.oCrc); } } if (CPA_DC_CRC32 == checksumType) { pDcResults->checksum = crc_external->crc32; } else if (CPA_DC_ADLER32 == checksumType) { pDcResults->checksum = crc_external->adler32; } } void dcHandleIntegrityChecksums(dc_compression_cookie_t *pCookie, CpaCrcData *crc_external, CpaDcRqResults *pDcResults, CpaDcHuffType huffType, CpaDcCompType compType, CpaDcChecksum checksumType, CpaBoolean isDcNs, icp_qat_comp_chain_20_cmd_id_t chain_id) { dc_integrity_crc_fw_t *crc_internal = &pCookie->dataIntegrityCrcs; CpaBoolean integrityErrorOccurred = CPA_FALSE; Cpa64U swCrc64I = DC_DEFAULT_CRC, swCrc64O = DC_DEFAULT_CRC; dc_block_type_t blockType = DC_STATIC_TYPE; CpaBoolean verifyHwIntegrityCrcs = pCookie->pDcOpData->verifyHwIntegrityCrcs; sal_compression_service_t *pService = NULL; dc_capabilities_t *pDcCapabilities = NULL; dc_hw_gen_types_t hw_gen = DC_CAPS_GEN4_HW; CpaCrcControlData crcControlData = { 0 }; dc_session_desc_t *pSessionDesc = NULL; CpaBoolean bProgCrc = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; pService = (sal_compression_service_t *)(pCookie->dcInstance); pDcCapabilities = &pService->dc_capabilities; hw_gen = pDcCapabilities->deviceData.hw_gen; if (!isDcNs) { pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle); bProgCrc = pSessionDesc->crcConfig.useProgCrcSetup; } /* Simply set block type as per huffman type. * Only set blockType to DC_DYNAMIC_TYPE because it's copying * of the OCRC64 from the XLT field specific to dynamic deflate * compression for Gen4 HW. In all other cases the OCRC64 will * be copied from the CPR field. */ if ((DC_CAPS_GEN4_HW == hw_gen) && (CPA_DC_DEFLATE == compType) && (CPA_DC_HT_FULL_DYNAMIC == huffType) && (DC_COMPRESSION_REQUEST == pCookie->compDecomp)) { blockType = DC_DYNAMIC_TYPE; } /* Move results from internal firmware buffer (opaque to user) * into structure fields visible to user */ crc_external->crc32 = crc_internal->crc32; crc_external->adler32 = crc_internal->adler32; /* Copy compression input CRC to iCrc field of * CpaIntegrityCrc64b structure */ crc_external->integrityCrc64b.iCrc = crc_internal->iCrc64Cpr; if (DC_DYNAMIC_TYPE == blockType) { /* Copy translator output CRC to oCrc field of * CpaIntegrityCrc64b structure */ crc_external->integrityCrc64b.oCrc = crc_internal->oCrc64Xlt; } else { /* Copy compression output CRC to oCrc field of * CpaIntegrityCrc64b structure */ crc_external->integrityCrc64b.oCrc = crc_internal->oCrc64Cpr; } /* Compare H/W CRCs against software ones if required */ if (CPA_TRUE == verifyHwIntegrityCrcs) { /* Different SW algorithms used if using hardcoded crc parameters * versus programmable crc parameters. */ if (!bProgCrc) { /* Calculate checksum on input data */ swCrc64I = dcCalculateCrc64( pCookie->pUserSrcBuff, pDcResults->consumed, DC_DEFAULT_CRC); /* Calculate checksum on output data */ swCrc64O = dcCalculateCrc64(pCookie->pUserDestBuff, pDcResults->produced, DC_DEFAULT_CRC); } else { /* Set the crc control data */ crcControlData.initialValue = pSessionDesc->crcConfig.crcParam.iCrc64Cpr; crcControlData.polynomial = pSessionDesc->crcConfig.crcParam.crc64Poly; crcControlData.xorOut = pSessionDesc->crcConfig.crcParam.xor64Out; crcControlData.reflectIn = pSessionDesc->crcConfig.crcParam.reflectIn ? CPA_TRUE : CPA_FALSE; crcControlData.reflectOut = pSessionDesc->crcConfig.crcParam.reflectOut ? CPA_TRUE : CPA_FALSE; /* Calculate checksum on input data */ status = dcCalculateProgCrc64(&crcControlData, pSessionDesc->crcConfig.pCrcLookupTable, pCookie->pUserSrcBuff, pDcResults->consumed, &swCrc64I); if (CPA_STATUS_SUCCESS == status) { if (DC_DYNAMIC_TYPE == blockType) { /* Get the seed checksum for the output */ crcControlData.initialValue = pSessionDesc->crcConfig.crcParam.oCrc64Xlt; } else { /* Get the seed checksum for the output */ crcControlData.initialValue = pSessionDesc->crcConfig.crcParam.oCrc64Cpr; } /* Calculate checksum on output data */ status = dcCalculateProgCrc64( &crcControlData, pSessionDesc->crcConfig.pCrcLookupTable, pCookie->pUserDestBuff, pDcResults->produced, &swCrc64O); } } switch (chain_id) { case ICP_QAT_FW_CHAINING_20_CMD_COMPRESS_ENCRYPT: if (crc_external->integrityCrc64b.iCrc != swCrc64I || CPA_STATUS_SUCCESS != status) { integrityErrorOccurred = CPA_TRUE; } break; case ICP_QAT_FW_CHAINING_20_CMD_DECRYPT_DECOMPRESS: if (crc_external->integrityCrc64b.oCrc != swCrc64O || CPA_STATUS_SUCCESS != status) { integrityErrorOccurred = CPA_TRUE; } break; default: if (crc_external->integrityCrc64b.iCrc != swCrc64I || crc_external->integrityCrc64b.oCrc != swCrc64O || CPA_STATUS_SUCCESS != status) { integrityErrorOccurred = CPA_TRUE; } break; } } if (CPA_TRUE == integrityErrorOccurred) { LAC_LOG_ERROR("CRC Data integrity failure detected."); LAC_LOG_ERROR_PARAMS("\tsoftware input buffer CRC64 = 0x%016llx", swCrc64I); LAC_LOG_ERROR_PARAMS("\tsoftware output buffer CRC64 = 0x%016llx", swCrc64O); LAC_LOG_ERROR_PARAMS("\tinternal compression input CRC64 = 0x%016llx", crc_internal->iCrc64Cpr); LAC_LOG_ERROR_PARAMS("\tinternal compression output CRC64 = 0x%016llx", crc_internal->oCrc64Cpr); /* Report extra CRCs for dynamic compression */ if (DC_DYNAMIC_TYPE == blockType) { LAC_LOG_ERROR_PARAMS( "\tinternal translator output CRC64 = 0x%016llx", crc_internal->oCrc64Xlt); } /* IA should indicate CRC integrity error, but does not * override hardware error code if one was already set */ if (CPA_DC_OK == pDcResults->status || CPA_DC_OVERFLOW == pDcResults->status) { pDcResults->status = CPA_DC_CRC_INTEG_ERR; } } if (CPA_DC_CRC32 == checksumType) { pDcResults->checksum = crc_external->crc32; } else if (CPA_DC_ADLER32 == checksumType || CPA_DC_XXHASH32 == checksumType) { /* XXHASH32 and Adler share the same member */ pDcResults->checksum = crc_external->adler32; } } #endif void dcCompression_ProcessCallback(void *pRespMsg) { CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_comp_resp_t *pCompRespMsg = NULL; void *callbackTag = NULL; Cpa64U *pReqData = NULL; CpaDcDpOpData *pResponse = NULL; CpaDcRqResults *pResults = NULL; CpaDcCallbackFn pCbFunc = NULL; dc_session_desc_t *pSessionDesc = NULL; sal_compression_service_t *pService = NULL; dc_compression_cookie_t *pCookie = NULL; CpaDcOpData *pOpData = NULL; CpaBoolean cmpPass = CPA_TRUE, xlatPass = CPA_TRUE; CpaBoolean isDcDp = CPA_FALSE; Cpa8U cmpErr = ERR_CODE_NO_ERROR, xlatErr = ERR_CODE_NO_ERROR; dc_request_dir_t compDecomp = DC_COMPRESSION_REQUEST; Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; Cpa8U hdrFlags = 0; dc_capabilities_t *pDcCapabilities = NULL; CpaBoolean bypassIncompleteFileErr = CPA_FALSE; CpaBoolean uncompressedDataSupported = CPA_FALSE; dc_hw_gen_types_t hw_gen; /* Cast response message to compression response message type */ pCompRespMsg = (icp_qat_fw_comp_resp_t *)pRespMsg; #ifdef ICP_PARAM_CHECK LAC_ASSERT_NOT_NULL(pCompRespMsg); #endif #ifndef ICP_DC_ONLY #ifndef KERNEL_SPACE if (pCompRespMsg->comn_resp.response_type == ICP_QAT_FW_COMN_REQ_CPM_FW_COMP_CHAIN) { dcChainProcessResults(pRespMsg); return; } #endif #endif /* Extract request data pointer from the opaque data */ LAC_MEM_SHARED_READ_TO_PTR(pCompRespMsg->opaque_data, pReqData); #ifdef ICP_PARAM_CHECK LAC_ASSERT_NOT_NULL(pReqData); #endif /* Extract fields from the request data structure */ pCookie = (dc_compression_cookie_t *)pReqData; if (DCNS == (LAC_ARCH_UINT)pCookie->pSessionHandle || DCDPNS == (LAC_ARCH_UINT)pCookie->pSessionHandle) { dcNsCompression_ProcessCallback(pRespMsg); return; } pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle); pService = (sal_compression_service_t *)(pCookie->dcInstance); /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; bypassIncompleteFileErr = pDcCapabilities->deflate.bypassIncompleteFileErr; uncompressedDataSupported = pDcCapabilities->deviceData.uncompressedDataSupported; hw_gen = pDcCapabilities->deviceData.hw_gen; isDcDp = pSessionDesc->isDcDp; if (CPA_TRUE == isDcDp) { pResponse = (CpaDcDpOpData *)pReqData; if (NULL != pResponse) { pResults = &(pResponse->results); } if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { compDecomp = DC_DECOMPRESSION_REQUEST; } pCookie = NULL; } else { pSessionDesc = pCookie->pSessionDesc; pResults = pCookie->pResults; callbackTag = pCookie->callbackTag; pCbFunc = pCookie->pSessionDesc->pCompressionCb; compDecomp = pCookie->compDecomp; pOpData = pCookie->pDcOpData; } isDcDp = pSessionDesc->isDcDp; opStatus = pCompRespMsg->comn_resp.comn_status; hdrFlags = pCompRespMsg->comn_resp.hdr_flags; /* Get the cmp error code */ cmpErr = pCompRespMsg->comn_resp.comn_error.s1.cmp_err_code; #ifdef ICP_DC_ERROR_SIMULATION if ((CPA_FALSE == isDcDp) && (0 != pCookie->dcErrorToSimulate)) { cmpErr = pCookie->dcErrorToSimulate; } #endif /* Check for compression request opStatus and update callback status accordingly. * In case of an invalid request parameter or an unsupported request status is returned. * In such cases, produced and consumed values are set to zero. */ if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(opStatus)) { LAC_LOG_ERROR("Compression feature is not supported"); status = CPA_STATUS_UNSUPPORTED; } else if (ICP_QAT_FW_COMN_RESP_INVALID_PARAMETER_GET(opStatus)) { LAC_LOG_ERROR("Request has an invalid parameter"); status = CPA_STATUS_INVALID_PARAM; } if (CPA_STATUS_SUCCESS != status) { if (NULL != pResults) { pResults->status = (Cpa8S)cmpErr; pResults->consumed = 0; pResults->produced = 0; } if (CPA_TRUE == isDcDp) { if (NULL != pResponse) { /* Decrement number of stateless pending callbacks for session */ pSessionDesc->pendingDpStatelessCbCount--; pResponse->responseStatus = CPA_STATUS_UNSUPPORTED; (pService->pDcDpCb)(pResponse); } } else { if (pCookie != NULL) { /* Decrement number of pending callbacks for session */ if (CPA_DC_STATELESS == pSessionDesc->sessState) { osalAtomicDec( &(pCookie->pSessionDesc->pendingStatelessCbCount)); } else if (0 != osalAtomicGet( &pCookie->pSessionDesc->pendingStatefulCbCount)) { osalAtomicDec( &(pCookie->pSessionDesc->pendingStatefulCbCount)); } /* Free the memory pool */ Lac_MemPoolEntryFree(pCookie); pCookie = NULL; } if (NULL != pCbFunc) { pCbFunc(callbackTag, status); } } if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompCompletedErrors, pService); } else { COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } SAL_MISC_ERR_STATS_INC(cmpErr, &pService->generic_service_info); return; } else { /* Check compression response status */ cmpPass = (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(opStatus)); SAL_MISC_ERR_STATS_INC(cmpErr, &pService->generic_service_info); } /* Cancel the incomplete file error code only for DEFLATE algorithm */ if ((CPA_TRUE == bypassIncompleteFileErr) && (CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr) && (pSessionDesc->compType == CPA_DC_DEFLATE)) { cmpPass = CPA_TRUE; cmpErr = ERR_CODE_NO_ERROR; } /* log the slice hang, ssm parity and endpoint push/pull error inside the * response */ if (ERR_CODE_SSM_ERROR == (Cpa8S)cmpErr) { LAC_LOG_ERROR("The slice hang is detected on the compression slice"); } else if (ERR_CODE_SSM_PARITY_ERROR == (Cpa8S)cmpErr) { LAC_LOG_ERROR("Operation resulted in a parity error in one or more " "accelerators."); } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)cmpErr) { LAC_LOG_ERROR( "The PCIe End Point Push/Pull or TI/RI Parity error detected."); } /* We return the compression error code for now. We would need to update * the API if we decide to return both error codes */ if (NULL != pResults) pResults->status = (Cpa8S)cmpErr; #ifndef ICP_DC_DYN_NOT_SUPPORTED /* Check the translator status */ if ((DC_COMPRESSION_REQUEST == compDecomp) && (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) { /* Check translator response status */ xlatPass = (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(opStatus)); /* Get the translator error code */ xlatErr = pCompRespMsg->comn_resp.comn_error.s1.xlat_err_code; /* Return a fatal error or a potential error in the translator slice * if the compression slice did not return any error */ if (pResults && ((CPA_DC_OK == pResults->status) || (CPA_DC_FATALERR == (Cpa8S)xlatErr))) { pResults->status = (Cpa8S)xlatErr; } } #endif /* Update dc error counter */ if (pResults) dcErrorLog(pResults->status); if (CPA_FALSE == isDcDp) { if (CPA_FALSE == pDcCapabilities->overflowResubmitUnsupported) { /* In case of any error for an end of packet request, we need to * update the request type for the following request */ if (CPA_DC_FLUSH_FINAL == pCookie->flushFlag && cmpPass && xlatPass) { pSessionDesc->requestType = DC_REQUEST_FIRST; } else { pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT; } } /* * Block drop when using LZ4 output CRC format without header * (CPA_DC_LZ4_OUTPUT_WITHOUT_HEADER) is supported. */ if (DC_COMPRESSION_REQUEST == compDecomp && CPA_DC_LZ4_MULTIBLOCK_WITHOUT_HEADER == (Cpa8S)cmpErr) { cmpPass = CPA_TRUE; } else if ((CPA_DC_STATEFUL == pSessionDesc->sessState) || ((CPA_DC_STATELESS == pSessionDesc->sessState) && (DC_COMPRESSION_REQUEST == compDecomp))) { /* Overflow is a valid use case for Traditional API only. * Stateful Overflow is supported in both compression and * decompression direction. * Stateless Overflow is supported only in compression direction. */ if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) { if (CPA_TRUE == pDcCapabilities->overflowResubmitUnsupported) { cmpPass = CPA_FALSE; } else { cmpPass = CPA_TRUE; } } #ifndef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) { if (CPA_TRUE == pDcCapabilities->overflowResubmitUnsupported) { xlatPass = CPA_FALSE; } else { xlatPass = CPA_TRUE; } } #endif } } else { if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) { cmpPass = CPA_FALSE; } #ifndef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) { /* XLT overflow is not valid for Data Plane requests */ xlatPass = CPA_FALSE; } #endif } if (pResults && (CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) { /* Extract the response from the firmware */ pResults->consumed = pCompRespMsg->comp_resp_pars.input_byte_counter; pResults->produced = pCompRespMsg->comp_resp_pars.output_byte_counter; pSessionDesc->cumulativeConsumedBytes += pResults->consumed; /* Handle Checksum for end to end data integrity. */ if ((CPA_TRUE != isDcDp) && (CPA_TRUE == pDcCapabilities->crcIntegrity.supported) && (CPA_TRUE == pCookie->integrityCrcCheck && NULL != pOpData) && (NULL != pOpData->pCrcData)) { if (hw_gen < DC_CAPS_GEN4_HW) { dcHandleIntegrityChecksumsLegacy(pCookie, pOpData->pCrcData, pResults, pSessionDesc->huffType, pSessionDesc->checksumType, pSessionDesc->sessState, pSessionDesc->sessDirection, CPA_FALSE); } else { if (CPA_DC_LZ4_MULTIBLOCK_WITHOUT_HEADER != pResults->status) { dcHandleIntegrityChecksums(pCookie, pOpData->pCrcData, pResults, pSessionDesc->huffType, pSessionDesc->compType, pSessionDesc->checksumType, CPA_FALSE, ICP_QAT_FW_NO_CHAINING_20); } } if ((CPA_DC_CRC_INTEG_ERR == pResults->status) || (CPA_DC_LZ4_MULTIBLOCK_WITHOUT_HEADER == pResults->status)) { cmpPass = CPA_FALSE; } #ifdef TREAT_CRC_FROM_COMP_ENGINE_AS_ERROR if ((DC_COMPRESSION_REQUEST == compDecomp) && (CPA_DC_OK == pResults->status)) { /* Check if CRC is computed from DCPR accelerator */ if (!ICP_QAT_FW_COMN_HDR_E2E_DCPR_FLAG_GET(hdrFlags)) { pResults->status = CPA_DC_E2E_NO_DECOMPRESSION; } } #endif } else { if (CPA_DC_CRC32 == pSessionDesc->checksumType) { pResults->checksum = pCompRespMsg->comp_resp_pars.crc.legacy.curr_crc32; } else if ((CPA_DC_ADLER32 == pSessionDesc->checksumType) || (CPA_DC_XXHASH32 == pSessionDesc->checksumType)) { pResults->checksum = pCompRespMsg->comp_resp_pars.crc.legacy.curr_adler_32; } } } if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) { if ((DC_COMPRESSION_REQUEST == compDecomp) && (CPA_TRUE == uncompressedDataSupported)) { /* Check if returned data is a stored block * in compression direction */ if (pResults) pResults->dataUncompressed = ICP_QAT_FW_COMN_HDR_ST_BLK_FLAG_GET(hdrFlags); /* Check for reset of xxhash state */ if (CPA_DC_OVERFLOW != (Cpa8S)cmpErr) dcResetXxhashState(pSessionDesc, pCookie); } if (pResults && (DC_DECOMPRESSION_REQUEST == compDecomp)) { pResults->endOfLastBlock = (ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET == ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(opStatus)); } /* Check if a CNV recovery happened and * increase stats counter */ if ((DC_COMPRESSION_REQUEST == compDecomp) && ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdrFlags) && ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdrFlags)) { COMPRESSION_STAT_INC(numCompCnvErrorsRecovered, pService); } if (CPA_TRUE == isDcDp && NULL != pResponse) { pResponse->responseStatus = CPA_STATUS_SUCCESS; } else { if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompCompleted, pService); } else { COMPRESSION_STAT_INC(numDecompCompleted, pService); } } } if ((CPA_FALSE == cmpPass) || (CPA_FALSE == xlatPass)) { if (pResults) { #ifdef ICP_DC_RETURN_COUNTERS_ON_ERROR /* Extract the response from the firmware */ if (CPA_FALSE == pDcCapabilities->overflowResubmitUnsupported) { pResults->consumed = pCompRespMsg->comp_resp_pars.input_byte_counter; pResults->produced = pCompRespMsg->comp_resp_pars.output_byte_counter; } else { pResults->consumed = 0; pResults->produced = 0; } if (CPA_DC_STATEFUL == pSessionDesc->sessState) { pSessionDesc->cumulativeConsumedBytes += pResults->consumed; } else { /* In the stateless case all requests have both SOP and EOP set */ pSessionDesc->cumulativeConsumedBytes = pResults->consumed; } #else pResults->consumed = 0; pResults->produced = 0; #endif if (CPA_DC_OVERFLOW == pResults->status && CPA_DC_STATELESS == pSessionDesc->sessState) { /* This error message will be returned by Data Plane API in both * compression and decompression direction. With Traditional API * this error message will be returned only in stateless * decompression direction */ LAC_LOG_ERROR( "Unrecoverable error: stateless overflow. You may " "need to increase the size of your destination buffer"); } } if (CPA_TRUE == isDcDp && NULL != pResponse) { pResponse->responseStatus = CPA_STATUS_FAIL; } else { if (pResults == NULL || (CPA_DC_OK != pResults->status && CPA_DC_INCOMPLETE_FILE_ERR != pResults->status)) { status = CPA_STATUS_FAIL; } if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompCompletedErrors, pService); } else { COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } } } if (CPA_TRUE == isDcDp) { if (pResponse) { /* Decrement number of stateless pending callbacks for session */ pSessionDesc->pendingDpStatelessCbCount--; (pService->pDcDpCb)(pResponse); } } else { /* Decrement number of pending callbacks for session */ if (CPA_DC_STATELESS == pSessionDesc->sessState) { osalAtomicDec(&(pCookie->pSessionDesc->pendingStatelessCbCount)); } else if (0 != osalAtomicGet(&pCookie->pSessionDesc->pendingStatefulCbCount)) { osalAtomicDec(&(pCookie->pSessionDesc->pendingStatefulCbCount)); } /* Free the memory pool */ Lac_MemPoolEntryFree(pCookie); pCookie = NULL; if (NULL != pCbFunc) { pCbFunc(callbackTag, status); } } } CpaStatus dcCompression_SwRespMsgCallback(lac_memblk_bucket_t *pBucket) { lac_mem_blk_t **pBucketBlk = NULL; lac_mem_blk_t *pCurrentBlk = NULL; Cpa32U numBucketBlks = 0; Cpa32U numSwResp = 0; Cpa32U startIndex = 0; Cpa32U iter = 0; dc_compression_cookie_t *pCookie = NULL; CpaDcCallbackFn pCbFunc = NULL; CpaStatus status = CPA_STATUS_RETRY; #ifndef DISABLE_STATS sal_compression_service_t *pService = NULL; #endif LAC_ASSERT_NOT_NULL(pBucket); pBucketBlk = pBucket->mem_blk; LAC_ASSERT_NOT_NULL(pBucketBlk); startIndex = pBucket->startIndex; numBucketBlks = pBucket->numBucketBlks; numSwResp = pBucket->numBlksInRing; for (iter = 0; iter < numSwResp; iter++) { pCurrentBlk = pBucketBlk[(startIndex + iter) % numBucketBlks]; pCookie = (dc_compression_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + sizeof(lac_mem_blk_t)); LAC_LOG_DEBUG1("DC dummy response index = %llx", pCurrentBlk->opaque); #ifndef DISABLE_STATS pService = (sal_compression_service_t *)(pCookie->dcInstance); /* extract fields from request data struct */ if (DC_COMPRESSION_REQUEST == pCookie->compDecomp) { COMPRESSION_STAT_INC(numCompCompletedErrors, pService); } else { COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } #endif if (CPA_DC_STATELESS == pCookie->pSessionDesc->sessState) { osalAtomicDec(&(pCookie->pSessionDesc->pendingStatelessCbCount)); } else { osalAtomicDec(&(pCookie->pSessionDesc->pendingStatefulCbCount)); } pCbFunc = pCookie->pSessionDesc->pCompressionCb; pCbFunc(pCookie->callbackTag, CPA_STATUS_FAIL); Lac_MemPoolEntryFree(pCookie); } if (0 != numSwResp) { status = CPA_STATUS_SUCCESS; } return status; } #ifdef ICP_PARAM_CHECK /** ***************************************************************************** * @ingroup Dc_DataCompression * Check that all the parameters in the pOpData structure are valid * * @description * Check that all the parameters in the pOpData structure are valid * * @param[in] pService Pointer to the compression service * @param[in] pOpData Pointer to request information structure * holding parameters for cpaDcCompress2 and * CpaDcDecompressData2 * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ #ifndef KERNEL_SPACE CpaStatus dcCheckOpData(sal_compression_service_t *pService, CpaDcOpData *pOpData, CpaDcSessionDir sessDirection) { CpaDcSkipMode skipMode = 0; dc_capabilities_t *pDcCapabilities = NULL; if ((pOpData->flushFlag < CPA_DC_FLUSH_NONE) || (pOpData->flushFlag > CPA_DC_FLUSH_FULL)) { LAC_INVALID_PARAM_LOG("Invalid flushFlag value"); return CPA_STATUS_INVALID_PARAM; } skipMode = pOpData->inputSkipData.skipMode; if ((skipMode < CPA_DC_SKIP_DISABLED) || (skipMode > CPA_DC_SKIP_STRIDE)) { LAC_INVALID_PARAM_LOG("Invalid input skip mode value"); return CPA_STATUS_INVALID_PARAM; } skipMode = pOpData->outputSkipData.skipMode; if ((skipMode < CPA_DC_SKIP_DISABLED) || (skipMode > CPA_DC_SKIP_STRIDE)) { LAC_INVALID_PARAM_LOG("Invalid output skip mode value"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->integrityCrcCheck == CPA_FALSE && pOpData->verifyHwIntegrityCrcs == CPA_TRUE) { LAC_INVALID_PARAM_LOG("integrityCrcCheck must be set to true" "in order to enable verifyHwIntegrityCrcs"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->integrityCrcCheck != CPA_TRUE && pOpData->integrityCrcCheck != CPA_FALSE) { LAC_INVALID_PARAM_LOG("Invalid integrityCrcCheck value"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->verifyHwIntegrityCrcs != CPA_TRUE && pOpData->verifyHwIntegrityCrcs != CPA_FALSE) { LAC_INVALID_PARAM_LOG("Invalid verifyHwIntegrityCrcs value"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->compressAndVerify != CPA_TRUE && pOpData->compressAndVerify != CPA_FALSE) { LAC_INVALID_PARAM_LOG("Invalid cnv decompress check value"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_COMPRESS == sessDirection) { if (pOpData->compressAndVerify != CPA_TRUE && pOpData->compressAndVerify != CPA_FALSE) { LAC_INVALID_PARAM_LOG("Invalid compressAndVerify value"); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE != pOpData->compressAndVerifyAndRecover && CPA_TRUE != pOpData->compressAndVerifyAndRecover) { LAC_INVALID_PARAM_LOG("Invalid compressAndVerifyAndRecover value"); return CPA_STATUS_INVALID_PARAM; } if ((CPA_FALSE == pOpData->compressAndVerify) && (CPA_TRUE == pOpData->compressAndVerifyAndRecover)) { LAC_INVALID_PARAM_LOG( "Invalid combination of compressAndVerify and " "compressAndVerifyAndRecover value"); return CPA_STATUS_INVALID_PARAM; } } /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; if ((CPA_TRUE == pOpData->integrityCrcCheck) && (CPA_FALSE == pDcCapabilities->crcIntegrity.supported)) { LAC_INVALID_PARAM_LOG("Integrity CRC check is not " "supported on this device"); return CPA_STATUS_INVALID_PARAM; } if (CPA_TRUE == pOpData->integrityCrcCheck && NULL == pOpData->pCrcData) { LAC_INVALID_PARAM_LOG("Integrity CRC data structure is " "not initialized in CpaDcOpData"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif /** ***************************************************************************** * @ingroup Dc_DataCompression * Check the compression source buffer for Batch and Pack API. * * @description * Check that all the parameters used for a Batch and Pack compression * request are valid. This function essentially checks the source buffer * parameters and results structure parameters. * * @param[in] pSessionHandle Session handle * @param[in] pSrcBuff Pointer to data buffer for compression * @param[in] pDestBuff Pointer to buffer space allocated for * output data * @param[in] pResults Pointer to results structure * @param[in] flushFlag Indicates the type of flush to be * performed * @param[in] srcBuffSize Size of the source buffer * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ CpaStatus dcCheckSourceData(sal_compression_service_t *pService, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, Cpa64U srcBuffSize, CpaDcSkipData *skipData) { dc_session_desc_t *pSessionDesc = NULL; CpaStatus status = CPA_STATUS_SUCCESS; dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; CpaBoolean zeroLengthReqSupported = CPA_FALSE; LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pSrcBuff); LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(pResults); pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); if (NULL == pSessionDesc) { LAC_INVALID_PARAM_LOG("Session handle is not as expected"); return CPA_STATUS_INVALID_PARAM; } if ((flushFlag < CPA_DC_FLUSH_NONE) || (flushFlag > CPA_DC_FLUSH_FULL)) { LAC_INVALID_PARAM_LOG("Invalid flushFlag value"); return CPA_STATUS_INVALID_PARAM; } if (pSrcBuff == pDestBuff) { LAC_INVALID_PARAM_LOG("In place operation is not supported"); return CPA_STATUS_INVALID_PARAM; } /* Compressing zero byte is only supported for limited use cases when * using stateless sessions. */ if ((CPA_DC_STATELESS == pSessionDesc->sessState) && (0 == srcBuffSize) && (NULL == skipData)) { status = dcGetZeroLengthReqCapabilityStatus( pDcCapabilities, pSessionDesc->compType, &zeroLengthReqSupported); if (CPA_STATUS_SUCCESS != status) { return status; } if (CPA_TRUE != zeroLengthReqSupported) { LAC_INVALID_PARAM_LOG("The source buffer size needs to be greater " "than zero byte for stateless sessions"); return CPA_STATUS_INVALID_PARAM; } } if (srcBuffSize > DC_BUFFER_MAX_SIZE) { LAC_INVALID_PARAM_LOG("The source buffer size needs to be less than or " "equal to 2^32-1 bytes"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Check the compression or decompression function parameters. * * @description * Check that all the parameters used for a Batch and Pack compression * request are valid. This function essentially checks the destination * buffer parameters and intermediate buffer parameters. * * @param[in] pService Pointer to the compression service * @param[in] pSessionHandle Session handle * @param[in] pDestBuff Pointer to buffer space allocated for * output data * @param[in] compDecomp Direction of the operation * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ CpaStatus dcCheckDestinationData(sal_compression_service_t *pService, CpaDcSessionHandle pSessionHandle, CpaBufferList *pDestBuff, dc_request_dir_t compDecomp) { dc_session_desc_t *pSessionDesc = NULL; Cpa64U destBuffSize = 0; dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; Cpa16U numInterBuffs = pDcCapabilities->numInterBuffs; LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pDestBuff); pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); if (NULL == pSessionDesc) { LAC_INVALID_PARAM_LOG("Session handle is not as expected"); return CPA_STATUS_INVALID_PARAM; } if (LacBuffDesc_BufferListVerify( pDestBuff, &destBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid destination buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } if (destBuffSize > DC_BUFFER_MAX_SIZE) { LAC_INVALID_PARAM_LOG("The destination buffer size needs to be less " "than or equal to 2^32-1 bytes"); return CPA_STATUS_INVALID_PARAM; } if (CPA_TRUE == pSessionDesc->isDcDp) { LAC_INVALID_PARAM_LOG("The session type should not be data plane"); return CPA_STATUS_INVALID_PARAM; } if (DC_COMPRESSION_REQUEST == compDecomp) { #ifndef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { /* Check if intermediate buffers are supported */ if ((numInterBuffs > 0) && ((0 == pService->pInterBuffPtrsArrayPhyAddr) || (NULL == pService->pInterBuffPtrsArray))) { LAC_LOG_ERROR( "No intermediate buffer defined for this instance " "- see cpaDcStartInstance"); return CPA_STATUS_INVALID_PARAM; } /* Ensure that the destination buffer size is greater or equal * to devices min output buff size for dynamic compression */ if (destBuffSize < pDcCapabilities->deviceData.minOutputBuffSizeDynamic) { LAC_INVALID_PARAM_LOG1( "Destination buffer size should be " "greater or equal to %d bytes", pDcCapabilities->deviceData.minOutputBuffSizeDynamic); return CPA_STATUS_INVALID_PARAM; } } else #else if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions " "are not supported"); return CPA_STATUS_INVALID_PARAM; } else #endif { /* Ensure that the destination buffer size is greater or equal * to devices minimal output buffer size for static compression */ if (destBuffSize < pDcCapabilities->deviceData.minOutputBuffSize) { LAC_INVALID_PARAM_LOG1( "Destination buffer size should be " "greater or equal to %d bytes", pDcCapabilities->deviceData.minOutputBuffSize); return CPA_STATUS_INVALID_PARAM; } } } else { /* Ensure that the destination buffer size is greater than * 0 bytes */ if (destBuffSize < DC_DEST_BUFFER_DEC_MIN_SIZE) { LAC_INVALID_PARAM_LOG("Destination buffer size should be " "greater than 0 bytes"); return CPA_STATUS_INVALID_PARAM; } } return CPA_STATUS_SUCCESS; } #endif /** ***************************************************************************** * @ingroup Dc_DataCompression * Populate the compression request parameters * * @description * This function will populate the compression request parameters * * @param[out] pCompReqParams Pointer to the compression request parameters * @param[in] pCookie Pointer to the compression cookie * *****************************************************************************/ void dcCompRequestParamsPopulate(icp_qat_fw_comp_req_params_t *pCompReqParams, dc_compression_cookie_t *pCookie) { LAC_ENSURE_NOT_NULL(pCompReqParams); LAC_ENSURE_NOT_NULL(pCookie); pCompReqParams->comp_len = pCookie->srcTotalDataLenInBytes; pCompReqParams->out_buffer_sz = pCookie->dstTotalDataLenInBytes; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Create the requests for compression or decompression * * @description * Create the requests for compression or decompression. This function * will update the cookie will all required information. * * @param{out] pCookie Pointer to the compression cookie * @param[in] pService Pointer to the compression service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in pSessionHandle Session handle * @param[in] pSrcBuff Pointer to data buffer for compression * @param[in] pDestBuff Pointer to buffer space for data after * compression * @param[in] pResults Pointer to results structure * @param[in] flushFlag Indicates the type of flush to be * performed * @param[in] pOpData Pointer to request information structure * holding parameters for cpaDcCompress2 * and CpaDcDecompressData2 * @param[in] callbackTag Pointer to the callback tag * @param[in] compDecomp Direction of the operation * @param[in] compressAndVerify Compress and Verify * @param[in] pDictionary Pointer to a CpaFlatBuffer containing * the compression dictionary * @param[in] dictionarySize The size of the compression dictionary * in bytes * @param[in] dictionaryType The type of the compression dictionary * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ CpaStatus dcCreateRequest(dc_compression_cookie_t *pCookie, sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, CpaDcOpData *pOpData, void *callbackTag, dc_request_dir_t compDecomp, dc_cnv_mode_t cnvMode, CpaDcDictionaryData *pDictionaryData) { icp_qat_fw_comp_req_t *pMsg = NULL; icp_qat_fw_comp_req_params_t *pCompReqParams = NULL; Cpa64U srcAddrPhys = 0, dstAddrPhys = 0; Cpa64U srcTotalDataLenInBytes = 0, dstTotalDataLenInBytes = 0; Cpa32U rpCmdFlags = 0; Cpa8U sop = ICP_QAT_FW_COMP_SOP; Cpa8U eop = ICP_QAT_FW_COMP_EOP; Cpa8U crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; Cpa8U bFinal = ICP_QAT_FW_COMP_NOT_BFINAL; Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; Cpa8U cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; Cpa8U cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX; Cpa8U xxhashAccMode = ICP_QAT_FW_COMP_NO_XXHASH_ACC; CpaStatus status = CPA_STATUS_SUCCESS; CpaDcFlush flush = CPA_DC_FLUSH_NONE; Cpa32U initial_adler = DC_DEFAULT_ADLER32; Cpa32U initial_crc32 = DC_DEFAULT_CRC; icp_qat_fw_comp_req_t *pReqCache = NULL; dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; CpaBoolean errorInjectionSupported = CPA_FALSE; Cpa32U errorInjectionCode = ICP_QAT_FW_COMP_CNV_ERROR_NONE; Cpa16U numInterBuffs = 0; CpaBoolean statefulLiteUnsupported = CPA_FALSE; Cpa32U val32 = 0; icp_qat_fw_comp_dict_type_t fwDictType = ICP_QAT_FW_COMP_DICT_TYPE_NONE; icp_qat_hw_compression_config_t *pCompConfig = NULL; Cpa64U dictionaryLenInBytes = 0; CpaBoolean zeroLengthRequestsSupported = CPA_FALSE; if (NULL == pDictionaryData) { status = dcGetZeroLengthReqCapabilityStatus(pDcCapabilities, pSessionDesc->compType, &zeroLengthRequestsSupported); if (CPA_STATUS_SUCCESS != status) { return status; } /* Write the buffer descriptors */ if (zeroLengthRequestsSupported) { status = LacBuffDesc_BufferListDescWriteAllow0BuffGetSize( pSrcBuff, &srcAddrPhys, CPA_FALSE, &srcTotalDataLenInBytes, &(pService->generic_service_info)); } else { status = LacBuffDesc_BufferListDescWriteAndGetSize( pSrcBuff, &srcAddrPhys, CPA_FALSE, &srcTotalDataLenInBytes, &(pService->generic_service_info)); } } else { /* Write the buffer list descriptors. Zero byte length dictionaries * are not acceptable with dictionary compression. */ status = LacBuffDesc_BufferListDescWriteWithDictAndGetSize( pSrcBuff, pDictionaryData->pDictionaryBuff, &srcAddrPhys, CPA_FALSE, &srcTotalDataLenInBytes, &(pService->generic_service_info)); LacBuffDesc_BufferListTotalSizeGet(pDictionaryData->pDictionaryBuff, &dictionaryLenInBytes); } if (status != CPA_STATUS_SUCCESS) { return status; } status = LacBuffDesc_BufferListDescWriteAndGetSize( pDestBuff, &dstAddrPhys, CPA_FALSE, &dstTotalDataLenInBytes, &(pService->generic_service_info)); if (status != CPA_STATUS_SUCCESS) { return status; } errorInjectionSupported = pDcCapabilities->cnv.errorInjection; numInterBuffs = pDcCapabilities->numInterBuffs; statefulLiteUnsupported = pDcCapabilities->statefulLiteUnsupported; /* Populate the compression cookie */ pCookie->dcInstance = pService; pCookie->pSessionHandle = pSessionHandle; pCookie->callbackTag = callbackTag; pCookie->pSessionDesc = pSessionDesc; pCookie->pDcOpData = pOpData; pCookie->pResults = pResults; pCookie->compDecomp = compDecomp; #ifdef ICP_DC_ERROR_SIMULATION /* Inject DC error in cookie if simulation is active */ if (dcErrorSimEnabled()) { pCookie->dcErrorToSimulate = dcGetErrors(); } else { pCookie->dcErrorToSimulate = 0; } #endif pCookie->pUserSrcBuff = NULL; pCookie->pUserDestBuff = NULL; pCookie->integrityCrcCheck = CPA_FALSE; pCookie->verifyHwIntegrityCrcs = CPA_FALSE; /* Extract flush flag from either the opData or from the * parameter. Opdata have been introduced with APIs * cpaDcCompressData2 and cpaDcDecompressData2 */ if (NULL != pOpData) { flush = pOpData->flushFlag; #ifndef KERNEL_SPACE pCookie->integrityCrcCheck = pOpData->integrityCrcCheck; pCookie->verifyHwIntegrityCrcs = pOpData->verifyHwIntegrityCrcs; #endif } else { flush = flushFlag; } pCookie->flushFlag = flush; /* The firmware expects the length in bytes for source and destination to be * Cpa32U parameters. However the total data length could be bigger as * allocated by the user. We ensure that this is not the case in * dcCheckSourceData and cast the values to Cpa32U here */ if (!pCookie->dcChain.isDcChaining) { pCookie->srcTotalDataLenInBytes = (Cpa32U)srcTotalDataLenInBytes; } else if (pCookie->dcChain.isDcChaining && !pCookie->srcTotalDataLenInBytes) { /* Chaining is not supported with zero length request */ pCookie->srcTotalDataLenInBytes = (Cpa32U)srcTotalDataLenInBytes; } #ifndef ICP_DC_DYN_NOT_SUPPORTED if ((numInterBuffs > 0) && (DC_COMPRESSION_REQUEST == compDecomp) && (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) { if (pService->minInterBuffSizeInBytes < (Cpa32U)dstTotalDataLenInBytes) { pCookie->dstTotalDataLenInBytes = (Cpa32U)(pService->minInterBuffSizeInBytes); } else { pCookie->dstTotalDataLenInBytes = (Cpa32U)dstTotalDataLenInBytes; } } else #endif { pCookie->dstTotalDataLenInBytes = (Cpa32U)dstTotalDataLenInBytes; } /* Device can not decompress an odd byte decompression request * if bFinal is not set */ if (CPA_TRUE != pDcCapabilities->deviceData.oddByteDecompNobFinal) { if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && (CPA_DC_FLUSH_FINAL != flushFlag) && (DC_DECOMPRESSION_REQUEST == compDecomp) && (pCookie->srcTotalDataLenInBytes & 0x1)) { pCookie->srcTotalDataLenInBytes--; } } /* Device can not decompress odd byte interim requests */ if (CPA_TRUE != pDcCapabilities->deviceData.oddByteDecompInterim) { if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && (CPA_DC_FLUSH_FINAL != flushFlag) && (CPA_DC_FLUSH_FULL != flushFlag) && (DC_DECOMPRESSION_REQUEST == compDecomp) && (pCookie->srcTotalDataLenInBytes & 0x1)) { pCookie->srcTotalDataLenInBytes--; } } pMsg = (icp_qat_fw_comp_req_t *)&pCookie->request; if (DC_COMPRESSION_REQUEST == compDecomp) { pReqCache = &(pSessionDesc->reqCacheComp); } else { pReqCache = &(pSessionDesc->reqCacheDecomp); } /* Fills the msg from the template cached in the session descriptor */ if (CPA_DC_STATELESS == pSessionDesc->sessState && DC_COMPRESSION_REQUEST == compDecomp) { LAC_SPINLOCK(&(pSessionDesc->updateLock)); osalMemCopy((void *)pMsg, (void *)(pReqCache), LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES); LAC_SPINUNLOCK(&(pSessionDesc->updateLock)); } else { osalMemCopy((void *)pMsg, (void *)(pReqCache), LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES); } if ((CPA_DC_STATELESS == pSessionDesc->sessState) && (DC_REQUEST_SUBSEQUENT == pSessionDesc->requestType) && (CPA_TRUE != statefulLiteUnsupported)) { switch (pSessionDesc->checksumType) { case CPA_DC_ADLER32: initial_adler = pResults->checksum; break; case CPA_DC_CRC32: initial_crc32 = pResults->checksum; break; default: break; /* XXHASH32 uses a different implementation and does not need initialising here. */ } } #ifndef KERNEL_SPACE /* Backup source and destination buffer addresses, * CRC calculations both for CNV and translator overflow * will be performed on them in the callback function. */ pCookie->pUserSrcBuff = pSrcBuff; pCookie->pUserDestBuff = pDestBuff; /* * Due to implementation of CNV support and need for backwards compatibility * certain fields in the request and response structs had been * changed, moved or placed in unions * cnvMode flag signifies fields to be selected from req/res * * Doing extended crc checks makes sense only when we want to do the actual * CNV */ if ((CPA_TRUE == pDcCapabilities->crcIntegrity.supported) && (CPA_TRUE == pCookie->integrityCrcCheck)) { /* Get physical address of E2E CRC buffer */ pMsg->comp_pars.crc.crc_data_addr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, &pCookie->dataIntegrityCrcs); if (!pMsg->comp_pars.crc.crc_data_addr) { LAC_LOG_ERROR("Unable to get the physical address of " "Data Integrity buffer.\n"); return CPA_STATUS_FAIL; } /* XXHASH32 uses a different initialisation mechanism */ pCookie->dataIntegrityCrcs.crc32 = initial_crc32; pCookie->dataIntegrityCrcs.adler32 = initial_adler; pCookie->dataIntegrityCrcs.iCrc64Cpr = pSessionDesc->crcConfig.crcParam.iCrc64Cpr; pCookie->dataIntegrityCrcs.oCrc64Cpr = pSessionDesc->crcConfig.crcParam.oCrc64Cpr; pCookie->dataIntegrityCrcs.reflectIn = pSessionDesc->crcConfig.crcParam.reflectIn; pCookie->dataIntegrityCrcs.reflectOut = pSessionDesc->crcConfig.crcParam.reflectOut; pCookie->dataIntegrityCrcs.oCrc64Xlt = pSessionDesc->crcConfig.crcParam.oCrc64Xlt; pCookie->dataIntegrityCrcs.crc64Poly = pSessionDesc->crcConfig.crcParam.crc64Poly; pCookie->dataIntegrityCrcs.xor64Out = pSessionDesc->crcConfig.crcParam.xor64Out; crcMode = ICP_QAT_FW_COMP_CRC_MODE_E2E; } else { /* Legacy request structure */ /* XXHASH32 uses a different initialisation mechanism */ pMsg->comp_pars.crc.legacy.initial_crc32 = initial_crc32; pMsg->comp_pars.crc.legacy.initial_adler = initial_adler; crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; } #endif /* Populate the cmdFlags */ if (CPA_TRUE == pDcCapabilities->overflowResubmitUnsupported && CPA_DC_FLUSH_FINAL == flush) { /* Leave default values for sop and eop flags */ bFinal = ICP_QAT_FW_COMP_BFINAL; /* Reinitialise the cumulative amount of consumed bytes */ pSessionDesc->cumulativeConsumedBytes = 0; } else { if (CPA_DC_STATEFUL == pSessionDesc->sessState) { pSessionDesc->previousRequestType = pSessionDesc->requestType; if (DC_REQUEST_FIRST == pSessionDesc->requestType) { /* Update the request type for following requests */ pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT; /* Reinitialise the cumulative amount of consumed bytes */ pSessionDesc->cumulativeConsumedBytes = 0; if (DC_COMPRESSION_REQUEST == compDecomp) { pSessionDesc->isSopForCompressionProcessed = CPA_TRUE; } else if (DC_DECOMPRESSION_REQUEST == compDecomp) { pSessionDesc->isSopForDecompressionProcessed = CPA_TRUE; } } else { if (DC_COMPRESSION_REQUEST == compDecomp) { if (CPA_TRUE == pSessionDesc->isSopForCompressionProcessed) { sop = ICP_QAT_FW_COMP_NOT_SOP; } else { pSessionDesc->isSopForCompressionProcessed = CPA_TRUE; } } else if (DC_DECOMPRESSION_REQUEST == compDecomp) { if (CPA_TRUE == pSessionDesc->isSopForDecompressionProcessed) { sop = ICP_QAT_FW_COMP_NOT_SOP; } else { pSessionDesc->isSopForDecompressionProcessed = CPA_TRUE; } } } if ((CPA_DC_FLUSH_FINAL == flush) || (CPA_DC_FLUSH_FULL == flush)) { /* Update the request type for following requests */ pSessionDesc->requestType = DC_REQUEST_FIRST; } else { eop = ICP_QAT_FW_COMP_NOT_EOP; } } else { if (DC_REQUEST_FIRST == pSessionDesc->requestType) { /* Reinitialise the cumulative amount of consumed bytes */ pSessionDesc->cumulativeConsumedBytes = 0; } } if (CPA_DC_FLUSH_FINAL == flush) { bFinal = ICP_QAT_FW_COMP_BFINAL; } } pCompReqParams = &(pMsg->comp_pars); /* Comp requests param populate * (LW 14 - 15)*/ dcCompRequestParamsPopulate(pCompReqParams, pCookie); switch (cnvMode) { case DC_CNVNR: cnvRecovery = ICP_QAT_FW_COMP_CNV_RECOVERY; /* Fall through is intended here, because for CNVNR * cnvDecompReq also needs to be set */ case DC_CNV: cnvDecompReq = ICP_QAT_FW_COMP_CNV; if (CPA_TRUE == errorInjectionSupported) { cnvErrorInjection = pSessionDesc->cnvErrorInjection; } break; case DC_NO_CNV: cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; break; } /* Extract accumulated xxhash flag from sessionDesc */ if ((CPA_TRUE == pDcCapabilities->lz4.supported) && (CPA_TRUE == pDcCapabilities->lz4.accumulateXXHash)) { xxhashAccMode = pSessionDesc->accumulateXXHash; } rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( sop, eop, bFinal, cnvDecompReq, cnvRecovery, cnvErrorInjection, crcMode, xxhashAccMode, errorInjectionCode, ICP_QAT_FW_COMP_NO_APPEND_CRC, ICP_QAT_FW_COMP_NO_DROP_DATA, ICP_QAT_FW_COMP_NO_PARTIAL_DECOMPRESS); ICP_QAT_FW_COMP_LZ4_OUTPUT_CRC_MODE_SET(rpCmdFlags, pSessionDesc->lz4OutputFormat); pMsg->comp_pars.req_par_flags = rpCmdFlags; if (pDictionaryData) { /* For compression direction dictionary requests set the replay * mode */ if (DC_COMPRESSION_REQUEST == compDecomp) { pCompConfig = (icp_qat_hw_compression_config_t *)(pMsg->cd_pars.sl .comp_slice_cfg_word); QAT_FIELD_SET(val32, ICP_QAT_HW_COMP_20_SOM_CONTROL_REPLAY_MODE, ICP_QAT_HW_COMP_20_CONFIG_CSR_SOM_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SOM_CONTROL_MASK); pCompConfig->upper_val |= BYTE_SWAP_32(val32); } /* LW 19 Populate Dictionary Parameters */ switch (pDictionaryData->dictionaryType) { case CPA_DC_UNCOMPRESSED_DICT: fwDictType = ICP_QAT_FW_COMP_DICT_TYPE_UNCOMPRESSED; break; case CPA_DC_COMPRESSED_DICT: default: break; } pMsg->comp_pars.dictionary_params = ICP_QAT_FW_COMP_DICTIONARY_PARAMS_BUILD(fwDictType, dictionaryLenInBytes); } /* Populates the QAT common request middle part of the message * (LW 6 to 11) */ SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pMsg, pCookie, DC_DEFAULT_QAT_PTR_TYPE, srcAddrPhys, dstAddrPhys, 0, 0); return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Send a compression request to QAT * * @description * Send the requests for compression or decompression to QAT * * @param{in] pCookie Pointer to the compression cookie * @param[in] pService Pointer to the compression service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in] compDecomp Direction of the operation * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ STATIC CpaStatus dcSendRequest(dc_compression_cookie_t *pCookie, sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc, dc_request_dir_t compDecomp) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa64U seq_num = ICP_ADF_INVALID_SEND_SEQ; icp_comms_trans_handle trans_handle = NULL; if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = pService->trans_handle_compression_tx; } else { trans_handle = pService->trans_handle_decompression_tx; } /* Send to QAT */ status = SalQatMsg_transPutMsg(trans_handle, (void *)&(pCookie->request), LAC_QAT_DC_REQ_SZ_LW, LAC_LOG_MSG_DC, &seq_num); if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && (CPA_STATUS_RETRY == status)) { /* reset requestType after receiving an retry on * the stateful request */ pSessionDesc->requestType = pSessionDesc->previousRequestType; } LAC_MEM_POOL_BLK_SET_OPAQUE(pCookie, seq_num); return status; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Process the synchronous and asynchronous case for compression or * decompression * * @description * Process the synchronous and asynchronous case for compression or * decompression. This function will then create and send the request to * the firmware. * * @param[in] pService Pointer to the compression service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in] dcInstance Instance handle derived from discovery * functions * @param[in] pSessionHandle Session handle * @param[in] pSrcBuff Pointer to data buffer for compression * @param[in] pDestBuff Pointer to buffer space for data after * compression * @param[in] pResults Pointer to results structure * @param[in] flushFlag Indicates the type of flush to be * performed * @param[in] pOpData Pointer to request information structure * holding parameters for cpaDcCompress2 and * CpaDcDecompressData2 * @param[in] callbackTag Pointer to the callback tag * @param[in] compDecomp Direction of the operation * @param[in] isAsyncMode Used to know if synchronous or asynchronous * mode * @param[in] compressAndVerify Compress and Verify mode * @param[in] pDictionaryData Pointer to CpaDcDictionaryData structure * containing parameters for dictionary * compression requests. If it is not a * dictionary request then this parameter * should be passed as NULL. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed * @retval CPA_STATUS_RESOURCE Resource error * *****************************************************************************/ CpaStatus dcCompDecompData(sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc, CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, CpaDcOpData *pOpData, void *callbackTag, dc_request_dir_t compDecomp, CpaBoolean isAsyncMode, dc_cnv_mode_t cnvMode, CpaDcDictionaryData *pDictionaryData) { CpaStatus status = CPA_STATUS_SUCCESS; dc_compression_cookie_t *pCookie = NULL; if ((LacSync_GenWakeupSyncCaller == pSessionDesc->pCompressionCb) && isAsyncMode == CPA_TRUE) { lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { status = dcCompDecompData(pService, pSessionDesc, dcInstance, pSessionHandle, pSrcBuff, pDestBuff, pResults, flushFlag, pOpData, pSyncCallbackData, compDecomp, CPA_FALSE, cnvMode, pDictionaryData); } else { return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus syncStatus = CPA_STATUS_SUCCESS; syncStatus = LacSync_WaitForCallback( pSyncCallbackData, DC_SYNC_CALLBACK_TIMEOUT, &status, NULL); /* If callback doesn't come back */ if (CPA_STATUS_SUCCESS != syncStatus) { if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompCompletedErrors, pService); } else { COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } LAC_LOG_ERROR("Callback timed out"); status = syncStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /* Allocate the compression cookie * The memory is freed in callback or in sendRequest if an error occurs */ do { if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc( pService->compression_mem_pool); } else { pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc( pService->decompression_mem_pool); } if (NULL == pCookie) { LAC_LOG_ERROR("Cannot get mem pool entry for compression"); status = CPA_STATUS_RESOURCE; return status; } else if ((void *)CPA_STATUS_RETRY == pCookie) { /* Give back the control to the OS */ osalYield(); } } while ((void *)CPA_STATUS_RETRY == pCookie); if (CPA_STATUS_SUCCESS == status) { /* Initialize the isDcChaining cookie parameter */ pCookie->dcChain.isDcChaining = CPA_FALSE; status = dcCreateRequest(pCookie, pService, pSessionDesc, pSessionHandle, pSrcBuff, pDestBuff, pResults, flushFlag, pOpData, callbackTag, compDecomp, cnvMode, pDictionaryData); } if (CPA_STATUS_SUCCESS == status) { /* Increment number of pending callbacks for session */ if (CPA_DC_STATELESS == pSessionDesc->sessState) { osalAtomicInc(&(pSessionDesc->pendingStatelessCbCount)); } status = dcSendRequest(pCookie, pService, pSessionDesc, compDecomp); if (CPA_STATUS_SUCCESS == status) { if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompRequests, pService); } else { COMPRESSION_STAT_INC(numDecompRequests, pService); } } else { /* Decrement number of pending callbacks for session */ if (CPA_DC_STATELESS == pSessionDesc->sessState) { osalAtomicDec(&(pSessionDesc->pendingStatelessCbCount)); } else { osalAtomicDec(&(pSessionDesc->pendingStatefulCbCount)); } } } /* numCompRequestsErrors or numDecompRequestsErrors must be incremented * if either dcCreateRequest or dcSendRequest does not return * CPA_STATUS_SUCCESS */ if (status != CPA_STATUS_SUCCESS) { if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompRequestsErrors, pService); } else { COMPRESSION_STAT_INC(numDecompRequestsErrors, pService); } /* Free the memory pool */ if (NULL != pCookie) { Lac_MemPoolEntryFree(pCookie); pCookie = NULL; } } return status; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Handle zero length compression or decompression requests * * @description * Handle zero length compression or decompression requests. * Note: This function uses the state registers stored in the * session for reading the previous checksum. * This function should only be called for stateful requests and * is not considered threadsafe. * * @param[in] pService Pointer to the compression service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in] pResults Pointer to results structure * @param[in] flushFlag Indicates the type of flush to be * performed * @param[in] callbackTag User supplied value to help correlate * the callback with its associated request * @param[in] compDecomp Direction of the operation * * @retval CPA_TRUE Zero length SOP or MOP processed * @retval CPA_FALSE Zero length EOP * *****************************************************************************/ STATIC CpaBoolean dcZeroLengthRequests(sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc, CpaDcRqResults *pResults, CpaDcFlush flushFlag, void *callbackTag, dc_request_dir_t compDecomp) { CpaBoolean status = CPA_FALSE; CpaDcCallbackFn pCbFunc = pSessionDesc->pCompressionCb; Cpa8U *pStateAddr = NULL; Cpa8U i = 0; if (DC_REQUEST_FIRST == pSessionDesc->requestType) { /* Reinitialise the cumulative amount of consumed bytes */ pSessionDesc->cumulativeConsumedBytes = 0; /* Zero length SOP */ if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { pResults->checksum = 1; } else { pResults->checksum = 0; } status = CPA_TRUE; } else if ((CPA_DC_FLUSH_NONE == flushFlag) || (CPA_DC_FLUSH_SYNC == flushFlag)) { /* Zero length MOP */ if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { if (DC_COMPRESSION_REQUEST == compDecomp) { pStateAddr = &pSessionDesc->stateRegistersComp[DC_STATE_ADLER32_OFFSET]; } else { pStateAddr = &pSessionDesc ->stateRegistersDecomp[DC_STATE_ADLER32_OFFSET]; } } else { if (DC_COMPRESSION_REQUEST == compDecomp) { pStateAddr = &pSessionDesc->stateRegistersComp[DC_STATE_CRC32_OFFSET]; } else { pStateAddr = &pSessionDesc->stateRegistersDecomp[DC_STATE_CRC32_OFFSET]; } } pResults->checksum = 0; for (i = 0; i < DC_CHECKSUM_SIZE_IN_BYTES; i++) { pResults->checksum |= ((Cpa32U) * (pStateAddr++) << (i * DC_8_BIT_SHIFT_POS)); } status = CPA_TRUE; } if (CPA_TRUE == status) { pResults->status = CPA_DC_OK; pResults->produced = 0; pResults->consumed = 0; /* Increment statistics */ if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompRequests, pService); COMPRESSION_STAT_INC(numCompCompleted, pService); } else { COMPRESSION_STAT_INC(numDecompRequests, pService); COMPRESSION_STAT_INC(numDecompCompleted, pService); } LAC_SPINUNLOCK(&(pSessionDesc->sessionLock)); if ((NULL != pCbFunc) && (LacSync_GenWakeupSyncCaller != pCbFunc)) { pCbFunc(callbackTag, CPA_STATUS_SUCCESS); } return CPA_TRUE; } return CPA_FALSE; } #ifdef ICP_PARAM_CHECK CpaStatus dcParamCheck(const CpaInstanceHandle dcInstance, const CpaDcSessionHandle pSessionHandle, const sal_compression_service_t *pService, const CpaBufferList *pSrcBuff, const CpaBufferList *pDestBuff, const CpaDcRqResults *pResults, const dc_session_desc_t *pSessionDesc, const CpaDcFlush flushFlag, const Cpa64U srcBuffSize) { if (dcCheckSourceData((sal_compression_service_t *)pService, pSessionHandle, (CpaBufferList *)pSrcBuff, (CpaBufferList *)pDestBuff, (CpaDcRqResults *)pResults, flushFlag, srcBuffSize, NULL) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (dcCheckDestinationData((sal_compression_service_t *)pService, pSessionHandle, (CpaBufferList *)pDestBuff, DC_COMPRESSION_REQUEST) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif CpaStatus cpaDcCompressData(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, void *callbackTag) { sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; CpaInstanceHandle insHandle = NULL; Cpa64U srcBuffSize = 0; dc_cnv_mode_t cnvMode = DC_CNV; #ifdef ICP_TRACE LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%x, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pResults, flushFlag, (LAC_ARCH_UINT)callbackTag); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pSessionHandle); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); /* This check is outside the parameter checking as it is needed to manage * zero length requests */ if (LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } #ifdef ICP_PARAM_CHECK /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK if (CPA_STATUS_SUCCESS != dcParamCheck(insHandle, pSessionHandle, pService, pSrcBuff, pDestBuff, pResults, pSessionDesc, flushFlag, srcBuffSize)) { return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions " "are not supported"); return CPA_STATUS_INVALID_PARAM; } #endif if (CPA_DC_STATEFUL == pSessionDesc->sessState) { LAC_INVALID_PARAM_LOG("Invalid session state, stateful sessions " "are not supported"); return CPA_STATUS_UNSUPPORTED; } if (!(pService->dc_capabilities.cnv.supported)) { LAC_INVALID_PARAM_LOG("CompressAndVerify feature is not supported"); return CPA_STATUS_UNSUPPORTED; } if (pService->dc_capabilities.cnv.recovery) { cnvMode = DC_CNVNR; } return dcCompDecompData(pService, pSessionDesc, dcInstance, pSessionHandle, pSrcBuff, pDestBuff, pResults, flushFlag, NULL, callbackTag, DC_COMPRESSION_REQUEST, CPA_TRUE, cnvMode, NULL); } /* Note: cpaDcCompressData2 would be thread unsafe if it is using * E2E functionality */ CpaStatus cpaDcCompressData2(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag) { sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; CpaInstanceHandle insHandle = NULL; Cpa64U srcBuffSize = 0; dc_cnv_mode_t cnvMode = DC_NO_CNV; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pOpData); if (((CPA_TRUE != pOpData->compressAndVerify) && (CPA_FALSE != pOpData->compressAndVerify)) || ((CPA_FALSE != pOpData->compressAndVerifyAndRecover) && (CPA_TRUE != pOpData->compressAndVerifyAndRecover))) { return CPA_STATUS_INVALID_PARAM; } if ((CPA_FALSE == pOpData->compressAndVerify) && (CPA_TRUE == pOpData->compressAndVerifyAndRecover)) { return CPA_STATUS_INVALID_PARAM; } #endif if ((CPA_TRUE == pOpData->compressAndVerify) && (CPA_TRUE == pOpData->compressAndVerifyAndRecover) && (CPA_FALSE == pOpData->integrityCrcCheck)) { return cpaDcCompressData(dcInstance, pSessionHandle, pSrcBuff, pDestBuff, pResults, pOpData->flushFlag, callbackTag); } if (CPA_FALSE == pOpData->compressAndVerify) { LAC_INVALID_PARAM_LOG( "Data compression without verification is not allowed"); return CPA_STATUS_UNSUPPORTED; } #ifdef ICP_TRACE LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pResults, (LAC_ARCH_UINT)callbackTag); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pSessionHandle); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); /* This check is outside the parameter checking as it is needed to manage * zero length requests */ if (LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } #ifdef ICP_PARAM_CHECK /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); if (CPA_TRUE == pOpData->compressAndVerify && CPA_DC_STATEFUL == pSessionDesc->sessState) { LAC_INVALID_PARAM_LOG("Invalid session state, stateful sessions " "are not supported with CNV"); return CPA_STATUS_UNSUPPORTED; } if (!(pService->dc_capabilities.cnv.supported) && (CPA_TRUE == pOpData->compressAndVerify)) { LAC_INVALID_PARAM_LOG("CompressAndVerify feature is not supported"); return CPA_STATUS_UNSUPPORTED; } if ((CPA_DC_LZ4 == pSessionDesc->compType) && (CPA_TRUE == pOpData->integrityCrcCheck)) { if (!(pService->generic_service_info.dcExtendedFeatures & DC_LZ4_E2E_COMP_CRC_EXTENDED_CAPABILITY)) { LAC_INVALID_PARAM_LOG("FW does not support LZ4 with" " integrityCrcCheck in the compression" " direction"); return CPA_STATUS_UNSUPPORTED; } if (pSessionDesc->accumulateXXHash) { LAC_INVALID_PARAM_LOG("LZ4 with integrityCrcCheck and " "acummulateXXHash enabled is not supported"); return CPA_STATUS_UNSUPPORTED; } if (pSessionDesc->autoSelectBestHuffmanTree != CPA_DC_ASB_DISABLED) { LAC_INVALID_PARAM_LOG("LZ4 with integrityCrcCheck and ASB enabled " "is not supported"); return CPA_STATUS_UNSUPPORTED; } if (!pOpData->compressAndVerify) { LAC_INVALID_PARAM_LOG("LZ4 with integrityCrcCheck and CNV disabled " "is not supported"); return CPA_STATUS_UNSUPPORTED; } if (pOpData->compressAndVerifyAndRecover) { LAC_INVALID_PARAM_LOG( "LZ4 with integrityCrcCheck and CNVNR enabled " "is not supported"); return CPA_STATUS_UNSUPPORTED; } } #ifdef ICP_PARAM_CHECK if (CPA_STATUS_SUCCESS != dcParamCheck(insHandle, pSessionHandle, pService, pSrcBuff, pDestBuff, pResults, pSessionDesc, pOpData->flushFlag, srcBuffSize)) { return CPA_STATUS_INVALID_PARAM; } #ifndef KERNEL_SPACE if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData, pSessionDesc->sessDirection)) { return CPA_STATUS_INVALID_PARAM; } #endif #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions " "are not supported"); return CPA_STATUS_INVALID_PARAM; } #endif if (CPA_TRUE != pOpData->compressAndVerify) { if (srcBuffSize > DC_COMP_MAX_BUFF_SIZE) { LAC_LOG_ERROR("Compression payload greater than 64KB is " "unsupported, when CnV is disabled\n"); return CPA_STATUS_UNSUPPORTED; } } if (CPA_DC_STATEFUL == pSessionDesc->sessState) { /* Lock the session to check if there are in-flight stateful requests */ LAC_SPINLOCK(&(pSessionDesc->sessionLock)); /* Check if there is already one in-flight stateful request */ if (0 != osalAtomicGet(&(pSessionDesc->pendingStatefulCbCount))) { LAC_LOG_ERROR("Only one in-flight stateful request supported"); LAC_SPINUNLOCK(&(pSessionDesc->sessionLock)); return CPA_STATUS_RETRY; } if (0 == srcBuffSize) { if (CPA_TRUE == dcZeroLengthRequests(pService, pSessionDesc, pResults, pOpData->flushFlag, callbackTag, DC_COMPRESSION_REQUEST)) { return CPA_STATUS_SUCCESS; } } osalAtomicInc(&(pSessionDesc->pendingStatefulCbCount)); LAC_SPINUNLOCK(&(pSessionDesc->sessionLock)); } if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) && (pService->dc_capabilities.cnv.recovery == CPA_TRUE)) { cnvMode = DC_CNVNR; } else if (CPA_TRUE == pOpData->compressAndVerify) { cnvMode = DC_CNV; } return dcCompDecompData(pService, pSessionDesc, dcInstance, pSessionHandle, pSrcBuff, pDestBuff, pResults, pOpData->flushFlag, pOpData, callbackTag, DC_COMPRESSION_REQUEST, CPA_TRUE, cnvMode, NULL); } CpaStatus dcCheckDictData(CpaDcDictionaryData *pDictionaryData, sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc) { CpaBoolean dictCompSupported = CPA_FALSE; #ifdef ICP_PARAM_CHECK Cpa64U dictionaryBuffSize = 0; LAC_CHECK_NULL_PARAM(pDictionaryData); LAC_CHECK_NULL_PARAM(pDictionaryData->pDictionaryBuff); if (LacBuffDesc_BufferListVerify(pDictionaryData->pDictionaryBuff, &dictionaryBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid dictionary buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_UNCOMPRESSED_DICT != pDictionaryData->dictionaryType) { LAC_INVALID_PARAM_LOG("Invalid dictionary type"); return CPA_STATUS_INVALID_PARAM; } #endif /* Check for uncompressed dictionary support */ return dcGetUncompDictSupportCapabilityStatus(&pService->dc_capabilities, pSessionDesc->compType, pSessionDesc->sessDirection, &dictCompSupported); } CpaStatus cpaDcDecompressData(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, void *callbackTag) { sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; dc_capabilities_t *pDcCapabilities = NULL; CpaInstanceHandle insHandle = NULL; Cpa64U srcBuffSize = 0; CpaBoolean zerolengthRequestsSupported = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_TRACE LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%x, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pResults, flushFlag, (LAC_ARCH_UINT)callbackTag); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); LAC_CHECK_NULL_PARAM(pSessionHandle); /* Ensure this is a compression or decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); /* Retrieve capability */ pDcCapabilities = &pService->dc_capabilities; status = dcGetZeroLengthReqCapabilityStatus( pDcCapabilities, pSessionDesc->compType, &zerolengthRequestsSupported); if (CPA_STATUS_SUCCESS != status) { return status; } /* This check is outside the parameter checking as it is needed to manage * zero length requests */ if (LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } #ifdef ICP_PARAM_CHECK if (dcCheckSourceData(pService, pSessionHandle, pSrcBuff, pDestBuff, pResults, flushFlag, srcBuffSize, NULL) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (dcCheckDestinationData(pService, pSessionHandle, pDestBuff, DC_DECOMPRESSION_REQUEST) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_PARAM_CHECK if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) { LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions " "are not supported"); return CPA_STATUS_INVALID_PARAM; } #endif if (CPA_DC_STATEFUL == pSessionDesc->sessState) { /* Lock the session to check if there are in-flight stateful requests */ LAC_SPINLOCK(&(pSessionDesc->sessionLock)); /* Check if there is already one in-flight stateful request */ if (0 != osalAtomicGet(&(pSessionDesc->pendingStatefulCbCount))) { LAC_LOG_ERROR("Only one in-flight stateful request supported"); LAC_SPINUNLOCK(&(pSessionDesc->sessionLock)); return CPA_STATUS_RETRY; } if ((0 == srcBuffSize) || ((1 == srcBuffSize) && (CPA_DC_FLUSH_FINAL != flushFlag) && (CPA_DC_FLUSH_FULL != flushFlag) && (CPA_FALSE == zerolengthRequestsSupported))) { if (CPA_TRUE == dcZeroLengthRequests(pService, pSessionDesc, pResults, flushFlag, callbackTag, DC_DECOMPRESSION_REQUEST)) { return CPA_STATUS_SUCCESS; } } osalAtomicInc(&(pSessionDesc->pendingStatefulCbCount)); LAC_SPINUNLOCK(&(pSessionDesc->sessionLock)); } return dcCompDecompData(pService, pSessionDesc, dcInstance, pSessionHandle, pSrcBuff, pDestBuff, pResults, flushFlag, NULL, callbackTag, DC_DECOMPRESSION_REQUEST, CPA_TRUE, DC_NO_CNV, NULL); } CpaStatus cpaDcDecompressData2(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag) { sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; dc_capabilities_t *pDcCapabilities = NULL; CpaInstanceHandle insHandle = NULL; Cpa64U srcBuffSize = 0; CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean zerolengthRequestsSupported = CPA_FALSE; #ifdef ICP_TRACE LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pResults, (LAC_ARCH_UINT)callbackTag); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pOpData); /* Ensure this is a compression or decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif pService = (sal_compression_service_t *)insHandle; /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; status = dcGetZeroLengthReqCapabilityStatus( pDcCapabilities, pSessionDesc->compType, &zerolengthRequestsSupported); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Cannot get zero length support from capabilities"); return status; } /* This check is outside the parameter checking as it is needed to manage * zero length requests */ if (CPA_STATUS_SUCCESS != LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT)) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } #ifdef ICP_PARAM_CHECK if (CPA_STATUS_SUCCESS != dcCheckSourceData(pService, pSessionHandle, pSrcBuff, pDestBuff, pResults, CPA_DC_FLUSH_NONE, srcBuffSize, NULL)) { return CPA_STATUS_INVALID_PARAM; } if (CPA_STATUS_SUCCESS != dcCheckDestinationData(pService, pSessionHandle, pDestBuff, DC_DECOMPRESSION_REQUEST)) { return CPA_STATUS_INVALID_PARAM; } if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData, pSessionDesc->sessDirection)) { return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) { LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions " "are not supported"); return CPA_STATUS_INVALID_PARAM; } #endif if (CPA_DC_STATEFUL == pSessionDesc->sessState) { /* Lock the session to check if there are in-flight stateful requests */ LAC_SPINLOCK(&(pSessionDesc->sessionLock)); /* Check if there is already one in-flight stateful request */ if (0 != osalAtomicGet(&(pSessionDesc->pendingStatefulCbCount))) { LAC_LOG_ERROR("Only one in-flight stateful request supported"); LAC_SPINUNLOCK(&(pSessionDesc->sessionLock)); return CPA_STATUS_RETRY; } /* Gen 4 handle 0 len requests in FW */ if (CPA_FALSE == zerolengthRequestsSupported) { if ((0 == srcBuffSize) || ((1 == srcBuffSize) && (CPA_DC_FLUSH_FINAL != pOpData->flushFlag) && (CPA_DC_FLUSH_FULL != pOpData->flushFlag))) { if (CPA_TRUE == dcZeroLengthRequests(pService, pSessionDesc, pResults, pOpData->flushFlag, callbackTag, DC_DECOMPRESSION_REQUEST)) { return CPA_STATUS_SUCCESS; } } } osalAtomicInc(&(pSessionDesc->pendingStatefulCbCount)); LAC_SPINUNLOCK(&(pSessionDesc->sessionLock)); } return dcCompDecompData(pService, pSessionDesc, insHandle, pSessionHandle, pSrcBuff, pDestBuff, pResults, pOpData->flushFlag, pOpData, callbackTag, DC_DECOMPRESSION_REQUEST, CPA_TRUE, DC_NO_CNV, NULL); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_dictionary.c000066400000000000000000000313721503624047500315270ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_dictionary.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of dictionary to compress a data buffer * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "dc_datapath.h" #include "sal_service_state.h" #include "lac_buffer_desc.h" CpaStatus cpaDcCompressDataWithDict(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcDictionaryData *pDictionaryData, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag) { sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; CpaInstanceHandle insHandle = NULL; Cpa64U srcBuffSize = 0; dc_cnv_mode_t cnvMode = DC_NO_CNV; CpaStatus retStatus = CPA_STATUS_SUCCESS; #ifdef ICP_TRACE LAC_LOG8("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pDictionaryData, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pResults, (LAC_ARCH_UINT)callbackTag); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pSessionHandle); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); #endif if (CPA_FALSE == pOpData->compressAndVerify) { LAC_UNSUPPORTED_PARAM_LOG( "Data compression without verification are not allowed"); return CPA_STATUS_UNSUPPORTED; } /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); #ifdef ICP_PARAM_CHECK /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif pService = (sal_compression_service_t *)insHandle; pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); /* This check is outside the parameter checking as it is needed to manage * zero length requests. For dictionary compression there is an * expectation that a buffer list that includes metadata is supplied. */ if (LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } #ifdef ICP_PARAM_CHECK if (CPA_STATUS_SUCCESS != dcParamCheck(insHandle, pSessionHandle, pService, pSrcBuff, pDestBuff, pResults, pSessionDesc, pOpData->flushFlag, srcBuffSize)) { return CPA_STATUS_INVALID_PARAM; } #ifndef KERNEL_SPACE LAC_CHECK_NULL_PARAM(pOpData); if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData, pSessionDesc->sessDirection)) { return CPA_STATUS_INVALID_PARAM; } #endif #endif retStatus = dcCheckDictData(pDictionaryData, pService, pSessionDesc); if (CPA_STATUS_SUCCESS != retStatus) { return retStatus; } if (!(pService->dc_capabilities.cnv.supported) && (CPA_TRUE == pOpData->compressAndVerify)) { LAC_UNSUPPORTED_PARAM_LOG("CompressAndVerify feature is not supported"); return CPA_STATUS_UNSUPPORTED; } if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) && (CPA_FALSE == pService->dc_capabilities.cnv.recovery)) { LAC_UNSUPPORTED_PARAM_LOG("CompressAndVerifyAndRecover feature is not" " supported for dictionary requests"); return CPA_STATUS_UNSUPPORTED; } #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions are" "not supported"); return CPA_STATUS_INVALID_PARAM; } #endif if (CPA_TRUE == pOpData->compressAndVerify) { cnvMode = DC_CNV; } return dcCompDecompData(pService, pSessionDesc, insHandle, pSessionHandle, pSrcBuff, pDestBuff, pResults, pOpData->flushFlag, pOpData, callbackTag, DC_COMPRESSION_REQUEST, CPA_TRUE, cnvMode, pDictionaryData); } CpaStatus cpaDcDecompressDataWithDict(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcDictionaryData *pDictionaryData, CpaDcOpData *pOpData, CpaDcRqResults *pResults, void *callbackTag) { sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; CpaInstanceHandle insHandle = NULL; Cpa64U srcBuffSize = 0; CpaStatus retStatus = CPA_STATUS_SUCCESS; #ifdef ICP_TRACE LAC_LOG8("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%x, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pDictionaryData, (LAC_ARCH_UINT)pResults, pOpData->flushFlag, (LAC_ARCH_UINT)callbackTag); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); /* Ensure this is a compression or decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pOpData); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); pService = (sal_compression_service_t *)insHandle; pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); retStatus = dcCheckDictData(pDictionaryData, pService, pSessionDesc); if (CPA_STATUS_SUCCESS != retStatus) { return retStatus; } /* This check is outside the parameter checking as it is needed to manage * zero length requests */ if (CPA_STATUS_SUCCESS != LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT)) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } #ifdef ICP_PARAM_CHECK if (CPA_STATUS_SUCCESS != dcCheckSourceData(pService, pSessionHandle, pSrcBuff, pDestBuff, pResults, CPA_DC_FLUSH_NONE, srcBuffSize, NULL)) { return CPA_STATUS_INVALID_PARAM; } if (CPA_STATUS_SUCCESS != dcCheckDestinationData( pService, pSessionHandle, pDestBuff, DC_DECOMPRESSION_REQUEST)) { return CPA_STATUS_INVALID_PARAM; } if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData, pSessionDesc->sessDirection)) { return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) { LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions " "are not supported"); return CPA_STATUS_INVALID_PARAM; } #endif return dcCompDecompData(pService, pSessionDesc, insHandle, pSessionHandle, pSrcBuff, pDestBuff, pResults, pOpData->flushFlag, pOpData, callbackTag, DC_DECOMPRESSION_REQUEST, CPA_TRUE, DC_NO_CNV, pDictionaryData); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_dp.c000066400000000000000000001046131503624047500277640ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_dp.c * * @defgroup cpaDcDp Data Compression Data Plane API * * @ingroup cpaDcDp * * @description * Implementation of the Data Compression DP operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" #include "cpa_dc_dp.h" #include "icp_qat_fw_comp.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_session.h" #include "dc_datapath.h" #include "dc_capabilities.h" #include "dc_ns_datapath.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_log.h" #include "sal_types_compression.h" #include "lac_sal.h" #include "lac_sync.h" #include "sal_service_state.h" #include "sal_qat_cmn_msg.h" #include "icp_sal_poll.h" #ifdef ICP_PARAM_CHECK /** ***************************************************************************** * @ingroup cpaDcDp * Check that pOpData is valid * * @description * Check that all the parameters defined in the pOpData are valid * * @param[in] pOpData Pointer to a structure containing the * request parameters * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ STATIC CpaStatus dcDataPlaneParamCheck(const CpaDcDpOpData *pOpData) { sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; CpaDcSessionDir sessDirection; CpaDcHuffType huffType; dc_capabilities_t *pDcCapabilities = NULL; Cpa16U numInterBuffs = 0; LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pOpData->dcInstance); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( pOpData->dcInstance, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); pService = (sal_compression_service_t *)(pOpData->dcInstance); /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; numInterBuffs = pDcCapabilities->numInterBuffs; /* Allow either only session or only NS setup data. One of these objects * must be present, and the other must be NULL. */ if (!pOpData->pSessionHandle == !pOpData->pSetupData) { LAC_INVALID_PARAM_LOG("Application must select either a session or NS " "setup data"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->pSessionHandle) { pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); if (NULL == pSessionDesc) { LAC_INVALID_PARAM_LOG("Session handle not as expected"); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE == pSessionDesc->isDcDp) { LAC_INVALID_PARAM_LOG("The session type should be data plane"); return CPA_STATUS_INVALID_PARAM; } sessDirection = pSessionDesc->sessDirection; huffType = pSessionDesc->huffType; } else { /* Stateful is not supported */ if (CPA_DC_STATELESS != pOpData->pSetupData->sessState) { LAC_INVALID_PARAM_LOG("Invalid sessState value"); return CPA_STATUS_INVALID_PARAM; } if (CPA_STATUS_SUCCESS != dcCheckSessionData(pOpData->pSetupData, pOpData->dcInstance)) { return CPA_STATUS_INVALID_PARAM; } sessDirection = pOpData->pSetupData->sessDirection; huffType = pOpData->pSetupData->huffType; if (CPA_DC_DIR_DECOMPRESS < sessDirection) { LAC_INVALID_PARAM_LOG("Invalid direction of operation"); return CPA_STATUS_INVALID_PARAM; } } /* Compressing zero byte is not supported */ if ((CPA_DC_DIR_COMPRESS == sessDirection) && (0 == pOpData->bufferLenToCompress)) { LAC_INVALID_PARAM_LOG("The source buffer length to compress needs to " "be greater than zero byte"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->sessDirection > CPA_DC_DIR_DECOMPRESS) { LAC_INVALID_PARAM_LOG("Invalid direction of operation"); return CPA_STATUS_INVALID_PARAM; } if (0 == pOpData->srcBuffer) { LAC_INVALID_PARAM_LOG("Invalid srcBuffer"); return CPA_STATUS_INVALID_PARAM; } if (0 == pOpData->destBuffer) { LAC_INVALID_PARAM_LOG("Invalid destBuffer"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->srcBuffer == pOpData->destBuffer) { LAC_INVALID_PARAM_LOG("In place operation is not supported"); return CPA_STATUS_INVALID_PARAM; } if (0 == pOpData->thisPhys) { LAC_INVALID_PARAM_LOG("Invalid thisPhys"); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE == pDcCapabilities->cnv.supported) { LAC_UNSUPPORTED_PARAM_LOG("CNV Strict mode set, no CnV capability"); return CPA_STATUS_UNSUPPORTED; } if ((CPA_FALSE == pDcCapabilities->cnv.supported) && (CPA_TRUE == pOpData->compressAndVerify)) { LAC_UNSUPPORTED_PARAM_LOG( "CompressAndVerify not set, no CNV capability"); return CPA_STATUS_UNSUPPORTED; } if ((CPA_TRUE == pDcCapabilities->cnv.supported) && (CPA_TRUE == pDcCapabilities->cnv.recovery)) { if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) && (CPA_FALSE == pOpData->compressAndVerify)) { LAC_INVALID_PARAM_LOG("CnVnR option set, without setting CnV"); return CPA_STATUS_INVALID_PARAM; } } if (CPA_TRUE == pDcCapabilities->cnv.supported) { if ((CPA_FALSE == pDcCapabilities->cnv.recovery) && (CPA_TRUE == pOpData->compressAndVerifyAndRecover)) { LAC_UNSUPPORTED_PARAM_LOG("CnVnR not set, no CnVnR capability"); return CPA_STATUS_UNSUPPORTED; } } if ((CPA_DP_BUFLIST == pOpData->srcBufferLen) && (CPA_DP_BUFLIST != pOpData->destBufferLen)) { LAC_INVALID_PARAM_LOG( "The source and destination buffers need to be " "of the same type (both flat buffers or buffer lists)"); return CPA_STATUS_INVALID_PARAM; } if ((CPA_DP_BUFLIST != pOpData->srcBufferLen) && (CPA_DP_BUFLIST == pOpData->destBufferLen)) { LAC_INVALID_PARAM_LOG( "The source and destination buffers need to be " "of the same type (both flat buffers or buffer lists)"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DP_BUFLIST != pOpData->srcBufferLen) { if (pOpData->srcBufferLen < pOpData->bufferLenToCompress) { LAC_INVALID_PARAM_LOG("srcBufferLen is smaller than " "bufferLenToCompress"); return CPA_STATUS_INVALID_PARAM; } if (pOpData->destBufferLen < pOpData->bufferLenForData) { LAC_INVALID_PARAM_LOG("destBufferLen is smaller than " "bufferLenForData"); return CPA_STATUS_INVALID_PARAM; } } else { /* We are assuming that there is enough memory in the source and * destination buffer lists. We only receive physical addresses of the * buffers so we are unable to test it here */ LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->srcBuffer); LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->destBuffer); } LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->thisPhys); if ((CPA_DC_DIR_COMPRESS == sessDirection) || (CPA_DC_DIR_COMBINED == sessDirection)) { #ifndef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == huffType) { /* Check if Intermediate Buffer Array pointer is NULL */ if ((numInterBuffs > 0) && ((0 == pService->pInterBuffPtrsArrayPhyAddr) || (NULL == pService->pInterBuffPtrsArray))) { LAC_LOG_ERROR( "No intermediate buffer defined for this instance " "- see cpaDcStartInstance"); return CPA_STATUS_INVALID_PARAM; } /* Ensure that the destination buffer length for data is greater * or equal to minOutputBuffSizeDynamic */ if (pOpData->bufferLenForData < pDcCapabilities->deviceData.minOutputBuffSizeDynamic) { LAC_INVALID_PARAM_LOG1( "Destination buffer length for data " "should be greater or equal to %d", pDcCapabilities->deviceData.minOutputBuffSizeDynamic); return CPA_STATUS_INVALID_PARAM; } } else #else if (CPA_DC_HT_FULL_DYNAMIC == huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic compression " "not supported"); return CPA_STATUS_INVALID_PARAM; } else #endif { /* Ensure that the destination buffer length for data is greater * or equal to minimal output buffer size */ if (pOpData->bufferLenForData < pDcCapabilities->deviceData.minOutputBuffSize) { LAC_INVALID_PARAM_LOG1( "Destination buffer size should be " "greater or equal to %d bytes", pDcCapabilities->deviceData.minOutputBuffSize); return CPA_STATUS_INVALID_PARAM; } } } return CPA_STATUS_SUCCESS; } #endif CpaStatus cpaDcDpGetSessionSize(CpaInstanceHandle dcInstance, CpaDcSessionSetupData *pSessionData, Cpa32U *pSessionSize) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionSize); #endif status = dcGetSessionSize(dcInstance, pSessionData, pSessionSize, NULL); #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionData, (LAC_ARCH_UINT)pSessionSize, *pSessionSize); #endif return status; } CpaStatus cpaDcDpInitSession(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcSessionSetupData *pSessionData) { CpaStatus status = CPA_STATUS_SUCCESS; dc_session_desc_t *pSessionDesc = NULL; sal_compression_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSessionData); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(dcInstance); SAL_CHECK_ADDR_TRANS_SETUP(dcInstance); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( dcInstance, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif pService = (sal_compression_service_t *)dcInstance; /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(pService); #ifdef ICP_PARAM_CHECK /* Stateful is not supported */ if (CPA_DC_STATELESS != pSessionData->sessState) { LAC_INVALID_PARAM_LOG("Invalid sessState value"); return CPA_STATUS_INVALID_PARAM; } #endif status = dcInitSession(dcInstance, pSessionHandle, pSessionData, NULL, NULL); if (CPA_STATUS_SUCCESS == status) { pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); LAC_CHECK_NULL_PARAM(pSessionDesc); pSessionDesc->isDcDp = CPA_TRUE; ICP_QAT_FW_COMN_PTR_TYPE_SET( pSessionDesc->reqCacheDecomp.comn_hdr.comn_req_flags, DC_DP_QAT_PTR_TYPE); ICP_QAT_FW_COMN_PTR_TYPE_SET( pSessionDesc->reqCacheComp.comn_hdr.comn_req_flags, DC_DP_QAT_PTR_TYPE); } return status; } CpaStatus cpaDcDpRemoveSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle); #endif return cpaDcRemoveSession(dcInstance, pSessionHandle); } CpaStatus cpaDcDpUpdateSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcSessionUpdateData *pUpdateSessionData) { return cpaDcUpdateSession(dcInstance, pSessionHandle, pUpdateSessionData); } CpaStatus cpaDcDpRegCbFunc(const CpaInstanceHandle dcInstance, const CpaDcDpCallbackFn pNewCb) { sal_compression_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pNewCb); #endif /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(dcInstance); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( dcInstance, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); LAC_CHECK_NULL_PARAM(pNewCb); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(dcInstance); pService = (sal_compression_service_t *)dcInstance; pService->pDcDpCb = pNewCb; return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup cpaDcDp * * @description * Writes the message to the ring * * @param[in] pOpData Pointer to a structure containing the * request parameters * @param[in] pCurrentQatMsg Pointer to current QAT message on the ring * @param[in] pNsRefQatMsg Pointer to QAT NS reference message on the * ring * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_UNSUPPORTED Unsupported algorithm/feature *****************************************************************************/ STATIC CpaStatus dcDpWriteRingMsg(CpaDcDpOpData *pOpData, icp_qat_fw_comp_req_t *pCurrentQatMsg, icp_qat_fw_comp_req_t *pNsRefQatMsg) { icp_qat_fw_comp_req_t *pReqCache = NULL; dc_session_desc_t *pSessionDesc = NULL; Cpa8U bufferFormat; Cpa8U cnv = ICP_QAT_FW_COMP_NO_CNV; Cpa8U cnvnr = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; CpaBoolean cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX; sal_compression_service_t *pService = NULL; CpaStatus status; dc_capabilities_t *pDcCapabilities = NULL; pService = (sal_compression_service_t *)(pOpData->dcInstance); if (pOpData->pSessionHandle) { pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); if (CPA_DC_DIR_COMPRESS == pOpData->sessDirection) { pReqCache = &(pSessionDesc->reqCacheComp); } else { pReqCache = &(pSessionDesc->reqCacheDecomp); } /* Fills in the template DC ET ring message - cached from the * session descriptor */ osalMemCopy((void *)pCurrentQatMsg, (void *)(pReqCache), (LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES)); } else { if (pNsRefQatMsg) { /* Fills in the template DC ET ring message - cached from the * first request in the batch */ osalMemCopy((void *)pCurrentQatMsg, (void *)pNsRefQatMsg, (LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES)); } else { status = dcNsCreateBaseRequest( pCurrentQatMsg, pService, pOpData->pSetupData); if (CPA_STATUS_SUCCESS != status) { return status; } ICP_QAT_FW_COMN_PTR_TYPE_SET( pCurrentQatMsg->comn_hdr.comn_req_flags, DC_DP_QAT_PTR_TYPE); } } /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; if (CPA_DC_DIR_COMPRESS == pOpData->sessDirection) { /* CNV check */ if (CPA_TRUE == pOpData->compressAndVerify) { cnv = ICP_QAT_FW_COMP_CNV; if (CPA_TRUE == pDcCapabilities->cnv.errorInjection) { if (pOpData->pSessionHandle) { cnvErrorInjection = pSessionDesc->cnvErrorInjection; } else { cnvErrorInjection = pService->generic_service_info.ns_isCnvErrorInjection; } } /* CNVNR check */ if (CPA_TRUE == pOpData->compressAndVerifyAndRecover) { cnvnr = ICP_QAT_FW_COMP_CNV_RECOVERY; } } } if (CPA_DP_BUFLIST == pOpData->srcBufferLen) { bufferFormat = QAT_COMN_PTR_TYPE_SGL; } else { bufferFormat = QAT_COMN_PTR_TYPE_FLAT; } pCurrentQatMsg->comp_pars.req_par_flags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( ICP_QAT_FW_COMP_SOP, ICP_QAT_FW_COMP_EOP, ICP_QAT_FW_COMP_BFINAL, cnv, cnvnr, cnvErrorInjection, ICP_QAT_FW_COMP_CRC_MODE_LEGACY, ICP_QAT_FW_COMP_NO_XXHASH_ACC, ICP_QAT_FW_COMP_CNV_ERROR_NONE, ICP_QAT_FW_COMP_NO_APPEND_CRC, ICP_QAT_FW_COMP_NO_DROP_DATA, ICP_QAT_FW_COMP_NO_PARTIAL_DECOMPRESS); SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pCurrentQatMsg, pOpData, bufferFormat, pOpData->srcBuffer, pOpData->destBuffer, pOpData->srcBufferLen, pOpData->destBufferLen); pCurrentQatMsg->comp_pars.comp_len = pOpData->bufferLenToCompress; pCurrentQatMsg->comp_pars.out_buffer_sz = pOpData->bufferLenForData; return CPA_STATUS_SUCCESS; } CpaStatus cpaDcDpEnqueueOp(CpaDcDpOpData *pOpData, const CpaBoolean performOpNow) { icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL; icp_comms_trans_handle trans_handle = NULL; dc_session_desc_t *pSessionDesc = NULL; sal_compression_service_t *pService = NULL; CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_DC_DYN_NOT_SUPPORTED CpaDcHuffType huffType; #endif #ifdef ICP_PARAM_CHECK CpaDcSessionDir sessDirection; status = dcDataPlaneParamCheck(pOpData); if (CPA_STATUS_SUCCESS != status) { return status; } #endif if ((CPA_FALSE == pOpData->compressAndVerify) && (CPA_DC_DIR_COMPRESS == pOpData->sessDirection)) { return CPA_STATUS_UNSUPPORTED; } #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, %d)\n", (LAC_ARCH_UINT)pOpData, performOpNow); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(pOpData->dcInstance); pService = (sal_compression_service_t *)(pOpData->dcInstance); if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = ((sal_compression_service_t *)pOpData->dcInstance) ->trans_handle_compression_tx; } else { trans_handle = ((sal_compression_service_t *)pOpData->dcInstance) ->trans_handle_decompression_tx; } if (pOpData->pSessionHandle) { pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); #ifdef ICP_PARAM_CHECK sessDirection = pSessionDesc->sessDirection; #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED huffType = pSessionDesc->huffType; #endif } else { #ifdef ICP_PARAM_CHECK sessDirection = pOpData->pSetupData->sessDirection; #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED huffType = pOpData->pSetupData->huffType; #endif } #ifdef ICP_PARAM_CHECK if ((CPA_DC_DIR_COMPRESS == pOpData->sessDirection) && (CPA_DC_DIR_DECOMPRESS == sessDirection)) { LAC_INVALID_PARAM_LOG("(a) The session or (b) the NS setup data does " "not support this direction of operation"); return CPA_STATUS_INVALID_PARAM; } else if ((CPA_DC_DIR_DECOMPRESS == pOpData->sessDirection) && (CPA_DC_DIR_COMPRESS == sessDirection)) { LAC_INVALID_PARAM_LOG("(a) The session or (b) the NS setup data does " "not support this direction of operation"); return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic compression " "not supported"); return CPA_STATUS_INVALID_PARAM; } #endif icp_adf_getSingleQueueAddr(trans_handle, (void **)&pCurrentQatMsg); if (NULL == pCurrentQatMsg) { return CPA_STATUS_RETRY; } status = dcDpWriteRingMsg(pOpData, pCurrentQatMsg, NULL); if (CPA_STATUS_SUCCESS != status) { return status; } if (pOpData->pSessionHandle) { pSessionDesc->pendingDpStatelessCbCount++; } if (CPA_TRUE == performOpNow) { status = icp_adf_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { if (pOpData->pSessionHandle) { pSessionDesc->pendingDpStatelessCbCount--; } return status; } } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcDpEnqueueOpBatch(const Cpa32U numberRequests, CpaDcDpOpData *pOpData[], const CpaBoolean performOpNow) { icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL; icp_qat_fw_comp_req_t *pNsRefQatMsg = NULL; icp_comms_trans_handle trans_handle = NULL; dc_session_desc_t *pSessionDesc = NULL; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; sal_compression_service_t *pService = NULL; #ifdef ICP_DC_DYN_NOT_SUPPORTED CpaDcHuffType huffType; #endif #ifdef ICP_PARAM_CHECK CpaDcSessionDir sessDirection; LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pOpData[0]); LAC_CHECK_NULL_PARAM(pOpData[0]->dcInstance); #endif pService = (sal_compression_service_t *)(pOpData[0]->dcInstance); #ifdef ICP_PARAM_CHECK if ((numberRequests == 0) || (numberRequests > pService->maxNumCompConcurrentReq)) { LAC_INVALID_PARAM_LOG1("The number of requests needs to be between 1 " "and %d", pService->maxNumCompConcurrentReq); return CPA_STATUS_INVALID_PARAM; } for (i = 0; i < numberRequests; i++) { status = dcDataPlaneParamCheck(pOpData[i]); if (CPA_STATUS_SUCCESS != status) { return status; } /* Check that all instance handles and session handles are the same */ if (pOpData[i]->dcInstance != pOpData[0]->dcInstance) { LAC_INVALID_PARAM_LOG("All instance handles should be the same " "in the pOpData"); return CPA_STATUS_INVALID_PARAM; } if (pOpData[0]->pSessionHandle) { if (pOpData[i]->pSessionHandle != pOpData[0]->pSessionHandle) { LAC_INVALID_PARAM_LOG("All session handles should be the same " "in the pOpData"); return CPA_STATUS_INVALID_PARAM; } } else { if (pOpData[i]->pSetupData != pOpData[0]->pSetupData) { LAC_INVALID_PARAM_LOG("All NS setup data should be the same " "in the pOpData"); return CPA_STATUS_INVALID_PARAM; } } } #endif #ifdef ICP_TRACE LAC_LOG3("Called with params (%d, 0x%lx, %d)\n", numberRequests, (LAC_ARCH_UINT)pOpData, performOpNow); #endif for (i = 0; i < numberRequests; i++) { if ((CPA_FALSE == pOpData[i]->compressAndVerify) && (CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection)) { return CPA_STATUS_UNSUPPORTED; } } /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(pOpData[0]->dcInstance); if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = ((sal_compression_service_t *)pOpData[0]->dcInstance) ->trans_handle_compression_tx; } else { trans_handle = ((sal_compression_service_t *)pOpData[0]->dcInstance) ->trans_handle_decompression_tx; } if (pOpData[0]->pSessionHandle) { pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData[0]->pSessionHandle); #ifdef ICP_PARAM_CHECK sessDirection = pSessionDesc->sessDirection; #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED huffType = pSessionDesc->huffType; #endif } else { #ifdef ICP_PARAM_CHECK sessDirection = pOpData[0]->pSetupData->sessDirection; #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED huffType = pOpData[0]->pSetupData->huffType; #endif } #ifdef ICP_PARAM_CHECK for (i = 0; i < numberRequests; i++) { if ((CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection) && (CPA_DC_DIR_DECOMPRESS == sessDirection)) { LAC_INVALID_PARAM_LOG("(a) The session or (b) the NS setup data " "does not support this direction of " "operation"); return CPA_STATUS_INVALID_PARAM; } else if ((CPA_DC_DIR_DECOMPRESS == pOpData[i]->sessDirection) && (CPA_DC_DIR_COMPRESS == sessDirection)) { LAC_INVALID_PARAM_LOG("(a) The session or (b) the NS setup data " "does not support this direction of " "operation"); return CPA_STATUS_INVALID_PARAM; } } #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (CPA_DC_HT_FULL_DYNAMIC == huffType) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic sessions " "not supported"); return CPA_STATUS_INVALID_PARAM; } #endif icp_adf_getQueueMemory( trans_handle, numberRequests, (void **)&pCurrentQatMsg); if (NULL == pCurrentQatMsg) { return CPA_STATUS_RETRY; } pNsRefQatMsg = NULL; for (i = 0; i < numberRequests; i++) { status = dcDpWriteRingMsg(pOpData[i], pCurrentQatMsg, pNsRefQatMsg); if (CPA_STATUS_SUCCESS != status) { return status; } if (!pNsRefQatMsg && pOpData[0]->pSetupData) { pNsRefQatMsg = pCurrentQatMsg; } icp_adf_getQueueNext(trans_handle, (void **)&pCurrentQatMsg); } if (pOpData[0]->pSessionHandle) { pSessionDesc->pendingDpStatelessCbCount += numberRequests; } if (CPA_TRUE == performOpNow) { status = icp_adf_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { if (pOpData[0]->pSessionHandle) { pSessionDesc->pendingDpStatelessCbCount -= numberRequests; } return status; } } return CPA_STATUS_SUCCESS; } CpaStatus icp_sal_DcPollDpInstance(CpaInstanceHandle dcInstance, Cpa32U responseQuota) { icp_comms_trans_handle trans_handle = NULL; sal_compression_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, %d)\n", (LAC_ARCH_UINT)dcInstance, responseQuota); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(dcInstance); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( dcInstance, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(dcInstance); pService = (sal_compression_service_t *)(dcInstance); if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = ((sal_compression_service_t *)dcInstance) ->trans_handle_compression_rx; } else { trans_handle = ((sal_compression_service_t *)dcInstance) ->trans_handle_decompression_rx; } return icp_adf_pollQueue(trans_handle, responseQuota); } CpaStatus cpaDcDpPerformOpNow(CpaInstanceHandle dcInstance) { icp_comms_trans_handle trans_handle = NULL; sal_compression_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG1("Called with params (0x%lx)\n", (LAC_ARCH_UINT)dcInstance); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(dcInstance); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( dcInstance, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(dcInstance); pService = (sal_compression_service_t *)(dcInstance); if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = ((sal_compression_service_t *)dcInstance) ->trans_handle_compression_tx; } else { trans_handle = ((sal_compression_service_t *)dcInstance) ->trans_handle_decompression_tx; } if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { return icp_adf_updateQueueTail(trans_handle); } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcDpEnqueueOpWithPartRead(CpaDcDpOpData *pOpData, CpaDcDpPartialReadData *pPartReadData, const CpaBoolean performOpNow) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaDcDpEnqueueOpWithZeroPad(CpaDcDpOpData *pOpData, const CpaBoolean performOpNow) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaDcDpEnqueueOpWithPartReadBatch( const Cpa32U numberRequests, CpaDcDpOpData *pOpData[], CpaDcDpPartialReadData *pPartReadData[], const CpaBoolean performOpNow) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaDcDpEnqueueOpWithZeroPadBatch(const Cpa32U numberRequests, CpaDcDpOpData *pOpData[], const CpaBoolean performOpNow) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaDcDpIsPartReadSupported(const CpaInstanceHandle instanceHandle, CpaBoolean *pFlag) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaDcDpIsZeroPadSupported(const CpaInstanceHandle instanceHandle, CpaBoolean *pFlag) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_err_sim.c000066400000000000000000000102141503624047500310120ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_err_sim.c * * @ingroup Dc_DataCompression * * @description * Implementation of the Data Compression error inject operations. * *****************************************************************************/ #include "dc_err_sim.h" #include "lac_log.h" static Cpa8U num_dc_errors; static CpaDcReqStatus dc_error; CpaStatus dcSetNumError(Cpa8U numErrors, CpaDcReqStatus dcError) { if ((dcError < CPA_DC_EMPTY_DYM_BLK) || (dcError >= CPA_DC_OK) || (CPA_DC_INCOMPLETE_FILE_ERR == dcError)) { LAC_LOG_ERROR1("Unsupported ErrorType %d\n", dcError); return CPA_STATUS_FAIL; } num_dc_errors = numErrors; dc_error = dcError; return CPA_STATUS_SUCCESS; } CpaBoolean dcErrorSimEnabled(void) { if (num_dc_errors > 0) { return CPA_TRUE; } else { return CPA_FALSE; } } CpaDcReqStatus dcGetErrors(void) { CpaDcReqStatus error = 0; if (DC_ERROR_SIM == num_dc_errors) { error = dc_error; } else if (num_dc_errors > 0 && num_dc_errors <= DC_ERROR_SIM_MAX) { num_dc_errors--; error = dc_error; } else { error = 0; } return error; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_header_footer.c000066400000000000000000000346741503624047500322000ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_header_footer.c * * @ingroup Dc_DataCompression * * @description * Implementation of the Data Compression header and footer operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" #include "icp_adf_init.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_header_footer.h" #include "dc_header_footer_lz4.h" #include "dc_session.h" #include "dc_datapath.h" CpaStatus dcDeflateGenerateHeader(CpaFlatBuffer *pDestBuff, CpaDcChecksum checksum, CpaDcCompLvl compLevel, Cpa32U *count) { Cpa8U *pDest = NULL; Cpa16U header = 0, level = 0; /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(pDestBuff->pData); LAC_CHECK_NULL_PARAM(count); #endif /* Adding a Gzip header */ if (CPA_DC_CRC32 == checksum) { pDest = pDestBuff->pData; #ifdef ICP_PARAM_CHECK if (pDestBuff->dataLenInBytes < DC_GZIP_HEADER_SIZE) { LAC_INVALID_PARAM_LOG("The dataLenInBytes of the dest buffer " "is too small"); return CPA_STATUS_INVALID_PARAM; } #endif pDest[0] = DC_GZIP_ID1; /* ID1 */ pDest[1] = DC_GZIP_ID2; /* ID2 */ pDest[2] = 0x08; /* CM = 8 denotes "deflate" compression */ pDest[3] = 0x00; /* FLG = 0 denotes "No extra fields" */ pDest[4] = 0x00; pDest[5] = 0x00; pDest[6] = 0x00; pDest[7] = 0x00; /* MTIME = 0x00 means time stamp not available */ /* XFL = 4 - compressor used fastest compression, */ /* XFL = 2 - compressor used maximum compression. */ pDest[8] = 0; if (CPA_DC_L1 == compLevel) pDest[8] = DC_GZIP_FAST_COMP; else pDest[8] = DC_GZIP_MAX_COMP; pDest[9] = DC_GZIP_FILESYSTYPE; /* OS = 0 means FAT filesystem (MS-DOS, OS/2, NT/Win32), 3 - Unix */ /* Set to the number of bytes added to the buffer */ *count = DC_GZIP_HEADER_SIZE; } /* Adding a Zlib header */ else if (CPA_DC_ADLER32 == checksum) { pDest = pDestBuff->pData; #ifdef ICP_PARAM_CHECK if (pDestBuff->dataLenInBytes < DC_ZLIB_HEADER_SIZE) { LAC_INVALID_PARAM_LOG("The dataLenInBytes of the dest buffer " "is too small"); return CPA_STATUS_INVALID_PARAM; } #endif /* CMF = CM | CMINFO. CM = 8 denotes "deflate" compression, CMINFO = 7 indicates a 32K window size */ /* Depending on the device, at compression levels above L1, the window size can be 8 or 16K bytes. The file will decompress ok if a greater window size is specified in the header. */ header = (DC_ZLIB_CM_DEFLATE + (DC_32K_WINDOW_SIZE << DC_ZLIB_WINDOWSIZE_OFFSET)) << LAC_NUM_BITS_IN_BYTE; switch (compLevel) { case CPA_DC_L1: level = DC_ZLIB_LEVEL_0; break; case CPA_DC_L2: level = DC_ZLIB_LEVEL_1; break; case CPA_DC_L3: level = DC_ZLIB_LEVEL_2; break; default: level = DC_ZLIB_LEVEL_3; } /* Bits 6 - 7: FLEVEL, compression level */ header |= level << DC_ZLIB_FLEVEL_OFFSET; /* The header has to be a multiple of 31 */ header += DC_ZLIB_HEADER_OFFSET - (header % DC_ZLIB_HEADER_OFFSET); pDest[0] = (Cpa8U)(header >> LAC_NUM_BITS_IN_BYTE); pDest[1] = (Cpa8U)header; /* Set to the number of bytes added to the buffer */ *count = DC_ZLIB_HEADER_SIZE; } /* If deflate but no checksum required */ else { *count = 0; } return CPA_STATUS_SUCCESS; } CpaStatus dcDeflateGenerateFooter(CpaFlatBuffer *pDestBuff, CpaDcRqResults *pResults, Cpa64U totalLength, CpaDcChecksum checksum) { Cpa8U *pDest = NULL; Cpa32U crc32 = 0; Cpa32U adler32 = 0; #ifdef ICP_PARAM_CHECK /* Check parameters */ LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(pDestBuff->pData); LAC_CHECK_NULL_PARAM(pResults); #endif pDest = pDestBuff->pData; if (CPA_DC_CRC32 == checksum) { #ifdef ICP_PARAM_CHECK if (pDestBuff->dataLenInBytes < DC_GZIP_FOOTER_SIZE) { LAC_INVALID_PARAM_LOG( "The dataLenInBytes of the destination buffer is too " "small"); return CPA_STATUS_INVALID_PARAM; } if (UINT32_MAX - pResults->produced < DC_GZIP_FOOTER_SIZE) { LAC_INVALID_PARAM_LOG("Footer size will make produced byte counter " "overflow"); return CPA_STATUS_INVALID_PARAM; } #endif crc32 = pResults->checksum; /* Crc32 of the uncompressed data */ pDest[0] = (Cpa8U)crc32; pDest[1] = (Cpa8U)(crc32 >> LAC_NUM_BITS_IN_BYTE); pDest[2] = (Cpa8U)(crc32 >> 2 * LAC_NUM_BITS_IN_BYTE); pDest[3] = (Cpa8U)(crc32 >> 3 * LAC_NUM_BITS_IN_BYTE); /* Length of the uncompressed data */ pDest[4] = (Cpa8U)totalLength; pDest[5] = (Cpa8U)(totalLength >> LAC_NUM_BITS_IN_BYTE); pDest[6] = (Cpa8U)(totalLength >> 2 * LAC_NUM_BITS_IN_BYTE); pDest[7] = (Cpa8U)(totalLength >> 3 * LAC_NUM_BITS_IN_BYTE); /* Increment produced by the number of bytes added to the buffer */ pResults->produced += DC_GZIP_FOOTER_SIZE; } else if (CPA_DC_ADLER32 == checksum) { #ifdef ICP_PARAM_CHECK if (pDestBuff->dataLenInBytes < DC_ZLIB_FOOTER_SIZE) { LAC_INVALID_PARAM_LOG( "The dataLenInBytes of the destination buffer is too " "small"); return CPA_STATUS_INVALID_PARAM; } if (UINT32_MAX - pResults->produced < DC_ZLIB_FOOTER_SIZE) { LAC_INVALID_PARAM_LOG("Footer size will make produced byte counter " "overflow"); return CPA_STATUS_INVALID_PARAM; } #endif adler32 = pResults->checksum; /* Adler32 of the uncompressed data */ pDest[0] = (Cpa8U)(adler32 >> 3 * LAC_NUM_BITS_IN_BYTE); pDest[1] = (Cpa8U)(adler32 >> 2 * LAC_NUM_BITS_IN_BYTE); pDest[2] = (Cpa8U)(adler32 >> LAC_NUM_BITS_IN_BYTE); pDest[3] = (Cpa8U)adler32; /* Increment produced value by the number of bytes added with the * footer */ pResults->produced += DC_ZLIB_FOOTER_SIZE; } else { LAC_INVALID_PARAM_LOG("Invalid checksum type"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle, CpaFlatBuffer *pDestBuff, Cpa32U *count) { dc_session_desc_t *pSessionDesc = NULL; CpaStatus ret = CPA_STATUS_FAIL; #ifdef ICP_TRACE if (NULL == count) { LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)count); } else { LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)count, *count); } #endif /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(pDestBuff->pData); LAC_CHECK_NULL_PARAM(count); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK if (NULL == pSessionDesc) { LAC_INVALID_PARAM_LOG("Session handle not as expected"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { LAC_INVALID_PARAM_LOG("Invalid session direction"); return CPA_STATUS_INVALID_PARAM; } #endif switch (pSessionDesc->compType) { case CPA_DC_DEFLATE: ret = dcDeflateGenerateHeader(pDestBuff, pSessionDesc->checksumType, pSessionDesc->compLevel, count); if (CPA_STATUS_SUCCESS != ret) return ret; break; case CPA_DC_LZ4: if (CPA_DC_XXHASH32 == pSessionDesc->checksumType) { ret = dc_lz4_generate_header(pDestBuff, pSessionDesc->lz4BlockMaxSize, pSessionDesc->lz4BlockIndependence, count); if (CPA_STATUS_SUCCESS != ret) return ret; } break; default: /* There is no header for other compression formats */ *count = 0; } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle, CpaFlatBuffer *pDestBuff, CpaDcRqResults *pRes) { dc_session_desc_t *pSessionDesc = NULL; CpaStatus ret = CPA_STATUS_FAIL; #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pRes); #endif /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(pDestBuff->pData); LAC_CHECK_NULL_PARAM(pRes); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK if (NULL == pSessionDesc) { LAC_INVALID_PARAM_LOG("Session handle not as expected"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { LAC_INVALID_PARAM_LOG("Invalid session direction"); return CPA_STATUS_INVALID_PARAM; } #endif switch (pSessionDesc->compType) { case CPA_DC_DEFLATE: ret = dcDeflateGenerateFooter(pDestBuff, pRes, pSessionDesc->cumulativeConsumedBytes, pSessionDesc->checksumType); if (CPA_STATUS_SUCCESS != ret) return ret; break; case CPA_DC_LZ4: ret = dc_lz4_generate_footer(pDestBuff, pRes); if (CPA_STATUS_SUCCESS != ret) return ret; pRes->produced += DC_LZ4_FOOTER_SIZE; break; default: LAC_INVALID_PARAM_LOG("Invalid compression type\n"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_header_footer_lz4.c000066400000000000000000000163211503624047500327560ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_header_footer_lz4.c * * @ingroup Dc_DataCompression * * @description * Implementation of the Data Compression header and footer operations for * LZ4 algorithm. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "lac_common.h" #include "dc_session.h" #include "dc_header_footer_lz4.h" #include "dc_xxhash32.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #pragma pack(push, 1) typedef struct { Cpa8U dict_id : 1; /* dictionary present */ Cpa8U resv1 : 1; Cpa8U cnt_cksum : 1; /* content checksum present */ Cpa8U cnt_size : 1; /* content size present */ Cpa8U blk_cksum : 1; /* block checksum present */ Cpa8U blk_indep : 1; /* block linked/independent */ Cpa8U version : 2; /* version */ } lz4_hdr_flag_byte; typedef struct { Cpa32U magic; /* LZ4 magic number */ union { lz4_hdr_flag_byte bit_field; Cpa8U addr; }; Cpa8U resv2 : 4; Cpa8U blk_maxsize : 3; /* max block size */ Cpa8U resv3 : 1; Cpa8U hdr_cksum; /* header checksum */ } lz4_hdr_t; typedef struct { Cpa32U end_mark; /* LZ4 end mark */ Cpa32U cnt_cksum; /* content checksum */ } lz4_footer_t; #pragma pack(pop) /* If compilation fails on below lines structures: lz4_hdr_t or lz4_footer_t * have invalid size. */ typedef Cpa8U static_assert_lz4_header_size [(sizeof(lz4_hdr_t) == DC_LZ4_HEADER_SIZE) ? 1 : -1]; typedef Cpa8U static_assert_lz4_footer_size [(sizeof(lz4_footer_t) == DC_LZ4_FOOTER_SIZE) ? 1 : -1]; CpaStatus dc_lz4_generate_header(const CpaFlatBuffer *dest_buff, const CpaDcCompLZ4BlockMaxSize max_block_size, const CpaBoolean block_indep, Cpa32U *count) { CpaStatus status = CPA_STATUS_SUCCESS; lz4_hdr_t *header_ptr; /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_PARAM_RANGE(block_indep, 0, 2); LAC_CHECK_NULL_PARAM(dest_buff); LAC_CHECK_NULL_PARAM(dest_buff->pData); LAC_CHECK_NULL_PARAM(count); LAC_CHECK_PARAM_RANGE(max_block_size, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, CPA_DC_LZ4_MAX_BLOCK_SIZE_4M + 1); if (dest_buff->dataLenInBytes < DC_LZ4_HEADER_SIZE) { LAC_INVALID_PARAM_LOG("The dataLenInBytes of the dest buffer " "is too small"); return CPA_STATUS_INVALID_PARAM; } #endif osalMemSet(dest_buff->pData, 0, DC_LZ4_HEADER_SIZE); header_ptr = (lz4_hdr_t *)dest_buff->pData; header_ptr->magic = DC_LZ4_FH_ID; header_ptr->bit_field.version = DC_LZ4_FH_FLG_VERSION; header_ptr->bit_field.blk_indep = block_indep; header_ptr->bit_field.cnt_cksum = 1; header_ptr->blk_maxsize = max_block_size + DC_LZ4_FH_MAX_BLK_SIZE_ENUM_MIN; status = dcXxhash32Lz4HdrChecksum( &header_ptr->addr, (Cpa32U)(&header_ptr->hdr_cksum - &header_ptr->addr), &header_ptr->hdr_cksum); if (status != CPA_STATUS_SUCCESS) return CPA_STATUS_FAIL; *count = (Cpa32U)DC_LZ4_HEADER_SIZE; return CPA_STATUS_SUCCESS; } CpaStatus dc_lz4_generate_footer(const CpaFlatBuffer *dest_buff, const CpaDcRqResults *pRes) { lz4_footer_t *footer_ptr; /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(dest_buff); LAC_CHECK_NULL_PARAM(dest_buff->pData); LAC_CHECK_NULL_PARAM(pRes); if (dest_buff->dataLenInBytes < DC_LZ4_FOOTER_SIZE) { LAC_INVALID_PARAM_LOG("The dataLenInBytes of the dest buffer " "is too small for LZ4 footer"); return CPA_STATUS_INVALID_PARAM; } #endif osalMemSet(dest_buff->pData, 0, DC_LZ4_FOOTER_SIZE); footer_ptr = (lz4_footer_t *)dest_buff->pData; footer_ptr->end_mark = DC_LZ4_FF_END_MARK; footer_ptr->cnt_cksum = pRes->checksum; return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_ns_datapath.c000066400000000000000000001641301503624047500316470ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_ns_datapath.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of the No-Session (NS) variant of Data Compression * datapath operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" #include "cpa_dc_dp.h" #include "icp_qat_hw_20_comp.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_session.h" #include "dc_datapath.h" #include "dc_ns_datapath.h" #include "sal_statistics.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_log.h" #include "sal_types_compression.h" #include "dc_stats.h" #include "lac_buffer_desc.h" #include "lac_sal.h" #include "lac_sync.h" #include "sal_service_state.h" #include "sal_qat_cmn_msg.h" #ifdef ICP_DC_ERROR_SIMULATION #include "dc_err_sim.h" #endif #include "dc_error_counter.h" #include "dc_crc32.h" #include "dc_crc64.h" #include "sal_misc_error_stats.h" void dcNsCompression_ProcessCallback(void *pRespMsg) { CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_comp_resp_t *pCompRespMsg = NULL; void *callbackTag = NULL; Cpa64U *pReqData = NULL; CpaDcDpOpData *pDpOpData = NULL; CpaDcRqResults *pResults = NULL; CpaDcCallbackFn pCbFunc = NULL; sal_compression_service_t *pService = NULL; dc_compression_cookie_t *pCookie = NULL; CpaDcOpData *pOpData = NULL; CpaBoolean cmpPass = CPA_TRUE, xlatPass = CPA_TRUE; CpaBoolean integrityCrcCheck = CPA_FALSE; Cpa8S cmpErr = ERR_CODE_NO_ERROR; #ifndef ICP_DC_DYN_NOT_SUPPORTED Cpa8S xlatErr = ERR_CODE_NO_ERROR; #endif dc_request_dir_t compDecomp = DC_COMPRESSION_REQUEST; Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; Cpa8U hdrFlags = 0; CpaDcChecksum checksumType = CPA_DC_NONE; CpaBoolean isDcDp = CPA_FALSE; CpaDcCompType compType = CPA_DC_DEFLATE; CpaDcHuffType huffType = CPA_DC_HT_STATIC; dc_capabilities_t *pDcCapabilities = NULL; CpaBoolean bypassIncompleteFileErr = CPA_FALSE; CpaBoolean uncompressedDataSupported = CPA_FALSE; CpaDcSessionDir sessDirection = CPA_DC_DIR_COMPRESS; dc_hw_gen_types_t hw_gen; /* Cast response message to compression response message type */ pCompRespMsg = (icp_qat_fw_comp_resp_t *)pRespMsg; #ifdef ICP_PARAM_CHECK LAC_ASSERT_NOT_NULL(pCompRespMsg); if (!pCompRespMsg) return; #endif /* Extract request data pointer from the opaque data */ LAC_MEM_SHARED_READ_TO_PTR(pCompRespMsg->opaque_data, pReqData); #ifdef ICP_PARAM_CHECK LAC_ASSERT_NOT_NULL(pReqData); if (!pReqData) return; #endif /* Extract fields from the request data structure */ pCookie = (dc_compression_cookie_t *)pReqData; pService = (sal_compression_service_t *)(pCookie->dcInstance); #ifdef ICP_PARAM_CHECK LAC_ASSERT_NOT_NULL(pService); #endif /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; bypassIncompleteFileErr = pDcCapabilities->deflate.bypassIncompleteFileErr; uncompressedDataSupported = pDcCapabilities->deviceData.uncompressedDataSupported; hw_gen = pDcCapabilities->deviceData.hw_gen; if (DCDPNS == (LAC_ARCH_UINT)pCookie->pSessionHandle) { isDcDp = CPA_TRUE; pDpOpData = (CpaDcDpOpData *)pReqData; pResults = &pDpOpData->results; if (CPA_DC_DIR_DECOMPRESS == pDpOpData->sessDirection) { compDecomp = DC_DECOMPRESSION_REQUEST; } compType = pDpOpData->pSetupData->compType; huffType = pDpOpData->pSetupData->huffType; checksumType = pDpOpData->pSetupData->checksum; pCookie = NULL; } else { pResults = pCookie->pResults; callbackTag = pCookie->callbackTag; pCbFunc = pCookie->pCbFunc; compDecomp = pCookie->compDecomp; pOpData = pCookie->pDcOpData; checksumType = pCookie->checksumType; switch (pCookie->request.comn_hdr.service_cmd_id) { case ICP_QAT_FW_COMP_20_CMD_LZ4_COMPRESS: case ICP_QAT_FW_COMP_20_CMD_LZ4_DECOMPRESS: compType = CPA_DC_LZ4; break; case ICP_QAT_FW_COMP_20_CMD_LZ4S_COMPRESS: compType = CPA_DC_LZ4S; break; } if (ICP_QAT_FW_COMP_CMD_DYNAMIC == pCookie->request.comn_hdr.service_cmd_id) { huffType = CPA_DC_HT_FULL_DYNAMIC; } } if (DC_DECOMPRESSION_REQUEST == compDecomp) { sessDirection = CPA_DC_DIR_DECOMPRESS; } opStatus = pCompRespMsg->comn_resp.comn_status; if (NULL != pOpData) { integrityCrcCheck = pOpData->integrityCrcCheck; } hdrFlags = pCompRespMsg->comn_resp.hdr_flags; /* Get the cmp error code */ cmpErr = (Cpa8S)pCompRespMsg->comn_resp.comn_error.s1.cmp_err_code; #ifdef ICP_DC_ERROR_SIMULATION if (!isDcDp && 0 != pCookie->dcErrorToSimulate) { cmpErr = pCookie->dcErrorToSimulate; } #endif if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(opStatus)) { /* Compression not supported by firmware, set produced/consumed to * zero and call the cb function with status CPA_STATUS_UNSUPPORTED */ LAC_LOG_ERROR("Compression feature not supported"); status = CPA_STATUS_UNSUPPORTED; pResults->status = cmpErr; pResults->consumed = 0; pResults->produced = 0; if (isDcDp) { pDpOpData->responseStatus = status; (pService->pDcDpCb)(pDpOpData); } else { /* Free the memory pool */ if (NULL != pCookie) { Lac_MemPoolEntryFree(pCookie); pCookie = NULL; } if (NULL != pCbFunc) { pCbFunc(callbackTag, status); } } if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompCompletedErrors, pService); } else { COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } SAL_MISC_ERR_STATS_INC(cmpErr, &pService->generic_service_info); return; } else { /* Check compression response status */ cmpPass = ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(opStatus); SAL_MISC_ERR_STATS_INC(cmpErr, &pService->generic_service_info); } switch (cmpErr) { case ERR_CODE_HW_INCOMPLETE_FILE: /* Cancel the incomplete file error code only for DEFLATE algorithm */ if ((CPA_TRUE == bypassIncompleteFileErr) && (CPA_DC_DEFLATE == compType)) { cmpPass = CPA_TRUE; cmpErr = ERR_CODE_NO_ERROR; } break; case ERR_CODE_SSM_ERROR: /* log the slice hang error inside the response */ LAC_LOG_ERROR( "The slice hang is detected on the compression slice"); break; case ERR_CODE_SSM_PARITY_ERROR: /* log ssm parity error inside the response */ LAC_LOG_ERROR("Operation resulted in a parity error in one or more " "accelerators."); break; case ERR_CODE_ENDPOINT_ERROR: /* log the endpoint push/pull error inside the response */ LAC_LOG_ERROR( "The PCIe End Point Push/Pull or TI/RI Parity error detected."); break; } /* We return the compression error code for now. We would need to update * the API if we decide to return both error codes */ pResults->status = cmpErr; #ifndef ICP_DC_DYN_NOT_SUPPORTED /* Check the translator status */ if ((DC_COMPRESSION_REQUEST == compDecomp) && (CPA_DC_HT_FULL_DYNAMIC == huffType)) { /* Check translator response status */ xlatPass = ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(opStatus); /* Get the translator error code */ xlatErr = (Cpa8S)pCompRespMsg->comn_resp.comn_error.s1.xlat_err_code; /* Return a fatal error or a potential error in the translator slice * if the compression slice did not return any error */ if ((ERR_CODE_NO_ERROR == cmpErr) || (ERR_CODE_FATAL_ERROR == xlatErr)) { pResults->status = xlatErr; } } #endif /* Update dc error counter */ dcErrorLog(pResults->status); if (!isDcDp) { if (DC_COMPRESSION_REQUEST == compDecomp) { /* Overflow is a valid use case for Traditional API only. * Stateless Overflow is supported only in compression direction. */ if (ERR_CODE_OVERFLOW_ERROR == cmpErr) cmpPass = CPA_TRUE; #ifndef ICP_DC_DYN_NOT_SUPPORTED if (ERR_CODE_OVERFLOW_ERROR == xlatErr) xlatPass = CPA_TRUE; #endif } } else { if (ERR_CODE_OVERFLOW_ERROR == cmpErr) cmpPass = CPA_FALSE; #ifndef ICP_DC_DYN_NOT_SUPPORTED if (ERR_CODE_OVERFLOW_ERROR == xlatErr) /* XLT overflow is not valid for Data Plane requests */ xlatPass = CPA_FALSE; #endif } if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) { /* Extract the response from the firmware */ pResults->consumed = pCompRespMsg->comp_resp_pars.input_byte_counter; pResults->produced = pCompRespMsg->comp_resp_pars.output_byte_counter; /* Handle Checksum for end to end data integrity. */ if ((CPA_TRUE == integrityCrcCheck) && (CPA_TRUE == pDcCapabilities->crcIntegrity.supported)) { if (hw_gen >= DC_CAPS_GEN4_HW) { dcHandleIntegrityChecksums(pCookie, pOpData->pCrcData, pResults, huffType, compType, checksumType, CPA_TRUE, ICP_QAT_FW_NO_CHAINING_20); } else { dcHandleIntegrityChecksumsLegacy(pCookie, pOpData->pCrcData, pResults, huffType, checksumType, CPA_DC_STATELESS, sessDirection, CPA_TRUE); } if (pResults->status == CPA_DC_CRC_INTEG_ERR) { cmpPass = CPA_FALSE; } } else { if (CPA_DC_CRC32 == checksumType) { pResults->checksum = pCompRespMsg->comp_resp_pars.crc.legacy.curr_crc32; } else if ((CPA_DC_ADLER32 == checksumType) || (CPA_DC_XXHASH32 == checksumType)) { pResults->checksum = pCompRespMsg->comp_resp_pars.crc.legacy.curr_adler_32; } } } if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) { if ((DC_COMPRESSION_REQUEST == compDecomp) && (CPA_TRUE == uncompressedDataSupported)) { /* Check if returned data is a stored block * in compression direction */ pResults->dataUncompressed = ICP_QAT_FW_COMN_HDR_ST_BLK_FLAG_GET(hdrFlags); } if (DC_DECOMPRESSION_REQUEST == compDecomp) { pResults->endOfLastBlock = ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET == ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(opStatus); } /* Check if a CNV recovery happened and * increase stats counter */ if ((DC_COMPRESSION_REQUEST == compDecomp) && ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdrFlags) && ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdrFlags)) { COMPRESSION_STAT_INC(numCompCnvErrorsRecovered, pService); } if (isDcDp) { pDpOpData->responseStatus = CPA_STATUS_SUCCESS; } else { if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompCompleted, pService); } else { COMPRESSION_STAT_INC(numDecompCompleted, pService); } } } if ((CPA_FALSE == cmpPass) || (CPA_FALSE == xlatPass)) { #ifdef ICP_DC_RETURN_COUNTERS_ON_ERROR /* Extract the response from the firmware */ pResults->consumed = pCompRespMsg->comp_resp_pars.input_byte_counter; pResults->produced = pCompRespMsg->comp_resp_pars.output_byte_counter; #else pResults->consumed = 0; pResults->produced = 0; #endif if (ERR_CODE_OVERFLOW_ERROR == pResults->status) { /* With Traditional API this error message will be returned only in * stateless decompression direction */ LAC_LOG_ERROR( "Unrecoverable error: stateless overflow. You may " "need to increase the size of your destination buffer"); } if (isDcDp) { pDpOpData->responseStatus = CPA_STATUS_FAIL; } else { if (ERR_CODE_NO_ERROR != pResults->status && ERR_CODE_HW_INCOMPLETE_FILE != pResults->status) { status = CPA_STATUS_FAIL; } if (DC_COMPRESSION_REQUEST == compDecomp) { COMPRESSION_STAT_INC(numCompCompletedErrors, pService); } else { COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } } } if (isDcDp) { (pService->pDcDpCb)(pDpOpData); } else { /* Free the memory pool */ if (NULL != pCookie) { Lac_MemPoolEntryFree(pCookie); pCookie = NULL; } if (NULL != pCbFunc) { pCbFunc(callbackTag, status); } } } #ifdef ICP_PARAM_CHECK STATIC CpaStatus dcNsCheckDestinationData(sal_compression_service_t *pService, CpaDcNsSetupData *pSetupData, CpaBufferList *pDestBuff, dc_request_dir_t compDecomp) { dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; Cpa16U numInterBuffs = pDcCapabilities->numInterBuffs; Cpa64U destBuffSize = 0; if (LacBuffDesc_BufferListVerify( pDestBuff, &destBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid destination buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } if (compDecomp == DC_COMPRESSION_REQUEST) { if (pSetupData->huffType == CPA_DC_HT_FULL_DYNAMIC) { #ifndef ICP_DC_DYN_NOT_SUPPORTED /* Check if intermediate buffers are available */ if ((numInterBuffs > 0) && (pService->pInterBuffPtrsArrayPhyAddr == 0 || pService->pInterBuffPtrsArray == NULL)) { LAC_LOG_ERROR( "No intermediate buffer defined for this instance " "- see cpaDcStartInstance"); return CPA_STATUS_INVALID_PARAM; } /* Ensure that the destination buffer size is greater or equal * to devices min output buffer size for dynamic compression */ if (destBuffSize < pDcCapabilities->deviceData.minOutputBuffSizeDynamic) { LAC_INVALID_PARAM_LOG1( "Destination buffer size should be " "greater or equal to %u bytes", pDcCapabilities->deviceData.minOutputBuffSizeDynamic); return CPA_STATUS_INVALID_PARAM; } #else LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic compression " "not supported"); return CPA_STATUS_INVALID_PARAM; #endif } else { /* Ensure that the destination buffer size is greater or equal * to devices min output buff size for static compression */ if (destBuffSize < pDcCapabilities->deviceData.minOutputBuffSize) { LAC_INVALID_PARAM_LOG1( "Destination buffer size should be " "greater or equal to %d bytes", pDcCapabilities->deviceData.minOutputBuffSize); return CPA_STATUS_INVALID_PARAM; } } } else { /* Ensure that the destination buffer size is greater than * 0 bytes */ if (destBuffSize < DC_DEST_BUFFER_DEC_MIN_SIZE) { LAC_INVALID_PARAM_LOG("Destination buffer size should be " "greater than 0 bytes"); return CPA_STATUS_INVALID_PARAM; } } /* The firmware expects the size of the destination to be a Cpa32U * parameter. However, the total size (all flat buffers added up) could be * bigger, as it's allocated by the user. We ensure that this is not the * case. */ if (destBuffSize > DC_BUFFER_MAX_SIZE) { LAC_INVALID_PARAM_LOG("The destination buffer size needs to be less " "than or equal to 2^32-1 bytes"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } STATIC CpaStatus dcNsCheckSourceData(Cpa64U srcBuffSize) { /* Compressing zero bytes is not supported for stateless operation */ if (srcBuffSize == 0) { LAC_INVALID_PARAM_LOG("The source buffer size needs to be greater than " "zero bytes for stateless operation"); return CPA_STATUS_INVALID_PARAM; } /* The firmware expects the size of the source to be a Cpa32U parameter. * However, the total size (all flat buffers added up) could be bigger, as * it's allocated by the user. We ensure that this is not the case. */ if (srcBuffSize > DC_BUFFER_MAX_SIZE) { LAC_INVALID_PARAM_LOG("The source buffer size needs to be less than or " "equal to 2^32-1 bytes"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif void dcNsCompHwBlockPopulate(void *pServiceType, void *pSessionDescp, CpaDcNsSetupData *pSetupData, icp_qat_hw_compression_config_t *pCompConfig, void *compDecompDir, CpaBoolean bNsOp) { sal_compression_service_t *pService = NULL; dc_request_dir_t compDecomp; pService = (sal_compression_service_t *)pServiceType; compDecomp = *(dc_request_dir_t *)compDecompDir; icp_qat_hw_compression_direction_t dir = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS; icp_qat_hw_compression_algo_t algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE; icp_qat_hw_compression_depth_t depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; /* The file type is set to ICP_QAT_HW_COMPRESSION_FILE_TYPE_0. The other * modes will be used in the future for precompiled huffman trees */ icp_qat_hw_compression_file_type_t filetype = ICP_QAT_HW_COMPRESSION_FILE_TYPE_0; icp_qat_hw_compression_delayed_match_t dmm; if (pSetupData->compType != CPA_DC_DEFLATE) { LAC_ENSURE(CPA_FALSE, "Algorithm not supported for Compression\n"); } /* Set delay match mode */ if (CPA_TRUE == pService->dc_capabilities.deviceData.enableDmm) { dmm = ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; } else { dmm = ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED; } /* Dealing with compression, so reset the direction and depth. */ if (compDecomp == DC_COMPRESSION_REQUEST) { dir = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS; switch (pSetupData->compLevel) { case CPA_DC_L1: depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; break; case CPA_DC_L2: depth = ICP_QAT_HW_COMPRESSION_DEPTH_4; break; case CPA_DC_L3: depth = ICP_QAT_HW_COMPRESSION_DEPTH_8; break; case CPA_DC_L4: depth = ICP_QAT_HW_COMPRESSION_DEPTH_16; break; default: depth = pService->dc_capabilities.deviceData .highestHwCompressionDepth; break; } } pCompConfig->lower_val = ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(dir, dmm, algo, depth, filetype); /* Upper 32-bits of the configuration word do not need to be * configured with legacy devices. */ pCompConfig->upper_val = 0; } STATIC void dcNsCompContentDescPopulate(sal_compression_service_t *pService, CpaDcNsSetupData *pSetupData, CpaPhysicalAddr contextBufferAddrPhys, icp_qat_fw_comp_req_t *pMsg, icp_qat_fw_slice_t nextSlice, dc_request_dir_t compDecomp) { icp_qat_fw_comp_cd_hdr_t *pCompControlBlock = NULL; icp_qat_hw_compression_config_t *pCompConfig = NULL; dc_capabilities_t *pDcCapabilities = NULL; LAC_ENSURE_NOT_NULL(pService); LAC_ENSURE_NOT_NULL(pSetupData); LAC_ENSURE_NOT_NULL(pMsg); pCompControlBlock = &pMsg->comp_cd_ctrl; /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; /* Non-standard aliasing on the following line. */ pCompConfig = (icp_qat_hw_compression_config_t *)(pMsg->cd_pars.sl .comp_slice_cfg_word); ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, nextSlice); ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP); pCompControlBlock->comp_cfg_offset = 0; /* Disable all banks */ pCompControlBlock->ram_bank_flags = 0; pCompControlBlock->comp_state_addr = 0; pCompControlBlock->ram_banks_addr = 0; pCompControlBlock->resrvd = 0; /* Populate Compression Hardware Setup Block */ (pDcCapabilities->dcNsCompHwBlockPopulate)((void *)pService, NULL, pSetupData, pCompConfig, (void *)&compDecomp, CPA_TRUE); } CpaStatus dcNsCreateBaseRequest(icp_qat_fw_comp_req_t *pMsg, sal_compression_service_t *pService, CpaDcNsSetupData *pSetupData) { CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_serv_specif_flags cmdFlags = 0; Cpa8U secureRam = ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; Cpa8U sessType = ICP_QAT_FW_COMP_STATELESS_SESSION; Cpa8U autoSelectBest = ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST; Cpa8U enhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST; Cpa8U disableType0EnhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; Cpa8U dcCmdId = ICP_QAT_FW_COMP_CMD_STATIC; icp_qat_fw_comn_flags cmnRequestFlags = 0; icp_qat_fw_ext_serv_specif_flags extServiceCmdFlags = 0; CpaDcAutoSelectBest autoSelectBestProfile; dc_capabilities_t *pDcCapabilities = NULL; Cpa16U numInterBuffs = 0; dc_hw_gen_types_t hw_gen; LAC_OS_BZERO(pMsg, sizeof(icp_qat_fw_comp_req_t)); cmnRequestFlags = ICP_QAT_FW_COMN_FLAGS_BUILD( DC_DEFAULT_QAT_PTR_TYPE, QAT_COMN_CD_FLD_TYPE_16BYTE_DATA); LAC_ASSERT_NOT_NULL(pService); pDcCapabilities = &pService->dc_capabilities; numInterBuffs = pDcCapabilities->numInterBuffs; hw_gen = pDcCapabilities->deviceData.hw_gen; if (pService->generic_service_info.capabilitiesMask & ICP_ACCEL_CAPABILITIES_INLINE) { secureRam = ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF; } else { secureRam = pService->dc_capabilities.deviceData.useDevRam; } autoSelectBestProfile = pSetupData->autoSelectBestHuffmanTree; /* Enable or disable ASB in the uniform manner for all the algorithms */ if (hw_gen >= DC_CAPS_GEN4_HW) { switch (autoSelectBestProfile) { case CPA_DC_ASB_STATIC_DYNAMIC: case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS: case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS: /* Enable compression ratio optimization */ autoSelectBestProfile = CPA_DC_ASB_ENABLED; break; case CPA_DC_ASB_DISABLED: default: /* Keep setting from setup data */ break; } } if (pSetupData->sessDirection == CPA_DC_DIR_COMPRESS) { dcNsCompContentDescPopulate(pService, pSetupData, 0, pMsg, ICP_QAT_FW_SLICE_DRAM_WR, DC_COMPRESSION_REQUEST); } else { dcNsCompContentDescPopulate(pService, pSetupData, 0, pMsg, ICP_QAT_FW_SLICE_DRAM_WR, DC_DECOMPRESSION_REQUEST); } #ifndef ICP_DC_DYN_NOT_SUPPORTED if ((numInterBuffs > 0) && (pSetupData->sessDirection == CPA_DC_DIR_COMPRESS) && (pSetupData->huffType == CPA_DC_HT_FULL_DYNAMIC)) { pMsg->u1.xlt_pars.inter_buff_ptr = pService->pInterBuffPtrsArrayPhyAddr; } #endif /* Clearing translator content descriptor header, largely for several * reserved members, as it's otherwise unused. */ memset(&pMsg->u2.xlt_cd_ctrl, 0, sizeof(icp_qat_fw_xlt_cd_hdr_t)); /* Populate the cmdFlags */ switch (autoSelectBestProfile) { case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS: disableType0EnhancedAutoSelectBest = ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; /* Fall through. */ case CPA_DC_ASB_ENABLED: case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS: enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST; /* Fall through. */ case CPA_DC_ASB_STATIC_DYNAMIC: autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; break; case CPA_DC_ASB_DISABLED: break; } cmdFlags = ICP_QAT_FW_COMP_FLAGS_BUILD(sessType, autoSelectBest, enhancedAutoSelectBest, disableType0EnhancedAutoSelectBest, secureRam); if (pSetupData->sessDirection == CPA_DC_DIR_COMPRESS) { status = dcGetCompressCommandId( pService, (CpaDcSessionSetupData *)pSetupData, &dcCmdId); } else { status = dcGetDecompressCommandId( pService, (CpaDcSessionSetupData *)pSetupData, &dcCmdId); } if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("Couldn't get command ID for current parameters."); return status; } pMsg->comp_pars.crc.legacy.initial_adler = 1; pMsg->comp_pars.crc.legacy.initial_crc32 = 0; /* Populate header of the common request message */ SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pMsg, ICP_QAT_FW_COMN_REQ_CPM_FW_COMP, dcCmdId, cmnRequestFlags, cmdFlags, extServiceCmdFlags); return CPA_STATUS_SUCCESS; } STATIC CpaStatus dcNsCreateRequest(dc_compression_cookie_t *pCookie, sal_compression_service_t *pService, CpaDcNsSetupData *pSetupData, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, CpaDcOpData *pOpData, void *callbackTag, dc_request_dir_t compDecomp, dc_cnv_mode_t cnvMode) { icp_qat_fw_comp_req_t *pMsg = NULL; icp_qat_fw_comp_req_params_t *pCompReqParams = NULL; Cpa64U srcAddrPhys = 0, dstAddrPhys = 0; Cpa64U srcTotalDataLenInBytes = 0, dstTotalDataLenInBytes = 0; Cpa32U rpCmdFlags = 0; Cpa8U sop = ICP_QAT_FW_COMP_SOP; Cpa8U eop = ICP_QAT_FW_COMP_EOP; Cpa8U bFinal = ICP_QAT_FW_COMP_NOT_BFINAL; Cpa8U crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; Cpa8U cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; CpaBoolean cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX; CpaBoolean integrityCrcCheck = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; CpaDcFlush flush = CPA_DC_FLUSH_NONE; Cpa32U initial_adler = 1; Cpa32U initial_xxhash = 0; Cpa32U initial_crc32 = 0; dc_capabilities_t *pDcCapabilities = NULL; CpaBoolean errorInjectionSupported = CPA_FALSE; Cpa32U errorInjectionCode = ICP_QAT_FW_COMP_CNV_ERROR_NONE; Cpa16U numInterBuffs = 0; dc_hw_gen_types_t hw_gen; LAC_ASSERT_NOT_NULL(pService); pMsg = &pCookie->request; status = dcNsCreateBaseRequest(pMsg, pService, pSetupData); if (status != CPA_STATUS_SUCCESS) { return status; } /* Write the buffer descriptors */ status = LacBuffDesc_BufferListDescWriteAndGetSize( pSrcBuff, &srcAddrPhys, CPA_FALSE, &srcTotalDataLenInBytes, &(pService->generic_service_info)); if (status != CPA_STATUS_SUCCESS) { return status; } status = LacBuffDesc_BufferListDescWriteAndGetSize( pDestBuff, &dstAddrPhys, CPA_FALSE, &dstTotalDataLenInBytes, &(pService->generic_service_info)); if (status != CPA_STATUS_SUCCESS) { return status; } pDcCapabilities = &pService->dc_capabilities; errorInjectionSupported = pDcCapabilities->cnv.errorInjection; numInterBuffs = pDcCapabilities->numInterBuffs; hw_gen = pDcCapabilities->deviceData.hw_gen; /* Populate the compression cookie */ pCookie->dcInstance = pService; pCookie->pSessionHandle = (CpaDcSessionHandle)DCNS; pCookie->callbackTag = callbackTag; pCookie->pSessionDesc = NULL; pCookie->pDcOpData = pOpData; pCookie->pResults = pResults; pCookie->compDecomp = compDecomp; pCookie->checksumType = pSetupData->checksum; #ifdef ICP_DC_ERROR_SIMULATION /* Inject DC error in cookie if simulation is active */ if (dcErrorSimEnabled()) { pCookie->dcErrorToSimulate = dcGetErrors(); } else { pCookie->dcErrorToSimulate = 0; } #endif pCookie->pUserSrcBuff = NULL; pCookie->pUserDestBuff = NULL; /* Extract flush flag from either the opData or from the * parameter. Opdata have been introduce with APIs * cpaDcCompressData2 and cpaDcDecompressData2 */ if (pOpData != NULL) { flush = pOpData->flushFlag; integrityCrcCheck = pOpData->integrityCrcCheck; } else { flush = flushFlag; } pCookie->flushFlag = flush; pCookie->srcTotalDataLenInBytes = (Cpa32U)srcTotalDataLenInBytes; #ifndef ICP_DC_DYN_NOT_SUPPORTED /* In order to avoid (as opposed to prevent) overflow, the sizes of the * destination buffer and the intermediate buffer are synchronised. They * share the same field in the request message, and it is set to the * smaller of the two sizes. */ if ((numInterBuffs > 0) && (compDecomp == DC_COMPRESSION_REQUEST) && (pSetupData->huffType == CPA_DC_HT_FULL_DYNAMIC) && ((Cpa32U)dstTotalDataLenInBytes > pService->minInterBuffSizeInBytes)) { pCookie->dstTotalDataLenInBytes = (Cpa32U)pService->minInterBuffSizeInBytes; } else { pCookie->dstTotalDataLenInBytes = (Cpa32U)dstTotalDataLenInBytes; } #else pCookie->dstTotalDataLenInBytes = (Cpa32U)dstTotalDataLenInBytes; #endif if (pSetupData->checksum == CPA_DC_ADLER32) { initial_adler = pResults->checksum; } else if (pSetupData->checksum == CPA_DC_XXHASH32) { /* There is no seeding with xxHash. */ initial_xxhash = 0; } else { initial_crc32 = pResults->checksum; } /* Backup source and destination buffer addresses, * CRC calculations both for CNV and translator overflow * will be performed on them in the callback function. */ pCookie->pUserSrcBuff = pSrcBuff; pCookie->pUserDestBuff = pDestBuff; if ((CPA_TRUE == integrityCrcCheck) && (CPA_TRUE == pDcCapabilities->crcIntegrity.supported)) { /* Get physical address of E2E CRC buffer */ pMsg->comp_pars.crc.crc_data_addr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, &pCookie->dataIntegrityCrcs); if (!pMsg->comp_pars.crc.crc_data_addr) { LAC_LOG_ERROR("Unable to get the physical address of " "Data Integrity buffer.\n"); return CPA_STATUS_FAIL; } pCookie->dataIntegrityCrcs.crc32 = initial_crc32; if (pSetupData->checksum == CPA_DC_XXHASH32) { pCookie->dataIntegrityCrcs.xxhash32 = initial_xxhash; } else { pCookie->dataIntegrityCrcs.adler32 = initial_adler; } if (hw_gen < DC_CAPS_GEN4_HW) { pCookie->dataIntegrityCrcs.oCrc32Cpr = DC_DEFAULT_CRC; pCookie->dataIntegrityCrcs.iCrc32Cpr = DC_DEFAULT_CRC; pCookie->dataIntegrityCrcs.oCrc32Xlt = DC_DEFAULT_CRC; pCookie->dataIntegrityCrcs.iCrc32Xlt = DC_DEFAULT_CRC; pCookie->dataIntegrityCrcs.xorFlags = DC_XOR_FLAGS_DEFAULT; pCookie->dataIntegrityCrcs.crcPoly = DC_CRC_POLY_DEFAULT; pCookie->dataIntegrityCrcs.xorOut = DC_XOR_OUT_DEFAULT; pCookie->dataIntegrityCrcs.deflateBlockType = DC_STATIC_TYPE; } else { pCookie->dataIntegrityCrcs.iCrc64Cpr = DC_DEFAULT_CRC; pCookie->dataIntegrityCrcs.oCrc64Cpr = DC_DEFAULT_CRC; pCookie->dataIntegrityCrcs.reflectIn = DC_REFLECT_IN_DEFAULT; pCookie->dataIntegrityCrcs.reflectOut = DC_REFLECT_OUT_DEFAULT; pCookie->dataIntegrityCrcs.oCrc64Xlt = DC_DEFAULT_CRC; pCookie->dataIntegrityCrcs.crc64Poly = DC_CRC64_POLY_DEFAULT; pCookie->dataIntegrityCrcs.xor64Out = DC_XOR64_OUT_DEFAULT; } crcMode = ICP_QAT_FW_COMP_CRC_MODE_E2E; } else { /* Legacy request structure */ if (pSetupData->checksum == CPA_DC_XXHASH32) { /* initial_adler field is also used for initializing xxhash */ pMsg->comp_pars.crc.legacy.initial_adler = initial_xxhash; } else { pMsg->comp_pars.crc.legacy.initial_adler = initial_adler; } pMsg->comp_pars.crc.legacy.initial_crc32 = initial_crc32; crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; } /* Populate the cmdFlags */ /* (LW 14 - 15) */ pCompReqParams = &(pMsg->comp_pars); dcCompRequestParamsPopulate(pCompReqParams, pCookie); if (flush == CPA_DC_FLUSH_FINAL) { bFinal = ICP_QAT_FW_COMP_BFINAL; } switch (cnvMode) { case DC_CNVNR: cnvRecovery = ICP_QAT_FW_COMP_CNV_RECOVERY; /* Fall through is intended here, because for CNVNR * cnvDecompReq also needs to be set */ case DC_CNV: cnvDecompReq = ICP_QAT_FW_COMP_CNV; if (CPA_TRUE == errorInjectionSupported) { cnvErrorInjection = pService->generic_service_info.ns_isCnvErrorInjection; } break; case DC_NO_CNV: cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; break; } /* LW 18 */ rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( sop, eop, bFinal, cnvDecompReq, cnvRecovery, cnvErrorInjection, crcMode, ICP_QAT_FW_COMP_NO_XXHASH_ACC, errorInjectionCode, ICP_QAT_FW_COMP_NO_APPEND_CRC, ICP_QAT_FW_COMP_NO_DROP_DATA, ICP_QAT_FW_COMP_NO_PARTIAL_DECOMPRESS); /* Clear the xxHash accumulator flag, as a rolling checksum isn't supported * in the NS API. */ ICP_QAT_FW_COMP_XXHASH_ACC_MODE_SET(rpCmdFlags, CPA_FALSE); pMsg->comp_pars.req_par_flags = rpCmdFlags; /* Populates the QAT common request middle part of the message * (LW 6 to 11) */ SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pMsg, pCookie, DC_DEFAULT_QAT_PTR_TYPE, srcAddrPhys, dstAddrPhys, 0, 0); return CPA_STATUS_SUCCESS; } STATIC CpaStatus dcNsCompDecompData(sal_compression_service_t *pService, CpaDcNsSetupData *pSetupData, CpaDcCallbackFn callbackFn, CpaInstanceHandle dcInstance, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, CpaDcOpData *pOpData, void *callbackTag, dc_request_dir_t compDecomp, dc_cnv_mode_t cnvMode) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus syncStatus = CPA_STATUS_SUCCESS; dc_compression_cookie_t *pCookie = NULL; lac_sync_op_data_t *pSyncCallbackData = NULL; CpaBoolean syncMode = CPA_FALSE; icp_comms_trans_handle trans_handle = NULL; if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = pService->trans_handle_compression_tx; } else { trans_handle = pService->trans_handle_decompression_tx; } if (!callbackFn) { syncMode = CPA_TRUE; } /* Allocate the compression cookie * The memory is freed in callback or in sendRequest if an error occurs */ do { if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc( pService->compression_mem_pool); } else { pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc( pService->decompression_mem_pool); } if (pCookie == NULL) { if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { LAC_LOG_ERROR("Cannot get mem pool entry for compression"); } else { LAC_LOG_ERROR("Cannot get mem pool entry for decompression"); } status = CPA_STATUS_RESOURCE; return status; } else if (pCookie == (void *)CPA_STATUS_RETRY) { /* Give back the control to the OS */ osalYield(); } } while (pCookie == (void *)CPA_STATUS_RETRY); if (syncMode == CPA_TRUE) { if (status == CPA_STATUS_SUCCESS) { status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (NULL == pSyncCallbackData) { LAC_LOG_ERROR("cannot create a sync cookie for compression."); status = CPA_STATUS_RESOURCE; /* Free the memory pool */ if (pCookie != NULL) { Lac_MemPoolEntryFree(pCookie); pCookie = NULL; } return status; } callbackFn = LacSync_GenWakeupSyncCaller; callbackTag = pSyncCallbackData; } } if (status == CPA_STATUS_SUCCESS) { /* For asynchronous - use the user supplied callback * for synchronous - use the internal synchronous callback */ pCookie->pCbFunc = callbackFn; status = dcNsCreateRequest(pCookie, pService, pSetupData, pSrcBuff, pDestBuff, pResults, flushFlag, pOpData, callbackTag, compDecomp, cnvMode); } if (status == CPA_STATUS_SUCCESS) { /* Send to QAT */ status = SalQatMsg_transPutMsg(trans_handle, (void *)&(pCookie->request), LAC_QAT_DC_REQ_SZ_LW, LAC_LOG_MSG_DC, NULL); } if (status == CPA_STATUS_SUCCESS) { if (compDecomp == DC_COMPRESSION_REQUEST) { COMPRESSION_STAT_INC(numCompRequests, pService); } else { COMPRESSION_STAT_INC(numDecompRequests, pService); } } else { if (compDecomp == DC_COMPRESSION_REQUEST) { COMPRESSION_STAT_INC(numCompRequestsErrors, pService); } else { COMPRESSION_STAT_INC(numDecompRequestsErrors, pService); } /* Free the memory pool */ if (pCookie != NULL) { Lac_MemPoolEntryFree(pCookie); pCookie = NULL; } } if (syncMode == CPA_TRUE) { if (status == CPA_STATUS_SUCCESS) { syncStatus = LacSync_WaitForCallback( pSyncCallbackData, DC_SYNC_CALLBACK_TIMEOUT, &status, NULL); /* If callback doesn't come back */ if (syncStatus != CPA_STATUS_SUCCESS) { if (compDecomp == DC_COMPRESSION_REQUEST) { COMPRESSION_STAT_INC(numCompCompletedErrors, pService); } else { COMPRESSION_STAT_INC(numDecompCompletedErrors, pService); } /* Free the memory pool */ if (pCookie != NULL) { Lac_MemPoolEntryFree(pCookie); pCookie = NULL; } LAC_LOG_ERROR("Callback timed out"); status = syncStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); } return status; } CpaStatus cpaDcNsDecompressData(CpaInstanceHandle dcInstance, CpaDcNsSetupData *pSetupData, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, CpaDcCallbackFn callbackFn, void *callbackTag) { sal_compression_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK Cpa64U srcBuffSize = 0; #endif #ifdef ICP_TRACE LAC_LOG8("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSetupData, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pResults, (LAC_ARCH_UINT)callbackFn, (LAC_ARCH_UINT)callbackTag); #endif if (dcInstance == CPA_INSTANCE_HANDLE_SINGLE) { dcInstance = dcGetFirstHandle(); } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(dcInstance); LAC_CHECK_NULL_PARAM(pSetupData); LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pResults); #endif pService = (sal_compression_service_t *)dcInstance; #ifdef ICP_PARAM_CHECK /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE( dcInstance, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); SAL_CHECK_ADDR_TRANS_SETUP(dcInstance); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(dcInstance); #ifdef ICP_PARAM_CHECK /* Check that the parameters defined in pSetupData are valid for the * device */ if (dcCheckSessionData((CpaDcSessionSetupData *)pSetupData, dcInstance) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (pSetupData->sessDirection != CPA_DC_DIR_DECOMPRESS) { LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); return CPA_STATUS_INVALID_PARAM; } if (pSetupData->sessState == CPA_DC_STATEFUL) { LAC_INVALID_PARAM_LOG("Stateful mode of operation not available"); return CPA_STATUS_INVALID_PARAM; } if (dcCheckOpData(pService, pOpData, pSetupData->sessDirection) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (pOpData->flushFlag == CPA_DC_FLUSH_NONE || pOpData->flushFlag == CPA_DC_FLUSH_SYNC) { LAC_INVALID_PARAM_LOG( "Flush flags specific to stateful mode of operation not allowed"); return CPA_STATUS_INVALID_PARAM; } if (LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } if (dcNsCheckSourceData(srcBuffSize) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (dcNsCheckDestinationData( pService, pSetupData, pDestBuff, DC_DECOMPRESSION_REQUEST) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (pSrcBuff == pDestBuff) { LAC_INVALID_PARAM_LOG("In place operation not supported"); return CPA_STATUS_INVALID_PARAM; } #endif return dcNsCompDecompData(pService, pSetupData, callbackFn, dcInstance, pSrcBuff, pDestBuff, pResults, pOpData->flushFlag, pOpData, callbackTag, DC_DECOMPRESSION_REQUEST, DC_NO_CNV); } CpaStatus cpaDcNsCompressData(CpaInstanceHandle dcInstance, CpaDcNsSetupData *pSetupData, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcOpData *pOpData, CpaDcRqResults *pResults, CpaDcCallbackFn callbackFn, void *callbackTag) { sal_compression_service_t *pService = NULL; CpaInstanceHandle insHandle = NULL; Cpa64U srcBuffSize = 0; dc_cnv_mode_t cnvMode = DC_CNV; LAC_CHECK_NULL_PARAM(pOpData); if (pOpData->compressAndVerify != CPA_TRUE) { LAC_INVALID_PARAM_LOG( "Data compression without verification not allowed"); return CPA_STATUS_UNSUPPORTED; } #ifdef ICP_TRACE LAC_LOG8("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSetupData, (LAC_ARCH_UINT)pSrcBuff, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pResults, (LAC_ARCH_UINT)callbackFn, (LAC_ARCH_UINT)callbackTag); #endif if (dcInstance == CPA_INSTANCE_HANDLE_SINGLE) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pSetupData); LAC_CHECK_NULL_PARAM(pResults); #endif pService = (sal_compression_service_t *)insHandle; #ifdef ICP_PARAM_CHECK /* Ensure this is a compression instance */ SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(insHandle); #ifdef ICP_PARAM_CHECK /* Check that the parameters defined in pSetupData are valid for the * device */ if (dcCheckSessionData((CpaDcSessionSetupData *)pSetupData, insHandle) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (pSetupData->sessDirection != CPA_DC_DIR_COMPRESS) { LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); return CPA_STATUS_INVALID_PARAM; } if (pSetupData->sessState == CPA_DC_STATEFUL) { LAC_INVALID_PARAM_LOG("Stateful mode of operation not available"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_LZ4 == pSetupData->compType && CPA_TRUE == pSetupData->accumulateXXHash) { LAC_INVALID_PARAM_LOG("Invalid accumulateXXHash value"); return CPA_STATUS_INVALID_PARAM; } if ((CPA_DC_LZ4 == pSetupData->compType) && (CPA_TRUE == pOpData->integrityCrcCheck)) { LAC_INVALID_PARAM_LOG("LZ4 with integrityCrcCheck is not supported" " in the compression direction"); return CPA_STATUS_INVALID_PARAM; } if (dcCheckOpData(pService, pOpData, pSetupData->sessDirection) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (pOpData->compressAndVerifyAndRecover != CPA_TRUE && pOpData->compressAndVerifyAndRecover != CPA_FALSE) { return CPA_STATUS_INVALID_PARAM; } if (pOpData->compressAndVerify == CPA_FALSE && pOpData->compressAndVerifyAndRecover == CPA_TRUE) { return CPA_STATUS_INVALID_PARAM; } if (pOpData->flushFlag == CPA_DC_FLUSH_NONE || pOpData->flushFlag == CPA_DC_FLUSH_SYNC) { LAC_INVALID_PARAM_LOG( "Flush flags specific to stateful mode of operation not allowed"); return CPA_STATUS_INVALID_PARAM; } #endif /* This check is outside the parameter checking as it is needed to manage * zero length requests */ if (LacBuffDesc_BufferListVerifyNull( pSrcBuff, &srcBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); return CPA_STATUS_INVALID_PARAM; } #ifdef ICP_PARAM_CHECK if (dcNsCheckSourceData(srcBuffSize) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (dcNsCheckDestinationData( pService, pSetupData, pDestBuff, DC_COMPRESSION_REQUEST) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } if (pSrcBuff == pDestBuff) { LAC_INVALID_PARAM_LOG("In place operation not supported"); return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_DC_DYN_NOT_SUPPORTED if (pSetupData->huffType == CPA_DC_HT_FULL_DYNAMIC) { LAC_INVALID_PARAM_LOG("Invalid huffType value, dynamic compression " "not supported"); return CPA_STATUS_INVALID_PARAM; } #endif if (!(pService->dc_capabilities.cnv.supported) && (CPA_TRUE == pOpData->compressAndVerify)) { LAC_INVALID_PARAM_LOG("CompressAndVerify feature not supported"); return CPA_STATUS_UNSUPPORTED; } if (!(pService->dc_capabilities.cnv.recovery) && (CPA_TRUE == pOpData->compressAndVerifyAndRecover)) { LAC_INVALID_PARAM_LOG("CompressAndVerify feature not supported"); return CPA_STATUS_UNSUPPORTED; } if (CPA_TRUE == pOpData->compressAndVerifyAndRecover) { cnvMode = DC_CNVNR; } return dcNsCompDecompData(pService, pSetupData, callbackFn, insHandle, pSrcBuff, pDestBuff, pResults, pOpData->flushFlag, pOpData, callbackTag, DC_COMPRESSION_REQUEST, cnvMode); } CpaStatus dcNsSetCnvErrorInj(CpaInstanceHandle dcInstance, CpaBoolean enableCnvErrInj) { CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; dc_capabilities_t *pDcCapabilities = NULL; CpaBoolean errorInjectionSupported = CPA_FALSE; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; pDcCapabilities = &pService->dc_capabilities; errorInjectionSupported = pDcCapabilities->cnv.errorInjection; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pService); #endif if (CPA_FALSE == errorInjectionSupported) { LAC_ENSURE(CPA_FALSE, "Unsupported compression feature.\n"); return CPA_STATUS_UNSUPPORTED; } if (CPA_TRUE == enableCnvErrInj) { pService->generic_service_info.ns_isCnvErrorInjection = ICP_QAT_FW_COMP_CNV_DFX; } else { pService->generic_service_info.ns_isCnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX; } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_ns_header_footer.c000066400000000000000000000162701503624047500326700ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_ns_header_footer.c * * @ingroup Dc_DataCompression * * @description * Implementation of the No-Session (NS) variant of the Data Compression * header and footer operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_header_footer.h" #include "dc_header_footer_lz4.h" #include "dc_session.h" CpaStatus cpaDcNsGenerateHeader(CpaDcNsSetupData *pSetupData, CpaFlatBuffer *pDestBuff, Cpa32U *count) { CpaStatus ret = CPA_STATUS_FAIL; #ifdef ICP_TRACE if (NULL == count) { LAC_LOG3("Called with params (0x%1x, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)pSetupData, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)count); } else { LAC_LOG4("Called with params (0x%1x, 0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)pSetupData, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)count, *count); } #endif #ifdef ICP_PARAM_CHECK /* Check parameters */ LAC_CHECK_NULL_PARAM(pSetupData); LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(pDestBuff->pData); LAC_CHECK_NULL_PARAM(count); if (pSetupData->compLevel < CPA_DC_L1 || pSetupData->compLevel > CPA_DC_L12) { LAC_INVALID_PARAM_LOG("Invalid compression level"); return CPA_STATUS_INVALID_PARAM; } #endif switch (pSetupData->compType) { case CPA_DC_DEFLATE: ret = dcDeflateGenerateHeader( pDestBuff, pSetupData->checksum, pSetupData->compLevel, count); if (CPA_STATUS_SUCCESS != ret) return ret; break; case CPA_DC_LZ4: if (CPA_DC_XXHASH32 == pSetupData->checksum) { ret = dc_lz4_generate_header(pDestBuff, pSetupData->lz4BlockMaxSize, pSetupData->lz4BlockIndependence, count); if (CPA_STATUS_SUCCESS != ret) return ret; } break; default: /* There is no header for other compression formats */ *count = 0; } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcNsGenerateFooter(CpaDcNsSetupData *pSetupData, Cpa64U totalLength, CpaFlatBuffer *pDestBuff, CpaDcRqResults *pResults) { CpaStatus ret = CPA_STATUS_FAIL; #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%1x, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)pSetupData, (LAC_ARCH_UINT)totalLength, (LAC_ARCH_UINT)pDestBuff, (LAC_ARCH_UINT)pResults); #endif #ifdef ICP_PARAM_CHECK /* Check parameters */ LAC_CHECK_NULL_PARAM(pSetupData); LAC_CHECK_NULL_PARAM(pDestBuff); LAC_CHECK_NULL_PARAM(pDestBuff->pData); LAC_CHECK_NULL_PARAM(pResults); #endif switch (pSetupData->compType) { case CPA_DC_DEFLATE: ret = dcDeflateGenerateFooter( pDestBuff, pResults, totalLength, pSetupData->checksum); if (CPA_STATUS_SUCCESS != ret) return ret; break; case CPA_DC_LZ4: if (CPA_DC_XXHASH32 == pSetupData->checksum) { ret = dc_lz4_generate_footer(pDestBuff, pResults); if (ret != CPA_STATUS_SUCCESS) return ret; pResults->produced += DC_LZ4_FOOTER_SIZE; } break; default: LAC_INVALID_PARAM_LOG("Invalid compression type"); return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_session.c000066400000000000000000002572111503624047500310470ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_session.c * * @ingroup Dc_DataCompression * * @description * Implementation of the Data Compression session operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" #include "icp_qat_fw.h" #include "icp_qat_fw_comp.h" #include "icp_qat_hw.h" #include "icp_qat_hw_20_comp.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_session.h" #include "dc_datapath.h" #include "dc_capabilities.h" #include "lac_mem_pools.h" #include "sal_types_compression.h" #include "lac_buffer_desc.h" #include "sal_service_state.h" #include "sal_qat_cmn_msg.h" #include "dc_crc64.h" #ifdef ICP_PARAM_CHECK /** ***************************************************************************** * @ingroup Dc_DataCompression * Check supported session data * * @description * Check that all the parameters defined in the pSessionData are * supported * * @param[in] pSessionData Pointer to a user instantiated structure * containing session data * @param[in] dcInstance DC Instance Handle * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_UNSUPPORTED Unsupported feature * @retval CPA_STATUS_INVALID_PARAM Invalid parameter * *****************************************************************************/ STATIC CpaStatus dcCheckUnsupportedParams(const CpaDcSessionSetupData *pSessionData, CpaInstanceHandle dcInstance) { sal_compression_service_t *pCompService = (sal_compression_service_t *)dcInstance; dc_capabilities_t *pDcCapabilities = &pCompService->dc_capabilities; CpaBoolean deflateSupported = CPA_FALSE; CpaBoolean lz4Supported = CPA_FALSE; CpaBoolean lz4sSupported = CPA_FALSE; CpaBoolean staticSupported = CPA_FALSE; CpaBoolean dynamicSupported = CPA_FALSE; Cpa8U huffmanTypeSupport = 0; CpaBoolean asbEnablePref = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; switch (pCompService->generic_service_info.type) { case SAL_SERVICE_TYPE_COMPRESSION: if (CPA_FALSE == pDcCapabilities->deviceData.compressionServiceSupported) { LAC_UNSUPPORTED_PARAM_LOG("Dc capability not supported"); return CPA_STATUS_UNSUPPORTED; } break; case SAL_SERVICE_TYPE_DECOMPRESSION: if (CPA_FALSE == pDcCapabilities->deviceData.decompressionServiceSupported) { LAC_UNSUPPORTED_PARAM_LOG("Decomp capability not supported"); return CPA_STATUS_UNSUPPORTED; } break; default: LAC_INVALID_PARAM_LOG("Invalid service type for compression"); return CPA_STATUS_INVALID_PARAM; } deflateSupported = pDcCapabilities->deflate.supported; lz4Supported = pDcCapabilities->lz4.supported; lz4sSupported = pDcCapabilities->lz4s.supported; switch (pSessionData->compType) { case CPA_DC_DEFLATE: if (CPA_FALSE == deflateSupported) { LAC_UNSUPPORTED_PARAM_LOG( "Deflate algorithm not supported on current instance"); return CPA_STATUS_UNSUPPORTED; } /* Retrieve internal capabilities */ huffmanTypeSupport = pDcCapabilities->deflate.typeSupport; staticSupported = DC_CAPS_DEFLATE_TYPE_SUPPORT_GET( huffmanTypeSupport, DC_CAPS_DEFLATE_TYPE_STATIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); dynamicSupported = DC_CAPS_DEFLATE_TYPE_SUPPORT_GET( huffmanTypeSupport, DC_CAPS_DEFLATE_TYPE_DYNAMIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); if ((CPA_DC_HT_STATIC == pSessionData->huffType) && (CPA_FALSE == staticSupported)) { LAC_UNSUPPORTED_PARAM_LOG( "Static huffman encoding not supported " "on current instance"); return CPA_STATUS_UNSUPPORTED; } if ((CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) && (CPA_FALSE == dynamicSupported)) { LAC_UNSUPPORTED_PARAM_LOG( "Dynamic huffman encoding not supported " "on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_COMPRESS == pSessionData->sessDirection && !(pDcCapabilities->deflate.dirMask & DC_CAPS_COMPRESSION)) { LAC_UNSUPPORTED_PARAM_LOG("Deflate compression direction not " "supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_DECOMPRESS == pSessionData->sessDirection && !(pDcCapabilities->deflate.dirMask & DC_CAPS_DECOMPRESSION)) { LAC_UNSUPPORTED_PARAM_LOG("Deflate decompression direction not " "supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_COMBINED == pSessionData->sessDirection && (!(pDcCapabilities->deflate.dirMask & DC_CAPS_COMPRESSION) || !(pDcCapabilities->deflate.dirMask & DC_CAPS_DECOMPRESSION))) { LAC_UNSUPPORTED_PARAM_LOG("Deflate not supported for combined " "sessions on current instance"); return CPA_STATUS_UNSUPPORTED; } break; case CPA_DC_LZ4: if (CPA_FALSE == lz4Supported) { LAC_UNSUPPORTED_PARAM_LOG( "LZ4 algorithm not supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_FALSE == pDcCapabilities->lz4.accumulateXXHash && CPA_TRUE == pSessionData->accumulateXXHash) { LAC_UNSUPPORTED_PARAM_LOG( "XXHash32 Accumulate not supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_COMPRESS == pSessionData->sessDirection && !(pDcCapabilities->lz4.dirMask & DC_CAPS_COMPRESSION)) { LAC_UNSUPPORTED_PARAM_LOG( "LZ4 compression direction not supported " "on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_DECOMPRESS == pSessionData->sessDirection && !(pDcCapabilities->lz4.dirMask & DC_CAPS_DECOMPRESSION)) { LAC_UNSUPPORTED_PARAM_LOG("LZ4 decompression direction not " "supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_COMBINED == pSessionData->sessDirection && (!(pDcCapabilities->lz4.dirMask & DC_CAPS_COMPRESSION) || !(pDcCapabilities->lz4.dirMask & DC_CAPS_DECOMPRESSION))) { LAC_UNSUPPORTED_PARAM_LOG( "LZ4 not supported for combined sessions " "on current instance"); return CPA_STATUS_UNSUPPORTED; } break; case CPA_DC_LZ4S: if (CPA_FALSE == lz4sSupported) { LAC_UNSUPPORTED_PARAM_LOG( "LZ4s algorithm not supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_COMPRESS == pSessionData->sessDirection && !(pDcCapabilities->lz4s.dirMask & DC_CAPS_COMPRESSION)) { LAC_UNSUPPORTED_PARAM_LOG("LZ4s compression direction not " "supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_DECOMPRESS == pSessionData->sessDirection && !(pDcCapabilities->lz4s.dirMask & DC_CAPS_DECOMPRESSION)) { LAC_UNSUPPORTED_PARAM_LOG("LZ4s decompression direction not " "supported on current instance"); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_DIR_COMBINED == pSessionData->sessDirection && (!(pDcCapabilities->lz4s.dirMask & DC_CAPS_COMPRESSION) || !(pDcCapabilities->lz4s.dirMask & DC_CAPS_DECOMPRESSION))) { LAC_UNSUPPORTED_PARAM_LOG("LZ4s not supported for combined " "sessions on current instance"); return CPA_STATUS_UNSUPPORTED; } break; default: LAC_INVALID_PARAM_LOG("Invalid compType value"); return CPA_STATUS_INVALID_PARAM; } /* Retrieve capability */ if (CPA_DC_DIR_COMPRESS == pSessionData->sessDirection) { status = dcGetAsbEnablePrefCapabilityStatus( pDcCapabilities, pSessionData->compType, &asbEnablePref); if (CPA_STATUS_SUCCESS != status) { return status; } if ((pSessionData->autoSelectBestHuffmanTree == CPA_DC_ASB_DISABLED) && (CPA_TRUE == asbEnablePref)) { LAC_UNSUPPORTED_PARAM_LOG( "CPA_DC_ASB_DISABLED is not supported.\n"); return CPA_STATUS_UNSUPPORTED; } } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Check that pSessionData is valid * * @description * Check that all the parameters defined in the pSessionData are valid * * @param[in] pSessionData Pointer to a user instantiated structure * containing session data * @param[in] dcInstance DC Instance Handle * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_UNSUPPORTED Unsupported algorithm/feature * *****************************************************************************/ CpaStatus dcCheckSessionData(const CpaDcSessionSetupData *pSessionData, CpaInstanceHandle dcInstance) { CpaStatus status = CPA_STATUS_FAIL; CpaDcInstanceCapabilities instanceCapabilities = {0}; sal_compression_service_t *pService = (sal_compression_service_t *)dcInstance; dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; cpaDcQueryCapabilities(dcInstance, &instanceCapabilities); status = dcCheckUnsupportedParams(pSessionData, dcInstance); if (CPA_STATUS_SUCCESS != status) { LAC_INVALID_PARAM_LOG("Trying to set unsupported features"); return status; } if ((pSessionData->compLevel < CPA_DC_L1) || (pSessionData->compLevel > CPA_DC_L12)) { LAC_INVALID_PARAM_LOG("Invalid compLevel value"); return CPA_STATUS_INVALID_PARAM; } if ((pSessionData->autoSelectBestHuffmanTree < CPA_DC_ASB_DISABLED) || (pSessionData->autoSelectBestHuffmanTree > CPA_DC_ASB_ENABLED)) { LAC_INVALID_PARAM_LOG("Invalid autoSelectBestHuffmanTree value"); return CPA_STATUS_INVALID_PARAM; } if ((pSessionData->huffType < CPA_DC_HT_STATIC) || (pSessionData->huffType > CPA_DC_HT_FULL_DYNAMIC) || (CPA_DC_HT_PRECOMP == pSessionData->huffType)) { LAC_INVALID_PARAM_LOG("Invalid huffType value"); return CPA_STATUS_INVALID_PARAM; } if ((pSessionData->sessDirection < CPA_DC_DIR_COMPRESS) || (pSessionData->sessDirection > CPA_DC_DIR_COMBINED)) { LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); return CPA_STATUS_INVALID_PARAM; } if ((pService->generic_service_info.type == SAL_SERVICE_TYPE_DECOMPRESSION) && ((pSessionData->sessDirection == CPA_DC_DIR_COMPRESS) || (pSessionData->sessDirection == CPA_DC_DIR_COMBINED))) { LAC_INVALID_PARAM_LOG("Invalid Service Type and SessDirection"); return CPA_STATUS_INVALID_PARAM; } if ((pService->generic_service_info.type == SAL_SERVICE_TYPE_DECOMPRESSION) && (pSessionData->sessState == CPA_DC_STATEFUL)) { LAC_INVALID_PARAM_LOG("Invalid Service Type and sessState"); return CPA_STATUS_INVALID_PARAM; } if ((pSessionData->sessState < CPA_DC_STATEFUL) || (pSessionData->sessState > CPA_DC_STATELESS)) { LAC_INVALID_PARAM_LOG("Invalid sessState value"); return CPA_STATUS_INVALID_PARAM; } if ((pSessionData->checksum < CPA_DC_NONE) || (pSessionData->checksum > CPA_DC_XXHASH32)) { LAC_INVALID_PARAM_LOG("Invalid checksum value"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_XXHASH32 == pSessionData->checksum && CPA_DC_DEFLATE == pSessionData->compType) { LAC_INVALID_PARAM_LOG("Invalid checksum type for DEFLATE compression"); return CPA_STATUS_INVALID_PARAM; } if ((CPA_DC_LZ4 == pSessionData->compType) && (CPA_DC_XXHASH32 != pSessionData->checksum) && (CPA_DC_NONE != pSessionData->checksum)) { LAC_INVALID_PARAM_LOG("Invalid checksum type for LZ4 compression"); return CPA_STATUS_INVALID_PARAM; } if ((CPA_DC_LZ4S == pSessionData->compType) && (CPA_DC_NONE != pSessionData->checksum) && (CPA_DC_XXHASH32 != pSessionData->checksum)) { LAC_INVALID_PARAM_LOG("Invalid checksum type for LZ4S compression"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_LZ4 == pSessionData->compType) { if ((pSessionData->lz4BlockMaxSize < CPA_DC_LZ4_MAX_BLOCK_SIZE_64K) || (pSessionData->lz4BlockMaxSize > CPA_DC_LZ4_MAX_BLOCK_SIZE_4M)) { LAC_INVALID_PARAM_LOG("Invalid LZ4 Block Max Size value."); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE != pSessionData->lz4BlockChecksum && CPA_TRUE != pSessionData->lz4BlockChecksum) { LAC_INVALID_PARAM_LOG("Invalid LZ4 Block checksum setting."); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE != pSessionData->lz4BlockIndependence && CPA_TRUE != pSessionData->lz4BlockIndependence) { LAC_INVALID_PARAM_LOG("Invalid LZ4 Block independence setting."); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE != pSessionData->accumulateXXHash && CPA_TRUE != pSessionData->accumulateXXHash) { LAC_INVALID_PARAM_LOG("Invalid LZ4 accumulateXXHash setting."); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection && (!((1 << (pSessionData->lz4BlockMaxSize)) & pDcCapabilities->lz4.maxBlockSize))) { LAC_UNSUPPORTED_PARAM_LOG("UnSupported LZ4 Block Max Size value"); return CPA_STATUS_UNSUPPORTED; } } if (CPA_DC_LZ4S == pSessionData->compType) { if ((pSessionData->minMatch < CPA_DC_MIN_3_BYTE_MATCH) || (pSessionData->minMatch > CPA_DC_MIN_4_BYTE_MATCH)) { LAC_INVALID_PARAM_LOG("Invalid LZ4S Min match value."); return CPA_STATUS_INVALID_PARAM; } } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Check that pCrcControlData is valid * * @description * Check that all the parameters defined in the pCrcControlData are valid * * @param[in] pCrcControlData Pointer to a user instantiated structure * containing session CRC control data. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ CpaStatus dcCheckSessionCrcControlData(const CpaCrcControlData *pCrcControlData) { /* CRC polynomial must not be zero */ if (pCrcControlData->polynomial == 0) { LAC_INVALID_PARAM_LOG("Invalid CRC polynomial value = 0"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif static void setBlockIndep(icp_qat_hw_comp_20_config_csr_upper_t *conf) { conf->scb_mode_reset = ICP_QAT_HW_COMP_20_SCB_MODE_RESET_MASK_RESET_COUNTERS_AND_HISTORY; } static void setBlockDep(icp_qat_hw_comp_20_config_csr_upper_t *conf) { conf->scb_mode_reset = ICP_QAT_HW_COMP_20_SCB_MODE_RESET_MASK_RESET_COUNTERS; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Populate the compression hardware block * * @description * This function will populate the compression hardware block and update * the size in bytes of the block * * @param[in] pService Pointer to the service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in] pCompConfig Pointer to slice config word * @param[in] compDecomp Direction of the operation * *****************************************************************************/ void dcCompHwBlockPopulate(void *pServiceType, void *pSessionDescp, CpaDcNsSetupData *pSetupData, icp_qat_hw_compression_config_t *pCompConfig, void *compDecompDir, CpaBoolean bNsOp) { icp_qat_hw_compression_direction_t dir = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS; icp_qat_hw_compression_algo_t algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE; icp_qat_hw_compression_depth_t depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; icp_qat_hw_compression_file_type_t filetype = ICP_QAT_HW_COMPRESSION_FILE_TYPE_0; icp_qat_hw_compression_delayed_match_t dmm; sal_compression_service_t *pService = NULL; dc_capabilities_t *pDcCapabilities = NULL; dc_session_desc_t *pSessionDesc = NULL; dc_request_dir_t compDecomp; pService = (sal_compression_service_t *)pServiceType; pSessionDesc = (dc_session_desc_t *)pSessionDescp; pDcCapabilities = &pService->dc_capabilities; compDecomp = *(dc_request_dir_t *)compDecompDir; /* Set the direction */ if (DC_COMPRESSION_REQUEST == compDecomp) { dir = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS; } else { dir = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS; } if (CPA_DC_DEFLATE == pSessionDesc->compType) { algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE; } else { LAC_LOG_ERROR("Algorithm not supported for Compression\n"); } /* Set delay match mode */ if (CPA_TRUE == pDcCapabilities->deviceData.enableDmm) { dmm = ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; } else { dmm = ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED; } /* Set the depth */ if (DC_DECOMPRESSION_REQUEST == compDecomp) { depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; } else { switch (pSessionDesc->compLevel) { case CPA_DC_L1: depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; break; case CPA_DC_L2: depth = ICP_QAT_HW_COMPRESSION_DEPTH_4; break; case CPA_DC_L3: depth = ICP_QAT_HW_COMPRESSION_DEPTH_8; break; default: depth = ICP_QAT_HW_COMPRESSION_DEPTH_16; } } /* The file type is set to ICP_QAT_HW_COMPRESSION_FILE_TYPE_0. The other * modes will be used in the future for precompiled huffman trees */ filetype = ICP_QAT_HW_COMPRESSION_FILE_TYPE_0; pCompConfig->lower_val = ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(dir, dmm, algo, depth, filetype); /* Upper 32-bits of the configuration word do not need to be * configured with legacy devices. */ pCompConfig->upper_val = 0; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Populate the compression hardware block for QAT Gen4 * * @description * This function will populate the compression hardware block and update * for QAT Gen4 the size in bytes of the block * * @param[in] pService Pointer to the service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in] pSetupData Pointer to setup data * @param[in] pCompConfig Pointer to slice config word * @param[in] compDecomp Direction of the operation * @param[in] bNsOp Boolean to indicate no session operation * *****************************************************************************/ void dcCompHwBlockPopulateGen4(void *pServiceType, void *pSessionDescp, CpaDcNsSetupData *pSetupData, icp_qat_hw_compression_config_t *pCompConfig, void *compDecompDir, CpaBoolean bNsOp) { CpaDcCompType compType = 0; CpaDcCompLvl compLevel = 0; CpaDcHuffType huffType; CpaDcCompMinMatch minMatch; CpaDcCompLZ4BlockMaxSize lz4BlockMaxSize; CpaBoolean lz4BlockChecksum, lz4BlockIndependence; sal_compression_service_t *pService = NULL; dc_capabilities_t *pDcCapabilities = NULL; dc_session_desc_t *pSessionDesc = NULL; dc_request_dir_t compDecomp; pService = (sal_compression_service_t *)pServiceType; pSessionDesc = (dc_session_desc_t *)pSessionDescp; pDcCapabilities = &pService->dc_capabilities; compDecomp = *(dc_request_dir_t *)compDecompDir; if (bNsOp) { compType = pSetupData->compType; compLevel = pSetupData->compLevel; huffType = pSetupData->huffType; minMatch = pSetupData->minMatch; lz4BlockMaxSize = pSetupData->lz4BlockMaxSize; lz4BlockChecksum = pSetupData->lz4BlockChecksum; lz4BlockIndependence = pSetupData->lz4BlockIndependence; } else { compType = pSessionDesc->compType; compLevel = pSessionDesc->compLevel; huffType = pSessionDesc->huffType; minMatch = pSessionDesc->minMatch; lz4BlockMaxSize = pSessionDesc->lz4BlockMaxSize; lz4BlockChecksum = pSessionDesc->lz4BlockChecksum; lz4BlockIndependence = pSessionDesc->lz4BlockIndependence; } /* Direction: Compression */ if (DC_COMPRESSION_REQUEST == compDecomp) { icp_qat_hw_comp_20_config_csr_upper_t hw_comp_upper_csr; icp_qat_hw_comp_20_config_csr_lower_t hw_comp_lower_csr; osalMemSet(&hw_comp_upper_csr, 0, sizeof hw_comp_upper_csr); osalMemSet(&hw_comp_lower_csr, 0, sizeof hw_comp_lower_csr); /* Disable Literal + Length Limit Block Drop by default */ hw_comp_lower_csr.lllbd = ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_DISABLED; switch (compType) { case CPA_DC_DEFLATE: /* DEFLATE algorithm settings */ hw_comp_lower_csr.skip_ctrl = ICP_QAT_HW_COMP_20_BYTE_SKIP_3BYTE_LITERAL; if (CPA_DC_HT_FULL_DYNAMIC == huffType) { hw_comp_lower_csr.algo = ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_ILZ77; } else /* Static DEFLATE */ { hw_comp_lower_csr.algo = ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_DEFLATE; hw_comp_upper_csr.scb_ctrl = ICP_QAT_HW_COMP_20_SCB_CONTROL_DISABLE; } break; case CPA_DC_LZ4: /* LZ4 algorithm settings */ hw_comp_lower_csr.algo = ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_LZ4; hw_comp_upper_csr.lbms = (icp_qat_hw_comp_20_lbms_t)lz4BlockMaxSize; hw_comp_lower_csr.mmctrl = ICP_QAT_HW_COMP_20_MIN_MATCH_CONTROL_MATCH_4B; if (CPA_TRUE == lz4BlockIndependence) { setBlockIndep(&hw_comp_upper_csr); } else { setBlockDep(&hw_comp_upper_csr); } break; case CPA_DC_LZ4S: /* LZ4S algorithm settings */ hw_comp_lower_csr.algo = ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_LZ4S; hw_comp_lower_csr.mmctrl = (icp_qat_hw_comp_20_min_match_control_t)minMatch; hw_comp_upper_csr.scb_ctrl = ICP_QAT_HW_COMP_20_SCB_CONTROL_DISABLE; break; default: LAC_LOG_ERROR("Compression algorithm not supported\n"); break; } /* Set the search depth */ switch (compLevel) { case CPA_DC_L1: case CPA_DC_L2: case CPA_DC_L3: case CPA_DC_L4: case CPA_DC_L5: hw_comp_lower_csr.sd = ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_1; hw_comp_lower_csr.hash_col = ICP_QAT_HW_COMP_20_SKIP_HASH_COLLISION_DONT_ALLOW; break; case CPA_DC_L6: case CPA_DC_L7: case CPA_DC_L8: hw_comp_lower_csr.sd = ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_6; break; case CPA_DC_L9: hw_comp_lower_csr.sd = ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_9; break; default: hw_comp_lower_csr.sd = pDcCapabilities->deviceData.highestHwCompressionDepth; if ((CPA_DC_HT_FULL_DYNAMIC == huffType) && (CPA_DC_DEFLATE == compType)) { /* Enable Literal + Length Limit Block Drop * with dynamic deflate compression when * highest compression levels are selected. */ hw_comp_lower_csr.lllbd = ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_ENABLED; } break; } /* Same for all algorithms */ hw_comp_lower_csr.abd = ICP_QAT_HW_COMP_20_ABD_ABD_DISABLED; hw_comp_lower_csr.hash_update = ICP_QAT_HW_COMP_20_SKIP_HASH_UPDATE_DONT_ALLOW; hw_comp_lower_csr.edmm = (CPA_TRUE == pDcCapabilities->deviceData.enableDmm) ? ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_ENABLED : ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_DISABLED; /* Enable Adaptive Block Drop with dynamic deflate * compression when levels 10-12 are selected. * This field is ignored by firmware for devices that * do not support adaptive block drop */ if ((CPA_DC_HT_FULL_DYNAMIC == huffType) && (CPA_DC_DEFLATE == compType) && (CPA_DC_L10 == compLevel || CPA_DC_L11 == compLevel || CPA_DC_L12 == compLevel)) { hw_comp_lower_csr.abd = ICP_QAT_HW_COMP_20_ABD_ABD_ENABLED; } /* Hard-coded HW-specific values */ hw_comp_upper_csr.nice = ICP_QAT_HW_COMP_20_CONFIG_CSR_NICE_PARAM_DEFAULT_VAL; hw_comp_upper_csr.lazy = ICP_QAT_HW_COMP_20_CONFIG_CSR_LAZY_PARAM_DEFAULT_VAL; pCompConfig->upper_val = ICP_QAT_FW_COMP_20_BUILD_CONFIG_UPPER(hw_comp_upper_csr); pCompConfig->lower_val = ICP_QAT_FW_COMP_20_BUILD_CONFIG_LOWER(hw_comp_lower_csr); } else /* Direction: Decompression */ { icp_qat_hw_decomp_20_config_csr_lower_t hw_decomp_lower_csr; osalMemSet(&hw_decomp_lower_csr, 0, sizeof hw_decomp_lower_csr); /* Set the algorithm */ if (CPA_DC_DEFLATE == compType) { hw_decomp_lower_csr.algo = ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_DEFLATE; } else if (CPA_DC_LZ4 == compType) { hw_decomp_lower_csr.algo = (icp_qat_hw_decomp_20_hw_comp_format_t) ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_LZ4; hw_decomp_lower_csr.lbms = (icp_qat_hw_decomp_20_lbms_t)lz4BlockMaxSize; if (CPA_TRUE == lz4BlockChecksum) { hw_decomp_lower_csr.lbc = ICP_QAT_HW_DECOMP_20_LZ4_BLOCK_CHKSUM_PRESENT; } else { hw_decomp_lower_csr.lbc = ICP_QAT_HW_DECOMP_20_LZ4_BLOCK_CHKSUM_ABSENT; } } else if (CPA_DC_LZ4S == compType) { hw_decomp_lower_csr.algo = (icp_qat_hw_decomp_20_hw_comp_format_t) ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_LZ4S; hw_decomp_lower_csr.mmctrl = (icp_qat_hw_decomp_20_min_match_control_t)minMatch; } else { LAC_LOG_ERROR("Algorithm not supported for Decompression\n"); } pCompConfig->upper_val = 0; pCompConfig->lower_val = ICP_QAT_FW_DECOMP_20_BUILD_CONFIG_LOWER(hw_decomp_lower_csr); } } /** ***************************************************************************** * @ingroup Dc_DataCompression * Populate the compression content descriptor * * @description * This function will populate the compression content descriptor * * @param[in] pService Pointer to the service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in] contextBufferAddrPhys Physical address of the context buffer * @param[out] pMsg Pointer to the compression message * @param[in] nextSlice Next slice * @param[in] compDecomp Direction of the operation * *****************************************************************************/ STATIC void dcCompContentDescPopulate(sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc, CpaPhysicalAddr contextBufferAddrPhys, icp_qat_fw_comp_req_t *pMsg, icp_qat_fw_slice_t nextSlice, dc_request_dir_t compDecomp) { icp_qat_fw_comp_cd_hdr_t *pCompControlBlock = NULL; icp_qat_hw_compression_config_t *pCompConfig = NULL; CpaBoolean bankEnabled = CPA_FALSE; /* Retrieve internal capabilities */ dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; LAC_ENSURE_NOT_NULL(pService); LAC_ENSURE_NOT_NULL(pSessionDesc); LAC_ENSURE_NOT_NULL(pMsg); pCompControlBlock = (icp_qat_fw_comp_cd_hdr_t *)&(pMsg->comp_cd_ctrl); pCompConfig = (icp_qat_hw_compression_config_t *)(pMsg->cd_pars.sl .comp_slice_cfg_word); ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, nextSlice); ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP); pCompControlBlock->comp_cfg_offset = 0; if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && (CPA_DC_DEFLATE == pSessionDesc->compType) && (DC_DECOMPRESSION_REQUEST == compDecomp)) { /* Enable A, B, C, D, and E (CAMs). */ pCompControlBlock->ram_bank_flags = ICP_QAT_FW_COMP_RAM_FLAGS_BUILD( ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */ ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank E */ ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank D */ ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank C */ ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank B */ ICP_QAT_FW_COMP_BANK_ENABLED); /* Bank A */ bankEnabled = CPA_TRUE; } else if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && (CPA_DC_LZ4 == pSessionDesc->compType) && (DC_DECOMPRESSION_REQUEST == compDecomp)) { /* Enable A, B, C, and D (no CAMs for LZ4). */ pCompControlBlock->ram_bank_flags = ICP_QAT_FW_COMP_RAM_FLAGS_BUILD( ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank E */ ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank D */ ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank C */ ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank B */ ICP_QAT_FW_COMP_BANK_ENABLED); /* Bank A */ bankEnabled = CPA_TRUE; } else { /* Disable all banks */ pCompControlBlock->ram_bank_flags = ICP_QAT_FW_COMP_RAM_FLAGS_BUILD( ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank E */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank D */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank C */ ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank B */ ICP_QAT_FW_COMP_BANK_DISABLED); /* Bank A */ } if (DC_COMPRESSION_REQUEST == compDecomp) { LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( pService->generic_service_info, pCompControlBlock->comp_state_addr, pSessionDesc->stateRegistersComp); } else { LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( pService->generic_service_info, pCompControlBlock->comp_state_addr, pSessionDesc->stateRegistersDecomp); } if (CPA_TRUE == bankEnabled) { pCompControlBlock->ram_banks_addr = contextBufferAddrPhys; } else { pCompControlBlock->ram_banks_addr = 0; } pCompControlBlock->resrvd = 0; /* Populate Compression Hardware Setup Block */ (pDcCapabilities->dcCompHwBlockPopulate)((void *)pService, (void *)pSessionDesc, NULL, pCompConfig, (void *)&compDecomp, CPA_FALSE); } /** ***************************************************************************** * @ingroup Dc_DataCompression * Populate the translator content descriptor * * @description * This function will populate the translator content descriptor * * @param[out] pMsg Pointer to the compression message * @param[in] nextSlice Next slice * *****************************************************************************/ void dcTransContentDescPopulate(icp_qat_fw_comp_req_t *pMsg, icp_qat_fw_slice_t nextSlice) { icp_qat_fw_xlt_cd_hdr_t *pTransControlBlock = NULL; LAC_ENSURE_NOT_NULL(pMsg); pTransControlBlock = (icp_qat_fw_xlt_cd_hdr_t *)&(pMsg->u2.xlt_cd_ctrl); LAC_ENSURE_NOT_NULL(pTransControlBlock); ICP_QAT_FW_COMN_NEXT_ID_SET(pTransControlBlock, nextSlice); ICP_QAT_FW_COMN_CURR_ID_SET(pTransControlBlock, ICP_QAT_FW_SLICE_XLAT); pTransControlBlock->resrvd1 = 0; pTransControlBlock->resrvd2 = 0; pTransControlBlock->resrvd3 = 0; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Get the context size and the history size * * @description * This function will get the size of the context buffer and the history * buffer. The history buffer is a subset of the context buffer and its * size is needed for stateful compression. * @param[in] dcInstance DC Instance Handle * * @param[in] pSessionData Pointer to a user instantiated * structure containing session data * @param[out] pContextSize Pointer to the context size * * @retval CPA_STATUS_SUCCESS Function executed successfully * * *****************************************************************************/ STATIC CpaStatus dcGetContextSize(CpaInstanceHandle dcInstance, CpaDcSessionSetupData *pSessionData, Cpa32U *pContextSize) { CpaStatus status = CPA_STATUS_SUCCESS; sal_compression_service_t *pCompService = NULL; pCompService = (sal_compression_service_t *)dcInstance; dc_capabilities_t *pDcCapabilities = &pCompService->dc_capabilities; *pContextSize = 0; if ((CPA_DC_STATEFUL == pSessionData->sessState) && (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection)) { switch (pSessionData->compType) { case CPA_DC_DEFLATE: *pContextSize = pDcCapabilities->deflate.inflateContextSize; break; case CPA_DC_LZ4: *pContextSize = pDcCapabilities->lz4.decompContextSize; break; default: LAC_LOG_ERROR("Invalid compression algorithm."); status = CPA_STATUS_UNSUPPORTED; break; } } return status; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Get the compression command id for the given session setup data. * * @description * This function will get the compression command id based on parameters *passed in the given session stup data. * @param[in] pService Pointer to the service * * @param[in] pSessionData Pointer to a user instantiated * structure containing session data * @param[out] pDcCmdId Pointer to the command id * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_UNSUPPORTED Unsupported algorithm/feature * *****************************************************************************/ CpaStatus dcGetCompressCommandId(sal_compression_service_t *pService, CpaDcSessionSetupData *pSessionData, Cpa8U *pDcCmdId) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pService); LAC_CHECK_NULL_PARAM(pSessionData); LAC_CHECK_NULL_PARAM(pDcCmdId); #endif *pDcCmdId = ICP_QAT_FW_COMP_CMD_DELIMITER; switch (pSessionData->compType) { case CPA_DC_DEFLATE: if (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) { *pDcCmdId = ICP_QAT_FW_COMP_CMD_DYNAMIC; } else if (CPA_DC_HT_STATIC == pSessionData->huffType) { *pDcCmdId = ICP_QAT_FW_COMP_CMD_STATIC; } break; case CPA_DC_LZ4: *pDcCmdId = ICP_QAT_FW_COMP_20_CMD_LZ4_COMPRESS; break; case CPA_DC_LZ4S: *pDcCmdId = ICP_QAT_FW_COMP_20_CMD_LZ4S_COMPRESS; break; default: LAC_LOG_ERROR("Algorithm not supported for compression\n"); status = CPA_STATUS_UNSUPPORTED; break; } return status; } /** ***************************************************************************** * @ingroup Dc_DataCompression * Get the decompression command id for the given session setup data. * * @description * This function will get the decompression command id based on parameters passed in the given session stup data. * @param[in] pService Pointer to the service * * @param[in] pSessionData Pointer to a user instantiated * structure containing session data * @param[out] pDcCmdId Pointer to the command id * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_UNSUPPORTED Unsupported algorithm/feature * *****************************************************************************/ CpaStatus dcGetDecompressCommandId(sal_compression_service_t *pService, CpaDcSessionSetupData *pSessionData, Cpa8U *pDcCmdId) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pService); LAC_CHECK_NULL_PARAM(pSessionData); LAC_CHECK_NULL_PARAM(pDcCmdId); #endif *pDcCmdId = -1; switch (pSessionData->compType) { case CPA_DC_DEFLATE: *pDcCmdId = ICP_QAT_FW_COMP_CMD_DECOMPRESS; break; case CPA_DC_LZ4: *pDcCmdId = ICP_QAT_FW_COMP_20_CMD_LZ4_DECOMPRESS; break; default: LAC_ENSURE(CPA_FALSE, "Algo not supported for decompression\n"); status = CPA_STATUS_UNSUPPORTED; break; } return status; } CpaStatus dcXxhash32SetState(dc_session_desc_t *pSessionDesc, Cpa32U seed) { CpaStatus status = CPA_STATUS_SUCCESS; xxhash_acc_state_buff_t *xxhashStateBuffer; LAC_CHECK_NULL_PARAM(pSessionDesc); xxhashStateBuffer = (xxhash_acc_state_buff_t *)pSessionDesc; /* Zero the compression state register */ LAC_OS_BZERO(xxhashStateBuffer, sizeof(xxhash_acc_state_buff_t)); xxhashStateBuffer->xxhash_state[0] = seed + XXHASH_PRIME32_A + XXHASH_PRIME32_B; xxhashStateBuffer->xxhash_state[1] = seed + XXHASH_PRIME32_B; xxhashStateBuffer->xxhash_state[2] = seed + 0; xxhashStateBuffer->xxhash_state[3] = seed - XXHASH_PRIME32_A; return status; } CpaStatus dcInitSessionCrcControl(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaCrcControlData *pCrcControlData) { dc_session_desc_t *pSessionDesc = NULL; dc_capabilities_t *pDcCapabilities = NULL; sal_compression_service_t *pService = NULL; CpaBoolean bPcrc64Supported = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pCrcControlData); /* Check that the parameters defined in the pCrcControlData are valid for * the device */ if (CPA_STATUS_SUCCESS != dcCheckSessionCrcControlData(pCrcControlData)) { return CPA_STATUS_INVALID_PARAM; } #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif pService = (sal_compression_service_t *)dcInstance; pDcCapabilities = &pService->dc_capabilities; dcGetPcrc64CapabilityStatus( pDcCapabilities, pSessionDesc->compType, &bPcrc64Supported); if (!bPcrc64Supported) { LAC_LOG_ERROR("Programmable CRC64 is unsupported"); return CPA_STATUS_UNSUPPORTED; } /* Generate the CRC64 lookup table for the provided polynomial */ status = dcGenerateLookupTable(pCrcControlData->polynomial, &pSessionDesc->crcConfig.pCrcLookupTable); if (CPA_STATUS_SUCCESS == status) { /* Set CRC parameters provided */ pSessionDesc->crcConfig.crcParam.crc64Poly = pCrcControlData->polynomial; pSessionDesc->crcConfig.crcParam.iCrc64Cpr = pCrcControlData->initialValue; pSessionDesc->crcConfig.crcParam.oCrc64Cpr = pCrcControlData->initialValue; pSessionDesc->crcConfig.crcParam.reflectIn = (Cpa32U)pCrcControlData->reflectIn; pSessionDesc->crcConfig.crcParam.reflectOut = (Cpa32U)pCrcControlData->reflectOut; pSessionDesc->crcConfig.crcParam.oCrc64Xlt = pCrcControlData->initialValue; pSessionDesc->crcConfig.crcParam.xor64Out = pCrcControlData->xorOut; pSessionDesc->crcConfig.useProgCrcSetup = CPA_TRUE; } return status; } CpaStatus dcInitSession(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcSessionSetupData *pSessionData, CpaBufferList *pContextBuffer, CpaDcCallbackFn callbackFn) { CpaStatus status = CPA_STATUS_SUCCESS; sal_compression_service_t *pService = NULL; icp_qat_fw_comp_req_t *pReqCache = NULL; dc_session_desc_t *pSessionDesc = NULL; CpaPhysicalAddr contextAddrPhys = 0; CpaPhysicalAddr physAddress = 0; CpaPhysicalAddr physAddressAligned = 0; Cpa32U minContextSize = 0, historySize = 0; icp_qat_fw_serv_specif_flags cmdFlags = 0; Cpa8U secureRam = ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; Cpa8U sessType = ICP_QAT_FW_COMP_STATELESS_SESSION; Cpa8U autoSelectBest = ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST; Cpa8U enhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST; Cpa8U disableType0EnhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; Cpa8U dcCmdId = ICP_QAT_FW_COMP_CMD_STATIC; icp_qat_fw_comn_flags cmnRequestFlags = 0; icp_qat_fw_ext_serv_specif_flags extServiceCmdFlags = 0; dc_capabilities_t *pDcCapabilities; CpaBoolean capabilityDcStateful = CPA_FALSE; Cpa16U numInterBuffs = 0; cmnRequestFlags = ICP_QAT_FW_COMN_FLAGS_BUILD( DC_DEFAULT_QAT_PTR_TYPE, QAT_COMN_CD_FLD_TYPE_16BYTE_DATA); pService = (sal_compression_service_t *)dcInstance; /* Retrieve internal capabilities */ pDcCapabilities = &pService->dc_capabilities; capabilityDcStateful = DC_CAPS_BITFIELD_GET(pDcCapabilities->sessState, CPA_DC_STATEFUL); numInterBuffs = pDcCapabilities->numInterBuffs; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pSessionData); /* Check that the parameters defined in the pSessionData are valid and * supported by the device */ status = dcCheckSessionData(pSessionData, dcInstance); if (CPA_STATUS_SUCCESS != status) { return status; } #endif if ((CPA_DC_STATEFUL == pSessionData->sessState) && (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection)) { LAC_UNSUPPORTED_PARAM_LOG("Stateful sessions are not supported"); return CPA_STATUS_UNSUPPORTED; } /* Check for Gen4 and stateful, return error if both exist */ if ((CPA_FALSE == capabilityDcStateful) && CPA_DC_STATEFUL == pSessionData->sessState) { LAC_INVALID_PARAM_LOG("Stateful sessions are not supported"); return CPA_STATUS_UNSUPPORTED; } secureRam = pDcCapabilities->deviceData.useDevRam; if ((numInterBuffs > 0) && (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType)) { /* Test if DRAM is available for the intermediate buffers */ if ((NULL == pService->pInterBuffPtrsArray) && (0 == pService->pInterBuffPtrsArrayPhyAddr)) { if (CPA_DC_ASB_STATIC_DYNAMIC == pSessionData->autoSelectBestHuffmanTree) { /* Define the Huffman tree as static */ pSessionData->huffType = CPA_DC_HT_STATIC; } else { LAC_LOG_ERROR("No buffer defined for this instance - see " "cpaDcStartInstance"); return CPA_STATUS_RESOURCE; } } } if ((CPA_DC_STATEFUL == pSessionData->sessState) && (CPA_DC_DEFLATE == pSessionData->compType || CPA_DC_LZ4 == pSessionData->compType)) { /* Get the size of the context buffer */ status = dcGetContextSize(dcInstance, pSessionData, &minContextSize); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Unable to get the context size of the session\n"); return status; } #ifdef ICP_PARAM_CHECK /* If the minContextSize is zero it means we will not save or restore * any history */ if (0 != minContextSize) { Cpa64U contextBuffSize = 0; LAC_CHECK_NULL_PARAM(pContextBuffer); if (LacBuffDesc_BufferListVerify( pContextBuffer, &contextBuffSize, LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { return CPA_STATUS_INVALID_PARAM; } /* Ensure that the context buffer size is greater or equal * to minContextSize */ if (contextBuffSize < minContextSize) { LAC_INVALID_PARAM_LOG1("Context buffer size should be " "greater or equal to %d", minContextSize); return CPA_STATUS_INVALID_PARAM; } } #endif } /* Re-align the session structure to 64 byte alignment */ physAddress = LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, (Cpa8U *)pSessionHandle + sizeof(void *)); if (physAddress == 0) { LAC_LOG_ERROR("Unable to get the physical address of the session\n"); return CPA_STATUS_FAIL; } physAddressAligned = (CpaPhysicalAddr)LAC_ALIGN_POW2_ROUNDUP( physAddress, LAC_64BYTE_ALIGNMENT); pSessionDesc = (dc_session_desc_t *) /* Move the session pointer by the physical offset between aligned and unaligned memory */ ((Cpa8U *)pSessionHandle + sizeof(void *) + (physAddressAligned - physAddress)); /* Save the aligned pointer in the first bytes (size of LAC_ARCH_UINT) * of the session memory */ *((LAC_ARCH_UINT *)pSessionHandle) = (LAC_ARCH_UINT)pSessionDesc; /* Zero the compression session */ LAC_OS_BZERO(pSessionDesc, sizeof(dc_session_desc_t)); /* Write the buffer descriptor for context/history */ if (0 != minContextSize) { status = LacBuffDesc_BufferListDescWrite(pContextBuffer, &contextAddrPhys, CPA_FALSE, &(pService->generic_service_info)); if (status != CPA_STATUS_SUCCESS) { return status; } pSessionDesc->pContextBuffer = pContextBuffer; pSessionDesc->historyBuffSize = historySize; } pSessionDesc->cumulativeConsumedBytes = 0; /* Initialise pSessionDesc */ pSessionDesc->requestType = DC_REQUEST_FIRST; pSessionDesc->huffType = pSessionData->huffType; pSessionDesc->compType = pSessionData->compType; pSessionDesc->checksumType = pSessionData->checksum; pSessionDesc->autoSelectBestHuffmanTree = pSessionData->autoSelectBestHuffmanTree; pSessionDesc->sessDirection = pSessionData->sessDirection; pSessionDesc->sessState = pSessionData->sessState; pSessionDesc->compLevel = pSessionData->compLevel; pSessionDesc->lz4BlockMaxSize = pSessionData->lz4BlockMaxSize; pSessionDesc->lz4BlockChecksum = pSessionData->lz4BlockChecksum; pSessionDesc->lz4BlockIndependence = pSessionData->lz4BlockIndependence; pSessionDesc->accumulateXXHash = pSessionData->accumulateXXHash; pSessionDesc->minMatch = pSessionData->minMatch; pSessionDesc->isDcDp = CPA_FALSE; pSessionDesc->minContextSize = minContextSize; pSessionDesc->isSopForCompressionProcessed = CPA_FALSE; pSessionDesc->isSopForDecompressionProcessed = CPA_FALSE; pSessionDesc->crcConfig.useProgCrcSetup = CPA_FALSE; pSessionDesc->crcConfig.pCrcLookupTable = NULL; pSessionDesc->lz4OutputFormat = CPA_DC_LZ4_OUTPUT_WITH_HEADER; /* Alter auto select best setting depending on the hardware version */ /* Configure CRC parameters based on the hardware version */ if (DC_CAPS_GEN4_HW != pDcCapabilities->deviceData.hw_gen) { /* Gen 2 hardware devices */ if (CPA_DC_ASB_ENABLED == pSessionDesc->autoSelectBestHuffmanTree) { /* Select best compression ratio optimization setting */ pSessionDesc->autoSelectBestHuffmanTree = CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS; } /* Gen2 hardcoded CRC parameters */ pSessionDesc->crcConfig.crcParam.crcPoly = DC_CRC_POLY_DEFAULT; pSessionDesc->crcConfig.crcParam.iCrc32Cpr = DC_DEFAULT_CRC; pSessionDesc->crcConfig.crcParam.oCrc32Cpr = DC_DEFAULT_CRC; pSessionDesc->crcConfig.crcParam.iCrc32Xlt = DC_DEFAULT_CRC; pSessionDesc->crcConfig.crcParam.oCrc32Xlt = DC_DEFAULT_CRC; pSessionDesc->crcConfig.crcParam.xorFlags = DC_XOR_FLAGS_DEFAULT; pSessionDesc->crcConfig.crcParam.xorOut = DC_XOR_OUT_DEFAULT; pSessionDesc->crcConfig.crcParam.deflateBlockType = DC_STATIC_TYPE; } else { /* Gen 4 hardware devices */ switch (pSessionDesc->autoSelectBestHuffmanTree) { case CPA_DC_ASB_STATIC_DYNAMIC: /* Fall through */ case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS: case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS: case CPA_DC_ASB_ENABLED: /* Enable compression ratio optimization */ pSessionDesc->autoSelectBestHuffmanTree = CPA_DC_ASB_ENABLED; break; case CPA_DC_ASB_DISABLED: default: /* Keep setting from session setup data */ break; } /* Gen4 hardcoded CRC parameters */ pSessionDesc->crcConfig.crcParam.crc64Poly = DC_CRC64_POLY_DEFAULT; pSessionDesc->crcConfig.crcParam.iCrc64Cpr = DC_DEFAULT_CRC; pSessionDesc->crcConfig.crcParam.oCrc64Cpr = DC_DEFAULT_CRC; pSessionDesc->crcConfig.crcParam.reflectIn = DC_REFLECT_IN_DEFAULT; pSessionDesc->crcConfig.crcParam.reflectOut = DC_REFLECT_OUT_DEFAULT; pSessionDesc->crcConfig.crcParam.oCrc64Xlt = DC_DEFAULT_CRC; pSessionDesc->crcConfig.crcParam.xor64Out = DC_XOR64_OUT_DEFAULT; } if (CPA_DC_LZ4 == pSessionDesc->compType && CPA_TRUE == pSessionDesc->accumulateXXHash && CPA_DC_ASB_ENABLED == pSessionDesc->autoSelectBestHuffmanTree) { LAC_LOG_ERROR("Unsupported combination of accumulateXXHash" " and autoSelectBestHuffmanTree."); return CPA_STATUS_UNSUPPORTED; } if (CPA_DC_STATELESS == pSessionDesc->sessState && CPA_DC_LZ4 == pSessionDesc->compType && CPA_TRUE == pSessionDesc->accumulateXXHash) { if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection || CPA_DC_DIR_COMBINED == pSessionDesc->sessDirection) { LAC_LOG_ERROR("AccumulateXXHash not supported on decompression" " or combined sessions."); return CPA_STATUS_UNSUPPORTED; } dcXxhash32SetState(pSessionDesc, 0); } if (CPA_DC_STATEFUL == pSessionData->sessState) { /* Init the spinlock used to lock the access to the number of stateful * in-flight requests */ status = LAC_SPINLOCK_INIT(&(pSessionDesc->sessionLock)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Spinlock init failed for sessionLock"); return CPA_STATUS_RESOURCE; } } if (CPA_DC_STATELESS == pSessionDesc->sessState) { /* Init the spinlock used to lock access to the cached session data */ status = LAC_SPINLOCK_INIT(&(pSessionDesc->updateLock)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Spinlock init failed for updateLock"); return CPA_STATUS_RESOURCE; } } /* For asynchronous - use the user supplied callback * for synchronous - use the internal synchronous callback */ pSessionDesc->pCompressionCb = ((void *)NULL != (void *)callbackFn) ? callbackFn : LacSync_GenWakeupSyncCaller; /* Reset the pending callback counters */ osalAtomicSet(0, &pSessionDesc->pendingStatelessCbCount); osalAtomicSet(0, &pSessionDesc->pendingStatefulCbCount); pSessionDesc->pendingDpStatelessCbCount = 0; if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) { if ((DC_CAPS_GEN4_HW != pDcCapabilities->deviceData.hw_gen) && CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) { /* Populate the compression section of the content descriptor */ dcCompContentDescPopulate(pService, pSessionDesc, contextAddrPhys, &(pSessionDesc->reqCacheComp), ICP_QAT_FW_SLICE_XLAT, DC_COMPRESSION_REQUEST); /* Populate the translator section of the content descriptor */ dcTransContentDescPopulate(&(pSessionDesc->reqCacheComp), ICP_QAT_FW_SLICE_DRAM_WR); if (0 != pService->pInterBuffPtrsArrayPhyAddr) { pReqCache = &(pSessionDesc->reqCacheComp); pReqCache->u1.xlt_pars.inter_buff_ptr = pService->pInterBuffPtrsArrayPhyAddr; } } else { dcCompContentDescPopulate(pService, pSessionDesc, contextAddrPhys, &(pSessionDesc->reqCacheComp), ICP_QAT_FW_SLICE_DRAM_WR, DC_COMPRESSION_REQUEST); } } /* Populate the compression section of the content descriptor for * the decompression case or combined */ if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) { dcCompContentDescPopulate(pService, pSessionDesc, contextAddrPhys, &(pSessionDesc->reqCacheDecomp), ICP_QAT_FW_SLICE_DRAM_WR, DC_DECOMPRESSION_REQUEST); } if (CPA_DC_STATEFUL == pSessionData->sessState) { sessType = ICP_QAT_FW_COMP_STATEFUL_SESSION; LAC_OS_BZERO(&pSessionDesc->stateRegistersComp, sizeof(pSessionDesc->stateRegistersComp)); LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp, sizeof(pSessionDesc->stateRegistersDecomp)); } /* Populate the cmdFlags */ switch (pSessionDesc->autoSelectBestHuffmanTree) { case CPA_DC_ASB_DISABLED: break; case CPA_DC_ASB_STATIC_DYNAMIC: autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; break; case CPA_DC_ASB_ENABLED: /* Fall through */ case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS: /* CPA_DC_ASB_ENABLED provides the same settings as * CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS. */ autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST; break; case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS: autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST; disableType0EnhancedAutoSelectBest = ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; break; default: break; } cmdFlags = ICP_QAT_FW_COMP_FLAGS_BUILD(sessType, autoSelectBest, enhancedAutoSelectBest, disableType0EnhancedAutoSelectBest, secureRam); if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) { status = dcGetCompressCommandId(pService, pSessionData, &dcCmdId); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR( "Couldn't get compress command ID for current session data."); return status; } pReqCache = &(pSessionDesc->reqCacheComp); pReqCache->comp_pars.crc.legacy.initial_adler = 1; pReqCache->comp_pars.crc.legacy.initial_crc32 = 0; /* Populate header of the common request message */ SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache, ICP_QAT_FW_COMN_REQ_CPM_FW_COMP, dcCmdId, cmnRequestFlags, cmdFlags, extServiceCmdFlags); } if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) { status = dcGetDecompressCommandId(pService, pSessionData, &dcCmdId); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR( "Couldn't get decompress command ID for current session data."); return status; } pReqCache = &(pSessionDesc->reqCacheDecomp); pReqCache->comp_pars.crc.legacy.initial_adler = 1; pReqCache->comp_pars.crc.legacy.initial_crc32 = 0; /* Populate header of the common request message */ SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache, ICP_QAT_FW_COMN_REQ_CPM_FW_COMP, dcCmdId, cmnRequestFlags, cmdFlags, extServiceCmdFlags); } return status; } STATIC CpaStatus dcCheckUpdateSession(const CpaInstanceHandle insHandle, dc_session_desc_t *pSessionDesc, CpaDcSessionUpdateData *pUpdateSessionData) { sal_compression_service_t *pService = (sal_compression_service_t *)insHandle; /* Retrieve internal capabilities */ dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; /* Check if DRAM is available for the intermediate buffers * for dynamic compression */ if ((pDcCapabilities->numInterBuffs > 0) && (CPA_DC_HT_FULL_DYNAMIC == pUpdateSessionData->huffType) && (NULL == pService->pInterBuffPtrsArray) && (0 == pService->pInterBuffPtrsArrayPhyAddr)) { LAC_LOG_ERROR("No intermediate buffer defined for this instance - see " "cpaDcStartInstance"); return CPA_STATUS_RESOURCE; } if (CPA_DC_STATEFUL == pSessionDesc->sessState) { LAC_LOG_ERROR("Stateful sessions are not supported\n"); return CPA_STATUS_INVALID_PARAM; } if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { LAC_LOG_ERROR("Decompression sessions are not supported\n"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } STATIC CpaStatus dcUpdateSession(const CpaInstanceHandle insHandle, dc_session_desc_t *pSessionDesc, CpaDcSessionUpdateData *pUpdateSessionData) { sal_compression_service_t *pService = (sal_compression_service_t *)insHandle; icp_qat_fw_comp_req_t *pReqCacheComp = &(pSessionDesc->reqCacheComp); icp_qat_fw_comn_req_hdr_t *pHeader = &(pReqCacheComp->comn_hdr); icp_qat_hw_compression_config_t *pCompConfig = (icp_qat_hw_compression_config_t *)(pReqCacheComp->cd_pars.sl .comp_slice_cfg_word); icp_qat_fw_comp_cd_hdr_t *pCompControlBlock = (icp_qat_fw_comp_cd_hdr_t *)&(pReqCacheComp->comp_cd_ctrl); dc_request_dir_t compDecomp; /* Retrieve internal capabilities */ dc_capabilities_t *pDcCapabilities = &pService->dc_capabilities; compDecomp = DC_COMPRESSION_REQUEST; /* Acquire a lock prior to updating the session parameters * for traditional only */ if (CPA_FALSE == pSessionDesc->isDcDp) { LAC_SPINLOCK(&(pSessionDesc->updateLock)); } pDcCapabilities->deviceData.enableDmm = pUpdateSessionData->enableDmm ? 1 : 0; pSessionDesc->compLevel = pUpdateSessionData->compLevel; pSessionDesc->huffType = pUpdateSessionData->huffType; if (CPA_DC_HT_FULL_DYNAMIC == pUpdateSessionData->huffType) { ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_XLAT); ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP); /* Populate the translator section of the content descriptor */ dcTransContentDescPopulate(pReqCacheComp, ICP_QAT_FW_SLICE_DRAM_WR); pReqCacheComp->u1.xlt_pars.inter_buff_ptr = pService->pInterBuffPtrsArrayPhyAddr; pHeader->service_cmd_id = ICP_QAT_FW_COMP_CMD_DYNAMIC; } else { ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_DRAM_WR); ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP); pHeader->service_cmd_id = ICP_QAT_FW_COMP_CMD_STATIC; } /* Populate Compression Hardware Setup Block */ (pDcCapabilities->dcCompHwBlockPopulate)((void *)pService, (void *)pSessionDesc, NULL, pCompConfig, (void *)&compDecomp, CPA_FALSE); /* Release the lock after updating session parameters */ if (CPA_FALSE == pSessionDesc->isDcDp) { LAC_SPINUNLOCK(&(pSessionDesc->updateLock)); } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcInitSession(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcSessionSetupData *pSessionData, CpaBufferList *pContextBuffer, CpaDcCallbackFn callbackFn) { CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pSessionData, (LAC_ARCH_UINT)pContextBuffer, (LAC_ARCH_UINT)callbackFn); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(insHandle); SAL_CHECK_ADDR_TRANS_SETUP(insHandle); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif pService = (sal_compression_service_t *)insHandle; /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(pService); return dcInitSession( insHandle, pSessionHandle, pSessionData, pContextBuffer, callbackFn); } CpaStatus cpaDcUpdateSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcSessionUpdateData *pUpdateSessionData) { CpaStatus status = CPA_STATUS_SUCCESS; dc_session_desc_t *pSessionDesc = NULL; CpaInstanceHandle insHandle = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); LAC_CHECK_NULL_PARAM(pUpdateSessionData); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pUpdateSessionData); #endif if (CPA_TRUE == pSessionDesc->isDcDp) { insHandle = dcInstance; } else { if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif /* Check if SAL is running otherwise return an error */ SAL_RUNNING_CHECK(insHandle); status = dcCheckUpdateSession(insHandle, pSessionDesc, pUpdateSessionData); if (CPA_STATUS_SUCCESS == status) { status = dcUpdateSession(insHandle, pSessionDesc, pUpdateSessionData); } return status; } CpaStatus cpaDcSetLZ4OutputFormat(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaDcLZ4OutputFormat outLZ4Format) { CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; dc_session_desc_t *pSessionDesc = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); if (CPA_DC_LZ4_OUTPUT_WITH_HEADER > outLZ4Format || CPA_DC_LZ4_OUTPUT_WITHOUT_HEADER < outLZ4Format) { LAC_INVALID_PARAM_LOG("Invalid outLZ4Format"); return CPA_STATUS_INVALID_PARAM; } #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)outLZ4Format); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif /* Check if SAL is running otherwise return an error */ SAL_RUNNING_CHECK(insHandle); if (CPA_DC_LZ4 != pSessionDesc->compType) { LAC_INVALID_PARAM_LOG("Invalid compression type"); return CPA_STATUS_INVALID_PARAM; } pService = (sal_compression_service_t *)insHandle; if (!(pService->generic_service_info.dcExtendedFeatures & DC_LZ4_E2E_COMP_CRC_OVER_BLOCK_EXTENDED_CAPABILITY) && (CPA_DC_LZ4_OUTPUT_WITHOUT_HEADER == outLZ4Format)) { LAC_UNSUPPORTED_PARAM_LOG("CRC over LZ4 data block (without header) " "feature not supported"); return CPA_STATUS_UNSUPPORTED; } pSessionDesc->lz4OutputFormat = outLZ4Format; return CPA_STATUS_SUCCESS; } CpaStatus cpaDcResetXXHashState(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle insHandle = NULL; dc_session_desc_t *pSessionDesc = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); #endif /* Check if SAL is running otherwise return an error */ SAL_RUNNING_CHECK(insHandle); if (CPA_DC_STATELESS == pSessionDesc->sessState && CPA_DC_LZ4 == pSessionDesc->compType && CPA_TRUE == pSessionDesc->accumulateXXHash) { /* Check if there are stateless pending requests */ if (0 != osalAtomicGet(&(pSessionDesc->pendingStatelessCbCount))) { LAC_LOG_ERROR("There are stateless requests pending"); return CPA_STATUS_RETRY; } dcXxhash32SetState(pSessionDesc, 0); } else { LAC_LOG_ERROR("Only Stateless LZ4 session with accumulateXXHash can " "reset state."); return CPA_STATUS_UNSUPPORTED; } return status; } CpaStatus cpaDcResetSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle insHandle = NULL; dc_session_desc_t *pSessionDesc = NULL; Cpa64U numPendingStateless = 0; Cpa64U numPendingStateful = 0; icp_comms_trans_handle trans_handle = NULL; sal_compression_service_t *pService = NULL; #ifdef ICP_DEBUG Cpa32U i = 0; CpaBufferList *pContextBuffer = NULL; #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle); #endif if (CPA_TRUE == pSessionDesc->isDcDp) { insHandle = dcInstance; } else { if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif /* Check if SAL is running otherwise return an error */ SAL_RUNNING_CHECK(insHandle); pService = (sal_compression_service_t *)(insHandle); if (CPA_TRUE == pSessionDesc->isDcDp) { if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = ((sal_compression_service_t *)insHandle) ->trans_handle_compression_tx; } else { trans_handle = ((sal_compression_service_t *)insHandle) ->trans_handle_decompression_tx; } if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { LAC_LOG_ERROR("There are remaining messages on the ring"); /* Process the remaining messages on the ring */ status = icp_adf_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { return status; } return CPA_STATUS_RETRY; } /* Check if there are stateless pending requests */ if (0 != pSessionDesc->pendingDpStatelessCbCount) { LAC_LOG_ERROR1("There are %llu stateless DP requests pending", pSessionDesc->pendingDpStatelessCbCount); return CPA_STATUS_RETRY; } } else { numPendingStateless = osalAtomicGet(&(pSessionDesc->pendingStatelessCbCount)); numPendingStateful = osalAtomicGet(&(pSessionDesc->pendingStatefulCbCount)); /* Check if there are stateless pending requests */ if (0 != numPendingStateless) { LAC_LOG_ERROR1("There are %llu stateless requests pending", numPendingStateless); return CPA_STATUS_RETRY; } /* Check if there are stateful pending requests */ if (0 != numPendingStateful) { LAC_LOG_ERROR1("There are %llu stateful requests pending", numPendingStateful); return CPA_STATUS_RETRY; } #ifdef ICP_DEBUG pContextBuffer = pSessionDesc->pContextBuffer; if (pContextBuffer) { /* Fill context buffer with 0xFF in debug mode */ for (i = 0; i < pContextBuffer->numBuffers; i++) { osalMemSet(pContextBuffer->pBuffers[i].pData, 0xFF, pContextBuffer->pBuffers[i].dataLenInBytes); } } #endif /* Reset pSessionDesc */ pSessionDesc->requestType = DC_REQUEST_FIRST; pSessionDesc->cumulativeConsumedBytes = 0; pSessionDesc->cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX; } /* Reset the pending callback counters */ osalAtomicSet(0, &pSessionDesc->pendingStatelessCbCount); osalAtomicSet(0, &pSessionDesc->pendingStatefulCbCount); pSessionDesc->pendingDpStatelessCbCount = 0; if (CPA_DC_STATEFUL == pSessionDesc->sessState) { LAC_OS_BZERO(&pSessionDesc->stateRegistersComp, sizeof(pSessionDesc->stateRegistersComp)); LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp, sizeof(pSessionDesc->stateRegistersDecomp)); } return status; } CpaStatus cpaDcRemoveSession(const CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle insHandle = NULL; dc_session_desc_t *pSessionDesc = NULL; Cpa64U numPendingStateless = 0; Cpa64U numPendingStateful = 0; icp_comms_trans_handle trans_handle = NULL; sal_compression_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionHandle); #endif pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle); #endif if (CPA_TRUE == pSessionDesc->isDcDp) { insHandle = dcInstance; } else { if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif /* Check if SAL is running otherwise return an error */ SAL_RUNNING_CHECK(insHandle); pService = (sal_compression_service_t *)(insHandle); if (CPA_TRUE == pSessionDesc->isDcDp) { if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { trans_handle = ((sal_compression_service_t *)insHandle) ->trans_handle_compression_tx; } else { trans_handle = ((sal_compression_service_t *)insHandle) ->trans_handle_decompression_tx; } if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { LAC_LOG_ERROR("There are remaining messages on the ring"); /* Process the remaining messages on the ring */ status = icp_adf_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { return status; } return CPA_STATUS_RETRY; } /* Check if there are stateless pending requests */ if (0 != pSessionDesc->pendingDpStatelessCbCount) { LAC_LOG_ERROR1("There are %llu stateless DP requests pending", pSessionDesc->pendingDpStatelessCbCount); return CPA_STATUS_RETRY; } } else { numPendingStateless = osalAtomicGet(&(pSessionDesc->pendingStatelessCbCount)); numPendingStateful = osalAtomicGet(&(pSessionDesc->pendingStatefulCbCount)); /* Check if there are stateless pending requests */ if (0 != numPendingStateless) { LAC_LOG_ERROR1("There are %llu stateless requests pending", numPendingStateless); status = CPA_STATUS_RETRY; } /* Check if there are stateful pending requests */ if (0 != numPendingStateful) { LAC_LOG_ERROR1("There are %llu stateful requests pending", numPendingStateful); status = CPA_STATUS_RETRY; } if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && (CPA_STATUS_SUCCESS == status)) { LAC_SPINLOCK_DESTROY(&(pSessionDesc->sessionLock)); } } if (CPA_DC_STATELESS == pSessionDesc->sessState) { LAC_SPINLOCK_DESTROY(&(pSessionDesc->updateLock)); } /* Free the CRC lookup table if one was allocated */ if (NULL != pSessionDesc->crcConfig.pCrcLookupTable) { LAC_OS_FREE(pSessionDesc->crcConfig.pCrcLookupTable); } return status; } CpaStatus dcGetSessionSize(CpaInstanceHandle dcInstance, CpaDcSessionSetupData *pSessionData, Cpa32U *pSessionSize, Cpa32U *pContextSize) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle insHandle = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK /* Check parameters */ LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pSessionData); status = dcCheckSessionData(pSessionData, insHandle); if (CPA_STATUS_SUCCESS != status) { return status; } #endif /* Get session size for session data */ *pSessionSize = sizeof(dc_session_desc_t) + LAC_64BYTE_ALIGNMENT + sizeof(LAC_ARCH_UINT); if (NULL != pContextSize) { status = dcGetContextSize(insHandle, pSessionData, pContextSize); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Unable to get the context size of the session\n"); return status; } } return CPA_STATUS_SUCCESS; } CpaStatus cpaDcGetSessionSize(CpaInstanceHandle dcInstance, CpaDcSessionSetupData *pSessionData, Cpa32U *pSessionSize, Cpa32U *pContextSize) { CpaStatus status = CPA_STATUS_SUCCESS; /* Check parameter */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionSize); LAC_CHECK_NULL_PARAM(pContextSize); #endif status = dcGetSessionSize(dcInstance, pSessionData, pSessionSize, pContextSize); #ifdef ICP_TRACE LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx[%d], 0x%lx[%d])\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionData, (LAC_ARCH_UINT)pSessionSize, *pSessionSize, (LAC_ARCH_UINT)pContextSize, *pContextSize); #endif return status; } #ifdef ICP_DC_ERROR_SIMULATION CpaStatus dcSetCnvError(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(dcInstance); LAC_CHECK_NULL_PARAM(pSessionHandle); #endif dc_session_desc_t *pSessionDesc = NULL; CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; /* Retrieve internal capabilities */ dc_capabilities_t *pDcCapabilities = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; pDcCapabilities = &pService->dc_capabilities; if (CPA_TRUE != pDcCapabilities->cnv.errorInjection) { LAC_LOG_ERROR("Unsupported compression feature.\n"); return CPA_STATUS_UNSUPPORTED; } pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif pSessionDesc->cnvErrorInjection = ICP_QAT_FW_COMP_CNV_DFX; return CPA_STATUS_SUCCESS; } #endif /* ICP_DC_ERROR_SIMULATION */ CpaStatus cpaDcSetCrcControlData(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaCrcControlData *pCrcControlData) { #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pSessionHandle, (LAC_ARCH_UINT)pCrcControlData); #endif return dcInitSessionCrcControl(dcInstance, pSessionHandle, pCrcControlData); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_stats.c000066400000000000000000000130151503624047500305120ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_stats.c * * @ingroup Dc_DataCompression * * @description * Implementation of the Data Compression stats operations. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_common.h" #include "icp_accel_devices.h" #include "sal_statistics.h" #include "dc_session.h" #include "dc_datapath.h" #include "lac_mem_pools.h" #include "sal_service_state.h" #include "sal_types_compression.h" #include "dc_stats.h" CpaStatus dcStatsInit(sal_compression_service_t *pService) { CpaStatus status = CPA_STATUS_SUCCESS; status = LAC_OS_MALLOC(&(pService->pCompStatsArr), COMPRESSION_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { COMPRESSION_STATS_RESET(pService); } return status; } void dcStatsFree(sal_compression_service_t *pService) { if (NULL != pService->pCompStatsArr) { LAC_OS_FREE(pService->pCompStatsArr); } } void dcStatsReset(sal_compression_service_t *pService) { COMPRESSION_STATS_RESET(pService); } CpaStatus cpaDcGetStats(CpaInstanceHandle dcInstance, CpaDcStats *pStatistics) { sal_compression_service_t *pService = NULL; CpaInstanceHandle insHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pStatistics); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pStatistics); #endif SAL_RUNNING_CHECK(insHandle); #ifdef ICP_PARAM_CHECK /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); #endif /* Retrieves the statistics for compression */ COMPRESSION_STATS_GET(pStatistics, pService); return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/dc_xxhash32.c000066400000000000000000000153541503624047500310340ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_xxhash.c * * @defgroup Dc_DataCompression DC Data Compression * * @ingroup Dc_DataCompression * * @description * Implementation of the xxhash32 operation. * *****************************************************************************/ #include "dc_xxhash32.h" /* ******************************************************************* * 32-bit hash functions *********************************************************************/ static const Cpa32U XXHASH_PRIME32_A = 0x9E3779B1U; static const Cpa32U XXHASH_PRIME32_B = 0x85EBCA77U; static const Cpa32U XXHASH_PRIME32_C = 0xC2B2AE3DU; static const Cpa32U XXHASH_PRIME32_D = 0x27D4EB2FU; static const Cpa32U XXHASH_PRIME32_E = 0x165667B1U; #define XXH32_STRIP_SIZE 16 #define ROTATE_LEFT_32(n, d) ((n << d) | (n >> (-d & 31))) /* Static function definitions */ static Cpa32U xxh32Avalanche(Cpa32U xxHash32); static CpaStatus calculateXxh32(const Cpa8U *xxH32input, Cpa32U dataLength, Cpa32U seed, Cpa32U *result); static Cpa32U xxh32ConsumeRemaining(Cpa32U xxHash32Accumulator, const Cpa8U *ptr, Cpa32U remainingBytes); CpaStatus dcXxhash32Lz4HdrChecksum(const void *xxH32input, const Cpa32U dataLength, Cpa8U *checksum) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U result = 0; Cpa32U seed = 0; LAC_CHECK_PARAM_RANGE(dataLength, 2, 16); status = calculateXxh32(xxH32input, dataLength, seed, &result); if (CPA_STATUS_SUCCESS != status) return CPA_STATUS_FAIL; *checksum = (Cpa8U)(result >> 8) & 0xFF; return CPA_STATUS_SUCCESS; } /*Calculate the XXH32 on a block of data */ static CpaStatus calculateXxh32(const Cpa8U *xxH32input, Cpa32U dataLength, Cpa32U seed, Cpa32U *result) { Cpa32U xxHash32Accumulator = 0; #ifdef ICP_PARAM_CHECK /* Check for null parameters */ LAC_CHECK_NULL_PARAM(xxH32input); LAC_CHECK_NULL_PARAM(result); #endif if (dataLength < XXH32_STRIP_SIZE) xxHash32Accumulator = seed + XXHASH_PRIME32_E; else return CPA_STATUS_FAIL; /* Add data length to accumulator */ xxHash32Accumulator += (Cpa32U)dataLength; /* Consume the remaining bytes of input (< 16) */ *result = xxh32ConsumeRemaining(xxHash32Accumulator, xxH32input, dataLength); return CPA_STATUS_SUCCESS; } static Cpa32U xxh32ConsumeRemaining(Cpa32U xxHash32Accumulator, const Cpa8U *ptr, Cpa32U remainingBytes) { /* Input buffer less that 16 bytes. Each round is a block of 4 bytes(strip). * The bytes are processed in blocks of 4 and we keep processing until * we have less than 4 bytes left in the buffer */ while (remainingBytes >= 4) { xxHash32Accumulator += *(Cpa32U *)ptr * XXHASH_PRIME32_C; xxHash32Accumulator = ROTATE_LEFT_32(xxHash32Accumulator, 17) * XXHASH_PRIME32_D; ptr += 4; remainingBytes -= 4; } /* Remaining bytes left after above calculation use following */ while (remainingBytes > 0) { xxHash32Accumulator += (*ptr++) * XXHASH_PRIME32_E; xxHash32Accumulator = ROTATE_LEFT_32(xxHash32Accumulator, 11) * XXHASH_PRIME32_A; remainingBytes -= 1; } return xxh32Avalanche(xxHash32Accumulator); } static Cpa32U xxh32Avalanche(Cpa32U xxHash32) { xxHash32 ^= xxHash32 >> 15; xxHash32 *= XXHASH_PRIME32_B; xxHash32 ^= xxHash32 >> 13; xxHash32 *= XXHASH_PRIME32_C; xxHash32 ^= xxHash32 >> 16; return (xxHash32); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/icp_sal_dc_err_sim.c000066400000000000000000000076271503624047500325220ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file icp_sal_dc_err_sim.c * * @defgroup SalCommon * * @ingroup SalCommon * *****************************************************************************/ /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_error_counter.h" #ifdef ICP_DC_ERROR_SIMULATION #include "dc_err_sim.h" #endif CpaStatus icp_sal_dc_simulate_error(Cpa8U numErrors, Cpa8S dcError) { #ifdef ICP_DC_ERROR_SIMULATION return dcSetNumError(numErrors, dcError); #else return CPA_STATUS_UNSUPPORTED; #endif } Cpa64U icp_sal_get_dc_error(Cpa8S dcError) { return getDcErrorCounter(dcError); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/000077500000000000000000000000001503624047500301655ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_capabilities.h000066400000000000000000000771371503624047500334540ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file dc_capabilities.h * * @defgroup dc_capabilities Capabilitites feature description for dc * * @ingroup LacCommon * * @description * This file contains details of the new dc capabilities feature. * *****************************************************************************/ #ifndef DC_CAPABILITIES_H #define DC_CAPABILITIES_H #ifdef __cplusplus extern "C" { #endif #include "cpa_dc.h" #include "icp_qat_hw.h" /** ***************************************************************************** * @ingroup dc_capabilities * DC algo data bitfields * @description * Data compression algorithms' data bitfields definitions * to create sufficient place for features; used to create big enough * tables of structs for supported algorithms *****************************************************************************/ /**< Deflate related definitions */ #define DC_CAPS_BF_DEFLATE_TYPE_SUPPORT (2) /**< deflate type support */ /**< LZ4 related definitions */ /**< LZ4 block size: * 0b0001: 64K * 0b0010: 256K * 0b0100: 1M * 0b1000: 4M */ #define DC_CAPS_BF_LZ4_MAXBLSIZE (4) /**< LZ4s related definitions */ /**< min match sizes * 0b01: 3bytes * 0b10: 4bytes */ #define DC_CAPS_BF_MIN_MATCH (2) /**< direction * 0b01: compression * 0b10: decompression */ #define DC_CAPS_BF_DIR (2) /**< dictionary type * 0b01: un-compressed * 0b10: compressed */ #define DC_CAPS_BF_DICT (2) /**< checksums * 0b0001: CRC32 * 0b0010: ADLER32 * 0b0100: XXHASH32 * 0b1000: XXHASH64 */ #define DC_CAPS_BF_CHECKSUM (4) /**< ASB */ #define DC_CAPS_BF_ASB (3) /**< ASB */ #define DC_CAPS_BF_ASB_TSH (3) /**< ASB Threshold */ #define DC_CAPS_BF_ASB_RATIO (1) /**< ASB Ratio */ /**< session state * 0b01: stateful * 0b10: stateless */ #define DC_CAPS_BF_STATE (2) /**< window size */ #define DC_CAPS_BF_WINSIZE (3) /**< Values for setting capabilities */ #define DC_CAPS_COMPRESSION (0x1) #define DC_CAPS_DECOMPRESSION (0x2) #define DC_CAPS_CRC32 (0x1) #define DC_CAPS_ADLER32 (0x2) #define DC_CAPS_XXHASH32 (0x4) #define DC_CAPS_XXHASH64 (0x8) #define DC_CAPS_STATEFUL (0x1) #define DC_CAPS_STATELESS (0x2) #define DC_CAPS_LZ4_64K (0x1) #define DC_CAPS_LZ4_256K (0x2) #define DC_CAPS_LZ4_1M (0x4) #define DC_CAPS_LZ4_4M (0x8) #define DC_CAPS_LZ4S_3B (0x1) #define DC_CAPS_LZ4S_4B (0x2) #define DC_CAPS_UNCOMPRESSED_DICT (0x1) #define DC_CAPS_COMPRESSED_DICT (0x2) #define DC_CAPS_DEFLATE_SUPPORTED (0x1) #define DC_CAPS_LZ4_SUPPORTED (0x4) #define DC_CAPS_LZ4S_SUPPORTED (0x8) #define DC_CAPS_PCRC (0x4) #define DC_CAPS_DYNAMIC_HUFF_BUFF_REQ (0x400) #define DC_CAPS_XXHASH32_OFFSET (1) #define DC_CAPS_XXHASH64_OFFSET (2) #define DC_CAPS_DYNAMIC_HUFF_OFFSET (10) #define DC_CAPS_PCRC_OFFSET (2) #define DC_CAPS_LZ4_OFFSET (2) #define DC_CAPS_ADLER32_OFFSET (1) #define DC_CAPS_PCRC_OFFSET (2) #define DC_CAPS_LZ4S_OFFSET (3) #define DC_CAPS_CNVNR_EXTENDED_OFFSET (8) /* Restriction on the source buffer size for compression due to the firmware * processing */ #define DC_SRC_BUFFER_MIN_SIZE (15) /* Restriction on the destination buffer size for compression due to * the management of skid buffers in the firmware */ #define DC_DEST_BUFFER_STA_MIN_SIZE (64) #define DC_DEST_BUFFER_DYN_MIN_SIZE (128) #define DC_DEST_BUFFER_DYN_MIN_SIZE_GEN4 (512) /* Minimum destination buffer size for Gen4 is * 2 bytes + skid */ #define DC_DEST_BUFFER_STA_MIN_SIZE_GEN4 (1026) /* Size of the history window. * Base 2 logarithm of maximum window size minus 8. Each bit represents a * possible window size. Note: In compression direction only one windows size * can be set based on the HW generation and the standard. */ #define DC_4K_WINDOW_SIZE (4) #define DC_8K_WINDOW_SIZE (5) #define DC_16K_WINDOW_SIZE (6) #define DC_32K_WINDOW_SIZE (7) #define DC_64K_WINDOW_SIZE (8) #define DC_4K_WINDOW_MASK (1 << DC_4K_WINDOW_SIZE) #define DC_8K_WINDOW_MASK (1 << DC_8K_WINDOW_SIZE) #define DC_16K_WINDOW_MASK (1 << DC_16K_WINDOW_SIZE) #define DC_32K_WINDOW_MASK (1 << DC_32K_WINDOW_SIZE) #define DC_64K_WINDOW_MASK (1 << DC_64K_WINDOW_SIZE) /* C4xxx device requires minimum 47 bytes for output buffer * size for static compression */ #define DC_DEST_BUFFER_MIN_SIZE (47) /* Context size */ #define DC_DEFLATE_MAX_CONTEXT_SIZE (49152) #define DC_INFLATE_CONTEXT_SIZE (36864) #define DC_LZ4_DECOMP_CONTEXT_SIZE (32768) #define DC_DEFLATE_EH_MAX_CONTEXT_SIZE (65536) #define DC_DEFLATE_EH_MIN_CONTEXT_SIZE (49152) #define DC_INFLATE_EH_CONTEXT_SIZE (34032) /* Maximum number of intermediate buffers SGLs for devices * with a maximum of 6 compression slices */ #define DC_QAT_MAX_NUM_INTER_BUFFERS_6COMP_SLICES (12) /* Maximum number of intermediate buffers SGLs for devices * with a maximum of 10 max compression slices */ #define DC_QAT_MAX_NUM_INTER_BUFFERS_10COMP_SLICES (20) /* Maximum number of intermediate buffers SGLs for devices * with a maximum of 8 compression slices and 24 AEs */ #define DC_QAT_MAX_NUM_INTER_BUFFERS_8COMP_SLICES (48) /* Maximum number of intermediate buffers SGLs for devices * with a maximum of 4 max compression slices and 12 AEs */ #define DC_QAT_MAX_NUM_INTER_BUFFERS_4COMP_SLICES (24) /* Maximum number of intermediate buffers SGLs for devices * with a maximum of 12 max compression slices and 32 AEs */ #define DC_QAT_MAX_NUM_INTER_BUFFERS_12COMP_SLICES (64) /* Mask used to check the CompressAndVerify capability bit */ #define DC_CNV_EXTENDED_CAPABILITY (0x01) /* Mask used to check the CompressAndVerifyAndRecover capability bit */ #define DC_CNVNR_EXTENDED_CAPABILITY (0x100) /* Mask used to check chaining hash then compress capability bit */ #define DC_CHAIN_HASH_THEN_COMPRESS_EXTENDED_CAPABILITY (0x200000) /* Mask used to check the LZ4 compress programmable CRC capability bit */ #define DC_LZ4_E2E_COMP_CRC_EXTENDED_CAPABILITY (0x20000000) /* Mask used to check the LZ4 compress programmable CRC without LZ4 block header * capability bit */ #define DC_LZ4_E2E_COMP_CRC_OVER_BLOCK_EXTENDED_CAPABILITY (0x40000000) typedef enum dc_bit_field_sizes { DC_BITFIELD_SIZE_1 = 1, DC_BITFIELD_SIZE_2, DC_BITFIELD_SIZE_3, DC_BITFIELD_SIZE_4, DC_BITFIELD_SIZE_5, DC_BITFIELD_SIZE_6, DC_BITFIELD_SIZE_7, DC_BITFIELD_SIZE_8 } dc_bit_field_sizes_t; /** ***************************************************************************** * @ingroup dc_capabilities * Capabilitities content for ASB * @description * Auto Select Best (ASB) capabilitities struct. *****************************************************************************/ typedef struct dc_capabilities_asb_s { /**< Auto Select Best (ASB), see \ref CpaDcAutoSelectBest */ Cpa8U asb : DC_CAPS_BF_ASB; /**< ASB Threshold */ Cpa8U asbTsh : DC_CAPS_BF_ASB_TSH; /**< ASB Ratio */ Cpa8U asbRatio : DC_CAPS_BF_ASB_RATIO; /**< ASB supported */ Cpa8U supported : DC_BITFIELD_SIZE_1; /**< ASB Threshold supported */ Cpa8U asbTshSupported : DC_BITFIELD_SIZE_1; /**< ASB Ratio supported */ Cpa8U asbRatioSupported : DC_BITFIELD_SIZE_1; Cpa8U asbReserved : DC_BITFIELD_SIZE_6; } dc_capabilities_asb_t; /** ***************************************************************************** * @ingroup dc_capabilities * Capabilitities content for Compress and Verify (CnV) * @description * Compress and Verify (CnV) capabilitities struct. *****************************************************************************/ typedef struct dc_capabilities_cnv_s { /**< CnV supported */ Cpa8U supported : DC_BITFIELD_SIZE_1; /**< CnV strict mode supported */ Cpa8U strict : DC_BITFIELD_SIZE_1; /**< CnV recovery supported */ Cpa8U recovery : DC_BITFIELD_SIZE_1; /**< CnV error injection */ Cpa8U errorInjection : DC_BITFIELD_SIZE_1; Cpa8U cnvReserved : DC_BITFIELD_SIZE_4; } dc_capabilities_cnv_t; /** ***************************************************************************** * @ingroup dc_capabilities * Capabilitities content for CRC integrity * @description * CRC integrity struct. *****************************************************************************/ typedef struct dc_capabilities_crc_integrity_s { /**< Integrity supported */ Cpa8U supported : DC_BITFIELD_SIZE_1; /**< If set to true, the implementation will verify that data * integrity is preserved through the processing pipeline. * Integrity CRC checking is not supported for decompression operations * over data that contains multiple gzip headers. */ /**< 32-bit Integrity CRCs */ Cpa8U checkCRC32 : DC_BITFIELD_SIZE_1; /**< 64-bit integrity CRCs */ Cpa8U checkCRC64 : DC_BITFIELD_SIZE_1; Cpa8U integrityReserved : DC_BITFIELD_SIZE_5; } dc_capabilities_crc_integrity_t; /** ***************************************************************************** * @ingroup dc_capabilities * Supported types (index) of deflate compression. * @description * - static * - dynamic *****************************************************************************/ typedef enum dc_deflate_types { DC_CAPS_DEFLATE_TYPE_STATIC = 0, DC_CAPS_DEFLATE_TYPE_DYNAMIC = 1, } dc_deflate_types_t; /** ***************************************************************************** * @ingroup dc_capabilities * Type's support of deflate compression. * @description * - unsupported * - supported *****************************************************************************/ typedef enum dc_deflate_type_support { DC_CAPS_DEFLATE_TYPE_UNSUPPORTED = 0, DC_CAPS_DEFLATE_TYPE_SUPPORTED = 1, } dc_deflate_type_support_t; #define DC_CAPS_DEFLATE_TYPE_SUPPORT_SET(capability, type, support) \ capability &= ~(0x1 << type); /* Mask others */ \ capability |= support << type; /* Add support for type */ #define DC_CAPS_DEFLATE_TYPE_SUPPORT_GET(capability, type, support) \ (((capability >> type) & 0x1) == support) ? CPA_TRUE : CPA_FALSE; /** ***************************************************************************** * @ingroup dc_capabilities * DC deflate capabilitities content * @description * Definition of deflate capabilitities data *****************************************************************************/ typedef struct dc_capabilities_deflate_s { /**< Number of bytes internally available to be used when * constructing dynamic Huffman trees */ Cpa32U internalHuffmanMem; /**< Inflate content size */ Cpa32U inflateContextSize; /**< Bits set to '1' for each valid window size supported by * the compression implementation */ Cpa16U validWindowSizeMaskCompression; /**< Bits set to '1' for each valid window size supported by * the decompression implementation */ Cpa16U validWindowSizeMaskDecompression; /**< Flag to define if algorithm is supported (TRUE) or not (FALSE) */ Cpa8U supported : DC_BITFIELD_SIZE_1; /**< Flag to indicate if dictionary compression is supported (TRUE) or not * (FALSE) */ Cpa8U dictCompSupported : DC_BITFIELD_SIZE_1; /**< Dictionary type, see \ref CpaDcDictType */ Cpa8U dictCap : DC_BITFIELD_SIZE_2; /**< Session direction, see \ref CpaDcDir */ Cpa8U dirMask : DC_BITFIELD_SIZE_2; /**< Bypass incomplete operation if file error */ Cpa8U bypassIncompleteFileErr : DC_BITFIELD_SIZE_1; /**< True if the algorithm is supported by Auto select * best feature */ Cpa8U asbSupported : DC_BITFIELD_SIZE_1; /**< Window size, see \ref CpaDcCompWindowSize */ Cpa8U historyBufferSize : DC_BITFIELD_SIZE_3; /**< Support for deflate types, 2-bit matrix based on * \ref dc_deflate_types_t and \ref dc_deflate_type_support * 0b00: STATIC UNSUPPORTED, DYNAMIC UNSUPPORTED * 0b01: STATIC SUPPORTED, DYNAMIC UNSUPPORTED * 0b10: STATIC UNSUPPORTED, DYNAMIC SUPPORTED * 0b11: STATIC SUPPORTED, DYNAMIC SUPPORTED */ Cpa8U typeSupport : DC_BITFIELD_SIZE_2; /**< True if an instance specific buffer is required to perform * a dynamic Huffman tree deflate request */ Cpa8U dynamicHuffmanBufferReq : DC_BITFIELD_SIZE_1; /**< True if the Instance supports precompiled Huffman trees in * deflate blocks */ Cpa8U precompiledHuffman : DC_BITFIELD_SIZE_1; /**< True if zero length requests */ Cpa8U zerolengthRequests : DC_BITFIELD_SIZE_1; /**< True if the current compression format supports programmable CRC64 */ Cpa8U programmableCrc64 : DC_BITFIELD_SIZE_1; /**< True if its preferred to keep ASB enabled */ Cpa8U asbEnablePref : DC_BITFIELD_SIZE_1; /**< True if the algorithm supports HASH THEN COMPRESS chaining * operation */ Cpa8U hashThenCompressSupported : DC_BITFIELD_SIZE_1; /**< True if the algorithm supports COMPRESS_THEN_AEAD * chaining operation */ Cpa8U compressThenAeadSupported : DC_BITFIELD_SIZE_1; /**< True if the algorithm supports AEAD_THEN_DECOMPRESS * chaining operation */ Cpa8U aeadThenDecompressSupported : DC_BITFIELD_SIZE_1; Cpa8U deflateReserved : DC_BITFIELD_SIZE_3; } dc_capabilities_deflate_t; #define DC_CAPS_DEFLATE_LENGTH (sizeof(dc_capabilities_deflate_t)) /** ***************************************************************************** * @ingroup dc_capabilities * DC lz4 capabilitities content * @description * Definition of lz4 capabilitities data *****************************************************************************/ typedef struct dc_capabilities_lz4_s { /**< LZ4 decompression context size */ Cpa32U decompContextSize; /**< Bits set to '1' for each valid window size supported by * the compression implementation */ Cpa16U validWindowSizeMaskCompression; /**< Bits set to '1' for each valid window size supported by * the decompression implementation */ Cpa16U validWindowSizeMaskDecompression; /**< Flag to define if algorithm is supported (TRUE) or not (FALSE) */ Cpa8U supported : DC_BITFIELD_SIZE_1; /**< Flag to indicate if dictionary compression is supported (TRUE) or not * (FALSE) */ Cpa8U dictCompSupported : DC_BITFIELD_SIZE_1; /**< Dictionary type, see \ref CpaDcDictType */ Cpa8U dictCap : DC_BITFIELD_SIZE_2; /**< Session direction, see \ref CpaDcDir */ Cpa8U dirMask : DC_BITFIELD_SIZE_2; /**< Bypass incomplete operation if file error */ Cpa8U bypassIncompleteFileErr : DC_BITFIELD_SIZE_1; /**< True if the algorithm is supported by Auto select * best feature */ Cpa8U asbSupported : DC_BITFIELD_SIZE_1; /**< Window size, see \ref CpaDcCompWindowSize */ Cpa8U historyBufferSize : DC_BITFIELD_SIZE_3; /**< Maximum LZ4 output block size, see \ref CpaDcCompLZ4BlockMaxSize */ Cpa8U maxBlockSize : DC_BITFIELD_SIZE_4; /**< LZ4 Block Independence Flag setting */ Cpa8U blockIndependence : DC_BITFIELD_SIZE_1; /**< LZ4 Block Checksum setting for the LZ4 request */ Cpa8U blockChecksum : DC_BITFIELD_SIZE_1; /**< If TRUE the xxHash calculation for LZ4 requests using the session * based APIs will be accumulated across requests */ Cpa8U accumulateXXHash : DC_BITFIELD_SIZE_1; /**< True if the Instance can calculate an xxHash-32 hash over * the uncompressed data */ Cpa8U checksumXXHash32 : DC_BITFIELD_SIZE_1; /**< True if zero length requests */ Cpa8U zerolengthRequests : DC_BITFIELD_SIZE_1; /**< True if the current compression format supports programmable CRC64 */ Cpa8U programmableCrc64 : DC_BITFIELD_SIZE_1; /**< True if its preferred to keep ASB enabled */ Cpa8U asbEnablePref : DC_BITFIELD_SIZE_1; /**< True if the algorithm supports HASH THEN COMPRESS chaining * operation */ Cpa8U hashThenCompressSupported : DC_BITFIELD_SIZE_1; /**< True if the algorithm supports COMPRESS_THEN_AEAD * chaining operation */ Cpa8U compressThenAeadSupported : DC_BITFIELD_SIZE_1; /**< True if the algorithm supports AEAD_THEN_DECOMPRESS * chaining operation */ Cpa8U aeadThenDecompressSupported : DC_BITFIELD_SIZE_1; Cpa8U lz4Reserved : DC_BITFIELD_SIZE_7; } dc_capabilities_lz4_t; #define DC_CAPS_LZ4_LENGTH (sizeof(dc_capabilities_lz4_t)) /** ***************************************************************************** * @ingroup dc_capabilities * DC lz4s capabilitities content * @description * Definition of lz4s capabilitities data *****************************************************************************/ typedef struct dc_capabilities_lz4s_s { /**< Bits set to '1' for each valid window size supported by * the compression implementation */ Cpa16U validWindowSizeMaskCompression; /**< Bits set to '1' for each valid window size supported by * the decompression implementation */ Cpa16U validWindowSizeMaskDecompression; /**< Flag to define if algorithm is supported (TRUE) or not (FALSE) */ Cpa8U supported : DC_BITFIELD_SIZE_1; /**< Flag to indicate if dictionary compression is supported (TRUE) or not * (FALSE) */ Cpa8U dictCompSupported : DC_BITFIELD_SIZE_1; /**< Dictionary type, see \ref CpaDcDictType */ Cpa8U dictCap : DC_BITFIELD_SIZE_2; /**< Session direction, see \ref CpaDcDir */ Cpa8U dirMask : DC_BITFIELD_SIZE_2; /**< Bypass incomplete operation if file error */ Cpa8U bypassIncompleteFileErr : DC_BITFIELD_SIZE_1; /**< True if the algorithm is supported by Auto select * best feature */ Cpa8U asbSupported : DC_BITFIELD_SIZE_1; /**< Window size, see \ref CpaDcCompWindowSize */ Cpa8U historyBufferSize : DC_BITFIELD_SIZE_3; /**< Min Match size, see \ref CpaDcCompMinMatch */ Cpa8U minMatch : DC_BITFIELD_SIZE_2; /**< True if the Instance can calculate an xxHash-32 hash over * the uncompressed data */ Cpa8U checksumXXHash32 : DC_BITFIELD_SIZE_1; /**< True if zero length requests */ Cpa8U zerolengthRequests : DC_BITFIELD_SIZE_1; /**< True if the current compression format supports programmable CRC64 */ Cpa8U programmableCrc64 : DC_BITFIELD_SIZE_1; /**< True if its preferred to keep ASB enabled */ Cpa8U asbEnablePref : DC_BITFIELD_SIZE_1; Cpa8U lz4sReserved : DC_BITFIELD_SIZE_7; } dc_capabilities_lz4s_t; #define DC_CAPS_LZ4S_LENGTH (sizeof(dc_capabilities_lz4s_t)) /** ***************************************************************************** * @ingroup dc_capabilities * Supported HW device generations. * @description * - QAT supported device generations ranging between Gen2 and Gen4. *****************************************************************************/ typedef enum dc_hw_gen_types { DC_CAPS_GEN2_HW = 2, DC_CAPS_GEN4_HW, DC_CAPS_GEN5_HW, } dc_hw_gen_types_t; /** ***************************************************************************** * @ingroup dc_capabilities * HW device DC capabilitities content * * @description * Definition of supported compression HW capabilitities * *****************************************************************************/ typedef struct dc_hw_device_capabilities_s /* sal_compression_device_data */ { /**< Device specific minimum output buffer size for static compression */ Cpa32U minOutputBuffSize; /**< Device specific minimum output buffer size for dynamic compression */ Cpa32U minOutputBuffSizeDynamic; /**< Maximum compression depths are supported */ Cpa8U highestHwCompressionDepth; /**< H/W generations */ Cpa8U hw_gen; /**< Enable/disable secureRam/acceleratorRam for intermediate buffers */ Cpa8U useDevRam : DC_BITFIELD_SIZE_1; /**< When set, implies device can decompress interim odd byte length * stateful decompression requests */ Cpa8U oddByteDecompInterim : DC_BITFIELD_SIZE_1; /**< When set, implies device can decompress odd byte length * stateful decompression requests when bFinal is absent */ Cpa8U oddByteDecompNobFinal : DC_BITFIELD_SIZE_1; /**< Flag to indicate if translator slice overflow is supported */ Cpa8U translatorOverflow : DC_BITFIELD_SIZE_1; /**< Flag to enable/disable delayed match mode */ Cpa8U enableDmm : DC_BITFIELD_SIZE_1; /**< Flag to indicate that uncompressed data are supported */ Cpa8U uncompressedDataSupported : DC_BITFIELD_SIZE_1; /**< decompressionServiceSupported and compressionServiceSupported * This combination of 2 flags indicates the supported services. In * the table below, each service runs on a dedicated ring pair or * queue. * * Compression | Decompression | Services * service | service |----------------------------- * supported | supported | compression | decompression *=========================================================== * false | false | disabled | disabled *----------------------------------------------------------- * true | false | enabled | disabled * | |(legacy mode)| *----------------------------------------------------------- * false | true | disabled | enabled *----------------------------------------------------------- * true | true | enabled | enabled */ /**< Flag to indicate if device supports decompression as a * separate service */ Cpa8U decompressionServiceSupported : DC_BITFIELD_SIZE_1; /**< Flag to indicate if device supports compression as a * service. When set, this service supports both compression and * decompression direction. */ Cpa8U compressionServiceSupported : DC_BITFIELD_SIZE_1; } dc_hw_device_capabilities_t /* sal_compression_device_data_t */; #define DC_CAPS_HW_DATA_LENGTH (sizeof(dc_hw_device_capabilities_t)) /** ***************************************************************************** * @ingroup dc_capabilities * DC capabilitities content * @description * Capabilitities struct to define data compression features. *****************************************************************************/ typedef struct dc_capabilities_s { /**< Device specific data, see \ref sal_compression_device_data_t */ dc_hw_device_capabilities_t deviceData; /**< CRC integrity */ dc_capabilities_crc_integrity_t crcIntegrity; /**< ASB */ dc_capabilities_asb_t asb; /**< CnV */ dc_capabilities_cnv_t cnv; /**< Algorithms related content, see \ref CpaDcCompType */ dc_capabilities_deflate_t deflate; dc_capabilities_lz4_t lz4; dc_capabilities_lz4s_t lz4s; /**< Generic data not related to device and not related * to the type of algorithm */ /**< Number of intermediate buffers */ Cpa16U numInterBuffs; /**< Session state, see \ref CpaDcState */ Cpa8U sessState : DC_BITFIELD_SIZE_2; /**< Checksum, see \ref CpaDcChecksum */ Cpa8U checksum : DC_BITFIELD_SIZE_4; /**< True if the instance supports stopping and reporting the end * of the last block in a compressed stream during a decompression * operation. */ Cpa8U endOfLastBlock : DC_BITFIELD_SIZE_1; /**< True if the instance does not support overflow resubmit */ Cpa8U overflowResubmitUnsupported : DC_BITFIELD_SIZE_1; /**< True if the instance does not support stateful lite */ Cpa8U statefulLiteUnsupported : DC_BITFIELD_SIZE_1; /**< If set to true the instance supports determinism in compression * direction */ Cpa8U determinism : DC_BITFIELD_SIZE_1; /**< Partially decompress a payload to fill up a certain amount of the * destination buffer */ Cpa8U partialDecompression : DC_BITFIELD_SIZE_1; /**< True if the instance supports 'batch and pack' compression */ Cpa8U batchAndPack : DC_BITFIELD_SIZE_1; /**< True if stored block generation */ Cpa8U storedBlockGeneration : DC_BITFIELD_SIZE_1; Cpa8U genericDeprecatedReserve : DC_BITFIELD_SIZE_1; /**< True if the instance supports parity error reporting */ Cpa8U reportParityError : DC_BITFIELD_SIZE_1; Cpa8U genericReserve : DC_BITFIELD_SIZE_1; /**< Populate the compression hardware block for QAT */ void (*dcCompHwBlockPopulate)( void *pService, void *pSessionDesc, CpaDcNsSetupData *pSetupData, icp_qat_hw_compression_config_t *pCompConfig, void *compDecomp, CpaBoolean bNsOp); void (*dcNsCompHwBlockPopulate)( void *pService, void *pSessionDesc, CpaDcNsSetupData *pSetupData, icp_qat_hw_compression_config_t *pCompConfig, void *compDecomp, CpaBoolean bNsOp); /**< Compress bound API's to calculate destination buffer size */ CpaStatus (*dcDeflateBound)(void *pService, CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize); CpaStatus (*dcLZ4Bound)(Cpa32U inputSize, Cpa32U *outputSize); CpaStatus (*dcLZ4SBound)(Cpa32U inputSize, Cpa32U *outputSize); } dc_capabilities_t; /* Type to access extended features bit fields */ typedef struct dc_extended_features_s { unsigned is_cnv : 1; /* Bit<0> */ unsigned padding : 7; unsigned is_cnvnr : 1; /* Bit<8> */ unsigned padding1 : 7; unsigned is_chain_compress_then_hash : 1; /* Bit<16> */ unsigned is_chain_compress_then_encrypt : 1; /* Bit<17> */ unsigned is_chain_compress_then_hash_encrypt : 1; /* Bit<18> */ unsigned is_chain_compress_then_encrypt_hash : 1; /* Bit<19> */ unsigned is_chain_compress_then_aead : 1; /* Bit<20> */ unsigned is_chain_hash_then_compress : 1; /* Bit<21> */ unsigned is_chain_hash_verify_then_decompress : 1; /* Bit<22> */ unsigned is_chain_decrypt_then_decompress : 1; /* Bit<23> */ unsigned is_chain_hash_verify_decrypt_then_decompress : 1; /* Bit<24> */ unsigned is_chain_decrypt_hash_verify_then_decompress : 1; /* Bit<25> */ unsigned is_chain_aead_then_decompress : 1; /* Bit<26> */ unsigned is_chain_decompress_then_hash_verify : 1; /* Bit<27> */ unsigned is_chain_compress_then_aead_then_hash : 1; /* Bit<28> */ unsigned is_e2e_comp_crc_over_header_plus_block : 1; /* Bit<29> */ unsigned is_e2e_comp_crc_over_block : 1; /* Bit<30> */ unsigned reserved : 1; } __attribute__((__packed__)) dc_extd_ftrs_t; /* Structure to refer extended FW capabilities */ typedef struct fw_caps_s { Cpa16U comp_algos; Cpa16U cksum_algos; Cpa32U deflate_caps; Cpa16U lz4_caps; Cpa16U lz4s_caps; Cpa8U is_fw_caps; } fw_caps_t; #define DC_CAPS_SECTION_LENGTH (sizeof(dc_capabilities_t)) #define DC_CAPS_BITFIELD_SET(capability, idx) capability |= (1 << idx); #define DC_CAPS_BITFIELD_CLR(capability, idx) capability &= ~(1 << idx); #define DC_CAPS_BITFIELD_GET(capability, idx) \ (capability & (1 << idx)) ? CPA_TRUE : CPA_FALSE; #define LAC_SHIFT_RIGHT(capability, shift) ((capability) >> (shift)) CpaStatus dcGetAsbAlgoSupportCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus); CpaStatus dcGetUncompDictSupportCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, Cpa32U dirMask, CpaBoolean *pCapStatus); CpaStatus dcGetZeroLengthReqCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus); CpaStatus dcGetPcrc64CapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus); CpaStatus SalCtrl_SetDCCaps(dc_capabilities_t *pDcCapabilities, int device_type, Cpa32U dcExtendedFeatures, fw_caps_t *fw_caps); CpaStatus dcGetHashChainingCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus); CpaStatus dcGetCompAeadChainingCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus); CpaStatus dcGetAeadDecompChainingCapabilityStatus( dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus); CpaStatus dcGetAsbEnablePrefCapabilityStatus(dc_capabilities_t *pDcCapabilities, Cpa32U algo, CpaBoolean *pCapStatus); #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* DC_CAPABILITIES_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_chain.h000066400000000000000000000245261503624047500320770ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_chain.h * * @ingroup Dc_Chaining * * @description * Definition of the data compression and crypto chaining parameters. * *****************************************************************************/ #ifndef DC_CHAIN_H #define DC_CHAIN_H #include "sal_types_compression.h" #include "icp_qat_fw_dc_chain.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "cpa_dc_chain.h" #include "lac_session.h" #include "dc_session.h" #define DC_CHAIN_TYPE_GET(pType) (*(CpaDcChainSessionType *)pType) #define DC_COMP_SESSION_SIZE \ (sizeof(dc_session_desc_t) + sizeof(LAC_ARCH_UINT) + LAC_64BYTE_ALIGNMENT) #define FIRST_DC_CHAIN_ITEM 0 #define NOT_APPLICABLE 0 /* List of the different OpData types supported as defined in the DC Chain API * header file. */ typedef enum dc_chain_opdata_type_e { DC_CHAIN_OPDATA_TYPE0 = 0, /**< Refer to the API definition for CpaDcChainOpData format */ } dc_chain_opdata_type_t; typedef struct dc_chain_opdata_ext_s { void *pOpData; /**< Pointer to the OpData structure being used */ dc_chain_opdata_type_t opDataType; /**< Indicates the type of OpData being used */ } dc_chain_opdata_ext_t; /* List of the different results structure types supported as defined in the DC * Chain API header file. */ typedef enum dc_chain_results_type_e { DC_CHAIN_RESULTS_TYPE0 = 0, /**< Refer to the API definition for CpaDcChainRqResults format */ } dc_chain_results_type_t; typedef struct dc_chain_results_ext_s { void *pResults; /**< Pointer to the results structure being used */ dc_chain_results_type_t resultsType; /**< Indicates the type of results being used */ } dc_chain_results_ext_t; typedef struct dc_chain_cmd_tbl_s { Cpa16U link0_key; /**< Session type key for first session in chaining */ Cpa16U link1_key; /**< Session type key for second session in chaining */ Cpa16U link2_key; /**< Session type key for third session in chaining */ icp_qat_comp_chain_cmd_id_t cmd_id; /**< Chaining operation */ icp_qat_comp_chain_20_cmd_id_t cmd_20_id; /**< Chaining 2.0 operation */ } dc_chain_cmd_tbl_t; typedef struct dc_chain_cookie_s { CpaInstanceHandle dcInstance; /**< Compression instance handle */ CpaDcSessionHandle pSessionHandle; /**< Pointer to the session handle */ icp_qat_fw_comp_chain_req_t request; /**< Compression chaining request */ dc_chain_results_ext_t extResults; /**< Extensible results buffer holding consumed and produced data */ void *pDcRspAddr; /**< chaining compression response buffer */ void *pCyRspAddr; /**< chaining hash response buffer */ void *pDcCookieAddr; /**< chaining compression cookie buffer */ void *pCyCookieAddr; /**< chaining hash cookie buffer */ void *callbackTag; /**< Opaque data supplied by the client */ } dc_chain_cookie_t; typedef struct dc_chain_session_head_s { union { icp_qat_comp_chain_req_hdr_t comn_hdr; /**< Compression chaining header for Gen2 */ icp_qat_fw_comn_req_hdr_t comn_hdr2; /**< Compression chaining header for non Gen2 */ } hdr; Cpa16U numLinks; dc_session_desc_t *pDcSessionDesc; lac_session_desc_t *pCySessionDesc; CpaDcCallbackFn pdcChainCb; /**< Callback function defined for the traditional compression session */ OsalAtomic pendingChainCbCount; /**< Keeps track of number of pending requests on stateless session */ } dc_chain_session_head_t; /** ***************************************************************************** * @ingroup Dc_Chaining * Initialize chaining service * * @description * Initialize chaining service, it will be call by * compression service initialization API * * @param[in,out] pCompService Compression service * @param[out] pChainService Chaining service * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ CpaStatus dcChainServiceInit(sal_compression_service_t *pCompService, sal_dc_chain_service_t *pChainService); /** ***************************************************************************** * @ingroup Dc_Chaining * Shutdown chaining service * * @description * Shutdown chaining service, it will be called by * compression shutdown API * * @param[in,out] pCompService Compression service * @param[in] pChainService Chaining service * * @retval none * *****************************************************************************/ void dcChainServiceShutdown(sal_compression_service_t *pCompService, sal_dc_chain_service_t *pChainService); /** ***************************************************************************** * @ingroup Dc_Chaining * Chaining perform operation * * @description * Chaining perform operation * * @param[in] dcInstance Instance handle derived from discovery * functions. * @param[in] pSessionHandle Pointer to a session handle. * @param[in] pSrcBuff Source buffer * @param[in] pDestBuff Destination buffer * @param[in] pInterBuff Pointer to intermediate buffer to be * used as internal staging area for * chaining operations. * @param[in] operation Chaining operation type * @param[in] numOperations Number of operations for the chaining * @param[in] pChainOpDataExt Extensible chaining operation data * @param[in,out] pResultsExt Extensible chaining response result * @param[in] callbackTag For synchronous operation this callback * shall be a null pointer. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_RESOURCE Failed to allocate required resources * @retval CPA_STATUS_RETRY Request re-submission needed * *****************************************************************************/ CpaStatus dcChainPerformOp(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaBufferList *pInterBuff, CpaDcChainOperations operation, Cpa8U numOperations, dc_chain_opdata_ext_t *pChainOpDataExt, dc_chain_results_ext_t *pResultsExt, void *callbackTag); /** ***************************************************************************** * @ingroup Dc_Chaining * Chaining response callback * * @description * Chaining response callback * * @param[in] pRespMsg Chaining response descriptor * * @retval none * *****************************************************************************/ void dcChainProcessResults(void *pRespMsg); #endif /* DC_CHAIN_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_crc32.h000066400000000000000000000112531503624047500317220ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef DC_CRC32_H_ #define DC_CRC32_H_ #include #include #include "lac_common.h" #include "dc_session.h" /** * @description * Calculates CRC-32 checksum for given buffer, adhering to RFC 1952 CRC * * @param[in] initial_crc Initial CRC-32 value (used for multi-segment calc) * @param[in] buffer Pointer to data byte array to calculate CRC on * @param[in] buffer_length Length of data array * * @retval uint32_t 32bit long CRC checksum for given buffer */ #ifdef USE_CCODE_CRC uint32_t crc32_gzip_refl_base(uint32_t initial_crc, uint8_t *buffer, uint64_t buffer_length); #else extern uint32_t crc32_gzip_refl_by8(uint32_t initial_crc, uint8_t *buffer, uint64_t buffer_length); #endif /** * @description * Helper function to calculate CRC32 checksum on a buffer list. * * For a given SGL, the CRC32 checksum is calculated based on the * size of the buffer list. * * @param[out] checksum New CRC32 checksum value * @param[in] pBufferList virtual address of src SGL to calculate CRC on. * @param[in] consumedBytes total number of bytes inside of pUserSrcBuff * to calculate CRC checksum for. * @param[in] seedChecksum Input checksum from where the calculation * will start from. * @note * currently only CRC-32 (0x4C11DB7) algorithm is supported for calculating * CRCs on input and output buffers and CRC value is expected to be * 32bit long. */ Cpa32U dcCalculateCrc32(CpaBufferList *pBufferList, Cpa32U consumedBytes, const Cpa32U seedChecksum); #endif /* end of DC_CRC32_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_crc64.h000066400000000000000000000155701503624047500317350ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef DC_CRC64_H_ #define DC_CRC64_H_ #include #include #include "lac_common.h" #include "dc_session.h" /** * @description * Calculates CRC-64 ECMA-182 checksum for given buffer * * @param[in] initial_crc Initial CRC-64 value (used for multi-segment calc) * @param[in] buffer Pointer to data byte array to calculate CRC on * @param[in] buffer_length Length of data array * * @retval uint64_t 64bit long CRC checksum for given buffer */ #ifdef USE_CCODE_CRC uint64_t crc64_ecma_norm_base(uint64_t initial_crc, const uint8_t *buffer, uint64_t buffer_length); #else extern uint64_t crc64_ecma_norm_by8(uint64_t initial_crc, const uint8_t *buffer, uint64_t buffer_length); #endif /** * @description * Helper function to calculate CRC64 checksum on a buffer list. * * For a given SGL, the CRC64 checksum is calculated based on the * size of the buffer list. * * @param[out] checksum New CRC64 checksum value * @param[in] pBufferList virtual address of src SGL to calculate CRC on. * @param[in] consumedBytes total number of bytes inside of pUserSrcBuff * to calculate CRC checksum for. * @param[in] seedChecksum Input checksum from where the calculation * will start from. * @note * currently only CRC-64 ECMA-182 (0x42f0E1EBA9EA3693) algorithm * is supported for calculating CRCs on input and output buffers * and CRC value is expected to be 64bit long. */ Cpa64U dcCalculateCrc64(const CpaBufferList *pBufferList, Cpa32U consumedBytes, Cpa64U seedChecksum); /** * @description * Creates a lookup table for CRC64 calculation * * Function creates a lookup table for a given polynomial. This table is * used to speed up CRC64 calculation at runtime. * * @param[in] crc64Polynomial CRC64 polynomial used for generating the CRC * lookup table. * @param[out] pCrcLookupTable Address of pointer to the CRC lookup table * created. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_RESOURCE Memory allocation error * */ CpaStatus dcGenerateLookupTable(Cpa64U crc64Polynomial, Cpa64U **pCrcLookupTable); /** * @description * Calculates programmable CRC-64 checksum for given Buffer List * * Function loops through all of the flat buffers in the buffer list. * CRC is calculated for each flat buffer, but output CRC from * buffer[0] is used as input seed for buffer[1] CRC calculation * (and so on until looped through all flat buffers). * Resulting CRC is final CRC for all buffers in the buffer list struct * * @param[in] pCrcConfig Pointer to the CRC configuration used for * calculating the checksum. * @param[in] pCrcLookupTable Pointer to the CRC lookup table used for * calculating the checksum. * @param[in] bufferList Pointer to data byte array to calculate CRC * on. * @param[in] consumedBytes Total number of bytes to calculate CRC on * (for all buffer in buffer list) * @param[out] pSwCrc Pointer to 64bit long CRC checksum for the * given buffer list. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in */ CpaStatus dcCalculateProgCrc64(const CpaCrcControlData *pCrcConfig, Cpa64U *pCrcLookupTable, const CpaBufferList *pBufferList, Cpa32U consumedBytes, Cpa64U *pSwCrc); #endif /* end of DC_CRC64_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_datapath.h000066400000000000000000000454761503624047500326120ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_datapath.h * * @ingroup Dc_DataCompression * * @description * Definition of the Data Compression datapath parameters. * ******************* * **********************************************************/ #ifndef DC_DATAPATH_H_ #define DC_DATAPATH_H_ #include "cpa_dc.h" #include "dc_session.h" #include "sal_types_compression.h" #include "lac_mem_pools.h" #include "icp_qat_fw_dc_chain.h" #define LAC_QAT_DC_REQ_SZ_LW 32 #define LAC_QAT_DC_RESP_SZ_LW 8 /* C62x and C3xxx pcie rev0 devices require an additional 32bytes */ #define DC_DEST_BUFFER_STA_ADDITIONAL_SIZE (32) /* Minimum destination buffer size for decompression */ #define DC_DEST_BUFFER_DEC_MIN_SIZE (1) /* Restriction on the source and destination buffer sizes for compression due * to the firmware taking 32 bits parameters. The max size is 2^32-1 */ #define DC_BUFFER_MAX_SIZE (0xFFFFFFFF) /* DC Source & Destination buffer type (FLAT/SGL) */ #define DC_DEFAULT_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_SGL #define DC_DP_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT /* Offset to first byte of Input Byte Counter (IBC) in state register */ #define DC_STATE_IBC_OFFSET (8) /* Size in bytes of input byte counter (IBC) in state register */ #define DC_IBC_SIZE_IN_BYTES (4) /* Offset to first byte to CRC32 in state register */ #define DC_STATE_CRC32_OFFSET (40) /* Offset to first byte to output CRC32 in state register */ #define DC_STATE_OUTPUT_CRC32_OFFSET (48) /* Offset to first byte to input CRC32 in state register */ #define DC_STATE_INPUT_CRC32_OFFSET (52) /* Offset to first byte of ADLER32 in state register */ #define DC_STATE_ADLER32_OFFSET (44) /* 8 bit mask value */ #define DC_8_BIT_MASK (0xff) /* 8 bit shift position */ #define DC_8_BIT_SHIFT_POS (8) /* Size in bytes of checksum */ #define DC_CHECKSUM_SIZE_IN_BYTES (4) /* Mask used to set the most significant bit to zero */ #define DC_STATE_REGISTER_ZERO_MSB_MASK (0x7F) /* Mask used to keep only the most significant bit and set the others to zero */ #define DC_STATE_REGISTER_KEEP_MSB_MASK (0x80) /* Compression state register word containing the parity bit */ #define DC_STATE_REGISTER_PARITY_BIT_WORD (5) /* Location of the parity bit within the compression state register word */ #define DC_STATE_REGISTER_PARITY_BIT (7) /* size which needs to be reserved before the results field to * align the results field with the API struct */ #define DC_API_ALIGNMENT_OFFSET (offsetof(CpaDcDpOpData, results)) /* Default values for CNV integrity checks, * those are used to inform hardware of specifying CRC parameters to be used * when calculating CRCs */ #define DC_CRC_POLY_DEFAULT 0x04c11db7 #define DC_CRC64_POLY_DEFAULT 0x42f0e1eba9ea3693ULL #define DC_XOR_FLAGS_DEFAULT 0x000e0000 #define DC_XOR_OUT_DEFAULT 0xffffffff #define DC_XOR64_OUT_DEFAULT 0x0ULL #define DC_XOR64_MASK_DEFAULT 0x0ULL #define DC_DEFAULT_CRC 0x0 #define DC_DEFAULT_ADLER32 0x1 #define DC_REFLECT_IN_DEFAULT 0x0 #define DC_REFLECT_OUT_DEFAULT 0x0 /* DC Chain info in compression cookie */ typedef struct dc_chain_info_s { CpaBoolean isDcChaining; /* True if this request is part of a DC Chain operation */ } dc_chain_info_t; /* List of the different OpData types supported as defined in the DC API header * file. */ typedef enum dc_opdata_type_e { DC_OPDATA_TYPE0 = 0, /**< Refer to the API definition for CpaDcOpData format */ DC_OPDATA_TYPE1 /**< Refer to the API definition for CpaDcOpData2 format */ } dc_opdata_type_t; typedef struct dc_opdata_ext_s { void *pOpData; /**< Pointer to the OpData structure being used */ dc_opdata_type_t opDataType; /**< Indicates the type of OpData being used */ } dc_opdata_ext_t; /** ******************************************************************************* * @ingroup cpaDc Data Compression * Compression cookie * @description * This cookie stores information for a particular compression or * decompression perform op. * This includes various user-supplied parameters for the operation which * will be needed in our callback function. * A pointer to this cookie is stored in the opaque data field of the QAT * message so that it can be accessed in the asynchronous callback. * @note * The order of the parameters within this structure is important. It needs * to match the order of the parameters in CpaDcDpOpData up to the * pSessionHandle. This allows the correct processing of the callback. *****************************************************************************/ typedef struct dc_compression_cookie_s { Cpa8U dcReqParamsBuffer[DC_API_ALIGNMENT_OFFSET]; /**< Memory block - was previously reserved for request parameters. * Now size maintained so following members align with API struct, * but no longer used for request parameters */ CpaDcRqResults reserved; /**< This is reserved for results to correctly align the structure * to match the one from the data plane API */ CpaInstanceHandle dcInstance; /**< Compression instance handle */ CpaDcSessionHandle pSessionHandle; /**< Pointer to the session handle. It is either a real address or a * special value used to identify requests coming from the NS API. */ icp_qat_fw_comp_req_t request; /**< Compression request */ void *callbackTag; /**< Opaque data supplied by the client */ dc_session_desc_t *pSessionDesc; /**< Pointer to the session descriptor */ CpaDcFlush flushFlag; /**< Flush flag */ CpaDcOpData *pDcOpData; /**< struct containing flags and CRC related data for this session */ CpaBoolean integrityCrcCheck; /**< If set to true, the implementation will verify that data * integrity is preserved through the processing pipeline. * This behaviour supports stateless and stateful behavior for * both static and dynamic Huffman encoding. * * Integrity CRC checking is not supported for decompression operations * over data that contains multiple gzip headers. */ CpaBoolean verifyHwIntegrityCrcs; /**< If set to true, software calculated CRCs will be compared * against hardware generated integrity CRCs to ensure that data * integrity is maintained when transferring data to and from the * hardware accelerator. */ CpaDcRqResults *pResults; /**< Pointer to result buffer holding consumed and produced data */ Cpa32U srcTotalDataLenInBytes; /**< Total length of the source data */ Cpa32U dstTotalDataLenInBytes; /**< Total length of the destination data */ dc_request_dir_t compDecomp; /**< Used to know whether the request is compression or decompression. * Useful when defining the session as combined */ #ifdef ICP_DC_ERROR_SIMULATION CpaDcReqStatus dcErrorToSimulate; /**< Dc error inject simulation */ #endif CpaBufferList *pUserSrcBuff; /**< virtual userspace ptr to source SGL */ CpaBufferList *pUserDestBuff; /**< virtual userspace ptr to destination SGL */ CpaDcCallbackFn pCbFunc; /**< Callback function defined for the traditional sessionless API */ CpaDcChecksum checksumType; /**< Type of checksum */ dc_integrity_crc_fw_t dataIntegrityCrcs; /**< Data integrity table */ dc_chain_info_t dcChain; /**< DC Chain info if DC used as part of a DC Chain operation. */ } dc_compression_cookie_t; /** ***************************************************************************** * @ingroup Dc_DataCompression * Callback function called for compression and decompression requests in * asynchronous mode * * @description * Called to process compression and decompression response messages. This * callback will check for errors, update the statistics and will call the * user callback * * @param[in] pRespMsg Response message * *****************************************************************************/ void dcCompression_ProcessCallback(void *pRespMsg); #ifndef KERNEL_SPACE #ifdef ICP_PARAM_CHECK CpaStatus dcCheckOpData(sal_compression_service_t *pService, CpaDcOpData *pOpData, CpaDcSessionDir sessDirection); #endif #endif /** *************************************************************************** * @ingroup Dc_DataCompression * Generates DC dummy response * * @description * This function is called during the error state of the device to * generate dummy responses from the DC request memory pool. * * @param[in] pBucket pointer to the bucket of memblks * * @retval CPA_STATUS_SUCCESS Successfully polled a memory pool with data * that generate dummy responses. * @retval CPA_STATUS_RETRY There are no inflight requests in the * memory pool associated with the instance * ***************************************************************************/ CpaStatus dcCompression_SwRespMsgCallback(lac_memblk_bucket_t *pBucket); /** ***************************************************************************** * @ingroup Dc_DataCompression * Describes CNV and CNVNR modes * * @description * This enum is used to indicate the CNV modes. * *****************************************************************************/ typedef enum dc_cnv_mode_s { DC_NO_CNV = 0, /* CNV = CPA_FALSE, CNVNR = CPA_FALSE */ DC_CNV, /* CNV = CPA_TRUE, CNVNR = CPA_FALSE */ DC_CNVNR, /* CNV = CPA_TRUE, CNVNR = CPA_TRUE */ } dc_cnv_mode_t; /** ***************************************************************************** * @ingroup Dc_DataCompression * Create the requests for compression or decompression * * @description * Create the requests for compression or decompression. This function * will update the cookie will all required information. * * @param[out] pCookie Pointer to the compression cookie * @param[in] pService Pointer to the compression service * @param[in] pSessionDesc Pointer to the session descriptor * @param[in] pSessionHandle Session handle * @param[in] pSrcBuff Pointer to data buffer for compression * @param[in] pDestBuff Pointer to buffer space for data after * compression * @param[in] pResults Pointer to results structure * @param[in] flushFlag Indicates the type of flush to be * performed * @param[in] pOpData Pointer to request information structure * holding parameters for cpaDcCompress2 * and CpaDcDecompressData2 * @param[in] callbackTag Pointer to the callback tag * @param[in] compDecomp Direction of the operation * @param[in] cnvMode CNV Mode * @param[in] pDictionaryData Pointer to CpaDcDictionaryData structure * containing parameters for dictionary * compression requests. If it is not a * dictionary request then this parameter * should be passed as NULL. * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ CpaStatus dcCreateRequest(dc_compression_cookie_t *pCookie, sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, CpaDcOpData *pOpData, void *callbackTag, dc_request_dir_t compDecomp, dc_cnv_mode_t cnvMode, CpaDcDictionaryData *pDictionaryData); /** ***************************************************************************** * @ingroup Dc_DataCompression * Populate the compression request parameters * * @description * This function will populate the compression request parameters * * @param[out] pCompReqParams Pointer to the compression request parameters * @param[in] pCookie Pointer to the compression cookie * *****************************************************************************/ void dcCompRequestParamsPopulate(icp_qat_fw_comp_req_params_t *pCompReqParams, dc_compression_cookie_t *pCookie); void dcHandleIntegrityChecksums(dc_compression_cookie_t *pCookie, CpaCrcData *crc_external, CpaDcRqResults *pDcResults, CpaDcHuffType huffType, CpaDcCompType compType, CpaDcChecksum checksumType, CpaBoolean isDcNs, icp_qat_comp_chain_20_cmd_id_t chain_id); void dcHandleIntegrityChecksumsLegacy(dc_compression_cookie_t *pCookie, CpaCrcData *crc_external, CpaDcRqResults *pDcResults, CpaDcHuffType huffType, CpaDcChecksum checksumType, CpaDcSessionState sessState, CpaDcSessionDir sessDirection, CpaBoolean isDcNs); CpaStatus dcParamCheck(const CpaInstanceHandle dcInstance, const CpaDcSessionHandle pSessionHandle, const sal_compression_service_t *pService, const CpaBufferList *pSrcBuff, const CpaBufferList *pDestBuff, const CpaDcRqResults *pResults, const dc_session_desc_t *pSessionDesc, const CpaDcFlush flushFlag, const Cpa64U srcBuffSize); CpaStatus dcCompDecompData(sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc, CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, CpaDcOpData *pOpData, void *callbackTag, dc_request_dir_t compDecomp, CpaBoolean isAsyncMode, dc_cnv_mode_t cnvMode, CpaDcDictionaryData *pDictionaryData); CpaStatus dcCheckSourceData(sal_compression_service_t *pService, CpaDcSessionHandle pSessionHandle, CpaBufferList *pSrcBuff, CpaBufferList *pDestBuff, CpaDcRqResults *pResults, CpaDcFlush flushFlag, Cpa64U srcBuffSize, CpaDcSkipData *skipData); CpaStatus dcCheckDestinationData(sal_compression_service_t *pService, CpaDcSessionHandle pSessionHandle, CpaBufferList *pDestBuff, dc_request_dir_t compDecomp); CpaStatus dcCheckOpData(sal_compression_service_t *pService, CpaDcOpData *pOpData, CpaDcSessionDir sessDirection); CpaStatus dcCheckDictData(CpaDcDictionaryData *pDictionaryData, sal_compression_service_t *pService, dc_session_desc_t *pSessionDesc); #endif /* DC_DATAPATH_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_err_sim.h000066400000000000000000000067641503624047500324610ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_err_sim.h * * @ingroup Dc_DataCompression * * @description * Definition of the Data Compression Error Simulation parameters. * *****************************************************************************/ #ifndef DC_ERROR_SIM_H #define DC_ERROR_SIM_H #include "cpa_types.h" #include "cpa_dc.h" #define DC_ERROR_SIM 0xFF #define DC_ERROR_SIM_MAX 0xFE CpaDcReqStatus dcGetErrors(void); CpaStatus dcSetNumError(Cpa8U numErrors, CpaDcReqStatus dcError); CpaBoolean dcErrorSimEnabled(void); #endif /* DC_ERROR_SIM_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_error_counter.h000066400000000000000000000066741503624047500337110ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_error_counter.h * * @ingroup Dc_DataCompression * * @description * Definition of the Data Compression Error Counter parameters. * *****************************************************************************/ #ifndef DC_ERROR_COUNTER_H #define DC_ERROR_COUNTER_H #include "cpa_types.h" #include "cpa_dc.h" #define MAX_DC_ERROR_TYPE 101 void dcErrorLog(CpaDcReqStatus dcError); Cpa64U getDcErrorCounter(CpaDcReqStatus dcError); #endif /* DC_ERROR_COUNTER_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_header_footer.h000066400000000000000000000106761503624047500336240ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_header_footer.h * * @ingroup Dc_DataCompression * * @description * Definition of the Data Compression header and footer parameters. * *****************************************************************************/ #ifndef DC_HEADER_FOOTER_H_ #define DC_HEADER_FOOTER_H_ /* Header and footer sizes for Zlib and Gzip */ #define DC_ZLIB_HEADER_SIZE (2) #define DC_GZIP_HEADER_SIZE (10) #define DC_ZLIB_FOOTER_SIZE (4) #define DC_GZIP_FOOTER_SIZE (8) /* Values used to build the headers for Zlib and Gzip */ #define DC_GZIP_ID1 (0x1f) #define DC_GZIP_ID2 (0x8b) #define DC_GZIP_FILESYSTYPE (0x03) #define DC_ZLIB_WINDOWSIZE_OFFSET (4) #define DC_ZLIB_FLEVEL_OFFSET (6) #define DC_ZLIB_HEADER_OFFSET (31) /* Compression level for Zlib */ #define DC_ZLIB_LEVEL_0 (0) #define DC_ZLIB_LEVEL_1 (1) #define DC_ZLIB_LEVEL_2 (2) #define DC_ZLIB_LEVEL_3 (3) /* CM parameter for Zlib */ #define DC_ZLIB_CM_DEFLATE (8) /* Type of Gzip compression */ #define DC_GZIP_FAST_COMP (4) #define DC_GZIP_MAX_COMP (2) CpaStatus dcDeflateGenerateHeader(CpaFlatBuffer *pDestBuff, CpaDcChecksum checksum, CpaDcCompLvl compLevel, Cpa32U *count); CpaStatus dcDeflateGenerateFooter(CpaFlatBuffer *pDestBuff, CpaDcRqResults *pRes, Cpa64U totalLength, CpaDcChecksum checksum); #endif /* DC_HEADER_FOOTER_H_ */ dc_header_footer_lz4.h000066400000000000000000000131011503624047500343200ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_header_footer_lz4.h * * @ingroup Dc_DataCompression * * @description * Definition of the Data Compression header and footer parameters * for LZ4. * *****************************************************************************/ #ifndef DC_HEADER_FOOTER_LZ4_H_ #define DC_HEADER_FOOTER_LZ4_H_ #include "lac_common.h" /* Header and footer size LZ4 */ #define DC_LZ4_HEADER_SIZE 7 #define DC_LZ4_FOOTER_SIZE 8 /* Values used to build the headers for LZ4 */ #define DC_LZ4_FH_ID 0x184D2204U #define DC_LZ4_FH_FLG_VERSION 0x1 #define DC_LZ4_FH_MAX_BLK_SIZE_ENUM_MIN 4 /* Values used to build footers for LZ4 */ #define DC_LZ4_FF_END_MARK 0x0 /** ***************************************************************************** * @ingroup dc_lz4_generate_header * Generate the LZ4 Header. * * @description * This function generates the LZ4 compression header. * * @param[in] dest_buff Pointer to the destination buffer the * LZ4 header will be written to. * @param[in] max_block_size LZ4 Maximum block size. * @param[in] block_indep LZ4 block independence value. * @param[in,out] count Pointer to counter that stores * amount of generated bytes. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. *****************************************************************************/ CpaStatus dc_lz4_generate_header(const CpaFlatBuffer *dest_buff, const CpaDcCompLZ4BlockMaxSize max_block_size, const CpaBoolean block_indep, Cpa32U *count); /** ***************************************************************************** * @ingroup dc_lz4_generate_footer * Generate the LZ4 footer. * * @description * This function generates the LZ4 compression footer. * * @param[in] dest_buff Pointer to the destination buffer where * the LZ4 footer will be written to. * @param[in] pRes Pointer to the CpaDcRqResults structure * that holds XXHASH32. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. *****************************************************************************/ CpaStatus dc_lz4_generate_footer(const CpaFlatBuffer *dest_buff, const CpaDcRqResults *pRes); #endif /* DC_HEADER_FOOTER_LZ4_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_ns_datapath.h000066400000000000000000000136501503624047500332770ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_ns_datapath.h * * @ingroup Dc_DataCompression * * @description * Definition of the Data Compression datapath parameters. * ****************************************************************************/ #ifndef DC_NS_DATAPATH_H #define DC_NS_DATAPATH_H /* No-Session [NS] operations can come into the lib on the following APIs: * - Traditional API [Trad] : cpaDcNsXxx APIs * - Data-plane API [DP] : cpaDcDpEnqueueXxx with * CpaDcDpOpData->pSetupData populated and * pSessionHandle = NULL * The response from the firmware needs to be handled differently * depending on whether the request came in the DP or Trad path. * * As the pSessionHandle field in the internal cookie is superfluous for * NS operations, that field is overloaded to convey DP/Trad information. * This field is set when the request is set up and examined during the * response handling. */ #define DCNS 1 #define DCDPNS 0 void dcNsCompression_ProcessCallback(void *pRespMsg); /** ***************************************************************************** * @ingroup Dc_DataCompression * Construct compression base request * * @description * This function will construct a compression base request, i.e. a request * that serves as the base for a Traditional API request or a Data Plane * API request. The function is the NS API equivalent of dcInitSession. * * @param[out] pMsg Pointer to empty message * @param[in] pService Pointer to compression service * @param[in] pSetupData Pointer to (de)compression parameters * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_UNSUPPORTED Unsupported algorithm/feature *****************************************************************************/ CpaStatus dcNsCreateBaseRequest(icp_qat_fw_comp_req_t *pMsg, sal_compression_service_t *pService, CpaDcNsSetupData *pSetupData); /** ***************************************************************************** * @ingroup Dc_DataCompression * Set the cnvErrorInjection flag in sal compression service request * * @description * This function enables/disable the CnVError injection for the No-Session * case. All Compression requests sent are injected with CnV errors. * * @param[in] dcInstance Instance Handle * @param[in] enableCnvErrInj TRUE/FALSE to Enable/Disable CnV Error * Injection * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * @retval CPA_STATUS_UNSUPPORTED Unsupported feature *****************************************************************************/ CpaStatus dcNsSetCnvErrorInj(CpaInstanceHandle dcInstance, CpaBoolean enableCnvErrInj); #endif /* DC_NS_DATAPATH_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_session.h000066400000000000000000000632041503624047500324740ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dc_session.h * * @ingroup Dc_DataCompression * * @description * Definition of the Data Compression session parameters. * *****************************************************************************/ #ifndef DC_SESSION_H #define DC_SESSION_H #include "cpa_dc_dp.h" #include "icp_qat_fw_comp.h" #include "sal_qat_cmn_msg.h" #include "sal_types_compression.h" /* Maximum size of the state registers decompression 128 bytes */ #define DC_QAT_DCPR_STATE_REGISTERS_MAX_SIZE (128) /* Maximum size of the state registers compression 64 bytes * for legacy devices and not for CPM2.0 as it * does not support stateful compression */ #define DC_QAT_CPR_STATE_REGISTERS_MAX_SIZE (64) /* Retrieve the session descriptor pointer from the session context structure * that the user allocates. The pointer to the internally realigned address * is stored at the start of the session context that the user allocates */ #define DC_SESSION_DESC_FROM_CTX_GET(pSession) \ (dc_session_desc_t *)(*(LAC_ARCH_UINT *)pSession) /* Maximum size for the compression part of the content descriptor */ #define DC_QAT_COMP_CONTENT_DESC_SIZE sizeof(icp_qat_fw_comp_cd_hdr_t) /* Maximum size for the translator part of the content descriptor */ #define DC_QAT_TRANS_CONTENT_DESC_SIZE \ (sizeof(icp_qat_fw_xlt_cd_hdr_t) + DC_QAT_MAX_TRANS_SETUP_BLK_SZ) /* Maximum size of the decompression content descriptor */ #define DC_QAT_CONTENT_DESC_DECOMP_MAX_SIZE \ LAC_ALIGN_POW2_ROUNDUP(DC_QAT_COMP_CONTENT_DESC_SIZE, \ (1 << LAC_64BYTE_ALIGNMENT_SHIFT)) /* Maximum size of the compression content descriptor */ #define DC_QAT_CONTENT_DESC_COMP_MAX_SIZE \ LAC_ALIGN_POW2_ROUNDUP(DC_QAT_COMP_CONTENT_DESC_SIZE + \ DC_QAT_TRANS_CONTENT_DESC_SIZE, \ (1 << LAC_64BYTE_ALIGNMENT_SHIFT)) /* Xxhash32 accumulator initialisers */ #define XXHASH_PRIME32_A 0x9E3779B1U #define XXHASH_PRIME32_B 0x85EBCA77U /* Direction of the request */ typedef enum dc_request_dir_e { DC_COMPRESSION_REQUEST = 1, DC_DECOMPRESSION_REQUEST } dc_request_dir_t; /* Type of the compression request */ typedef enum dc_request_type_e { DC_REQUEST_FIRST = 1, DC_REQUEST_SUBSEQUENT } dc_request_type_t; typedef enum dc_block_type_e { DC_CLEARTEXT_TYPE = 0, DC_STATIC_TYPE, DC_DYNAMIC_TYPE } dc_block_type_t; /* Internal data structure supporting end to end data integrity checks. */ typedef struct dc_integrity_crc_fw_s { Cpa32U crc32; /* CRC32 checksum returned for compressed data */ union { Cpa32U adler32; /* ADLER32 checksum returned for compressed data */ Cpa32U xxhash32; /* XXHASH32 checksum returned for compressed data */ }; union { struct { Cpa32U oCrc32Cpr; /* CRC32 checksum returned for data output by compression * accelerator */ Cpa32U iCrc32Cpr; /* CRC32 checksum returned for input data to compression accelerator */ Cpa32U oCrc32Xlt; /* CRC32 checksum returned for data output by translator accelerator */ Cpa32U iCrc32Xlt; /* CRC32 checksum returned for input data to translator accelerator */ Cpa32U xorFlags; /* Initialise transactor pCRC controls in state register */ Cpa32U crcPoly; /* CRC32 polynomial used by hardware */ Cpa32U xorOut; /* CRC32 from XOR stage (Input CRC is xor'ed with value in the * state) */ Cpa32U deflateBlockType; /* Bit 1 - Bit 0 * 0 0 -> RAW DATA + Deflate header. * This will not produced any CRC check because * the output will not come from the slices. * It will be a simple copy from input to output * buffers list. * 0 1 -> Static deflate block type * 1 0 -> Dynamic deflate block type * 1 1 -> Invalid type */ }; struct { Cpa64U iCrc64Cpr; /* CRC64 checksum returned for input data to compression accelerator */ Cpa64U oCrc64Cpr; /* CRC64 checksum returned for data output by compression * accelerator */ Cpa32U reflectIn; /* Flag to indicate if the input should be reflected */ Cpa32U reflectOut; /* Flag to indicate if the output should be reflected */ Cpa64U oCrc64Xlt; /* CRC64 checksum returned for data output by translator accelerator */ Cpa64U crc64Poly; /* CRC64 polynomial used by hardware */ Cpa64U xor64Out; /* CRC64 from XOR stage (Input CRC is xor'ed with value in the * state) */ Cpa64U xor64Mask; /* XOR mask used by XOR stage */ }; }; } dc_integrity_crc_fw_t; typedef struct dc_sw_checksums_s { union { struct { Cpa32U swCrc32I; Cpa32U swCrc32O; }; struct { Cpa64U swCrc64I; Cpa64U swCrc64O; }; }; } dc_sw_checksums_t; /* Configuration data for CRC operation */ typedef struct dc_crc_config_s { dc_integrity_crc_fw_t crcParam; /**< Crc parameters for firmware */ Cpa64U *pCrcLookupTable; /**< Lookup table to speed up CRC calculation at runtime */ CpaBoolean useProgCrcSetup; /**< Flag to indicate if programmable CRC parameters used */ } dc_crc_config_t; /* Session descriptor structure for compression */ typedef struct dc_session_desc_s { Cpa8U stateRegistersComp[DC_QAT_CPR_STATE_REGISTERS_MAX_SIZE]; /**< State registers for compression */ Cpa8U stateRegistersDecomp[DC_QAT_DCPR_STATE_REGISTERS_MAX_SIZE]; /**< State registers for decompression */ icp_qat_fw_comp_req_t reqCacheComp; /**< Cache as much as possible of the compression request in a pre-built * request */ icp_qat_fw_comp_req_t reqCacheDecomp; /**< Cache as much as possible of the decompression request in a pre-built * request */ dc_request_type_t requestType; /**< Type of the compression request. As stateful mode do not support more * than one in-flight request there is no need to use spinlocks */ dc_request_type_t previousRequestType; /**< Type of the previous compression request. Used in cases where there the * stateful operation needs to be resubmitted */ CpaDcHuffType huffType; /**< Huffman tree type */ CpaDcCompType compType; /**< Compression type */ CpaDcChecksum checksumType; /**< Type of checksum */ CpaDcAutoSelectBest autoSelectBestHuffmanTree; /**< Indicates if the implementation selects the best Huffman encoding */ CpaDcSessionDir sessDirection; /**< Session direction */ CpaDcSessionState sessState; /**< Session state */ Cpa32U deflateWindowSize; /**< Window size */ CpaDcCompLvl compLevel; /**< Compression level */ CpaDcCompLZ4BlockMaxSize lz4BlockMaxSize; /**generic_service_info.stats->bDcStatsEnabled) \ { \ osalAtomicInc( \ &pService->pCompStatsArr[offsetof(CpaDcStats, statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) #else #define COMPRESSION_STAT_INC(statistic, pService) #endif /* Macro to get all Compression stats (from internal array of atomics) */ #define COMPRESSION_STATS_GET(compStats, pService) \ do \ { \ int i; \ for (i = 0; i < COMPRESSION_NUM_STATS; i++) \ { \ ((Cpa64U *)compStats)[i] = \ osalAtomicGet(&pService->pCompStatsArr[i]); \ } \ } while (0) /* Macro to reset all Compression stats */ #define COMPRESSION_STATS_RESET(pService) \ do \ { \ int i; \ for (i = 0; i < COMPRESSION_NUM_STATS; i++) \ { \ osalAtomicSet(0, &pService->pCompStatsArr[i]); \ } \ } while (0) /** ******************************************************************************* * @ingroup Dc_DataCompression * Initialises the compression stats * * @description * This function allocates and initialises the stats array to 0 * * @param[in] pService Pointer to a compression service structure * * @retval CPA_STATUS_SUCCESS initialisation successful * @retval CPA_STATUS_RESOURCE array allocation failed * *****************************************************************************/ CpaStatus dcStatsInit(sal_compression_service_t *pService); /** ******************************************************************************* * @ingroup Dc_DataCompression * Frees the compression stats * * @description * This function frees the stats array * * @param[in] pService Pointer to a compression service structure * * @retval None * *****************************************************************************/ void dcStatsFree(sal_compression_service_t *pService); /** ******************************************************************************* * @ingroup Dc_DataCompression * Resets the compression stats * * @description * This function resets the stats array * * @param[in] pService Pointer to a compression service structure * * @retval None * *****************************************************************************/ void dcStatsReset(sal_compression_service_t *pService); #endif /* DC_STATS_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/include/dc_xxhash32.h000066400000000000000000000067221503624047500324630ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef DC_XXHASH_H_ #define DC_XXHASH_H_ #include "cpa.h" #include "cpa_dc.h" #include "lac_common.h" /** * @description * Calculate LZ4 checksum on an input buffer * * @param[return] checksum New LZ4 checksum value. * @param[in] xxH32input Virtual addr of src input to calculate hash on. * @param[in] dataLength Length in bytes the input data is. */ CpaStatus dcXxhash32Lz4HdrChecksum(const void *xxH32input, const Cpa32U dataLength, Cpa8U *checksum); #endif /* end of DC_XXHASH32_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/compression/reg_sizes.asm000066400000000000000000000170221503624047500312400ustar00rootroot00000000000000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Copyright(c) 2011-2024 Intel Corporation All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in ; the documentation and/or other materials provided with the ; distribution. ; * Neither the name of Intel Corporation nor the names of its ; contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ; SPDX-License-Identifier: BSD-3-Clause ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %ifndef _REG_SIZES_ASM_ %define _REG_SIZES_ASM_ %ifndef AS_FEATURE_LEVEL %define AS_FEATURE_LEVEL 4 %endif %define EFLAGS_HAS_CPUID (1<<21) %define FLAG_CPUID1_ECX_CLMUL (1<<1) %define FLAG_CPUID1_EDX_SSE2 (1<<26) %define FLAG_CPUID1_ECX_SSE3 (1) %define FLAG_CPUID1_ECX_SSE4_1 (1<<19) %define FLAG_CPUID1_ECX_SSE4_2 (1<<20) %define FLAG_CPUID1_ECX_POPCNT (1<<23) %define FLAG_CPUID1_ECX_AESNI (1<<25) %define FLAG_CPUID1_ECX_OSXSAVE (1<<27) %define FLAG_CPUID1_ECX_AVX (1<<28) %define FLAG_CPUID1_EBX_AVX2 (1<<5) %define FLAG_CPUID7_EBX_AVX2 (1<<5) %define FLAG_CPUID7_EBX_AVX512F (1<<16) %define FLAG_CPUID7_EBX_AVX512DQ (1<<17) %define FLAG_CPUID7_EBX_AVX512IFMA (1<<21) %define FLAG_CPUID7_EBX_AVX512PF (1<<26) %define FLAG_CPUID7_EBX_AVX512ER (1<<27) %define FLAG_CPUID7_EBX_AVX512CD (1<<28) %define FLAG_CPUID7_EBX_AVX512BW (1<<30) %define FLAG_CPUID7_EBX_AVX512VL (1<<31) %define FLAG_CPUID7_ECX_AVX512VBMI (1<<1) %define FLAG_CPUID7_ECX_AVX512VBMI2 (1 << 6) %define FLAG_CPUID7_ECX_GFNI (1 << 8) %define FLAG_CPUID7_ECX_VAES (1 << 9) %define FLAG_CPUID7_ECX_VPCLMULQDQ (1 << 10) %define FLAG_CPUID7_ECX_VNNI (1 << 11) %define FLAG_CPUID7_ECX_BITALG (1 << 12) %define FLAG_CPUID7_ECX_VPOPCNTDQ (1 << 14) %define FLAGS_CPUID7_EBX_AVX512_G1 (FLAG_CPUID7_EBX_AVX512F | FLAG_CPUID7_EBX_AVX512VL | FLAG_CPUID7_EBX_AVX512BW | FLAG_CPUID7_EBX_AVX512CD | FLAG_CPUID7_EBX_AVX512DQ) %define FLAGS_CPUID7_ECX_AVX512_G2 (FLAG_CPUID7_ECX_AVX512VBMI2 | FLAG_CPUID7_ECX_GFNI | FLAG_CPUID7_ECX_VAES | FLAG_CPUID7_ECX_VPCLMULQDQ | FLAG_CPUID7_ECX_VNNI | FLAG_CPUID7_ECX_BITALG | FLAG_CPUID7_ECX_VPOPCNTDQ) %define FLAG_XGETBV_EAX_XMM (1<<1) %define FLAG_XGETBV_EAX_YMM (1<<2) %define FLAG_XGETBV_EAX_XMM_YMM 0x6 %define FLAG_XGETBV_EAX_ZMM_OPM 0xe0 %define FLAG_CPUID1_EAX_AVOTON 0x000406d0 %define FLAG_CPUID1_EAX_STEP_MASK 0xfffffff0 ; define d and w variants for registers %define raxd eax %define raxw ax %define raxb al %define rbxd ebx %define rbxw bx %define rbxb bl %define rcxd ecx %define rcxw cx %define rcxb cl %define rdxd edx %define rdxw dx %define rdxb dl %define rsid esi %define rsiw si %define rsib sil %define rdid edi %define rdiw di %define rdib dil %define rbpd ebp %define rbpw bp %define rbpb bpl %define ymm0x xmm0 %define ymm1x xmm1 %define ymm2x xmm2 %define ymm3x xmm3 %define ymm4x xmm4 %define ymm5x xmm5 %define ymm6x xmm6 %define ymm7x xmm7 %define ymm8x xmm8 %define ymm9x xmm9 %define ymm10x xmm10 %define ymm11x xmm11 %define ymm12x xmm12 %define ymm13x xmm13 %define ymm14x xmm14 %define ymm15x xmm15 %define zmm0x xmm0 %define zmm1x xmm1 %define zmm2x xmm2 %define zmm3x xmm3 %define zmm4x xmm4 %define zmm5x xmm5 %define zmm6x xmm6 %define zmm7x xmm7 %define zmm8x xmm8 %define zmm9x xmm9 %define zmm10x xmm10 %define zmm11x xmm11 %define zmm12x xmm12 %define zmm13x xmm13 %define zmm14x xmm14 %define zmm15x xmm15 %define zmm16x xmm16 %define zmm17x xmm17 %define zmm18x xmm18 %define zmm19x xmm19 %define zmm20x xmm20 %define zmm21x xmm21 %define zmm22x xmm22 %define zmm23x xmm23 %define zmm24x xmm24 %define zmm25x xmm25 %define zmm26x xmm26 %define zmm27x xmm27 %define zmm28x xmm28 %define zmm29x xmm29 %define zmm30x xmm30 %define zmm31x xmm31 %define zmm0y ymm0 %define zmm1y ymm1 %define zmm2y ymm2 %define zmm3y ymm3 %define zmm4y ymm4 %define zmm5y ymm5 %define zmm6y ymm6 %define zmm7y ymm7 %define zmm8y ymm8 %define zmm9y ymm9 %define zmm10y ymm10 %define zmm11y ymm11 %define zmm12y ymm12 %define zmm13y ymm13 %define zmm14y ymm14 %define zmm15y ymm15 %define zmm16y ymm16 %define zmm17y ymm17 %define zmm18y ymm18 %define zmm19y ymm19 %define zmm20y ymm20 %define zmm21y ymm21 %define zmm22y ymm22 %define zmm23y ymm23 %define zmm24y ymm24 %define zmm25y ymm25 %define zmm26y ymm26 %define zmm27y ymm27 %define zmm28y ymm28 %define zmm29y ymm29 %define zmm30y ymm30 %define zmm31y ymm31 %define DWORD(reg) reg %+ d %define WORD(reg) reg %+ w %define BYTE(reg) reg %+ b %define XWORD(reg) reg %+ x %ifidn __OUTPUT_FORMAT__,elf32 section .note.gnu.property note alloc noexec align=4 DD 0x00000004,0x0000000c,0x00000005,0x00554e47 DD 0xc0000002,0x00000004,0x00000003 %endif %ifidn __OUTPUT_FORMAT__,elf64 section .note.gnu.property note alloc noexec align=8 DD 0x00000004,0x00000010,0x00000005,0x00554e47 DD 0xc0000002,0x00000004,0x00000003,0x00000000 %endif %ifidn __OUTPUT_FORMAT__,elf32 section .note.GNU-stack noalloc noexec nowrite progbits section .text %endif %ifidn __OUTPUT_FORMAT__,elf64 %define __x86_64__ section .note.GNU-stack noalloc noexec nowrite progbits section .text %endif %ifidn __OUTPUT_FORMAT__,win64 %define __x86_64__ %endif %ifidn __OUTPUT_FORMAT__,macho64 %define __x86_64__ %endif %ifdef __x86_64__ %define endbranch db 0xf3, 0x0f, 0x1e, 0xfa %else %define endbranch db 0xf3, 0x0f, 0x1e, 0xfb %endif %ifdef REL_TEXT %define WRT_OPT %elifidn __OUTPUT_FORMAT__, elf64 %define WRT_OPT wrt ..plt %else %define WRT_OPT %endif %macro mk_global 1-3 %ifdef __NASM_VER__ %ifidn __OUTPUT_FORMAT__, macho64 global %1 %elifidn __OUTPUT_FORMAT__, win64 global %1 %else global %1:%2 %3 %endif %else global %1:%2 %3 %endif %endmacro ; Fixes for nasm lack of MS proc helpers %ifdef __NASM_VER__ %ifidn __OUTPUT_FORMAT__, win64 %macro alloc_stack 1 sub rsp, %1 %endmacro %macro proc_frame 1 %1: %endmacro %macro save_xmm128 2 movdqa [rsp + %2], %1 %endmacro %macro save_reg 2 mov [rsp + %2], %1 %endmacro %macro rex_push_reg 1 push %1 %endmacro %macro push_reg 1 push %1 %endmacro %define end_prolog %endif %define endproc_frame %endif %ifidn __OUTPUT_FORMAT__, macho64 %define elf64 macho64 mac_equ equ 1 %endif %endif ; ifndef _REG_SIZES_ASM_ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/000077500000000000000000000000001503624047500255215ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/000077500000000000000000000000001503624047500264725ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/000077500000000000000000000000001503624047500314205ustar00rootroot00000000000000lac_dh_control_path.c000066400000000000000000000111511503624047500354720ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * @file lac_dh_control_path.c Control path functions for diffie hellman. * Implements the API functions and the init and shutdown functions * * @ingroup LacDh * *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "cpa_cy_dh.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Osal include */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_sym.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_common.h" #include "lac_hooks.h" #include "lac_dh_stats_p.h" /* ******************************************************************************** * Static Variables ******************************************************************************** */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ /** ***************************************************************************** * @ingroup LacDh * *****************************************************************************/ #ifdef QAT_LEGACY_ALGORITHMS CpaStatus LacDh_Init(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; /* Initialise and reset all statistics */ status = LacDh_StatsInit(instanceHandle); /* Call compile time param check function to ensure it is included in the build by the compiler */ LacDh_CompileTimeAssertions(); return status; } /* LacDh_Init */ #else CpaStatus LacDh_Init(CpaInstanceHandle instanceHandle) { LAC_LOG("DH algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } #endif lac_dh_data_path.c000066400000000000000000001015171503624047500347310ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * * @file lac_dh_data_path.c * * @defgroup LacDh Diffie Hellman * * @ingroup LacAsym * * diffie hellman data path functions * * @lld_start * * @lld_overview * This is the Diffie Hellman feature implementation. It implements 2 DH API * services: phase 1 and phase 2. Statistics are maintained for each service. * For each service the parameters supplied by the client are checked, and then * input/output argument lists are constructed before calling the pke comms * layer. * * The service implementations are a straightforward * marshalling of client-supplied parameters for the QAT. I.e. there is * minimal logic handled by this component. Buffer alignment is handled by * the PKE QAT Comms layer. * * The user's input buffers are checked for null params, correct length, msb * and lsb set where necessary. The following parameter checks based on the * standard are also performed for Diffie Hellman * * * Diffie Hellman: * Phase 1: y = g^x mod p (PKCS #3) * * Test: P must have msb set * Test: P must be odd * Test: 0 < g < p * Test: 0 < x < p-1 * * Phase 2: z = y^x mod p (PKCS #3) * * Test: P must have msb set * Test: P must be odd * Test: 0 < x < p-1 * * @lld_dependencies * - @ref LacAsymCommonQatComms "PKE QAT Comms" : For creating and sending * messages to the QAT * - @ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_initialisation * On instance initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ /* API Includes */ #include "cpa.h" #include "cpa_cy_dh.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ /* OSAL Includes */ #include "Osal.h" /* FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" /* ADF includes */ #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_debug.h" #include "icp_adf_transport.h" /* Look Aside Includes */ #include "lac_log.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_sync.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "lac_dh_stats_p.h" /** ****************************************************************************** * @ingroup LacDh * @description * This enum lists the types of diffie hellman operation. *****************************************************************************/ typedef enum { LAC_DH_OP = 0, /**< Diffie Hellman operation */ LAC_DH_G2_OP /**< Diffie Hellman operation when exp = 2 */ } lac_dh_op_type_t; /* ******************************************************************************* * Static Variables ******************************************************************************* */ #define LAC_G2_DELTA (-2) /**< @ingroup LacDh * the delta to be subtracted from the exponent when testing for * g2 type operation */ #ifdef QAT_LEGACY_ALGORITHMS /* Maps between operation sizes and PKE function ids */ static const Cpa32U lacDHSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_768_BITS, PKE_DH_768}, {LAC_1024_BITS, PKE_DH_1024}, {LAC_1536_BITS, PKE_DH_1536}, {LAC_2048_BITS, PKE_DH_2048}, {LAC_3072_BITS, PKE_DH_3072}, {LAC_4096_BITS, PKE_DH_4096}, {LAC_8192_BITS, PKE_DH_8192}}; /* Maps between operation sizes and PKE function ids */ static const Cpa32U lacDHG2SizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_768_BITS, PKE_DH_G2_768}, {LAC_1024_BITS, PKE_DH_G2_1024}, {LAC_1536_BITS, PKE_DH_G2_1536}, {LAC_2048_BITS, PKE_DH_G2_2048}, {LAC_3072_BITS, PKE_DH_G2_3072}, {LAC_4096_BITS, PKE_DH_G2_4096}, {LAC_8192_BITS, PKE_DH_G2_8192}}; /* ******************************************************************************* * Define static function definitions ******************************************************************************* */ /* * This function verifies that all the input parameters for the Diffie Hellman * Phase 1 operation are valid and also returns the opSize in bytes */ STATIC CpaStatus LacDh_Phase1GetOpSizeAndCheck( const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pDhPhase1Cb, const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, CpaFlatBuffer *pLocalOctetStringPV, Cpa32U *pOpSizeInBytes); /* * This function verifies that all the input parameters for the Diffie Hellman * Phase 2 operation are valid and also returns the opSize in Bytes */ STATIC CpaStatus LacDh_Phase2GetOpSizeAndCheck( const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pDhPhase2Cb, const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, CpaFlatBuffer *pOctetStringSecretKey, Cpa32U *pOpSizeInBytes); /* * This function is called after a Diffie Hellman * Phase1 message has been received from the QAT. */ STATIC void LacDh_ProcessPhase1Cb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData); /* * This function is called after a Diffie Hellman * Phase2 message has been received from the QAT. */ STATIC void LacDh_ProcessPhase2Cb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData); /* * This function is the synchronous version of cpaCyDhKeyGenPhase1 */ STATIC CpaStatus LacDh_SynKeyGenPhase1(const CpaInstanceHandle instanceHandle, const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, CpaFlatBuffer *pLocalOctetStringPV); /* * This function is the synchronous version of cpaCyDhKeyGenPhase2Secret */ STATIC CpaStatus LacDh_SynKeyGenPhase2Secret( const CpaInstanceHandle instanceHandle, const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, CpaFlatBuffer *pOctetStringSecretKey); /* ******************************************************************************* * Global Variables ******************************************************************************* */ /* ******************************************************************************* * Define public/global function definitions ******************************************************************************* */ #ifdef ICP_PARAM_CHECK STATIC CpaBoolean LacDh_IsValidDhSize(Cpa32U opSizeInBytes) { Cpa32U opSizeInBits = LAC_BYTES_TO_BITS(opSizeInBytes); if ((LAC_768_BITS != opSizeInBits) && (LAC_1024_BITS != opSizeInBits) && (LAC_1536_BITS != opSizeInBits) && (LAC_2048_BITS != opSizeInBits) && (LAC_3072_BITS != opSizeInBits) && (LAC_4096_BITS != opSizeInBits) && (LAC_8192_BITS != opSizeInBits)) { LAC_INVALID_PARAM_LOG( "Invalid operation size. Valid op sizes for " "DH are 768, 1024, 1536, 2048, 3072, 4096 and 8192 bits."); return CPA_FALSE; } return CPA_TRUE; } #endif STATIC lac_dh_op_type_t LacDh_GetDhOpType(const CpaFlatBuffer *pExp) { LAC_ASSERT_NOT_NULL(pExp); /* if exp is equal to 2 then return op type G2, otherwise normal DH op */ if (0 == LacPke_CompareZero(pExp, LAC_G2_DELTA)) { return LAC_DH_G2_OP; } return LAC_DH_OP; } STATIC CpaStatus LacDh_SynKeyGenPhase1(const CpaInstanceHandle instanceHandle, const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, CpaFlatBuffer *pLocalOctetStringPV) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDhKeyGenPhase1(instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, pPhase1KeyGenData, pLocalOctetStringPV); } else { LAC_DH_STAT_INC(numDhPhase1KeyGenRequestErrors, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { /* * Inc stats only if the wait for callback failed. */ LAC_DH_STAT_INC(numDhPhase1KeyGenCompletedErrors, instanceHandle); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } STATIC CpaStatus LacDh_SynKeyGenPhase2Secret( const CpaInstanceHandle instanceHandle, const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, CpaFlatBuffer *pOctetStringSecretKey) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDhKeyGenPhase2Secret(instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, pPhase2SecretKeyGenData, pOctetStringSecretKey); } else { LAC_DH_STAT_INC(numDhPhase2KeyGenRequestErrors, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { /* * Inc stats only if the wait for callback failed. */ LAC_DH_STAT_INC(numDhPhase2KeyGenCompletedErrors, instanceHandle); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** ***************************************************************************** * @ingroup LacDh * *****************************************************************************/ CpaStatus cpaCyDhKeyGenPhase1( const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pDhPhase1Cb, void *pCallbackTag, const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, CpaFlatBuffer *pLocalOctetStringPV) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; icp_qat_fw_mmp_input_param_t inArgList = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outArgList = {.flat_array = {0}}; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U opSizeInBytes = 0; lac_pke_op_cb_data_t cbData = {0}; lac_dh_op_type_t opType = LAC_DH_OP; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pDhPhase1Cb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pPhase1KeyGenData, (LAC_ARCH_UINT)pLocalOctetStringPV); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if Diffie-Hellman is supported */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dh); /* Check if the API has been called in synchronous mode */ if (NULL == pDhPhase1Cb) { return LacDh_SynKeyGenPhase1( instanceHandle, pPhase1KeyGenData, pLocalOctetStringPV); } /* Get the opSize and check the members of the key gen data struct */ status = LacDh_Phase1GetOpSizeAndCheck(instanceHandle, pDhPhase1Cb, pPhase1KeyGenData, pLocalOctetStringPV, &opSizeInBytes); if (CPA_STATUS_SUCCESS == status) { opType = LacDh_GetDhOpType( (const CpaFlatBuffer *)&(pPhase1KeyGenData->baseG)); /* Zero ms bytes of the output buffer - assumes size of output buffer is greater or equal to sizeInBytes */ osalMemSet(pLocalOctetStringPV->pData, 0, (pLocalOctetStringPV->dataLenInBytes - opSizeInBytes)); if (LAC_DH_OP == opType) { functionalityId = LacPke_GetMmpId(LAC_BYTES_TO_BITS(opSizeInBytes), lacDHSizeIdMap, LAC_ARRAY_LEN(lacDHSizeIdMap)); /* Fill out input lists - we use mmp_dh_768 for all functionalityIds - checked at compile time (see lac_dh_intereface_check.c) that this is a valid assumption */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_dh_768.g, &(pPhase1KeyGenData->baseG)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, g)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, g)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_dh_768.e, &(pPhase1KeyGenData->privateValueX)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, e)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, e)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_dh_768.m, &(pPhase1KeyGenData->primeP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, m)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, m)] = CPA_FALSE; /* Fill out output lists */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_dh_768.r, pLocalOctetStringPV); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_output_t, r)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_dh_output_t, r)] = CPA_FALSE; } else { /* opType == LAC_DH_G2_OP */ functionalityId = LacPke_GetMmpId(LAC_BYTES_TO_BITS(opSizeInBytes), lacDHG2SizeIdMap, LAC_ARRAY_LEN(lacDHG2SizeIdMap)); /* Fill out input lists */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_dh_g2_768.e, &(pPhase1KeyGenData->privateValueX)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_input_t, e)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_input_t, e)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_dh_g2_768.m, &(pPhase1KeyGenData->primeP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_input_t, m)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_input_t, m)] = CPA_FALSE; /* Fill out Output List */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_dh_g2_768.r, pLocalOctetStringPV); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_output_t, r)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_output_t, r)] = CPA_FALSE; } cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pPhase1KeyGenData; cbData.pClientCb = pDhPhase1Cb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pLocalOctetStringPV; status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacDh_ProcessPhase1Cb, &cbData, instanceHandle); } if (CPA_STATUS_SUCCESS != status) { LAC_DH_STAT_INC(numDhPhase1KeyGenRequestErrors, instanceHandle); } else { LAC_DH_STAT_INC(numDhPhase1KeyGenRequests, instanceHandle); } return status; } CpaStatus LacDh_Phase1GetOpSizeAndCheck( const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pDhPhase1Cb, const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, CpaFlatBuffer *pLocalOctetStringPV, Cpa32U *pOpSizeInBytes) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDhPhase1Cb); /* Check members of pPhase1KeyGenData are valid. Check pPrimeP, pBaseG, * pLocalOctetStringPV and pPrivateValueX */ LAC_CHECK_NULL_PARAM(pPhase1KeyGenData); LAC_CHECK_NULL_PARAM(pLocalOctetStringPV); LAC_CHECK_FLAT_BUFFER(&pPhase1KeyGenData->primeP); #endif /* Set the opSizeInBytes */ *pOpSizeInBytes = LacPke_GetMinBytes(&(pPhase1KeyGenData->primeP)); #ifdef ICP_PARAM_CHECK if (CPA_FALSE == LacDh_IsValidDhSize((*pOpSizeInBytes))) { LAC_INVALID_PARAM_LOG("Invalid size for opSizeInBytes"); return CPA_STATUS_INVALID_PARAM; } /* Check that the MSB and LSB of the prime buffer is set */ LAC_CHECK_FLAT_BUFFER_MSB_LSB( &(pPhase1KeyGenData->primeP), (*pOpSizeInBytes), CPA_TRUE, CPA_TRUE); /* Check other input buffers for NULL and zero-len */ LAC_CHECK_FLAT_BUFFER_PARAM(&pPhase1KeyGenData->baseG, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &pPhase1KeyGenData->privateValueX, CHECK_NONE, 0); /* output params - based on buffer size */ LAC_CHECK_FLAT_BUFFER_PARAM( pLocalOctetStringPV, CHECK_GREATER_EQUALS, (*pOpSizeInBytes)); /* Standards based checks */ /* 0 < g < p */ LAC_CHECK_NON_ZERO_PARAM(&(pPhase1KeyGenData->baseG)); if (LacPke_Compare( &(pPhase1KeyGenData->baseG), 0, &(pPhase1KeyGenData->primeP), 0) >= 0) { LAC_INVALID_PARAM_LOG("baseG must be < primeP"); return CPA_STATUS_INVALID_PARAM; } /* 0 < x < p-1 */ LAC_CHECK_NON_ZERO_PARAM(&(pPhase1KeyGenData->privateValueX)); if (LacPke_Compare(&(pPhase1KeyGenData->privateValueX), 0, &(pPhase1KeyGenData->primeP), -1) >= 0) { LAC_INVALID_PARAM_LOG("privateValueX must be < primeP - 1"); return CPA_STATUS_INVALID_PARAM; } #endif return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup LacDh * *****************************************************************************/ CpaStatus cpaCyDhKeyGenPhase2Secret( const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pDhPhase2Cb, void *pCallbackTag, const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, CpaFlatBuffer *pOctetStringSecretKey) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; icp_qat_fw_mmp_input_param_t inArgList = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outArgList = {.flat_array = {0}}; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; lac_pke_op_cb_data_t cbData = {0}; Cpa32U opSizeInBytes = 0; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pDhPhase2Cb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pPhase2SecretKeyGenData, (LAC_ARCH_UINT)pOctetStringSecretKey); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if Diffie-Hellman is supported */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dh); /* Check if the API has been called in synchronous mode */ if (NULL == pDhPhase2Cb) { return LacDh_SynKeyGenPhase2Secret( instanceHandle, pPhase2SecretKeyGenData, pOctetStringSecretKey); } /* Get the opSize and check the members of the key gen data struct */ status = LacDh_Phase2GetOpSizeAndCheck(instanceHandle, pDhPhase2Cb, pPhase2SecretKeyGenData, pOctetStringSecretKey, &opSizeInBytes); if (CPA_STATUS_SUCCESS == status) { /* Always use LAC_DH_OP service for Phase2 */ functionalityId = LacPke_GetMmpId(LAC_BYTES_TO_BITS(opSizeInBytes), lacDHSizeIdMap, LAC_ARRAY_LEN(lacDHSizeIdMap)); /* Fill out input lists */ LAC_MEM_SHARED_WRITE_FROM_PTR( inArgList.mmp_dh_768.g, &(pPhase2SecretKeyGenData->remoteOctetStringPV)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, g)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, g)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( inArgList.mmp_dh_768.e, &(pPhase2SecretKeyGenData->privateValueX)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, e)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, e)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_dh_768.m, &(pPhase2SecretKeyGenData->primeP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, m)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_dh_input_t, m)] = CPA_FALSE; /* Fill out output lists */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_dh_768.r, pOctetStringSecretKey); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dh_output_t, r)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_dh_output_t, r)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pPhase2SecretKeyGenData; cbData.pClientCb = pDhPhase2Cb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pOctetStringSecretKey; status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacDh_ProcessPhase2Cb, &cbData, instanceHandle); } /* if any of the preceding steps failed then we need to perform clean up */ if (CPA_STATUS_SUCCESS != status) { LAC_DH_STAT_INC(numDhPhase2KeyGenRequestErrors, instanceHandle); } else { LAC_DH_STAT_INC(numDhPhase2KeyGenRequests, instanceHandle); } return status; } STATIC CpaStatus LacDh_Phase2GetOpSizeAndCheck( const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pDhPhase2Cb, const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, CpaFlatBuffer *pOctetStringSecretKey, Cpa32U *pOpSizeInBytes) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pDhPhase2Cb); LAC_CHECK_NULL_PARAM(pPhase2SecretKeyGenData); LAC_CHECK_NULL_PARAM(pOctetStringSecretKey); LAC_CHECK_FLAT_BUFFER(&pPhase2SecretKeyGenData->primeP); #endif *pOpSizeInBytes = LacPke_GetMinBytes(&(pPhase2SecretKeyGenData->primeP)); #ifdef ICP_PARAM_CHECK if (CPA_FALSE == LacDh_IsValidDhSize((*pOpSizeInBytes))) { LAC_INVALID_PARAM_LOG("Invalid size for opSizeInBytes"); return CPA_STATUS_INVALID_PARAM; } /* Check that the MSB and LSB of the prime buffer is set */ LAC_CHECK_FLAT_BUFFER_MSB_LSB(&(pPhase2SecretKeyGenData->primeP), (*pOpSizeInBytes), CPA_TRUE, CPA_TRUE); /* Check remoteOctetStringPV */ LAC_CHECK_FLAT_BUFFER_PARAM_PKE( &(pPhase2SecretKeyGenData->remoteOctetStringPV), CHECK_LESS_EQUALS, (*pOpSizeInBytes), CPA_FALSE); /* Check privateValueX for NULL and zero-len */ LAC_CHECK_FLAT_BUFFER_PARAM( &pPhase2SecretKeyGenData->privateValueX, CHECK_NONE, 0); /* output params */ LAC_CHECK_FLAT_BUFFER_PARAM( pOctetStringSecretKey, CHECK_GREATER_EQUALS, (*pOpSizeInBytes)); /* Standards based checks */ /* 0 < x < p-1 */ LAC_CHECK_NON_ZERO_PARAM(&(pPhase2SecretKeyGenData->privateValueX)); if (LacPke_Compare(&(pPhase2SecretKeyGenData->privateValueX), 0, &(pPhase2SecretKeyGenData->primeP), -1) >= 0) { LAC_INVALID_PARAM_LOG("privateValueX must be < primeP - 1"); return CPA_STATUS_INVALID_PARAM; } #endif return CPA_STATUS_SUCCESS; } void LacDh_ProcessPhase1Cb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDhPhase1KeyGenOpData *pOpData = NULL; CpaFlatBuffer *pLocalOctetStringPV = NULL; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDhPhase1KeyGenOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pLocalOctetStringPV = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pLocalOctetStringPV); /* increment stats */ LAC_DH_STAT_INC(numDhPhase1KeyGenCompleted, instanceHandle); if (CPA_STATUS_SUCCESS != status) { LAC_DH_STAT_INC(numDhPhase1KeyGenCompletedErrors, instanceHandle); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pLocalOctetStringPV); } void LacDh_ProcessPhase2Cb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDhPhase2SecretKeyGenOpData *pOpData = NULL; CpaFlatBuffer *pOctetStringSecretKey = NULL; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDhPhase2SecretKeyGenOpData *)LAC_CONST_PTR_CAST( pCbData->pClientOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOctetStringSecretKey = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pOctetStringSecretKey); /* increment stats */ LAC_DH_STAT_INC(numDhPhase2KeyGenCompleted, instanceHandle); if (CPA_STATUS_SUCCESS != status) { LAC_DH_STAT_INC(numDhPhase2KeyGenCompletedErrors, instanceHandle); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pOctetStringSecretKey); } #else CpaStatus cpaCyDhKeyGenPhase1( const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pDhPhase1Cb, void *pCallbackTag, const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, CpaFlatBuffer *pLocalOctetStringPV) { LAC_LOG("DH algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaCyDhKeyGenPhase2Secret( const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pDhPhase2Cb, void *pCallbackTag, const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, CpaFlatBuffer *pOctetStringSecretKey) { LAC_LOG("DH algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } #endif lac_dh_interface_check.c000066400000000000000000000177301503624047500361040ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_dh_interface_check.c * * @ingroup Lac_Dh * * This file checks at compile time that the IA/FW interface is as expected * For example, in lac_dh_data_path.c we use the fact that the index of g in the * structure icp_qat_fw_mmp_dh_768_input_t is equal to the index of g in the * structure icp_qat_fw_mmp_dh_768_input_t. If this assumption becomes invalid * (FW interface changes to break the assumption or the compiler moves things * around) this file will fail to compile. * * Note for structures with only 1 member no check is required. * ***************************************************************************/ #include "cpa.h" #include "icp_qat_fw_pke.h" #include "icp_qat_fw_mmp.h" #include "lac_common.h" #define COMPILE_TIME_ASSERT(pred) \ switch (0) \ { \ case 0: \ case pred:; \ } void LacDh_CompileTimeAssertions(void) { /* ************************************************************* * DH Checks * ************************************************************* */ /* Check that icp_qat_fw_mmp_dh_768_input_t, icp_qat_fw_mmp_dh_1024_input_t, icp_qat_fw_mmp_dh_1536_input_t, icp_qat_fw_mmp_dh_2048_input_t, icp_qat_fw_mmp_dh_3072_input_t, icp_qat_fw_mmp_dh_4096_input_t, icp_qat_fw_mmp_dh_8192_input_t structures are equivalent */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dh_1024_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_1024_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_1024_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dh_1536_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_1536_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_1536_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dh_2048_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_2048_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_2048_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dh_3072_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_3072_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_3072_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dh_4096_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_4096_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_4096_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dh_8192_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_8192_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_8192_input_t, m)); /* ************************************************************* * DH G2 Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_1024_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_1024_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_1536_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_1536_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_2048_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_2048_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_3072_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_3072_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_4096_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_4096_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_8192_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_768_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dh_g2_8192_input_t, m)); } lac_dh_stats.c000066400000000000000000000236021503624047500341400ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * * @file lac_dh_stats.c diffie hellman stats functions * * @ingroup LacDh * @description This file implements functions for Diffie Hellman stats. *****************************************************************************/ #include "cpa.h" #include "cpa_cy_dh.h" /* Osal include */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_common.h" #include "lac_hooks.h" #include "sal_service_state.h" #include "sal_statistics.h" #include "lac_dh_stats_p.h" /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* Number of Diffie Helman statistics */ #ifdef QAT_LEGACY_ALGORITHMS #define LAC_DH_NUM_STATS (sizeof(CpaCyDhStats64) / sizeof(Cpa64U)) /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ CpaStatus LacDh_StatsInit(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pCryptoService->pLacDhStatsArr), LAC_DH_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { LAC_OS_BZERO( LAC_CONST_VOLATILE_PTR_CAST(pCryptoService->pLacDhStatsArr), LAC_DH_NUM_STATS * sizeof(OsalAtomic)); } return status; } void LacDh_StatsFree(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; if (NULL != pCryptoService->pLacDhStatsArr) { LAC_OS_FREE(pCryptoService->pLacDhStatsArr); } } void LacDh_StatsReset(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_OS_BZERO(LAC_CONST_VOLATILE_PTR_CAST(pCryptoService->pLacDhStatsArr), LAC_DH_NUM_STATS * sizeof(OsalAtomic)); } CpaStatus cpaCyDhQueryStats(CpaInstanceHandle instanceHandle_in, CpaCyDhStats *pDhStats) { Cpa32U i = 0; sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pDhStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_RUNNING_CHECK(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dh); LAC_CHECK_NULL_PARAM(pDhStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; for (i = 0; i < LAC_DH_NUM_STATS; i++) { ((Cpa32U *)pDhStats)[i] = (Cpa32U)osalAtomicGet(&pCryptoService->pLacDhStatsArr[i]); } return CPA_STATUS_SUCCESS; } /* cpaCyDhQueryStats */ CpaStatus cpaCyDhQueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyDhStats64 *pDhStats) { Cpa32U i = 0; sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pDhStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_RUNNING_CHECK(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dh); LAC_CHECK_NULL_PARAM(pDhStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; for (i = 0; i < LAC_DH_NUM_STATS; i++) { ((Cpa64U *)pDhStats)[i] = osalAtomicGet(&pCryptoService->pLacDhStatsArr[i]); } return CPA_STATUS_SUCCESS; } /* cpaCyDhQueryStats64 */ #ifndef DISABLE_STATS void LacDh_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; if (CPA_TRUE == pCryptoService->generic_service_info.stats->bDhStatsEnabled) { osalAtomicInc(&pCryptoService->pLacDhStatsArr[offset / sizeof(Cpa64U)]); } } /* LacDh_StatIncrement */ #endif /* DISABLE_STATS */ void LacDh_StatsShow(CpaInstanceHandle instanceHandle) { CpaCyDhStats64 dhStats = {0}; (void)cpaCyDhQueryStats64(instanceHandle, &dhStats); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " Diffie Hellman Stats " BORDER "\n" SEPARATOR); /* perform Info */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DH Phase1 Key Gen Requests: %16llu " BORDER "\n" BORDER " DH Phase1 Key Gen Request Err: %16llu " BORDER "\n" BORDER " DH Phase1 Key Gen Completed: %16llu " BORDER "\n" BORDER " DH Phase1 Key Gen Completed Err:%16llu " BORDER "\n" SEPARATOR, dhStats.numDhPhase1KeyGenRequests, dhStats.numDhPhase1KeyGenRequestErrors, dhStats.numDhPhase1KeyGenCompleted, dhStats.numDhPhase1KeyGenCompletedErrors); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DH Phase2 Key Gen Requests: %16llu " BORDER "\n" BORDER " DH Phase2 Key Gen Request Err: %16llu " BORDER "\n" BORDER " DH Phase2 Key Gen Completed: %16llu " BORDER "\n" BORDER " DH Phase2 Key Gen Completed Err:%16llu " BORDER "\n" SEPARATOR, dhStats.numDhPhase2KeyGenRequests, dhStats.numDhPhase2KeyGenRequestErrors, dhStats.numDhPhase2KeyGenCompleted, dhStats.numDhPhase2KeyGenCompletedErrors); } #else CpaStatus LacDh_StatsInit(CpaInstanceHandle instanceHandle) { LAC_LOG_DEBUG("DH algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } void LacDh_StatsFree(CpaInstanceHandle instanceHandle) { LAC_LOG_DEBUG("DH algorithm is not supported\n"); } void LacDh_StatsReset(CpaInstanceHandle instanceHandle) { LAC_LOG_DEBUG("DH algorithm is not supported\n"); } CpaStatus cpaCyDhQueryStats(CpaInstanceHandle instanceHandle_in, CpaCyDhStats *pDhStats) { LAC_LOG_DEBUG("DH algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaCyDhQueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyDhStats64 *pDhStats) { LAC_LOG_DEBUG("DH algorithm is not supported\n"); return CPA_STATUS_UNSUPPORTED; } void LacDh_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle) { LAC_LOG_DEBUG("DH algorithm is not supported\n"); } void LacDh_StatsShow(CpaInstanceHandle instanceHandle) { LAC_LOG_DEBUG("DH algorithm is not supported\n"); } #endif lac_dh_stats_p.h000066400000000000000000000143021503624047500344610ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/diffie_hellman/* * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** ******************************************************************************* * @file lac_dh_stats_p.h Definitions and prototypes for Diffie Hellman stats * * @ingroup LacDh * * @lld_start * In the LAC API the stats fields are defined as Cpa32U but * OsalAtomic is the type that the atomic API supports. Therefore we * need to define a structure internally with the same fields as the API * stats structure, but each field must be of type OsalAtomic. * * - Incrementing Statistics:\n * Atomically increment the statistic on the internal stats structure. * * - Providing a copy of the stats back to the user:\n * Use atomicGet to read the atomic variable for each stat field in the * local internal stat structure. These values are saved in structure * (as defined by the LAC API) that the client will provide a pointer * to as a parameter. * * - Stats Show:\n * Use atomicGet to read the atomic variables for each field in the local * internal stat structure and print to the screen * * - Stats Array:\n * A macro is used to get the offset off the stat in the structure. This * offset is passed to a function which uses it to increment the stat * at that offset. * * @lld_end * ***************************************************************************/ /******************************************************************************/ #ifndef _LAC_DH_STATS_P_H_ #define _LAC_DH_STATS_P_H_ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "cpa_cy_dh.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /******************************************************************************/ /** ******************************************************************************* * Increment a diffie hellman statistic * * @description * Increment the statistics * * @param[in] statistic The field in the statistics structure to be * incremented * @param[in] instanceHandle accel handle * * @retval None * *****************************************************************************/ #ifndef DISABLE_STATS #define LAC_DH_STAT_INC(statistic, instanceHandle) \ LacDh_StatsInc(offsetof(CpaCyDhStats64, statistic), instanceHandle) #else /* Stats disabled */ #define LAC_DH_STAT_INC(statistic, instanceHandle) #endif /** ******************************************************************************* * @ingroup LacDh * Init Statistics structures * * @description * This function allocates stats arrays and clears the DH statistics * for the given instance handle. * * @param[in] instanceHandle Instance Handle * * @retval CPA_STATUS_SUCCESS initialization successful * @retval CPA_STATUS_RESOURCE array allocation failed ******************************************************************************/ CpaStatus LacDh_StatsInit(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * This function increments the given DH stat * * @param[in] offset offset of stat field in structure * @param[in] instanceHandle the acceleration handle whose statistics we are * dealing with * @retval None ******************************************************************************/ #ifndef DISABLE_STATS void LacDh_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle); #endif /** ******************************************************************************* * @ingroup LacDh * This function prints the stats to standard out. * @retval None ******************************************************************************/ void LacDh_StatsShow(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacDh * Compile time check of FW interface * * @description * Performs a compile time check of PKE interface to ensure IA assumptions * about the interface are valid. * *****************************************************************************/ void LacDh_CompileTimeAssertions(void); #endif /* _LAC_DH_STATS_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/dsa/000077500000000000000000000000001503624047500272415ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/dsa/lac_dsa.c000066400000000000000000003521361503624047500310050ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_dsa.c * * @ingroup Lac_Dsa * * This file contains the implementation of DSA functions * ***************************************************************************/ /* **************************************************************************** * Include public/global header files **************************************************************************** */ /* Include API files */ #include "cpa.h" #include "cpa_cy_dsa.h" /* **************************************************************************** * Include private header files **************************************************************************** */ /* Osal includes */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "icp_adf_init.h" #include "lac_sal.h" #include "sal_service_state.h" #include "lac_sal_ctrl.h" #include "lac_pke_mmp.h" #include "lac_common.h" #include "lac_dsa.h" #include "lac_hooks.h" #include "lac_pke_qat_comms.h" #include "lac_pke_utils.h" #include "sal_statistics.h" /* **************************************************************************** * Global Variables **************************************************************************** */ /* **************************************************************************** * Static Variables **************************************************************************** */ #ifdef QAT_LEGACY_ALGORITHMS static const Cpa32U lacDsaGenPSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_DSA_1024_160_PAIR, PKE_DSA_GEN_P_1024_160}, {LAC_DSA_2048_224_PAIR, PKE_DSA_GEN_P_2048_224}, {LAC_DSA_2048_256_PAIR, PKE_DSA_GEN_P_2048_256}, {LAC_DSA_3072_256_PAIR, PKE_DSA_GEN_P_3072_256}}; /**< * Maps between operation sizes and PKE GEN_P function ids */ static const Cpa32U lacDsaGenGSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_DSA_L_1024, PKE_DSA_GEN_G_1024}, {LAC_DSA_L_2048, PKE_DSA_GEN_G_2048}, {LAC_DSA_L_3072, PKE_DSA_GEN_G_3072}}; /**< * Maps between operation sizes and PKE GEN_G function ids */ static const Cpa32U lacDsaGenYSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_DSA_L_1024, PKE_DSA_GEN_Y_1024}, {LAC_DSA_L_2048, PKE_DSA_GEN_Y_2048}, {LAC_DSA_L_3072, PKE_DSA_GEN_Y_3072}}; /**< * Maps between operation size and PKE GEN_Y function ids */ static const Cpa32U lacDsaSignRSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_DSA_1024_160_PAIR, PKE_DSA_SIGN_R_1024_160}, {LAC_DSA_2048_224_PAIR, PKE_DSA_SIGN_R_2048_224}, {LAC_DSA_2048_256_PAIR, PKE_DSA_SIGN_R_2048_256}, {LAC_DSA_3072_256_PAIR, PKE_DSA_SIGN_R_3072_256}}; /**< * Maps between operation sizes and PKE SIGN_R function ids */ static const Cpa32U lacDsaSignSSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_DSA_N_160, PKE_DSA_SIGN_S_160}, {LAC_DSA_N_224, PKE_DSA_SIGN_S_224}, {LAC_DSA_N_256, PKE_DSA_SIGN_S_256}}; /**< * Maps between operation size and PKE SIGN_S function ids */ static const Cpa32U lacDsaSignRsSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_DSA_1024_160_PAIR, PKE_DSA_SIGN_R_S_1024_160}, {LAC_DSA_2048_224_PAIR, PKE_DSA_SIGN_R_S_2048_224}, {LAC_DSA_2048_256_PAIR, PKE_DSA_SIGN_R_S_2048_256}, {LAC_DSA_3072_256_PAIR, PKE_DSA_SIGN_R_S_3072_256}}; /**< * Maps between operation sizes and PKE SIGN_R_S function ids */ static const Cpa32U lacDsaVerifySizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_DSA_1024_160_PAIR, PKE_DSA_VERIFY_1024_160}, {LAC_DSA_2048_224_PAIR, PKE_DSA_VERIFY_2048_224}, {LAC_DSA_2048_256_PAIR, PKE_DSA_VERIFY_2048_256}, {LAC_DSA_3072_256_PAIR, PKE_DSA_VERIFY_3072_256}}; /**< * Maps between operation sizes and PKE VERIFY function ids */ #endif /* QAT_LEGACY_ALGORITHMS */ /**< Number of DSA stats */ #define LAC_DSA_NUM_STATS (sizeof(CpaCyDsaStats64) / sizeof(Cpa64U)) /**< macro to initialize all DSA stats (stored in internal array of atomics) */ #define LAC_DSA_STATS_INIT(pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_DSA_NUM_STATS; i++) \ { \ osalAtomicSet(0, &(pCryptoService)->pLacDsaStatsArr[i]); \ } \ } while (0) /* macro to increment a DSA stat (derives offset into array of atomics) */ #ifndef DISABLE_STATS #define LAC_DSA_STAT_INC(statistic, pCryptoService) \ do \ { \ if (CPA_TRUE == \ pCryptoService->generic_service_info.stats->bDsaStatsEnabled) \ { \ osalAtomicInc( \ &(pCryptoService) \ ->pLacDsaStatsArr[offsetof(CpaCyDsaStats64, statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) #else #define LAC_DSA_STAT_INC(statistic, pCryptoService) #endif /**< macro to get all 32bit DSA stats (from internal array of atomics) */ #define LAC_DSA_STATS32_GET(dsaStats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_DSA_NUM_STATS; i++) \ { \ ((Cpa32U *)&(dsaStats))[i] = \ (Cpa32U)osalAtomicGet(&(pCryptoService)->pLacDsaStatsArr[i]); \ } \ } while (0) /**< macro to get all 64bit DSA stats (from internal array of atomics) */ #define LAC_DSA_STATS64_GET(dsaStats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_DSA_NUM_STATS; i++) \ { \ ((Cpa64U *)&(dsaStats))[i] = \ osalAtomicGet(&(pCryptoService)->pLacDsaStatsArr[i]); \ } \ } while (0) /* **************************************************************************** * Define static function definitions **************************************************************************** */ /* **************************************************************************** * Define public/global function definitions **************************************************************************** */ /** *************************************************************************** * @ingroup Lac_Dsa * Given DSA {L,N} Pair (L is the bit len of P and N is the * bit len of Q as defined in FIPS186-3) this function returns * a value from the lac_dsa_ln_pair_t enum ***************************************************************************/ #ifdef QAT_LEGACY_ALGORITHMS STATIC lac_dsa_ln_pairs_t LacDsa_GetLNPair(Cpa32U opSizeLBits, Cpa32U opSizeNBits) { if ((LAC_1024_BITS == opSizeLBits) && (LAC_160_BITS == opSizeNBits)) { return LAC_DSA_1024_160_PAIR; } else if ((LAC_2048_BITS == opSizeLBits) && (LAC_224_BITS == opSizeNBits)) { return LAC_DSA_2048_224_PAIR; } else if ((LAC_2048_BITS == opSizeLBits) && (LAC_256_BITS == opSizeNBits)) { return LAC_DSA_2048_256_PAIR; } else if ((LAC_3072_BITS == opSizeLBits) && (LAC_256_BITS == opSizeNBits)) { return LAC_DSA_3072_256_PAIR; } else { return LAC_DSA_INVALID_PAIR; } } /** *************************************************************************** * @ingroup Lac_Dsa * Given DSA the bit len of P this function returns * a value from the lac_dsa_l_values_t enum ***************************************************************************/ STATIC lac_dsa_l_values_t LacDsa_GetL(Cpa32U sizeLBits) { if (LAC_1024_BITS == sizeLBits) { return LAC_DSA_L_1024; } else if (LAC_2048_BITS == sizeLBits) { return LAC_DSA_L_2048; } else if (LAC_3072_BITS == sizeLBits) { return LAC_DSA_L_3072; } else { return LAC_DSA_L_INVALID; } } /** *************************************************************************** * @ingroup Lac_Dsa * Given DSA the bit len of Q this function returns * a value from the lac_dsa_n_values_t enum ***************************************************************************/ STATIC lac_dsa_n_values_t LacDsa_GetN(Cpa32U sizeNBits) { if (LAC_160_BITS == sizeNBits) { return LAC_DSA_N_160; } else if (LAC_224_BITS == sizeNBits) { return LAC_DSA_N_224; } else if (LAC_256_BITS == sizeNBits) { return LAC_DSA_N_256; } else { return LAC_DSA_N_INVALID; } } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * Given the bit len of P (i.e. L) this function checks if GenY * input param X is in appropriate range ***************************************************************************/ STATIC CpaStatus LacDsa_CheckSizeX(Cpa32U bitLenL, Cpa32U sizeXBits) { if (((LAC_1024_BITS == bitLenL) && (sizeXBits <= LAC_160_BITS)) || ((LAC_1024_BITS != bitLenL) && (sizeXBits <= LAC_256_BITS))) { return CPA_STATUS_SUCCESS; } return CPA_STATUS_INVALID_PARAM; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA P Parameter Generation internal callback ***************************************************************************/ STATIC void LacDsaPParamGenCallback(CpaStatus status, CpaBoolean protocolStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyDsaGenCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDsaPParamGenOpData *pOpData = NULL; CpaFlatBuffer *pP = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyDsaGenCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDsaPParamGenOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pP = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pP); #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaPParamGenCompleted, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaPParamGenCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, protocolStatus, pP); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * DSA P Parameter Generation parameter check ***************************************************************************/ STATIC CpaStatus LacDsaPParamGenParamCheck(CpaCyDsaGenCbFunc pCb, const CpaCyDsaPParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pP) { /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pProtocolStatus); LAC_CHECK_NULL_PARAM(pP); LAC_ENSURE_NOT_NULL(pCb); /* check parameters for null, zero len and LSB not set */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->X, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Q, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->Q); LAC_CHECK_FLAT_BUFFER_PARAM(pP, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA P Parameter Generation synchronous function ***************************************************************************/ STATIC CpaStatus LacDsaPParamGenSyn(const CpaInstanceHandle instanceHandle, const CpaCyDsaPParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pP) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDsaGenPParam(instanceHandle, LacSync_GenFlatBufVerifyCb, pSyncCallbackData, pOpData, pProtocolStatus, pP); } else { #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaPParamGenRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pProtocolStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { /* * Inc stats only if the wait for callback failed. */ #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaPParamGenCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #endif /* QAT_LEGACY_ALGORITHMS */ /** *************************************************************************** * @ingroup Lac_Dsa * DSA P Parameter Generation API function ***************************************************************************/ CpaStatus cpaCyDsaGenPParam(const CpaInstanceHandle instanceHandle_in, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaPParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pP) { #ifdef QAT_LEGACY_ALGORITHMS CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; CpaBoolean internalMemIn[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOut[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = NULL; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U bitLenX = 0, bitLenQ = 0; Cpa32U byteLenX = 0; lac_dsa_ln_pairs_t opIndex = LAC_DSA_INVALID_PAIR; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised*/ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacDsaPParamGenSyn(instanceHandle, pOpData, pProtocolStatus, pP); if (NULL != pProtocolStatus) { LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d], 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, *pProtocolStatus, (LAC_ARCH_UINT)pP); } else { LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, (LAC_ARCH_UINT)pP); } return status; #else return LacDsaPParamGenSyn(instanceHandle, pOpData, pProtocolStatus, pP); #endif } #ifdef ICP_PARAM_CHECK /* check remaining parameters */ status = LacDsaPParamGenParamCheck(pCb, pOpData, pProtocolStatus, pP); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->X), &bitLenX); } if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->Q), &bitLenQ); } if (CPA_STATUS_SUCCESS == status) { opIndex = LacDsa_GetLNPair(bitLenX, bitLenQ); byteLenX = LAC_BITS_TO_BYTES(bitLenX); #ifdef ICP_PARAM_CHECK if (LAC_DSA_INVALID_PAIR == opIndex) { LAC_INVALID_PARAM_LOG("X is not such that 2^(L-1) <= X < 2^L " "or Q is not such that 2^(N-1) <= Q < 2^N. " "Supported {L,N} = {1024, 160}, {2048, 224} " "{2048, 256}, {3072, 256}"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Ensure output buffer is the required size */ if (pP->dataLenInBytes < byteLenX) { LAC_INVALID_PARAM_LOG("Output Buffer has incorrect length"); status = CPA_STATUS_INVALID_PARAM; } #endif } if (CPA_STATUS_SUCCESS == status) { /* If output buffer is larger than L we need to zero MS bytes */ osalMemSet(pP->pData, 0, (pP->dataLenInBytes - byteLenX)); functionalityId = LacPke_GetMmpId( opIndex, lacDsaGenPSizeIdMap, LAC_ARRAY_LEN(lacDsaGenPSizeIdMap)); /* Note: Using mmp_dsa_gen_p_1024_160 for all functionalityIds - checked at compile time (see lac_dsa_interface_check.c) that this is a valid assumption */ /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_p_1024_160.x, &pOpData->X); /* bitLenX is either 1024, 2048 or 3072 - all multiples of 64 bits so no need to round up the size to nearest QW */ inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_input_t, x)] = byteLenX; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_input_t, x)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_p_1024_160.q, &pOpData->Q); /* bitLenQ is either 160, 224 or 256 - not all multiples of 64 bits so we need to round out to nearest QW */ inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_input_t, q)] = LAC_ALIGN_POW2_ROUNDUP(LAC_BITS_TO_BYTES(bitLenQ), LAC_QUAD_WORD_IN_BYTES); internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_input_t, q)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_dsa_gen_p_1024_160.p, pP); outArgSizeList[0] = byteLenX; internalMemOut[0] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pP; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &in, &out, internalMemIn, internalMemOut, LacDsaPParamGenCallback, &cbData, instanceHandle); } #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaPParamGenRequests, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaPParamGenRequestErrors, pCryptoService); } #endif return status; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } #ifdef QAT_LEGACY_ALGORITHMS /** *************************************************************************** * @ingroup Lac_Dsa * DSA G Parameter Generation internal callback ***************************************************************************/ STATIC void LacDsaGParamGenCallback(CpaStatus status, CpaBoolean protocolStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyDsaGenCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDsaGParamGenOpData *pOpData = NULL; CpaFlatBuffer *pG = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyDsaGenCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDsaGParamGenOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pG = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pG); #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaGParamGenCompleted, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaGParamGenCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, protocolStatus, pG); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * DSA G Parameter Generation parameter check ***************************************************************************/ STATIC CpaStatus LacDsaGParamGenParamCheck(const CpaCyDsaGenCbFunc pCb, const CpaCyDsaGParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pG) { /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for valid output pointers */ LAC_CHECK_NULL_PARAM(pProtocolStatus); LAC_CHECK_NULL_PARAM(pG); /* check parameters for null, zero len and LSB not set */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->P, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->P); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Q, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->Q); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->H, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(pG, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA G Parameter Generation synchronous function ***************************************************************************/ STATIC CpaStatus LacDsaGParamGenSyn(const CpaInstanceHandle instanceHandle, const CpaCyDsaGParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pG) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDsaGenGParam(instanceHandle, LacSync_GenFlatBufVerifyCb, pSyncCallbackData, pOpData, pProtocolStatus, pG); } else { #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaGParamGenRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pProtocolStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_DSA_STAT_INC(numDsaGParamGenCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #endif /* QAT_LEGACY_ALGORITHMS */ /** *************************************************************************** * @ingroup Lac_Dsa * DSA G Parameter Generation API function ***************************************************************************/ CpaStatus cpaCyDsaGenGParam(const CpaInstanceHandle instanceHandle_in, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaGParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pG) { #ifdef QAT_LEGACY_ALGORITHMS CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemIn[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOut[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U bitLenL = 0, nonceN = 0; Cpa32U opSizeLInBytes = 0; lac_dsa_l_values_t opIndex = LAC_DSA_L_INVALID; #ifdef ICP_PARAM_CHECK lac_dsa_ln_pairs_t lnPair = LAC_DSA_INVALID_PAIR; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised*/ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacDsaGParamGenSyn(instanceHandle, pOpData, pProtocolStatus, pG); if (NULL != pProtocolStatus) { LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d], 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, *pProtocolStatus, (LAC_ARCH_UINT)pG); } else { LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, (LAC_ARCH_UINT)pG); } return status; #else return LacDsaGParamGenSyn(instanceHandle, pOpData, pProtocolStatus, pG); #endif } #ifdef ICP_PARAM_CHECK /* check remaining parameters */ status = LacDsaGParamGenParamCheck(pCb, pOpData, pProtocolStatus, pG); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->P), &bitLenL); } if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->Q), &nonceN); } if (CPA_STATUS_SUCCESS == status) { opIndex = LacDsa_GetL(bitLenL); opSizeLInBytes = LAC_BITS_TO_BYTES(bitLenL); #ifdef ICP_PARAM_CHECK lnPair = LacDsa_GetLNPair(bitLenL, nonceN); if (LAC_DSA_INVALID_PAIR == lnPair) { LAC_INVALID_PARAM_LOG("P, Q out of range " "Supported {L,N} = {1024, 160}, {2048, 224} " "{2048, 256}, {3072, 256}"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 1 < h < p-1 */ if ((LacPke_CompareZero(&(pOpData->H), -1) <= 0) || (LacPke_Compare(&(pOpData->H), 0, &(pOpData->P), -1) >= 0)) { LAC_INVALID_PARAM_LOG("H out of Range"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure output buffer is the required size */ if (pG->dataLenInBytes < opSizeLInBytes) { LAC_INVALID_PARAM_LOG("Output Buffer has incorrect length"); status = CPA_STATUS_INVALID_PARAM; } #endif } if (CPA_STATUS_SUCCESS == status) { /* If output buffer is larger than L we need to zero MS bytes */ osalMemSet(pG->pData, 0, (pG->dataLenInBytes - opSizeLInBytes)); functionalityId = LacPke_GetMmpId( opIndex, lacDsaGenGSizeIdMap, LAC_ARRAY_LEN(lacDsaGenGSizeIdMap)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_g_1024.p, &pOpData->P); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_input_t, p)] = opSizeLInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_g_1024.q, &pOpData->Q); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_input_t, q)] = LAC_ALIGN_POW2_ROUNDUP(LAC_BITS_TO_BYTES(nonceN), LAC_QUAD_WORD_IN_BYTES); internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_g_1024.h, &pOpData->H); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_input_t, h)] = opSizeLInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_input_t, h)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_dsa_gen_g_1024.g, pG); outArgSizeList[0] = opSizeLInBytes; internalMemOut[0] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pG; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &in, &out, internalMemIn, internalMemOut, LacDsaGParamGenCallback, &cbData, instanceHandle); } #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaGParamGenRequests, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaGParamGenRequestErrors, pCryptoService); } #endif return status; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } #ifdef QAT_LEGACY_ALGORITHMS /** *************************************************************************** * @ingroup Lac_Dsa * DSA Y Parameter Generation internal callback ***************************************************************************/ STATIC void LacDsaYParamGenCallback(CpaStatus status, CpaBoolean protocolStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyDsaGenCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDsaYParamGenOpData *pOpData = NULL; CpaFlatBuffer *pY = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyDsaGenCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDsaYParamGenOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pY = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pY); #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaYParamGenCompleted, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaYParamGenCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, protocolStatus, pY); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * DSA Y Parameter Generation parameter check ***************************************************************************/ STATIC CpaStatus LacDsaYParamGenParamCheck(const CpaCyDsaGenCbFunc pCb, const CpaCyDsaYParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pY) { /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for valid output pointers */ LAC_CHECK_NULL_PARAM(pProtocolStatus); LAC_CHECK_NULL_PARAM(pY); /* check parameters for null, zero size, or LSB not set */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->P, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->P); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->G, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->X, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(pY, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA Y Parameter Generation synchronous function ***************************************************************************/ STATIC CpaStatus LacDsaYParamGenSyn(const CpaInstanceHandle instanceHandle, const CpaCyDsaYParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pY) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDsaGenYParam(instanceHandle, LacSync_GenFlatBufVerifyCb, pSyncCallbackData, pOpData, pProtocolStatus, pY); } else { #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaYParamGenRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pProtocolStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_DSA_STAT_INC(numDsaYParamGenCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #endif /* QAT_LEGACY_ALGORITHMS */ /** *************************************************************************** * @ingroup Lac_Dsa * DSA Y Parameter Generation API function ***************************************************************************/ CpaStatus cpaCyDsaGenYParam(const CpaInstanceHandle instanceHandle_in, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaYParamGenOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pY) { #ifdef QAT_LEGACY_ALGORITHMS CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemIn[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOut[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U bitLenL = 0, opSizeLInBytes = 0; Cpa32U bitLenX = 0; lac_dsa_l_values_t opIndex = LAC_DSA_L_INVALID; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised*/ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacDsaYParamGenSyn(instanceHandle, pOpData, pProtocolStatus, pY); if (NULL != pProtocolStatus) { LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d], 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, *pProtocolStatus, (LAC_ARCH_UINT)pY); } else { LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, (LAC_ARCH_UINT)pY); } return status; #else return LacDsaYParamGenSyn(instanceHandle, pOpData, pProtocolStatus, pY); #endif } #ifdef ICP_PARAM_CHECK /* check remaining parameters */ status = LacDsaYParamGenParamCheck(pCb, pOpData, pProtocolStatus, pY); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->P), &bitLenL); } if (CPA_STATUS_SUCCESS == status) { opIndex = LacDsa_GetL(bitLenL); opSizeLInBytes = LAC_BITS_TO_BYTES(bitLenL); #ifdef ICP_PARAM_CHECK if (LAC_DSA_L_INVALID == opIndex) { LAC_INVALID_PARAM_LOG("P does not support size L " "Supported {L,N} = {1024, 160}, {2048, 224} " "{2048, 256}, {3072, 256}"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 1 < g < p */ if ((LacPke_CompareZero(&(pOpData->G), -1) <= 0) || (LacPke_Compare(&(pOpData->G), 0, &(pOpData->P), 0) >= 0)) { LAC_INVALID_PARAM_LOG("G out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check the bit length of X */ bitLenX = LAC_BYTES_TO_BITS(LacPke_GetMinBytes(&(pOpData->X))); if (CPA_STATUS_SUCCESS != LacDsa_CheckSizeX(bitLenL, bitLenX)) { LAC_INVALID_PARAM_LOG("X out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Ensure output buffer is the required size */ if (pY->dataLenInBytes < opSizeLInBytes) { LAC_INVALID_PARAM_LOG("Output Buffer has incorrect length"); status = CPA_STATUS_INVALID_PARAM; } #endif } if (CPA_STATUS_SUCCESS == status) { /* If output buffer is larger than L we need to zero MS bytes */ osalMemSet(pY->pData, 0, (pY->dataLenInBytes - opSizeLInBytes)); functionalityId = LacPke_GetMmpId( opIndex, lacDsaGenYSizeIdMap, LAC_ARRAY_LEN(lacDsaGenYSizeIdMap)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_y_1024.p, &pOpData->P); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_input_t, p)] = opSizeLInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_y_1024.g, &pOpData->G); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_input_t, g)] = opSizeLInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_input_t, g)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_gen_y_1024.x, &pOpData->X); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_input_t, x)] = LAC_ALIGN_POW2_ROUNDUP(LAC_BITS_TO_BYTES(bitLenX), LAC_QUAD_WORD_IN_BYTES); internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_input_t, x)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_dsa_gen_y_1024.y, pY); outArgSizeList[0] = opSizeLInBytes; internalMemOut[0] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pY; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &in, &out, internalMemIn, internalMemOut, LacDsaYParamGenCallback, &cbData, instanceHandle); } #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaYParamGenRequests, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaYParamGenRequestErrors, pCryptoService); } #endif return status; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } #ifdef QAT_LEGACY_ALGORITHMS /** *************************************************************************** * @ingroup Lac_Dsa * DSA R Sign internal callback ***************************************************************************/ STATIC void LacDsaRSignCallback(CpaStatus status, CpaBoolean protocolStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyDsaGenCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDsaRSignOpData *pOpData = NULL; CpaFlatBuffer *pR = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyDsaGenCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDsaRSignOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pR = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pR); #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaRSignCompleted, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaRSignCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, protocolStatus, pR); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * DSA R Sign parameter check ***************************************************************************/ STATIC CpaStatus LacDsaRSignParamCheck(const CpaCyDsaGenCbFunc pCb, const CpaCyDsaRSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR) { /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for output pointers */ LAC_CHECK_NULL_PARAM(pProtocolStatus); LAC_CHECK_NULL_PARAM(pR); /* check parameters for null, zero len and LSB not set */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->K, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->P, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->P); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Q, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->Q); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->G, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(pR, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA R Sign synchronous function ***************************************************************************/ STATIC CpaStatus LacDsaRSignSyn(const CpaInstanceHandle instanceHandle, const CpaCyDsaRSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDsaSignR(instanceHandle, LacSync_GenFlatBufVerifyCb, pSyncCallbackData, pOpData, pProtocolStatus, pR); } else { #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaRSignRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pProtocolStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_DSA_STAT_INC(numDsaRSignCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #endif /* QAT_LEGACY_ALGORITHMS */ /** *************************************************************************** * @ingroup Lac_Dsa * DSA R Sign API function ***************************************************************************/ CpaStatus cpaCyDsaSignR(const CpaInstanceHandle instanceHandle_in, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaRSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR) { #ifdef QAT_LEGACY_ALGORITHMS CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemIn[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOut[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U bitLenL = 0, nonceN = 0; Cpa32U opSizeNInBytes = 0; lac_dsa_ln_pairs_t opIndex = LAC_DSA_INVALID_PAIR; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised*/ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacDsaRSignSyn(instanceHandle, pOpData, pProtocolStatus, pR); if (NULL != pProtocolStatus) { LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d], 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, *pProtocolStatus, (LAC_ARCH_UINT)pR); } else { LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, (LAC_ARCH_UINT)pR); } return status; #else return LacDsaRSignSyn(instanceHandle, pOpData, pProtocolStatus, pR); #endif } #ifdef ICP_PARAM_CHECK /* check remaining parameters */ status = LacDsaRSignParamCheck(pCb, pOpData, pProtocolStatus, pR); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->P), &bitLenL); } if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->Q), &nonceN); } if (CPA_STATUS_SUCCESS == status) { opIndex = LacDsa_GetLNPair(bitLenL, nonceN); /* N values of 160 or 224 do not result in an even number of QW so we need to round up */ opSizeNInBytes = LAC_ALIGN_POW2_ROUNDUP(LAC_BITS_TO_BYTES(nonceN), LAC_QUAD_WORD_IN_BYTES); #ifdef ICP_PARAM_CHECK if (LAC_DSA_INVALID_PAIR == opIndex) { LAC_INVALID_PARAM_LOG("P, Q out of range " "Supported {L,N} = {1024, 160}, {2048, 224} " "{2048, 256}, {3072, 256}"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < k < q */ if ((LacPke_CompareZero(&(pOpData->K), 0) == 0) || (LacPke_Compare(&(pOpData->K), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("K out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 1 < g < p */ if ((LacPke_CompareZero(&(pOpData->G), -1) <= 0) || (LacPke_Compare(&(pOpData->G), 0, &(pOpData->P), 0) >= 0)) { LAC_INVALID_PARAM_LOG("G out of Range"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure output buffer is the required size (note does not need to be rounded up to nearest QW) */ if (pR->dataLenInBytes < LAC_BITS_TO_BYTES(nonceN)) { LAC_INVALID_PARAM_LOG("Output Buffer has incorrect length"); status = CPA_STATUS_INVALID_PARAM; } #endif } if (CPA_STATUS_SUCCESS == status) { /* If output buffer is larger than N we need to zero MS bytes */ osalMemSet( pR->pData, 0, (pR->dataLenInBytes - LAC_BITS_TO_BYTES(nonceN))); functionalityId = LacPke_GetMmpId( opIndex, lacDsaSignRSizeIdMap, LAC_ARRAY_LEN(lacDsaSignRSizeIdMap)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_1024_160.k, &pOpData->K); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, k)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, k)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_1024_160.p, &pOpData->P); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, p)] = LAC_BITS_TO_BYTES(bitLenL); internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_1024_160.q, &pOpData->Q); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, q)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_1024_160.g, &pOpData->G); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, p)] = LAC_BITS_TO_BYTES(bitLenL); internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_input_t, g)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_dsa_sign_r_1024_160.r, pR); outArgSizeList[0] = opSizeNInBytes; internalMemOut[0] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pR; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &in, &out, internalMemIn, internalMemOut, LacDsaRSignCallback, &cbData, instanceHandle); } #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaRSignRequests, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaRSignRequestErrors, pCryptoService); } #endif return status; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } #ifdef QAT_LEGACY_ALGORITHMS /** *************************************************************************** * @ingroup Lac_Dsa * DSA S Sign internal callback ***************************************************************************/ STATIC void LacDsaSSignCallback(CpaStatus status, CpaBoolean protocolStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyDsaGenCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDsaSSignOpData *pOpData = NULL; CpaFlatBuffer *pS = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyDsaGenCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDsaSSignOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pS = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pS); #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaSSignCompleted, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaSSignCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, protocolStatus, pS); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * DSA S Sign parameter check ***************************************************************************/ STATIC CpaStatus LacDsaSSignParamCheck(const CpaCyDsaGenCbFunc pCb, const CpaCyDsaSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pS) { /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for valid out buffer and data pointers */ LAC_CHECK_NULL_PARAM(pS); LAC_CHECK_NULL_PARAM(pProtocolStatus); /* check parameters for null, 0 size, and LSB not set */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Z, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->K, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Q, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->Q); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->R, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->X, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(pS, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA S Sign synchronous function ***************************************************************************/ STATIC CpaStatus LacDsaSignSSyn(const CpaInstanceHandle instanceHandle, const CpaCyDsaSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDsaSignS(instanceHandle, LacSync_GenFlatBufVerifyCb, pSyncCallbackData, pOpData, pProtocolStatus, pS); } else { #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaSSignRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pProtocolStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_DSA_STAT_INC(numDsaSSignCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #endif /* QAT_LEGACY_ALGORITHMS */ /** *************************************************************************** * @ingroup Lac_Dsa * DSA S Sign API function ***************************************************************************/ CpaStatus cpaCyDsaSignS(const CpaInstanceHandle instanceHandle_in, const CpaCyDsaGenCbFunc pCb, void *pCallbackTag, const CpaCyDsaSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pS) { #ifdef QAT_LEGACY_ALGORITHMS CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemIn[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOut[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U nonceN = 0, opSizeInByte = 0; #ifdef ICP_PARAM_CHECK Cpa32U byteLen = 0; #endif lac_dsa_n_values_t opIndex = LAC_DSA_N_INVALID; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised*/ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacDsaSignSSyn(instanceHandle, pOpData, pProtocolStatus, pS); if (NULL != pProtocolStatus) { LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d], 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, *pProtocolStatus, (LAC_ARCH_UINT)pS); } else { LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pProtocolStatus, (LAC_ARCH_UINT)pS); } return status; #endif return LacDsaSignSSyn(instanceHandle, pOpData, pProtocolStatus, pS); } #ifdef ICP_PARAM_CHECK /* check remaining parameters */ status = LacDsaSSignParamCheck(pCb, pOpData, pProtocolStatus, pS); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->Q), &nonceN); } if (CPA_STATUS_SUCCESS == status) { opIndex = LacDsa_GetN(nonceN); opSizeInByte = LAC_ALIGN_POW2_ROUNDUP(LAC_BITS_TO_BYTES(nonceN), LAC_QUAD_WORD_IN_BYTES); #ifdef ICP_PARAM_CHECK if (LAC_DSA_N_INVALID == opIndex) { LAC_INVALID_PARAM_LOG("Q not support size N " "Supported {L,N} = {1024, 160}, {2048, 224} " "{2048, 256}, {3072, 256}"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check byte len of z */ byteLen = LacPke_GetMinBytes(&(pOpData->Z)); if (byteLen > LAC_BITS_TO_BYTES(nonceN)) { LAC_INVALID_PARAM_LOG("Z out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < k < q */ if ((LacPke_CompareZero(&(pOpData->K), 0) == 0) || (LacPke_Compare(&(pOpData->K), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("K out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < r < q */ if ((LacPke_CompareZero(&(pOpData->R), 0) == 0) || (LacPke_Compare(&(pOpData->R), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("R out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < x < q */ if ((LacPke_CompareZero(&(pOpData->X), 0) == 0) || (LacPke_Compare(&(pOpData->X), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("X out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Ensure output buffer is the required size */ if (pS->dataLenInBytes < LAC_BITS_TO_BYTES(nonceN)) { LAC_INVALID_PARAM_LOG("Output Buffer has incorrect length"); status = CPA_STATUS_INVALID_PARAM; } #endif } if (CPA_STATUS_SUCCESS == status) { /* If output buffer is larger than N we need to zero MS bytes */ osalMemSet( pS->pData, 0, (pS->dataLenInBytes - LAC_BITS_TO_BYTES(nonceN))); functionalityId = LacPke_GetMmpId( opIndex, lacDsaSignSSizeIdMap, LAC_ARRAY_LEN(lacDsaSignSSizeIdMap)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_s_160.m, &pOpData->Z); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, m)] = opSizeInByte; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, m)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_s_160.k, &pOpData->K); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, k)] = opSizeInByte; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, k)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_s_160.q, &pOpData->Q); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, q)] = opSizeInByte; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_s_160.r, &pOpData->R); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, r)] = opSizeInByte; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, r)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_s_160.x, &pOpData->X); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, x)] = opSizeInByte; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_input_t, x)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_dsa_sign_s_160.s, pS); outArgSizeList[0] = opSizeInByte; internalMemOut[0] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pS; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &in, &out, internalMemIn, internalMemOut, LacDsaSSignCallback, &cbData, instanceHandle); } #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaSSignRequests, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaSSignRequestErrors, pCryptoService); } #endif return status; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } #ifdef QAT_LEGACY_ALGORITHMS /** *************************************************************************** * @ingroup Lac_Dsa * DSA RS Sign internal callback ***************************************************************************/ STATIC void LacDsaRSSignCallback(CpaStatus status, CpaBoolean protocolStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyDsaRSSignCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDsaRSSignOpData *pOpData = NULL; CpaFlatBuffer *pR = NULL; CpaFlatBuffer *pS = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyDsaRSSignCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDsaRSSignOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pR = pCbData->pOutputData1; pS = pCbData->pOutputData2; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pR); LAC_ASSERT_NOT_NULL(pS); #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaRSSignCompleted, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaRSSignCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, protocolStatus, pR, pS); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * DSA RS Sign parameter check ***************************************************************************/ STATIC CpaStatus LacDsaRSSignParamCheck(const CpaCyDsaRSSignCbFunc pCb, const CpaCyDsaRSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for valid out buffer pointers */ LAC_CHECK_NULL_PARAM(pProtocolStatus); LAC_CHECK_NULL_PARAM(pR); LAC_CHECK_NULL_PARAM(pS); /* check parameters for null, zero size and LSB not set */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Z, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->K, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->P, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->P); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Q, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->Q); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->G, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->X, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(pR, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(pS, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA RS Sign synchronous function ***************************************************************************/ STATIC CpaStatus LacDsaRSSignSyn(const CpaInstanceHandle instanceHandle, const CpaCyDsaRSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDsaSignRS(instanceHandle, LacSync_GenDualFlatBufVerifyCb, pSyncCallbackData, pOpData, pProtocolStatus, pR, pS); } else { #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaRSSignRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pProtocolStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_DSA_STAT_INC(numDsaRSSignCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #endif /* QAT_LEGACY_ALGORITHMS */ /** *************************************************************************** * @ingroup Lac_Dsa * DSA RS Sign API function ***************************************************************************/ CpaStatus cpaCyDsaSignRS(const CpaInstanceHandle instanceHandle_in, const CpaCyDsaRSSignCbFunc pCb, void *pCallbackTag, const CpaCyDsaRSSignOpData *pOpData, CpaBoolean *pProtocolStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { #ifdef QAT_LEGACY_ALGORITHMS CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemIn[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOut[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U bitLenL = 0, nonceN = 0; Cpa32U opSizeNInBytes = 0; #ifdef ICP_PARAM_CHECK Cpa32U byteLen = 0; #endif lac_dsa_ln_pairs_t opIndex = LAC_DSA_INVALID_PAIR; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised*/ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacDsaRSSignSyn(instanceHandle, pOpData, pProtocolStatus, pR, pS); if (NULL != pProtocolStatus) { LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx[%d]" ", 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, *pProtocolStatus, (LAC_ARCH_UINT)pR, (LAC_ARCH_UINT)pS); } else { LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx" ", 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pR, (LAC_ARCH_UINT)pS); } return status; #else return LacDsaRSSignSyn( instanceHandle, pOpData, pProtocolStatus, pR, pS); #endif } #ifdef ICP_PARAM_CHECK /* check remaining parameters */ status = LacDsaRSSignParamCheck(pCb, pOpData, pProtocolStatus, pR, pS); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->P), &bitLenL); } if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->Q), &nonceN); } if (CPA_STATUS_SUCCESS == status) { opIndex = LacDsa_GetLNPair(bitLenL, nonceN); opSizeNInBytes = LAC_ALIGN_POW2_ROUNDUP(LAC_BITS_TO_BYTES(nonceN), LAC_QUAD_WORD_IN_BYTES); #ifdef ICP_PARAM_CHECK if (LAC_DSA_INVALID_PAIR == opIndex) { LAC_INVALID_PARAM_LOG("P, Q out of range " "Supported {L,N} = {1024, 160}, {2048, 224} " "{2048, 256}, {3072, 256}"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check byte len of z */ byteLen = LacPke_GetMinBytes(&(pOpData->Z)); if (byteLen > LAC_BITS_TO_BYTES(nonceN)) { LAC_INVALID_PARAM_LOG("Z out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < k < q */ if ((LacPke_CompareZero(&(pOpData->K), 0) == 0) || (LacPke_Compare(&(pOpData->K), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("K out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 1 < g < p */ if ((LacPke_CompareZero(&(pOpData->G), -1) <= 0) || (LacPke_Compare(&(pOpData->G), 0, &(pOpData->P), 0) >= 0)) { LAC_INVALID_PARAM_LOG("G out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < x < q */ if ((LacPke_CompareZero(&(pOpData->X), 0) == 0) || (LacPke_Compare(&(pOpData->X), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("X out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Ensure output buffers are the required size */ if (pR->dataLenInBytes < LAC_BITS_TO_BYTES(nonceN)) { LAC_INVALID_PARAM_LOG("Output Buffer R has incorrect length"); status = CPA_STATUS_INVALID_PARAM; } if (pS->dataLenInBytes < LAC_BITS_TO_BYTES(nonceN)) { LAC_INVALID_PARAM_LOG("Output Buffer S has incorrect length"); status = CPA_STATUS_INVALID_PARAM; } #endif } if (CPA_STATUS_SUCCESS == status) { /* If output buffers are larger than N we need to zero MS bytes */ osalMemSet( pR->pData, 0, (pR->dataLenInBytes - LAC_BITS_TO_BYTES(nonceN))); osalMemSet( pS->pData, 0, (pS->dataLenInBytes - LAC_BITS_TO_BYTES(nonceN))); functionalityId = LacPke_GetMmpId(opIndex, lacDsaSignRsSizeIdMap, LAC_ARRAY_LEN(lacDsaSignRsSizeIdMap)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_s_1024_160.m, &pOpData->Z); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, m)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, m)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_s_1024_160.k, &pOpData->K); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, k)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, k)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_s_1024_160.p, &pOpData->P); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, p)] = LAC_BITS_TO_BYTES(bitLenL); internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_s_1024_160.q, &pOpData->Q); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, q)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_s_1024_160.g, &pOpData->G); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, g)] = LAC_BITS_TO_BYTES(bitLenL); internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, g)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_sign_r_s_1024_160.x, &pOpData->X); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, x)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_input_t, x)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_dsa_sign_r_s_1024_160.r, pR); outArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_output_t, r)] = opSizeNInBytes; internalMemOut[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_output_t, r)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_dsa_sign_r_s_1024_160.s, pS); outArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_output_t, s)] = opSizeNInBytes; internalMemOut[LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_output_t, s)] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pR; cbData.pOutputData2 = pS; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &in, &out, internalMemIn, internalMemOut, LacDsaRSSignCallback, &cbData, instanceHandle); } #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaRSSignRequests, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaRSSignRequestErrors, pCryptoService); } #endif return status; #else return CPA_STATUS_UNSUPPORTED; #endif } #ifdef QAT_LEGACY_ALGORITHMS /** *************************************************************************** * @ingroup Lac_Dsa * DSA Verify internal callback ***************************************************************************/ STATIC void LacDsaVerifyCallback(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyDsaVerifyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyDsaVerifyOpData *pOpData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyDsaVerifyCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyDsaVerifyOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaVerifyCompleted, pCryptoService); if (CPA_FALSE == pass) { LAC_DSA_STAT_INC(numDsaVerifyFailures, pCryptoService); } } else { LAC_DSA_STAT_INC(numDsaVerifyCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pass); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Dsa * DSA Verify parameter check ***************************************************************************/ STATIC CpaStatus LacDsaVerifyParamCheck(const CpaCyDsaVerifyCbFunc pCb, const CpaCyDsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for valid output pointer */ LAC_CHECK_NULL_PARAM(pVerifyStatus); /* check parameters for null, zero len and LSB not set */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->R, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->S, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Z, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->P, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->P); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Q, CHECK_NONE, 0); LAC_CHECK_ODD_PARAM(&pOpData->Q); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->G, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->Y, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Dsa * DSA Verify synchronous function ***************************************************************************/ STATIC CpaStatus LacDsaVerifySyn(const CpaInstanceHandle instanceHandle, const CpaCyDsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyDsaVerify(instanceHandle, LacSync_GenVerifyCb, pSyncCallbackData, pOpData, pVerifyStatus); } else { #ifndef DISABLE_STATS LAC_DSA_STAT_INC(numDsaVerifyRequests, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pVerifyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_DSA_STAT_INC(numDsaVerifyCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #endif /* QAT_LEGACY_ALGORITHMS */ /** *************************************************************************** * @ingroup Lac_Dsa * DSA Verify API function ***************************************************************************/ CpaStatus cpaCyDsaVerify(const CpaInstanceHandle instanceHandle_in, const CpaCyDsaVerifyCbFunc pCb, void *pCallbackTag, const CpaCyDsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { #ifdef QAT_LEGACY_ALGORITHMS CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; CpaBoolean internalMemIn[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U bitLenL = 0, nonceN = 0; Cpa32U opSizeLInBytes = 0, opSizeNInBytes = 0; #ifdef ICP_PARAM_CHECK Cpa32U byteLen = 0; #endif lac_dsa_ln_pairs_t opIndex = LAC_DSA_INVALID_PAIR; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised*/ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacDsaVerifySyn(instanceHandle, pOpData, pVerifyStatus); if (NULL != pVerifyStatus) { LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pVerifyStatus, *pVerifyStatus); } else { LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pVerifyStatus); } return status; #else return LacDsaVerifySyn(instanceHandle, pOpData, pVerifyStatus); #endif } #ifdef ICP_PARAM_CHECK /* check remaining parameters */ status = LacDsaVerifyParamCheck(pCb, pOpData, pVerifyStatus); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->P), &bitLenL); } if (CPA_STATUS_SUCCESS == status) { status = LacPke_GetBitLen(&(pOpData->Q), &nonceN); } if (CPA_STATUS_SUCCESS == status) { opIndex = LacDsa_GetLNPair(bitLenL, nonceN); opSizeLInBytes = LAC_BITS_TO_BYTES(bitLenL); opSizeNInBytes = LAC_ALIGN_POW2_ROUNDUP(LAC_BITS_TO_BYTES(nonceN), LAC_QUAD_WORD_IN_BYTES); #ifdef ICP_PARAM_CHECK if (LAC_DSA_INVALID_PAIR == opIndex) { LAC_INVALID_PARAM_LOG("P, Q out of range " "Supported {L,N} = {1024, 160}, {2048, 224} " "{2048, 256}, {3072, 256}"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 1 < g < p */ if ((LacPke_CompareZero(&(pOpData->G), -1) <= 0) || (LacPke_Compare(&(pOpData->G), 0, &(pOpData->P), 0) >= 0)) { LAC_INVALID_PARAM_LOG("G out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check y < p */ if (LacPke_Compare(&(pOpData->Y), 0, &(pOpData->P), 0) >= 0) { LAC_INVALID_PARAM_LOG("Y out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check byte len of z */ byteLen = LacPke_GetMinBytes(&(pOpData->Z)); if (byteLen > LAC_BITS_TO_BYTES(nonceN)) { LAC_INVALID_PARAM_LOG("Z out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < r < q */ if ((LacPke_CompareZero(&(pOpData->R), 0) == 0) || (LacPke_Compare(&(pOpData->R), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("R out of Range"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < s < q */ if ((LacPke_CompareZero(&(pOpData->S), 0) == 0) || (LacPke_Compare(&(pOpData->S), 0, &(pOpData->Q), 0) >= 0)) { LAC_INVALID_PARAM_LOG("S out of Range"); status = CPA_STATUS_INVALID_PARAM; } #endif } if (CPA_STATUS_SUCCESS == status) { functionalityId = LacPke_GetMmpId(opIndex, lacDsaVerifySizeIdMap, LAC_ARRAY_LEN(lacDsaVerifySizeIdMap)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_verify_1024_160.r, &pOpData->R); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, r)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, r)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_verify_1024_160.s, &pOpData->S); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, s)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, s)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_verify_1024_160.m, &pOpData->Z); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, m)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, m)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_verify_1024_160.p, &pOpData->P); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, p)] = opSizeLInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_verify_1024_160.q, &pOpData->Q); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, q)] = opSizeNInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_verify_1024_160.g, &pOpData->G); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, g)] = opSizeLInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, g)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_dsa_verify_1024_160.y, &pOpData->Y); inArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, y)] = opSizeLInBytes; internalMemIn[LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_input_t, y)] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, NULL, &in, &out, internalMemIn, NULL, LacDsaVerifyCallback, &cbData, instanceHandle); } #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_DSA_STAT_INC(numDsaVerifyRequests, pCryptoService); } else { LAC_DSA_STAT_INC(numDsaVerifyRequestErrors, pCryptoService); } #endif return status; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } /** *************************************************************************** * @ingroup Lac_Dsa * DSA Statistics Query API function ***************************************************************************/ CpaStatus cpaCyDsaQueryStats(CpaInstanceHandle instanceHandle, CpaCyDsaStats *pDsaStats) { #ifdef QAT_LEGACY_ALGORITHMS sal_crypto_service_t *pCryptoService = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pDsaStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pDsaStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; /* get stats into user supplied stats structure */ LAC_DSA_STATS32_GET(*pDsaStats, pCryptoService); return CPA_STATUS_SUCCESS; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } /** *************************************************************************** * @ingroup Lac_Dsa * DSA 64bit Statistics Query API function ***************************************************************************/ CpaStatus cpaCyDsaQueryStats64(CpaInstanceHandle instanceHandle, CpaCyDsaStats64 *pDsaStats) { #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pDsaStats); #endif #ifdef QAT_LEGACY_ALGORITHMS sal_crypto_service_t *pCryptoService = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* check this is a crypto or asym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); /* Check if dsa capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, dsa); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pDsaStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; /* get stats into user supplied stats structure */ LAC_DSA_STATS64_GET(*pDsaStats, pCryptoService); return CPA_STATUS_SUCCESS; #else /* !QAT_LEGACY_ALGORITHMS */ return CPA_STATUS_UNSUPPORTED; #endif } /** *************************************************************************** * @ingroup Lac_Dsa * DSA Initialization function ***************************************************************************/ CpaStatus LacDsa_Init(CpaInstanceHandle instanceHandle) { #ifndef QAT_LEGACY_ALGORITHMS return CPA_STATUS_UNSUPPORTED; #else sal_crypto_service_t *pCryptoService = NULL; CpaStatus status = CPA_STATUS_SUCCESS; pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pCryptoService->pLacDsaStatsArr), LAC_DSA_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { /* initialize stats to zero */ LAC_DSA_STATS_INIT(pCryptoService); } /* Call compile time param check function to ensure it is included in the build by the compiler */ LacDsa_CompileTimeAssertions(); return status; #endif } /** * @ingroup Lac_Dsa */ void LacDsa_StatsFree(CpaInstanceHandle instanceHandle) { #ifdef QAT_LEGACY_ALGORITHMS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; if (NULL != pCryptoService->pLacDsaStatsArr) { LAC_OS_FREE(pCryptoService->pLacDsaStatsArr); } #endif } /** * @ingroup Lac_Dsa */ void LacDsa_StatsReset(CpaInstanceHandle instanceHandle) { #ifdef QAT_LEGACY_ALGORITHMS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_DSA_STATS_INIT(pCryptoService); #endif } /** *************************************************************************** * @ingroup Lac_Dsa * DSA Stats Show function ***************************************************************************/ void LacDsa_StatsShow(CpaInstanceHandle instanceHandle) { #ifdef QAT_LEGACY_ALGORITHMS CpaCyDsaStats64 dsaStats = {0}; /* retrieve the stats */ (void)cpaCyDsaQueryStats64(instanceHandle, &dsaStats); /* log the stats to the standard output */ /* engine info */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " DSA Stats " BORDER "\n" SEPARATOR); /* p parameter generation requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DSA P Param Gen Requests-Succ: %16llu " BORDER "\n" BORDER " DSA P Param Gen Requests-Err: %16llu " BORDER "\n" BORDER " DSA P Param Gen Completed-Succ: %16llu " BORDER "\n" BORDER " DSA P Param Gen Completed-Err: %16llu " BORDER "\n" SEPARATOR, dsaStats.numDsaPParamGenRequests, dsaStats.numDsaPParamGenRequestErrors, dsaStats.numDsaPParamGenCompleted, dsaStats.numDsaPParamGenCompletedErrors); /* g parameter generation requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DSA G Param Gen Requests-Succ: %16llu " BORDER "\n" BORDER " DSA G Param Gen Requests-Err: %16llu " BORDER "\n" BORDER " DSA G Param Gen Completed-Succ: %16llu " BORDER "\n" BORDER " DSA G Param Gen Completed-Err: %16llu " BORDER "\n" SEPARATOR, dsaStats.numDsaGParamGenRequests, dsaStats.numDsaGParamGenRequestErrors, dsaStats.numDsaGParamGenCompleted, dsaStats.numDsaGParamGenCompletedErrors); /* y parameter generation requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DSA Y Param Gen Requests-Succ: %16llu " BORDER "\n" BORDER " DSA Y Param Gen Requests-Err: %16llu " BORDER "\n" BORDER " DSA Y Param Gen Completed-Succ: %16llu " BORDER "\n" BORDER " DSA Y Param Gen Completed-Err: %16llu " BORDER "\n" SEPARATOR, dsaStats.numDsaYParamGenRequests, dsaStats.numDsaYParamGenRequestErrors, dsaStats.numDsaYParamGenCompleted, dsaStats.numDsaYParamGenCompletedErrors); /* r sign requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DSA R Sign Requests-Succ: %16llu " BORDER "\n" BORDER " DSA R Sign Request-Err: %16llu " BORDER "\n" BORDER " DSA R Sign Completed-Succ: %16llu " BORDER "\n" BORDER " DSA R Sign Completed-Err: %16llu " BORDER "\n" SEPARATOR, dsaStats.numDsaRSignRequests, dsaStats.numDsaRSignRequestErrors, dsaStats.numDsaRSignCompleted, dsaStats.numDsaRSignCompletedErrors); /* s sign requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DSA S Sign Requests-Succ: %16llu " BORDER "\n" BORDER " DSA S Sign Request-Err: %16llu " BORDER "\n" BORDER " DSA S Sign Completed-Succ: %16llu " BORDER "\n" BORDER " DSA S Sign Completed-Err: %16llu " BORDER "\n" SEPARATOR, dsaStats.numDsaSSignRequests, dsaStats.numDsaSSignRequestErrors, dsaStats.numDsaSSignCompleted, dsaStats.numDsaSSignCompletedErrors); /* rs sign requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DSA RS Sign Requests-Succ: %16llu " BORDER "\n" BORDER " DSA RS Sign Request-Err: %16llu " BORDER "\n" BORDER " DSA RS Sign Completed-Succ: %16llu " BORDER "\n" BORDER " DSA RS Sign Completed-Err: %16llu " BORDER "\n" SEPARATOR, dsaStats.numDsaRSSignRequests, dsaStats.numDsaRSSignRequestErrors, dsaStats.numDsaRSSignCompleted, dsaStats.numDsaRSSignCompletedErrors); /* verify requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " DSA Verify Requests-Succ: %16llu " BORDER "\n" BORDER " DSA Verify Request-Err: %16llu " BORDER "\n" BORDER " DSA Verify Completed-Succ: %16llu " BORDER "\n" BORDER " DSA Verify Completed-Err: %16llu " BORDER "\n" BORDER " DSA Verify Completed-Failure: %16llu " BORDER "\n" SEPARATOR, dsaStats.numDsaVerifyRequests, dsaStats.numDsaVerifyRequestErrors, dsaStats.numDsaVerifyCompleted, dsaStats.numDsaVerifyCompletedErrors, dsaStats.numDsaVerifyFailures); #else /* !QAT_LEGACY_ALGORITHMS */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, " DSA not supported \n"); #endif } lac_dsa_interface_check.c000066400000000000000000000444211503624047500340760ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/dsa/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_dsa_interface_check.c * * @ingroup Lac_Dsa * * This file checks at compile time that the IA/FW interface is as expected * For example, in lac_dsa.c we use the fact that the index of x in the * structure icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t is equal to the index of * x in the structure icp_qat_fw_mmp_dsa_gen_p_2048_224_input_t. If this * assumption becomes invalid (FW interface changes to break the assumption * or the compiler moves things around) this file will fail to compile. * * Note for structures with only 1 member no check is required. * * ***************************************************************************/ #include "cpa.h" #include "icp_qat_fw_pke.h" #include "icp_qat_fw_mmp.h" #include "lac_common.h" #define COMPILE_TIME_ASSERT(pred) \ switch (0) \ { \ case 0: \ case pred:; \ } void LacDsa_CompileTimeAssertions(void) { /* ************************************************************* * GEN P Checks * ************************************************************* */ /* Check that icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t structures are equivalent */ COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_2048_224_input_t, x)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_2048_224_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_2048_256_input_t, x)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_2048_256_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_3072_256_input_t, x)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_p_3072_256_input_t, q)); /* ************************************************************* * GEN G Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_2048_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_2048_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_1024_input_t, h) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_2048_input_t, h)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_3072_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_3072_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_1024_input_t, h) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_g_3072_input_t, h)); /* ************************************************************* * GEN Y Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_2048_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_1024_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_2048_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_1024_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_2048_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_3072_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_1024_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_3072_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_1024_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_gen_y_3072_input_t, x)); /* ************************************************************* * SIGN R Checks * ************************************************************* */ COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t, k)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t, k)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t, k)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t, g)); /* ************************************************************* * SIGN S Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_224_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_224_input_t, k)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_224_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_224_input_t, r)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_224_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_256_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_256_input_t, k)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_256_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_256_input_t, r)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_s_256_input_t, x)); /* ************************************************************* * SIGN RS Checks * ************************************************************* */ COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t, m)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t, k)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t, x)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t, m)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t, k)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t, x)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t, m)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, k) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t, k)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t, x)); /* Check outputs */ COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_t, r)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, s) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_t, s)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_t, r)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, s) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_t, s)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t, r)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, s) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t, s)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t, r)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t, s) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t, s)); /* ************************************************************* * VERIFY Checks * ************************************************************* */ COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_224_input_t, r)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, s) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_224_input_t, s)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_224_input_t, m)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_224_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_224_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_224_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, y) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_224_input_t, y)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_256_input_t, r)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, s) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_256_input_t, s)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_256_input_t, m)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_256_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_256_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_256_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, y) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_2048_256_input_t, y)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, r) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_3072_256_input_t, r)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, s) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_3072_256_input_t, s)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_3072_256_input_t, m)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_3072_256_input_t, p)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_3072_256_input_t, q)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, g) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_3072_256_input_t, g)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_1024_160_input_t, y) == LAC_IDX_OF(icp_qat_fw_mmp_dsa_verify_3072_256_input_t, y)); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/000077500000000000000000000000001503624047500272245ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec.c000066400000000000000000002102411503624047500305760ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * * @file lac_ec.c * * @ingroup Lac_Ec * * Elliptic Curve functions * * @lld_start * * @lld_overview * This file implements Elliptic Curve api functions. * @lld_dependencies * - \ref LacAsymCommonQatComms "PKE QAT Comms" : For creating and sending * messages to the QAT * - \ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_initialisation * On initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * ***************************************************************************/ /* **************************************************************************** * Include public/global header files **************************************************************************** */ /* API Includes */ #include "cpa.h" #include "cpa_cy_ec.h" /* OSAL Includes */ #include "Osal.h" /* ADF Includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* QAT FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" /* Look Aside Includes */ #include "lac_log.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_sync.h" #include "lac_ec.h" #include "lac_ec_nist_curves.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "sal_service_state.h" #include "sal_statistics.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #endif typedef struct _OptCurveParams { Cpa32U dataOperationSizeBytes; Cpa32U function_point; Cpa32U function_generator; const Cpa8U *p; const Cpa8U *h; const Cpa8U *a; const Cpa8U *b; } OptCurveParams; /* ******************************************************************************** * Global Variables ******************************************************************************** */ #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #endif typedef const CpaCyEcCurveParametersWeierstrass *LacEc_WSCurvePtr; /**< number of 'in' arguments in the arguments size list for point verify */ #define LAC_EC_POINT_VERIFY_NUM_IN_ARGS 5 /**< number of 'in' arguments in the arguments size list for point multiply */ #define LAC_EC_POINT_MULTIPLY_NUM_IN_ARGS 7 /**< number of 'out' arguments in the arguments size list for point multiply */ #define LAC_EC_POINT_MULTIPLY_NUM_OUT_ARGS 2 /**< number of 'in' arguments in the arguments size list for the P256 and P384 * Point Multiply operation */ #define LAC_POINT_MULTIPLY_P256P384_NUM_IN_ARGS 3 /**< number of 'out' arguments in the arguments size list for the P256 and P384 * Point Multiply operation */ #define LAC_POINT_MULTIPLY_P256P384_NUM_OUT_ARGS 2 /**< number of EC statistics */ #define LAC_EC_NUM_STATS (sizeof(CpaCyEcStats64) / sizeof(Cpa64U)) #define LAC_EC_STATS_GET(ecStats, pCryptoService) \ do \ { \ Cpa32U i = 0; \ \ for (i = 0; i < LAC_EC_NUM_STATS; i++) \ { \ ((Cpa64U *)&(ecStats))[i] = \ osalAtomicGet(&pCryptoService->pLacEcStatsArr[i]); \ } \ } while (0) /**< @ingroup Lac_Ec * macro to get all EC stats (from internal array of atomics) * assumes pCryptoService has already been validated */ /**< @ingroup Lac_Ec * macro to collect EC stats in sample period of time */ typedef struct _PointMultiplyOpData { const CpaFlatBuffer *xg; const CpaFlatBuffer *yg; const CpaFlatBuffer *h; const CpaFlatBuffer *q; const CpaFlatBuffer *a; const CpaFlatBuffer *b; const CpaFlatBuffer *k; const CpaFlatBuffer *pXk; const CpaFlatBuffer *pYk; } PointMultiplyOpData; #define LacEcPointMultiplyOpDataWrite(in, out, data) \ do \ { \ \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.xg, (data)->xg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.yg, (data)->yg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.h, (data)->h); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.q, (data)->q); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.a, (data)->a); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.b, (data)->b); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.k, (data)->k); \ \ /* populate output parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.xk, (data)->pXk); \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.yk, (data)->pYk); \ } while (0); /**< @ingroup Lac_Ec * macro to write in/out parameters for the Point Multiply operation*/ #define LacEcGeneratorPointMultiplyWrite(in, out, data) \ do \ { \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.k, (data)->k); \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.xr, (data)->pXk); \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.yr, (data)->pYk); \ } while (0); /**< @ingroup Lac_Ec * macro to write in/out parameters for the Generator * Point Multiply operation*/ #define LacEcP256P384PointMultiplyWrite(in, out, data) \ do \ { \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.xp, (data)->xg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.yp, (data)->yg); \ LacEcGeneratorPointMultiplyWrite(in, out, data) \ } while (0); /**< @ingroup Lac_Ec * macro to write in/out parameters for the Generic P256 and P384 * Point Multiply operation*/ #define LacEcPointVerifyFillStruct(in, px, py, pp, pa, pb) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.xq, px); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.yq, py); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.q, pp); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.a, pa); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.b, pb); \ } while (0); /**< @ingroup Lac_Ec * macro to write in parameters for the Point Verify operation */ /* **************************************************************************** * Define static function definitions **************************************************************************** */ STATIC CpaStatus LacEc_CommonPointVerify(const CpaInstanceHandle instanceHandle_in, const void *pCb, void *pCallbackTag, const CpaCyEcPointVerifyOpData *pOpData_Legacy, const CpaCyEcGenericPointVerifyOpData *pOpData_Generic, CpaBoolean *pVerifyStatus); /** *************************************************************************** * @ingroup Lac_Ec * return the size in bytes of biggest number in CpaCyEcPointMultiplyOpData * * @description * return the size of the biggest number in * CpaCyEcPointMultiplyOpData. * * @param[in] pOpData Pointer to a CpaCyEcPointMultiplyOpData structure * * @retval max the size in bytes of the biggest number * ***************************************************************************/ STATIC Cpa32U LacEc_PointMultiplyOpDataSizeGetMax(const CpaCyEcPointMultiplyOpData *pOpData) { return LacPke_GetMaxLnOfNBuffers(7, &(pOpData->xg), &(pOpData->yg), &(pOpData->h), &(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->k)); } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC Cpa32U LacEc_PointMultiplyWeierstrassSizeGetMax( LacEc_WSCurvePtr pCurveWeierstrass) { return LacPke_GetMaxLnOfNBuffers(4, &(pCurveWeierstrass->h), &(pCurveWeierstrass->p), &(pCurveWeierstrass->a), &(pCurveWeierstrass->b)); } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC Cpa32U LacEc_GenericPointMultiplyOperationSizeGetMax( const CpaCyEcGenericPointMultiplyOpData *pOpData) { return LAC_MAX(LacEc_PointMultiplyWeierstrassSizeGetMax( &(pOpData->pCurve->parameters.weierstrassParameters)), LacPke_GetMaxLnOfNBuffers( 3, &(pOpData->xP), &(pOpData->yP), &(pOpData->k))); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ec * EC Point Multiply function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEc_PointMultiplyBasicParamCheck(const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyOpData *pOpData, const CpaBoolean *pMultiplyStatus, const CpaFlatBuffer *pXk, const CpaFlatBuffer *pYk) { /* check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pMultiplyStatus); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LAC_CHECK_NULL_PARAM(pOpData->a.pData); LAC_CHECK_SIZE(&(pOpData->a), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->b.pData); LAC_CHECK_SIZE(&(pOpData->b), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->q.pData); LAC_CHECK_SIZE(&(pOpData->q), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xg.pData); LAC_CHECK_SIZE(&(pOpData->xg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yg.pData); LAC_CHECK_SIZE(&(pOpData->yg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pXk); LAC_CHECK_NULL_PARAM(pYk); LAC_CHECK_NULL_PARAM(pXk->pData); LAC_CHECK_SIZE(pXk, CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pYk->pData); LAC_CHECK_SIZE(pYk, CHECK_NONE, 0); /* Check Cofactor - pData of FlatBuffer can be NULL if dataLenInBytes=0 */ if ((NULL == pOpData->h.pData) && (0 != pOpData->h.dataLenInBytes)) { LAC_INVALID_PARAM_LOG("pOpData->h.pData is NULL and " "pOpData->h.dataLenInBytes !=0"); return CPA_STATUS_INVALID_PARAM; } if (NULL != pOpData->h.pData) { LAC_CHECK_SIZE(&(pOpData->h), CHECK_NONE, 0); } if (CPA_CY_EC_FIELD_TYPE_PRIME != pOpData->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pOpData->fieldType) { return CPA_STATUS_INVALID_PARAM; } /* Check that q is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->q)); return CPA_STATUS_SUCCESS; } #endif #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEc_BasicParamCheckWeierstrass(const CpaCyEcCurve *pCurve) { LAC_CHECK_NULL_PARAM(pCurve); const CpaCyEcCurveType curveType = pCurve->curveType; /* Valid curve types are: * CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_PRIME = 1 * CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_BINARY = 2 * CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_KOBLITZ_BINARY = 3 * They are all covered by mask of 3 */ const Cpa32U validTypesMask = 3U; if ((curveType & validTypesMask) != curveType) { return CPA_STATUS_INVALID_PARAM; } if (CPA_CY_EC_FIELD_TYPE_PRIME != pCurve->parameters.weierstrassParameters.fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pCurve->parameters.weierstrassParameters.fieldType) { return CPA_STATUS_INVALID_PARAM; } LAC_CHECK_FLAT_BUFFER_PARAM(&(pCurve->parameters.weierstrassParameters.p), CHECK_LESS_EQUALS, LAC_EC_SIZE_BYTES_MAX); LAC_CHECK_ODD_PARAM(&(pCurve->parameters.weierstrassParameters.p)); LAC_CHECK_FLAT_BUFFER_PARAM( &(pCurve->parameters.weierstrassParameters.a), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &(pCurve->parameters.weierstrassParameters.b), CHECK_NONE, 0); if (NULL == pCurve->parameters.weierstrassParameters.h.pData) { if (0 != pCurve->parameters.weierstrassParameters.h.dataLenInBytes) { LAC_INVALID_PARAM_LOG( "pCurve->parameters.weierstrassParameters.h.pData is NULL and " "pCurve->parameters.weierstrassParameters.h.dataLenInBytes " "!=0"); return CPA_STATUS_INVALID_PARAM; } } else { LAC_CHECK_SIZE( &(pCurve->parameters.weierstrassParameters.h), CHECK_NONE, 0); } return CPA_STATUS_SUCCESS; } #endif #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEc_GenericPointMultiplyBasicParamCheck( const CpaCyEcGenericPointMultiplyOpData *pOpData, const CpaBoolean *pMultiplyStatus, const CpaFlatBuffer *pOutX, const CpaFlatBuffer *pOutY) { LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_FLAT_BUFFER_PARAM(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&(pOpData->xP), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&(pOpData->yP), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pMultiplyStatus); LAC_CHECK_FLAT_BUFFER_PARAM(pOutX, CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(pOutY, CHECK_NONE, 0); /* Currently we require Weierstrass curve - no other type is supported */ return LacEc_BasicParamCheckWeierstrass(pOpData->pCurve); } #endif /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC void LacEcc_PointMultiplySynchronousCallback(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaBoolean opResult, CpaFlatBuffer *pOutX, CpaFlatBuffer *pOutY) { LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEcc_CommonPathPointMultiplyOperation( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcPointMultiplyOpData *pOpData_Legacy, const CpaCyEcGenericPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pOutX, CpaFlatBuffer *pOutY); /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEc_CommonPathPointMultiplySynchronous( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyOpData *pOpData_Legacy, const CpaCyEcGenericPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pOutX, CpaFlatBuffer *pOutY) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { status = LacEcc_CommonPathPointMultiplyOperation( instanceHandle, LacEcc_PointMultiplySynchronousCallback, pSyncCallbackData, pOpData_Legacy, pOpData, pMultiplyStatus, pOutX, pOutY); } else { LAC_EC_STAT_INC(numEcPointMultiplyRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { status = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != status) { LAC_EC_STAT_INC(numEcPointMultiplyCompletedError, pCryptoService); } } else { LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ec * EC Point Multiply internal callback ***************************************************************************/ STATIC void LacEc_PointMultiplyCallback(CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcPointMultiplyCbFunc pCb = NULL; void *pCallbackTag = NULL; void *pOpData = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcPointMultiplyCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)pCbData->pClientOpData; pXk = pCbData->pOutputData1; pYk = pCbData->pOutputData2; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pXk); LAC_ASSERT_NOT_NULL(pYk); /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_EC_STAT_INC(numEcPointMultiplyCompleted, pCryptoService); } else { LAC_EC_STAT_INC(numEcPointMultiplyCompletedError, pCryptoService); } if ((CPA_FALSE == multiplyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_EC_STAT_INC(numEcPointMultiplyCompletedOutputInvalid, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pXk, pYk); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ec * EC Point Verify function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEc_PointVerifyBasicParamCheckWeierstrass( const CpaInstanceHandle instanceHandle, const CpaCyEcGenericPointVerifyOpData *pOpData, const CpaBoolean *pVerifyStatus) { /* check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pOpData->pCurve); LAC_CHECK_NULL_PARAM(pVerifyStatus); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LacEc_WSCurvePtr pWeirstrassCurve = &(pOpData->pCurve->parameters.weierstrassParameters); LAC_CHECK_FLAT_BUFFER_PARAM(&(pWeirstrassCurve->a), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&(pWeirstrassCurve->b), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &(pWeirstrassCurve->p), CHECK_LESS_EQUALS, LAC_EC_SIZE_BYTES_MAX); LAC_CHECK_FLAT_BUFFER_PARAM(&(pOpData->xP), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM(&(pOpData->yP), CHECK_NONE, 0); if (CPA_CY_EC_FIELD_TYPE_PRIME != pWeirstrassCurve->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pWeirstrassCurve->fieldType) { return CPA_STATUS_INVALID_PARAM; } /* Check that p is odd */ LAC_CHECK_ODD_PARAM(&(pWeirstrassCurve->p)); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ec * EC Point Verify function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEc_PointVerifyBasicParamCheck(const CpaInstanceHandle instanceHandle, const CpaCyEcPointVerifyOpData *pOpData, const CpaBoolean *pVerifyStatus) { /* check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pVerifyStatus); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LAC_CHECK_NULL_PARAM(pOpData->a.pData); LAC_CHECK_SIZE(&(pOpData->a), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->b.pData); LAC_CHECK_SIZE(&(pOpData->b), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->q.pData); LAC_CHECK_SIZE(&(pOpData->q), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xq.pData); LAC_CHECK_SIZE(&(pOpData->xq), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yq.pData); LAC_CHECK_SIZE(&(pOpData->yq), CHECK_NONE, 0); if (CPA_CY_EC_FIELD_TYPE_PRIME != pOpData->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pOpData->fieldType) { return CPA_STATUS_INVALID_PARAM; } /* Check that q is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->q)); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Ec * EC Point Verify synchronous function ***************************************************************************/ STATIC CpaStatus LacEc_CommonPointVerifySyn( const CpaInstanceHandle instanceHandle, const CpaCyEcPointVerifyOpData *pOpData_Legacy, const CpaCyEcGenericPointVerifyOpData *pOpData_Generic, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sync_op_data_t *pSyncCallbackData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the generic synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = LacEc_CommonPointVerify(instanceHandle, LacSync_GenVerifyCb, pSyncCallbackData, pOpData_Legacy, pOpData_Generic, pVerifyStatus); } else { LAC_EC_STAT_INC(numEcPointVerifyRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pVerifyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { LAC_EC_STAT_INC(numEcPointVerifyCompletedErrors, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ec * EC Point Verify internal callback ***************************************************************************/ STATIC void LacEc_PointVerifyCallback(CpaStatus status, CpaBoolean verifyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcPointVerifyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcPointVerifyOpData *pOpData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcPointVerifyCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyEcPointVerifyOpData *)pCbData->pClientOpData; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_EC_STAT_INC(numEcPointVerifyCompleted, pCryptoService); } else { LAC_EC_STAT_INC(numEcPointVerifyCompletedErrors, pCryptoService); } if ((CPA_FALSE == verifyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_EC_STAT_INC(numEcPointVerifyCompletedOutputInvalid, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, verifyStatus); } /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ CpaStatus cpaCyEcPointVerify(const CpaInstanceHandle instanceHandle_in, const CpaCyEcPointVerifyCbFunc pCb, void *pCallbackTag, const CpaCyEcPointVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { return LacEc_CommonPointVerify( instanceHandle_in, pCb, pCallbackTag, pOpData, NULL, pVerifyStatus); } /** *************************************************************************** * @ingroup LacEc * Detect P256 or P384 and get optimised MMP function id ***************************************************************************/ STATIC CpaBoolean LacEc_GetOptFunctionId(const sal_crypto_service_t *pService, CpaCyEcFieldType primeRepresentation, const CpaFlatBuffer *pP, const CpaFlatBuffer *pH, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, Cpa32U *dataOperationSizeBytes, Cpa32U *function, CpaBoolean generator) { *function = 0; if (!pService->generic_service_info.optimisedCurveSupport) return CPA_FALSE; int i = 0; OptCurveParams curves[] = { /* P256 */ { .dataOperationSizeBytes = LAC_BITS_TO_BYTES(LAC_256_BITS), .function_point = PKE_EC_POINT_MULTIPLICATION_P256, .function_generator = PKE_EC_GENERATOR_MULTIPLICATION_P256, .p = nist_p256_p, .h = nist_p256_h, .a = nist_p256_a, .b = nist_p256_b }, /* P384 */ { .dataOperationSizeBytes = LAC_BITS_TO_BYTES(LAC_384_BITS), .function_point = PKE_EC_POINT_MULTIPLICATION_P384, .function_generator = PKE_EC_GENERATOR_MULTIPLICATION_P384, .p = nist_p384_p, .h = nist_p384_h, .a = nist_p384_a, .b = nist_p384_b }, }; /* Loop through each curve returning when found and setting * dataOperationSizeBytes and function id */ for (i = 0; i < ARRAY_SIZE(curves); i++) { CpaBoolean res = CPA_CY_EC_FIELD_TYPE_PRIME == primeRepresentation; /* if the curve has not the prime representation continue searching */ if (!res) continue; res = (NULL == pH->pData) || LacPke_CompareFlatAndPtr( pH, curves[i].h, curves[i].dataOperationSizeBytes); if (!res) continue; res = LacPke_CompareFlatAndPtr( pP, curves[i].p, curves[i].dataOperationSizeBytes); if (!res) continue; res = LacPke_CompareFlatAndPtr( pA, curves[i].a, curves[i].dataOperationSizeBytes); if (!res) continue; res = LacPke_CompareFlatAndPtr( pB, curves[i].b, curves[i].dataOperationSizeBytes); if (res == CPA_TRUE) { *dataOperationSizeBytes = curves[i].dataOperationSizeBytes; if (generator) { *function = curves[i].function_generator; } else { *function = curves[i].function_point; } return CPA_TRUE; } } return CPA_FALSE; /* not found any optimised curve */ } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEcc_PointMultiplyFillMMPStructsOpDataWrite( icp_qat_fw_mmp_input_param_t *in, Cpa32U *inSizes, CpaBoolean *inAlloc, icp_qat_fw_mmp_output_param_t *out, Cpa32U *outSizes, CpaBoolean *outAlloc, Cpa32U *function, Cpa32U size, Cpa32U representation, const PointMultiplyOpData *data); /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEcc_CommonPathPointMultiply( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcPointMultiplyOpData *pOpData_Legacy, const CpaCyEcGenericPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pOutX, CpaFlatBuffer *pOutY); /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ CpaStatus cpaCyEcPointMultiply(const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { LAC_CHECK_NULL_PARAM(pOpData); return LacEcc_CommonPathPointMultiply(instanceHandle, pCb, pCallbackTag, pOpData, NULL, pMultiplyStatus, pXk, pYk); } /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ STATIC CpaStatus LacEcc_CommonPathUnoptimised( const CpaCyEcPointMultiplyOpData *pOpData_Legacy, const CpaCyEcGenericPointMultiplyOpData *pOpData, CpaCyEcFieldType primeRepresentation, const CpaFlatBuffer *pP, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, const CpaFlatBuffer *pH, const CpaFlatBuffer *pK, const CpaFlatBuffer *pXp, const CpaFlatBuffer *pYp, Cpa32U *dataOperationSizeBytes) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U maxDataSize = 0u; if (pOpData_Legacy) { maxDataSize = LacEc_PointMultiplyOpDataSizeGetMax(pOpData_Legacy); } else { maxDataSize = LacEc_GenericPointMultiplyOperationSizeGetMax(pOpData); } status = LacEc_GetRange(maxDataSize, dataOperationSizeBytes); LAC_CHECK_STATUS(status); if ((LAC_EC_SIZE_QW4_IN_BYTES == *dataOperationSizeBytes) && (CPA_CY_EC_FIELD_TYPE_BINARY == primeRepresentation)) { LacEc_CheckCurve4QWGF2(dataOperationSizeBytes, pP, pA, pB, NULL, pH); } #ifdef ICP_PARAM_CHECK if (LAC_EC_SIZE_QW9_IN_BYTES == *dataOperationSizeBytes) { if (CPA_CY_EC_FIELD_TYPE_PRIME == primeRepresentation) { status = LacEc_CheckCurve9QWGFP(pP, pA, pB, NULL, pH, pXp, pYp); } else { status = LacEc_CheckCurve9QWGF2(pP, pA, pB, NULL, pH, pXp, pYp); } } LAC_CHECK_STATUS(status); /* Check size of h*k result */ /* log2(h*k) = log2(h) +log2(k) */ /* highest bit position of (h*k) = floor[log2(h*k)] */ /* max(floor[log2(h*k)]) = floor[log2(h)] +floor[log2(k)] + 1 */ /* for h>1 and k>1, else if h=1 or k=1 check is already done */ /* by earlier buffer checks */ Cpa32U bit_pos_k = 0u; Cpa32U bit_pos_h = 0u; Cpa32U temp = 0u; CpaBoolean isZero = CPA_FALSE; LacPke_GetBitPos(pK, &bit_pos_k, &temp, &isZero); if (NULL == pH->pData) { bit_pos_h = 0u; } else { LacPke_GetBitPos(pH, &bit_pos_h, &temp, &isZero); } if ((bit_pos_h > 0u) && (bit_pos_k > 0u)) { Cpa32U requiredBits = bit_pos_k + bit_pos_h + 1; if (CPA_CY_EC_FIELD_TYPE_PRIME == primeRepresentation) { /* In GFP case h*k should fit in dataOperationSizeBytes */ Cpa32U bufferBits = LAC_BYTES_TO_BITS(*dataOperationSizeBytes) - 1; if (bufferBits < requiredBits) { if (LAC_EC_SIZE_QW4_IN_BYTES == *dataOperationSizeBytes) { /* Use 8QW service instead */ *dataOperationSizeBytes = LAC_EC_SIZE_QW8_IN_BYTES; } else { /* In 8QW case invalid param (similarly for 9QW but code won't get this far)*/ LAC_INVALID_PARAM_LOG("log2(k)+log2(h) is NOT <512"); status = CPA_STATUS_INVALID_PARAM; } } } else { /* In GF2 9QW and 4QW special cases h has already been checked (and is known by MMP) and the size of k has already been checked in getRange function so just need to check 8QW case */ Cpa32U bufferBits = LAC_BYTES_TO_BITS(LAC_EC_SIZE_QW9_IN_BYTES) - 1; if (bufferBits < requiredBits) { if (LAC_EC_SIZE_QW8_IN_BYTES == *dataOperationSizeBytes) /* For 8QW h*k should fit in 9QW */ { LAC_INVALID_PARAM_LOG("log2(k)+log2(h) is NOT <576"); status = CPA_STATUS_INVALID_PARAM; } } } } /* Ensure that h!=0 */ /* This is invalid for all secure curves */ /* pH=NULL is sent to PKE as h=0 which is understood by MMP program as h=1 as required - therefore need to eliminate invalid h=0 case here */ LAC_CHECK_STATUS(status); if (NULL != pH->pData && (0 == LacPke_CompareZero(pH, 0))) { LAC_INVALID_PARAM_LOG("Cofactor == 0"); status = CPA_STATUS_INVALID_PARAM; } LAC_CHECK_STATUS(status); /* Check that q>3 for GFP (i.e. highest bit position needs to be greater than 1) or that deg(q)>2 for GF2 (i.e. highest bit position needs to be greater than 2) */ Cpa32U bit_pos_p = 0u; LacPke_GetBitPos(pP, &bit_pos_p, &temp, &isZero); if (((CPA_CY_EC_FIELD_TYPE_BINARY == primeRepresentation) && (bit_pos_p < LAC_EC_MIN_MOD_BIT_POS_GF2)) || ((CPA_CY_EC_FIELD_TYPE_PRIME == primeRepresentation) && (bit_pos_p < LAC_EC_MIN_MOD_BIT_POS_GFP))) { LAC_INVALID_PARAM_LOG("q is too small"); status = CPA_STATUS_INVALID_PARAM; } #endif return status; } /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ STATIC CpaStatus LacEcc_CommonPathPointMultiplyOperation( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcPointMultiplyOpData *pOpData_Legacy, const CpaCyEcGenericPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pOutX, CpaFlatBuffer *pOutY) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCyEcFieldType primeRepresentation = CPA_CY_EC_FIELD_TYPE_PRIME; const CpaFlatBuffer *pP = NULL; const CpaFlatBuffer *pA = NULL; const CpaFlatBuffer *pB = NULL; const CpaFlatBuffer *pH = NULL; const CpaFlatBuffer *pK = NULL; const CpaFlatBuffer *pXp = NULL; const CpaFlatBuffer *pYp = NULL; CpaBoolean generator = CPA_FALSE; lac_pke_op_cb_data_t cbData = {0}; if (pOpData_Legacy) { #ifdef ICP_PARAM_CHECK /* Basic NULL Param Checking */ status = LacEc_PointMultiplyBasicParamCheck( instanceHandle, pOpData_Legacy, pMultiplyStatus, pOutX, pOutY); LAC_CHECK_STATUS(status); #endif primeRepresentation = pOpData_Legacy->fieldType; pP = &pOpData_Legacy->q; pA = &pOpData_Legacy->a; pB = &pOpData_Legacy->b; pH = &pOpData_Legacy->h; pK = &pOpData_Legacy->k; pXp = &pOpData_Legacy->xg; pYp = &pOpData_Legacy->yg; cbData.pClientOpData = pOpData_Legacy; } else { #ifdef ICP_PARAM_CHECK /* Basic NULL Param Checking */ status = LacEc_GenericPointMultiplyBasicParamCheck(pOpData, pMultiplyStatus, pOutX, pOutY); LAC_CHECK_STATUS(status); #endif LacEc_WSCurvePtr cpWpCp = &pOpData->pCurve->parameters.weierstrassParameters; primeRepresentation = cpWpCp->fieldType; pP = &cpWpCp->p; pA = &cpWpCp->a; pB = &cpWpCp->b; pH = &cpWpCp->h; pK = &pOpData->k; pXp = &pOpData->xP; pYp = &pOpData->yP; generator = pOpData->generator; cbData.pClientOpData = pOpData; } #ifdef ICP_PARAM_CHECK /* Check that output buffers are big enough */ Cpa32U maxModLen = LacPke_GetMinBytes(pP); LAC_CHECK_SIZE(pOutX, CHECK_GREATER_EQUALS, maxModLen); LAC_CHECK_SIZE(pOutY, CHECK_GREATER_EQUALS, maxModLen); #endif cbData.pCallbackTag = pCallbackTag; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pOutX; cbData.pOutputData2 = pOutY; cbData.pClientCb = pCb; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; Cpa32U functionID = 0u; Cpa32U dataOperationSizeBytes = 0u; CpaBoolean optimisedSupported = CPA_FALSE; PointMultiplyOpData data = { .xg = pXp, .yg = pYp, .h = pH, .q = pP, .a = pA, .b = pB, .k = pK, .pXk = pOutX, .pYk = pOutY }; optimisedSupported = LacEc_GetOptFunctionId((sal_crypto_service_t *)instanceHandle, primeRepresentation, pP, pH, pA, pB, &dataOperationSizeBytes, &functionID, generator); if (!optimisedSupported) { status = LacEcc_CommonPathUnoptimised(pOpData_Legacy, pOpData, primeRepresentation, pP, pA, pB, pH, pK, pXp, pYp, &dataOperationSizeBytes); } LAC_CHECK_STATUS(status); /* Zero the output buffers */ osalMemSet(pOutX->pData, 0, pOutX->dataLenInBytes); osalMemSet(pOutY->pData, 0, pOutY->dataLenInBytes); /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS(inArgSizeList, LAC_EC_POINT_MULTIPLY_NUM_IN_ARGS, dataOperationSizeBytes); LAC_EC_SET_LIST_PARAMS(outArgSizeList, LAC_EC_POINT_MULTIPLY_NUM_OUT_ARGS, dataOperationSizeBytes); /* Set all input and output memory to externally allocated */ LAC_EC_SET_LIST_PARAMS( internalMemInList, LAC_EC_POINT_MULTIPLY_NUM_IN_ARGS, CPA_FALSE); LAC_EC_SET_LIST_PARAMS( internalMemOutList, LAC_EC_POINT_MULTIPLY_NUM_OUT_ARGS, CPA_FALSE); /* Populate input and output buffers for MMP and set function ID */ /* Note datalenInBytes of input flatbuffers can be greater than * dataOperationSizeBytes. CreateRequest() allows for this - pke buffer * will offset into client buffer. */ status = LacEcc_PointMultiplyFillMMPStructsOpDataWrite(&in, inArgSizeList, internalMemInList, &out, outArgSizeList, internalMemOutList, &functionID, dataOperationSizeBytes, primeRepresentation, &data); LAC_CHECK_STATUS(status); /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionID, inArgSizeList, outArgSizeList, &in, &out, internalMemInList, internalMemOutList, LacEc_PointMultiplyCallback, &cbData, instanceHandle); return status; } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEcc_PointMultiplyFillMMPStructsOpDataWrite( icp_qat_fw_mmp_input_param_t *in, Cpa32U *inSizes, CpaBoolean *inAlloc, icp_qat_fw_mmp_output_param_t *out, Cpa32U *outSizes, CpaBoolean *outAlloc, Cpa32U *function, Cpa32U size, Cpa32U representation, const PointMultiplyOpData *data) { /* All input and output memory is externally allocated */ const CpaBoolean externallyAllocated = CPA_FALSE; /* Populate input and output buffers for optimised MMP functions */ switch (*function) { case PKE_EC_POINT_MULTIPLICATION_P256: LAC_EC_SET_LIST_PARAMS(inSizes, 3, size); LAC_EC_SET_LIST_PARAMS(inAlloc, 3, externallyAllocated); LAC_EC_SET_LIST_PARAMS(outSizes, 2, size); LAC_EC_SET_LIST_PARAMS(outAlloc, 2, externallyAllocated); LacEcP256P384PointMultiplyWrite( in->mmp_ec_point_multiplication_p256, out->mmp_ec_point_multiplication_p256, data); return CPA_STATUS_SUCCESS; case PKE_EC_GENERATOR_MULTIPLICATION_P256: LAC_EC_SET_LIST_PARAMS(inSizes, 1, size); LAC_EC_SET_LIST_PARAMS(inAlloc, 1, externallyAllocated); LAC_EC_SET_LIST_PARAMS(outSizes, 2, size); LAC_EC_SET_LIST_PARAMS(outAlloc, 2, externallyAllocated); LacEcGeneratorPointMultiplyWrite( in->mmp_ec_generator_multiplication_p256, out->mmp_ec_generator_multiplication_p256, data); return CPA_STATUS_SUCCESS; case PKE_EC_POINT_MULTIPLICATION_P384: LAC_EC_SET_LIST_PARAMS(inSizes, 3, size); LAC_EC_SET_LIST_PARAMS(inAlloc, 3, externallyAllocated); LAC_EC_SET_LIST_PARAMS(outSizes, 2, size); LAC_EC_SET_LIST_PARAMS(outAlloc, 2, externallyAllocated); LacEcP256P384PointMultiplyWrite( in->mmp_ec_point_multiplication_p384, out->mmp_ec_point_multiplication_p384, data); return CPA_STATUS_SUCCESS; case PKE_EC_GENERATOR_MULTIPLICATION_P384: LAC_EC_SET_LIST_PARAMS(inSizes, 1, size); LAC_EC_SET_LIST_PARAMS(inAlloc, 1, externallyAllocated); LAC_EC_SET_LIST_PARAMS(outSizes, 2, size); LAC_EC_SET_LIST_PARAMS(outAlloc, 2, externallyAllocated); LacEcGeneratorPointMultiplyWrite( in->mmp_ec_generator_multiplication_p384, out->mmp_ec_generator_multiplication_p384, data); return CPA_STATUS_SUCCESS; } LAC_ASSERT(0 == *function, "Here *functionID should be 0"); /* Populate input and output buffers for MMP and set function ID */ if (CPA_CY_EC_FIELD_TYPE_PRIME == representation) { switch (size) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcPointMultiplyOpDataWrite( in->maths_point_multiplication_gfp_l256, out->maths_point_multiplication_gfp_l256, data); *function = MATHS_POINT_MULTIPLICATION_GFP_L256; return CPA_STATUS_SUCCESS; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcPointMultiplyOpDataWrite( in->maths_point_multiplication_gfp_l512, out->maths_point_multiplication_gfp_l512, data); *function = MATHS_POINT_MULTIPLICATION_GFP_L512; return CPA_STATUS_SUCCESS; case LAC_EC_SIZE_QW9_IN_BYTES: { Cpa32U index = LAC_IDX_OF( icp_qat_fw_maths_point_multiplication_gfp_521_input_t, h); LacEcPointMultiplyOpDataWrite( in->maths_point_multiplication_gfp_521, out->maths_point_multiplication_gfp_521, data); *function = MATHS_POINT_MULTIPLICATION_GFP_521; LAC_ASSERT(LAC_MAX_MMP_INPUT_PARAMS > index, "invalid cofactor index"); inSizes[index] = LAC_QUAD_WORD_IN_BYTES; return CPA_STATUS_SUCCESS; } default: return CPA_STATUS_INVALID_PARAM; } } else { switch (size) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcPointMultiplyOpDataWrite( in->maths_point_multiplication_gf2_l256, out->maths_point_multiplication_gf2_l256, data); *function = MATHS_POINT_MULTIPLICATION_GF2_L256; return CPA_STATUS_SUCCESS; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcPointMultiplyOpDataWrite( in->maths_point_multiplication_gf2_l512, out->maths_point_multiplication_gf2_l512, data); *function = MATHS_POINT_MULTIPLICATION_GF2_L512; return CPA_STATUS_SUCCESS; case LAC_EC_SIZE_QW9_IN_BYTES: { Cpa32U index = LAC_IDX_OF( icp_qat_fw_maths_point_multiplication_gf2_571_input_t, h); LacEcPointMultiplyOpDataWrite( in->maths_point_multiplication_gf2_571, out->maths_point_multiplication_gf2_571, data); *function = MATHS_POINT_MULTIPLICATION_GF2_571; LAC_ASSERT(LAC_MAX_MMP_INPUT_PARAMS > index, "invalid cofactor index"); inSizes[index] = LAC_QUAD_WORD_IN_BYTES; return CPA_STATUS_SUCCESS; } default: return CPA_STATUS_INVALID_PARAM; } } return CPA_STATUS_INVALID_PARAM; } /** *************************************************************************** * @ingroup Lac_Ec * EC Point Verify for Weierstrass curves ***************************************************************************/ STATIC CpaStatus LacEc_CommonPointVerify(const CpaInstanceHandle instanceHandle_in, const void *pCb, void *pCallbackTag, const CpaCyEcPointVerifyOpData *pOpData_Legacy, const CpaCyEcGenericPointVerifyOpData *pOpData_Generic, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U dataOperationSizeBytes = 0; void *pOpData; sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = instanceHandle_in; const CpaFlatBuffer *pX; const CpaFlatBuffer *pY; const CpaFlatBuffer *pMod; const CpaFlatBuffer *pA; const CpaFlatBuffer *pB; const Cpa32U pCount = 5; CpaCyEcFieldType fieldType; CpaCyEcCurveParameters *pCurveParameters; #ifdef ICP_PARAM_CHECK Cpa32U bit_pos_q = 0; Cpa32U temp = 0; CpaBoolean isZero = CPA_FALSE; #endif if (pOpData_Legacy != NULL && pOpData_Generic == NULL) { /* legacy api parameters */ pOpData = (void *)pOpData_Legacy; pX = &pOpData_Legacy->xq; pY = &pOpData_Legacy->yq; pMod = &pOpData_Legacy->q; pA = &pOpData_Legacy->a; pB = &pOpData_Legacy->b; fieldType = pOpData_Legacy->fieldType; } else if (pOpData_Legacy == NULL && pOpData_Generic != NULL) { /* generic api parameters */ pOpData = (void *)pOpData_Generic; pCurveParameters = &pOpData_Generic->pCurve->parameters; pX = &pOpData_Generic->xP; pY = &pOpData_Generic->yP; pMod = &pCurveParameters->weierstrassParameters.p; pA = &pCurveParameters->weierstrassParameters.a; pB = &pCurveParameters->weierstrassParameters.b; fieldType = pCurveParameters->weierstrassParameters.fieldType; } else { return CPA_STATUS_INVALID_PARAM; } LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ec); /* Check if the API has been called in synchronous mode */ if (NULL == pCb) { #ifdef ICP_PARAM_CHECK /* Check for valid pointers */ LAC_CHECK_NULL_PARAM(pVerifyStatus); #endif status = LacEc_CommonPointVerifySyn( instanceHandle, pOpData_Legacy, pOpData_Generic, pVerifyStatus); #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pOpData_Legacy, (LAC_ARCH_UINT)pOpData_Generic, (LAC_ARCH_UINT)pVerifyStatus, *pVerifyStatus); #endif return status; } #ifdef ICP_PARAM_CHECK /* Basic NULL Param Checking */ if (pOpData_Legacy) { status = LacEc_PointVerifyBasicParamCheck( instanceHandle, pOpData_Legacy, pVerifyStatus); } else { status = LacEc_PointVerifyBasicParamCheckWeierstrass( instanceHandle, pOpData_Generic, pVerifyStatus); } if (CPA_STATUS_SUCCESS == status) { #endif /* Determine size */ status = LacEc_GetRange( LacPke_GetMaxLnOfNBuffers(pCount, pX, pY, pMod, pA, pB), &dataOperationSizeBytes); #ifdef ICP_PARAM_CHECK } #endif if (CPA_STATUS_SUCCESS == status) { if ((LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes) && (CPA_CY_EC_FIELD_TYPE_BINARY == fieldType)) { /* Check if it is a NIST curve if not use 8QW */ LacEc_CheckCurve4QWGF2( &dataOperationSizeBytes, pMod, pA, pB, NULL, NULL); } } #ifdef ICP_PARAM_CHECK if ((CPA_STATUS_SUCCESS == status) && (LAC_EC_SIZE_QW9_IN_BYTES == dataOperationSizeBytes)) { /* 9QW checks */ if (CPA_CY_EC_FIELD_TYPE_PRIME == fieldType) { /* Check if it is a NIST curve (if not, then invalid param) */ /* Also checks that xq and yq are less than 2^521 */ status = LacEc_CheckCurve9QWGFP(pMod, pA, pB, NULL, NULL, pX, pY); } else { /*Check if it is a NIST curve (if not, then invalid param) */ /* Also checks that deg xq and yq are less than deg q */ status = LacEc_CheckCurve9QWGF2(pMod, pA, pB, NULL, NULL, pX, pY); } } if (CPA_STATUS_SUCCESS == status) { /* Check that q>3 for GFP (i.e. highest bit position needs to be greater than 1) or that deg(q)>2 for GF2 (i.e. highest bit position needs to be greater than 2) */ LacPke_GetBitPos(pMod, &bit_pos_q, &temp, &isZero); if (((CPA_CY_EC_FIELD_TYPE_BINARY == fieldType) && (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GF2)) || ((CPA_CY_EC_FIELD_TYPE_PRIME == fieldType) && (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GFP))) { LAC_INVALID_PARAM_LOG("q is not as required - too small"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; lac_pke_op_cb_data_t cbData = {0}; Cpa32U functionID = 0; /* Holding the calculated size of the input parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS(inArgSizeList, LAC_EC_POINT_VERIFY_NUM_IN_ARGS, dataOperationSizeBytes); /* Set input memory to externally allocated */ LAC_EC_SET_LIST_PARAMS( internalMemInList, LAC_EC_POINT_VERIFY_NUM_IN_ARGS, CPA_FALSE); /* populate callback data */ cbData.pCallbackTag = pCallbackTag; cbData.pClientCb = pCb; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = NULL; cbData.pOutputData2 = NULL; /* Populate input buffers and output buffer and set function ID */ if (CPA_CY_EC_FIELD_TYPE_PRIME == fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcPointVerifyFillStruct( in.maths_point_verify_gfp_l256, pX, pY, pMod, pA, pB); functionID = MATHS_POINT_VERIFY_GFP_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcPointVerifyFillStruct( in.maths_point_verify_gfp_l512, pX, pY, pMod, pA, pB); functionID = MATHS_POINT_VERIFY_GFP_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcPointVerifyFillStruct( in.maths_point_verify_gfp_521, pX, pY, pMod, pA, pB); functionID = MATHS_POINT_VERIFY_GFP_521; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } else { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcPointVerifyFillStruct( in.maths_point_verify_gf2_l256, pX, pY, pMod, pA, pB); functionID = MATHS_POINT_VERIFY_GF2_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcPointVerifyFillStruct( in.maths_point_verify_gf2_l512, pX, pY, pMod, pA, pB); functionID = MATHS_POINT_VERIFY_GF2_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcPointVerifyFillStruct( in.maths_point_verify_gf2_571, pX, pY, pMod, pA, pB); functionID = MATHS_POINT_VERIFY_GF2_571; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } if (CPA_STATUS_SUCCESS == status) { /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionID, inArgSizeList, NULL, &in, &out, internalMemInList, NULL, LacEc_PointVerifyCallback, &cbData, instanceHandle); } } pCryptoService = (sal_crypto_service_t *)instanceHandle; /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_EC_STAT_INC(numEcPointVerifyRequests, pCryptoService); } else { LAC_EC_STAT_INC(numEcPointVerifyRequestErrors, pCryptoService); } return status; } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ CpaStatus cpaCyEcQueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyEcStats64 *pEcStats) { sal_crypto_service_t *pCryptoService; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pEcStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); pCryptoService = (sal_crypto_service_t *)instanceHandle; /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ec); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pEcStats); /* get stats into user supplied stats structure */ LAC_EC_STATS_GET(*pEcStats, pCryptoService); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ec * Generic ECC point verification operation ***************************************************************************/ CpaStatus cpaCyEcGenericPointVerify( const CpaInstanceHandle instanceHandle, const CpaCyEcPointVerifyCbFunc pCb, void *pCallbackTag, const CpaCyEcGenericPointVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pOpData->pCurve); switch (pOpData->pCurve->curveType) { case CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_PRIME: /* Fall through */ case CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_BINARY: case CPA_CY_EC_CURVE_TYPE_WEIERSTRASS_KOBLITZ_BINARY: status = LacEc_CommonPointVerify(instanceHandle, pCb, pCallbackTag, NULL, pOpData, pVerifyStatus); break; default: /* other curve types are currently unsupported */ status = CPA_STATUS_INVALID_PARAM; break; } return status; } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ STATIC CpaStatus LacEcc_CommonPathPointMultiply( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcPointMultiplyOpData *pOpData_Legacy, const CpaCyEcGenericPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pOutX, CpaFlatBuffer *pOutY) { CpaInstanceHandle usedInstanceHandle = instanceHandle; LAC_CHECK_STATUS(LacEc_ValidateInstance(&usedInstanceHandle)); SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(usedInstanceHandle, ec); CpaStatus status = CPA_STATUS_SUCCESS; if (NULL == pCb) /* Synchronous mode */ { status = LacEc_CommonPathPointMultiplySynchronous(usedInstanceHandle, pOpData_Legacy, pOpData, pMultiplyStatus, pOutX, pOutY); } else { status = LacEcc_CommonPathPointMultiplyOperation(usedInstanceHandle, pCb, pCallbackTag, pOpData_Legacy, pOpData, pMultiplyStatus, pOutX, pOutY); } #ifdef ICP_TRACE LAC_LOG7("Called with params (0x%lx -> 0x%1x, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx,", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)usedInstanceHandle, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData_Legacy, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pMultiplyStatus); LAC_LOG2(" 0x%lx, 0x%lx\n)", (LAC_ARCH_UINT)pOutX, (LAC_ARCH_UINT)pOutY); #endif sal_crypto_service_t *pService = (sal_crypto_service_t *)usedInstanceHandle; if (CPA_STATUS_SUCCESS == status) { LAC_EC_STAT_INC(numEcPointMultiplyRequests, pService); } else { LAC_EC_STAT_INC(numEcPointMultiplyRequestErrors, pService); } return status; } /** *************************************************************************** * @ingroup LacEc * ***************************************************************************/ CpaStatus cpaCyEcGenericPointMultiply( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcGenericPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pOutX, CpaFlatBuffer *pOutY) { LAC_CHECK_NULL_PARAM(pOpData); return LacEcc_CommonPathPointMultiply(instanceHandle, pCb, pCallbackTag, NULL, pOpData, pMultiplyStatus, pOutX, pOutY); } CpaStatus cpaCyEcDpaGenericPointMultiply( const CpaInstanceHandle instanceHandle, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcGenericPointMultiplyOpData *pOpData, const CpaFlatBuffer *pRandom, const CpaBoolean createRandomData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_common.c000066400000000000000000001472641503624047500321640ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * * @file lac_ec_common.c * * @defgroup Lac_Ec Elliptic Curve * * @ingroup LacAsym * * Elliptic Curve Cryptography common functions * * @lld_start * * @lld_overview * This is the Elliptic Curve common functions. * * @lld_dependencies * - \ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_initialisation * On initialisation this component clears the stats and allocates memory * pool. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * ***************************************************************************/ /* **************************************************************************** * Include public/global header files **************************************************************************** */ /* API Includes */ #include "cpa.h" #include "cpa_cy_ec.h" #include "cpa_cy_ecdh.h" #include "cpa_cy_ecdsa.h" #include "cpa_cy_ecsm2.h" /* OSAL Includes */ #include "Osal.h" /* adf includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" /* Look Aside Includes */ #include "lac_common.h" #include "lac_log.h" #include "lac_pke_qat_comms.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_hooks.h" #include "lac_pke_utils.h" #include "lac_sync.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_ec.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_ec_nist_curves.h" /* SAL includes */ #include "sal_service_state.h" #define LAC_EC_NUM_STATS (sizeof(CpaCyEcStats64) / sizeof(Cpa64U)) #define LAC_ECDH_NUM_STATS (sizeof(CpaCyEcdhStats64) / sizeof(Cpa64U)) #define LAC_ECDSA_NUM_STATS (sizeof(CpaCyEcdsaStats64) / sizeof(Cpa64U)) #define LAC_ECSM2_NUM_STATS (sizeof(CpaCyEcsm2Stats64) / sizeof(Cpa64U)) #define LAC_EC_ALL_STATS_CLEAR(pCryptoService) \ do \ { \ Cpa32U i = 0; \ \ for (i = 0; i < LAC_EC_NUM_STATS; i++) \ { \ osalAtomicSet(0, &pCryptoService->pLacEcStatsArr[i]); \ } \ for (i = 0; i < LAC_ECDH_NUM_STATS; i++) \ { \ osalAtomicSet(0, &pCryptoService->pLacEcdhStatsArr[i]); \ } \ for (i = 0; i < LAC_ECDSA_NUM_STATS; i++) \ { \ osalAtomicSet(0, &pCryptoService->pLacEcdsaStatsArr[i]); \ } \ for (i = 0; i < LAC_ECSM2_NUM_STATS; i++) \ { \ osalAtomicSet(0, &pCryptoService->pLacEcsm2StatsArr[i]); \ } \ } while (0) /**< @ingroup Lac_Ec * macro to initialize all EC stats (stored in internal array of atomics) * assumes pCryptoService has already been validated */ /** *************************************************************************** * @ingroup Lac_Ec * ECC Initialisation function * ***************************************************************************/ CpaStatus LacEc_Init(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = NULL; CpaStatus status = CPA_STATUS_SUCCESS; pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pCryptoService->pLacEcStatsArr), LAC_EC_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { status = LAC_OS_MALLOC(&(pCryptoService->pLacEcdhStatsArr), LAC_ECDH_NUM_STATS * sizeof(OsalAtomic)); } if (CPA_STATUS_SUCCESS == status) { status = LAC_OS_MALLOC(&(pCryptoService->pLacEcdsaStatsArr), LAC_ECDSA_NUM_STATS * sizeof(OsalAtomic)); } if (CPA_STATUS_SUCCESS == status) { status = LAC_OS_MALLOC(&(pCryptoService->pLacEcsm2StatsArr), LAC_ECSM2_NUM_STATS * sizeof(OsalAtomic)); } /* initialize stats to zero */ if (CPA_STATUS_SUCCESS == status) { LAC_EC_ALL_STATS_CLEAR(pCryptoService); } return status; } void LacEc_StatsFree(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; if (NULL != pCryptoService->pLacEcStatsArr) { LAC_OS_FREE(pCryptoService->pLacEcStatsArr); } if (NULL != pCryptoService->pLacEcdhStatsArr) { LAC_OS_FREE(pCryptoService->pLacEcdhStatsArr); } if (NULL != pCryptoService->pLacEcdsaStatsArr) { LAC_OS_FREE(pCryptoService->pLacEcdsaStatsArr); } if (NULL != pCryptoService->pLacEcsm2StatsArr) { LAC_OS_FREE(pCryptoService->pLacEcsm2StatsArr); } } void LacEc_StatsReset(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_EC_ALL_STATS_CLEAR(pCryptoService); } /** *************************************************************************** * @ingroup Lac_Ec * Resolves and validates instanceHandle. ***************************************************************************/ CpaStatus LacEc_ValidateInstance(CpaInstanceHandle *pInstanceHandle) { if (CPA_INSTANCE_HANDLE_SINGLE == *pInstanceHandle) { *pInstanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } #ifdef ICP_PARAM_CHECK /* instance checks - if fail, no inc stats just return */ /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(*pInstanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(*pInstanceHandle); #endif /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(*pInstanceHandle); #ifdef ICP_PARAM_CHECK /* ensure this is a crypto or asym instance with pke enabled */ const Cpa32U instanceType = SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM; SAL_CHECK_INSTANCE_TYPE(*pInstanceHandle, instanceType); #endif return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ec * Ecc Stats Show function ***************************************************************************/ void LacEc_StatsShow(CpaInstanceHandle instanceHandle) { CpaCyEcStats64 ecStats = {0}; CpaCyEcdhStats64 ecdhStats = {0}; CpaCyEcdsaStats64 ecdsaStats = {0}; CpaCyEcsm2Stats64 ecsm2Stats = {0}; /* retrieve the stats */ (void)cpaCyEcQueryStats64(instanceHandle, &ecStats); (void)cpaCyEcdhQueryStats64(instanceHandle, &ecdhStats); (void)cpaCyEcdsaQueryStats64(instanceHandle, &ecdsaStats); (void)cpaCyEcsm2QueryStats64(instanceHandle, &ecsm2Stats); /* log the stats to the standard output */ /* engine info */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " ECDSA Stats " BORDER "\n" SEPARATOR); /* sign r requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECDSA Sign R Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign R Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign R Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign R Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign R Output Invalid: %16llu " BORDER "\n" SEPARATOR, ecdsaStats.numEcdsaSignRRequests, ecdsaStats.numEcdsaSignRRequestErrors, ecdsaStats.numEcdsaSignRCompleted, ecdsaStats.numEcdsaSignRCompletedErrors, ecdsaStats.numEcdsaSignRCompletedOutputInvalid); /* s sign requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECDSA Sign S Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign S Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign S Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign S Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign S Output Invalid: %16llu " BORDER "\n" SEPARATOR, ecdsaStats.numEcdsaSignSRequests, ecdsaStats.numEcdsaSignSRequestErrors, ecdsaStats.numEcdsaSignSCompleted, ecdsaStats.numEcdsaSignSCompletedErrors, ecdsaStats.numEcdsaSignSCompletedOutputInvalid); /* rs sign requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECDSA Sign RS Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Output Invalid: %16llu " BORDER "\n" SEPARATOR, ecdsaStats.numEcdsaSignRSRequests, ecdsaStats.numEcdsaSignRSRequestErrors, ecdsaStats.numEcdsaSignRSCompleted, ecdsaStats.numEcdsaSignRSCompletedErrors, ecdsaStats.numEcdsaSignRSCompletedOutputInvalid); /* verify requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECDSA Verify Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Verify Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Verify Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Verify Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Verify Output Invalid: %16llu " BORDER "\n" SEPARATOR, ecdsaStats.numEcdsaVerifyRequests, ecdsaStats.numEcdsaVerifyRequestErrors, ecdsaStats.numEcdsaVerifyCompleted, ecdsaStats.numEcdsaVerifyCompletedErrors, ecdsaStats.numEcdsaVerifyCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " EC Stats " BORDER "\n" SEPARATOR); /* ec point multiply requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " EC Pt Multiply Requests-Succ: %16llu " BORDER "\n" BORDER " EC Pt Multiply Request-Err: %16llu " BORDER "\n" BORDER " EC Pt Multiply Completed-Succ: %16llu " BORDER "\n" BORDER " EC Pt Multiply Completed-Err: %16llu " BORDER "\n" BORDER " EC Pt Multiply Output Invalid: %16llu " BORDER "\n" SEPARATOR, ecStats.numEcPointMultiplyRequests, ecStats.numEcPointMultiplyRequestErrors, ecStats.numEcPointMultiplyCompleted, ecStats.numEcPointMultiplyCompletedError, ecStats.numEcPointMultiplyCompletedOutputInvalid); /* ec point verify requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " EC Pt Verify Requests-Succ: %16llu " BORDER "\n" BORDER " EC Pt Verify Request-Err: %16llu " BORDER "\n" BORDER " EC Pt Verify Completed-Succ: %16llu " BORDER "\n" BORDER " EC Pt Verify Completed-Err: %16llu " BORDER "\n" BORDER " EC Pt Verify Output Invalid: %16llu " BORDER "\n" SEPARATOR, ecStats.numEcPointVerifyRequests, ecStats.numEcPointVerifyRequestErrors, ecStats.numEcPointVerifyCompleted, ecStats.numEcPointVerifyCompletedErrors, ecStats.numEcPointVerifyCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " ECDH Stats " BORDER "\n" SEPARATOR); /* ecdh point multiply requests */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECDH Pt Multiply Requests-Succ: %16llu " BORDER "\n" BORDER " ECDH Pt Multiply Request-Err: %16llu " BORDER "\n" BORDER " ECDH Pt Multiply Completed-Succ:%16llu " BORDER "\n" BORDER " ECDH Pt Multiply Completed-Err: %16llu " BORDER "\n" BORDER " ECDH Pt Multiply Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecdhStats.numEcdhPointMultiplyRequests, ecdhStats.numEcdhPointMultiplyRequestErrors, ecdhStats.numEcdhPointMultiplyCompleted, ecdhStats.numEcdhPointMultiplyCompletedError, ecdhStats.numEcdhRequestCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " ECSM2 Stats " BORDER "\n" SEPARATOR); /* ecsm2 status */ osalLog( OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Point Multiplication Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Point Multiplication Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Point Multiplication Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Point Multiplication Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Point Multiplication Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2PointMultiplyRequests, ecsm2Stats.numEcsm2PointMultiplyRequestErrors, ecsm2Stats.numEcsm2PointMultiplyCompleted, ecsm2Stats.numEcsm2PointMultiplyCompletedError, ecsm2Stats.numEcsm2PointMultiplyCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Generator Multiplication Requests-Succ: " "%16llu " BORDER "\n" BORDER " ECSM2 Generator Multiplication Request-Err: " "%16llu " BORDER "\n" BORDER " ECSM2 Generator Multiplication Completed-Succ: " "%16llu " BORDER "\n" BORDER " ECSM2 Generator Multiplication Completed-Err: " "%16llu " BORDER "\n" BORDER " ECSM2 Generator Multiplication Completed-Output Invalid:" "%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2GeneratorMultiplyRequests, ecsm2Stats.numEcsm2GeneratorMultiplyRequestErrors, ecsm2Stats.numEcsm2GeneratorMultiplyCompleted, ecsm2Stats.numEcsm2GeneratorMultiplyCompletedError, ecsm2Stats.numEcsm2GeneratorMultiplyCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Point Verify Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Point Verify Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Point Verify Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Point Verify Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Point Verify Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2PointVerifyRequests, ecsm2Stats.numEcsm2PointVerifyRequestErrors, ecsm2Stats.numEcsm2PointVerifyCompleted, ecsm2Stats.numEcsm2PointVerifyCompletedError, ecsm2Stats.numEcsm2PointVerifyCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Sign Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Sign Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Sign Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Sign Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Sign Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2SignRequests, ecsm2Stats.numEcsm2SignRequestErrors, ecsm2Stats.numEcsm2SignCompleted, ecsm2Stats.numEcsm2SignCompletedError, ecsm2Stats.numEcsm2SignCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Verify Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Verify Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Verify Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Verify Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Verify Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2VerifyRequests, ecsm2Stats.numEcsm2VerifyRequestErrors, ecsm2Stats.numEcsm2VerifyCompleted, ecsm2Stats.numEcsm2VerifyCompletedError, ecsm2Stats.numEcsm2VerifyCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Encrypt Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Encrypt Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Encrypt Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Encrypt Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Encrypt Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2EncryptRequests, ecsm2Stats.numEcsm2EncryptRequestErrors, ecsm2Stats.numEcsm2EncryptCompleted, ecsm2Stats.numEcsm2EncryptCompletedError, ecsm2Stats.numEcsm2EncryptCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Decrypt Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Decrypt Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Decrypt Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Decrypt Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Decrypt Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2DecryptRequests, ecsm2Stats.numEcsm2DecryptRequestErrors, ecsm2Stats.numEcsm2DecryptCompleted, ecsm2Stats.numEcsm2DecryptCompletedError, ecsm2Stats.numEcsm2DecryptCompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Key Exchange Phase1 Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase1 Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase1 Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase1 Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase1 Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2KeyExPhase1Requests, ecsm2Stats.numEcsm2KeyExPhase1RequestErrors, ecsm2Stats.numEcsm2KeyExPhase1Completed, ecsm2Stats.numEcsm2KeyExPhase1CompletedError, ecsm2Stats.numEcsm2KeyExPhase1CompletedOutputInvalid); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " ECSM2 Key Exchange Phase2 Requests-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase2 Request-Err: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase2 Completed-Succ: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase2 Completed-Err: %16llu " BORDER "\n" BORDER " ECSM2 Key Exchange Phase2 Completed-Output Invalid:%16llu " BORDER "\n" SEPARATOR, ecsm2Stats.numEcsm2KeyExPhase2Requests, ecsm2Stats.numEcsm2KeyExPhase2RequestErrors, ecsm2Stats.numEcsm2KeyExPhase2Completed, ecsm2Stats.numEcsm2KeyExPhase2CompletedError, ecsm2Stats.numEcsm2KeyExPhase2CompletedOutputInvalid); } void LacEc_CheckCurve4QWGF2(Cpa32U *pNumQWs, const CpaFlatBuffer *pQ, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, const CpaFlatBuffer *pR, const CpaFlatBuffer *pH) { Cpa32U bit_pos = 0; Cpa32U index = 0; size_t j = 0; CpaBoolean possible_curve = CPA_FALSE; CpaBoolean isZero = CPA_FALSE; /* Check modulus - Never NULL*/ LacPke_GetBitPos(pQ, &bit_pos, &index, &isZero); if (NIST_GF2_Q_163_BIT_POS == bit_pos) { for (j = 0; j < (pQ->dataLenInBytes - index); j++) { if (nist_gf2_163_q[j] != pQ->pData[j + index]) { break; } } if (j == (pQ->dataLenInBytes - index)) { possible_curve = CPA_TRUE; } } /* if(NIST_GF2_Q_163_BIT_POS == bit_pos) */ else { if (NIST_GF2_Q_233_BIT_POS == bit_pos) { for (j = 0; j < (pQ->dataLenInBytes - index); j++) { if (nist_gf2_233_q[j] != pQ->pData[j + index]) { break; } } if (j == (pQ->dataLenInBytes - index)) { possible_curve = CPA_TRUE; } } } /* else(NIST_GF2_Q_163_BIT_POS != bit_pos) */ if (CPA_TRUE != possible_curve) { /* Modulus not as required - cannot use L256 service */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } if (NIST_GF2_Q_163_BIT_POS == bit_pos) { /* Possibly K163 or B163 Curves */ /* Check coeff A - Never NULL */ LacPke_GetBitPos(pA, &bit_pos, &index, &isZero); /* Coeff A is expected to be 1 - therefore no need to check the value of A just check the isZero flag and its bit_pos */ if ((NIST_GF2_A_163_BIT_POS != bit_pos) || (CPA_TRUE == isZero)) { /* Coeff A not as required for K163 or B163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } /* Check cofactor - Can be NULL */ if (NULL != pH) { if (NULL != pH->pData) { LacPke_GetBitPos(pH, &bit_pos, &index, &isZero); if ((NIST_GF2_H_163_BIT_POS != bit_pos) || (nist_gf2_163_h[0] != pH->pData[index])) { /* Cofactor not as required for K163 or B163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* if(NULL != pH->pData) */ } /* if(NULL != pH) */ /* Check coeff B - Never NULL */ LacPke_GetBitPos(pB, &bit_pos, &index, &isZero); /* Coeff B for K163 is expected to be 1 - therefore no need to check value just check isZero and bit_pos */ if ((NIST_GF2_B_K163_BIT_POS == bit_pos) && (CPA_FALSE == isZero)) { /* Check Order - Can be NULL */ if (NULL != pR) { LacPke_GetBitPos(pR, &bit_pos, &index, &isZero); if (NIST_GF2_R_163_BIT_POS == bit_pos) { for (j = 0; j < (pR->dataLenInBytes - index); j++) { if (nist_koblitz_gf2_163_r[j] != pR->pData[j + index]) { break; } } if (j != (pR->dataLenInBytes - index)) { /* Order not as required for K163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* if(NIST_GF2_R_163_BIT_POS == bit_pos) */ else { /* Order not as required for K163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* if(NULL != pR) */ /* Found K163 curve - can use L256 service */ *(pNumQWs) = LAC_EC_SIZE_QW4_IN_BYTES; return; } /* if((NIST_GF2_B_K163_BIT_POS == bit_pos) && (CPA_FALSE ==isZero)) */ else { /* Check for B163 curve */ if (NIST_GF2_B_B163_BIT_POS == bit_pos) { for (j = 0; j < (pB->dataLenInBytes - index); j++) { if (nist_binary_gf2_163_b[j] != pB->pData[j + index]) { break; } } if (j != (pB->dataLenInBytes - index)) { /* Coeff B not as required for B163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } /* Check Order - Can be NULL */ if (NULL != pR) { LacPke_GetBitPos(pR, &bit_pos, &index, &isZero); if (NIST_GF2_R_163_BIT_POS == bit_pos) { for (j = 0; j < (pR->dataLenInBytes - index); j++) { if (nist_binary_gf2_163_r[j] != pR->pData[j + index]) { break; } } if (j != (pR->dataLenInBytes - index)) { /* Order not as required for B163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } else { /* Order not as required for B163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* if(NULL != pR) */ /* Found B163 curve - can use L256 service */ *(pNumQWs) = LAC_EC_SIZE_QW4_IN_BYTES; return; } /* if(NIST_GF2_B_B163_BIT_POS == bit_pos) */ else { /* Coeff B not as required for K163 or B163 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /*else((NIST_GF2_B_K163_BIT_POS != bit_pos)||(CPA_FALSE !=isZero))*/ } /* if(NIST_GF2_Q_163_BIT_POS == bit_pos) */ else { /* Possibly K233 or B233 Curves - pQ has been validated */ /* Check coeff A - Never NULL*/ LacPke_GetBitPos(pA, &bit_pos, &index, &isZero); if (CPA_TRUE == isZero) { /* coeff A = 0 - possibly K233 */ /* Check Cofactor - Can be NULL */ if (NULL != pH) { if (NULL != pH->pData) { LacPke_GetBitPos(pH, &bit_pos, &index, &isZero); if ((NIST_GF2_H_K233_BIT_POS != bit_pos) || (nist_koblitz_gf2_233_h[0] != pH->pData[index])) { /* Cofactor not as required for K233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } } /* if(NULL != pH) */ /* Check Coeff B */ LacPke_GetBitPos(pB, &bit_pos, &index, &isZero); /* Coeff B is expected to be 1 - therefore no need to check value just check isZero and bit_pos */ if ((NIST_GF2_B_K233_BIT_POS != bit_pos) || (CPA_TRUE == isZero)) { /* Coeff B not as required for K233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } /* Check R */ if (NULL != pR) { LacPke_GetBitPos(pR, &bit_pos, &index, &isZero); if (NIST_GF2_R_K233_BIT_POS == bit_pos) { for (j = 0; j < (pR->dataLenInBytes - index); j++) { if (nist_koblitz_gf2_233_r[j] != pR->pData[j + index]) { break; } } if (j != (pR->dataLenInBytes - index)) { /* Order not as required for K233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } else { /* Order not as required for K233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* if(NULL != pR) */ /* Found K233 curve - can use L256 service */ *(pNumQWs) = LAC_EC_SIZE_QW4_IN_BYTES; return; } /* if(CPA_TRUE == isZero) */ else { /* Check if coeff A = 1 */ if (NIST_GF2_A_233_BIT_POS == bit_pos) { /* Possibly B233 */ /* Check Cofactor - Can be NULL */ if (NULL != pH) { if (NULL != pH->pData) { LacPke_GetBitPos(pH, &bit_pos, &index, &isZero); if ((NIST_GF2_H_B233_BIT_POS != bit_pos) || (nist_binary_gf2_233_h[0] != pH->pData[index])) { /* Cofactor not as required for B233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } } /* if(NULL != pH)*/ /* Check Coeff B */ LacPke_GetBitPos(pB, &bit_pos, &index, &isZero); if (NIST_GF2_B_B233_BIT_POS == bit_pos) { for (j = 0; j < (pB->dataLenInBytes - index); j++) { if (nist_binary_gf2_233_b[j] != pB->pData[j + index]) { break; } } if (j != (pB->dataLenInBytes - index)) { /* Coeff B not as required for B233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* if(NIST_GF2_B_B233_BIT_POS == bit_pos) */ else { /* Coeff B not as required for B233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } /* Check R */ if (NULL != pR) { LacPke_GetBitPos(pR, &bit_pos, &index, &isZero); if (NIST_GF2_R_B233_BIT_POS == bit_pos) { for (j = 0; j < (pR->dataLenInBytes - index); j++) { if (nist_binary_gf2_233_r[j] != pR->pData[j + index]) { break; } } if (j != (pR->dataLenInBytes - index)) { /* Order not as required for B233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } else { /* Order not as required for B233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* if(NULL != pR) */ /* Found B233 curve - can use L256 service */ *(pNumQWs) = LAC_EC_SIZE_QW4_IN_BYTES; return; } /* if(NIST_GF2_A_233_BIT_POS == bit_pos) */ else { /* Coeff A not as required for K233 or B233 curve */ *(pNumQWs) = LAC_EC_SIZE_QW8_IN_BYTES; return; } } /* else(CPA_TRUE != isZero) */ } /* else(NIST_GF2_Q_163_BIT_POS != bit_pos) */ return; } CpaStatus LacEc_CheckCurve9QWGFP(const CpaFlatBuffer *pQ, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, const CpaFlatBuffer *pR, const CpaFlatBuffer *pH, const CpaFlatBuffer *pX, const CpaFlatBuffer *pY) { /* status invalid unless curve is found */ CpaStatus status = CPA_STATUS_INVALID_PARAM; Cpa32U bit_pos = 0; Cpa32U index = 0; size_t j = 0; CpaBoolean isZero = CPA_FALSE; /* Check modulus - Never NULL*/ LacPke_GetBitPos(pQ, &bit_pos, &index, &isZero); if (NIST_GFP_Q_521_BIT_POS != bit_pos) { /* Length of modulus not 521 */ LAC_INVALID_PARAM_LOG("Modulus not as expected for NIST P-521 curve"); return status; } else { /* Modulus correct length - check value */ for (j = 0; j < (pQ->dataLenInBytes - index); j++) { if (nist_p521_q[j] != pQ->pData[j + index]) { break; } } if (j != (pQ->dataLenInBytes - index)) { /* Modulus != 2^521-1 */ LAC_INVALID_PARAM_LOG("Modulus not as expected for NIST " "P-521 curve"); return status; } } /* Modulus as required for NIST GFP-521 curve - next check A coeff */ LacPke_GetBitPos(pA, &bit_pos, &index, &isZero); if (NIST_GFP_A_521_BIT_POS != bit_pos) { /* Length not correct for P-521 curve */ LAC_INVALID_PARAM_LOG("Coeff A not as expected for NIST P-521 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pA->dataLenInBytes - index); j++) { if (nist_p521_a[j] != pA->pData[j + index]) { break; } } if (j != (pA->dataLenInBytes - index)) { /* Value not as required for P_521 curve */ LAC_INVALID_PARAM_LOG("Coeff A not as expected for NIST " "P-521 curve"); return status; } } /* Modulus and A coeff as required - next check B coeff */ LacPke_GetBitPos(pB, &bit_pos, &index, &isZero); if (NIST_GFP_B_521_BIT_POS != bit_pos) { /* Length not correct for P-521 curve */ LAC_INVALID_PARAM_LOG("Coeff B not as expected for NIST P-521 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pB->dataLenInBytes - index); j++) { if (nist_p521_b[j] != pB->pData[j + index]) { break; } } if (j != (pB->dataLenInBytes - index)) { /* Value not as required for P-521 curve */ LAC_INVALID_PARAM_LOG("Coeff B not as expected for NIST " "P-521 curve"); return status; } } /* Modulus, A and B coeffs as required - next check Order */ if (NULL != pR) { LacPke_GetBitPos(pR, &bit_pos, &index, &isZero); if (NIST_GFP_R_521_BIT_POS != bit_pos) { /* Length not correct for P-521 curve */ LAC_INVALID_PARAM_LOG("Order not as expected for NIST " "P-521 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pR->dataLenInBytes - index); j++) { if (nist_p521_r[j] != pR->pData[j + index]) { break; } } if (j != (pR->dataLenInBytes - index)) { /* Value not as required for P-521 curve */ LAC_INVALID_PARAM_LOG("Order not as expected for NIST " "P-521 curve"); return status; } } } /* if(NULL !== pR) */ /* Modulus, A and B coeffs and Order as required - next check Cofactor */ if (NULL != pH) { if (NULL != pH->pData) { LacPke_GetBitPos(pH, &bit_pos, &index, &isZero); if ((NIST_GFP_H_521_BIT_POS != bit_pos) || (CPA_TRUE == isZero)) { /* Length not correct for P-521 curve */ LAC_INVALID_PARAM_LOG("Cofactor not as expected for NIST " "P-521 curve"); return status; } } } /* Curve as required - now check that x and y <= Modulus (2^521-1) */ if (NULL != pX) { LacPke_GetBitPos(pX, &bit_pos, &index, &isZero); if (bit_pos > NIST_GFP_Q_521_BIT_POS) { /* x greater than Modulus */ LAC_INVALID_PARAM_LOG("X coordinate not as expected for NIST " "P-521 curve"); return status; } } if (NULL != pY) { LacPke_GetBitPos(pY, &bit_pos, &index, &isZero); if (bit_pos > NIST_GFP_Q_521_BIT_POS) { /* y coeff greater than Modulus */ LAC_INVALID_PARAM_LOG("Y coordinate not as expected for NIST " "P-521 curve"); return status; } } /* Curve as required - return success */ return CPA_STATUS_SUCCESS; } CpaStatus LacEc_CheckCurve9QWGF2(const CpaFlatBuffer *pQ, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, const CpaFlatBuffer *pR, const CpaFlatBuffer *pH, const CpaFlatBuffer *pX, const CpaFlatBuffer *pY) { /* status invalid unless curve is found */ CpaStatus status = CPA_STATUS_INVALID_PARAM; Cpa32U bit_pos = 0; Cpa32U index = 0; size_t j = 0; CpaBoolean isZero = CPA_FALSE; /* Check modulus - Never NULL*/ LacPke_GetBitPos(pQ, &bit_pos, &index, &isZero); if (NIST_GF2_Q_571_BIT_POS != bit_pos) { /* Length of modulus not as required */ LAC_INVALID_PARAM_LOG("Modulus not as expected for NIST 571 curves"); return status; } else { /* Modulus correct length - check value */ for (j = 0; j < (pQ->dataLenInBytes - index); j++) { if (nist_gf2_571_q[j] != pQ->pData[j + index]) { break; } } if (j != (pQ->dataLenInBytes - index)) { /* Modulus value not as required */ LAC_INVALID_PARAM_LOG("Modulus not as expected for NIST " "571 curves"); return status; } } /* Modulus as required for NIST 571 curves - next check A coeff */ LacPke_GetBitPos(pA, &bit_pos, &index, &isZero); if (NIST_GF2_A_571_BIT_POS != bit_pos) { /* For K-571 A coeff = 0 and for B-571 A coeff = 1, therefore bit_pos = 1 is only valid cases */ /* Length of A coeff not as required for K-571 or B-571 */ LAC_INVALID_PARAM_LOG("Coeff A not as expected for NIST 571 curves"); return status; } if (CPA_TRUE == isZero) { /* Check for K-571 curve */ /* Check B Coeff */ LacPke_GetBitPos(pB, &bit_pos, &index, &isZero); if ((NIST_GF2_B_K571_BIT_POS != bit_pos) || (CPA_TRUE == isZero)) { /* Length not correct for K-571 curve */ LAC_INVALID_PARAM_LOG("Coeff B not as expected for NIST " "K571 curve"); return status; } /* Modulus, Coeff A and B as required for K-571 */ /* Check Order */ if (NULL != pR) { LacPke_GetBitPos(pR, &bit_pos, &index, &isZero); if (NIST_GF2_R_K571_BIT_POS != bit_pos) { /* Length not correct for K-571 curve */ LAC_INVALID_PARAM_LOG("Order not as expected for NIST " "K571 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pR->dataLenInBytes - index); j++) { if (nist_koblitz_gf2_571_r[j] != pR->pData[j + index]) { break; } } if (j != (pR->dataLenInBytes - index)) { /* Value not as required for K-571 curve */ LAC_INVALID_PARAM_LOG("Order not as expected for NIST " "K571 curve"); return status; } } } /* if(NULL = pR) */ /* Check Cofactor */ if (NULL != pH) { if (NULL != pH->pData) { LacPke_GetBitPos(pH, &bit_pos, &index, &isZero); if (NIST_GF2_H_K571_BIT_POS != bit_pos) { /* Length not correct for K-571 curve */ LAC_INVALID_PARAM_LOG("Cofactor not as expected for NIST " "K571 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pH->dataLenInBytes - index); j++) { if (nist_koblitz_gf2_571_h[j] != pH->pData[j + index]) { break; } } if (j != (pH->dataLenInBytes - index)) { /* Value not as required for K-571 curve */ LAC_INVALID_PARAM_LOG( "Cofactor not as expected for NIST" " K571 curve"); return status; } } } /* if(NULL != pH->pData) */ } /* if(NULL != pH) */ /* Found K-571 curve - now check degree of X and Y is required */ if (NULL != pX) { LacPke_GetBitPos(pX, &bit_pos, &index, &isZero); if (bit_pos >= NIST_GF2_Q_571_BIT_POS) { /* deg X should be less than deg modulus */ LAC_INVALID_PARAM_LOG("X coordinate not as expected for NIST " "K571 curve"); return status; } } if (NULL != pY) { LacPke_GetBitPos(pY, &bit_pos, &index, &isZero); if (bit_pos >= NIST_GF2_Q_571_BIT_POS) { /* deg Y should be less than deg modulus */ LAC_INVALID_PARAM_LOG("Y coordinate not as expected for NIST " "K571 curve"); return status; } } status = CPA_STATUS_SUCCESS; } /* if(CPA_TRUE==isZero) */ else { /* Check for B-571 curve */ /* Check B Coeff */ LacPke_GetBitPos(pB, &bit_pos, &index, &isZero); if (NIST_GF2_B_B571_BIT_POS != bit_pos) { /* Length not correct for B-571 curve */ LAC_INVALID_PARAM_LOG("Coeff B not as expected for NIST " "B571 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pB->dataLenInBytes - index); j++) { if (nist_binary_gf2_571_b[j] != pB->pData[j + index]) { break; } } if (j != (pB->dataLenInBytes - index)) { /* Value not as required for B-571 curve */ LAC_INVALID_PARAM_LOG("Coeff B not as expected for NIST " "B571 curve"); return status; } } /* Modulus, Coeff A and B as required for B-571 */ /* Check Order */ if (NULL != pR) { LacPke_GetBitPos(pR, &bit_pos, &index, &isZero); if (NIST_GF2_R_B571_BIT_POS != bit_pos) { /* Length not correct for B-571 curve */ LAC_INVALID_PARAM_LOG("Order not as expected for NIST " "B571 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pR->dataLenInBytes - index); j++) { if (nist_binary_gf2_571_r[j] != pR->pData[j + index]) { break; } } if (j != (pR->dataLenInBytes - index)) { /* Value not as required for B-571 curve */ LAC_INVALID_PARAM_LOG("Order not as expected for NIST " "B571 curve"); return status; } } } /* if(NULL != pR) */ /* Check Cofactor */ if (NULL != pH) { if (NULL != pH->pData) { LacPke_GetBitPos(pH, &bit_pos, &index, &isZero); if (NIST_GF2_H_B571_BIT_POS != bit_pos) { /* Length not correct for B-571 curve */ LAC_INVALID_PARAM_LOG("Cofactor not as expected for NIST " "B571 curve"); return status; } else { /* Valid length - check value */ for (j = 0; j < (pH->dataLenInBytes - index); j++) { if (nist_binary_gf2_571_h[j] != pH->pData[j + index]) { break; } } if (j != (pH->dataLenInBytes - index)) { /* Value not as required for B-571 curve */ LAC_INVALID_PARAM_LOG( "Cofactor not as expected for NIST" " B571 curve"); return status; } } } /* if(NULL != pH->pData) */ } /* if(NULL != pH) */ /* Found B-571 curve */ if (NULL != pX) { LacPke_GetBitPos(pX, &bit_pos, &index, &isZero); if (bit_pos >= NIST_GF2_Q_571_BIT_POS) { /* deg X should be less than deg modulus */ LAC_INVALID_PARAM_LOG("X coordinate not as expected for NIST " "B571 curve"); return status; } } if (NULL != pY) { LacPke_GetBitPos(pY, &bit_pos, &index, &isZero); if (bit_pos >= NIST_GF2_Q_571_BIT_POS) { /* deg Y should be less than deg modulus */ LAC_INVALID_PARAM_LOG("Y coordinate not as expected for NIST " "B571 curve"); return status; } } status = CPA_STATUS_SUCCESS; } /* else(CPA_TRUE != isZero) */ return status; } CpaStatus LacEc_GetRange(Cpa32U size, Cpa32U *pMax) { CpaStatus status = CPA_STATUS_SUCCESS; LAC_ASSERT_NOT_NULL(pMax); #ifndef QAT_LEGACY_ALGORITHMS if (LAC_EC_SIZE_QW4_IN_BYTES > size) { LAC_LOG("ECC algorithm is not supported for curve lengths less than " "256 bits\n"); return CPA_STATUS_UNSUPPORTED; } #endif if (LAC_EC_SIZE_QW4_IN_BYTES >= size) { size = LAC_EC_SIZE_QW4_IN_BYTES; } else if (LAC_EC_SIZE_QW8_IN_BYTES >= size) { size = LAC_EC_SIZE_QW8_IN_BYTES; } else if (LAC_EC_SIZE_QW9_IN_BYTES >= size) { size = LAC_EC_SIZE_QW9_IN_BYTES; } else { status = CPA_STATUS_INVALID_PARAM; } *pMax = size; return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_montedwds.c000066400000000000000000000760021503624047500326670ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * * @file lac_ec_montedwds.c * * @ingroup Lac_Ec_MontEdwds * * Elliptic Curve Montgomery and Edwards functions * * @lld_start * * @lld_overview * This file implements Elliptic Curve Montgomery and Edwards api functions. * @lld_dependencies * - \ref LacAsymCommonQatComms "PKE QAT Comms" : For creating and sending * messages to the QAT * - \ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_initialisation * On initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * ***************************************************************************/ /* **************************************************************************** * Include public/global header files **************************************************************************** */ /* API Includes */ #include "cpa.h" #include "cpa_cy_ec.h" #include "cpa_cy_im.h" /* QAT FW includes */ #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" /* Look Aside Includes */ #include "lac_common.h" #include "lac_mem_pools.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_ec.h" #include "lac_sal_types.h" #include "lac_sal.h" #include "lac_sync.h" #include "lac_sal_types_crypto.h" #include "sal_service_state.h" #define LAC_EC_MONTEDWDS_DATA_LEN_IN_BYTES 32 /* **************************************************************************** * Define static function definitions **************************************************************************** */ #ifdef ICP_PARAM_CHECK /** ***************************************************************************** * @ingroup LacEcMontEdwds * * @description * This function is used to perform basic checks on the * input parameters (eg., checks data buffers for NULL and 0 dataLen) * * @param[in] instanceHandle Instance handle * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[in] pMultiplyStatus Multiply status. * @param[in] pXk Pointer to xk flat buffer. * @param[in] pYk Pointer to yk flat buffer. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_INVALID_PARAM Invalid curve type * ****************************************************************************/ STATIC CpaStatus LacEcMontEdwds_PointMultiplyParamCheck( const CpaInstanceHandle instanceHandle, const CpaCyEcMontEdwdsPointMultiplyOpData *pOpData, const CpaBoolean *pMultiplyStatus, const CpaFlatBuffer *pXk, const CpaFlatBuffer *pYk) { Cpa32U dataLen = LAC_EC_MONTEDWDS_DATA_LEN_IN_BYTES; /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pMultiplyStatus); if (CPA_CY_EC_MONTEDWDS_CURVE448_TYPE == pOpData->curveType || CPA_CY_EC_MONTEDWDS_ED448_TYPE == pOpData->curveType) { dataLen = 2 * LAC_EC_MONTEDWDS_DATA_LEN_IN_BYTES; } switch (pOpData->curveType) { case CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE: case CPA_CY_EC_MONTEDWDS_CURVE448_TYPE: LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->k, CHECK_EQUALS, dataLen); LAC_CHECK_FLAT_BUFFER_PARAM(pXk, CHECK_EQUALS, dataLen); if (CPA_FALSE == pOpData->generator) LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->x, CHECK_EQUALS, dataLen); break; case CPA_CY_EC_MONTEDWDS_ED25519_TYPE: case CPA_CY_EC_MONTEDWDS_ED448_TYPE: LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->k, CHECK_EQUALS, dataLen); LAC_CHECK_FLAT_BUFFER_PARAM(pXk, CHECK_EQUALS, dataLen); LAC_CHECK_FLAT_BUFFER_PARAM(pYk, CHECK_EQUALS, dataLen); if (CPA_FALSE == pOpData->generator) { LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->x, CHECK_EQUALS, dataLen); LAC_CHECK_FLAT_BUFFER_PARAM(&pOpData->y, CHECK_EQUALS, dataLen); } break; default: return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif /** ***************************************************************************** * @ingroup LacEcMontEdwds * * @description * This function is used to perform the point multiply synchronous * * @param[in] instanceHandle Instance handle * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[in] pMultiplyStatus Multiply status. * @param[in] pXk Pointer to xk flat buffer. * @param[in] pYk Pointer to yk flat buffer. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_INVALID_PARAM Invalid curve type * ****************************************************************************/ STATIC CpaStatus LacEcMontEdwds_PointMultiplySyn( const CpaInstanceHandle instanceHandle, const CpaCyEcMontEdwdsPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_FAIL, wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS != status) { LAC_EC_STAT_INC(numEcPointMultiplyRequestErrors, pCryptoService); return status; } /* Call the asynchronous version of the function * with the generic synchronous callback function as a parameter. */ status = cpaCyEcMontEdwdsPointMultiply(instanceHandle, LacSync_GenDualFlatBufVerifyCb, pSyncCallbackData, pOpData, pMultiplyStatus, pXk, pYk); if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { LAC_EC_STAT_INC(numEcPointMultiplyCompletedError, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** ***************************************************************************** * @ingroup Lac_Ec_MontEdwds * Creates a PKE EC_MONTEDWDS request for the QAT. * * @description * This function takes the parameters for a PKE EC_ED QAT request, create * the request, and fills in the per request PKE fields. The request can * subsequently be sent to the QAT using LacPke_SendRequest(). In the * event of an error this function will tidy up any resources associated * with the request handle and set it to PKE_INVALID_HANDLE. * * @pre * The requests in the request pool have been initialised using * Lac_MemPoolInitAsymRequest(). * * @param[in,out] pRequestHandle Pointer to hold the handle for the request * created by this call. If the incoming value * is non-zero then the new request is appended * to the request (chain) already associated * with the handle. For a single request, or * the first request in a chain, the passed in * handle value must be zero * i.e. PKE_INVALID_HANDLE). * @param[in] functionalityId The PKE functionality id. * @param[in] pInArgList Pointer to the list of input params. This * should contain the client-provided flat * buffer pointers. Any entries in the list * which are not used must be set to 0. * @param[in] pOutArgList Pointer to the list of output params. This * should contain the client-provided flat * buffer pointers. Any entries in the list * which are not used must be set to 0. * @param[in] pPkeOpCbFunc This function is invoked when the response is * received from the QAT * @param[in] pCbData Callback data to be returned (by copy) * unchanged in the callback. * @param[in] instanceHandle InstanceHandle * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RESOURCE Resource error (e.g. failed memory allocation) * ******************************************************************************/ STATIC CpaStatus LacEcMontEdwds_CreateRequest(lac_pke_request_handle_t *pRequestHandle, Cpa32U functionalityId, icp_qat_fw_mmp_input_param_t *pInArgList, icp_qat_fw_mmp_output_param_t *pOutArgList, lac_pke_op_cb_func_t pPkeOpCbFunc, lac_pke_op_cb_data_t *pCbData, CpaInstanceHandle instanceHandle) { lac_pke_qat_req_data_t *pReqData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; CpaFlatBuffer *pParam = NULL; Cpa8U idx = 0; /* Allocate request data */ do { pReqData = Lac_MemPoolEntryAlloc(pCryptoService->lac_pke_req_pool); if (NULL == pReqData) { LAC_LOG_ERROR("Cannot get a mem pool entry"); return CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pReqData) { osalYield(); } } while ((void *)CPA_STATUS_RETRY == pReqData); /* Ensure correct request structure alignment */ LAC_ASSERT( LAC_ADDRESS_ALIGNED(&pReqData->u1.request, LAC_OPTIMAL_ALIGNMENT_SHIFT), "request structure not correctly aligned"); /* Ensure correct input argument list structure alignment */ LAC_ASSERT(LAC_ADDRESS_ALIGNED(&pReqData->u2.inArgList, LAC_OPTIMAL_ALIGNMENT_SHIFT), "inArgList structure not correctly aligned"); /* Ensure correct output argument list structure alignment */ LAC_ASSERT(LAC_ADDRESS_ALIGNED(&pReqData->u3.outArgList, LAC_OPTIMAL_ALIGNMENT_SHIFT), "outArgList structure not correctly aligned"); /* Clear the previous param info */ LAC_OS_BZERO(&pReqData->paramInfo, sizeof(pReqData->paramInfo)); /* Store request data pointer in the request handle */ *pRequestHandle = (lac_pke_request_handle_t)pReqData; /* Initialize next, head, and tail request data pointers */ pReqData->pNextReqData = NULL; pReqData->pHeadReqData = pReqData; /* Note: tail pointer is only valid in head request data struct */ pReqData->pTailReqData = pReqData; /* Populate request data structure */ pReqData->cbInfo.cbFunc = pPkeOpCbFunc; pReqData->cbInfo.cbData = *pCbData; pReqData->cbInfo.instanceHandle = instanceHandle; pReqData->pNextReqData = NULL; /* Set functionality ID */ pReqData->u1.request.pke_hdr.cd_pars.func_id = functionalityId; /* LWs 14 and 15 set to zero for this request for now */ pReqData->u1.request.next_req_adr = 0; /* Store correctly sized in parameters in QAT structure*/ for (idx = 0; 0 != pInArgList->flat_array[idx]; idx++) { /* Get user input data */ pParam = (CpaFlatBuffer *)(UARCH_INT)pInArgList->flat_array[idx]; LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( pCryptoService->generic_service_info, pReqData->u2.inArgList.flat_array[idx], pParam->pData); } /* Set number in inputs */ pReqData->u1.request.input_param_count = idx; /* Store correctly sized out parameters in QAT structure */ for (idx = 0; 0 != pOutArgList->flat_array[idx]; idx++) { /* Get user input data */ pParam = (CpaFlatBuffer *)(UARCH_INT)pOutArgList->flat_array[idx]; LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( pCryptoService->generic_service_info, pReqData->u3.outArgList.flat_array[idx], pParam->pData); } /* Set number in outputs */ pReqData->u1.request.output_param_count = idx; LAC_ASSERT( ((pReqData->u1.request.input_param_count + pReqData->u1.request.output_param_count) <= LAC_MAX_MMP_PARAMS), "number of input/output parameters exceeds maximum allowed"); return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup LacEcMontEdwds * Sends a single (unchained) PKE Ec_MontEdwds request to the QAT. * * @description * This function takes the parameters for a PKE Ec_MontEdwds QAT request, * creates the request, fills in the PKE fields and sends it to the QAT. * It does not block waiting for a response. Instead the callback function * is invoked when the response from the QAT has been processed. * * @param[in] functionalityId The PKE functionality id. * @param[in] pInArgList Pointer to the list of input params. This * should contain the client-provided flat buffer * pointers. Any entries in the list which are not * used must be set to 0. * @param[in] pOutArgList Pointer to the list of output params. This * should contain the client-provided flat buffer * pointers. Any entries in the list which are not * used must be set to 0. * @param[in] pPkeOpCbFunc This function is invoked when the response is * received from the QAT * @param[in] pCbData Callback data to be returned in the callback. * @param[in] instanceHandle InstanceHandle * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RESOURCE Resource error (e.g. failed memory allocation) * @retval CPA_STATUS_RETRY Ring full * *****************************************************************************/ CpaStatus LacEcMontEdwds_SendSingleRequest( Cpa32U functionalityId, icp_qat_fw_mmp_input_param_t *pInArgList, icp_qat_fw_mmp_output_param_t *pOutArgList, lac_pke_op_cb_func_t pPkeOpCbFunc, lac_pke_op_cb_data_t *pCbData, CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_FAIL; lac_pke_request_handle_t requestHandle = LAC_PKE_INVALID_HANDLE; /* Prepare the Ec_MontEdwds request */ status = LacEcMontEdwds_CreateRequest(&requestHandle, functionalityId, pInArgList, pOutArgList, pPkeOpCbFunc, pCbData, instanceHandle); /* Send the request */ if (CPA_STATUS_SUCCESS == status) { status = LacPke_SendRequest(&requestHandle, instanceHandle); } return status; } /** ****************************************************************************** * @ingroup LacEcMontEdwds * * @description * This function is used to perform point multiply internal callback * * @param[in] status Status to be checked * @param[in] pMultiplyStatus Multiply status. * @param[in] instanceHandle Instance handle * @param[in] pCbData Callback data * *****************************************************************************/ STATIC void LacEcMontEdwds_PointMultiplyCallback( CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcPointMultiplyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcPointMultiplyOpData *pOpData = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcPointMultiplyCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyEcPointMultiplyOpData *)pCbData->pClientOpData; pXk = pCbData->pOutputData1; pYk = pCbData->pOutputData2; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pXk); LAC_ASSERT_NOT_NULL(pYk); /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_EC_STAT_INC(numEcPointMultiplyCompleted, pCryptoService); } else { LAC_EC_STAT_INC(numEcPointMultiplyCompletedError, pCryptoService); } /* For Montgomery & Edwards curves multiplyStatus is always true, * so no effect on statistics. */ /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pXk, pYk); } /** ****************************************************************************** * @ingroup LacEcMontEdwds * Map user data for ec curve to QAT. * * @description * This function takes the parameters for a PKE Ec_MontEdwds QAT request, * creates the request, fills in the PKE fields and sends it to the QAT. * It does not block waiting for a response. Instead the callback function * is invoked when the response from the QAT has been processed. * * @param[in] pXk Pointer to xk flat buffer. * @param[in] pYk Pointer to yk flat buffer. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[in] pIn Pointer to icp_qat_fw_mmp_input_param_t * @param[in] pOut Pointer to icp_qat_fw_mmp_output_param_t * @param[out] functionalityId The PKE functionality id. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_INVALID_PARAM Invalid curve type * *****************************************************************************/ STATIC CpaStatus LacEcMontEdwds_MapEcCruvesDataToQat( CpaFlatBuffer *pXk, CpaFlatBuffer *pYk, const CpaCyEcMontEdwdsPointMultiplyOpData *pOpData, icp_qat_fw_mmp_input_param_t *pIn, icp_qat_fw_mmp_output_param_t *pOut, Cpa32U *functionID) { switch (pOpData->curveType) { case CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE: if (pOpData->generator) { LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->generator_multiplication_c25519.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->generator_multiplication_c25519.xr, pXk); *functionID = GENERATOR_MULTIPLICATION_C25519; } else { LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->point_multiplication_c25519.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->point_multiplication_c25519.xp, &pOpData->x); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->point_multiplication_c25519.xr, pXk); *functionID = POINT_MULTIPLICATION_C25519; } break; case CPA_CY_EC_MONTEDWDS_ED25519_TYPE: if (pOpData->generator) { LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->generator_multiplication_ed25519.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->generator_multiplication_ed25519.xr, pXk); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->generator_multiplication_ed25519.yr, pYk); *functionID = GENERATOR_MULTIPLICATION_ED25519; } else { LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->point_multiplication_ed25519.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->point_multiplication_ed25519.xp, &pOpData->x); LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->point_multiplication_ed25519.yp, &pOpData->y); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->point_multiplication_ed25519.xr, pXk); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->point_multiplication_ed25519.yr, pYk); *functionID = POINT_MULTIPLICATION_ED25519; } break; case CPA_CY_EC_MONTEDWDS_CURVE448_TYPE: if (pOpData->generator) { LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->generator_multiplication_c448.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->generator_multiplication_c448.xr, pXk); *functionID = GENERATOR_MULTIPLICATION_C448; } else { LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->point_multiplication_c448.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->point_multiplication_c448.xp, &pOpData->x); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->point_multiplication_c448.xr, pXk); *functionID = POINT_MULTIPLICATION_C448; } break; case CPA_CY_EC_MONTEDWDS_ED448_TYPE: if (pOpData->generator) { LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->generator_multiplication_ed448.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->generator_multiplication_ed448.xr, pXk); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->generator_multiplication_ed448.yr, pYk); *functionID = GENERATOR_MULTIPLICATION_ED448; } else { LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->point_multiplication_ed448.k, &pOpData->k); LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->point_multiplication_ed448.xp, &pOpData->x); LAC_MEM_SHARED_WRITE_FROM_PTR( pIn->point_multiplication_ed448.yp, &pOpData->y); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->point_multiplication_ed448.xr, pXk); LAC_MEM_SHARED_WRITE_FROM_PTR( pOut->point_multiplication_ed448.yr, pYk); *functionID = POINT_MULTIPLICATION_ED448; } break; default: { LAC_LOG_ERROR("Invalid Curve Type"); return CPA_STATUS_INVALID_PARAM; } } return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup LacEc * Perform EC Point Multiplication on an Edwards or Montgomery curve as * defined in RFC#7748. * * @description * This function performs Elliptic Curve Point Multiplication as per * RFC#7748 * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to * a NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pMultiplyStatus In synchronous mode, the multiply output is * valid (CPA_TRUE) or the output is invalid * (CPA_FALSE). * @param[out] pXk Pointer to xk flat buffer. * @param[out] pYk Pointer to yk flat buffer. * *****************************************************************************/ CpaStatus cpaCyEcMontEdwdsPointMultiply( const CpaInstanceHandle instanceHandle_in, const CpaCyEcPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcMontEdwdsPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle instanceHandle = NULL; sal_crypto_service_t *pCryptoService = NULL; Cpa32U functionID = 0; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; /* Populate callback data */ lac_pke_op_cb_data_t cbData = {.pClientCb = pCb, .pCallbackTag = pCallbackTag, .pClientOpData = pOpData, .pOpaqueData = NULL, .pOutputData1 = pXk, .pOutputData2 = pYk}; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* Check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* Ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* Ensure this is a crypto instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecEdMont); /* Check if the API has been called in synchronous mode */ if (NULL == pCb) { /* Call synchronous mode function */ status = LacEcMontEdwds_PointMultiplySyn( instanceHandle, pOpData, pMultiplyStatus, pXk, pYk); #ifdef ICP_TRACE LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "%d, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (NULL == pMultiplyStatus) ? 0 : *pMultiplyStatus, (LAC_ARCH_UINT)pXk, (LAC_ARCH_UINT)pYk); #endif return status; } pCryptoService = (sal_crypto_service_t *)instanceHandle; #ifdef ICP_PARAM_CHECK /* Basic NULL Param Checking */ status = LacEcMontEdwds_PointMultiplyParamCheck( instanceHandle, pOpData, pMultiplyStatus, pXk, pYk); if (CPA_STATUS_SUCCESS != status) { LAC_EC_STAT_INC(numEcPointMultiplyRequestErrors, pCryptoService); return status; } #endif /* Zero the output buffers */ osalMemSet(pXk->pData, 0, pXk->dataLenInBytes); if (CPA_CY_EC_MONTEDWDS_ED25519_TYPE == pOpData->curveType || CPA_CY_EC_MONTEDWDS_ED448_TYPE == pOpData->curveType) { osalMemSet(pYk->pData, 0, pYk->dataLenInBytes); } status = LacEcMontEdwds_MapEcCruvesDataToQat( pXk, pYk, pOpData, &in, &out, &functionID); if (CPA_STATUS_SUCCESS != status) { LAC_EC_STAT_INC(numEcPointMultiplyRequestErrors, pCryptoService); return status; } /* Send the PKE request to the QAT */ status = LacEcMontEdwds_SendSingleRequest(functionID, &in, &out, LacEcMontEdwds_PointMultiplyCallback, &cbData, instanceHandle); /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_EC_STAT_INC(numEcPointMultiplyRequests, pCryptoService); } else { LAC_EC_STAT_INC(numEcPointMultiplyRequestErrors, pCryptoService); } return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ec_nist_curves.c000066400000000000000000000343331503624047500332300ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * @file lac_ec_nist_curves.c * * @ingroup Lac_Ec * * Definitions for the following NIST recommended elliptic curves: * - PRIME 256 (P256) * - PRIME 384 (P384) * - PRIME 521 (P521) * - KOBLITZ 163 (K163) * - BINARY 163 (B163) * - KOBLITZ 233 (K233) * - BINARY 233 (B233) * - KOBLITZ 571 (K571) * - BINARY 571 (B571) * *****************************************************************************/ #include "lac_ec_nist_curves.h" /*********** NIST PRIME 256 CURVE ****************/ Cpa8U nist_p256_p[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; Cpa8U nist_p256_a[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc }; Cpa8U nist_p256_b[] = { 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b }; Cpa8U nist_p256_n[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51 }; Cpa8U nist_p256_h[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; Cpa8U nist_p256_gX[] = { 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96 }; Cpa8U nist_p256_gY[] = { 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 }; /*********** NIST PRIME 384 CURVE ****************/ Cpa8U nist_p384_p[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }; Cpa8U nist_p384_a[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc }; Cpa8U nist_p384_b[] = { 0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b, 0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef }; Cpa8U nist_p384_n[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73 }; Cpa8U nist_p384_h[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; Cpa8U nist_p384_gX[] = { 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7 }; Cpa8U nist_p384_gY[] = { 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f }; /*********** NIST PRIME 521 CURVE ****************/ Cpa8U nist_p521_q[] = { 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; Cpa8U nist_p521_a[] = { 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc }; Cpa8U nist_p521_b[] = { 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x9, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, 0xbf, 0x7, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x0 }; Cpa8U nist_p521_r[] = { 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x1, 0x48, 0xf7, 0x9, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x9 }; /*********** NIST 163 KOBLITZ AND BINARY CURVES ****************/ const Cpa8U nist_gf2_163_q[] = {0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc9}; const Cpa8U nist_gf2_163_a[] = {0x1}; const Cpa8U nist_gf2_163_h[] = {0x2}; /*********** NIST 163 KOBLITZ CURVE ****************/ const Cpa8U nist_koblitz_gf2_163_b[] = {0x1}; const Cpa8U nist_koblitz_gf2_163_r[] = { 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x8, 0xa2, 0xe0, 0xcc, 0xd, 0x99, 0xf8, 0xa5, 0xef}; /*********** NIST 163 BINARY CURVE ****************/ const Cpa8U nist_binary_gf2_163_b[] = { 0x2, 0xa, 0x60, 0x19, 0x7, 0xb8, 0xc9, 0x53, 0xca, 0x14, 0x81, 0xeb, 0x10, 0x51, 0x2f, 0x78, 0x74, 0x4a, 0x32, 0x5, 0xfd}; const Cpa8U nist_binary_gf2_163_r[] = {0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x92, 0xfe, 0x77, 0xe7, 0xc, 0x12, 0xa4, 0x23, 0x4c, 0x33}; /*********** NIST 233 KOBLITZ AND BINARY CURVES ****************/ const Cpa8U nist_gf2_233_q[] = { 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}; /*********** NIST 233 KOBLITZ CURVE ****************/ const Cpa8U nist_koblitz_gf2_233_h[] = {0x4}; const Cpa8U nist_koblitz_gf2_233_a[] = {0x0}; const Cpa8U nist_koblitz_gf2_233_b[] = {0x1}; const Cpa8U nist_koblitz_gf2_233_r[] = { 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x9d, 0x5b, 0xb9, 0x15, 0xbc, 0xd4, 0x6e, 0xfb, 0x1a, 0xd5, 0xf1, 0x73, 0xab, 0xdf}; /*********** NIST 233 BINARY CURVE ****************/ const Cpa8U nist_binary_gf2_233_h[] = {0x2}; const Cpa8U nist_binary_gf2_233_a[] = {0x1}; const Cpa8U nist_binary_gf2_233_b[] = { 0x66, 0x64, 0x7e, 0xde, 0x6c, 0x33, 0x2c, 0x7f, 0x8c, 0x9, 0x23, 0xbb, 0x58, 0x21, 0x3b, 0x33, 0x3b, 0x20, 0xe9, 0xce, 0x42, 0x81, 0xfe, 0x11, 0x5f, 0x7d, 0x8f, 0x90, 0xad}; const Cpa8U nist_binary_gf2_233_r[] = { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0xe9, 0x74, 0xe7, 0x2f, 0x8a, 0x69, 0x22, 0x3, 0x1d, 0x26, 0x3, 0xcf, 0xe0, 0xd7}; /*********** NIST 571 KOBLITZ AND BINARY CURVES ****************/ const Cpa8U nist_gf2_571_q[] = { 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x25}; /*********** NIST 571 KOBLITZ CURVE ****************/ const Cpa8U nist_koblitz_gf2_571_h[] = {0x4}; const Cpa8U nist_koblitz_gf2_571_r[] = { 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x13, 0x18, 0x50, 0xe1, 0xf1, 0x9a, 0x63, 0xe4, 0xb3, 0x91, 0xa8, 0xdb, 0x91, 0x7f, 0x41, 0x38, 0xb6, 0x30, 0xd8, 0x4b, 0xe5, 0xd6, 0x39, 0x38, 0x1e, 0x91, 0xde, 0xb4, 0x5c, 0xfe, 0x77, 0x8f, 0x63, 0x7c, 0x10, 0x1}; /*********** NIST 571 BINARY CURVE ****************/ const Cpa8U nist_binary_gf2_571_b[] = { 0x2, 0xf4, 0xe, 0x7e, 0x22, 0x21, 0xf2, 0x95, 0xde, 0x29, 0x71, 0x17, 0xb7, 0xf3, 0xd6, 0x2f, 0x5c, 0x6a, 0x97, 0xff, 0xcb, 0x8c, 0xef, 0xf1, 0xcd, 0x6b, 0xa8, 0xce, 0x4a, 0x9a, 0x18, 0xad, 0x84, 0xff, 0xab, 0xbd, 0x8e, 0xfa, 0x59, 0x33, 0x2b, 0xe7, 0xad, 0x67, 0x56, 0xa6, 0x6e, 0x29, 0x4a, 0xfd, 0x18, 0x5a, 0x78, 0xff, 0x12, 0xaa, 0x52, 0xe, 0x4d, 0xe7, 0x39, 0xba, 0xca, 0xc, 0x7f, 0xfe, 0xff, 0x7f, 0x29, 0x55, 0x72, 0x7a}; const Cpa8U nist_binary_gf2_571_h[] = {0x2}; const Cpa8U nist_binary_gf2_571_r[] = { 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x61, 0xce, 0x18, 0xff, 0x55, 0x98, 0x73, 0x8, 0x5, 0x9b, 0x18, 0x68, 0x23, 0x85, 0x1e, 0xc7, 0xdd, 0x9c, 0xa1, 0x16, 0x1d, 0xe9, 0x3d, 0x51, 0x74, 0xd6, 0x6e, 0x83, 0x82, 0xe9, 0xbb, 0x2f, 0xe8, 0x4e, 0x47}; qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecdh.c000066400000000000000000001124531503624047500311200ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * * @file lac_ecdh.c * * @ingroup Lac_Ec * * Elliptic Curve Diffie Hellman functions * * @lld_start * * @lld_overview * This file implements the Elliptic Curve Diffie-Hellman apis. * @lld_dependencies * - \ref LacAsymCommonQatComms "PKE QAT Comms" : For creating and sending * messages to the QAT * - \ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_initialisation * On initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * ***************************************************************************/ /* **************************************************************************** * Include public/global header files **************************************************************************** */ /* API Includes */ #include "cpa.h" #include "cpa_cy_ecdh.h" /* OSAL Includes */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* Include QAT files */ #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" #include "icp_qat_fw_la.h" /* Look Aside Includes */ #include "lac_log.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_sync.h" #include "lac_ec.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "sal_statistics.h" /* ******************************************************************************** * Global Variables ******************************************************************************** */ /**< number of 'in' arguments in the arguments size list for point verify */ #define LAC_ECDH_POINT_VERIFY_NUM_IN_ARGS 5 /**< number of 'in' arguments in the arguments size list for point multiply */ #define LAC_ECDH_POINT_MULTIPLY_NUM_IN_ARGS 7 /**< number of 'out' arguments in the arguments size list for point multiply */ #define LAC_ECDH_POINT_MULTIPLY_NUM_OUT_ARGS 2 /**< number of ECDH statistics */ #define LAC_ECDH_NUM_STATS (sizeof(CpaCyEcdhStats64) / sizeof(Cpa64U)) #ifndef DISABLE_STATS #define LAC_ECDH_STAT_INC(statistic, pCryptoService) \ do \ { \ if (CPA_TRUE == \ pCryptoService->generic_service_info.stats->bEccStatsEnabled) \ { \ osalAtomicInc( \ &pCryptoService->pLacEcdhStatsArr[offsetof(CpaCyEcdhStats64, \ statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) /**< @ingroup Lac_Ecdh * macro to increment a ECDH stat (derives offset into array of atomics) */ #else #define LAC_ECDH_STAT_INC(statistic, pCryptoService) \ do \ { \ } while (0) #endif #define LAC_ECDH_STATS_GET(ecdhStats, pCryptoService) \ do \ { \ Cpa32U i = 0; \ \ for (i = 0; i < LAC_ECDH_NUM_STATS; i++) \ { \ ((Cpa64U *)&(ecdhStats))[i] = \ osalAtomicGet(&pCryptoService->pLacEcdhStatsArr[i]); \ } \ } while (0) /**< @ingroup Lac_Ecdh * macro to collect a ECDH stat in sample period of performance counters */ /**< @ingroup Lac_Ecdh * macro to get all ECDH stats (from internal array of atomics) */ #define LacEcdhPointMultiplyOpDataWrite(in, out, pOpData, pXk, pYk) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.xg, &pOpData->xg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.yg, &pOpData->yg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.h, &pOpData->h); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.q, &pOpData->q); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.a, &pOpData->a); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.b, &pOpData->b); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.k, &pOpData->k); \ \ /* populate output parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.xk, pXk); \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.yk, pYk); \ } while (0); /**< @ingroup Lac_Ecdh * macro to write in/out parameters for the ECDH Point Multiply operation*/ #define LacEcdhPointVerifyOpDataWrite(in, pOpData) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.xq, &pOpData->xg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.yq, &pOpData->yg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.q, &pOpData->q); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.a, &pOpData->a); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.b, &pOpData->b); \ } while (0); /**< @ingroup Lac_Ecdh * macro to write in parameters for the Point Verify operation */ /* **************************************************************************** * Define static function definitions **************************************************************************** */ /** *************************************************************************** * @ingroup Lac_Ecdh * return the min size in bytes of biggest number in flat buffer * in CpaCyEcdhPointMultiplyOpData structure * * @description * return the size of the biggest number in * CpaCyEcdhPointMultiplyOpData. * * @param[in] pOpData Pointer to a CpaCyEcdhPointMultiplyOpData structure * * @retval max the size of the biggest number * ***************************************************************************/ STATIC Cpa32U LacEcdh_PointMultiplyOpDataSizeGetMax( const CpaCyEcdhPointMultiplyOpData *pOpData) { Cpa32U max = 0; /* need to find max size in bytes of number in input buffers .. */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->h)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->q)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->a)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->b)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); return max; } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ecdh * ECDH Point Multiply function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcdh_PointMultiplyBasicParamCheck( const CpaInstanceHandle instanceHandle, const CpaCyEcdhPointMultiplyOpData *pOpData, const CpaBoolean *pMultiplyStatus, const CpaFlatBuffer *pXk, const CpaFlatBuffer *pYk) { /* check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pMultiplyStatus); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LAC_CHECK_NULL_PARAM(pOpData->a.pData); LAC_CHECK_SIZE(&(pOpData->a), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->b.pData); LAC_CHECK_SIZE(&(pOpData->b), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->q.pData); LAC_CHECK_SIZE(&(pOpData->q), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xg.pData); LAC_CHECK_SIZE(&(pOpData->xg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yg.pData); LAC_CHECK_SIZE(&(pOpData->yg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pXk); LAC_CHECK_NULL_PARAM(pYk); LAC_CHECK_NULL_PARAM(pXk->pData); LAC_CHECK_SIZE(pXk, CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pYk->pData); LAC_CHECK_SIZE(pYk, CHECK_NONE, 0); /* Check Cofactor - pData of FlatBuffer can be NULL if dataLenInBytes=0 */ LAC_CHECK_NULL_PARAM(&pOpData->h); if ((NULL == pOpData->h.pData) && (0 != pOpData->h.dataLenInBytes)) { LAC_INVALID_PARAM_LOG("pOpData->h.pData is NULL and " "pOpData->h.dataLenInBytes !=0"); return CPA_STATUS_INVALID_PARAM; } if (NULL != pOpData->h.pData) { LAC_CHECK_SIZE(&(pOpData->h), CHECK_NONE, 0); } if (CPA_CY_EC_FIELD_TYPE_PRIME != pOpData->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pOpData->fieldType) { return CPA_STATUS_INVALID_PARAM; } /*Check that q is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->q)); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Ecdh * ECDH Point Multiply synchronous function ***************************************************************************/ STATIC CpaStatus LacEcdh_PointMultiplySyn(const CpaInstanceHandle instanceHandle, const CpaCyEcdhPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the generic synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyEcdhPointMultiply(instanceHandle, LacSync_GenDualFlatBufVerifyCb, pSyncCallbackData, pOpData, pMultiplyStatus, pXk, pYk); } else { LAC_ECDH_STAT_INC(numEcdhPointMultiplyRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { LAC_ECDH_STAT_INC(numEcdhPointMultiplyCompletedError, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ecdh * ECDH Point Multiply internal callback ***************************************************************************/ STATIC void LacEcdh_PointMultiplyCallback(CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcdhPointMultiplyCbFunc pCb = NULL; CpaCyEcdhPointMultiplyOpData *pOpData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif void *pCallbackTag = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcdhPointMultiplyCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyEcdhPointMultiplyOpData *)pCbData->pClientOpData; pXk = pCbData->pOutputData1; pYk = pCbData->pOutputData2; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pXk); LAC_ASSERT_NOT_NULL(pYk); /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDH_STAT_INC(numEcdhPointMultiplyCompleted, pCryptoService); } else { LAC_ECDH_STAT_INC(numEcdhPointMultiplyCompletedError, pCryptoService); } /* check for exception */ if ((CPA_FALSE == multiplyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECDH_STAT_INC(numEcdhRequestCompletedOutputInvalid, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pXk, pYk); } /** *************************************************************************** * @ingroup Lac_Ecdh * ***************************************************************************/ CpaStatus cpaCyEcdhPointMultiply(const CpaInstanceHandle instanceHandle_in, const CpaCyEcdhPointMultiplyCbFunc pCb, void *pCallbackTag, const CpaCyEcdhPointMultiplyOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U dataOperationSizeBytes = 0; CpaInstanceHandle instanceHandle = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif #ifdef ICP_PARAM_CHECK Cpa32U bit_pos_k = 0, bit_pos_h = 0, bit_pos_q = 0; Cpa32U temp = 0; Cpa32U maxModLen = 0; CpaBoolean isZero = CPA_FALSE; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* instance checks - if fail, no inc stats just return */ /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* ensure LAC is initialised - return error if not */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Ensure ecdh capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecdh); /* Check if the API has been called in synchronous mode */ if (NULL == pCb) { #ifdef ICP_TRACE #ifdef ICP_PARAM_CHECK /* Check for valid pointers */ LAC_CHECK_NULL_PARAM(pMultiplyStatus); #endif status = LacEcdh_PointMultiplySyn( instanceHandle, pOpData, pMultiplyStatus, pXk, pYk); LAC_LOG7("Called with params (0x%x, 0x%x, 0x%x, 0x%x, " "%d, 0x%x, 0x%x)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, *pMultiplyStatus, (LAC_ARCH_UINT)pXk, (LAC_ARCH_UINT)pYk); return status; #else /* Call synchronous mode function */ return LacEcdh_PointMultiplySyn( instanceHandle, pOpData, pMultiplyStatus, pXk, pYk); #endif } #ifdef ICP_PARAM_CHECK /* Basic Param Checking - NULL params, buffer lengths etc. */ status = LacEcdh_PointMultiplyBasicParamCheck( instanceHandle, pOpData, pMultiplyStatus, pXk, pYk); /* Check that output buffers are big enough */ if (CPA_STATUS_SUCCESS == status) { maxModLen = LacPke_GetMinBytes(&(pOpData->q)); if ((pXk->dataLenInBytes < maxModLen) || (pYk->dataLenInBytes < maxModLen)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { #endif /* Determine size */ status = LacEc_GetRange(LacEcdh_PointMultiplyOpDataSizeGetMax(pOpData), &dataOperationSizeBytes); #ifdef ICP_PARAM_CHECK } #endif if (CPA_STATUS_SUCCESS == status) { if ((LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes) && (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType)) { /* Check if it is a NIST curve if not use 8QW */ LacEc_CheckCurve4QWGF2(&dataOperationSizeBytes, &(pOpData->q), &(pOpData->a), &(pOpData->b), NULL, &(pOpData->h)); } } #ifdef ICP_PARAM_CHECK if ((CPA_STATUS_SUCCESS == status) && (LAC_EC_SIZE_QW9_IN_BYTES == dataOperationSizeBytes)) { /* 9QW checks */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* Check if it is a NIST curve if not inval param */ /* Also checks that xG and yG are less than 2^521 */ status = LacEc_CheckCurve9QWGFP(&(pOpData->q), &(pOpData->a), &(pOpData->b), NULL, &(pOpData->h), &(pOpData->xg), &(pOpData->yg)); } else { /*Check if it is a NIST curve if not inval param */ /* Also checks that deg of xG and yG are less than deg q */ status = LacEc_CheckCurve9QWGF2(&(pOpData->q), &(pOpData->a), &(pOpData->b), NULL, &(pOpData->h), &(pOpData->xg), &(pOpData->yg)); } } if (CPA_STATUS_SUCCESS == status) { /* Check size of h*k result */ /* log2(h*k) = log2(h) +log2(k) */ /* highest bit position of (h*k) = floor[log2(h*k)] */ /* max(floor[log2(h*k)]) = floor[log2(h)] +floor[log2(k)] + 1 */ /* for h>1 and k>1, else if h=1 or k=1 check is already done */ /* by earlier buffer checks */ LacPke_GetBitPos(&(pOpData->k), &bit_pos_k, &temp, &isZero); if (NULL == pOpData->h.pData) { bit_pos_h = 0; } else { LacPke_GetBitPos(&(pOpData->h), &bit_pos_h, &temp, &isZero); } if ((bit_pos_h > 0) && (bit_pos_k > 0)) { /* So h>1 and k>1 so we need to check i floor[log2(h)] +floor[log2(k)] + 1 */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* In GFP case h*k should fit in dataOperationSizeBytes */ if ((LAC_BYTES_TO_BITS(dataOperationSizeBytes) - 1) < (bit_pos_k + bit_pos_h + 1)) { if (dataOperationSizeBytes != LAC_EC_SIZE_QW4_IN_BYTES) { /* In 8QW case invalid param (similarly for 9QW but code won't get this far */ LAC_INVALID_PARAM_LOG("log2(k)+log2(h) is NOT <512"); status = CPA_STATUS_INVALID_PARAM; } else { /* Use 8QW service instead */ dataOperationSizeBytes = LAC_EC_SIZE_QW8_IN_BYTES; } } } else { /* In GF2 9QW and 4QW special cases h has already been checked (and is known by MMP) and the size of k has already been checked in getRange function so just need to check 8QW case */ if (LAC_EC_SIZE_QW8_IN_BYTES == dataOperationSizeBytes) { /* For 8QW h*k should fit in 9QW */ if ((LAC_BYTES_TO_BITS(LAC_EC_SIZE_QW9_IN_BYTES) - 1) < (bit_pos_k + bit_pos_h + 1)) { LAC_INVALID_PARAM_LOG("log2(k)+log2(h) is NOT <576"); status = CPA_STATUS_INVALID_PARAM; } } } } } if (CPA_STATUS_SUCCESS == status) { /* Ensure that h!=0 */ /* This is invalid for all secure curves */ /* pH=NULL is sent to PKE as h=0 which is understood by MMP program as h=1 as required - therefore need to eliminate invalid h=0 case here */ if (NULL != pOpData->h.pData) { if (0 == LacPke_CompareZero(&(pOpData->h), 0)) { LAC_INVALID_PARAM_LOG("Cofactor == 0"); status = CPA_STATUS_INVALID_PARAM; } } } if (CPA_STATUS_SUCCESS == status) { /* Check that q>3 for GFP (i.e. highest bit position needs to be greater than 1) or that deg(q)>2 for GF2 (i.e. highest bit position needs to be greater than 2) */ LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); if (((CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType) && (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GF2)) || ((CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) && (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GFP))) { LAC_INVALID_PARAM_LOG("q is not as required - too small"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { icp_qat_fw_mmp_input_param_t inPointVerify = {.flat_array = {0}}; icp_qat_fw_mmp_input_param_t inPointMultiply = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outPointVerify = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outPointMultiply = {.flat_array = {0}}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeListPointVerify[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U inArgSizeListPointMultiply[LAC_MAX_MMP_INPUT_PARAMS] = {0}; /*Cpa32U outArgSizeListMultiply[LAC_MAX_MMP_OUTPUT_PARAMS] = {0};*/ CpaBoolean internalMemInListVerify[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE}; CpaBoolean internalMemInListMultiply[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE}; CpaBoolean internalMemOutListMultiply[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; Cpa32U functionIdPointVerify = 0; Cpa32U functionIdPointMultiply = 0; lac_pke_request_handle_t pRequestHandle = LAC_PKE_INVALID_HANDLE; /* Clear output buffers */ osalMemSet(pXk->pData, 0, pXk->dataLenInBytes); osalMemSet(pYk->pData, 0, pYk->dataLenInBytes); /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pXk; cbData.pOutputData2 = pYk; /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS(inArgSizeListPointVerify, LAC_ECDH_POINT_VERIFY_NUM_IN_ARGS, dataOperationSizeBytes); LAC_EC_SET_LIST_PARAMS(inArgSizeListPointMultiply, LAC_ECDH_POINT_MULTIPLY_NUM_IN_ARGS, dataOperationSizeBytes); /*LAC_EC_SET_LIST_PARAMS( outArgSizeListMultiply, LAC_ECDH_POINT_MULTIPLY_NUM_OUT_ARGS, dataOperationSizeBytes); unused param */ /* Set all memory to be externally allocated */ LAC_EC_SET_LIST_PARAMS(internalMemInListVerify, LAC_ECDH_POINT_VERIFY_NUM_IN_ARGS, CPA_FALSE); LAC_EC_SET_LIST_PARAMS(internalMemInListMultiply, LAC_ECDH_POINT_MULTIPLY_NUM_IN_ARGS, CPA_FALSE); LAC_EC_SET_LIST_PARAMS(internalMemOutListMultiply, LAC_ECDH_POINT_MULTIPLY_NUM_OUT_ARGS, CPA_FALSE); /* Populate input buffers and output buffer and set function ID */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdhPointVerifyOpDataWrite( inPointVerify.maths_point_verify_gfp_l256, pOpData); functionIdPointVerify = MATHS_POINT_VERIFY_GFP_L256; LacEcdhPointMultiplyOpDataWrite( inPointMultiply.maths_point_multiplication_gfp_l256, outPointMultiply.maths_point_multiplication_gfp_l256, pOpData, pXk, pYk); functionIdPointMultiply = MATHS_POINT_MULTIPLICATION_GFP_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdhPointVerifyOpDataWrite( inPointVerify.maths_point_verify_gfp_l512, pOpData); functionIdPointVerify = MATHS_POINT_VERIFY_GFP_L512; LacEcdhPointMultiplyOpDataWrite( inPointMultiply.maths_point_multiplication_gfp_l512, outPointMultiply.maths_point_multiplication_gfp_l512, pOpData, pXk, pYk); functionIdPointMultiply = MATHS_POINT_MULTIPLICATION_GFP_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: { Cpa32U index = 0; LacEcdhPointVerifyOpDataWrite( inPointVerify.maths_point_verify_gfp_521, pOpData); functionIdPointVerify = MATHS_POINT_VERIFY_GFP_521; LacEcdhPointMultiplyOpDataWrite( inPointMultiply.maths_point_multiplication_gfp_521, outPointMultiply.maths_point_multiplication_gfp_521, pOpData, pXk, pYk); functionIdPointMultiply = MATHS_POINT_MULTIPLICATION_GFP_521; /* cofactor size is 1 qw */ index = LAC_IDX_OF( icp_qat_fw_maths_point_multiplication_gfp_521_input_t, h); LAC_ASSERT(LAC_MAX_MMP_INPUT_PARAMS > index, "invalid cofactor index"); inArgSizeListPointMultiply[index] = LAC_QUAD_WORD_IN_BYTES; break; } default: status = CPA_STATUS_INVALID_PARAM; break; } } else { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdhPointVerifyOpDataWrite( inPointVerify.maths_point_verify_gf2_l256, pOpData); functionIdPointVerify = MATHS_POINT_VERIFY_GF2_L256; LacEcdhPointMultiplyOpDataWrite( inPointMultiply.maths_point_multiplication_gf2_l256, outPointMultiply.maths_point_multiplication_gf2_l256, pOpData, pXk, pYk); functionIdPointMultiply = MATHS_POINT_MULTIPLICATION_GF2_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdhPointVerifyOpDataWrite( inPointVerify.maths_point_verify_gf2_l512, pOpData); functionIdPointVerify = MATHS_POINT_VERIFY_GF2_L512; LacEcdhPointMultiplyOpDataWrite( inPointMultiply.maths_point_multiplication_gf2_l512, outPointMultiply.maths_point_multiplication_gf2_l512, pOpData, pXk, pYk); functionIdPointMultiply = MATHS_POINT_MULTIPLICATION_GF2_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: { Cpa32U index = 0; LacEcdhPointVerifyOpDataWrite( inPointVerify.maths_point_verify_gf2_571, pOpData); functionIdPointVerify = MATHS_POINT_VERIFY_GF2_571; LacEcdhPointMultiplyOpDataWrite( inPointMultiply.maths_point_multiplication_gf2_571, outPointMultiply.maths_point_multiplication_gf2_571, pOpData, pXk, pYk); functionIdPointMultiply = MATHS_POINT_MULTIPLICATION_GF2_571; /* cofactor size is 1 qw */ index = LAC_IDX_OF( icp_qat_fw_maths_point_multiplication_gf2_571_input_t, h); LAC_ASSERT(LAC_MAX_MMP_INPUT_PARAMS > index, "invalid cofactor index"); inArgSizeListPointMultiply[index] = LAC_QUAD_WORD_IN_BYTES; break; } default: status = CPA_STATUS_INVALID_PARAM; break; } } /* Chain 2 requests: Point Verify and Point Multiply iff pointVerify flag is set */ if (CPA_TRUE == pOpData->pointVerify) { if (CPA_STATUS_SUCCESS == status) { /* create a PKE request to the QAT */ status = LacPke_CreateRequest(&pRequestHandle, functionIdPointVerify, inArgSizeListPointVerify, NULL, &inPointVerify, &outPointVerify, internalMemInListVerify, NULL, LacEcdh_PointMultiplyCallback, &cbData, instanceHandle); } } if (CPA_STATUS_SUCCESS == status) { /* create a PKE request to the QAT */ status = LacPke_CreateRequest(&pRequestHandle, functionIdPointMultiply, inArgSizeListPointMultiply, inArgSizeListPointMultiply, &inPointMultiply, &outPointMultiply, internalMemInListMultiply, internalMemOutListMultiply, LacEcdh_PointMultiplyCallback, &cbData, instanceHandle); } if (CPA_STATUS_SUCCESS == status) { /* send request chain */ status = LacPke_SendRequest(&pRequestHandle, instanceHandle); } } #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDH_STAT_INC(numEcdhPointMultiplyRequests, pCryptoService); } else { LAC_ECDH_STAT_INC(numEcdhPointMultiplyRequestErrors, pCryptoService); } #endif return status; } /** *************************************************************************** * @ingroup Lac_Ecdh * ***************************************************************************/ CpaStatus cpaCyEcdhQueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyEcdhStats64 *pEcdhStats) { CpaInstanceHandle instanceHandle = NULL; sal_crypto_service_t *pCryptoService = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%x, 0x%x)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pEcdhStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* ensure LAC is initialised - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); /* Ensure ecdh capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecdh); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pEcdhStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; /* get stats into user supplied stats structure */ LAC_ECDH_STATS_GET(*pEcdhStats, pCryptoService); return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecdsa.c000066400000000000000000003407731503624047500313040ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * * @file lac_ecdsa.c * * @ingroup Lac_Ec * * Elliptic Curve Digital Signature Algorithm functions * * @lld_start * * @lld_overview * This file implements the Elliptic Curve DSA apis. It implements 4 * Ecdsa API services: signature generation (r, s, rs), and signature * verification. Statistics are maintained per instance for each service. * The parameters supplied by the client are checked, and then input/output * argument lists are constructed before calling the PKE Comms layer to * create and send a request to the QAT. * * For Ecdsa signRS and verify the number of input parameters to the function * is greater than the number of input parameters allowed for the PKE service * Therefore, for the 2 of these functions we copy and concatenate all inputs * to 1 internal buffer and this is sent to QAT for processing. * * In all other cases the service implementations are a straightforward * marshalling of client-supplied parameters for the QAT. I.e. there is * minimal logic handled by this component. * * For Ecdsa Verification function the output is the result of the verification * returned by the QAT in the form of pass/fail status. The status is * returned to the caller. * * @lld_dependencies * - \ref LacAsymCommonQatComms "PKE QAT Comms" : For creating and sending * messages to the QAT * - \ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @note * The ECDSA feature may be called in Asynchronous or Synchronous modes. * In Asynchronous mode the user supplies a Callback function to the API. * Control returns to the client after the message has been sent to the QAT * and the Callback gets invoked when the QAT completes the operation. There * is NO BLOCKING. This mode is preferred for maximum performance. * In Synchronous mode the client supplies no Callback function pointer (NULL) * and the point of execution is placed on a wait-queue internally, and this * is de-queued once the QAT completes the operation. Hence, Synchronous mode * is BLOCKING. So avoid using in an interrupt context. To achieve maximum * performance from the API Asynchronous mode is preferred. * * @performance * * @lld_initialisation * On initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * ***************************************************************************/ /* **************************************************************************** * Include public/global header files **************************************************************************** */ /* API Includes */ #include "cpa.h" #include "cpa_cy_ecdsa.h" /* OSAL Includes */ #include "Osal.h" /* ADF Includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* QAT includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" #include "icp_qat_fw_pke.h" /* Look Aside Includes */ #include "lac_log.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_sync.h" #include "lac_ec.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "sal_statistics.h" #include "lac_ec_nist_curves.h" typedef struct _OptCurveParams { Cpa32U dataOperationSizeBytes; Cpa32U functionRS; const Cpa8U *p; const Cpa8U *n; const Cpa8U *a; const Cpa8U *b; } OptCurveParams; /* ******************************************************************************** * Global Variables ******************************************************************************** */ #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #endif /**< number of 'in' arguments in the arguments size list for Sign R */ #define LAC_ECDSA_SIGNR_NUM_IN_ARGS 7 /**< number of 'out' arguments in the arguments size list for Sign R */ #define LAC_ECDSA_SIGNR_NUM_OUT_ARGS 1 /**< number of 'in' arguments in the arguments size list for Sign S */ #define LAC_ECDSA_SIGNS_NUM_IN_ARGS 5 /**< number of 'out' arguments in the arguments size list for Sign S */ #define LAC_ECDSA_SIGNS_NUM_OUT_ARGS 1 /**< number of 'in' arguments in the arguments size list for Sign RS */ #define LAC_ECDSA_SIGNRS_NUM_IN_ARGS 1 /**< number of input parameters to QA API for Sign RS */ #define LAC_ECDSA_SIGNRS_NUM_IN_QA_API 9 /**< number of 'out' arguments in the arguments size list for Sign RS */ #define LAC_ECDSA_SIGNRS_NUM_OUT_ARGS 2 /**< number of 'in' arguments in the arguments size list for Verify */ #define LAC_ECDSA_VERIFY_NUM_IN_ARGS 1 /**< number of input parameters to QA API for Verify */ #define LAC_ECDSA_VERIFY_NUM_IN_QA_API 11 /**< number of 'in' arguments in the arguments size list for Sign RS P256 P384 */ #define LAC_ECDSA_SIGNRS_P256P384_NUM_IN_ARGS 3 /**< number of 'out' arguments in the arguments size list for Sign RS P256 P384 */ #define LAC_ECDSA_SIGNRS_P256P384_NUM_OUT_ARGS 2 /**< number of ECDSA statistics */ #define LAC_ECDSA_NUM_STATS (sizeof(CpaCyEcdsaStats64) / sizeof(Cpa64U)) #ifndef DISABLE_STATS #define LAC_ECDSA_STAT_INC(statistic, pCryptoService) \ do \ { \ if (CPA_TRUE == \ pCryptoService->generic_service_info.stats->bEccStatsEnabled) \ { \ osalAtomicInc( \ &pCryptoService->pLacEcdsaStatsArr[offsetof(CpaCyEcdsaStats64, \ statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) /**< @ingroup Lac_Ec * macro to increment a ECDSA stat (derives offset into array of atomics) */ #else #define LAC_ECDSA_STAT_INC(statistic, pCryptoService) \ (pCryptoService) = (pCryptoService) #endif #define LAC_ECDSA_STATS_GET(ecdsaStats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_ECDSA_NUM_STATS; i++) \ { \ ((Cpa64U *)&(ecdsaStats))[i] = \ osalAtomicGet(&pCryptoService->pLacEcdsaStatsArr[i]); \ } \ } while (0) /**< @ingroup Lac_Ec * macro to collect a ECDSA stat in sample period of performance counters */ /**< @ingroup Lac_Ec * macro to get all ECDSA stats (from internal array of atomics) */ #define LacEcdsaSignROpDataWrite(in, out, pOpData, pR) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.xg, &pOpData->xg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.yg, &pOpData->yg); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.n, &pOpData->n); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.q, &pOpData->q); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.a, &pOpData->a); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.b, &pOpData->b); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.k, &pOpData->k); \ \ /* populate output parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.r, pR); \ } while (0); /* macro to populate Sign R parameters from CpaCyEcdsaSignROpData or * CpaCyEcdsaSignRSOpData structures */ #define LacEcdsaSignSOpDataWrite(in, out, pOpData, pS) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.e, &pOpData->m); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.d, &pOpData->d); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.r, &pOpData->r); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.k, &pOpData->k); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.n, &pOpData->n); \ \ /* populate output parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.s, pS); \ } while (0); /* macro to populate parameters from CpaCyEcdsaSignSOpData structure */ #define LacEcdsaSignRSOpDataWrite(in_struct, out, pConcateBuff, pR, pS) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in_struct.in, pConcateBuff); \ \ /* populate output parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.r, pR); \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.s, pS); \ } while (0); /* macro to populate Sign RS parameters */ #define LacEcdsaP256P384SignRSOpDataWrite(in, out, pOpData, pR, pS) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.k, &pOpData->k); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.e, &pOpData->m); \ LAC_MEM_SHARED_WRITE_FROM_PTR(in.d, &pOpData->d); \ \ /* populate output parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.r, pR); \ LAC_MEM_SHARED_WRITE_FROM_PTR(out.s, pS); \ } while (0); /**< @ingroup Lac_Ec * macro to write in/out parameters for the P256 and P384 * Ecdsa SignRS operation */ #define LacEcdsaVerifyOpDataWrite(in_struct, pConcateBuff) \ do \ { \ /* populate input parameters */ \ LAC_MEM_SHARED_WRITE_FROM_PTR(in_struct.in, pConcateBuff); \ } while (0); /* macro to populate Verify parameters from CpaCyEcdsaSignVerifyOpData * structure and other */ /* **************************************************************************** * Define static function definitions **************************************************************************** */ STATIC CpaStatus LacEcdsa_EcdsaSignRS(const CpaInstanceHandle instanceHandle_in, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); /** *************************************************************************** * @ingroup Lac_Ec * return the size of the biggest number in CpaCyEcdsaSignROpData * * @description * return the size of the biggest number in CpaCyEcdsaSignROpData * * @param[in] pOpData Pointer to a CpaCyEcdsaSignROpData structure * * @retval max the size in bytes of the biggest input number * ***************************************************************************/ STATIC Cpa32U LacEcdsa_SignROpDataSizeGetMax(const CpaCyEcdsaSignROpData *pOpData) { Cpa32U max = 0; /* need to find max size in bytes of the number in input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->n)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->q)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->a)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->b)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); return max; } /** **************************************************************************** * @ingroup Lac_Ec * return the size of the biggest number in CpaCyEcdsaSignSOpData * * @description * return the size of the biggest number in CpaCyEcdsaSignSOpData * * @param[in] pOpData Pointer to a CpaCyEcdsaSignSOpData structure * * @retval max the size in bytes of the biggest number * ***************************************************************************/ STATIC Cpa32U LacEcdsa_SignSOpDataSizeGetMax(const CpaCyEcdsaSignSOpData *pOpData) { Cpa32U max = 0; /* need to find max size in bytes of number in input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->m)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->d)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->r)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->n)), max); return max; } /** *************************************************************************** * @ingroup Lac_Ec * return the size of the biggest number in CpaCyEcdsaSignRSOpData * * @description * return the size of the biggest number in CpaCyEcdsaSignRSOpData * * @param[in] pOpData Pointer to a CpaCyEcdsaSignRSOpData structure * * @retval max the size in bytes of the biggest number * ***************************************************************************/ STATIC Cpa32U LacEcdsa_SignRSOpDataSizeGetMax(const CpaCyEcdsaSignRSOpData *pOpData) { Cpa32U max = 0; /* need to find max size in bytes of number in input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->m)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->d)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->q)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->n)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->a)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->b)), max); return max; } /** *************************************************************************** * @ingroup Lac_Ec * return the size of the biggest number in CpaCyEcdsaVerifyOpData * * @description * return the size of the biggest number in CpaCyEcdsaVerifyOpData * * @param[in] pOpData Pointer to a CpaCyEcdsaVerifyOpData structure * * @retval max the size in bytes of the biggest number * ***************************************************************************/ STATIC Cpa32U LacEcdsa_VerifyOpDataSizeGetMax(const CpaCyEcdsaVerifyOpData *pOpData) { Cpa32U max = 0; /* need to find max size in bytes of number in input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yg)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->n)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->q)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->a)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->b)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->m)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->r)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->s)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xp)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yp)), max); return max; } /** *************************************************************************** * @ingroup Lac_Ec * Copies least significant len bytes from a flat buffer (if length of * flat buffer is less than len padding will be added). * * @description * This function copies data in a flat buffer to memory pointed to by * ptr. This function performs no checks so it is assumed that there is * enough memory allocated. * * @param[in/out] ptr Pointer to a pointer to an array of Cpa8U * @param[in] pBuff Pointer to a CpaFlatBuffer structure * @param[in] len Number of bytes to copy. * This is the amount by which *ptr is * incremented also. * ***************************************************************************/ STATIC void LacEc_FlatBuffToConcate(Cpa8U **ptr, const CpaFlatBuffer *pBuff, Cpa32U len) { Cpa8U *pMem = NULL; pMem = (Cpa8U *)*ptr; if (pBuff->dataLenInBytes < len) { /* pad */ osalMemSet(pMem, 0, (len - pBuff->dataLenInBytes)); pMem = pMem + (len - pBuff->dataLenInBytes); /* copy all flat buffer */ memcpy(pMem, pBuff->pData, pBuff->dataLenInBytes); pMem = pMem + pBuff->dataLenInBytes; } else { /* no padding is required and we may need to index into flatbuffer - only lsbs are copied */ memcpy(pMem, &(pBuff->pData[pBuff->dataLenInBytes - len]), len); pMem = pMem + len; } *ptr = pMem; } /** *************************************************************************** * @ingroup LacEc * Detect P256 or P384 and get optimised MMP function id ***************************************************************************/ STATIC CpaBoolean LacEcdsa_SignRSGetOptFunctionId(CpaCyEcFieldType primeRepresentation, const CpaFlatBuffer *pP, const CpaFlatBuffer *pN, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, Cpa32U *dataOperationSizeBytes, Cpa32U *function) { int i = 0; OptCurveParams curves[] = { /* P256 */ { .dataOperationSizeBytes = LAC_BITS_TO_BYTES(LAC_256_BITS), .functionRS = PKE_ECDSA_SIGN_RS_P256, .p = nist_p256_p, .n = nist_p256_n, .a = nist_p256_a, .b = nist_p256_b }, /* P384 */ { .dataOperationSizeBytes = LAC_BITS_TO_BYTES(LAC_384_BITS), .functionRS = PKE_ECDSA_SIGN_RS_P384, .p = nist_p384_p, .n = nist_p384_n, .a = nist_p384_a, .b = nist_p384_b }, }; *function = 0; /* Loop through each curve returning when found and setting * dataOperationSizeBytes and function id */ for (i = 0; i < ARRAY_SIZE(curves); i++) { CpaBoolean res = CPA_CY_EC_FIELD_TYPE_PRIME == primeRepresentation; /* if the curve has not the prime representation continue searching */ if (!res) continue; res = LacPke_CompareFlatAndPtr( pN, curves[i].n, curves[i].dataOperationSizeBytes); if (!res) continue; res = LacPke_CompareFlatAndPtr( pP, curves[i].p, curves[i].dataOperationSizeBytes); if (!res) continue; res = LacPke_CompareFlatAndPtr( pA, curves[i].a, curves[i].dataOperationSizeBytes); if (!res) continue; res = LacPke_CompareFlatAndPtr( pB, curves[i].b, curves[i].dataOperationSizeBytes); if (res == CPA_TRUE) { *dataOperationSizeBytes = curves[i].dataOperationSizeBytes; *function = curves[i].functionRS; return CPA_TRUE; } } return CPA_FALSE; /* not found any optimised curve */ } /** *************************************************************************** * @ingroup LacEc * Fill MMP struct for optimised Sign RS P256 and P384 ***************************************************************************/ STATIC CpaStatus LacEcdsa_SignRSFillMMPStructsOpt(icp_qat_fw_mmp_input_param_t *in, Cpa32U *inSizes, CpaBoolean *inAlloc, icp_qat_fw_mmp_output_param_t *out, Cpa32U *outSizes, CpaBoolean *outAlloc, Cpa32U function, Cpa32U size, const CpaCyEcdsaSignRSOpData *pOpData, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_SUCCESS; /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS( inSizes, LAC_ECDSA_SIGNRS_P256P384_NUM_IN_ARGS, size); LAC_EC_SET_LIST_PARAMS( outSizes, LAC_ECDSA_SIGNRS_P256P384_NUM_OUT_ARGS, size); /* Set all memory to externally allocated */ LAC_EC_SET_LIST_PARAMS( inAlloc, LAC_ECDSA_SIGNRS_P256P384_NUM_IN_ARGS, CPA_FALSE); LAC_EC_SET_LIST_PARAMS( outAlloc, LAC_ECDSA_SIGNRS_P256P384_NUM_OUT_ARGS, CPA_FALSE); switch (function) { case PKE_ECDSA_SIGN_RS_P256: LacEcdsaP256P384SignRSOpDataWrite(in->mmp_ecdsa_sign_rs_p256, out->mmp_ecdsa_sign_rs_p256, pOpData, pR, pS); break; case PKE_ECDSA_SIGN_RS_P384: LacEcdsaP256P384SignRSOpDataWrite(in->mmp_ecdsa_sign_rs_p384, out->mmp_ecdsa_sign_rs_p384, pOpData, pR, pS); break; default: status = CPA_STATUS_INVALID_PARAM; break; } return status; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign R synchronous function ***************************************************************************/ STATIC CpaStatus LacEcdsa_SignRSyn(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignROpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sync_op_data_t *pSyncCallbackData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the generic synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyEcdsaSignR(instanceHandle, LacSync_GenFlatBufVerifyCb, pSyncCallbackData, pOpData, pMultiplyStatus, pR); } else { LAC_ECDSA_STAT_INC(numEcdsaSignRRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { LAC_ECDSA_STAT_INC(numEcdsaSignRCompletedErrors, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign R internal callback ***************************************************************************/ STATIC void LacEcdsa_SignRCallback(CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcdsaGenSignCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcdsaSignROpData *pOpData = NULL; CpaFlatBuffer *pR = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcdsaGenSignCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyEcdsaSignROpData *)pCbData->pClientOpData; pR = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pR); LAC_ASSERT_NOT_NULL(pR->pData); /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDSA_STAT_INC(numEcdsaSignRCompleted, pCryptoService); } else { LAC_ECDSA_STAT_INC(numEcdsaSignRCompletedErrors, pCryptoService); } if ((CPA_FALSE == multiplyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECDSA_STAT_INC(numEcdsaSignRCompletedOutputInvalid, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pR); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign R parameter check ***************************************************************************/ STATIC CpaStatus LacEcdsa_SignRBasicParamCheck(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignROpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR) { /* check for NULL pointers */ LAC_CHECK_NULL_PARAM(pMultiplyStatus); LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pR); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LAC_CHECK_NULL_PARAM(pOpData->a.pData); LAC_CHECK_SIZE(&(pOpData->a), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->b.pData); LAC_CHECK_SIZE(&(pOpData->b), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->q.pData); LAC_CHECK_SIZE(&(pOpData->q), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xg.pData); LAC_CHECK_SIZE(&(pOpData->xg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yg.pData); LAC_CHECK_SIZE(&(pOpData->yg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->n.pData); LAC_CHECK_SIZE(&(pOpData->n), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pR->pData); LAC_CHECK_SIZE(pR, CHECK_NONE, 0); if (CPA_CY_EC_FIELD_TYPE_PRIME != pOpData->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pOpData->fieldType) { return CPA_STATUS_INVALID_PARAM; } /* Check that q is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->q)); /* Check that n is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->n)); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ CpaStatus cpaCyEcdsaSignR(const CpaInstanceHandle instanceHandle_in, const CpaCyEcdsaGenSignCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignROpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U dataOperationSizeBytes = 0; CpaInstanceHandle instanceHandle = NULL; sal_crypto_service_t *pCryptoService = NULL; #ifdef ICP_PARAM_CHECK Cpa32S compare = 1; Cpa32U bit_pos_q = 0, bit_pos_x = 0, bit_pos_y = 0; Cpa32U temp = 0; Cpa32U maxModLen = 0; CpaBoolean isZero = CPA_FALSE; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* instance checks - if fail, no inc stats just return */ /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* ensure LAC is initialised - return error if not */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecdsa); /* Check if the API has been called in synchronous mode */ if (NULL == pCb) { #ifdef ICP_TRACE #ifdef ICP_PARAM_CHECK /* Check for valid pointers */ LAC_CHECK_NULL_PARAM(pMultiplyStatus); #endif status = LacEcdsa_SignRSyn(instanceHandle, pOpData, pMultiplyStatus, pR); LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d], 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pMultiplyStatus, *pMultiplyStatus, (LAC_ARCH_UINT)pR); return status; #else /* Call synchronous mode function */ return LacEcdsa_SignRSyn(instanceHandle, pOpData, pMultiplyStatus, pR); #endif } #ifdef ICP_PARAM_CHECK /* Basic Param Checking */ status = LacEcdsa_SignRBasicParamCheck( instanceHandle, pOpData, pMultiplyStatus, pR); /* Check that output buffer is big enough */ if (CPA_STATUS_SUCCESS == status) { maxModLen = LacPke_GetMinBytes(&(pOpData->n)); if (pR->dataLenInBytes < maxModLen) { LAC_INVALID_PARAM_LOG("Output buffer not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif pCryptoService = (sal_crypto_service_t *)instanceHandle; if (CPA_STATUS_SUCCESS == status) { /* Determine size */ status = LacEc_GetRange(LacEcdsa_SignROpDataSizeGetMax(pOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if ((LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes) && (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType)) { /* Check if it is a NIST curve if not use 8QW */ LacEc_CheckCurve4QWGF2(&dataOperationSizeBytes, &(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL); } } #ifdef ICP_PARAM_CHECK if ((CPA_STATUS_SUCCESS == status) && (LAC_EC_SIZE_QW9_IN_BYTES == dataOperationSizeBytes)) { /* 9QW checks */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* Check if is is a NIST curve (if not it is an invalid param) */ /* Also checks that xG and yG are less than 2^521 */ status = LacEc_CheckCurve9QWGFP(&(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL, &(pOpData->xg), &(pOpData->yg)); } else { /* Check if is is a NIST curve (if not it is an invalid param) */ /* Also checks that deg xG and yG are less than 571 */ status = LacEc_CheckCurve9QWGF2(&(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL, &(pOpData->xg), &(pOpData->yg)); } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < k < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->k)); compare = LacPke_Compare(&(pOpData->k), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("k is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Ensure base point is not (0,0) */ if ((0 == LacPke_CompareZero(&(pOpData->xg), 0)) && (0 == LacPke_CompareZero(&(pOpData->yg), 0))) { LAC_INVALID_PARAM_LOG("Invalid base point"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* For GFP check that q>3 and xg and yg less than q (note for 9QW case have already ensured xg and yg <=q still need to eliminate xg and yg ==q case) */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* Ensure q > 3 */ LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); if (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GFP) { LAC_INVALID_PARAM_LOG("q is not > 3 as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure xg < q */ compare = LacPke_Compare(&(pOpData->xg), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("xg is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure yg < q */ compare = LacPke_Compare(&(pOpData->yg), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("yg is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } } /* For GF2 4 and 8 QW check that deg(q)>2 and that deg(xg) and deg(yg) are less than deg(q) (note: already checked for 9QW case) */ if (((LAC_EC_SIZE_QW8_IN_BYTES == dataOperationSizeBytes) || (LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes)) && (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType)) { LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); if (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GF2) { LAC_INVALID_PARAM_LOG("deg(q) is not > 2 as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure deg(xg) < deg(q) for non zero xg */ LacPke_GetBitPos(&(pOpData->xg), &bit_pos_x, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_x >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(xg) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure deg(yg) < deg(q) for non zero yg */ LacPke_GetBitPos(&(pOpData->yg), &bit_pos_y, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_y >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(yg) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } } } #endif if (CPA_STATUS_SUCCESS == status) { icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; lac_pke_op_cb_data_t cbData = {0}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; Cpa32U functionID = 0; /* clear output buffer */ osalMemSet(pR->pData, 0, pR->dataLenInBytes); /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pR; /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS( inArgSizeList, LAC_ECDSA_SIGNR_NUM_IN_ARGS, dataOperationSizeBytes); LAC_EC_SET_LIST_PARAMS(outArgSizeList, LAC_ECDSA_SIGNR_NUM_OUT_ARGS, dataOperationSizeBytes); /* Set all memory to externally allocated */ LAC_EC_SET_LIST_PARAMS( internalMemInList, LAC_ECDSA_SIGNR_NUM_IN_ARGS, CPA_FALSE); LAC_EC_SET_LIST_PARAMS( internalMemOutList, LAC_ECDSA_SIGNR_NUM_OUT_ARGS, CPA_FALSE); /* Populate input buffers and output buffer and set function ID */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaSignROpDataWrite(in.mmp_ecdsa_sign_r_gfp_l256, out.mmp_ecdsa_sign_r_gfp_l256, pOpData, pR); functionID = PKE_ECDSA_SIGN_R_GFP_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaSignROpDataWrite(in.mmp_ecdsa_sign_r_gfp_l512, out.mmp_ecdsa_sign_r_gfp_l512, pOpData, pR); functionID = PKE_ECDSA_SIGN_R_GFP_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaSignROpDataWrite(in.mmp_ecdsa_sign_r_gfp_521, out.mmp_ecdsa_sign_r_gfp_521, pOpData, pR); functionID = PKE_ECDSA_SIGN_R_GFP_521; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } else { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaSignROpDataWrite(in.mmp_ecdsa_sign_r_gf2_l256, out.mmp_ecdsa_sign_r_gf2_l256, pOpData, pR); functionID = PKE_ECDSA_SIGN_R_GF2_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaSignROpDataWrite(in.mmp_ecdsa_sign_r_gf2_l512, out.mmp_ecdsa_sign_r_gf2_l512, pOpData, pR); functionID = PKE_ECDSA_SIGN_R_GF2_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaSignROpDataWrite(in.mmp_ecdsa_sign_r_gf2_571, out.mmp_ecdsa_sign_r_gf2_571, pOpData, pR); functionID = PKE_ECDSA_SIGN_R_GF2_571; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } if (CPA_STATUS_SUCCESS == status) { /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionID, inArgSizeList, outArgSizeList, &in, &out, internalMemInList, internalMemOutList, LacEcdsa_SignRCallback, &cbData, instanceHandle); } } /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDSA_STAT_INC(numEcdsaSignRRequests, pCryptoService); } else { LAC_ECDSA_STAT_INC(numEcdsaSignRRequestErrors, pCryptoService); } return status; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign S synchronous function ***************************************************************************/ STATIC CpaStatus LacEcdsa_SignSSyn(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sync_op_data_t *pSyncCallbackData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the generic synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyEcdsaSignS(instanceHandle, LacSync_GenFlatBufVerifyCb, pSyncCallbackData, pOpData, pMultiplyStatus, pS); } else { LAC_ECDSA_STAT_INC(numEcdsaSignSRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { LAC_ECDSA_STAT_INC(numEcdsaSignSCompletedErrors, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign S internal callback ***************************************************************************/ STATIC void LacEcdsa_SignSCallback(CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcdsaGenSignCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcdsaSignSOpData *pOpData = NULL; CpaFlatBuffer *pS = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcdsaGenSignCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyEcdsaSignSOpData *)pCbData->pClientOpData; pS = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pS); LAC_ASSERT_NOT_NULL(pS->pData); /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDSA_STAT_INC(numEcdsaSignSCompleted, pCryptoService); } else { LAC_ECDSA_STAT_INC(numEcdsaSignSCompletedErrors, pCryptoService); } if ((CPA_FALSE == multiplyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECDSA_STAT_INC(numEcdsaSignSCompletedOutputInvalid, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pS); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign S parameter check ***************************************************************************/ STATIC CpaStatus LacEcdsa_SignSBasicParamCheck(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pS) { /* check for NULL pointers */ LAC_CHECK_NULL_PARAM(pMultiplyStatus); LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pS); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LAC_CHECK_NULL_PARAM(pOpData->m.pData); LAC_CHECK_SIZE(&(pOpData->m), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->d.pData); LAC_CHECK_SIZE(&(pOpData->d), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->r.pData); LAC_CHECK_SIZE(&(pOpData->r), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->n.pData); LAC_CHECK_SIZE(&(pOpData->n), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pS->pData); LAC_CHECK_SIZE(pS, CHECK_NONE, 0); if (CPA_CY_EC_FIELD_TYPE_PRIME != pOpData->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pOpData->fieldType) { return CPA_STATUS_INVALID_PARAM; } /* Check that n is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->n)); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ CpaStatus cpaCyEcdsaSignS(const CpaInstanceHandle instanceHandle_in, const CpaCyEcdsaGenSignCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U dataOperationSizeBytes = 0; CpaInstanceHandle instanceHandle = NULL; sal_crypto_service_t *pCryptoService = NULL; #ifdef ICP_PARAM_CHECK Cpa32S compare = 1; Cpa32U maxModLen = 1; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* instance checks - if fail, no inc stats just return */ /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* ensure LAC is initialised - return error if not */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecdsa); /* Check if the API has been called in synchronous mode */ if (NULL == pCb) { #ifdef ICP_TRACE #ifdef ICP_PARAM_CHECK /* Check for valid pointers */ LAC_CHECK_NULL_PARAM(pMultiplyStatus); #endif status = LacEcdsa_SignSSyn(instanceHandle, pOpData, pMultiplyStatus, pS); LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx[%d], 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pMultiplyStatus, *pMultiplyStatus, (LAC_ARCH_UINT)pS); return status; #else /* Call synchronous mode function */ return LacEcdsa_SignSSyn(instanceHandle, pOpData, pMultiplyStatus, pS); #endif } #ifdef ICP_PARAM_CHECK /* Basic Param Checking */ status = LacEcdsa_SignSBasicParamCheck( instanceHandle, pOpData, pMultiplyStatus, pS); /* Check that output buffer is big enough */ if (CPA_STATUS_SUCCESS == status) { maxModLen = LacPke_GetMinBytes(&(pOpData->n)); if (pS->dataLenInBytes < maxModLen) { LAC_INVALID_PARAM_LOG("Output buffer not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif pCryptoService = (sal_crypto_service_t *)instanceHandle; if (CPA_STATUS_SUCCESS == status) { /* Determine size */ status = LacEc_GetRange(LacEcdsa_SignSOpDataSizeGetMax(pOpData), &dataOperationSizeBytes); } #ifdef ICP_PARAM_CHECK if (CPA_STATUS_SUCCESS == status) { /* Check 0 < k < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->k)); compare = LacPke_Compare(&(pOpData->k), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("k is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < r < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->r)); compare = LacPke_Compare(&(pOpData->r), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("r is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < d < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->d)); compare = LacPke_Compare(&(pOpData->d), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("d is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; lac_pke_op_cb_data_t cbData = {0}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; Cpa32U functionID = 0; /* clear output buffer - needs to be done in case pS->dataLenInBytes > dataOperationSizeBytes */ osalMemSet(pS->pData, 0, pS->dataLenInBytes); /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pS; /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS( inArgSizeList, LAC_ECDSA_SIGNS_NUM_IN_ARGS, dataOperationSizeBytes); LAC_EC_SET_LIST_PARAMS(outArgSizeList, LAC_ECDSA_SIGNS_NUM_OUT_ARGS, dataOperationSizeBytes); /* Set memory to externally allocated */ LAC_EC_SET_LIST_PARAMS( internalMemInList, LAC_ECDSA_SIGNS_NUM_IN_ARGS, CPA_FALSE); LAC_EC_SET_LIST_PARAMS( internalMemOutList, LAC_ECDSA_SIGNS_NUM_OUT_ARGS, CPA_FALSE) /* Populate input buffers and output buffer and set function ID */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaSignSOpDataWrite(in.mmp_ecdsa_sign_s_gfp_l256, out.mmp_ecdsa_sign_s_gfp_l256, pOpData, pS); functionID = PKE_ECDSA_SIGN_S_GFP_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaSignSOpDataWrite(in.mmp_ecdsa_sign_s_gfp_l512, out.mmp_ecdsa_sign_s_gfp_l512, pOpData, pS); functionID = PKE_ECDSA_SIGN_S_GFP_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaSignSOpDataWrite(in.mmp_ecdsa_sign_s_gfp_521, out.mmp_ecdsa_sign_s_gfp_521, pOpData, pS); functionID = PKE_ECDSA_SIGN_S_GFP_521; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } else { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaSignSOpDataWrite(in.mmp_ecdsa_sign_s_gf2_l256, out.mmp_ecdsa_sign_s_gf2_l256, pOpData, pS); functionID = PKE_ECDSA_SIGN_S_GF2_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaSignSOpDataWrite(in.mmp_ecdsa_sign_s_gf2_l512, out.mmp_ecdsa_sign_s_gf2_l512, pOpData, pS); functionID = PKE_ECDSA_SIGN_S_GF2_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaSignSOpDataWrite(in.mmp_ecdsa_sign_s_gf2_571, out.mmp_ecdsa_sign_s_gf2_571, pOpData, pS); functionID = PKE_ECDSA_SIGN_S_GF2_571; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } if (CPA_STATUS_SUCCESS == status) { /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionID, inArgSizeList, outArgSizeList, &in, &out, internalMemInList, internalMemOutList, LacEcdsa_SignSCallback, &cbData, instanceHandle); } } /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDSA_STAT_INC(numEcdsaSignSRequests, pCryptoService); } else { LAC_ECDSA_STAT_INC(numEcdsaSignSRequestErrors, pCryptoService); } return status; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign R & S synchronous function ***************************************************************************/ STATIC CpaStatus LacEcdsa_SignRSSyn(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sync_op_data_t *pSyncCallbackData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the generic synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = LacEcdsa_EcdsaSignRS(instanceHandle, LacSync_GenDualFlatBufVerifyCb, pSyncCallbackData, pOpData, pMultiplyStatus, pR, pS); } else { LAC_ECDSA_STAT_INC(numEcdsaSignRSRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { LAC_ECDSA_STAT_INC(numEcdsaSignRSCompletedErrors, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign R & S internal callback ***************************************************************************/ STATIC void LacEcdsa_SignRSCallback(CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcdsaSignRSCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcdsaSignRSOpData *pOpData = NULL; CpaFlatBuffer *pR = NULL; CpaFlatBuffer *pS = NULL; Cpa8U *pMemPoolConcate = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcdsaSignRSCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyEcdsaSignRSOpData *)pCbData->pClientOpData; pR = pCbData->pOutputData1; pS = pCbData->pOutputData2; pMemPoolConcate = (Cpa8U *)(pCbData->pOpaqueData); LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pR); LAC_ASSERT_NOT_NULL(pR->pData); LAC_ASSERT_NOT_NULL(pS); LAC_ASSERT_NOT_NULL(pS->pData); /* When we use opptimised path for P256/P384 we do not allocate pMemPoolConcate so in that case pMemPoolConcate is NULL and we should not free it */ /* Free Mem Pool Entry */ if (pMemPoolConcate) Lac_MemPoolEntryFree(pMemPoolConcate); /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDSA_STAT_INC(numEcdsaSignRSCompleted, pCryptoService); } else { LAC_ECDSA_STAT_INC(numEcdsaSignRSCompletedErrors, pCryptoService); } if ((CPA_FALSE == multiplyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECDSA_STAT_INC(numEcdsaSignRSCompletedOutputInvalid, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pR, pS); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Sign R & S parameter check ***************************************************************************/ STATIC CpaStatus LacEcdsa_SignRSBasicParamCheck(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { /* check for NULL pointers */ LAC_CHECK_NULL_PARAM(pMultiplyStatus); LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pR); LAC_CHECK_NULL_PARAM(pS); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LAC_CHECK_NULL_PARAM(pOpData->a.pData); LAC_CHECK_SIZE(&(pOpData->a), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->b.pData); LAC_CHECK_SIZE(&(pOpData->b), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->q.pData); LAC_CHECK_SIZE(&(pOpData->q), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xg.pData); LAC_CHECK_SIZE(&(pOpData->xg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yg.pData); LAC_CHECK_SIZE(&(pOpData->yg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->n.pData); LAC_CHECK_SIZE(&(pOpData->n), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->m.pData); LAC_CHECK_SIZE(&(pOpData->m), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->d.pData); LAC_CHECK_SIZE(&(pOpData->d), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pR->pData); LAC_CHECK_SIZE(pR, CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pS->pData); LAC_CHECK_SIZE(pS, CHECK_NONE, 0); if (CPA_CY_EC_FIELD_TYPE_PRIME != pOpData->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pOpData->fieldType) { return CPA_STATUS_INVALID_PARAM; } /* Check that q is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->q)); /* Check that n is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->n)); return CPA_STATUS_SUCCESS; } #endif CpaStatus LacEcdsa_OptimisedSignRS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = NULL; CpaBoolean optCurve = CPA_FALSE; Cpa32U functionID = 0; Cpa32U dataOperationSize = 0; pCryptoService = (sal_crypto_service_t *)instanceHandle; if (!pCryptoService->generic_service_info.optimisedCurveSupport) return CPA_STATUS_UNSUPPORTED; #ifdef ICP_PARAM_CHECK Cpa32S compare = 0; /* Check 0 < k < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->k)); compare = LacPke_Compare(&(pOpData->k), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("k is not < n as required"); return CPA_STATUS_INVALID_PARAM; } /* Check 0 < d < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->d)); compare = LacPke_Compare(&(pOpData->d), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("d is not < n as required"); return CPA_STATUS_INVALID_PARAM; } #endif optCurve = LacEcdsa_SignRSGetOptFunctionId(pOpData->fieldType, &(pOpData->q), &(pOpData->n), &(pOpData->a), &(pOpData->b), &dataOperationSize, &functionID); if (optCurve == CPA_FALSE) /* The optimised path is not supported for the curve */ return CPA_STATUS_UNSUPPORTED; icp_qat_fw_mmp_input_param_t inRS = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outRS = {.flat_array = {0}}; lac_pke_op_cb_data_t cbData = {0}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; /* clear output buffers */ osalMemSet(pR->pData, 0, pR->dataLenInBytes); osalMemSet(pS->pData, 0, pS->dataLenInBytes); cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pR; cbData.pOutputData2 = pS; status = LacEcdsa_SignRSFillMMPStructsOpt(&inRS, inArgSizeList, internalMemInList, &outRS, outArgSizeList, internalMemOutList, functionID, dataOperationSize, pOpData, pR, pS); /* Send pke request */ if (CPA_STATUS_SUCCESS == status) { /* build a PKE request */ status = LacPke_SendSingleRequest(functionID, inArgSizeList, outArgSizeList, &inRS, &outRS, internalMemInList, internalMemOutList, LacEcdsa_SignRSCallback, &cbData, instanceHandle); } if (CPA_STATUS_SUCCESS == status) { /* increment stats */ LAC_ECDSA_STAT_INC(numEcdsaSignRSRequests, pCryptoService); } else { /* increment stats */ LAC_ECDSA_STAT_INC(numEcdsaSignRSRequestErrors, pCryptoService); } return status; } /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ CpaStatus cpaCyEcdsaSignRS(const CpaInstanceHandle instanceHandle_in, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { #ifdef ICP_TRACE LAC_LOG7("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pMultiplyStatus, (LAC_ARCH_UINT)pR, (LAC_ARCH_UINT)pS); #endif return LacEcdsa_EcdsaSignRS(instanceHandle_in, pCb, pCallbackTag, pOpData, pMultiplyStatus, pR, pS); } STATIC CpaStatus LacEcdsa_EcdsaSignRS(const CpaInstanceHandle instanceHandle_in, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U dataOperationSizeBytes = 0; CpaInstanceHandle instanceHandle = NULL; sal_crypto_service_t *pCryptoService = NULL; #ifdef ICP_PARAM_CHECK Cpa32S compare = 0; Cpa32U bit_pos_q = 0, bit_pos_x = 0, bit_pos_y = 0; Cpa32U temp = 0; Cpa32U maxModLen = 0; CpaBoolean isZero = CPA_FALSE; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* instance checks - if fail, no inc stats just return */ /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* ensure LAC is initialised - return error if not */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecdsa); pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Check if the API has been called in synchronous mode */ if (NULL == pCb) { /* Call synchronous mode function */ return LacEcdsa_SignRSSyn(instanceHandle, pOpData, pMultiplyStatus, pR, pS); } #ifdef ICP_PARAM_CHECK /* Basic Param Checking */ status = LacEcdsa_SignRSBasicParamCheck(instanceHandle, pOpData, pMultiplyStatus, pR, pS); /* Check that output buffers are big enough */ if (CPA_STATUS_SUCCESS == status) { maxModLen = LacPke_GetMinBytes(&(pOpData->n)); if ((pR->dataLenInBytes < maxModLen) || (pS->dataLenInBytes < maxModLen)) { LAC_INVALID_PARAM_LOG("Output buffer not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { CpaStatus isSupported = CPA_STATUS_SUCCESS; isSupported = LacEcdsa_OptimisedSignRS( instanceHandle, pCb, pCallbackTag, pOpData, pR, pS); /* If LacEcdsa_OptimisedSignRS returns CPA_STATUS_UNSUPPORTED, * this means that the optimised path is not supported for the curve. * Continue with the unoptimised in that case. */ if (CPA_STATUS_UNSUPPORTED != isSupported) return isSupported; } if (CPA_STATUS_SUCCESS == status) { /* Determine size */ status = LacEc_GetRange(LacEcdsa_SignRSOpDataSizeGetMax(pOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if ((LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes) && (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType)) { /* Check if it is a NIST curve if not use 8QW */ LacEc_CheckCurve4QWGF2(&dataOperationSizeBytes, &(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL); } } #ifdef ICP_PARAM_CHECK if ((CPA_STATUS_SUCCESS == status) && (LAC_EC_SIZE_QW9_IN_BYTES == dataOperationSizeBytes)) { /* 9QW checks */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* Check if is is a NIST curve (if not it is an invalid param) */ /* Also checks that xG and yG are less than 2^521 */ status = LacEc_CheckCurve9QWGFP(&(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL, &(pOpData->xg), &(pOpData->yg)); } else { /* Check if is is a NIST curve (if not it is an invalid param) */ /* Also checks that xG and yG are less than 571 bits */ status = LacEc_CheckCurve9QWGF2(&(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL, &(pOpData->xg), &(pOpData->yg)); } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < k < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->k)); compare = LacPke_Compare(&(pOpData->k), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("k is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < d < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->d)); compare = LacPke_Compare(&(pOpData->d), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("d is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Ensure base point is not (0,0) */ if ((0 == LacPke_CompareZero(&(pOpData->xg), 0)) && (0 == LacPke_CompareZero(&(pOpData->yg), 0))) { LAC_INVALID_PARAM_LOG("Invalid base point"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* For GFP check q>3 and xg and yg less than q */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* Ensure q > 3 */ LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); if (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GFP) { LAC_INVALID_PARAM_LOG("q is not > 3 as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure xg < q */ compare = LacPke_Compare(&(pOpData->xg), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("xg is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure yg < q */ compare = LacPke_Compare(&(pOpData->yg), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("yg is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } } /* For GF2 4 and 8 QW check deg(q)>2 and deg(xg) and deg(yg) less than deg(q) (note: already checked for 9QW case) */ if (((LAC_EC_SIZE_QW8_IN_BYTES == dataOperationSizeBytes) || (LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes)) && (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType)) { LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); if (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GF2) { LAC_INVALID_PARAM_LOG("deg(q) is not > 2 as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure deg(xg) < deg(q) for non zero xg */ LacPke_GetBitPos(&(pOpData->xg), &bit_pos_x, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_x >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(xg) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure deg(yg) < deg(q) for non zero yg */ LacPke_GetBitPos(&(pOpData->yg), &bit_pos_y, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_y >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(yg) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } } } #endif if (CPA_STATUS_SUCCESS == status) { Cpa8U *pMemPoolConcate = NULL; Cpa8U *pConcateTemp = NULL; CpaFlatBuffer *pInBuff = NULL; icp_qat_fw_mmp_input_param_t inRS = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outRS = {.flat_array = {0}}; lac_pke_op_cb_data_t cbData = {0}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; Cpa32U functionID = 0; /* clear output buffers */ osalMemSet(pR->pData, 0, pR->dataLenInBytes); osalMemSet(pS->pData, 0, pS->dataLenInBytes); /* Need to concatenate user inputs - copy to ecc mempool memory */ do { pMemPoolConcate = (Cpa8U *)Lac_MemPoolEntryAlloc(pCryptoService->lac_ec_pool); if (NULL == pMemPoolConcate) { LAC_LOG_ERROR("Cannot get mem pool entry"); status = CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pMemPoolConcate) { osalYield(); } } while ((void *)CPA_STATUS_RETRY == pMemPoolConcate); if (CPA_STATUS_SUCCESS == status) { /* Concatenate x,y, n, q, a, b, k, m, d */ pConcateTemp = pMemPoolConcate; LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->d), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->m), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->k), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->b), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->a), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->q), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->n), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->yg), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->xg), dataOperationSizeBytes); pInBuff = (CpaFlatBuffer *)pConcateTemp; pInBuff->dataLenInBytes = (dataOperationSizeBytes * LAC_ECDSA_SIGNRS_NUM_IN_QA_API); pInBuff->pData = pMemPoolConcate; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = pMemPoolConcate; cbData.pOutputData1 = pR; cbData.pOutputData2 = pS; /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS( inArgSizeList, LAC_ECDSA_SIGNRS_NUM_IN_ARGS, (LAC_ECDSA_SIGNRS_NUM_IN_QA_API * dataOperationSizeBytes)); LAC_EC_SET_LIST_PARAMS(outArgSizeList, LAC_ECDSA_SIGNRS_NUM_OUT_ARGS, dataOperationSizeBytes); /* Input memory to QAT is internally allocated */ LAC_EC_SET_LIST_PARAMS( internalMemInList, LAC_ECDSA_SIGNRS_NUM_IN_ARGS, CPA_TRUE); /* Output memory to QAT is externally allocated */ LAC_EC_SET_LIST_PARAMS( internalMemOutList, LAC_ECDSA_SIGNRS_NUM_OUT_ARGS, CPA_FALSE); /* Populate input buffers and output buffers and set function IDs */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaSignRSOpDataWrite( inRS.mmp_ecdsa_sign_rs_gfp_l256, outRS.mmp_ecdsa_sign_rs_gfp_l256, pInBuff, pR, pS); functionID = PKE_ECDSA_SIGN_RS_GFP_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaSignRSOpDataWrite( inRS.mmp_ecdsa_sign_rs_gfp_l512, outRS.mmp_ecdsa_sign_rs_gfp_l512, pInBuff, pR, pS); functionID = PKE_ECDSA_SIGN_RS_GFP_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaSignRSOpDataWrite( inRS.mmp_ecdsa_sign_rs_gfp_521, outRS.mmp_ecdsa_sign_rs_gfp_521, pInBuff, pR, pS); functionID = PKE_ECDSA_SIGN_RS_GFP_521; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } else { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaSignRSOpDataWrite( inRS.mmp_ecdsa_sign_rs_gf2_l256, outRS.mmp_ecdsa_sign_rs_gf2_l256, pInBuff, pR, pS); functionID = PKE_ECDSA_SIGN_RS_GF2_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaSignRSOpDataWrite( inRS.mmp_ecdsa_sign_rs_gf2_l512, outRS.mmp_ecdsa_sign_rs_gf2_l512, pInBuff, pR, pS); functionID = PKE_ECDSA_SIGN_RS_GF2_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaSignRSOpDataWrite( inRS.mmp_ecdsa_sign_rs_gf2_571, outRS.mmp_ecdsa_sign_rs_gf2_571, pInBuff, pR, pS); functionID = PKE_ECDSA_SIGN_RS_GF2_571; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } /* Send pke request */ if (CPA_STATUS_SUCCESS == status) { /* build a PKE request */ status = LacPke_SendSingleRequest(functionID, inArgSizeList, outArgSizeList, &inRS, &outRS, internalMemInList, internalMemOutList, LacEcdsa_SignRSCallback, &cbData, instanceHandle); } if (CPA_STATUS_SUCCESS != status) { /* Free Mem Pool */ if (NULL != pMemPoolConcate) { Lac_MemPoolEntryFree(pMemPoolConcate); } } } } if (CPA_STATUS_SUCCESS == status) { /* increment stats */ LAC_ECDSA_STAT_INC(numEcdsaSignRSRequests, pCryptoService); } else { /* increment stats */ LAC_ECDSA_STAT_INC(numEcdsaSignRSRequestErrors, pCryptoService); } return status; } CpaStatus cpaCyEcdsaDpaSignRS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, const CpaFlatBuffer *pRandom, const CpaBoolean createRandomData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { return CPA_STATUS_UNSUPPORTED; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Verify synchronous function ***************************************************************************/ STATIC CpaStatus LacEcdsa_VerifySyn(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sync_op_data_t *pSyncCallbackData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the asynchronous version of the function * with the generic synchronous callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyEcdsaVerify(instanceHandle, LacSync_GenVerifyCb, pSyncCallbackData, pOpData, pVerifyStatus); } else { LAC_ECDSA_STAT_INC(numEcdsaVerifyRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pVerifyStatus); if (CPA_STATUS_SUCCESS != wCbStatus) { LAC_ECDSA_STAT_INC(numEcdsaVerifyCompletedErrors, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Verify internal callback ***************************************************************************/ STATIC void LacEcdsa_VerifyCallback(CpaStatus status, CpaBoolean verifyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcdsaVerifyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcdsaVerifyOpData *pOpData = NULL; Cpa8U *pMemPoolConcate = NULL; sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyEcdsaVerifyCbFunc)pCbData->pClientCb; pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyEcdsaVerifyOpData *)pCbData->pClientOpData; pMemPoolConcate = (Cpa8U *)(pCbData->pOpaqueData); LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pMemPoolConcate); /* Free Mem Pool Entry */ Lac_MemPoolEntryFree(pMemPoolConcate); /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDSA_STAT_INC(numEcdsaVerifyCompleted, pCryptoService); if (CPA_FALSE == verifyStatus) { LAC_ECDSA_STAT_INC(numEcdsaVerifyCompletedOutputInvalid, pCryptoService); } } else { LAC_ECDSA_STAT_INC(numEcdsaVerifyCompletedErrors, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, verifyStatus); } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ec * ECDSA Verify parameter check ***************************************************************************/ STATIC CpaStatus LacEcdsa_VerifyBasicParamCheck(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { /* check for NULL pointers */ LAC_CHECK_NULL_PARAM(pVerifyStatus); LAC_CHECK_NULL_PARAM(pOpData); /* Check flat buffers in pOpData for NULL and dataLen of 0*/ LAC_CHECK_NULL_PARAM(pOpData->a.pData); LAC_CHECK_SIZE(&(pOpData->a), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->b.pData); LAC_CHECK_SIZE(&(pOpData->b), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->q.pData); LAC_CHECK_SIZE(&(pOpData->q), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xg.pData); LAC_CHECK_SIZE(&(pOpData->xg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yg.pData); LAC_CHECK_SIZE(&(pOpData->yg), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->n.pData); LAC_CHECK_SIZE(&(pOpData->n), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->m.pData); LAC_CHECK_SIZE(&(pOpData->m), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->r.pData); LAC_CHECK_SIZE(&(pOpData->r), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->s.pData); LAC_CHECK_SIZE(&(pOpData->s), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xp.pData); LAC_CHECK_SIZE(&(pOpData->xp), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yp.pData); LAC_CHECK_SIZE(&(pOpData->yp), CHECK_NONE, 0); if (CPA_CY_EC_FIELD_TYPE_PRIME != pOpData->fieldType && CPA_CY_EC_FIELD_TYPE_BINARY != pOpData->fieldType) { return CPA_STATUS_INVALID_PARAM; } /* Check that q is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->q)); /* Check that n is odd */ LAC_CHECK_ODD_PARAM(&(pOpData->n)); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ CpaStatus cpaCyEcdsaVerify(const CpaInstanceHandle instanceHandle_in, const CpaCyEcdsaVerifyCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U dataOperationSizeBytes = 0; sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_PARAM_CHECK Cpa32S compare = 1; Cpa32U bit_pos_q = 0, bit_pos_x = 0, bit_pos_y = 0; Cpa32U temp = 0; CpaBoolean isZero = CPA_FALSE; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* instance checks - if fail, no inc stats just return */ /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* ensure LAC is initialised - return error if not */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecdsa); /* Check if the API has been called in synchronous mode */ if (NULL == pCb) { #ifdef ICP_TRACE #ifdef ICP_PARAM_CHECK /* Check for valid pointers */ LAC_CHECK_NULL_PARAM(pVerifyStatus); #endif status = LacEcdsa_VerifySyn(instanceHandle, pOpData, pVerifyStatus); LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx[%d]\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pVerifyStatus, *pVerifyStatus); return status; #else /* Call synchronous mode function */ return LacEcdsa_VerifySyn(instanceHandle, pOpData, pVerifyStatus); #endif } #ifdef ICP_PARAM_CHECK /* Basic Param Checking */ status = LacEcdsa_VerifyBasicParamCheck(instanceHandle, pOpData, pVerifyStatus); #endif pCryptoService = (sal_crypto_service_t *)instanceHandle; if (CPA_STATUS_SUCCESS == status) { /* Determine size */ status = LacEc_GetRange(LacEcdsa_VerifyOpDataSizeGetMax(pOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if ((LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes) && (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType)) { /* Check if it is a NIST curve if not use 8QW */ LacEc_CheckCurve4QWGF2(&dataOperationSizeBytes, &(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL); } } #ifdef ICP_PARAM_CHECK if ((CPA_STATUS_SUCCESS == status) && (LAC_EC_SIZE_QW9_IN_BYTES == dataOperationSizeBytes)) { /* 9QW checks */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* Check if it is a NIST curve (if not it is an invalid param) */ /* Also checks that xG and yG are less than 2^521 */ status = LacEc_CheckCurve9QWGFP(&(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL, &(pOpData->xg), &(pOpData->yg)); } else { /* Check if it is a NIST curve (if not it is an invalid param) */ /* Also checks that xG and yG are less than 571 bits */ status = LacEc_CheckCurve9QWGF2(&(pOpData->q), &(pOpData->a), &(pOpData->b), &(pOpData->n), NULL, &(pOpData->xg), &(pOpData->yg)); } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < r < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->r)); compare = LacPke_Compare(&(pOpData->r), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("r is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Check 0 < s < n */ LAC_CHECK_NON_ZERO_PARAM(&(pOpData->s)); compare = LacPke_Compare(&(pOpData->s), 0, &(pOpData->n), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("s is not < n as required"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Ensure base point is not (0,0) */ if ((0 == LacPke_CompareZero(&(pOpData->xg), 0)) && (0 == LacPke_CompareZero(&(pOpData->yg), 0))) { LAC_INVALID_PARAM_LOG("Invalid base point"); status = CPA_STATUS_INVALID_PARAM; } /* For GFP check q>3 and xg and yg less than q */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); if (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GFP) { LAC_INVALID_PARAM_LOG("q is not > 3 as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure xg < q */ compare = LacPke_Compare(&(pOpData->xg), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("xg is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure yg < q */ compare = LacPke_Compare(&(pOpData->yg), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("yg is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } } /* For GF2 8QW check deg(q)>2 (already done for GF2 4QW) and for GF2 4QW and 8QW check deg(xg) and deg(yg) less than deg(q). (note: already checked for 9QW case) */ if (((LAC_EC_SIZE_QW8_IN_BYTES == dataOperationSizeBytes) || (LAC_EC_SIZE_QW4_IN_BYTES == dataOperationSizeBytes)) && (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType)) { LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); if ((LAC_EC_SIZE_QW8_IN_BYTES == dataOperationSizeBytes) && (bit_pos_q < LAC_EC_MIN_MOD_BIT_POS_GF2)) { LAC_INVALID_PARAM_LOG("deg(q) is not > 2 as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure deg(xg) < deg(q) for non zero xg */ LacPke_GetBitPos(&(pOpData->xg), &bit_pos_x, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_x >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(xg) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure deg(yg) < deg(q) for non zero yg */ LacPke_GetBitPos(&(pOpData->yg), &bit_pos_y, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_y >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(yg) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } } } if (CPA_STATUS_SUCCESS == status) { /* Ensure public key is not (0,0) */ if ((0 == LacPke_CompareZero(&(pOpData->xp), 0)) && (0 == LacPke_CompareZero(&(pOpData->yp), 0))) { LAC_INVALID_PARAM_LOG("Invalid public point"); status = CPA_STATUS_INVALID_PARAM; } /* For GFP check xp and yp less than q */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { /* Ensure xp < q */ compare = LacPke_Compare(&(pOpData->xp), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("xp is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure yp < q */ compare = LacPke_Compare(&(pOpData->yp), 0, &(pOpData->q), 0); if (compare >= 0) { LAC_INVALID_PARAM_LOG("yp is not < q as required"); status = CPA_STATUS_INVALID_PARAM; } } /* For GF2 check deg(xp) and deg(yp) less than deg(q) */ if (CPA_CY_EC_FIELD_TYPE_BINARY == pOpData->fieldType) { LacPke_GetBitPos(&(pOpData->q), &bit_pos_q, &temp, &isZero); /* Note we know deg(q)>2 and it is odd */ /* Ensure deg(xp) < deg(q) for non zero xp */ LacPke_GetBitPos(&(pOpData->xp), &bit_pos_x, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_x >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(xp) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } /* Ensure deg(yp) < deg(q) for non zero yg */ LacPke_GetBitPos(&(pOpData->yp), &bit_pos_y, &temp, &isZero); if ((CPA_TRUE != isZero) && (bit_pos_y >= bit_pos_q)) { LAC_INVALID_PARAM_LOG("deg(yp) is not < deg(q) as required"); status = CPA_STATUS_INVALID_PARAM; } } } #endif if (CPA_STATUS_SUCCESS == status) { Cpa8U *pMemPoolConcate = NULL; Cpa8U *pConcateTemp = NULL; CpaFlatBuffer *pInBuff = NULL; Cpa32U functionID = 0; icp_qat_fw_mmp_input_param_t inVerify = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outVerify = {.flat_array = {0}}; lac_pke_op_cb_data_t cbData = {0}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; /* Need to concatenate user inputs - copy to ecc mempool memory */ do { pMemPoolConcate = (Cpa8U *)Lac_MemPoolEntryAlloc(pCryptoService->lac_ec_pool); if (NULL == pMemPoolConcate) { LAC_LOG_ERROR("Cannot get mem pool entry"); /* increment stats */ LAC_ECDSA_STAT_INC(numEcdsaVerifyRequestErrors, pCryptoService); status = CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pMemPoolConcate) { osalYield(); } } while ((void *)CPA_STATUS_RETRY == pMemPoolConcate); if (CPA_STATUS_SUCCESS == status) { /* Concatenate q, b, a, yp, xp, yg, xg, n, r, s, m */ /* Only concatenates least dataOperationSizeBytes bits of the buffers as this is all of interest to PKE rest of buffer is zero (see previous checks) */ pConcateTemp = pMemPoolConcate; LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->q), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->b), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->a), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->yp), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->xp), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->yg), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->xg), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->n), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->r), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->s), dataOperationSizeBytes); LacEc_FlatBuffToConcate( &pConcateTemp, &(pOpData->m), dataOperationSizeBytes); pInBuff = (CpaFlatBuffer *)pConcateTemp; pInBuff->dataLenInBytes = (dataOperationSizeBytes * LAC_ECDSA_VERIFY_NUM_IN_QA_API); pInBuff->pData = pMemPoolConcate; /* populate callback data */ cbData.pClientCb = pCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pOpData; cbData.pOpaqueData = pMemPoolConcate; /* Set the size for all parameters to be padded to */ LAC_EC_SET_LIST_PARAMS( inArgSizeList, LAC_ECDSA_VERIFY_NUM_IN_ARGS, (LAC_ECDSA_VERIFY_NUM_IN_QA_API * dataOperationSizeBytes)); /* Input Memory to QAT is internally allocated */ internalMemInList[0] = CPA_TRUE; /* Populate input buffers and output buffers and set function IDs */ if (CPA_CY_EC_FIELD_TYPE_PRIME == pOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaVerifyOpDataWrite( inVerify.mmp_ecdsa_verify_gfp_l256, pInBuff); functionID = PKE_ECDSA_VERIFY_GFP_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaVerifyOpDataWrite( inVerify.mmp_ecdsa_verify_gfp_l512, pInBuff); functionID = PKE_ECDSA_VERIFY_GFP_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaVerifyOpDataWrite( inVerify.mmp_ecdsa_verify_gfp_521, pInBuff); functionID = PKE_ECDSA_VERIFY_GFP_521; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } else { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: LacEcdsaVerifyOpDataWrite( inVerify.mmp_ecdsa_verify_gf2_l256, pInBuff); functionID = PKE_ECDSA_VERIFY_GF2_L256; break; case LAC_EC_SIZE_QW8_IN_BYTES: LacEcdsaVerifyOpDataWrite( inVerify.mmp_ecdsa_verify_gf2_l512, pInBuff); functionID = PKE_ECDSA_VERIFY_GF2_L512; break; case LAC_EC_SIZE_QW9_IN_BYTES: LacEcdsaVerifyOpDataWrite( inVerify.mmp_ecdsa_verify_gf2_571, pInBuff); functionID = PKE_ECDSA_VERIFY_GF2_571; break; default: status = CPA_STATUS_INVALID_PARAM; break; } } /* Send pke request */ if (CPA_STATUS_SUCCESS == status) { /* build a PKE request */ status = LacPke_SendSingleRequest(functionID, inArgSizeList, NULL, &inVerify, &outVerify, internalMemInList, NULL, LacEcdsa_VerifyCallback, &cbData, instanceHandle); } if (CPA_STATUS_SUCCESS != status) { /* Free Mem Pool */ if (NULL != pMemPoolConcate) { Lac_MemPoolEntryFree(pMemPoolConcate); } } } } /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECDSA_STAT_INC(numEcdsaVerifyRequests, pCryptoService); } else { LAC_ECDSA_STAT_INC(numEcdsaVerifyRequestErrors, pCryptoService); } return status; } /** *************************************************************************** * @ingroup Lac_Ec * ***************************************************************************/ CpaStatus cpaCyEcdsaQueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyEcdsaStats64 *pEcdsaStats) { sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pEcdsaStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_RUNNING_CHECK(instanceHandle); /* ensure this is a crypto or asym instance with pke enabled */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, ecdsa); LAC_CHECK_NULL_PARAM(pEcdsaStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; /* get stats into user supplied stats structure */ LAC_ECDSA_STATS_GET(*pEcdsaStats, pCryptoService); return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_ecsm2.c000066400000000000000000003515771503624047500312420ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * * @file lac_ecsm2.c * * @ingroup Lac_Ecsm2 * * SM2 functions * SM2 algorithm is using a fixed EC curve. * The length of the params is fixed to LAC_EC_SM2_SIZE_BYTES(32 bytes). * More details in http://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 * * @lld_start * * @lld_overview * This file implements SM2 api functions. * @lld_dependencies * - \ref LacAsymCommonQatComms "PKE QAT Comms" : For creating and sending * messages to the QAT * - \ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_initialisation * On initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * ***************************************************************************/ /* * **************************************************************************** * * Include public/global header files * **************************************************************************** * */ /* API Includes */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_ecsm2.h" /* OSAL Includes */ #include "Osal.h" /* ADF Includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* QAT Includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" #include "icp_qat_fw_pke.h" /* Lookaside Includes */ #include "lac_log.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_sync.h" #include "lac_ec.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "sal_statistics.h" #define LAC_EC_SM2_SIZE_BYTES LAC_BITS_TO_BYTES(LAC_256_BITS) /**< number of ECSM2 statistics */ #define LAC_ECSM2_NUM_STATS (sizeof(CpaCyEcsm2Stats64) / sizeof(Cpa64U)) #ifndef DISABLE_STATS #define LAC_ECSM2_STAT_INC(statistic, pCryptoService) \ do \ { \ if (CPA_TRUE == \ pCryptoService->generic_service_info.stats->bEccStatsEnabled) \ { \ osalAtomicInc(&(pCryptoService) \ ->pLacEcsm2StatsArr[offsetof(CpaCyEcsm2Stats64, \ statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) /**< @ingroup Lac_Ec * macro to increment a ECSM2 stat (derives offset into array of atomics) */ #else #define LAC_ECSM2_STAT_INC(statistic, pCryptoService) \ (pCryptoService) = (pCryptoService) #endif #define LAC_ECSM2_STATS_GET(ecsm2Stats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_ECSM2_NUM_STATS; i++) \ { \ ((Cpa64U *)&(ecsm2Stats))[i] = \ osalAtomicGet(&pCryptoService->pLacEcsm2StatsArr[i]); \ } \ } while (0) /**< @ingroup Lac_Ec * macro to collect an ECDSA stat in sample period of performance counters */ #if defined(COUNTERS) && !defined(DISABLE_STATS) #define LAC_ECSM2_TIMESTAMP_BEGIN(pCbData, operationDir, instanceHandle) \ LacEcsm2_StatsBegin(pCbData, operationDir, instanceHandle); #define LAC_ECSM2_TIMESTAMP_END(pCbData, operationDir, instanceHandle) \ LacEcsm2_StatsEnd(pCbData, operationDir, instanceHandle); void LacEcsm2_StatsBegin(void *pCbData, ecsm2_request_type_t operationDir, CpaInstanceHandle instanceHandle); void LacEcsm2_StatsEnd(void *pCbData, ecsm2_request_type_t operationDir, CpaInstanceHandle instanceHandle); #else #define LAC_ECSM2_TIMESTAMP_BEGIN(pCbData, operationDir, instanceHandle) #define LAC_ECSM2_TIMESTAMP_END(pCbData, operationDir, instanceHandle) #endif /* **************************************************************************** * Define static function definitions **************************************************************************** */ /** *************************************************************************** * @ingroup Lac_Ecsm2 * return the size in bytes of biggest number in * CpaCyEcsm2PointMultiplyOpData * * @description * return the size of the biggest number in * CpaCyEcsm2PointMultiplyOpData. * * @param[in] pOpData Pointer to a CpaCyEcsm2PointMultiplyOpData structure * * @retval max the size in bytes of the biggest number * ***************************************************************************/ STATIC Cpa32U LacEcsm2_PointMulOpDataSizeGetMax(const CpaCyEcsm2PointMultiplyOpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->x)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->y)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); return max; } STATIC Cpa32U LacEcsm2_GeneratorMulOpDataSizeGetMax( const CpaCyEcsm2GeneratorMultiplyOpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); return max; } STATIC Cpa32U LacEcsm2_PointVerifyOpDataSizeGetMax(const CpaCyEcsm2PointVerifyOpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->x)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->y)), max); return max; } STATIC Cpa32U LacEcsm2_SignOpDataSizeGetMax(const CpaCyEcsm2SignOpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->e)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->d)), max); return max; } STATIC Cpa32U LacEcsm2_VerifyOpDataSizeGetMax(const CpaCyEcsm2VerifyOpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->e)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->r)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->s)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xP)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yP)), max); return max; } STATIC Cpa32U LacEcsm2_EncOpDataSizeGetMax(const CpaCyEcsm2EncryptOpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->k)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xP)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yP)), max); return max; } STATIC Cpa32U LacEcsm2_DecOpDataSizeGetMax(const CpaCyEcsm2DecryptOpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->d)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->x1)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->y1)), max); return max; } STATIC Cpa32U LacEcsm2_KeyExPhase1OpDataSizeGetMax(const CpaCyEcsm2KeyExPhase1OpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->r)), max); return max; } STATIC Cpa32U LacEcsm2_KeyExPhase2OpDataSizeGetMax(const CpaCyEcsm2KeyExPhase2OpData *pOpData) { Cpa32U max = 0; /* Get maximal size in bytes with number of input buffers */ max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->r)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->d)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->x1)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->x2)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->y2)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->xP)), max); max = LAC_MAX(LacPke_GetMinBytes(&(pOpData->yP)), max); return max; } /********************************************************************** * @ingroup Lac_Ecsm2 * SM2 Signature synchronous function * **********************************************************************/ STATIC CpaStatus LacEcsm2_SignSyn(const CpaInstanceHandle instanceHandle, const CpaCyEcsm2SignOpData *pEcsm2SignOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the synchronous callback * function as a parameter. */ status = cpaCyEcsm2Sign(instanceHandle, (CpaCyEcsm2SignCbFunc)LacSync_GenDualFlatBufVerifyCb, pSyncCallbackData, pEcsm2SignOpData, pSignStatus, pR, pS); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pSignStatus); if ((CPA_STATUS_SUCCESS != wCbStatus) || (CPA_TRUE != *pSignStatus)) { status = wCbStatus; LAC_LOG("ECSM2 SIGN FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * SM2 signature verify synchronous function ***************************************************************************/ STATIC CpaStatus LacEcsm2_VerifySyn(const CpaInstanceHandle instanceHandle, const CpaCyEcsm2VerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the generic synchronous callback * function as a parameter. */ status = cpaCyEcsm2Verify(instanceHandle, (CpaCyEcsm2VerifyCbFunc)LacSync_GenVerifyCb, pSyncCallbackData, pOpData, pVerifyStatus); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pVerifyStatus); if (CPA_STATUS_SUCCESS != wCbStatus || CPA_TRUE != *pVerifyStatus) { status = wCbStatus; LAC_LOG("ECSM2 SIGN VERIFY FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /********************************************************************** * @ingroup Lac_Ecsm2 * SM2 point multiply synchronous function * **********************************************************************/ STATIC CpaStatus LacEcsm2_PointMultiplySyn( const CpaInstanceHandle instanceHandle, const CpaCyEcsm2PointMultiplyOpData *pEcsm2PointMulOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the synchronous callback * function as a parameter. */ status = cpaCyEcsm2PointMultiply( instanceHandle, (CpaCyEcPointMultiplyCbFunc)LacSync_GenDualFlatBufVerifyCb, pSyncCallbackData, pEcsm2PointMulOpData, pMultiplyStatus, pXk, pYk); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != wCbStatus || CPA_TRUE != *pMultiplyStatus) { status = wCbStatus; LAC_LOG("ECSM2 POINT MULTIPLY FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /********************************************************************** * @ingroup Lac_Ecsm2 * SM2 generator multiply synchronous function * **********************************************************************/ STATIC CpaStatus LacEcsm2_GenMultiplySyn( const CpaInstanceHandle instanceHandle, const CpaCyEcsm2GeneratorMultiplyOpData *pEcsm2GenMulOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pXy) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the synchronous callback * function as a parameter. */ status = cpaCyEcsm2GeneratorMultiply( instanceHandle, (CpaCyEcPointMultiplyCbFunc)LacSync_GenDualFlatBufVerifyCb, pSyncCallbackData, pEcsm2GenMulOpData, pMultiplyStatus, pXk, pXy); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pMultiplyStatus); if (CPA_STATUS_SUCCESS != wCbStatus || CPA_TRUE != *pMultiplyStatus) { status = wCbStatus; LAC_LOG("ECSM2 GENERATOR MULTIPLY FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 point verify synchronous function ***************************************************************************/ STATIC CpaStatus LacEcsm2_PointVerifySyn(const CpaInstanceHandle instanceHandle, const CpaCyEcsm2PointVerifyOpData *pOpData, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the generic synchronous callback * function as a parameter. */ status = cpaCyEcsm2PointVerify(instanceHandle, (CpaCyEcPointVerifyCbFunc)LacSync_GenVerifyCb, pSyncCallbackData, pOpData, pVerifyStatus); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pVerifyStatus); if (CPA_STATUS_SUCCESS != wCbStatus || CPA_TRUE != *pVerifyStatus) { status = wCbStatus; LAC_LOG("ECSM2 POINT VERIFY FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /********************************************************************** * @ingroup Lac_Ecsm2 * SM2 Encryption synchronous function * **********************************************************************/ STATIC CpaStatus LacEcsm2_EncSyn(const CpaInstanceHandle instanceHandle, const CpaCyEcsm2EncryptOpData *pEcsm2EncOpData, CpaCyEcsm2EncryptOutputData *pEcsm2EncOutput) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the synchronous callback * function as a parameter. */ status = cpaCyEcsm2Encrypt(instanceHandle, (CpaCyGenFlatBufCbFunc)LacSync_GenFlatBufCb, pSyncCallbackData, pEcsm2EncOpData, pEcsm2EncOutput); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { status = wCbStatus; LAC_LOG("ECSM2 ENCRYPTION FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /********************************************************************** * @ingroup Lac_Ecsm2 * SM2 Decryption synchronous function * **********************************************************************/ STATIC CpaStatus LacEcsm2_DecSyn(const CpaInstanceHandle instanceHandle, const CpaCyEcsm2DecryptOpData *pEcsm2DecOpData, CpaCyEcsm2DecryptOutputData *pEcsm2DecOutput) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the synchronous callback * function as a parameter. */ status = cpaCyEcsm2Decrypt(instanceHandle, (CpaCyGenFlatBufCbFunc)LacSync_GenFlatBufCb, pSyncCallbackData, pEcsm2DecOpData, pEcsm2DecOutput); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { status = wCbStatus; LAC_LOG("ECSM2 DECRYPTION FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /********************************************************************** * @ingroup Lac_Ecsm2 * SM2 key exchange phase 1 synchronous function * **********************************************************************/ STATIC CpaStatus LacEcsm2_KeyexPhase1Syn( const CpaInstanceHandle instanceHandle, const CpaCyEcsm2KeyExPhase1OpData *pEcsm2KeyExPhase1OpData, CpaCyEcsm2KeyExOutputData *pEcsm2KeyExPhase1OutputData) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the synchronous callback * function as a parameter. */ status = cpaCyEcsm2KeyExPhase1(instanceHandle, (CpaCyGenFlatBufCbFunc)LacSync_GenFlatBufCb, pSyncCallbackData, pEcsm2KeyExPhase1OpData, pEcsm2KeyExPhase1OutputData); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { status = wCbStatus; LAC_LOG("ECSM2 KEY EXCHANGE PHASE 1 FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /********************************************************************** * @ingroup Lac_Ecsm2 * SM2 key exchange phase 2 synchronous function * **********************************************************************/ STATIC CpaStatus LacEcsm2_KeyexPhase2Syn( const CpaInstanceHandle instanceHandle, const CpaCyEcsm2KeyExPhase2OpData *pEcsm2KeyExPhase2OpData, CpaCyEcsm2KeyExOutputData *pEcsm2KeyExPhase2OutputData) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus wCbStatus = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { /* Call the asynchronous version of the function * with the synchronous callback * function as a parameter. */ status = cpaCyEcsm2KeyExPhase2(instanceHandle, (CpaCyGenFlatBufCbFunc)LacSync_GenFlatBufCb, pSyncCallbackData, pEcsm2KeyExPhase2OpData, pEcsm2KeyExPhase2OutputData); } else { return status; } if (CPA_STATUS_SUCCESS == status) { wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { status = wCbStatus; LAC_LOG("ECSM2 KEY EXCHANGE PHASE 2 FAILED!!\n"); } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we are finished * with cookie so that it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Signature internal callback ***************************************************************************/ STATIC void LacEcsm2_SignCb(CpaStatus status, CpaBoolean signStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcsm2SignCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2SignOpData *pOpData = NULL; CpaFlatBuffer *pR = NULL; CpaFlatBuffer *pS = NULL; /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyEcsm2SignCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pR = pCbData->pOutputData1; pS = pCbData->pOutputData2; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment Sign stats */ LAC_ECSM2_TIMESTAMP_END(pCbData, LAC_ECSM2_SIGN_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2SignCompleted, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2SignCompletedError, pCryptoService); } if ((CPA_FALSE == signStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2SignCompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, signStatus, pR, pS); } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Signature Verify internal callback ***************************************************************************/ STATIC void LacEcsm2_VerifyCb(CpaStatus status, CpaBoolean verifyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcsm2VerifyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2VerifyOpData *pOpData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyEcsm2VerifyCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); #ifndef DISABLE_STATS /* Increment Verify stats */ LAC_ECSM2_TIMESTAMP_END(pCbData, LAC_ECSM2_VERIFY_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2VerifyCompleted, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2VerifyCompletedError, pCryptoService); } if ((CPA_FALSE == verifyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2VerifyCompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, verifyStatus); } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Encryption internal callback ***************************************************************************/ STATIC void LacEcsm2_EncCb(CpaStatus status, CpaBoolean encStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2EncryptOpData *pOpData = NULL; CpaCyEcsm2EncryptOutputData *pOutData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOutData = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pOutData); #ifndef DISABLE_STATS /* Increment Enc stats */ LAC_ECSM2_TIMESTAMP_END(pCbData, LAC_ECSM2_ENC_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2EncryptCompleted, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2EncryptCompletedError, pCryptoService); } if ((CPA_FALSE == encStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2EncryptCompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, (void *)pOutData); } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Decryption internal callback ***************************************************************************/ STATIC void LacEcsm2_DecCb(CpaStatus status, CpaBoolean decStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2DecryptOpData *pOpData = NULL; CpaCyEcsm2DecryptOutputData *pOutData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOutData = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pOutData); #ifndef DISABLE_STATS /* Increment Decrypt stats */ LAC_ECSM2_TIMESTAMP_END(pCbData, LAC_ECSM2_DEC_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2DecryptCompleted, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2DecryptCompletedError, pCryptoService); } if ((CPA_FALSE == decStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2DecryptCompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, (void *)pOutData); } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Key Exchange Phase 1 internal callback ***************************************************************************/ STATIC void LacEcsm2_KeyExPhase1Cb(CpaStatus status, CpaBoolean keyexStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2KeyExPhase1OpData *pOpData = NULL; CpaCyEcsm2KeyExOutputData *pOutData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOutData = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pOutData); #ifndef DISABLE_STATS /* Increment Key Exchange Phase1 stats */ LAC_ECSM2_TIMESTAMP_END( pCbData, LAC_ECSM2_KEY_EXCHANGE_P1_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase1Completed, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase1CompletedError, pCryptoService); } if ((CPA_FALSE == keyexStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase1CompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, (void *)pOutData); } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Key Exchange Phase 2 internal callback ***************************************************************************/ STATIC void LacEcsm2_KeyExPhase2Cb(CpaStatus status, CpaBoolean keyexStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2KeyExPhase2OpData *pOpData = NULL; CpaCyEcsm2KeyExOutputData *pOutData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOutData = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pOutData); #ifndef DISABLE_STATS /* Increment Key Exchange Phase 2 stats */ LAC_ECSM2_TIMESTAMP_END( pCbData, LAC_ECSM2_KEY_EXCHANGE_P2_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase2Completed, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase2CompletedError, pCryptoService); } if ((CPA_FALSE == keyexStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase2CompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, (void *)pOutData); } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Point Multiplication internal callback ***************************************************************************/ STATIC void LacEcsm2_PointMulCb(CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcPointMultiplyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2PointMultiplyOpData *pOpData = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyEcPointMultiplyCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pXk = pCbData->pOutputData1; pYk = pCbData->pOutputData2; LAC_ASSERT_NOT_NULL(pXk); LAC_ASSERT_NOT_NULL(pYk); #ifndef DISABLE_STATS /* Increment Point Multiply stats */ LAC_ECSM2_TIMESTAMP_END( pCbData, LAC_ECSM2_POINT_MULTIPLY_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2PointMultiplyCompleted, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2PointMultiplyCompletedError, pCryptoService); } if ((CPA_FALSE == multiplyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2PointMultiplyCompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pXk, pYk); } /*************************************************************************** * @ingroup Lac_Ecsm2 * SM2 Generator Multiplication internal callback ***************************************************************************/ STATIC void LacEcsm2_GenMulCb(CpaStatus status, CpaBoolean multiplyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcPointMultiplyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2GeneratorMultiplyOpData *pOpData = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyEcPointMultiplyCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pXk = pCbData->pOutputData1; pYk = pCbData->pOutputData2; LAC_ASSERT_NOT_NULL(pXk); LAC_ASSERT_NOT_NULL(pYk); #ifndef DISABLE_STATS /* Increment Point Generator stats */ LAC_ECSM2_TIMESTAMP_END( pCbData, LAC_ECSM2_GEN_POINT_MULTIPLY_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2GeneratorMultiplyCompleted, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2GeneratorMultiplyCompletedError, pCryptoService); } if ((CPA_FALSE == multiplyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2GeneratorMultiplyCompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, multiplyStatus, pXk, pYk); } /*************************************************************************** * @ingroup Lac_Ecsm2 * EC Point Verify internal callback ***************************************************************************/ STATIC void LacEcsm2_PointVerifyCb(CpaStatus status, CpaBoolean verifyStatus, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyEcPointVerifyCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyEcsm2PointVerifyOpData *pOpData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* Extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (void *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCb = (CpaCyEcPointVerifyCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); #ifndef DISABLE_STATS /* Increment Point Verify stats */ LAC_ECSM2_TIMESTAMP_END( pCbData, LAC_ECSM2_POINT_VERIFY_REQUEST, instanceHandle); if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2PointVerifyCompleted, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2PointVerifyCompletedError, pCryptoService); } if ((CPA_FALSE == verifyStatus) && (CPA_STATUS_SUCCESS == status)) { LAC_ECSM2_STAT_INC(numEcsm2PointVerifyCompletedOutputInvalid, pCryptoService); } #endif /* Invoke the user callback */ pCb(pCallbackTag, status, pOpData, verifyStatus); } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Check if SM2 is supported by ***************************************************************************/ STATIC CpaStatus LacEcsm2_HwCapabilityCheck(const CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCyCapabilitiesInfo capInfo = { 0 }; status = cpaCyQueryCapabilities(instanceHandle, &capInfo); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("Failed to query instance capabilities"); return status; } if (!capInfo.ecSm2Supported) { LAC_UNSUPPORTED_PARAM_LOG("Unsupported Algorithm ECSM2"); return CPA_STATUS_UNSUPPORTED; } return status; } #ifdef ICP_PARAM_CHECK /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Point Multiply function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_PointMultiplyBasicParamCheck( const CpaCyEcsm2PointMultiplyOpData *pOpData, const CpaBoolean *pMultiplyStatus, const CpaFlatBuffer *pXk, const CpaFlatBuffer *pYk) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pMultiplyStatus); LAC_CHECK_NULL_PARAM(pXk); LAC_CHECK_NULL_PARAM(pYk); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->x.pData); LAC_CHECK_SIZE(&(pOpData->x), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->y.pData); LAC_CHECK_SIZE(&(pOpData->y), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pXk->pData); LAC_CHECK_SIZE(pXk, CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pYk->pData); LAC_CHECK_SIZE(pYk, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Generator Multiply function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_GenMultiplyBasicParamCheck( const CpaCyEcsm2GeneratorMultiplyOpData *pOpData, const CpaBoolean *pMultiplyStatus, const CpaFlatBuffer *pXk, const CpaFlatBuffer *pYk) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pMultiplyStatus); LAC_CHECK_NULL_PARAM(pXk); LAC_CHECK_NULL_PARAM(pYk); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pXk->pData); LAC_CHECK_SIZE(pXk, CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pYk->pData); LAC_CHECK_SIZE(pYk, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Point Verify function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_PointVerifyBasicParamCheck(const CpaCyEcsm2PointVerifyOpData *pOpData, const CpaBoolean *pVerifyStatus) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pVerifyStatus); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->x.pData); LAC_CHECK_SIZE(&(pOpData->x), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->y.pData); LAC_CHECK_SIZE(&(pOpData->y), CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Signature function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_SignBasicParamCheck(const CpaBoolean *pSignStatus, const CpaCyEcsm2SignOpData *pOpData, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pSignStatus); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->e.pData); LAC_CHECK_SIZE(&(pOpData->e), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->d.pData); LAC_CHECK_SIZE(&(pOpData->d), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pR); LAC_CHECK_NULL_PARAM(pS); LAC_CHECK_NULL_PARAM(pR->pData); LAC_CHECK_SIZE(pR, CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pS->pData); LAC_CHECK_SIZE(pS, CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Signature Verify function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_VerifyBasicParamCheck(const CpaCyEcsm2VerifyOpData *pOpData, const CpaBoolean *pVerifyStatus) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pVerifyStatus); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->e.pData); LAC_CHECK_SIZE(&(pOpData->e), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->r.pData); LAC_CHECK_SIZE(&(pOpData->r), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->s.pData); LAC_CHECK_SIZE(&(pOpData->s), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xP.pData); LAC_CHECK_SIZE(&(pOpData->xP), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yP.pData); LAC_CHECK_SIZE(&(pOpData->yP), CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Encryption function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_EncBasicParamCheck(const CpaCyEcsm2EncryptOpData *pOpData, const CpaCyEcsm2EncryptOutputData *pOut) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->k.pData); LAC_CHECK_SIZE(&(pOpData->k), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xP.pData); LAC_CHECK_SIZE(&(pOpData->xP), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yP.pData); LAC_CHECK_SIZE(&(pOpData->yP), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut); LAC_CHECK_NULL_PARAM(pOut->x1.pData); LAC_CHECK_SIZE(&(pOut->x1), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut->y1.pData); LAC_CHECK_SIZE(&(pOut->y1), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut->x2.pData); LAC_CHECK_SIZE(&(pOut->x2), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut->y2.pData); LAC_CHECK_SIZE(&(pOut->y2), CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Decryption function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_DecBasicParamCheck(const CpaCyEcsm2DecryptOpData *pOpData, const CpaCyEcsm2DecryptOutputData *pOut) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->d.pData); LAC_CHECK_SIZE(&(pOpData->d), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->x1.pData); LAC_CHECK_SIZE(&(pOpData->x1), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->y1.pData); LAC_CHECK_SIZE(&(pOpData->y1), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut); LAC_CHECK_NULL_PARAM(pOut->x2.pData); LAC_CHECK_SIZE(&(pOut->x2), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut->y2.pData); LAC_CHECK_SIZE(&(pOut->y2), CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Key Exchange Phase1 function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_KeyExPhase1BasicParamCheck(const CpaCyEcsm2KeyExPhase1OpData *pOpData, const CpaCyEcsm2KeyExOutputData *pOut) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->r.pData); LAC_CHECK_SIZE(&(pOpData->r), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut); LAC_CHECK_NULL_PARAM(pOut->x.pData); LAC_CHECK_SIZE(&(pOut->x), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut->y.pData); LAC_CHECK_SIZE(&(pOut->y), CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * ECSM2 Key Exchange Phase2 function to perform basic checks on the IN * parameters (e.g. checks data buffers for NULL and 0 dataLen) ***************************************************************************/ STATIC CpaStatus LacEcsm2_KeyExPhase2BasicParamCheck(const CpaCyEcsm2KeyExPhase2OpData *pOpData, const CpaCyEcsm2KeyExOutputData *pOut) { /* Check for null parameters */ LAC_CHECK_NULL_PARAM(pOpData); /* Check flat buffers in pOpData for NULL and dataLen of 0 */ LAC_CHECK_NULL_PARAM(pOpData->r.pData); LAC_CHECK_SIZE(&(pOpData->r), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->d.pData); LAC_CHECK_SIZE(&(pOpData->d), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->x1.pData); LAC_CHECK_SIZE(&(pOpData->x1), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->x2.pData); LAC_CHECK_SIZE(&(pOpData->x2), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->y2.pData); LAC_CHECK_SIZE(&(pOpData->y2), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->xP.pData); LAC_CHECK_SIZE(&(pOpData->xP), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOpData->yP.pData); LAC_CHECK_SIZE(&(pOpData->yP), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut); LAC_CHECK_NULL_PARAM(pOut->x.pData); LAC_CHECK_SIZE(&(pOut->x), CHECK_NONE, 0); LAC_CHECK_NULL_PARAM(pOut->y.pData); LAC_CHECK_SIZE(&(pOut->y), CHECK_NONE, 0); return CPA_STATUS_SUCCESS; } #endif /* ICP_PARAM_CHECK */ /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 point multiplication operation * ***************************************************************************/ CpaStatus cpaCyEcsm2PointMultiply( const CpaInstanceHandle instanceHandle_in, const CpaCyEcPointMultiplyCbFunc pEcsm2PointMulCb, void *pCallbackTag, const CpaCyEcsm2PointMultiplyOpData *pEcsm2PointMulOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2PointMulCb) { /* Call synchronous mode function */ return LacEcsm2_PointMultiplySyn( instanceHandle, pEcsm2PointMulOpData, pMultiplyStatus, pXk, pYk); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_PointMultiplyBasicParamCheck( pEcsm2PointMulOpData, pMultiplyStatus, pXk, pYk); if (status == CPA_STATUS_SUCCESS) { /* Check that output buffers are big enough * for SM2 algorithm, the length is fixed, * equal to LAC_EC_SM2_SIZE_BYTES (32 bytes) */ if ((pXk->dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pYk->dataLenInBytes < LAC_EC_SM2_SIZE_BYTES)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { /* Determine size - based on input numbers */ status = LacEc_GetRange( LacEcsm2_PointMulOpDataSizeGetMax(pEcsm2PointMulOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2PointMulOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_POINT_MULTIPLICATION; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR( inArgList.mmp_ecsm2_point_multiplication.k, &(pEcsm2PointMulOpData->k)); pInArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_input_t, k)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_input_t, k)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( inArgList.mmp_ecsm2_point_multiplication.x, &(pEcsm2PointMulOpData->x)); pInArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_input_t, x)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_input_t, x)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( inArgList.mmp_ecsm2_point_multiplication.y, &(pEcsm2PointMulOpData->y)); pInArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_input_t, y)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_input_t, y)] = CPA_FALSE; /* Fill output list, x,y */ LAC_MEM_SHARED_WRITE_FROM_PTR( outArgList.mmp_ecsm2_point_multiplication.xd, pXk); pOutArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, xd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, xd)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( outArgList.mmp_ecsm2_point_multiplication.yd, pYk); pOutArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, yd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, yd)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2PointMulOpData; cbData.pClientCb = pEcsm2PointMulCb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pXk; cbData.pOutputData2 = pYk; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_POINT_MULTIPLY_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_PointMulCb, &cbData, instanceHandle); } #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2PointMultiplyRequests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2PointMultiplyRequestErrors, pCryptoService); } #endif return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 point generator multiplication operation * ***************************************************************************/ CpaStatus cpaCyEcsm2GeneratorMultiply( const CpaInstanceHandle instanceHandle_in, const CpaCyEcPointMultiplyCbFunc pEcsm2GenMulCb, void *pCallbackTag, const CpaCyEcsm2GeneratorMultiplyOpData *pEcsm2GenMulOpData, CpaBoolean *pMultiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2GenMulCb) { /* Call synchronous mode function */ return LacEcsm2_GenMultiplySyn( instanceHandle, pEcsm2GenMulOpData, pMultiplyStatus, pXk, pYk); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_GenMultiplyBasicParamCheck( pEcsm2GenMulOpData, pMultiplyStatus, pXk, pYk); /* Check that output buffers are big enough * for SM2 algorithm, the length is fixed, * equal to LAC_EC_SM2_SIZE_BYTES (32 bytes) */ if (CPA_STATUS_SUCCESS == status) { if ((pXk->dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pYk->dataLenInBytes < LAC_EC_SM2_SIZE_BYTES)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif /* Determine size - based on input numbers */ if (CPA_STATUS_SUCCESS == status) { status = LacEc_GetRange( LacEcsm2_GeneratorMulOpDataSizeGetMax(pEcsm2GenMulOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2GenMulOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_GENERATOR_MULTIPLICATION; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR( inArgList.mmp_ecsm2_generator_multiplication.k, &(pEcsm2GenMulOpData->k)); pInArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_generator_multiplication_input_t, k)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_generator_multiplication_input_t, k)] = CPA_FALSE; /* Fill output list, x,y */ LAC_MEM_SHARED_WRITE_FROM_PTR( outArgList.mmp_ecsm2_point_multiplication.xd, pXk); pOutArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, xd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, xd)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( outArgList.mmp_ecsm2_point_multiplication.yd, pYk); pOutArgSizeList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, yd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF( icp_qat_fw_mmp_ecsm2_point_multiplication_output_t, yd)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2GenMulOpData; cbData.pClientCb = pEcsm2GenMulCb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pXk; cbData.pOutputData2 = pYk; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_GEN_POINT_MULTIPLY_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_GenMulCb, &cbData, instanceHandle); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2GeneratorMultiplyRequests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2GeneratorMultiplyRequestErrors, pCryptoService); } #endif } return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 point verify operation * ***************************************************************************/ CpaStatus cpaCyEcsm2PointVerify( const CpaInstanceHandle instanceHandle_in, const CpaCyEcPointVerifyCbFunc pEcsm2PointVerifyCb, void *pCallbackTag, const CpaCyEcsm2PointVerifyOpData *pEcsm2PointVerifyOpData, CpaBoolean *pPointVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2PointVerifyCb) { /* Call synchronous mode function */ return LacEcsm2_PointVerifySyn( instanceHandle, pEcsm2PointVerifyOpData, pPointVerifyStatus); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_PointVerifyBasicParamCheck(pEcsm2PointVerifyOpData, pPointVerifyStatus); #endif if (CPA_STATUS_SUCCESS == status) { /* Determine size - based on input numbers */ status = LacEc_GetRange( LacEcsm2_PointVerifyOpDataSizeGetMax(pEcsm2PointVerifyOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2PointVerifyOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_POINT_VERIFY; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_point_verify.x, &(pEcsm2PointVerifyOpData->x)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_point_verify_input_t, x)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_point_verify_input_t, x)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_point_verify.y, &(pEcsm2PointVerifyOpData->y)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_point_verify_input_t, y)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_point_verify_input_t, y)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2PointVerifyOpData; cbData.pClientCb = pEcsm2PointVerifyCb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = NULL; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_POINT_VERIFY_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_PointVerifyCb, &cbData, instanceHandle); } #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2PointVerifyRequests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2PointVerifyRequestErrors, pCryptoService); } #endif return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 signature operation * ***************************************************************************/ CpaStatus cpaCyEcsm2Sign(const CpaInstanceHandle instanceHandle_in, const CpaCyEcsm2SignCbFunc pEcsm2SignCb, void *pCallbackTag, const CpaCyEcsm2SignOpData *pEcsm2SignOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2SignCb) { /* Call synchronous mode function */ return LacEcsm2_SignSyn( instanceHandle, pEcsm2SignOpData, pSignStatus, pR, pS); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_SignBasicParamCheck(pSignStatus, pEcsm2SignOpData, pR, pS); if (CPA_STATUS_SUCCESS == status) { /* Check that output buffers are big enough * for SM2 algorithm, the length is fixed, * equal to LAC_EC_SM2_SIZE_BYTES (32 bytes) */ if ((pR->dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pS->dataLenInBytes < LAC_EC_SM2_SIZE_BYTES)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif /* Determine size - based on input numbers */ if (CPA_STATUS_SUCCESS == status) { status = LacEc_GetRange(LacEcsm2_SignOpDataSizeGetMax(pEcsm2SignOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2SignOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_SIGN_RS; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_sign_rs.k, &(pEcsm2SignOpData->k)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_input_t, k)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_input_t, k)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_sign_rs.e, &(pEcsm2SignOpData->e)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_input_t, e)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_input_t, e)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_sign_rs.d, &(pEcsm2SignOpData->d)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_input_t, d)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_input_t, d)] = CPA_FALSE; /* Fill output list, R, S */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_sign_rs.r, pR); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_output_t, r)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_output_t, r)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_sign_rs.s, pS); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_output_t, s)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_sign_rs_output_t, s)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2SignOpData; cbData.pClientCb = pEcsm2SignCb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pR; cbData.pOutputData2 = pS; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_SIGN_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_SignCb, &cbData, instanceHandle); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2SignRequests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2SignRequestErrors, pCryptoService); } #endif } return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 signature verify operation * ***************************************************************************/ CpaStatus cpaCyEcsm2Verify(const CpaInstanceHandle instanceHandle_in, const CpaCyEcsm2VerifyCbFunc pEcsm2VerifyCb, void *pCallbackTag, const CpaCyEcsm2VerifyOpData *pEcsm2VerifyOpData, CpaBoolean *pVerifyStatus) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2VerifyCb) { /* Call synchronous mode function */ return LacEcsm2_VerifySyn( instanceHandle, pEcsm2VerifyOpData, pVerifyStatus); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_VerifyBasicParamCheck(pEcsm2VerifyOpData, pVerifyStatus); #endif if (CPA_STATUS_SUCCESS == status) { /* Determine size - based on input numbers */ status = LacEc_GetRange(LacEcsm2_VerifyOpDataSizeGetMax(pEcsm2VerifyOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2VerifyOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_VERIFY; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_verify.e, &(pEcsm2VerifyOpData->e)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, e)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, e)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_verify.r, &(pEcsm2VerifyOpData->r)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, r)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, r)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_verify.s, &(pEcsm2VerifyOpData->s)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, s)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, s)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_verify.xp, &(pEcsm2VerifyOpData->xP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, xp)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, xp)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_verify.yp, &(pEcsm2VerifyOpData->yP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, yp)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_verify_input_t, yp)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2VerifyOpData; cbData.pClientCb = pEcsm2VerifyCb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = NULL; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_VERIFY_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_VerifyCb, &cbData, instanceHandle); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2VerifyRequests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2VerifyRequestErrors, pCryptoService); } #endif } return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 encryption operation * ***************************************************************************/ CpaStatus cpaCyEcsm2Encrypt(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pEcsm2EncCb, void *pCallbackTag, const CpaCyEcsm2EncryptOpData *pEcsm2EncOpData, CpaCyEcsm2EncryptOutputData *pEcsm2EncOutputData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2EncCb) { /* Call synchronous mode function */ return LacEcsm2_EncSyn( instanceHandle, pEcsm2EncOpData, pEcsm2EncOutputData); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_EncBasicParamCheck(pEcsm2EncOpData, pEcsm2EncOutputData); if (CPA_STATUS_SUCCESS == status) { /* Check that output buffers are big enough * for SM2 algorithm, the length is fixed, * equal to LAC_EC_SM2_SIZE_BYTES (32 bytes) */ if ((pEcsm2EncOutputData->x1.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pEcsm2EncOutputData->y1.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pEcsm2EncOutputData->x2.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pEcsm2EncOutputData->y2.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { /* Determine size - based on input numbers */ status = LacEc_GetRange(LacEcsm2_EncOpDataSizeGetMax(pEcsm2EncOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2EncOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_ENCRYPTION; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_encryption.k, &(pEcsm2EncOpData->k)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_input_t, k)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_input_t, k)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_encryption.xp, &(pEcsm2EncOpData->xP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_input_t, xp)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_input_t, xp)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_encryption.yp, &(pEcsm2EncOpData->yP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_input_t, yp)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_input_t, yp)] = CPA_FALSE; /* Fill output list, x1,y1,x2,y2 */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_encryption.xc, &(pEcsm2EncOutputData->x1)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, xc)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, xc)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_encryption.yc, &(pEcsm2EncOutputData->y1)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, yc)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, yc)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_encryption.xpb, &(pEcsm2EncOutputData->x2)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, xpb)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, xpb)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_encryption.ypb, &(pEcsm2EncOutputData->y2)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, ypb)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_encryption_output_t, ypb)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2EncOpData; cbData.pClientCb = pEcsm2EncCb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pEcsm2EncOutputData; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_ENC_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_EncCb, &cbData, instanceHandle); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2EncryptRequests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2EncryptRequestErrors, pCryptoService); } #endif } return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 point decryption operation * ***************************************************************************/ CpaStatus cpaCyEcsm2Decrypt(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pEcsm2DecCb, void *pCallbackTag, const CpaCyEcsm2DecryptOpData *pEcsm2DecOpData, CpaCyEcsm2DecryptOutputData *pEcsm2DecOutputData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2DecCb) { /* Call synchronous mode function */ return LacEcsm2_DecSyn( instanceHandle, pEcsm2DecOpData, pEcsm2DecOutputData); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_DecBasicParamCheck(pEcsm2DecOpData, pEcsm2DecOutputData); if (CPA_STATUS_SUCCESS == status) { /* Check that output buffers are big enough * for SM2 algorithm, the length is fixed, * equal to LAC_EC_SM2_SIZE_BYTES (32 bytes) */ if ((pEcsm2DecOutputData->x2.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pEcsm2DecOutputData->y2.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { /* Determine size - based on input numbers */ status = LacEc_GetRange(LacEcsm2_DecOpDataSizeGetMax(pEcsm2DecOpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2DecOpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_DECRYPTION; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_decryption.d, &(pEcsm2DecOpData->d)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_input_t, d)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_input_t, d)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_decryption.xpb, &(pEcsm2DecOpData->x1)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_input_t, xpb)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_input_t, xpb)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_decryption.ypb, &(pEcsm2DecOpData->y1)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_input_t, ypb)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_input_t, ypb)] = CPA_FALSE; /* Fill output list x2 y2 */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_decryption.xd, &(pEcsm2DecOutputData->x2)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_output_t, xd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_output_t, xd)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_decryption.yd, &(pEcsm2DecOutputData->y2)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_output_t, yd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_decryption_output_t, yd)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2DecOpData; cbData.pClientCb = pEcsm2DecCb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pEcsm2DecOutputData; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_DEC_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_DecCb, &cbData, instanceHandle); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2DecryptRequests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2DecryptRequestErrors, pCryptoService); } #endif } return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 key exchange phase 1 operation * ***************************************************************************/ CpaStatus cpaCyEcsm2KeyExPhase1( const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pEcsm2KeyExPhase1Cb, void *pCallbackTag, const CpaCyEcsm2KeyExPhase1OpData *pEcsm2KeyExPhase1OpData, CpaCyEcsm2KeyExOutputData *pEcsm2KeyExPhase1OutputData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2KeyExPhase1Cb) { /* Call synchronous mode function */ return LacEcsm2_KeyexPhase1Syn(instanceHandle, pEcsm2KeyExPhase1OpData, pEcsm2KeyExPhase1OutputData); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_KeyExPhase1BasicParamCheck(pEcsm2KeyExPhase1OpData, pEcsm2KeyExPhase1OutputData); if (CPA_STATUS_SUCCESS == status) { /* Check that output buffers are big enough * for SM2 algorithm, the length is fixed, * equal to LAC_EC_SM2_SIZE_BYTES (32 bytes) */ if ((pEcsm2KeyExPhase1OutputData->x.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pEcsm2KeyExPhase1OutputData->y.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { /* Determine size - based on input numbers */ status = LacEc_GetRange( LacEcsm2_KeyExPhase1OpDataSizeGetMax(pEcsm2KeyExPhase1OpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2KeyExPhase1OpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_KEYEX_P1; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p1.k, &(pEcsm2KeyExPhase1OpData->r)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p1_input_t, k)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p1_input_t, k)] = CPA_FALSE; /* Fill output list, x,y */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_keyex_p1.xd, &(pEcsm2KeyExPhase1OutputData->x)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p1_output_t, xd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p1_output_t, xd)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_keyex_p1.yd, &(pEcsm2KeyExPhase1OutputData->y)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p1_output_t, yd)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p1_output_t, yd)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2KeyExPhase1OpData; cbData.pClientCb = pEcsm2KeyExPhase1Cb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pEcsm2KeyExPhase1OutputData; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_KEY_EXCHANGE_P1_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_KeyExPhase1Cb, &cbData, instanceHandle); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase1Requests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase1RequestErrors, pCryptoService); } #endif } return status; } /** *************************************************************************** * @ingroup Lac_Ecsm2 * * @description * SM2 key exchange phase 2 operation * ***************************************************************************/ CpaStatus cpaCyEcsm2KeyExPhase2( const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pEcsm2KeyExPhase2Cb, void *pCallbackTag, const CpaCyEcsm2KeyExPhase2OpData *pEcsm2KeyExPhase2OpData, CpaCyEcsm2KeyExOutputData *pEcsm2KeyExPhase2OutputData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = instanceHandle_in; Cpa32U dataOperationSizeBytes = 0; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = { 0 }; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = { 0 }; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = { CPA_FALSE }; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = { CPA_FALSE }; icp_qat_fw_mmp_input_param_t inArgList = { .flat_array = { 0 } }; icp_qat_fw_mmp_output_param_t outArgList = { .flat_array = { 0 } }; Cpa32U functionalityId = 0; lac_pke_op_cb_data_t cbData = { 0 }; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService = NULL; #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); /* Check if the API has been called in synchronous mode */ if (NULL == pEcsm2KeyExPhase2Cb) { /* Call synchronous mode function */ return LacEcsm2_KeyexPhase2Syn(instanceHandle, pEcsm2KeyExPhase2OpData, pEcsm2KeyExPhase2OutputData); } #ifdef ICP_PARAM_CHECK /* Parameter check - NULL params, buffer lengths etc. */ status = LacEcsm2_KeyExPhase2BasicParamCheck(pEcsm2KeyExPhase2OpData, pEcsm2KeyExPhase2OutputData); if (CPA_STATUS_SUCCESS == status) { /* Check that output buffers are big enough * for SM2 algorithm, the length is fixed, * equal to LAC_EC_SM2_SIZE_BYTES (32 bytes) */ if ((pEcsm2KeyExPhase2OutputData->x.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES) || (pEcsm2KeyExPhase2OutputData->y.dataLenInBytes < LAC_EC_SM2_SIZE_BYTES)) { LAC_INVALID_PARAM_LOG("Output buffers not big enough"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { /* Determine size - based on input numbers */ status = LacEc_GetRange( LacEcsm2_KeyExPhase2OpDataSizeGetMax(pEcsm2KeyExPhase2OpData), &dataOperationSizeBytes); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_EC_FIELD_TYPE_PRIME == pEcsm2KeyExPhase2OpData->fieldType) { switch (dataOperationSizeBytes) { case LAC_EC_SIZE_QW4_IN_BYTES: functionalityId = PKE_ECSM2_KEYEX_P2; break; case LAC_EC_SIZE_QW8_IN_BYTES: case LAC_EC_SIZE_QW9_IN_BYTES: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; default: LAC_INVALID_PARAM_LOG( "SM2 curves other than GFP P-256 are not supported"); status = CPA_STATUS_INVALID_PARAM; break; } } else { LAC_INVALID_PARAM_LOG("SM2 curve over binary field not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* Fill input list */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p2.r, &(pEcsm2KeyExPhase2OpData->r)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, r)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, r)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p2.d, &(pEcsm2KeyExPhase2OpData->d)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, d)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, d)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p2.x1, &(pEcsm2KeyExPhase2OpData->x1)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, x1)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, x1)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p2.x2, &(pEcsm2KeyExPhase2OpData->x2)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, x2)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, x2)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p2.y2, &(pEcsm2KeyExPhase2OpData->y2)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, y2)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, y2)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p2.xp, &(pEcsm2KeyExPhase2OpData->xP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, xp)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, xp)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.mmp_ecsm2_keyex_p2.yp, &(pEcsm2KeyExPhase2OpData->yP)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, yp)] = dataOperationSizeBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_input_t, yp)] = CPA_FALSE; /* Fill output list, x,y */ LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_keyex_p2.xus, &(pEcsm2KeyExPhase2OutputData->x)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_output_t, xus)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_output_t, xus)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.mmp_ecsm2_keyex_p2.yus, &(pEcsm2KeyExPhase2OutputData->y)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_output_t, yus)] = dataOperationSizeBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_ecsm2_keyex_p2_output_t, yus)] = CPA_FALSE; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEcsm2KeyExPhase2OpData; cbData.pClientCb = pEcsm2KeyExPhase2Cb; cbData.pOpaqueData = NULL; cbData.pOutputData1 = pEcsm2KeyExPhase2OutputData; LAC_ECSM2_TIMESTAMP_BEGIN(&cbData, LAC_ECSM2_KEY_EXCHANGE_P2_REQUEST, (sal_crypto_service_t *)instanceHandle); status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacEcsm2_KeyExPhase2Cb, &cbData, instanceHandle); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase2Requests, pCryptoService); } else { LAC_ECSM2_STAT_INC(numEcsm2KeyExPhase2RequestErrors, pCryptoService); } #endif } return status; } CpaStatus cpaCyEcsm2QueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyEcsm2Stats64 *pEcsm2Stats) { sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = instanceHandle_in; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pEcsm2Stats); #endif /* Instance checks */ LAC_CHECK_STATUS(LacEc_ValidateInstance(&instanceHandle)); /* Check for HW support */ LAC_CHECK_STATUS(LacEcsm2_HwCapabilityCheck(instanceHandle)); pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_CHECK_NULL_PARAM(pEcsm2Stats); /* Get stats into user supplied stats structure */ LAC_ECSM2_STATS_GET(*pEcsm2Stats, pCryptoService); return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/ecc/lac_kpt_ecdsa.c000066400000000000000000000062141503624047500321470ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * * @file lac_kpt_ecdsa.c * * @ingroup Lac_KptEc * * This file implements Elliptic Curve Digital Signature Algorithm with * protected private key * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_ecdsa.h" #include "cpa_cy_kpt.h" /** *************************************************************************** * @ingroup Lac_KptEc * This function performs KPT ECDSA Sign R & S. * ***************************************************************************/ CpaStatus cpaCyKptEcdsaSignRS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyKptEcdsaSignRSOpData *pOpData, CpaBoolean *pSignStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS, CpaCyKptUnwrapContext *pKptUnwrapContext) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/000077500000000000000000000000001503624047500301155ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_dsa.h000066400000000000000000000163701503624047500316630ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * @file lac_dsa.h * * @defgroup Lac_Dsa DSA * * @ingroup LacAsym * * Interfaces exposed by the DSA component * * @lld_start * * @lld_overview * This is the DSA feature implementation. It implements 7 DSA API services: * parameter generation (p, g, y), signature generation (r, s, rs), and * signature verification. Statistics are maintained for each service. For * each service the parameters supplied by the client are checked, and then * input/output argument lists are constructed before calling the PKE QAT * Comms layer to create and send a request to the QAT. * * For DSA P Parameter Generation two inputs are required by the QAT which are * handled internally so the client is not aware of them. They are products * of small primes, used by the QAT to perform a GCD (or alternatively * Pollard-Rho) test on the generated P parameter as an initial (non-robust, * but fast) primality test. These two inputs are allocated and managed * internally by this component. * * For Verification service the output is the result of the verification * returned by the QAT in the form of pass/fail status. The status is * returned to the caller. * * In all other cases the service implementations are a straightforward * marshalling of client-supplied parameters for the QAT. I.e. there is * minimal logic handled by this component. Buffer alignment, and padding up * to a whole number of quadwords, is handled by the PKE QAT Comms layer. * * @lld_initialisation * On initialization this component allocates the two product-of-small-primes * parameters (psp1 and psp2) for the DSA P Parameter Generation operation. * It also clears the stats. * * @note * The DSA feature may be called in Asynchronous or Synchronous modes. * In Asynchronous mode the user supplies a Callback function to the API. * Control returns to the client after the message has been sent to the QAT and * the Callback gets invoked when the QAT completes the operation. There is NO * BLOCKING. This mode is preferred for maximum performance. * In Synchronous mode the client supplies no Callback function pointer (NULL) * and the point of execution is placed on a wait-queue internally, and this is * de-queued once the QAT completes the operation. Hence, Synchronous mode is * BLOCKING. So avoid using in an interrupt context. To achieve maximum * performance from the API Asynchronous mode is preferred. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * *****************************************************************************/ /*****************************************************************************/ #ifndef LAC_DSA_H #define LAC_DSA_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ /* ****************************************************************************** * @ingroup LacDsa * DSA {L,N} pairs supported by FIPS186-3 * * @description * enumeration containing the possible {L,N} pairs input * *******************************************************************************/ typedef enum lac_dsa_ln_pairs_s { LAC_DSA_INVALID_PAIR = 0, LAC_DSA_1024_160_PAIR, LAC_DSA_2048_224_PAIR, LAC_DSA_2048_256_PAIR, LAC_DSA_3072_256_PAIR } lac_dsa_ln_pairs_t; /* ****************************************************************************** * @ingroup LacDsa * DSA L values supported by FIPS186-3 * * @description * enumeration containing the possible L values * *******************************************************************************/ typedef enum lac_dsa_l_values_s { LAC_DSA_L_INVALID = 0, LAC_DSA_L_1024, LAC_DSA_L_2048, LAC_DSA_L_3072 } lac_dsa_l_values_t; /* ****************************************************************************** * @ingroup LacDsa * DSA N values supported by FIPS186-3 * * @description * enumeration containing the possible N values * *******************************************************************************/ typedef enum lac_dsa_n_values_s { LAC_DSA_N_INVALID = 0, LAC_DSA_N_160, LAC_DSA_N_224, LAC_DSA_N_256 } lac_dsa_n_values_t; /** ******************************************************************************* * @ingroup Lac_Dsa * print the DSA stats to standard output * * @description * For each engine this function copies the stats using the function * cpaCyDsaQueryStats64. It then prints contents of this structure to * standard output * * @see cpaCyDsaQueryStats64() * *****************************************************************************/ void LacDsa_StatsShow(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup Lac_Dsa * Compile time check of FW interface * * @description * Performs a compile time check of PKE interface to ensure IA assumptions * about the interface are valid. * *****************************************************************************/ void LacDsa_CompileTimeAssertions(void); #endif /* LAC_DSA_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_ec.h000066400000000000000000000352711503624047500315040ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * @file lac_ec.h * * @ingroup Lac_Ec * * Elliptic Curve components - EC, ECDH and ECDSA - common include file * * @lld_start * * @lld_overview * This is the common include location for Elliptic Curve components * * @lld_initialisation * * @lld_module_algorithms * * @lld_process_context * * @lld_end * *****************************************************************************/ /*****************************************************************************/ #ifndef LAC_EC_H #define LAC_EC_H #include "cpa_cy_ecdsa.h" #define LAC_EC_SIZE_BYTES_MAX LAC_BITS_TO_BYTES(LAC_576_BITS) #define LAC_EC_SIZE_BYTES_MIN LAC_BITS_TO_BYTES(LAC_256_BITS) #define LAC_EC_SIZE_QW9_IN_BYTES LAC_EC_SIZE_BYTES_MAX #define LAC_EC_SIZE_QW8_IN_BYTES LAC_BITS_TO_BYTES(LAC_512_BITS) #define LAC_EC_SIZE_QW4_IN_BYTES LAC_EC_SIZE_BYTES_MIN #define LAC_EC_NUM_CONCAT_INPUTS 11 #define LAC_EC_MIN_MOD_BIT_POS_GFP 2 #define LAC_EC_MIN_MOD_BIT_POS_GF2 3 #define LAC_EC_SET_LIST_PARAMS(list, list_size, val) \ do \ { \ int i; \ for (i = 0; i < list_size; i++) \ { \ list[i] = val; \ } \ } while (0); /**< @ingroup Lac_Ec * macro to set elements in list to a specified value */ #ifndef DISABLE_STATS #define LAC_EC_STAT_INC(statistic, pCryptoService) \ do \ { \ if (CPA_TRUE == \ pCryptoService->generic_service_info.stats->bEccStatsEnabled) \ { \ osalAtomicInc( \ &pCryptoService \ ->pLacEcStatsArr[offsetof(CpaCyEcStats64, statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) #else #define LAC_EC_STAT_INC(statistic, pCryptoService) \ (pCryptoService) = (pCryptoService) #endif /**< @ingroup Lac_Ec * macro to increment a EC stat (derives offset into array of atomics) * assumes pCryptoService has already been validated */ /** ****************************************************************************** * @ingroup Lac_Ec * return the ECC service QW value for a given size. * * @description * This function will return the QWs value (LAC_EC_SIZE_QW4_IN_BYTES, * LAC_EC_SIZE_QW8_IN_BYTES or LAC_EC_SIZE_QW9_IN_BYTES) according to the * size. * * @param[in] size input size * @param[out] pMax QW value returned according to size * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Size is invalid. In this case, pMax will * be set to size * @retval CPA_STATUS_UNSUPPORTED Size is unsupported/deprecated. * *****************************************************************************/ CpaStatus LacEc_GetRange(Cpa32U size, Cpa32U *pMax); /** ****************************************************************************** * @ingroup Lac_Ec * print the ECC stats to standard output * * @description * prints all ECC stats (i.e. ec stats, ecdh stats and ecdsa stats) * *****************************************************************************/ void LacEc_StatsShow(CpaInstanceHandle instanceHandle); /** ****************************************************************************** * @ingroup Lac_Ec * Resolves and validates passed instance handle. * * @description * First resolves passed value to real instance i.e. handles * CPA_INSTANCE_HANDLE_SINGLE. * Next it checks if instance is currently running and if it is of * proper kind: SAL_SERVICE_TYPE_CRYPTO or SAL_SERVICE_TYPE_CRYPTO_ASYM * * @param[in/out] pInstanceHandle in: Should point to instance handle to * be validated or special value of * CPA_INSTANCE_HANDLE_SINGLE. * out: When CPA_STATUS_SUCCESS is returned, * it points to a valid instanceHandle. * * @retval CPA_STATUS_SUCCESS Instance resolved and confirmed valid. * @retval CPA_STATUS_RESTARTING Instance is restarting. * @retval CPA_STATUS_INVALID_PARAM Instance is NULL. * @retval CPA_STATUS_FAIL Wrong type of instance, instance not * running or address translation failed. * *****************************************************************************/ CpaStatus LacEc_ValidateInstance(CpaInstanceHandle *pInstanceHandle); /** ****************************************************************************** * @ingroup Lac_Ec * Check if curve can use the optimized MMP GF2_L256 service * * @description * If curve is NIST standard B-163, K-163, B-233 or K-233 then optimized * MMP GF2_L256 service can be used. If not, then GF2_L512 can be used. * * @param[in/out] pNumQWs Initially this will have a value * LAC_EC_SIZE_QW4_IN_BYTES but will be changed to * LAC_EC_SIZE_QW8_IN_BYTES if curve not NIST * standard B-163, K-163, B-233 or K-233. * @param[in] pQ Pointer to FlatBuffer holding modulus. * @param[in] pA Pointer to FlatBuffer holding curve coeff A. * @param[in] pB Pointer to FlatBuffer holding curve coeff B. * @param[in] pR Pointer to FlatBuffer holding order of curve * (can be NULL if check not required). * @param[in] pH Pointer to FlatBuffer holding cofactor (can * be NULL if check not required). * * *****************************************************************************/ void LacEc_CheckCurve4QWGF2(Cpa32U *pNumQWs, const CpaFlatBuffer *pQ, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, const CpaFlatBuffer *pR, const CpaFlatBuffer *pH); /** ****************************************************************************** * @ingroup Lac_Ec * Check if curve is NIST P-521 * * @description * If curve is NIST standard P-521 then PKE GFP_521 service can be used. * If curve is not NIST standard curve then invalid param returned. * * @param[in] pQ Pointer to FlatBuffer holding modulus. * @param[in] pA Pointer to FlatBuffer holding curve coeff A. * @param[in] pB Pointer to FlatBuffer holding curve coeff B. * @param[in] pR Pointer to FlatBuffer holding order of curve * (can be NULL if check not required). * @param[in] pH Pointer to FlatBuffer holding cofactor (can * be NULL if check not required). * @param[in] pX Pointer to FlatBuffer holding x coordinate * (can be NULL if check not required). * @param[in] pY Pointer to FlatBuffer holding y coordinate * (can be NULL if check not required). * * @retval CPA_STATUS_SUCCESS Curve is as required 521 service can be * used. * @retval CPA_STATUS_INVALID_PARAM Curve is not NIST P-521 or x and y * coordinates are greater than 521 bits. * *****************************************************************************/ CpaStatus LacEc_CheckCurve9QWGFP(const CpaFlatBuffer *pQ, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, const CpaFlatBuffer *pR, const CpaFlatBuffer *pH, const CpaFlatBuffer *pX, const CpaFlatBuffer *pY); /** ****************************************************************************** * @ingroup Lac_Ec * Check if curve is NIST K-571 or B-571 * * @description * If curve is NIST standard K-571 or B-571 then PKE GF2_571 service can be * used. If curve is not NIST standard curve then invalid param returned. * * @param[in] pQ Pointer to FlatBuffer holding modulus. * @param[in] pA Pointer to FlatBuffer holding curve coeff A. * @param[in] pB Pointer to FlatBuffer holding curve coeff B. * @param[in] pR Pointer to FlatBuffer holding order of curve * (can be NULL if check not required). * @param[in] pH Pointer to FlatBuffer holding cofactor (can * be NULL if check not required). * @param[in] pX Pointer to FlatBuffer holding x coordinate * (can be NULL if check not required). * @param[in] pY Pointer to FlatBuffer holding y coordinate * (can be NULL if check not required). * * @retval CPA_STATUS_SUCCESS Curve is as required 571 service can be * used. * @retval CPA_STATUS_INVALID_PARAM Curve is not NIST K-571 or NIST B-571 curve * or x or y coeff have degree greater than * or equal to the modulus. * * *****************************************************************************/ CpaStatus LacEc_CheckCurve9QWGF2(const CpaFlatBuffer *pQ, const CpaFlatBuffer *pA, const CpaFlatBuffer *pB, const CpaFlatBuffer *pR, const CpaFlatBuffer *pH, const CpaFlatBuffer *pX, const CpaFlatBuffer *pY); /** ****************************************************************************** * @ingroup Lac_Ecdsa * Check if there is optimised ecdsa SignRS MMP function id for the curve. * * @description * If the there is optimised ecdsa SignRS MMP function for the curve it * sends a request to firmware with optimised function ID. * * @param[in] instanceHandle Instance handle. * @param[in] pCb Callback function pointer. If this is set to a * NULL value the function will operate * synchronously. * @param[in] pCallbackTag User-supplied value to help identify request. * @param[in] pOpData Structure containing all the data needed to * perform the operation. The client code * allocates the memory for this structure. This * component takes ownership of the memory until * it is returned in the callback. * @param[out] pR ECDSA message signature r. * @param[out] pS ECDSA message signature s. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_RESTARTING API implementation is restarting. Resubmit * the request. * @retval CPA_STATUS_UNSUPPORTED Optimised EcdsaSignRS is not supported for * the platform or the curve. * *****************************************************************************/ CpaStatus LacEcdsa_OptimisedSignRS(const CpaInstanceHandle instanceHandle, const CpaCyEcdsaSignRSCbFunc pCb, void *pCallbackTag, const CpaCyEcdsaSignRSOpData *pOpData, CpaFlatBuffer *pR, CpaFlatBuffer *pS); #endif /* LAC_EC_H */ lac_ec_nist_curves.h000066400000000000000000000135711503624047500340500ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * @file lac_ec_nist_curves.h * * @ingroup Lac_Ec * * Definitions for the following NIST recommended elliptic curves: * - PRIME 256 (P256) * - PRIME 384 (P384) * - PRIME 521 (P521) * - KOBLITZ 163 (K163) * - BINARY 163 (B163) * - KOBLITZ 233 (K233) * - BINARY 233 (B233) * - KOBLITZ 571 (K571) * - BINARY 571 (B571) * *****************************************************************************/ #ifndef LAC_EC_NIST_CURVES_H #define LAC_EC_NIST_CURVES_H #include "cpa_types.h" // for Cpa8U /*********** NIST PRIME 256 CURVE ****************/ #define NIST_GFP_P_256_BIT_POS 256 #define NIST_GFP_A_256_BIT_POS 256 #define NIST_GFP_B_256_BIT_POS 255 #define NIST_GFP_R_256_BIT_POS 256 #define NIST_GFP_GX_256_BIT_POS 255 #define NIST_GFP_GY_256_BIT_POS 255 extern Cpa8U nist_p256_p[]; extern Cpa8U nist_p256_a[]; extern Cpa8U nist_p256_b[]; extern Cpa8U nist_p256_n[]; extern Cpa8U nist_p256_h[]; extern Cpa8U nist_p256_gX[]; extern Cpa8U nist_p256_gY[]; /*********** NIST PRIME 384 CURVE ****************/ #define NIST_GFP_P_384_BIT_POS 384 #define NIST_GFP_A_384_BIT_POS 384 #define NIST_GFP_B_384_BIT_POS 384 #define NIST_GFP_R_384_BIT_POS 384 #define NIST_GFP_GX_384_BIT_POS 384 #define NIST_GFP_GY_384_BIT_POS 382 extern Cpa8U nist_p384_p[]; extern Cpa8U nist_p384_a[]; extern Cpa8U nist_p384_b[]; extern Cpa8U nist_p384_n[]; extern Cpa8U nist_p384_h[]; extern Cpa8U nist_p384_gX[]; extern Cpa8U nist_p384_gY[]; /*********** NIST PRIME 521 CURVE ****************/ #define NIST_GFP_Q_521_BIT_POS 520 #define NIST_GFP_A_521_BIT_POS 520 #define NIST_GFP_B_521_BIT_POS 518 #define NIST_GFP_H_521_BIT_POS 0 #define NIST_GFP_R_521_BIT_POS 520 extern Cpa8U nist_p521_q[]; extern Cpa8U nist_p521_a[]; extern Cpa8U nist_p521_b[]; extern Cpa8U nist_p521_r[]; /*********** NIST 163 KOBLITZ AND BINARY CURVES ****************/ #define NIST_GF2_Q_163_BIT_POS 163 #define NIST_GF2_A_163_BIT_POS 0 #define NIST_GF2_H_163_BIT_POS 1 #define NIST_GF2_R_163_BIT_POS 162 extern const Cpa8U nist_gf2_163_q[]; extern const Cpa8U nist_gf2_163_a[]; extern const Cpa8U nist_gf2_163_h[]; /*********** NIST 163 KOBLITZ CURVE ****************/ #define NIST_GF2_B_K163_BIT_POS 0 extern const Cpa8U nist_koblitz_gf2_163_b[]; extern const Cpa8U nist_koblitz_gf2_163_r[]; /*********** NIST 163 BINARY CURVE ****************/ #define NIST_GF2_B_B163_BIT_POS 161 extern const Cpa8U nist_binary_gf2_163_b[]; extern const Cpa8U nist_binary_gf2_163_r[]; /*********** NIST 233 KOBLITZ AND BINARY CURVES ****************/ #define NIST_GF2_Q_233_BIT_POS 233 #define NIST_GF2_A_233_BIT_POS 0 extern const Cpa8U nist_gf2_233_q[]; /*********** NIST 233 KOBLITZ CURVE ****************/ #define NIST_GF2_H_K233_BIT_POS 2 #define NIST_GF2_B_K233_BIT_POS 0 #define NIST_GF2_R_K233_BIT_POS 231 extern const Cpa8U nist_koblitz_gf2_233_h[]; extern const Cpa8U nist_koblitz_gf2_233_a[]; extern const Cpa8U nist_koblitz_gf2_233_b[]; extern const Cpa8U nist_koblitz_gf2_233_r[]; /*********** NIST 233 BINARY CURVE ****************/ #define NIST_GF2_H_B233_BIT_POS 1 #define NIST_GF2_B_B233_BIT_POS 230 #define NIST_GF2_R_B233_BIT_POS 232 extern const Cpa8U nist_binary_gf2_233_h[]; extern const Cpa8U nist_binary_gf2_233_a[]; extern const Cpa8U nist_binary_gf2_233_b[]; extern const Cpa8U nist_binary_gf2_233_r[]; /*********** NIST 571 KOBLITZ AND BINARY CURVES ****************/ #define NIST_GF2_Q_571_BIT_POS 571 #define NIST_GF2_A_571_BIT_POS 0 extern const Cpa8U nist_gf2_571_q[]; /*********** NIST 571 KOBLITZ CURVE ****************/ #define NIST_GF2_B_K571_BIT_POS 0 #define NIST_GF2_H_K571_BIT_POS 2 #define NIST_GF2_R_K571_BIT_POS 569 extern const Cpa8U nist_koblitz_gf2_571_h[]; extern const Cpa8U nist_koblitz_gf2_571_r[]; /*********** NIST 571 BINARY CURVE ****************/ #define NIST_GF2_B_B571_BIT_POS 569 #define NIST_GF2_H_B571_BIT_POS 1 #define NIST_GF2_R_B571_BIT_POS 569 extern const Cpa8U nist_binary_gf2_571_b[]; extern const Cpa8U nist_binary_gf2_571_h[]; extern const Cpa8U nist_binary_gf2_571_r[]; #endif /* LAC_EC_NIST_CURVES_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_ln.h000066400000000000000000000132421503624047500315200ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /************************************************************************** * @file lac_ln.h * * @defgroup LacAsymLn Large Number ModExp and ModInv * * @ingroup LacAsym * * Interfaces exposed by the LN Component * * @lld_start * * @lld_overview * This is the Large Number ModExp and ModInv feature implementation. It * implements two LN services: Modular Exponentiation and Modular Inversion. * * The input data size for each service can be any up to 4096 bits in length. * For each service the parameters supplied by the client are checked and then * the QAT functionality is chosen based upon input data size (buffer size less * leading zeros). In addition, the Modular Inversion service checks on the * even/odd combinations of the input data before choosing the flavour of the * QAT function. * * Finally the input/output argument lists are constructed before calling * the PKE QAT Comms layer to create and send a request to the QAT. * * Buffer alignment, and padding up to a chosen size (whole number of quadwords * matching the size of functionality ID) is handled by the PKE QAT Comms layer. * * Statistics are maintained for each service. * * @note * This feature may be called in Asynchronous or Synchronous modes. * In Asynchronous mode the user supplies a Callback function to the API. * Control returns to the client after the message has been sent to the QAT and * the Callback gets invoked when the QAT completes the operation. There is NO * BLOCKING. This mode is preferred for maximum performance. * In Synchronous mode the client supplies no Callback function pointer (NULL) * and the point of execution is placed on a wait-queue internally, and this is * de-queued once the QAT completes the operation. Hence, Synchronous mode is * BLOCKING. So avoid using in an interrupt context. To achieve maximum * performance from the API Asynchronous mode is preferred. * * @lld_dependencies * - @ref LacPkeQatComms "PKE QAT Comms" : For creating and sending messages * to the QAT * - @ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_initialisation * On initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end * ***************************************************************************/ /*****************************************************************************/ #ifndef LAC_LN_H #define LAC_LN_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ /** ******************************************************************************* * @ingroup LacAsymLn * print the LN stats to standard output * * @description * For each Instance this function copies the stats using the function * cpaCyLnStatsQuery64. It then prints contents of this structure to * standard output * * @param[in] instanceHandle * * @see cpaCyLnStatsQuery64() * *****************************************************************************/ void LacLn_StatsShow(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup Lac_Ln * Compile time check of FW interface * * @description * Performs a compile time check of PKE interface to ensure IA assumptions * about the interface are valid. * *****************************************************************************/ void LacLn_CompileTimeAssertions(void); #endif /* LAC_LN_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_pke_mmp.h000066400000000000000000000152341503624047500325420ustar00rootroot00000000000000/* * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** *************************************************************************** * @file lac_pke_mmp.h * * @defgroup LacAsymCommonMmp Lac Pke Mmp * * @ingroup LacAsymCommon * * This file defines the structs and constants necessary to communicate * with the QAT. ******************************************************************************/ #ifndef _LAC_PKE_MMP_H_ #define _LAC_PKE_MMP_H_ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ #include "icp_qat_fw_mmp.h" /******************************************************************************/ /* A functionality id that is guaranteed to be invalid */ #define LAC_PKE_INVALID_FUNC_ID 0 /* A index for mapping table that is guaranteed to be invalid */ #define LAC_PKE_INVALID_INDEX -1 /* Current total of input/output parameters */ #define LAC_MAX_MMP_PARAMS 8 /*PKE offset in status flags*/ #define PKE_STATUS_FLAG_OFFSET 8 /* * The QAT interface provides us with structs for each operation size. * They all have the same parameters (validated at compile time) so to * get generic structs we simply typedef one of the size specific structs. */ typedef icp_qat_fw_mmp_dh_768_input_t icp_qat_fw_mmp_dh_input_t; typedef icp_qat_fw_mmp_dh_768_output_t icp_qat_fw_mmp_dh_output_t; typedef icp_qat_fw_mmp_dh_g2_768_input_t icp_qat_fw_mmp_dh_g2_input_t; typedef icp_qat_fw_mmp_dh_g2_768_output_t icp_qat_fw_mmp_dh_g2_output_t; typedef icp_qat_fw_mmp_rsa_dp1_1024_input_t icp_qat_fw_mmp_rsa_dp1_input_t; typedef icp_qat_fw_mmp_rsa_dp1_1024_output_t icp_qat_fw_mmp_rsa_dp1_output_t; typedef icp_qat_fw_mmp_rsa_dp2_1024_input_t icp_qat_fw_mmp_rsa_dp2_input_t; typedef icp_qat_fw_mmp_rsa_dp2_1024_output_t icp_qat_fw_mmp_rsa_dp2_output_t; typedef icp_qat_fw_mmp_rsa_kp1_1024_input_t icp_qat_fw_mmp_rsa_kp1_input_t; typedef icp_qat_fw_mmp_rsa_kp1_1024_output_t icp_qat_fw_mmp_rsa_kp1_output_t; typedef icp_qat_fw_mmp_rsa_kp2_1024_input_t icp_qat_fw_mmp_rsa_kp2_input_t; typedef icp_qat_fw_mmp_rsa_kp2_1024_output_t icp_qat_fw_mmp_rsa_kp2_output_t; typedef icp_qat_fw_mmp_rsa_ep_1024_input_t icp_qat_fw_mmp_rsa_ep_input_t; typedef icp_qat_fw_mmp_rsa_ep_1024_output_t icp_qat_fw_mmp_rsa_ep_output_t; /* Similarly for DSA */ typedef icp_qat_fw_mmp_dsa_gen_g_1024_input_t icp_qat_fw_mmp_dsa_gen_g_input_t; typedef icp_qat_fw_mmp_dsa_gen_y_1024_input_t icp_qat_fw_mmp_dsa_gen_y_input_t; typedef icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t icp_qat_fw_mmp_dsa_gen_p_input_t; typedef icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t icp_qat_fw_mmp_dsa_sign_r_input_t; typedef icp_qat_fw_mmp_dsa_sign_s_160_input_t icp_qat_fw_mmp_dsa_sign_s_input_t; typedef icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t icp_qat_fw_mmp_dsa_sign_r_s_input_t; typedef icp_qat_fw_mmp_dsa_verify_1024_160_input_t icp_qat_fw_mmp_dsa_verify_input_t; typedef icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t icp_qat_fw_mmp_dsa_sign_r_s_output_t; #define LAC_MAX_MMP_INPUT_PARAMS \ (sizeof(icp_qat_fw_mmp_input_param_t) / sizeof(Cpa64U)) #define LAC_MAX_MMP_OUTPUT_PARAMS \ (sizeof(icp_qat_fw_mmp_output_param_t) / sizeof(Cpa64U)) /* * This enumeration defines the column array indexes for the * various SIZE:ID tables. */ typedef enum { LAC_PKE_SIZE_COLUMN = 0, LAC_PKE_ID_COLUMN, LAC_PKE_NUM_COLUMNS } lac_size_id_map_columns_t; /** ******************************************************************************* * @ingroup LacAsymCommonMmp * Returns the MMP Id for the given size in bits from the given table. * * @param[in] sizeInBits the size of the operation * @param[in] pSizeIdTable table of mmp ids for that operation * @param[in] numTableEntries number of mmp ids for that operation ******************************************************************************/ Cpa32U LacPke_GetMmpId(Cpa32U sizeInBits, const Cpa32U pSizeIdTable[][LAC_PKE_NUM_COLUMNS], Cpa32U numTableEntries); /** ******************************************************************************* * @ingroup LacAsymCommonMmp * Returns the table entry for the given data size in bits that can be * treated with the shortest operation size from the given table. * * @param[in] sizeInBits the size of the operation * @param[in] pSizeIdTable table of mmp ids for that operation * @param[in] numTableEntries number of mmp ids for that operation *****************************************************************************/ Cpa32U LacPke_GetIndex_VariableSize( Cpa32U sizeInBits, const Cpa32U pSizeIdTable[][LAC_PKE_NUM_COLUMNS], Cpa32U numTableEntries); #endif /* _LAC_PKE_MMP_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_pke_qat_comms.h000066400000000000000000000564051503624047500337410ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @defgroup LacAsym Asymmetric * * @ingroup Lac * * Asymmetric component includes Diffie Hellman, Rsa, Dsa, ECC and Prime. **************************************************************************/ /** *************************************************************************** * @defgroup LacAsymCommon Asymmetric Common * * @ingroup LacAsym * * Asymmetric common includes pke utils, mmp and qat communication layer **************************************************************************/ /** *************************************************************************** * @file lac_pke_qat_comms.h * * @defgroup LacAsymCommonQatComms QAT Communication Layer * * @ingroup LacAsymCommon * * Asymmetric QAT Communication Layer * * @lld_start * * @lld_overview * This is the LAC PKE QAT Comms component. It takes care of the creation * of PKE messages in the format the QAT expects, and also the sending of * these messages to the QAT. As part of PKE message creation, flat buffers * are internally resized by this component if necessary. Also PKE request * chaining, where multiple requests are linked together and just the head * request is sent to the QAT, is supported by this component. This component * also takes care of the allocation and freeing of request data structures * to minimize the work required by calling code. * * The expected usage is that clients will create input/output parameter * lists, with flat buffer pointers stored in the correct order and location * within these lists. They will then call the function to create and send * a PKE request to the QAT. If the client wishes to chain requests, then * they will create multiple requests using the same handle, and then send * the request chain as a normal request. * * The clients call the asynchronous function to send the message to the QAT. * They pass in a callback function and callback data when creating the * message. When the response is received from the QAT the callback function * is invoked with the LAC status, the QAT pass/fail status, and the callback * data as params. * * In the case of request chaining, the QAT will abort the execution of * requests in the chain if any request fails. The response message will * correspond to the last executed request in the chain. As each request * has its own (potentially unique) callback data, a client could in theory * determine which request in the chain failed if this info is needed. * * @lld_dependencies * - @ref QatComms "ADF" : For sending messages to the QAT, and for * setting the response callback * - @ref LacMem "Mem" : For memory allocation and freeing, virtual/physical * address translation, and translating between scalar and pointer types * * @lld_initialisation * On initialization this component sets the response callback for messages * of type PKE, so that they can be handled by this component. * * @lld_module_algorithms * To support request chaining, this component builds up a linked list of * requests, and maintains the head of the list in the handle that gets * returned to the caller. Each element of the list has a pointer to the * head of the list so that the entire list can be freed by knowing any * element of the list. Each element of the list maintains a next pointer * to facilitate list traversal. Only the head element of the list maintains * a tail pointer, to facilitate adding to the end of the list. The head * element is static, so can readily be stored in each element, but as the * tail element is dynamic (it changes as the list grows) its not convenient * to store and maintain it in each element. Instead to get the tail of the * list you must first get the head of the list to get the tail pointer. * * @lld_process_context * * @lld_end ****************************************************************************/ /******************************************************************************/ #ifndef _LAC_PKE_QAT_COMMS_H_ #define _LAC_PKE_QAT_COMMS_H_ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "cpa_types.h" #include "cpa_cy_common.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* ADF include */ #include "icp_adf_transport.h" /* QAT include */ #include "icp_qat_fw_pke.h" #include "icp_qat_fw_mmp.h" /* SAL include */ #include "lac_pke_mmp.h" #include "lac_sync.h" #include "lac_mem_pools.h" /** ***************************************************************************** * @ingroup LacAsymCommonQatComms * * @description * PKE request callback data structure * *****************************************************************************/ typedef struct lac_pke_op_cb_data_s { const void *pClientCb; /**< client callback function pointer */ void *pCallbackTag; /**< client callback correlator */ const void *pClientOpData; /**< client callback operation data pointer */ void *pOpaqueData; /**< generic opaque data pointer */ /* Output data */ void *pOutputData1; /**< Output data pointer 1 */ void *pOutputData2; /**< Output data pointer 2 */ lac_sync_op_data_t *pSyncCookie; /**< synchronous cookie */ #ifdef COUNTERS Cpa64U timeStamp; #endif } lac_pke_op_cb_data_t; /** ***************************************************************************** * @ingroup LacAsymCommonQatComms * * @description * This is the callback prototype for the non-blocking PKE operations. It * takes a status, pass flag, acceleration handle, and callback data pointer * as parameters and returns void. This function will be invoked when a * PKE response is received from the QAT to a previously issued PKE request. * * @param[in] status status of the operation * @param[in] pass result of the operation. For operations such as * verify which require the QAT to perform a test * then this parameter shall be set to CPA_TRUE if * the test succeeds or CPA_FALSE if the test * fails. * For messages which do not perform a test e.g. * encrypt, decrypt then this parameter shall * always be CPA_TRUE. * @param[in] instanceHandle Acceleration engine to which the message was * sent. * @param[in] pCbData this field contains a copy of the callback data * passed when the request was created. *****************************************************************************/ typedef void (*lac_pke_op_cb_func_t)(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData); /** ***************************************************************************** * @ingroup LacAsymCommonQatComms * * @description * Contains the data for a pke op callback * *****************************************************************************/ typedef struct lac_pke_qat_req_data_cb_info_s { lac_pke_op_cb_func_t cbFunc; /**< Callback function */ lac_pke_op_cb_data_t cbData; /**< Callback function data */ CpaInstanceHandle instanceHandle; /**< Acceleration engine for request */ } lac_pke_qat_req_data_cb_info_t; /** ***************************************************************************** * @ingroup LacAsymCommonQatComms * * @description * Contains the input and output buffer data * *****************************************************************************/ typedef struct lac_pke_qat_req_data_param_info_s { CpaFlatBuffer *clientInputParams[LAC_MAX_MMP_INPUT_PARAMS]; /**< the client input parameters (unaligned flat buffers) */ CpaFlatBuffer *clientOutputParams[LAC_MAX_MMP_OUTPUT_PARAMS]; /**< the client output parameters (unaligned flat buffers) */ Cpa8U *pkeInputParams[LAC_MAX_MMP_INPUT_PARAMS]; /* the PKE input parameters (aligned data pointers) */ Cpa8U *pkeOutputParams[LAC_MAX_MMP_OUTPUT_PARAMS]; /* the PKE output parameters (aligned data pointers) */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS]; /* Array of input arguments sizes */ Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS]; /* Array of output arguments sizes */ } lac_pke_qat_req_data_param_info_t; /** *************************************************************************** * @ingroup LacAsymCommonQatComms * Request data for QAT messages * * @description * This structure defines the request data for PKE QAT messages. This is * used to store data which is known when the message is sent and which we wish * to retrieve when the response message is processed. **************************************************************************/ typedef struct lac_pke_qat_req_data_s { /* use union to ensure optimal alignment */ union lac_pke_qat_req_data_request_u { icp_qat_fw_pke_request_t request; /**< the PKE request */ Cpa8U padding[1 << LAC_OPTIMAL_ALIGNMENT_SHIFT]; } u1; /* use union to ensure optimal alignment */ union lac_pke_qat_req_data_in_args_u { icp_qat_fw_mmp_input_param_t inArgList; /**< msg input arg list */ Cpa8U padding[1 << LAC_OPTIMAL_ALIGNMENT_SHIFT]; } u2; /* use union to ensure optimal alignment */ union lac_pke_qat_req_data_out_args_u { icp_qat_fw_mmp_output_param_t outArgList; /**< msg output arg list */ Cpa8U padding[1 << LAC_OPTIMAL_ALIGNMENT_SHIFT]; } u3; lac_pke_qat_req_data_cb_info_t cbInfo; /**< Callback info */ lac_pke_qat_req_data_param_info_t paramInfo; /**< Parameter info */ struct lac_pke_qat_req_data_s *pNextReqData; /**< next req data ptr */ struct lac_pke_qat_req_data_s *pHeadReqData; /**< head req data ptr */ struct lac_pke_qat_req_data_s *pTailReqData; /**< tail req data ptr */ } lac_pke_qat_req_data_t; typedef void *lac_pke_request_handle_t; /**< @ingroup LacAsymCommonQatComms * Handle to a PKE request. The handle is created using LacPke_CreateRequest() * and is subsequently used to send the request using LacPke_SendRequest(). */ #define LAC_PKE_INVALID_HANDLE ((lac_pke_request_handle_t)0) /**< @ingroup LacAsymCommonQatComms * Invalid PKE request handle. */ /** *************************************************************************** * @ingroup LacAsymCommonQatComms * Handles a PKE response * * @description * This function is called by ADF when a response is * received from the QAT to a PKE request. The pPkeRespMsg is the message read * off the ring. * * @param[in] pRespMsg pointer to the response message * ***************************************************************************/ void LacPke_MsgCallback(void *pRespMsg); /** *************************************************************************** * @ingroup LacAsymCommonQatComms * Generates pke dummy response * * @description * This function is called during the error state of the device to * generate dummy responses from the pke request memory pool. * * @param[in] pBucket pointer to the bucket of memblks * * @retval CPA_STATUS_SUCCESS Successfully polled a memory pool with data * that generate dummy responses. * @retval CPA_STATUS_RETRY There are no in-flight requests in the * memory pool associated with the instance * ***************************************************************************/ CpaStatus LacPke_SwRespMsgCallback(lac_memblk_bucket_t *pBucket); /** ******************************************************************************* * @ingroup LacAsymCommonQatComms * Inits a PKE request in the request pool. * * @description * This function inits a PKE request with all information constant * for the instance. * * @pre * All the instance information (mmplib, flowid, etc. ) is set * before this function is called. * * @param[in,out] pData pointer to the request * @param[in] instanceHandle instanceHandle * * @retval none * ******************************************************************************/ void LacPke_InitAsymRequest(Cpa8U *pData, CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacAsymCommonQatComms * Creates a PKE request for the QAT. * * @description * This function takes the parameters for a PKE QAT request, creates the * request, resizes the input & output buffer parameters, and fills in the per * request PKE fields. The request can subsequently be sent to the QAT using * LacPke_SendRequest(). In the event of an error this function will tidy up * any resources associated with the request handle and set it to * PKE_INVALID_HANDLE. * * @pre * The requests in the request pool have been initialised using * Lac_MemPoolInitAsymRequest(). * * @param[in,out] pRequestHandle Pointer to hold the handle for the request * created by this call. If the incoming value * is non-zero then the new request is appended * to the request (chain) already associated * with the handle. For a single request, or * the first request in a chain, the passed in * handle value must be zero * (i.e. PKE_INVALID_HANDLE). * * @param[in] functionalityId the PKE functionality id. * @param[in] pInArgSizeList pointer to a list of input sizes required by * QAT. The client-provided input flat buffers * greater than or equal to their corresponding * size will be passed to QAT. Buffers that are * less than the required size will be copied into * internal driver buffers before being passed to * QAT. * @param[in] pOutArgSizeList pointer to a list of output sizes required by * QAT. * @param[in] pInArgList pointer to the list of input params. This * should contain the client-provided flat buffer * pointers. Any entries in the list which are not * used must be set to 0. * @param[in] pOutArgList pointer to the list of output params. This * should contain the client-provided flat buffer * pointers. Any entries in the list which are not * used must be set to 0. * @param[in] pInternalInMemList pointer to a list of Booleans that indicate if * input data buffers passed to QAT are internally * or externally allocated. This information needs * to be tracked to ensure we use the correct * virt2phys function. * @param[in] pInternalInMemList pointer to a list of Booleans that indicate if * output data buffers passed to QAT are internally * or externally allocated. * @param[in] pPkeOpCbFunc this function is invoked when the response is * received from the QAT * @param[in] pCbData callback data to be returned (by copy) * unchanged in the callback. * @param[in] instanceHandle instanceHandle * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RESOURCE Resource error (e.g. failed memory allocation) * ******************************************************************************/ CpaStatus LacPke_CreateRequest(lac_pke_request_handle_t *pRequestHandle, Cpa32U functionalityId, Cpa32U *pInArgSizeList, Cpa32U *pOutArgSizeList, icp_qat_fw_mmp_input_param_t *pInArgList, icp_qat_fw_mmp_output_param_t *pOutArgList, CpaBoolean *pInternalInMemList, CpaBoolean *pInternalOutMemList, lac_pke_op_cb_func_t pPkeOpCbFunc, lac_pke_op_cb_data_t *pCbData, CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacAsymCommonQatComms * Sends a PKE request to the QAT. * * @description * This function sends a PKE request, previously created using * LacPke_CreateRequest(), to the QAT. It does not block waiting for a * response. Instead the callback function is invoked when the response from * the QAT has been processed. * * @param[in,out] pRequestHandle the handle of the PKE request (chain) to be * sent. Will be set to CPA_INVALID_HANDLE in * the case of any error. * @param[in] instanceHandle Acceleration engine to which the message * will be sent. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RETRY Ring full * ******************************************************************************/ CpaStatus LacPke_SendRequest(lac_pke_request_handle_t *pRequestHandle, CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacAsymCommonQatComms * Sends a single (unchained) PKE request to the QAT. * * @description * This function takes the parameters for a PKE QAT request, creates the * request, fills in the PKE fields and sends it to the QAT. It does not block * waiting for a response. Instead the callback function is invoked when the * response from the QAT has been processed. * * @param[in] functionalityId the PKE functionality id. * @param[in] pInArgSizeList pointer to a list of input sizes required by * QAT. The client-provided input flat buffers * greater than or equal to their corresponding * size will be passed to QAT. Buffers that are * less than the required size will be copied into * internal driver buffers before being passed to * QAT. * @param[in] pOutArgSizeList pointer to a list of output sizes required by * QAT. * @param[in] pInArgList pointer to the list of input params. This * should contain the client-provided flat buffer * pointers. Any entries in the list which are not * used must be set to 0. * @param[in] pOutArgList pointer to the list of output params. This * should contain the client-provided flat buffer * pointers. Any entries in the list which are not * used must be set to 0. * @param[in] pInternalInMemList pointer to a list of Booleans that indicate if * input data buffers passed to QAT are internally * or externally allocated. This information needs * to be tracked to ensure we use the correct * virt2phys function. * @param[in] pInternalInMemList pointer to a list of Booleans that indicate if * output data buffers passed to QAT are internally * or externally allocated. * @param[in] pPkeOpCbFunc this function is invoked when the response is * received from the QAT * @param[in] pCbData callback data to be returned (by copy) * unchanged in the callback. * @param[in] instanceHandle instanceHandle * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RESOURCE Resource error (e.g. failed memory allocation) * @retval CPA_STATUS_RETRY Ring full * ******************************************************************************/ CpaStatus LacPke_SendSingleRequest(Cpa32U functionalityId, Cpa32U *pInArgSizeList, Cpa32U *pOutArgSizeList, icp_qat_fw_mmp_input_param_t *pInArgList, icp_qat_fw_mmp_output_param_t *pOutArgList, CpaBoolean *pInternalInMemList, CpaBoolean *pInternalOutMemList, lac_pke_op_cb_func_t pPkeOpCbFunc, lac_pke_op_cb_data_t *pCbData, CpaInstanceHandle instanceHandle); #endif /* _LAC_PKE_QAT_COMMS_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_pke_utils.h000066400000000000000000000734121503624047500331130ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_pke_utils.h * * @defgroup LacAsymCommonUtils Lac Pke Utils * * @ingroup LacAsymCommon * * utils that are PKE specific * ******************************************************************************/ /******************************************************************************/ #ifndef _LAC_PKE_UTILS_H_ #define _LAC_PKE_UTILS_H_ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include #include "cpa.h" #include "cpa_cy_common.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ #include "Osal.h" #include "lac_mem.h" /******************************************************************************/ /* ******************************************************************************* * LAC PKE Operation sizes ******************************************************************************* */ #define LAC_128_BITS (128) #define LAC_160_BITS (160) #define LAC_192_BITS (192) #define LAC_224_BITS (224) #define LAC_256_BITS (256) #define LAC_384_BITS (384) #define LAC_512_BITS (512) #define LAC_576_BITS (576) #define LAC_768_BITS (768) #define LAC_1024_BITS (1024) #define LAC_1536_BITS (1536) #define LAC_2048_BITS (2048) #define LAC_2560_BITS (2560) #define LAC_3072_BITS (3072) #define LAC_3584_BITS (3584) #define LAC_4096_BITS (4096) #define LAC_8192_BITS (8192) #define LAC_MAX_OP_SIZE_IN_BITS LAC_8192_BITS /**< @ingroup LacAsymCommon * Maximum PKE operation in bits */ #define LAC_MAX_PRIME_SIZE_IN_BITS LAC_4096_BITS /**< @ingroup LacAsymCommon * Maximum prime size in bits */ #define LAC_QAT_ASYM_REQ_SZ_LW 16 /**< @ingroup LacAsymCommon * LAC PKE QAT Request message size) */ #define LAC_QAT_ASYM_RESP_SZ_LW 8 /**< @ingroup LacAsymCommon * LAC PKE QAT Response message size) */ #ifdef MAX_MR_ROUND #define LAC_PRIME_MAX_MR MAX_MR_ROUND #else #define LAC_PRIME_MAX_MR 50 #endif /**< * MAX number of MR rounds can be decided at compile time */ #define LAC_PKE_MAX_CHAIN_LENGTH (LAC_PRIME_MAX_MR + 3) /**< @ingroup LacAsymCommon * LAC PKE Max number of PKE requests that can be chained per QAT message. * In the case of prime we can have LAC_PRIME_MAX_MR MR messages, 1 gcd * message, 1 fermat message and 1 lucas message per QAT message (on the ring). * In the case of ECDH we chain 2 request (pt_mul and pt_verify). We should * scale our asym request memory pool for the worst case */ #define LAC_PKE_BUFFERS_PER_OP_MAX 14 /**< @ingroup LacAsymCommon * LAC PKE Max number of Alignment buffers required per QAT message * In the case of prime we can have 1 gcd message (1 input), 1 fermat message * (1 input) and 1 lucas message (1 input) per QAT message. * We only resize the prime twice however, once in the GCD case and once for * all other cases. MR buffer never needs to be resize. This is ensured by API * definition. * * In the case of ECDH we can have 14 inputs and outputs. * * For all other cases the number of inputs and outputs sum to * (ICP_QAT_FW_PKE_INPUT_COUNT_MAX+ICP_QAT_FW_PKE_OUTPUT_COUNT_MAX) per * QAT message. */ /** ******************************************************************************* * @ingroup LacAsymCommonUtils * This macro calculates the length of the given array * * @param[in] array the array whose length we are calculating * ******************************************************************************/ #define LAC_ARRAY_LEN(array) (sizeof(array) / sizeof(array[0])) /** ******************************************************************************* * @ingroup LacAsymCommonUtils * This macro returns the greater value - x or y * * @param[in] x parameter to compare * @param[in] y parameter to compare against * @sideeffect this macro is false if x and/or y are not constant * ******************************************************************************/ #define LAC_MAX(x, y) (x > y) ? x : y /** ******************************************************************************* * @ingroup LacAsymCommonUtils * This macro converts all negative 32 bit numbers to -1 and all positive * 32 bit numbers to +1 * * @param[in] num 32-bit signed number to convert * ******************************************************************************/ #define LAC_SIGNED_CONVERT32(num) ((((num) >> 31) << 1) + 1) /** ***************************************************************************** * @ingroup LacAsymCommonUtils * * @description * This enum lists the types of param check that can be performed on the # * size of a buffer. * *****************************************************************************/ typedef enum { CHECK_EQUALS = 0, CHECK_LESS_EQUALS, CHECK_GREATER_EQUALS, CHECK_NONE } lac_pke_size_check_type_t; /** ******************************************************************************* * @ingroup LacAsymCommonUtils * This macro checks if the flat buffer data is ODD * * @param[in] pBuffer pointer to the flat buffer to check * * @return CPA_STATUS_INVALID_PARAM Not odd * @return void Odd * ******************************************************************************/ #define LAC_CHECK_ODD_PARAM(pBuffer) \ do \ { \ if (!((pBuffer)->pData[(pBuffer)->dataLenInBytes - 1] & 0x01)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " doesn't have LSB set"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Checks that a flat buffer's size is correct. * * @description * Checks that a flat buffer's size is correct. The check type specifies * the type of check to be performed e.g. less than or equals, equals etc. * If any check fails an error is logged and the calling function is * returned out of with an error. * * @param[in] pBuffer pointer to the flat buffer to check * @param[in] checkType type of check performed on the buffer's length * @param[in] lenInBytes the required length * * @return CPA_STATUS_INVALID_PARAM Length check failed * @return void All checks passed ******************************************************************************/ #define LAC_CHECK_SIZE(pBuffer, checkType, lenInBytes) \ do \ { \ if ((pBuffer)->dataLenInBytes == 0) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " has incorrect length of zero"); \ return CPA_STATUS_INVALID_PARAM; \ } \ \ if ((CHECK_EQUALS == checkType) && \ ((pBuffer)->dataLenInBytes != lenInBytes)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " has incorrect length"); \ return CPA_STATUS_INVALID_PARAM; \ } \ else if ((CHECK_LESS_EQUALS == checkType) && \ ((pBuffer)->dataLenInBytes > lenInBytes)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " has incorrect length"); \ return CPA_STATUS_INVALID_PARAM; \ } \ else if ((CHECK_GREATER_EQUALS == checkType) && (lenInBytes > 0)) \ { \ if ((pBuffer)->dataLenInBytes < lenInBytes) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " has incorrect length"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } \ \ } while (0) /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Checks that a flat buffer is valid and the size of the buffer is correct. * * @description * This macro checks that a flat buffer is not null, that its length is * correct. * If any check fails an error is logged and the calling function is * returned out of with an error. * * @param[in] pBuffer pointer to the flat buffer to check * @param[in] checkType type of check performed on the buffer's length * @param[in] lenInBytes the required length * * @return CPA_STATUS_INVALID_PARAM Null, Length, LSB and/or MSB checks failed * @return void All checks passed ******************************************************************************/ #define LAC_CHECK_FLAT_BUFFER_PARAM(pBuffer, checkType, lenInBytes) \ do \ { \ LAC_CHECK_FLAT_BUFFER(pBuffer); \ LAC_CHECK_SIZE((pBuffer), checkType, lenInBytes); \ } while (0) /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Checks that a number in a flat buffer is valid. * * @description * This macro checks that a flat buffer is not null, that its length is * non-zero, checks the byte length of the number in the buffer relative to * lenInBytes and optionally checks that the LSB is set. * If any check fails an error is logged and the calling function is * returned out of with an error. * * @param[in] pBuffer pointer to the flat buffer to check * @param[in] checkType type of check performed on the buffer's length * @param[in] lenInBytes the required byte length * @param[in] checkLsb flag to indicate whether (true) or not (false) * to check that the LSB is set * * @return CPA_STATUS_INVALID_PARAM Null, Length, LSB checks failed * @return void All checks passed ******************************************************************************/ #define LAC_CHECK_FLAT_BUFFER_PARAM_PKE( \ pBuffer, checkType, lenInBytes, checkLsb) \ do \ { \ LAC_CHECK_FLAT_BUFFER(pBuffer); \ if ((pBuffer)->dataLenInBytes == 0) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " has incorrect length of zero"); \ return CPA_STATUS_INVALID_PARAM; \ } \ if ((CHECK_EQUALS == checkType) && \ (lenInBytes != LacPke_GetMinBytes(pBuffer))) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer \ " contains number of incorrect size"); \ return CPA_STATUS_INVALID_PARAM; \ } \ else if ((CHECK_LESS_EQUALS == checkType) && \ (LacPke_GetMinBytes(pBuffer) > lenInBytes)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer \ " contains number that is too large"); \ return CPA_STATUS_INVALID_PARAM; \ } \ else if ((CHECK_GREATER_EQUALS == checkType) && \ (LacPke_GetMinBytes(pBuffer) < lenInBytes)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer \ " contains number that is too small"); \ return CPA_STATUS_INVALID_PARAM; \ } \ if (checkLsb) \ { \ LAC_CHECK_ODD_PARAM(pBuffer); \ } \ } while (0) /* define MSB/LSB check flags */ #define LAC_CHECK_MSB_YES 1 #define LAC_CHECK_MSB_NO 0 #define LAC_CHECK_LSB_YES 1 #define LAC_CHECK_LSB_NO 0 /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Checks msb/lsb of a number in a flatbuffer given the bytelen of * the number. * * @description * This macro optionally checks that the MSB and/or the LSB of a number * in a flat buffer (given the byteLen of the number) is set. * If any check fails an error is logged and the calling function is * returned out of with an error. * * @param[in] pBuffer pointer to the flat buffer to check (MUST have * dataLenInBytes >= lenInbytes) * @param[in] lenInBytes the byte length of the number in the buffer * @param[in] checkMsb flag to indicate whether (true) or not (false) * to check that the MSB is set * @param[in] checkLsb flag to indicate whether (true) or not (false) * to check that the LSB is set * * @return CPA_STATUS_INVALID_PARAM LSB and/or MSB checks failed * @return void All checks passed ******************************************************************************/ #define LAC_CHECK_FLAT_BUFFER_MSB_LSB(pBuffer, lenInBytes, checkMsb, checkLsb) \ do \ { \ if (checkMsb && \ !((pBuffer)->pData[(pBuffer)->dataLenInBytes - lenInBytes] & \ 0x80)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " doesn't have MSB set"); \ return CPA_STATUS_INVALID_PARAM; \ } \ if (checkLsb) \ { \ LAC_CHECK_ODD_PARAM(pBuffer); \ } \ } while (0) /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Checks that a flat buffer is non zero. * * @description * This macro checks that a flat buffer's data is non zero. * * @param[in] pBuffer pointer to the flat buffer to check * dataLenInBytes MUST be greater than 0 * * @return CPA_STATUS_INVALID_PARAM Non zero check failed * @return void All checks passed ******************************************************************************/ #define LAC_CHECK_NON_ZERO_PARAM(pBuffer) \ do \ { \ if (0 == LacPke_CompareZero((pBuffer), 0)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " cannot be zero"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Checks that a flat buffer data size is non zero. * * @description * This macro checks that a flat buffer's data size is non zero. * * @param[in] pBuffer pointer to the flat buffer to check * * @return CPA_STATUS_INVALID_PARAM Non zero check failed * @return void Check passed ******************************************************************************/ #define LAC_CHECK_ZERO_SIZE(pBuffer) \ do \ { \ if ((pBuffer)->dataLenInBytes == 0) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " has incorrect length of zero"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Compare one large integer (+- delta) to another (+- delta) * * @description * This function compares two large integers. The deltas are added to * the large integers and may be negative. The sum of the sizes of the buffers * containing the large numbers must be greater than 0. * * @param[in] pBufferA first integer * @param[in] lengthA length of first integer in bytes * @param[in] deltaA delta, -(1<<30)< deltaA < (1<<30) * @param[in] pBufferB second integer * @param[in] lengthB length of second integer in bytes * @param[in] deltaB delta, -(1<<30)< deltaB < (1<<30) * * @retval less than 0 if integerA + deltaA < integerB + deltaB * @retval 0 if integerA + deltaA = integerB + deltaB * @retval greater than 0 if integerA + deltaA > integerB + deltaB * ******************************************************************************/ Cpa32S LacPke_CompareIntPtrs(const Cpa8U *pBufferA, Cpa32U lengthA, const Cpa32S deltaA, const Cpa8U *pBufferB, Cpa32U lengthB, const Cpa32S deltaB); /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Compare one large integer (+- delta) to another (+- delta) * * @description * This function compares two large integers. The deltas are added to * the large integers and may be negative. The sum of the sizes of the buffers * containing the large numbers must be greater than 0. * * @param[in] pFlatBufferA first integer * @param[in] deltaA delta, -(1<<30)< deltaA < (1<<30) * @param[in] pFlatBufferB second integer * @param[in] deltaB delta, -(1<<30)< deltaB < (1<<30) * * @retval less than 0 if integerA + deltaA < integerB + deltaB * @retval 0 if integerA + deltaA = integerB + deltaB * @retval greater than 0 if integerA + deltaA > integerB + deltaB * ******************************************************************************/ Cpa32S LacPke_Compare(const CpaFlatBuffer *pFlatBufferA, const Cpa32S deltaA, const CpaFlatBuffer *pFlatBufferB, const Cpa32S deltaB); /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Compare one large integer (+- delta) to 0 * * @description * This function compares a large integer to 0. The delta is added to * the large integer and may be negative. * * @param[in] pFlatBuffer buffer containing large integer MUST have * dataLenInBytes > 0 * @param[in] delta delta * * @retval less than 0 if integerA + deltaA < 0 * @retval 0 if integerA + deltaA = 0 * @retval greater than 0 if integerA + deltaA > 0 * ******************************************************************************/ Cpa32S LacPke_CompareZero(const CpaFlatBuffer *pFlatBuffer, const Cpa32S delta); /** ******************************************************************************* * @ingroup LacAsymCommonUtils * Compare one large integer to another * * @description * This function checks whether two large integers are equal. * * @param[in] pFlatBufferA first integer in a flat buffer * @param[in] pBufferB second integer * @param[in] lengthB length of second integer in bytes * * @retval CPA_TRUE if integers are equal * CPA_FALSE otherwise * ******************************************************************************/ CpaBoolean LacPke_CompareFlatAndPtr(const CpaFlatBuffer *pFlatBufferA, const Cpa8U *pBufferB, Cpa32U lengthB); /** ****************************************************************************** * @ingroup LacAsymCommonUtils * Returns the min length in bytes required to represent a number in a flat * buffer * * @description * Returns the min length in bytes required to represent a number in a flat * buffer. If the buffer is 0 this dataLenInBytes will be returned. * * @param[in] pBuffer pointer to FlatBuffer (should NOT be NULL). * pData of the FlatBuffer can be NULL iff * dataLenInBytes=0 * @retval most significant byte of number in FlatBuffer * *****************************************************************************/ Cpa32U LacPke_GetMinBytes(const CpaFlatBuffer *pBuffer); /** ****************************************************************************** * @ingroup LacAsymCommonUtils * Returns the highest bit position of a number in a flat buffer * (except if number is zero, see below). * Also returns index to access most significant byte of flat buffer * * @description * If X is a number in a FlatBuffer then this function calculates * floor[log2(X)] for X>0. * This can be used to locate the position of the msb (position indexed * from 0). For example, floor[log2(1)] = 0 = b1 (the 0th bit is set). * For example, floor[log2(8)] = 3 = b1000 (the 3rd bit is set). * For example, floor[log2(21)] = 4 = b10101 (the 4th bit is set). * * If X=0 floor[log2(X)] is "undefined" but in this function it is * convenient to set the isZero flag CPA_TRUE and BitPos=0. * * Currently limited to buffers with max 4096 bits (we have no pke service * for bigger numbers) * * @param[in] pBuffer pointer to FlatBuffer (should NOT be NULL). * pData of the FlatBuffer can be NULL iff * dataLenInBytes=0 * @param[in/out] pBitPos value will be updated to floor[log2(X)] for X>0 * or if X=0 it will be set to 0, where X is the * number in FlatBuffer. If dataLenInBytes=0 then * this will be set to 0. * @param[in/out] pIndexMsb value will be updated to access most * significant byte of number in FlatBuffer * If number in buffer is 0 then index will be set * to dataLenInBytes-1. If dataLenInBytes=0 * (i.e. pData == NULL) then index will * be set to -1 * @param[in/out] pIsZero will be set CPA_TRUE if number in FlatBuffer = * 0. If dataLenInBytes=0 then this will be set * CPA_TRUE * * @retval CPA_STATUS_INVALID_PARAM if number is greater than 512 bytes * CPA_STATUS_SUCCESS otherwise * *****************************************************************************/ CpaStatus LacPke_GetBitPos(const CpaFlatBuffer *pBuffer, Cpa32U *pBitPos, Cpa32U *pIndexMsb, CpaBoolean *pIsZero); /** ****************************************************************************** * @ingroup LacAsymCommonUtils * Returns the bit length of a number in a flat buffer. Note if number is * zero bitLen = 0; * * @description * Returns the minimum number of bits need to represent a number in a * buffer. If more than 4096 bits are required we return _INVALID_PARAM * (we have no pke service for bigger numbers) * * @param[in] pBuffer pointer to FlatBuffer (should NOT be NULL). * pData of the FlatBuffer can be NULL iff * dataLenInBytes=0 * @param[in/out] pBitLen value will be updated to minimum number of bits * needed to represent number in FlatBuffer. * * @retval CPA_STATUS_INVALID_PARAM if number is greater than 4096 bytes * CPA_STATUS_SUCCESS otherwise * *****************************************************************************/ CpaStatus LacPke_GetBitLen(const CpaFlatBuffer *pBuffer, Cpa32U *pBitLen); /** *************************************************************************** * @ingroup LacAsymCommonUtils * Return the size in bytes of biggest number in provided n buffers * * @description * Return the size of the biggest number in provided buffers where n * specify buffer count. If NULL pointer was detected is skipped from * comparison. * * @param[in] n number of buffers to compare * @param[in] ... list of pointers to a flat buffers * * @retval max the size of the biggest number * ***************************************************************************/ Cpa32U LacPke_GetMaxLnOfNBuffers(int n, ...); #endif /* _LAC_PKE_UTILS_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/include/lac_prime.h000066400000000000000000000317641503624047500322340ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** *************************************************************************** * @file lac_prime.h * * @defgroup Lac_Prime Prime * * @ingroup LacAsym * * Interfaces exposed by the Prime Component * * @lld_start * * @lld_overview * This is the Prime feature implementation. It implements four methods for * primality test: GCD, Fermat test, Miller-Rabin and Lucas test. The client may * require combined testing, i.e. up to one GCD + up to one Fermat + up to * 50 Miller-Rabin rounds + up to one Lucas. * * For Miller-Rabin test the client supplies the array of random numbers. * Further processing requires a flat buffer to be associated with each random * number. The memory for these flat buffers is assigned internally, as needed, * from the pre-allocated memory pool. * * In addition to the standard check on the parameters supplied by the client, * the prime candidate of the acceptable length is tested for MSB and LSB (non- * -even number). For Miller-Rabin method, the number of requested rounds must * not exceed 50, the supplied random numbers must match the prime candidate in * length and have to fall in within 1 and prime-1 (1 < random < prime-1) * boundaries. * * The requests for service are created and chained as necessary for multiple * tests in the increasing complexity order: GCD->Fermat->Miller-Rabin->Lucas. * The internal functions are called to calculate the function ID for each * method and to construct the input/output argument lists before calling the * PKE QAT Comms layer to create the request. After all requests have been * created, the PKE QAT Comms layer is called to propagate the requests to the * QAT. * * Buffer alignment is handled by the PKE QAT Comms layer. * * @lld_dependencies * - @ref LacPkeQatComms "PKE QAT Comms" : For creating and sending messages * to the QAT * - @ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - OSAL : For atomics and logging * * @lld_module_algorithms * LacPke_CreateRequest() function takes the parameters for a PKE QAT request, * creates the request, aligns the input & output buffer parameters, and fills * in the PKE fields. The request can subsequently be sent to the QAT using * LacPke_SendRequest(). In the event of an error this function will tidy up any * resources associated with request handle and set it to PKE_INVALID_HANDLE. * When the chain of requests is formed (with the same requestHandle) each * request structure gets a pointer filled in to point to the next structure * (PKE request). * * LacPke_SendRequest() function sends a PKE request, previously created using * LacPke_CreateRequest(), to the QAT. It does NOT block waiting for a response. * In the case of synchronous mode the blocking is done elsewhere in the code * using wait-queues, and the callback method is handled internally. The * callback function is invoked when the response from the QAT has been * processed. When a chain of requests is formed, this function sends the * request - head of the chain to the QAT. The QAT performs the required * operation, in this case the flavour of Prime test. In the event of a * successful operation (positive result) the QAT checks if there is a pointer * to point to the next request structure, automatically invokes the next * request, performs the operation and so on. * * If any operation returns a negative result then the QAT sends a negative * respond back regardless of reaching the end request or not. Similarly, * only when all operations result in a positive outcome and the QAT reaches * the end of the chain and only then is able to send a positive response. * * @note * The Prime feature may be called in Asynchronous or Synchronous modes. * In Asynchronous mode the user supplies a Callback function to the API. * Control returns to the client after the message has been sent to the QAT and * the Callback gets invoked when the QAT completes the operation. There is NO * BLOCKING. This mode is preferred for maximum performance. * In Synchronous mode the client supplies no Callback function pointer (NULL) * and the point of execution is placed on a wait-queue internally, and this is * de-queued once the QAT completes the operation. Hence, Synchronous mode is * BLOCKING. So avoid using in an interrupt context. To achieve maximum * performance from the API Asynchronous mode is preferred. * * @lld_process_context * * @lld_end * ***************************************************************************/ /*****************************************************************************/ #ifndef LAC_PRIME_H #define LAC_PRIME_H #include "cpa.h" /* Include Osal files */ #include "Osal.h" /* Include QAT files */ #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" /*** Types definitions ***/ typedef enum { LAC_PRIME_TEST_START_DELIMITER, LAC_PRIME_GCD, LAC_PRIME_FERMAT, LAC_PRIME_MILLER_RABIN, LAC_PRIME_LUCAS, LAC_PRIME_TEST_END_DELIMITER } lac_prime_test_t; /** ******************************************************************************* * @ingroup Lac_Prime * print the Prime stats to standard output * * @description * For each Instance this function copies the stats using the function * cpaCyPrimeQueryStats. It then prints contents of this structure to * standard output. * * @param[in] instanceHandle instanceHandle * * @see cpaCyPrimeQueryStats() * *****************************************************************************/ void LacPrime_StatsShow(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup Lac_Prime * Prime Get Function ID function * * @description * Given the opLenInBits this function selects the appropriate PKE * functionID * * @param[in] testId prime test to be carried out * @param[in] opLenInBits pointer to length in bits of the prime candidate * to be tested. This value may be updated by this * function to the PKE interface requires data of * a larger length * @retval FunctionID functionID to be used * *****************************************************************************/ Cpa32U LacPrimeGetFuncID(lac_prime_test_t testId, Cpa32U *opLenInBits); /** ******************************************************************************* * @ingroup Lac_Prime * Populate Prime Input and Output Parameter function * * @description * Given the testId this function fills out the lists describing the * input and output parameters to PKE * * @param[in] testId prime test to be carried out * @param[in] opSizeInBytes length in bytes of the prime candidate * @param[in] pIn pointer to icp_qat_fw_mmp_input_param_t * structure to be filled out by this function * @param[in] pOut pointer to icp_qat_fw_mmp_output_param_t * structure to be filled out by this function * @param[in] pInSize pointer to array of input buffer sizes to be * filled out by this function * @param[in] pInternalMemInList pointer to array of booleans describing if * memory is internally or externally allocated. * Elements of this array will be modified by this * function * @param[in] internalPrimeMem boolean to indicate if the prime is in * internally or externally allocated memory. * @param[in] pPrimeBuff pointer to flatbuffer holding the prime. It can * either be the user supplied buffer or an internal * buffer in the case where the prime has been * previously resized. * @param[in] pInputMillerRabinBuffer if testId == MILLER_RABIN then this * contains the pointer the the flatbuffer * describing the Miller Rabin input data * otherwise can be NULL * *****************************************************************************/ void LacPrimePopulateParam(lac_prime_test_t testId, Cpa32U opSizeInBytes, icp_qat_fw_mmp_input_param_t *pIn, icp_qat_fw_mmp_output_param_t *pOut, Cpa32U *pInSize, CpaBoolean *pInternalMemInList, CpaBoolean internalPrimeMem, CpaFlatBuffer *pPrimeBuff, const CpaFlatBuffer *pInputMillerRabinBuffer); #ifdef ICP_PARAM_CHECK /** ******************************************************************************* * @ingroup Lac_Prime * Prime Test Parameter Check * * @description * Performs basic validation of the client's input parameters. * Checks for NULL pointers etc. * * @param[in] pCb user supplied callback function or in the sync * case our internal callback function * @param[in] pOpData pointer to user supplied CpaCyPrimeTestOpData * structure * @param[in] pTestPassed pointer to memory to write the result of the * prime check * * @retval CPA_STATUS_SUCCESS Validation passed * @retval CPA_STATUS_INVALID_PARAM Validation failed * *****************************************************************************/ CpaStatus LacPrimeParameterCheck(CpaCyPrimeTestCbFunc pCb, CpaCyPrimeTestOpData *pOpData, CpaBoolean *pTestPassed); #endif /** ******************************************************************************* * @ingroup Lac_Prime * Prime Test Callback Function * * @description * Called by PKE QAT COMMS when a response to a prime message is received * from the QAT. This function increments stats and frees resources where * appropriate before calling the client's callback. * * @param[in] status status of the response message received from QAT * @param[in] pass result of prime test from PKE. If CPA_FALSE prime * candidate is composite. If CPA_TRUE there is a * possibility the prime candidate is prime * @param[in] instanceHandle Identifies the instance processing this request * @param[in] pCbData pointer to callback data * *****************************************************************************/ void LacPrimeTestCallback(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData); /** ******************************************************************************* * @ingroup Lac_Prime * Compile time check of FW interface * * @description * Performs a compile time check of PKE interface to ensure IA assumptions * about the interface are valid. * *****************************************************************************/ void LacPrime_CompileTimeAssertions(void); #endif /* LAC_PRIME_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/large_number/000077500000000000000000000000001503624047500311345ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/large_number/lac_ln.c000066400000000000000000001256421503624047500325420ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_ln.c Large Number API Implementation * * @ingroup LacAsymLn * * @description * This file contains the implementation of Large Number * functions * ***************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ /* Include API files */ #include "cpa.h" #include "cpa_cy_ln.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Osal Includes */ #include "Osal.h" /* adf Includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "sal_service_state.h" #include "lac_sal_ctrl.h" #include "lac_pke_qat_comms.h" #include "lac_hooks.h" #include "lac_ln.h" #include "lac_pke_utils.h" #include "sal_statistics.h" /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* Number of LN statistics */ #define LAC_LN_NUM_STATS (sizeof(CpaCyLnStats64) / sizeof(Cpa64U)) /* ******************************************************************************** * Static Variables ******************************************************************************** */ /* macro to initialize all Large Number (LN) Service stats * (stored in internal array of atomics) */ #define LAC_LN_STATS_INIT(pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_LN_NUM_STATS; i++) \ { \ osalAtomicSet(0, &pCryptoService->pLacLnStatsArr[i]); \ } \ } while (0) /* macro to increment a Large Number (LN) Service stat * (derives offset into array of atomics) */ #ifndef DISABLE_STATS #define LAC_LN_STAT_INC(statistic, pCryptoService) \ do \ { \ if (CPA_TRUE == \ pCryptoService->generic_service_info.stats->bLnStatsEnabled) \ { \ osalAtomicInc( \ &pCryptoService \ ->pLacLnStatsArr[offsetof(CpaCyLnStats64, statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) #else #define LAC_LN_STAT_INC(statistic, pCryptoService) #endif /* macro to get Large Number (LN) Service 32bit stats (from internal array of * atomics) * into user supplied structure CpaCyLnStats pointed by lnStats * pointer */ #define LAC_LN_STATS32_GET(lnStats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_LN_NUM_STATS; i++) \ { \ ((Cpa32U *)&(lnStats))[i] = \ (Cpa32U)osalAtomicGet(&pCryptoService->pLacLnStatsArr[i]); \ } \ } while (0) /* macro to get Large Number (LN) Service 64bit stats (from internal array of * atomics) * into user supplied structure CpaCyLnStats pointed by lnStats * pointer */ #define LAC_LN_STATS64_GET(lnStats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_LN_NUM_STATS; i++) \ { \ ((Cpa64U *)&(lnStats))[i] = \ osalAtomicGet(&pCryptoService->pLacLnStatsArr[i]); \ } \ } while (0) /* Maps between operation sizes and Large Number Modular Exponentiation * function ids */ static const Cpa32U lacMathsModexpSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_512_BITS, MATHS_MODEXP_L512}, {LAC_1024_BITS, MATHS_MODEXP_L1024}, {LAC_1536_BITS, MATHS_MODEXP_L1536}, {LAC_2048_BITS, MATHS_MODEXP_L2048}, {LAC_2560_BITS, MATHS_MODEXP_L2560}, {LAC_3072_BITS, MATHS_MODEXP_L3072}, {LAC_3584_BITS, MATHS_MODEXP_L3584}, {LAC_4096_BITS, MATHS_MODEXP_L4096}, {LAC_8192_BITS, MATHS_MODEXP_L8192}}; /* Maps between operation sizes and Large Number Modular Inversion Odd * function ids */ static const Cpa32U lacMathsModinvOddSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_128_BITS, MATHS_MODINV_ODD_L128}, {LAC_192_BITS, MATHS_MODINV_ODD_L192}, {LAC_256_BITS, MATHS_MODINV_ODD_L256}, {LAC_384_BITS, MATHS_MODINV_ODD_L384}, {LAC_512_BITS, MATHS_MODINV_ODD_L512}, {LAC_768_BITS, MATHS_MODINV_ODD_L768}, {LAC_1024_BITS, MATHS_MODINV_ODD_L1024}, {LAC_1536_BITS, MATHS_MODINV_ODD_L1536}, {LAC_2048_BITS, MATHS_MODINV_ODD_L2048}, {LAC_3072_BITS, MATHS_MODINV_ODD_L3072}, {LAC_4096_BITS, MATHS_MODINV_ODD_L4096}, {LAC_8192_BITS, MATHS_MODINV_ODD_L8192}}; /* Maps between operation sizes and Large Number Modular Inversion Even * function ids */ static const Cpa32U lacMathsModinvEvenSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_128_BITS, MATHS_MODINV_EVEN_L128}, {LAC_192_BITS, MATHS_MODINV_EVEN_L192}, {LAC_256_BITS, MATHS_MODINV_EVEN_L256}, {LAC_384_BITS, MATHS_MODINV_EVEN_L384}, {LAC_512_BITS, MATHS_MODINV_EVEN_L512}, {LAC_768_BITS, MATHS_MODINV_EVEN_L768}, {LAC_1024_BITS, MATHS_MODINV_EVEN_L1024}, {LAC_1536_BITS, MATHS_MODINV_EVEN_L1536}, {LAC_2048_BITS, MATHS_MODINV_EVEN_L2048}, {LAC_3072_BITS, MATHS_MODINV_EVEN_L3072}, {LAC_4096_BITS, MATHS_MODINV_EVEN_L4096}, {LAC_8192_BITS, MATHS_MODINV_EVEN_L8192}}; /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ /** ******************************************************************************* * @ingroup LacAsymLn * Ln Get Buffer Data Size in Bytes function * The function scans the input buffer to locate the most significant non-zero * byte of a number in big endian order. ******************************************************************************/ STATIC Cpa32U LacGetBufferDataSizeInBytes(const CpaFlatBuffer *pBuffer) { Cpa32U dataSizeInBytes = 0; Cpa32U counter = 0; if (NULL != pBuffer) { Cpa32U maxDataSize = pBuffer->dataLenInBytes; for (counter = 0; (counter < maxDataSize) && (0 == dataSizeInBytes); counter++) { if (pBuffer->pData[counter]) { dataSizeInBytes = maxDataSize - counter; } } } return dataSizeInBytes; } /** ******************************************************************************* * @ingroup LacAsymLn * Large Number Modular Exponentiation internal callback function ******************************************************************************/ STATIC void LacLnModExpCallback(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; CpaCyLnModExpOpData *pOpData = NULL; void *pCallbackTag = NULL; CpaFlatBuffer *pResult = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* retrieve data from the callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOpData = (CpaCyLnModExpOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCallbackTag = pCbData->pCallbackTag; pResult = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pResult); /* pass flag is not used here */ #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_LN_STAT_INC(numLnModExpCompleted, pCryptoService); } else { LAC_LN_STAT_INC(numLnModExpCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pResult); } #ifdef ICP_PARAM_CHECK /** ******************************************************************************* * @ingroup LacAsymLn * Ln ModExp parameter check ******************************************************************************/ STATIC CpaStatus LacLnModExpParameterCheck(const CpaCyGenFlatBufCbFunc pCb, CpaCyLnModExpOpData *pOpData, CpaFlatBuffer *pResult) { CpaStatus status = CPA_STATUS_SUCCESS; /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for null Operational Data parameters */ LAC_CHECK_NULL_PARAM(pOpData); /* check for null result pointer */ LAC_CHECK_NULL_PARAM(pResult); /* check for null argument parameters */ LAC_CHECK_FLAT_BUFFER(&pOpData->base); LAC_CHECK_ZERO_SIZE(&pOpData->base); LAC_CHECK_FLAT_BUFFER(&pOpData->exponent); LAC_CHECK_ZERO_SIZE(&pOpData->exponent); LAC_CHECK_FLAT_BUFFER(&pOpData->modulus); LAC_CHECK_ZERO_SIZE(&pOpData->modulus); LAC_CHECK_FLAT_BUFFER(pResult); LAC_CHECK_ZERO_SIZE(pResult); /* Zero modulus is an invalid parameter */ LAC_CHECK_NON_ZERO_PARAM(&pOpData->modulus); return status; } #endif /** *************************************************************************** * @ingroup LacAsymLn * Large Number Modular Exponentiation synchronous function ***************************************************************************/ STATIC CpaStatus LacLnModExpSyn(const CpaInstanceHandle instanceHandle, const CpaCyLnModExpOpData *pLnModExpOpData, CpaFlatBuffer *pResult) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyLnModExp(instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, pLnModExpOpData, pResult); } else { #ifndef DISABLE_STATS LAC_LN_STAT_INC(numLnModExpRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_LN_STAT_INC(numLnModExpCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** ******************************************************************************* * @ingroup LacAsymLn * Large Number Modular Exponentiation API function ******************************************************************************/ CpaStatus cpaCyLnModExp(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pLnModExpCb, void *pCallbackTag, const CpaCyLnModExpOpData *pLnModExpOpData, CpaFlatBuffer *pResult) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U index = LAC_PKE_INVALID_INDEX; Cpa32U dataOperationSize = 0; Cpa32U dataLenCommon = 0; Cpa32U dataLenBase = 0; Cpa32U dataLenExponent = 0; Cpa32U dataLenModulus = 0; Cpa32U dataLenResult = 0; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; #endif icp_qat_fw_mmp_input_param_t inArgList = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outArgList = {.flat_array = {0}}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; /* Data that will be passed back in call back function - opaque data */ lac_pke_op_cb_data_t lnModExpData = {0}; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pLnModExpCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pLnModExpOpData, (LAC_ARCH_UINT)pResult); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if the API has been called in sync mode */ if (NULL == pLnModExpCb) { return LacLnModExpSyn(instanceHandle, pLnModExpOpData, pResult); } #ifdef ICP_PARAM_CHECK /* check that the input parameters are valid */ status = LacLnModExpParameterCheck( pLnModExpCb, LAC_CONST_PTR_CAST(pLnModExpOpData), pResult); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { /* calculate the actual data size of the input parameters in bytes */ dataLenBase = LacGetBufferDataSizeInBytes(&pLnModExpOpData->base); dataLenExponent = LacGetBufferDataSizeInBytes(&pLnModExpOpData->exponent); dataLenModulus = LacGetBufferDataSizeInBytes(&pLnModExpOpData->modulus); dataLenResult = pResult->dataLenInBytes; /* the Result buffer size has to be at least the size of the Modulus */ if (dataLenResult < dataLenModulus) { LAC_INVALID_PARAM_LOG("Result buffer size must be >= Modulus size"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* calculate the biggest common bit size for the three * input parameters */ dataLenCommon = (dataLenBase > dataLenExponent) ? dataLenBase : dataLenExponent; dataLenCommon = (dataLenCommon > dataLenModulus) ? dataLenCommon : dataLenModulus; dataLenCommon = LAC_BYTES_TO_BITS(dataLenCommon); /* One row in the mapping table contains operation size and matching * function Id. First, calculate the index of that row using the common * data length */ index = LacPke_GetIndex_VariableSize( dataLenCommon, lacMathsModexpSizeIdMap, LAC_ARRAY_LEN(lacMathsModexpSizeIdMap)); if (LAC_PKE_INVALID_INDEX == index) { LAC_LOG_ERROR("The input data size is not supported"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /* the input/output parameters have to be padded to the operation size * for QAT processing so assign the new size in bytes to each parameter * before the request has been sent out to QAT */ dataOperationSize = LAC_BITS_TO_BYTES( (lacMathsModexpSizeIdMap[index][LAC_PKE_SIZE_COLUMN])); /* get the functionality ID that matches operation size */ functionalityId = lacMathsModexpSizeIdMap[index][LAC_PKE_ID_COLUMN]; /* preserve user parameters for when our Call Back * function kicks in, after sending the head request */ lnModExpData.pClientCb = pLnModExpCb; lnModExpData.pCallbackTag = pCallbackTag; lnModExpData.pClientOpData = pLnModExpOpData; lnModExpData.pOpaqueData = NULL; lnModExpData.pOutputData1 = pResult; /* User allocated some memory for the result. Initialise it with zeros * beforehand */ LAC_OS_BZERO(pResult->pData, dataLenResult); /* populate input/output parameters - use maths_modexp_l512 structure for all functionalityIDs - verified at compile time */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.maths_modexp_l512.g, &pLnModExpOpData->base); inArgSizeList[LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g)] = dataOperationSize; internalMemInList[LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.maths_modexp_l512.e, &pLnModExpOpData->exponent); inArgSizeList[LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e)] = dataOperationSize; internalMemInList[LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.maths_modexp_l512.m, &pLnModExpOpData->modulus); inArgSizeList[LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m)] = dataOperationSize; internalMemInList[LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.maths_modexp_l512.r, pResult); outArgSizeList[0] = dataOperationSize; internalMemOutList[0] = CPA_FALSE; /* Send a PKE request */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacLnModExpCallback, &lnModExpData, instanceHandle); } #ifndef DISABLE_STATS /* update stats. */ if (CPA_STATUS_SUCCESS == status) { /* increment stats: * Total number of LN ModExp test requested operations */ LAC_LN_STAT_INC(numLnModExpRequests, pCryptoService); } else { /* on failure increment stats: * Total number of LN ModExp test errors recorded */ LAC_LN_STAT_INC(numLnModExpRequestErrors, pCryptoService); } #endif return status; } /** ******************************************************************************* * @ingroup LacAsymLn * Large Number Modular Inversion internal callback function ******************************************************************************/ STATIC void LacLnModInvCallback(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; CpaCyLnModInvOpData *pOpData = NULL; void *pCallbackTag = NULL; CpaFlatBuffer *pResult = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif /* retrieve data from the callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOpData = (CpaCyLnModInvOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pCallbackTag = pCbData->pCallbackTag; pResult = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); LAC_ASSERT_NOT_NULL(pResult); /* pass flag is not used here */ #ifndef DISABLE_STATS /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_LN_STAT_INC(numLnModInvCompleted, pCryptoService); } else { LAC_LN_STAT_INC(numLnModInvCompletedErrors, pCryptoService); } #endif /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pResult); } #ifdef ICP_PARAM_CHECK /** ******************************************************************************* * @ingroup LacAsymLn * Ln ModInv parameter check ******************************************************************************/ STATIC CpaStatus LacLnModInvParameterCheck(const CpaCyGenFlatBufCbFunc pCb, CpaCyLnModInvOpData *pOpData, CpaFlatBuffer *pResult) { CpaStatus status = CPA_STATUS_SUCCESS; /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for null Operational Data parameters */ LAC_CHECK_NULL_PARAM(pOpData); /* check for null result pointer */ LAC_CHECK_NULL_PARAM(pResult); /* check for null argument parameters */ LAC_CHECK_FLAT_BUFFER(&pOpData->A); LAC_CHECK_ZERO_SIZE(&pOpData->A); LAC_CHECK_FLAT_BUFFER(&pOpData->B); LAC_CHECK_ZERO_SIZE(&pOpData->B); LAC_CHECK_FLAT_BUFFER(pResult); LAC_CHECK_ZERO_SIZE(pResult); /* Input parameters should not be equal to zero */ LAC_CHECK_NON_ZERO_PARAM(&pOpData->A); LAC_CHECK_NON_ZERO_PARAM(&pOpData->B); /* the input parameters are invalid if both modulus (B) and the value to be * inverted (A) are even (LSB is not set)*/ if ((!(pOpData->A.pData[pOpData->A.dataLenInBytes - 1] & 0x01)) && (!(pOpData->B.pData[pOpData->B.dataLenInBytes - 1] & 0x01))) { LAC_INVALID_PARAM_LOG("Both modulus and value to invert are even"); status = CPA_STATUS_INVALID_PARAM; } return status; } #endif /** *************************************************************************** * @ingroup LacAsymLn * Large Number Modular Inversion synchronous function ***************************************************************************/ STATIC CpaStatus LacLnModInvSyn(const CpaInstanceHandle instanceHandle, const CpaCyLnModInvOpData *pLnModInvOpData, CpaFlatBuffer *pResult) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyLnModInv(instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, pLnModInvOpData, pResult); } else { #ifndef DISABLE_STATS LAC_LN_STAT_INC(numLnModInvRequestErrors, pCryptoService); #endif return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { #ifndef DISABLE_STATS /* * Inc stats only if the wait for callback failed. */ LAC_LN_STAT_INC(numLnModInvCompletedErrors, pCryptoService); #endif status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** ******************************************************************************* * @ingroup LacAsymLn * Large Number Modular Inversion API function ******************************************************************************/ CpaStatus cpaCyLnModInv(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pLnModInvCb, void *pCallbackTag, const CpaCyLnModInvOpData *pLnModInvOpData, CpaFlatBuffer *pResult) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U index = LAC_PKE_INVALID_INDEX; Cpa32U dataOperationSize = 0; Cpa32U dataLenCommon = 0; Cpa32U dataLenA = 0; Cpa32U dataLenB = 0; Cpa32U dataLenResult = 0; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; #endif icp_qat_fw_mmp_input_param_t inArgList = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outArgList = {.flat_array = {0}}; /* Holding the calculated size of the input/output parameters */ Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U outArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; /* Data that will be passed back in call back function - opaque data */ lac_pke_op_cb_data_t lnModInvData = {0}; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pLnModInvCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pLnModInvOpData, (LAC_ARCH_UINT)pResult); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if the API has been called in sync mode */ if (NULL == pLnModInvCb) { return LacLnModInvSyn(instanceHandle, pLnModInvOpData, pResult); } #ifdef ICP_PARAM_CHECK /* check that the input parameters are valid */ status = LacLnModInvParameterCheck( pLnModInvCb, LAC_CONST_PTR_CAST(pLnModInvOpData), pResult); #endif #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; #endif if (CPA_STATUS_SUCCESS == status) { /* calculate the actual data size of the input parameters in bytes */ dataLenA = LacGetBufferDataSizeInBytes(&pLnModInvOpData->A); dataLenB = LacGetBufferDataSizeInBytes(&pLnModInvOpData->B); dataLenResult = pResult->dataLenInBytes; /* the Result buffer size has to be at least the size of the Modulus */ if (dataLenResult < dataLenB) { LAC_INVALID_PARAM_LOG("Result buffer size less then Modulus size"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* calculate the biggest common bit size for the two input params */ dataLenCommon = (dataLenA > dataLenB) ? dataLenA : dataLenB; dataLenCommon = LAC_BYTES_TO_BITS(dataLenCommon); /* Both ODD and EVEN mapping table contain the same operation sizes. * data length. The ODD table is used here */ index = LacPke_GetIndex_VariableSize( dataLenCommon, lacMathsModinvOddSizeIdMap, LAC_ARRAY_LEN(lacMathsModinvOddSizeIdMap)); if (LAC_PKE_INVALID_INDEX == index) { LAC_INVALID_PARAM_LOG("The input data size is not supported"); status = CPA_STATUS_INVALID_PARAM; } } if (CPA_STATUS_SUCCESS == status) { /* the input/output parameters have to be padded to the operation size * for QAT processing so assign the new size in bytes to each parameter * before the request has been sent out to QAT */ /* Both ODD and EVEN mapping tables can give the right operation size * that corresponds to the index. The ODD table is used here. */ dataOperationSize = LAC_BITS_TO_BYTES( (lacMathsModinvOddSizeIdMap[index][LAC_PKE_SIZE_COLUMN])); /* get functionality ID based on odd/even character of the parameters - * we already confirmed that at least one parameter is odd, otherwise * we wouldn't reach this point */ if (!(pLnModInvOpData->B.pData[pLnModInvOpData->B.dataLenInBytes - 1] & 0x01)) { /* if pA is odd and pB is even (already confirmed that at least * one is odd), look into EVEN functionality ID pool */ functionalityId = lacMathsModinvEvenSizeIdMap[index][LAC_PKE_ID_COLUMN]; } else { /* if pA is odd/even and pB parameter is odd, look into ODD * functionality ID pool */ functionalityId = lacMathsModinvOddSizeIdMap[index][LAC_PKE_ID_COLUMN]; } /* preserve user parameters for when our Call Back * function kicks in, after sending the head request */ lnModInvData.pClientCb = pLnModInvCb; lnModInvData.pCallbackTag = pCallbackTag; lnModInvData.pClientOpData = pLnModInvOpData; lnModInvData.pOpaqueData = NULL; lnModInvData.pOutputData1 = pResult; /* User allocated some memory for the result. Initialise it with zeros * beforehand */ LAC_OS_BZERO(pResult->pData, dataLenResult); /* populate input/output parameters - using maths_modinv_odd_l128 structure for all - verified at compile time that this can be done */ LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.maths_modinv_odd_l128.a, &pLnModInvOpData->A); inArgSizeList[LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a)] = dataOperationSize; internalMemInList[LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(inArgList.maths_modinv_odd_l128.b, &pLnModInvOpData->B); inArgSizeList[LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b)] = dataOperationSize; internalMemInList[LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(outArgList.maths_modinv_odd_l128.c, pResult); outArgSizeList[0] = dataOperationSize; internalMemOutList[0] = CPA_FALSE; /* Send a PKE request */ status = LacPke_SendSingleRequest(functionalityId, inArgSizeList, outArgSizeList, &inArgList, &outArgList, internalMemInList, internalMemOutList, LacLnModInvCallback, &lnModInvData, instanceHandle); } #ifndef DISABLE_STATS /* update stats. */ if (CPA_STATUS_SUCCESS == status) { /* increment stats: * Total number of LN ModExp test requested operations */ LAC_LN_STAT_INC(numLnModInvRequests, pCryptoService); } else { /* on failure increment stats: * Total number of LN ModExp test errors recorded */ LAC_LN_STAT_INC(numLnModInvRequestErrors, pCryptoService); } #endif return status; } /** ******************************************************************************* * @ingroup LacAsymLn * Ln Statistics Query API function ******************************************************************************/ CpaStatus cpaCyLnStatsQuery(CpaInstanceHandle instanceHandle_in, CpaCyLnStats *pLnStats) { #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; #endif CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pLnStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* check this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pLnStats); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* get stats into user supplied stats structure */ LAC_LN_STATS32_GET(*pLnStats, pCryptoService); #endif return CPA_STATUS_SUCCESS; } /** ******************************************************************************* * @ingroup LacAsymLn * Ln Statistics Query API function ******************************************************************************/ CpaStatus cpaCyLnStatsQuery64(CpaInstanceHandle instanceHandle_in, CpaCyLnStats64 *pLnStats) { #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; #endif CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pLnStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* check this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pLnStats); #ifndef DISABLE_STATS pCryptoService = (sal_crypto_service_t *)instanceHandle; /* get stats into user supplied stats structure */ LAC_LN_STATS64_GET(*pLnStats, pCryptoService); #endif return CPA_STATUS_SUCCESS; } /** ******************************************************************************* * @ingroup LacAsymLn * Ln Initialization function ******************************************************************************/ CpaStatus LacLn_Init(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pCryptoService->pLacLnStatsArr), LAC_LN_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { /* initialize stats to zero */ LAC_LN_STATS_INIT(pCryptoService); } #endif /* Call compile time param check function to ensure it is included in the build by the compiler */ LacLn_CompileTimeAssertions(); return status; } void LacLn_StatsFree(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; if (NULL != pCryptoService->pLacLnStatsArr) { LAC_OS_FREE(pCryptoService->pLacLnStatsArr); } } void LacLn_StatsReset(CpaInstanceHandle instanceHandle) { #ifndef DISABLE_STATS sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_LN_STATS_INIT(pCryptoService); #endif } /** ******************************************************************************* * @ingroup LacAsymLn * Ln Stats Show function ******************************************************************************/ void LacLn_StatsShow(CpaInstanceHandle instanceHandle) { CpaCyLnStats64 lnStats = {0}; /* retrieve the stats */ (void)cpaCyLnStatsQuery64(instanceHandle, &lnStats); /* log the stats to the standard output */ /* Engine Info */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " LN ModExp/ModInv Stats " BORDER "\n" SEPARATOR); /* Large Number Modular Exponentationstats operations stats */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " LN ModEXP successful requests: %16llu " BORDER "\n" BORDER " LN ModEXP requests with error: %16llu " BORDER "\n" BORDER " LN ModEXP completed operations: %16llu " BORDER "\n" BORDER " LN ModEXP not completed-errors: %16llu " BORDER "\n" SEPARATOR, lnStats.numLnModExpRequests, lnStats.numLnModExpRequestErrors, lnStats.numLnModExpCompleted, lnStats.numLnModExpCompletedErrors); /* Large Number Modular Inversion operations stats */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " LN ModINV successful requests: %16llu " BORDER "\n" BORDER " LN ModINV requests with error: %16llu " BORDER "\n" BORDER " LN ModINV completed operations: %16llu " BORDER "\n" BORDER " LN ModINV not completed-errors: %16llu " BORDER "\n" SEPARATOR, lnStats.numLnModInvRequests, lnStats.numLnModInvRequestErrors, lnStats.numLnModInvCompleted, lnStats.numLnModInvCompletedErrors); } lac_ln_interface_check.c000066400000000000000000000351041503624047500356310ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/large_number/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_ln_interface_check.c * * @ingroup Lac_Ln * * This file checks at compile time that the IA/FW interface is as expected * For example, in lac_ln.c we use the fact that the index of g in the * structure icp_qat_fw_maths_modexp_l512_input_t is equal to the index of * g in the structure icp_qat_fw_maths_modexp_l1024_input_t. If this * assumption becomes invalid (FW interface changes to break the assumption * or the compiler moves things around) this file will fail to compile. * * Note for structures with only 1 member no check is required. * * ***************************************************************************/ #include "cpa.h" #include "icp_qat_fw_pke.h" #include "icp_qat_fw_mmp.h" #include "lac_common.h" #define COMPILE_TIME_ASSERT(pred) \ switch (0) \ { \ case 0: \ case pred:; \ } void LacLn_CompileTimeAssertions(void) { /* ************************************************************* * MOD EXP Checks * ************************************************************* */ /* Check that icp_qat_fw_maths_modexp_l512_input_t, icp_qat_fw_maths_modexp_l1024_input_t, icp_qat_fw_maths_modexp_l1536_input_t, icp_qat_fw_maths_modexp_l2048_input_t, icp_qat_fw_maths_modexp_l2560_input_t, icp_qat_fw_maths_modexp_l3072_input_t, icp_qat_fw_maths_modexp_l3584_input_t, icp_qat_fw_maths_modexp_l4096_input_t, icp_qat_fw_maths_modexp_l8192_input_t structures are equivalent */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l1024_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l1024_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l1024_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l1536_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l1536_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l1536_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l2048_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l2048_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l2048_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l2560_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l2560_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l2560_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l3072_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l3072_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l3072_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l3584_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l3584_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l3584_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l4096_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l4096_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l4096_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, g) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l8192_input_t, g)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, e) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l8192_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_maths_modexp_l512_input_t, m) == LAC_IDX_OF(icp_qat_fw_maths_modexp_l8192_input_t, m)); /* ************************************************************* * MOD INV Checks - ODD * ************************************************************* */ COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l192_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l192_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l256_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l256_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l384_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l384_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l512_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l512_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l768_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l768_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l1024_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l1024_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l1536_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l1536_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l2048_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l2048_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l3072_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l3072_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l4096_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l4096_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l8192_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l8192_input_t, b)); /* ************************************************************* * MOD INV Checks - EVEN * ************************************************************* */ COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l192_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l192_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l256_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l256_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l384_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l384_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l512_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l512_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l768_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l768_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l1024_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l1024_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l1536_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l1536_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l2048_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l2048_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l3072_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l3072_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l4096_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l4096_input_t, b)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, a) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l8192_input_t, a)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_maths_modinv_odd_l128_input_t, b) == LAC_IDX_OF(icp_qat_fw_maths_modinv_even_l8192_input_t, b)); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/000077500000000000000000000000001503624047500306215ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_mmp.c000066400000000000000000000104631503624047500332400ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** *************************************************************************** * @file lac_pke_mmp.c * * @ingroup LacAsymCommonMmp * * Implementation of mmp related functions ******************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "lac_common.h" #include "lac_pke_mmp.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* ******************************************************************************** * Static Variables ******************************************************************************** */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ Cpa32U LacPke_GetMmpId(Cpa32U sizeInBits, const Cpa32U pSizeIdTable[][LAC_PKE_NUM_COLUMNS], Cpa32U numTableEntries) { Cpa32U id = LAC_PKE_INVALID_FUNC_ID; Cpa32U sizeIndex = 0; for (sizeIndex = 0; sizeIndex < numTableEntries; sizeIndex++) { if (pSizeIdTable[sizeIndex][LAC_PKE_SIZE_COLUMN] == sizeInBits) { id = pSizeIdTable[sizeIndex][LAC_PKE_ID_COLUMN]; break; } } return id; } Cpa32U LacPke_GetIndex_VariableSize( Cpa32U sizeInBits, const Cpa32U pSizeIdTable[][LAC_PKE_NUM_COLUMNS], Cpa32U numTableEntries) { Cpa32U index = LAC_PKE_INVALID_INDEX; Cpa32U sizeIndex = 0; for (sizeIndex = 0; (sizeIndex < numTableEntries) && (LAC_PKE_INVALID_INDEX == index); sizeIndex++) { if (sizeInBits <= pSizeIdTable[sizeIndex][LAC_PKE_SIZE_COLUMN]) { index = sizeIndex; break; } } return index; } lac_pke_qat_comms.c000066400000000000000000001021041503624047500343450ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/* * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** *************************************************************************** * @file lac_pke_qat_comms.c * * @ingroup LacAsymCommonQatComms * * This file implements the API for creating PKE QAT messages and sending * these to the QAT. It implements an API for creating a PKE QAT request, and * for sending a PKE message to the QAT. * ***************************************************************************/ /* **************************************************************************** * Include public/global header files **************************************************************************** */ #include "cpa.h" /* **************************************************************************** * Include private header files **************************************************************************** */ /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* QAT includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_pke.h" #include "icp_qat_fw_mmp.h" /* SAL includes */ #include "lac_common.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "sal_qat_cmn_msg.h" #include "lac_pke_qat_comms.h" #include "lac_pke_utils.h" #include "lac_pke_mmp.h" #include "sal_misc_error_stats.h" /* **************************************************************************** * Static Variables **************************************************************************** */ /* **************************************************************************** * Define static function definitions **************************************************************************** */ /******************************************************************** * @ingroup LacAsymCommonQatComms * * @description * This function fills in LW0 and LW 1 of the PKE Header * * @param[in] pMsg Pointer to 64B Request Msg buffer * @param[in] serviceType Request types * @param[in] cmnFlags Common request flag * * * @assumptions * * @return * None * *****************************************/ STATIC void LacPke_HdrWrite(icp_qat_fw_pke_request_t *pMsg, icp_qat_fw_comn_request_id_t serviceType, icp_qat_fw_comn_flags_pke cmnFlags, icp_qat_fw_comn_flags cmnFlagsExt) { icp_qat_fw_req_pke_hdr_t *pHeader = &(pMsg->pke_hdr); osalMemSet(pHeader, 0, sizeof(icp_qat_fw_req_pke_hdr_t)); /* LW0 */ pHeader->resrvd1 = 0; pHeader->resrvd2 = 0; pHeader->service_type = (uint8_t)serviceType; ICP_QAT_FW_PKE_RQ_VALID_FLAG_SET((*pHeader), ICP_QAT_FW_COMN_REQ_FLAG_SET); /* LW1 */ pHeader->comn_req_flags = cmnFlags; pHeader->comn_req_flags_ext = cmnFlagsExt; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * Resizes parameters for a PKE request if required * * @description * This function resizes the flat buffer parameters for a PKE request, if * required, by calling icp_LacBufferResize for each input/output flat buffer * parameter in the request data structure. LacPke_RestoreParams is the * corresponding function for undoing the buffer copies. * * @param[in] pParamInfo The data pointers of the flat buffers from the * clientInputParams and clientOutputParams * arrays are resized as necessary and stored in * the pkeInputParams and pkeOutputParams arrays * respectively. The client...Params arrays are * processed one-by-one from the start, and * processing ends once a NULL parameter is * encountered. Consequently, the pke...Params * arrays should be initialized to zero as NULL * inputs won't be written as NULL outputs. * @param[in/out] pInternalInMemList * pointer to a list of Booleans that indicate if * input data buffers passed to QAT are internally or * externally allocated. This information needs to * be tracked to ensure we use the correct virt2phys * function, values may be updated by this function. * @param[in/out] pInternalOutMemList * pointer to a list of Booleans that indicate if * output data buffers passed to QAT are internally * or externally allocated, values may be updated by * this function. * @param[in] instanceHandle instanceHandle * * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RESOURCE Resource error (e.g. failed memory allocation) * * @see LacPke_RestoreParams() * @see icp_LacBufferResize() ***************************************************************************/ STATIC CpaStatus LacPke_ResizeParams(lac_pke_qat_req_data_param_info_t *pParamInfo, CpaBoolean *pInternalInMemList, CpaBoolean *pInternalOutMemList, CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; LAC_CHECK_NULL_PARAM(pParamInfo); /* resize input parameter flat buffers (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_INPUT_PARAMS) && (NULL != pParamInfo->clientInputParams[i]); i++) { LAC_CHECK_NULL_PARAM(pInternalInMemList); /* resize buffer (round length up to whole quadwords) if required */ Cpa32U dataLen = pParamInfo->clientInputParams[i]->dataLenInBytes; Cpa32U dataRoundLen = dataLen; Cpa32U offset = 0; if (pParamInfo->inArgSizeList[i]) { dataRoundLen = pParamInfo->inArgSizeList[i]; offset = (dataLen > pParamInfo->inArgSizeList[i]) ? (dataLen - pParamInfo->inArgSizeList[i]) : 0; } pParamInfo->pkeInputParams[i] = icp_LacBufferResize( instanceHandle, pParamInfo->clientInputParams[i]->pData + offset, dataLen - offset, LAC_ALIGN_POW2_ROUNDUP(dataRoundLen, LAC_QUAD_WORD_IN_BYTES), &(pInternalInMemList[i])); status = (!pParamInfo->pkeInputParams[i] ? CPA_STATUS_RESOURCE : status); LAC_CHECK_STATUS(status); } /* resize output parameter flat buffers (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_OUTPUT_PARAMS) && (NULL != pParamInfo->clientOutputParams[i]); i++) { LAC_CHECK_NULL_PARAM(pInternalOutMemList); /* resize buffer (and round length up to whole quadwords) if required */ /* Need to copy when resizing output buffer for case where status returned by PKE is _FALSE */ Cpa32U dataLen = pParamInfo->clientOutputParams[i]->dataLenInBytes; Cpa32U dataRoundLen = dataLen; Cpa32U offset = 0; if (pParamInfo->outArgSizeList[i]) { dataRoundLen = pParamInfo->outArgSizeList[i]; offset = (dataLen > pParamInfo->outArgSizeList[i]) ? (dataLen - pParamInfo->outArgSizeList[i]) : 0; } pParamInfo->pkeOutputParams[i] = icp_LacBufferResize( instanceHandle, pParamInfo->clientOutputParams[i]->pData + offset, dataLen - offset, LAC_ALIGN_POW2_ROUNDUP(dataRoundLen, LAC_QUAD_WORD_IN_BYTES), &(pInternalOutMemList[i])); status = (!pParamInfo->pkeOutputParams[i] ? CPA_STATUS_RESOURCE : status); LAC_CHECK_STATUS(status); } return status; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * Restores parameters for a PKE request * * @description * This function restores the flat buffer parameters for a PKE request, by * calling icp_LacBufferRestore for each input/output flat buffer parameter in * the request data structure. LacPke_ResizeParams is the corresponding * function for doing the buffer resize. * * @param pParamInfo IN The data pointers from the pkeInputParams and * pkeOutputParams arrays are restored and stored * in the data pointers of the flat buffers in * the clientInputParams and clientOutputParams * arrays respectively. The pke...Params arrays * are processed one-by-one from the start, and * processing ends once a NULL parameter is * encountered. Consequently, the * client...Params arrays should be initialized * to zero as NULL inputs won't be written as * NULL outputs. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RESOURCE Resource error (e.g. failed memory free) * * @see LacPke_ResizeParams() * @see icp_LacBufferRestore() ***************************************************************************/ STATIC CpaStatus LacPke_RestoreParams(lac_pke_qat_req_data_param_info_t *pParamInfo) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; /* restore input parameter flat buffers (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_INPUT_PARAMS) && (NULL != pParamInfo->pkeInputParams[i]); i++) { /* restore buffer */ /* don't copy when restoring an input buffer */ Cpa32U dataLen = pParamInfo->clientInputParams[i]->dataLenInBytes; Cpa32U dataRoundLen = dataLen; Cpa32U offset = 0; if (pParamInfo->inArgSizeList[i]) { dataRoundLen = pParamInfo->inArgSizeList[i]; offset = (dataLen > pParamInfo->inArgSizeList[i]) ? (dataLen - pParamInfo->inArgSizeList[i]) : 0; } status = icp_LacBufferRestore( pParamInfo->clientInputParams[i]->pData + offset, dataLen - offset, pParamInfo->pkeInputParams[i], LAC_ALIGN_POW2_ROUNDUP(dataRoundLen, LAC_QUAD_WORD_IN_BYTES), CPA_FALSE); LAC_CHECK_STATUS(status); } /* restore output parameter flat buffers (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_OUTPUT_PARAMS) && (NULL != pParamInfo->pkeOutputParams[i]); i++) { /* restore buffer */ Cpa32U dataLen = pParamInfo->clientOutputParams[i]->dataLenInBytes; Cpa32U dataRoundLen = dataLen; Cpa32U offset = 0; if (pParamInfo->outArgSizeList[i]) { dataRoundLen = pParamInfo->outArgSizeList[i]; offset = (dataLen > pParamInfo->outArgSizeList[i]) ? (dataLen - pParamInfo->outArgSizeList[i]) : 0; } status = icp_LacBufferRestore( pParamInfo->clientOutputParams[i]->pData + offset, dataLen - offset, pParamInfo->pkeOutputParams[i], LAC_ALIGN_POW2_ROUNDUP(dataRoundLen, LAC_QUAD_WORD_IN_BYTES), CPA_TRUE); LAC_CHECK_STATUS(status); } return status; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * Destroys a PKE request * * @description * This function destroys a PKE request that was created using * LacPke_CreateRequest(). It should be called if an error occurs during * request create or request send, or else as part of the response callback. * * @param pRequestHandle IN Pointer to the request handle that identifies * the request to be destroyed. The request * handle will get set to LAC_PKE_INVALID_HANDLE. * * @retval CPA_STATUS_SUCCESS No error * @retval CPA_STATUS_RESOURCE Resource error (e.g. failed memory free) * * @see LacPke_CreateRequest() ***************************************************************************/ STATIC CpaStatus LacPke_DestroyRequest(lac_pke_request_handle_t *pRequestHandle) { CpaStatus status = CPA_STATUS_SUCCESS; lac_pke_qat_req_data_t *pReqData = NULL; /* extract head request data pointer from the request handle */ pReqData = *pRequestHandle; /* invalidate the request handle */ *pRequestHandle = LAC_PKE_INVALID_HANDLE; /* free all request data structures in the chain - continue even in the case of errors */ while (NULL != pReqData) { lac_pke_qat_req_data_t *pNextReqData = pReqData->pNextReqData; /* restore parameters (i.e. undo resizing) */ if (CPA_STATUS_SUCCESS != LacPke_RestoreParams(&pReqData->paramInfo)) { status = CPA_STATUS_RESOURCE; } LAC_MEM_POOL_BLK_SET_OPAQUE(pReqData, ICP_ADF_INVALID_SEND_SEQ); Lac_MemPoolEntryFree(pReqData); pReqData = pNextReqData; } return status; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * PKE callback ***************************************************************************/ void LacPke_MsgCallback(void *pRespMsg) { CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean pass = CPA_TRUE, isFwUnSupp = CPA_FALSE; Cpa8U comnErr = ERR_CODE_NO_ERROR; icp_qat_fw_pke_resp_t *pPkeRespMsg = NULL; lac_pke_request_handle_t requestHandle = LAC_PKE_INVALID_HANDLE; lac_pke_qat_req_data_t *pReqData = NULL; lac_pke_op_cb_func_t pCbFunc = NULL; lac_pke_op_cb_data_t cbData = {0}; /* cast response message to PKE response message type */ pPkeRespMsg = (icp_qat_fw_pke_resp_t *)pRespMsg; /* Check for FW Unsupported error */ isFwUnSupp = ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET( pPkeRespMsg->pke_resp_hdr.resp_status.pke_resp_flags); /* check QAT response status */ pass = (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_PKE_RESP_PKE_STAT_GET( pPkeRespMsg->pke_resp_hdr.resp_status.pke_resp_flags)); comnErr = pPkeRespMsg->pke_resp_hdr.resp_status.comn_err_code; /* log the slice hang, ssm parity and endpoint push/pull error inside the * response */ if (ERR_CODE_SSM_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR("The slice hang error is detected on the MMP slice. "); } else if (ERR_CODE_SSM_PARITY_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR("Operation resulted in a parity error in one or more " "accelerators."); } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR( "The PCIe End Point Push/Pull or TI/RI Parity error detected."); } /* extract request data pointer from the opaque data */ LAC_MEM_SHARED_READ_TO_PTR(pPkeRespMsg->opaque_data, pReqData); /* extract fields from request data struct */ pCbFunc = pReqData->cbInfo.cbFunc; cbData = pReqData->cbInfo.cbData; instanceHandle = pReqData->cbInfo.instanceHandle; SAL_MISC_ERR_STATS_INC( comnErr, &((sal_crypto_service_t *)instanceHandle)->generic_service_info); /* destroy the request */ requestHandle = (lac_pke_request_handle_t)pReqData->pHeadReqData; status = LacPke_DestroyRequest(&requestHandle); if (isFwUnSupp) { status = CPA_STATUS_UNSUPPORTED; } /* call the client callback */ (*pCbFunc)(status, pass, instanceHandle, &cbData); } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * PKE dummy response generation ***************************************************************************/ CpaStatus LacPke_SwRespMsgCallback(lac_memblk_bucket_t *pBucket) { lac_mem_blk_t **pBucketBlk = NULL; lac_mem_blk_t *pCurrentBlk = NULL; Cpa32U numBucketBlks = 0; Cpa32U numSwResp = 0; Cpa32U startIndex = 0; Cpa32U iter = 0; lac_pke_qat_req_data_t *pReqData = NULL; lac_pke_op_cb_func_t pCbFunc = NULL; lac_pke_op_cb_data_t cbData = {0}; CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; CpaStatus status = CPA_STATUS_RETRY; LAC_ASSERT_NOT_NULL(pBucket); pBucketBlk = pBucket->mem_blk; LAC_ASSERT_NOT_NULL(pBucketBlk); startIndex = pBucket->startIndex; numBucketBlks = pBucket->numBucketBlks; numSwResp = pBucket->numBlksInRing; for (iter = 0; iter < numSwResp; iter++) { pCurrentBlk = pBucketBlk[(startIndex + iter) % numBucketBlks]; pReqData = (lac_pke_qat_req_data_t *)((LAC_ARCH_UINT)(pCurrentBlk) + sizeof(lac_mem_blk_t)); LAC_LOG_DEBUG1("Asym dummy response index = %llx", pCurrentBlk->opaque); /* extract fields from request data struct */ pCbFunc = pReqData->cbInfo.cbFunc; cbData = pReqData->cbInfo.cbData; instanceHandle = pReqData->cbInfo.instanceHandle; (*pCbFunc)(CPA_STATUS_FAIL, CPA_FALSE, instanceHandle, &cbData); Lac_MemPoolEntryFree(pReqData); } if (0 != numSwResp) { status = CPA_STATUS_SUCCESS; } return status; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * Init PKE requests ***************************************************************************/ void LacPke_InitAsymRequest(Cpa8U *pData, CpaInstanceHandle instanceHandle) { lac_pke_qat_req_data_t *pReqData = (lac_pke_qat_req_data_t *)pData; /* No flag update done or necessary*/ icp_qat_fw_comn_flags_pke cmnRequestFlags = ICP_QAT_FW_COMN_FLAGS_BUILD( QAT_COMN_PTR_TYPE_FLAT, QAT_COMN_CD_FLD_TYPE_64BIT_ADR); icp_qat_fw_req_pke_mid_t *pMid = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; icp_qat_fw_comn_flags cmnRequestFlagsExt = 0; /* LWs 0-1 set as for common header */ LacPke_HdrWrite((&(pReqData->u1.request)), ICP_QAT_FW_COMN_REQ_CPM_FW_PKE, cmnRequestFlags, cmnRequestFlagsExt); /* LWs 2-5 are part of PKE header, but not common header so set up * separately */ /*LW2-3*/ pReqData->u1.request.pke_hdr.cd_pars.content_desc_addr = 0; /* LW4-5 */ pReqData->u1.request.pke_hdr.cd_pars.content_desc_resrvd = 0; pReqData->u1.request.pke_hdr.cd_pars.func_id = 0; /* * Common request middle part (LW 6-11) * */ pMid = &(pReqData->u1.request.pke_mid); LAC_MEM_SHARED_WRITE_FROM_PTR(pMid->opaque_data, pReqData); pMid->src_data_addr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pCryptoService->generic_service_info, &pReqData->u2.inArgList); pMid->dest_data_addr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pCryptoService->generic_service_info, &pReqData->u3.outArgList); /* part of LW12 */ pReqData->u1.request.resrvd1 = 0; /* LW13 */ pReqData->u1.request.resrvd2 = 0; /* LW14-15 */ pReqData->u1.request.next_req_adr = 0; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * PKE request creation ***************************************************************************/ CpaStatus LacPke_CreateRequest(lac_pke_request_handle_t *pRequestHandle, Cpa32U functionalityId, Cpa32U *pInArgSizeList, Cpa32U *pOutArgSizeList, icp_qat_fw_mmp_input_param_t *pInArgList, icp_qat_fw_mmp_output_param_t *pOutArgList, CpaBoolean *pInternalInMemList, CpaBoolean *pInternalOutMemList, lac_pke_op_cb_func_t pPkeOpCbFunc, lac_pke_op_cb_data_t *pCbData, CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; lac_pke_qat_req_data_t *pReqData = NULL; size_t i = 0; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* allocate request data */ do { pReqData = Lac_MemPoolEntryAlloc(pCryptoService->lac_pke_req_pool); if ((NULL == pReqData)) { LAC_LOG_ERROR("Cannot get a mem pool entry"); status = CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pReqData) { osalYield(); } } while ((void *)CPA_STATUS_RETRY == pReqData); if (CPA_STATUS_SUCCESS == status) { LAC_ASSERT_NOT_NULL(pReqData); /* ensure correct request structure alignment */ LAC_ASSERT(LAC_ADDRESS_ALIGNED(&pReqData->u1.request, LAC_OPTIMAL_ALIGNMENT_SHIFT), "request structure not correctly aligned"); /* ensure correct input argument list structure alignment */ LAC_ASSERT(LAC_ADDRESS_ALIGNED(&pReqData->u2.inArgList, LAC_OPTIMAL_ALIGNMENT_SHIFT), "inArgList structure not correctly aligned"); /* ensure correct output argument list structure alignment */ LAC_ASSERT(LAC_ADDRESS_ALIGNED(&pReqData->u3.outArgList, LAC_OPTIMAL_ALIGNMENT_SHIFT), "outArgList structure not correctly aligned"); /* initialize handle for single request, or first in a chain */ if (*pRequestHandle == LAC_PKE_INVALID_HANDLE) { /* store request data pointer in the request handle */ *pRequestHandle = (lac_pke_request_handle_t)pReqData; /* initialize next, head, and tail request data pointers */ pReqData->pNextReqData = NULL; pReqData->pHeadReqData = pReqData; /* note: tail pointer is only valid in head request data struct */ pReqData->pTailReqData = pReqData; } else /* handle second or subsequent request in a chain */ { lac_pke_qat_req_data_t *pHeadReqData = NULL; lac_pke_qat_req_data_t *pTailReqData = NULL; /* extract head request data pointer from the request handle */ pHeadReqData = *pRequestHandle; LAC_ASSERT_NOT_NULL(pHeadReqData); /* get tail request data pointer from head request data pointer */ pTailReqData = pHeadReqData->pTailReqData; LAC_ASSERT_NOT_NULL(pTailReqData); /* chain the two requests */ pTailReqData->u1.request.next_req_adr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pCryptoService->generic_service_info, pReqData); /* chain the request data structures */ pTailReqData->pNextReqData = pReqData; pHeadReqData->pTailReqData = pReqData; pReqData->pNextReqData = NULL; pReqData->pHeadReqData = pHeadReqData; /* note: tail pointer not stored here as it changes (unlike head) */ } /* populate request data structure */ pReqData->cbInfo.cbFunc = pPkeOpCbFunc; pReqData->cbInfo.cbData = *pCbData; pReqData->cbInfo.instanceHandle = instanceHandle; pReqData->pNextReqData = NULL; /* clear the previous param info */ LAC_OS_BZERO(&pReqData->paramInfo, sizeof(pReqData->paramInfo)); /* if the list is passed by the user, store it in preallocated memory */ if (NULL != pInArgSizeList) { memcpy(&pReqData->paramInfo.inArgSizeList, pInArgSizeList, sizeof(pReqData->paramInfo.inArgSizeList)); } if (NULL != pOutArgSizeList) { memcpy(&pReqData->paramInfo.outArgSizeList, pOutArgSizeList, sizeof(pReqData->paramInfo.outArgSizeList)); } /** @performance : the caller's input/output parameter lists are copied here into internal structures. it would be more efficient, if possible, to have the caller populate the internal structure directly. */ /* store input parameters in req struct (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_INPUT_PARAMS) && (0 != pInArgList->flat_array[i]); i++) { LAC_MEM_SHARED_READ_TO_PTR( pInArgList->flat_array[i], pReqData->paramInfo.clientInputParams[i]); } /* store output parameters in req struct (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_OUTPUT_PARAMS) && (0 != pOutArgList->flat_array[i]); i++) { LAC_MEM_SHARED_READ_TO_PTR( pOutArgList->flat_array[i], pReqData->paramInfo.clientOutputParams[i]); } /* resize parameters */ status = LacPke_ResizeParams(&pReqData->paramInfo, pInternalInMemList, pInternalOutMemList, instanceHandle); } if (CPA_STATUS_SUCCESS == status) { Cpa8U numInputParams = 0; Cpa8U numOutputParams = 0; pReqData->u1.request.pke_hdr.cd_pars.func_id = functionalityId; /* LW 14 and 15 set to zero for this request for now */ pReqData->u1.request.next_req_adr = 0; /* store correctly sized in params in QAT struct (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_INPUT_PARAMS) && (NULL != pReqData->paramInfo.pkeInputParams[i]); i++) { if (CPA_TRUE == pInternalInMemList[i]) { /* pkeInputParams[i] is referencing internally allocated memory */ pReqData->u2.inArgList.flat_array[i] = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pCryptoService->generic_service_info, pReqData->paramInfo.pkeInputParams[i]); } else { /* pkeInputParams[i] is referencing externally allocated memory */ LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( pCryptoService->generic_service_info, pReqData->u2.inArgList.flat_array[i], pReqData->paramInfo.pkeInputParams[i]); } } numInputParams = i; for (i = numInputParams; i < LAC_MAX_MMP_INPUT_PARAMS; i++) { pReqData->u2.inArgList.flat_array[i] = 0; } /* store correctly sized out params in QAT struct (end if NULL encountered) */ for (i = 0; (i < LAC_MAX_MMP_OUTPUT_PARAMS) && (NULL != pReqData->paramInfo.pkeOutputParams[i]); i++) { if ((NULL != pInternalOutMemList) && (CPA_TRUE == pInternalOutMemList[i])) { pReqData->u3.outArgList.flat_array[i] = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pCryptoService->generic_service_info, pReqData->paramInfo.pkeOutputParams[i]); } else { LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( pCryptoService->generic_service_info, pReqData->u3.outArgList.flat_array[i], pReqData->paramInfo.pkeOutputParams[i]); } } numOutputParams = i; for (i = numOutputParams; i < LAC_MAX_MMP_OUTPUT_PARAMS; i++) { pReqData->u3.outArgList.flat_array[i] = 0; } LAC_ASSERT(((numInputParams + numOutputParams) <= LAC_MAX_MMP_PARAMS), "number of input/output parameters exceeds maximum allowed"); /* Complete LW12 */ pReqData->u1.request.input_param_count = numInputParams; pReqData->u1.request.output_param_count = numOutputParams; } /* clean up in the event of an error */ if (CPA_STATUS_SUCCESS != status) { /* destroy the request (chain) */ (void)LacPke_DestroyRequest(pRequestHandle); } return status; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * PKE request send to QAT ***************************************************************************/ CpaStatus LacPke_SendRequest(lac_pke_request_handle_t *pRequestHandle, CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; lac_pke_qat_req_data_t *pHeadReqData = NULL; Cpa64U seq_num = ICP_ADF_INVALID_SEND_SEQ; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_ASSERT_NOT_NULL(pRequestHandle); /* extract head request data pointer from the request handle */ pHeadReqData = *pRequestHandle; LAC_ASSERT_NOT_NULL(pHeadReqData); /* send the request (chain) */ status = SalQatMsg_transPutMsg(pCryptoService->trans_handle_asym_tx, (void *)&(pHeadReqData->u1.request), LAC_QAT_ASYM_REQ_SZ_LW, LAC_LOG_MSG_PKE, &seq_num); if (CPA_STATUS_SUCCESS != status) { /* destroy the request (chain) */ (void)LacPke_DestroyRequest(pRequestHandle); return status; } LAC_MEM_POOL_BLK_SET_OPAQUE(pHeadReqData, seq_num); return status; } /** *************************************************************************** * @ingroup LacAsymCommonQatComms * PKE request create and send to QAT ***************************************************************************/ CpaStatus LacPke_SendSingleRequest(Cpa32U functionalityId, Cpa32U *pInArgSizeList, Cpa32U *pOutArgSizeList, icp_qat_fw_mmp_input_param_t *pInArgList, icp_qat_fw_mmp_output_param_t *pOutArgList, CpaBoolean *pInMemBool, CpaBoolean *pOutMemBool, lac_pke_op_cb_func_t pPkeOpCbFunc, lac_pke_op_cb_data_t *pCbData, CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; lac_pke_request_handle_t requestHandle = LAC_PKE_INVALID_HANDLE; /* prepare the request */ status = LacPke_CreateRequest(&requestHandle, functionalityId, pInArgSizeList, pOutArgSizeList, pInArgList, pOutArgList, pInMemBool, pOutMemBool, pPkeOpCbFunc, pCbData, instanceHandle); if (CPA_STATUS_SUCCESS == status) { /* send the request */ status = LacPke_SendRequest(&requestHandle, instanceHandle); } return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/pke_common/lac_pke_utils.c000066400000000000000000000265011503624047500336070ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_pke_utils.c * * @ingroup LacAsymCommonUtils * * Implementation of utils that are PKE specific * ******************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* OSAL includes */ #include "Osal.h" /* ADF includes */ #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_debug.h" #include "icp_adf_transport.h" #include "icp_adf_poll.h" #include "icp_accel_devices.h" /* FW includes */ #include "icp_qat_fw_mmp_ids.h" #include "icp_qat_fw_la.h" /* SAL includes */ #include "lac_common.h" #include "lac_mem.h" #include "lac_log.h" #include "lac_mem_pools.h" #include "lac_ec.h" #include "lac_sym.h" #include "lac_list.h" #include "lac_sal_types_crypto.h" #include "lac_pke_qat_comms.h" #include "lac_pke_utils.h" /* ******************************************************************************** * Static Variables ******************************************************************************** */ /* * Values below used to wait on completion of mmp liveness request * by polling completion variable. 10-second timeout chosen, to avoid * infinite wait */ #define LAC_PKE_WAIT_COUNT (1000) /**< Number of times to sleep and wakeup */ #define LAC_PKE_DELAY_IN_MS (10) /**< Time to sleep in ms */ #define MMP_LIVENESS_DATA_SIZE 64 /**< Size of buffer sent in PKE liveness requests */ #define PKE_FW_ID_IDX 0 /**< index of Cpa32U array where fw id can be found */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ Cpa32S LacPke_CompareIntPtrs(const Cpa8U *pBufferA, Cpa32U lenA, const Cpa32S deltaA, const Cpa8U *pBufferB, Cpa32U lenB, const Cpa32S deltaB) { Cpa32S delta = 0; Cpa32S notZero = 0; LAC_ASSERT_NOT_NULL(pBufferA); LAC_ASSERT_NOT_NULL(pBufferB); LAC_ENSURE(((deltaA > -(1 << 30)) && (deltaA < (1 << 30))), "deltaA out of range"); LAC_ENSURE(((deltaB > -(1 << 30)) && (deltaB < (1 << 30))), "deltaB out of range"); delta = deltaA - deltaB; LAC_ENSURE((lenA + lenB > 0), "Invalid Buffer lengths"); /* Shortcut for buffers of the same size */ if ((lenA == lenB) && (delta == 0)) { return memcmp(pBufferA, pBufferB, lenA); } /* Run a full subtraction byte per byte starting from the least significant byte and taking care of buffers of different sizes */ while (lenA | lenB) { if (lenA) { delta += pBufferA[--lenA]; } if (lenB) { delta -= pBufferB[--lenB]; } notZero |= (delta & 0xFF); /* signed arithmetic shift */ delta >>= LAC_NUM_BITS_IN_BYTE; } /* Convert all neg numbers to -1 and all positive numbers to +1 */ return notZero ? LAC_SIGNED_CONVERT32(delta) : 0; } Cpa32S LacPke_Compare(const CpaFlatBuffer *pFlatBufferA, const Cpa32S deltaA, const CpaFlatBuffer *pFlatBufferB, const Cpa32S deltaB) { Cpa32S delta = 0; Cpa32S notZero = 0; Cpa32U lenA = 0; Cpa32U lenB = 0; LAC_ASSERT_NOT_NULL(pFlatBufferA); LAC_ASSERT_NOT_NULL(pFlatBufferB); LAC_ASSERT_NOT_NULL(pFlatBufferA->pData); LAC_ASSERT_NOT_NULL(pFlatBufferB->pData); LAC_ENSURE(((deltaA > -(1 << 30)) && (deltaA < (1 << 30))), "deltaA out of range"); LAC_ENSURE(((deltaB > -(1 << 30)) && (deltaB < (1 << 30))), "deltaB out of range"); delta = deltaA - deltaB; lenA = pFlatBufferA->dataLenInBytes; lenB = pFlatBufferB->dataLenInBytes; LAC_ENSURE((lenA + lenB > 0), "Invalid Buffer lengths"); /* Shortcut for buffers of the same size */ if ((lenA == lenB) && (delta == 0)) { return memcmp(pFlatBufferA->pData, pFlatBufferB->pData, lenA); } /* Run a full subtraction byte per byte starting from the least significant byte and taking care of buffers of different sizes */ while (lenA | lenB) { if (lenA) { delta += pFlatBufferA->pData[--lenA]; } if (lenB) { delta -= pFlatBufferB->pData[--lenB]; } notZero |= (delta & 0xFF); /* signed arithmetic shift */ delta >>= LAC_NUM_BITS_IN_BYTE; } /* Convert all neg numbers to -1 and all positive numbers to +1 */ return notZero ? LAC_SIGNED_CONVERT32(delta) : 0; } Cpa32S LacPke_CompareZero(const CpaFlatBuffer *pLargeInteger, const Cpa32S delta) { Cpa32S result = 0; Cpa32U i = 0; LAC_ASSERT_NOT_NULL(pLargeInteger); LAC_ENSURE(((delta >= -128) && (delta <= 127)), "delta out of range"); i = pLargeInteger->dataLenInBytes - 1; while (i--) { if (pLargeInteger->pData[i]) { /* Data in Buffer+delta>0 */ return 1; } } result = pLargeInteger->pData[(pLargeInteger->dataLenInBytes - 1)] + delta; return result; } CpaBoolean LacPke_CompareFlatAndPtr(const CpaFlatBuffer *pFlatBufferA, const Cpa8U *pBufferB, Cpa32U lengthB) { if (NULL == pFlatBufferA) { return CPA_FALSE; } if (0 == LacPke_CompareIntPtrs(pFlatBufferA->pData, pFlatBufferA->dataLenInBytes, 0, pBufferB, lengthB, 0)) { return CPA_TRUE; } return CPA_FALSE; } Cpa32U LacPke_GetMinBytes(const CpaFlatBuffer *pBuffer) { Cpa32U buffSizeInBytes = pBuffer->dataLenInBytes; Cpa32U i = 0; /* starting at the MSB loop through all bytes until find the first non-zero byte if it exists */ while ((i < buffSizeInBytes) && (pBuffer->pData[i] == 0)) { i++; } return (buffSizeInBytes - i); } CpaStatus LacPke_GetBitPos(const CpaFlatBuffer *pBuffer, Cpa32U *pBitPos, Cpa32U *pIndexMsb, CpaBoolean *pIsZero) { Cpa32U numBytes = 0; Cpa32U buffSizeInBytes = pBuffer->dataLenInBytes; Cpa32U bitPosition = 0; Cpa8U msByte = 0; /* Set zero flag false initially*/ *pIsZero = CPA_FALSE; /* Find the first non-zero byte from end of buffer */ numBytes = LacPke_GetMinBytes(pBuffer); /* set pIndexMsb */ *pIndexMsb = buffSizeInBytes - numBytes; if (0 == numBytes) { /* Number is 0 */ *pIsZero = CPA_TRUE; (*pIndexMsb)--; bitPosition = 0; } else { if (numBytes > LAC_BITS_TO_BYTES(LAC_4096_BITS)) { LAC_INVALID_PARAM_LOG("Number size not supported"); return CPA_STATUS_INVALID_PARAM; } /* calc bit position rounded up to nearest byte */ bitPosition = (numBytes * LAC_NUM_BITS_IN_BYTE) - 1; msByte = pBuffer->pData[(*pIndexMsb)]; /* Locate the msb in the MSB */ while ((msByte & 0x80) == 0) { msByte <<= 1; bitPosition--; } } *pBitPos = bitPosition; return CPA_STATUS_SUCCESS; } CpaStatus LacPke_GetBitLen(const CpaFlatBuffer *pBuffer, Cpa32U *pBitLen) { Cpa32U numBytes = 0; Cpa32U buffSizeInBytes = pBuffer->dataLenInBytes; Cpa32U bitLength = 0; Cpa8U msByte = 0; /* Find the first non-zero byte */ numBytes = LacPke_GetMinBytes(pBuffer); if (0 == numBytes) { /* Number is 0 */ bitLength = 0; } else { if (numBytes > LAC_BITS_TO_BYTES(LAC_4096_BITS)) { LAC_INVALID_PARAM_LOG("Number size not supported"); return CPA_STATUS_INVALID_PARAM; } /* calc bit position rounded up to nearest byte */ bitLength = (numBytes * LAC_NUM_BITS_IN_BYTE); msByte = pBuffer->pData[(buffSizeInBytes - numBytes)]; /* Locate the msb in the MSB */ while ((msByte & 0x80) == 0) { msByte <<= 1; bitLength--; } } *pBitLen = bitLength; return CPA_STATUS_SUCCESS; } Cpa32U LacPke_GetMaxLnOfNBuffers(int n, ...) { va_list args; va_start(args, n); Cpa32U max = 0; CpaFlatBuffer* buf; int i = 0; for (i = 0; i < n; i++) { if ((buf = va_arg(args, CpaFlatBuffer*)) == NULL) continue; max = LAC_MAX(LacPke_GetMinBytes(buf), max); } va_end(args); return max; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/prime/000077500000000000000000000000001503624047500276065ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/prime/lac_prime.c000066400000000000000000001316461503624047500317200ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_prime.c Prime API Implementation * * @ingroup Lac_Prime * * @description * This file contains the implementation of Prime functions * ***************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ /* Include API files */ #include "cpa.h" #include "cpa_cy_prime.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Include Osal files */ #include "Osal.h" /* Include QAT files */ #include "icp_qat_fw_mmp.h" #include "icp_qat_fw_mmp_ids.h" #include "icp_qat_fw_la.h" /* Include ADF files */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* Include LAC files */ #include "lac_common.h" #include "lac_log.h" #include "lac_pke_qat_comms.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_hooks.h" #include "lac_prime.h" #include "lac_pke_utils.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "sal_service_state.h" #include "lac_sal_ctrl.h" #include "sal_statistics.h" /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* Number of Prime statistics */ #define LAC_PRIME_NUM_STATS (sizeof(CpaCyPrimeStats64) / sizeof(Cpa64U)) /* Minimal MillerRabin round size in byte */ #define LAC_PRIME_MIN_MILLER_RABIN_SIZE_IN_BYTES 64 /* ******************************************************************************** * Static Variables ******************************************************************************** */ #define LAC_PRIME_STATS_INIT(pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_PRIME_NUM_STATS; i++) \ { \ osalAtomicSet(0, &(pCryptoService)->pLacPrimeStatsArr[i]); \ } \ } while (0) /**< * macro to initialize all Prime stats (stored in internal array of atomics) */ #ifndef DISABLE_STATS #define LAC_PRIME_STAT_INC(statistic, pCryptoService) \ do \ { \ if (CPA_TRUE == \ pCryptoService->generic_service_info.stats->bPrimeStatsEnabled) \ { \ osalAtomicInc(&(pCryptoService) \ ->pLacPrimeStatsArr[offsetof(CpaCyPrimeStats64, \ statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) /**< * macro to increment a Prime stat (derives offset into array of atomics) */ #else #define LAC_PRIME_STAT_INC(statistic, pCryptoService) \ (pCryptoService) = (pCryptoService) #endif #define LAC_PRIME_STATS32_GET(primeStats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_PRIME_NUM_STATS; i++) \ { \ ((Cpa32U *)&(primeStats))[i] = (Cpa32U)osalAtomicGet( \ &(pCryptoService)->pLacPrimeStatsArr[i]); \ } \ } while (0) /**< * macro to get all Prime 32bit stats (from internal array of atomics) into * user supplied structure CpaCyPrimeStats pointed by primeStats pointer */ #define LAC_PRIME_STATS64_GET(primeStats, pCryptoService) \ do \ { \ Cpa32U i; \ \ for (i = 0; i < LAC_PRIME_NUM_STATS; i++) \ { \ ((Cpa64U *)&(primeStats))[i] = \ osalAtomicGet(&(pCryptoService)->pLacPrimeStatsArr[i]); \ } \ } while (0) /**< * macro to get all Prime 64bit stats (from internal array of atomics) into * user supplied structure CpaCyPrimeStats64 pointed by primeStats pointer */ static const Cpa32U lacGcdSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_160_BITS, PKE_GCD_PT_192}, {LAC_192_BITS, PKE_GCD_PT_192}, {LAC_256_BITS, PKE_GCD_PT_256}, {LAC_384_BITS, PKE_GCD_PT_384}, {LAC_512_BITS, PKE_GCD_PT_512}, {LAC_768_BITS, PKE_GCD_PT_768}, {LAC_1024_BITS, PKE_GCD_PT_1024}, {LAC_1536_BITS, PKE_GCD_PT_1536}, {LAC_2048_BITS, PKE_GCD_PT_2048}, {LAC_3072_BITS, PKE_GCD_PT_3072}, {LAC_4096_BITS, PKE_GCD_PT_4096}}; /**< * Maps between operation sizes and GCD PKE function ids */ static const Cpa32U lacFermatSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_160_BITS, PKE_FERMAT_PT_160}, {LAC_512_BITS, PKE_FERMAT_PT_512}, {LAC_768_BITS, PKE_FERMAT_PT_768}, {LAC_1024_BITS, PKE_FERMAT_PT_1024}, {LAC_1536_BITS, PKE_FERMAT_PT_1536}, {LAC_2048_BITS, PKE_FERMAT_PT_2048}, {LAC_3072_BITS, PKE_FERMAT_PT_3072}, {LAC_4096_BITS, PKE_FERMAT_PT_4096}}; /**< * Maps between operation sizes and Fermat PKE function ids */ static const Cpa32U lacLucasSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_160_BITS, PKE_LUCAS_PT_160}, {LAC_512_BITS, PKE_LUCAS_PT_512}, {LAC_768_BITS, PKE_LUCAS_PT_768}, {LAC_1024_BITS, PKE_LUCAS_PT_1024}, {LAC_1536_BITS, PKE_LUCAS_PT_1536}, {LAC_2048_BITS, PKE_LUCAS_PT_2048}, {LAC_3072_BITS, PKE_LUCAS_PT_3072}, {LAC_4096_BITS, PKE_LUCAS_PT_4096}}; /**< * Maps between operation sizes and Lucas PKE function ids */ static const Cpa32U lacMrSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_160_BITS, PKE_MR_PT_160}, {LAC_512_BITS, PKE_MR_PT_512}, {LAC_768_BITS, PKE_MR_PT_768}, {LAC_1024_BITS, PKE_MR_PT_1024}, {LAC_1536_BITS, PKE_MR_PT_1536}, {LAC_2048_BITS, PKE_MR_PT_2048}, {LAC_3072_BITS, PKE_MR_PT_3072}, {LAC_4096_BITS, PKE_MR_PT_4096}}; /**< * Maps between operation sizes and Miller-Rabin PKE function ids */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ /** ******************************************************************************* * @ingroup Lac_Prime * Prime Test internal callback function ******************************************************************************/ void LacPrimeTestCallback(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyPrimeTestCbFunc pCb = NULL; CpaCyPrimeTestOpData *pOpData = NULL; CpaFlatBuffer *pBuffInMillerRabin = NULL; void *pCallbackTag = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; /* retrieve data from the callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCb = (CpaCyPrimeTestCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pOpData = (CpaCyPrimeTestOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); pBuffInMillerRabin = (CpaFlatBuffer *)(pCbData->pOpaqueData); pCallbackTag = pCbData->pCallbackTag; LAC_ASSERT_NOT_NULL(pCb); LAC_ASSERT_NOT_NULL(pOpData); /* free the array of the input/output flat buffers */ if (NULL != pBuffInMillerRabin) { Lac_MemPoolEntryFree(pBuffInMillerRabin); } /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_PRIME_STAT_INC(numPrimeTestCompleted, pCryptoService); if (CPA_FALSE == pass) { LAC_PRIME_STAT_INC(numPrimeTestFailures, pCryptoService); } } else { LAC_PRIME_STAT_INC(numPrimeTestCompletedErrors, pCryptoService); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pass); } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Get Function ID function ******************************************************************************/ Cpa32U LacPrimeGetFuncID(lac_prime_test_t testId, Cpa32U *pOpLenInBits) { Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; /* * get functionality ID for GCD request */ if (LAC_PRIME_GCD == testId) { functionalityId = LacPke_GetMmpId( (*pOpLenInBits), lacGcdSizeIdMap, LAC_ARRAY_LEN(lacGcdSizeIdMap)); if ((LAC_PKE_INVALID_FUNC_ID == functionalityId) && ((*pOpLenInBits) < LAC_512_BITS)) { functionalityId = PKE_GCD_PT_512; /* Select new OpLen */ *pOpLenInBits = LAC_512_BITS; } } /* * get functionality ID for Fermat request */ else if (LAC_PRIME_FERMAT == testId) { functionalityId = LacPke_GetMmpId((*pOpLenInBits), lacFermatSizeIdMap, LAC_ARRAY_LEN(lacFermatSizeIdMap)); if ((LAC_PKE_INVALID_FUNC_ID == functionalityId) && ((*pOpLenInBits) < LAC_512_BITS)) { functionalityId = PKE_FERMAT_PT_L512; /* Select new OpLen */ *pOpLenInBits = LAC_512_BITS; } } /* * get functionality ID for Miller-Rabin request */ else if (LAC_PRIME_MILLER_RABIN == testId) { functionalityId = LacPke_GetMmpId( (*pOpLenInBits), lacMrSizeIdMap, LAC_ARRAY_LEN(lacMrSizeIdMap)); if ((LAC_PKE_INVALID_FUNC_ID == functionalityId) && ((*pOpLenInBits) < LAC_512_BITS)) { functionalityId = PKE_MR_PT_L512; /* Select new OpLen */ *pOpLenInBits = LAC_512_BITS; } } /* * get functionality ID for Lucas request */ else if (LAC_PRIME_LUCAS == testId) { functionalityId = LacPke_GetMmpId((*pOpLenInBits), lacLucasSizeIdMap, LAC_ARRAY_LEN(lacLucasSizeIdMap)); if ((LAC_PKE_INVALID_FUNC_ID == functionalityId) && ((*pOpLenInBits) < LAC_512_BITS)) { functionalityId = PKE_LUCAS_PT_L512; /* Select new OpLen */ *pOpLenInBits = LAC_512_BITS; } } return functionalityId; } /** ******************************************************************************* * @ingroup Lac_Prime * Populate Prime Input and Output Parameter function ******************************************************************************/ void LacPrimePopulateParam(lac_prime_test_t testId, Cpa32U opSizeInBytes, icp_qat_fw_mmp_input_param_t *pIn, icp_qat_fw_mmp_output_param_t *pOut, Cpa32U *pInSize, CpaBoolean *pInternalMemInList, CpaBoolean internalPrimeMem, CpaFlatBuffer *pPrimeBuff, const CpaFlatBuffer *pInputMillerRabinBuffer) { /* * populate input/output parameters for GCD request * using mmp_gcd_pt_192 as generic structure */ if (LAC_PRIME_GCD == testId) { LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->mmp_gcd_pt_192.m, pPrimeBuff); pInSize[0] = opSizeInBytes; pInternalMemInList[0] = internalPrimeMem; } /* * populate input/output parameters for Fermat request * using mmp_fermat_pt_160 as generic structure */ else if (LAC_PRIME_FERMAT == testId) { LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->mmp_fermat_pt_160.m, pPrimeBuff); pInSize[0] = opSizeInBytes; pInternalMemInList[0] = internalPrimeMem; } /* * populate input/output parameters Miller-Rabin request * using mmp_mr_pt_160 as generic structure */ else if (LAC_PRIME_MILLER_RABIN == testId) { /* populate input/output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->mmp_mr_pt_160.x, pInputMillerRabinBuffer); pInSize[LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x)] = opSizeInBytes; /* FlatBuffer is internally allocated but the memory we send to QAT is externally allocated */ pInternalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->mmp_mr_pt_160.m, pPrimeBuff); pInSize[LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m)] = opSizeInBytes; pInternalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m)] = internalPrimeMem; } /* * populate input/output parameters for Lucas request * using mmp_lucas_pt_160 as generic structure */ else if (LAC_PRIME_LUCAS == testId) { LAC_MEM_SHARED_WRITE_FROM_PTR(pIn->mmp_lucas_pt_160.m, pPrimeBuff); pInSize[0] = opSizeInBytes; pInternalMemInList[0] = internalPrimeMem; } } #ifdef ICP_PARAM_CHECK /** ******************************************************************************* * @ingroup Lac_Prime * Prime Test parameter check ******************************************************************************/ CpaStatus LacPrimeParameterCheck(CpaCyPrimeTestCbFunc pCb, CpaCyPrimeTestOpData *pOpData, CpaBoolean *pTestPassed) { Cpa32U roundMillerRabin = 0; CpaStatus status = CPA_STATUS_SUCCESS; /* check for valid callback function pointer */ LAC_CHECK_NULL_PARAM(pCb); /* check for null Operational Data parameters */ LAC_CHECK_NULL_PARAM(pOpData); /* Check for bad pointer */ LAC_CHECK_NULL_PARAM(pTestPassed); /* check for null Prime candidate parameter */ LAC_CHECK_FLAT_BUFFER(&pOpData->primeCandidate); /* for the better readability assign the number of rounds for * Miller-Rabin test and Prime Candidate data length */ roundMillerRabin = pOpData->numMillerRabinRounds; /* Check that the Prime Candidate is within size limits, * not-even (LSB is set) and not-null */ LAC_CHECK_FLAT_BUFFER_PARAM_PKE(&pOpData->primeCandidate, CHECK_LESS_EQUALS, LAC_MAX_PRIME_SIZE_IN_BITS, LAC_CHECK_LSB_YES); /* It is an error if no test is booked */ if (!((pOpData->performGcdTest) || (pOpData->performFermatTest) || (roundMillerRabin != 0) || (pOpData->performLucasTest))) { LAC_INVALID_PARAM_LOG("No prime test was selected"); status = CPA_STATUS_INVALID_PARAM; } /* Check that, if test has been booked, the Miller-Rabin parameters are set * correctly */ if ((roundMillerRabin > 0) && (CPA_STATUS_SUCCESS == status)) { /* Number of Miller-Rabin rounds must not exceed maximum allowed! */ if (roundMillerRabin <= LAC_PRIME_MAX_MR) { /* Check the input buffer size for Miller-Rabin (array of random * numbers) the size of the buffer is validated later */ LAC_CHECK_FLAT_BUFFER_PARAM( &pOpData->millerRabinRandomInput, CHECK_NONE, 0); } else { LAC_INVALID_PARAM_LOG("Number of Miller-Rabin rounds too high"); status = CPA_STATUS_INVALID_PARAM; } } return status; } #endif /** *************************************************************************** * @ingroup Lac_Prime * Prime Test synchronous function ***************************************************************************/ STATIC CpaStatus LacPrimeTestSyn(const CpaInstanceHandle instanceHandle, CpaCyPrimeTestOpData *pOpData, CpaBoolean *pTestPassed) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyPrimeTest(instanceHandle, LacSync_GenVerifyCb, pSyncCallbackData, pOpData, pTestPassed); } else { LAC_PRIME_STAT_INC(numPrimeTestRequestErrors, pCryptoService); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, pTestPassed); if (CPA_STATUS_SUCCESS != wCbStatus) { /* * Inc stats only if the wait for callback failed. */ LAC_PRIME_STAT_INC(numPrimeTestCompletedErrors, pCryptoService); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Test API function ******************************************************************************/ CpaStatus cpaCyPrimeTest(const CpaInstanceHandle instanceHandle_in, const CpaCyPrimeTestCbFunc pCb, void *pCallbackTag, const CpaCyPrimeTestOpData *pOpData, CpaBoolean *pTestPassed) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; lac_prime_test_t testId = LAC_PRIME_FERMAT; Cpa32U roundMillerRabin = 0; Cpa32U functionalityId = 0; Cpa32U numRounds = 0; Cpa32U indexMillerRabin = 0; Cpa32U round = 0; Cpa32U inputLenInBits = 0; /* bit length of prime candidate */ Cpa32U inputLenInBytes = 0; /* byte length of prime candidate */ Cpa32U mrRoundSizeInBytes = 0; /* byte length of a MR round buffer */ CpaBoolean isZero = CPA_FALSE; Cpa32U tempOpLenInBits = 0; Cpa32U dataOpLenInBytes = 0; /* Number of bytes required by PKE service */ sal_crypto_service_t *pCryptoService = NULL; icp_qat_fw_mmp_input_param_t inArgList = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t outArgList = {.flat_array = {0}}; Cpa32U inArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalPrimeMem = CPA_FALSE; /* Array of random numbers for MIller-Rabin test is stored in a block of * memory. For further processing, one flat buffer has to be formed for * each random number. * * Define array of flat buffers to hold input random numbers * for prime test. */ CpaFlatBuffer *pBuffInputMillerRabin = NULL; /* * Pointer to flat buffer used to hold the prime candidate this can * be either the user supplied buffer or an internal flat buffer * in the case where the prime input has been resized by pke_common. * This prevents further copies in the chain. */ CpaFlatBuffer *pBuffPrimeInternal = NULL; /* Data that will be passed back in call back function - opaque data */ lac_pke_op_cb_data_t primeTestData = {0}; /* For a single request, or the first request in a chain of requests, the * requestHandle value must be zero (i.e. LAC_PKE_INVALID_HANDLE). The * non-zero value means that the new request is chained to the * request (chain) already associated with the handle. */ lac_pke_request_handle_t requestHandle = LAC_PKE_INVALID_HANDLE; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle - can't update stats otherwise */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif /* Check if prime capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, prime); pCryptoService = (sal_crypto_service_t *)instanceHandle; /* Check if the API has been called in sync mode */ if (NULL == pCb) { #ifdef ICP_TRACE status = LacPrimeTestSyn( instanceHandle, LAC_CONST_PTR_CAST(pOpData), pTestPassed); if (NULL != pTestPassed) { LAC_LOG6("Called with params (0x%lx, 0x%lx, " "0x%lx, 0x%lx, 0x%lx[%d]\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pTestPassed, *pTestPassed); } else { LAC_LOG5("Called with params (0x%lx, 0x%lx, " "0x%lx, 0x%lx, 0x%lx\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pOpData, (LAC_ARCH_UINT)pTestPassed); } return status; #else return LacPrimeTestSyn( instanceHandle, LAC_CONST_PTR_CAST(pOpData), pTestPassed); #endif } #ifdef ICP_PARAM_CHECK /* check that the input parameters are valid */ status = LacPrimeParameterCheck(pCb, LAC_CONST_PTR_CAST(pOpData), pTestPassed); #endif if (CPA_STATUS_SUCCESS == status) { /* for the better readability assign the number of rounds for * Miller-Rabin test and Prime Candidate data length */ roundMillerRabin = pOpData->numMillerRabinRounds; /* Get bit and byte length of the primeCandidate */ status = LacPke_GetBitPos(&(pOpData->primeCandidate), &inputLenInBits, &inputLenInBytes, &isZero); inputLenInBits++; inputLenInBytes = pOpData->primeCandidate.dataLenInBytes - inputLenInBytes; /* The size of a MR buffer MUST be * max(LAC_PRIME_MIN_MILLER_RABIN_SIZE_IN_BYTES, x) * where: x is the minimum number of bytes required to represent the * prime candidate, i.e. x = ceiling((ceiling(log2(p)))/8). */ mrRoundSizeInBytes = LAC_MAX(LAC_PRIME_MIN_MILLER_RABIN_SIZE_IN_BYTES, inputLenInBytes); } if ((CPA_STATUS_SUCCESS == status) && (roundMillerRabin > 0)) { /* In the case of MR we need to divide up the client provided millerRabinRandomInput buffer the best we can. To do this we need to find out the PKE service we will use and the size of the input it expects */ tempOpLenInBits = inputLenInBits; functionalityId = LacPrimeGetFuncID(testId, &tempOpLenInBits); if (LAC_PKE_INVALID_FUNC_ID == functionalityId) { LAC_INVALID_PARAM_LOG("Prime candidate bit length not" " supported. Supported bit lengths include" " all lengths less than 512, 512, 768, 1024" " 1536, 2048, 3072 and 4096"); status = CPA_STATUS_INVALID_PARAM; } } #ifdef ICP_PARAM_CHECK if ((CPA_STATUS_SUCCESS == status) && (roundMillerRabin > 0)) { /* check the buffer size of millerRabinRandomInput */ if (pOpData->millerRabinRandomInput.dataLenInBytes == (roundMillerRabin * mrRoundSizeInBytes)) { /* Each random number MUST be greater than 1 and less than the prime * candidate - 1*/ CpaFlatBuffer randomNumber = { .pData = pOpData->millerRabinRandomInput.pData, .dataLenInBytes = mrRoundSizeInBytes}; Cpa32U round = 0; for (round = 1; round <= roundMillerRabin; round++) { if ((LacPke_CompareZero(&randomNumber, -1) <= 0) || (LacPke_Compare( &randomNumber, 0, &(pOpData->primeCandidate), -1) >= 0)) { LAC_INVALID_PARAM_LOG1("pOpData->millerRabinRandomInput " "#%u has incorrect range", round); status = CPA_STATUS_INVALID_PARAM; break; } randomNumber.pData += mrRoundSizeInBytes; } } else { /* not enough random buffer provided */ LAC_INVALID_PARAM_LOG("pOpData->millerRabinRandomInput has " "incorrect length"); status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { /* Allocating the memory for the array of flat buffers in which the * elements to hold input random numbers for Miller-Rabin test is * stored. * The first element of this array is reserved for storing the * resized prime if required. */ do { pBuffInputMillerRabin = (CpaFlatBuffer *)Lac_MemPoolEntryAlloc( pCryptoService->lac_prime_pool); if (NULL == pBuffInputMillerRabin) { LAC_LOG_ERROR("Cannot get mem pool entry"); /* on failure increment stats: */ LAC_PRIME_STAT_INC(numPrimeTestRequestErrors, pCryptoService); status = CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pBuffInputMillerRabin) { osalYield(); } } while ((void *)CPA_STATUS_RETRY == pBuffInputMillerRabin); } if ((CPA_STATUS_SUCCESS == status) && (roundMillerRabin > 0)) { /* pointer to the array of random numbers for Miller-Rabin test. Used to * calculate the addresses of the array members */ Cpa8U *pCurrentAddress = pOpData->millerRabinRandomInput.pData; /* Link the random number from Miller-Rabin array to the designated * member of the array of flat buffers. * First flat buffer is not used as it is reserved for resized prime */ for (indexMillerRabin = 1; indexMillerRabin <= roundMillerRabin; indexMillerRabin++) { /* Members of the array of flat buffers that will hold random * number for M-R test. In fact, each buffer's pData pointer is * assigned the address of the corresponding random number in the * user given block of memory. */ pBuffInputMillerRabin[indexMillerRabin].pData = pCurrentAddress; pBuffInputMillerRabin[indexMillerRabin].dataLenInBytes = mrRoundSizeInBytes; pCurrentAddress += mrRoundSizeInBytes; } } if (CPA_STATUS_SUCCESS == status) { /* Prime is user supplied prime until after we have resized */ pBuffPrimeInternal = (CpaFlatBuffer *)(&(pOpData->primeCandidate)); /* preserve user parameters and the OutputBuffer for when our Call Back function kicks in, after sending the head request */ /* Note for all prime messages this should be the same as we do not know what request in the chain will generate the response - this means we allocate pBuffInputMillerRabin even if we do not need it */ primeTestData.pClientCb = pCb; primeTestData.pCallbackTag = pCallbackTag; primeTestData.pClientOpData = pOpData; primeTestData.pOpaqueData = pBuffInputMillerRabin; } /* Create the PKE request and chain as necessary for multiple tests in * order of the increasing complexity: Fermat->Miller-Rabin->Lucas. * Send the request when finished. */ for (testId = (lac_prime_test_t)(LAC_PRIME_TEST_START_DELIMITER + 1); (testId < LAC_PRIME_TEST_END_DELIMITER) && (CPA_STATUS_SUCCESS == status); testId++) { /* assign the number of rounds per test */ if (testId == LAC_PRIME_GCD) { numRounds = (pOpData->performGcdTest ? 1 : 0); } if (testId == LAC_PRIME_FERMAT) { numRounds = (pOpData->performFermatTest ? 1 : 0); } if (testId == LAC_PRIME_MILLER_RABIN) { numRounds = roundMillerRabin; } if (testId == LAC_PRIME_LUCAS) { numRounds = (pOpData->performLucasTest ? 1 : 0); } /* get functionality ID and dataOpLen for undergoing test */ if (numRounds > 0) { tempOpLenInBits = inputLenInBits; /* tempOpLenInBits may get rounded updated by this function */ functionalityId = LacPrimeGetFuncID(testId, &tempOpLenInBits); if (LAC_PKE_INVALID_FUNC_ID == functionalityId) { LAC_INVALID_PARAM_LOG( "Prime candidate bit length not" " supported. Supported bit lengths include" " all lengths less than 512, 512, 768, 1024" " 1536, 2048, 3072 and 4096"); status = CPA_STATUS_INVALID_PARAM; } } /* populate parameters and create request for each round */ for (round = 1; (round <= numRounds) && (CPA_STATUS_SUCCESS == status); round++) { LAC_OS_BZERO(&inArgList, sizeof(icp_qat_fw_mmp_input_param_t)); LAC_OS_BZERO(&outArgList, sizeof(icp_qat_fw_mmp_output_param_t)); /* Number of bytes required by PKE - needs to be rounded up to nearest QW multiple */ /* Note that the the number of bytes required by PKE for Fermat, MR and Lucas tests are the same but the number of bytes required for GCD tests may be different */ dataOpLenInBytes = LAC_ALIGN_POW2_ROUNDUP( LAC_BITS_TO_BYTES(tempOpLenInBits), LAC_QUAD_WORD_IN_BYTES); /* populate input/output parameters first */ LacPrimePopulateParam( testId, dataOpLenInBytes, &inArgList, &outArgList, inArgSizeList, internalMemInList, internalPrimeMem, ((LAC_PRIME_GCD == testId) ? (CpaFlatBuffer *)(&pOpData->primeCandidate) : pBuffPrimeInternal), (LAC_PRIME_MILLER_RABIN == testId) ? &pBuffInputMillerRabin[round] : NULL); /* Create PKE request */ status = LacPke_CreateRequest(&requestHandle, functionalityId, inArgSizeList, NULL, &inArgList, &outArgList, internalMemInList, NULL, LacPrimeTestCallback, &primeTestData, instanceHandle); if ((CPA_STATUS_SUCCESS == status) && (LAC_PRIME_GCD != testId) && (pBuffPrimeInternal->dataLenInBytes < dataOpLenInBytes)) { /* Request was successfully created, the test is not GCD and the prime buffer size was less than required - that means that an internal resize buffer was allocated by pke_common. As Fermat, MR and Lucas all require the same input buffer sizes we should use this new correctly sized buffer as input to all other prime requests in the chain to avoid further resizing */ /* Assumption here is that all prime services except GCD are the same size, i.e. one of 160,512,L512,768,1024, 1536, 2048,3072 or 4096 */ lac_pke_qat_req_data_t *pReq = requestHandle; if (NULL != pReq->pNextReqData) { /* Not first request in chain - i.e. a GCD message has already been built */ pReq = pReq->pNextReqData; } if (LAC_PRIME_MILLER_RABIN == testId) { pBuffInputMillerRabin[0].pData = pReq->paramInfo.pkeInputParams[LAC_IDX_OF( icp_qat_fw_mmp_mr_pt_160_input_t, m)]; } else { /* For all other cases prime is first in the list */ pBuffInputMillerRabin[0].pData = pReq->paramInfo.pkeInputParams[0]; } pBuffInputMillerRabin[0].dataLenInBytes = dataOpLenInBytes; internalPrimeMem = CPA_TRUE; pBuffPrimeInternal = &(pBuffInputMillerRabin[0]); } } } /* now, after the requests has been created, * send the head request to the QAT */ if (CPA_STATUS_SUCCESS == status) { /* send request chain */ status = LacPke_SendRequest(&requestHandle, instanceHandle); } /* update stats. In case of failure free the memory */ if (CPA_STATUS_SUCCESS == status) { /* increment stats: * Total number of prime number test requested operations */ LAC_PRIME_STAT_INC(numPrimeTestRequests, pCryptoService); } else { /* on failure increment stats: * Total number of prime number test errors recorded */ LAC_PRIME_STAT_INC(numPrimeTestRequestErrors, pCryptoService); /* if allocated, free the memory on failure */ if (NULL != pBuffInputMillerRabin) { /* free the array of the input flat buffers */ Lac_MemPoolEntryFree(pBuffInputMillerRabin); } } return status; } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Statistics Query API function ******************************************************************************/ CpaStatus cpaCyPrimeQueryStats(CpaInstanceHandle instanceHandle_in, struct _CpaCyPrimeStats *pPrimeStats) { sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pPrimeStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* check this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); /* Check if prime capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, prime); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pPrimeStats); /* get stats into user supplied stats structure */ pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_PRIME_STATS32_GET(*pPrimeStats, pCryptoService); return CPA_STATUS_SUCCESS; } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Statistics Query API function ******************************************************************************/ CpaStatus cpaCyPrimeQueryStats64(CpaInstanceHandle instanceHandle_in, CpaCyPrimeStats64 *pPrimeStats) { sal_crypto_service_t *pCryptoService = NULL; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pPrimeStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* ensure LAC is running - return error if not */ SAL_RUNNING_CHECK(instanceHandle); /* check this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); /* Check if prime capability is enabled */ SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, prime); /* check for null parameters */ LAC_CHECK_NULL_PARAM(pPrimeStats); /* get stats into user supplied stats structure */ pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_PRIME_STATS64_GET(*pPrimeStats, pCryptoService); return CPA_STATUS_SUCCESS; } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Initialization function ******************************************************************************/ CpaStatus LacPrime_Init(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = NULL; CpaStatus status = CPA_STATUS_SUCCESS; pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pCryptoService->pLacPrimeStatsArr), LAC_PRIME_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { /* initialize stats to zero */ LAC_PRIME_STATS_INIT(pCryptoService); } /* Call compile time param check function to ensure it is included in the build by the compiler */ LacPrime_CompileTimeAssertions(); return status; } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Stats cleanup function ******************************************************************************/ void LacPrime_StatsFree(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; if (NULL != pCryptoService->pLacPrimeStatsArr) { LAC_OS_FREE(pCryptoService->pLacPrimeStatsArr); } } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Stats reset function ******************************************************************************/ void LacPrime_StatsReset(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = NULL; pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_PRIME_STATS_INIT(pCryptoService); } /** ******************************************************************************* * @ingroup Lac_Prime * Prime Stats Show function ******************************************************************************/ void LacPrime_StatsShow(CpaInstanceHandle instanceHandle) { CpaCyPrimeStats64 primeStats = {0}; /* retrieve the stats */ (void)cpaCyPrimeQueryStats64(instanceHandle, &primeStats); /* log the stats to the standard output */ /* Engine Info */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " PRIME Stats " BORDER "\n" SEPARATOR); /* Parameter generation requests - PRIME stats */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " PRIME successful requests: %16llu " BORDER "\n" BORDER " PRIME failed requests: %16llu " BORDER "\n" BORDER " PRIME successfully completed: %16llu " BORDER "\n" BORDER " PRIME failed completion: %16llu " BORDER "\n" BORDER " PRIME completed - not a prime: %16llu " BORDER "\n" SEPARATOR, primeStats.numPrimeTestRequests, primeStats.numPrimeTestRequestErrors, primeStats.numPrimeTestCompleted, primeStats.numPrimeTestCompletedErrors, primeStats.numPrimeTestFailures); } lac_prime_interface_check.c000066400000000000000000000151211503624047500350030ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/prime/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_prime_interface_check.c * * @ingroup Lac_Prime * * This file checks at compile time that the IA/FW interface is as expected * For example, in lac_prime.c we use the fact that the index of x in the * structure icp_qat_fw_mmp_mr_pt_160_input_t is equal to the index of * x in the structure icp_qat_fw_mmp_mr_pt_512_input_t. If this * assumption becomes invalid (FW interface changes to break the assumption * or the compiler moves things around) this file will fail to compile. * * Note for structures with only 1 member no check is required. * * ***************************************************************************/ #include "cpa.h" #include "icp_qat_fw_pke.h" #include "icp_qat_fw_mmp.h" #include "lac_pke_utils.h" #define MAX_MR_ROUNDS_SUPPORTED 50 #define MIN_MR_ROUNDS_SUPPORTED 1 /**< * MAX number of MR rounds can be decided at compile time - use these a limits for compile time check on this number */ #define COMPILE_TIME_ASSERT(pred) \ switch (0) \ { \ case 0: \ case pred:; \ } void LacPrime_CompileTimeAssertions(void) { /* ************************************************************ * Check 0 < LAC_PRIME_MAX_MR <= 50 * ************************************************************ */ COMPILE_TIME_ASSERT(LAC_PRIME_MAX_MR <= MAX_MR_ROUNDS_SUPPORTED); COMPILE_TIME_ASSERT(LAC_PRIME_MAX_MR >= MIN_MR_ROUNDS_SUPPORTED); /* ************************************************************* * MR interface check - note for all other prime services there * is only 1 member in the structure * ************************************************************* */ /* Check that icp_qat_fw_mmp_mr_pt_160_input_t, icp_qat_fw_mmp_mr_pt_512_input_t, icp_qat_fw_mmp_mr_pt_768_input_t, icp_qat_fw_mmp_mr_pt_1024_input_t, icp_qat_fw_mmp_mr_pt_1536_input_t, icp_qat_fw_mmp_mr_pt_2048_input_t, icp_qat_fw_mmp_mr_pt_3072_input_t, icp_qat_fw_mmp_mr_pt_4096_input_t, icp_qat_fw_mmp_mr_pt_l512_input_t structures are equivalent */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_512_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_512_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_768_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_768_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_1024_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_1024_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_1536_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_1536_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_2048_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_2048_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_3072_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_3072_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_4096_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_4096_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, x) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_l512_input_t, x)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_160_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_mr_pt_l512_input_t, m)); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/000077500000000000000000000000001503624047500272575ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_kpt_rsa_decrypt.c000066400000000000000000000060221503624047500334370ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * @file lac_kpt_rsa_decrypt.c * * @ingroup Lac_KptRsa * * This file implements data decryption function for KPT RSA. * *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "cpa_cy_rsa.h" #include "cpa_cy_kpt.h" /** ***************************************************************************** * @ingroup Lac_KptRsa * This function performs KPT RSA decryption. * *****************************************************************************/ CpaStatus cpaCyKptRsaDecrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyKptRsaDecryptOpData *pDecryptOpData, CpaFlatBuffer *pOutputData, CpaCyKptUnwrapContext *pKptUnwrapContext) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa.c000066400000000000000000000271141503624047500310340ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * @file lac_rsa.c * * @defgroup LacRsa RSA * * @ingroup LacAsym * * This file implements functions for RSA. * * @lld_start * * @lld_overview * This is the RSA feature implementation. It implements 3 RSA API * services: keygen, encrypt and decrypt. Statistics are maintained for each * service. * For each service the parameters supplied by the client are checked, and then * input/output argument lists are constructed before calling the PKE QAT * Comms layer to create and send a request to the QAT. * * For encrypt operations there is only one type of public key so only one * QAT message can be constructed. however for keygen and decrypt there are two * types of private key to be dealt with. This means that one of two messages * can be sent to the QAT. In these cases all common processing shall be done * first. Then we branch depending on the key type and perform key specific * processing. * * In all cases the service implementations are a straightforward * marshalling of client-supplied parameters for the QAT. i.e. there is * minimal logic handled by this component. Resize buffers are handled by * the PKE QAT Comms layer. * * The user's input buffers are checked for null params, correct length, msb * and lsb set where necessary. The following parameter checks based on the * standard are also performed for RSA * * RSA Keygen: * Test: p and q must have the msb /lsb set. * Test: Will check that e > = 3 before sending to the QAT. * e is odd * Test: Once the QAT has returned can check that e < n * Test: Once the QAT has returned can check that the top bit of * n is set * * Encrypt: * Test: The message parameter must satisfy 0 < m < = n-1 * Test: The Modulus n must have the msb/lsb set. * * Decrypt: * Form 1: * Test: The ciphertext must satisfy 0 < c < = n-1. * Test: Modulus n has msb /lsb set. * Form 2: * Test: p and q must have the msb /lsb set. * Test: For prime tests will just check that p and q * are odd. * Test: 1 < Dp < p-1 * Test: 1 < Dq < q-1 * Test: 1 < = qInv < p (this could be 1) * * @lld_dependencies * - @ref LacAsymCommonQatComms "PKE QAT Comms" : For creating and sending * messages to the QAT * - @ref LacMem "Mem" : For memory allocation and freeing, and translating * between scalar and pointer types * - @ref LacAsymCommon "PKE Common" : For MMP generic structures and param * checking macros * - OSAL : For atomics and logging * * @lld_initialisation * On initialization this component clears the stats. * * @lld_module_algorithms * * @lld_process_context * * @lld_end *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ /* Include API files */ #include "cpa.h" #include "cpa_cy_rsa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Include Osal files */ #include "Osal.h" /* Include LAC files */ #include "lac_mem.h" #include "lac_common.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_rsa_p.h" /* ******************************************************************************** * Static Variables ******************************************************************************** */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ CpaBoolean LacRsa_IsValidRsaSize(Cpa32U opSizeInBytes) { Cpa32U opSizeInBits = LAC_NUM_BITS_IN_BYTE * opSizeInBytes; #ifdef QAT_LEGACY_ALGORITHMS if ((LAC_512_BITS != opSizeInBits) && (LAC_1024_BITS != opSizeInBits) && (LAC_1536_BITS != opSizeInBits) && (LAC_2048_BITS != opSizeInBits) && (LAC_3072_BITS != opSizeInBits) && (LAC_4096_BITS != opSizeInBits) && (LAC_8192_BITS != opSizeInBits)) #else if ((LAC_2048_BITS != opSizeInBits) && (LAC_3072_BITS != opSizeInBits) && (LAC_4096_BITS != opSizeInBits) && (LAC_8192_BITS != opSizeInBits)) #endif { #ifdef QAT_LEGACY_ALGORITHMS LAC_INVALID_PARAM_LOG( "Invalid operation size. Valid op sizes for " "RSA are 512, 1024, 1536, 2048, 3072, 4096 and 8192 bits."); #else LAC_INVALID_PARAM_LOG( "Invalid operation size. Valid op sizes for " "RSA are 2048, 3072, 4096 and 8192 bits."); #endif return CPA_FALSE; } return CPA_TRUE; } CpaStatus LacRsa_Type2StdsCheck(CpaCyRsaPrivateKeyRep2 *pPrivateKeyRep2) { /* * @note ideally we we check for type two keys that c < n. However * we cannot guarantee that the a type 2 key struct has the correct * values set for the type 1 fields (n is a type 1 field). */ /* Standards based check: 1 < Dp < p-1 */ if (LacPke_CompareZero(&(pPrivateKeyRep2->exponent1Dp), -1) <= 0) { LAC_INVALID_PARAM_LOG("exponent1Dp must be > 1"); return CPA_STATUS_INVALID_PARAM; } if (LacPke_Compare(&(pPrivateKeyRep2->exponent1Dp), 0, &(pPrivateKeyRep2->prime1P), -1) >= 0) { LAC_INVALID_PARAM_LOG("exponent1Dp must be < prime1P - 1"); return CPA_STATUS_INVALID_PARAM; } /* Standards based check: 1 < Dq < q-1 */ if (LacPke_CompareZero(&(pPrivateKeyRep2->exponent2Dq), -1) <= 0) { LAC_INVALID_PARAM_LOG("exponent2Dq must be > 1"); return CPA_STATUS_INVALID_PARAM; } if (LacPke_Compare(&(pPrivateKeyRep2->exponent2Dq), 0, &(pPrivateKeyRep2->prime2Q), -1) >= 0) { LAC_INVALID_PARAM_LOG("exponent2Dq must be < pPrime2Q - 1"); return CPA_STATUS_INVALID_PARAM; } /* Standards based check: 1 <= qInv < p */ LAC_CHECK_NON_ZERO_PARAM(&(pPrivateKeyRep2->coefficientQInv)); if (LacPke_Compare(&(pPrivateKeyRep2->coefficientQInv), 0, &(pPrivateKeyRep2->prime1P), 0) >= 0) { LAC_INVALID_PARAM_LOG("coefficientQInv must be < prime1P"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } CpaStatus LacRsa_CheckPrivateKeyParam(CpaCyRsaPrivateKey *pPrivateKey) { LAC_CHECK_NULL_PARAM(pPrivateKey); if (CPA_CY_RSA_VERSION_TWO_PRIME != pPrivateKey->version) { LAC_INVALID_PARAM_LOG("Invalid pPrivateKey->version"); return CPA_STATUS_INVALID_PARAM; } switch (pPrivateKey->privateKeyRepType) { case CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1: { LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep1.privateExponentD), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep1.modulusN), CHECK_NONE, 0); } break; case CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2: { LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep2.prime1P), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep2.prime2Q), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep2.exponent1Dp), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep2.exponent2Dq), CHECK_NONE, 0); LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep2.coefficientQInv), CHECK_NONE, 0); } break; default: { /* Invalid Key Type */ LAC_INVALID_PARAM_LOG("Invalid pPrivateKey->privateKeyRepType"); return CPA_STATUS_INVALID_PARAM; } } return CPA_STATUS_SUCCESS; } Cpa32U LacRsa_GetPrivateKeyOpSize(const CpaCyRsaPrivateKey *pPrivateKey) { Cpa32U sizeInBytes = 0; LAC_ASSERT_NOT_NULL(pPrivateKey); switch (pPrivateKey->privateKeyRepType) { case CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1: { sizeInBytes += LacPke_GetMinBytes(&(pPrivateKey->privateKeyRep1.modulusN)); } break; case CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2: { sizeInBytes = LacPke_GetMinBytes(&(pPrivateKey->privateKeyRep2.prime1P)); if (sizeInBytes != LacPke_GetMinBytes(&(pPrivateKey->privateKeyRep2.prime2Q))) { LAC_LOG_ERROR( "prime1P.dataLenInBytes != prime2Q.dataLenInBytes"); sizeInBytes = 0; } else { sizeInBytes = sizeInBytes << 1; } } break; default: { /* Invalid Key Type */ LAC_LOG_ERROR("Invalid Private Key Type."); } } return sizeInBytes; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_control_path.c000066400000000000000000000103361503624047500336060ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * @file lac_rsa_control_path.c * * @ingroup LacRsa * * This file implements the API functions and the init and shutdown functions. * *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "cpa_cy_rsa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Osal include */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_common.h" #include "lac_hooks.h" #include "lac_rsa_p.h" #include "lac_rsa_stats_p.h" /* ******************************************************************************** * Static Variables ******************************************************************************** */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ CpaStatus LacRsa_Init(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; /* Initialise and reset all statistics */ status = LacRsa_StatsInit(instanceHandle); /* Call compile time param check function to ensure it is included in the build by the compiler */ LacRsa_CompileTimeAssertions(); return status; } /* LacRsa_Init */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_decrypt.c000066400000000000000000000600201503624047500325570ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * @file lac_rsa_decrypt.c * * @ingroup LacRsa * * This file implements decrypt functions for RSA. * *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "cpa_cy_rsa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Osal include */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp_ids.h" /* Include LAC files */ #include "lac_common.h" #include "lac_pke_qat_comms.h" #include "lac_pke_utils.h" #include "lac_pke_mmp.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "lac_rsa_p.h" #include "lac_rsa_stats_p.h" /* ******************************************************************************** * Static Variables ******************************************************************************** */ static const Cpa32U lacRsaDp1SizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_512_BITS, PKE_RSA_DP1_512}, {LAC_1024_BITS, PKE_RSA_DP1_1024}, {LAC_1536_BITS, PKE_RSA_DP1_1536}, {LAC_2048_BITS, PKE_RSA_DP1_2048}, {LAC_3072_BITS, PKE_RSA_DP1_3072}, {LAC_4096_BITS, PKE_RSA_DP1_4096}, {LAC_8192_BITS, PKE_RSA_DP1_8192}}; /**< * Maps between operation sizes and PKE function ids */ static const Cpa32U lacRsaDp2SizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_512_BITS, PKE_RSA_DP2_512}, {LAC_1024_BITS, PKE_RSA_DP2_1024}, {LAC_1536_BITS, PKE_RSA_DP2_1536}, {LAC_2048_BITS, PKE_RSA_DP2_2048}, {LAC_3072_BITS, PKE_RSA_DP2_3072}, {LAC_4096_BITS, PKE_RSA_DP2_4096}, {LAC_8192_BITS, PKE_RSA_DP2_8192}}; /**< * Maps between operation sizes and PKE function ids */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* * This function checks the parameters for an RSA decrypt operation. It returns * the appropriate error in the case of null and invalid params and also * unsupported operations. */ #ifdef ICP_PARAM_CHECK STATIC CpaStatus LacRsa_DecryptParamsCheck(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData); #endif /* * This function is called by the pke comms module after an RSA Encrypt * message has been received from the QAT. */ STATIC void LacRsa_ProcessDecCb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData); /* * This function performs RSA Decrypt for type 1 private keys. */ STATIC CpaStatus LacRsa_Type1Decrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData); /* * This function performs RSA Decrypt for type 2 private keys. */ STATIC CpaStatus LacRsa_Type2Decrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData); /* * This is the LAC RSA Decrypt synchronous function. */ STATIC CpaStatus LacRsa_DecryptSynch(const CpaInstanceHandle instanceHandle, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData); STATIC CpaStatus LacRsa_Decrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, rsa); /* Check if the API has been called in sync mode */ if (NULL == pRsaDecryptCb) { return LacRsa_DecryptSynch(instanceHandle, pDecryptData, pOutputData); } #ifdef ICP_PARAM_CHECK /* Check RSA Decrypt params and return an error if invalid */ status = LacRsa_DecryptParamsCheck(instanceHandle, pRsaDecryptCb, pDecryptData, pOutputData); #endif if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 == pDecryptData->pRecipientPrivateKey->privateKeyRepType) { status = LacRsa_Type1Decrypt(instanceHandle, pRsaDecryptCb, pCallbackTag, pDecryptData, pOutputData); } else /* Must be type2 key as param check has passed */ { status = LacRsa_Type2Decrypt(instanceHandle, pRsaDecryptCb, pCallbackTag, pDecryptData, pOutputData); } } /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_RSA_STAT_INC(numRsaDecryptRequests, instanceHandle); } else { LAC_RSA_STAT_INC(numRsaDecryptRequestErrors, instanceHandle); } return status; } /** ***************************************************************************** * @ingroup LacRsa * *****************************************************************************/ CpaStatus cpaCyRsaDecrypt(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pRsaDecryptCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pDecryptData, (LAC_ARCH_UINT)pOutputData); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); #endif status = LacRsa_Decrypt(instanceHandle, pRsaDecryptCb, pCallbackTag, pDecryptData, pOutputData); return status; } CpaStatus cpaCyRsaDpaDecrypt(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptData, const CpaCyRsaDpaOpData *pDpaOpData, CpaFlatBuffer *pOutputData) { return CPA_STATUS_UNSUPPORTED; } STATIC CpaStatus LacRsa_DecryptSynch(const CpaInstanceHandle instanceHandle, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = LacRsa_Decrypt(instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, pDecryptData, pOutputData); } else { LAC_RSA_STAT_INC(numRsaDecryptRequestErrors, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { /* * Inc stats only if the wait for callback failed. */ LAC_RSA_STAT_INC(numRsaDecryptCompletedErrors, instanceHandle); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #ifdef ICP_PARAM_CHECK STATIC CpaStatus LacRsa_DecryptParamsCheck(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U opSizeInBytes = 0; LAC_CHECK_NULL_PARAM(pRsaDecryptCb); /* Check user parameters */ LAC_CHECK_NULL_PARAM(pDecryptData); /* Check the Private Key is correct version, type and for NULL params */ status = LacRsa_CheckPrivateKeyParam(pDecryptData->pRecipientPrivateKey); LAC_CHECK_STATUS(status); /* Get the opSize */ opSizeInBytes = LacRsa_GetPrivateKeyOpSize(pDecryptData->pRecipientPrivateKey); if (CPA_FALSE == LacRsa_IsValidRsaSize(opSizeInBytes)) { LAC_INVALID_PARAM_LOG( "Invalid Private Key Size - pDecryptData->pRecipientPrivateKey"); return CPA_STATUS_INVALID_PARAM; } /* Check message and ciphertext buffers */ LAC_CHECK_FLAT_BUFFER_PARAM_PKE(&(pDecryptData->inputData), CHECK_LESS_EQUALS, opSizeInBytes, CPA_FALSE); LAC_CHECK_FLAT_BUFFER_PARAM( pOutputData, CHECK_GREATER_EQUALS, opSizeInBytes); if (CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 == pDecryptData->pRecipientPrivateKey->privateKeyRepType) { /* Check MSB and LSB of the modulus */ LAC_CHECK_RSA_BUFFER_MSB_LSB( &(pDecryptData->pRecipientPrivateKey->privateKeyRep1.modulusN), opSizeInBytes, CPA_TRUE, CPA_TRUE); /* Standards based check: 0 < inputData < n */ LAC_CHECK_NON_ZERO_PARAM(&(pDecryptData->inputData)); if (LacPke_Compare( &(pDecryptData->inputData), 0, &(pDecryptData->pRecipientPrivateKey->privateKeyRep1.modulusN), 0) >= 0) { LAC_INVALID_PARAM_LOG("inputData must be < modulusN"); return CPA_STATUS_INVALID_PARAM; } } else { /* Check MSB and LSB of the modulus */ LAC_CHECK_FLAT_BUFFER_MSB_LSB( &(pDecryptData->pRecipientPrivateKey->privateKeyRep2.prime1P), (opSizeInBytes >> 1), CPA_TRUE, CPA_TRUE); LAC_CHECK_FLAT_BUFFER_MSB_LSB( &(pDecryptData->pRecipientPrivateKey->privateKeyRep2.prime2Q), (opSizeInBytes >> 1), CPA_TRUE, CPA_TRUE); status = LacRsa_Type2StdsCheck( &(pDecryptData->pRecipientPrivateKey->privateKeyRep2)); LAC_CHECK_STATUS(status); } return status; } #endif CpaStatus LacRsa_Type1Decrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData) { Cpa32U opSizeInBytes = 0; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; LAC_ASSERT_NOT_NULL(pDecryptData); LAC_ASSERT_NOT_NULL(pOutputData); opSizeInBytes = LacRsa_GetPrivateKeyOpSize(pDecryptData->pRecipientPrivateKey); functionalityId = LacPke_GetMmpId(LAC_BYTES_TO_BITS(opSizeInBytes), lacRsaDp1SizeIdMap, LAC_ARRAY_LEN(lacRsaDp1SizeIdMap)); if (LAC_PKE_INVALID_FUNC_ID == functionalityId) { LAC_INVALID_PARAM_LOG("Invalid Private Key Size - " "pDecryptData->pRecipientPrivateKey\n"); return CPA_STATUS_INVALID_PARAM; } /* Zero ms bytes of output buffer */ osalMemSet( pOutputData->pData, 0, (pOutputData->dataLenInBytes - opSizeInBytes)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_dp1_1024.c, &(pDecryptData->inputData)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_input_t, c)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_input_t, c)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_dp1_1024.d, &(pDecryptData->pRecipientPrivateKey->privateKeyRep1.privateExponentD)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_input_t, d)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_input_t, d)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_dp1_1024.n, &(pDecryptData->pRecipientPrivateKey->privateKeyRep1.modulusN)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_input_t, n)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_input_t, n)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_rsa_dp1_1024.m, pOutputData); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_output_t, m)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_output_t, m)] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pRsaDecryptCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pDecryptData; cbData.pOutputData1 = pOutputData; /* send a PKE request to the QAT */ return LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &in, &out, internalMemInList, internalMemOutList, LacRsa_ProcessDecCb, &cbData, instanceHandle); } CpaStatus LacRsa_Type2Decrypt(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaDecryptCb, void *pCallbackTag, const CpaCyRsaDecryptOpData *pDecryptData, CpaFlatBuffer *pOutputData) { Cpa32U opSizeInBytes = 0; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; CpaStatus status = CPA_STATUS_FAIL; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; LAC_ASSERT_NOT_NULL(pDecryptData); LAC_ASSERT_NOT_NULL(pOutputData); opSizeInBytes = LacRsa_GetPrivateKeyOpSize(pDecryptData->pRecipientPrivateKey); functionalityId = LacPke_GetMmpId(LAC_BYTES_TO_BITS(opSizeInBytes), lacRsaDp2SizeIdMap, LAC_ARRAY_LEN(lacRsaDp2SizeIdMap)); if (LAC_PKE_INVALID_FUNC_ID == functionalityId) { LAC_INVALID_PARAM_LOG( "Invalid Private Key Size - pDecryptData->pRecipientPrivateKey"); return CPA_STATUS_INVALID_PARAM; } /* Zero ms bytes of output buffer */ osalMemSet( pOutputData->pData, 0, (pOutputData->dataLenInBytes - opSizeInBytes)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_dp2_1024.c, &(pDecryptData->inputData)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, c)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, c)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_dp2_1024.p, &(pDecryptData->pRecipientPrivateKey->privateKeyRep2.prime1P)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, p)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_dp2_1024.q, &(pDecryptData->pRecipientPrivateKey->privateKeyRep2.prime2Q)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, q)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_dp2_1024.dp, &(pDecryptData->pRecipientPrivateKey->privateKeyRep2.exponent1Dp)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, dp)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, dp)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_dp2_1024.dq, &(pDecryptData->pRecipientPrivateKey->privateKeyRep2.exponent2Dq)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, dq)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, dq)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_dp2_1024.qinv, &(pDecryptData->pRecipientPrivateKey->privateKeyRep2.coefficientQInv)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, qinv)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_input_t, qinv)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_rsa_dp2_1024.m, pOutputData); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_output_t, m)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_output_t, m)] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pRsaDecryptCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pDecryptData; cbData.pOutputData1 = pOutputData; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &in, &out, internalMemInList, internalMemOutList, LacRsa_ProcessDecCb, &cbData, instanceHandle); return status; } void LacRsa_ProcessDecCb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyRsaDecryptOpData *pOpData = NULL; CpaFlatBuffer *pOutputData = NULL; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = (void *)pCbData->pCallbackTag; pOpData = (CpaCyRsaDecryptOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); LAC_ASSERT_NOT_NULL(pOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); LAC_ASSERT_NOT_NULL(pCb); pOutputData = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pOutputData); /* increment stats */ LAC_RSA_STAT_INC(numRsaDecryptCompleted, instanceHandle); if (CPA_STATUS_SUCCESS != status) { LAC_RSA_STAT_INC(numRsaDecryptCompletedErrors, instanceHandle); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pOutputData); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_encrypt.c000066400000000000000000000401731503624047500326000ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * @file lac_rsa_encrypt.c * * @ingroup LacRsa * * This file implements encrypt functions for RSA. * *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ /* Include API files */ #include "cpa.h" #include "cpa_cy_rsa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Osal include */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp_ids.h" /* Include LAC files */ #include "lac_common.h" #include "lac_pke_qat_comms.h" #include "lac_pke_utils.h" #include "lac_pke_mmp.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "lac_rsa_p.h" #include "lac_rsa_stats_p.h" /* ******************************************************************************** * Static Variables ******************************************************************************** */ static const Cpa32U lacRsaEncSizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_512_BITS, PKE_RSA_EP_512}, {LAC_1024_BITS, PKE_RSA_EP_1024}, {LAC_1536_BITS, PKE_RSA_EP_1536}, {LAC_2048_BITS, PKE_RSA_EP_2048}, {LAC_3072_BITS, PKE_RSA_EP_3072}, {LAC_4096_BITS, PKE_RSA_EP_4096}, {LAC_8192_BITS, PKE_RSA_EP_8192}}; /**< * Maps between operation sizes and PKE function ids */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* * This function performs synchronous version of the RSA Encrypt. */ STATIC CpaStatus LacRsa_EncryptSynch(const CpaInstanceHandle instanceHandle, const CpaCyRsaEncryptOpData *pEncryptData, CpaFlatBuffer *pOutputData); /* * Based on the bit length of the modulus this function sets opSizeInBytes * used to select the correct MMP service. * This function also checks the parameters for an RSA encrypt operation. It * returns the appropriate error in the case of null and invalid params and also * unsupported operations. */ STATIC CpaStatus LacRsa_EncGetOpSizeAndCheck(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaEncryptCb, const CpaCyRsaEncryptOpData *pEncryptData, CpaFlatBuffer *pOutputData, Cpa32U *pOpSizeInBytes); /* * This function is called by the pke comms module after an RSA Encrypt * message has been received from the QAT. */ STATIC void LacRsa_ProcessEncCb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData); /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ /** ***************************************************************************** * @ingroup LacRsa * *****************************************************************************/ CpaStatus cpaCyRsaEncrypt(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pRsaEncryptCb, void *pCallbackTag, const CpaCyRsaEncryptOpData *pEncryptData, CpaFlatBuffer *pOutputData) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; lac_pke_op_cb_data_t cbData = {0}; Cpa32U opSizeInBytes = 0; Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pRsaEncryptCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pEncryptData, (LAC_ARCH_UINT)pOutputData); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, rsa); /* Check if the API has been called in sync mode */ if (NULL == pRsaEncryptCb) { return LacRsa_EncryptSynch(instanceHandle, pEncryptData, pOutputData); } /* Get the opSize and check RSA Encrypt params and return an error if invalid */ status = LacRsa_EncGetOpSizeAndCheck(instanceHandle, pRsaEncryptCb, pEncryptData, pOutputData, &opSizeInBytes); if (CPA_STATUS_SUCCESS == status) { functionalityId = LacPke_GetMmpId(opSizeInBytes * LAC_NUM_BITS_IN_BYTE, lacRsaEncSizeIdMap, LAC_ARRAY_LEN(lacRsaEncSizeIdMap)); if (LAC_PKE_INVALID_FUNC_ID == functionalityId) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /* Zero ms bytes of output buffer (Note: verified in LacRsa_EncGetOpSizeAndCheck() that buffer size >= opSizeInBytes) */ osalMemSet(pOutputData->pData, 0, (pOutputData->dataLenInBytes - opSizeInBytes)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_ep_1024.m, &(pEncryptData->inputData)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_input_t, m)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_input_t, m)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( in.mmp_rsa_ep_1024.e, &(pEncryptData->pPublicKey->publicExponentE)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_input_t, e)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_input_t, e)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_ep_1024.n, &(pEncryptData->pPublicKey->modulusN)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_input_t, n)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_input_t, n)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_rsa_ep_1024.c, pOutputData); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_output_t, c)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_output_t, c)] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pRsaEncryptCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pEncryptData; cbData.pOutputData1 = pOutputData; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &in, &out, internalMemInList, internalMemOutList, (lac_pke_op_cb_func_t)LacRsa_ProcessEncCb, &cbData, instanceHandle); } /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_RSA_STAT_INC(numRsaEncryptRequests, instanceHandle); } else { LAC_RSA_STAT_INC(numRsaEncryptRequestErrors, instanceHandle); } return status; } STATIC CpaStatus LacRsa_EncryptSynch(const CpaInstanceHandle instanceHandle, const CpaCyRsaEncryptOpData *pEncryptData, CpaFlatBuffer *pOutputData) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyRsaEncrypt(instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, pEncryptData, pOutputData); } else { LAC_RSA_STAT_INC(numRsaEncryptRequestErrors, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { /* * Inc stats only if the wait for callback failed. */ LAC_RSA_STAT_INC(numRsaEncryptCompletedErrors, instanceHandle); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } CpaStatus LacRsa_EncGetOpSizeAndCheck(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pRsaEncryptCb, const CpaCyRsaEncryptOpData *pEncryptData, CpaFlatBuffer *pOutputData, Cpa32U *pOpSizeInBytes) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pRsaEncryptCb); /* Check user parameters */ LAC_CHECK_NULL_PARAM(pEncryptData); LAC_CHECK_NULL_PARAM(pEncryptData->pPublicKey); LAC_CHECK_NULL_PARAM(pOutputData); LAC_CHECK_FLAT_BUFFER(&pEncryptData->pPublicKey->modulusN); #endif /* Check sizes. Operation size is the public key modulus length. * Message and cipher buffers must be able to accommodate messages of * this length */ *pOpSizeInBytes = LacPke_GetMinBytes(&(pEncryptData->pPublicKey->modulusN)); #ifdef ICP_PARAM_CHECK if (CPA_FALSE == LacRsa_IsValidRsaSize((*pOpSizeInBytes))) { LAC_INVALID_PARAM_LOG("Invalid data length for pPublicKey->modulusN"); return CPA_STATUS_INVALID_PARAM; } LAC_CHECK_RSA_BUFFER_MSB_LSB(&(pEncryptData->pPublicKey->modulusN), (*pOpSizeInBytes), CPA_TRUE, CPA_TRUE); LAC_CHECK_FLAT_BUFFER_PARAM_PKE( &(pEncryptData->pPublicKey->publicExponentE), CHECK_LESS_EQUALS, (*pOpSizeInBytes), CPA_TRUE); /* Check message and ciphertext buffers */ LAC_CHECK_FLAT_BUFFER_PARAM_PKE(&(pEncryptData->inputData), CHECK_LESS_EQUALS, (*pOpSizeInBytes), CPA_FALSE); LAC_CHECK_FLAT_BUFFER_PARAM( pOutputData, CHECK_GREATER_EQUALS, (*pOpSizeInBytes)); /* Standards based check: 0 < m < n */ LAC_CHECK_NON_ZERO_PARAM(&(pEncryptData->inputData)); if (LacPke_Compare(&(pEncryptData->inputData), 0, &(pEncryptData->pPublicKey->modulusN), 0) >= 0) { LAC_INVALID_PARAM_LOG("inputData must be < modulusN"); return CPA_STATUS_INVALID_PARAM; } /* Note PKE will check e is within range */ #endif return status; } void LacRsa_ProcessEncCb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyGenFlatBufCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyRsaEncryptOpData *pOpData = NULL; CpaFlatBuffer *pOutputData = NULL; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyRsaEncryptOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); LAC_ASSERT_NOT_NULL(pOpData); pCb = (CpaCyGenFlatBufCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); LAC_ASSERT_NOT_NULL(pCb); pOutputData = pCbData->pOutputData1; LAC_ASSERT_NOT_NULL(pOutputData); /* increment stats */ LAC_RSA_STAT_INC(numRsaEncryptCompleted, instanceHandle); if (CPA_STATUS_SUCCESS != status) { LAC_RSA_STAT_INC(numRsaEncryptCompletedErrors, instanceHandle); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pOutputData); } lac_rsa_interface_check.c000066400000000000000000000621371503624047500341360ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** *************************************************************************** * @file lac_rsa_interface_check.c * * @ingroup Lac_Rsa * * This file checks at compile time that the IA/FW interface is as expected * For example, in lac_rsa_keygen.c we use the fact that the index of p in the * structure icp_qat_fw_mmp_rsa_kp1_1024_input_t is equal to the index of * p in the structure icp_qat_fw_mmp_rsa_kp1_2048_input_t. If this * assumption becomes invalid (FW interface changes to break the assumption * or the compiler moves things around) this file will fail to compile. * * Note for structures with only 1 member no check is required. * ***************************************************************************/ #include "cpa.h" #include "icp_qat_fw_pke.h" #include "icp_qat_fw_mmp.h" #include "lac_common.h" #define COMPILE_TIME_ASSERT(pred) \ switch (0) \ { \ case 0: \ case pred:; \ } void LacRsa_CompileTimeAssertions(void) { /* ************************************************************* * KEY GEN TYPE 1 Checks * ************************************************************* */ /* Check that icp_qat_fw_mmp_rsa_kp1_512_input_t, icp_qat_fw_mmp_rsa_kp1_1024_input_t, icp_qat_fw_mmp_rsa_kp1_1536_input_t, icp_qat_fw_mmp_rsa_kp1_2048_input_t, icp_qat_fw_mmp_rsa_kp1_3072_input_t, icp_qat_fw_mmp_rsa_kp1_4096_input_t structures are equivalent */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_512_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_512_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_512_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1536_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1536_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1536_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_2048_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_2048_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_2048_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_3072_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_3072_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_3072_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_4096_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_4096_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_4096_input_t, e)); /* Check outputs */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_512_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_512_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1536_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1536_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_2048_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_2048_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_3072_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_3072_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_4096_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_4096_output_t, d)); /* ************************************************************* * KEY GEN TYPE 2 Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_input_t, e)) /* Check outputs */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_output_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_output_t, dq)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_512_output_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_output_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_output_t, dq)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1536_output_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_output_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_output_t, dq)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_2048_output_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_output_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_output_t, dq)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_3072_output_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_output_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_output_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_output_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_output_t, dq)); COMPILE_TIME_ASSERT( LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_1024_output_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_4096_output_t, qinv)); /* ************************************************************* * ENCRYPT Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_512_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_512_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_512_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1536_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1536_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1536_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_2048_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_2048_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_2048_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_3072_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_3072_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_3072_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_4096_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_4096_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_4096_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, m) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_8192_input_t, m)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, e) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_8192_input_t, e)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_ep_8192_input_t, n)); /* ************************************************************* * DECRYPT TYPE 1 Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_512_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_512_input_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_512_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1536_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1536_input_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1536_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_2048_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_2048_input_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_2048_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_3072_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_3072_input_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_3072_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_4096_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_4096_input_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_4096_input_t, n)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_8192_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, d) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_8192_input_t, d)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_1024_input_t, n) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp1_8192_input_t, n)); /* ************************************************************* * DECRYPT TYPE 2 Checks * ************************************************************* */ COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_512_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_512_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_512_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_512_input_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_512_input_t, dq)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_512_input_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1536_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1536_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1536_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1536_input_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1536_input_t, dq)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1536_input_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_2048_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_2048_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_2048_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_2048_input_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_2048_input_t, dq)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_2048_input_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_3072_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_3072_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_3072_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_3072_input_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_3072_input_t, dq)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_3072_input_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_4096_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_4096_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_4096_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_4096_input_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_4096_input_t, dq)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_4096_input_t, qinv)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, c) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_8192_input_t, c)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, p) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_8192_input_t, p)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, q) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_8192_input_t, q)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dp) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_8192_input_t, dp)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, dq) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_8192_input_t, dq)); COMPILE_TIME_ASSERT(LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_1024_input_t, qinv) == LAC_IDX_OF(icp_qat_fw_mmp_rsa_dp2_8192_input_t, qinv)); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_keygen.c000066400000000000000000000751611503624047500324030ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ***************************************************************************** * @file lac_rsa_keygen.c * * @ingroup LacRsa * * This file implements keygen functions for RSA. * *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ /* Include API files */ #include "cpa.h" #include "cpa_cy_rsa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Osal include */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp_ids.h" /* Include LAC files */ #include "lac_common.h" #include "lac_pke_qat_comms.h" #include "lac_pke_utils.h" #include "lac_pke_mmp.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "lac_rsa_p.h" #include "lac_rsa_stats_p.h" /* ******************************************************************************** * Static Variables ******************************************************************************** */ #define LAC_RSA_KEYGEN_MIN_EXP -3 /**< * Exponenent for key gen ops must be >= 3 */ static const Cpa32U lacRsaKp1SizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_512_BITS, PKE_RSA_KP1_512}, {LAC_1024_BITS, PKE_RSA_KP1_1024}, {LAC_1536_BITS, PKE_RSA_KP1_1536}, {LAC_2048_BITS, PKE_RSA_KP1_2048}, {LAC_3072_BITS, PKE_RSA_KP1_3072}, {LAC_4096_BITS, PKE_RSA_KP1_4096}}; /**< * Maps between operation sizes and PKE function ids */ static const Cpa32U lacRsaKp2SizeIdMap[][LAC_PKE_NUM_COLUMNS] = { {LAC_512_BITS, PKE_RSA_KP2_512}, {LAC_1024_BITS, PKE_RSA_KP2_1024}, {LAC_1536_BITS, PKE_RSA_KP2_1536}, {LAC_2048_BITS, PKE_RSA_KP2_2048}, {LAC_3072_BITS, PKE_RSA_KP2_3072}, {LAC_4096_BITS, PKE_RSA_KP2_4096}}; /**< * Maps between operation sizes and PKE function ids */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* * This function performs synchronous version of the RSA Key Gen. */ STATIC CpaStatus LacRsa_KeyGenSync(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey); /* * This function is the synchronous callback function. */ STATIC void LacRsa_KeyGenSyncCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey); /* * This function checks the parameters for an RSA encrypt operation. It returns * the appropriate error in the case of null and invalid params and also * unsupported operations. */ #ifdef ICP_PARAM_CHECK STATIC CpaStatus LacRsa_KeyGenParamsCheck(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey); #endif /* * This function is called by the pke comms module after an RSA Encrypt * message has been received from the QAT. */ STATIC void LacRsa_ProcessKeyCb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData); /* * This function performs RSA Decrypt for type 1 private keys. */ STATIC CpaStatus LacRsa_Type1KeyGen(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, void *pCallbackTag, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey); /* * This function performs RSA Decrypt for type 2 private keys. */ STATIC CpaStatus LacRsa_Type2KeyGen(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, void *pCallbackTag, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey); /* ******************************************************************************** * Global Variables ******************************************************************************** */ /* ******************************************************************************** * Define static function definitions ******************************************************************************** */ /* ******************************************************************************** * Define public/global function definitions ******************************************************************************** */ /** ***************************************************************************** * @ingroup LacRsa * *****************************************************************************/ CpaStatus cpaCyRsaGenKey(const CpaInstanceHandle instanceHandle_in, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, void *pCallbackTag, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pRsaKeyGenCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pKeyGenData, (LAC_ARCH_UINT)pPrivateKey, (LAC_ARCH_UINT)pPublicKey); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); #endif SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, rsa); /* Check if the API has been called in sync mode */ if (NULL == pRsaKeyGenCb) { return LacRsa_KeyGenSync( instanceHandle, pKeyGenData, pPrivateKey, pPublicKey); } #ifdef ICP_PARAM_CHECK /* Check RSA KeyGen params and return an error if invalid */ status = LacRsa_KeyGenParamsCheck( instanceHandle, pRsaKeyGenCb, pKeyGenData, pPrivateKey, pPublicKey); #endif if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 == pKeyGenData->privateKeyRepType) { status = LacRsa_Type1KeyGen(instanceHandle, pRsaKeyGenCb, pCallbackTag, pKeyGenData, pPrivateKey, pPublicKey); } else /* Must be type2 key as param check has passed */ { status = LacRsa_Type2KeyGen(instanceHandle, pRsaKeyGenCb, pCallbackTag, pKeyGenData, pPrivateKey, pPublicKey); } } /* increment stats */ if (CPA_STATUS_SUCCESS == status) { LAC_RSA_STAT_INC(numRsaKeyGenRequests, instanceHandle); } else { LAC_RSA_STAT_INC(numRsaKeyGenRequestErrors, instanceHandle); } return status; } STATIC void LacRsa_KeyGenSyncCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey) { LacSync_GenWakeupSyncCaller(pCallbackTag, status); } STATIC CpaStatus LacRsa_KeyGenSync(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey) { CpaStatus status = CPA_STATUS_FAIL; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); /* * Call the async version of the function * with the sync callback function as a parameter. */ if (CPA_STATUS_SUCCESS == status) { status = cpaCyRsaGenKey(instanceHandle, LacRsa_KeyGenSyncCb, pSyncCallbackData, pKeyGenData, pPrivateKey, pPublicKey); } else { LAC_RSA_STAT_INC(numRsaKeyGenRequestErrors, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus wCbStatus = CPA_STATUS_FAIL; wCbStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_PKE_SYNC_CALLBACK_TIMEOUT, &status, NULL); if (CPA_STATUS_SUCCESS != wCbStatus) { /* * Inc stats only if the wait for callback failed. */ LAC_RSA_STAT_INC(numRsaKeyGenCompletedErrors, instanceHandle); status = wCbStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #ifdef ICP_PARAM_CHECK CpaStatus LacRsa_KeyGenParamsCheck(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U opSizeInBytes = 0; Cpa32U byteLenP = 0; Cpa32U byteLenQ = 0; LAC_CHECK_NULL_PARAM(pRsaKeyGenCb); /* Check user parameters */ LAC_CHECK_NULL_PARAM(pKeyGenData); LAC_CHECK_NULL_PARAM(pPrivateKey); LAC_CHECK_NULL_PARAM(pPublicKey); LAC_CHECK_FLAT_BUFFER(&pKeyGenData->prime1P); LAC_CHECK_FLAT_BUFFER(&pKeyGenData->prime2Q); /* Get size in bytes based on MS byte - msb validated later */ byteLenP = LacPke_GetMinBytes(&(pKeyGenData->prime1P)); byteLenQ = LacPke_GetMinBytes(&(pKeyGenData->prime2Q)); if (byteLenP != byteLenQ) { LAC_INVALID_PARAM_LOG("Invalid (p,q) pair"); return CPA_STATUS_INVALID_PARAM; } /* opSize = byteLenP + byteLenQ */ opSizeInBytes = byteLenP << 1; if (pKeyGenData->modulusLenInBytes != opSizeInBytes) { LAC_INVALID_PARAM_LOG("Invalid (n,p,q) set"); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE == LacRsa_IsValidRsaSize(opSizeInBytes)) { LAC_INVALID_PARAM_LOG("Invalid pKeyGenData->modulusLenInBytes Size. "); return CPA_STATUS_INVALID_PARAM; } /* Complete check of p and q buffers - msb and lsb check */ LAC_CHECK_FLAT_BUFFER_MSB_LSB( &(pKeyGenData->prime1P), byteLenP, CPA_TRUE, CPA_TRUE); LAC_CHECK_FLAT_BUFFER_MSB_LSB( &(pKeyGenData->prime2Q), byteLenQ, CPA_TRUE, CPA_TRUE); if ((CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 != pKeyGenData->privateKeyRepType) && (CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2 != pKeyGenData->privateKeyRepType)) { LAC_INVALID_PARAM_LOG("Invalid pKeyGenData->privateKeyRepType. "); return CPA_STATUS_INVALID_PARAM; } /* Check input buffers */ LAC_CHECK_FLAT_BUFFER_PARAM_PKE(&(pKeyGenData->publicExponentE), CHECK_LESS_EQUALS, opSizeInBytes, CPA_TRUE); /* Check the output buffers - ensure they are valid and large enough */ /* Check public key */ LAC_CHECK_FLAT_BUFFER_PARAM( &(pPublicKey->modulusN), CHECK_GREATER_EQUALS, opSizeInBytes); /* Check private key */ if (CPA_CY_RSA_VERSION_TWO_PRIME != pPrivateKey->version) { LAC_INVALID_PARAM_LOG("Invalid pPrivateKey->version"); return CPA_STATUS_INVALID_PARAM; } if (pPrivateKey->privateKeyRepType != pKeyGenData->privateKeyRepType) { LAC_INVALID_PARAM_LOG("Invalid pPrivateKey->privateKeyRepType. "); return CPA_STATUS_INVALID_PARAM; } /* For both key representations modulusN and ExponentD are generated */ LAC_CHECK_FLAT_BUFFER_PARAM(&(pPrivateKey->privateKeyRep1.modulusN), CHECK_GREATER_EQUALS, opSizeInBytes); LAC_CHECK_FLAT_BUFFER_PARAM(&(pPrivateKey->privateKeyRep1.privateExponentD), CHECK_GREATER_EQUALS, opSizeInBytes); /* For type 2 key additional output buffers to check */ if (CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2 == pKeyGenData->privateKeyRepType) { /* For KeyGen we do not output P and Q so no need to check these buffers */ LAC_CHECK_FLAT_BUFFER_PARAM(&(pPrivateKey->privateKeyRep2.exponent1Dp), CHECK_GREATER_EQUALS, byteLenP); LAC_CHECK_FLAT_BUFFER_PARAM(&(pPrivateKey->privateKeyRep2.exponent2Dq), CHECK_GREATER_EQUALS, byteLenP); LAC_CHECK_FLAT_BUFFER_PARAM( &(pPrivateKey->privateKeyRep2.coefficientQInv), CHECK_GREATER_EQUALS, byteLenP); } /* Standards based check: e >= 3 */ if (LacPke_CompareZero(&(pKeyGenData->publicExponentE), LAC_RSA_KEYGEN_MIN_EXP) < 0) { LAC_INVALID_PARAM_LOG("publicExponentE must be >= 3"); return CPA_STATUS_INVALID_PARAM; } return status; } #endif CpaStatus LacRsa_Type1KeyGen(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, void *pCallbackTag, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey) { Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; Cpa32U opSizeInBytes = 0; CpaStatus status = CPA_STATUS_SUCCESS; lac_pke_op_cb_data_t cbData = {0}; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; LAC_ASSERT_NOT_NULL(pKeyGenData); LAC_CHECK_FLAT_BUFFER(&pKeyGenData->prime1P); LAC_CHECK_FLAT_BUFFER(&pKeyGenData->prime2Q); /* Get size in bytes based on MS byte */ opSizeInBytes = LacPke_GetMinBytes(&(pKeyGenData->prime1P)); /* Byte length of P and Q are equal therefore we can double */ opSizeInBytes = opSizeInBytes << 1; functionalityId = LacPke_GetMmpId(LAC_BYTES_TO_BITS(opSizeInBytes), lacRsaKp1SizeIdMap, LAC_ARRAY_LEN(lacRsaKp1SizeIdMap)); if (LAC_PKE_INVALID_FUNC_ID == functionalityId) { status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /* Zero ms bytes of output buffers */ osalMemSet(pPublicKey->modulusN.pData, 0, (pPublicKey->modulusN.dataLenInBytes - opSizeInBytes)); osalMemSet( pPrivateKey->privateKeyRep1.privateExponentD.pData, 0, (pPrivateKey->privateKeyRep1.privateExponentD.dataLenInBytes - opSizeInBytes)); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_kp1_1024.p, &(pKeyGenData->prime1P)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_input_t, p)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_kp1_1024.q, &(pKeyGenData->prime2Q)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_input_t, q)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_kp1_1024.e, &(pPublicKey->publicExponentE)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_input_t, e)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_input_t, e)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_rsa_kp1_1024.n, &(pPublicKey->modulusN)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_output_t, n)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_output_t, n)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( out.mmp_rsa_kp1_1024.d, &(pPrivateKey->privateKeyRep1.privateExponentD)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_output_t, d)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp1_output_t, d)] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pRsaKeyGenCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pKeyGenData; cbData.pOutputData1 = pPrivateKey; cbData.pOutputData2 = pPublicKey; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &in, &out, internalMemInList, internalMemOutList, LacRsa_ProcessKeyCb, &cbData, instanceHandle); /* @performance * the in and out structures are allocated on the stack. This forces # * the underlying function to allocate and copy. why not allocate * nicely aligned in and out structures ? (this is a general comment * for all functions)*/ } return status; } CpaStatus LacRsa_Type2KeyGen(const CpaInstanceHandle instanceHandle, const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, void *pCallbackTag, const CpaCyRsaKeyGenOpData *pKeyGenData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey) { Cpa32U functionalityId = LAC_PKE_INVALID_FUNC_ID; Cpa32U pInArgSizeList[LAC_MAX_MMP_INPUT_PARAMS] = {0}; Cpa32U pOutArgSizeList[LAC_MAX_MMP_OUTPUT_PARAMS] = {0}; CpaBoolean internalMemInList[LAC_MAX_MMP_INPUT_PARAMS] = {CPA_FALSE}; CpaBoolean internalMemOutList[LAC_MAX_MMP_OUTPUT_PARAMS] = {CPA_FALSE}; Cpa32U opSizeInBytes = 0; CpaStatus status = CPA_STATUS_SUCCESS; lac_pke_op_cb_data_t cbData = {0}; icp_qat_fw_mmp_input_param_t in = {.flat_array = {0}}; icp_qat_fw_mmp_output_param_t out = {.flat_array = {0}}; LAC_ASSERT_NOT_NULL(pKeyGenData); LAC_CHECK_FLAT_BUFFER(&pKeyGenData->prime1P); LAC_CHECK_FLAT_BUFFER(&pKeyGenData->prime2Q); /* Get size in bytes based on MSB */ opSizeInBytes = LacPke_GetMinBytes(&(pKeyGenData->prime1P)); /* Byte length of P and Q are equal therefore we can double */ opSizeInBytes = opSizeInBytes << 1; functionalityId = LacPke_GetMmpId(LAC_BYTES_TO_BITS(opSizeInBytes), lacRsaKp2SizeIdMap, LAC_ARRAY_LEN(lacRsaKp2SizeIdMap)); if (LAC_PKE_INVALID_FUNC_ID == functionalityId) { status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /* Zero ms bytes of output buffers */ osalMemSet(pPublicKey->modulusN.pData, 0, (pPublicKey->modulusN.dataLenInBytes - opSizeInBytes)); osalMemSet( pPrivateKey->privateKeyRep1.privateExponentD.pData, 0, (pPrivateKey->privateKeyRep1.privateExponentD.dataLenInBytes - opSizeInBytes)); osalMemSet(pPrivateKey->privateKeyRep2.exponent1Dp.pData, 0, (pPrivateKey->privateKeyRep2.exponent1Dp.dataLenInBytes - LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes))); osalMemSet(pPrivateKey->privateKeyRep2.exponent2Dq.pData, 0, (pPrivateKey->privateKeyRep2.exponent2Dq.dataLenInBytes - LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes))); osalMemSet(pPrivateKey->privateKeyRep2.coefficientQInv.pData, 0, (pPrivateKey->privateKeyRep2.coefficientQInv.dataLenInBytes - LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes))); /* populate input parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_kp2_1024.p, &(pKeyGenData->prime1P)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_input_t, p)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_input_t, p)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_kp2_1024.q, &(pKeyGenData->prime2Q)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_input_t, q)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_input_t, q)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR(in.mmp_rsa_kp2_1024.e, &(pPublicKey->publicExponentE)); pInArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_input_t, e)] = opSizeInBytes; internalMemInList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_input_t, e)] = CPA_FALSE; /* populate output parameters */ LAC_MEM_SHARED_WRITE_FROM_PTR(out.mmp_rsa_kp2_1024.n, &(pPublicKey->modulusN)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, n)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, n)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( out.mmp_rsa_kp2_1024.d, &(pPrivateKey->privateKeyRep1.privateExponentD)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, d)] = opSizeInBytes; internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, d)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( out.mmp_rsa_kp2_1024.dp, &(pPrivateKey->privateKeyRep2.exponent1Dp)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, dp)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, dp)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( out.mmp_rsa_kp2_1024.dq, &(pPrivateKey->privateKeyRep2.exponent2Dq)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, dq)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, dq)] = CPA_FALSE; LAC_MEM_SHARED_WRITE_FROM_PTR( out.mmp_rsa_kp2_1024.qinv, &(pPrivateKey->privateKeyRep2.coefficientQInv)); pOutArgSizeList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, qinv)] = LAC_RSA_TYPE_2_BUF_SIZE_GET(opSizeInBytes); internalMemOutList[LAC_IDX_OF(icp_qat_fw_mmp_rsa_kp2_output_t, qinv)] = CPA_FALSE; /* populate callback data */ cbData.pClientCb = pRsaKeyGenCb; cbData.pCallbackTag = pCallbackTag; cbData.pClientOpData = pKeyGenData; cbData.pOutputData1 = pPrivateKey; cbData.pOutputData2 = pPublicKey; /* send a PKE request to the QAT */ status = LacPke_SendSingleRequest(functionalityId, pInArgSizeList, pOutArgSizeList, &in, &out, internalMemInList, internalMemOutList, LacRsa_ProcessKeyCb, &cbData, instanceHandle); } return status; } void LacRsa_ProcessKeyCb(CpaStatus status, CpaBoolean pass, CpaInstanceHandle instanceHandle, lac_pke_op_cb_data_t *pCbData) { CpaCyRsaKeyGenCbFunc pCb = NULL; void *pCallbackTag = NULL; CpaCyRsaKeyGenOpData *pOpData = NULL; CpaCyRsaPrivateKey *pPrivateKey = NULL; CpaCyRsaPublicKey *pPublicKey = NULL; /* extract info from callback data structure */ LAC_ASSERT_NOT_NULL(pCbData); pCallbackTag = pCbData->pCallbackTag; pOpData = (CpaCyRsaKeyGenOpData *)LAC_CONST_PTR_CAST(pCbData->pClientOpData); LAC_ASSERT_NOT_NULL(pOpData); pCb = (CpaCyRsaKeyGenCbFunc)LAC_CONST_PTR_CAST(pCbData->pClientCb); pPrivateKey = (CpaCyRsaPrivateKey *)pCbData->pOutputData1; pPublicKey = (CpaCyRsaPublicKey *)pCbData->pOutputData2; LAC_ASSERT_NOT_NULL(pPrivateKey); LAC_ASSERT_NOT_NULL(pPublicKey); if (CPA_STATUS_SUCCESS == status) { if (CPA_FALSE == pass) { LAC_LOG_ERROR( "Cannot generate a valid RSA public key from provided " "e, p, and q input parameters"); status = CPA_STATUS_FAIL; } } /* Standards based checks on the public key */ if (CPA_STATUS_SUCCESS == status) { /* n must have one of the two most sig bits set and e < n */ if (!(pPublicKey->modulusN.pData[pPublicKey->modulusN.dataLenInBytes - pOpData->modulusLenInBytes] & 0xC0)) { LAC_LOG_ERROR("The number n = p * q is out of range or invalid"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (LacPke_Compare( &(pOpData->publicExponentE), 0, &(pPublicKey->modulusN), 0) >= 0) { LAC_INVALID_PARAM_LOG("(e,n) is not a valid RSA public key n <= e"); status = CPA_STATUS_FAIL; } } /* Private key - need to copy modulusN */ if (CPA_STATUS_SUCCESS == status) { memcpy(pPrivateKey->privateKeyRep1.modulusN.pData, pPublicKey->modulusN.pData, pPublicKey->modulusN.dataLenInBytes); } /* increment stats */ LAC_RSA_STAT_INC(numRsaKeyGenCompleted, instanceHandle); if (CPA_STATUS_SUCCESS != status) { LAC_RSA_STAT_INC(numRsaKeyGenCompletedErrors, instanceHandle); } /* invoke the user callback */ pCb(pCallbackTag, status, pOpData, pPrivateKey, pPublicKey); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_p.h000066400000000000000000000171731503624047500313640ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ /** ******************************************************************************* * @file lac_rsa_p.h * * @ingroup LacRsa * * This file defines private data for RSA operations. * * @note * RSA operations may be called in Asynchronous or Synchronous modes. * In Asynchronous mode the user supplies a Callback function to the API. * Control returns to the client after the message has been sent to the QAT and * the Callback gets invoked when the QAT completes the operation. There is NO * BLOCKING. This mode is preferred for maximum performance. * In Synchronous mode the client supplies no Callback function pointer (NULL) * and the point of execution is placed on a wait-queue internally, and this is * de-queued once the QAT completes the operation. Hence, Synchronous mode is * BLOCKING. So avoid using in an interrupt context. To achieve maximum * performance from the API Asynchronous mode is preferred. * ******************************************************************************/ /******************************************************************************/ #ifndef _LAC_RSA_P_H_ #define _LAC_RSA_P_H_ /* Calculate the buffer size for type 2 key buffers. This is half the operation * size */ #define LAC_RSA_TYPE_2_BUF_SIZE_GET(size) ((size) >> 1) /** ******************************************************************************* * @ingroup LacRsa * Checks msb/lsb of a number in a flatbuffer given the bytelen of * the number of RSA operations. * * @description * This macro optionally checks that the 2 MSBs and/or the LSB of a number * in a flat buffer (given the bytenLen of the number). * If any check fails an error is logged and the calling function is * returned out of with an error. * * @param[in] pBuffer pointer to the flat buffer to check * @param[in] lenInBytes the byte length of the number in the buffer * @param[in] checkMsb flag to indicate whether (true) or not (false) * to check that one of the 2 MSBs are set * @param[in] checkLsb flag to indicate whether (true) or not (false) * to check that the LSB is set * * @return CPA_STATUS_INVALID_PARAM LSB and/or MSB checks failed * @return void All checks passed ******************************************************************************/ #define LAC_CHECK_RSA_BUFFER_MSB_LSB(pBuffer, lenInBytes, checkMsb, checkLsb) \ do \ { \ if (checkMsb && \ !((pBuffer)->pData[(pBuffer)->dataLenInBytes - lenInBytes] & \ 0xC0)) \ { \ LAC_INVALID_PARAM_LOG( \ #pBuffer " must have one of the 2 most significant bits set"); \ return CPA_STATUS_INVALID_PARAM; \ } \ \ if (checkLsb && \ !((pBuffer)->pData[(pBuffer)->dataLenInBytes - 1] & 0x01)) \ { \ LAC_INVALID_PARAM_LOG(#pBuffer " doesn't have LSB set"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacRsa * This function checks that the given RSA size is valid * * @description * This function checks that the given RSA size is valid. Valid sizes * are 1024, 2048 and 4096 bits. * * @param[in] opSizeInBytes the length to be checked * * @retval CPA_TRUE * @retval CPA_FALSE ******************************************************************************/ CpaBoolean LacRsa_IsValidRsaSize(Cpa32U opSizeInBytes); /** ******************************************************************************* * @ingroup LacRsa * This function checks a given RSA private key for NULL params * * @description * This function checks that the given RSA private key is valid * * @param[in] pPrivateKey the private key to be checked * * @retval CPA_STATUS_SUCCESS * @retval CPA_STATUS_INVALID_PARAM ******************************************************************************/ CpaStatus LacRsa_CheckPrivateKeyParam(CpaCyRsaPrivateKey *pPrivateKey); /** ******************************************************************************* * @ingroup LacRsa * This function returns the size of the operation based on this private * key in bytes. * * @description * This function returns the size of the operation based on this private * key in bytes. This is the length of the modulus for type 1 keys and the * length of p + the length of q for the type 2 keys. * * @param[in] pPrivateKey the RSA private key - either type 1 or type 2 * * @retval the size of the operation based on this private key in bytes. ******************************************************************************/ Cpa32U LacRsa_GetPrivateKeyOpSize(const CpaCyRsaPrivateKey *pPrivateKey); /* * Performs standards based checks for type2 rsa keys */ CpaStatus LacRsa_Type2StdsCheck(CpaCyRsaPrivateKeyRep2 *pPrivateKeyRep2); /* * Performs compile time checks on RSA interface */ void LacRsa_CompileTimeAssertions(void); #endif /* _LAC_RSA_P_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_stats.c000066400000000000000000000223521503624047500322510ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * @file lac_rsa_stats.c * * @ingroup LacRsa * * @description This file implements functions for RSA stats. *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ /* Include API files */ #include "cpa.h" #include "cpa_cy_rsa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /* Osal include */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" #include "icp_qat_fw_mmp_ids.h" /* Include LAC files */ #include "lac_common.h" #include "lac_pke_qat_comms.h" #include "lac_pke_utils.h" #include "lac_pke_mmp.h" #include "lac_sym.h" #include "lac_list.h" #include "sal_service_state.h" #include "lac_sal_types_crypto.h" #include "lac_rsa_p.h" #include "sal_statistics.h" #include "lac_rsa_stats_p.h" /* Number of RSA statistics */ #define LAC_RSA_NUM_STATS (sizeof(CpaCyRsaStats64) / sizeof(Cpa64U)) CpaStatus LacRsa_StatsInit(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pCryptoService->pLacRsaStatsArr), LAC_RSA_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { LAC_OS_BZERO( LAC_CONST_VOLATILE_PTR_CAST(pCryptoService->pLacRsaStatsArr), LAC_RSA_NUM_STATS * sizeof(OsalAtomic)); } return status; } void LacRsa_StatsFree(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; if (NULL != pCryptoService->pLacRsaStatsArr) { LAC_OS_FREE(pCryptoService->pLacRsaStatsArr); } } void LacRsa_StatsReset(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; LAC_OS_BZERO(LAC_CONST_VOLATILE_PTR_CAST(pCryptoService->pLacRsaStatsArr), LAC_RSA_NUM_STATS * sizeof(OsalAtomic)); } /** ***************************************************************************** * @ingroup LacRsa * *****************************************************************************/ CpaStatus cpaCyRsaQueryStats(CpaInstanceHandle instanceHandle_in, struct _CpaCyRsaStats *pRsaStats) { Cpa32U i = 0; sal_crypto_service_t *pCryptoService; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pRsaStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_RUNNING_CHECK(instanceHandle); LAC_CHECK_NULL_PARAM(pRsaStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; for (i = 0; i < LAC_RSA_NUM_STATS; i++) { ((Cpa32U *)pRsaStats)[i] = (Cpa32U)osalAtomicGet(&pCryptoService->pLacRsaStatsArr[i]); } return CPA_STATUS_SUCCESS; } /* cpaCyRsaQueryStats */ /** ***************************************************************************** * @ingroup LacRsa * *****************************************************************************/ CpaStatus cpaCyRsaQueryStats64(CpaInstanceHandle instanceHandle_in, CpaCyRsaStats64 *pRsaStats) { Cpa32U i = 0; sal_crypto_service_t *pCryptoService; CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pRsaStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_RUNNING_CHECK(instanceHandle); LAC_CHECK_NULL_PARAM(pRsaStats); pCryptoService = (sal_crypto_service_t *)instanceHandle; for (i = 0; i < LAC_RSA_NUM_STATS; i++) { ((Cpa64U *)pRsaStats)[i] = osalAtomicGet(&pCryptoService->pLacRsaStatsArr[i]); } return CPA_STATUS_SUCCESS; } /* cpaCyRsaQueryStats64 */ #ifndef DISABLE_STATS void LacRsa_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pCryptoService; pCryptoService = (sal_crypto_service_t *)instanceHandle; if (CPA_TRUE == pCryptoService->generic_service_info.stats->bRsaStatsEnabled) { osalAtomicInc( &pCryptoService->pLacRsaStatsArr[offset / sizeof(Cpa64U)]); } } /* LacRsa_StatIncrement */ #endif /* DISABLE_STATS */ void LacRsa_StatsShow(CpaInstanceHandle instanceHandle) { CpaCyRsaStats64 rsaStats = {0}; (void)cpaCyRsaQueryStats64(instanceHandle, &rsaStats); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " RSA Stats " BORDER "\n" SEPARATOR); /*Perform Info*/ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " RSA Key Gen Requests: %16llu " BORDER "\n" BORDER " RSA Key Gen Request Errors %16llu " BORDER "\n" BORDER " RSA Key Gen Completed: %16llu " BORDER "\n" BORDER " RSA Key Gen Completed Errors: %16llu " BORDER "\n" SEPARATOR, rsaStats.numRsaKeyGenRequests, rsaStats.numRsaKeyGenRequestErrors, rsaStats.numRsaKeyGenCompleted, rsaStats.numRsaKeyGenCompletedErrors); /*Perform Info*/ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " RSA Encrypt Requests: %16llu " BORDER "\n" BORDER " RSA Encrypt Request Errors: %16llu " BORDER "\n" BORDER " RSA Encrypt Completed: %16llu " BORDER "\n" BORDER " RSA Encrypt Completed Errors: %16llu " BORDER "\n" SEPARATOR, rsaStats.numRsaEncryptRequests, rsaStats.numRsaEncryptRequestErrors, rsaStats.numRsaEncryptCompleted, rsaStats.numRsaEncryptCompletedErrors); /*Perform Info*/ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " RSA Decrypt Requests: %16llu " BORDER "\n" BORDER " RSA Decrypt Request Errors: %16llu " BORDER "\n" BORDER " RSA Decrypt Completed: %16llu " BORDER "\n" BORDER " RSA Decrypt Completed Errors: %16llu " BORDER "\n" SEPARATOR, rsaStats.numRsaDecryptRequests, rsaStats.numRsaDecryptRequestErrors, rsaStats.numRsaDecryptCompleted, rsaStats.numRsaDecryptCompletedErrors); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/asym/rsa/lac_rsa_stats_p.h000066400000000000000000000125371503624047500326010ustar00rootroot00000000000000/* * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** ******************************************************************************* * @file lac_rsa_stats_p.h * * @ingroup LacRsa * * @description * This file contains the definitions and prototypes for RSA * statistics. * * @lld_start * In the LAC API the stats fields are defined as Cpa32U but * OsalAtomic is the type that the atomic API supports. Therefore we * need to define a structure internally with the same fields as the API * stats structure, but each field must be of type OsalAtomic. * * - Incrementing Statistics:\n * Atomically increment the statistic on the internal stats structure. * * - Providing a copy of the stats back to the user:\n * Use atomicGet to read the atomic variable for each stat field in the * local internal stat structure. These values are saved in structure * (as defined by the LAC API) that the client will provide a pointer * to as a parameter. * * - Stats Show:\n * Use atomicGet to read the atomic variables for each field in the local * internal stat structure and print to the screen * * - Stats Array:\n * A macro is used to get the offset off the stat in the structure. This * offset is passed to a function which uses it to increment the stat * at that offset. * * @lld_end * ***************************************************************************/ /******************************************************************************/ #ifndef _LAC_RSA_STATS_P_H_ #define _LAC_RSA_STATS_P_H_ /** ******************************************************************************* * @ingroup LacRsa * increment an RSA statistic * * @description * Increment the statistics * * @param[in] statistic The field in the statistics structure to be * incremented * @param[in] instanceHandle instanceHandle * * @retval None * *****************************************************************************/ #ifndef DISABLE_STATS #define LAC_RSA_STAT_INC(statistic, instanceHandle) \ LacRsa_StatsInc(offsetof(CpaCyRsaStats64, statistic), instanceHandle) #else /* Stats disabled */ #define LAC_RSA_STAT_INC(statistic, instanceHandle) #endif /** ******************************************************************************* * @ingroup LacRsa * This function allocates and clears the Rsa statistics for * the given accel handle * @param[in] instanceHandle instanceHandle * @retval CPA_STATUS_SUCCESS initialization successful * @retval CPA_STATUS_RESOURCE allocation of stats array failed ******************************************************************************/ CpaStatus LacRsa_StatsInit(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacRsa * This function increments the given Rsa stat * * @param[in] offset offset of stat field in structure * @param[in] instanceHandle the instanceHandle whose statistics we are * dealing with * @retval None ******************************************************************************/ #ifndef DISABLE_STATS void LacRsa_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle); #endif /** ******************************************************************************* * @ingroup LacRsa * This function prints the stats to standard out. * @param[in] instanceHandle instanceHandle * @retval None ******************************************************************************/ void LacRsa_StatsShow(CpaInstanceHandle instanceHandle); #endif /* _LAC_RSA_STATS_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/kpt/000077500000000000000000000000001503624047500263175ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/kpt/provision/000077500000000000000000000000001503624047500303475ustar00rootroot00000000000000lac_kpt_provision.c000066400000000000000000000100241503624047500341560ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/kpt/provision/* * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** ***************************************************************************** * @file lac_kpt_provision.c * * @ingroup LacKptProvision * * This file implements KPT provision service APIs. * *****************************************************************************/ /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" #include "cpa_cy_kpt.h" /** *************************************************************************** * @ingroup LacKptProvision * Query KPT issue key certificate from QAT driver ***************************************************************************/ CpaStatus cpaCyKptQueryIssuingKeys(const CpaInstanceHandle instanceHandle, CpaFlatBuffer *pPublicX509IssueCert, CpaCyKptKeyManagementStatus *pKptStatus) { return CPA_STATUS_UNSUPPORTED; } /** *************************************************************************** * @ingroup LacKptProvision * Query KPT device credential from QAT device ***************************************************************************/ CpaStatus cpaCyKptQueryDeviceCredentials( const CpaInstanceHandle instanceHandle, CpaCyKptValidationKey *pDevCredential, CpaCyKptKeyManagementStatus *pKptStatus) { return CPA_STATUS_UNSUPPORTED; } /** *************************************************************************** * @ingroup LacKptProvision * Load KPT key into QAT device ***************************************************************************/ CpaStatus cpaCyKptLoadKey(CpaInstanceHandle instanceHandle, CpaCyKptLoadKey *pSWK, CpaCyKptHandle *keyHandle, CpaCyKptKeyManagementStatus *pKptStatus) { return CPA_STATUS_UNSUPPORTED; } /** *************************************************************************** * @ingroup LacKptProvision * Delete KPT key from QAT device ***************************************************************************/ CpaStatus cpaCyKptDeleteKey(CpaInstanceHandle instanceHandle, CpaCyKptHandle keyHandle, CpaCyKptKeyManagementStatus *pKptStatus) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/000077500000000000000000000000001503624047500263315ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/drbg/000077500000000000000000000000001503624047500272475ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/drbg/lac_sym_drbg_api.c000066400000000000000000000121231503624047500326700ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_sym_drbg_api.c * * @ingroup LacSym_Drbg * * @description * Implementation of the Deterministic Random Bit Generation API * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_drbg.h" /** * @ingroup cpaCyDrbg */ CpaStatus cpaCyDrbgSessionGetSize(const CpaInstanceHandle instanceHandle_in, const CpaCyDrbgSessionSetupData *pSetupData, Cpa32U *pSize) { return CPA_STATUS_UNSUPPORTED; } /** * @ingroup cpaCyDrbg */ CpaStatus cpaCyDrbgInitSession(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pGenCb, const CpaCyGenericCbFunc pReseedCb, const CpaCyDrbgSessionSetupData *pSetupData, CpaCyDrbgSessionHandle sessionHandle, Cpa32U *pSeedLen) { return CPA_STATUS_UNSUPPORTED; } /** * @ingroup cpaCyDrbg */ CpaStatus cpaCyDrbgGen(const CpaInstanceHandle instanceHandle_in, void *pCallbackTag, CpaCyDrbgGenOpData *pOpData, CpaFlatBuffer *pPseudoRandomBits) { return CPA_STATUS_UNSUPPORTED; } /** * @ingroup cpaCyDrbg */ CpaStatus cpaCyDrbgReseed(const CpaInstanceHandle instanceHandle_in, void *pCallbackTag, CpaCyDrbgReseedOpData *pOpData) { return CPA_STATUS_UNSUPPORTED; } /** * @ingroup cpaCyDrbg */ CpaStatus cpaCyDrbgRemoveSession(const CpaInstanceHandle instanceHandle_in, CpaCyDrbgSessionHandle sessionHandle) { return CPA_STATUS_UNSUPPORTED; } /** * @ingroup cpaCyDrbg */ CpaStatus cpaCyDrbgQueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCyDrbgStats64 *pStats) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/000077500000000000000000000000001503624047500277545ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_session.h000066400000000000000000001001471503624047500324320ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_session.h * * @defgroup LacSym_Session Session * * @ingroup LacSym * * Definition of symmetric session descriptor structure * * @lld_start * * @lld_overview * A session is required for each symmetric operation. The session descriptor * holds information about the session from when the session is initialised to * when the session is removed. The session descriptor is used in the * subsequent perform operations in the paths for both sending the request and * receiving the response. The session descriptor and any other state * information required for processing responses from the QAT are stored in an * internal cookie. A pointer to this cookie is stored in the opaque data * field of the QAT request. * * The user allocates the memory for the session using the size returned from * \ref cpaCySymSessionCtxGetSize(). Internally this memory is re-aligned on a * 64 byte boundary for use by the QAT engine. The aligned pointer is saved in * the first bytes (size of void *) of the session memory. This address * is then dereferenced in subsequent performs to get access to the session * descriptor. * * LAC Session Init\n The session descriptor is re-aligned and * populated. This includes populating the content descriptor which contains * the hardware setup for the QAT engine. The content descriptor is a read * only structure after session init and a pointer to it is sent to the QAT * for each perform operation. * * LAC Perform \n * The address for the session descriptor is got by dereferencing the first * bytes of the session memory (size of void *). For each successful * request put on the ring, the pendingCbCount for the session is incremented. * * LAC Callback \n * For each successful response the pendingCbCount for the session is * decremented. See \ref LacSymCb_ProcessCallbackInternal() * * LAC Session Remove \n * The address for the session descriptor is got by dereferencing the first * bytes of the session memory (size of void *). * The pendingCbCount for the session is checked to see if it is 0. If it is * non 0 then there are requests in flight. An error is returned to the user. * * Concurrency\n * A reference count is used to prevent the descriptor being removed * while there are requests in flight. * * Reference Count\n * - The perform function increments the reference count for the session. * - The callback function decrements the reference count for the session. * - The Remove function checks the reference count to ensure that it is 0. * * @lld_dependencies * - \ref LacMem "Memory" - Inline memory functions * - Osal: logging, locking & virt to phys translations. * * @lld_initialisation * * @lld_module_algorithms * * @lld_process_context * * @lld_end * *****************************************************************************/ /***************************************************************************/ #ifndef LAC_SYM_SESSION_H #define LAC_SYM_SESSION_H /* * Common alignment attributes to ensure * hashStatePrefixBuffer is 64-byte aligned */ #define ALIGN_START(x) #define ALIGN_END(x) __attribute__((__aligned__(x))) /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "Osal.h" #include "icp_accel_devices.h" #include "lac_list.h" #include "lac_sal_types.h" #include "sal_qat_cmn_msg.h" #include "lac_sym_cipher_defs.h" #include "lac_sym.h" #include "lac_sym_hash_defs.h" #include "lac_sym_qat_hash.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ /** ***************************************************************************** * @ingroup LacSym * Spc state * * @description * This enum is used to indicate the Spc state. * *****************************************************************************/ typedef enum lac_single_pass_state_e { SPC_NO, SPC_PROBABLE, SPC_YES } lac_single_pass_state_t; /** ******************************************************************************* * @ingroup LacSym_Session * Symmetric session descriptor * @description * This structure stores information about a session * Note: struct types lac_session_d1_s and lac_session_d2_s are subsets of * this structure. Elements in all three should retain the same order * Only this structure is used in the session init call. The other two are * for determining the size of memory to allocate. * The comments section of each of the other two structures below show * the conditions that determine which session context memory size to use. *****************************************************************************/ typedef struct lac_session_desc_s { Cpa8U contentDescriptor[LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE]; /**< QAT Content Descriptor for this session. * NOTE: Field must be correctly aligned in memory for access by QAT engine */ Cpa8U contentDescriptorOptimised[LAC_SYM_OPTIMISED_CD_SIZE]; /**< QAT Optimised Content Descriptor for this session. * NOTE: Field must be correctly aligned in memory for access by QAT engine */ CpaCySymOp symOperation; /**< type of command to be performed */ sal_qat_content_desc_info_t contentDescInfo; /**< info on the content descriptor */ sal_qat_content_desc_info_t contentDescOptimisedInfo; /**< info on the optimised content descriptor */ icp_qat_fw_la_cmd_id_t laCmdId; /**Block Vs. Stream Ciphers\n * Block ciphers are treated slightly differently than Stream ciphers by this * cipher component. Supported stream ciphers consist of AES and * TripleDES algorithms in CTR mode, and ARC4. The 2 primary differences are: * - Data buffers for block ciphers are required to be a multiple of the * block size defined for the algorithm (e.g. 8 bytes for DES). For stream * ciphers, there is no such restriction. * - For stream ciphers, decryption is performed by setting the QAT hardware * to encryption mode. * * Memory address alignment of data buffers \n * The QAT requires that most data buffers are aligned on an 8-byte memory * address boundary (64-byte boundary for optimum performance). For Cipher, * this applies to the cipher key buffer passed in the Content Descriptor, * and the IV/State buffer passed in the Request Parameters block in each * request. Both of these buffers are provided by the user. It does not * apply to the cipher source/destination data buffers. * Alignment of the key buffer is ensured because the key is always copied * from the user provided buffer into a new (aligned) buffer for the QAT * (the hardware setup block, which configures the QAT slice). This is done * once only during session registration, and the user's key buffer can be * effectively discarded after that. * The IV/State buffer is provided per-request by the user, so it is recommended * to the user to provide aligned buffers for optimal performance. In the case * where an unaligned buffer is provided, a new temporary buffer is allocated * and the user's IV/State data is copied into this buffer. The aligned buffer * is then passed to the QAT in the request. In the response callback, if the * IV was updated by the QAT, the contents are copied back to the user's buffer * and the temporary buffer is freed. * * @lld_process_context * * Session Register Sequence Diagram: For ARC4 cipher algorithm * \msc * APP [label="Application"], SYM [label="Symmetric LAC"], * Achain [label="Alg chain"], Cipher, SQAT [label="Symmetric QAT"]; * * APP=>SYM [ label = "cpaCySymInitSession(cbFunc)", * URL="\ref cpaCySymInitSession()"] ; * SYM=>SYM [ label = "LacSymSession_ParamCheck()", * URL="\ref LacSymSession_ParamCheck()"]; * SYM=>Achain [ label = "LacAlgChain_SessionInit()", * URL="\ref LacAlgChain_SessionInit()"]; * Achain=>Cipher [ label = "LacCipher_SessionSetupDataCheck()", * URL="\ref LacCipher_SessionSetupDataCheck()"]; * Achain<SQAT [ label = "LacSymQat_CipherContentDescPopulate()", * URL="\ref LacSymQat_CipherContentDescPopulate()"]; * Achain<SQAT [ label = "LacSymQat_CipherArc4StateInit()", * URL="\ref LacSymQat_CipherArc4StateInit()"]; * Achain<SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; * APP<SYM [ label = "cpaCySymPerformOp()", * URL="\ref cpaCySymPerformOp()"] ; * SYM=>SYM [ label = "LacSym_Perform()", * URL="\ref LacSym_Perform()"]; * SYM=>SYM [ label = "LacSymPerform_BufferParamCheck()", * URL="\ref LacSymPerform_BufferParamCheck()"]; * SYM<Achain [ label = "LacAlgChain_Perform()", * URL="\ref LacCipher()"]; * Achain=>Cipher [ label = "LacCipher_PerformParamCheck()", * URL="\ref LacCipher_PerformParamCheck()"]; * Achain<LMP [label="Lac_MemPoolEntryAlloc()", * URL="\ref Lac_MemPoolEntryAlloc()"]; * Achain<Cipher [ label = "LacCipher_PerformIvCheckAndAlign()", * URL="\ref LacCipher_PerformIvCheckAndAlign()"]; * Achain<SQAT [ label = "LacSymQat_CipherRequestParamsPopulate()", * URL="\ref LacSymQat_CipherRequestParamsPopulate()"]; * Achain<BUF [ label = "LacBuffDesc_BufferListDescWrite()", * URL = "\ref LacBuffDesc_BufferListDescWrite()"]; * Achain<SQAT [ label = "SalQatMsg_CmnMsgAndReqParamsPopulate()", * URL="\ref SalQatMsg_CmnMsgAndReqParamsPopulate()"]; * Achain<SYMQ [ label = "LacSymQueue_RequestSend()", * URL="\ref LacSymQueue_RequestSend()"]; * SYMQ=>QATCOMMS [ label = "QatComms_MsgSend()", * URL="\ref QatComms_MsgSend()"]; * SYMQ<SYM [ label = "LacSym_PartialPacketStateUpdate()", * URL="\ref LacSym_PartialPacketStateUpdate()"]; * SYM<SC [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; * SYM<QATCOMMS [label ="QatComms_ResponseMsgHandler()", * URL="\ref QatComms_ResponseMsgHandler()"]; * QATCOMMS=>SQAT [label ="LacSymQat_SymRespHandler()", * URL="\ref LacSymQat_SymRespHandler()"]; * SQAT=>SYMCB [label="LacSymCb_ProcessCallback()", * URL="\ref LacSymCb_ProcessCallback()"]; * SYMCB=>SYMCB [label="LacSymCb_ProcessCallbackInternal()", * URL="\ref LacSymCb_ProcessCallbackInternal()"]; * SYMCB=>LMP [label="Lac_MemPoolEntryFree()", * URL="\ref Lac_MemPoolEntryFree()"]; * SYMCB<SC [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; * SYMCB<APP [label="cbFunc"]; * SYMCB<a. HMAC Precomputes\n * HMAC algorithm is specified as follows: * \f$ HMAC(msg) = hash((key \oplus opad) \parallel * hash((key \oplus ipad) \parallel msg ))\f$. * The key is fixed per session, and is padded up to the block size of the * algorithm if necessary and xored with the ipad/opad. The following portion * of the operation can be precomputed: \f$ hash(key \oplus ipad) \f$ as the * output of this intermediate hash will be the same for every perform * operation. This intermediate state is the intermediate state of a partial * partial packet. It is used as the initialiser state to \f$ hash(msg) \f$. * The same applies to \f$ hash(key \oplus ipad) \f$. There is a saving in * the data path by the length of time it takes to do two hashes on a block * size of data. Note: a partial packet operation generates an intermediate * state. The final operation on a partial packet or when a full packet is * used applies padding and gives the final hash result. Essentially for the * inner hash, a partial packet final is issued on the data, using the * precomputed intermediate state and returns the digest. * * For the HMAC precomputes, \ref LacSymHash_HmacPreCompute(), there are two * hash operations done using a internal content descriptor to configure the * QAT. A first partial packet is specified as the packet type for the * pre-computes as we need the state that uses the initialiser constants * specific to the algorithm. The resulting output is copied from the hash * state prefix buffer into the QAT content descriptor for the session being * initialised. The state is used each perform operation as the initialiser * to the algorithm * * b. AES XCBC Precomputes\n * A similar technique to HMAC will be used to generate the precomputes for * AES XCBC. In this case a cipher operation will be used to generate the * precomputed result. The Pre-compute operation involves deriving 3 128-bit * keys (K1, K2 and K3) from the 128-bit secret key K. * * - K1 = 0x01010101010101010101010101010101 encrypted with Key K * - K2 = 0x02020202020202020202020202020202 encrypted with Key K * - K3 = 0x03030303030303030303030303030303 encrypted with Key K * * A content descriptor is created with the cipher algorithm set to AES * in ECB mode and with the keysize set to 128 bits. The 3 constants, 16 bytes * each, are copied into the src buffer and an in-place cipher operation is * performed on the 48 bytes. ECB mode does not maintain the state, therefore * the 3 keys can be encrypted in one perform. The encrypted result is used by * the state2 field in the hash setup block of the content descriptor. * * The precompute operations use a different lac command ID and thus have a * different route in the response path to the symmetric code. In this * precompute callback function the output of the precompute operation is * copied into the content descriptor for the session being registered. * * c. AES CCM Precomputes\n * The precomputes for AES CCM are trivial, i.e. there is no need to perform * a cipher or a digest operation. Instead, the key is stored directly in * the state2 field. * * d. AES GCM Precomputes\n * As with AES XCBC precomputes, a cipher operation will be used to generate * the precomputed result for AES GCM. In this case the Galois Hash * Multiplier (H) must be derived and stored in the state2 field. H is * derived by encrypting a 16-byte block of zeroes with the * cipher/authentication key, using AES in ECB mode. * * Key size for Auth algorithms\n * Min Size\n * RFC 2104 states "The key for HMAC can be of any length. However, less than * L bytes is strongly discouraged as it would decrease the security strength * of the function." * * FIPS 198a states "The size of the key, K, shall be equal to or greater than * L/2, where L is the size of the hash function output." * * RFC 4434 states "If the key has fewer than 128 bits, lengthen it to exactly * 128 bits by padding it on the right with zero bits. * * A key length of 0 upwards is accepted. It is up to the client to pass in a * key that complies with the standard they wish to support. * * Max Size\n * RFC 2104 section 2 states : "Applications that use keys longer than B bytes * will first hash the key using H and then use the resultant L byte string * as the actual key to HMAC * * RFC 4434 section 2 states: * "If the key is 129 bits or longer, shorten it to exactly 128 bits * by performing the steps in AES-XCBC-PRF-128 (that is, the * algorithm described in this document). In that re-application of * this algorithm, the key is 128 zero bits; the message is the * too-long current key." * * We push this up to the client. They need to do the hash operation through * the LAC API if the key is greater than the block size of the algorithm. This * will reduce the key size to the digest size of the algorithm. * * RFC 3566 section 4 states: * AES-XCBC-MAC-96 is a secret key algorithm. For use with either ESP or * AH a fixed key length of 128-bits MUST be supported. Key lengths * other than 128-bits MUST NOT be supported (i.e., only 128-bit keys are * to be used by AES-XCBC-MAC-96). * * In this case it is up to the client to provide a key that complies with * the standards. i.e. exactly 128 bits in size. * * * HMAC-MD5-96 and HMAC-SHA1-96\n * HMAC-MD5-96 and HMAC-SHA1-96 are defined as requirements by Look Aside * IPsec. The differences between HMAC-SHA1 and HMAC-SHA1-96 are that the * digest produced is truncated and there are strict requirements on the * size of the key that is used. * * They are supported in LAC by HMAC-MD5 and HMAC-SHA1. The field * \ref CpaCySymHashSetupData::digestResultLenInBytes in the LAC API in * bytes needs to be set to 12 bytes. There are also requirements regarding * the keysize. It is up to the client to ensure the key size meets the * requirements of the standards they are using. * * RFC 2403: HMAC-MD5-96 Key lengths other than 128-bits MUST NOT be supported. * HMAC-MD5-96 produces a 128-bit authenticator value. For use with either * ESP or AH, a truncated value using the first 96 bits MUST be supported. * * RFC2404: HMAC-SHA1-96 Key lengths other than 160- bits MUST NOT be supported * HMAC-SHA-1-96 produces a 160-bit authenticator value. For use with either * ESP or AH, a truncated value using the first 96 bits MUST be supported. * * Out of place operations * When verify is disabled, the digest will be written to the destination * buffer. When verify is enabled, the digest calculated is compared to the * digest stored in the source buffer. * * Partial Packets * Partial packets are handled in the \ref LacSym "Symmetric" component for * the request. The hash callback function handles the update of the state * in the callback. * * * @lld_process_context * * Session Register Sequence Diagram: For hash modes plain and nested. * \msc * APP [label="Application"], SYM [label="Symmetric LAC"], * Achain [label="Alg chain"], Hash, SQAT [label="Symmetric QAT"]; * * APP=>SYM [ label = "cpaCySymInitSession(cbFunc)", * URL="\ref cpaCySymInitSession()"] ; * SYM=>SYM [ label = "LacSymSession_ParamCheck()", * URL="\ref LacSymSession_ParamCheck()"]; * SYM=>Achain [ label = "LacAlgChain_SessionInit()", * URL="\ref LacAlgChain_SessionInit()"]; * Achain=>Hash [ label = "LacHash_HashContextCheck()", * URL="\ref LacHash_HashContextCheck()"]; * Achain<SQAT [ label = "LacSymQat_HashContentDescInit()", * URL="\ref LacSymQat_HashContentDescInit()"]; * Achain<Hash [ label = "LacHash_StatePrefixAadBufferInit()", * URL="\ref LacHash_StatePrefixAadBufferInit()"]; * Hash=>SQAT [ label = "LacSymQat_HashStatePrefixAadBufferSizeGet()", * URL="\ref LacSymQat_HashStatePrefixAadBufferSizeGet()"]; * Hash<SQAT [ label = "LacSymQat_HashStatePrefixAadBufferPopulate()", * URL="\ref LacSymQat_HashStatePrefixAadBufferPopulate()"]; * Hash<SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; * APP<SYM [ label = "cpaCySymPerformOp()", * URL="\ref cpaCySymPerformOp()"] ; * SYM=>SYM [ label = "LacSymPerform_BufferParamCheck()", * URL="\ref LacSymPerform_BufferParamCheck()"]; * SYM=>Achain [ label = "LacAlgChain_Perform()", * URL="\ref LacAlgChain_Perform()"]; * Achain=>Achain [ label = "Lac_MemPoolEntryAlloc()", * URL="\ref Lac_MemPoolEntryAlloc()"]; * Achain=>SQAT [ label = "LacSymQat_packetTypeGet()", * URL="\ref LacSymQat_packetTypeGet()"]; * Achain<Achain [ label = "LacBuffDesc_BufferListTotalSizeGet()", * URL="\ref LacBuffDesc_BufferListTotalSizeGet()"]; * Achain=>Hash [ label = "LacHash_PerformParamCheck()", * URL = "\ref LacHash_PerformParamCheck()"]; * Achain<SQAT [ label = "LacSymQat_HashRequestParamsPopulate()", * URL="\ref LacSymQat_HashRequestParamsPopulate()"]; * Achain<Achain [ label = "LacBuffDesc_BufferListDescWrite()", * URL="\ref LacBuffDesc_BufferListDescWrite()"]; * Achain=>SQAT [ label = "SalQatMsg_CmnMsgAndReqParamsPopulate()", * URL="\ref SalQatMsg_CmnMsgAndReqParamsPopulate()"]; * Achain<SYM [ label = "LacSymQueue_RequestSend()", * URL="\ref LacSymQueue_RequestSend()"]; * SYM=>QATCOMMS [ label = "QatComms_MsgSend()", * URL="\ref QatComms_MsgSend()"]; * SYM<SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; * APP<QATCOMMS [label ="QatComms_ResponseMsgHandler()", * URL="\ref QatComms_ResponseMsgHandler()"]; * QATCOMMS=>SQAT [label ="LacSymQat_SymRespHandler()", * URL="\ref LacSymQat_SymRespHandler()"]; * SQAT=>SYM [label="LacSymCb_ProcessCallback()", * URL="\ref LacSymCb_ProcessCallback()"]; * SYM=>SYM [label = "LacSymCb_ProcessCallbackInternal()", * URL="\ref LacSymCb_ProcessCallbackInternal()"]; * SYM=>SYM [label = "Lac_MemPoolEntryFree()", * URL="\ref Lac_MemPoolEntryFree()"]; * SYM=>SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; * SYM=>APP [label="cbFunc"]; * APP>>SYM [label="return"]; * SYM>>SQAT [label="return"]; * SQAT>>QATCOMMS [label="return"]; * \endmsc * * @lld_end * *****************************************************************************/ /*****************************************************************************/ #ifndef LAC_SYM_HASH_H #define LAC_SYM_HASH_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "cpa_cy_sym.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_session.h" #include "lac_buffer_desc.h" /** ***************************************************************************** * @ingroup LacHash * Definition of callback function. * * @description * This is the callback function prototype. The callback function is * invoked when a hash precompute operation completes. * * @param[in] pCallbackTag Opaque value provided by user while making * individual function call. * * @retval * None *****************************************************************************/ typedef void (*lac_hash_precompute_done_cb_t)(void *pCallbackTag); /* * WARNING: There are no checks done on the parameters of the functions in * this file. The expected values of the parameters are documented and it is * up to the caller to provide valid values. */ /** ******************************************************************************* * @ingroup LacHash * validate the hash context * * @description * The client populates the hash context in the session context structure * This is passed as parameter to the session register API function and * needs to be validated. * * @param[in] pHashSetupData pointer to hash context structure * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_INVALID_PARAM Invalid parameter * *****************************************************************************/ CpaStatus LacHash_HashContextCheck(CpaInstanceHandle instanceHandle, const CpaCySymHashSetupData *pHashSetupData); /** ****************************************************************************** * @ingroup LacHash * Populate the hash pre-compute data. * * @description * This function populates the state1 and state2 fields with the hash * pre-computes. This is only done for authentication. The state1 * and state2 pointers must be set to point to the correct locations * in the content descriptor where the precompute result(s) will be * written, before this function is called. * * @param[in] instanceHandle Instance Handle * @param[in] pSessionSetup pointer to session setup data * @param[in] callbackFn Callback function which is invoked when * the precompute operation is completed * @param[in] pCallbackTag Opaque data which is passed back to the user * as a parameter in the callback function * @param[out] pWorkingBuffer Pointer to working buffer, sufficient memory * must be allocated by the caller for this. * Assumption that this is 8 byte aligned. * @param[out] pState1 pointer to State 1 in content descriptor * @param[out] pState2 pointer to State 2 in content descriptor * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_RETRY Retry the operation. * @retval CPA_STATUS_RESOURCE Error Allocating memory * @retval CPA_STATUS_FAIL Operation Failed * *****************************************************************************/ CpaStatus LacHash_PrecomputeDataCreate(const CpaInstanceHandle instanceHandle, CpaCySymSessionSetupData *pSessionSetup, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag, Cpa8U *pWorkingBuffer, Cpa8U *pState1, Cpa8U *pState2); /** ****************************************************************************** * @ingroup LacHash * populate the hash state prefix aad buffer. * * @description * This function populates the hash state prefix aad buffer. This function * is not called for CCM/GCM operations as the AAD data varies per request * and is stored in the cookie as opposed to the session descriptor. * * @param[in] pHashSetupData pointer to hash setup structure * @param[in] pHashControlBlock pointer to hash control block * @param[in] qatHashMode QAT Mode for hash * @param[in] pHashStateBuffer pointer to hash state prefix aad buffer * @param[in] pHashStateBufferInfo Pointer to hash state prefix buffer info * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_FAIL Operation Failed * *****************************************************************************/ CpaStatus LacHash_StatePrefixAadBufferInit( sal_service_t *pService, const CpaCySymHashSetupData *pHashSetupData, icp_qat_la_bulk_req_ftr_t *pHashControlBlock, icp_qat_hw_auth_mode_t qatHashMode, Cpa8U *pHashStateBuffer, lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo); /** ******************************************************************************* * @ingroup LacHash * Check parameters for a hash perform operation * * @description * This function checks the parameters for a hash perform operation. * * @param[in] pSessionDesc Pointer to session descriptor. * @param[in] pOpData Pointer to request parameters. * @param[in] srcPktSize Total size of the Buffer List * @param[in] pVerifyResult Pointer to user flag * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_INVALID_PARAM Invalid Parameter * *****************************************************************************/ CpaStatus LacHash_PerformParamCheck(CpaInstanceHandle instanceHandle, lac_session_desc_t *pSessionDesc, const CpaCySymOpData *pOpData, Cpa64U srcPktSize, const CpaBoolean *pVerifyResult); /** ******************************************************************************* * @ingroup LacHash * Perform hash precompute operation for HMAC * * @description * This function sends 2 requests to the CPM for the hmac precompute * operations. The results of the ipad and opad state calculation * is copied into pState1 and pState2 (e.g. these may be the state1 and * state2 buffers in a hash content descriptor) and when * the final operation has completed the condition passed as a param to * this function is set to true. * * This function performs the XORing of the IPAD and OPAD constants to * the key (which was padded to the block size of the algorithm) * * @param[in] instanceHandle Instance Handle * @param[in] hashAlgorithm Hash Algorithm * @param[in] authKeyLenInBytes Length of Auth Key * @param[in] pAuthKey Pointer to Auth Key * @param[out] pWorkingMemory Pointer to working memory that is carved * up and used in the pre-compute operations. * Assumption that this is 8 byte aligned. * @param[out] pState1 Pointer to State 1 in content descriptor * @param[out] pState2 Pointer to State 2 in content descriptor * @param[in] callbackFn Callback function which is invoked when * the precompute operation is completed * @param[in] pCallbackTag Opaque data which is passed back to the user * as a parameter in the callback function * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_RETRY Retry the operation. * @retval CPA_STATUS_FAIL Operation Failed * *****************************************************************************/ CpaStatus LacSymHash_HmacPreComputes(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLenInBytes, Cpa8U *pAuthKey, Cpa8U *pWorkingMemory, Cpa8U *pState1, Cpa8U *pState2, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag); /** ******************************************************************************* * @ingroup LacHash * Perform hash precompute operation for XCBC MAC and GCM * * @description * This function sends 1 request to the CPM for the precompute operation * based on an AES ECB cipher. The results of the calculation is copied * into pState (this may be a pointer to the State 2 buffer in a Hash * content descriptor) and when the operation has completed the condition * passed as a param to this function is set to true. * * @param[in] instanceHandle Instance Handle * @param[in] hashAlgorithm Hash Algorithm * @param[in] authKeyLenInBytes Length of Auth Key * @param[in] pAuthKey Auth Key * @param[out] pWorkingMemory Pointer to working memory that is carved * up and used in the pre-compute operations. * Assumption that this is 8 byte aligned. * @param[out] pState Pointer to output state * @param[in] callbackFn Callback function which is invoked when * the precompute operation is completed * @param[in] pCallbackTag Opaque data which is passed back to the user * as a parameter in the callback function * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_RETRY Retry the operation. * @retval CPA_STATUS_FAIL Operation Failed * *****************************************************************************/ CpaStatus LacSymHash_AesECBPreCompute(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLenInBytes, Cpa8U *pAuthKey, Cpa8U *pWorkingMemory, Cpa8U *pState, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag); /** ******************************************************************************* * @ingroup LacHash * initialise data structures for the hash precompute operations * * @description * This function registers the precompute callback handler function, which * is different to the default one used by symmetric. Content descriptors * are pre-allocated for the hmac precomputes as they are constant for * these operations. * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_RESOURCE Error allocating memory * *****************************************************************************/ CpaStatus LacSymHash_HmacPrecompInit(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHash * free resources allocated for the precompute operations * * @description * free up the memory allocated on init time for the content descriptors * that were allocated for the HMAC precompute operations. * * @return none * *****************************************************************************/ void LacSymHash_HmacPrecompShutdown(CpaInstanceHandle instanceHandle); #endif /* LAC_SYM_HASH_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_hash_defs.h000066400000000000000000000353671503624047500335760ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_hash_defs.h * * @defgroup LacHashDefs Hash Definitions * * @ingroup LacHash * * Constants for hash algorithms * ***************************************************************************/ #ifndef LAC_SYM_HASH_DEFS_H #define LAC_SYM_HASH_DEFS_H /* Constant for MD5 algorithm */ #define LAC_HASH_MD5_BLOCK_SIZE 64 /**< @ingroup LacHashDefs * MD5 block size in bytes */ #define LAC_HASH_MD5_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * MD5 digest length in bytes */ #define LAC_HASH_MD5_STATE_SIZE 16 /**< @ingroup LacHashDefs * MD5 state size */ /* Constants for SHA1 algorithm */ #define LAC_HASH_SHA1_BLOCK_SIZE 64 /**< @ingroup LacHashDefs * SHA1 Block size in bytes */ #define LAC_HASH_SHA1_DIGEST_SIZE 20 /**< @ingroup LacHashDefs * SHA1 digest length in bytes */ #define LAC_HASH_SHA1_STATE_SIZE 20 /**< @ingroup LacHashDefs * SHA1 state size */ /* Constants for SHA224 algorithm */ #define LAC_HASH_SHA224_BLOCK_SIZE 64 /**< @ingroup LacHashDefs * SHA224 block size in bytes */ #define LAC_HASH_SHA224_DIGEST_SIZE 28 /**< @ingroup LacHashDefs * SHA224 digest length in bytes */ #define LAC_HASH_SHA224_STATE_SIZE 32 /**< @ingroup LacHashDefs * SHA224 state size */ /* Constants for SHA256 algorithm */ #define LAC_HASH_SHA256_BLOCK_SIZE 64 /**< @ingroup LacHashDefs * SHA256 block size in bytes */ #define LAC_HASH_SHA256_DIGEST_SIZE 32 /**< @ingroup LacHashDefs * SHA256 digest length */ #define LAC_HASH_SHA256_STATE_SIZE 32 /**< @ingroup LacHashDefs * SHA256 state size */ /* Constants for SHA384 algorithm */ #define LAC_HASH_SHA384_BLOCK_SIZE 128 /**< @ingroup LacHashDefs * SHA384 block size in bytes */ #define LAC_HASH_SHA384_DIGEST_SIZE 48 /**< @ingroup LacHashDefs * SHA384 digest length in bytes */ #define LAC_HASH_SHA384_STATE_SIZE 64 /**< @ingroup LacHashDefs * SHA384 state size */ /* Constants for SHA512 algorithm */ #define LAC_HASH_SHA512_BLOCK_SIZE 128 /**< @ingroup LacHashDefs * SHA512 block size in bytes */ #define LAC_HASH_SHA512_DIGEST_SIZE 64 /**< @ingroup LacHashDefs * SHA512 digest length in bytes */ #define LAC_HASH_SHA512_STATE_SIZE 64 /**< @ingroup LacHashDefs * SHA512 state size */ /* Constants for SHA3_224 algorithm */ #define LAC_HASH_SHA3_224_BLOCK_SIZE 144 /**< @ingroup LacHashDefs * SHA3_224 block size in bytes */ #define LAC_HASH_SHA3_224_DIGEST_SIZE 28 /**< @ingroup LacHashDefs * SHA3_224 digest length in bytes */ #define LAC_HASH_SHA3_224_STATE_SIZE 28 /**< @ingroup LacHashDefs * SHA3_224 state size */ /* Constants for SHA3_256 algorithm */ #define LAC_HASH_SHA3_256_BLOCK_SIZE 136 /**< @ingroup LacHashDefs * SHA3_256 block size in bytes */ #define LAC_HASH_SHA3_256_DIGEST_SIZE 32 /**< @ingroup LacHashDefs * SHA3_256 digest length in bytes */ #define LAC_HASH_SHA3_256_STATE_SIZE 32 /**< @ingroup LacHashDefs * SHA3_256 state size */ /* Constants for SHA3_384 algorithm */ #define LAC_HASH_SHA3_384_BLOCK_SIZE 104 /**< @ingroup LacHashDefs * SHA3_384 block size in bytes */ #define LAC_HASH_SHA3_384_DIGEST_SIZE 48 /**< @ingroup LacHashDefs * SHA3_384 digest length in bytes */ #define LAC_HASH_SHA3_384_STATE_SIZE 48 /**< @ingroup LacHashDefs * SHA3_384 state size */ /* Constants for SHA3_512 algorithm */ #define LAC_HASH_SHA3_512_BLOCK_SIZE 72 /**< @ingroup LacHashDefs * SHA3_512 block size in bytes */ #define LAC_HASH_SHA3_512_DIGEST_SIZE 64 /**< @ingroup LacHashDefs * SHA3_512 digest length in bytes */ #define LAC_HASH_SHA3_512_STATE_SIZE 64 /**< @ingroup LacHashDefs * SHA3_512 state size */ /* Constants for POLY algorithm */ #define LAC_HASH_POLY_BLOCK_SIZE 64 /**< @ingroup LacHashDefs * POLY block size in bytes */ #define LAC_HASH_POLY_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * POLY digest length */ #define LAC_HASH_POLY_STATE_SIZE 0 /**< @ingroup LacHashDefs * POLY state size */ /* Constants for SM3 algorithm */ #define LAC_HASH_SM3_BLOCK_SIZE 64 /**< @ingroup LacHashDefs * SM3 block size in bytes */ #define LAC_HASH_SM3_DIGEST_SIZE 32 /**< @ingroup LacHashDefs * SM3 digest length */ #define LAC_HASH_SM3_STATE_SIZE 32 /**< @ingroup LacHashDefs * SM3 state size */ /* Constants for XCBC precompute algorithm */ #define LAC_HASH_XCBC_PRECOMP_KEY_NUM 3 /**< @ingroup LacHashDefs * The Pre-compute operation involves deriving 3 128-bit * keys (K1, K2 and K3) */ /* Constants for XCBC MAC algorithm */ #define LAC_HASH_XCBC_MAC_BLOCK_SIZE 16 /**< @ingroup LacHashDefs * XCBC_MAC block size in bytes */ #define LAC_HASH_XCBC_MAC_128_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * XCBC_MAC_PRF_128 digest length in bytes */ /* Constants for AES CMAC algorithm */ #define LAC_HASH_CMAC_BLOCK_SIZE 16 /**< @ingroup LacHashDefs * AES CMAC block size in bytes */ #define LAC_HASH_CMAC_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * AES CMAC digest length in bytes */ /* constants for AES CCM */ #define LAC_HASH_AES_CCM_BLOCK_SIZE 16 /**< @ingroup LacHashDefs * block size for CBC-MAC part of CCM */ #define LAC_HASH_AES_CCM_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * untruncated size of authentication field */ /* constants for AES GCM */ #define LAC_HASH_AES_GCM_BLOCK_SIZE 16 /**< @ingroup LacHashDefs * block size for Galois Hash 128 part of CCM */ #define LAC_HASH_AES_GCM_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * untruncated size of authentication field */ /* constants for KASUMI F9 */ #define LAC_HASH_KASUMI_F9_BLOCK_SIZE 8 /**< @ingroup LacHashDefs * KASUMI_F9 block size in bytes */ #define LAC_HASH_KASUMI_F9_DIGEST_SIZE 4 /**< @ingroup LacHashDefs * KASUMI_F9 digest size in bytes */ /* constants for SNOW3G UIA2 */ #define LAC_HASH_SNOW3G_UIA2_BLOCK_SIZE 8 /**< @ingroup LacHashDefs * SNOW3G UIA2 block size in bytes */ #define LAC_HASH_SNOW3G_UIA2_DIGEST_SIZE 4 /**< @ingroup LacHashDefs * SNOW3G UIA2 digest size in bytes */ /* constants for AES CBC MAC */ #define LAC_HASH_AES_CBC_MAC_BLOCK_SIZE 16 /**< @ingroup LacHashDefs * AES CBC MAC block size in bytes */ #define LAC_HASH_AES_CBC_MAC_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * AES CBC MAC digest size in bytes */ #define LAC_HASH_ZUC_EIA3_BLOCK_SIZE 4 /**< @ingroup LacHashDefs * ZUC EIA3 block size in bytes */ #define LAC_HASH_ZUC_EIA3_DIGEST_SIZE 4 /**< @ingroup LacHashDefs * ZUC EIA3 digest size in bytes */ /* constants for ZUC-256 with 32 bit MAC */ #define LAC_HASH_ZUC_256_MAC_32_BLOCK_SIZE 4 /**< @ingroup LacHashDefs * ZUC-256 with 32 bit MAC block size in bytes */ #define LAC_HASH_ZUC_256_MAC_32_DIGEST_SIZE 4 /**< @ingroup LacHashDefs * ZUC-256 with 32 bit MAC digest size in bytes */ /* constants for ZUC-256 with 64 bit MAC */ #define LAC_HASH_ZUC_256_MAC_64_BLOCK_SIZE 4 /**< @ingroup LacHashDefs * ZUC-256 with 64 bit MAC block size in bytes */ #define LAC_HASH_ZUC_256_MAC_64_DIGEST_SIZE 8 /**< @ingroup LacHashDefs * ZUC-256 with 64 bit MAC digest size in bytes */ /* constants for ZUC-256 with 128 bit MAC */ #define LAC_HASH_ZUC_256_MAC_128_BLOCK_SIZE 4 /**< @ingroup LacHashDefs * ZUC-256 with 128 bit MAC block size in bytes */ #define LAC_HASH_ZUC_256_MAC_128_DIGEST_SIZE 16 /**< @ingroup LacHashDefs * ZUC-256 with 128 bit MAC digest size in bytes */ /* constants for AES GCM ICV allowed sizes */ #define LAC_HASH_AES_GCM_ICV_SIZE_8 8 #define LAC_HASH_AES_GCM_ICV_SIZE_12 12 #define LAC_HASH_AES_GCM_ICV_SIZE_16 16 /* constants for AES CCM ICV allowed sizes */ #define LAC_HASH_AES_CCM_ICV_SIZE_MIN 4 #define LAC_HASH_AES_CCM_ICV_SIZE_MAX 16 /* constants for authentication algorithms */ #define LAC_HASH_IPAD_BYTE 0x36 /**< @ingroup LacHashDefs * Ipad Byte */ #define LAC_HASH_OPAD_BYTE 0x5c /**< @ingroup LacHashDefs * Opad Byte */ #define LAC_HASH_IPAD_4_BYTES 0x36363636 /**< @ingroup LacHashDefs * Ipad for 4 Bytes */ #define LAC_HASH_OPAD_4_BYTES 0x5c5c5c5c /**< @ingroup LacHashDefs * Opad for 4 Bytes */ /* Key Modifier (KM) value used in Kasumi algorithm in F9 mode to XOR * Integrity Key (IK) */ #define LAC_HASH_KASUMI_F9_KEY_MODIFIER_4_BYTES 0xAAAAAAAA /**< @ingroup LacHashDefs * Kasumi F9 Key Modifier for 4 bytes */ #define LAC_SYM_QAT_HASH_IV_REQ_MAX_SIZE_QW 2 /**< @ingroup LacSymQatHash * Maximum size of IV embedded in the request. * This is set to 2, namely 4 LONGWORDS. */ #define LAC_SYM_QAT_HASH_STATE1_MAX_SIZE_BYTES LAC_HASH_SHA512_BLOCK_SIZE /**< @ingroup LacSymQatHash * Maximum size of state1 in the hash setup block of the content descriptor. * This is set to the block size of SHA512. */ #define LAC_SYM_QAT_HASH_STATE2_MAX_SIZE_BYTES LAC_HASH_SHA512_BLOCK_SIZE /**< @ingroup LacSymQatHash * Maximum size of state2 in the hash setup block of the content descriptor. * This is set to the block size of SHA512. */ #define LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES 255 /**< Maximum size of the inner and outer prefix for nested hashing operations. * This is got from the maximum size supported by the accelerator which stores * the size in an 8bit field */ #define LAC_MAX_HASH_STATE_STORAGE_SIZE \ (sizeof(icp_qat_hw_auth_counter_t) + LAC_HASH_SHA512_STATE_SIZE) /**< Maximum size of the hash state storage section of the hash state prefix * buffer */ #define LAC_MAX_HASH_STATE_BUFFER_SIZE_BYTES \ LAC_MAX_HASH_STATE_STORAGE_SIZE + \ (LAC_ALIGN_POW2_ROUNDUP(LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES, \ LAC_QUAD_WORD_IN_BYTES) * \ 2) /**< Maximum size of the hash state prefix buffer will be for nested hash when * there is the maximum sized inner prefix and outer prefix */ #define LAC_MAX_AAD_SIZE_BYTES 256 /**< Maximum size of AAD in bytes */ #define IS_HMAC_ALG(algorithm) \ ((algorithm == CPA_CY_SYM_HASH_MD5) || \ (algorithm == CPA_CY_SYM_HASH_SHA1) || \ (algorithm == CPA_CY_SYM_HASH_SHA224) || \ (algorithm == CPA_CY_SYM_HASH_SHA256) || \ (algorithm == CPA_CY_SYM_HASH_SHA384) || \ (algorithm == CPA_CY_SYM_HASH_SHA512) || (LAC_HASH_IS_SHA3(algorithm)) || \ (algorithm == CPA_CY_SYM_HASH_SM3)) /**< @ingroup LacSymQatHash * Macro to detect if the hash algorithm is a HMAC algorithm */ #define IS_HASH_MODE_1(qatHashMode) (ICP_QAT_HW_AUTH_MODE1 == qatHashMode) /**< @ingroup LacSymQatHash * Macro to detect is qat hash mode is set to 1 (precompute mode) * only used with algorithms in hash mode CPA_CY_SYM_HASH_MODE_AUTH */ #define IS_HASH_MODE_2(qatHashMode) (ICP_QAT_HW_AUTH_MODE2 == qatHashMode) /**< @ingroup LacSymQatHash * Macro to detect is qat hash mode is set to 2. This is used for TLS and * mode 2 HMAC (no preompute mode) */ #define IS_HASH_MODE_2_AUTH(qatHashMode, hashMode) \ ((IS_HASH_MODE_2(qatHashMode)) && (CPA_CY_SYM_HASH_MODE_AUTH == hashMode)) /**< @ingroup LacSymQatHash * Macro to check for qat hash mode is set to 2 and the hash mode is * Auth. This applies to HMAC algorithms (no pre compute). This is used * to differentiate between TLS and HMAC */ #define IS_HASH_MODE_2_NESTED(qatHashMode, hashMode) \ ((IS_HASH_MODE_2(qatHashMode)) && (CPA_CY_SYM_HASH_MODE_NESTED == hashMode)) /**< @ingroup LacSymQatHash * Macro to check for qat hash mode is set to 2 and the LAC hash mode is * Nested. This applies to TLS. This is used to differentiate between * TLS and HMAC */ #define LAC_HASH_IS_SHA3(algo) \ ((algo == CPA_CY_SYM_HASH_SHA3_224) || \ (algo == CPA_CY_SYM_HASH_SHA3_256) || \ (algo == CPA_CY_SYM_HASH_SHA3_384) || (algo == CPA_CY_SYM_HASH_SHA3_512)) /**< @ingroup LacSymQatHash * Macro to check if the hash algorithm is SHA3 */ #endif /* LAC_SYM_HASH_DEFS_H */ lac_sym_hash_precomputes.h000066400000000000000000000232351503624047500351330ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_hash_precomputes.h * * @defgroup LacHashDefs Hash Definitions * * @ingroup LacHash * * Constants for hash algorithms * ***************************************************************************/ #ifndef LAC_SYM_HASH_PRECOMPUTES_H #define LAC_SYM_HASH_PRECOMPUTES_H #include "lac_sym_hash.h" #define LAC_SYM_AES_CMAC_RB_128 0x87 /* constant used for */ /* CMAC calculation */ #define LAC_SYM_HASH_MSBIT_MASK 0x80 /* Mask to check MSB top bit */ /* zero or one */ #define LAC_SINGLE_BUFFER_HW_META_SIZE \ (sizeof(icp_buffer_list_desc_t) + sizeof(icp_flat_buffer_desc_t)) /**< size of memory to allocate for the HW buffer list that is sent to the * QAT */ #define LAC_SYM_HASH_PRECOMP_MAX_WORKING_BUFFER \ ((sizeof(lac_sym_hash_precomp_op_data_t) * 2) + \ sizeof(lac_sym_hash_precomp_op_t)) /**< maximum size of the working data for the HMAC precompute operations * * Maximum size of lac_sym_hash_precomp_op_data_t is 264 bytes. For hash * precomputes there are 2 of these structures and a further * lac_sym_hash_precomp_op_t structure required. This comes to a total of 536 * bytes. * For the asynchronous version of the precomputes, the memory for the hash * state prefix buffer is used as the working memory. There are 584 bytes * which are alloacted for the hash state prefix buffer which is enough to * carve up for the precomputes. */ #define LAC_SYM_HASH_PRECOMP_MAX_AES_ECB_DATA \ ((ICP_QAT_HW_AES_128_KEY_SZ) * (3)) /**< Maximum size for the data that an AES ECB precompute is generated on */ /** ***************************************************************************** * @ingroup LacHashDefs * Precompute type enum * @description * Enum used to distinguish between precompute types * *****************************************************************************/ typedef enum { LAC_SYM_HASH_PRECOMP_HMAC = 1, /**< Hmac precompute operation. Copy state from hash state buffer */ LAC_SYM_HASH_PRECOMP_AES_ECB, /**< XCBC/CGM precompute, Copy state from data buffer */ } lac_sym_hash_precomp_type_t; /** ***************************************************************************** * @ingroup LacHashDefs * overall precompute management structure * @description * structure used to manage the precompute operations for a session * *****************************************************************************/ typedef struct lac_sym_hash_precomp_op_s { lac_hash_precompute_done_cb_t callbackFn; /**< Callback function to be invoked when the final precompute completes */ void *pCallbackTag; /**< Opaque data to be passed back as a parameter in the callback */ OsalAtomic opsPending; /**< counter used to determine if the current precompute is the * final one. */ } lac_sym_hash_precomp_op_t; /** ***************************************************************************** * @ingroup LacHashDefs * hmac precompute structure as used by the QAT * @description * data used by the QAT for HMAC precomputes * * Must be allocated on an 8-byte aligned memory address. * *****************************************************************************/ typedef struct lac_sym_hash_hmac_precomp_qat_s { Cpa8U data[LAC_HASH_SHA512_BLOCK_SIZE]; /**< data to be hashed - block size of data for the algorithm */ /* NOTE: to save space we could have got the QAT to overwrite * this with the hash state storage */ icp_qat_fw_la_auth_req_params_t hashReqParams; /**< Request parameters as read in by the QAT */ Cpa8U bufferDesc[LAC_SINGLE_BUFFER_HW_META_SIZE]; /**< Buffer descriptor structure */ Cpa8U hashStateStorage[LAC_MAX_HASH_STATE_STORAGE_SIZE]; /**< Internal buffer where QAT writes the intermediate partial * state that is used in the precompute */ } lac_sym_hash_hmac_precomp_qat_t; /** ***************************************************************************** * @ingroup LacHashDefs * AES ECB precompute structure as used by the QAT * @description * data used by the QAT for AES ECB precomptes * * Must be allocated on an 8-byte aligned memory address. * *****************************************************************************/ typedef struct lac_sym_hash_aes_precomp_qat_s { Cpa8U contentDesc[LAC_SYM_QAT_MAX_CIPHER_SETUP_BLK_SZ]; /**< Content descriptor for a cipher operation */ Cpa8U data[LAC_SYM_HASH_PRECOMP_MAX_AES_ECB_DATA]; /**< The data to be ciphered is contained here and the result is * written in place back into this buffer */ icp_qat_fw_la_cipher_req_params_t cipherReqParams; /**< Request parameters as read in by the QAT */ Cpa8U bufferDesc[LAC_SINGLE_BUFFER_HW_META_SIZE]; /**< Buffer descriptor structure */ } lac_sym_hash_aes_precomp_qat_t; /** ***************************************************************************** * @ingroup LacHashDefs * overall structure for managing a single precompute operation * @description * overall structure for managing a single precompute operation * * Must be allocated on an 8-byte aligned memory address. * *****************************************************************************/ typedef struct lac_sym_hash_precomp_op_data_s { sal_crypto_service_t *pInstance; /**< Instance handle for the operation */ Cpa8U reserved[4]; /**< padding to align later structures on minimum 8-Byte address */ lac_sym_hash_precomp_type_t opType; /**< operation type to determine the precompute type in the callback */ lac_sym_hash_precomp_op_t *pOpStatus; /**< structure containing the counter and the condition for the overall * precompute operation. This is a pointer because the memory structure * may be shared between precomputes when there are more than 1 as in the * case of HMAC */ union { lac_sym_hash_hmac_precomp_qat_t hmacQatData; /**< Data sent to the QAT for hmac precomputes */ lac_sym_hash_aes_precomp_qat_t aesQatData; /**< Data sent to the QAT for AES ECB precomputes */ } u; /**< ASSUMPTION: The above structures are 8 byte aligned if the overall * struct is 8 byte aligned, as there are two 4 byte fields before this * union */ Cpa32U stateSize; /**< Size of the state to be copied into the state pointer in the content * descriptor */ Cpa8U *pState; /**< pointer to the state in the content descriptor where the result of * the precompute should be copied to */ } lac_sym_hash_precomp_op_data_t; #endif /* LAC_SYM_HASH_PRECOMPUTES_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_key.h000066400000000000000000000217001503624047500324240ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_sym_key.h * * @defgroup LacSymKey Key Generation * * @ingroup LacSym * * @lld_start * * @lld_overview * * Key generation component is responsible for SSL, TLS & MGF operations. All * memory required for the keygen operations is got from the keygen cookie * structure which is carved up as required. * * For SSL the QAT accelerates the nested hash function with MD5 as the * outer hash and SHA1 as the inner hash. * * Refer to sections in draft-freier-ssl-version3-02.txt: * 6.1 Asymmetric cryptographic computations - This refers to converting * the pre-master secret to the master secret. * 6.2.2 Converting the master secret into keys and MAC secrets - Using * the master secret to generate the key material. * * For TLS the QAT accelerates the PRF function as described in * rfc4346 - TLS version 1.1 (this obsoletes rfc2246 - TLS version 1.0) * 5. HMAC and the pseudorandom function - For the TLS PRF and getting * S1 and S2 from the secret. * 6.3. Key calculation - For how the key material is generated * 7.4.9. Finished - How the finished message uses the TLS PRF * 8.1. Computing the master secret * * * @lld_dependencies * \ref LacSymQatHash: for building up hash content descriptor * \ref LacMem: for virt to phys conversions * * @lld_initialisation * The response handler is registered with Symmetric. The Maximum SSL is * allocated. A structure is allocated containing all the TLS labels that * are supported. On shutdown the memory for these structures are freed. * * @lld_module_algorithms * @lld_process_context * * @lld_end * * *****************************************************************************/ #ifndef LAC_SYM_KEY_H_ #define LAC_SYM_KEY_H_ #include "cpa_cy_key.h" /**< @ingroup LacSymKey * Label for SSL. Size is 136 bytes for 16 iterations, which can theroretically * generate up to 256 bytes of output data. QAT will generate a maximum of * 255 bytes */ #define LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL ("master secret") /**< @ingroup LacSymKey * Label for TLS Master Secret Key Derivation, as defined in RFC4346 */ #define LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL ("key expansion") /**< @ingroup LacSymKey * Label for TLS Key Material Generation, as defined in RFC4346. */ #define LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL ("client finished") /**< @ingroup LacSymKey * Label for TLS Client finished Message, as defined in RFC4346. */ #define LAC_SYM_KEY_TLS_SERVER_FIN_LABEL ("server finished") /**< @ingroup LacSymKey * Label for TLS Server finished Message, as defined in RFC4346. */ /* ******************************************************************************* * Define Constants and Macros for SSL, TLS and MGF ******************************************************************************* */ #define LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW 0 /**< Used to indicate there is no hash block offset in the content descriptor */ #define ICP_QAT_SECRET_LEN_MAX 1024 /**< Maximum secret length passed to cpaCyKeyGenTls2() */ /** ****************************************************************************** * @ingroup LacSymKey * TLS label struct * * @description * This structure is used to hold the various TLS labels. Each field is * on an 8 byte boundary provided the structure itself is 8 bytes aligned. *****************************************************************************/ typedef struct lac_sym_key_tls_labels_s { Cpa8U masterSecret[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; /**< Master secret label */ Cpa8U keyMaterial[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; /**< Key material label */ Cpa8U clientFinished[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; /**< client finished label */ Cpa8U serverFinished[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; /**< server finished label */ } lac_sym_key_tls_labels_t; /** ****************************************************************************** * @ingroup LacSymKey * TLS HKDF sub label struct * * @description * This structure is used to hold the various TLS HKDF sub labels. * Each field is on an 8 byte boundary. *****************************************************************************/ typedef struct lac_sym_key_tls_hkdf_sub_labels_s { CpaCyKeyGenHKDFExpandLabel keySublabel256; /**< CPA_CY_HKDF_SUBLABEL_KEY */ CpaCyKeyGenHKDFExpandLabel ivSublabel256; /**< CPA_CY_HKDF_SUBLABEL_IV */ CpaCyKeyGenHKDFExpandLabel resumptionSublabel256; /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ CpaCyKeyGenHKDFExpandLabel finishedSublabel256; /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ CpaCyKeyGenHKDFExpandLabel keySublabel384; /**< CPA_CY_HKDF_SUBLABEL_KEY */ CpaCyKeyGenHKDFExpandLabel ivSublabel384; /**< CPA_CY_HKDF_SUBLABEL_IV */ CpaCyKeyGenHKDFExpandLabel resumptionSublabel384; /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ CpaCyKeyGenHKDFExpandLabel finishedSublabel384; /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ CpaCyKeyGenHKDFExpandLabel keySublabelChaChaPoly; /**< CPA_CY_HKDF_SUBLABEL_KEY */ CpaCyKeyGenHKDFExpandLabel ivSublabelChaChaPoly; /**< CPA_CY_HKDF_SUBLABEL_IV */ CpaCyKeyGenHKDFExpandLabel resumptionSublabelChaChaPoly; /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ CpaCyKeyGenHKDFExpandLabel finishedSublabelChaChaPoly; /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ Cpa64U sublabelPhysAddr256; /**< Physical address of the SHA-256 subLabels */ Cpa64U sublabelPhysAddr384; /**< Physical address of the SHA-384 subLabels */ Cpa64U sublabelPhysAddrChaChaPoly; /**< Physical address of the ChaChaPoly subLabels */ } lac_sym_key_tls_hkdf_sub_labels_t; /** ****************************************************************************** * @ingroup LacSymKey * This function prints the stats to standard out. * * @retval CPA_STATUS_SUCCESS Status Success * @retval CPA_STATUS_FAIL General failure * *****************************************************************************/ void LacKeygen_StatsShow(CpaInstanceHandle instanceHandle); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_partial.h000066400000000000000000000202301503624047500332650ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file lac_sym_partial.h * * @defgroup LacSymPartial Partial Packets * * @ingroup LacSymCommon * * Partial packet handling code * * @lld_start * * Partials In Flight\n * The API states that for partial packets the client should not submit * the next partial request until the callback for the current partial has * been called. We have chosen to enforce this rather than letting the user * proceed where they would get an incorrect digest, cipher result. * * Maintain a SpinLock for partials in flight per session. Try and acquire this * SpinLock. If it can't be acquired return an error straight away to the client * as there is already a partial in flight. There is no blocking in the data * path for this. * * By preventing any other partials from coming in while a partial is in flight * we can check and change the state of the session without having to lock * round it (dont want to have to lock and block in the data path). The state * of the session indicates the previous packet type that a request was * successfully completed for. The last packet type is only updated for partial * packets. This state determines the packet types that can be accepted. * e.g a last partial will not be accepted unless the previous packet was a * partial. By only allowing one partial packet to be in flight, there is no * need to lock around the update of the previous packet type for the session. * * The ECB Cipher mode, ciphers each block separately. No state is maintained * between blocks. There is no need to wait for the callback for previous * partial in ECB mode as the result of the previous partial has no impact on * it. The API and our implementation only allows 1 partial packet to be in * flight per session, therefore a partial packet request for ECB mode must * be fully completed (ie. callback called) before the next partial request * can be issued. * * Partial Ordering\n * The ordering that the user submits partial packets will be checked. * (we could have let the user proceed where they will get an incorrect * digest/cipher result but chose against this). * * -# Maintain the last packet type of a partial operation for the session. If * there have been no previous partials, we will accept only first partials * -# The state must be set to partial before we will accept a final partial. * i.e. a partial request must have already completed. * * The last packet type is updated in the callback for partial packets as this * is the only place we can guarantee that a partial packet operation has been * completed. When a partial completes the state can be updated from FULL to * PARTIAL. The SpinLock for partial packets in flight for the session can be * unlocked at this point. On a final Partial request the last packet type is * reset back to FULL. NOTE: This is not done at the same time as the check in * the perform as if an error occurs we would have to roll back the state * * For Hash mode it is possible to interleave full and a single partial * packet stream in a session as the hash state buffer is updated for partial * packets. It is not touched by full packets. For cipher mode, as the client * manages the state, they can interleave full and a single partial packets. * For ARC4, the state is managed internally and the packet type will always * be set to partial internally. * * @lld_end * ***************************************************************************/ /***************************************************************************/ #ifndef LAC_SYM_PARTIAL_H #define LAC_SYM_PARTIAL_H #include "cpa.h" #include "cpa_cy_sym.h" /***************************************************************************/ /** ******************************************************************************* * @ingroup LacSymPartial * check if partial packet request is valid for a session * * @description * This function checks to see if there is a partial packet request in * flight and then if the partial state is correct * * @param[in] packetType Partial packet request * @param[in] partialState Partial state of session * * @retval CPA_STATUS_SUCCESS Normal Operation * @retval CPA_STATUS_INVALID_PARAM Invalid Parameter * *****************************************************************************/ CpaStatus LacSym_PartialPacketStateCheck(CpaCySymPacketType packetType, CpaCySymPacketType partialState); /** ******************************************************************************* * @ingroup LacSymPartial * update the state of the partial packet in a session * * @description * This function is called in callback operation. It updates the state * of a partial packet in a session and indicates that there is no * longer a partial packet in flight for the session * * @param[in] packetType Partial packet request * @param[out] pPartialState Pointer to partial state of session * *****************************************************************************/ void LacSym_PartialPacketStateUpdate(CpaCySymPacketType packetType, CpaCySymPacketType *pPartialState); #endif /* LAC_SYM_PARTIAL_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat.h000066400000000000000000000253761503624047500324360ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat.h * * @defgroup LacSymQat Symmetric QAT * * @ingroup LacSym * * Interfaces for populating the qat structures for a symmetric operation * * @lld_start * * @lld_overview * This file documents the interfaces for populating the qat structures * that are common for all symmetric operations. * * @lld_dependencies * - \ref LacSymQatHash "Hash QAT Comms" Sym Qat commons for Hash * - \ref LacSymQat_Cipher "Cipher QAT Comms" Sym Qat commons for Cipher * - OSAL: logging * - \ref LacMem "Memory" - Inline memory functions * * @lld_initialisation * This component is initialized during the LAC initialisation sequence. It * is called by the Symmetric Initialisation function. * * @lld_module_algorithms * * @lld_process_context * Refer to \ref LacHash "Hash" and \ref LacCipher "Cipher" for sequence * diagrams to see their interactions with this code. * * * @lld_end * *****************************************************************************/ /*****************************************************************************/ #ifndef LAC_SYM_QAT_H #define LAC_SYM_QAT_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "cpa_cy_sym.h" #include "icp_accel_devices.h" #include "icp_qat_fw_la.h" #include "icp_qat_hw.h" #include "lac_session.h" #include "sal_qat_cmn_msg.h" #include "lac_common.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #define LAC_SYM_DEFAULT_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_SGL #define LAC_SYM_DP_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT #define LAC_SYM_KEY_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT /**< @ingroup LacSymQat * LAC SYM Source & Destination buffer type (FLAT/SGL) */ #define LAC_QAT_SYM_REQ_SZ_LW 32 #define LAC_QAT_SYM_RESP_SZ_LW 8 /** ******************************************************************************* * @ingroup LacSymQat * Symmetric crypto response handler * * @description * This function handles the symmetric crypto response * * @param[in] instanceHandle void* pRespMsg * * *****************************************************************************/ void LacSymQat_SymRespHandler(void *pRespMsg); /** ******************************************************************************* * @ingroup LacSymQat * Initialise the Symmetric QAT code * * @description * This function initialises the symmetric QAT code * * @param[in] instanceHandle Instance handle * * @return CPA_STATUS_SUCCESS Operation successful * @return CPA_STATUS_FAIL Initialisation Failed * *****************************************************************************/ CpaStatus LacSymQat_Init(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacSymQat * Register a response handler function for a symmetric command ID * * @description * This function registers a response handler function for a symmetric * operation. * * Note: This operation should only be performed once by the init function * of a component. There is no corresponding deregister function, but * registering a NULL function pointer will have the same effect. There * MUST not be any requests in flight when calling this function. * * @param[in] lacCmdId Command Id of operation * @param[in] pCbHandler callback handler function * * @return None * *****************************************************************************/ void LacSymQat_RespHandlerRegister(icp_qat_fw_la_cmd_id_t lacCmdId, sal_qat_resp_handler_func_t pCbHandler); /** ****************************************************************************** * @ingroup LacSymQat * get the QAT packet type * * @description * This function returns the QAT packet type for a LAC packet type. The * LAC packet type does not indicate a first partial. therefore for a * partial request, the previous packet type needs to be looked at to * figure out if the current partial request is a first partial. * * * @param[in] packetType LAC Packet type * @param[in] packetState LAC Previous Packet state * @param[out] pQatPacketType Packet type using the QAT macros * * @return none * *****************************************************************************/ void LacSymQat_packetTypeGet(CpaCySymPacketType packetType, CpaCySymPacketType packetState, Cpa32U *pQatPacketType); /** ****************************************************************************** * @ingroup LacSymQat * Populate the command flags based on the packet type * * @description * This function populates the following flags in the Symmetric Crypto * service_specif_flags field of the common header of the request: * - LA_PARTIAL * - UPDATE_STATE * - RET_AUTH_RES * - CMP_AUTH_RES * based on looking at the input params listed below. * * @param[in] qatPacketType Packet type * @param[in] cmdId Command Id * @param[in] cipherAlgorithm Cipher Algorithm * @param[out] pLaCommandFlags Command Flags * * @return none * *****************************************************************************/ void LacSymQat_LaPacketCommandFlagSet(Cpa32U qatPacketType, icp_qat_fw_la_cmd_id_t laCmdId, CpaCySymCipherAlgorithm cipherAlgorithm, Cpa16U *pLaCommandFlags, Cpa32U ivLenInBytes); /** ****************************************************************************** * @ingroup LacSymQat * * * @description * defaults the common request service specific flags * * @param[in] laCmdFlags Common request service specific flags * @param[in] symOp Type of operation performed e.g hash or cipher * * @return none * *****************************************************************************/ void LacSymQat_LaSetDefaultFlags(icp_qat_fw_serv_specif_flags *laCmdFlags, CpaCySymOp symOp); /** ****************************************************************************** * @ingroup LacSymQat * * * @description * this function defines whether the shared constants table can be used * for a particular cipher and hash algorithm * * @param[in] ptr to session * @param[in] ptr to return offset into table for cipher config * @param[in] ptr to return offset into table for hash config * * @return CPA_TRUE if Constants table is available for use, CPA_FALSE if it's * not. * *****************************************************************************/ CpaBoolean LacSymQat_UseSymConstantsTable(lac_session_desc_t *pSession, Cpa8U *cipherOffset, Cpa8U *hashOffset); /** ****************************************************************************** * @ingroup LacSymQat * * * @description * this function calculates whether the optimized content descriptor can * be used for a particular chained cipher and hash algorithm * * @param[in] ptr to session * * @return CPA_TRUE if optimized CD can be used, CPA_FALSE if it's not. * *****************************************************************************/ CpaBoolean LacSymQat_UseOptimisedContentDesc(lac_session_desc_t *pSession); #endif /* LAC_SYM_QAT_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_cipher.h000066400000000000000000000340041503624047500337540ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat_cipher.h * * @defgroup LacSymQat_Cipher Cipher QAT * * @ingroup LacSymQat * * external interfaces for populating QAT structures for cipher operations. * *****************************************************************************/ /*****************************************************************************/ #ifndef LAC_SYM_QAT_CIPHER_H #define LAC_SYM_QAT_CIPHER_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa_cy_sym.h" #include "icp_qat_fw_la.h" #include "lac_session.h" #include "lac_sal_types_crypto.h" /* ************************************************************************** * @ingroup LacSymQat_Cipher * * @description * Defines for building the cipher request params cache * ************************************************************************** */ #define LAC_SYM_QAT_CIPHER_NEXT_ID_BIT_OFFSET 24 #define LAC_SYM_QAT_CIPHER_CURR_ID_BIT_OFFSET 16 #define LAC_SYM_QAT_CIPHER_STATE_SIZE_BIT_OFFSET 8 #define LAC_SYM_QAT_CIPHER_GCM_SPC_OFFSET_IN_DRAM 9 #define LAC_SYM_QAT_CIPHER_CCM_SPC_OFFSET_IN_DRAM 8 #define LAC_SYM_QAT_CIPHER_CHACHA_SPC_OFFSET_IN_DRAM 2 #define LAC_SYM_QAT_CIPHER_SPC_STATE_SIZE 48 /** ****************************************************************************** * @ingroup LacSymQat_Cipher * Retrieve the cipher block size in bytes for a given algorithm * * @description * This function returns a hard-coded block size for the specific cipher * algorithm * * @param[in] cipherAlgorithm Cipher algorithm for the current session * * @retval The block size, in bytes, for the given cipher algorithm * *****************************************************************************/ Cpa8U LacSymQat_CipherBlockSizeBytesGet( CpaCySymCipherAlgorithm cipherAlgorithm); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * Retrieve the cipher IV/state size in bytes for a given algorithm * * @description * This function returns a hard-coded IV/state size for the specific cipher * algorithm * * @param[in] cipherAlgorithm Cipher algorithm for the current session * * @retval The IV/state size, in bytes, for the given cipher algorithm * *****************************************************************************/ Cpa32U LacSymQat_CipherIvSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * Populate the cipher request params structure * * @description * This function is passed a pointer to the 128B request block. * (This memory must be allocated prior to calling this function). It * populates: * - the cipher fields of the req_params block in the request. No * need to zero this first, all fields will be populated. * - the corresponding CIPH_IV_FLD flag in the serv_specif_flags field * of the common header. * To do this it uses the parameters described below and the following *fields from the request block which must be populated prior to calling this *function: * - cd_ctrl.cipher_state_sz * - UPDATE_STATE flag in comn_hdr.serv_specif_flags * * * @param[in] pSessionDesc The session descriptor. * * @param[in] pReq Pointer to request block. * * @param[in] cipherOffsetInBytes Offset to cipher data in user data buffer * * @param[in] cipherLenInBytes Length of cipher data in buffer * * @param[in] ivBufferPhysAddr Physical address of aligned IV/state * buffer * @param[in] pIvBufferVirt Virtual address of aligned IV/state * buffer * @retval void * *****************************************************************************/ CpaStatus LacSymQat_CipherRequestParamsPopulate( lac_session_desc_t *pSessionDesc, icp_qat_fw_la_bulk_req_t *pReq, Cpa32U cipherOffsetInBytes, Cpa32U cipherLenInBytes, Cpa64U ivBufferPhysAddr, Cpa8U *pIvBufferVirt); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * Derive initial ARC4 cipher state from a base key * * @description * An initial state for an ARC4 cipher session is derived from the base * key provided by the user, using the ARC4 Key Scheduling Algorithm (KSA) * * @param[in] pKey The base key provided by the user * * @param[in] keyLenInBytes The length of the base key provided. * The range of valid values is 1-256 bytes * * @param[out] pArc4CipherState The initial state is written to this buffer, * including i and j values, and 6 bytes of padding * so 264 bytes must be allocated for this buffer * by the caller * * @retval void * *****************************************************************************/ void LacSymQat_CipherArc4StateInit(const Cpa8U *pKey, Cpa32U keyLenInBytes, Cpa8U *pArc4CipherState); /** ****************************************************************************** * @ingroup LacSymQat_CipherXTSModeUpdateKeyLen * Update the initial XTS key after the first partial has been received. * * @description * For XTS mode using partial packets, after the first partial response * has been received, the the key length needs to be halved for subsequent * partials. * * @param[in] pSessionDesc The session descriptor. * * @param[in] newKeySizeInBytes The new key size.. * * @retval void * *****************************************************************************/ void LacSymQat_CipherXTSModeUpdateKeyLen(lac_session_desc_t *pSessionDesc, Cpa32U newKeySizeInBytes); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * LacSymQat_CipherCtrlBlockInitialize() * * @description * initialize the cipher control block with all zeros * * @param[in] pMsg Pointer to the common request message * * @retval void * *****************************************************************************/ void LacSymQat_CipherCtrlBlockInitialize(icp_qat_fw_la_bulk_req_t *pMsg); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * LacSymQat_CipherCtrlBlockWrite() * * @description * This function populates the cipher control block of the common request * message * * @param[in] pMsg Pointer to the common request message * * @param[in] cipherAlgorithm Cipher Algorithm to be used * * @param[in] targetKeyLenInBytes cipher key length in bytes of selected * algorithm * * @param[in] sliceType Cipher slice type to be used * * @param[out] nextSlice SliceID for next control block * entry. This value is known only by * the calling component * * @param[out] cipherCfgOffsetInQuadWord Offset into the config table in QW * * @retval void * *****************************************************************************/ void LacSymQat_CipherCtrlBlockWrite(icp_qat_la_bulk_req_ftr_t *pMsg, Cpa32U cipherAlgorithm, Cpa32U targetKeyLenInBytes, Cpa32U sliceType, icp_qat_fw_slice_t nextSlice, Cpa8U cipherCfgOffsetInQuadWord); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * LacSymQat_CipherHwBlockPopulateCfgData() * * @description * Populate the physical HW block with config data * * @param[in] pSession Pointer to the session data * * @param[in] pCipherHwBlock pointer to the hardware control block * in the common message * * @param[in] pSizeInBytes * * @retval void * *****************************************************************************/ void LacSymQat_CipherHwBlockPopulateCfgData(lac_session_desc_t *pSession, const void *pCipherHwBlock, Cpa32U *pSizeInBytes); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * LacSymQat_CipherGetCfgData() * * @description * setup the config data for cipher * * @param[in] pSession Pointer to the session data * * @param[in] pAlgorithm * * @param[in] pMode * @param[in] pDir * @param[in] pKey_convert * * @retval void * *****************************************************************************/ void LacSymQat_CipherGetCfgData(lac_session_desc_t *pSession, icp_qat_hw_cipher_algo_t *pAlgorithm, icp_qat_hw_cipher_mode_t *pMode, icp_qat_hw_cipher_dir_t *pDir, icp_qat_hw_cipher_convert_t *pKey_convert); /** ****************************************************************************** * @ingroup LacSymQat_Cipher * LacSymQat_CipherHwBlockPopulateKeySetup() * * @description * populate the key setup data in the cipher hardware control block * in the common request message * * @param[in] pSessionDesc The session descriptor. * * @param[in] pCipherSetupData Pointer to cipher setup data * * @param[in] targetKeyLenInBytes Target key length. If key length given * in cipher setup data is less that this, * the key will be "rounded up" to this * target length by padding it with 0's. * In normal no-padding case, the target * key length MUST match the key length * in the cipher setup data. * * @param[in] sliceType Cipher slice type to be used * * @param[in] pCipherHwBlock Pointer to the cipher hardware block * * @param[out] pCipherHwBlockSizeBytes Size in bytes of cipher setup block * * * @retval void * *****************************************************************************/ void LacSymQat_CipherHwBlockPopulateKeySetup( lac_session_desc_t *pSessionDesc, const CpaCySymCipherSetupData *pCipherSetupData, Cpa32U targetKeyLenInBytes, Cpa32U sliceType, const void *pCipherHwBlock, Cpa32U *pCipherHwBlockSizeBytes); #endif /* LAC_SYM_QAT_CIPHER_H */ lac_sym_qat_constants_table.h000066400000000000000000000160401503624047500356060ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat_constants_table.h * * @ingroup LacSymQat * * API to be used for the CySym constants table. * *****************************************************************************/ #ifndef LAC_SYM_QAT_CONSTANTS_TABLE_H #define LAC_SYM_QAT_CONSTANTS_TABLE_H #include "cpa.h" #include "icp_qat_fw_la.h" typedef struct lac_sym_qat_constants_s { /* Note these arrays must match the tables in lac_sym_qat_constants.c * icp_qat_hw_cipher_lookup_tbl and icp_qat_hw_auth_lookup_tbl */ uint8_t cipher_offset[ICP_QAT_HW_CIPHER_DELIMITER] [ICP_QAT_HW_CIPHER_MODE_DELIMITER][2][2]; uint8_t auth_offset[ICP_QAT_HW_AUTH_ALGO_DELIMITER] [ICP_QAT_HW_AUTH_MODE_DELIMITER][2]; } lac_sym_qat_constants_t; /** ******************************************************************************* * @ingroup LacSymQat * LacSymQat_ConstantsInitLookupTables * * * @description * The SymCy constants table is 1K of static data which is passed down * to the FW to be stored in SHRAM for use by the FW. * This function populates the associated lookup tables which the IA * driver uses. * Where there is config data available in the constants table the lookup * table stores the offset into the constants table. * Where there's no suitable config data available in the constants table * zero is stored in the lookup table. * * @return none * *****************************************************************************/ void LacSymQat_ConstantsInitLookupTables(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacSymQat * LacSymQat_ConstantsGetCipherOffset * * @description * This function looks up the cipher constants lookup array for * a specific cipher algorithm, mode, direction and convert flag. * If the lookup table value is zero then there's no suitable config data * available in the constants table. * If the value > zero, then there is config data available in the constants * table which is stored in SHRAM for use by the FW. The value is the offset * into the constants table, it is returned to the caller in poffset. * * * @param[in] Cipher Algorithm * @param[in] Cipher Mode * @param[in] Direction - encrypt/decrypt * @param[in] convert / no convert * @param[out] offset into constants table * * @return none * *****************************************************************************/ void LacSymQat_ConstantsGetCipherOffset(CpaInstanceHandle instanceHandle, uint8_t algo, uint8_t mode, uint8_t direction, uint8_t convert, uint8_t *poffset); /** ******************************************************************************* * @ingroup LacSymQat * LacSymQat_ConstantsGetAuthOffset * * @description * This function looks up the auth constants lookup array for * a specific auth algorithm, mode, direction and convert flag. * If the lookup table value is zero then there's no suitable config data * available in the constants table. * If the value > zero, then there is config data available in the constants * table which is stored in SHRAM for use by the FW. The value is the offset * into the constants table, it is returned to the caller in poffset. * * * @param[in] auth Algorithm * @param[in] auth Mode * @param[in] nested / no nested * @param[out] offset into constants table * * @return none * *****************************************************************************/ void LacSymQat_ConstantsGetAuthOffset(CpaInstanceHandle instanceHandle, uint8_t algo, uint8_t mode, uint8_t nested, uint8_t *poffset); #endif /* LAC_SYM_QAT_SHRAM_CONSTANTS_TABLE_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_hash.h000066400000000000000000000357161503624047500334400ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat_hash.h * * @defgroup LacSymQatHash Hash QAT * * @ingroup LacSymQat * * interfaces for populating qat structures for a hash operation * *****************************************************************************/ /*****************************************************************************/ #ifndef LAC_SYM_QAT_HASH_H #define LAC_SYM_QAT_HASH_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "cpa_cy_sym.h" #include "icp_qat_fw_la.h" #include "icp_qat_hw.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_common.h" /** ****************************************************************************** * @ingroup LacSymQatHash * hash precomputes * * @description * This structure contains information on the hash precomputes * *****************************************************************************/ typedef struct lac_sym_qat_hash_precompute_info_s { Cpa8U *pState1; /**< state1 pointer */ Cpa32U state1Size; /**< state1 size */ Cpa8U *pState2; /**< state2 pointer */ Cpa32U state2Size; /**< state2 size */ } lac_sym_qat_hash_precompute_info_t; /** ****************************************************************************** * @ingroup LacSymQatHash * hash state prefix buffer info * * @description * This structure contains information on the hash state prefix aad buffer * *****************************************************************************/ typedef struct lac_sym_qat_hash_state_buffer_info_s { Cpa64U pDataPhys; /**< Physical pointer to the hash state prefix buffer */ Cpa8U *pData; /**< Virtual pointer to the hash state prefix buffer */ Cpa8U stateStorageSzQuadWords; /**< hash state storage size in quad words */ Cpa8U prefixAadSzQuadWords; /**< inner prefix/aad and outer prefix size in quad words */ } lac_sym_qat_hash_state_buffer_info_t; /** ****************************************************************************** * @ingroup LacSymQatHash * Init the hash specific part of the content descriptor. * * @description * This function populates the hash specific fields of the control block * and the hardware setup block for a digest session. This function sets * the size param to hold the size of the hash setup block. * * In the case of hash only, the content descriptor will contain just a * hash control block and hash setup block. In the case of chaining it * will contain the hash control block and setup block along with the * control block and setup blocks of additional services. * * Note: The memory for the content descriptor MUST be allocated prior to * calling this function. The memory for the hash control block and hash * setup block MUST be set to 0 prior to calling this function. * * @image html contentDescriptor.png "Content Descriptor" * * @param[in] pMsg Pointer to req Parameter Footer * * @param[in] pHashSetupData Pointer to the hash setup data as * defined in the LAC API. * * @param[in] pHwBlockBase Pointer to the base of the hardware * setup block * * @param[in] hashBlkOffsetInHwBlock Offset in quad-words from the base of * the hardware setup block where the * hash block will start. This offset * is stored in the control block. It * is used to figure out where to write * that hash setup block. * * @param[in] nextSlice SliceID for next control block * entry This value is known only by * the calling component * * @param[in] qatHashMode QAT hash mode * * @param[in] useSymConstantsTable Indicate if Shared-SRAM constants table * is used for this session. If CPA_TRUE, * the h/w setup block is NOT populated * * @param[in] useOptimisedContentDesc Indicate if optimised content desc * is used for this session. * * @param[in] pPrecompute For auth mode, this is the pointer * to the precompute data. Otherwise this * should be set to NULL * * @param[out] pHashBlkSizeInBytes size in bytes of hash setup block * * @return void * *****************************************************************************/ void LacSymQat_HashContentDescInit( icp_qat_la_bulk_req_ftr_t *pMsg, CpaInstanceHandle instanceHandle, const CpaCySymHashSetupData *pHashSetupData, void *pHwBlockBase, Cpa32U hashBlkOffsetInHwBlock, icp_qat_fw_slice_t nextSlice, icp_qat_hw_auth_mode_t qatHashMode, CpaBoolean useSymConstantsTable, CpaBoolean useOptimisedContentDesc, lac_sym_qat_hash_precompute_info_t *pPrecompute, Cpa32U *pHashBlkSizeInBytes); /** ****************************************************************************** * @ingroup LacSymQatHash * Calculate the size of the hash state prefix aad buffer * * @description * This function inspects the hash control block and based on the values * in the fields, it calculates the size of the hash state prefix aad * buffer. * * A partial packet processing request is possible at any stage during a * hash session. In this case, there will always be space for the hash * state storage field of the hash state prefix buffer. When there is * AAD data just the inner prefix AAD data field is used. * * @param[in] pMsg Pointer to the Request Message * * @param[out] pHashStateBuf Pointer to hash state prefix buffer info * structure. * * @return None * *****************************************************************************/ void LacSymQat_HashStatePrefixAadBufferSizeGet( icp_qat_la_bulk_req_ftr_t *pMsg, lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf); /** ****************************************************************************** * @ingroup LacSymQatHash * Populate the fields of the hash state prefix buffer * * @description * This function populates the inner prefix/aad fields and/or the outer * prefix field of the hash state prefix buffer. * * @param[in] pHashStateBuf Pointer to hash state prefix buffer info * structure. * * @param[in] pMsg Pointer to the Request Message * * @param[in] pInnerPrefixAad Pointer to the Inner Prefix or Aad data * This is NULL where if the data size is 0 * * @param[in] innerPrefixSize Size of inner prefix/aad data in bytes * * @param[in] pOuterPrefix Pointer to the Outer Prefix data. This is * NULL where the data size is 0. * * @param[in] outerPrefixSize Size of the outer prefix data in bytes * * @return void * *****************************************************************************/ void LacSymQat_HashStatePrefixAadBufferPopulate( lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, icp_qat_la_bulk_req_ftr_t *pMsg, Cpa8U *pInnerPrefixAad, Cpa8U innerPrefixSize, Cpa8U *pOuterPrefix, Cpa8U outerPrefixSize); /** ****************************************************************************** * @ingroup LacSymQatHash * Populate the hash request params structure * * @description * This function is passed a pointer to the 128B Request block. * (This memory must be allocated prior to calling this function). It * populates the fields of this block using the parameters as described * below. It is also expected that this structure has been set to 0 * prior to calling this function. * * * @param[in] pReq Pointer to 128B request block. * * @param[in] authOffsetInBytes start offset of data that the digest is to * be computed on. * * @param[in] authLenInBytes Length of data digest calculated on * * @param[in] pService Pointer to service data * * @param[in] pHashStateBuf Pointer to hash state buffer info. This * structure contains the pointers and sizes. * If there is no hash state prefix buffer * required, this parameter can be set to NULL * * @param[in] qatPacketType Packet type using QAT macros. The hash * state buffer pointer and state size will be * different depending on the packet type * * @param[in] hashResultSize Size of the final hash result in bytes. * * @param[in] digestVerify Indicates if verify is enabled or not * * @param[in] pAuthResult Virtual pointer to digest * * @param[in] pHKDFSecret Pointer to HKDF salt or PRK * * @return CPA_STATUS_SUCCESS or CPA_STATUS_FAIL * *****************************************************************************/ CpaStatus LacSymQat_HashRequestParamsPopulate( icp_qat_fw_la_bulk_req_t *pReq, Cpa32U authOffsetInBytes, Cpa32U authLenInBytes, sal_service_t *pService, lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, Cpa32U qatPacketType, Cpa32U hashResultSize, CpaBoolean digestVerify, Cpa8U *pAuthResult, CpaCySymHashAlgorithm alg, void *pHKDFSecret); /** ****************************************************************************** * @ingroup LacSymQatHash * * * @description * This fn returns the QAT values for hash algorithm and nested fields * * * @param[in] pInstance Pointer to service instance. * * @param[in] qatHashMode Value for hash mode on the fw qat *interface. * * @param[in] apiHashMode Value for hash mode on the QA API. * * @param[in] apiHashAlgorithm Value for hash algorithm on the QA API. * * @param[out] pQatAlgorithm Pointer to return fw qat value for *algorithm. * @param[in] authKeyLenInBytes Length of the authentication key in bytes. * only used for ZUC-EIA/AES_CMAC algorithms. * default value 0 for the other algorithms. * @param[in] digestResultLenInBytes Length of the hash result in bytes * only used for ZUC-EIA/AES_CMAC algorithms. * default value 0 for the other algorithms. * @param[out] pQatNested Pointer to return fw qat value for nested. * * * @return * none * *****************************************************************************/ void LacSymQat_HashGetCfgData(CpaInstanceHandle pInstance, icp_qat_hw_auth_mode_t qatHashMode, CpaCySymHashMode apiHashMode, CpaCySymHashAlgorithm apiHashAlgorithm, icp_qat_hw_auth_algo_t *pQatAlgorithm, CpaBoolean *pQatNested, Cpa32U authKeyLenInBytes, Cpa32U digestResultLenInBytes); void LacSymQat_HashSetupReqParamsMetaData( icp_qat_la_bulk_req_ftr_t *pMsg, CpaInstanceHandle instanceHandle, const CpaCySymHashSetupData *pHashSetupData, CpaBoolean hashStateBuffer, icp_qat_hw_auth_mode_t qatHashMode, CpaBoolean digestVerify); #endif /* LAC_SYM_QAT_HASH_H */ lac_sym_qat_hash_defs_lookup.h000066400000000000000000000241201503624047500357360ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat_hash_defs_lookup.h * * @defgroup LacSymQatHashDefsLookup Hash Defs Lookup * * @ingroup LacSymQatHash * * API to be used for the hash defs lookup table. * *****************************************************************************/ #ifndef LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H #define LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H #include "cpa.h" #include "cpa_cy_sym.h" /** ****************************************************************************** * @ingroup LacSymQatHashDefsLookup * Finishing Hash algorithm * @description * This define points to the last available hash algorithm * @NOTE: If a new algorithm is added to the api, this #define * MUST be updated to being the last hash algorithm in the struct * CpaCySymHashAlgorithm in the file cpa_cy_sym.h *****************************************************************************/ #define LAC_HASH_ALG_END CPA_CY_SYM_HASH_SM3 /** ****************************************************************************** * @ingroup LacSymQatHashDefsLookup * Default authKeyLenInBytes * @description * This define the default value for authKeyLenInBytes used in * LacSymQat_HashAlgLookupGet and LacSymQat_HashDefsLookupGet *****************************************************************************/ #define LAC_SYM_HASH_DEFAULT_AUTHKEY_LENS 0 /** ****************************************************************************** * @ingroup LacSymQatHashDefsLookup * Default digestResultLenInBytes * @description * This define the default value for digestResultLenInBytes used in * LacSymQat_HashAlgLookupGet and LacSymQat_HashDefsLookupGet *****************************************************************************/ #define LAC_SYM_HASH_DEFAULT_DIGEST_LENS 0 /***************************************************************************/ /** ****************************************************************************** * @ingroup LacSymQatHashDefsLookup * hash algorithm specific structure * @description * This structure contain constants specific to an algorithm. *****************************************************************************/ typedef struct lac_sym_qat_hash_alg_info_s { Cpa32U digestLength; /**< Digest length in bytes */ Cpa32U blockLength; /**< Block length in bytes */ Cpa8U *initState; /**< Initialiser state for hash algorithm */ Cpa32U stateSize; /**< size of above state in bytes */ } lac_sym_qat_hash_alg_info_t; /** ****************************************************************************** * @ingroup LacSymQatHashDefsLookup * hash qat specific structure * @description * This structure contain constants as defined by the QAT for an * algorithm. *****************************************************************************/ typedef struct lac_sym_qat_hash_qat_info_s { Cpa32U algoEnc; /**< QAT Algorithm encoding */ Cpa32U authCounter; /**< Counter value for Auth */ Cpa32U state1Length; /**< QAT state1 length in bytes */ Cpa32U state2Length; /**< QAT state2 length in bytes */ } lac_sym_qat_hash_qat_info_t; /** ****************************************************************************** * @ingroup LacSymQatHashDefsLookup * hash defs structure * @description * This type contains pointers to the hash algorithm structure and * to the hash qat specific structure *****************************************************************************/ typedef struct lac_sym_qat_hash_defs_s { lac_sym_qat_hash_alg_info_t *algInfo; /**< pointer to hash info structure */ lac_sym_qat_hash_qat_info_t *qatInfo; /**< pointer to hash QAT info structure */ } lac_sym_qat_hash_defs_t; /** ******************************************************************************* * @ingroup LacSymQatHashDefsLookup * initialise the hash lookup table * * @description * This function initialises the digest lookup table. * * @note * This function does not have a corresponding shutdown function. * * @return CPA_STATUS_SUCCESS Operation successful * @return CPA_STATUS_RESOURCE Allocating of hash lookup table failed * *****************************************************************************/ CpaStatus LacSymQat_HashLookupInit(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacSymQatHashDefsLookup * get hash algorithm specific structure from lookup table * * @description * This function looks up the hash lookup array for a structure * containing data specific to a hash algorithm. The hashAlgorithm enum * value MUST be in the correct range prior to calling this function. * * @param[in] hashAlgorithm Hash Algorithm * @param[in] authKeyLenInBytes Length of the authentication key in bytes. * only used for ZUC-EIA/AES_CMAC algorithms. * default value 0 for the other algorithms. * @param[in] digestResultLenInBytes Length of the hash result in bytes * only used for ZUC-EIA/AES_CMAC algorithms. * default value 0 for the other algorithms. * @param[out] ppHashAlgInfo Hash Alg Info structure * * @return None * *****************************************************************************/ void LacSymQat_HashAlgLookupGet(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, lac_sym_qat_hash_alg_info_t **ppHashAlgInfo, Cpa32U authKeyLenInBytes, Cpa32U digestResultLenInBytes); /** ******************************************************************************* * @ingroup LacSymQatHashDefsLookup * get hash definitions from lookup table. * * @description * This function looks up the hash lookup array for a structure * containing data specific to a hash algorithm. This includes both * algorithm specific info and qat specific infro. The hashAlgorithm enum * value MUST be in the correct range prior to calling this function. * * @param[in] hashAlgorithm Hash Algorithm * @param[in] authKeyLenInBytes Length of the authentication key in bytes. * only used for ZUC-EIA/AES_CMAC algorithms. * default value 0 for the other algorithms. * @param[in] digestResultLenInBytes Length of the hash result in bytes * only used for ZUC-EIA/AES_CMAC algorithms. * default value 0 for the other algorithms. * @param[out] ppHashDefsInfo Hash Defs structure * * @return void * *****************************************************************************/ void LacSymQat_HashDefsLookupGet(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, lac_sym_qat_hash_defs_t **ppHashDefsInfo, Cpa32U authKeyLenInBytes, Cpa32U digestResultLenInBytes); #endif /* LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_qat_key.h000066400000000000000000000222651503624047500333000ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat_key.h * * @defgroup LacSymQatKey Key QAT * * @ingroup LacSymQat * * interfaces for populating qat structures for a key operation * *****************************************************************************/ #ifndef LAC_SYM_QAT_KEY_H #define LAC_SYM_QAT_KEY_H #include "cpa.h" #include "lac_sym.h" #include "icp_qat_fw_la.h" #include "cpa_cy_key.h" /** ****************************************************************************** * @ingroup LacSymQatKey * Number of bytes generated per iteration * @description * This define is the number of bytes generated per iteration *****************************************************************************/ #define LAC_SYM_QAT_KEY_SSL_BYTES_PER_ITERATION (16) /** ****************************************************************************** * @ingroup LacSymQatKey * Shift to calculate the number of iterations * @description * This define is the shift to calculate the number of iterations *****************************************************************************/ #define LAC_SYM_QAT_KEY_SSL_ITERATIONS_SHIFT LAC_16BYTE_ALIGNMENT_SHIFT /** ******************************************************************************* * @ingroup LacSymKey * Populate the SSL request * * @description * Populate the SSL request * * @param[out] pKeyGenReqHdr Pointer to Key Generation request Header * @param[out] pKeyGenReqMid Pointer to LW's 14/15 of Key Gen request * @param[in] generatedKeyLenInBytes Length of Key generated * @param[in] labelLenInBytes Length of Label * @param[in] secretLenInBytes Length of Secret * @param[in] iterations Number of iterations. This is related * to the label length. * * @return None * *****************************************************************************/ void LacSymQat_KeySslRequestPopulate( icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, Cpa32U generatedKeyLenInBytes, Cpa32U labelLenInBytes, Cpa32U secretLenInBytes, Cpa32U iterations); /** ******************************************************************************* * @ingroup LacSymKey * Populate the TLS request * * @description * Populate the TLS request * * @param[out] pKeyGenReq Pointer to Key Generation request * @param[in] generatedKeyLenInBytes Length of Key generated * @param[in] labelLenInBytes Length of Label * @param[in] secretLenInBytes Length of Secret * @param[in] seedLenInBytes Length of Seed * @param[in] cmdId Command Id to differentiate TLS versions * * @return None * *****************************************************************************/ void LacSymQat_KeyTlsRequestPopulate( icp_qat_fw_la_key_gen_common_t *pKeyGenReqParams, Cpa32U generatedKeyLenInBytes, Cpa32U labelLenInBytes, Cpa32U secretLenInBytes, Cpa8U seedLenInBytes, icp_qat_fw_la_cmd_id_t cmdId); /** ******************************************************************************* * @ingroup LacSymKey * Populate MGF request * * @description * Populate MGF request * * @param[out] pKeyGenReqHdr Pointer to Key Generation request Header * @param[out] pKeyGenReqMid Pointer to LW's 14/15 of Key Gen request * @param[in] seedLenInBytes Length of Seed * @param[in] maskLenInBytes Length of Mask * @param[in] hashLenInBytes Length of hash * * @return None * *****************************************************************************/ void LacSymQat_KeyMgfRequestPopulate( icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, Cpa8U seedLenInBytes, Cpa16U maskLenInBytes, Cpa8U hashLenInBytes); /** ******************************************************************************* * @ingroup LacSymKey * Populate the SSL key material input * * @description * Populate the SSL key material input * * @param[in] pService Pointer to service * @param[out] pSslKeyMaterialInput Pointer to SSL key material input * @param[in] pSeed Pointer to Seed * @param[in] labelPhysAddr Physical address of the label * @param[in] pSecret Pointer to Secret * * @return None * *****************************************************************************/ void LacSymQat_KeySslKeyMaterialInputPopulate( sal_service_t *pService, icp_qat_fw_la_ssl_key_material_input_t *pSslKeyMaterialInput, void *pSeed, Cpa64U labelPhysAddr, void *pSecret); /** ******************************************************************************* * @ingroup LacSymKey * Populate the TLS key material input * * @description * Populate the TLS key material input * * @param[in] pService Pointer to service * @param[out] pTlsKeyMaterialInput Pointer to TLS key material input * @param[in] pSeed Pointer to Seed * @param[in] labelPhysAddr Physical address of the label * * @return None * *****************************************************************************/ void LacSymQat_KeyTlsKeyMaterialInputPopulate( sal_service_t *pService, icp_qat_fw_la_tls_key_material_input_t *pTlsKeyMaterialInput, void *pSeed, Cpa64U labelPhysAddr); /** ******************************************************************************* * @ingroup LacSymKey * Populate the TLS HKDF key material input * * @description * Populate the TLS HKDF key material input * * @param[in] pService Pointer to service * @param[out] pTlsHKDFKeyMaterialInput Pointer to HKDF TLS key material input * @param[in] pKeyGenTlsHKDFOpData Pointer to HKDF key data * @param[in] sublabelPhysAddr Physical address of the sub label * @param[in] cmdId Command ID * * @return None * *****************************************************************************/ void LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( sal_service_t *pService, icp_qat_fw_la_hkdf_key_material_input_t *pTlsHKDFKeyMaterialInput, CpaCyKeyGenHKDFOpData *pKeyGenTlsHKDFOpData, Cpa64U subLabelPhysAddr, icp_qat_fw_la_cmd_id_t cmdId); #endif /* LAC_SYM_QAT_KEY_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_queue.h000066400000000000000000000112341503624047500327610ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file lac_sym_queue.h * * @defgroup LacSymQueue Symmetric request queueing functions * * @ingroup LacSym * * Function prototypes for sending/queuing symmetric requests *****************************************************************************/ #ifndef LAC_SYM_QUEUE_H #define LAC_SYM_QUEUE_H #include "cpa.h" #include "lac_session.h" #include "lac_sym.h" /** ******************************************************************************* * @ingroup LacSymQueue * Send a request message to the QAT, or queue it if necessary * * @description * This function will send a request message to the QAT. However, if a * blocking condition exists on the session (e.g. partial packet in flight, * precompute in progress), then the message will instead be pushed on to * the request queue for the session and will be sent later to the QAT * once the blocking condition is cleared. * * @param[in] instanceHandle Handle for instance of QAT * @param[in] pRequest Pointer to request cookie * @param[out] pSessionDesc Pointer to session descriptor * * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RESOURCE Problem Acquiring system resource * @retval CPA_STATUS_RETRY Failed to send message to QAT due to queue * full condition * *****************************************************************************/ CpaStatus LacSymQueue_RequestSend(const CpaInstanceHandle instanceHandle, lac_sym_bulk_cookie_t *pRequest, lac_session_desc_t *pSessionDesc); #endif /* LAC_SYM_QUEUE_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/include/lac_sym_stats.h000066400000000000000000000222061503624047500327740ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file lac_sym_stats.h * * @defgroup LacSymCommon Symmetric Common * * @ingroup LacSym * * Symmetric Common consists of common statistics, buffer and partial packet * functionality. * ***************************************************************************/ /** *************************************************************************** * @defgroup LacSymStats Statistics * * @ingroup LacSymCommon * * definitions and prototypes for LAC symmetric statistics. * * @lld_start * In the LAC API the stats fields are defined as Cpa32U but * OsalAtomic is the type that the atomic API supports. Therefore we * need to define a structure internally with the same fields as the API * stats structure, but each field must be of type OsalAtomic. * * - Incrementing Statistics:\n * Atomically increment the statistic on the internal stats structure. * * - Providing a copy of the stats back to the user:\n * Use atomicGet to read the atomic variable for each stat field in the * local internal stat structure. These values are saved in structure * (as defined by the LAC API) that the client will provide a pointer * to as a parameter. * * - Stats Show:\n * Use atomicGet to read the atomic variables for each field in the local * internal stat structure and print to the screen * * - Stats Array:\n * A macro is used to get the offset off the stat in the structure. This * offset is passed to a function which uses it to increment the stat * at that offset. * * @lld_end * ***************************************************************************/ /***************************************************************************/ #ifndef LAC_SYM_STATS_H #define LAC_SYM_STATS_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_cy_common.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ /** ******************************************************************************* * @ingroup LacSymStats * increment a symmetric statistic * * @description * Increment the statistics * * @param statistic IN The field in the symmetric statistics structure to be * incremented * @param instanceHandle IN engine Id Number * * @retval None * *****************************************************************************/ #ifndef DISABLE_STATS #define LAC_SYM_STAT_INC(statistic, instanceHandle) \ LacSym_StatsInc(offsetof(CpaCySymStats64, statistic), instanceHandle) #else #define LAC_SYM_STAT_INC(statistic, instanceHandle) #endif /** ******************************************************************************* * @ingroup LacSymStats * initialises the symmetric stats * * @description * This function allocates and initialises the stats array to 0 * * @param instanceHandle Instance Handle * * @retval CPA_STATUS_SUCCESS initialisation successful * @retval CPA_STATUS_RESOURCE array allocation failed * *****************************************************************************/ CpaStatus LacSym_StatsInit(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacSymStats * Frees the symmetric stats * * @description * This function frees the stats array * * @param instanceHandle Instance Handle * * @retval None * *****************************************************************************/ void LacSym_StatsFree(CpaInstanceHandle instanceHandle); void LacSym_StatsReset(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacSymStats * Increment a stat * * @description * This function incrementes a stat for a specific engine. * * @param offset IN offset of stat field in structure * @param instanceHandle IN qat Handle * * @retval None * *****************************************************************************/ #ifndef DISABLE_STATS void LacSym_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle); #endif /** ******************************************************************************* * @ingroup LacSymStats * Copy the contents of the statistics structure for an engine * * @description * This function copies the 32bit symmetric statistics structure for * a specific engine into an address supplied as a parameter. * * @param instanceHandle IN engine Id Number * @param pSymStats OUT stats structure to copy the stats for the into * * @retval None * *****************************************************************************/ void LacSym_Stats32CopyGet(CpaInstanceHandle instanceHandle, struct _CpaCySymStats *const pSymStats); /** ******************************************************************************* * @ingroup LacSymStats * Copy the contents of the statistics structure for an engine * * @description * This function copies the 64bit symmetric statistics structure for * a specific engine into an address supplied as a parameter. * * @param instanceHandle IN engine Id Number * @param pSymStats OUT stats structure to copy the stats for the into * * @retval None * *****************************************************************************/ void LacSym_Stats64CopyGet(CpaInstanceHandle instanceHandle, CpaCySymStats64 *const pSymStats); /** ******************************************************************************* * @ingroup LacSymStats * print the symmetric stats to standard output * * @description * The statistics for symmetric are printed to standard output. * * @retval None * * @see LacSym_StatsCopyGet() * *****************************************************************************/ void LacSym_StatsShow(CpaInstanceHandle instanceHandle); #endif /* LAC_SYM_STATS_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/key/000077500000000000000000000000001503624047500271215ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/key/lac_sym_key.c000066400000000000000000004105721503624047500315750ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_sym_key.c * * @ingroup LacSymKey * * This file contains the implementation of all keygen functionality * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_key.h" #include "cpa_cy_im.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "lac_sym.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_qat.h" #include "lac_sal.h" #include "lac_sym_key.h" #include "lac_sal_types_crypto.h" #include "sal_service_state.h" #include "lac_sym_qat_key.h" #include "lac_sym_hash_defs.h" #include "sal_statistics.h" #include "lac_hooks.h" /* Number of statistics */ #define LAC_KEY_NUM_STATS (sizeof(CpaCyKeyGenStats64) / sizeof(Cpa64U)) /* Array indexes to access HKDF sublabel values */ #define LAC_KEY_HKDF_DIGEST 0 #define LAC_KEY_HKDF_SUBLABELS_MAX (CPA_CY_HKDF_KEY_MAX_LABEL_COUNT + 1) #ifndef DISABLE_STATS #define LAC_KEY_STAT_INC(statistic, instanceHandle) \ do \ { \ sal_crypto_service_t *pService = NULL; \ LAC_ENSURE(instanceHandle != NULL, \ "LAC_KEY_STAT_INC - instanceHandle NULL\n"); \ pService = (sal_crypto_service_t *)instanceHandle; \ if (CPA_TRUE == \ pService->generic_service_info.stats->bKeyGenStatsEnabled) \ { \ osalAtomicInc(&pService->pLacKeyStats[offsetof(CpaCyKeyGenStats64, \ statistic) / \ sizeof(Cpa64U)]); \ } \ } while (0) /**< macro to increment a Key stat (derives offset into array of atomics) */ #else #define LAC_KEY_STAT_INC(statistic, instanceHandle) #endif #define LAC_KEY_STATS32_GET(keyStats, instanceHandle) \ do \ { \ int i; \ sal_crypto_service_t *pService = \ (sal_crypto_service_t *)instanceHandle; \ for (i = 0; i < LAC_KEY_NUM_STATS; i++) \ { \ ((Cpa32U *)&(keyStats))[i] = \ (Cpa32U)osalAtomicGet(&pService->pLacKeyStats[i]); \ } \ } while (0) /**< macro to get all 32bit Key stats (from internal array of atomics) */ #define LAC_KEY_STATS64_GET(keyStats, instanceHandle) \ do \ { \ int i; \ sal_crypto_service_t *pService = \ (sal_crypto_service_t *)instanceHandle; \ for (i = 0; i < LAC_KEY_NUM_STATS; i++) \ { \ ((Cpa64U *)&(keyStats))[i] = \ osalAtomicGet(&pService->pLacKeyStats[i]); \ } \ } while (0) /**< macro to get all 64bit Key stats (from internal array of atomics) */ #define IS_HKDF_UNSUPPORTED(cmdId, hkdfSupported) \ ((ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= cmdId && \ ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= cmdId) && \ !hkdfSupported) \ /**< macro to check whether the HKDF algorithm can be supported on the device */ /* Sublabel for HKDF TLS Key Generation, as defined in RFC8446. */ static const Cpa8U key256[] = {0, 16, 9, 't', 'l', 's', '1', '3', ' ', 'k', 'e', 'y', 0}; static const Cpa8U key384[] = {0, 32, 9, 't', 'l', 's', '1', '3', ' ', 'k', 'e', 'y', 0}; static const Cpa8U keyChaChaPoly[] = {0, 32, 9, 't', 'l', 's', '1', '3', ' ', 'k', 'e', 'y', 0}; /* Sublabel for HKDF TLS IV key Generation, as defined in RFC8446. */ static const Cpa8U iv256[] = {0, 12, 8, 't', 'l', 's', '1', '3', ' ', 'i', 'v', 0}; static const Cpa8U iv384[] = {0, 12, 8, 't', 'l', 's', '1', '3', ' ', 'i', 'v', 0}; /* Sublabel for HKDF TLS RESUMPTION key Generation, as defined in RFC8446. */ static const Cpa8U resumption256[] = {0, 32, 16, 't', 'l', 's', '1', '3', ' ', 'r', 'e', 's', 'u', 'm', 'p', 't', 'i', 'o', 'n', 0}; static const Cpa8U resumption384[] = {0, 48, 16, 't', 'l', 's', '1', '3', ' ', 'r', 'e', 's', 'u', 'm', 'p', 't', 'i', 'o', 'n', 0}; /* Sublabel for HKDF TLS FINISHED key Generation, as defined in RFC8446. */ static const Cpa8U finished256[] = { 0, 32, 14, 't', 'l', 's', '1', '3', ' ', 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', 0 }; static const Cpa8U finished384[] = { 0, 48, 14, 't', 'l', 's', '1', '3', ' ', 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', 0 }; /** ****************************************************************************** * @ingroup LacSymKey * Return the digest size of hash or cipher. * @description * Return the output key size of specific hash or cipher for specified * sub label * * @param[in] hash = SHA256, SHA384. * cipherSuite = AES_128_GCM, AES_256_GCM, AES_128_CCM, * AES_128_CCM_8 and CHACHA20_POLY1305. * subLabels = KEY, IV, RESUMPTION, and FINISHED. * @return the expected digest size of hash or cipher. * Each row in the array represents digest values for * hash, key, iv and resumption for the given cipher suite. * *****************************************************************************/ STATIC const Cpa32U cipherSuiteHKDFHashSizes[][LAC_KEY_HKDF_SUBLABELS_MAX] = { {0, 0, 0, 0, 0}, /* Not used */ {32, 16, 12, 32, 32}, /* AES_128_GCM_SHA256 */ {48, 32, 12, 48, 48}, /* AES_256_GCM_SHA384 */ {32, 32, 12, 32, 32}, /* CHACHA20_POLY1305_SHA256 */ {32, 16, 12, 32, 32}, /* AES_128_CCM_SHA256 */ {32, 16, 12, 32, 32} /* AES_128_CCM_8_SHA256 */ }; /** ****************************************************************************** * @ingroup LacSymKey * SSL/TLS stat type * * @description * This enum determines which stat should be incremented *****************************************************************************/ typedef enum { LAC_KEY_REQUESTS = 0, /**< Key requests sent */ LAC_KEY_REQUEST_ERRORS, /**< Key requests errors */ LAC_KEY_COMPLETED, /**< Key requests which received responses */ LAC_KEY_COMPLETED_ERRORS /**< Key requests which received responses with errors */ } lac_key_stat_type_t; /*** Local functions prototypes ***/ STATIC void LacSymKey_MgfHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, void *pOpaqueData, icp_qat_fw_comn_flags cmnRespFlags); STATIC CpaStatus LacSymKey_MgfSync(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const void *pKeyGenMgfOpData, CpaFlatBuffer *pGeneratedMaskBuffer, CpaBoolean bIsExtRequest); STATIC void LacSymKey_SslTlsHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, void *pOpaqueData, icp_qat_fw_comn_flags cmnRespFlags); STATIC CpaStatus LacSymKey_SslTlsSync(CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, icp_qat_fw_la_cmd_id_t lacCmdId, void *pKeyGenSslTlsOpData, Cpa8U hashAlgCipher, CpaFlatBuffer *pKeyGenOutpuData); /*** Implementation ***/ /** ****************************************************************************** * @ingroup LacSymKey * Get the instance handle. Support single handle. * @param[in] instanceHandle_in user supplied handle. * @retval CpaInstanceHandle the instance handle */ CpaInstanceHandle LacKey_GetHandle(CpaInstanceHandle instanceHandle_in) { CpaInstanceHandle instanceHandle = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } LAC_ENSURE_NOT_NULL(instanceHandle); return instanceHandle; } /** ******************************************************************************* * @ingroup LacSymKey * Perform SSL/TLS key gen operation * * @description * Perform SSL/TLS key gen operation * * @param[in] instanceHandle QAT device handle. * @param[in] pKeyGenCb Pointer to callback function to be invoked * when the operation is complete. * @param[in] pCallbackTag Opaque User Data for this specific call. * @param[in] lacCmdId Lac command ID (identify SSL & TLS ops) * @param[in] pKeyGenSslTlsOpData Structure containing all the data needed to * perform the SSL/TLS key generation * operation. * @param[in] hashAlgCipher Specifies the hash algorithm or cipher suite * to use. * According to RFC5246, this should be * "SHA-256 or a stronger standard hash * function." * For TLS1.3, this should be set to a cipher * suite in TLS operation that requires HKDF * key operations. * @param[out] pKeyGenOutputData pointer to where output result should be * written * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Function should be retried. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * *****************************************************************************/ STATIC CpaStatus LacSymKey_KeyGenSslTls_GenCommon(CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, icp_qat_fw_la_cmd_id_t lacCmdId, void *pKeyGenSslTlsOpData, Cpa8U hashAlgCipher, CpaFlatBuffer *pKeyGenOutputData); /** ****************************************************************************** * @ingroup LacSymKey * Increment stat for TLS or SSL operation * * @description * This is a generic function to update the stats for either a TLS or SSL * operation. * * @param[in] lacCmdId Indicate SSL or TLS operations * @param[in] statType Statistics Type * @param[in] instanceHandle Instance Handle * * @return None * *****************************************************************************/ STATIC void LacKey_StatsInc(icp_qat_fw_la_cmd_id_t lacCmdId, lac_key_stat_type_t statType, CpaInstanceHandle instanceHandle) { if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { switch (statType) { case LAC_KEY_REQUESTS: LAC_KEY_STAT_INC(numSslKeyGenRequests, instanceHandle); break; case LAC_KEY_REQUEST_ERRORS: LAC_KEY_STAT_INC(numSslKeyGenRequestErrors, instanceHandle); break; case LAC_KEY_COMPLETED: LAC_KEY_STAT_INC(numSslKeyGenCompleted, instanceHandle); break; case LAC_KEY_COMPLETED_ERRORS: LAC_KEY_STAT_INC(numSslKeyGenCompletedErrors, instanceHandle); break; default: LAC_ENSURE(CPA_FALSE, "Invalid statistics type"); break; } } else /* TLS v1.0/1.1 and 1.2*/ { switch (statType) { case LAC_KEY_REQUESTS: LAC_KEY_STAT_INC(numTlsKeyGenRequests, instanceHandle); break; case LAC_KEY_REQUEST_ERRORS: LAC_KEY_STAT_INC(numTlsKeyGenRequestErrors, instanceHandle); break; case LAC_KEY_COMPLETED: LAC_KEY_STAT_INC(numTlsKeyGenCompleted, instanceHandle); break; case LAC_KEY_COMPLETED_ERRORS: LAC_KEY_STAT_INC(numTlsKeyGenCompletedErrors, instanceHandle); break; default: LAC_ENSURE(CPA_FALSE, "Invalid statistics type"); break; } } } void LacKeygen_StatsShow(CpaInstanceHandle instanceHandle) { CpaCyKeyGenStats64 keyStats = {0}; LAC_KEY_STATS64_GET(keyStats, instanceHandle); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " Key Stats: " BORDER "\n" SEPARATOR); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " SSL Key Requests: %16llu " BORDER "\n" BORDER " SSL Key Request Errors: %16llu " BORDER "\n" BORDER " SSL Key Completed %16llu " BORDER "\n" BORDER " SSL Key Complete Errors: %16llu " BORDER "\n" SEPARATOR, keyStats.numSslKeyGenRequests, keyStats.numSslKeyGenRequestErrors, keyStats.numSslKeyGenCompleted, keyStats.numSslKeyGenCompletedErrors); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " TLS Key Requests: %16llu " BORDER "\n" BORDER " TLS Key Request Errors: %16llu " BORDER "\n" BORDER " TLS Key Completed %16llu " BORDER "\n" BORDER " TLS Key Complete Errors: %16llu " BORDER "\n" SEPARATOR, keyStats.numTlsKeyGenRequests, keyStats.numTlsKeyGenRequestErrors, keyStats.numTlsKeyGenCompleted, keyStats.numTlsKeyGenCompletedErrors); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " MGF Key Requests: %16llu " BORDER "\n" BORDER " MGF Key Request Errors: %16llu " BORDER "\n" BORDER " MGF Key Completed %16llu " BORDER "\n" BORDER " MGF Key Complete Errors: %16llu " BORDER "\n" SEPARATOR, keyStats.numMgfKeyGenRequests, keyStats.numMgfKeyGenRequestErrors, keyStats.numMgfKeyGenCompleted, keyStats.numMgfKeyGenCompletedErrors); } /** @ingroup LacSymKey */ CpaStatus cpaCyKeyGenQueryStats(CpaInstanceHandle instanceHandle_in, struct _CpaCyKeyGenStats *pSymKeyStats) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSymKeyStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSymKeyStats); #endif SAL_RUNNING_CHECK(instanceHandle); LAC_KEY_STATS32_GET(*pSymKeyStats, instanceHandle); return CPA_STATUS_SUCCESS; } /** @ingroup LacSymKey */ CpaStatus cpaCyKeyGenQueryStats64(CpaInstanceHandle instanceHandle_in, CpaCyKeyGenStats64 *pSymKeyStats) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSymKeyStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSymKeyStats); #endif SAL_RUNNING_CHECK(instanceHandle); LAC_KEY_STATS64_GET(*pSymKeyStats, instanceHandle); return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup LacSymKey * Return the size of the digest for a specific hash algorithm. * @description * Return the expected digest size based on the sha algorithm submitted. * The only supported value are sha256, sha384 and sha512. * * @param[in] hashAlgorithm either sha256, sha384 or sha512. * @return the expected size or 0 for an invalid hash. * *****************************************************************************/ STATIC Cpa32U getDigestSizeFromHashAlgo(CpaCySymHashAlgorithm hashAlgorithm) { switch (hashAlgorithm) { case CPA_CY_SYM_HASH_SHA256: return LAC_HASH_SHA256_DIGEST_SIZE; case CPA_CY_SYM_HASH_SHA384: return LAC_HASH_SHA384_DIGEST_SIZE; case CPA_CY_SYM_HASH_SHA512: return LAC_HASH_SHA512_DIGEST_SIZE; case CPA_CY_SYM_HASH_SM3: return LAC_HASH_SM3_DIGEST_SIZE; default: return 0; } } /** ****************************************************************************** * @ingroup LacSymKey * Return the hash algorithm for a specific cipher. * @description * Return the hash algorithm related to the cipher suite. * Supported hash's are SHA256, and SHA384. * * @param[in] cipherSuite AES_128_GCM, AES_256_GCM, AES_128_CCM, * AES_128_CCM_8 and CHACHA20_POLY1305. * @return the expected hash algorithm or 0 for an invalid cipher. * *****************************************************************************/ STATIC CpaCySymHashAlgorithm LacSymKey_getHashAlgorithmFromCipherSuiteHKDF( CpaCyKeyHKDFCipherSuite cipherSuite) { switch (cipherSuite) { case CPA_CY_HKDF_TLS_AES_128_GCM_SHA256: case CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256: case CPA_CY_HKDF_TLS_AES_128_CCM_SHA256: case CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256: return CPA_CY_SYM_HASH_SHA256; case CPA_CY_HKDF_TLS_AES_256_GCM_SHA384: return CPA_CY_SYM_HASH_SHA384; default: return CPA_CY_SYM_HASH_NONE; } } /** ****************************************************************************** * @ingroup LacSymKey * Key Generation MGF response handler * * @description * Handles Key Generation MGF response messages from the QAT. * * @param[in] lacCmdId Command id of the original request * @param[in] pOpaqueData Pointer to opaque data that was in request * @param[in] cmnRespFlags Indicates whether request succeeded * * @return void * *****************************************************************************/ STATIC void LacSymKey_MgfHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, void *pOpaqueData, icp_qat_fw_comn_flags cmnRespFlags) { CpaCyKeyGenMgfOpData *pMgfOpData = NULL; lac_sym_key_cookie_t *pCookie = NULL; CpaCyGenFlatBufCbFunc pKeyGenMgfCb = NULL; void *pCallbackTag = NULL; CpaFlatBuffer *pGeneratedKeyBuffer = NULL; CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean respStatusOk = CPA_FALSE; pCookie = (lac_sym_key_cookie_t *)pOpaqueData; if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(cmnRespFlags)) { status = CPA_STATUS_UNSUPPORTED; LAC_KEY_STAT_INC(numMgfKeyGenCompletedErrors, pCookie->instanceHandle); } else { respStatusOk = (ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)) ? CPA_TRUE : CPA_FALSE; if (CPA_TRUE == respStatusOk) { status = CPA_STATUS_SUCCESS; LAC_KEY_STAT_INC(numMgfKeyGenCompleted, pCookie->instanceHandle); } else { status = CPA_STATUS_FAIL; LAC_KEY_STAT_INC(numMgfKeyGenCompletedErrors, pCookie->instanceHandle); } } pKeyGenMgfCb = (CpaCyGenFlatBufCbFunc)(pCookie->pKeyGenCb); LAC_ASSERT_NOT_NULL(pKeyGenMgfCb); pMgfOpData = pCookie->pKeyGenOpData; pCallbackTag = pCookie->pCallbackTag; pGeneratedKeyBuffer = pCookie->pKeyGenOutputData; Lac_MemPoolEntryFree(pCookie); (*pKeyGenMgfCb)(pCallbackTag, status, pMgfOpData, pGeneratedKeyBuffer); } /** ****************************************************************************** * @ingroup LacSymKey * Synchronous mode of operation wrapper function * * @description * Wrapper function to implement synchronous mode of operation for * cpaCyKeyGenMgf and cpaCyKeyGenMgfExt function. * * @param[in] instanceHandle Instance handle * @param[in] pKeyGenCb Internal callback function pointer * @param[in] pCallbackTag Callback tag * @param[in] pKeyGenMgfOpData Pointer to user provided Op Data structure * @param[in] pGeneratedMaskBuffer Pointer to a buffer where generated mask * will be stored * @param[in] bIsExtRequest Indicates origin of function call; * if CPA_TRUE then the call comes from * cpaCyKeyGenMgfExt function, otherwise * from cpaCyKeyGenMgf * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Function should be retried. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Unsupported feature. * *****************************************************************************/ STATIC CpaStatus LacSymKey_MgfSync(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const void *pKeyGenMgfOpData, CpaFlatBuffer *pGeneratedMaskBuffer, CpaBoolean bIsExtRequest) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { if (CPA_TRUE == bIsExtRequest) { status = cpaCyKeyGenMgfExt( instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, (const CpaCyKeyGenMgfOpDataExt *)pKeyGenMgfOpData, pGeneratedMaskBuffer); } else { status = cpaCyKeyGenMgf(instanceHandle, LacSync_GenFlatBufCb, pSyncCallbackData, (const CpaCyKeyGenMgfOpData *)pKeyGenMgfOpData, pGeneratedMaskBuffer); } } else { /* Failure allocating sync cookie */ LAC_KEY_STAT_INC(numMgfKeyGenRequestErrors, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus syncStatus = CPA_STATUS_SUCCESS; syncStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_SYM_SYNC_CALLBACK_TIMEOUT, &status, NULL); /* If callback doesn't come back */ if (CPA_STATUS_SUCCESS != syncStatus) { LAC_KEY_STAT_INC(numMgfKeyGenCompletedErrors, instanceHandle); LAC_LOG_ERROR("Callback timed out"); status = syncStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /** ****************************************************************************** * @ingroup LacSymKey * Perform MGF key gen operation * * @description * This function performs MGF key gen operation. It is common for requests * coming from both cpaCyKeyGenMgf and cpaCyKeyGenMgfExt QAT API * functions. * * @param[in] instanceHandle Instance handle * @param[in] pKeyGenCb Pointer to callback function to be invoked * when the operation is complete. * @param[in] pCallbackTag Opaque User Data for this specific call. * @param[in] pOpData Pointer to the Op Data structure provided by * the user in API function call. For calls * originating from cpaCyKeyGenMgfExt it will * point to CpaCyKeyGenMgfOpDataExt type of * structure while for calls originating from * cpaCyKeyGenMgf it will point to * CpaCyKeyGenMgfOpData type of structure. * @param[in] pKeyGenMgfOpData Pointer to the user provided * CpaCyKeyGenMgfOpData structure. For calls * originating from cpaCyKeyGenMgf it will * point to the same structure as pOpData * parameter; for calls originating from * cpaCyKeyGenMgfExt it will point to the * baseOpData member of the * CpaCyKeyGenMgfOpDataExt structure passed in * as a parameter to the API function call. * @param[in] pGeneratedMaskBuffer Pointer to a buffer where generated mask * will be stored * @param[in] hashAlgorithm Indicates which hash algorithm is to be used * to perform MGF key gen operation. For calls * originating from cpaCyKeyGenMgf it will * always be CPA_CY_SYM_HASH_SHA1. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Function should be retried. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_UNSUPPORTED Unsupported feature. * *****************************************************************************/ STATIC CpaStatus LacSymKey_MgfCommon(const CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const void *pOpData, const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, CpaFlatBuffer *pGeneratedMaskBuffer, CpaCySymHashAlgorithm hashAlgorithm) { CpaStatus status = CPA_STATUS_SUCCESS; icp_qat_fw_la_bulk_req_t keyGenReq = {{0}}; icp_qat_la_bulk_req_hdr_t keyGenReqHdr = {{0}}; icp_qat_fw_la_key_gen_common_t keyGenReqMid = {{0}}; icp_qat_la_bulk_req_ftr_t keyGenReqFtr = {{{0}}}; Cpa8U *pMsgDummy = NULL; Cpa8U *pCacheDummyHdr = NULL; Cpa8U *pCacheDummyMid = NULL; Cpa8U *pCacheDummyFtr = NULL; sal_qat_content_desc_info_t contentDescInfo = {0}; lac_sym_key_cookie_t *pCookie = NULL; lac_sym_cookie_t *pSymCookie = NULL; sal_crypto_service_t *pService = NULL; Cpa64U inputPhysAddr = 0; Cpa64U outputPhysAddr = 0; Cpa64U seq_num = ICP_ADF_INVALID_SEND_SEQ; /* Structure initializer is supported by C99, but it is * not supported by some former Intel compiler. */ #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 1300) #pragma warning(disable : 188) #endif CpaCySymHashSetupData hashSetupData = {0}; #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 1300) #pragma warning(enable) #endif Cpa32U hashBlkSizeInBytes = 0; lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; icp_qat_fw_serv_specif_flags laCmdFlags = 0; icp_qat_fw_comn_flags cmnRequestFlags = ICP_QAT_FW_COMN_FLAGS_BUILD( QAT_COMN_PTR_TYPE_FLAT, QAT_COMN_CD_FLD_TYPE_64BIT_ADR); #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pKeyGenMgfOpData); LAC_CHECK_NULL_PARAM(pGeneratedMaskBuffer); LAC_CHECK_NULL_PARAM(pGeneratedMaskBuffer->pData); LAC_CHECK_NULL_PARAM(pKeyGenMgfOpData->seedBuffer.pData); LAC_ASSERT_NOT_NULL(pKeyGenCb); /* Maximum seed length for MGF1 request */ if (pKeyGenMgfOpData->seedBuffer.dataLenInBytes > ICP_QAT_FW_LA_MGF_SEED_LEN_MAX) { LAC_INVALID_PARAM_LOG("seedBuffer.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* Maximum mask length for MGF1 request */ if (pKeyGenMgfOpData->maskLenInBytes > ICP_QAT_FW_LA_MGF_MASK_LEN_MAX) { LAC_INVALID_PARAM_LOG("maskLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* check for enough space in the flat buffer */ if (pKeyGenMgfOpData->maskLenInBytes > pGeneratedMaskBuffer->dataLenInBytes) { LAC_INVALID_PARAM_LOG("pGeneratedMaskBuffer.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } #endif pService = (sal_crypto_service_t *)instanceHandle; /* Get hash alg info */ LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, LAC_SYM_HASH_DEFAULT_AUTHKEY_LENS, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); /* Allocate the cookie */ do { pCookie = (lac_sym_key_cookie_t *)Lac_MemPoolEntryAlloc( pService->lac_sym_cookie_pool); if (NULL == pCookie) { LAC_LOG_ERROR("Cannot get mem pool entry"); status = CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pCookie) { osalYield(); } else { pSymCookie = (lac_sym_cookie_t *)pCookie; pSymCookie->cookieType = LAC_SYM_KEY_COOKIE_TYPE; } } while ((void *)CPA_STATUS_RETRY == pCookie); if (CPA_STATUS_SUCCESS == status) { /* populate the cookie */ pCookie->instanceHandle = instanceHandle; pCookie->pCallbackTag = pCallbackTag; pCookie->pKeyGenOpData = (void *)LAC_CONST_PTR_CAST(pOpData); pCookie->pKeyGenCb = pKeyGenCb; pCookie->pKeyGenOutputData = pGeneratedMaskBuffer; hashSetupData.hashAlgorithm = hashAlgorithm; hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN; hashSetupData.digestResultLenInBytes = pHashAlgInfo->digestLength; /* Populate the CD ctrl Block (LW 27 - LW 31) * and the CD Hash HW setup block*/ LacSymQat_HashContentDescInit( &(keyGenReqFtr), instanceHandle, &hashSetupData, /* point to base of hw setup block */ (Cpa8U *)pCookie->contentDesc, LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW, ICP_QAT_FW_SLICE_DRAM_WR, ICP_QAT_HW_AUTH_MODE0, /* just a plain hash */ CPA_FALSE, /* Not using sym Constants Table in Shared SRAM */ CPA_FALSE, /* not using the optimised Content Desc */ NULL, &hashBlkSizeInBytes); /* Populate the Req param LW 14-26 */ LacSymQat_KeyMgfRequestPopulate( &keyGenReqHdr, &keyGenReqMid, (Cpa8U)pKeyGenMgfOpData->seedBuffer.dataLenInBytes, (Cpa16U)pKeyGenMgfOpData->maskLenInBytes, (Cpa8U)pHashAlgInfo->digestLength); contentDescInfo.pData = pCookie->contentDesc; contentDescInfo.hardwareSetupBlockPhys = LAC_MEM_CAST_PTR_TO_UINT64(pSymCookie->keyContentDescDevAddr); contentDescInfo.hwBlkSzQuadWords = LAC_BYTES_TO_QUADWORDS(hashBlkSizeInBytes); /* Populate common request fields */ inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, pKeyGenMgfOpData->seedBuffer.pData)); if (inputPhysAddr == 0) { LAC_LOG_ERROR("Unable to get the seed buffer physical address\n"); status = CPA_STATUS_FAIL; } outputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pGeneratedMaskBuffer->pData)); if (outputPhysAddr == 0) { LAC_LOG_ERROR("Unable to get the physical address of the mask\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /* Make up the full keyGenReq struct from its constituents */ pMsgDummy = (Cpa8U *)&(keyGenReq); pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); osalMemCopy(pMsgDummy, pCacheDummyHdr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); osalMemSet((pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), 0, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_MID_IN_LW), pCacheDummyMid, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_MID_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), pCacheDummyFtr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)&(keyGenReq), &(contentDescInfo)); SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&keyGenReq, ICP_QAT_FW_COMN_REQ_CPM_FW_LA, ICP_QAT_FW_LA_CMD_MGF1, cmnRequestFlags, laCmdFlags, 0); /* * MGF uses a flat buffer but we can use zero for source and * dest length because the firmware will use the seed length, * hash length and mask length to find source length. * */ SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)&(keyGenReq), pCookie, LAC_SYM_KEY_QAT_PTR_TYPE, inputPhysAddr, outputPhysAddr, 0, 0); status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, (void *)&(keyGenReq), LAC_QAT_SYM_REQ_SZ_LW, &seq_num); } if (CPA_STATUS_SUCCESS == status) { /* Update stats */ LAC_KEY_STAT_INC(numMgfKeyGenRequests, instanceHandle); LAC_MEM_POOL_BLK_SET_OPAQUE(pCookie, seq_num); } else { LAC_KEY_STAT_INC(numMgfKeyGenRequestErrors, instanceHandle); /* clean up memory */ if (NULL != pCookie) { Lac_MemPoolEntryFree(pCookie); } } return status; } /** * cpaCyKeyGenMgf */ CpaStatus cpaCyKeyGenMgf(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, CpaFlatBuffer *pGeneratedMaskBuffer) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pKeyGenCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pKeyGenMgfOpData, (LAC_ARCH_UINT)pGeneratedMaskBuffer); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or sym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif #ifdef ICP_PARAM_CHECK /* Param check specific for Ext function, rest of parameters validated * in LacSymKey_MgfCommon */ LAC_CHECK_NULL_PARAM(pKeyGenMgfOpData); #endif /* If synchronous Operation */ if (NULL == pKeyGenCb) { return LacSymKey_MgfSync(instanceHandle, pKeyGenCb, pCallbackTag, (const void *)pKeyGenMgfOpData, pGeneratedMaskBuffer, CPA_FALSE); } /* Asynchronous Operation */ return LacSymKey_MgfCommon(instanceHandle, pKeyGenCb, pCallbackTag, (const void *)pKeyGenMgfOpData, pKeyGenMgfOpData, pGeneratedMaskBuffer, CPA_CY_SYM_HASH_SHA1); } /** * cpaCyKeyGenMgfExt */ CpaStatus cpaCyKeyGenMgfExt(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenMgfOpDataExt *pKeyGenMgfOpDataExt, CpaFlatBuffer *pGeneratedMaskBuffer) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pKeyGenCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pKeyGenMgfOpDataExt, (LAC_ARCH_UINT)pGeneratedMaskBuffer); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK /* check for valid acceleration handle */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); #endif /* check LAC is initialised */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK /* check this is a crypto or sym instance */ SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif /* If synchronous Operation */ if (NULL == pKeyGenCb) { return LacSymKey_MgfSync(instanceHandle, pKeyGenCb, pCallbackTag, (const void *)pKeyGenMgfOpDataExt, pGeneratedMaskBuffer, CPA_TRUE); } #ifdef ICP_PARAM_CHECK /* Param check specific for Ext function, rest of parameters validated * in LacSymKey_MgfCommon */ LAC_CHECK_NULL_PARAM(pKeyGenMgfOpDataExt); if (CPA_CY_SYM_HASH_MD5 > pKeyGenMgfOpDataExt->hashAlgorithm || CPA_CY_SYM_HASH_SHA512 < pKeyGenMgfOpDataExt->hashAlgorithm) { LAC_INVALID_PARAM_LOG("hashAlgorithm"); return CPA_STATUS_INVALID_PARAM; } #endif /* Asynchronous Operation */ return LacSymKey_MgfCommon(instanceHandle, pKeyGenCb, pCallbackTag, (const void *)pKeyGenMgfOpDataExt, &pKeyGenMgfOpDataExt->baseOpData, pGeneratedMaskBuffer, pKeyGenMgfOpDataExt->hashAlgorithm); } /** ****************************************************************************** * @ingroup LacSymKey * Key Generation SSL & TLS response handler * * @description * Handles Key Generation SSL & TLS response messages from the QAT. * * @param[in] lacCmdId Command id of the original request * @param[in] pOpaqueData Pointer to opaque data that was in request * @param[in] cmnRespFlags LA response flags * * @return void * *****************************************************************************/ STATIC void LacSymKey_SslTlsHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, void *pOpaqueData, icp_qat_fw_comn_flags cmnRespFlags) { void *pSslTlsOpData = NULL; CpaCyGenFlatBufCbFunc pKeyGenSslTlsCb = NULL; lac_sym_key_cookie_t *pCookie = NULL; void *pCallbackTag = NULL; CpaFlatBuffer *pGeneratedKeyBuffer = NULL; CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean respStatusOk = CPA_FALSE; pCookie = (lac_sym_key_cookie_t *)pOpaqueData; if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(cmnRespFlags)) { status = CPA_STATUS_UNSUPPORTED; LacKey_StatsInc( lacCmdId, LAC_KEY_COMPLETED_ERRORS, pCookie->instanceHandle); } else { respStatusOk = (ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)) ? CPA_TRUE : CPA_FALSE; if (CPA_TRUE == respStatusOk) { LacKey_StatsInc( lacCmdId, LAC_KEY_COMPLETED, pCookie->instanceHandle); } else { status = CPA_STATUS_FAIL; LacKey_StatsInc( lacCmdId, LAC_KEY_COMPLETED_ERRORS, pCookie->instanceHandle); } } pSslTlsOpData = pCookie->pKeyGenOpData; pKeyGenSslTlsCb = (CpaCyGenFlatBufCbFunc)(pCookie->pKeyGenCb); LAC_ASSERT_NOT_NULL(pKeyGenSslTlsCb); pCallbackTag = pCookie->pCallbackTag; pGeneratedKeyBuffer = pCookie->pKeyGenOutputData; Lac_MemPoolEntryFree(pCookie); (*pKeyGenSslTlsCb)( pCallbackTag, status, pSslTlsOpData, pGeneratedKeyBuffer); } /** ******************************************************************************* * @ingroup LacSymKey * Synchronous mode of operation function wrapper for performing SSL/TLS * key gen operation * * @description * Synchronous mode of operation function wrapper for performing SSL/TLS * key gen operation * * @param[in] instanceHandle QAT device handle. * @param[in] pKeyGenCb Pointer to callback function to be invoked * when the operation is complete. * @param[in] pCallbackTag Opaque User Data for this specific call. * @param[in] lacCmdId Lac command ID (identify SSL & TLS ops) * @param[in] pKeyGenSslTlsOpData Structure containing all the data needed to * perform the SSL/TLS key generation * operation. * @param[in] hashAlgCipher Specifies the hash algorithm or cipher suite * to use. * According to RFC5246, this should be * "SHA-256 or a stronger standard hash * function." * For TLS1.3, this should be set to a cipher * suite in TLS operation that requires HKDF * key operations. * @param[out] pKeyGenOutputData Pointer to where output result should be * written * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Function should be retried. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * *****************************************************************************/ STATIC CpaStatus LacSymKey_SslTlsSync(CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, icp_qat_fw_la_cmd_id_t lacCmdId, void *pKeyGenSslTlsOpData, Cpa8U hashAlgCipher, CpaFlatBuffer *pKeyGenOutpuData) { lac_sync_op_data_t *pSyncCallbackData = NULL; CpaStatus status = CPA_STATUS_SUCCESS; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { status = LacSymKey_KeyGenSslTls_GenCommon(instanceHandle, pKeyGenCb, pSyncCallbackData, lacCmdId, pKeyGenSslTlsOpData, hashAlgCipher, pKeyGenOutpuData); } else { /* Failure allocating sync cookie */ LacKey_StatsInc(lacCmdId, LAC_KEY_REQUEST_ERRORS, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus syncStatus = CPA_STATUS_SUCCESS; syncStatus = LacSync_WaitForCallback( pSyncCallbackData, LAC_SYM_SYNC_CALLBACK_TIMEOUT, &status, NULL); /* If callback doesn't come back */ if (CPA_STATUS_SUCCESS != syncStatus) { LacKey_StatsInc(lacCmdId, LAC_KEY_COMPLETED_ERRORS, instanceHandle); LAC_LOG_ERROR("Callback timed out"); status = syncStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } STATIC CpaStatus computeHashKey(CpaFlatBuffer *secret, CpaFlatBuffer *hash, CpaCySymHashAlgorithm *hashAlgorithm) { CpaStatus status = CPA_STATUS_SUCCESS; switch (*hashAlgorithm) { case CPA_CY_SYM_HASH_MD5: status = osalHashMD5Full( secret->pData, hash->pData, secret->dataLenInBytes); break; case CPA_CY_SYM_HASH_SHA1: status = osalHashSHA1Full( secret->pData, hash->pData, secret->dataLenInBytes); break; case CPA_CY_SYM_HASH_SHA256: status = osalHashSHA256Full( secret->pData, hash->pData, secret->dataLenInBytes); break; case CPA_CY_SYM_HASH_SHA384: status = osalHashSHA384Full( secret->pData, hash->pData, secret->dataLenInBytes); break; case CPA_CY_SYM_HASH_SHA512: status = osalHashSHA512Full( secret->pData, hash->pData, secret->dataLenInBytes); break; default: status = CPA_STATUS_FAIL; } return status; } /** ******************************************************************************* * @ingroup LacSymKey * Key generation for TLS v1.3 using HKDF * @description * Generates TLSv1.3 key * * @param[in] instanceHandle Instance handle * @param[in] pKeyGenSslTlsOpData Pointer to SSL/TKS key data * @param[in] pKeyGenReqFtr Pointer to icp_qat_la_bulk_req_ftr * @param[in] pSymCookie Pointer to lac_sym_cookie * @param[out] pHashSetupData pointer to Hash setup data * @param[out] pKeyGenReq Pointer to icp_qat_fw_la_bulk_req * @param[out] pKeyGenReqMid Pointer to icp_qat_fw_la_key_gen_common * @param[in] cmdId Keygen operation to perform. * @param[in] hashAlgCipher Specifies the cipher we are using. * This should be set to a * cipher suite in TLS operation that * requires HKDF key operations. * *****************************************************************************/ STATIC CpaStatus LacSymKey_KeyGenSslTls3GenCommon(CpaInstanceHandle instanceHandle, void *pKeyGenSslTlsOpData, icp_qat_la_bulk_req_ftr_t *pKeyGenReqFtr, lac_sym_cookie_t *pSymCookie, CpaCySymHashSetupData *pHashSetupData, icp_qat_fw_la_bulk_req_t *pKeyGenReq, icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, icp_qat_fw_la_cmd_id_t lacCmdId, Cpa8U hashAlgCipher) { Cpa32U labelInfo = 0; Cpa64U subLabelPhysAddr = 0; CpaStatus status = CPA_STATUS_FAIL; CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pKeyGenReqFtr->cd_ctrl); CpaCySymHashNestedModeSetupData *pNestedModeSetupData = &(pHashSetupData->nestedModeSetupData); lac_sym_qat_hash_state_buffer_info_t hashStateBufferInfo = {0, 0, 0, 0}; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; hashStateBufferInfo.pData = ((lac_sym_key_cookie_t *)pSymCookie)->hashStateBuffer; hashStateBufferInfo.pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64(pSymCookie->keyHashStateBufferDevAddr); LacSymQat_HashSetupReqParamsMetaData(pKeyGenReqFtr, instanceHandle, pHashSetupData, CPA_FALSE, /* no hash prefix buffer */ ICP_QAT_HW_AUTH_MODE2, /* TLS 1.3 */ CPA_FALSE); hashStateBufferInfo.prefixAadSzQuadWords = LAC_BYTES_TO_QUADWORDS( pKeyGenReqFtr->serv_specif_rqpars.u2.inner_prefix_sz + pHashControlBlock->outer_prefix_sz); /* Copy prefix data into hash state buffer */ LacSymQat_HashStatePrefixAadBufferPopulate( &hashStateBufferInfo, pKeyGenReqFtr, pNestedModeSetupData->pInnerPrefixData, (Cpa8U)pNestedModeSetupData->innerPrefixLenInBytes, pNestedModeSetupData->pOuterPrefixData, (Cpa8U)pNestedModeSetupData->outerPrefixLenInBytes); /* Firmware only looks at hash state buffer pointer and the * hash state buffer size so all other fields are set to 0 */ status = LacSymQat_HashRequestParamsPopulate( pKeyGenReq, 0, /* Auth offset */ 0, /* Auth length */ &(pService->generic_service_info), &hashStateBufferInfo, /* Hash state prefix buffer */ ICP_QAT_FW_LA_PARTIAL_NONE, 0, /* Hash result size */ CPA_FALSE, NULL, CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ pKeyGenTlsOpData->secret); /* IKM or PRK */ if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("LacSymQat_HashRequestParamsPopulate failed\n"); } if (CPA_STATUS_SUCCESS == status) { if (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= lacCmdId && ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND >= lacCmdId) { /* TLS v1.3 */ labelInfo = pKeyGenTlsOpData->infoLen; subLabelPhysAddr = 0; /* No subLabels used */ } else if (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == lacCmdId || ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL == lacCmdId) { /* TLS v1.3 LABEL */ /* For EXTRACT, EXPAND, FW expects info to be passed as label */ labelInfo = pKeyGenTlsOpData->numLabels; /* Number of Labels */ /* Get physical address of subLabels */ switch (hashAlgCipher) { case CPA_CY_HKDF_TLS_AES_128_GCM_SHA256: case CPA_CY_HKDF_TLS_AES_128_CCM_SHA256: case CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256: subLabelPhysAddr = pService->pTlsHKDFSubLabel->sublabelPhysAddr256; break; case CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256: subLabelPhysAddr = pService->pTlsHKDFSubLabel->sublabelPhysAddrChaChaPoly; break; case CPA_CY_HKDF_TLS_AES_256_GCM_SHA384: subLabelPhysAddr = pService->pTlsHKDFSubLabel->sublabelPhysAddr384; break; default: break; } } LacSymQat_KeyTlsRequestPopulate( pKeyGenReqMid, cipherSuiteHKDFHashSizes[hashAlgCipher][LAC_KEY_HKDF_DIGEST], labelInfo, pKeyGenTlsOpData->secretLen, (Cpa8U)pKeyGenTlsOpData->seedLen, lacCmdId); LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( &(pService->generic_service_info), &(((lac_sym_key_cookie_t *)pSymCookie)->u.tlsHKDFKeyInput), pKeyGenTlsOpData, subLabelPhysAddr, lacCmdId); } return status; } STATIC CpaStatus LacSymKey_KeyGenSslTls_GenCommon(CpaInstanceHandle instanceHandle, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, icp_qat_fw_la_cmd_id_t lacCmdId, void *pKeyGenSslTlsOpData, Cpa8U hashAlgCipher, CpaFlatBuffer *pKeyGenOutputData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean precompute = CPA_FALSE; icp_qat_fw_la_bulk_req_t keyGenReq = {{0}}; icp_qat_la_bulk_req_hdr_t keyGenReqHdr = {{0}}; icp_qat_fw_la_key_gen_common_t keyGenReqMid = {{0}}; icp_qat_la_bulk_req_ftr_t keyGenReqFtr = {{{0}}}; Cpa8U *pMsgDummy = NULL; Cpa8U *pCacheDummyHdr = NULL; Cpa8U *pCacheDummyMid = NULL; Cpa8U *pCacheDummyFtr = NULL; lac_sym_key_cookie_t *pCookie = NULL; lac_sym_cookie_t *pSymCookie = NULL; Cpa64U inputPhysAddr = 0; Cpa64U outputPhysAddr = 0; /* Structure initializer is supported by C99, but it is * not supported by some former Intel compiler. */ #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 1300) #pragma warning(disable : 188) #endif CpaCySymHashSetupData hashSetupData = {0}; sal_qat_content_desc_info_t contentDescInfo = {0}; #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER < 1300) #pragma warning(enable) #endif Cpa32U hashBlkSizeInBytes = 0; Cpa32U tlsPrefixLen = 0; CpaFlatBuffer inputSecret = {0}; CpaFlatBuffer hashKeyOutput = {0}; Cpa32U uSecretLen = 0; CpaCySymHashNestedModeSetupData *pNestedModeSetupData = &(hashSetupData.nestedModeSetupData); icp_qat_fw_serv_specif_flags laCmdFlags = 0; icp_qat_fw_comn_flags cmnRequestFlags = ICP_QAT_FW_COMN_FLAGS_BUILD( QAT_COMN_PTR_TYPE_FLAT, QAT_COMN_CD_FLD_TYPE_64BIT_ADR); sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; Cpa64U seq_num = ICP_ADF_INVALID_SEND_SEQ; /* If synchronous Operation */ if (NULL == pKeyGenCb) { return LacSymKey_SslTlsSync(instanceHandle, LacSync_GenFlatBufCb, pCallbackTag, lacCmdId, pKeyGenSslTlsOpData, hashAlgCipher, pKeyGenOutputData); } /* Allocate the cookie */ do { pCookie = (lac_sym_key_cookie_t *)Lac_MemPoolEntryAlloc( pService->lac_sym_cookie_pool); if (NULL == pCookie) { LAC_LOG_ERROR("Cannot get mem pool entry"); status = CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pCookie) { osalYield(); } else { pSymCookie = (lac_sym_cookie_t *)pCookie; pSymCookie->cookieType = LAC_SYM_KEY_COOKIE_TYPE; } } while ((void *)CPA_STATUS_RETRY == pCookie); if (CPA_STATUS_SUCCESS == status) { icp_qat_hw_auth_mode_t qatHashMode = 0; if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { qatHashMode = ICP_QAT_HW_AUTH_MODE0; } else /* TLS v1.0/1.1 or v1.2 */ { qatHashMode = ICP_QAT_HW_AUTH_MODE2; } pCookie->instanceHandle = pService; pCookie->pCallbackTag = pCallbackTag; pCookie->pKeyGenCb = pKeyGenCb; pCookie->pKeyGenOpData = pKeyGenSslTlsOpData; pCookie->pKeyGenOutputData = pKeyGenOutputData; hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_NESTED; if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { /* SSL3 */ hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; hashSetupData.digestResultLenInBytes = LAC_HASH_MD5_DIGEST_SIZE; pNestedModeSetupData->outerHashAlgorithm = CPA_CY_SYM_HASH_MD5; pNestedModeSetupData->pInnerPrefixData = NULL; pNestedModeSetupData->innerPrefixLenInBytes = 0; pNestedModeSetupData->pOuterPrefixData = NULL; pNestedModeSetupData->outerPrefixLenInBytes = 0; } else if ((ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= lacCmdId) && (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= lacCmdId)) { /* TLS v1.3 */ CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; CpaCySymHashAlgorithm hashAlgorithm = LacSymKey_getHashAlgorithmFromCipherSuiteHKDF(hashAlgCipher); /* Set HASH data */ hashSetupData.hashAlgorithm = hashAlgorithm; /* Calculate digest length from the HASH type */ hashSetupData.digestResultLenInBytes = cipherSuiteHKDFHashSizes[hashAlgCipher][LAC_KEY_HKDF_DIGEST]; /* Outer Hash type is the same as inner hash type */ pNestedModeSetupData->outerHashAlgorithm = hashAlgorithm; /* EXPAND (PRK): * Outer prefix = secret, inner prefix = secret * EXTRACT (SEED/SALT) * Outer prefix = seed, inner prefix = seed * Secret <= 64 Bytes * We do not pre compute as secret can't be larger than 64 bytes */ if ((ICP_QAT_FW_LA_CMD_HKDF_EXPAND == lacCmdId) || (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == lacCmdId)) { pNestedModeSetupData->pInnerPrefixData = pKeyGenTlsOpData->secret; pNestedModeSetupData->pOuterPrefixData = pKeyGenTlsOpData->secret; pNestedModeSetupData->innerPrefixLenInBytes = pKeyGenTlsOpData->secretLen; pNestedModeSetupData->outerPrefixLenInBytes = pKeyGenTlsOpData->secretLen; } else { pNestedModeSetupData->pInnerPrefixData = pKeyGenTlsOpData->seed; pNestedModeSetupData->pOuterPrefixData = pKeyGenTlsOpData->seed; pNestedModeSetupData->innerPrefixLenInBytes = pKeyGenTlsOpData->seedLen; pNestedModeSetupData->outerPrefixLenInBytes = pKeyGenTlsOpData->seedLen; } } else if (ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == lacCmdId) { /* TLS v1.2 */ CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; CpaCySymHashAlgorithm hashAlgorithm = (CpaCySymHashAlgorithm)hashAlgCipher; uSecretLen = pKeyGenTlsOpData->secret.dataLenInBytes; hashSetupData.hashAlgorithm = hashAlgorithm; hashSetupData.digestResultLenInBytes = (Cpa32U)getDigestSizeFromHashAlgo(hashAlgorithm); pNestedModeSetupData->outerHashAlgorithm = (CpaCySymHashAlgorithm)hashAlgorithm; if (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == pKeyGenTlsOpData->tlsOp || CPA_CY_KEY_TLS_OP_USER_DEFINED == pKeyGenTlsOpData->tlsOp) { switch (hashAlgorithm) { case CPA_CY_SYM_HASH_SM3: precompute = CPA_FALSE; break; case CPA_CY_SYM_HASH_SHA256: if (uSecretLen > ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX) { precompute = CPA_TRUE; } break; case CPA_CY_SYM_HASH_SHA384: case CPA_CY_SYM_HASH_SHA512: if (uSecretLen > ICP_QAT_FW_LA_TLS_SECRET_LEN_MAX) { precompute = CPA_TRUE; } break; default: break; } } if (CPA_TRUE == precompute) { /* Case when secret > algorithm block size */ /* RFC 4868: For SHA-256 Block size is 512 bits, for SHA-384 and * SHA-512 Block size is 1024 bits */ /* Initialize pointer where SHAxxx key will go. */ hashKeyOutput.pData = &pCookie->hashKeyBuffer[0]; hashKeyOutput.dataLenInBytes = hashSetupData.digestResultLenInBytes; computeHashKey(&pKeyGenTlsOpData->secret, &hashKeyOutput, &hashSetupData.hashAlgorithm); /* outer prefix = secret , inner prefix = secret * secret < 64 bytes */ pNestedModeSetupData->pInnerPrefixData = hashKeyOutput.pData; pNestedModeSetupData->pOuterPrefixData = hashKeyOutput.pData; pNestedModeSetupData->innerPrefixLenInBytes = hashKeyOutput.dataLenInBytes; pNestedModeSetupData->outerPrefixLenInBytes = hashKeyOutput.dataLenInBytes; } else { /* outer prefix = secret , inner prefix = secret * secret <= 64 bytes */ pNestedModeSetupData->pInnerPrefixData = pKeyGenTlsOpData->secret.pData; pNestedModeSetupData->pOuterPrefixData = pKeyGenTlsOpData->secret.pData; pNestedModeSetupData->innerPrefixLenInBytes = pKeyGenTlsOpData->secret.dataLenInBytes; pNestedModeSetupData->outerPrefixLenInBytes = pKeyGenTlsOpData->secret.dataLenInBytes; } } else { /* TLS v1.0/v1.1 */ CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; CpaCySymHashAlgorithm hashAlgorithm = CPA_CY_SYM_HASH_SHA1; hashSetupData.hashAlgorithm = hashAlgorithm; hashSetupData.digestResultLenInBytes = LAC_HASH_MD5_DIGEST_SIZE; pNestedModeSetupData->outerHashAlgorithm = CPA_CY_SYM_HASH_MD5; uSecretLen = pKeyGenTlsOpData->secret.dataLenInBytes; /* We want to handle pre_master_secret > 128 bytes therefore we * only verify if the current operation is Master Secret Derive * or user defined. * The other operations remain unchanged. */ if ((uSecretLen > ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX) && (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == pKeyGenTlsOpData->tlsOp || CPA_CY_KEY_TLS_OP_USER_DEFINED == pKeyGenTlsOpData->tlsOp)) { /* Since the pre_master_secret is > 128, we split the input * pre_master_secret in 2 halves and compute the MD5 of the * first half and the SHA1 on the second half. */ CpaCySymHashAlgorithm hashAlgorithm = CPA_CY_SYM_HASH_MD5; /* secret = [s1 | s2 ] * s1 = outer prefix, s2 = inner prefix * length of s1 and s2 = ceil(secret_length / 2) * (secret length + 1)/2 will always give the ceil as division * by 2 * (>>1) will give the smallest integral value not less than arg */ tlsPrefixLen = (pKeyGenTlsOpData->secret.dataLenInBytes + 1) >> 1; inputSecret.dataLenInBytes = tlsPrefixLen; inputSecret.pData = pKeyGenTlsOpData->secret.pData; /* Initialize pointer where MD5 key will go. */ hashKeyOutput.pData = &pCookie->hashKeyBuffer[0]; hashKeyOutput.dataLenInBytes = LAC_HASH_MD5_DIGEST_SIZE; computeHashKey(&inputSecret, &hashKeyOutput, &hashAlgorithm); pNestedModeSetupData->pOuterPrefixData = &pCookie->hashKeyBuffer[0]; pNestedModeSetupData->outerPrefixLenInBytes = LAC_HASH_MD5_DIGEST_SIZE; /* Point to the second half of the pre_master_secret */ inputSecret.pData = pKeyGenTlsOpData->secret.pData + (pKeyGenTlsOpData->secret.dataLenInBytes - tlsPrefixLen); /* Compute the SHA1 on the second half of the pre_master_secret */ hashAlgorithm = CPA_CY_SYM_HASH_SHA1; /* Initialize pointer where SHA1 key will go. */ hashKeyOutput.pData = &pCookie->hashKeyBuffer[LAC_HASH_MD5_DIGEST_SIZE]; hashKeyOutput.dataLenInBytes = LAC_HASH_SHA1_DIGEST_SIZE; computeHashKey(&inputSecret, &hashKeyOutput, &hashAlgorithm); pNestedModeSetupData->pInnerPrefixData = &pCookie->hashKeyBuffer[LAC_HASH_MD5_DIGEST_SIZE]; pNestedModeSetupData->innerPrefixLenInBytes = LAC_HASH_SHA1_DIGEST_SIZE; } else { /* secret = [s1 | s2 ] * s1 = outer prefix, s2 = inner prefix * length of s1 and s2 = ceil(secret_length / 2) * (secret length + 1)/2 will always give the ceil as division * by 2 * (>>1) will give the smallest integral value not less than arg */ tlsPrefixLen = (pKeyGenTlsOpData->secret.dataLenInBytes + 1) >> 1; /* last byte of s1 will be first byte of s2 if Length is odd */ pNestedModeSetupData->pInnerPrefixData = pKeyGenTlsOpData->secret.pData + (pKeyGenTlsOpData->secret.dataLenInBytes - tlsPrefixLen); pNestedModeSetupData->pOuterPrefixData = pKeyGenTlsOpData->secret.pData; pNestedModeSetupData->innerPrefixLenInBytes = pNestedModeSetupData->outerPrefixLenInBytes = tlsPrefixLen; } } /* note that following function doesn't look at inner/outer * prefix pointers in nested digest ctx */ LacSymQat_HashContentDescInit( &(keyGenReqFtr), instanceHandle, &hashSetupData, /* pointer to base of hw setup block */ pCookie->contentDesc, LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW, ICP_QAT_FW_SLICE_DRAM_WR, qatHashMode, CPA_FALSE, /* Not using sym Constants Table in Shared SRAM */ CPA_FALSE, /* not using the optimised content Desc */ NULL, /* precompute data */ &hashBlkSizeInBytes); if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { /* SSL3 */ CpaCyKeyGenSslOpData *pKeyGenSslOpData = (CpaCyKeyGenSslOpData *)pKeyGenSslTlsOpData; Cpa8U *pLabel = NULL; Cpa32U labelLen = 0; Cpa8U iterations = 0; Cpa64U labelPhysAddr = 0; /* iterations = ceiling of output required / output per iteration * Ceiling of a / b = (a + (b-1)) / b */ iterations = (pKeyGenSslOpData->generatedKeyLenInBytes + (LAC_SYM_QAT_KEY_SSL_BYTES_PER_ITERATION - 1)) >> LAC_SYM_QAT_KEY_SSL_ITERATIONS_SHIFT; if (CPA_CY_KEY_SSL_OP_USER_DEFINED == pKeyGenSslOpData->sslOp) { pLabel = pKeyGenSslOpData->userLabel.pData; labelLen = pKeyGenSslOpData->userLabel.dataLenInBytes; labelPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pLabel); if (labelPhysAddr == 0) { LAC_LOG_ERROR("Unable to get the physical address of the" " label\n"); status = CPA_STATUS_FAIL; } } else { pLabel = pService->pSslLabel; /* calculate label length. * eg. 3 iterations is ABBCCC so length is 6 */ labelLen = ((iterations * iterations) + iterations) >> 1; labelPhysAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, pLabel); } LacSymQat_KeySslRequestPopulate( &keyGenReqHdr, &keyGenReqMid, pKeyGenSslOpData->generatedKeyLenInBytes, labelLen, pKeyGenSslOpData->secret.dataLenInBytes, iterations); LacSymQat_KeySslKeyMaterialInputPopulate( &(pService->generic_service_info), &(pCookie->u.sslKeyInput), pKeyGenSslOpData->seed.pData, labelPhysAddr, pKeyGenSslOpData->secret.pData); inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64(pSymCookie->keySslKeyInputDevAddr); } else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == lacCmdId || ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == lacCmdId) { /* TLS v1.0/1.1 or v1.2*/ CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; lac_sym_qat_hash_state_buffer_info_t hashStateBufferInfo = {0}; CpaBoolean hashStateBuffer = CPA_FALSE; icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(keyGenReqFtr.cd_ctrl); icp_qat_la_auth_req_params_t *pHashReqParams = NULL; Cpa8U *pLabel = NULL; Cpa32U labelLen = 0; Cpa64U labelPhysAddr = 0; hashStateBufferInfo.pData = pCookie->hashStateBuffer; hashStateBufferInfo.pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64( pSymCookie->keyHashStateBufferDevAddr); hashStateBufferInfo.stateStorageSzQuadWords = 0; LacSymQat_HashSetupReqParamsMetaData(&(keyGenReqFtr), instanceHandle, &(hashSetupData), hashStateBuffer, qatHashMode, CPA_FALSE); pHashReqParams = (icp_qat_la_auth_req_params_t *)&( keyGenReqFtr.serv_specif_rqpars); hashStateBufferInfo.prefixAadSzQuadWords = LAC_BYTES_TO_QUADWORDS(pHashReqParams->u2.inner_prefix_sz + pHashControlBlock->outer_prefix_sz); /* Copy prefix data into hash state buffer */ pMsgDummy = (Cpa8U *)&(keyGenReq); pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); osalMemCopy(pMsgDummy, pCacheDummyHdr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_MID_IN_LW), pCacheDummyMid, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_MID_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), pCacheDummyFtr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); LacSymQat_HashStatePrefixAadBufferPopulate( &hashStateBufferInfo, &keyGenReqFtr, pNestedModeSetupData->pInnerPrefixData, (Cpa8U)pNestedModeSetupData->innerPrefixLenInBytes, pNestedModeSetupData->pOuterPrefixData, (Cpa8U)pNestedModeSetupData->outerPrefixLenInBytes); /* Firmware only looks at hash state buffer pointer and the * hash state buffer size so all other fields are set to 0 */ status = LacSymQat_HashRequestParamsPopulate( &(keyGenReq), 0, /* auth offset */ 0, /* auth len*/ &(pService->generic_service_info), &hashStateBufferInfo, /* hash state prefix buffer */ ICP_QAT_FW_LA_PARTIAL_NONE, 0, /* hash result size */ CPA_FALSE, NULL, CPA_CY_SYM_HASH_NONE, /* hash algorithm */ NULL); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("LacSymQat_HashRequestParamsPopulate failed\n"); } if (CPA_STATUS_SUCCESS == status) { /* Set up the labels and their lengths */ if (CPA_CY_KEY_TLS_OP_USER_DEFINED == pKeyGenTlsOpData->tlsOp) { pLabel = pKeyGenTlsOpData->userLabel.pData; labelLen = pKeyGenTlsOpData->userLabel.dataLenInBytes; labelPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pLabel); } else if (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == pKeyGenTlsOpData->tlsOp) { pLabel = pService->pTlsLabel->masterSecret; labelLen = sizeof(LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL) - 1; labelPhysAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, pLabel); } else if (CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE == pKeyGenTlsOpData->tlsOp) { pLabel = pService->pTlsLabel->keyMaterial; labelLen = sizeof(LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL) - 1; labelPhysAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, pLabel); } else if (CPA_CY_KEY_TLS_OP_CLIENT_FINISHED_DERIVE == pKeyGenTlsOpData->tlsOp) { pLabel = pService->pTlsLabel->clientFinished; labelLen = sizeof(LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL) - 1; labelPhysAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, pLabel); } else { pLabel = pService->pTlsLabel->serverFinished; labelLen = sizeof(LAC_SYM_KEY_TLS_SERVER_FIN_LABEL) - 1; labelPhysAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, pLabel); } if (labelPhysAddr == 0) { LAC_LOG_ERROR("Unable to get the physical address of the" " label\n"); status = CPA_STATUS_FAIL; } LacSymQat_KeyTlsRequestPopulate( &keyGenReqMid, pKeyGenTlsOpData->generatedKeyLenInBytes, labelLen, pKeyGenTlsOpData->secret.dataLenInBytes, (Cpa8U)pKeyGenTlsOpData->seed.dataLenInBytes, lacCmdId); LacSymQat_KeyTlsKeyMaterialInputPopulate( &(pService->generic_service_info), &(pCookie->u.tlsKeyInput), pKeyGenTlsOpData->seed.pData, labelPhysAddr); inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( pSymCookie->keyTlsKeyInputDevAddr); } } else if (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= lacCmdId && ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= lacCmdId) { /* TLS v1.3 / TLS v1.3 LABEL */ status = LacSymKey_KeyGenSslTls3GenCommon(instanceHandle, pKeyGenSslTlsOpData, &keyGenReqFtr, pSymCookie, &hashSetupData, &keyGenReq, &keyGenReqMid, lacCmdId, hashAlgCipher); if (CPA_STATUS_SUCCESS == status) { inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( pSymCookie->keyTlsKeyInputDevAddr); } } if (CPA_STATUS_SUCCESS == status) { outputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pKeyGenOutputData->pData)); if (outputPhysAddr == 0) { LAC_LOG_ERROR("Unable to get the physical address of the" " output buffer\n"); status = CPA_STATUS_FAIL; } } } if (CPA_STATUS_SUCCESS == status) { Cpa8U lw26[4]; char *tmp = NULL; unsigned char a; int n = 0; /* Make up the full keyGenReq struct from its constituents */ /* before calling the SalQatMsg functions below. */ /* Note: The full cache struct has been reduced to a */ /* header, mid and footer for memory size reduction */ pMsgDummy = (Cpa8U *)&(keyGenReq); pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); osalMemCopy(pMsgDummy, pCacheDummyHdr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_MID_IN_LW), pCacheDummyMid, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_MID_IN_LW)); osalMemCopy(&lw26, pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), LAC_LONG_WORD_IN_BYTES); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), pCacheDummyFtr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); tmp = (char *)(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW)); /* copy LW26, or'd with what's already there, into the Msg, for TLS */ for (n = 0; n < LAC_LONG_WORD_IN_BYTES; n++) { a = (unsigned char)*(tmp + n); lw26[n] = lw26[n] | a; } osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), &lw26, LAC_LONG_WORD_IN_BYTES); contentDescInfo.pData = pCookie->contentDesc; contentDescInfo.hardwareSetupBlockPhys = LAC_MEM_CAST_PTR_TO_UINT64(pSymCookie->keyContentDescDevAddr); contentDescInfo.hwBlkSzQuadWords = LAC_BYTES_TO_QUADWORDS(hashBlkSizeInBytes); /* Populate common request fields */ SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)&(keyGenReq), &(contentDescInfo)); SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&keyGenReq, ICP_QAT_FW_COMN_REQ_CPM_FW_LA, lacCmdId, cmnRequestFlags, laCmdFlags, 0); SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)&(keyGenReq), pCookie, LAC_SYM_KEY_QAT_PTR_TYPE, inputPhysAddr, outputPhysAddr, 0, 0); /* Send message */ status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, (void *)&(keyGenReq), LAC_QAT_SYM_REQ_SZ_LW, &seq_num); } if (CPA_STATUS_SUCCESS == status) { /* Update stats */ LacKey_StatsInc(lacCmdId, LAC_KEY_REQUESTS, pCookie->instanceHandle); LAC_MEM_POOL_BLK_SET_OPAQUE(pCookie, seq_num); } else { /* clean up cookie memory */ if (NULL != pCookie) { LacKey_StatsInc( lacCmdId, LAC_KEY_REQUEST_ERRORS, pCookie->instanceHandle); Lac_MemPoolEntryFree(pCookie); } } return status; } #ifdef ICP_PARAM_CHECK /** ******************************************************************************* * @ingroup LacSymKey * Compute output length for TLS v1.3 EXPAND_LABEL and * EXTRACT_AND_EXPAND_LABEL operation. * @description * The expected output buffer length is computed based on the * number of labels configured as input. * * @param[in] pHKDFData Pointer to a structure containing all * the data needed to perform the key * generation operation. * @param[in] hashAlgCipher Specifies the cipher we are using. * This should be set to a * cipher suite in TLS operation that * requires HKDF key operations. * @param[out] pOutputLen Total output key size in bytes * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * *****************************************************************************/ STATIC CpaStatus LacSymKey_GetOutputLengthForLabelOp(CpaCyKeyGenHKDFOpData *pHKDFData, Cpa8U hashAlgCipher, Cpa32U *pOutputLen) { Cpa8U subl_mask = 0, subl_idx = 1, subLabel = (CPA_CY_HKDF_SUBLABEL_KEY | CPA_CY_HKDF_SUBLABEL_IV | CPA_CY_HKDF_SUBLABEL_RESUMPTION | CPA_CY_HKDF_SUBLABEL_FINISHED); Cpa16U i = 0; for (i = 0; i < pHKDFData->numLabels; i++) { /* Check that the labelLen does not overflow */ if (CPA_CY_HKDF_KEY_MAX_LABEL_SZ < pHKDFData->label[i].labelLen) { LAC_INVALID_PARAM_LOG1("CpaCyKeyGenHKDFOpData.label[%d].labelLen", i); return CPA_STATUS_INVALID_PARAM; } if (pHKDFData->label[i].sublabelFlag & ~subLabel) { LAC_INVALID_PARAM_LOG1("CpaCyKeyGenHKDFOpData.label[%d]." "subLabelFlag", i); return CPA_STATUS_INVALID_PARAM; } /* Calculate the appended subLabel output lengths and * check that the output buffer that the user has * supplied is of the correct length. */ *pOutputLen += cipherSuiteHKDFHashSizes[hashAlgCipher][LAC_KEY_HKDF_DIGEST]; /* Get mask of subLabel */ subl_mask = pHKDFData->label[i].sublabelFlag; for (subl_idx = 1; subl_idx <= CPA_CY_HKDF_KEY_MAX_LABEL_COUNT; subl_idx++) { /* Add the used subLabel key lengths */ if (subl_mask & 1) { *pOutputLen += cipherSuiteHKDFHashSizes[hashAlgCipher][subl_idx]; } subl_mask >>= 1; } } return CPA_STATUS_SUCCESS; } /** ******************************************************************************* * @ingroup LacSymKey * Parameters check for TLS v1.3 * @description * Check user parameters against the firmware/spec requirements. * The Output key length expected for the specific operation is * computed and returned as an output parameter. * * @param[in] pKeyGenOpData Pointer to a structure containing all * the data needed to perform the key * generation operation. * @param[in] hashAlgCipher Specifies the cipher we are using. * This should be set to a * cipher suite in TLS operation that * requires HKDF key operations. * @param[in] cmdId Keygen operation to perform. * @param[out] pOutputLen Total output key size in bytes * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * *****************************************************************************/ STATIC CpaStatus LacSymKey_CheckParamTls3(const void *pKeyGenOpData, Cpa8U hashAlgCipher, icp_qat_fw_la_cmd_id_t cmdId, Cpa32U *pOutputLen) { Cpa32U maxSecretLen = CPA_CY_HKDF_KEY_MAX_SECRET_SZ, digest_size = 0, maxSeedLen = 0; CpaCySymHashAlgorithm hashAlgorithm = LacSymKey_getHashAlgorithmFromCipherSuiteHKDF(hashAlgCipher); CpaCyKeyGenHKDFOpData *pHKDFData = (CpaCyKeyGenHKDFOpData *)pKeyGenOpData; *pOutputLen = 0; /* Check using supported hash function */ digest_size = getDigestSizeFromHashAlgo(hashAlgorithm); if (0 == digest_size) { LAC_INVALID_PARAM_LOG("Hash function not supported"); return CPA_STATUS_INVALID_PARAM; } /* Number of labels does not exceed the MAX */ if (pHKDFData->numLabels > CPA_CY_HKDF_KEY_MAX_LABEL_COUNT) { LAC_INVALID_PARAM_LOG("CpaCyKeyGenHKDFOpData.numLabels"); return CPA_STATUS_INVALID_PARAM; } maxSeedLen = cipherSuiteHKDFHashSizes[hashAlgCipher][LAC_KEY_HKDF_DIGEST]; switch (cmdId) { case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: if (maxSeedLen < pHKDFData->seedLen) { LAC_INVALID_PARAM_LOG("CpaCyKeyGenHKDFOpData.seedLen"); return CPA_STATUS_INVALID_PARAM; } *pOutputLen = digest_size; break; case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: if (CPA_CY_HKDF_KEY_MAX_INFO_SZ < pHKDFData->infoLen) { LAC_INVALID_PARAM_LOG("CpaCyKeyGenHKDFOpData.infoLen"); return CPA_STATUS_INVALID_PARAM; } *pOutputLen = digest_size; maxSecretLen = cipherSuiteHKDFHashSizes[hashAlgCipher][LAC_KEY_HKDF_DIGEST]; break; case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: if (maxSeedLen < pHKDFData->seedLen) { LAC_INVALID_PARAM_LOG("CpaCyKeyGenHKDFOpData.seedLen"); return CPA_STATUS_INVALID_PARAM; } if (CPA_CY_HKDF_KEY_MAX_INFO_SZ < pHKDFData->infoLen) { LAC_INVALID_PARAM_LOG("CpaCyKeyGenHKDFOpData.infoLen"); return CPA_STATUS_INVALID_PARAM; } *pOutputLen = digest_size * 2; break; case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: { if (maxSeedLen < pHKDFData->seedLen) { LAC_INVALID_PARAM_LOG("CpaCyKeyGenHKDFOpData.seedLen"); return CPA_STATUS_INVALID_PARAM; } if (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL == cmdId) *pOutputLen = digest_size; else maxSecretLen = cipherSuiteHKDFHashSizes[hashAlgCipher] [LAC_KEY_HKDF_DIGEST]; if (CPA_STATUS_SUCCESS != LacSymKey_GetOutputLengthForLabelOp( pHKDFData, hashAlgCipher, pOutputLen)) { *pOutputLen = 0; return CPA_STATUS_INVALID_PARAM; } } break; default: break; } /* Maximum secret length for TLS1.3 Key Gen request */ if (pHKDFData->secretLen > maxSecretLen) { LAC_INVALID_PARAM_LOG("HKDF.secretLen"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } /** * @ingroup LacSymKey * Parameters check for TLS v1.0/1.1, v1.2, v1.3 and SSL3 * @description * Check user parameters against the firmware/spec requirements. * * @param[in] pKeyGenOpData Pointer to a structure containing all * the data needed to perform the key * generation operation. * @param[in] hashAlgCipher Specifies the hash algorithm or cipher * suite to use. * According to RFC5246, this should be * "SHA-256 or a stronger standard hash * function." * For TLS1.3, this should be set to a * ciphersuite in TLS operation that * requires HKDF key operations. * @param[in] pGeneratedKeyBuffer User output buffers. * @param[in] cmdId Keygen operation to perform. */ STATIC CpaStatus LacSymKey_CheckParamSslTls(const void *pKeyGenOpData, Cpa8U hashAlgCipher, const CpaFlatBuffer *pGeneratedKeyBuffer, icp_qat_fw_la_cmd_id_t cmdId) { /* Api max value */ Cpa32U maxSecretLen = 0; Cpa32U maxSeedLen = 0; Cpa32U maxOutputLen = 0; /* User info */ Cpa32U uSecretLen = 0; Cpa32U uSeedLen = 0; Cpa32U uOutputLen = 0; LAC_CHECK_NULL_PARAM(pKeyGenOpData); LAC_CHECK_NULL_PARAM(pGeneratedKeyBuffer); LAC_CHECK_NULL_PARAM(pGeneratedKeyBuffer->pData); if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == cmdId) { /* SSL3 */ CpaCyKeyGenSslOpData *opData = (CpaCyKeyGenSslOpData *)pKeyGenOpData; /* User info */ uSecretLen = opData->secret.dataLenInBytes; uSeedLen = opData->seed.dataLenInBytes; uOutputLen = opData->generatedKeyLenInBytes; /* Api max value */ maxSecretLen = ICP_QAT_FW_LA_SSL_SECRET_LEN_MAX; maxSeedLen = ICP_QAT_FW_LA_SSL_SEED_LEN_MAX; maxOutputLen = ICP_QAT_FW_LA_SSL_OUTPUT_LEN_MAX; /* Check user buffers */ LAC_CHECK_NULL_PARAM(opData->secret.pData); LAC_CHECK_NULL_PARAM(opData->seed.pData); /* check operation*/ if ((Cpa32U)opData->sslOp > CPA_CY_KEY_SSL_OP_USER_DEFINED) { LAC_INVALID_PARAM_LOG("opData->sslOp"); return CPA_STATUS_INVALID_PARAM; } if ((Cpa32U)opData->sslOp == CPA_CY_KEY_SSL_OP_USER_DEFINED) { LAC_CHECK_NULL_PARAM(opData->userLabel.pData); /* Maximum label length for SSL Key Gen request */ if (opData->userLabel.dataLenInBytes > ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX) { LAC_INVALID_PARAM_LOG("userLabel.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } /* only seed length for SSL3 Key Gen request */ if (maxSeedLen != uSeedLen) { LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* Maximum output length for SSL3 Key Gen request */ if (uOutputLen > maxOutputLen) { LAC_INVALID_PARAM_LOG("generatedKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == cmdId || ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == cmdId) { /* TLS v1.1 and 1.2*/ CpaCyKeyGenTlsOpData *opData = (CpaCyKeyGenTlsOpData *)pKeyGenOpData; /* User info */ uSecretLen = opData->secret.dataLenInBytes; uSeedLen = opData->seed.dataLenInBytes; uOutputLen = opData->generatedKeyLenInBytes; if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == cmdId) { /* Api max value */ /* ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX needs to be multiplied * by 4 in order to verify the 512 conditions. We did not change * ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX as it represents * the max value that firmware can handle. */ maxSecretLen = ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX * 4; } else { /* To support DH8k we use 1024 secret key length */ maxSecretLen = ICP_QAT_SECRET_LEN_MAX; /* Check Hash algorithm */ if (0 == getDigestSizeFromHashAlgo(hashAlgCipher)) { LAC_INVALID_PARAM_LOG("hashAlgorithm"); return CPA_STATUS_INVALID_PARAM; } } maxSeedLen = ICP_QAT_FW_LA_TLS_SEED_LEN_MAX; maxOutputLen = ICP_QAT_FW_LA_TLS_OUTPUT_LEN_MAX; /* Check user buffers */ LAC_CHECK_NULL_PARAM(opData->secret.pData); LAC_CHECK_NULL_PARAM(opData->seed.pData); /* check operation*/ if ((Cpa32U)opData->tlsOp > CPA_CY_KEY_TLS_OP_USER_DEFINED) { LAC_INVALID_PARAM_LOG("opData->tlsOp"); return CPA_STATUS_INVALID_PARAM; } else if ((Cpa32U)opData->tlsOp == CPA_CY_KEY_TLS_OP_USER_DEFINED) { LAC_CHECK_NULL_PARAM(opData->userLabel.pData); /* Maximum label length for TLS Key Gen request */ if (opData->userLabel.dataLenInBytes > ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX) { LAC_INVALID_PARAM_LOG("userLabel.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } /* Maximum/only seed length for TLS Key Gen request */ if (((Cpa32U)opData->tlsOp != CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE) && ((Cpa32U)opData->tlsOp != CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE)) { if (uSeedLen > maxSeedLen) { LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else { if (maxSeedLen != uSeedLen) { LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } /* Maximum output length for TLS Key Gen request */ if (uOutputLen > maxOutputLen) { LAC_INVALID_PARAM_LOG("generatedKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= cmdId && ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= cmdId) { /* TLS v1.3 */ if (CPA_STATUS_SUCCESS != LacSymKey_CheckParamTls3( pKeyGenOpData, hashAlgCipher, cmdId, &uOutputLen)) return CPA_STATUS_INVALID_PARAM; } else { LAC_INVALID_PARAM_LOG("TLS/SSL operation"); return CPA_STATUS_INVALID_PARAM; } /* Maximum secret length for TLS1.1/TLS1.2/SSL3 Key Gen request */ if (uSecretLen > maxSecretLen) { LAC_INVALID_PARAM_LOG("secret.dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* Check for enough space in the flat buffer */ if (uOutputLen > pGeneratedKeyBuffer->dataLenInBytes) { LAC_INVALID_PARAM_LOG("pGeneratedKeyBuffer->dataLenInBytes"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif /** * */ /** * @ingroup LacSymKey * Common Keygen Code for TLS v1.0/1.1, v1.2 and SSL3. * @description * Check user parameters and perform the required operation. * * @param[in] instanceHandle_in Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenOpData Pointer to a structure containing all * the data needed to perform the key * generation operation. * @param[in] hashAlgCipher Specifies the hash algorithm or * hash cipher to use. * For TLS1.2, as per RFC5246, * this should be "SHA-256 or * a stronger standard hash function." * For TLS1.3, this should be set to a * cipher suite in TLS operation that * requires HKDF key operations. * @param[out] pGeneratedKeyBuffer User output buffer. * @param[in] cmdId Keygen operation to perform. */ STATIC CpaStatus LacSymKey_KeyGenSslTls(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const void *pKeyGenOpData, Cpa8U hashAlgCipher, CpaFlatBuffer *pGeneratedKeyBuffer, icp_qat_fw_la_cmd_id_t cmdId) { #ifdef ICP_PARAM_CHECK CpaStatus status = CPA_STATUS_FAIL; #endif CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif SAL_RUNNING_CHECK(instanceHandle); if ((ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= cmdId) && (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= cmdId)) { SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, hkdf); } #ifdef ICP_PARAM_CHECK status = LacSymKey_CheckParamSslTls( pKeyGenOpData, hashAlgCipher, pGeneratedKeyBuffer, cmdId); if (CPA_STATUS_SUCCESS != status) { return status; } #endif return LacSymKey_KeyGenSslTls_GenCommon(instanceHandle, pKeyGenCb, pCallbackTag, cmdId, LAC_CONST_PTR_CAST(pKeyGenOpData), hashAlgCipher, pGeneratedKeyBuffer); } /** * @ingroup LacSymKey * SSL Key Generation Function. * @description * This function is used for SSL key generation. It implements the key * generation function defined in section 6.2.2 of the SSL 3.0 * specification as described in * http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt. * * The input seed is taken as a flat buffer and the generated key is * returned to caller in a flat destination data buffer. * * @param[in] instanceHandle_in Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenSslOpData Pointer to a structure containing all * the data needed to perform the SSL key * generation operation. The client code * allocates the memory for this * structure. This component takes * ownership of the memory until it is * returned in the callback. * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. */ CpaStatus cpaCyKeyGenSsl(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenSslOpData *pKeyGenSslOpData, CpaFlatBuffer *pGeneratedKeyBuffer) { #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pKeyGenCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pKeyGenSslOpData, (LAC_ARCH_UINT)pGeneratedKeyBuffer); #endif return LacSymKey_KeyGenSslTls(instanceHandle_in, pKeyGenCb, pCallbackTag, LAC_CONST_PTR_CAST(pKeyGenSslOpData), CPA_CY_SYM_OP_NONE, /* hash algorithm */ pGeneratedKeyBuffer, ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE); } /** * @ingroup LacSymKey * TLS Key Generation Function. * @description * This function is used for TLS key generation. It implements the * TLS PRF (Pseudo Random Function) as defined by RFC2246 (TLS v1.0) * and RFC4346 (TLS v1.1). * * The input seed is taken as a flat buffer and the generated key is * returned to caller in a flat destination data buffer. * * @param[in] instanceHandle_in Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenTlsOpData Pointer to a structure containing all * the data needed to perform the TLS key * generation operation. The client code * allocates the memory for this * structure. This component takes * ownership of the memory until it is * returned in the callback. * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. * */ CpaStatus cpaCyKeyGenTls(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, CpaFlatBuffer *pGeneratedKeyBuffer) { #ifdef ICP_TRACE LAC_LOG5("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pKeyGenCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pKeyGenTlsOpData, (LAC_ARCH_UINT)pGeneratedKeyBuffer); #endif return LacSymKey_KeyGenSslTls(instanceHandle_in, pKeyGenCb, pCallbackTag, LAC_CONST_PTR_CAST(pKeyGenTlsOpData), CPA_CY_SYM_OP_NONE, /* hash algorithm */ pGeneratedKeyBuffer, ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE); } /** * @ingroup LacSymKey * @description * This function is used for TLS key generation. It implements the * TLS PRF (Pseudo Random Function) as defined by RFC5246 (TLS v1.2). * * The input seed is taken as a flat buffer and the generated key is * returned to caller in a flat destination data buffer. * * @param[in] instanceHandle_in Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenTlsOpData Pointer to a structure containing all * the data needed to perform the TLS key * generation operation. The client code * allocates the memory for this * structure. This component takes * ownership of the memory until it is * returned in the callback. * @param[in] hashAlgorithm Specifies the hash algorithm to use. * According to RFC5246, this should be * "SHA-256 or a stronger standard hash * function." * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. */ CpaStatus cpaCyKeyGenTls2(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, CpaCySymHashAlgorithm hashAlgorithm, CpaFlatBuffer *pGeneratedKeyBuffer) { #ifdef ICP_TRACE LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, %d, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pKeyGenCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pKeyGenTlsOpData, hashAlgorithm, (LAC_ARCH_UINT)pGeneratedKeyBuffer); #endif return LacSymKey_KeyGenSslTls(instanceHandle_in, pKeyGenCb, pCallbackTag, LAC_CONST_PTR_CAST(pKeyGenTlsOpData), hashAlgorithm, pGeneratedKeyBuffer, ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE); } /** * @ingroup LacSymKey * @description * This function is used for TLS1.3 HKDF key generation. It implements * the "extract-then-expand" paradigm as defined by RFC 5869. * * The input seed/secret/info is taken as a flat buffer and the generated * key(s)/labels are returned to caller in a flat data buffer. * * @param[in] instanceHandle_in Instance handle. * @param[in] pKeyGenCb Pointer to callback function to be * invoked when the operation is complete. * If this is set to a NULL value the * function will operate synchronously. * @param[in] pCallbackTag Opaque User Data for this specific * call. Will be returned unchanged in the * callback. * @param[in] pKeyGenTlsOpData Pointer to a structure containing * the data needed to perform the HKDF key * generation operation. * The client code allocates the memory * for this structure as contiguous * pinned memory. * This component takes ownership of the * memory until it is returned in the * callback. * @param[in] cipherSuite Specifies the hash cipher suite to use. * This should be set to a cipher suite in * TLS operation that requires HKDF key * operations. * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient * buffer to hold the key generation * output. The data pointer SHOULD be * aligned on an 8-byte boundary. The * length field passed in represents the * size of the buffer in bytes. The value * that is returned is the size of the * result key in bytes. * On invocation the callback function * will contain this parameter in the * pOut parameter. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Resubmit the request. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_RESOURCE Error related to system resources. */ CpaStatus cpaCyKeyGenTls3(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pKeyGenCb, void *pCallbackTag, const CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, CpaCyKeyHKDFCipherSuite cipherSuite, CpaFlatBuffer *pGeneratedKeyBuffer) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pKeyGenTlsOpData); switch (pKeyGenTlsOpData->hkdfKeyOp) { case CPA_CY_HKDF_KEY_EXTRACT: case CPA_CY_HKDF_KEY_EXPAND: case CPA_CY_HKDF_KEY_EXTRACT_EXPAND: case CPA_CY_HKDF_KEY_EXPAND_LABEL: case CPA_CY_HKDF_KEY_EXTRACT_EXPAND_LABEL: break; default: LAC_INVALID_PARAM_LOG1("Invalid HKDF operation [%d]", pKeyGenTlsOpData->hkdfKeyOp); return CPA_STATUS_INVALID_PARAM; } #endif #ifdef ICP_TRACE LAC_LOG6("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx, %d, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pKeyGenCb, (LAC_ARCH_UINT)pCallbackTag, (LAC_ARCH_UINT)pKeyGenTlsOpData, cipherSuite, (LAC_ARCH_UINT)pGeneratedKeyBuffer); #endif return LacSymKey_KeyGenSslTls( instanceHandle_in, pKeyGenCb, pCallbackTag, LAC_CONST_PTR_CAST(pKeyGenTlsOpData), cipherSuite, pGeneratedKeyBuffer, (icp_qat_fw_la_cmd_id_t)pKeyGenTlsOpData->hkdfKeyOp); } /* * LacSymKey_StatsInit */ CpaStatus LacSymKey_StatsInit(CpaInstanceHandle instanceHandle_in) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); sal_crypto_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); #endif pService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pService->pLacKeyStats), LAC_KEY_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { LAC_OS_BZERO((void *)pService->pLacKeyStats, LAC_KEY_NUM_STATS * sizeof(OsalAtomic)); } return status; } /* * LacSymKey_Init */ CpaStatus LacSymKey_Init(CpaInstanceHandle instanceHandle_in) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); sal_crypto_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); #endif pService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_CAMALLOC(&pService->pSslLabel, ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX, LAC_8BYTE_ALIGNMENT, pService->nodeAffinity); if (CPA_STATUS_SUCCESS == status) { Cpa32U i = 0; Cpa32U offset = 0; /* Initialise SSL label ABBCCC..... */ for (i = 0; i < ICP_QAT_FW_LA_SSL_ITERATES_LEN_MAX; i++) { osalMemSet(pService->pSslLabel + offset, 'A' + i, i + 1); offset += (i + 1); } /* allocate memory for TLS labels */ status = LAC_OS_CAMALLOC(&pService->pTlsLabel, sizeof(lac_sym_key_tls_labels_t), LAC_8BYTE_ALIGNMENT, pService->nodeAffinity); } if (CPA_STATUS_SUCCESS == status) { /* Allocate memory for HKDF sub_labels */ status = LAC_OS_CAMALLOC(&pService->pTlsHKDFSubLabel, sizeof(lac_sym_key_tls_hkdf_sub_labels_t), LAC_8BYTE_ALIGNMENT, pService->nodeAffinity); } if (CPA_STATUS_SUCCESS == status) { LAC_OS_BZERO(pService->pTlsLabel, sizeof(lac_sym_key_tls_labels_t)); /* copy the TLS labels into the dynamically allocated structure */ memcpy(pService->pTlsLabel->masterSecret, LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL, sizeof(LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL) - 1); memcpy(pService->pTlsLabel->keyMaterial, LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL, sizeof(LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL) - 1); memcpy(pService->pTlsLabel->clientFinished, LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL, sizeof(LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL) - 1); memcpy(pService->pTlsLabel->serverFinished, LAC_SYM_KEY_TLS_SERVER_FIN_LABEL, sizeof(LAC_SYM_KEY_TLS_SERVER_FIN_LABEL) - 1); LAC_OS_BZERO(pService->pTlsHKDFSubLabel, sizeof(lac_sym_key_tls_hkdf_sub_labels_t)); /* Copy the TLS v1.3 subLabels into the dynamically allocated struct */ /* KEY SHA-256 */ memcpy(&pService->pTlsHKDFSubLabel->keySublabel256, &key256, sizeof(key256)); pService->pTlsHKDFSubLabel->keySublabel256.labelLen = sizeof(key256); pService->pTlsHKDFSubLabel->keySublabel256.sublabelFlag = 1 << QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS; /* KEY SHA-384 */ memcpy(&pService->pTlsHKDFSubLabel->keySublabel384, &key384, sizeof(key384)); pService->pTlsHKDFSubLabel->keySublabel384.labelLen = sizeof(key384); pService->pTlsHKDFSubLabel->keySublabel384.sublabelFlag = 1 << QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS; /* KEY CHACHAPOLY */ memcpy(&pService->pTlsHKDFSubLabel->keySublabelChaChaPoly, &keyChaChaPoly, sizeof(keyChaChaPoly)); pService->pTlsHKDFSubLabel->keySublabelChaChaPoly.labelLen = sizeof(keyChaChaPoly); pService->pTlsHKDFSubLabel->keySublabelChaChaPoly.sublabelFlag = 1 << QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS; /* IV SHA-256 */ memcpy( &pService->pTlsHKDFSubLabel->ivSublabel256, &iv256, sizeof(iv256)); pService->pTlsHKDFSubLabel->ivSublabel256.labelLen = sizeof(iv256); pService->pTlsHKDFSubLabel->ivSublabel256.sublabelFlag = 1 << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; /* IV SHA-384 */ memcpy( &pService->pTlsHKDFSubLabel->ivSublabel384, &iv384, sizeof(iv384)); pService->pTlsHKDFSubLabel->ivSublabel384.labelLen = sizeof(iv384); pService->pTlsHKDFSubLabel->ivSublabel384.sublabelFlag = 1 << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; /* IV CHACHAPOLY */ memcpy(&pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly, &iv256, sizeof(iv256)); pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly.labelLen = sizeof(iv256); pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly.sublabelFlag = 1 << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; /* RESUMPTION SHA-256 */ memcpy(&pService->pTlsHKDFSubLabel->resumptionSublabel256, &resumption256, sizeof(resumption256)); pService->pTlsHKDFSubLabel->resumptionSublabel256.labelLen = sizeof(resumption256); /* RESUMPTION SHA-384 */ memcpy(&pService->pTlsHKDFSubLabel->resumptionSublabel384, &resumption384, sizeof(resumption384)); pService->pTlsHKDFSubLabel->resumptionSublabel384.labelLen = sizeof(resumption384); /* RESUMPTION CHACHAPOLY */ memcpy(&pService->pTlsHKDFSubLabel->resumptionSublabelChaChaPoly, &resumption256, sizeof(resumption256)); pService->pTlsHKDFSubLabel->resumptionSublabelChaChaPoly.labelLen = sizeof(resumption256); /* FINISHED SHA-256 */ memcpy(&pService->pTlsHKDFSubLabel->finishedSublabel256, &finished256, sizeof(finished256)); pService->pTlsHKDFSubLabel->finishedSublabel256.labelLen = sizeof(finished256); /* FINISHED SHA-384 */ memcpy(&pService->pTlsHKDFSubLabel->finishedSublabel384, &finished384, sizeof(finished384)); pService->pTlsHKDFSubLabel->finishedSublabel384.labelLen = sizeof(finished384); /* FINISHED CHACHAPOLY */ memcpy(&pService->pTlsHKDFSubLabel->finishedSublabelChaChaPoly, &finished256, sizeof(finished256)); pService->pTlsHKDFSubLabel->finishedSublabelChaChaPoly.labelLen = sizeof(finished256); /* Set physical address of sublabels */ pService->pTlsHKDFSubLabel->sublabelPhysAddr256 = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, &pService->pTlsHKDFSubLabel->keySublabel256); pService->pTlsHKDFSubLabel->sublabelPhysAddr384 = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, &pService->pTlsHKDFSubLabel->keySublabel384); pService->pTlsHKDFSubLabel->sublabelPhysAddrChaChaPoly = LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, &pService->pTlsHKDFSubLabel->keySublabelChaChaPoly); /* Register response handlers */ LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXTRACT, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXPAND, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister( ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL, LacSymKey_SslTlsHandleResponse); LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_MGF1, LacSymKey_MgfHandleResponse); } if (CPA_STATUS_SUCCESS != status) { LAC_OS_CAFREE(pService->pSslLabel); LAC_OS_CAFREE(pService->pTlsLabel); LAC_OS_CAFREE(pService->pTlsHKDFSubLabel); } return status; } /* * LacSymKey_StatsFree */ CpaStatus LacSymKey_StatsFree(CpaInstanceHandle instanceHandle_in) { CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); sal_crypto_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); #endif pService = (sal_crypto_service_t *)instanceHandle; if (NULL != pService->pLacKeyStats) { LAC_OS_FREE(pService->pLacKeyStats); } return CPA_STATUS_SUCCESS; } /* * LacSymKey_StatsReset */ CpaStatus LacSymKey_StatsReset(CpaInstanceHandle instanceHandle_in) { CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); sal_crypto_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); #endif pService = (sal_crypto_service_t *)instanceHandle; LAC_OS_BZERO((void *)pService->pLacKeyStats, LAC_KEY_NUM_STATS * sizeof(OsalAtomic)); return CPA_STATUS_SUCCESS; } /* * LacSymKey_Shutdown */ CpaStatus LacSymKey_Shutdown(CpaInstanceHandle instanceHandle_in) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); sal_crypto_service_t *pService = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); #endif pService = (sal_crypto_service_t *)instanceHandle; LAC_OS_CAFREE(pService->pSslLabel); LAC_OS_CAFREE(pService->pTlsLabel); LAC_OS_CAFREE(pService->pTlsHKDFSubLabel); return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_alg_chain.c000066400000000000000000003521071503624047500321210ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_alg_chain.c Algorithm Chaining Perform * * @ingroup LacAlgChain ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_debug.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_mem.h" #include "lac_log.h" #include "lac_sym.h" #include "lac_list.h" #include "icp_qat_fw_la.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_sym_alg_chain.h" #include "lac_sym_cipher.h" #include "lac_sym_cipher_defs.h" #include "lac_sym_hash.h" #include "lac_sym_hash_defs.h" #include "lac_sym_qat_cipher.h" #include "lac_sym_qat_hash.h" #include "lac_sym_stats.h" #include "lac_sym_queue.h" #include "lac_sym_cb.h" #include "sal_string_parse.h" #include "lac_sym_auth_enc.h" #include "lac_sym_qat.h" /* Cipher block maximal size for session update purpose */ #define CCM_GCM_CIPHER_MAX_BLOCK_SIZE \ (ICP_QAT_HW_AES_256_KEY_SZ + sizeof(icp_qat_hw_ucs_cipher_config_t)) /* Session writer timeout */ #define LOCK_SESSION_WRITER_TIMEOUT 1000 #define LAC_IS_LEGACY_ALGORITHMS(cipherAlgo, hashAlgo) \ ((CPA_CY_SYM_CIPHER_ARC4 == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_AES_ECB == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_DES_CBC == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_DES_ECB == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_3DES_ECB == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_3DES_CBC == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_3DES_CTR == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_AES_F8 == (cipherAlgo)) || \ (CPA_CY_SYM_CIPHER_SM4_ECB == (cipherAlgo)) || \ (CPA_CY_SYM_HASH_MD5 == (hashAlgo)) || \ (CPA_CY_SYM_HASH_SHA1 == (hashAlgo)) || \ (CPA_CY_SYM_HASH_SHA224 == (hashAlgo)) || \ (CPA_CY_SYM_HASH_SHA3_224 == (hashAlgo))) #define MAX_HASH_PARTIALS_SIZE (4ULL * 1024 * 1024 * 1024) static inline void LacAlgChain_LockSessionReader( lac_session_desc_t *pSessionDesc) { /* Session lock in TRAD API */ if (!pSessionDesc->isDPSession) { while (osalAtomicTestAndSet(1, &pSessionDesc->accessLock)) ; pSessionDesc->accessReaders++; osalAtomicRelease(&pSessionDesc->accessLock); } } static inline void LacAlgChain_UnlockSessionReader( lac_session_desc_t *pSessionDesc) { /* Session lock in TRAD API */ if (!pSessionDesc->isDPSession) { while (osalAtomicTestAndSet(1, &pSessionDesc->accessLock)) ; pSessionDesc->accessReaders--; osalAtomicRelease(&pSessionDesc->accessLock); } } static inline CpaStatus LacAlgChain_LockSessionWriter( lac_session_desc_t *pSessionDesc) { CpaStatus status = CPA_STATUS_SUCCESS; if (!pSessionDesc->isDPSession) { while (osalAtomicTestAndSet(1, &pSessionDesc->accessLock)) ; if (pSessionDesc->accessReaders || osalAtomicGet(&(pSessionDesc->u.pendingCbCount)) > 0) { status = CPA_STATUS_RETRY; osalAtomicRelease(&pSessionDesc->accessLock); } } else { /* DP API */ if (pSessionDesc->u.pendingDpCbCount > 0) { status = CPA_STATUS_RETRY; } } return status; } static inline void LacAlgChain_UnlockSessionWriter( lac_session_desc_t *pSessionDesc) { /* Session lock in TRAD API */ if (!pSessionDesc->isDPSession) { osalAtomicRelease(&pSessionDesc->accessLock); } } /** * @ingroup LacAlgChain * This callback function will be invoked whenever a hash precompute * operation completes. It will dequeue and send any QAT requests * which were queued up while the precompute was in progress. * * @param[in] callbackTag Opaque value provided by user. This will * be a pointer to the session descriptor. * * @retval * None * */ STATIC void LacSymAlgChain_HashPrecomputeDoneCb(void *callbackTag) { LacSymCb_PendingReqsDequeue((lac_session_desc_t *)callbackTag); } /** * @ingroup LacAlgChain * Walk the buffer list and find the address for the given offset within * a buffer. * * @param[in] pBufferList Buffer List * @param[in] packetOffset Offset in the buffer list for which address * is to be found. * @param[out] ppDataPtr This is where the sought pointer will be put * @param[out] pSpaceLeft Pointer to a variable in which information about * available space from the given offset to the end * of the flat buffer it is located in will be returned * * @retval CPA_STATUS_SUCCESS Address with a given offset is found in the list * @retval CPA_STATUS_FAIL Address with a given offset not found in the list. * */ STATIC CpaStatus LacSymAlgChain_PtrFromOffsetGet(const CpaBufferList *pBufferList, const Cpa32U packetOffset, Cpa8U **ppDataPtr) { Cpa32U currentOffset = 0; Cpa32U i = 0; for (i = 0; i < pBufferList->numBuffers; i++) { Cpa8U *pCurrData = pBufferList->pBuffers[i].pData; Cpa32U currDataSize = pBufferList->pBuffers[i].dataLenInBytes; /* If the offset is within the address space of the current buffer */ if ((packetOffset >= currentOffset) && (packetOffset < (currentOffset + currDataSize))) { /* increment by offset of the address in the current buffer */ *ppDataPtr = pCurrData + (packetOffset - currentOffset); return CPA_STATUS_SUCCESS; } /* Increment by the size of the buffer */ currentOffset += currDataSize; } return CPA_STATUS_FAIL; } typedef struct { Cpa32U key; Cpa8U offs; } pair_t; /* This table is generated from const_tab in adf_admin.c * It contains configuration word with the corresponding offset in the SHRAM. * If original const_tab is modified, this one shall be updated too. */ STATIC const pair_t const_tab[] = { /* ALGO_DES | ECB_MODE | ENCRYPT | NO_CONVERT */ {0x1, 9}, /* ALGO_DES | ECB_MODE | DECRYPT | NO_CONVERT */ {0x101, 10}, /* ALGO_DES | CBC_MODE | ENCRYPT | NO_CONVERT */ {0x11, 11}, /* ALGO_DES | CBC_MODE | DECRYPT | NO_CONVERT */ {0x111, 12}, /* ALGO_DES | CTR_MODE | ENCRYPT | NO_CONVERT */ {0x21, 13}, /* ALGO_AES128 | ECB_MODE | ENCRYPT | NO_CONVERT */ {0x3, 14}, /* ALGO_AES128 | ECB_MODE | ENCRYPT | KEY_CONVERT */ {0x203, 15}, /* ALGO_AES128 | ECB_MODE | DECRYPT | NO_CONVERT */ {0x103, 16}, /* ALGO_AES128 | ECB_MODE | DECRYPT | KEY_CONVERT */ {0x303, 17}, /* ALGO_AES128 | CBC_MODE | ENCRYPT | NO_CONVERT */ {0x13, 18}, /* ALGO_AES128 | CBC_MODE | ENCRYPT | KEY_CONVERT */ {0x213, 19}, /* ALGO_AES128 | CBC_MODE | DECRYPT | NO_CONVERT */ {0x113, 20}, /* ALGO_AES128 | CBC_MODE | DECRYPT | KEY_CONVERT */ {0x313, 21}, /* ALGO_AES128 | CTR_MODE | ENCRYPT | NO_CONVERT */ {0x23, 22}, /* ALGO_AES128 | F8_MODE | ENCRYPT | NO_CONVERT */ {0x33, 23}, /* ALGO_ARC4 | ECB_MODE | ENCRYPT | NO_CONVERT */ {0x6, 24}, /* ALGO_ARC4 | ECB_MODE | ENCRYPT | KEY_CONVERT */ {0x206, 25}, }; #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #endif STATIC Cpa8U LacAlg_GetOffs(const Cpa32U *key, const CpaCySymOp operation) { /* Supported only cipher mode. */ if (CPA_CY_SYM_OP_CIPHER == operation) { size_t i = 0; for (i = 0; i < ARRAY_SIZE(const_tab); ++i) { if (*key == const_tab[i].key) return const_tab[i].offs; } } return 0; } static void LacAlgChain_CipherCDBuild_ForOptimisedCD( const CpaCySymCipherSetupData *pCipherData, lac_session_desc_t *pSessionDesc, icp_qat_fw_slice_t nextSlice, Cpa8U cipherOffsetInConstantsTable, Cpa8U *pOptimisedHwBlockBaseInDRAM, Cpa32U *pOptimisedHwBlockOffsetInDRAM) { Cpa8U *pCipherKeyField = NULL; Cpa32U sizeInBytes = 0; pCipherKeyField = pOptimisedHwBlockBaseInDRAM; /* Need to build up the alternative CD for SHRAM Constants Table use with * an optimised content desc of 64 bytes for this case. * Cipher key will be in the Content desc in DRAM, The cipher config data * is now in the SHRAM constants table. */ LacSymQat_CipherHwBlockPopulateKeySetup(pSessionDesc, pCipherData, pCipherData->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, pCipherKeyField, &sizeInBytes); LacSymQat_CipherCtrlBlockWrite(&(pSessionDesc->shramReqCacheFtr), pSessionDesc->cipherAlgorithm, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, nextSlice, cipherOffsetInConstantsTable); *pOptimisedHwBlockOffsetInDRAM += sizeInBytes; } static void LacAlgChain_CipherCDBuild_ForSHRAM( const CpaCySymCipherSetupData *pCipherData, lac_session_desc_t *pSessionDesc, icp_qat_fw_slice_t nextSlice, Cpa8U cipherOffsetInConstantsTable) { Cpa32U sizeInBytes = 0; Cpa8U *pCipherKeyField = NULL; /* Need to build up the alternative CD for SHRAM Constants Table use * Cipher key will be in the Request, The cipher config data is now in the * SHRAM constants table. And nothing is now stored in the content desc */ pCipherKeyField = (Cpa8U *)&( pSessionDesc->shramReqCacheHdr.cd_pars.s1.serv_specif_fields); LacSymQat_CipherHwBlockPopulateKeySetup(pSessionDesc, pCipherData, pCipherData->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, pCipherKeyField, &sizeInBytes); LacSymQat_CipherCtrlBlockWrite(&(pSessionDesc->shramReqCacheFtr), pSessionDesc->cipherAlgorithm, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, nextSlice, cipherOffsetInConstantsTable); } static void LacAlgChain_CipherCDBuild( const CpaCySymCipherSetupData *pCipherData, lac_session_desc_t *pSessionDesc, icp_qat_fw_slice_t nextSlice, Cpa8U cipherOffsetInConstantsTable, icp_qat_fw_comn_flags *pCmnRequestFlags, icp_qat_fw_serv_specif_flags *pLaCmdFlags, Cpa8U *pHwBlockBaseInDRAM, Cpa32U *pHwBlockOffsetInDRAM, Cpa32U capabilitiesMask) { Cpa8U *pCipherKeyField = NULL; Cpa8U cipherOffsetInReqQW = 0; Cpa32U sizeInBytes = 0; void *pCfgData = NULL; Cpa32U cfgOffset = 0; LAC_ENSURE_NOT_NULL(pHwBlockBaseInDRAM); LAC_ENSURE_NOT_NULL(pHwBlockOffsetInDRAM); /* Construct the ContentDescriptor in DRAM */ cipherOffsetInReqQW = (*pHwBlockOffsetInDRAM / LAC_QUAD_WORD_IN_BYTES); ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET( *pLaCmdFlags, ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_CD_SETUP); /* construct cipherConfig in CD in DRAM */ cfgOffset = *pHwBlockOffsetInDRAM; pCfgData = pHwBlockBaseInDRAM + cfgOffset; LacSymQat_CipherHwBlockPopulateCfgData( pSessionDesc, pCfgData, &sizeInBytes); ICP_QAT_FW_LA_SLICE_TYPE_SET(*pLaCmdFlags, pSessionDesc->cipherSliceType); *pHwBlockOffsetInDRAM += sizeInBytes; /* Cipher key will be in CD in DRAM. * The Request contains a ptr to the CD. * This ptr will be copied into the request later once the CD is * fully constructed, but the flag is set here. */ pCipherKeyField = pHwBlockBaseInDRAM + *pHwBlockOffsetInDRAM; ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(*pCmnRequestFlags, QAT_COMN_CD_FLD_TYPE_64BIT_ADR); LacSymQat_CipherHwBlockPopulateKeySetup(pSessionDesc, pCipherData, pCipherData->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, pCipherKeyField, &sizeInBytes); /* update offset */ *pHwBlockOffsetInDRAM += sizeInBytes; cipherOffsetInConstantsTable = LacAlg_GetOffs(pCfgData, pSessionDesc->symOperation); /* The key can be embedded only if key length <= 16 bytes * and algorithm configuration is found in the SHRAM constant table. */ if (cipherOffsetInConstantsTable > 0 && sizeInBytes <= sizeof(icp_qat_fw_comn_req_hdr_cd_pars_t) && ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE != pSessionDesc->cipherSliceType) { /* Algorithm configuration is found in the SHRAM constant table. */ cipherOffsetInReqQW = cipherOffsetInConstantsTable; /* Specify that CFG_OFFSET field contains * an offset in the SHRAM constant table. */ ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET( *pLaCmdFlags, ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_SHRAM_CP); /* Specify that LW2-5 contains embedded data. */ ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(*pCmnRequestFlags, QAT_COMN_CD_FLD_TYPE_16BYTE_DATA); /* Copy the key into LW2-5. */ memcpy( &pSessionDesc->reqCacheHdr.cd_pars, pCipherKeyField, sizeInBytes); /* Reset data offset. */ *pHwBlockOffsetInDRAM = cfgOffset; sizeInBytes = 0; } LacSymQat_CipherCtrlBlockWrite(&(pSessionDesc->reqCacheFtr), pSessionDesc->cipherAlgorithm, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, nextSlice, cipherOffsetInReqQW); if (SPC_NO != pSessionDesc->singlePassState) { LacSymQat_CipherCtrlBlockWrite(&(pSessionDesc->reqSpcCacheFtr), pSessionDesc->cipherAlgorithm, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, ICP_QAT_FW_SLICE_DRAM_WR, cipherOffsetInReqQW); } } void LacAlgChain_HashCDBuild( const CpaCySymHashSetupData *pHashData, CpaInstanceHandle instanceHandle, lac_session_desc_t *pSessionDesc, icp_qat_fw_slice_t nextSlice, Cpa8U hashOffsetInConstantsTable, icp_qat_fw_comn_flags *pCmnRequestFlags, icp_qat_fw_serv_specif_flags *pLaCmdFlags, lac_sym_qat_hash_precompute_info_t *pPrecomputeData, lac_sym_qat_hash_precompute_info_t *pPrecomputeDataOptimisedCd, Cpa8U *pHwBlockBaseInDRAM, Cpa32U *pHwBlockOffsetInDRAM, Cpa8U *pOptimisedHwBlockBaseInDRAM, Cpa32U *pOptimisedHwBlockOffsetInDRAM) { Cpa32U sizeInBytes = 0; Cpa32U hwBlockOffsetInQuadWords = *pHwBlockOffsetInDRAM / LAC_QUAD_WORD_IN_BYTES; /* build: * - the hash part of the ContentDescriptor in DRAM */ /* - the hash part of the CD control block in the Request template */ LacSymQat_HashContentDescInit(&(pSessionDesc->reqCacheFtr), instanceHandle, pHashData, pHwBlockBaseInDRAM, hwBlockOffsetInQuadWords, nextSlice, pSessionDesc->qatHashMode, CPA_FALSE, CPA_FALSE, pPrecomputeData, &sizeInBytes); /* Using DRAM CD so update offset */ *pHwBlockOffsetInDRAM += sizeInBytes; sizeInBytes = 0; if (pSessionDesc->useOptimisedContentDesc) { LacSymQat_HashContentDescInit(&(pSessionDesc->shramReqCacheFtr), instanceHandle, pHashData, pOptimisedHwBlockBaseInDRAM, hashOffsetInConstantsTable, nextSlice, pSessionDesc->qatHashMode, CPA_TRUE, CPA_TRUE, pPrecomputeDataOptimisedCd, &sizeInBytes); LAC_ENSURE_NOT_NULL(pOptimisedHwBlockOffsetInDRAM); if (NULL != pOptimisedHwBlockOffsetInDRAM) { *pOptimisedHwBlockOffsetInDRAM += sizeInBytes; } } else if (pSessionDesc->useSymConstantsTable) { /* Need to build up the alternative CD for SHRAM Constants Table use */ LacSymQat_HashContentDescInit(&(pSessionDesc->shramReqCacheFtr), instanceHandle, pHashData, pHwBlockBaseInDRAM, hashOffsetInConstantsTable, nextSlice, pSessionDesc->qatHashMode, CPA_TRUE, CPA_FALSE, pPrecomputeData, &sizeInBytes); } } STATIC Cpa16U LacAlgChain_GetCipherConfigSize(lac_session_desc_t *pSessionDesc) { if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE == pSessionDesc->cipherSliceType) { return sizeof(icp_qat_hw_ucs_cipher_config_t); } else { return sizeof(icp_qat_hw_cipher_config_t); } } STATIC Cpa16U LacAlgChain_GetCipherConfigOffset(lac_session_desc_t *pSessionDesc) { Cpa16U offset = 0; if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation || (SPC_NO != pSessionDesc->singlePassState)) { icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *cd_ctrl = (icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *)&pSessionDesc->reqCacheFtr .cd_ctrl; offset = cd_ctrl->cipher_cfg_offset; } else if (CPA_CY_SYM_OP_CIPHER == pSessionDesc->symOperation) { icp_qat_fw_cipher_cd_ctrl_hdr_t *cd_ctrl = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&pSessionDesc->reqCacheFtr .cd_ctrl; offset = cd_ctrl->cipher_cfg_offset; } return offset * LAC_QUAD_WORD_IN_BYTES; } STATIC CpaStatus LacAlgChain_SessionCipherKeyUpdate(lac_session_desc_t *pSessionDesc, Cpa8U *pCipherKey) { CpaStatus status = CPA_STATUS_SUCCESS; if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { LacSymQat_CipherArc4StateInit(pCipherKey, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherARC4InitialState); } else { CpaCySymCipherSetupData cipherSetupData = {0}; Cpa32U sizeInBytes; Cpa8U *pCipherKeyField; Cpa16U cipherConfigSize; Cpa16U cipherConfigOffset; sal_qat_content_desc_info_t *pCdInfo = &(pSessionDesc->contentDescInfo); cipherSetupData.cipherAlgorithm = pSessionDesc->cipherAlgorithm; cipherSetupData.cipherKeyLenInBytes = pSessionDesc->cipherKeyLenInBytes; cipherSetupData.pCipherKey = pCipherKey; cipherSetupData.cipherDirection = pSessionDesc->cipherDirection; cipherConfigSize = LacAlgChain_GetCipherConfigSize(pSessionDesc); cipherConfigOffset = LacAlgChain_GetCipherConfigOffset(pSessionDesc); pCipherKeyField = (Cpa8U *)pCdInfo->pData + cipherConfigOffset + cipherConfigSize; switch (pSessionDesc->symOperation) { case CPA_CY_SYM_OP_CIPHER: { LacSymQat_CipherHwBlockPopulateKeySetup( pSessionDesc, &(cipherSetupData), cipherSetupData.cipherKeyLenInBytes, pSessionDesc->cipherSliceType, pCipherKeyField, &sizeInBytes); if (pSessionDesc->useSymConstantsTable) { pCipherKeyField = (Cpa8U *)&(pSessionDesc->shramReqCacheHdr.cd_pars.s1 .serv_specif_fields); LacSymQat_CipherHwBlockPopulateKeySetup( pSessionDesc, &(cipherSetupData), cipherSetupData.cipherKeyLenInBytes, pSessionDesc->cipherSliceType, pCipherKeyField, &sizeInBytes); } } break; case CPA_CY_SYM_OP_ALGORITHM_CHAINING: { LacSymQat_CipherHwBlockPopulateKeySetup( pSessionDesc, &(cipherSetupData), cipherSetupData.cipherKeyLenInBytes, pSessionDesc->cipherSliceType, pCipherKeyField, &sizeInBytes); } break; default: LAC_LOG_ERROR("Invalid sym operation\n"); status = CPA_STATUS_INVALID_PARAM; break; } } return status; } STATIC CpaStatus LacAlgChain_SessionAuthKeyUpdate(lac_session_desc_t *pSessionDesc, Cpa8U *authKey) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pHwBlockBaseInDRAM = NULL; Cpa8U *pOutHashSetup = NULL; Cpa8U *pInnerState1 = NULL; Cpa8U *pInnerState2 = NULL; CpaCySymSessionSetupData sessionSetup; Cpa16U cipherConfigSize; LAC_OS_BZERO(&sessionSetup, sizeof(sessionSetup)); cipherConfigSize = LacAlgChain_GetCipherConfigSize(pSessionDesc); icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *cd_ctrl = (icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *)&pSessionDesc->reqCacheFtr .cd_ctrl; pHwBlockBaseInDRAM = (Cpa8U *)pSessionDesc->contentDescInfo.pData; sessionSetup.hashSetupData.hashAlgorithm = pSessionDesc->hashAlgorithm; sessionSetup.hashSetupData.hashMode = pSessionDesc->hashMode; sessionSetup.hashSetupData.authModeSetupData.authKey = authKey; sessionSetup.hashSetupData.authModeSetupData.authKeyLenInBytes = pSessionDesc->authKeyLenInBytes; sessionSetup.hashSetupData.authModeSetupData.aadLenInBytes = pSessionDesc->aadLenInBytes; sessionSetup.hashSetupData.digestResultLenInBytes = pSessionDesc->hashResultSize; sessionSetup.cipherSetupData.cipherAlgorithm = pSessionDesc->cipherAlgorithm; sessionSetup.cipherSetupData.cipherKeyLenInBytes = pSessionDesc->cipherKeyLenInBytes; /* Calculate hash states offsets */ pInnerState1 = pHwBlockBaseInDRAM + cd_ctrl->hash_cfg_offset * LAC_QUAD_WORD_IN_BYTES + sizeof(icp_qat_hw_auth_setup_t); pInnerState2 = pInnerState1 + cd_ctrl->inner_state1_sz; pOutHashSetup = pInnerState2 + cd_ctrl->inner_state2_sz; /* Calculate offset of cipher key */ if (pSessionDesc->laCmdId == ICP_QAT_FW_LA_CMD_CIPHER_HASH) { sessionSetup.cipherSetupData.pCipherKey = (Cpa8U *)pHwBlockBaseInDRAM + cipherConfigSize; } else if (pSessionDesc->laCmdId == ICP_QAT_FW_LA_CMD_HASH_CIPHER) { sessionSetup.cipherSetupData.pCipherKey = pOutHashSetup + cipherConfigSize; } if (CPA_CY_SYM_HASH_SHA3_256 == pSessionDesc->hashAlgorithm || CPA_CY_SYM_HASH_SM3 == pSessionDesc->hashAlgorithm) { if (CPA_FALSE == pSessionDesc->isAuthEncryptOp) { lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = &(pSessionDesc->hashStateBufferInfo); sal_crypto_service_t *pService = (sal_crypto_service_t *)pSessionDesc->pInstance; status = LacHash_StatePrefixAadBufferInit( &(pService->generic_service_info), &(sessionSetup.hashSetupData), &(pSessionDesc->reqCacheFtr), pSessionDesc->qatHashMode, pSessionDesc->hashStatePrefixBuffer, pHashStateBufferInfo); /* SHRAM Constants Table not used for Auth-Enc */ } } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm) { Cpa8U *pAuthKey = (Cpa8U *)pOutHashSetup + sizeof(icp_qat_hw_cipher_config_t); memcpy(pAuthKey, authKey, pSessionDesc->authKeyLenInBytes); } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm || CPA_CY_SYM_HASH_AES_CBC_MAC == pSessionDesc->hashAlgorithm) { memcpy(pInnerState2, authKey, pSessionDesc->authKeyLenInBytes); } else if (CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm || CPA_CY_SYM_HASH_KASUMI_F9 == pSessionDesc->hashAlgorithm || IS_HASH_MODE_1(pSessionDesc->qatHashMode)) { if (CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm) { osalMemSet(pInnerState2, 0, cd_ctrl->inner_state2_sz); } /* Block messages until precompute is completed */ pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; status = LacHash_PrecomputeDataCreate( pSessionDesc->pInstance, (CpaCySymSessionSetupData *)&(sessionSetup), LacSymAlgChain_HashPrecomputeDoneCb, pSessionDesc, pSessionDesc->hashStatePrefixBuffer, pInnerState1, pInnerState2); } return status; } static void buildCmdData(lac_session_desc_t *pSessionDesc, CpaCySymAlgChainOrder *chainOrder, Cpa16U *proto, icp_qat_fw_serv_specif_flags *laCmdFlags, icp_qat_fw_ext_serv_specif_flags *laExtCmdFlags, icp_qat_fw_comn_flags *cmnRequestFlags) { /* LW 28 is used to set hash flags for AlgChaining. */ icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *cd_ctrl = (icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *)&pSessionDesc->reqCacheFtr .cd_ctrl; /* proto refers to Protocol Flags, which is legacy FW <=> IA interface for * ZUC and Snow3G. Use extended protocol flags for AlgChaining. */ *proto = ICP_QAT_FW_LA_NO_PROTO; /* no CCM/GCM/Snow3G */ switch (pSessionDesc->symOperation) { case CPA_CY_SYM_OP_CIPHER: pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; if (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == pSessionDesc->cipherAlgorithm) { *proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; ICP_QAT_FW_USE_WCP_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WCP_SLICE); } else if (CPA_CY_SYM_CIPHER_ZUC_EEA3 == pSessionDesc->cipherAlgorithm) { *proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; ICP_QAT_FW_USE_WCP_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WCP_SLICE); } else if (CPA_CY_SYM_CIPHER_AES_F8 == pSessionDesc->cipherAlgorithm) { ICP_QAT_FW_USE_WCP_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WCP_SLICE); } if (LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)) { *proto = ICP_QAT_FW_LA_CCM_PROTO; } break; case CPA_CY_SYM_OP_HASH: pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_AUTH; if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm) { *proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; ICP_QAT_FW_USE_WAT_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WAT_SLICE); } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm) { *proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; ICP_QAT_FW_USE_WAT_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WAT_SLICE); } else if ((CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm) && (ICP_QAT_HW_AES_128_KEY_SZ != pSessionDesc->authKeyLenInBytes)) { ICP_QAT_FW_USE_WAT_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WAT_SLICE); } break; case CPA_CY_SYM_OP_ALGORITHM_CHAINING: if (LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)) { *proto = ICP_QAT_FW_LA_CCM_PROTO; /* Derive chainOrder from direction for isAuthEncryptOp * cases */ /* For CCM & GCM modes: force digest verify flag _TRUE for decrypt and _FALSE for encrypt. For all other cases use user defined value */ if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == pSessionDesc->cipherDirection) { *chainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; pSessionDesc->digestVerify = CPA_FALSE; } else { *chainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; pSessionDesc->digestVerify = CPA_TRUE; } } else if (LAC_CIPHER_IS_GCM(pSessionDesc->cipherAlgorithm)) { *proto = ICP_QAT_FW_LA_GCM_PROTO; /* Derive chainOrder from direction for isAuthEncryptOp * cases */ /* For CCM & GCM modes: force digest verify flag _TRUE for decrypt and _FALSE for encrypt. For all other cases use user defined value */ if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == pSessionDesc->cipherDirection) { *chainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; pSessionDesc->digestVerify = CPA_FALSE; } else { *chainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; pSessionDesc->digestVerify = CPA_TRUE; } } else if (LAC_CIPHER_IS_CHACHA(pSessionDesc->cipherAlgorithm)) { if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == pSessionDesc->cipherDirection) { *chainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; } else { *chainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; } } else { pSessionDesc->isAuthEncryptOp = CPA_FALSE; if (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == pSessionDesc->cipherAlgorithm) { *proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_SET( *laExtCmdFlags, QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS); ICP_QAT_FW_USE_WCP_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WCP_SLICE); } else if (CPA_CY_SYM_CIPHER_ZUC_EEA3 == pSessionDesc->cipherAlgorithm) { *proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_SET( *laExtCmdFlags, QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS); ICP_QAT_FW_USE_WCP_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WCP_SLICE); } if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm) { ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_SET( *laExtCmdFlags, QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS); /* Need to set LW 28 hash flags as well. */ ICP_QAT_FW_HASH_FLAG_SNOW3G_UIA2_SET(cd_ctrl->hash_flags, QAT_FW_LA_SNOW3G_UIA2); ICP_QAT_FW_USE_WAT_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WAT_SLICE); } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm) { ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_SET( *laExtCmdFlags, QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS); /* Need to set LW 28 hash flags as well. */ ICP_QAT_FW_HASH_FLAG_ZUC_EIA3_SET(cd_ctrl->hash_flags, QAT_FW_LA_ZUC_EIA3); ICP_QAT_FW_USE_WAT_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WAT_SLICE); } if (CPA_CY_SYM_CIPHER_AES_F8 == pSessionDesc->cipherAlgorithm) { ICP_QAT_FW_USE_WCP_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WCP_SLICE); } if ((CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm) && (ICP_QAT_HW_AES_128_KEY_SZ != pSessionDesc->authKeyLenInBytes)) { ICP_QAT_FW_USE_WAT_SLICE_SET(*laExtCmdFlags, QAT_LA_USE_WAT_SLICE); } } if (CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH == *chainOrder) { pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER_HASH; } else if (CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER == *chainOrder) { pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_HASH_CIPHER; } break; default: break; } /* * Build the header flags with the default settings for this session. */ if (pSessionDesc->isDPSession == CPA_TRUE) { *cmnRequestFlags = ICP_QAT_FW_COMN_FLAGS_BUILD( QAT_COMN_CD_FLD_TYPE_64BIT_ADR, LAC_SYM_DP_QAT_PTR_TYPE); } else { *cmnRequestFlags = ICP_QAT_FW_COMN_FLAGS_BUILD( QAT_COMN_CD_FLD_TYPE_64BIT_ADR, LAC_SYM_DEFAULT_QAT_PTR_TYPE); } LacSymQat_LaSetDefaultFlags(laCmdFlags, pSessionDesc->symOperation); return; } static void updateLaCmdFlags(lac_session_desc_t *pSessionDesc, Cpa16U proto, icp_qat_fw_serv_specif_flags *laCmdFlags, icp_qat_fw_ext_serv_specif_flags laExtCmdFlags) { CpaBoolean extServFlagEnabled = (CpaBoolean)ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_GET(laExtCmdFlags); if (pSessionDesc->isAuth || (SPC_NO != pSessionDesc->singlePassState)) { if (pSessionDesc->digestVerify) { ICP_QAT_FW_LA_CMP_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_CMP_AUTH_RES); ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_RET_AUTH_RES); } else { ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_RET_AUTH_RES); ICP_QAT_FW_LA_CMP_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); } } /* New FW <=> IA interface */ if (extServFlagEnabled && (CPA_CY_SYM_CIPHER_ZUC_EEA3 == pSessionDesc->cipherAlgorithm)) { /* Use new FW <=> IA interface to support wider range of alg chaining * In this case ZUC protocol flag needs to be only set for ZUC_EEA3 * cipher algorithm (LWs 1). ZUC_EIA3 hash algorithm has corresponding * flag in hash_flags (LWs 28). */ ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(*laCmdFlags, proto); } /* Legacy FW <=> IA interface */ else if (!extServFlagEnabled && ((CPA_CY_SYM_CIPHER_ZUC_EEA3 == pSessionDesc->cipherAlgorithm) || (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm))) { /* New bit position (12) for ZUC. The FW provides a specific macro * to use to set the ZUC proto flag. With the new FW I/F this needs * to be set for both Cipher and Auth */ ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(*laCmdFlags, proto); } else { /* Configure the common header */ ICP_QAT_FW_LA_PROTO_SET(*laCmdFlags, proto); } /* set Append flag, if digest is appended */ if (pSessionDesc->digestIsAppended) { ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(*laCmdFlags, ICP_QAT_FW_LA_DIGEST_IN_BUFFER); } else { ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_DIGEST_IN_BUFFER); } } STATIC CpaStatus LacAlgChain_SessionDirectionUpdate(lac_session_desc_t *pSessionDesc, CpaCySymCipherDirection cipherDirection) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sizeInBytes = 0; Cpa8U *pCfgData = NULL; CpaBoolean useSymConstants = CPA_FALSE; sal_qat_content_desc_info_t *pCdInfo = &(pSessionDesc->contentDescInfo); Cpa8U *pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; Cpa16U cipherConfigSize; Cpa16U cipherConfigOffset; cipherConfigSize = LacAlgChain_GetCipherConfigSize(pSessionDesc); cipherConfigOffset = LacAlgChain_GetCipherConfigOffset(pSessionDesc); /* Nothing changed - exiting */ if (pSessionDesc->cipherDirection == cipherDirection) { return CPA_STATUS_SUCCESS; } /* Update session descriptor */ pSessionDesc->cipherDirection = cipherDirection; switch (pSessionDesc->symOperation) { case CPA_CY_SYM_OP_CIPHER: { pCfgData = pHwBlockBaseInDRAM + cipherConfigOffset; if (SPC_NO != pSessionDesc->singlePassState) { /* Update digest verify setting, LA flags and message */ if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == pSessionDesc->cipherDirection) { pSessionDesc->digestVerify = CPA_FALSE; } else { pSessionDesc->digestVerify = CPA_TRUE; } updateLaCmdFlags( pSessionDesc, LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm) ? ICP_QAT_FW_LA_CCM_PROTO : 0, &pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); SalQatMsg_CmnHdrWrite( (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqSpcCacheHdr), ICP_QAT_FW_COMN_REQ_CPM_FW_LA, pSessionDesc->laCmdId, pSessionDesc->cmnRequestFlags, pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); } LacSymQat_CipherHwBlockPopulateCfgData( pSessionDesc, pCfgData, &sizeInBytes); if (pSessionDesc->useSymConstantsTable) { Cpa8U hashOffsetInConstantsTable = 0; Cpa8U cipherOffsetInConstantsTable = 0; useSymConstants = LacSymQat_UseSymConstantsTable( pSessionDesc, &cipherOffsetInConstantsTable, &hashOffsetInConstantsTable); if (useSymConstants != CPA_TRUE) { status = CPA_STATUS_FAIL; break; } LacSymQat_CipherCtrlBlockWrite( &(pSessionDesc->shramReqCacheFtr), pSessionDesc->cipherAlgorithm, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, ICP_QAT_FW_SLICE_DRAM_WR, cipherOffsetInConstantsTable); } } break; case CPA_CY_SYM_OP_ALGORITHM_CHAINING: { CpaCySymHashSetupData hashData; hashData.hashAlgorithm = pSessionDesc->hashAlgorithm; hashData.hashMode = pSessionDesc->hashMode; hashData.authModeSetupData.aadLenInBytes = pSessionDesc->aadLenInBytes; hashData.authModeSetupData.authKeyLenInBytes = pSessionDesc->authKeyLenInBytes; hashData.digestResultLenInBytes = pSessionDesc->hashResultSize; if (CPA_FALSE == pSessionDesc->isAuthEncryptOp) { pCfgData = pHwBlockBaseInDRAM + cipherConfigOffset; LacSymQat_CipherHwBlockPopulateCfgData( pSessionDesc, pCfgData, &sizeInBytes); } else { Cpa16U proto = 0; CpaCySymAlgChainOrder chainOrder = 0; lac_sym_qat_hash_precompute_info_t precomputeData = {0}; Cpa8U cipherBlk[CCM_GCM_CIPHER_MAX_BLOCK_SIZE] = {0}; icp_qat_fw_serv_specif_flags laCmdFlags = 0; icp_qat_fw_ext_serv_specif_flags laExtCmdFlags = 0; Cpa32U cipherBlkSizeInBytes = 0; Cpa32U hashBlkSizeInBytes = 0; icp_qat_fw_comn_flags cmnRequestFlags = 0; /* Calculate cipher and hash block size */ cipherBlkSizeInBytes = cipherConfigSize + pSessionDesc->cipherKeyLenInBytes; hashBlkSizeInBytes = pCdInfo->hwBlkSzQuadWords * LAC_QUAD_WORD_IN_BYTES - cipherBlkSizeInBytes; /* Build configuration data */ buildCmdData(pSessionDesc, &chainOrder, &proto, &laCmdFlags, &laExtCmdFlags, &cmnRequestFlags); /* Make backup of cipher */ memcpy(cipherBlk, pHwBlockBaseInDRAM + cipherConfigOffset, cipherBlkSizeInBytes); if (CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER == chainOrder) { memmove(pHwBlockBaseInDRAM, pHwBlockBaseInDRAM + cipherBlkSizeInBytes, hashBlkSizeInBytes); memcpy(pHwBlockBaseInDRAM + hashBlkSizeInBytes, cipherBlk, cipherBlkSizeInBytes); /* build: * - the hash part of the ContentDescriptor in DRAM */ /* - the hash part of the CD control block in the Request * template */ LacSymQat_HashContentDescInit(&(pSessionDesc->reqCacheFtr), pSessionDesc->pInstance, &hashData, pHwBlockBaseInDRAM, 0, ICP_QAT_FW_SLICE_CIPHER, pSessionDesc->qatHashMode, CPA_FALSE, CPA_FALSE, &precomputeData, &sizeInBytes); LacSymQat_CipherCtrlBlockWrite( &(pSessionDesc->reqCacheFtr), pSessionDesc->cipherAlgorithm, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, ICP_QAT_FW_SLICE_DRAM_WR, hashBlkSizeInBytes / LAC_QUAD_WORD_IN_BYTES); } else { memmove(pHwBlockBaseInDRAM + cipherBlkSizeInBytes, pHwBlockBaseInDRAM, hashBlkSizeInBytes); memcpy(pHwBlockBaseInDRAM, cipherBlk, cipherBlkSizeInBytes); LacSymQat_CipherCtrlBlockWrite( &(pSessionDesc->reqCacheFtr), pSessionDesc->cipherAlgorithm, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherSliceType, ICP_QAT_FW_SLICE_AUTH, 0); /* build: * - the hash part of the ContentDescriptor in DRAM */ /* - the hash part of the CD control block in the Request * template */ LacSymQat_HashContentDescInit(&(pSessionDesc->reqCacheFtr), pSessionDesc->pInstance, &hashData, pHwBlockBaseInDRAM, cipherBlkSizeInBytes / LAC_QUAD_WORD_IN_BYTES, ICP_QAT_FW_SLICE_DRAM_WR, pSessionDesc->qatHashMode, CPA_FALSE, CPA_FALSE, &precomputeData, &sizeInBytes); } LacSymQat_HashSetupReqParamsMetaData( &(pSessionDesc->reqCacheFtr), pSessionDesc->pInstance, &hashData, CPA_TRUE, pSessionDesc->qatHashMode, pSessionDesc->digestVerify); /* Update message header */ { icp_qat_fw_comn_req_t *pMsg = (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqCacheHdr); /* Updates command flags basing on configured alg */ updateLaCmdFlags( pSessionDesc, proto, &laCmdFlags, laExtCmdFlags); SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pMsg, ICP_QAT_FW_COMN_REQ_CPM_FW_LA, pSessionDesc->laCmdId, cmnRequestFlags, laCmdFlags, laExtCmdFlags); } } } break; default: status = CPA_STATUS_UNSUPPORTED; break; } return status; } /** @ingroup LacAlgChain */ CpaStatus LacAlgChain_SessionUpdate( lac_session_desc_t *pSessionDesc, const CpaCySymSessionUpdateData *pSessionUpdateData) { CpaStatus status = CPA_STATUS_SUCCESS; /* Local copy to further modification */ Cpa32U flags = pSessionUpdateData->flags; Cpa8U *authKey = pSessionUpdateData->authKey; LAC_ENSURE_NOT_NULL(pSessionDesc); LAC_ENSURE_NOT_NULL(pSessionUpdateData); #ifdef ICP_PARAM_CHECK LAC_CHECK_PARAM_RANGE(pSessionUpdateData->flags, 1, (CPA_CY_SYM_SESUPD_CIPHER_KEY | CPA_CY_SYM_SESUPD_AUTH_KEY | CPA_CY_SYM_SESUPD_CIPHER_DIR) + 1); if (CPA_CY_SYM_SESUPD_CIPHER_KEY & flags) { LAC_CHECK_NULL_PARAM(pSessionUpdateData->pCipherKey); if (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation) { LAC_UNSUPPORTED_PARAM_LOG( "Cannot update cipher key on Hash session"); return CPA_STATUS_UNSUPPORTED; } } if (CPA_CY_SYM_SESUPD_AUTH_KEY & flags) { LAC_CHECK_NULL_PARAM(authKey); if ((CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation || CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation) && (CPA_CY_SYM_HASH_MODE_AUTH != pSessionDesc->hashMode)) { LAC_UNSUPPORTED_PARAM_LOG( "Cannot update auth key on other mode than auth."); return CPA_STATUS_UNSUPPORTED; } if (CPA_CY_SYM_OP_CIPHER == pSessionDesc->symOperation) { LAC_UNSUPPORTED_PARAM_LOG( "Cannot update auth key on Cipher session"); return CPA_STATUS_UNSUPPORTED; } if (LAC_CIPHER_IS_GCM(pSessionDesc->cipherAlgorithm) || LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)) { LAC_UNSUPPORTED_PARAM_LOG( "Update of auth key on GCM/CCM is not supported"); return CPA_STATUS_UNSUPPORTED; } } if (CPA_CY_SYM_SESUPD_CIPHER_DIR & flags) { if ((pSessionUpdateData->cipherDirection != CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) && (pSessionUpdateData->cipherDirection != CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT)) { LAC_INVALID_PARAM_LOG("Invalid Cipher Direction"); return CPA_STATUS_INVALID_PARAM; } if (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation) { LAC_UNSUPPORTED_PARAM_LOG( "Cannot change direction on Hash session"); return CPA_STATUS_UNSUPPORTED; } } #endif status = LacAlgChain_LockSessionWriter(pSessionDesc); if (CPA_STATUS_SUCCESS != status) { return status; } if (CPA_CY_SYM_SESUPD_CIPHER_KEY & flags) { /* In case of GCM/CCM update the auth key as well */ if (LAC_CIPHER_IS_GCM(pSessionDesc->cipherAlgorithm) || LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)) { flags |= CPA_CY_SYM_SESUPD_AUTH_KEY; authKey = pSessionUpdateData->pCipherKey; } status = LacAlgChain_SessionCipherKeyUpdate( pSessionDesc, pSessionUpdateData->pCipherKey); } if (CPA_STATUS_SUCCESS == status && (CPA_CY_SYM_SESUPD_AUTH_KEY & flags) && pSessionDesc->isAuth) { status = LacAlgChain_SessionAuthKeyUpdate(pSessionDesc, authKey); } if (CPA_STATUS_SUCCESS == status && (CPA_CY_SYM_SESUPD_CIPHER_DIR & flags)) { status = LacAlgChain_SessionDirectionUpdate( pSessionDesc, pSessionUpdateData->cipherDirection); } LacAlgChain_UnlockSessionWriter(pSessionDesc); return status; } STATIC lac_single_pass_state_t LacSymAlgChain_GetSpcState(CpaCySymCipherAlgorithm cipher, CpaCySymHashAlgorithm hash, Cpa32U capabilitiesMask) { lac_single_pass_state_t state = SPC_NO; if (capabilitiesMask & ICP_ACCEL_CAPABILITIES_CHACHA_POLY) { switch (cipher) { case CPA_CY_SYM_CIPHER_CHACHA: { if (CPA_CY_SYM_HASH_POLY == hash) state = SPC_YES; break; } case CPA_CY_SYM_CIPHER_AES_GCM: { if ((CPA_CY_SYM_HASH_AES_GCM == hash) || (CPA_CY_SYM_HASH_AES_GMAC == hash)) state = SPC_PROBABLE; break; } default: /* Do Nothing as it is SPC_NO */ break; } } if (LAC_CIPHER_IS_SPC_CCM(cipher, hash, capabilitiesMask)) { state = SPC_PROBABLE; } return state; } /** @ingroup LacAlgChain */ CpaStatus LacAlgChain_SessionInit( const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, lac_session_desc_t *pSessionDesc) { CpaStatus stat, status = CPA_STATUS_SUCCESS; sal_qat_content_desc_info_t *pCdInfo = NULL; sal_qat_content_desc_info_t *pCdInfoOptimised = NULL; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; Cpa32U capabilitiesMask = pService->generic_service_info.capabilitiesMask; Cpa8U *pHwBlockBaseInDRAM = NULL; Cpa8U *pOptimisedHwBlockBaseInDRAM = NULL; Cpa32U hwBlockOffsetInDRAM = 0; Cpa32U optimisedHwBlockOffsetInDRAM = 0; Cpa8U cipherOffsetInConstantsTable = 0; Cpa8U hashOffsetInConstantsTable = 0; icp_qat_fw_comn_flags cmnRequestFlags = 0; icp_qat_fw_comn_req_t *pMsg = NULL; icp_qat_fw_comn_req_t *pMsgS = NULL; icp_qat_fw_slice_t nextSlice = ICP_QAT_FW_SLICE_NULL; const CpaCySymCipherSetupData *pCipherData; const CpaCySymHashSetupData *pHashData; Cpa16U proto = ICP_QAT_FW_LA_NO_PROTO; /* no CCM/GCM/Snow3G */ CpaCySymAlgChainOrder chainOrder = 0; lac_sym_qat_hash_precompute_info_t precomputeData = {0}; lac_sym_qat_hash_precompute_info_t precomputeDataOptimisedCd = {0}; LAC_ENSURE_NOT_NULL(instanceHandle); LAC_ENSURE_NOT_NULL(pSessionSetupData); LAC_ENSURE_NOT_NULL(pSessionDesc); pCipherData = &(pSessionSetupData->cipherSetupData); pHashData = &(pSessionSetupData->hashSetupData); #ifndef QAT_LEGACY_ALGORITHMS if (LAC_IS_LEGACY_ALGORITHMS(pCipherData->cipherAlgorithm, pHashData->hashAlgorithm)) { LAC_UNSUPPORTED_PARAM_LOG("Unsupported Cipher/Hash Algorithm"); return CPA_STATUS_UNSUPPORTED; } #endif /*------------------------------------------------------------------------- * Populate session data *-----------------------------------------------------------------------*/ /* Initialise Request Queue */ stat = LAC_SPINLOCK_INIT(&pSessionDesc->requestQueueLock); if (CPA_STATUS_SUCCESS != stat) { LAC_LOG_ERROR("Spinlock init failed for sessionLock"); return CPA_STATUS_RESOURCE; } /* Initialise session readers writers */ osalAtomicSet(0, &pSessionDesc->accessLock); pSessionDesc->pRequestQueueHead = NULL; pSessionDesc->pRequestQueueTail = NULL; pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; pSessionDesc->pInstance = instanceHandle; pSessionDesc->digestIsAppended = pSessionSetupData->digestIsAppended; pSessionDesc->digestVerify = pSessionSetupData->verifyDigest; /* Reset the pending callback counter */ osalAtomicSet(0, &pSessionDesc->u.pendingCbCount); pSessionDesc->u.pendingDpCbCount = 0; pSessionDesc->accessReaders = 0; /* Partial state must be set to full, to indicate that next packet * expected on the session is a full packet or the start of a * partial packet. */ pSessionDesc->partialState = CPA_CY_SYM_PACKET_TYPE_FULL; pSessionDesc->symOperation = pSessionSetupData->symOperation; switch (pSessionDesc->symOperation) { case CPA_CY_SYM_OP_CIPHER: pSessionDesc->isCipher = CPA_TRUE; pSessionDesc->isAuth = CPA_FALSE; pSessionDesc->isAuthEncryptOp = CPA_FALSE; pSessionDesc->singlePassState = SPC_NO; break; case CPA_CY_SYM_OP_HASH: pSessionDesc->isCipher = CPA_FALSE; pSessionDesc->isAuth = CPA_TRUE; pSessionDesc->isAuthEncryptOp = CPA_FALSE; pSessionDesc->singlePassState = SPC_NO; break; case CPA_CY_SYM_OP_ALGORITHM_CHAINING: { pSessionDesc->isCipher = CPA_TRUE; pSessionDesc->isAuth = CPA_TRUE; pSessionDesc->singlePassState = LacSymAlgChain_GetSpcState(pCipherData->cipherAlgorithm, pHashData->hashAlgorithm, capabilitiesMask); switch (pSessionSetupData->cipherSetupData.cipherAlgorithm) { case CPA_CY_SYM_CIPHER_AES_CCM: { pSessionDesc->isAuthEncryptOp = CPA_TRUE; pSessionDesc->digestIsAppended = CPA_TRUE; } break; case CPA_CY_SYM_CIPHER_AES_GCM: case CPA_CY_SYM_CIPHER_CHACHA: pSessionDesc->isAuthEncryptOp = CPA_TRUE; break; default: { pSessionDesc->isAuthEncryptOp = CPA_FALSE; /* Use the chainOrder passed in */ chainOrder = pSessionSetupData->algChainOrder; #ifdef ICP_PARAM_CHECK if ((chainOrder != CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER) && (chainOrder != CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH)) { LAC_INVALID_PARAM_LOG("algChainOrder"); return CPA_STATUS_INVALID_PARAM; } #endif } break; } } break; default: pSessionDesc->singlePassState = SPC_NO; break; } if (pSessionDesc->isCipher) { /* Populate cipher specific session data */ #ifdef ICP_PARAM_CHECK status = LacCipher_SessionSetupDataCheck( pCipherData, capabilitiesMask, (sal_service_t *)pService); #endif if (CPA_STATUS_SUCCESS == status) { pSessionDesc->cipherAlgorithm = pCipherData->cipherAlgorithm; pSessionDesc->cipherKeyLenInBytes = pCipherData->cipherKeyLenInBytes; pSessionDesc->cipherDirection = pCipherData->cipherDirection; /* ARC4 base key isn't added to the content descriptor, because * we don't need to pass it directly to the QAT engine. Instead * an initial cipher state & key matrix is derived from the * base key and provided to the QAT through the state pointer * in the request params. We'll store this initial state in * the session descriptor. */ if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { LacSymQat_CipherArc4StateInit( pCipherData->pCipherKey, pSessionDesc->cipherKeyLenInBytes, pSessionDesc->cipherARC4InitialState); pSessionDesc->cipherARC4InitialStatePhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pSessionDesc->cipherARC4InitialState); if (0 == pSessionDesc->cipherARC4InitialStatePhysAddr) { LAC_LOG_ERROR("Unable to get the physical address of " "the initial state for ARC4\n"); status = CPA_STATUS_FAIL; } } } } if ((CPA_STATUS_SUCCESS == status) && pSessionDesc->isAuth) { /* Populate auth-specific session data */ const CpaCySymHashSetupData *pHashData = &pSessionSetupData->hashSetupData; #ifdef ICP_PARAM_CHECK status = LacHash_HashContextCheck(instanceHandle, pHashData); #endif if (CPA_STATUS_SUCCESS == status) { pSessionDesc->hashResultSize = pHashData->digestResultLenInBytes; pSessionDesc->hashMode = pHashData->hashMode; pSessionDesc->hashAlgorithm = pHashData->hashAlgorithm; /* Save the authentication key length for further update */ if (CPA_CY_SYM_HASH_MODE_AUTH == pHashData->hashMode) { pSessionDesc->authKeyLenInBytes = pHashData->authModeSetupData.authKeyLenInBytes; } if (CPA_TRUE == pSessionDesc->isAuthEncryptOp || (pHashData->hashAlgorithm == CPA_CY_SYM_HASH_SNOW3G_UIA2 || pHashData->hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3)) { pSessionDesc->aadLenInBytes = pHashData->authModeSetupData.aadLenInBytes; } /* Set the QAT hash mode */ if ((pHashData->hashMode == CPA_CY_SYM_HASH_MODE_NESTED) || (pHashData->hashMode == CPA_CY_SYM_HASH_MODE_PLAIN) || (pHashData->hashMode == CPA_CY_SYM_HASH_MODE_AUTH && pHashData->hashAlgorithm == CPA_CY_SYM_HASH_AES_CBC_MAC)) { pSessionDesc->qatHashMode = ICP_QAT_HW_AUTH_MODE0; } else /* CPA_CY_SYM_HASH_MODE_AUTH && anything except CPA_CY_SYM_HASH_AES_CBC_MAC */ { if (IS_HMAC_ALG(pHashData->hashAlgorithm)) { /* SHA3 HMAC do not support precompute, force MODE2 * for AUTH */ if (LAC_HASH_IS_SHA3(pHashData->hashAlgorithm) || (CPA_CY_SYM_HASH_SM3 == pHashData->hashAlgorithm)) { pSessionDesc->qatHashMode = ICP_QAT_HW_AUTH_MODE2; } else { /* Set default HMAC Hash mode value */ pSessionDesc->qatHashMode = ICP_QAT_HW_AUTH_MODE1; } } else { pSessionDesc->qatHashMode = ICP_QAT_HW_AUTH_MODE1; } } } } /*------------------------------------------------------------------------- * build the message templates * create two content descriptors in the case we can support using SHRAM * constants and an optimised content descriptor. we have to do this in case * of partials. * 64 byte content descriptor is used in the SHRAM case for * AES-128-HMAC-SHA1 *-----------------------------------------------------------------------*/ if (CPA_STATUS_SUCCESS == status) { pSessionDesc->cipherSliceType = LacCipher_GetCipherSliceType( &pService->generic_service_info, pSessionDesc->cipherAlgorithm); pSessionDesc->useOptimisedContentDesc = CPA_FALSE; /* Build configuration data */ buildCmdData(pSessionDesc, &chainOrder, &proto, &pSessionDesc->laCmdFlags, &pSessionDesc->laExtCmdFlags, &cmnRequestFlags); /* Disable SymConstantsTable based CD optimization when UCS slice is * used for Gen4 device. */ if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE == pSessionDesc->cipherSliceType && pService->generic_service_info.isGen4) { pSessionDesc->useSymConstantsTable = CPA_FALSE; } else { pSessionDesc->useSymConstantsTable = LacSymQat_UseSymConstantsTable(pSessionDesc, &cipherOffsetInConstantsTable, &hashOffsetInConstantsTable); } /* for a certain combination of Algorithm Chaining we want to use an optimised content descriptor (CD) block */ if (pSessionDesc->symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING && pSessionDesc->useSymConstantsTable == CPA_TRUE) { pSessionDesc->useOptimisedContentDesc = LacSymQat_UseOptimisedContentDesc(pSessionDesc); } /* setup some convenience pointers */ pCdInfo = &(pSessionDesc->contentDescInfo); pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; hwBlockOffsetInDRAM = 0; /* set up the pointer for the optimised content desc if this is possible * we still have to support both cd types in case of partials so * we construct both */ if (pSessionDesc->useOptimisedContentDesc == CPA_TRUE) { pCdInfoOptimised = &(pSessionDesc->contentDescOptimisedInfo); pOptimisedHwBlockBaseInDRAM = (Cpa8U *)pCdInfoOptimised->pData; optimisedHwBlockOffsetInDRAM = 0; } switch (pSessionDesc->symOperation) { case CPA_CY_SYM_OP_CIPHER: { LacAlgChain_CipherCDBuild(pCipherData, pSessionDesc, ICP_QAT_FW_SLICE_DRAM_WR, cipherOffsetInConstantsTable, &pSessionDesc->cmnRequestFlags, &pSessionDesc->laCmdFlags, pHwBlockBaseInDRAM, &hwBlockOffsetInDRAM, capabilitiesMask); if (pSessionDesc->useSymConstantsTable) { LacAlgChain_CipherCDBuild_ForSHRAM( pCipherData, pSessionDesc, ICP_QAT_FW_SLICE_DRAM_WR, cipherOffsetInConstantsTable); } } break; case CPA_CY_SYM_OP_HASH: /* Use ICP_QAT_FW_SLICE_DRAM_WR if this is a Crypto HASH as part * of a DC Chaining (Compression) operation on Gen2 devices */ if ((SAL_SERVICE_TYPE_COMPRESSION == pService->generic_service_info.type) && !pService->generic_service_info.isGen4) { nextSlice = ICP_QAT_FW_SLICE_DRAM_WR; } LacAlgChain_HashCDBuild(pHashData, instanceHandle, pSessionDesc, nextSlice, hashOffsetInConstantsTable, &pSessionDesc->cmnRequestFlags, &pSessionDesc->laCmdFlags, &precomputeData, &precomputeDataOptimisedCd, pHwBlockBaseInDRAM, &hwBlockOffsetInDRAM, NULL, NULL); break; case CPA_CY_SYM_OP_ALGORITHM_CHAINING: /* For CCM/GCM, CPM firmware currently expects the cipher and * hash h/w setup blocks to be arranged according to the chain * order (Except for GCM/CCM, order doesn't actually matter as * long as the config offsets are set correctly in CD control * blocks */ if (CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER == chainOrder) { LacAlgChain_HashCDBuild(pHashData, instanceHandle, pSessionDesc, ICP_QAT_FW_SLICE_CIPHER, hashOffsetInConstantsTable, &pSessionDesc->cmnRequestFlags, &pSessionDesc->laCmdFlags, &precomputeData, &precomputeDataOptimisedCd, pHwBlockBaseInDRAM, &hwBlockOffsetInDRAM, pOptimisedHwBlockBaseInDRAM, &optimisedHwBlockOffsetInDRAM); LacAlgChain_CipherCDBuild(pCipherData, pSessionDesc, ICP_QAT_FW_SLICE_DRAM_WR, cipherOffsetInConstantsTable, &pSessionDesc->cmnRequestFlags, &pSessionDesc->laCmdFlags, pHwBlockBaseInDRAM, &hwBlockOffsetInDRAM, capabilitiesMask); if (pSessionDesc->useOptimisedContentDesc) { LacAlgChain_CipherCDBuild_ForOptimisedCD( pCipherData, pSessionDesc, ICP_QAT_FW_SLICE_DRAM_WR, cipherOffsetInConstantsTable, pOptimisedHwBlockBaseInDRAM, &optimisedHwBlockOffsetInDRAM); } if (SPC_NO != pSessionDesc->singlePassState) { pCdInfo->hwBlkSzQuadWords = (LAC_BYTES_TO_QUADWORDS(hwBlockOffsetInDRAM)); pMsg = (icp_qat_fw_comn_req_t *)&( pSessionDesc->reqSpcCacheHdr); SalQatMsg_ContentDescHdrWrite( (icp_qat_fw_comn_req_t *)pMsg, pCdInfo); } } else /* CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH */ { LacAlgChain_CipherCDBuild(pCipherData, pSessionDesc, ICP_QAT_FW_SLICE_AUTH, cipherOffsetInConstantsTable, &pSessionDesc->cmnRequestFlags, &pSessionDesc->laCmdFlags, pHwBlockBaseInDRAM, &hwBlockOffsetInDRAM, capabilitiesMask); if (pSessionDesc->useOptimisedContentDesc) { LacAlgChain_CipherCDBuild_ForOptimisedCD( pCipherData, pSessionDesc, ICP_QAT_FW_SLICE_AUTH, cipherOffsetInConstantsTable, pOptimisedHwBlockBaseInDRAM, &optimisedHwBlockOffsetInDRAM); } if (SPC_NO != pSessionDesc->singlePassState) { pCdInfo->hwBlkSzQuadWords = LAC_BYTES_TO_QUADWORDS(hwBlockOffsetInDRAM); pMsg = (icp_qat_fw_comn_req_t *)&( pSessionDesc->reqSpcCacheHdr); SalQatMsg_ContentDescHdrWrite( (icp_qat_fw_comn_req_t *)pMsg, pCdInfo); } LacAlgChain_HashCDBuild(pHashData, instanceHandle, pSessionDesc, ICP_QAT_FW_SLICE_DRAM_WR, hashOffsetInConstantsTable, &pSessionDesc->cmnRequestFlags, &pSessionDesc->laCmdFlags, &precomputeData, &precomputeDataOptimisedCd, pHwBlockBaseInDRAM, &hwBlockOffsetInDRAM, pOptimisedHwBlockBaseInDRAM, &optimisedHwBlockOffsetInDRAM); } break; default: LAC_LOG_ERROR("Invalid sym operation\n"); status = CPA_STATUS_INVALID_PARAM; } } if ((CPA_STATUS_SUCCESS == status) && pSessionDesc->isAuth) { lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = &(pSessionDesc->hashStateBufferInfo); CpaBoolean hashStateBuffer = CPA_TRUE; /* set up fields in both the cd_ctrl and reqParams which describe * the ReqParams block */ LacSymQat_HashSetupReqParamsMetaData(&(pSessionDesc->reqCacheFtr), instanceHandle, pHashData, hashStateBuffer, pSessionDesc->qatHashMode, pSessionDesc->digestVerify); if (pSessionDesc->useSymConstantsTable) { /* Need to set up for SHRAM Constants Table use also */ LacSymQat_HashSetupReqParamsMetaData( &(pSessionDesc->shramReqCacheFtr), instanceHandle, pHashData, hashStateBuffer, pSessionDesc->qatHashMode, pSessionDesc->digestVerify); } /* populate the hash state prefix buffer info structure * (part of user allocated session memory & the * buffer itself. For CCM/GCM the buffer is stored in the * cookie and is not initialised here). */ if (CPA_FALSE == pSessionDesc->isAuthEncryptOp) { #ifdef ICP_PARAM_CHECK LAC_CHECK_64_BYTE_ALIGNMENT( &(pSessionDesc->hashStatePrefixBuffer[0])); #endif { status = LacHash_StatePrefixAadBufferInit( &(pService->generic_service_info), pHashData, &(pSessionDesc->reqCacheFtr), pSessionDesc->qatHashMode, pSessionDesc->hashStatePrefixBuffer, pHashStateBufferInfo); /* SHRAM Constants Table not used for Auth-Enc */ } if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to populate hash state buffer or key.\n"); } } if (CPA_STATUS_SUCCESS == status) { if (IS_HASH_MODE_1(pSessionDesc->qatHashMode) || CPA_CY_SYM_HASH_ZUC_EIA3 == pHashData->hashAlgorithm) { #ifdef ICP_PARAM_CHECK LAC_CHECK_64_BYTE_ALIGNMENT( &(pSessionDesc->hashStatePrefixBuffer[0])); #endif /* Block messages until precompute is completed */ pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; status = LacHash_PrecomputeDataCreate( instanceHandle, (CpaCySymSessionSetupData *)pSessionSetupData, LacSymAlgChain_HashPrecomputeDoneCb, pSessionDesc, pSessionDesc->hashStatePrefixBuffer, precomputeData.pState1, precomputeData.pState2); if (pSessionDesc->useOptimisedContentDesc) { status = LacHash_PrecomputeDataCreate( instanceHandle, (CpaCySymSessionSetupData *)pSessionSetupData, LacSymAlgChain_HashPrecomputeDoneCb, pSessionDesc, pSessionDesc->hashStatePrefixBuffer, precomputeDataOptimisedCd.pState1, precomputeDataOptimisedCd.pState2); } } else if (pHashData->hashAlgorithm == CPA_CY_SYM_HASH_AES_CBC_MAC) { LAC_OS_BZERO(precomputeData.pState2, precomputeData.state2Size); memcpy(precomputeData.pState2, pHashData->authModeSetupData.authKey, pHashData->authModeSetupData.authKeyLenInBytes); } } } if (CPA_STATUS_SUCCESS == status) { /* Configure the ContentDescriptor field in the request if not done already */ pCdInfo->hwBlkSzQuadWords = LAC_BYTES_TO_QUADWORDS(hwBlockOffsetInDRAM); pMsg = (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqCacheHdr); SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)pMsg, pCdInfo); pMsgS = (icp_qat_fw_comn_req_t *)&(pSessionDesc->shramReqCacheHdr); /*If we are using the optimised CD then we have to set this up correctly in the SHARM reqCache*/ if (pSessionDesc->useOptimisedContentDesc && pCdInfoOptimised) { pCdInfoOptimised->hwBlkSzQuadWords = LAC_BYTES_TO_QUADWORDS(optimisedHwBlockOffsetInDRAM); SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)pMsgS, pCdInfoOptimised); } /* Updates command flags basing on configured alg */ updateLaCmdFlags(pSessionDesc, proto, &pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pMsg, ICP_QAT_FW_COMN_REQ_CPM_FW_LA, pSessionDesc->laCmdId, pSessionDesc->cmnRequestFlags, pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); /* Need to duplicate if SHRAM Constants Table used */ if (pSessionDesc->useSymConstantsTable) { ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET( pSessionDesc->laCmdFlags, ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_SHRAM_CP); /* Only Direct CD can be used with SHRAM constants page */ if (!pSessionDesc->useOptimisedContentDesc) { ICP_QAT_FW_COMN_CD_FLD_TYPE_SET( cmnRequestFlags, QAT_COMN_CD_FLD_TYPE_16BYTE_DATA); } SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pMsgS, ICP_QAT_FW_COMN_REQ_CPM_FW_LA, pSessionDesc->laCmdId, cmnRequestFlags, pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); } } return status; } /** @ingroup LacAlgChain */ CpaStatus LacAlgChain_Perform(const CpaInstanceHandle instanceHandle, lac_session_desc_t *pSessionDesc, void *pCallbackTag, const CpaCySymOpData *pOpData, lac_sym_bulk_cookie_t *pCookie, const CpaBufferList *pSrcBuffer, CpaBufferList *pDstBuffer, CpaBoolean *pVerifyResult) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; Cpa32U capabilitiesMask = pService->generic_service_info.capabilitiesMask; lac_sym_cookie_t *pSymCookie = NULL; icp_qat_fw_la_bulk_req_t *pMsg = NULL; icp_qat_fw_la_cipher_20_req_params_t *pCipher20ReqParams = NULL; Cpa8U *pMsgDummy = NULL; Cpa8U *pCacheDummyHdr = NULL; Cpa8U *pCacheDummyFtr = NULL; Cpa32U qatPacketType = 0; CpaBufferList *pBufferList = NULL; Cpa8U *pDigestResult = NULL; Cpa64U srcAddrPhys = 0; Cpa64U dstAddrPhys = 0; icp_qat_fw_la_cmd_id_t laCmdId; sal_qat_content_desc_info_t *pCdInfo = NULL; Cpa8U *pHwBlockBaseInDRAM = NULL; Cpa32U hwBlockOffsetInDRAM = 0; Cpa32U sizeInBytes = 0; icp_qat_fw_cipher_cd_ctrl_hdr_t *pSpcCdCtrlHdr = NULL; CpaBoolean isDcChaining = CPA_FALSE; CpaCySymCipherAlgorithm cipher; CpaCySymHashAlgorithm hash; Cpa8U paddingLen = 0; Cpa8U blockLen = 0; CpaBoolean digestIsAppended = CPA_FALSE; Cpa32U aadLenInBytes = 0; CpaBoolean isSpGcm, isSpCcp, isSpCcm; #ifdef ICP_PARAM_CHECK Cpa64U srcPktSize = 0; Cpa64U dstPktSize = 0; #endif LAC_ENSURE_NOT_NULL(pSessionDesc); LAC_ENSURE_NOT_NULL(pOpData); LacAlgChain_LockSessionReader(pSessionDesc); /* Set the command id */ laCmdId = pSessionDesc->laCmdId; cipher = pSessionDesc->cipherAlgorithm; hash = pSessionDesc->hashAlgorithm; /* pCookie will already be allocated for DC Chaining requests */ if (NULL != pCookie) { isDcChaining = pCookie->dcChain.isDcChaining; } if (CPA_CY_SYM_HASH_AES_GMAC == hash) { pSessionDesc->aadLenInBytes = pOpData->messageLenToHashInBytes; #ifdef ICP_PARAM_CHECK if (pOpData->messageLenToHashInBytes == 0 || pOpData->pAdditionalAuthData != NULL) { LAC_INVALID_PARAM_LOG("For AES_GMAC, AAD Length " "(messageLenToHashInBytes) must " "be non zero and pAdditionalAuthData " "must be NULL"); /* Unlock session on error */ LacAlgChain_UnlockSessionReader(pSessionDesc); return CPA_STATUS_INVALID_PARAM; } #endif } aadLenInBytes = pSessionDesc->aadLenInBytes; isSpGcm = LAC_CIPHER_IS_SPC_GCM(cipher, hash, capabilitiesMask); isSpCcp = LAC_CIPHER_IS_SPC_CCP(cipher, hash, capabilitiesMask); isSpCcm = LAC_CIPHER_IS_SPC_CCM(cipher, hash, capabilitiesMask); /* Convert Alg Chain Request to Cipher Request for CCP, * AES_GCM and AES_CCM single pass. * HW supports only 12 bytes IVs for single pass CCP and AES_GCM, * there is no such restriction for single pass CCM */ if ((SPC_NO != pSessionDesc->singlePassState) && ((LAC_CIPHER_SPC_IV_SIZE == pOpData->ivLenInBytes && (isSpGcm || isSpCcp)) || isSpCcm)) { pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; laCmdId = pSessionDesc->laCmdId; pSessionDesc->symOperation = CPA_CY_SYM_OP_CIPHER; pSessionDesc->singlePassState = SPC_YES; pSessionDesc->isCipher = CPA_TRUE; pSessionDesc->isAuthEncryptOp = CPA_FALSE; pSessionDesc->isAuth = CPA_FALSE; #ifdef ICP_PARAM_CHECK if (CPA_CY_SYM_HASH_AES_GMAC == hash) { if (ICP_QAT_FW_SPC_AAD_SZ_MAX < aadLenInBytes) { LAC_INVALID_PARAM_LOG("aadLenInBytes for AES_GMAC"); /* Unlock session on error */ LacAlgChain_UnlockSessionReader(pSessionDesc); return CPA_STATUS_INVALID_PARAM; } } #endif /* New bit position (13) for SINGLE PASS. * The FW provides a specific macro to use to set the proto flag */ ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET( pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_SINGLE_PASS_PROTO); pCdInfo = &(pSessionDesc->contentDescInfo); pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == pSessionDesc->cipherDirection) { if (LAC_CIPHER_IS_GCM(cipher)) hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( LAC_SYM_QAT_CIPHER_GCM_SPC_OFFSET_IN_DRAM); else if (LAC_CIPHER_IS_CHACHA(cipher)) hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( LAC_SYM_QAT_CIPHER_CHACHA_SPC_OFFSET_IN_DRAM); } else if (isSpCcm) { hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( LAC_SYM_QAT_CIPHER_CCM_SPC_OFFSET_IN_DRAM); } /* Update cipher slice type */ pSessionDesc->cipherSliceType = LacCipher_GetCipherSliceType( &pService->generic_service_info, pSessionDesc->cipherAlgorithm); ICP_QAT_FW_LA_SLICE_TYPE_SET(pSessionDesc->laCmdFlags, pSessionDesc->cipherSliceType); /* construct cipherConfig in CD in DRAM */ LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, pHwBlockBaseInDRAM + hwBlockOffsetInDRAM, &sizeInBytes); SalQatMsg_CmnHdrWrite( (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqSpcCacheHdr), ICP_QAT_FW_COMN_REQ_CPM_FW_LA, laCmdId, pSessionDesc->cmnRequestFlags, pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); } else if ((SPC_YES == pSessionDesc->singlePassState) && (LAC_CIPHER_SPC_IV_SIZE != pOpData->ivLenInBytes)) { pSessionDesc->symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; pSessionDesc->singlePassState = SPC_PROBABLE; pSessionDesc->isCipher = CPA_TRUE; pSessionDesc->isAuthEncryptOp = CPA_TRUE; pSessionDesc->isAuth = CPA_TRUE; pCdInfo = &(pSessionDesc->contentDescInfo); pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == pSessionDesc->cipherDirection) { pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER_HASH; } else { pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_HASH_CIPHER; } laCmdId = pSessionDesc->laCmdId; ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET(pSessionDesc->laCmdFlags, 0); ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_GCM_PROTO); LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, pHwBlockBaseInDRAM + hwBlockOffsetInDRAM, &sizeInBytes); SalQatMsg_CmnHdrWrite( (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqCacheHdr), ICP_QAT_FW_COMN_REQ_CPM_FW_LA, laCmdId, pSessionDesc->cmnRequestFlags, pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); } #ifdef ICP_PARAM_CHECK else if (LAC_CIPHER_IS_CHACHA(cipher) && (LAC_CIPHER_SPC_IV_SIZE != pOpData->ivLenInBytes)) { LAC_INVALID_PARAM_LOG("IV for CHACHA"); /* Unlock session on error */ LacAlgChain_UnlockSessionReader(pSessionDesc); return CPA_STATUS_INVALID_PARAM; } #endif if ((CPA_TRUE == pSessionDesc->isAuthEncryptOp) || isSpCcm) { if (CPA_CY_SYM_HASH_AES_CCM == hash) { #ifdef ICP_PARAM_CHECK status = LacSymAlgChain_CheckCCMData(pOpData->pAdditionalAuthData, pOpData->pIv, pOpData->messageLenToCipherInBytes, pOpData->ivLenInBytes); #endif if (CPA_STATUS_SUCCESS == status) { LacSymAlgChain_PrepareCCMData( pSessionDesc, pOpData->pAdditionalAuthData, pOpData->pIv, pOpData->messageLenToCipherInBytes, pOpData->ivLenInBytes); } } else if (CPA_CY_SYM_HASH_AES_GCM == hash) { #ifdef ICP_PARAM_CHECK if (aadLenInBytes != 0 && pOpData->pAdditionalAuthData == NULL) { LAC_INVALID_PARAM_LOG("pAdditionalAuthData"); status = CPA_STATUS_INVALID_PARAM; } #endif if (CPA_STATUS_SUCCESS == status) { LacSymAlgChain_PrepareGCMData(pSessionDesc, pOpData->pAdditionalAuthData); } } } if (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation && CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) { /* Accumulate the size of partial hash requests. */ pSessionDesc->totalHashPartialReq += pOpData->messageLenToHashInBytes; /* Check if hash request size is 4GB or more. */ if (CPA_STATUS_SUCCESS == status && MAX_HASH_PARTIALS_SIZE <= pSessionDesc->totalHashPartialReq) { LAC_LOG_ERROR("Partial Hash processing of size 4GB or more " "not supported"); pSessionDesc->totalHashPartialReq = 0; status = CPA_STATUS_FAIL; } else if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == pOpData->packetType) { pSessionDesc->totalHashPartialReq = 0; } } /* Allocate cookie (used by callback function). * If calling from DC Chaining then cookie should already be * allocated. */ if ((CPA_STATUS_SUCCESS == status) && (NULL == pCookie)) { do { pSymCookie = (lac_sym_cookie_t *)Lac_MemPoolEntryAlloc( pService->lac_sym_cookie_pool); if (pSymCookie == NULL) { LAC_LOG_ERROR("Cannot allocate cookie - NULL"); status = CPA_STATUS_RESOURCE; } else if ((void *)CPA_STATUS_RETRY == pSymCookie) { #ifdef ICP_NONBLOCKING_PARTIALS_PERFORM status = CPA_STATUS_RETRY; break; #else osalYield(); #endif } else { pCookie = &(pSymCookie->u.bulkCookie); pSymCookie->cookieType = LAC_SYM_BULK_COOKIE_TYPE; /* Initialize cookie isDcChaining field. This function uses * a local variable for isDcChaining but other places may use * the cookie so it needs to be correctly initialized. */ if (NULL != pCookie) pCookie->dcChain.isDcChaining = CPA_FALSE; } } while ((void *)CPA_STATUS_RETRY == pSymCookie); } if ((CPA_STATUS_SUCCESS == status) && (NULL == pCookie)) { status = CPA_STATUS_RESOURCE; } if (CPA_STATUS_SUCCESS == status) { /* write the buffer descriptors */ if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(cipher, hash) || (pSessionDesc->symOperation == CPA_CY_SYM_OP_HASH)) { status = LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( (CpaBufferList *)pSrcBuffer, &srcAddrPhys, CPA_FALSE, &(pService->generic_service_info)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Unable to write src buffer descriptors"); } /* For out of place operations */ if ((pSrcBuffer != pDstBuffer) && (CPA_STATUS_SUCCESS == status)) { status = LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( pDstBuffer, &dstAddrPhys, CPA_FALSE, &(pService->generic_service_info)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Unable to write dest buffer descriptors"); } } } else { status = LacBuffDesc_BufferListDescWrite( (CpaBufferList *)pSrcBuffer, &srcAddrPhys, CPA_FALSE, &(pService->generic_service_info)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Unable to write src buffer descriptors in " "LacBuffDesc_BufferListDescWrite"); } /* For out of place operations */ if ((pSrcBuffer != pDstBuffer) && (CPA_STATUS_SUCCESS == status)) { status = LacBuffDesc_BufferListDescWrite( pDstBuffer, &dstAddrPhys, CPA_FALSE, &(pService->generic_service_info)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Unable to write dest buffer descriptors in " "LacBuffDesc_BufferListDescWrite"); } } } } if (CPA_STATUS_SUCCESS == status && pCookie != NULL) { /* populate the cookie */ pCookie->pCallbackTag = pCallbackTag; pCookie->sessionCtx = pOpData->sessionCtx; pCookie->pOpData = (const CpaCySymOpData *)pOpData; pCookie->pDstBuffer = pDstBuffer; pCookie->updateSessionIvOnSend = CPA_FALSE; pCookie->updateUserIvOnRecieve = CPA_FALSE; pCookie->updateKeySizeOnRecieve = CPA_FALSE; pCookie->pNext = NULL; pCookie->instanceHandle = pService; /* get the qat packet type for LAC packet type */ LacSymQat_packetTypeGet( pOpData->packetType, pSessionDesc->partialState, &qatPacketType); /* * For XTS mode, the key size must be updated after * the first partial has been sent. Set a flag here so the * response knows to do this. */ if (LAC_CIPHER_IS_XTS_MODE(cipher) && (laCmdId != ICP_QAT_FW_LA_CMD_AUTH) && (CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) && (qatPacketType == ICP_QAT_FW_LA_PARTIAL_START)) { pCookie->updateKeySizeOnRecieve = CPA_TRUE; } /* * Now create the Request. * Start by populating it from the cache in the session descriptor. */ pMsg = &(pCookie->qatMsg); pMsgDummy = (Cpa8U *)pMsg; if (SPC_YES == pSessionDesc->singlePassState) { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqSpcCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqSpcCacheFtr); } else { /* Normally, we want to use the SHRAM Constants Table if possible * for best performance (less DRAM accesses incurred by CPM). But * we can't use it for partial-packet hash operations. This is why * we build 2 versions of the message template at sessionInit, * one for SHRAM Constants Table usage and the other (default) for * Content Descriptor h/w setup data in DRAM. And we chose between * them here on a per-request basis, when we know the packetType */ if ((!pSessionDesc->useSymConstantsTable) || (pSessionDesc->isAuth && (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType))) { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqCacheFtr); } else { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->shramReqCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->shramReqCacheFtr); } } osalMemCopy(pMsgDummy, pCacheDummyHdr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); osalMemSet((pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), 0, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), pCacheDummyFtr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); /* * Populate the comn_mid section */ SalQatMsg_CmnMidWrite(pMsg, pCookie, LAC_SYM_DEFAULT_QAT_PTR_TYPE, srcAddrPhys, dstAddrPhys, 0, 0); /* * Populate the serv_specif_flags field of the Request header * Some of the flags are set up here. * Others are set up later when the RequestParams are set up. */ LacSymQat_LaPacketCommandFlagSet(qatPacketType, laCmdId, cipher, &pMsg->comn_hdr.serv_specif_flags, pOpData->ivLenInBytes); if (SPC_YES == pSessionDesc->singlePassState) { ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( pMsg->comn_hdr.serv_specif_flags, ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS); if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) { ICP_QAT_FW_LA_RET_AUTH_SET(pMsg->comn_hdr.serv_specif_flags, ICP_QAT_FW_LA_NO_RET_AUTH_RES); ICP_QAT_FW_LA_CMP_AUTH_SET(pMsg->comn_hdr.serv_specif_flags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); } } ICP_QAT_FW_LA_SLICE_TYPE_SET(pMsg->comn_hdr.serv_specif_flags, pSessionDesc->cipherSliceType); #ifdef ICP_PARAM_CHECK LacBuffDesc_BufferListTotalSizeGet(pSrcBuffer, &srcPktSize); LacBuffDesc_BufferListTotalSizeGet(pDstBuffer, &dstPktSize); #endif /* * Populate the CipherRequestParams section of the Request */ if (laCmdId != ICP_QAT_FW_LA_CMD_AUTH) { Cpa8U *pIvBuffer = NULL; #ifdef ICP_PARAM_CHECK status = LacCipher_PerformParamCheck(cipher, pOpData, srcPktSize); #endif if (CPA_STATUS_SUCCESS == status) { /* align cipher IV */ status = LacCipher_PerformIvCheck(&(pService->generic_service_info), pCookie, qatPacketType, &pIvBuffer); } if ((SPC_YES == pSessionDesc->singlePassState) && ((ICP_QAT_FW_LA_PARTIAL_MID == qatPacketType) || (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType))) { /* For SPC stateful cipher state size for mid and * end partial packet is 48 bytes */ pSpcCdCtrlHdr = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); pSpcCdCtrlHdr->cipher_state_sz = LAC_BYTES_TO_QUADWORDS(LAC_SYM_QAT_CIPHER_SPC_STATE_SIZE); } /*populate the cipher request parameters */ if (CPA_STATUS_SUCCESS == status) { Cpa64U ivBufferPhysAddr = 0; if (pIvBuffer != NULL) { /* User OpData memory being used for IV buffer */ /* get the physical address */ ivBufferPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pIvBuffer); if (0 == ivBufferPhysAddr) { LAC_LOG_ERROR("Unable to get the physical address " "of the IV\n"); status = CPA_STATUS_FAIL; } } if (status == CPA_STATUS_SUCCESS) { status = LacSymQat_CipherRequestParamsPopulate( pSessionDesc, pMsg, pOpData->cryptoStartSrcOffsetInBytes, pOpData->messageLenToCipherInBytes, ivBufferPhysAddr, pIvBuffer); } } if ((SPC_YES == pSessionDesc->singlePassState) && CPA_STATUS_SUCCESS == status) { Cpa64U aadBufferPhysAddr = 0; /* For CHACHA, AES-GCM and AES-CCM there is an AAD buffer if * aadLenInBytes is nonzero In case of AES-GMAC, AAD buffer * passed in the src buffer. * Additionally even if aadLenInBytes is 0 for AES-CCM, * still AAD buffer need to be used, as it contains B0 block * and encoded AAD len. */ if ((0 != aadLenInBytes && CPA_CY_SYM_HASH_AES_GMAC != hash) || isSpCcm) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pOpData->pAdditionalAuthData); #endif /* In case of AES_CCM, B0 block size and 2 bytes of AAD len * encoding need to be added to total AAD data len */ if (isSpCcm) aadLenInBytes += LAC_CIPHER_CCM_AAD_OFFSET; blockLen = LacSymQat_CipherBlockSizeBytesGet(cipher); if (blockLen && (aadLenInBytes % blockLen) != 0) { paddingLen = blockLen - (aadLenInBytes % blockLen); osalMemSet(&pOpData->pAdditionalAuthData[aadLenInBytes], 0, paddingLen); } /* User OpData memory being used for AAD buffer */ /* get the physical address */ aadBufferPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pOpData->pAdditionalAuthData); if (0 == aadBufferPhysAddr) { LAC_LOG_ERROR("Unable to get the physical address " "of the aad\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { pCipher20ReqParams = (void *)((Cpa8U *)&(pMsg->serv_specif_rqpars) + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); if (pService->generic_service_info.isGen4) { pCipher20ReqParams->spc_aad_addr = aadBufferPhysAddr; pCipher20ReqParams->spc_aad_sz = pSessionDesc->aadLenInBytes; pCipher20ReqParams->spc_aad_offset = 0; if (isSpCcm) pCipher20ReqParams->spc_aad_sz += LAC_CIPHER_CCM_AAD_OFFSET; } if (CPA_TRUE != pSessionDesc->digestIsAppended) { Cpa64U digestBufferPhysAddr = 0; /* User OpData memory being used for digest buffer */ /* get the physical address */ digestBufferPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pOpData->pDigestResult); if (0 != digestBufferPhysAddr) { if (pService->generic_service_info.isGen4) { pCipher20ReqParams->spc_auth_res_addr = digestBufferPhysAddr; pCipher20ReqParams->spc_auth_res_sz = (Cpa8U)pSessionDesc->hashResultSize; } } else { LAC_LOG_ERROR("Unable to get the physical address " "of the digest\n"); status = CPA_STATUS_FAIL; } } else { #ifdef ICP_PARAM_CHECK /* Check if the dest buffer can handle the digest, only * for last packet */ if (((ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) || (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType))) { if (dstPktSize < (pOpData->cryptoStartSrcOffsetInBytes + pOpData->messageLenToCipherInBytes + pSessionDesc->hashResultSize)) status = CPA_STATUS_INVALID_PARAM; } #endif if (pService->generic_service_info.isGen4) { pCipher20ReqParams->spc_auth_res_sz = (Cpa8U)pSessionDesc->hashResultSize; } } } } } /* * Set up HashRequestParams part of Request */ if ((status == CPA_STATUS_SUCCESS) && (laCmdId != ICP_QAT_FW_LA_CMD_CIPHER)) { Cpa32U authOffsetInBytes = pOpData->hashStartSrcOffsetInBytes; Cpa32U authLenInBytes = pOpData->messageLenToHashInBytes; #ifdef ICP_PARAM_CHECK status = LacHash_PerformParamCheck(instanceHandle, pSessionDesc, pOpData, srcPktSize, pVerifyResult); #endif if (CPA_STATUS_SUCCESS == status) { /* Info structure for CCM/GCM */ lac_sym_qat_hash_state_buffer_info_t hashStateBufferInfo = {0}; lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = &(pSessionDesc->hashStateBufferInfo); if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { icp_qat_fw_la_auth_req_params_t *pHashReqParams = (icp_qat_fw_la_auth_req_params_t *)((Cpa8U *)&(pMsg->serv_specif_rqpars) + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); hashStateBufferInfo.pData = pOpData->pAdditionalAuthData; if (pOpData->pAdditionalAuthData == NULL) { hashStateBufferInfo.pDataPhys = 0; } else { hashStateBufferInfo.pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64( LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pOpData->pAdditionalAuthData)); } hashStateBufferInfo.stateStorageSzQuadWords = 0; hashStateBufferInfo.prefixAadSzQuadWords = LAC_BYTES_TO_QUADWORDS(pHashReqParams->u2.aad_sz); /* Overwrite hash state buffer info structure pointer * with the one created for CCM/GCM */ pHashStateBufferInfo = &hashStateBufferInfo; /* Aad buffer could be null in the GCM case */ if (0 == hashStateBufferInfo.pDataPhys && CPA_CY_SYM_HASH_AES_GCM != hash && CPA_CY_SYM_HASH_AES_GMAC != hash) { LAC_LOG_ERROR("Unable to get the physical address" "of the AAD\n"); status = CPA_STATUS_FAIL; } /* for CCM/GCM the hash and cipher data regions * are equal */ authOffsetInBytes = pOpData->cryptoStartSrcOffsetInBytes; /* For authenticated encryption, authentication length is * determined by messageLenToCipherInBytes for AES-GCM and * AES-CCM, and by messageLenToHashInBytes for AES-GMAC. * You don't see the latter here, as that is the initial * value of authLenInBytes. */ if (hash != CPA_CY_SYM_HASH_AES_GMAC) authLenInBytes = pOpData->messageLenToCipherInBytes; } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hash || CPA_CY_SYM_HASH_ZUC_EIA3 == hash) { hashStateBufferInfo.pData = pOpData->pAdditionalAuthData; hashStateBufferInfo.pDataPhys = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, hashStateBufferInfo.pData); hashStateBufferInfo.stateStorageSzQuadWords = 0; hashStateBufferInfo.prefixAadSzQuadWords = LAC_BYTES_TO_QUADWORDS(aadLenInBytes); pHashStateBufferInfo = &hashStateBufferInfo; if (0 == hashStateBufferInfo.pDataPhys) { LAC_LOG_ERROR("Unable to get the physical address" "of the AAD\n"); status = CPA_STATUS_FAIL; } } if (CPA_CY_SYM_HASH_AES_CCM == hash) { if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == pSessionDesc->cipherDirection) { /* On a decrypt path pSrcBuffer is used as this is * where encrypted digest is located. Firmware * uses encrypted digest for compare/verification*/ pBufferList = (CpaBufferList *)pSrcBuffer; } else { /* On an encrypt path pDstBuffer is used as this is * where encrypted digest will be written */ pBufferList = (CpaBufferList *)pDstBuffer; } status = LacSymAlgChain_PtrFromOffsetGet( pBufferList, pOpData->cryptoStartSrcOffsetInBytes + pOpData->messageLenToCipherInBytes, &pDigestResult); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Cannot set digest pointer within the" " buffer list - offset out of bounds"); } } else { pDigestResult = pOpData->pDigestResult; } if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation) { /* In alg chaining mode, packets are not seen as partials * for hash operations. Override to NONE. */ qatPacketType = ICP_QAT_FW_LA_PARTIAL_NONE; } digestIsAppended = pSessionDesc->digestIsAppended; #ifdef ICP_PARAM_CHECK if (CPA_TRUE == digestIsAppended) { /*Check if the destination buffer can handle the digest * if digestIsAppend is true*/ if (srcPktSize < (authOffsetInBytes + authLenInBytes + pSessionDesc->hashResultSize)) { status = CPA_STATUS_INVALID_PARAM; } } #endif if (CPA_STATUS_SUCCESS == status) { /* populate the hash request parameters */ status = LacSymQat_HashRequestParamsPopulate( pMsg, authOffsetInBytes, authLenInBytes, &(pService->generic_service_info), pHashStateBufferInfo, qatPacketType, pSessionDesc->hashResultSize, pSessionDesc->digestVerify, digestIsAppended ? NULL : pDigestResult, hash, NULL); } } } } /* DC Chaining has its own callback count so skip */ if (CPA_FALSE == isDcChaining) { /* Increase pending callbacks before unlocking session */ if (CPA_STATUS_SUCCESS == status) { osalAtomicInc(&(pSessionDesc->u.pendingCbCount)); } } LacAlgChain_UnlockSessionReader(pSessionDesc); /* Send message now if this is not a DC Chaining operation */ if (CPA_FALSE == isDcChaining) { /* * send the message to the QAT */ if (CPA_STATUS_SUCCESS == status) { status = LacSymQueue_RequestSend(instanceHandle, pCookie, pSessionDesc); if (CPA_STATUS_SUCCESS != status) { /* Decrease pending callback counter on send fail. */ osalAtomicDec(&(pSessionDesc->u.pendingCbCount)); } } } /* Case that will catch all error status's for this function */ if (CPA_STATUS_SUCCESS != status) { /* free the cookie */ if (NULL != pSymCookie) { Lac_MemPoolEntryFree(pSymCookie); } if (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation && CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType && pSessionDesc->totalHashPartialReq) { pSessionDesc->totalHashPartialReq -= pOpData->messageLenToHashInBytes; } } return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_api.c000066400000000000000000001547741503624047500307770ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file lac_sym_api.c Implementation of the symmetric API * * @ingroup LacSym * ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_cy_im.h" #include "Osal.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_transport_dp.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "icp_qat_fw_la.h" /* ****************************************************************************** * Include private header files ****************************************************************************** */ #include "lac_common.h" #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym.h" #include "lac_sym_qat.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_session.h" #include "lac_sym_cipher.h" #include "lac_sym_hash.h" #include "lac_sym_alg_chain.h" #include "lac_sym_stats.h" #include "lac_sym_partial.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_cb.h" #include "lac_buffer_desc.h" #include "lac_sync.h" #include "lac_hooks.h" #include "lac_sal_types_crypto.h" #include "sal_service_state.h" /* Macro for checking if partial packet are supported for a given * symmetric operation */ #define IS_PARTIAL_ON_SYM_OP_SUPPORTED( \ symOp, cipherAlgorithm, hashAlgorithm, hashMode) \ (((CPA_CY_SYM_OP_CIPHER == symOp) && \ (CPA_CY_SYM_CIPHER_KASUMI_F8 != cipherAlgorithm) && \ (CPA_CY_SYM_CIPHER_AES_F8 != cipherAlgorithm) && \ (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 != cipherAlgorithm) && \ (CPA_CY_SYM_CIPHER_ZUC_EEA3 != cipherAlgorithm)) || \ ((CPA_CY_SYM_OP_HASH == symOp) && \ (CPA_CY_SYM_HASH_KASUMI_F9 != hashAlgorithm) && \ (CPA_CY_SYM_HASH_SNOW3G_UIA2 != hashAlgorithm) && \ (CPA_CY_SYM_HASH_ZUC_EIA3 != hashAlgorithm)) || \ ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == symOp) && \ (CPA_CY_SYM_CIPHER_KASUMI_F8 != cipherAlgorithm) && \ (CPA_CY_SYM_CIPHER_AES_F8 != cipherAlgorithm) && \ (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 != cipherAlgorithm) && \ (CPA_CY_SYM_CIPHER_ZUC_EEA3 != cipherAlgorithm) && \ (CPA_CY_SYM_CIPHER_CHACHA != cipherAlgorithm) && \ (CPA_CY_SYM_HASH_KASUMI_F9 != hashAlgorithm) && \ (CPA_CY_SYM_HASH_SNOW3G_UIA2 != hashAlgorithm) && \ (CPA_CY_SYM_HASH_SHA3_256 != hashAlgorithm) && \ (CPA_CY_SYM_HASH_ZUC_EIA3 != hashAlgorithm) && \ (CPA_CY_SYM_HASH_POLY != hashAlgorithm))) #define IS_EXT_ALG_CHAIN_UNSUPPORTED( \ cipherAlgorithm, hashAlgorithm, extAlgchainSupported) \ ((((CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm || \ CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) && \ CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) || \ ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm || \ CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm || \ CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm) && \ CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) || \ ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm || \ CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm || \ CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) && \ CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm)) && \ !extAlgchainSupported) /*** Local functions definitions ***/ #ifdef ICP_PARAM_CHECK STATIC CpaStatus LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer, const CpaBufferList *const pDstBuffer, const lac_session_desc_t *const pSessionDesc, const CpaCySymOpData *const pOpData); #endif void LacDp_WriteRingMsgFull(CpaCySymDpOpData *pRequest, icp_qat_fw_la_bulk_req_t *pCurrentQatMsg); void LacDp_WriteRingMsgOpt(CpaCySymDpOpData *pRequest, icp_qat_fw_la_bulk_req_t *pCurrentQatMsg); void getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes); /** ***************************************************************************** * @ingroup LacSym * Generic bufferList callback function. * @description * This function is used when the API is called in synchronous mode. * It's assumed the callbackTag holds a lac_sync_op_data_t type * and when the callback is received, this callback shall set the * status and opResult element of that cookie structure and * kick the sid. * This function may be used directly as a callback function. * * @param[in] callbackTag Callback Tag * @param[in] status Status of callback * @param[in] operationType Operation Type * @param[in] pOpData Pointer to the Op Data * @param[out] pDstBuffer Pointer to destination buffer list * @param[out] opResult Boolean to indicate the result of the operation * * @return void * *****************************************************************************/ void LacSync_GenBufListVerifyCb(void *pCallbackTag, CpaStatus status, CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean opResult) { LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); } /* ******************************************************************************* * Define static function definitions ******************************************************************************* */ /** * @ingroup LacSym * Function which performs capability checks on session setup data * * @param[in] CpaInstanceHandle Instance handle * @param[in] pSessionSetupData Pointer to session setup data * * @retval CPA_STATUS_SUCCESS The operation succeeded * @retval CPA_STATUS_INVALID_PARAM An invalid parameter value was selected * @retval CPA_STATUS_UNSUPPORTED An unsupported algorithm was selected */ STATIC CpaStatus LacSymSession_CapabilityCheck(const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymCapabilitiesInfo symCapInfo; CpaBoolean extAlgchainSupported = CPA_FALSE; CpaCyCapabilitiesInfo cyCapInfo = { 0 }; /* initialize convenient pointers to cipher and hash contexts */ const CpaCySymCipherSetupData *const pCipherSetupData = (const CpaCySymCipherSetupData *)&pSessionSetupData->cipherSetupData; const CpaCySymHashSetupData *const pHashSetupData = &pSessionSetupData->hashSetupData; status = SalCtrl_CySymQueryCapabilities(instanceHandle, &symCapInfo); LAC_CHECK_STATUS(status); SalCtrl_CyQueryCapabilities(instanceHandle, &cyCapInfo); extAlgchainSupported = cyCapInfo.extAlgchainSupported; /* Ensure cipher algorithm is correct and supported */ if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionSetupData->symOperation) || (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation)) { /* Protect against value of cipher outside the bitmap * and check if cipher algorithm is correct */ if (pCipherSetupData->cipherAlgorithm >= CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE) { LAC_INVALID_PARAM_LOG("cipherAlgorithm"); return CPA_STATUS_INVALID_PARAM; } if (!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, pCipherSetupData->cipherAlgorithm)) { LAC_UNSUPPORTED_PARAM_LOG("UnSupported cipherAlgorithm"); return CPA_STATUS_UNSUPPORTED; } } /* Ensure hash algorithm is correct and supported */ if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionSetupData->symOperation) || (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation)) { /* Protect against value of hash outside the bitmap * and check if hash algorithm is correct */ if (pHashSetupData->hashAlgorithm >= CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) { LAC_INVALID_PARAM_LOG("hashAlgorithm"); return CPA_STATUS_INVALID_PARAM; } if (!CPA_BITMAP_BIT_TEST(symCapInfo.hashes, pHashSetupData->hashAlgorithm)) { LAC_UNSUPPORTED_PARAM_LOG("UnSupported hashAlgorithm"); return CPA_STATUS_UNSUPPORTED; } } /* Ensure CCM, GCM, Kasumi, Snow3G and ZUC cipher and hash algorithms are * selected together for Algorithm Chaining */ if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionSetupData->symOperation) { if (IS_EXT_ALG_CHAIN_UNSUPPORTED(pCipherSetupData->cipherAlgorithm, pHashSetupData->hashAlgorithm, extAlgchainSupported)) { LAC_UNSUPPORTED_PARAM_LOG("ExtAlgChain feature not supported"); return CPA_STATUS_UNSUPPORTED; } } return CPA_STATUS_SUCCESS; } #ifdef ICP_PARAM_CHECK /** * @ingroup LacSym * Function which performs parameter checks on session setup data * * @param[in] CpaInstanceHandle Instance handle * @param[in] pSessionSetupData Pointer to session setup data * * @retval CPA_STATUS_SUCCESS The operation succeeded * @retval CPA_STATUS_INVALID_PARAM An invalid parameter value was selected * @retval CPA_STATUS_UNSUPPORTED An unsupported algorithm with invalid * keysize was found */ STATIC CpaStatus LacSymSession_ParamCheck(const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData) { /* initialize convenient pointers to cipher and hash contexts */ const CpaCySymCipherSetupData *const pCipherSetupData = (const CpaCySymCipherSetupData *)&pSessionSetupData->cipherSetupData; const CpaCySymHashSetupData *const pHashSetupData = &pSessionSetupData->hashSetupData; Cpa32U mask = ((sal_service_t *)instanceHandle)->capabilitiesMask; /* Ensure cipher algorithm is correct and supported */ if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionSetupData->symOperation) || (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation)) { if (pCipherSetupData->cipherAlgorithm == CPA_CY_SYM_CIPHER_ZUC_EEA3) { if (!(mask & ICP_ACCEL_CAPABILITIES_ZUC_256) && (pCipherSetupData->cipherKeyLenInBytes == ICP_QAT_HW_ZUC_256_KEY_SZ)) { LAC_INVALID_PARAM_LOG("Cipher algorithm ZUC_256 unsupported."); return CPA_STATUS_UNSUPPORTED; } } } /* Ensure hash algorithm is correct and supported */ if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionSetupData->symOperation) || (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation)) { if (pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) { if (!(mask & ICP_ACCEL_CAPABILITIES_ZUC_256) && (pHashSetupData->authModeSetupData.authKeyLenInBytes == ICP_QAT_HW_ZUC_256_KEY_SZ)) { LAC_INVALID_PARAM_LOG("Hash algorithm ZUC_256 unsupported."); return CPA_STATUS_UNSUPPORTED; } } if (pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_AES_CMAC) { if (!(mask & ICP_ACCEL_CAPABILITIES_WIRELESS_CRYPTO_EXT) && (pHashSetupData->authModeSetupData.authKeyLenInBytes == ICP_QAT_HW_AES_192_KEY_SZ || pHashSetupData->authModeSetupData.authKeyLenInBytes == ICP_QAT_HW_AES_256_KEY_SZ)) { LAC_INVALID_PARAM_LOG("Hash algorithm AES_CMAC with 192/256" "bits key unsupported."); return CPA_STATUS_UNSUPPORTED; } } } /* ensure CCM, GCM, Kasumi, Snow3G and ZUC cipher and hash algorithms are * selected together for Algorithm Chaining */ if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionSetupData->symOperation) { /* ensure both hash and cipher algorithms are POLY and CHACHA */ if (((CPA_CY_SYM_CIPHER_CHACHA == pCipherSetupData->cipherAlgorithm) && (CPA_CY_SYM_HASH_POLY != pHashSetupData->hashAlgorithm)) || ((CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm) && (CPA_CY_SYM_CIPHER_CHACHA != pCipherSetupData->cipherAlgorithm))) { LAC_INVALID_PARAM_LOG("Invalid combination of Cipher/Hash " "Algorithms for CHACHA/POLY"); return CPA_STATUS_INVALID_PARAM; } /* ensure both hash and cipher algorithms are CCM */ if (((CPA_CY_SYM_CIPHER_AES_CCM == pCipherSetupData->cipherAlgorithm) && (CPA_CY_SYM_HASH_AES_CCM != pHashSetupData->hashAlgorithm)) || ((CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) && (CPA_CY_SYM_CIPHER_AES_CCM != pCipherSetupData->cipherAlgorithm))) { LAC_INVALID_PARAM_LOG( "Invalid combination of Cipher/Hash Algorithms for CCM"); return CPA_STATUS_INVALID_PARAM; } /* ensure both hash and cipher algorithms are GCM/GMAC */ if ((CPA_CY_SYM_CIPHER_AES_GCM == pCipherSetupData->cipherAlgorithm && (CPA_CY_SYM_HASH_AES_GCM != pHashSetupData->hashAlgorithm && CPA_CY_SYM_HASH_AES_GMAC != pHashSetupData->hashAlgorithm)) || ((CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm || CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) && CPA_CY_SYM_CIPHER_AES_GCM != pCipherSetupData->cipherAlgorithm)) { LAC_INVALID_PARAM_LOG( "Invalid combination of Cipher/Hash Algorithms for GCM"); return CPA_STATUS_INVALID_PARAM; } /* ensure both hash and cipher algorithms are Kasumi */ if (((CPA_CY_SYM_CIPHER_KASUMI_F8 == pCipherSetupData->cipherAlgorithm) && (CPA_CY_SYM_HASH_KASUMI_F9 != pHashSetupData->hashAlgorithm)) || ((CPA_CY_SYM_HASH_KASUMI_F9 == pHashSetupData->hashAlgorithm) && (CPA_CY_SYM_CIPHER_KASUMI_F8 != pCipherSetupData->cipherAlgorithm))) { LAC_INVALID_PARAM_LOG( "Invalid combination of Cipher/Hash Algorithms for Kasumi"); return CPA_STATUS_INVALID_PARAM; } /* Ensure that algorithm chaining operation is performed for supported * wireless algorithms. * * Following are supported algorithm chaining cipher + hash * combinations. Any cipher from the below list can be mixed with any * hash from below hash list. * * Ciphers: Snow3g_UEA2, ZUC_EEA3, AES_CTR, NULL_CIPHER. * * Hash: Snow3g_UIA2, ZUC_EIA3, AES_CMAC. */ if ((CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == pCipherSetupData->cipherAlgorithm) || (CPA_CY_SYM_CIPHER_ZUC_EEA3 == pCipherSetupData->cipherAlgorithm)) { if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 != pHashSetupData->hashAlgorithm) && (CPA_CY_SYM_HASH_ZUC_EIA3 != pHashSetupData->hashAlgorithm) && (CPA_CY_SYM_HASH_AES_CMAC != pHashSetupData->hashAlgorithm)) { LAC_INVALID_PARAM_LOG2("Invalid algorithm chaining " "combination, cipher: %d, hash: %d", pCipherSetupData->cipherAlgorithm, pHashSetupData->hashAlgorithm); return CPA_STATUS_INVALID_PARAM; } } else if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm)) { if ((CPA_CY_SYM_CIPHER_SNOW3G_UEA2 != pCipherSetupData->cipherAlgorithm) && (CPA_CY_SYM_CIPHER_ZUC_EEA3 != pCipherSetupData->cipherAlgorithm) && (CPA_CY_SYM_CIPHER_AES_CTR != pCipherSetupData->cipherAlgorithm) && (CPA_CY_SYM_CIPHER_NULL != pCipherSetupData->cipherAlgorithm)) { LAC_INVALID_PARAM_LOG2("Invalid algorithm chaining " "combination, hash: %d, cipher: %d", pHashSetupData->hashAlgorithm, pCipherSetupData->cipherAlgorithm); return CPA_STATUS_INVALID_PARAM; } } } /* Algorithm chaining is not selected by the application, therefore * prevent CCM/GCM from being used. */ else if (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation) { /* ensure cipher algorithm is not CCM, CHACHA or GCM */ if ((CPA_CY_SYM_CIPHER_AES_CCM == pCipherSetupData->cipherAlgorithm) || (CPA_CY_SYM_CIPHER_AES_GCM == pCipherSetupData->cipherAlgorithm) || (CPA_CY_SYM_CIPHER_CHACHA == pCipherSetupData->cipherAlgorithm)) { LAC_INVALID_PARAM_LOG("Invalid Cipher Algorithm for non-Algorithm " "Chaining operation"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation) { /* ensure hash algorithm is not CCM, POLY or GCM/GMAC */ if ((CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm)) { LAC_INVALID_PARAM_LOG( "Invalid Hash Algorithm for non-Algorithm Chaining operation"); return CPA_STATUS_INVALID_PARAM; } } /* Unsupported operation. Return error */ else { LAC_INVALID_PARAM_LOG("symOperation"); return CPA_STATUS_INVALID_PARAM; } /* ensure that cipher direction param is * valid for cipher and algchain ops */ if (CPA_CY_SYM_OP_HASH != pSessionSetupData->symOperation) { if ((pCipherSetupData->cipherDirection != CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) && (pCipherSetupData->cipherDirection != CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT)) { LAC_INVALID_PARAM_LOG("Invalid Cipher Direction"); return CPA_STATUS_INVALID_PARAM; } } return CPA_STATUS_SUCCESS; } #endif /*ICP_PARAM_CHECK*/ #ifdef ICP_PARAM_CHECK /** * @ingroup LacSym * Function which perform parameter checks on data buffers for symmetric * crypto operations * * @param[in] pSrcBuffer Pointer to source buffer list * @param[in] pDstBuffer Pointer to destination buffer list * @param[in] pSessionDesc Pointer to session descriptor * @param[in] pOpData Pointer to CryptoSymOpData. * * @retval CPA_STATUS_SUCCESS The operation succeeded * @retval CPA_STATUS_INVALID_PARAM An invalid parameter value was found */ STATIC CpaStatus LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer, const CpaBufferList *const pDstBuffer, const lac_session_desc_t *const pSessionDesc, const CpaCySymOpData *const pOpData) { Cpa64U srcBufferLen = 0, dstBufferLen = 0; CpaStatus status = CPA_STATUS_SUCCESS; /* verify packet type is in correct range */ switch (pOpData->packetType) { case CPA_CY_SYM_PACKET_TYPE_FULL: case CPA_CY_SYM_PACKET_TYPE_PARTIAL: case CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL: break; default: { LAC_INVALID_PARAM_LOG("packetType"); return CPA_STATUS_INVALID_PARAM; } } if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation && CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) && (0 == pOpData->messageLenToHashInBytes))) { if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(pSessionDesc->cipherAlgorithm, pSessionDesc->hashAlgorithm)) { status = LacBuffDesc_BufferListVerifyNull( pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT); } else { status = LacBuffDesc_BufferListVerify( pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT); } if (CPA_STATUS_SUCCESS != status) { LAC_INVALID_PARAM_LOG("Source buffer invalid"); return CPA_STATUS_INVALID_PARAM; } } else { /* check MetaData !NULL */ if (NULL == pSrcBuffer->pPrivateMetaData) { LAC_INVALID_PARAM_LOG("Source buffer MetaData cannot be NULL"); return CPA_STATUS_INVALID_PARAM; } } /* out of place checks */ if (pSrcBuffer != pDstBuffer) { /* exception for this check is zero length hash requests to allow */ /* for srcBufflen=DstBufferLen=0 */ if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation && CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) && (0 == pOpData->messageLenToHashInBytes))) { /* Verify buffer(s) for dest packet & return packet length */ if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(pSessionDesc->cipherAlgorithm, pSessionDesc->hashAlgorithm)) { status = LacBuffDesc_BufferListVerifyNull( pDstBuffer, &dstBufferLen, LAC_NO_ALIGNMENT_SHIFT); } else { status = LacBuffDesc_BufferListVerify( pDstBuffer, &dstBufferLen, LAC_NO_ALIGNMENT_SHIFT); } if (CPA_STATUS_SUCCESS != status) { LAC_INVALID_PARAM_LOG("Destination buffer invalid"); return CPA_STATUS_INVALID_PARAM; } } else { /* check MetaData !NULL */ if (NULL == pDstBuffer->pPrivateMetaData) { LAC_INVALID_PARAM_LOG("Dest buffer MetaData cannot be NULL"); return CPA_STATUS_INVALID_PARAM; } } /* Check that src Buffer and dst Buffer Lengths are equal */ /* CCM output needs to be longer than input buffer for appending tag*/ if (srcBufferLen != dstBufferLen && pSessionDesc->cipherAlgorithm != CPA_CY_SYM_CIPHER_AES_CCM) { LAC_INVALID_PARAM_LOG( "Source and Dest buffer lengths need to be equal "); return CPA_STATUS_INVALID_PARAM; } } /* Check for partial packet support for the session operation */ if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) { if (!(IS_PARTIAL_ON_SYM_OP_SUPPORTED(pSessionDesc->symOperation, pSessionDesc->cipherAlgorithm, pSessionDesc->hashAlgorithm, pSessionDesc->hashMode))) { /* return out here to simplify cleanup */ LAC_INVALID_PARAM_LOG( "Partial packets not supported for operation"); return CPA_STATUS_INVALID_PARAM; } else { /* This function checks to see if the partial packet sequence * is correct */ if (CPA_STATUS_SUCCESS != LacSym_PartialPacketStateCheck(pOpData->packetType, pSessionDesc->partialState)) { LAC_INVALID_PARAM_LOG("Partial packet Type"); return CPA_STATUS_INVALID_PARAM; } } } return CPA_STATUS_SUCCESS; } #endif /** @ingroup LacSym */ CpaStatus cpaCySymInitSession(const CpaInstanceHandle instanceHandle_in, const CpaCySymCbFunc pSymCb, const CpaCySymSessionSetupData *pSessionSetupData, CpaCySymSessionCtx pSessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; sal_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSymCb, (LAC_ARCH_UINT)pSessionSetupData, (LAC_ARCH_UINT)pSessionCtx); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif /*ICP_PARAM_CHECK*/ pService = (sal_service_t *)instanceHandle; /* check crypto service is running otherwise return an error */ SAL_RUNNING_CHECK(pService); status = LacSym_InitSession(instanceHandle, pSymCb, pSessionSetupData, CPA_FALSE, /* isDPSession */ pSessionCtx); if (CPA_STATUS_SUCCESS == status) { /* Increment the stats for a session registered successfully */ LAC_SYM_STAT_INC(numSessionsInitialized, instanceHandle); } else /* if there was an error */ { LAC_SYM_STAT_INC(numSessionErrors, instanceHandle); } return status; } CpaStatus cpaCySymSessionInUse(CpaCySymSessionCtx pSessionCtx, CpaBoolean *pSessionInUse) { CpaStatus status = CPA_STATUS_SUCCESS; lac_session_desc_t *pSessionDesc = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionInUse); LAC_CHECK_INSTANCE_HANDLE(pSessionCtx); #endif *pSessionInUse = CPA_FALSE; pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx); /* If there are pending requests */ if (pSessionDesc->isDPSession) { if (pSessionDesc->u.pendingDpCbCount) *pSessionInUse = CPA_TRUE; } else { if (osalAtomicGet(&(pSessionDesc->u.pendingCbCount))) *pSessionInUse = CPA_TRUE; } return status; } CpaStatus LacSym_InitSession(const CpaInstanceHandle instanceHandle, const CpaCySymCbFunc pSymCb, const CpaCySymSessionSetupData *pSessionSetupData, const CpaBoolean isDPSession, CpaCySymSessionCtx pSessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; lac_session_desc_t *pSessionDesc = NULL; Cpa32U sessionCtxSizeInBytes = 0; CpaPhysicalAddr physAddress = 0; CpaPhysicalAddr physAddressAligned = 0; sal_service_t *pService = NULL; const CpaCySymCipherSetupData *pCipherSetupData = NULL; const CpaCySymHashSetupData *pHashSetupData = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionSetupData); #endif /* Capability check done by calling function */ status = LacSymSession_CapabilityCheck(instanceHandle, pSessionSetupData); LAC_CHECK_STATUS(status); /* Instance param checking done by calling function */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionCtx); status = LacSymSession_ParamCheck(instanceHandle, pSessionSetupData); LAC_CHECK_STATUS(status); /* set the session priority for QAT AL*/ if ((CPA_CY_PRIORITY_HIGH == pSessionSetupData->sessionPriority) || (CPA_CY_PRIORITY_NORMAL == pSessionSetupData->sessionPriority)) { // do nothing - clean up this code. use RANGE macro } else { LAC_INVALID_PARAM_LOG("sessionPriority"); return CPA_STATUS_INVALID_PARAM; } #endif /*ICP_PARAM_CHECK*/ pCipherSetupData = &pSessionSetupData->cipherSetupData; pHashSetupData = &pSessionSetupData->hashSetupData; pService = (sal_service_t *)instanceHandle; /* Re-align the session structure to 64 byte alignment */ physAddress = LAC_OS_VIRT_TO_PHYS_EXTERNAL( (*pService), (Cpa8U *)pSessionCtx + sizeof(void *)); if (0 == physAddress) { LAC_LOG_ERROR("Unable to get the physical address of the session\n"); return CPA_STATUS_FAIL; } physAddressAligned = LAC_ALIGN_POW2_ROUNDUP(physAddress, LAC_64BYTE_ALIGNMENT); pSessionDesc = (lac_session_desc_t *) /* Move the session pointer by the physical offset between aligned and unaligned memory */ ((Cpa8U *)pSessionCtx + sizeof(void *) + (physAddressAligned - physAddress)); /* save the aligned pointer in the first bytes (size of unsigned long) * of the session memory */ *((LAC_ARCH_UINT *)pSessionCtx) = (LAC_ARCH_UINT)pSessionDesc; /* start off with a clean session */ /* Choose Session Context size */ getCtxSize(pSessionSetupData, &sessionCtxSizeInBytes); switch (sessionCtxSizeInBytes) { case LAC_SYM_SESSION_D1_SIZE: osalMemSet(pSessionDesc, 0, sizeof(lac_session_desc_d1_t)); break; case LAC_SYM_SESSION_D2_SIZE: osalMemSet(pSessionDesc, 0, sizeof(lac_session_desc_d2_t)); break; default: osalMemSet(pSessionDesc, 0, sizeof(lac_session_desc_t)); break; } /* Setup content descriptor info structure * assumption that content descriptor is the first field in * in the session descriptor */ pSessionDesc->contentDescInfo.pData = (Cpa8U *)pSessionDesc; pSessionDesc->contentDescInfo.hardwareSetupBlockPhys = physAddressAligned; pSessionDesc->contentDescOptimisedInfo.pData = ((Cpa8U *)pSessionDesc + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE); pSessionDesc->contentDescOptimisedInfo.hardwareSetupBlockPhys = (physAddressAligned + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE); /* Set the Common Session Information */ pSessionDesc->symOperation = pSessionSetupData->symOperation; if (CPA_FALSE == isDPSession) { /* For asynchronous - use the user supplied callback * for synchronous - use the internal synchronous callback */ pSessionDesc->pSymCb = ((void *)NULL != (void *)pSymCb) ? pSymCb : LacSync_GenBufListVerifyCb; } pSessionDesc->isDPSession = isDPSession; if ((CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_CIPHER_CHACHA == pCipherSetupData->cipherAlgorithm) || (CPA_CY_SYM_CIPHER_ARC4 == pCipherSetupData->cipherAlgorithm)) { pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgFull; } else { pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgOpt; } if (CPA_STATUS_SUCCESS == status) { /* Session set up via API call (not internal one) */ /* Services such as DRBG call the crypto api as part of their service * hence the need to for the flag, it is needed to distinguish between * an internal and external session. */ pSessionDesc->internalSession = CPA_FALSE; status = LacAlgChain_SessionInit( instanceHandle, pSessionSetupData, pSessionDesc); if (status != CPA_STATUS_SUCCESS) { LAC_SPINLOCK_DESTROY(&pSessionDesc->requestQueueLock); osalAtomicSet(0, &pSessionDesc->accessLock); } } return status; } /** @ingroup LacSym */ CpaStatus cpaCySymRemoveSession(const CpaInstanceHandle instanceHandle_in, CpaCySymSessionCtx pSessionCtx) { lac_session_desc_t *pSessionDesc = NULL; CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle instanceHandle = NULL; Cpa64U numPendingRequests = 0; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSessionCtx); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSessionCtx); #endif /*ICP_PARAM_CHECK*/ /* check crypto service is running otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); #endif /*ICP_PARAM_CHECK*/ if (CPA_TRUE == pSessionDesc->isDPSession) { /* * Based on one instance, we can initialize multiple sessions. * For example, we can initialize the session "X" and session "Y" with * the same instance "A". If there is no operation pending for session * "X", we can remove the session "X". * * Now we only check the @pSessionDesc->pendingDpCbCount, if it becomes * zero, we can remove the session. * * Why? * (1) We increase it in the cpaCySymDpEnqueueOp/ * cpaCySymDpEnqueueOpBatch. * (2) We decrease it in the LacSymCb_ProcessCallback. * * If the @pSessionDesc->pendingDpCbCount becomes zero, it means * there is no operation pending for the session "X" anymore, so we can * remove this session. Maybe there is still some requests left in the * instance's ring (icp_adf_queueDataToSend() returns true), but the * request does not belong to "X", it belongs to session "Y". */ numPendingRequests = pSessionDesc->u.pendingDpCbCount; } else { numPendingRequests = osalAtomicGet(&(pSessionDesc->u.pendingCbCount)); } /* If there are pending requests */ if (0 != numPendingRequests) { LAC_LOG1("There are %llu requests pending", numPendingRequests); status = CPA_STATUS_RETRY; if (CPA_TRUE == pSessionDesc->isDPSession) { /* Need to update tail if messages queue on tx hi ring for data plane api */ icp_comms_trans_handle trans_handle = ((sal_crypto_service_t *)instanceHandle)->trans_handle_sym_tx; if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { /* process the remaining messages in the ring */ LAC_LOG("Submitting enqueued requests"); /* * icp_adf_updateQueueTail */ status = SalQatMsg_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { return status; } return CPA_STATUS_RETRY; } } } if (CPA_STATUS_SUCCESS == status) { LAC_SPINLOCK_DESTROY(&pSessionDesc->requestQueueLock); osalAtomicSet(0, &pSessionDesc->accessLock); if (CPA_FALSE == pSessionDesc->isDPSession) { LAC_SYM_STAT_INC(numSessionsRemoved, instanceHandle); } } else if (CPA_FALSE == pSessionDesc->isDPSession) { LAC_SYM_STAT_INC(numSessionErrors, instanceHandle); } return status; } CpaStatus cpaCySymUpdateSession( CpaCySymSessionCtx pSessionCtx, const CpaCySymSessionUpdateData *pSessionUpdateData) { CpaStatus status = CPA_STATUS_SUCCESS; lac_session_desc_t *pSessionDesc = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionUpdateData); LAC_CHECK_NULL_PARAM(pSessionCtx); #endif pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx); if (CPA_CY_SYM_PACKET_TYPE_FULL != pSessionDesc->partialState) { return CPA_STATUS_FAIL; } status = LacAlgChain_SessionUpdate(pSessionDesc, pSessionUpdateData); return status; } /** @ingroup LacSym */ STATIC CpaStatus LacSym_Perform(const CpaInstanceHandle instanceHandle, void *callbackTag, const CpaCySymOpData *pOpData, const CpaBufferList *pSrcBuffer, CpaBufferList *pDstBuffer, CpaBoolean *pVerifyResult, CpaBoolean isAsyncMode) { lac_session_desc_t *pSessionDesc = NULL; CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif /* check crypto service is running otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pOpData); LAC_CHECK_NULL_PARAM(pOpData->sessionCtx); LAC_CHECK_NULL_PARAM(pSrcBuffer); LAC_CHECK_NULL_PARAM(pDstBuffer); #endif /*ICP_PARAM_CHECK*/ pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx); #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pSessionDesc); /*check whether Payload size is zero for CHACHA-POLY*/ if ((CPA_CY_SYM_CIPHER_CHACHA == pSessionDesc->cipherAlgorithm) && (CPA_CY_SYM_HASH_POLY == pSessionDesc->hashAlgorithm) && (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { if (!pOpData->messageLenToCipherInBytes) { LAC_INVALID_PARAM_LOG( "Invalid messageLenToCipherInBytes for CHACHA-POLY"); return CPA_STATUS_INVALID_PARAM; } } #endif /*ICP_PARAM_CHECK*/ /* If synchronous Operation - Callback function stored in the session * descriptor so a flag is set in the perform to indicate that * the perform is being re-called for the synchronous operation */ if ((LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb) && isAsyncMode == CPA_TRUE) { CpaBoolean opResult = CPA_FALSE; lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { status = LacSym_Perform(instanceHandle, pSyncCallbackData, pOpData, pSrcBuffer, pDstBuffer, pVerifyResult, CPA_FALSE); } else { /* Failure allocating sync cookie */ LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle); return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus syncStatus = CPA_STATUS_SUCCESS; syncStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_SYM_SYNC_CALLBACK_TIMEOUT, &status, &opResult); /* If callback doesn't come back */ if (CPA_STATUS_SUCCESS != syncStatus) { LAC_SYM_STAT_INC(numSymOpCompletedErrors, instanceHandle); LAC_LOG_ERROR("Callback timed out"); status = syncStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } if (CPA_STATUS_SUCCESS == status) { if (NULL != pVerifyResult) { *pVerifyResult = opResult; } } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } #ifdef ICP_PARAM_CHECK status = LacSymPerform_BufferParamCheck( (const CpaBufferList *)pSrcBuffer, pDstBuffer, pSessionDesc, pOpData); LAC_CHECK_STATUS(status); if ((!pSessionDesc->digestIsAppended) && (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { /* Check that pDigestResult is not NULL */ LAC_CHECK_NULL_PARAM(pOpData->pDigestResult); } #endif /*ICP_PARAM_CHECK*/ status = LacAlgChain_Perform(instanceHandle, pSessionDesc, callbackTag, pOpData, NULL, pSrcBuffer, pDstBuffer, pVerifyResult); if (CPA_STATUS_SUCCESS == status) { /* check for partial packet support for the session operation */ if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) { LacSym_PartialPacketStateUpdate(pOpData->packetType, &pSessionDesc->partialState); } /* increment #requests stat */ LAC_SYM_STAT_INC(numSymOpRequests, instanceHandle); } /* Retry also results in the errors stat been incremented */ else { /* increment #errors stat */ LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle); } return status; } /** @ingroup LacSym */ CpaStatus cpaCySymPerformOp(const CpaInstanceHandle instanceHandle_in, void *callbackTag, const CpaCySymOpData *pOpData, const CpaBufferList *pSrcBuffer, CpaBufferList *pDstBuffer, CpaBoolean *pVerifyResult) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE CpaStatus status = CPA_STATUS_SUCCESS; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_TRACE status = LacSym_Perform(instanceHandle, callbackTag, pOpData, pSrcBuffer, pDstBuffer, pVerifyResult, CPA_TRUE); LAC_LOG("Currently being called\n"); return (status); #else return LacSym_Perform(instanceHandle, callbackTag, pOpData, pSrcBuffer, pDstBuffer, pVerifyResult, CPA_TRUE); #endif } /** @ingroup LacSym */ CpaStatus cpaCySymQueryStats(const CpaInstanceHandle instanceHandle_in, struct _CpaCySymStats *pSymStats) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSymStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSymStats); #endif /*ICP_PARAM_CHECK*/ /* check if crypto service is running * otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); /* copy the fields from the internal structure into the api defined * structure */ LacSym_Stats32CopyGet(instanceHandle, pSymStats); return CPA_STATUS_SUCCESS; } /** @ingroup LacSym */ CpaStatus cpaCySymQueryStats64(const CpaInstanceHandle instanceHandle_in, CpaCySymStats64 *pSymStats) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSymStats); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSymStats); #endif /*ICP_PARAM_CHECK*/ /* check if crypto service is running * otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); /* copy the fields from the internal structure into the api defined * structure */ LacSym_Stats64CopyGet(instanceHandle, pSymStats); return CPA_STATUS_SUCCESS; } /** @ingroup LacSym */ CpaStatus cpaCySymSessionCtxGetSize( const CpaInstanceHandle instanceHandle_in, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes) { CpaInstanceHandle instanceHandle = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSessionSetupData); LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); #endif /*ICP_PARAM_CHECK*/ /* check crypto service is running otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); *pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE; #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSessionSetupData, (LAC_ARCH_UINT)pSessionCtxSizeInBytes, *pSessionCtxSizeInBytes); #endif return CPA_STATUS_SUCCESS; } /** @ingroup LacSym */ CpaStatus cpaCySymSessionCtxGetDynamicSize( const CpaInstanceHandle instanceHandle_in, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes) { CpaInstanceHandle instanceHandle = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSessionSetupData); LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); #endif /*ICP_PARAM_CHECK*/ /* check crypto service is running otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); /* Choose Session Context size */ getCtxSize(pSessionSetupData, pSessionCtxSizeInBytes); #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pSessionSetupData, (LAC_ARCH_UINT)pSessionCtxSizeInBytes, *pSessionCtxSizeInBytes); #endif return CPA_STATUS_SUCCESS; } void getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes) { /* using lac_session_desc_d1_t */ if ((pSessionSetupData->cipherSetupData.cipherAlgorithm != CPA_CY_SYM_CIPHER_ARC4) && (pSessionSetupData->cipherSetupData.cipherAlgorithm != CPA_CY_SYM_CIPHER_SNOW3G_UEA2) && (pSessionSetupData->hashSetupData.hashAlgorithm != CPA_CY_SYM_HASH_SNOW3G_UIA2) && (pSessionSetupData->cipherSetupData.cipherAlgorithm != CPA_CY_SYM_CIPHER_AES_CCM) && (pSessionSetupData->cipherSetupData.cipherAlgorithm != CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionSetupData->hashSetupData.hashMode != CPA_CY_SYM_HASH_MODE_AUTH) && (pSessionSetupData->hashSetupData.hashMode != CPA_CY_SYM_HASH_MODE_NESTED) && (pSessionSetupData->partialsNotRequired == CPA_TRUE)) { *pSessionCtxSizeInBytes = LAC_SYM_SESSION_D1_SIZE; } /* using lac_session_desc_d2_t */ else if (((pSessionSetupData->cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) || (pSessionSetupData->cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM)) && (pSessionSetupData->partialsNotRequired == CPA_TRUE)) { *pSessionCtxSizeInBytes = LAC_SYM_SESSION_D2_SIZE; } /* using lac_session_desc_t */ else { *pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE; } } /** ****************************************************************************** * @ingroup LacSym *****************************************************************************/ CpaStatus cpaCyBufferListGetMetaSize(const CpaInstanceHandle instanceHandle_in, Cpa32U numBuffers, Cpa32U *pSizeInBytes) { #ifdef ICP_PARAM_CHECK CpaInstanceHandle instanceHandle = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSizeInBytes); #endif /* In the case of zero buffers we still need to allocate one * descriptor to pass to the firmware */ if (0 == numBuffers) { numBuffers = 1; } /* Note: icp_buffer_list_desc_t is 8 bytes in size and * icp_flat_buffer_desc_t is 16 bytes in size. Therefore if * icp_buffer_list_desc_t is aligned * so will each icp_flat_buffer_desc_t structure */ *pSizeInBytes = sizeof(icp_buffer_list_desc_t) + (sizeof(icp_flat_buffer_desc_t) * numBuffers) + ICP_DESCRIPTOR_ALIGNMENT_BYTES; #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, %d, 0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle_in, numBuffers, (LAC_ARCH_UINT)pSizeInBytes, *pSizeInBytes); #endif return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_auth_enc.c000066400000000000000000000225261503624047500320010ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_auth_enc.c * * @ingroup LacAuthEnc * * @description * Authenticated encryption specific functionality. * For CCM related code NIST SP 800-38C is followed. * For GCM related code NIST SP 800-38D is followed. ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "Osal.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_debug.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_log.h" #include "lac_common.h" #include "lac_session.h" #include "lac_sym_auth_enc.h" /* These defines describe position of the flag fields * in B0 block for CCM algorithm*/ #define LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT 6 #define LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT 3 /* This macro builds flags field to be put in B0 block for CCM algorithm */ #define LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(Adata, t, q) \ ((((Adata) > 0 ? 1 : 0) << LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT) | \ ((((t)-2) >> 1) << LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT) | ((q)-1)) #ifdef ICP_PARAM_CHECK /** * @ingroup LacAuthEnc */ CpaStatus LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData, Cpa8U *pIv, Cpa32U messageLenToCipherInBytes, Cpa32U ivLenInBytes) { Cpa8U q = 0; LAC_CHECK_NULL_PARAM(pIv); LAC_CHECK_NULL_PARAM(pAdditionalAuthData); /* check if n is within permitted range */ if (ivLenInBytes < LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN || ivLenInBytes > LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX) { LAC_INVALID_PARAM_LOG2("ivLenInBytes for CCM algorithm " "must be between %d and %d inclusive", LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN, LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX); return CPA_STATUS_INVALID_PARAM; } q = LAC_ALG_CHAIN_CCM_NQ_CONST - ivLenInBytes; /* Check if q is big enough to hold actual length of message to cipher * if q = 8 -> maxlen = 2^64 always good as * messageLenToCipherInBytes is 32 bits * if q = 7 -> maxlen = 2^56 always good * if q = 6 -> maxlen = 2^48 always good * if q = 5 -> maxlen = 2^40 always good * if q = 4 -> maxlen = 2^32 always good. */ if ((messageLenToCipherInBytes >= (Cpa32U)(1 << (q * LAC_NUM_BITS_IN_BYTE))) && (q < sizeof(Cpa32U))) { LAC_INVALID_PARAM_LOG("messageLenToCipherInBytes too long for the given" " ivLenInBytes for CCM algorithm"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } #endif /** * @ingroup LacAuthEnc */ void LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc, Cpa8U *pAdditionalAuthData, Cpa8U *pIv, Cpa32U messageLenToCipherInBytes, Cpa32U ivLenInBytes) { Cpa8U n = (Cpa8U)ivLenInBytes; /* assumes ivLenInBytes has been param checked */ Cpa8U q = LAC_ALG_CHAIN_CCM_NQ_CONST - n; Cpa8U lenOfEncodedLen = 0; Cpa16U lenAEncoded = 0; Cpa32U bitStrQ = 0; /* populate Ctr0 block - stored in pIv */ pIv[0] = (q - 1); /* bytes 1 to n are already set with nonce by the user */ /* set last q bytes with 0 */ osalMemSet(pIv + n + 1, 0, q); /* Encode the length of associated data 'a'. As the API limits the length * of an array pointed by pAdditionalAuthData to be 240 bytes max, the * maximum length of 'a' might be 240 - 16 - 2 = 222. Hence the encoding * below is simplified. */ if (pSessionDesc->aadLenInBytes > 0) { lenOfEncodedLen = sizeof(Cpa16U); lenAEncoded = OSAL_HOST_TO_NW_16((Cpa16U)pSessionDesc->aadLenInBytes); } /* populate B0 block */ /* first, set the flags field */ pAdditionalAuthData[0] = LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS( lenOfEncodedLen, pSessionDesc->hashResultSize, q); /* bytes 1 to n are already set with nonce by the user*/ /* put Q in bytes 16-q...15 */ bitStrQ = OSAL_HOST_TO_NW_32(messageLenToCipherInBytes); if (q > sizeof(bitStrQ)) { osalMemSet(pAdditionalAuthData + n + 1, 0, q); osalMemCopy(pAdditionalAuthData + n + 1 + (q - sizeof(bitStrQ)), (Cpa8U *)&bitStrQ, sizeof(bitStrQ)); } else { osalMemCopy(pAdditionalAuthData + n + 1, ((Cpa8U *)&bitStrQ) + (sizeof(bitStrQ) - q), q); } /* populate B1-Bn blocks */ if (lenAEncoded > 0) { *(Cpa16U *)(&pAdditionalAuthData[1 + LAC_ALG_CHAIN_CCM_NQ_CONST]) = lenAEncoded; /* Next bytes are already set by the user with * the associated data 'a' */ /* Check if padding is required */ if (((pSessionDesc->aadLenInBytes + lenOfEncodedLen) % LAC_HASH_AES_CCM_BLOCK_SIZE) != 0) { Cpa8U paddingLen = 0; Cpa8U paddingIndex = 0; paddingLen = LAC_HASH_AES_CCM_BLOCK_SIZE - ((pSessionDesc->aadLenInBytes + lenOfEncodedLen) % LAC_HASH_AES_CCM_BLOCK_SIZE); paddingIndex = 1 + LAC_ALG_CHAIN_CCM_NQ_CONST; paddingIndex += lenOfEncodedLen + pSessionDesc->aadLenInBytes; osalMemSet(&pAdditionalAuthData[paddingIndex], 0, paddingLen); } } } /** * @ingroup LacAuthEnc */ void LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc, Cpa8U *pAdditionalAuthData) { Cpa8U paddingLen = 0; if ((pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE) != 0) { paddingLen = LAC_HASH_AES_GCM_BLOCK_SIZE - (pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE); osalMemSet( &pAdditionalAuthData[pSessionDesc->aadLenInBytes], 0, paddingLen); } } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_cb.c000066400000000000000000000650251503624047500306000ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file lac_sym_cb.c Callback handler functions for symmetric components * * @ingroup LacSym * ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "Osal.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_qat_fw_la.h" #include "icp_adf_transport.h" #include "icp_adf_debug.h" #include "lac_sym.h" #include "lac_sym_cipher.h" #include "lac_common.h" #include "lac_list.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_session.h" #include "lac_sym_stats.h" #include "lac_log.h" #include "lac_sym_cb.h" #include "lac_sym_hash.h" #include "lac_sym_qat_cipher.h" #include "lac_sym_qat.h" #define DEQUEUE_MSGPUT_MAX_RETRIES 10000 /* ******************************************************************************* * Define static function definitions ******************************************************************************* */ /** ***************************************************************************** * @ingroup LacSymCb * Function to clean computed data. * * @description * This function cleans GCM or CCM data in the case of a failure. * * @param[in] pSessionDesc pointer to the session descriptor * @param[out] pBufferList pointer to the bufferlist to clean * @param[in] pOpData pointer to operation data * @param[in] isCCM is it a CCM operation boolean * * @return None *****************************************************************************/ STATIC void LacSymCb_CleanUserData(const lac_session_desc_t *pSessionDesc, CpaBufferList *pBufferList, const CpaCySymOpData *pOpData, CpaBoolean isCCM) { Cpa32U authTagLen = 0; /* Retrieve authTagLen */ authTagLen = pSessionDesc->hashResultSize; /* Cleaning */ if (isCCM) { /* for CCM the digest is inside the buffer list */ LacBuffDesc_BufferListZeroFromOffset( pBufferList, pOpData->cryptoStartSrcOffsetInBytes, pOpData->messageLenToCipherInBytes + authTagLen); } else { /* clean buffer list */ LacBuffDesc_BufferListZeroFromOffset( pBufferList, pOpData->cryptoStartSrcOffsetInBytes, pOpData->messageLenToCipherInBytes); } if ((CPA_TRUE != pSessionDesc->digestIsAppended) && (NULL != pOpData->pDigestResult)) { /* clean digest */ osalMemSet(pOpData->pDigestResult, 0, authTagLen); } } /** ***************************************************************************** * @ingroup LacSymCb * Definition of callback function for processing symmetric responses * * @description * This callback is invoked to process symmetric response messages from * the QAT. It will extract some details from the message and invoke * the user's callback to complete a symmetric operation. * * @param[in] pCookie Pointer to cookie associated with this request * @param[in] qatRespStatusOkFlag Boolean indicating ok/fail status from QAT * @param[in] status Status variable indicating an error occurred * in sending the message (e.g. when dequeueing) * @param[in] pSessionDesc Session descriptor * * @return None *****************************************************************************/ STATIC void LacSymCb_ProcessCallbackInternal(lac_sym_bulk_cookie_t *pCookie, CpaBoolean qatRespStatusOkFlag, CpaStatus status, lac_session_desc_t *pSessionDesc) { CpaCySymCbFunc pSymCb = NULL; void *pCallbackTag = NULL; CpaCySymOpData *pOpData = NULL; CpaBufferList *pDstBuffer = NULL; CpaCySymOp operationType = CPA_CY_SYM_OP_NONE; CpaStatus dequeueStatus = CPA_STATUS_SUCCESS; #ifndef DISABLE_STATS CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; /* NOTE: cookie pointer validated in previous function */ instanceHandle = pCookie->instanceHandle; LAC_ENSURE(instanceHandle != NULL, "LacSymCb_ProcessCallbackInternal - instanceHandle NULL\n"); #endif pOpData = (CpaCySymOpData *)LAC_CONST_PTR_CAST(pCookie->pOpData); operationType = pSessionDesc->symOperation; /* Set the destination pointer to the one supplied in the cookie. */ pDstBuffer = pCookie->pDstBuffer; /* For a digest verify operation - for full packet and final partial * only, perform a comparison with the digest generated and with the one * supplied in the packet. In case of AES_GCM in SPC mode, destination * buffer needs to be cleared if digest verify operation fails */ if (((SPC_YES == pSessionDesc->singlePassState) || (CPA_CY_SYM_OP_CIPHER != operationType)) && (CPA_TRUE == pSessionDesc->digestVerify) && ((CPA_CY_SYM_PACKET_TYPE_FULL == pOpData->packetType) || (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == pOpData->packetType))) { if (CPA_FALSE == qatRespStatusOkFlag) { LAC_SYM_STAT_INC(numSymOpVerifyFailures, instanceHandle); /* The comparison has failed at this point (status is fail), * need to clean any sensitive calculated data up to this point. * The data calculated is no longer useful to the end result and * does not need to be returned to the user so setting buffers to * zero. */ if (pSessionDesc->cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { LacSymCb_CleanUserData( pSessionDesc, pDstBuffer, pOpData, CPA_TRUE); } else if (pSessionDesc->cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) { LacSymCb_CleanUserData( pSessionDesc, pDstBuffer, pOpData, CPA_FALSE); } } } else { /* Most commands have no point of failure and always return * success. This is the default response from the QAT. * If status is already set to an error value, don't overwrite it */ if ((CPA_STATUS_SUCCESS == status) && (CPA_TRUE != qatRespStatusOkFlag)) { LAC_LOG_ERROR("Response status value not as expected"); status = CPA_STATUS_FAIL; } } pSymCb = pSessionDesc->pSymCb; pCallbackTag = pCookie->pCallbackTag; /* State returned to the client for intermediate partials packets * for hash only and cipher only partial packets. Cipher update * allow next partial through */ if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) { if ((CPA_CY_SYM_OP_CIPHER == operationType) || (CPA_CY_SYM_OP_ALGORITHM_CHAINING == operationType)) { if (CPA_TRUE == pCookie->updateUserIvOnRecieve) { /* Update the user's IV buffer * Very important to do this BEFORE dequeuing * subsequent partial requests, as the state buffer * may get overwritten */ memcpy(pCookie->pOpData->pIv, pSessionDesc->cipherPartialOpState, pCookie->pOpData->ivLenInBytes); } if (CPA_TRUE == pCookie->updateKeySizeOnRecieve && LAC_CIPHER_IS_XTS_MODE(pSessionDesc->cipherAlgorithm)) { LacSymQat_CipherXTSModeUpdateKeyLen( pSessionDesc, pSessionDesc->cipherKeyLenInBytes / 2); } } } else if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == pOpData->packetType) { if ((CPA_CY_SYM_OP_CIPHER == operationType) || (CPA_CY_SYM_OP_ALGORITHM_CHAINING == operationType)) { if (CPA_TRUE == LAC_CIPHER_IS_XTS_MODE(pSessionDesc->cipherAlgorithm)) { /* * For XTS mode, we replace the updated key with * the original key - for subsequent partial requests * */ LacSymQat_CipherXTSModeUpdateKeyLen( pSessionDesc, pSessionDesc->cipherKeyLenInBytes); } } } if ((CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) && (qatRespStatusOkFlag != CPA_FALSE)) { /* There may be requests blocked pending the completion of this * operation */ dequeueStatus = LacSymCb_PendingReqsDequeue(pSessionDesc); if (CPA_STATUS_SUCCESS != dequeueStatus) { LAC_SYM_STAT_INC(numSymOpCompletedErrors, instanceHandle); qatRespStatusOkFlag = CPA_FALSE; if (CPA_STATUS_SUCCESS == status) { status = dequeueStatus; } } } if (CPA_STATUS_SUCCESS == status) { /* update stats */ if (pSessionDesc->internalSession == CPA_FALSE) { LAC_SYM_STAT_INC(numSymOpCompleted, instanceHandle); if (CPA_STATUS_SUCCESS != status) { LAC_SYM_STAT_INC(numSymOpCompletedErrors, instanceHandle); } } } LAC_MEM_POOL_BLK_SET_OPAQUE(pCookie, ICP_ADF_INVALID_SEND_SEQ); /* deallocate the memory for the internal callback cookie */ Lac_MemPoolEntryFree(pCookie); /* user callback function is the last thing to be called */ LAC_ASSERT_NOT_NULL(pSymCb); pSymCb(pCallbackTag, status, operationType, pOpData, pDstBuffer, qatRespStatusOkFlag); osalAtomicDec(&(pSessionDesc->u.pendingCbCount)); } /** ****************************************************************************** * @ingroup LacSymCb * Definition of callback function for processing symmetric Data Plane * responses * * @description * This callback checks the status, decrements the number of operations * pending and calls the user callback * * @param[in/out] pResponse pointer to the response structure * @param[in] qatRespStatusOkFlag status * @param[in] pSessionDesc pointer to the session descriptor * * @return None ******************************************************************************/ STATIC void LacSymCb_ProcessDpCallback(CpaCySymDpOpData *pResponse, CpaBoolean qatRespStatusOkFlag, CpaStatus status, lac_session_desc_t *pSessionDesc) { CpaCySymDpCbFunc pSymDpCb = NULL; /* For CCM and GCM, if qatRespStatusOkFlag is false, the data has to be * cleaned as stated in RFC 3610; in DP mode, it is the user responsibility * to do so */ if (((CPA_CY_SYM_OP_CIPHER == pSessionDesc->symOperation && (SPC_NO == pSessionDesc->singlePassState)) || (CPA_FALSE == pSessionDesc->digestVerify))) { /* If not doing digest compare and qatRespStatusOkFlag != CPA_TRUE then there is something very wrong */ if ((CPA_FALSE == qatRespStatusOkFlag) && (status != CPA_STATUS_UNSUPPORTED)) { LAC_LOG_ERROR("Response status value not as expected"); status = CPA_STATUS_FAIL; } } pSymDpCb = ((sal_crypto_service_t *)pResponse->instanceHandle)->pSymDpCb; LAC_ASSERT_NOT_NULL(pSymDpCb); pSymDpCb(pResponse, status, qatRespStatusOkFlag); /* * Decrement the number of pending CB. * * If the @pendingDpCbCount becomes zero, we may remove the session, please * read more information in the cpaCySymRemoveSession(). * * But there is a field in the @pResponse to store the session, * the "sessionCtx". In another word, in the above @->pSymDpCb() callback, * it may use the session again. If we decrease the @pendingDpCbCount before * the @->pSymDpCb(), there is a _risk_ the @->pSymDpCb() may reference to * a deleted session. * * So in order to avoid the risk, we decrease the @pendingDpCbCount after * the @->pSymDpCb() callback. */ --pSessionDesc->u.pendingDpCbCount; } /** ****************************************************************************** * @ingroup LacSymCb * Definition of callback function for processing symmetric responses * * @description * This callback, which is registered with the common symmetric response * message handler, is invoked to process symmetric response messages from * the QAT. It will extract the response status from the cmnRespFlags set * by the QAT, and then will pass it to @ref * LacSymCb_ProcessCallbackInternal to complete the response processing. * * @param[in] lacCmdId ID of the symmetric QAT command of the request * message * @param[in] pOpaqueData pointer to opaque data in the request message * @param[in] cmnRespFlags Flags set by QAT to indicate response status * * @return None ******************************************************************************/ STATIC void LacSymCb_ProcessCallback(icp_qat_fw_la_cmd_id_t lacCmdId, void *pOpaqueData, icp_qat_fw_comn_flags cmnRespFlags) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymDpOpData *pDpOpData = (CpaCySymDpOpData *)pOpaqueData; lac_session_desc_t *pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pDpOpData->sessionCtx); CpaBoolean qatRespStatusOkFlag = (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)); if (CPA_TRUE == pSessionDesc->isDPSession) { /* DP session */ if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(cmnRespFlags)) { status = CPA_STATUS_UNSUPPORTED; } LacSymCb_ProcessDpCallback( pDpOpData, qatRespStatusOkFlag, status, pSessionDesc); } else { /* Trad session */ LacSymCb_ProcessCallbackInternal((lac_sym_bulk_cookie_t *)pOpaqueData, qatRespStatusOkFlag, CPA_STATUS_SUCCESS, pSessionDesc); } } static CpaStatus LacSym_SwRespMsgCallbackBulk(lac_sym_cookie_t *pCookie, lac_mem_blk_t *pCurrentBlk) { CpaCySymCbFunc pSymCb = NULL; CpaCySymOpData *pOpData; lac_sym_bulk_cookie_t *pBulkCookie; lac_session_desc_t *pSessionDesc; void *pCallbackTag; pBulkCookie = &pCookie->u.bulkCookie; /* For Traditional API - user callback is stored in session * description structure */ pOpData = (CpaCySymOpData *)LAC_CONST_PTR_CAST(pBulkCookie->pOpData); LAC_ASSERT_NOT_NULL(pOpData); pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx); LAC_ASSERT_NOT_NULL(pSessionDesc); if (CPA_TRUE != pSessionDesc->isDPSession) { pSymCb = pSessionDesc->pSymCb; LAC_ASSERT_NOT_NULL(pSymCb); pCallbackTag = pBulkCookie->pCallbackTag; LAC_LOG_DEBUG1("Sym dummy response index = %llx", pCurrentBlk->opaque); pSymCb(pCallbackTag, CPA_STATUS_FAIL, pSessionDesc->symOperation, pOpData, pBulkCookie->pDstBuffer, CPA_FALSE); osalAtomicDec(&(pSessionDesc->u.pendingCbCount)); } Lac_MemPoolEntryFree(pCookie); return CPA_STATUS_SUCCESS; } static CpaStatus LacSym_SwRespMsgCallbackKey(lac_sym_cookie_t *pCookie, lac_mem_blk_t *pCurrentBlk) { CpaCyGenFlatBufCbFunc pKeyGenSslTlsCb = NULL; lac_sym_key_cookie_t *pKeyCookie; pKeyCookie = &pCookie->u.keyCookie; pKeyGenSslTlsCb = (CpaCyGenFlatBufCbFunc)(pKeyCookie->pKeyGenCb); LAC_ASSERT_NOT_NULL(pKeyGenSslTlsCb); LAC_LOG_DEBUG1("Sym dummy response index = %llx", pCurrentBlk->opaque); pKeyGenSslTlsCb(pKeyCookie->pCallbackTag, CPA_STATUS_FAIL, pKeyCookie->pKeyGenOpData, pKeyCookie->pKeyGenOutputData); Lac_MemPoolEntryFree(pCookie); return CPA_STATUS_SUCCESS; } /* ******************************************************************************* * Define public/global function definitions ******************************************************************************* */ /** *************************************************************************** * @ingroup LacSymCb * Symmetric cryptography dummy response generation function. ***************************************************************************/ CpaStatus LacSym_SwRespMsgCallback(lac_memblk_bucket_t *pBucket) { lac_mem_blk_t **pBucketBlk = NULL; lac_mem_blk_t *pCurrentBlk = NULL; Cpa32U numBucketBlks = 0; Cpa32U numSwResp = 0; Cpa32U startIndex = 0; Cpa32U iter = 0; lac_sym_cookie_t *pCookie = NULL; CpaStatus status; LAC_ASSERT_NOT_NULL(pBucket); pBucketBlk = pBucket->mem_blk; LAC_ASSERT_NOT_NULL(pBucketBlk); startIndex = pBucket->startIndex; numBucketBlks = pBucket->numBucketBlks; numSwResp = pBucket->numBlksInRing; for (iter = 0; iter < numSwResp; iter++) { status = CPA_STATUS_SUCCESS; pCurrentBlk = pBucketBlk[(startIndex + iter) % numBucketBlks]; if (NULL == pCurrentBlk) continue; pCookie = (lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + sizeof(lac_mem_blk_t)); switch (pCookie->cookieType) { case LAC_SYM_BULK_COOKIE_TYPE: status = LacSym_SwRespMsgCallbackBulk(pCookie, pCurrentBlk); break; case LAC_SYM_KEY_COOKIE_TYPE: status = LacSym_SwRespMsgCallbackKey(pCookie, pCurrentBlk); break; default: LAC_LOG_ERROR2( "Not supported cookie type: %d. SW response index = %llx.", pCookie->cookieType, pCurrentBlk->opaque); } if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR2( "Generating SW response (index = %llx) failed with status: %d.", pCurrentBlk->opaque, (int)status); } } if (0 != numSwResp) return CPA_STATUS_SUCCESS; return CPA_STATUS_RETRY; } /** * @ingroup LacSymCb * * @return CpaStatus * value returned will be the result of icp_adf_transPutMsg */ CpaStatus LacSymCb_PendingReqsDequeue(lac_session_desc_t *pSessionDesc) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pService = NULL; Cpa32U retries = 0; Cpa64U seq_num = ICP_ADF_INVALID_SEND_SEQ; LAC_ENSURE(pSessionDesc != NULL, "LacSymCb_PendingReqsDequeue - pSessionDesc NULL\n"); pService = (sal_crypto_service_t *)pSessionDesc->pInstance; /* Need to protect access to queue head and tail pointers, which may * be accessed by multiple contexts simultaneously for enqueue and * dequeue operations */ LAC_SPINLOCK(&pSessionDesc->requestQueueLock); /* Clear the blocking flag in the session descriptor */ pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; while ((NULL != pSessionDesc->pRequestQueueHead) && (CPA_TRUE == pSessionDesc->nonBlockingOpsInProgress)) { /* If we send a partial packet request, set the blockingOpsInProgress * flag for the session to indicate that subsequent requests must be * queued up until this request completes */ if (CPA_CY_SYM_PACKET_TYPE_FULL != pSessionDesc->pRequestQueueHead->pOpData->packetType) { pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; } /* At this point, we're clear to send the request. For cipher requests, * we need to check if the session IV needs to be updated. This can * only be done when no other partials are in flight for this session, * to ensure the cipherPartialOpState buffer in the session descriptor * is not currently in use */ if (CPA_TRUE == pSessionDesc->pRequestQueueHead->updateSessionIvOnSend) { if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { memcpy(pSessionDesc->cipherPartialOpState, pSessionDesc->cipherARC4InitialState, LAC_CIPHER_ARC4_STATE_LEN_BYTES); } else { memcpy(pSessionDesc->cipherPartialOpState, pSessionDesc->pRequestQueueHead->pOpData->pIv, pSessionDesc->pRequestQueueHead->pOpData->ivLenInBytes); } } /* * Now we'll attempt to send the message directly to QAT. We'll keep * looking until it succeeds (or at least a very high number of * retries), as the failure only happens when the ring is full, * and this is only a temporary situation. After a few retries, * space will become available, allowing the putMsg to succeed. */ retries = 0; do { /* Send directly to QAT */ status = icp_adf_transPutMsg( pService->trans_handle_sym_tx, (void *)&(pSessionDesc->pRequestQueueHead->qatMsg), LAC_QAT_SYM_REQ_SZ_LW, &seq_num); retries++; /* * Yield to allow other threads that may be on this session to poll * and make some space on the ring */ if (CPA_STATUS_SUCCESS != status) { osalYield(); } } while ((CPA_STATUS_SUCCESS != status) && (retries < DEQUEUE_MSGPUT_MAX_RETRIES)); if ((CPA_STATUS_SUCCESS != status) || (retries >= DEQUEUE_MSGPUT_MAX_RETRIES)) { LAC_LOG_ERROR( "Failed to icp_adf_transPutMsg, maximum retries exceeded."); goto cleanup; } LAC_MEM_POOL_BLK_SET_OPAQUE(pSessionDesc->pRequestQueueHead, seq_num); pSessionDesc->pRequestQueueHead = pSessionDesc->pRequestQueueHead->pNext; } /* If we've drained the queue, ensure the tail pointer is set to NULL */ if (NULL == pSessionDesc->pRequestQueueHead) { pSessionDesc->pRequestQueueTail = NULL; } cleanup: LAC_SPINUNLOCK(&pSessionDesc->requestQueueLock); return status; } /** * @ingroup LacSymCb */ void LacSymCb_CallbacksRegister() { /*** HASH ***/ LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_AUTH, LacSymCb_ProcessCallback); /*** ALGORITHM-CHAINING CIPHER_HASH***/ LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_CIPHER_HASH, LacSymCb_ProcessCallback); /*** ALGORITHM-CHAINING HASH_CIPHER***/ LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HASH_CIPHER, LacSymCb_ProcessCallback); /*** CIPHER ***/ LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_CIPHER, LacSymCb_ProcessCallback); /* Call compile time param check function to ensure it is included in the build by the compiler - this compile time check ensures callbacks run as expected */ LacSym_CompileTimeAssertions(); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_cipher.c000066400000000000000000000531701503624047500314640ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_cipher.c Cipher * * @ingroup LacCipher * * @description Functions specific to cipher ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "icp_qat_fw_la.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_sym_cipher.h" #include "lac_session.h" #include "lac_mem.h" #include "lac_common.h" #include "lac_list.h" #include "lac_sym.h" #include "lac_sym_key.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_sym_cipher_defs.h" #include "lac_sym_cipher.h" #include "lac_sym_stats.h" #include "lac_sym.h" #include "lac_sym_qat_cipher.h" #include "lac_log.h" #include "lac_buffer_desc.h" /* ******************************************************************************* * Static Variables ******************************************************************************* */ CpaStatus LacCipher_PerformIvCheck(sal_service_t *pService, lac_sym_bulk_cookie_t *pCbCookie, Cpa32U qatPacketType, Cpa8U **ppIvBuffer) { const CpaCySymOpData *pOpData = pCbCookie->pOpData; lac_session_desc_t *pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx); CpaCySymCipherAlgorithm algorithm = pSessionDesc->cipherAlgorithm; #ifdef ICP_PARAM_CHECK unsigned ivLenInBytes = 0; #endif switch (algorithm) { /* Perform IV check for CTR, CBC, XTS, F8 MODE. */ case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_3DES_CTR: case CPA_CY_SYM_CIPHER_AES_CCM: case CPA_CY_SYM_CIPHER_AES_GCM: case CPA_CY_SYM_CIPHER_CHACHA: case CPA_CY_SYM_CIPHER_AES_CBC: case CPA_CY_SYM_CIPHER_DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CBC: case CPA_CY_SYM_CIPHER_AES_F8: case CPA_CY_SYM_CIPHER_AES_XTS: case CPA_CY_SYM_CIPHER_SM4_CBC: case CPA_CY_SYM_CIPHER_SM4_CTR: { #ifdef ICP_PARAM_CHECK ivLenInBytes = LacSymQat_CipherIvSizeBytesGet(algorithm); LAC_CHECK_NULL_PARAM(pOpData->pIv); if (pOpData->ivLenInBytes != ivLenInBytes) { /* GCM with 12 byte IV is supported */ if (!((LAC_CIPHER_IS_GCM(algorithm) && pOpData->ivLenInBytes == LAC_CIPHER_IV_SIZE_GCM_12) || LAC_CIPHER_IS_CCM(algorithm))) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } } #endif /* Always copy the user's IV into another cipher state buffer if * the request is part of a partial packet sequence * (ensures that pipelined partial requests use same buffer) */ if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) { /* Set the value of the ppIvBuffer to that supplied * by the user. * NOTE: There is no guarantee that this address is aligned on * an 8 or 64 Byte address. */ *ppIvBuffer = pOpData->pIv; } else { /* For partial packets, we use a per-session buffer to maintain * the IV. This allows us to easily pass the updated IV forward * to the next partial in the sequence. This makes internal * buffering of partials easier to implement. */ *ppIvBuffer = pSessionDesc->cipherPartialOpState; /* Ensure that the user's IV buffer gets updated between partial * requests so that they may also see the residue from the * previous partial. Not needed for final partials though. */ if ((ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) || (ICP_QAT_FW_LA_PARTIAL_MID == qatPacketType)) { pCbCookie->updateUserIvOnRecieve = CPA_TRUE; if (ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) { /* if the previous partial state was full, then this is * the first partial in the sequence so we need to copy * in the user's IV. But, we have to be very careful * here not to overwrite the cipherPartialOpState just * yet in case there's a previous partial sequence in * flight, so we defer the copy for now. This will be * completed in the LacSymQueue_RequestSend() function. */ pCbCookie->updateSessionIvOnSend = CPA_TRUE; } /* For subsequent partials in a sequence, we'll reuse the * IV that was written back by the QAT, using internal * request queueing if necessary to ensure that the next * partial request isn't issued to the QAT until the * previous one completes */ } } } break; case CPA_CY_SYM_CIPHER_KASUMI_F8: { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pOpData->pIv); if (pOpData->ivLenInBytes != LAC_CIPHER_KASUMI_F8_IV_LENGTH) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } #endif *ppIvBuffer = pOpData->pIv; } break; case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pOpData->pIv); if (pOpData->ivLenInBytes != ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } #endif *ppIvBuffer = pOpData->pIv; } break; case CPA_CY_SYM_CIPHER_ARC4: { if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) { /* For full packets, the initial ARC4 state is stored in the * session descriptor. Use it directly. */ *ppIvBuffer = pSessionDesc->cipherARC4InitialState; } else { /* For partial packets, we maintain the running ARC4 state in * dedicated buffer in the session descriptor */ *ppIvBuffer = pSessionDesc->cipherPartialOpState; if (ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) { /* if the previous partial state was full, then this is the * first partial in the sequence so we need to * (re-)initialise the contents of the state buffer using * the initial state that is stored in the session * descriptor. But, we have to be very careful here not to * overwrite the cipherPartialOpState just yet in case * there's a previous partial sequence in flight, so we * defer the copy for now. This will be completed in the * LacSymQueue_RequestSend() function when clear to send. */ pCbCookie->updateSessionIvOnSend = CPA_TRUE; } } } break; case CPA_CY_SYM_CIPHER_ZUC_EEA3: { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pOpData->pIv); if ((pOpData->ivLenInBytes != ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) && (pOpData->ivLenInBytes != ICP_QAT_HW_ZUC_256_IV_SZ)) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } #endif *ppIvBuffer = pOpData->pIv; } break; default: *ppIvBuffer = NULL; } return CPA_STATUS_SUCCESS; } #ifdef ICP_PARAM_CHECK CpaStatus LacCipher_SessionSetupDataCheck( const CpaCySymCipherSetupData *pCipherSetupData, Cpa32U capabilitiesMask, sal_service_t *pService) { /* No key required for NULL algorithm */ if (!LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm)) { LAC_CHECK_NULL_PARAM(pCipherSetupData->pCipherKey); /* Check that algorithm and keys passed in are correct size */ switch (pCipherSetupData->cipherAlgorithm) { case CPA_CY_SYM_CIPHER_ARC4: if (pCipherSetupData->cipherKeyLenInBytes > ICP_QAT_HW_ARC4_KEY_SZ) { LAC_INVALID_PARAM_LOG("Invalid ARC4 cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_AES_CCM: if (!LAC_CIPHER_AES_V2(capabilitiesMask) && pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_128_KEY_SZ) { LAC_INVALID_PARAM_LOG("Invalid AES CCM cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_AES_XTS: if ((pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_128_XTS_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_256_XTS_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_UCS_AES_128_XTS_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_UCS_AES_256_XTS_KEY_SZ)) { LAC_INVALID_PARAM_LOG("Invalid AES XTS cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_AES_ECB: case CPA_CY_SYM_CIPHER_AES_CBC: case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_AES_GCM: if (((pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_128_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_192_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_256_KEY_SZ))) { LAC_INVALID_PARAM_LOG("Invalid AES cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_AES_F8: if ((pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_128_F8_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_192_F8_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_AES_256_F8_KEY_SZ)) { LAC_INVALID_PARAM_LOG("Invalid AES cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_DES_ECB: case CPA_CY_SYM_CIPHER_DES_CBC: if (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_DES_KEY_SZ) { LAC_INVALID_PARAM_LOG("Invalid DES cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_3DES_ECB: case CPA_CY_SYM_CIPHER_3DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CTR: if (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_3DES_KEY_SZ) { LAC_INVALID_PARAM_LOG( "Invalid Triple-DES cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_KASUMI_F8: /* QAT-FW only supports 128 bits Cipher Key size for Kasumi F8 * Ref: 3GPP TS 55.216 V6.2.0 */ if (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_KASUMI_KEY_SZ) { LAC_INVALID_PARAM_LOG("Invalid Kasumi cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: /* QAT-FW only supports 256 bits Cipher Key size for Snow_3G */ if (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) { LAC_INVALID_PARAM_LOG("Invalid Snow_3G cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_ZUC_EEA3: /* ZUC EEA3 */ if ((pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) && (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_ZUC_256_KEY_SZ)) { LAC_INVALID_PARAM_LOG("Invalid ZUC cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_CHACHA: if (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_CHACHAPOLY_KEY_SZ) { LAC_INVALID_PARAM_LOG( "Invalid CHACHAPOLY cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; case CPA_CY_SYM_CIPHER_SM4_ECB: case CPA_CY_SYM_CIPHER_SM4_CBC: case CPA_CY_SYM_CIPHER_SM4_CTR: if (pCipherSetupData->cipherKeyLenInBytes != ICP_QAT_HW_SM4_KEY_SZ) { LAC_INVALID_PARAM_LOG("Invalid SM4 cipher key length"); return CPA_STATUS_INVALID_PARAM; } break; default: LAC_INVALID_PARAM_LOG("Invalid cipher algorithm"); return CPA_STATUS_INVALID_PARAM; } } return CPA_STATUS_SUCCESS; } CpaStatus LacCipher_PerformParamCheck(CpaCySymCipherAlgorithm algorithm, const CpaCySymOpData *pOpData, const Cpa64U packetLen) { CpaStatus status = CPA_STATUS_SUCCESS; /* The following check will cover the dstBuffer as well, since * the dstBuffer cannot be smaller than the srcBuffer (checked in * LacSymPerform_BufferParamCheck() called from LacSym_Perform()) */ if ((pOpData->messageLenToCipherInBytes + pOpData->cryptoStartSrcOffsetInBytes) > packetLen) { LAC_INVALID_PARAM_LOG("cipher len + offset greater than " "srcBuffer packet len"); status = CPA_STATUS_INVALID_PARAM; } else { /* Perform algorithm-specific checks */ switch (algorithm) { case CPA_CY_SYM_CIPHER_ARC4: case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_3DES_CTR: case CPA_CY_SYM_CIPHER_AES_CCM: case CPA_CY_SYM_CIPHER_AES_GCM: case CPA_CY_SYM_CIPHER_CHACHA: case CPA_CY_SYM_CIPHER_KASUMI_F8: case CPA_CY_SYM_CIPHER_AES_F8: case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: case CPA_CY_SYM_CIPHER_ZUC_EEA3: case CPA_CY_SYM_CIPHER_SM4_CTR: /* No action needed */ break; /* * XTS Mode allow for ciphers which are not multiples of * the block size. */ case CPA_CY_SYM_CIPHER_AES_XTS: if ((pOpData->packetType == CPA_CY_SYM_PACKET_TYPE_FULL) || (pOpData->packetType == CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL)) { /* * If this is the last of a partial request */ if (pOpData->messageLenToCipherInBytes < ICP_QAT_HW_AES_BLK_SZ) { LAC_INVALID_PARAM_LOG( "data size must be greater than block" " size for last XTS partial or XTS " "full packet"); status = CPA_STATUS_INVALID_PARAM; } } break; default: /* Mask & check below is based on assumption that block size * is a power of 2. If data size is not a multiple of the * block size, the "remainder" bits selected by the mask be * non-zero */ if (pOpData->messageLenToCipherInBytes & (LacSymQat_CipherBlockSizeBytesGet(algorithm) - 1)) { LAC_INVALID_PARAM_LOG("data size must be block size" " multiple"); status = CPA_STATUS_INVALID_PARAM; } } } return status; } #endif Cpa32U LacCipher_GetCipherSliceType(sal_service_t *pService, CpaCySymCipherAlgorithm cipherAlgorithm) { Cpa32U sliceType = ICP_QAT_FW_LA_USE_LEGACY_SLICE_TYPE; Cpa32U capabilitiesMask = pService->capabilitiesMask; if (LAC_CIPHER_IS_XTS_MODE(cipherAlgorithm) || LAC_CIPHER_IS_CHACHA(cipherAlgorithm) || LAC_CIPHER_IS_GCM(cipherAlgorithm)) { sliceType = ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE; } else if (LAC_CIPHER_IS_CCM(cipherAlgorithm) && LAC_CIPHER_AES_V2(capabilitiesMask)) { sliceType = ICP_QAT_FW_LA_USE_LEGACY_SLICE_TYPE; } else if (LAC_CIPHER_IS_AES(cipherAlgorithm) && LAC_CIPHER_IS_CTR_MODE(cipherAlgorithm)) { sliceType = ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE; } return sliceType; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_compile_check.c000066400000000000000000000104051503624047500327710ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_compile_check.c * * @ingroup LacSym * * This file checks at compile time that some assumptions about the layout * of key structures are as expected. * * ***************************************************************************/ #include "cpa.h" #include "lac_common.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "lac_sym.h" #include "cpa_cy_sym_dp.h" #define COMPILE_TIME_ASSERT(pred) \ switch (0) \ { \ case 0: \ case pred:; \ } void LacSym_CompileTimeAssertions(void) { /* ************************************************************* * Check sessionCtx is at the same location in bulk cookie and * CpaCySymDpOpData. * This is required for the callbacks to work as expected - * see LacSymCb_ProcessCallback * ************************************************************* */ COMPILE_TIME_ASSERT(offsetof(lac_sym_bulk_cookie_t, sessionCtx) == offsetof(CpaCySymDpOpData, sessionCtx)); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_dp.c000066400000000000000000001443541503624047500306220ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_dp.c * Implementation of the symmetric data plane API * * @ingroup cpaCySymDp ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_cy_sym_dp.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_transport_dp.h" #include "icp_adf_debug.h" #include "icp_sal_poll.h" #include "lac_mem.h" #include "lac_log.h" #include "lac_sym.h" #include "lac_sym_cipher.h" #include "lac_sym_qat_cipher.h" #include "lac_list.h" #include "lac_sal_types_crypto.h" #include "sal_service_state.h" #include "lac_sym_auth_enc.h" typedef void (*write_ringMsgFunc_t)(CpaCySymDpOpData *pRequest, icp_qat_fw_la_bulk_req_t *pCurrentQatMsg); #ifdef ICP_PARAM_CHECK /** ***************************************************************************** * @ingroup cpaCySymDp * Check that the operation data is valid * * @description * Check that all the parameters defined in the operation data are valid * * @param[in] pRequest Pointer to an operation data for crypto * data plane API * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in * *****************************************************************************/ STATIC CpaStatus LacDp_EnqueueParamCheck(const CpaCySymDpOpData *pRequest) { lac_session_desc_t *pSessionDesc = NULL; CpaCySymCipherAlgorithm cipher = 0; CpaCySymHashAlgorithm hash = 0; Cpa32U capabilitiesMask = 0; LAC_CHECK_NULL_PARAM(pRequest); LAC_CHECK_NULL_PARAM(pRequest->instanceHandle); LAC_CHECK_NULL_PARAM(pRequest->sessionCtx); /* Ensure this is a crypto instance */ SAL_CHECK_INSTANCE_TYPE( pRequest->instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); if (NULL == pSessionDesc) { do { osalSleep(500); pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); } while (NULL == pSessionDesc); } if (NULL == pSessionDesc) { LAC_INVALID_PARAM_LOG("Session context not as expected"); return CPA_STATUS_INVALID_PARAM; } if (CPA_FALSE == pSessionDesc->isDPSession) { LAC_INVALID_PARAM_LOG("Session not initialised for data plane API"); return CPA_STATUS_INVALID_PARAM; } /*check whether Payload size is zero for CHACHA-POLY */ if ((CPA_CY_SYM_CIPHER_CHACHA == pSessionDesc->cipherAlgorithm) && (CPA_CY_SYM_HASH_POLY == pSessionDesc->hashAlgorithm) && (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { if (!pRequest->messageLenToCipherInBytes) { LAC_INVALID_PARAM_LOG( "Invalid messageLenToCipherInBytes for CHACHA-POLY"); return CPA_STATUS_INVALID_PARAM; } } if (0 == pRequest->srcBuffer) { LAC_INVALID_PARAM_LOG("Invalid srcBuffer"); return CPA_STATUS_INVALID_PARAM; } if (0 == pRequest->dstBuffer) { LAC_INVALID_PARAM_LOG("Invalid destBuffer"); return CPA_STATUS_INVALID_PARAM; } if (0 == pRequest->thisPhys) { LAC_INVALID_PARAM_LOG("Invalid thisPhys"); return CPA_STATUS_INVALID_PARAM; } /* Check that src buffer Len = dst buffer Len Note this also checks that they are of the same type */ if (pRequest->srcBufferLen != pRequest->dstBufferLen) { LAC_INVALID_PARAM_LOG( "Source and Destination buffer lengths need to be equal"); return CPA_STATUS_INVALID_PARAM; } /* digestVerify and digestIsAppended on Hash-Only operation not supported */ if (pSessionDesc->digestIsAppended && pSessionDesc->digestVerify && (pSessionDesc->symOperation == CPA_CY_SYM_OP_HASH)) { LAC_INVALID_PARAM_LOG("digestVerify and digestIsAppended set " "on Hash-Only operation is not supported"); return CPA_STATUS_INVALID_PARAM; } /* Cipher specific tests */ if (CPA_CY_SYM_OP_HASH != pSessionDesc->symOperation) { /* Perform IV check */ switch (pSessionDesc->cipherAlgorithm) { case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_3DES_CTR: case CPA_CY_SYM_CIPHER_AES_GCM: case CPA_CY_SYM_CIPHER_CHACHA: case CPA_CY_SYM_CIPHER_AES_CBC: case CPA_CY_SYM_CIPHER_DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CBC: case CPA_CY_SYM_CIPHER_AES_F8: case CPA_CY_SYM_CIPHER_SM4_CTR: case CPA_CY_SYM_CIPHER_SM4_CBC: { Cpa32U ivLenInBytes = LacSymQat_CipherIvSizeBytesGet( pSessionDesc->cipherAlgorithm); if (pRequest->ivLenInBytes != ivLenInBytes) { if (!(/* GCM with 12 byte IV is OK */ (LAC_CIPHER_IS_GCM(pSessionDesc->cipherAlgorithm) && pRequest->ivLenInBytes == LAC_CIPHER_IV_SIZE_GCM_12))) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } } if (0 == pRequest->iv) { LAC_INVALID_PARAM_LOG("invalid iv of 0"); return CPA_STATUS_INVALID_PARAM; } /* pRequest->pIv is only used for CCM so is not checked here */ } break; case CPA_CY_SYM_CIPHER_KASUMI_F8: { if (LAC_CIPHER_KASUMI_F8_IV_LENGTH != pRequest->ivLenInBytes) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } if (0 == pRequest->iv) { LAC_INVALID_PARAM_LOG("invalid iv of 0"); return CPA_STATUS_INVALID_PARAM; } } break; case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: { if (ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ != pRequest->ivLenInBytes) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } if (0 == pRequest->iv) { LAC_INVALID_PARAM_LOG("invalid iv of 0"); return CPA_STATUS_INVALID_PARAM; } } break; case CPA_CY_SYM_CIPHER_ZUC_EEA3: { if ((ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ != pRequest->ivLenInBytes) && (ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ == pSessionDesc->cipherKeyLenInBytes)) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } if ((ICP_QAT_HW_ZUC_256_IV_SZ != pRequest->ivLenInBytes) && (ICP_QAT_HW_ZUC_256_KEY_SZ == pSessionDesc->cipherKeyLenInBytes)) { LAC_INVALID_PARAM_LOG("invalid cipher IV size"); return CPA_STATUS_INVALID_PARAM; } if (0 == pRequest->iv) { LAC_INVALID_PARAM_LOG("invalid iv of 0"); return CPA_STATUS_INVALID_PARAM; } } break; case CPA_CY_SYM_CIPHER_AES_CCM: { if (CPA_STATUS_SUCCESS != LacSymAlgChain_CheckCCMData( pRequest->pAdditionalAuthData, pRequest->pIv, pRequest->messageLenToCipherInBytes, pRequest->ivLenInBytes)) { return CPA_STATUS_INVALID_PARAM; } } break; default: break; } /* Perform algorithm-specific checks */ switch (pSessionDesc->cipherAlgorithm) { case CPA_CY_SYM_CIPHER_ARC4: case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_3DES_CTR: case CPA_CY_SYM_CIPHER_AES_CCM: case CPA_CY_SYM_CIPHER_AES_GCM: case CPA_CY_SYM_CIPHER_CHACHA: case CPA_CY_SYM_CIPHER_KASUMI_F8: case CPA_CY_SYM_CIPHER_AES_F8: case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: case CPA_CY_SYM_CIPHER_ZUC_EEA3: case CPA_CY_SYM_CIPHER_SM4_CTR: /* No action needed */ break; default: { /* Mask & check below is based on assumption that block size is * a power of 2. If data size is not a multiple of the block * size, the "remainder" bits selected by the mask be non-zero */ if (pRequest->messageLenToCipherInBytes & (LacSymQat_CipherBlockSizeBytesGet( pSessionDesc->cipherAlgorithm) - 1)) { LAC_INVALID_PARAM_LOG("Data size must be block size" " multiple"); return CPA_STATUS_INVALID_PARAM; } } } cipher = pSessionDesc->cipherAlgorithm; hash = pSessionDesc->hashAlgorithm; capabilitiesMask = ((sal_crypto_service_t *)pRequest->instanceHandle) ->generic_service_info.capabilitiesMask; if (LAC_CIPHER_IS_SPC(cipher, hash, capabilitiesMask)) { /* For CHACHA and AES_GCM single pass there is an AAD buffer * if aadLenInBytes is nonzero. AES_GMAC AAD is stored in * source buffer, therefore there is no separate AAD buffer. * For AES_CCM single pass that always will be AAD buffer, * even if aadLenInBytes will be zero */ if (LAC_CIPHER_IS_SPC_CCM(cipher, hash, capabilitiesMask) || ((0 != pSessionDesc->aadLenInBytes) && (CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm))) { LAC_CHECK_NULL_PARAM(pRequest->pAdditionalAuthData); } /* Ensure AAD length for AES_GMAC spc */ if ((CPA_CY_SYM_HASH_AES_GMAC == hash) && (ICP_QAT_FW_SPC_AAD_SZ_MAX < pRequest->messageLenToHashInBytes)) { LAC_INVALID_PARAM_LOG("aadLenInBytes for AES_GMAC"); return CPA_STATUS_INVALID_PARAM; } } } /* Hash specific tests */ if (CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation) { /* For CCM, snow3G and ZUC there is always an AAD buffer For GCM there is an AAD buffer if aadLenInBytes is nonzero */ if ((CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm && (0 != pSessionDesc->aadLenInBytes))) { LAC_CHECK_NULL_PARAM(pRequest->pAdditionalAuthData); if (0 == pRequest->additionalAuthData) { LAC_INVALID_PARAM_LOG("Invalid additionalAuthData"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm || CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm) { if (0 == pRequest->additionalAuthData) { LAC_INVALID_PARAM_LOG("Invalid additionalAuthData"); return CPA_STATUS_INVALID_PARAM; } } if ((CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm) && (!pSessionDesc->digestIsAppended) && (0 == pRequest->digestResult)) { LAC_INVALID_PARAM_LOG("Invalid digestResult"); return CPA_STATUS_INVALID_PARAM; } if (CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) { if ((pRequest->cryptoStartSrcOffsetInBytes + pRequest->messageLenToCipherInBytes + pSessionDesc->hashResultSize) > pRequest->dstBufferLen) { LAC_INVALID_PARAM_LOG("CCM - Not enough room for" " digest in destination buffer"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_TRUE == pSessionDesc->digestIsAppended) { if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { if ((pRequest->hashStartSrcOffsetInBytes + pRequest->messageLenToHashInBytes + pSessionDesc->hashResultSize) > pRequest->dstBufferLen) { LAC_INVALID_PARAM_LOG("Append Digest - Not enough room for" " digest in destination buffer for " "AES GMAC algorithm"); return CPA_STATUS_INVALID_PARAM; } } if (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm) { if ((pRequest->cryptoStartSrcOffsetInBytes + pRequest->messageLenToCipherInBytes + pSessionDesc->hashResultSize) > pRequest->dstBufferLen) { LAC_INVALID_PARAM_LOG("Append Digest - Not enough room " "for digest in destination buffer" " for GCM algorithm"); return CPA_STATUS_INVALID_PARAM; } } if ((pRequest->hashStartSrcOffsetInBytes + pRequest->messageLenToHashInBytes + pSessionDesc->hashResultSize) > pRequest->dstBufferLen) { LAC_INVALID_PARAM_LOG("Append Digest - Not enough room for" " digest in destination buffer"); return CPA_STATUS_INVALID_PARAM; } } if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { if (pRequest->messageLenToHashInBytes == 0 || pRequest->pAdditionalAuthData != NULL) { LAC_INVALID_PARAM_LOG("For AES_GMAC, AAD Length " "(messageLenToHashInBytes) must be " "non zero and pAdditionalAuthData " "must be NULL"); return CPA_STATUS_INVALID_PARAM; } } } if (CPA_DP_BUFLIST != pRequest->srcBufferLen) { if ((CPA_CY_SYM_OP_HASH != pSessionDesc->symOperation) && ((pRequest->messageLenToCipherInBytes + pRequest->cryptoStartSrcOffsetInBytes) > pRequest->srcBufferLen)) { LAC_INVALID_PARAM_LOG("cipher len + offset greater than " "srcBufferLen"); return CPA_STATUS_INVALID_PARAM; } else if ((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation) && (CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm) && (CPA_CY_SYM_HASH_AES_GCM != pSessionDesc->hashAlgorithm) && (CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm) && ((pRequest->messageLenToHashInBytes + pRequest->hashStartSrcOffsetInBytes) > pRequest->srcBufferLen)) { LAC_INVALID_PARAM_LOG( "hash len + offset greater than srcBufferLen"); return CPA_STATUS_INVALID_PARAM; } } else { LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->srcBuffer); LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->dstBuffer); } LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->thisPhys); return CPA_STATUS_SUCCESS; } #endif /** ***************************************************************************** * @ingroup cpaCySymDp * Write Message on the ring and write request params * This is the optimized version, which should not be used for * algorithm of CCM, GCM, CHACHA and RC4 * * @description * Write Message on the ring and write request params * * @param[in/out] pRequest Pointer to operation data for crypto * data plane API * @param[in/out] pCurrentQatMsg Pointer to ring memory where msg will * be written * * @retval none * *****************************************************************************/ void LacDp_WriteRingMsgOpt(CpaCySymDpOpData *pRequest, icp_qat_fw_la_bulk_req_t *pCurrentQatMsg) { lac_session_desc_t *pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); Cpa8U *pMsgDummy = NULL; Cpa8U *pCacheDummyHdr = NULL; Cpa8U *pCacheDummyFtr = NULL; pMsgDummy = (Cpa8U *)pCurrentQatMsg; /* Write Request */ /* * Fill in the header and footer bytes of the ET ring message - cached from * the session descriptor. */ if (!pSessionDesc->useSymConstantsTable) { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqCacheFtr); } else { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->shramReqCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->shramReqCacheFtr); } osalMemCopy(pMsgDummy, pCacheDummyHdr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); osalMemSet( (pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), 0, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), pCacheDummyFtr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); SalQatMsg_CmnMidWrite(pCurrentQatMsg, pRequest, (CPA_DP_BUFLIST == pRequest->srcBufferLen ? QAT_COMN_PTR_TYPE_SGL : QAT_COMN_PTR_TYPE_FLAT), pRequest->srcBuffer, pRequest->dstBuffer, pRequest->srcBufferLen, pRequest->dstBufferLen); /* Write Request Params */ if (pSessionDesc->isCipher) { LacSymQat_CipherRequestParamsPopulate( pSessionDesc, pCurrentQatMsg, pRequest->cryptoStartSrcOffsetInBytes, pRequest->messageLenToCipherInBytes, pRequest->iv, pRequest->pIv); } if (pSessionDesc->isAuth) { lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = &(pSessionDesc->hashStateBufferInfo); icp_qat_fw_la_auth_req_params_t *pAuthReqPars = (icp_qat_fw_la_auth_req_params_t *)((Cpa8U *)&(pCurrentQatMsg->serv_specif_rqpars) + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_AES_GCM != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_ZUC_EIA3 != pSessionDesc->hashAlgorithm) && (pHashStateBufferInfo->prefixAadSzQuadWords > 0)) { /* prefixAadSzQuadWords > 0 when there is prefix data - i.e. nested hash or HMAC no precompute cases Note partials not supported on DP api so we do not need dynamic hash state in this case */ pRequest->additionalAuthData = pHashStateBufferInfo->pDataPhys + LAC_QUADWORDS_TO_BYTES( pHashStateBufferInfo->stateStorageSzQuadWords); } /* The first 24 bytes in icp_qat_fw_la_auth_req_params_t can be * copied directly from the op request data because they share a * corresponding layout. The remaining 4 bytes are taken * from the session message template and use values preconfigured at * sessionInit (updated per request for some specific cases below) */ memcpy(pAuthReqPars, (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), ((uintptr_t) & (pAuthReqPars->u2.inner_prefix_sz) - (uintptr_t)pAuthReqPars)); if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { pAuthReqPars->hash_state_sz = LAC_BYTES_TO_QUADWORDS(pAuthReqPars->u2.aad_sz); } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm || CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm) { pAuthReqPars->hash_state_sz = LAC_BYTES_TO_QUADWORDS(pSessionDesc->aadLenInBytes); } } } /** ***************************************************************************** * @ingroup cpaCySymDp * Write Message on the ring and write request params * * @description * Write Message on the ring and write request params * * @param[in/out] pRequest Pointer to operation data for crypto * data plane API * @param[in/out] pCurrentQatMsg Pointer to ring memory where msg will * be written * * @retval none * *****************************************************************************/ void LacDp_WriteRingMsgFull(CpaCySymDpOpData *pRequest, icp_qat_fw_la_bulk_req_t *pCurrentQatMsg) { lac_session_desc_t *pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); Cpa8U *pMsgDummy = NULL; Cpa8U *pCacheDummyHdr = NULL; Cpa8U *pCacheDummyFtr = NULL; sal_qat_content_desc_info_t *pCdInfo = NULL; icp_qat_fw_la_cipher_20_req_params_t *pCipher20ReqParams = NULL; Cpa8U *pHwBlockBaseInDRAM = NULL; Cpa32U hwBlockOffsetInDRAM = 0; Cpa32U sizeInBytes = 0; CpaCySymCipherAlgorithm cipher = pSessionDesc->cipherAlgorithm; CpaCySymHashAlgorithm hash = pSessionDesc->hashAlgorithm; sal_crypto_service_t *pService = (sal_crypto_service_t *)pRequest->instanceHandle; Cpa32U capabilitiesMask = ((sal_crypto_service_t *)pRequest->instanceHandle) ->generic_service_info.capabilitiesMask; CpaBoolean isGen4 = ((sal_crypto_service_t *)pRequest->instanceHandle) ->generic_service_info.isGen4; CpaBoolean isSpGcm = LAC_CIPHER_IS_SPC_GCM(cipher, hash, capabilitiesMask); CpaBoolean isSpCcp = LAC_CIPHER_IS_SPC_CCP(cipher, hash, capabilitiesMask); CpaBoolean isSpCcm = LAC_CIPHER_IS_SPC_CCM(cipher, hash, capabilitiesMask); Cpa8U paddingLen = 0; Cpa8U blockLen = 0; Cpa32U aadDataLen = 0; pMsgDummy = (Cpa8U *)pCurrentQatMsg; /* Write Request */ /* * Fill in the header and footer bytes of the ET ring message - cached from * the session descriptor. */ /* Convert Alg Chain Request to Cipher Request for CCP, * AES_GCM and AES_CCM single pass. * HW supports only 12 bytes IVs for single pass CCP and AES_GCM, * there is no such restriction for single pass CCM */ if ((SPC_NO != pSessionDesc->singlePassState) && ((LAC_CIPHER_SPC_IV_SIZE == pRequest->ivLenInBytes && (isSpGcm || isSpCcp)) || isSpCcm)) { pSessionDesc->singlePassState = SPC_YES; pSessionDesc->isCipher = CPA_TRUE; pSessionDesc->isAuthEncryptOp = CPA_FALSE; pSessionDesc->isAuth = CPA_FALSE; pSessionDesc->symOperation = CPA_CY_SYM_OP_CIPHER; pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { pSessionDesc->aadLenInBytes = pRequest->messageLenToHashInBytes; } /* New bit position (13) for SINGLE PASS. * The FW provides a specific macro to use to set the proto flag */ ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET( pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_SINGLE_PASS_PROTO); /* Set extended service flags - used only in algorithm chaining */ ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_SET(pSessionDesc->laExtCmdFlags, 0); pCdInfo = &(pSessionDesc->contentDescInfo); pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == pSessionDesc->cipherDirection) { if (LAC_CIPHER_IS_GCM(cipher)) hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( LAC_SYM_QAT_CIPHER_GCM_SPC_OFFSET_IN_DRAM); else if (LAC_CIPHER_IS_CHACHA(cipher)) hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( LAC_SYM_QAT_CIPHER_CHACHA_SPC_OFFSET_IN_DRAM); } else if (isSpCcm) { hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( LAC_SYM_QAT_CIPHER_CCM_SPC_OFFSET_IN_DRAM); } /* Update slice type, as used algos changed */ pSessionDesc->cipherSliceType = LacCipher_GetCipherSliceType( &pService->generic_service_info, cipher); ICP_QAT_FW_LA_SLICE_TYPE_SET(pSessionDesc->laCmdFlags, pSessionDesc->cipherSliceType); /* construct cipherConfig in CD in DRAM */ LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, pHwBlockBaseInDRAM + hwBlockOffsetInDRAM, &sizeInBytes); SalQatMsg_CmnHdrWrite( (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqSpcCacheHdr), ICP_QAT_FW_COMN_REQ_CPM_FW_LA, pSessionDesc->laCmdId, pSessionDesc->cmnRequestFlags, pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); } else if ((SPC_YES == pSessionDesc->singlePassState) && (LAC_CIPHER_SPC_IV_SIZE != pRequest->ivLenInBytes)) { pSessionDesc->symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; pSessionDesc->singlePassState = SPC_PROBABLE; pSessionDesc->isCipher = CPA_TRUE; pSessionDesc->isAuthEncryptOp = CPA_TRUE; pSessionDesc->isAuth = CPA_TRUE; pCdInfo = &(pSessionDesc->contentDescInfo); pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == pSessionDesc->cipherDirection) { pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER_HASH; } else { pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_HASH_CIPHER; } ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET(pSessionDesc->laCmdFlags, 0); ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_GCM_PROTO); LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, pHwBlockBaseInDRAM + hwBlockOffsetInDRAM, &sizeInBytes); SalQatMsg_CmnHdrWrite( (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqCacheHdr), ICP_QAT_FW_COMN_REQ_CPM_FW_LA, pSessionDesc->laCmdId, pSessionDesc->cmnRequestFlags, pSessionDesc->laCmdFlags, pSessionDesc->laExtCmdFlags); } else if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { pSessionDesc->aadLenInBytes = pRequest->messageLenToHashInBytes; } if (SPC_YES == pSessionDesc->singlePassState) { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqSpcCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqSpcCacheFtr); } else { if (!pSessionDesc->useSymConstantsTable) { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqCacheFtr); } else { pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->shramReqCacheHdr); pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->shramReqCacheFtr); } } osalMemCopy(pMsgDummy, pCacheDummyHdr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); osalMemSet( (pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), 0, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); osalMemCopy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), pCacheDummyFtr, (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); SalQatMsg_CmnMidWrite(pCurrentQatMsg, pRequest, (CPA_DP_BUFLIST == pRequest->srcBufferLen ? QAT_COMN_PTR_TYPE_SGL : QAT_COMN_PTR_TYPE_FLAT), pRequest->srcBuffer, pRequest->dstBuffer, pRequest->srcBufferLen, pRequest->dstBufferLen); if ((CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm && pSessionDesc->isAuth == CPA_TRUE) || isSpCcm) { /* prepare IV and AAD for CCM */ LacSymAlgChain_PrepareCCMData(pSessionDesc, pRequest->pAdditionalAuthData, pRequest->pIv, pRequest->messageLenToCipherInBytes, pRequest->ivLenInBytes); /* According to the API, for CCM and GCM, messageLenToHashInBytes * and hashStartSrcOffsetInBytes are not initialized by the * user and must be set by the driver */ pRequest->hashStartSrcOffsetInBytes = pRequest->cryptoStartSrcOffsetInBytes; pRequest->messageLenToHashInBytes = pRequest->messageLenToCipherInBytes; } else if ((SPC_YES != pSessionDesc->singlePassState) && (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm || CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm)) { /* GCM case */ if (CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm) { /* According to the API, for CCM and GCM, * messageLenToHashInBytes and hashStartSrcOffsetInBytes * are not initialized by the user and must be set * by the driver */ pRequest->hashStartSrcOffsetInBytes = pRequest->cryptoStartSrcOffsetInBytes; pRequest->messageLenToHashInBytes = pRequest->messageLenToCipherInBytes; LacSymAlgChain_PrepareGCMData(pSessionDesc, pRequest->pAdditionalAuthData); } if (LAC_CIPHER_IV_SIZE_GCM_12 == pRequest->ivLenInBytes) { ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( pCurrentQatMsg->comn_hdr.serv_specif_flags, ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS); } } /* Write Request Params */ if (pSessionDesc->isCipher) { if (CPA_CY_SYM_CIPHER_ARC4 == pSessionDesc->cipherAlgorithm) { /* ARC4 does not have an IV but the field is used to store the * initial state */ pRequest->iv = pSessionDesc->cipherARC4InitialStatePhysAddr; } ICP_QAT_FW_LA_SLICE_TYPE_SET(pCurrentQatMsg->comn_hdr.serv_specif_flags, pSessionDesc->cipherSliceType); LacSymQat_CipherRequestParamsPopulate( pSessionDesc, pCurrentQatMsg, pRequest->cryptoStartSrcOffsetInBytes, pRequest->messageLenToCipherInBytes, pRequest->iv, pRequest->pIv); if (SPC_YES == pSessionDesc->singlePassState) { pCipher20ReqParams = (void *)((Cpa8U *)&(pCurrentQatMsg->serv_specif_rqpars) + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); if (isGen4) { pCipher20ReqParams->spc_aad_addr = (Cpa64U)pRequest->additionalAuthData; pCipher20ReqParams->spc_aad_sz = pSessionDesc->aadLenInBytes; pCipher20ReqParams->spc_aad_offset = 0; if (isSpCcm) pCipher20ReqParams->spc_aad_sz += LAC_CIPHER_CCM_AAD_OFFSET; pCipher20ReqParams->spc_auth_res_addr = (Cpa64U)pRequest->digestResult; pCipher20ReqParams->spc_auth_res_sz = (Cpa8U)pSessionDesc->hashResultSize; } /* For CHACHA, AES_GCM and AES_CCM single pass AAD buffer needs * alignment if aadLenInBytes is nonzero. * In case of AES-GMAC, AAD buffer passed in the src buffer. * Additionally even if aadLenInBytes is 0 for AES-CCM, * still AAD buffer need to be used, as it contains B0 block * and encoded AAD len. */ if ((0 != pSessionDesc->aadLenInBytes && CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm) || isSpCcm) { blockLen = LacSymQat_CipherBlockSizeBytesGet( pSessionDesc->cipherAlgorithm); aadDataLen = pSessionDesc->aadLenInBytes; /* In case of AES_CCM, B0 block size and 2 bytes of AAD len * encoding need to be added to total AAD data len */ if (isSpCcm) aadDataLen += LAC_CIPHER_CCM_AAD_OFFSET; if (blockLen && (aadDataLen % blockLen) != 0) { paddingLen = blockLen - (aadDataLen % blockLen); osalMemSet(&pRequest->pAdditionalAuthData[aadDataLen], 0, paddingLen); } } } } if (pSessionDesc->isAuth) { lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = &(pSessionDesc->hashStateBufferInfo); icp_qat_fw_la_auth_req_params_t *pAuthReqPars = (icp_qat_fw_la_auth_req_params_t *)((Cpa8U *)&(pCurrentQatMsg->serv_specif_rqpars) + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_AES_GCM != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm && CPA_CY_SYM_HASH_ZUC_EIA3 != pSessionDesc->hashAlgorithm) && (pHashStateBufferInfo->prefixAadSzQuadWords > 0)) { /* prefixAadSzQuadWords > 0 when there is prefix data - i.e. nested hash or HMAC no precompute cases Note partials not supported on DP api so we do not need dynamic hash state in this case */ pRequest->additionalAuthData = pHashStateBufferInfo->pDataPhys + LAC_QUADWORDS_TO_BYTES( pHashStateBufferInfo->stateStorageSzQuadWords); } /* The first 24 bytes in icp_qat_fw_la_auth_req_params_t can be * copied directly from the op request data because they share a * corresponding layout. The remaining 4 bytes are taken * from the session message template and use values preconfigured at * sessionInit (updated per request for some specific cases below) */ memcpy(pAuthReqPars, (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), ((uintptr_t) & (pAuthReqPars->u2.inner_prefix_sz) - (uintptr_t)pAuthReqPars)); if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { pAuthReqPars->hash_state_sz = LAC_BYTES_TO_QUADWORDS(pAuthReqPars->u2.aad_sz); } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm || CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm) { pAuthReqPars->hash_state_sz = LAC_BYTES_TO_QUADWORDS(pSessionDesc->aadLenInBytes); } } } CpaStatus cpaCySymDpSessionCtxGetSize( const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* All other param checks are common with trad api */ /* Check for valid pointers */ LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); #endif status = cpaCySymSessionCtxGetSize( instanceHandle, pSessionSetupData, pSessionCtxSizeInBytes); #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pSessionSetupData, (LAC_ARCH_UINT)pSessionCtxSizeInBytes, *pSessionCtxSizeInBytes); #endif return status; } CpaStatus cpaCySymDpSessionCtxGetDynamicSize( const CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, Cpa32U *pSessionCtxSizeInBytes) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* All other param checks are common with trad api */ /* Check for valid pointers */ LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); #endif status = cpaCySymSessionCtxGetDynamicSize( instanceHandle, pSessionSetupData, pSessionCtxSizeInBytes); #ifdef ICP_TRACE LAC_LOG4("Called with params (0x%lx, 0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pSessionSetupData, (LAC_ARCH_UINT)pSessionCtxSizeInBytes, *pSessionCtxSizeInBytes); #endif return status; } /** @ingroup cpaCySymDp */ CpaStatus cpaCySymDpInitSession( CpaInstanceHandle instanceHandle, const CpaCySymSessionSetupData *pSessionSetupData, CpaCySymDpSessionCtx sessionCtx) { CpaStatus status = CPA_STATUS_FAIL; sal_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pSessionSetupData, (LAC_ARCH_UINT)sessionCtx); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSessionSetupData); #endif /*ICP_PARAM_CHECK*/ pService = (sal_service_t *)instanceHandle; /* Check crypto service is running otherwise return an error */ SAL_RUNNING_CHECK(pService); status = LacSym_InitSession(instanceHandle, NULL, /* Callback */ pSessionSetupData, CPA_TRUE, /* isDPSession */ sessionCtx); return status; } CpaStatus cpaCySymDpRemoveSession(const CpaInstanceHandle instanceHandle, CpaCySymDpSessionCtx sessionCtx) { #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)sessionCtx); #endif #ifdef ICP_PARAM_CHECK /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ LAC_CHECK_INSTANCE_HANDLE(instanceHandle); /* All other param checks are common with trad api */ #endif return cpaCySymRemoveSession(instanceHandle, sessionCtx); } CpaStatus cpaCySymDpRegCbFunc(const CpaInstanceHandle instanceHandle, const CpaCySymDpCbFunc pSymDpCb) { sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pSymDpCb); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pSymDpCb); #endif SAL_RUNNING_CHECK(instanceHandle); pService->pSymDpCb = pSymDpCb; return CPA_STATUS_SUCCESS; } CpaStatus cpaCySymDpEnqueueOp(CpaCySymDpOpData *pRequest, const CpaBoolean performOpNow) { icp_qat_fw_la_bulk_req_t *pCurrentQatMsg = NULL; icp_comms_trans_handle trans_handle = NULL; lac_session_desc_t *pSessionDesc = NULL; write_ringMsgFunc_t callFunc; CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, %d)\n", (LAC_ARCH_UINT)pRequest, performOpNow); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pRequest); status = LacDp_EnqueueParamCheck(pRequest); if (CPA_STATUS_SUCCESS != status) { return status; } #endif /* Check if SAL is running in crypto data plane otherwise return an error */ SAL_RUNNING_CHECK(pRequest->instanceHandle); trans_handle = ((sal_crypto_service_t *)pRequest->instanceHandle)->trans_handle_sym_tx; pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); icp_adf_getSingleQueueAddr(trans_handle, (void **)&pCurrentQatMsg); if (NULL == pCurrentQatMsg) { /* * No space is available on the queue. */ return CPA_STATUS_RETRY; } callFunc = (write_ringMsgFunc_t)pSessionDesc->writeRingMsgFunc; LAC_CHECK_NULL_PARAM(callFunc); callFunc(pRequest, pCurrentQatMsg); pSessionDesc->u.pendingDpCbCount++; if (CPA_TRUE == performOpNow) { status = SalQatMsg_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { pSessionDesc->u.pendingDpCbCount--; return status; } } return CPA_STATUS_SUCCESS; } CpaStatus cpaCySymDpPerformOpNow(const CpaInstanceHandle instanceHandle) { icp_comms_trans_handle trans_handle = NULL; CpaStatus status; #ifdef ICP_TRACE LAC_LOG1("Called with param (0x%lx)\n", (LAC_ARCH_UINT)instanceHandle); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); trans_handle = ((sal_crypto_service_t *)instanceHandle)->trans_handle_sym_tx; if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { status = SalQatMsg_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { return status; } } return CPA_STATUS_SUCCESS; } CpaStatus cpaCySymDpEnqueueOpBatch(const Cpa32U numberRequests, CpaCySymDpOpData *pRequests[], const CpaBoolean performOpNow) { icp_qat_fw_la_bulk_req_t *pCurrentQatMsg = NULL; icp_comms_trans_handle trans_handle = NULL; lac_session_desc_t *pSessionDesc = NULL; CpaStatus status = CPA_STATUS_SUCCESS; write_ringMsgFunc_t callFunc; Cpa32U i = 0; #ifdef ICP_PARAM_CHECK sal_crypto_service_t *pService = NULL; #endif #ifdef ICP_TRACE LAC_LOG3("Called with params (%d, 0x%lx, %d)\n", numberRequests, (LAC_ARCH_UINT)pRequests, performOpNow); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pRequests); LAC_CHECK_NULL_PARAM(pRequests[0]); LAC_CHECK_NULL_PARAM(pRequests[0]->instanceHandle); pService = (sal_crypto_service_t *)(pRequests[0]->instanceHandle); if ((0 == numberRequests) || (numberRequests > pService->maxNumSymReqBatch)) { LAC_INVALID_PARAM_LOG1("The number of requests needs to be between 1 " "and %d", pService->maxNumSymReqBatch); return CPA_STATUS_INVALID_PARAM; } for (i = 0; i < numberRequests; i++) { status = LacDp_EnqueueParamCheck(pRequests[i]); if (CPA_STATUS_SUCCESS != status) { return status; } /* Check that all instance handles are the same */ if (pRequests[i]->instanceHandle != pRequests[0]->instanceHandle) { LAC_INVALID_PARAM_LOG("All instance handles should be the same " "in the requests"); return CPA_STATUS_INVALID_PARAM; } } #endif /* Check if SAL is running in crypto data plane otherwise return an error */ SAL_RUNNING_CHECK(pRequests[0]->instanceHandle); trans_handle = ((sal_crypto_service_t *)pRequests[0]->instanceHandle) ->trans_handle_sym_tx; icp_adf_getQueueMemory( trans_handle, numberRequests, (void **)&pCurrentQatMsg); if (NULL == pCurrentQatMsg) { /* * No space is available on the queue. */ return CPA_STATUS_RETRY; } for (i = 0; i < numberRequests; i++) { pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequests[i]->sessionCtx); callFunc = (write_ringMsgFunc_t)pSessionDesc->writeRingMsgFunc; callFunc(pRequests[i], pCurrentQatMsg); icp_adf_getQueueNext(trans_handle, (void **)&pCurrentQatMsg); pSessionDesc->u.pendingDpCbCount++; } if (CPA_TRUE == performOpNow) { status = SalQatMsg_updateQueueTail(trans_handle); if (CPA_STATUS_SUCCESS != status) { pSessionDesc->u.pendingDpCbCount -= numberRequests; return status; } } return CPA_STATUS_SUCCESS; } CpaStatus icp_sal_CyPollDpInstance(const CpaInstanceHandle instanceHandle, const Cpa32U responseQuota) { icp_comms_trans_handle trans_handle = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_INSTANCE_HANDLE(instanceHandle); SAL_CHECK_INSTANCE_TYPE( instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); #endif /* Check if SAL is initialised otherwise return an error */ SAL_RUNNING_CHECK(instanceHandle); trans_handle = ((sal_crypto_service_t *)instanceHandle)->trans_handle_sym_rx; return icp_adf_pollQueue(trans_handle, responseQuota); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_hash.c000066400000000000000000001052671503624047500311420ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_hash.c * * @ingroup LacHash * * Hash specific functionality ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_common.h" #include "lac_mem.h" #include "lac_sal_types.h" #include "lac_sym.h" #include "lac_sal.h" #include "lac_session.h" #include "lac_sym_hash.h" #include "lac_log.h" #include "lac_sym_qat_hash.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_cb.h" #include "lac_sync.h" #define LAC_HASH_ALG_MODE_NOT_SUPPORTED(alg, mode) \ ((((CPA_CY_SYM_HASH_KASUMI_F9 == (alg)) || \ (CPA_CY_SYM_HASH_SNOW3G_UIA2 == (alg)) || \ (CPA_CY_SYM_HASH_AES_XCBC == (alg)) || \ (CPA_CY_SYM_HASH_AES_CCM == (alg)) || \ (CPA_CY_SYM_HASH_AES_GCM == (alg)) || \ (CPA_CY_SYM_HASH_AES_GMAC == (alg)) || \ (CPA_CY_SYM_HASH_AES_CMAC == (alg)) || \ (CPA_CY_SYM_HASH_ZUC_EIA3 == (alg))) && \ (CPA_CY_SYM_HASH_MODE_AUTH != (mode))) || \ ((LAC_HASH_IS_SHA3(alg)) && (CPA_CY_SYM_HASH_MODE_NESTED == (mode)))) /**< Macro to check for valid algorithm-mode combination */ void LacSync_GenBufListVerifyCb(void *pCallbackTag, CpaStatus status, CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean opResult); /** * @ingroup LacHash * This callback function will be invoked whenever a synchronous * hash precompute operation completes. It will set the wait * queue flag for the synchronous operation. * * @param[in] pCallbackTag Opaque value provided by user. This will * be a pointer to a wait queue flag. * * @retval * None * */ STATIC void LacHash_SyncPrecomputeDoneCb(void *pCallbackTag) { LacSync_GenWakeupSyncCaller(pCallbackTag, CPA_STATUS_SUCCESS); } /** @ingroup LacHash */ CpaStatus LacHash_StatePrefixAadBufferInit( sal_service_t *pService, const CpaCySymHashSetupData *pHashSetupData, icp_qat_la_bulk_req_ftr_t *pReq, icp_qat_hw_auth_mode_t qatHashMode, Cpa8U *pHashStateBuffer, lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo) { /* set up the hash state prefix buffer info structure */ pHashStateBufferInfo->pData = pHashStateBuffer; pHashStateBufferInfo->pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64( LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), pHashStateBuffer)); if (pHashStateBufferInfo->pDataPhys == 0) { LAC_LOG_ERROR("Unable to get the physical address of " "the hash state buffer\n"); return CPA_STATUS_FAIL; } LacSymQat_HashStatePrefixAadBufferSizeGet(pReq, pHashStateBufferInfo); /* Prefix data gets copied to the hash state buffer for nested mode */ if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { LacSymQat_HashStatePrefixAadBufferPopulate( pHashStateBufferInfo, pReq, pHashSetupData->nestedModeSetupData.pInnerPrefixData, (Cpa8U)pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes, pHashSetupData->nestedModeSetupData.pOuterPrefixData, (Cpa8U)pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes); } /* For mode2 HMAC the key gets copied into both the inner and * outer prefix fields */ else if (IS_HASH_MODE_2_AUTH(qatHashMode, pHashSetupData->hashMode)) { LacSymQat_HashStatePrefixAadBufferPopulate( pHashStateBufferInfo, pReq, pHashSetupData->authModeSetupData.authKey, (Cpa8U)pHashSetupData->authModeSetupData.authKeyLenInBytes, pHashSetupData->authModeSetupData.authKey, (Cpa8U)pHashSetupData->authModeSetupData.authKeyLenInBytes); } /* else do nothing for the other cases */ return CPA_STATUS_SUCCESS; } /** @ingroup LacHash */ CpaStatus LacHash_PrecomputeDataCreate(const CpaInstanceHandle instanceHandle, CpaCySymSessionSetupData *pSessionSetup, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag, Cpa8U *pWorkingBuffer, Cpa8U *pState1, Cpa8U *pState2) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pAuthKey = NULL; Cpa32U authKeyLenInBytes = 0; CpaCySymHashAlgorithm hashAlgorithm = pSessionSetup->hashSetupData.hashAlgorithm; CpaCySymHashAuthModeSetupData *pAuthModeSetupData = &pSessionSetup->hashSetupData.authModeSetupData; LAC_ENSURE_NOT_NULL(pWorkingBuffer); /* synchronous operation */ if (NULL == callbackFn) { lac_sync_op_data_t *pSyncCallbackData = NULL; status = LacSync_CreateSyncCookie(&pSyncCallbackData); if (CPA_STATUS_SUCCESS == status) { status = LacHash_PrecomputeDataCreate( instanceHandle, pSessionSetup, LacHash_SyncPrecomputeDoneCb, /* wait queue condition from sync cookie */ pSyncCallbackData, pWorkingBuffer, pState1, pState2); } else { return status; } if (CPA_STATUS_SUCCESS == status) { CpaStatus syncStatus = CPA_STATUS_SUCCESS; syncStatus = LacSync_WaitForCallback(pSyncCallbackData, LAC_SYM_SYNC_CALLBACK_TIMEOUT, &status, NULL); /* If callback doesn't come back */ if (CPA_STATUS_SUCCESS != syncStatus) { LAC_LOG_ERROR( "callback functions for precomputes did not return"); status = syncStatus; } } else { /* As the Request was not sent the Callback will never * be called, so need to indicate that we're finished * with cookie so it can be destroyed. */ LacSync_SetSyncCookieComplete(pSyncCallbackData); } LacSync_DestroySyncCookie(&pSyncCallbackData); return status; } /* set up convenience pointers */ pAuthKey = pAuthModeSetupData->authKey; authKeyLenInBytes = pAuthModeSetupData->authKeyLenInBytes; /* Pre-compute data state pointers must already be set up * by LacSymQat_HashSetupBlockInit() */ /* state1 is not allocated for AES XCBC/CCM/GCM/Kasumi/UIA2 * so for these algorithms set state2 only */ if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) { status = LacSymHash_AesECBPreCompute(instanceHandle, hashAlgorithm, authKeyLenInBytes, pAuthKey, pWorkingBuffer, pState2, callbackFn, pCallbackTag); } else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) { /* First, copy the original key to pState2 */ memcpy(pState2, pAuthKey, authKeyLenInBytes); /* Then precompute */ if (authKeyLenInBytes == ICP_QAT_HW_AES_128_KEY_SZ) { status = LacSymHash_AesECBPreCompute(instanceHandle, hashAlgorithm, authKeyLenInBytes, pAuthKey, pWorkingBuffer, pState2, callbackFn, pCallbackTag); } else { callbackFn(pCallbackTag); } } else if (CPA_CY_SYM_HASH_AES_CCM == hashAlgorithm) { /* * The Inner Hash Initial State2 block is 32 bytes long. * Therefore, for keys bigger than 128 bits (16 bytes), * there is no space for 16 zeroes. */ if (pSessionSetup->cipherSetupData.cipherKeyLenInBytes == ICP_QAT_HW_AES_128_KEY_SZ) { /* * The Inner Hash Initial State2 block must contain K * (the cipher key) and 16 zeroes which will be replaced with * EK(Ctr0) by the QAT-ME. */ /* write the auth key which for CCM is equivalent to cipher key */ osalMemCopy(pState2, pSessionSetup->cipherSetupData.pCipherKey, pSessionSetup->cipherSetupData.cipherKeyLenInBytes); /* initialize remaining buffer space to all zeroes */ LAC_OS_BZERO(pState2 + pSessionSetup->cipherSetupData.cipherKeyLenInBytes, ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ); } /* There is no request sent to the QAT for this operation, * so just invoke the user's callback directly to signal * completion of the precompute */ callbackFn(pCallbackTag); } else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm || CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { /* * The Inner Hash Initial State2 block contains the following * H (the Galois Hash Multiplier) * len(A) (the length of A), (length before padding) * 16 zeroes which will be replaced with EK(Ctr0) by the QAT. */ /* Memset state2 to 0 */ LAC_OS_BZERO(pState2, ICP_QAT_HW_GALOIS_H_SZ + ICP_QAT_HW_GALOIS_LEN_A_SZ + ICP_QAT_HW_GALOIS_E_CTR0_SZ); /* write H (the Galois Hash Multiplier) where H = E(K, 0...0) * This will only write bytes 0-15 of pState2 */ status = LacSymHash_AesECBPreCompute( instanceHandle, hashAlgorithm, pSessionSetup->cipherSetupData.cipherKeyLenInBytes, pSessionSetup->cipherSetupData.pCipherKey, pWorkingBuffer, pState2, callbackFn, pCallbackTag); if (CPA_STATUS_SUCCESS == status) { /* write len(A) (the length of A) into bytes 16-19 of pState2 * in big-endian format. This field is 8 bytes */ *(Cpa32U *)&pState2[ICP_QAT_HW_GALOIS_H_SZ] = LAC_MEM_WR_32(pAuthModeSetupData->aadLenInBytes); } } else if (CPA_CY_SYM_HASH_KASUMI_F9 == hashAlgorithm) { Cpa32U wordIndex = 0; Cpa32U *pTempKey = (Cpa32U *)(pState2 + authKeyLenInBytes); /* * The Inner Hash Initial State2 block must contain IK * (Initialisation Key), followed by IK XOR-ed with KM * (Key Modifier): IK||(IK^KM). */ /* write the auth key */ memcpy(pState2, pAuthKey, authKeyLenInBytes); /* initialise temp key with auth key */ memcpy(pTempKey, pAuthKey, authKeyLenInBytes); /* XOR Key with KASUMI F9 key modifier at 4 bytes level */ for (wordIndex = 0; wordIndex < LAC_BYTES_TO_LONGWORDS(authKeyLenInBytes); wordIndex++) { pTempKey[wordIndex] ^= LAC_HASH_KASUMI_F9_KEY_MODIFIER_4_BYTES; } /* There is no request sent to the QAT for this operation, * so just invoke the user's callback directly to signal * completion of the precompute */ callbackFn(pCallbackTag); } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) { /* * The Inner Hash Initial State2 should be all zeros */ LAC_OS_BZERO(pState2, ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ); /* There is no request sent to the QAT for this operation, * so just invoke the user's callback directly to signal * completion of the precompute */ callbackFn(pCallbackTag); } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm) { /* * The Inner Hash Initial State2 should contain the key * and zero the rest of the state. */ if (authKeyLenInBytes == ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) { LAC_OS_BZERO(pState2, ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ); } else { LAC_OS_BZERO(pState2, ICP_QAT_HW_ZUC_256_STATE2_SZ); } memcpy(pState2, pAuthKey, authKeyLenInBytes); /* There is no request sent to the QAT for this operation, * so just invoke the user's callback directly to signal * completion of the precompute */ callbackFn(pCallbackTag); } else if (CPA_CY_SYM_HASH_POLY == hashAlgorithm) { /* There is no request sent to the QAT for this operation, * so just invoke the user's callback directly to signal * completion of the precompute */ callbackFn(pCallbackTag); } else /* For Hmac Precomputes */ { status = LacSymHash_HmacPreComputes(instanceHandle, hashAlgorithm, authKeyLenInBytes, pAuthKey, pWorkingBuffer, pState1, pState2, callbackFn, pCallbackTag); } return status; } #ifdef ICP_PARAM_CHECK /** @ingroup LacHash */ CpaStatus LacHash_HashContextCheck(CpaInstanceHandle instanceHandle, const CpaCySymHashSetupData *pHashSetupData) { lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; lac_sym_qat_hash_alg_info_t *pOuterHashAlgInfo = NULL; CpaCySymCapabilitiesInfo capInfo; LAC_ENSURE_NOT_NULL(pHashSetupData); /*Protect against value of hash outside the bitmap*/ if (pHashSetupData->hashAlgorithm >= CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) { LAC_INVALID_PARAM_LOG("hashAlgorithm"); return CPA_STATUS_INVALID_PARAM; } SalCtrl_CySymQueryCapabilities(instanceHandle, &capInfo); if (!CPA_BITMAP_BIT_TEST(capInfo.hashes, pHashSetupData->hashAlgorithm) && pHashSetupData->hashAlgorithm != CPA_CY_SYM_HASH_AES_CBC_MAC) { LAC_INVALID_PARAM_LOG("hashAlgorithm"); return CPA_STATUS_INVALID_PARAM; } switch (pHashSetupData->hashMode) { case CPA_CY_SYM_HASH_MODE_PLAIN: case CPA_CY_SYM_HASH_MODE_AUTH: break; case CPA_CY_SYM_HASH_MODE_NESTED: break; default: { LAC_INVALID_PARAM_LOG("hashMode"); return CPA_STATUS_INVALID_PARAM; } } if (LAC_HASH_ALG_MODE_NOT_SUPPORTED(pHashSetupData->hashAlgorithm, pHashSetupData->hashMode)) { LAC_UNSUPPORTED_PARAM_LOG("hashAlgorithm and hashMode combination"); return CPA_STATUS_UNSUPPORTED; } LacSymQat_HashAlgLookupGet( instanceHandle, pHashSetupData->hashAlgorithm, &pHashAlgInfo, pHashSetupData->authModeSetupData.authKeyLenInBytes, pHashSetupData->digestResultLenInBytes); /* note: nested hash mode checks digest length against outer algorithm */ if ((CPA_CY_SYM_HASH_MODE_PLAIN == pHashSetupData->hashMode) || (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode)) { /* Check Digest Length is permitted by the algorithm */ if ((0 == pHashSetupData->digestResultLenInBytes) || (pHashSetupData->digestResultLenInBytes > pHashAlgInfo->digestLength)) { LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } if (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode) { if (CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm || CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) { Cpa32U aadDataSize = 0; /* RFC 4106: Implementations MUST support a full-length 16-octet * ICV, and MAY support 8 or 12 octet ICVs, and MUST NOT support * other ICV lengths. */ if ((pHashSetupData->digestResultLenInBytes != LAC_HASH_AES_GCM_ICV_SIZE_8) && (pHashSetupData->digestResultLenInBytes != LAC_HASH_AES_GCM_ICV_SIZE_12) && (pHashSetupData->digestResultLenInBytes != LAC_HASH_AES_GCM_ICV_SIZE_16)) { LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* ensure aadLen is within maximum limit imposed by QAT */ aadDataSize = pHashSetupData->authModeSetupData.aadLenInBytes; /* round the aad size to the multiple of GCM hash block size. */ aadDataSize = LAC_ALIGN_POW2_ROUNDUP(aadDataSize, LAC_HASH_AES_GCM_BLOCK_SIZE); if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX && CPA_CY_SYM_HASH_AES_GMAC != pHashSetupData->hashAlgorithm) { LAC_INVALID_PARAM_LOG("aadLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) { Cpa32U aadDataSize = 0; /* RFC 3610: Valid values are 4, 6, 8, 10, 12, 14, and 16 octets */ if ((pHashSetupData->digestResultLenInBytes >= LAC_HASH_AES_CCM_ICV_SIZE_MIN) && (pHashSetupData->digestResultLenInBytes <= LAC_HASH_AES_CCM_ICV_SIZE_MAX)) { if ((pHashSetupData->digestResultLenInBytes & 0x01) != 0) { LAC_INVALID_PARAM_LOG( "digestResultLenInBytes must be a multiple of 2"); return CPA_STATUS_INVALID_PARAM; } } else { LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* ensure aadLen is within maximum limit imposed by QAT */ /* at the beginning of the buffer there is B0 block */ aadDataSize = LAC_HASH_AES_CCM_BLOCK_SIZE; /* then, if there is some 'a' data, the buffer will store encoded * length of 'a' and 'a' itself */ if (pHashSetupData->authModeSetupData.aadLenInBytes > 0) { /* as the QAT API puts the requirement on the * pAdditionalAuthData not to be bigger than 240 bytes then we * just need 2 bytes to store encoded length of 'a' */ aadDataSize += sizeof(Cpa16U); aadDataSize += pHashSetupData->authModeSetupData.aadLenInBytes; } /* round the aad size to the multiple of CCM block size.*/ aadDataSize = LAC_ALIGN_POW2_ROUNDUP(aadDataSize, LAC_HASH_AES_CCM_BLOCK_SIZE); if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) { LAC_INVALID_PARAM_LOG("aadLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_KASUMI_F9 == pHashSetupData->hashAlgorithm) { /* QAT-FW only supports 128 bit Integrity Key size for Kasumi f9 * Ref: 3GPP TS 35.201 version 7.0.0 Release 7 */ if (pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_KASUMI_KEY_SZ) { LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) { /* QAT-FW only supports 128 bits Integrity Key size for Snow3g */ if (pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) { LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* For Snow3g hash aad field contains IV - it needs to be 16 * bytes long */ if (pHashSetupData->authModeSetupData.aadLenInBytes != ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ) { LAC_INVALID_PARAM_LOG("aadLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_AES_XCBC == pHashSetupData->hashAlgorithm || CPA_CY_SYM_HASH_AES_CBC_MAC == pHashSetupData->hashAlgorithm) { /* ensure auth key len is valid (128-bit keys supported) */ if ((pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_AES_128_KEY_SZ)) { LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_AES_CMAC == pHashSetupData->hashAlgorithm) { /* ensure auth key len is valid (128/192/256-bit keys supported) */ if ((pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_AES_128_KEY_SZ) && (pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_AES_192_KEY_SZ) && (pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_AES_256_KEY_SZ)) { LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm) { /* QAT-FW only supports 128/256 bits Integrity Key size for ZUC */ if ((pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) && (pHashSetupData->authModeSetupData.authKeyLenInBytes != ICP_QAT_HW_ZUC_256_KEY_SZ)) { LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } /* For ZUC EIA3 hash aad field contains IV - it needs to be 16 * bytes long */ if ((pHashSetupData->authModeSetupData.aadLenInBytes != ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) && (pHashSetupData->authModeSetupData.aadLenInBytes != ICP_QAT_HW_ZUC_256_IV_SZ)) { LAC_INVALID_PARAM_LOG("aadLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } else if (CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm) { if (pHashSetupData->digestResultLenInBytes != ICP_QAT_HW_SPC_CTR_SZ) { LAC_INVALID_PARAM_LOG("Digest Length for CCP"); return CPA_STATUS_INVALID_PARAM; } if (pHashSetupData->authModeSetupData.aadLenInBytes > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) { LAC_INVALID_PARAM_LOG("AAD Length for CCP"); return CPA_STATUS_INVALID_PARAM; } } else { /* The key size must be less than or equal the block length */ if (pHashSetupData->authModeSetupData.authKeyLenInBytes > pHashAlgInfo->blockLength) { LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); return CPA_STATUS_INVALID_PARAM; } } /* when the key size is greater than 0 check pointer is not null */ if (CPA_CY_SYM_HASH_AES_CCM != pHashSetupData->hashAlgorithm && CPA_CY_SYM_HASH_AES_GCM != pHashSetupData->hashAlgorithm && pHashSetupData->authModeSetupData.authKeyLenInBytes > 0) { LAC_CHECK_NULL_PARAM(pHashSetupData->authModeSetupData.authKey); } } else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { if (!CPA_BITMAP_BIT_TEST( capInfo.hashes, pHashSetupData->nestedModeSetupData.outerHashAlgorithm)) { LAC_INVALID_PARAM_LOG("outerHashAlgorithm"); return CPA_STATUS_INVALID_PARAM; } if (LAC_HASH_ALG_MODE_NOT_SUPPORTED( pHashSetupData->nestedModeSetupData.outerHashAlgorithm, pHashSetupData->hashMode)) { LAC_INVALID_PARAM_LOG( "outerHashAlgorithm and hashMode combination"); return CPA_STATUS_INVALID_PARAM; } LacSymQat_HashAlgLookupGet( instanceHandle, pHashSetupData->nestedModeSetupData.outerHashAlgorithm, &pOuterHashAlgInfo, pHashSetupData->authModeSetupData.authKeyLenInBytes, pHashSetupData->digestResultLenInBytes); /* Check Digest Length is permitted by the algorithm */ if ((0 == pHashSetupData->digestResultLenInBytes) || (pHashSetupData->digestResultLenInBytes > pOuterHashAlgInfo->digestLength)) { LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); return CPA_STATUS_INVALID_PARAM; } if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes > LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) { LAC_INVALID_PARAM_LOG("innerPrefixLenInBytes"); return CPA_STATUS_INVALID_PARAM; } if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes > 0) { LAC_CHECK_NULL_PARAM( pHashSetupData->nestedModeSetupData.pInnerPrefixData); } if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes > LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) { LAC_INVALID_PARAM_LOG("outerPrefixLenInBytes"); return CPA_STATUS_INVALID_PARAM; } if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes > 0) { LAC_CHECK_NULL_PARAM( pHashSetupData->nestedModeSetupData.pOuterPrefixData); } } return CPA_STATUS_SUCCESS; } /** @ingroup LacHash */ CpaStatus LacHash_PerformParamCheck(CpaInstanceHandle instanceHandle, lac_session_desc_t *pSessionDesc, const CpaCySymOpData *pOpData, Cpa64U srcPktSize, const CpaBoolean *pVerifyResult) { CpaStatus status = CPA_STATUS_SUCCESS; lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; CpaBoolean digestIsAppended = pSessionDesc->digestIsAppended; CpaBoolean digestVerify = pSessionDesc->digestVerify; CpaCySymOp symOperation = pSessionDesc->symOperation; CpaCySymHashAlgorithm hashAlgorithm = pSessionDesc->hashAlgorithm; /* digestVerify and digestIsAppended on Hash-Only operation not supported */ if (digestIsAppended && digestVerify && (CPA_CY_SYM_OP_HASH == symOperation)) { LAC_INVALID_PARAM_LOG("digestVerify and digestIsAppended set " "on Hash-Only operation is not supported"); return CPA_STATUS_INVALID_PARAM; } /* check the digest result pointer */ if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) && !digestIsAppended && (NULL == pOpData->pDigestResult)) { LAC_INVALID_PARAM_LOG("pDigestResult is NULL"); return CPA_STATUS_INVALID_PARAM; } /* * Check if the pVerifyResult pointer is not null for hash operation when * the packet is the last one and user has set verifyDigest flag * Also, this is only needed for symchronous operation, so check if the * callback pointer is the internal synchronous one rather than a user- * supplied one. */ if ((CPA_TRUE == digestVerify) && (CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) && (LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb)) { if (NULL == pVerifyResult) { LAC_INVALID_PARAM_LOG("Null pointer pVerifyResult for hash op"); return CPA_STATUS_INVALID_PARAM; } } /* verify start offset + messageLenToDigest is inside the source packet. * this also verifies that the start offset is inside the packet * Note: digest is specified as a pointer therefore it can be * written anywhere so we cannot check for this been inside a buffer * CCM/GCM specify the auth region using just the cipher params as this * region is the same for auth and cipher. It is not checked here */ if ((CPA_CY_SYM_HASH_AES_CCM == hashAlgorithm) || (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm)) { /* ensure AAD data pointer is non-NULL if AAD len > 0 */ if ((pSessionDesc->aadLenInBytes > 0) && (NULL == pOpData->pAdditionalAuthData)) { LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL"); return CPA_STATUS_INVALID_PARAM; } } else { if ((pOpData->hashStartSrcOffsetInBytes + pOpData->messageLenToHashInBytes) > srcPktSize) { LAC_INVALID_PARAM_LOG( "hashStartSrcOffsetInBytes + " "messageLenToHashInBytes > Src Buffer Packet Length"); return CPA_STATUS_INVALID_PARAM; } } /* For Snow3g & ZUC hash pAdditionalAuthData field * of OpData should contain IV */ if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) || (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm)) { if (NULL == pOpData->pAdditionalAuthData) { LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL"); return CPA_STATUS_INVALID_PARAM; } } /* partial packets need to be multiples of the algorithm block size in hash * only mode (except for final partial packet) */ if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) && (CPA_CY_SYM_OP_HASH == symOperation)) { LacSymQat_HashAlgLookupGet(instanceHandle, pSessionDesc->hashAlgorithm, &pHashAlgInfo, pSessionDesc->authKeyLenInBytes, pSessionDesc->hashResultSize); /* check if the message is a multiple of the block size. */ if (pOpData->messageLenToHashInBytes % pHashAlgInfo->blockLength != 0) { LAC_INVALID_PARAM_LOG2("message(%d) not block-size(%d) multiple", pOpData->messageLenToHashInBytes, pHashAlgInfo->blockLength); return CPA_STATUS_INVALID_PARAM; } } return status; } #endif lac_sym_hash_hw_precomputes.c000066400000000000000000000567641503624047500342160ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_hash_hw_precomputes.c * * @ingroup LacHashDefs * * Hash Precomputes ***************************************************************************/ /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "cpa_cy_sym.h" #include "Osal.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_debug.h" #include "icp_qat_fw_la.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_mem.h" #include "lac_sym.h" #include "lac_log.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "icp_accel_devices.h" #include "lac_sym_hash_defs.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "lac_session.h" #include "lac_sym_hash.h" #include "lac_sym_qat.h" #include "lac_sym_qat_hash.h" #include "lac_sym_qat_cipher.h" #include "lac_sym_hash_precomputes.h" /** ***************************************************************************** * @ingroup LacHashDefs * Definition of the callback function for processing responses for * precompute operations * * @description * This callback, which is registered with the common symmetric response * message handler, It is invoked to process precompute response messages * from the QAT. * * @param[in] lacCmdId ID of the symmetric QAT command of the request * message * @param[in] pOpaqueData pointer to opaque data in the request message * @param[in] cmnRespFlags Flags set by QAT to indicate response status * * @return None *****************************************************************************/ STATIC void LacSymHash_PrecompCbFunc(icp_qat_fw_la_cmd_id_t lacCmdId, void *pOpaqueData, icp_qat_fw_comn_flags cmnRespFlags) { lac_sym_hash_precomp_op_data_t *pPrecompOpData = (lac_sym_hash_precomp_op_data_t *)pOpaqueData; lac_sym_hash_precomp_op_t *pOpStatus = NULL; lac_session_desc_t *pSessionDesc = NULL; Cpa8U k1[LAC_HASH_CMAC_BLOCK_SIZE], k2[LAC_HASH_CMAC_BLOCK_SIZE]; Cpa8U *ptr = NULL; size_t i = 0; if (NULL == pPrecompOpData) { LAC_LOG_ERROR("Opaque data for precompute is NULL"); return; } pOpStatus = pPrecompOpData->pOpStatus; pSessionDesc = (lac_session_desc_t *)pOpStatus->pCallbackTag; if (LAC_SYM_HASH_PRECOMP_HMAC == pPrecompOpData->opType) { lac_sym_hash_hmac_precomp_qat_t *pHmacQatData = &pPrecompOpData->u.hmacQatData; /* Copy the hash state */ memcpy(pPrecompOpData->pState, (Cpa8U *)pHmacQatData->hashStateStorage + sizeof(icp_qat_hw_auth_counter_t), pPrecompOpData->stateSize); } else { lac_sym_hash_aes_precomp_qat_t *pAesQatData = &pPrecompOpData->u.aesQatData; if (pSessionDesc->hashAlgorithm == CPA_CY_SYM_HASH_AES_CMAC && pSessionDesc->symOperation == CPA_CY_SYM_OP_HASH) { /* Use K0 (stored in pAesQatData->data) to derive K1 and K2. * When you have the derived keys, copy them to * pPrecompOpData->pState but remember that at the beginning * is original key */ /* Calculating K1 */ for (i = 0, ptr = pAesQatData->data; i < LAC_HASH_CMAC_BLOCK_SIZE; i++, ptr++) { k1[i] = (*ptr) << 1; if (i != 0) { k1[i - 1] |= (*ptr) >> (LAC_NUM_BITS_IN_BYTE - 1); } if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { /* If msb of pAesQatData->data is set xor with RB. Because only the final byte of RB is non-zero this is all we need to xor */ if ((pAesQatData->data[0]) & LAC_SYM_HASH_MSBIT_MASK) { k1[i] ^= LAC_SYM_AES_CMAC_RB_128; } } } /* Calculating K2 */ for (i = 0; i < LAC_HASH_CMAC_BLOCK_SIZE; i++) { k2[i] = (k1[i]) << 1; if (i != 0) { k2[i - 1] |= (k1[i]) >> (LAC_NUM_BITS_IN_BYTE - 1); } if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { /* If msb of k1 is set xor last byte with RB */ if (k1[0] & LAC_SYM_HASH_MSBIT_MASK) { k2[i] ^= LAC_SYM_AES_CMAC_RB_128; } } } /* Now, when we have K1 & K2 lets copy them to the state2 */ ptr = pPrecompOpData->pState + LAC_HASH_CMAC_BLOCK_SIZE; memcpy(ptr, k1, LAC_HASH_CMAC_BLOCK_SIZE); ptr += LAC_HASH_CMAC_BLOCK_SIZE; memcpy(ptr, k2, LAC_HASH_CMAC_BLOCK_SIZE); } else { memcpy(pPrecompOpData->pState, pAesQatData->data, pPrecompOpData->stateSize); } } /* Check if there are any more pending requests by testing for opsPending * for 0. If there aren't then we can signal to the user that we're done */ if (CPA_FALSE != osalAtomicDecAndTest(&(pOpStatus->opsPending))) { pOpStatus->callbackFn(pOpStatus->pCallbackTag); } } CpaStatus LacSymHash_HmacPrecompInit(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; icp_qat_fw_auth_cd_ctrl_hdr_t *pContentDesc = NULL; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP, LacSymHash_PrecompCbFunc); status = LAC_OS_MALLOC(&(pService->ppHmacContentDesc), (LAC_HASH_ALG_END + 1) * sizeof(Cpa8U *)); LAC_CHECK_STATUS(status); for (i = CPA_CY_SYM_HASH_MD5; i <= CPA_CY_SYM_HASH_SHA512; i++) { pContentDesc = NULL; pHashAlgInfo = NULL; LacSymQat_HashAlgLookupGet(instanceHandle, i, &pHashAlgInfo, LAC_SYM_HASH_DEFAULT_AUTHKEY_LENS, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); status = LAC_OS_CAMALLOC(&pContentDesc, LAC_SYM_QAT_MAX_HASH_SETUP_BLK_SZ, LAC_64BYTE_ALIGNMENT, pService->nodeAffinity); if (CPA_STATUS_SUCCESS == status) { pService->ppHmacContentDesc[i] = (Cpa8U *)pContentDesc; } else { break; } } if (CPA_STATUS_SUCCESS != status) { for (i = CPA_CY_SYM_HASH_MD5; i <= CPA_CY_SYM_HASH_SHA512; i++) { LAC_OS_CAFREE(pService->ppHmacContentDesc[i]); } LAC_OS_FREE(pService->ppHmacContentDesc); } return status; } void LacSymHash_HmacPrecompShutdown(CpaInstanceHandle instanceHandle) { Cpa32U i = 0; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; if (NULL != pService->ppHmacContentDesc) { for (i = CPA_CY_SYM_HASH_MD5; i <= CPA_CY_SYM_HASH_SHA512; i++) { LAC_OS_CAFREE(pService->ppHmacContentDesc[i]); } LAC_OS_FREE(pService->ppHmacContentDesc); } } /** ******************************************************************************* * @ingroup LacHashDefs * Perform single hash precompute operation for HMAC * * @description * This function builds up a request and sends it to the QAT for a single * hmac precompute operation. * * @param[in] instanceHandle Instance Handle * @param[in] hashAlgorithm Hash Algorithm * @param[in] pHashOpData Operation data used for a single hmac * precompute operation for a session * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_RETRY Retry the operation. * @retval CPA_STATUS_FAIL Operation Failed * *****************************************************************************/ STATIC CpaStatus LacSymHash_HmacPreCompute(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, lac_sym_hash_precomp_op_data_t *pHashOpData) { CpaStatus status = CPA_STATUS_SUCCESS; icp_buffer_list_desc_t *pBufferListDesc = NULL; icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; Cpa64U srcAddrPhys = 0; lac_sym_qat_hash_state_buffer_info_t hashStateBufferInfo = {0}; icp_qat_fw_la_bulk_req_t bulkMsg; Cpa64U hashReqParamsPhys = 0; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; /* Convenience pointer */ lac_sym_hash_hmac_precomp_qat_t *pHmacQatData = &pHashOpData->u.hmacQatData; LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, LAC_SYM_HASH_DEFAULT_AUTHKEY_LENS, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); hashStateBufferInfo.pData = pHmacQatData->hashStateStorage; hashStateBufferInfo.pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pHmacQatData->hashStateStorage)); if (hashStateBufferInfo.pDataPhys == 0) { LAC_LOG_ERROR("Unable to get the physical address of " "the hashStateStorage\n"); return CPA_STATUS_FAIL; } hashStateBufferInfo.stateStorageSzQuadWords = LAC_BYTES_TO_QUADWORDS(sizeof(icp_qat_hw_auth_counter_t) + LAC_ALIGN_POW2_ROUNDUP(pHashAlgInfo->stateSize, LAC_QUAD_WORD_IN_BYTES)); hashStateBufferInfo.prefixAadSzQuadWords = 0; pBufferListDesc = (icp_buffer_list_desc_t *)pHmacQatData->bufferDesc; pBufferListDesc->numBuffers = 1; pCurrFlatBufDesc = (icp_flat_buffer_desc_t *)(pBufferListDesc->phyBuffers); pCurrFlatBufDesc->dataLenInBytes = pHashAlgInfo->blockLength; pCurrFlatBufDesc->phyBuffer = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pHmacQatData->data)); if (pCurrFlatBufDesc->phyBuffer == 0) { LAC_LOG_ERROR("Unable to get the physical address of " "the HMAC data\n"); return CPA_STATUS_FAIL; } srcAddrPhys = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pBufferListDesc)); if (srcAddrPhys == 0) { LAC_LOG_ERROR("Unable to get the physical address of " "the source buffer\n"); return CPA_STATUS_FAIL; } pHashOpData->pInstance = pService; hashReqParamsPhys = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, &(pHmacQatData->hashReqParams)); if (hashReqParamsPhys == 0) { LAC_LOG_ERROR("Unable to get the physical address of the hash request" " params\n"); return CPA_STATUS_FAIL; } /* Send to QAT */ status = SalQatMsg_transPutMsg(pService->trans_handle_sym_tx, (void *)&(bulkMsg), LAC_QAT_SYM_REQ_SZ_LW, LAC_LOG_MSG_SYMCYBULK, NULL); return status; } CpaStatus LacSymHash_HmacPreComputes(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLenInBytes, Cpa8U *pAuthKey, Cpa8U *pWorkingMemory, Cpa8U *pState1, Cpa8U *pState2, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag) { CpaStatus status = CPA_STATUS_SUCCESS; /* Memory is carved up for pHmacIpadOpData and for pHmacOpadOpData * one after another. As the structure size is a multiple of 8, if the * first one is aligned on an 8 byte boundary, so too will the second * structure. The pOpStatus structure is carved up just after these two * structures and has no alignment constraints. Pointer arithmetic is * used to carve the memory up. */ lac_sym_hash_precomp_op_data_t *pHmacIpadOpData = (lac_sym_hash_precomp_op_data_t *)pWorkingMemory; lac_sym_hash_precomp_op_data_t *pHmacOpadOpData = pHmacIpadOpData + 1; lac_sym_hash_precomp_op_t *pOpStatus = (lac_sym_hash_precomp_op_t *)(pHmacOpadOpData + 1); /* Convenience pointers */ lac_sym_hash_hmac_precomp_qat_t *pHmacIpadQatData = &pHmacIpadOpData->u.hmacQatData; lac_sym_hash_hmac_precomp_qat_t *pHmacOpadQatData = &pHmacOpadOpData->u.hmacQatData; lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; Cpa32U wordIndex = 0; Cpa32U padLenBytes = 0; LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, authKeyLenInBytes, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); /* Initialise opsPending to the number of operations * needed to complete this precompute */ osalAtomicSet(2, &(pOpStatus->opsPending)); pOpStatus->callbackFn = callbackFn; pOpStatus->pCallbackTag = pCallbackTag; pHmacIpadOpData->opType = LAC_SYM_HASH_PRECOMP_HMAC; pHmacIpadOpData->pOpStatus = pOpStatus; pHmacIpadOpData->pState = pState1; pHmacIpadOpData->stateSize = pHashAlgInfo->stateSize; pHmacOpadOpData->opType = LAC_SYM_HASH_PRECOMP_HMAC; pHmacOpadOpData->pOpStatus = pOpStatus; pHmacOpadOpData->pState = pState2; pHmacOpadOpData->stateSize = pHashAlgInfo->stateSize; /* Copy HMAC key into buffers */ if (authKeyLenInBytes > 0) { memcpy(pHmacIpadQatData->data, pAuthKey, authKeyLenInBytes); memcpy(pHmacOpadQatData->data, pAuthKey, authKeyLenInBytes); } padLenBytes = pHashAlgInfo->blockLength - authKeyLenInBytes; /* Clear the remaining buffer space */ if (padLenBytes > 0) { LAC_OS_BZERO(pHmacIpadQatData->data + authKeyLenInBytes, padLenBytes); LAC_OS_BZERO(pHmacOpadQatData->data + authKeyLenInBytes, padLenBytes); } /* XOR Key with IPAD at 4-byte level */ for (wordIndex = 0; wordIndex < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->blockLength); wordIndex++) { Cpa32U *pIpadData = ((Cpa32U *)pHmacIpadQatData->data) + wordIndex; Cpa32U *pOpadData = ((Cpa32U *)pHmacOpadQatData->data) + wordIndex; *pIpadData ^= LAC_HASH_IPAD_4_BYTES; *pOpadData ^= LAC_HASH_OPAD_4_BYTES; } status = LacSymHash_HmacPreCompute( instanceHandle, hashAlgorithm, pHmacIpadOpData); if (CPA_STATUS_SUCCESS == status) { status = LacSymHash_HmacPreCompute( instanceHandle, hashAlgorithm, pHmacOpadOpData); } return status; } CpaStatus LacSymHash_AesECBPreCompute(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLenInBytes, Cpa8U *pAuthKey, Cpa8U *pWorkingMemory, Cpa8U *pState, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag) { CpaStatus status = CPA_STATUS_SUCCESS; /* Carve up memory for the following structures: */ /* Memory is user supplied via session memory */ lac_sym_hash_precomp_op_data_t *pAesOpData = (lac_sym_hash_precomp_op_data_t *)pWorkingMemory; lac_sym_hash_precomp_op_t *pOpStatus = (lac_sym_hash_precomp_op_t *)(pAesOpData + 1); /* Convenience pointer */ lac_sym_hash_aes_precomp_qat_t *pAesQatData = &pAesOpData->u.aesQatData; icp_buffer_list_desc_t *pBufferListDesc = NULL; icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; icp_qat_fw_la_bulk_req_t bulkMsg; Cpa64U srcAddrPhys = 0; Cpa32U stateSize = 0; Cpa64U cipherRequestParamPhys = 0; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) { lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, authKeyLenInBytes, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); stateSize = pHashAlgInfo->stateSize; memcpy(pAesQatData->data, pHashAlgInfo->initState, stateSize); } else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) { lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, authKeyLenInBytes, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); /* Original state size includes K, K1 and K2 which are of equal length. * For precompute state size is only of the length of K which is equal * to the block size for CPA_CY_SYM_HASH_AES_CMAC. */ stateSize = LAC_HASH_CMAC_BLOCK_SIZE; memcpy(pAesQatData->data, pHashAlgInfo->initState, stateSize); } else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm) { stateSize = ICP_QAT_HW_GALOIS_H_SZ; LAC_OS_BZERO(pAesQatData->data, stateSize); } else { return CPA_STATUS_INVALID_PARAM; } /* Initialise opsPending to the number of operations * needed to complete this precompute */ osalAtomicSet(1, &(pOpStatus->opsPending)); pOpStatus->callbackFn = callbackFn; pOpStatus->pCallbackTag = pCallbackTag; pAesOpData->opType = LAC_SYM_HASH_PRECOMP_AES_ECB; pAesOpData->pOpStatus = pOpStatus; pAesOpData->stateSize = stateSize; pAesOpData->pState = pState; /* Key length must not exceed the max supported AES key length */ if (authKeyLenInBytes > ICP_QAT_HW_AES_256_KEY_SZ) { LAC_INVALID_PARAM_LOG("authKeyLenInBytes exceeds max supported size"); return CPA_STATUS_INVALID_PARAM; } pBufferListDesc = (icp_buffer_list_desc_t *)pAesQatData->bufferDesc; pBufferListDesc->numBuffers = 1; pCurrFlatBufDesc = (icp_flat_buffer_desc_t *)(pBufferListDesc->phyBuffers); pCurrFlatBufDesc->dataLenInBytes = stateSize; pCurrFlatBufDesc->phyBuffer = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pAesQatData->data)); if (pCurrFlatBufDesc->phyBuffer == 0) { LAC_LOG_ERROR("Unable to get the physical address of pAesQatData\n"); return CPA_STATUS_FAIL; } srcAddrPhys = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, pBufferListDesc)); if (srcAddrPhys == 0) { LAC_LOG_ERROR( "Unable to get the physical address of the source buffer\n"); return CPA_STATUS_FAIL; } pAesOpData->pInstance = pService; cipherRequestParamPhys = LAC_OS_VIRT_TO_PHYS_EXTERNAL( pService->generic_service_info, &pAesQatData->cipherReqParams); if (cipherRequestParamPhys == 0) { LAC_LOG_ERROR("Unable to get the physical address of the cipher" " request parameter\n"); return CPA_STATUS_FAIL; } /* Send to QAT */ status = SalQatMsg_transPutMsg(pService->trans_handle_sym_tx, (void *)&(bulkMsg), LAC_QAT_SYM_REQ_SZ_LW, LAC_LOG_MSG_SYMCYBULK, NULL); return status; } lac_sym_hash_sw_precomputes.c000066400000000000000000000364631503624047500342230ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_hash_sw_precomputes.c * * @ingroup LacHashDefs * * Hash Software ***************************************************************************/ /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "cpa_cy_sym.h" #include "Osal.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_debug.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_mem.h" #include "lac_sym.h" #include "lac_log.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "lac_sym_hash_defs.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_session.h" #include "lac_sym_hash_precomputes.h" STATIC CpaStatus LacSymHash_Compute(CpaCySymHashAlgorithm hashAlgorithm, lac_sym_qat_hash_alg_info_t *pHashAlgInfo, Cpa8U *in, Cpa8U *out) { /* * Call specific osal implementation. * Note: from SHA hashes appropriate endian swapping is required. * For sha1, sha224 and sha256 double words based swapping. * For sha384 and sha512 quad words swapping. * No endianness swapping for md5 is required. */ CpaStatus status = CPA_STATUS_FAIL; Cpa32U i = 0; switch (hashAlgorithm) { case CPA_CY_SYM_HASH_MD5: if (OSAL_SUCCESS != osalHashMD5(in, out)) { LAC_LOG_ERROR("osalHashMD5 Failed\n"); return status; } status = CPA_STATUS_SUCCESS; break; case CPA_CY_SYM_HASH_SHA1: if (OSAL_SUCCESS != osalHashSHA1(in, out)) { LAC_LOG_ERROR("osalHashSHA1 Failed\n"); return status; } for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); i++) { ((Cpa32U *)(out))[i] = LAC_MEM_WR_32(((Cpa32U *)(out))[i]); } status = CPA_STATUS_SUCCESS; break; case CPA_CY_SYM_HASH_SHA224: if (OSAL_SUCCESS != osalHashSHA224(in, out)) { LAC_LOG_ERROR("osalHashSHA224 Failed\n"); return status; } for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); i++) { ((Cpa32U *)(out))[i] = LAC_MEM_WR_32(((Cpa32U *)(out))[i]); } status = CPA_STATUS_SUCCESS; break; case CPA_CY_SYM_HASH_SHA256: if (OSAL_SUCCESS != osalHashSHA256(in, out)) { LAC_LOG_ERROR("osalHashSHA256 Failed\n"); return status; } for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); i++) { ((Cpa32U *)(out))[i] = LAC_MEM_WR_32(((Cpa32U *)(out))[i]); } status = CPA_STATUS_SUCCESS; break; case CPA_CY_SYM_HASH_SHA384: if (OSAL_SUCCESS != osalHashSHA384(in, out)) { LAC_LOG_ERROR("osalHashSHA384 Failed\n"); return status; } for (i = 0; i < LAC_BYTES_TO_QUADWORDS(pHashAlgInfo->stateSize); i++) { ((Cpa64U *)(out))[i] = LAC_MEM_WR_64(((Cpa64U *)(out))[i]); } status = CPA_STATUS_SUCCESS; break; case CPA_CY_SYM_HASH_SHA512: if (OSAL_SUCCESS != osalHashSHA512(in, out)) { LAC_LOG_ERROR("osalHashSHA512 Failed\n"); return status; } for (i = 0; i < LAC_BYTES_TO_QUADWORDS(pHashAlgInfo->stateSize); i++) { ((Cpa64U *)(out))[i] = LAC_MEM_WR_64(((Cpa64U *)(out))[i]); } status = CPA_STATUS_SUCCESS; break; default: return CPA_STATUS_INVALID_PARAM; } return status; } CpaStatus LacSymHash_HmacPreComputes(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLenInBytes, Cpa8U *pAuthKey, Cpa8U *pWorkingMemory, Cpa8U *pState1, Cpa8U *pState2, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag) { Cpa8U *pIpadData = NULL; Cpa8U *pOpadData = NULL; CpaStatus status = CPA_STATUS_FAIL; lac_sym_hash_precomp_op_data_t *pHmacIpadOpData = (lac_sym_hash_precomp_op_data_t *)pWorkingMemory; lac_sym_hash_precomp_op_data_t *pHmacOpadOpData = pHmacIpadOpData + 1; /* Convenience pointers */ lac_sym_hash_hmac_precomp_qat_t *pHmacIpadQatData = &pHmacIpadOpData->u.hmacQatData; lac_sym_hash_hmac_precomp_qat_t *pHmacOpadQatData = &pHmacOpadOpData->u.hmacQatData; lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; Cpa32U i = 0; Cpa32U padLenBytes = 0; LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, authKeyLenInBytes, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); pHmacIpadOpData->stateSize = pHashAlgInfo->stateSize; pHmacOpadOpData->stateSize = pHashAlgInfo->stateSize; /* Copy HMAC key into buffers */ if (authKeyLenInBytes > 0) { memcpy(pHmacIpadQatData->data, pAuthKey, authKeyLenInBytes); memcpy(pHmacOpadQatData->data, pAuthKey, authKeyLenInBytes); } padLenBytes = pHashAlgInfo->blockLength - authKeyLenInBytes; /* Clear the remaining buffer space */ if (padLenBytes > 0) { LAC_OS_BZERO(pHmacIpadQatData->data + authKeyLenInBytes, padLenBytes); LAC_OS_BZERO(pHmacOpadQatData->data + authKeyLenInBytes, padLenBytes); } /* XOR Key with IPAD at 4-byte level */ for (i = 0; i < pHashAlgInfo->blockLength; i++) { Cpa8U *ipad = pHmacIpadQatData->data + i; Cpa8U *opad = pHmacOpadQatData->data + i; *ipad ^= LAC_HASH_IPAD_BYTE; *opad ^= LAC_HASH_OPAD_BYTE; } pIpadData = (Cpa8U *)pHmacIpadQatData->data; pOpadData = (Cpa8U *)pHmacOpadQatData->data; status = LacSymHash_Compute( hashAlgorithm, pHashAlgInfo, (Cpa8U *)pIpadData, pState1); if (CPA_STATUS_SUCCESS == status) { status = LacSymHash_Compute( hashAlgorithm, pHashAlgInfo, (Cpa8U *)pOpadData, pState2); } if (CPA_STATUS_SUCCESS == status) { callbackFn(pCallbackTag); } return status; } CpaStatus LacSymHash_AesECBPreCompute(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLenInBytes, Cpa8U *pAuthKey, Cpa8U *pWorkingMemory, Cpa8U *pState, lac_hash_precompute_done_cb_t callbackFn, void *pCallbackTag) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U stateSize = 0, x = 0; lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) { Cpa8U *in = pWorkingMemory; Cpa8U *out = pState; LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, authKeyLenInBytes, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); stateSize = pHashAlgInfo->stateSize; memcpy(pWorkingMemory, pHashAlgInfo->initState, stateSize); for (x = 0; x < LAC_HASH_XCBC_PRECOMP_KEY_NUM; x++) { if (OSAL_SUCCESS != osalAESEncrypt(pAuthKey, authKeyLenInBytes, in, out)) { return status; } in += LAC_HASH_XCBC_MAC_BLOCK_SIZE; out += LAC_HASH_XCBC_MAC_BLOCK_SIZE; } status = CPA_STATUS_SUCCESS; } else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) { Cpa8U *out = pState; Cpa8U k1[LAC_HASH_CMAC_BLOCK_SIZE], k2[LAC_HASH_CMAC_BLOCK_SIZE]; Cpa8U *ptr = NULL; size_t i = 0; stateSize = LAC_HASH_CMAC_BLOCK_SIZE; LacSymQat_HashAlgLookupGet(instanceHandle, hashAlgorithm, &pHashAlgInfo, authKeyLenInBytes, LAC_SYM_HASH_DEFAULT_DIGEST_LENS); /* Original state size includes K, K1 and K2 which are of equal length. * For precompute state size is only of the length of K which is equal * to the block size for CPA_CY_SYM_HASH_AES_CMAC. * The algorithm is described in rfc4493 * K is just copeid, K1 and K2 need to be single inplace encrypt * with AES. * */ memcpy(out, pHashAlgInfo->initState, stateSize); memcpy(out, pAuthKey, authKeyLenInBytes); out += LAC_HASH_CMAC_BLOCK_SIZE; for (x = 0; x < LAC_HASH_XCBC_PRECOMP_KEY_NUM - 1; x++) { if (OSAL_SUCCESS != osalAESEncrypt(pAuthKey, authKeyLenInBytes, out, out)) { return status; } out += LAC_HASH_CMAC_BLOCK_SIZE; } ptr = pState + LAC_HASH_CMAC_BLOCK_SIZE; /* Derived keys (k1 and k2), copy them to pPrecompOpData->pState, * but remember that at the beginning is original key (K0) */ /* Calculating K1 */ for (i = 0; i < LAC_HASH_CMAC_BLOCK_SIZE; i++, ptr++) { k1[i] = (*ptr) << 1; if (i != 0) { k1[i - 1] |= (*ptr) >> (LAC_NUM_BITS_IN_BYTE - 1); } if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { /* If msb of pState + LAC_HASH_CMAC_BLOCK_SIZE is set xor with RB. Because only the final byte of RB is non-zero this is all we need to xor */ if ((*(pState + LAC_HASH_CMAC_BLOCK_SIZE)) & LAC_SYM_HASH_MSBIT_MASK) { k1[i] ^= LAC_SYM_AES_CMAC_RB_128; } } } /* Calculating K2 */ for (i = 0; i < LAC_HASH_CMAC_BLOCK_SIZE; i++) { k2[i] = (k1[i]) << 1; if (i != 0) { k2[i - 1] |= (k1[i]) >> (LAC_NUM_BITS_IN_BYTE - 1); } if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { /* If msb of k1 is set xor last byte with RB */ if (k1[0] & LAC_SYM_HASH_MSBIT_MASK) { k2[i] ^= LAC_SYM_AES_CMAC_RB_128; } } } /* Now, when we have K1 & K2 lets copy them to the state2 */ ptr = pState + LAC_HASH_CMAC_BLOCK_SIZE; memcpy(ptr, k1, LAC_HASH_CMAC_BLOCK_SIZE); ptr += LAC_HASH_CMAC_BLOCK_SIZE; memcpy(ptr, k2, LAC_HASH_CMAC_BLOCK_SIZE); status = CPA_STATUS_SUCCESS; } else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm || CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { Cpa8U *in = pWorkingMemory; Cpa8U *out = pState; LAC_OS_BZERO(pWorkingMemory, ICP_QAT_HW_GALOIS_H_SZ); if (OSAL_SUCCESS != osalAESEncrypt(pAuthKey, authKeyLenInBytes, in, out)) { return status; } status = CPA_STATUS_SUCCESS; } else { return CPA_STATUS_INVALID_PARAM; } callbackFn(pCallbackTag); return status; } CpaStatus LacSymHash_HmacPrecompInit(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; return status; } void LacSymHash_HmacPrecompShutdown(CpaInstanceHandle instanceHandle) { return; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_partial.c000066400000000000000000000122661503624047500316470ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file lac_sym_partial.c common partial packet functions * * @ingroup LacSym * ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "lac_sym.h" #include "cpa_cy_sym.h" #include "lac_common.h" #include "lac_sym_partial.h" CpaStatus LacSym_PartialPacketStateCheck(CpaCySymPacketType packetType, CpaCySymPacketType partialState) { CpaStatus status = CPA_STATUS_SUCCESS; /* ASSUMPTION - partial requests on a given session must be issued * sequentially to guarantee ordering * (i.e. issuing partials on concurrent threads for a particular session * just wouldn't work) */ /* state is no partial - only a partial is allowed */ if (((CPA_CY_SYM_PACKET_TYPE_FULL == partialState) && (CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType)) || /* state is partial - only a partial or final partial is allowed */ ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == partialState) && ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType) || (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType)))) { status = CPA_STATUS_SUCCESS; } else /* invalid sequence */ { LAC_INVALID_PARAM_LOG("invalid partial packet sequence"); status = CPA_STATUS_INVALID_PARAM; } return status; } void LacSym_PartialPacketStateUpdate(CpaCySymPacketType packetType, CpaCySymPacketType *pPartialState) { /* if previous packet was either a full or ended a partial stream, update * state to partial to indicate a new partial stream was created */ if (CPA_CY_SYM_PACKET_TYPE_FULL == *pPartialState) { *pPartialState = CPA_CY_SYM_PACKET_TYPE_PARTIAL; } else { /* if packet type is final - reset the partial state */ if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType) { *pPartialState = CPA_CY_SYM_PACKET_TYPE_FULL; } } } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_queue.c000066400000000000000000000211521503624047500313310ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file lac_sym_queue.c Functions for sending/queuing symmetric requests * * @ingroup LacSym * ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_debug.h" #include "icp_adf_transport.h" #include "lac_sym_queue.h" #include "lac_sym_qat.h" #include "lac_session.h" #include "lac_sym.h" #include "lac_log.h" #include "icp_qat_fw_la.h" #include "lac_sal_types_crypto.h" #define GetSingleBitFromByte(byte, bit) ((byte) & (1 << (bit))) /* ******************************************************************************* * Define public/global function definitions ******************************************************************************* */ CpaStatus LacSymQueue_RequestSend(const CpaInstanceHandle instanceHandle, lac_sym_bulk_cookie_t *pRequest, lac_session_desc_t *pSessionDesc) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean enqueued = CPA_FALSE; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; Cpa64U seq_num = ICP_ADF_INVALID_SEND_SEQ; /* Enqueue the message instead of sending directly if: * (i) a blocking operation is in progress * (ii) there are previous requests already in the queue */ if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) || (NULL != pSessionDesc->pRequestQueueTail)) { LAC_SPINLOCK(&pSessionDesc->requestQueueLock); /* Re-check blockingOpsInProgress and pRequestQueueTail in case either * changed before the lock was acquired. The lock is shared with * the callback context which drains this queue */ if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) || (NULL != pSessionDesc->pRequestQueueTail)) { /* Enqueue the message and exit */ /* The FIFO queue is made up of a head and tail pointer. * The head pointer points to the first/oldest, entry * in the queue, and the tail pointer points to the last/newest * entry in the queue */ if (NULL != pSessionDesc->pRequestQueueTail) { /* Queue is non-empty. Add this request to the list */ pSessionDesc->pRequestQueueTail->pNext = pRequest; } else { /* Queue is empty. Initialise the head pointer as well */ pSessionDesc->pRequestQueueHead = pRequest; } pSessionDesc->pRequestQueueTail = pRequest; /* request is queued, don't send to QAT here */ enqueued = CPA_TRUE; } LAC_SPINUNLOCK(&pSessionDesc->requestQueueLock); } if (CPA_FALSE == enqueued) { /* If we send a partial packet request, set the blockingOpsInProgress * flag for the session to indicate that subsequent requests must be * queued up until this request completes * * @assumption * If we have got here it means that there were no previous blocking * operations in progress and, since multiple partial packet requests * on a given session cannot be issued concurrently, there should be * no need for a critical section around the following code */ if (CPA_CY_SYM_PACKET_TYPE_FULL != pRequest->pOpData->packetType) { /* Select blocking operations which this request will complete */ pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; } /* At this point, we're clear to send the request. For cipher requests, * we need to check if the session IV needs to be updated. This can * only be done when no other partials are in flight for this session, * to ensure the cipherPartialOpState buffer in the session descriptor * is not currently in use */ if (CPA_TRUE == pRequest->updateSessionIvOnSend) { if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { memcpy(pSessionDesc->cipherPartialOpState, pSessionDesc->cipherARC4InitialState, LAC_CIPHER_ARC4_STATE_LEN_BYTES); } else { memcpy(pSessionDesc->cipherPartialOpState, pRequest->pOpData->pIv, pRequest->pOpData->ivLenInBytes); } } /* Send to QAT */ status = SalQatMsg_transPutMsg(pService->trans_handle_sym_tx, (void *)&(pRequest->qatMsg), LAC_QAT_SYM_REQ_SZ_LW, LAC_LOG_MSG_SYMCYBULK, &seq_num); if (CPA_STATUS_SUCCESS == status) { LAC_MEM_POOL_BLK_SET_OPAQUE(pRequest, seq_num); } else if ((CPA_CY_SYM_PACKET_TYPE_FULL != pRequest->pOpData->packetType)) { /* if fail to send request, we need to change * nonBlockingOpsInProgress to CPA_TRUE */ pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; } } return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/lac_sym_stats.c000066400000000000000000000173141503624047500313500ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file lac_sym_stats.c Implementation of symmetric stats * * @ingroup LacSym * ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_mem_pools.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "icp_qat_fw_la.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "sal_statistics.h" /* Number of Symmetric Crypto statistics */ #define LAC_SYM_NUM_STATS (sizeof(CpaCySymStats64) / sizeof(Cpa64U)) CpaStatus LacSym_StatsInit(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; status = LAC_OS_MALLOC(&(pService->pLacSymStatsArr), LAC_SYM_NUM_STATS * sizeof(OsalAtomic)); if (CPA_STATUS_SUCCESS == status) { LAC_OS_BZERO( (void *)LAC_CONST_VOLATILE_PTR_CAST(pService->pLacSymStatsArr), LAC_SYM_NUM_STATS * sizeof(OsalAtomic)); } return status; } void LacSym_StatsFree(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; if (NULL != pService->pLacSymStatsArr) { LAC_OS_FREE(pService->pLacSymStatsArr); } } void LacSym_StatsReset(CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; LAC_OS_BZERO((void *)LAC_CONST_VOLATILE_PTR_CAST(pService->pLacSymStatsArr), LAC_SYM_NUM_STATS * sizeof(OsalAtomic)); } #ifndef DISABLE_STATS void LacSym_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle) { sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; if (CPA_TRUE == pService->generic_service_info.stats->bSymStatsEnabled) { osalAtomicInc(&pService->pLacSymStatsArr[offset / sizeof(Cpa64U)]); } } #endif /* DISABLE_STATS */ void LacSym_Stats32CopyGet(CpaInstanceHandle instanceHandle, struct _CpaCySymStats *const pSymStats) { int i = 0; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; LAC_ENSURE(NULL != instanceHandle, "invalid handle\n"); LAC_ENSURE_NOT_NULL(pSymStats); for (i = 0; i < LAC_SYM_NUM_STATS; i++) { ((Cpa32U *)pSymStats)[i] = (Cpa32U)osalAtomicGet(&pService->pLacSymStatsArr[i]); } } void LacSym_Stats64CopyGet(CpaInstanceHandle instanceHandle, CpaCySymStats64 *const pSymStats) { int i = 0; sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; LAC_ENSURE(NULL != instanceHandle, "invalid handle\n"); LAC_ENSURE_NOT_NULL(pSymStats); for (i = 0; i < LAC_SYM_NUM_STATS; i++) { ((Cpa64U *)pSymStats)[i] = osalAtomicGet(&pService->pLacSymStatsArr[i]); } } void LacSym_StatsShow(CpaInstanceHandle instanceHandle) { CpaCySymStats64 symStats = {0}; LacSym_Stats64CopyGet(instanceHandle, &symStats); osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " Symmetric Stats " BORDER "\n" SEPARATOR); /* Session Info */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " Sessions Initialized: %16llu " BORDER "\n" BORDER " Sessions Removed: %16llu " BORDER "\n" BORDER " Session Errors: %16llu " BORDER "\n" SEPARATOR, symStats.numSessionsInitialized, symStats.numSessionsRemoved, symStats.numSessionErrors); /* Session info */ osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " Symmetric Requests: %16llu " BORDER "\n" BORDER " Symmetric Request Errors: %16llu " BORDER "\n" BORDER " Symmetric Completed: %16llu " BORDER "\n" BORDER " Symmetric Completed Errors: %16llu " BORDER "\n" BORDER " Symmetric Verify Failures: %16llu " BORDER "\n" SEPARATOR, symStats.numSymOpRequests, symStats.numSymOpRequestErrors, symStats.numSymOpCompleted, symStats.numSymOpCompletedErrors, symStats.numSymOpVerifyFailures); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/nrbg/000077500000000000000000000000001503624047500272615ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/nrbg/lac_sym_nrbg_api.c000066400000000000000000000074221503624047500327220ustar00rootroot00000000000000/************************************************************************* * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_sym_nrbg_api.c * * @ingroup LacSym_Nrbg * * Implementation of the Non-Deterministic Random Bit Generation API * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_nrbg.h" /** * cpaCyNrbgGetEntropy */ CpaStatus cpaCyNrbgGetEntropy(const CpaInstanceHandle instanceHandle_in, const CpaCyGenFlatBufCbFunc pCb, void *pCallbackTag, const CpaCyNrbgOpData *pOpData, CpaFlatBuffer *pEntropy) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/qat/000077500000000000000000000000001503624047500271165ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat.c000066400000000000000000000372071503624047500315670ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat.c Interfaces for populating the symmetric qat structures * * @ingroup LacSymQat * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "icp_accel_devices.h" #include "icp_adf_cfg.h" #include "lac_sym.h" #include "lac_sym_qat.h" #include "lac_sal_types_crypto.h" #include "sal_string_parse.h" #include "lac_sym_key.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_qat_constants_table.h" #include "lac_sym_qat_cipher.h" #include "lac_sym_qat_hash.h" #include "sal_misc_error_stats.h" #define EMBEDDED_CIPHER_KEY_MAX_SIZE 16 STATIC void LacSymQat_SymLogSliceHangError(icp_qat_fw_la_cmd_id_t symCmdId) { Cpa8U cmdId = symCmdId; switch (cmdId) { case ICP_QAT_FW_LA_CMD_CIPHER: case ICP_QAT_FW_LA_CMD_CIPHER_PRE_COMP: LAC_LOG_ERROR("slice hang detected on CPM cipher slice. "); break; case ICP_QAT_FW_LA_CMD_AUTH: case ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP: LAC_LOG_ERROR("slice hang detected on CPM auth slice. "); break; case ICP_QAT_FW_LA_CMD_CIPHER_HASH: case ICP_QAT_FW_LA_CMD_HASH_CIPHER: case ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE: case ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE: case ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE: case ICP_QAT_FW_LA_CMD_MGF1: default: LAC_LOG_ERROR("slice hang detected on CPM cipher or auth slice. "); } return; } /* sym crypto response handlers */ STATIC sal_qat_resp_handler_func_t respHandlerSymTbl[ICP_QAT_FW_LA_CMD_DELIMITER]; void LacSymQat_SymRespHandler(void *pRespMsg) { Cpa8U lacCmdId = 0; void *pOpaqueData = NULL; icp_qat_fw_la_resp_t *pRespMsgFn = NULL; sal_crypto_service_t *pInst = NULL; Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; Cpa8U comnErr = ERR_CODE_NO_ERROR; pRespMsgFn = (icp_qat_fw_la_resp_t *)pRespMsg; LAC_ENSURE(pRespMsgFn != NULL, "LacSymQat_SymRespHandler - pRespMsgFn NULL\n"); LAC_MEM_SHARED_READ_TO_PTR(pRespMsgFn->opaque_data, pOpaqueData); LAC_ENSURE(pOpaqueData != NULL, "LacSymQat_SymRespHandler - pOpaqueData NULL\n"); lacCmdId = pRespMsgFn->comn_resp.cmd_id; opStatus = pRespMsgFn->comn_resp.comn_status; comnErr = pRespMsgFn->comn_resp.comn_error.s.comn_err_code; pInst = (sal_crypto_service_t *)(((lac_sym_bulk_cookie_t *)pOpaqueData) ->instanceHandle); /* log the slice hang, ssm parity and endpoint push/pull error inside the * response */ if (ERR_CODE_SSM_ERROR == (Cpa8S)comnErr) { LacSymQat_SymLogSliceHangError(lacCmdId); } else if (ERR_CODE_SSM_PARITY_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR("Operation resulted in a parity error in one or more " "accelerators."); } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)comnErr) { LAC_LOG_ERROR("The PCIe End Point Push/Pull or" " TI/RI Parity error detected."); } SAL_MISC_ERR_STATS_INC(comnErr, &pInst->generic_service_info); /* call the response message handler registered for the command ID */ respHandlerSymTbl[lacCmdId]((icp_qat_fw_la_cmd_id_t)lacCmdId, pOpaqueData, (icp_qat_fw_comn_flags)opStatus); } CpaStatus LacSymQat_Init(CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_SUCCESS; /* Initialize the SHRAM constants table */ LacSymQat_ConstantsInitLookupTables(instanceHandle); /* Initialise the Hash lookup table */ status = LacSymQat_HashLookupInit(instanceHandle); return status; } void LacSymQat_RespHandlerRegister(icp_qat_fw_la_cmd_id_t lacCmdId, sal_qat_resp_handler_func_t pCbHandler) { LAC_ENSURE_RETURN_VOID((lacCmdId < ICP_QAT_FW_LA_CMD_DELIMITER), "Invalid Command ID"); /* set the response handler for the command ID */ respHandlerSymTbl[lacCmdId] = pCbHandler; } void LacSymQat_LaPacketCommandFlagSet(Cpa32U qatPacketType, icp_qat_fw_la_cmd_id_t laCmdId, CpaCySymCipherAlgorithm cipherAlgorithm, Cpa16U *pLaCommandFlags, Cpa32U ivLenInBytes) { /* For SM4/Chacha ciphers set command flag as partial none to proceed * with stateless processing */ if (LAC_CIPHER_IS_SM4(cipherAlgorithm) || LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) { ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags, ICP_QAT_FW_LA_PARTIAL_NONE); return; } ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags, qatPacketType); /* For ECB-mode ciphers, IV is NULL so update-state flag * must be disabled always. * For all other ciphers and auth * update state is disabled for full packets and final partials */ if ((ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) || (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType) || ((laCmdId != ICP_QAT_FW_LA_CMD_AUTH) && LAC_CIPHER_IS_ECB_MODE(cipherAlgorithm))) { ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags, ICP_QAT_FW_LA_NO_UPDATE_STATE); } /* For first or middle partials set the update state command flag */ else { ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags, ICP_QAT_FW_LA_UPDATE_STATE); if (laCmdId == ICP_QAT_FW_LA_CMD_AUTH) { /* For hash only partial - verify and return auth result are * disabled */ ICP_QAT_FW_LA_RET_AUTH_SET(*pLaCommandFlags, ICP_QAT_FW_LA_NO_RET_AUTH_RES); ICP_QAT_FW_LA_CMP_AUTH_SET(*pLaCommandFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); } } if ((LAC_CIPHER_IS_GCM(cipherAlgorithm)) && (LAC_CIPHER_IV_SIZE_GCM_12 == ivLenInBytes)) { ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET(*pLaCommandFlags, ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS); } } void LacSymQat_packetTypeGet(CpaCySymPacketType packetType, CpaCySymPacketType packetState, Cpa32U *pQatPacketType) { switch (packetType) { /* partial */ case CPA_CY_SYM_PACKET_TYPE_PARTIAL: /* if the previous state was full, then this is the first packet */ if (CPA_CY_SYM_PACKET_TYPE_FULL == packetState) { *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_START; } else { *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_MID; } break; /* final partial */ case CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL: *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_END; break; /* full packet - CPA_CY_SYM_PACKET_TYPE_FULL */ default: *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_NONE; } } void LacSymQat_LaSetDefaultFlags(icp_qat_fw_serv_specif_flags *laCmdFlags, CpaCySymOp symOp) { ICP_QAT_FW_LA_PARTIAL_SET(*laCmdFlags, ICP_QAT_FW_LA_PARTIAL_NONE); ICP_QAT_FW_LA_UPDATE_STATE_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_UPDATE_STATE); if (symOp != CPA_CY_SYM_OP_CIPHER) { ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_RET_AUTH_RES); } else { ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_RET_AUTH_RES); } ICP_QAT_FW_LA_CMP_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET(*laCmdFlags, ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS); } CpaBoolean LacSymQat_UseSymConstantsTable(lac_session_desc_t *pSession, Cpa8U *pCipherOffset, Cpa8U *pHashOffset) { CpaBoolean useOptimisedContentDesc = CPA_FALSE; CpaBoolean useSHRAMConstants = CPA_FALSE; LAC_ENSURE_NOT_NULL(pSession); LAC_ENSURE_NOT_NULL(pCipherOffset); LAC_ENSURE_NOT_NULL(pHashOffset); *pCipherOffset = 0; *pHashOffset = 0; LAC_LOG_DEBUG1("UseSymConstantsTable called. laCmdId = %d ", pSession->laCmdId); /* for chaining can we use the optimised content descriptor */ if (pSession->laCmdId == ICP_QAT_FW_LA_CMD_CIPHER_HASH || pSession->laCmdId == ICP_QAT_FW_LA_CMD_HASH_CIPHER) { useOptimisedContentDesc = LacSymQat_UseOptimisedContentDesc(pSession); } /* Cipher-only case or chaining */ if (pSession->laCmdId == ICP_QAT_FW_LA_CMD_CIPHER || useOptimisedContentDesc) { icp_qat_hw_cipher_algo_t algorithm; icp_qat_hw_cipher_mode_t mode; icp_qat_hw_cipher_dir_t dir; icp_qat_hw_cipher_convert_t key_convert; if (pSession->cipherKeyLenInBytes > sizeof(icp_qat_fw_comn_req_hdr_cd_pars_t)) { LAC_LOG_DEBUG1("keyLen > %d - don't use SymConstantsTable", sizeof(icp_qat_fw_comn_req_hdr_cd_pars_t)); return CPA_FALSE; } LacSymQat_CipherGetCfgData( pSession, &algorithm, &mode, &dir, &key_convert); /* Check if cipher config is available in table. */ LacSymQat_ConstantsGetCipherOffset(pSession->pInstance, algorithm, mode, dir, key_convert, pCipherOffset); if (*pCipherOffset > 0) { LAC_LOG_DEBUG("UseSymConstantsTable - cipher cfg in table"); useSHRAMConstants = CPA_TRUE; } else { LAC_LOG_DEBUG("cipher config not in SymConstantsTable"); useSHRAMConstants = CPA_FALSE; } } /* hash only case or when chaining, cipher must be found in SHRAM table for * optimised CD case */ if (pSession->laCmdId == ICP_QAT_FW_LA_CMD_AUTH || (useOptimisedContentDesc && useSHRAMConstants)) { icp_qat_hw_auth_algo_t algorithm; CpaBoolean nested; if (pSession->digestVerify) { LAC_LOG_DEBUG("digestVerify is set - don't use SymConstantsTable"); return CPA_FALSE; } if ((!(useOptimisedContentDesc && useSHRAMConstants)) && (pSession->qatHashMode == ICP_QAT_HW_AUTH_MODE1)) { /* we can only use the SHA1-mode1 in the SHRAM constants table when * we are using the optimised content desc */ LAC_LOG_DEBUG("HASH only SHA1-MODE1 - don't use SymConstTable"); return CPA_FALSE; } LacSymQat_HashGetCfgData(pSession->pInstance, pSession->qatHashMode, pSession->hashMode, pSession->hashAlgorithm, &algorithm, &nested, pSession->authKeyLenInBytes, pSession->hashResultSize); /* Check if config data is available in table. */ LacSymQat_ConstantsGetAuthOffset(pSession->pInstance, algorithm, pSession->qatHashMode, nested, pHashOffset); if (*pHashOffset > 0) { LAC_LOG_DEBUG("UseSymConstantsTable - hash cfg in table"); useSHRAMConstants = CPA_TRUE; } else { LAC_LOG_DEBUG("hash config not in SymConstantsTable"); useSHRAMConstants = CPA_FALSE; } } return useSHRAMConstants; } CpaBoolean LacSymQat_UseOptimisedContentDesc(lac_session_desc_t *pSession) { /* AES128-CBC-HMAC-SHA1 MODE 1*/ if ((pSession->cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CBC && pSession->cipherKeyLenInBytes <= EMBEDDED_CIPHER_KEY_MAX_SIZE) && (pSession->hashAlgorithm == CPA_CY_SYM_HASH_SHA1 && pSession->qatHashMode == ICP_QAT_HW_AUTH_MODE1)) { return CPA_TRUE; } else { return CPA_FALSE; } } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_cipher.c000066400000000000000000001175311503624047500331200ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_qat_cipher.c QAT-related support functions for Cipher * * @ingroup LacSymQat_Cipher * * @description Functions to support the QAT related operations for Cipher ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "Osal.h" #include "cpa.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "lac_sym_qat.h" #include "lac_sym_qat_cipher.h" #include "lac_mem.h" #include "lac_common.h" #include "cpa_cy_sym.h" #include "lac_sym_qat.h" #include "lac_sym_cipher_defs.h" #include "icp_qat_hw.h" #include "icp_qat_fw_la.h" #define LAC_UNUSED_POS_MASK 0x3 /* To determine an overflow on a 32 bit unsigned value */ #define UINT_OVERFLOW (0xFFFFFFFF00000000UL) /***************************************************************************** * Internal data *****************************************************************************/ typedef enum _icp_qat_hw_key_depend { IS_KEY_DEP_NO = 0, IS_KEY_DEP_YES, } icp_qat_hw_key_depend; /* LAC_CIPHER_IS_XTS_MODE */ static const uint8_t key_size_xts[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES128, /* ICP_QAT_HW_AES_128_XTS_KEY_SZ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES256 /* ICP_QAT_HW_AES_256_XTS_KEY_SZ */ }; /* LAC_CIPHER_IS_AES */ static const uint8_t key_size_aes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES128, /* ICP_QAT_HW_AES_128_KEY_SZ */ 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES192, /* ICP_QAT_HW_AES_192_KEY_SZ */ 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES256 /* ICP_QAT_HW_AES_256_KEY_SZ */ }; /* LAC_CIPHER_IS_AES_F8 */ static const uint8_t key_size_f8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES128, /* ICP_QAT_HW_AES_128_F8_KEY_SZ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES192, /* ICP_QAT_HW_AES_192_F8_KEY_SZ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_AES256 /* ICP_QAT_HW_AES_256_F8_KEY_SZ */ }; /* LAC_CIPHER_IS_ZUC_EEA3 */ static const uint8_t key_size_zuc_eea3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3, /* ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ICP_QAT_HW_CIPHER_ALGO_ZUC_256 /* ICP_QAT_HW_ZUC_256_KEY_SZ */ }; /* This array must be kept aligned with CpaCySymCipherAlgorithm enum but * offset by -1 as that enum starts at 1. LacSymQat_CipherGetCfgData() * below relies on that alignment and uses that enum -1 to index into this * array. */ typedef struct _icp_qat_hw_cipher_info { icp_qat_hw_cipher_algo_t algorithm; icp_qat_hw_cipher_mode_t mode; icp_qat_hw_cipher_convert_t key_convert[2]; icp_qat_hw_cipher_dir_t dir[2]; icp_qat_hw_key_depend isKeyLenDepend; const uint8_t *pAlgByKeySize; } icp_qat_hw_cipher_info; static const icp_qat_hw_cipher_info icp_qat_alg_info[] = { /* CPA_CY_SYM_CIPHER_NULL */ { ICP_QAT_HW_CIPHER_ALGO_NULL, ICP_QAT_HW_CIPHER_ECB_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_ARC4 */ { ICP_QAT_HW_CIPHER_ALGO_ARC4, ICP_QAT_HW_CIPHER_ECB_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, /* Streaming ciphers are a special case. Decrypt = encrypt */ { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_AES_ECB */ { ICP_QAT_HW_CIPHER_ALGO_AES128, ICP_QAT_HW_CIPHER_ECB_MODE, /* AES decrypt key needs to be reversed. Instead of reversing the key * at session registration, it is instead reversed on-the-fly by * setting the KEY_CONVERT bit here */ { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_YES, key_size_aes, }, /* CPA_CY_SYM_CIPHER_AES_CBC */ { ICP_QAT_HW_CIPHER_ALGO_AES128, ICP_QAT_HW_CIPHER_CBC_MODE, /* AES decrypt key needs to be reversed. Instead of reversing the key * at session registration, it is instead reversed on-the-fly by * setting the KEY_CONVERT bit here */ { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_YES, key_size_aes, }, /* CPA_CY_SYM_CIPHER_AES_CTR */ { ICP_QAT_HW_CIPHER_ALGO_AES128, ICP_QAT_HW_CIPHER_CTR_MODE, /* AES decrypt key needs to be reversed. Instead of reversing the key * at session registration, it is instead reversed on-the-fly by * setting the KEY_CONVERT bit here */ { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, /* Streaming ciphers are a special case. Decrypt = encrypt * Overriding default values previously set for AES */ { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_YES, key_size_aes, }, /* CPA_CY_SYM_CIPHER_AES_CCM */ { ICP_QAT_HW_CIPHER_ALGO_AES128, ICP_QAT_HW_CIPHER_CTR_MODE, /* AES decrypt key needs to be reversed. Instead of reversing the key * at session registration, it is instead reversed on-the-fly by * setting the KEY_CONVERT bit here */ { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, /* Streaming ciphers are a special case. Decrypt = encrypt * Overriding default values previously set for AES */ { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_YES, key_size_aes, }, /* CPA_CY_SYM_CIPHER_AES_GCM */ { ICP_QAT_HW_CIPHER_ALGO_AES128, ICP_QAT_HW_CIPHER_CTR_MODE, /* AES decrypt key needs to be reversed. Instead of reversing the key * at session registration, it is instead reversed on-the-fly by * setting the KEY_CONVERT bit here */ { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, /* Streaming ciphers are a special case. Decrypt = encrypt * Overriding default values previously set for AES */ { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_YES, key_size_aes, }, /* CPA_CY_SYM_CIPHER_DES_ECB */ { ICP_QAT_HW_CIPHER_ALGO_DES, ICP_QAT_HW_CIPHER_ECB_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_DES_CBC */ { ICP_QAT_HW_CIPHER_ALGO_DES, ICP_QAT_HW_CIPHER_CBC_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_3DES_ECB */ { ICP_QAT_HW_CIPHER_ALGO_3DES, ICP_QAT_HW_CIPHER_ECB_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_3DES_CBC */ { ICP_QAT_HW_CIPHER_ALGO_3DES, ICP_QAT_HW_CIPHER_CBC_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_3DES_CTR */ { ICP_QAT_HW_CIPHER_ALGO_3DES, ICP_QAT_HW_CIPHER_CTR_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, /* Streaming ciphers are a special case. Decrypt = encrypt * Overriding default values previously set for AES */ { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_KASUMI_F8 */ { ICP_QAT_HW_CIPHER_ALGO_KASUMI, ICP_QAT_HW_CIPHER_F8_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, /* Streaming ciphers are a special case. Decrypt = encrypt */ { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_SNOW3G_UEA2 */ { /* The KEY_CONVERT bit has to be set for Snow_3G operation */ ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2, ICP_QAT_HW_CIPHER_ECB_MODE, { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_AES_F8 */ { ICP_QAT_HW_CIPHER_ALGO_AES128, ICP_QAT_HW_CIPHER_F8_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, /* Streaming ciphers are a special case. Decrypt = encrypt */ { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_YES, key_size_f8, }, /* CPA_CY_SYM_CIPHER_AES_XTS */ { ICP_QAT_HW_CIPHER_ALGO_AES128, ICP_QAT_HW_CIPHER_XTS_MODE, /* Reverse the cipher key in library for decrypt direction and clearing * the key_convert bit in the configuration word for AES-XTS algorithm */ { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_YES, key_size_xts, }, /* CPA_CY_SYM_CIPHER_ZUC_EEA3 */ { ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3, ICP_QAT_HW_CIPHER_ECB_MODE, { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_YES, key_size_zuc_eea3, }, /* CPA_CY_SYM_CIPHER_CHACHA */ { ICP_QAT_HW_CIPHER_ALGO_CHACHA20_POLY1305, ICP_QAT_HW_CIPHER_CTR_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_SM4_ECB */ { ICP_QAT_HW_CIPHER_ALGO_SM4, ICP_QAT_HW_CIPHER_ECB_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_SM4_CBC */ { ICP_QAT_HW_CIPHER_ALGO_SM4, ICP_QAT_HW_CIPHER_CBC_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, IS_KEY_DEP_NO, NULL, }, /* CPA_CY_SYM_CIPHER_SM4_CTR */ { ICP_QAT_HW_CIPHER_ALGO_SM4, ICP_QAT_HW_CIPHER_CTR_MODE, { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, IS_KEY_DEP_NO, NULL, }, /* RESERVED#1 in order to align with unsupported algorithms in API repo */ { 0 }, /* RESERVED#2 in order to align with unsupported algorithms in API repo */ { 0 }, /* RESERVED#3 in order to align with unsupported algorithms in API repo */ { 0 }, }; /***************************************************************************** * Internal functions *****************************************************************************/ void LacSymQat_CipherCtrlBlockWrite(icp_qat_la_bulk_req_ftr_t *pMsg, Cpa32U cipherAlgorithm, Cpa32U targetKeyLenInBytes, Cpa32U sliceType, icp_qat_fw_slice_t nextSlice, Cpa8U cipherCfgOffsetInQuadWord) { icp_qat_fw_cipher_cd_ctrl_hdr_t *cd_ctrl = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); /* state_padding_sz is nonzero for f8 mode only */ cd_ctrl->cipher_padding_sz = 0; /* Special handling of AES 192 key for UCS slice. UCS requires it to have 32 bytes - set is as targetKeyLen in this case, and add padding. It makes no sense to force applications to provide such key length for couple reasons: 1. It won't be possible to distinguish between AES 192 and 256 based on key length only 2. Only some modes of AES will use UCS slice, then application will have to know which ones */ if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE == sliceType && ICP_QAT_HW_AES_192_KEY_SZ == targetKeyLenInBytes) { targetKeyLenInBytes = ICP_QAT_HW_UCS_AES_192_KEY_SZ; } switch (cipherAlgorithm) { /* Base Key is not passed down to QAT in the case of ARC4 or NULL */ case CPA_CY_SYM_CIPHER_ARC4: case CPA_CY_SYM_CIPHER_NULL: cd_ctrl->cipher_key_sz = 0; break; case CPA_CY_SYM_CIPHER_KASUMI_F8: cd_ctrl->cipher_key_sz = LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_KASUMI_F8_KEY_SZ); cd_ctrl->cipher_padding_sz = ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR; break; /* For Snow3G UEA2 content descriptor key size is key size plus iv size */ case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: cd_ctrl->cipher_key_sz = LAC_BYTES_TO_QUADWORDS( ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); break; case CPA_CY_SYM_CIPHER_AES_F8: cd_ctrl->cipher_key_sz = LAC_BYTES_TO_QUADWORDS(targetKeyLenInBytes); cd_ctrl->cipher_padding_sz = (2 * ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR); break; /* For ZUC EEA3 content descriptor key size is key size plus iv size */ case CPA_CY_SYM_CIPHER_ZUC_EEA3: /* For ZUC-128 EEA3 and ZUC-256, the content descriptor key size is key size plus iv size */ if (ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ == targetKeyLenInBytes) { cd_ctrl->cipher_key_sz = LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); } /* ICP_QAT_HW_ZUC_256_KEY_SZ assumed */ else { cd_ctrl->cipher_key_sz = LAC_BYTES_TO_QUADWORDS( ICP_QAT_HW_ZUC_256_KEY_SZ + ICP_QAT_HW_ZUC_256_IV_SZ); } break; default: cd_ctrl->cipher_key_sz = LAC_BYTES_TO_QUADWORDS(targetKeyLenInBytes); } cd_ctrl->cipher_state_sz = LAC_BYTES_TO_QUADWORDS(LacSymQat_CipherIvSizeBytesGet(cipherAlgorithm)); cd_ctrl->cipher_cfg_offset = cipherCfgOffsetInQuadWord; /* Amend obtained IV size for ZUC-256 */ if (LAC_CIPHER_IS_ZUC_256(cipherAlgorithm, targetKeyLenInBytes)) { cd_ctrl->cipher_state_sz = LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_ZUC_256_IV_SZ); } if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE != sliceType) { ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl, nextSlice); ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_CIPHER); } } void LacSymQat_CipherGetCfgData(lac_session_desc_t *pSession, icp_qat_hw_cipher_algo_t *pAlgorithm, icp_qat_hw_cipher_mode_t *pMode, icp_qat_hw_cipher_dir_t *pDir, icp_qat_hw_cipher_convert_t *pKey_convert) { int cipherIdx = 0; icp_qat_hw_cipher_dir_t cipherDirection = 0; LAC_ENSURE_NOT_NULL(pSession); LAC_ENSURE_NOT_NULL(pAlgorithm); LAC_ENSURE_NOT_NULL(pMode); LAC_ENSURE_NOT_NULL(pDir); LAC_ENSURE_NOT_NULL(pKey_convert); /* Set defaults */ *pKey_convert = ICP_QAT_HW_CIPHER_NO_CONVERT; *pAlgorithm = ICP_QAT_HW_CIPHER_ALGO_NULL; *pMode = ICP_QAT_HW_CIPHER_ECB_MODE; *pDir = ICP_QAT_HW_CIPHER_ENCRYPT; /* offset index as CpaCySymCipherAlgorithm enum starts from 1, not from 0 */ cipherIdx = pSession->cipherAlgorithm - 1; cipherDirection = pSession->cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT ? ICP_QAT_HW_CIPHER_ENCRYPT : ICP_QAT_HW_CIPHER_DECRYPT; /* Boundary check against the last value in the algorithm enum */ LAC_ENSURE_RETURN_VOID(pSession->cipherAlgorithm <= CPA_CY_SYM_CIPHER_SM4_CTR, "Invalid cipherAlgorithm value\n"); LAC_ENSURE_RETURN_VOID(cipherDirection <= ICP_QAT_HW_CIPHER_DECRYPT, "Invalid cipherDirection value\n"); *pAlgorithm = icp_qat_alg_info[cipherIdx].algorithm; *pMode = icp_qat_alg_info[cipherIdx].mode; *pDir = icp_qat_alg_info[cipherIdx].dir[cipherDirection]; *pKey_convert = icp_qat_alg_info[cipherIdx].key_convert[cipherDirection]; if (IS_KEY_DEP_NO != icp_qat_alg_info[cipherIdx].isKeyLenDepend) { *pAlgorithm = icp_qat_alg_info[cipherIdx] .pAlgByKeySize[pSession->cipherKeyLenInBytes]; LAC_ENSURE(ICP_QAT_HW_CIPHER_ALGO_NULL != *pAlgorithm, "Invalid AES key size\n"); } /* CCP and AES_GCM single pass, despite being limited to CTR/AEAD mode, * support both Encrypt/Decrypt modes - this is because of the * differences in the hash computation/verification paths in * encrypt/decrypt modes respectively. * By default CCP is set as CTR Mode.Set AEAD Mode for AES_GCM. */ if (SPC_YES == pSession->singlePassState) { if (LAC_CIPHER_IS_GCM(pSession->cipherAlgorithm)) *pMode = ICP_QAT_HW_CIPHER_GCM_MODE; else if (LAC_CIPHER_IS_CCM(pSession->cipherAlgorithm)) *pMode = ICP_QAT_HW_CIPHER_CCM_MODE; if (cipherDirection == ICP_QAT_HW_CIPHER_DECRYPT) *pDir = ICP_QAT_HW_CIPHER_DECRYPT; } } void LacSymQat_CipherHwBlockPopulateCfgData(lac_session_desc_t *pSession, const void *pCipherHwBlock, Cpa32U *pSizeInBytes) { icp_qat_hw_cipher_algo_t algorithm = ICP_QAT_HW_CIPHER_ALGO_NULL; icp_qat_hw_cipher_mode_t mode = ICP_QAT_HW_CIPHER_ECB_MODE; icp_qat_hw_cipher_dir_t dir = ICP_QAT_HW_CIPHER_ENCRYPT; icp_qat_hw_cipher_convert_t key_convert; icp_qat_hw_cipher_config_t *pCipherConfig = (icp_qat_hw_cipher_config_t *)pCipherHwBlock; icp_qat_hw_ucs_cipher_config_t *pUCSCipherConfig = (icp_qat_hw_ucs_cipher_config_t *)pCipherHwBlock; Cpa32U aed_hash_cmp_length = 0; Cpa32U val, reserved = 0; LAC_ENSURE_NOT_NULL(pCipherConfig); LAC_ENSURE_NOT_NULL(pSizeInBytes); *pSizeInBytes = 0; LacSymQat_CipherGetCfgData(pSession, &algorithm, &mode, &dir, &key_convert); /* Build the cipher config into the hardware setup block */ if (SPC_YES == pSession->singlePassState) { aed_hash_cmp_length = pSession->hashResultSize; reserved = ICP_QAT_HW_CIPHER_CONFIG_BUILD_UPPER(pSession->aadLenInBytes); } else { reserved = 0; } val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( mode, algorithm, key_convert, dir, aed_hash_cmp_length); *pSizeInBytes = sizeof(icp_qat_hw_cipher_config_t); /* UCS slice has 128-bit configuration register. * Legacy cipher slice has 64-bit config register */ if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE == pSession->cipherSliceType) { pUCSCipherConfig->val = val; pUCSCipherConfig->reserved[0] = reserved; pUCSCipherConfig->reserved[1] = 0; pUCSCipherConfig->reserved[2] = 0; *pSizeInBytes = sizeof(icp_qat_hw_ucs_cipher_config_t); /* For XTS mode use cached forward/reverse key depending on direction */ if (LAC_CIPHER_IS_XTS_MODE(pSession->cipherAlgorithm)) { Cpa8U *pCipherKey = (Cpa8U *)pCipherHwBlock + *pSizeInBytes; if (ICP_QAT_HW_CIPHER_DECRYPT == dir) { osalMemCopy(pCipherKey, pSession->cipherAesXtsKey1Reverse, pSession->cipherKeyLenInBytes >> 1); } else { osalMemCopy(pCipherKey, pSession->cipherAesXtsKey1Forward, pSession->cipherKeyLenInBytes >> 1); } } } else { pCipherConfig->val = val; pCipherConfig->reserved = reserved; *pSizeInBytes = sizeof(icp_qat_hw_cipher_config_t); } } void LacSymQat_CipherHwBlockPopulateKeySetup( lac_session_desc_t *pSessionDesc, const CpaCySymCipherSetupData *pCipherSetupData, Cpa32U targetKeyLenInBytes, Cpa32U sliceType, const void *pCipherHwBlock, Cpa32U *pSizeInBytes) { Cpa8U *pCipherKey = (Cpa8U *)pCipherHwBlock; Cpa32U actualKeyLenInBytes = pCipherSetupData->cipherKeyLenInBytes; Cpa64U tempKeyLenInBytes = 0; *pSizeInBytes = 0; /* Key is copied into content descriptor for all cases except for * Arc4 and Null cipher */ if (!(LAC_CIPHER_IS_ARC4(pCipherSetupData->cipherAlgorithm) || LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm))) { /* Special handling of AES 192 key for UCS slice. UCS requires it to have 32 bytes - set is as targetKeyLen in this case, and add padding. It makes no sense to force applications to provide such key length for couple reasons: 1. It won't be possible to distinguish between AES 192 and 256 based on key length only 2. Only some modes of AES will use UCS slice, then application will have to know which ones */ if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE == sliceType && ICP_QAT_HW_AES_192_KEY_SZ == targetKeyLenInBytes) { targetKeyLenInBytes = ICP_QAT_HW_UCS_AES_192_KEY_SZ; } /* Set the Cipher key field in the cipher block */ memcpy(pCipherKey, pCipherSetupData->pCipherKey, actualKeyLenInBytes); /* Pad the key with 0's if required */ if (targetKeyLenInBytes > actualKeyLenInBytes) { LAC_OS_BZERO(pCipherKey + actualKeyLenInBytes, targetKeyLenInBytes - actualKeyLenInBytes); } if (pCipherSetupData->cipherAlgorithm != CPA_CY_SYM_CIPHER_AES_XTS) *pSizeInBytes += targetKeyLenInBytes; switch (pCipherSetupData->cipherAlgorithm) { /* For Kasumi in F8 mode Cipher Key is concatenated with * Cipher Key XOR-ed with Key Modifier (CK||CK^KM) */ case CPA_CY_SYM_CIPHER_KASUMI_F8: { Cpa32U wordIndex = 0; Cpa32U *pu32CipherKey = (Cpa32U *)pCipherSetupData->pCipherKey; Cpa32U *pTempKey = (Cpa32U *)(pCipherKey + targetKeyLenInBytes); /* XOR Key with KASUMI F8 key modifier at 4 bytes level */ for (wordIndex = 0; wordIndex < LAC_BYTES_TO_LONGWORDS(targetKeyLenInBytes); wordIndex++) { pTempKey[wordIndex] = pu32CipherKey[wordIndex] ^ LAC_CIPHER_KASUMI_F8_KEY_MODIFIER_4_BYTES; } *pSizeInBytes += targetKeyLenInBytes; /* also add padding for F8 */ *pSizeInBytes += LAC_QUADWORDS_TO_BYTES(ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR); LAC_OS_BZERO((Cpa8U *)pTempKey + targetKeyLenInBytes, LAC_QUADWORDS_TO_BYTES( ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR)); } break; /* For AES in F8 mode Cipher Key is concatenated with * Cipher Key XOR-ed with Key Mask (CK||CK^KM) */ case CPA_CY_SYM_CIPHER_AES_F8: { Cpa32U index = 0; Cpa8U *pTempKey = pCipherKey + (targetKeyLenInBytes / 2); *pSizeInBytes += targetKeyLenInBytes; /* XOR Key with key Mask */ for (index = 0; index < targetKeyLenInBytes; index++) { pTempKey[index] = pCipherKey[index] ^ pTempKey[index]; } pTempKey = (pCipherKey + targetKeyLenInBytes); tempKeyLenInBytes = 2UL * targetKeyLenInBytes; /* Check for overflow */ if (!(tempKeyLenInBytes & UINT_OVERFLOW)) { /* also add padding for AES F8 */ *pSizeInBytes += 2 * targetKeyLenInBytes; LAC_OS_BZERO(pTempKey, 2 * targetKeyLenInBytes); } } break; case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: { /* For Snow3G zero area after the key for FW */ LAC_OS_BZERO(pCipherKey + targetKeyLenInBytes, ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); *pSizeInBytes += ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; } break; case CPA_CY_SYM_CIPHER_ZUC_EEA3: { if (targetKeyLenInBytes == ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) { /* For ZUC zero area after the key for FW */ LAC_OS_BZERO(pCipherKey + targetKeyLenInBytes, ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); *pSizeInBytes += ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ; } else if (targetKeyLenInBytes == ICP_QAT_HW_ZUC_256_KEY_SZ) { /* For ZUC zero area after the key for FW */ LAC_OS_BZERO(pCipherKey + targetKeyLenInBytes, ICP_QAT_HW_ZUC_256_IV_SZ); *pSizeInBytes += ICP_QAT_HW_ZUC_256_IV_SZ; } } break; case CPA_CY_SYM_CIPHER_AES_XTS: { /* For AES in XTS mode Cipher Key is concatenated with * second Cipher Key which is used for tweak calculation * (CK1||CK2). For decryption Cipher Key needs to be converted * to reverse key.*/ if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE == sliceType) { Cpa32U key_len = pCipherSetupData->cipherKeyLenInBytes >> 1; osalMemCopy(pSessionDesc->cipherAesXtsKey1Forward, pCipherSetupData->pCipherKey, key_len); osalAESKeyExpansionForward( pSessionDesc->cipherAesXtsKey1Forward, key_len, (UINT32 *)pSessionDesc->cipherAesXtsKey1Reverse); osalMemCopy(pSessionDesc->cipherAesXtsKey2, pCipherSetupData->pCipherKey + key_len, key_len); if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == pCipherSetupData->cipherDirection) { osalMemCopy(pCipherKey, pSessionDesc->cipherAesXtsKey1Reverse, key_len); } else { osalMemCopy(pCipherKey, pSessionDesc->cipherAesXtsKey1Forward, key_len); } } *pSizeInBytes += targetKeyLenInBytes; } break; default: break; } } } /***************************************************************************** * External functions *****************************************************************************/ Cpa8U LacSymQat_CipherBlockSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm) { Cpa8U blockSize = 0; switch (cipherAlgorithm) { case CPA_CY_SYM_CIPHER_ARC4: blockSize = LAC_CIPHER_ARC4_BLOCK_LEN_BYTES; break; /* Handle AES or AES_F8 */ case CPA_CY_SYM_CIPHER_AES_ECB: case CPA_CY_SYM_CIPHER_AES_CBC: case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_AES_CCM: case CPA_CY_SYM_CIPHER_AES_GCM: case CPA_CY_SYM_CIPHER_AES_XTS: case CPA_CY_SYM_CIPHER_AES_F8: blockSize = ICP_QAT_HW_AES_BLK_SZ; break; /* Handle DES */ case CPA_CY_SYM_CIPHER_DES_ECB: case CPA_CY_SYM_CIPHER_DES_CBC: blockSize = ICP_QAT_HW_DES_BLK_SZ; break; /* Handle TRIPLE DES */ case CPA_CY_SYM_CIPHER_3DES_ECB: case CPA_CY_SYM_CIPHER_3DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CTR: blockSize = ICP_QAT_HW_3DES_BLK_SZ; break; case CPA_CY_SYM_CIPHER_KASUMI_F8: blockSize = ICP_QAT_HW_KASUMI_BLK_SZ; break; case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: blockSize = ICP_QAT_HW_SNOW_3G_BLK_SZ; break; case CPA_CY_SYM_CIPHER_ZUC_EEA3: blockSize = ICP_QAT_HW_ZUC_3G_BLK_SZ; break; case CPA_CY_SYM_CIPHER_NULL: blockSize = LAC_CIPHER_NULL_BLOCK_LEN_BYTES; break; case CPA_CY_SYM_CIPHER_CHACHA: blockSize = ICP_QAT_HW_CHACHAPOLY_BLK_SZ; break; /* SM4 */ case CPA_CY_SYM_CIPHER_SM4_ECB: case CPA_CY_SYM_CIPHER_SM4_CBC: case CPA_CY_SYM_CIPHER_SM4_CTR: blockSize = ICP_QAT_HW_SM4_BLK_SZ; break; default: LAC_ENSURE(CPA_FALSE, "Algorithm not supported in Cipher"); } return blockSize; } Cpa32U LacSymQat_CipherIvSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm) { Cpa32U ivSize = 0; switch (cipherAlgorithm) { case CPA_CY_SYM_CIPHER_ARC4: ivSize = LAC_CIPHER_ARC4_STATE_LEN_BYTES; break; case CPA_CY_SYM_CIPHER_KASUMI_F8: ivSize = ICP_QAT_HW_KASUMI_BLK_SZ; break; case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: ivSize = ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; break; case CPA_CY_SYM_CIPHER_ZUC_EEA3: ivSize = ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ; break; case CPA_CY_SYM_CIPHER_CHACHA: ivSize = ICP_QAT_HW_CHACHAPOLY_IV_SZ; break; case CPA_CY_SYM_CIPHER_AES_ECB: case CPA_CY_SYM_CIPHER_DES_ECB: case CPA_CY_SYM_CIPHER_3DES_ECB: case CPA_CY_SYM_CIPHER_SM4_ECB: case CPA_CY_SYM_CIPHER_NULL: /* for all ECB Mode IV size is 0 */ break; default: ivSize = LacSymQat_CipherBlockSizeBytesGet(cipherAlgorithm); } return ivSize; } inline CpaStatus LacSymQat_CipherRequestParamsPopulate( lac_session_desc_t *pSessionDesc, icp_qat_fw_la_bulk_req_t *pReq, Cpa32U cipherOffsetInBytes, Cpa32U cipherLenInBytes, Cpa64U ivBufferPhysAddr, Cpa8U *pIvBufferVirt) { icp_qat_fw_la_cipher_req_params_t *pCipherReqParams; icp_qat_fw_cipher_cd_ctrl_hdr_t *pCipherCdCtrlHdr; icp_qat_fw_serv_specif_flags *pCipherSpecificFlags; Cpa32U usedBufSize = 0; Cpa32U totalBufSize = 0; #ifdef ICP_PARAM_CHECK LAC_ENSURE(NULL != pReq, "LacSymQat_CipherRequestParamsPopulate - " "pReq is NULL\n"); #endif pCipherReqParams = (icp_qat_fw_la_cipher_req_params_t *)((Cpa8U *)&(pReq->serv_specif_rqpars) + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); pCipherCdCtrlHdr = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pReq->cd_ctrl); pCipherSpecificFlags = &(pReq->comn_hdr.serv_specif_flags); pCipherReqParams->cipher_offset = cipherOffsetInBytes; pCipherReqParams->cipher_length = cipherLenInBytes; /* Don't copy the buffer into the Msg if * it's too big for the cipher_IV_array * OR if the FW needs to update it * OR if there's no buffer supplied * OR if last partial */ if ((pCipherCdCtrlHdr->cipher_state_sz > LAC_SYM_QAT_HASH_IV_REQ_MAX_SIZE_QW) || (ICP_QAT_FW_LA_UPDATE_STATE_GET(*pCipherSpecificFlags) == ICP_QAT_FW_LA_UPDATE_STATE) || (pIvBufferVirt == NULL) || (ICP_QAT_FW_LA_PARTIAL_GET(*pCipherSpecificFlags) == ICP_QAT_FW_LA_PARTIAL_END)) { /* Populate the field with a ptr to the flat buffer */ pCipherReqParams->u.s.cipher_IV_ptr = ivBufferPhysAddr; pCipherReqParams->u.s.resrvd1 = 0; /* Set the flag indicating the field format */ ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(*pCipherSpecificFlags, ICP_QAT_FW_CIPH_IV_64BIT_PTR); } else { /* Populate the field with the contents of the buffer, * zero field first as data may be smaller than the field */ totalBufSize = LAC_LONGWORDS_TO_BYTES(ICP_QAT_FW_NUM_LONGWORDS_4); usedBufSize = LAC_QUADWORDS_TO_BYTES(pCipherCdCtrlHdr->cipher_state_sz); /* Only initialise unused buffer if applicable*/ if (usedBufSize < totalBufSize) { osalMemSet( (&pCipherReqParams->u .cipher_IV_array[usedBufSize & LAC_UNUSED_POS_MASK]), 0, totalBufSize - usedBufSize); } /* In case of XTS mode using UCS slice, always encrypt the embedded IV. * IV provided by user needs to be encrypted to calculate initial tweak, * use pCipherReqParams->u.cipher_IV_array as destination buffer for * tweak value */ if (ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE == pSessionDesc->cipherSliceType && LAC_CIPHER_IS_XTS_MODE(pSessionDesc->cipherAlgorithm)) { osalAESEncrypt(pSessionDesc->cipherAesXtsKey2, pSessionDesc->cipherKeyLenInBytes >> 1, pIvBufferVirt, (Cpa8U *)pCipherReqParams->u.cipher_IV_array); } else { osalMemCopy(pCipherReqParams->u.cipher_IV_array, pIvBufferVirt, usedBufSize); } /* Set the flag indicating the field format */ ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(*pCipherSpecificFlags, ICP_QAT_FW_CIPH_IV_16BYTE_DATA); } return CPA_STATUS_SUCCESS; } void LacSymQat_CipherArc4StateInit(const Cpa8U *pKey, Cpa32U keyLenInBytes, Cpa8U *pArc4CipherState) { Cpa32U i = 0; Cpa32U j = 0; Cpa32U k = 0; for (i = 0; i < LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; ++i) { pArc4CipherState[i] = (Cpa8U)i; } for (i = 0, k = 0; i < LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; ++i, ++k) { Cpa8U swap = 0; if (k >= keyLenInBytes) k -= keyLenInBytes; j = (j + pArc4CipherState[i] + pKey[k]); if (j >= LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES) j %= LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; /* Swap state[i] & state[j] */ swap = pArc4CipherState[i]; pArc4CipherState[i] = pArc4CipherState[j]; pArc4CipherState[j] = swap; } /* Initialise i & j values for QAT */ pArc4CipherState[LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES] = 0; pArc4CipherState[LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES + 1] = 0; } /* Update the cipher_key_sz in the Request cache prepared and stored * in the session */ void LacSymQat_CipherXTSModeUpdateKeyLen(lac_session_desc_t *pSessionDesc, Cpa32U newKeySizeInBytes) { icp_qat_fw_cipher_cd_ctrl_hdr_t *pCipherControlBlock = NULL; pCipherControlBlock = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pSessionDesc->reqCacheFtr.cd_ctrl); pCipherControlBlock->cipher_key_sz = LAC_BYTES_TO_QUADWORDS(newKeySizeInBytes); } lac_sym_qat_constants_table.c000066400000000000000000000402331503624047500347440ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/qat/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_qat_constants_table.c * * @ingroup LacSymQat ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_common.h" #include "icp_qat_fw_la.h" #include "lac_log.h" #include "lac_mem.h" #include "sal_string_parse.h" #include "lac_sal_types_crypto.h" #include "sal_types_compression.h" STATIC uint8_t icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_DELIMITER] [ICP_QAT_HW_CIPHER_MODE_DELIMITER][2] [2]; /* IA version */ STATIC uint8_t icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_DELIMITER] [ICP_QAT_HW_AUTH_MODE_DELIMITER] [2]; /* IA version */ #define ICP_QAT_HW_FILL_LOOKUP_TBLS \ { \ \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_DES] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 9; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_DES] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_DECRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 10; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_DES] \ [ICP_QAT_HW_CIPHER_CBC_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 11; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_DES] \ [ICP_QAT_HW_CIPHER_CBC_MODE] \ [ICP_QAT_HW_CIPHER_DECRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 12; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_DES] \ [ICP_QAT_HW_CIPHER_CTR_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 13; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 14; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_KEY_CONVERT] = 15; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_DECRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 16; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_DECRYPT] \ [ICP_QAT_HW_CIPHER_KEY_CONVERT] = 17; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_CBC_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 18; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_CBC_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_KEY_CONVERT] = 19; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_CBC_MODE] \ [ICP_QAT_HW_CIPHER_DECRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 20; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_CBC_MODE] \ [ICP_QAT_HW_CIPHER_DECRYPT] \ [ICP_QAT_HW_CIPHER_KEY_CONVERT] = 21; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_CTR_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 22; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_AES128] \ [ICP_QAT_HW_CIPHER_F8_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 23; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_ARC4] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_NO_CONVERT] = 24; \ icp_qat_hw_cipher_lookup_tbl[ICP_QAT_HW_CIPHER_ALGO_ARC4] \ [ICP_QAT_HW_CIPHER_ECB_MODE] \ [ICP_QAT_HW_CIPHER_ENCRYPT] \ [ICP_QAT_HW_CIPHER_KEY_CONVERT] = 25; \ \ icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_MD5] \ [ICP_QAT_HW_AUTH_MODE0] \ [ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED] = 37; \ icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_SHA1] \ [ICP_QAT_HW_AUTH_MODE0] \ [ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED] = 41; \ icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_SHA1] \ [ICP_QAT_HW_AUTH_MODE1] \ [ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED] = 46; \ icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_SHA224] \ [ICP_QAT_HW_AUTH_MODE0] \ [ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED] = 48; \ icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_SHA256] \ [ICP_QAT_HW_AUTH_MODE0] \ [ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED] = 54; \ icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_SHA384] \ [ICP_QAT_HW_AUTH_MODE0] \ [ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED] = 60; \ icp_qat_hw_auth_lookup_tbl[ICP_QAT_HW_AUTH_ALGO_SHA512] \ [ICP_QAT_HW_AUTH_MODE0] \ [ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED] = 70; \ } /** ***************************************************************************** * @ingroup LacSymQat * LacSymQat_ConstantsInitLookupTables * * *****************************************************************************/ void LacSymQat_ConstantsInitLookupTables(CpaInstanceHandle instanceHandle) { sal_service_t *pService = (sal_service_t *)instanceHandle; lac_sym_qat_constants_t *pConstantsLookupTables; LAC_ENSURE_NOT_NULL(pService); /* Note the global tables are initialised first, then copied * to the service which probably seems like a waste of memory * and processing cycles as the global tables are never needed again * but this allows use of the ICP_QAT_HW_FILL_LOOKUP_TBLS macro * supplied by FW without modification */ if (SAL_SERVICE_TYPE_COMPRESSION == pService->type) { pConstantsLookupTables = &(((sal_compression_service_t *)pService) ->pDcChainService->constantsLookupTables); } else { pConstantsLookupTables = &(((sal_crypto_service_t *)pService)->constantsLookupTables); } /* First fill the global lookup tables with zeroes. */ osalMemSet( icp_qat_hw_cipher_lookup_tbl, 0, sizeof(icp_qat_hw_cipher_lookup_tbl)); osalMemSet( icp_qat_hw_auth_lookup_tbl, 0, sizeof(icp_qat_hw_auth_lookup_tbl)); /* Override lookup tables with the offsets into the SHRAM table * for supported algorithms/modes */ ICP_QAT_HW_FILL_LOOKUP_TBLS; /* Copy the global tables to the service instance */ memcpy(pConstantsLookupTables->cipher_offset, icp_qat_hw_cipher_lookup_tbl, sizeof(pConstantsLookupTables->cipher_offset)); memcpy(pConstantsLookupTables->auth_offset, icp_qat_hw_auth_lookup_tbl, sizeof(pConstantsLookupTables->auth_offset)); } /** ***************************************************************************** * @ingroup LacSymQat * LacSymQat_ConstantsGetCipherOffset * * *****************************************************************************/ void LacSymQat_ConstantsGetCipherOffset(CpaInstanceHandle instanceHandle, uint8_t algo, uint8_t mode, uint8_t direction, uint8_t convert, uint8_t *poffset) { sal_service_t *pService = (sal_service_t *)instanceHandle; lac_sym_qat_constants_t *pConstantsLookupTables; LAC_ENSURE_RANGE(algo, 0, ICP_QAT_HW_CIPHER_DELIMITER); LAC_ENSURE_RANGE(mode, 0, ICP_QAT_HW_CIPHER_MODE_DELIMITER); LAC_ENSURE_RANGE(direction, 0, 2); LAC_ENSURE_RANGE(convert, 0, 2); LAC_ENSURE_NOT_NULL(poffset); LAC_ENSURE_NOT_NULL(pService); if (SAL_SERVICE_TYPE_COMPRESSION == pService->type) { pConstantsLookupTables = &(((sal_compression_service_t *)pService) ->pDcChainService->constantsLookupTables); } else { pConstantsLookupTables = &(((sal_crypto_service_t *)pService)->constantsLookupTables); } *poffset = pConstantsLookupTables->cipher_offset[algo][mode][direction][convert]; LAC_LOG_DEBUG2( "cipher constants offset (quad_words) = %d (0x%x)", *poffset, *poffset); } /** ***************************************************************************** * @ingroup LacSymQat * LacSymQat_ConstantsGetAuthOffset * * *****************************************************************************/ void LacSymQat_ConstantsGetAuthOffset(CpaInstanceHandle instanceHandle, uint8_t algo, uint8_t mode, uint8_t nested, uint8_t *poffset) { sal_service_t *pService = (sal_service_t *)instanceHandle; lac_sym_qat_constants_t *pConstantsLookupTables; LAC_ENSURE_RANGE(algo, 0, ICP_QAT_HW_AUTH_ALGO_DELIMITER); LAC_ENSURE_RANGE(mode, 0, ICP_QAT_HW_AUTH_MODE_DELIMITER); LAC_ENSURE_RANGE(nested, 0, 2); LAC_ENSURE_NOT_NULL(poffset); LAC_ENSURE_NOT_NULL(pService); if (SAL_SERVICE_TYPE_COMPRESSION == pService->type) { pConstantsLookupTables = &(((sal_compression_service_t *)pService) ->pDcChainService->constantsLookupTables); } else { pConstantsLookupTables = &(((sal_crypto_service_t *)pService)->constantsLookupTables); } *poffset = pConstantsLookupTables->auth_offset[algo][mode][nested]; LAC_LOG_DEBUG2( "auth constants offset (quad_words) = %d (0x%x)", *poffset, *poffset); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_hash.c000066400000000000000000001172561503624047500325750ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_qat_hash.c * * @ingroup LacSymQatHash * * Implementation for populating QAT data structures for hash operation ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_cy_sym.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "lac_mem.h" #include "lac_sym.h" #include "lac_common.h" #include "lac_sym_qat.h" #include "lac_list.h" #include "lac_sal_types.h" #include "lac_sal_types_crypto.h" #include "lac_sym_qat_hash.h" #include "lac_sym_qat_hash_defs_lookup.h" /** * This structure contains pointers into the hash setup block of the * security descriptor. As the hash setup block contains fields that * are of variable length, pointers must be calculated to these fields * and the hash setup block is populated using these pointers. */ typedef struct lac_hash_blk_ptrs_s { icp_qat_hw_auth_setup_t *pInHashSetup; /**< inner hash setup */ Cpa8U *pInHashInitState1; /**< inner initial state 1 */ Cpa8U *pInHashInitState2; /**< inner initial state 2 */ icp_qat_hw_auth_setup_t *pOutHashSetup; /**< outer hash setup */ Cpa8U *pOutHashInitState1; /**< outer hash initial state */ } lac_hash_blk_ptrs_t; typedef struct lac_hash_blk_ptrs_optimised_s { Cpa8U *pInHashInitState1; /**< inner initial state 1 */ Cpa8U *pInHashInitState2; /**< inner initial state 2 */ } lac_hash_blk_ptrs_optimised_t; /** * This function calculates the pointers into the hash setup block * based on the control block * * @param[in] pHashControlBlock Pointer to hash control block * @param[in] pHwBlockBase pointer to base of hardware block * @param[out] pHashBlkPtrs structure containing pointers to * various fields in the hash setup block * * @return void */ STATIC void LacSymQat_HashHwBlockPtrsInit( icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, void *pHwBlockBase, lac_hash_blk_ptrs_t *pHashBlkPtrs); STATIC void LacSymQat_HashSetupBlockOptimisedFormatInit( const CpaCySymHashSetupData *pHashSetupData, icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, void *pHwBlockBase, icp_qat_hw_auth_mode_t qatHashMode, lac_sym_qat_hash_precompute_info_t *pPrecompute, lac_sym_qat_hash_defs_t *pHashDefs, lac_sym_qat_hash_defs_t *pOuterHashDefs); /** * This function populates the hash setup block * * @param[in] pHashSetupData Pointer to the hash context * @param[in] pHashControlBlock Pointer to hash control block * @param[in] pHwBlockBase pointer to base of hardware block * @param[in] qatHashMode QAT hash mode * @param[in] pPrecompute For auth mode, this is the pointer * to the precompute data. Otherwise this * should be set to NULL * @param[in] pHashDefs Pointer to Hash definitions * @param[in] pOuterHashDefs Pointer to Outer Hash definitions. * Required for nested hash mode only * @param[in] instanceHandle Instance Handle * * @return void */ STATIC void LacSymQat_HashSetupBlockInit( const CpaCySymHashSetupData *pHashSetupData, icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, void *pHwBlockBase, icp_qat_hw_auth_mode_t qatHashMode, lac_sym_qat_hash_precompute_info_t *pPrecompute, lac_sym_qat_hash_defs_t *pHashDefs, lac_sym_qat_hash_defs_t *pOuterHashDefs, CpaInstanceHandle instanceHandle); /** @ingroup LacSymQatHash */ void LacSymQat_HashGetCfgData(CpaInstanceHandle pInstance, icp_qat_hw_auth_mode_t qatHashMode, CpaCySymHashMode apiHashMode, CpaCySymHashAlgorithm apiHashAlgorithm, icp_qat_hw_auth_algo_t *pQatAlgorithm, CpaBoolean *pQatNested, Cpa32U authKeyLenInBytes, Cpa32U digestResultLenInBytes) { lac_sym_qat_hash_defs_t *pHashDefs = NULL; LAC_ENSURE_NOT_NULL(pInstance); LAC_ENSURE_NOT_NULL(pQatAlgorithm); LAC_ENSURE_NOT_NULL(pQatNested); LacSymQat_HashDefsLookupGet(pInstance, apiHashAlgorithm, &pHashDefs, authKeyLenInBytes, digestResultLenInBytes); LAC_ENSURE_NOT_NULL(pHashDefs); *pQatAlgorithm = pHashDefs->qatInfo->algoEnc; if (IS_HASH_MODE_2(qatHashMode)) { /* set bit for nested hashing */ *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED; } /* Nested hash in mode 0. */ else if (CPA_CY_SYM_HASH_MODE_NESTED == apiHashMode) { /* set bit for nested hashing */ *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED; } /* mode0 - plain or mode1 - auth */ else { *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED; } } /** @ingroup LacSymQatHash */ void LacSymQat_HashContentDescInit( icp_qat_la_bulk_req_ftr_t *pMsg, CpaInstanceHandle instanceHandle, const CpaCySymHashSetupData *pHashSetupData, void *pHwBlockBase, Cpa32U hwBlockOffsetInQuadWords, icp_qat_fw_slice_t nextSlice, icp_qat_hw_auth_mode_t qatHashMode, CpaBoolean useSymConstantsTable, CpaBoolean useOptimisedContentDesc, lac_sym_qat_hash_precompute_info_t *pPrecompute, Cpa32U *pHashBlkSizeInBytes) { icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); lac_sym_qat_hash_defs_t *pHashDefs = NULL; lac_sym_qat_hash_defs_t *pOuterHashDefs = NULL; Cpa32U hashSetupBlkSize = 0; Cpa32U authKeyLenInBytes = pHashSetupData->authModeSetupData.authKeyLenInBytes; Cpa32U digestResultLenInBytes = pHashSetupData->digestResultLenInBytes; LAC_ENSURE_NOT_NULL(pHashSetupData); LAC_ENSURE_NOT_NULL(pHwBlockBase); LAC_ENSURE_NOT_NULL(pHashBlkSizeInBytes); LacSymQat_HashDefsLookupGet(instanceHandle, pHashSetupData->hashAlgorithm, &pHashDefs, authKeyLenInBytes, digestResultLenInBytes); LAC_ENSURE_NOT_NULL(pHashDefs); /* setup the offset in QuadWords into the HW block */ cd_ctrl->hash_cfg_offset = (Cpa8U)hwBlockOffsetInQuadWords; ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl, nextSlice); ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_AUTH); /* Hmac in mode 2 TLS */ if (IS_HASH_MODE_2(qatHashMode)) { /* set bit for HMAC mode2 */ ICP_QAT_FW_HASH_FLAG_MODE2_SET(cd_ctrl->hash_flags, QAT_FW_LA_MODE2); } /* Nested hash in mode 0 */ else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { /* Set bit for nested hashing. * Make sure not to overwrite other flags in hash_flags byte. */ ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED); } /* mode0 - plain or mode1 - auth */ else { ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED); } /* set the final digest size */ cd_ctrl->final_sz = (Cpa8U)pHashSetupData->digestResultLenInBytes; /* set the state1 size */ cd_ctrl->inner_state1_sz = LAC_ALIGN_POW2_ROUNDUP( pHashDefs->qatInfo->state1Length, LAC_QUAD_WORD_IN_BYTES); /* set the inner result size to the digest length */ cd_ctrl->inner_res_sz = (Cpa8U)pHashDefs->algInfo->digestLength; /* set the state2 size - only for mode 1 Auth algos and AES CBC MAC */ if (IS_HASH_MODE_1(qatHashMode) || pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_AES_CBC_MAC || pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) { cd_ctrl->inner_state2_sz = LAC_ALIGN_POW2_ROUNDUP( pHashDefs->qatInfo->state2Length, LAC_QUAD_WORD_IN_BYTES); } else { cd_ctrl->inner_state2_sz = 0; } if (useSymConstantsTable) { cd_ctrl->inner_state2_offset = LAC_BYTES_TO_QUADWORDS(cd_ctrl->inner_state1_sz); /* size of inner part of hash setup block */ hashSetupBlkSize = cd_ctrl->inner_state1_sz + cd_ctrl->inner_state2_sz; } else { cd_ctrl->inner_state2_offset = cd_ctrl->hash_cfg_offset + LAC_BYTES_TO_QUADWORDS(sizeof(icp_qat_hw_auth_setup_t) + cd_ctrl->inner_state1_sz); /* size of inner part of hash setup block */ hashSetupBlkSize = sizeof(icp_qat_hw_auth_setup_t) + cd_ctrl->inner_state1_sz + cd_ctrl->inner_state2_sz; } /* For nested hashing - Fill in the outer fields */ if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode || IS_HASH_MODE_2(qatHashMode)) { /* For nested - use the outer algorithm. This covers TLS and * nested hash. For HMAC mode2 use inner algorithm again */ CpaCySymHashAlgorithm outerAlg = (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) ? pHashSetupData->nestedModeSetupData.outerHashAlgorithm : pHashSetupData->hashAlgorithm; LacSymQat_HashDefsLookupGet(instanceHandle, outerAlg, &pOuterHashDefs, authKeyLenInBytes, digestResultLenInBytes); LAC_ENSURE_NOT_NULL(pOuterHashDefs); /* outer config offset */ cd_ctrl->outer_config_offset = cd_ctrl->inner_state2_offset + LAC_BYTES_TO_QUADWORDS(cd_ctrl->inner_state2_sz); cd_ctrl->outer_state1_sz = LAC_ALIGN_POW2_ROUNDUP( pOuterHashDefs->algInfo->stateSize, LAC_QUAD_WORD_IN_BYTES); /* outer result size */ cd_ctrl->outer_res_sz = (Cpa8U)pOuterHashDefs->algInfo->digestLength; /* outer_prefix_offset will be the size of the inner prefix data * plus the hash state storage size. */ /* The prefix buffer is part of the ReqParams, so this param will be * setup where ReqParams are set up */ /* add on size of outer part of hash block */ hashSetupBlkSize += sizeof(icp_qat_hw_auth_setup_t) + cd_ctrl->outer_state1_sz; } else { cd_ctrl->outer_config_offset = 0; cd_ctrl->outer_state1_sz = 0; cd_ctrl->outer_res_sz = 0; } if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) { /* add the size for the cipher config word, the key and the IV*/ hashSetupBlkSize += sizeof(icp_qat_hw_cipher_config_t) + pHashSetupData->authModeSetupData.authKeyLenInBytes + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; } *pHashBlkSizeInBytes = hashSetupBlkSize; if (useOptimisedContentDesc) { LAC_LOG_DEBUG("Hash HwSetupBlock in DRAM optimised CD"); LacSymQat_HashSetupBlockOptimisedFormatInit(pHashSetupData, cd_ctrl, pHwBlockBase, qatHashMode, pPrecompute, pHashDefs, pOuterHashDefs); } else if (!useSymConstantsTable) { /***************************************************************************** * Populate Hash Setup block * *****************************************************************************/ LacSymQat_HashSetupBlockInit(pHashSetupData, cd_ctrl, pHwBlockBase, qatHashMode, pPrecompute, pHashDefs, pOuterHashDefs, instanceHandle); LAC_LOG_DEBUG("Hash HwSetupBlock in DRAM"); } } /* This fn populates fields in both the CD ctrl block and the ReqParams block * which describe the Hash ReqParams: * cd_ctrl.outer_prefix_offset * cd_ctrl.outer_prefix_sz * req_params.inner_prefix_sz/aad_sz * req_params.hash_state_sz * req_params.auth_res_sz * */ void LacSymQat_HashSetupReqParamsMetaData( icp_qat_la_bulk_req_ftr_t *pMsg, CpaInstanceHandle instanceHandle, const CpaCySymHashSetupData *pHashSetupData, CpaBoolean hashStateBuffer, icp_qat_hw_auth_mode_t qatHashMode, CpaBoolean digestVerify) { icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = NULL; icp_qat_la_auth_req_params_t *pHashReqParams = NULL; lac_sym_qat_hash_defs_t *pHashDefs = NULL; Cpa32U authKeyLenInBytes = pHashSetupData->authModeSetupData.authKeyLenInBytes; Cpa32U digestResultLenInBytes = pHashSetupData->digestResultLenInBytes; LAC_ENSURE_NOT_NULL(pMsg); LAC_ENSURE_NOT_NULL(pHashSetupData); cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); pHashReqParams = (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); LacSymQat_HashDefsLookupGet(instanceHandle, pHashSetupData->hashAlgorithm, &pHashDefs, authKeyLenInBytes, digestResultLenInBytes); LAC_ENSURE_NOT_NULL(pHashDefs); /* Hmac in mode 2 TLS */ if (IS_HASH_MODE_2(qatHashMode)) { /* Inner and outer prefixes are the block length */ pHashReqParams->u2.inner_prefix_sz = (Cpa8U)pHashDefs->algInfo->blockLength; cd_ctrl->outer_prefix_sz = (Cpa8U)pHashDefs->algInfo->blockLength; cd_ctrl->outer_prefix_offset = LAC_BYTES_TO_QUADWORDS(LAC_ALIGN_POW2_ROUNDUP( (pHashReqParams->u2.inner_prefix_sz), LAC_QUAD_WORD_IN_BYTES)); } /* Nested hash in mode 0 */ else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { /* set inner and outer prefixes */ pHashReqParams->u2.inner_prefix_sz = (Cpa8U)pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes; cd_ctrl->outer_prefix_sz = (Cpa8U)pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes; cd_ctrl->outer_prefix_offset = LAC_BYTES_TO_QUADWORDS(LAC_ALIGN_POW2_ROUNDUP( (pHashReqParams->u2.inner_prefix_sz), LAC_QUAD_WORD_IN_BYTES)); } /* mode0 - plain or mode1 - auth */ else { Cpa16U aadDataSize = 0; /* For Auth Encrypt set the aad size */ if (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) { /* at the beginning of the buffer there is B0 block */ aadDataSize = LAC_HASH_AES_CCM_BLOCK_SIZE; /* then, if there is some 'a' data, the buffer will store encoded * length of 'a' and 'a' itself */ if (pHashSetupData->authModeSetupData.aadLenInBytes > 0) { /* as the QAT API puts the requirement on the * pAdditionalAuthData not to be bigger than 240 bytes then we * just need 2 bytes to store encoded length of 'a' */ aadDataSize += sizeof(Cpa16U); aadDataSize += (Cpa16U)pHashSetupData->authModeSetupData.aadLenInBytes; } /* round the aad size to the multiple of CCM block size.*/ pHashReqParams->u2.aad_sz = LAC_ALIGN_POW2_ROUNDUP( aadDataSize, LAC_HASH_AES_CCM_BLOCK_SIZE); } else if (CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm) { aadDataSize = (Cpa16U)pHashSetupData->authModeSetupData.aadLenInBytes; /* round the aad size to the multiple of GCM hash block size. */ pHashReqParams->u2.aad_sz = LAC_ALIGN_POW2_ROUNDUP( aadDataSize, LAC_HASH_AES_GCM_BLOCK_SIZE); } else { pHashReqParams->u2.aad_sz = 0; } cd_ctrl->outer_prefix_sz = 0; cd_ctrl->outer_prefix_offset = 0; } /* If there is a hash state prefix buffer */ if (CPA_TRUE == hashStateBuffer) { /* Note, this sets up size for both aad and non-aad cases */ pHashReqParams->hash_state_sz = LAC_BYTES_TO_QUADWORDS( LAC_ALIGN_POW2_ROUNDUP(pHashReqParams->u2.inner_prefix_sz, LAC_QUAD_WORD_IN_BYTES) + LAC_ALIGN_POW2_ROUNDUP(cd_ctrl->outer_prefix_sz, LAC_QUAD_WORD_IN_BYTES)); } else { pHashReqParams->hash_state_sz = 0; } if (CPA_TRUE == digestVerify) { /* auth result size in bytes to be read in for a verify operation */ pHashReqParams->auth_res_sz = (Cpa8U)pHashSetupData->digestResultLenInBytes; } else { pHashReqParams->auth_res_sz = 0; } pHashReqParams->resrvd1 = 0; } void LacSymQat_HashHwBlockPtrsInit(icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl, void *pHwBlockBase, lac_hash_blk_ptrs_t *pHashBlkPtrs) { LAC_ENSURE_NOT_NULL(cd_ctrl); LAC_ENSURE_NOT_NULL(pHwBlockBase); LAC_ENSURE_NOT_NULL(pHashBlkPtrs); /* encoded offset for inner config is converted to a byte offset. */ pHashBlkPtrs->pInHashSetup = (icp_qat_hw_auth_setup_t *)((Cpa8U *)pHwBlockBase + (cd_ctrl->hash_cfg_offset * LAC_QUAD_WORD_IN_BYTES)); pHashBlkPtrs->pInHashInitState1 = (Cpa8U *)pHashBlkPtrs->pInHashSetup + sizeof(icp_qat_hw_auth_setup_t); pHashBlkPtrs->pInHashInitState2 = (Cpa8U *)(pHashBlkPtrs->pInHashInitState1) + cd_ctrl->inner_state1_sz; pHashBlkPtrs->pOutHashSetup = (icp_qat_hw_auth_setup_t *)((Cpa8U *)(pHashBlkPtrs->pInHashInitState2) + cd_ctrl->inner_state2_sz); pHashBlkPtrs->pOutHashInitState1 = (Cpa8U *)(pHashBlkPtrs->pOutHashSetup) + sizeof(icp_qat_hw_auth_setup_t); } STATIC void LacSymQat_HashSetupBlockInit( const CpaCySymHashSetupData *pHashSetupData, icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, void *pHwBlockBase, icp_qat_hw_auth_mode_t qatHashMode, lac_sym_qat_hash_precompute_info_t *pPrecompute, lac_sym_qat_hash_defs_t *pHashDefs, lac_sym_qat_hash_defs_t *pOuterHashDefs, CpaInstanceHandle instanceHandle) { Cpa32U innerConfig = 0; lac_hash_blk_ptrs_t hashBlkPtrs = {0}; Cpa32U aedHashCmpLength = 0; LacSymQat_HashHwBlockPtrsInit( pHashControlBlock, pHwBlockBase, &hashBlkPtrs); innerConfig = ICP_QAT_HW_AUTH_CONFIG_BUILD(qatHashMode, pHashDefs->qatInfo->algoEnc, pHashSetupData->digestResultLenInBytes); /* Set the Inner hash configuration */ hashBlkPtrs.pInHashSetup->auth_config.config = innerConfig; hashBlkPtrs.pInHashSetup->auth_config.reserved = 0; /* For mode 1 pre-computes for auth algorithms */ if (IS_HASH_MODE_1(qatHashMode) || CPA_CY_SYM_HASH_AES_CBC_MAC == pHashSetupData->hashAlgorithm || CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm) { /* for HMAC in mode 1 authCounter is the block size * else the authCounter is 0. The firmware expects the counter to be * big endian */ LAC_MEM_SHARED_WRITE_SWAP( hashBlkPtrs.pInHashSetup->auth_counter.counter, pHashDefs->qatInfo->authCounter); /* state 1 is set to 0 for the following algorithms */ if ((CPA_CY_SYM_HASH_AES_XCBC == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_CMAC == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_CBC_MAC == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_KASUMI_F9 == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm) || (CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm)) { LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1, pHashDefs->qatInfo->state1Length); } /* Pad remaining bytes of sha1 precomputes */ if (CPA_CY_SYM_HASH_SHA1 == pHashSetupData->hashAlgorithm) { Cpa32U state1PadLen = 0; Cpa32U state2PadLen = 0; if (pHashControlBlock->inner_state1_sz > pHashDefs->algInfo->stateSize) { state1PadLen = pHashControlBlock->inner_state1_sz - pHashDefs->algInfo->stateSize; } if (pHashControlBlock->inner_state2_sz > pHashDefs->algInfo->stateSize) { state2PadLen = pHashControlBlock->inner_state2_sz - pHashDefs->algInfo->stateSize; } if (state1PadLen > 0) { LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1 + pHashDefs->algInfo->stateSize, state1PadLen); } if (state2PadLen > 0) { LAC_OS_BZERO(hashBlkPtrs.pInHashInitState2 + pHashDefs->algInfo->stateSize, state2PadLen); } } LAC_ENSURE_NOT_NULL(pPrecompute); if (NULL != pPrecompute) { pPrecompute->state1Size = pHashDefs->qatInfo->state1Length; pPrecompute->state2Size = pHashDefs->qatInfo->state2Length; /* Set the destination for pre-compute state1 data to be written */ pPrecompute->pState1 = hashBlkPtrs.pInHashInitState1; /* Set the destination for pre-compute state1 data to be written */ pPrecompute->pState2 = hashBlkPtrs.pInHashInitState2; } } /* For digest and nested digest */ else { Cpa32U padLen = pHashControlBlock->inner_state1_sz - pHashDefs->algInfo->stateSize; /* counter set to 0 */ hashBlkPtrs.pInHashSetup->auth_counter.counter = 0; /* set the inner hash state 1 */ memcpy(hashBlkPtrs.pInHashInitState1, pHashDefs->algInfo->initState, pHashDefs->algInfo->stateSize); if (padLen > 0) { LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1 + pHashDefs->algInfo->stateSize, padLen); } } hashBlkPtrs.pInHashSetup->auth_counter.reserved = 0; /* Fill in the outer part of the hash setup block */ if ((CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode || IS_HASH_MODE_2(qatHashMode)) && (NULL != pOuterHashDefs)) { Cpa32U outerConfig = ICP_QAT_HW_AUTH_CONFIG_BUILD( qatHashMode, pOuterHashDefs->qatInfo->algoEnc, pHashSetupData->digestResultLenInBytes); Cpa32U padLen = pHashControlBlock->outer_state1_sz - pOuterHashDefs->algInfo->stateSize; /* populate the auth config */ hashBlkPtrs.pOutHashSetup->auth_config.config = outerConfig; hashBlkPtrs.pOutHashSetup->auth_config.reserved = 0; /* outer Counter set to 0 */ hashBlkPtrs.pOutHashSetup->auth_counter.counter = 0; hashBlkPtrs.pOutHashSetup->auth_counter.reserved = 0; /* set outer hash state 1 */ memcpy(hashBlkPtrs.pOutHashInitState1, pOuterHashDefs->algInfo->initState, pOuterHashDefs->algInfo->stateSize); if (padLen > 0) { LAC_OS_BZERO(hashBlkPtrs.pOutHashInitState1 + pOuterHashDefs->algInfo->stateSize, padLen); } } if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) { icp_qat_hw_cipher_config_t *pCipherConfig = (icp_qat_hw_cipher_config_t *)hashBlkPtrs.pOutHashSetup; pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD(ICP_QAT_HW_CIPHER_ECB_MODE, ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2, ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_ENCRYPT, aedHashCmpLength); pCipherConfig->reserved = 0; memcpy((Cpa8U *)pCipherConfig + sizeof(icp_qat_hw_cipher_config_t), pHashSetupData->authModeSetupData.authKey, pHashSetupData->authModeSetupData.authKeyLenInBytes); LAC_OS_BZERO((Cpa8U *)pCipherConfig + sizeof(icp_qat_hw_cipher_config_t) + pHashSetupData->authModeSetupData.authKeyLenInBytes, ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm) { icp_qat_hw_cipher_config_t *pCipherConfig = (icp_qat_hw_cipher_config_t *)hashBlkPtrs.pOutHashSetup; pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( ICP_QAT_HW_CIPHER_ECB_MODE, ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3, ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_ENCRYPT, aedHashCmpLength); pCipherConfig->reserved = 0; memcpy((Cpa8U *)pCipherConfig + sizeof(icp_qat_hw_cipher_config_t), pHashSetupData->authModeSetupData.authKey, pHashSetupData->authModeSetupData.authKeyLenInBytes); LAC_OS_BZERO((Cpa8U *)pCipherConfig + sizeof(icp_qat_hw_cipher_config_t) + pHashSetupData->authModeSetupData.authKeyLenInBytes, ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); } } void LacSymQat_HashOpHwBlockPtrsInit( icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl, void *pHwBlockBase, lac_hash_blk_ptrs_optimised_t *pHashBlkPtrs) { LAC_ENSURE_NOT_NULL(cd_ctrl); LAC_ENSURE_NOT_NULL(pHwBlockBase); LAC_ENSURE_NOT_NULL(pHashBlkPtrs); pHashBlkPtrs->pInHashInitState1 = (((Cpa8U *)pHwBlockBase) + 16); pHashBlkPtrs->pInHashInitState2 = (Cpa8U *)(pHashBlkPtrs->pInHashInitState1) + cd_ctrl->inner_state1_sz; } STATIC void LacSymQat_HashSetupBlockOptimisedFormatInit( const CpaCySymHashSetupData *pHashSetupData, icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, void *pHwBlockBase, icp_qat_hw_auth_mode_t qatHashMode, lac_sym_qat_hash_precompute_info_t *pPrecompute, lac_sym_qat_hash_defs_t *pHashDefs, lac_sym_qat_hash_defs_t *pOuterHashDefs) { Cpa32U state1PadLen = 0; Cpa32U state2PadLen = 0; lac_hash_blk_ptrs_optimised_t pHashBlkPtrs = {0}; LacSymQat_HashOpHwBlockPtrsInit( pHashControlBlock, pHwBlockBase, &pHashBlkPtrs); if (pHashControlBlock->inner_state1_sz > pHashDefs->algInfo->stateSize) { state1PadLen = pHashControlBlock->inner_state1_sz - pHashDefs->algInfo->stateSize; } if (pHashControlBlock->inner_state2_sz > pHashDefs->algInfo->stateSize) { state2PadLen = pHashControlBlock->inner_state2_sz - pHashDefs->algInfo->stateSize; } if (state1PadLen > 0) { LAC_OS_BZERO(pHashBlkPtrs.pInHashInitState1 + pHashDefs->algInfo->stateSize, state1PadLen); } if (state2PadLen > 0) { LAC_OS_BZERO(pHashBlkPtrs.pInHashInitState2 + pHashDefs->algInfo->stateSize, state2PadLen); } LAC_ENSURE_NOT_NULL(pPrecompute); if (NULL != pPrecompute) { pPrecompute->state1Size = pHashDefs->qatInfo->state1Length; pPrecompute->state2Size = pHashDefs->qatInfo->state2Length; /* Set the destination for pre-compute state1 data to be written */ pPrecompute->pState1 = pHashBlkPtrs.pInHashInitState1; /* Set the destination for pre-compute state1 data to be written */ pPrecompute->pState2 = pHashBlkPtrs.pInHashInitState2; } } void LacSymQat_HashStatePrefixAadBufferSizeGet( icp_qat_la_bulk_req_ftr_t *pMsg, lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf) { const icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl; icp_qat_la_auth_req_params_t *pHashReqParams; LAC_ENSURE_NOT_NULL(pMsg); LAC_ENSURE_NOT_NULL(pHashStateBuf); cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); pHashReqParams = (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); LAC_ENSURE_NOT_NULL(cd_ctrl); LAC_ENSURE_NOT_NULL(pHashReqParams); /* hash state storage needed to support partial packets. Space reserved * for this in all cases */ pHashStateBuf->stateStorageSzQuadWords = LAC_BYTES_TO_QUADWORDS( sizeof(icp_qat_hw_auth_counter_t) + cd_ctrl->inner_state1_sz); pHashStateBuf->prefixAadSzQuadWords = pHashReqParams->hash_state_sz; } void LacSymQat_HashStatePrefixAadBufferPopulate( lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, icp_qat_la_bulk_req_ftr_t *pMsg, Cpa8U *pInnerPrefixAad, Cpa8U innerPrefixSize, Cpa8U *pOuterPrefix, Cpa8U outerPrefixSize) { const icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); icp_qat_la_auth_req_params_t *pHashReqParams = (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); LAC_ENSURE_NOT_NULL(pHashStateBuf); LAC_ENSURE_NOT_NULL(cd_ctrl); /* * Let S be the supplied secret * S1 = S/2 if S is even and (S/2 + 1) if S is odd. * Set length S2 (inner prefix) = S1 and the start address * of S2 is S[S1/2] i.e. if S is odd then S2 starts at the last byte of S1 * _____________________________________________________________ * | outer prefix | padding | * |________________| | * | | * |____________________________________________________________| * | inner prefix | padding | * |________________| | * | | * |____________________________________________________________| * */ if (NULL != pInnerPrefixAad) { Cpa8U *pLocalInnerPrefix = (Cpa8U *)(pHashStateBuf->pData) + LAC_QUADWORDS_TO_BYTES(pHashStateBuf->stateStorageSzQuadWords); Cpa8U padding = pHashReqParams->u2.inner_prefix_sz - innerPrefixSize; /* copy the inner prefix or aad data */ memcpy(pLocalInnerPrefix, pInnerPrefixAad, innerPrefixSize); /* Reset with zeroes any area reserved for padding in this block */ if (0 < padding) { LAC_OS_BZERO(pLocalInnerPrefix + innerPrefixSize, padding); } } if (NULL != pOuterPrefix) { Cpa8U *pLocalOuterPrefix = (Cpa8U *)pHashStateBuf->pData + LAC_QUADWORDS_TO_BYTES(pHashStateBuf->stateStorageSzQuadWords + cd_ctrl->outer_prefix_offset); Cpa8U padding = LAC_QUADWORDS_TO_BYTES(pHashStateBuf->prefixAadSzQuadWords) - pHashReqParams->u2.inner_prefix_sz - outerPrefixSize; /* copy the outer prefix */ memcpy(pLocalOuterPrefix, pOuterPrefix, outerPrefixSize); /* Reset with zeroes any area reserved for padding in this block */ if (0 < padding) { LAC_OS_BZERO(pLocalOuterPrefix + outerPrefixSize, padding); } } } inline CpaStatus LacSymQat_HashRequestParamsPopulate( icp_qat_fw_la_bulk_req_t *pReq, Cpa32U authOffsetInBytes, Cpa32U authLenInBytes, sal_service_t *pService, lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, Cpa32U packetType, Cpa32U hashResultSize, CpaBoolean digestVerify, Cpa8U *pAuthResult, CpaCySymHashAlgorithm alg, void *pHKDFSecret) { Cpa64U authResultPhys = 0; icp_qat_fw_la_auth_req_params_t *pHashReqParams; #ifdef ICP_PARAM_CHECK LAC_ENSURE_NOT_NULL(pReq); #endif pHashReqParams = (icp_qat_fw_la_auth_req_params_t *)((Cpa8U *)&(pReq->serv_specif_rqpars) + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); /* For a full packet or last partial, we need to set the digest result * pointer */ if (NULL != pAuthResult) { authResultPhys = LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), (void *)pAuthResult); if (authResultPhys == 0) { LAC_LOG_ERROR("Unable to get the physical address of the" " auth result\n"); return CPA_STATUS_FAIL; } } pHashReqParams->auth_off = authOffsetInBytes; pHashReqParams->auth_len = authLenInBytes; /* Set the physical location of secret for HKDF */ if (NULL != pHKDFSecret) { LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pHashReqParams->u1.aad_adr, pHKDFSecret); if (0 == pHashReqParams->u1.aad_adr) { LAC_LOG_ERROR("Unable to get the physical address of the" " HKDF secret\n"); return CPA_STATUS_FAIL; } } /* For a full packet or last partial, we need to set the auth result * field */ pHashReqParams->auth_res_addr = authResultPhys; if (CPA_TRUE == digestVerify) { /* auth result size in bytes to be read in for a verify * operation */ pHashReqParams->auth_res_sz = (Cpa8U)hashResultSize; } else { pHashReqParams->auth_res_sz = 0; } /* If there is a hash state prefix buffer */ if (NULL != pHashStateBuf) { /* Only write the pointer to the buffer if the size is greater than 0 * this will be the case for plain and auth mode due to the * state storage required for partial packets and for nested mode (when * the prefix data is > 0) */ if ((pHashStateBuf->stateStorageSzQuadWords + pHashStateBuf->prefixAadSzQuadWords) > 0) { /* For the first partial packet, the QAT expects the pointer to the * inner prefix even if there is no memory allocated for this. The * QAT will internally calculate where to write the state back. */ if ((ICP_QAT_FW_LA_PARTIAL_START == packetType) || (ICP_QAT_FW_LA_PARTIAL_NONE == packetType)) { /* Prefix_addr changed to auth_partial_st_prefix */ pHashReqParams->u1.auth_partial_st_prefix = ((pHashStateBuf->pDataPhys) + LAC_QUADWORDS_TO_BYTES( pHashStateBuf->stateStorageSzQuadWords)); } else { pHashReqParams->u1.auth_partial_st_prefix = pHashStateBuf->pDataPhys; } } /* nested mode when the prefix data is 0 */ else { pHashReqParams->u1.auth_partial_st_prefix = 0; } /* For middle & last partial, state size is the hash state storage * if hash mode 2 this will include the prefix data */ if ((ICP_QAT_FW_LA_PARTIAL_MID == packetType) || (ICP_QAT_FW_LA_PARTIAL_END == packetType)) { pHashReqParams->hash_state_sz = (pHashStateBuf->stateStorageSzQuadWords + pHashStateBuf->prefixAadSzQuadWords); } /* For full packets and first partials set the state size to that of * the prefix/aad. prefix includes both the inner and outer prefix */ else { pHashReqParams->hash_state_sz = pHashStateBuf->prefixAadSzQuadWords; } } else { pHashReqParams->u1.auth_partial_st_prefix = 0; pHashReqParams->hash_state_sz = 0; } /* GMAC only */ if (CPA_CY_SYM_HASH_AES_GMAC == alg) { pHashReqParams->hash_state_sz = 0; pHashReqParams->u1.aad_adr = 0; } /* This field is only used by TLS requests */ /* In TLS case this is set after this function is called */ pHashReqParams->resrvd1 = 0; return CPA_STATUS_SUCCESS; } lac_sym_qat_hash_defs_lookup.c000066400000000000000000000706611503624047500351060ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/qat/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sym_qat_hash_defs_lookup.c Hash Definitions Lookup * * @ingroup LacHashDefsLookup ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_common.h" #include "lac_log.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "icp_adf_transport.h" #include "lac_sym.h" #include "icp_qat_fw_la.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sal_types_crypto.h" #include "lac_sym_hash_defs.h" #include "sal_types_compression.h" /* state size for xcbc mac consists of 3 * 16 byte keys */ #define LAC_SYM_QAT_XCBC_STATE_SIZE ((LAC_HASH_XCBC_MAC_BLOCK_SIZE)*3) #define LAC_SYM_QAT_CMAC_STATE_SIZE ((LAC_HASH_CMAC_BLOCK_SIZE)*3) /* This type is used for the mapping between the hash algorithm and * the corresponding hash definitions structure */ typedef struct lac_sym_qat_hash_def_map_s { CpaCySymHashAlgorithm hashAlgorithm; /* hash algorithm */ lac_sym_qat_hash_defs_t hashDefs; /* hash definitions pointers */ } lac_sym_qat_hash_def_map_t; /* ******************************************************************************* * Static Variables ******************************************************************************* */ /* initialisers as defined in FIPS and RFCS for digest operations */ /* md5 16 bytes - Initialiser state can be found in RFC 1321*/ STATIC Cpa8U md5InitialState[LAC_HASH_MD5_STATE_SIZE] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, }; /* SHA1 - 20 bytes - Initialiser state can be found in FIPS stds 180-2 */ STATIC Cpa8U sha1InitialState[LAC_HASH_SHA1_STATE_SIZE] = { 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0}; /* SHA 224 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */ STATIC Cpa8U sha224InitialState[LAC_HASH_SHA224_STATE_SIZE] = { 0xc1, 0x05, 0x9e, 0xd8, 0x36, 0x7c, 0xd5, 0x07, 0x30, 0x70, 0xdd, 0x17, 0xf7, 0x0e, 0x59, 0x39, 0xff, 0xc0, 0x0b, 0x31, 0x68, 0x58, 0x15, 0x11, 0x64, 0xf9, 0x8f, 0xa7, 0xbe, 0xfa, 0x4f, 0xa4}; /* SHA 256 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */ STATIC Cpa8U sha256InitialState[LAC_HASH_SHA256_STATE_SIZE] = { 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19}; /* SHA 384 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */ STATIC Cpa8U sha384InitialState[LAC_HASH_SHA384_STATE_SIZE] = { 0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8, 0x62, 0x9a, 0x29, 0x2a, 0x36, 0x7c, 0xd5, 0x07, 0x91, 0x59, 0x01, 0x5a, 0x30, 0x70, 0xdd, 0x17, 0x15, 0x2f, 0xec, 0xd8, 0xf7, 0x0e, 0x59, 0x39, 0x67, 0x33, 0x26, 0x67, 0xff, 0xc0, 0x0b, 0x31, 0x8e, 0xb4, 0x4a, 0x87, 0x68, 0x58, 0x15, 0x11, 0xdb, 0x0c, 0x2e, 0x0d, 0x64, 0xf9, 0x8f, 0xa7, 0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f, 0xa4}; /* SHA 512 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */ STATIC Cpa8U sha512InitialState[LAC_HASH_SHA512_STATE_SIZE] = { 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f, 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79}; /* SHA3 224 - 28 bytes */ STATIC Cpa8U sha3_224InitialState[LAC_HASH_SHA3_224_STATE_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* SHA3 256 - 32 bytes */ STATIC Cpa8U sha3_256InitialState[LAC_HASH_SHA3_256_STATE_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* SHA3 384 - 48 bytes */ STATIC Cpa8U sha3_384InitialState[LAC_HASH_SHA3_384_STATE_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* SHA3 512 - 64 bytes */ STATIC Cpa8U sha3_512InitialState[LAC_HASH_SHA3_512_STATE_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* SM3 - 32 bytes */ STATIC Cpa8U sm3InitialState[LAC_HASH_SM3_STATE_SIZE] = { 0x73, 0x80, 0x16, 0x6f, 0x49, 0x14, 0xb2, 0xb9, 0x17, 0x24, 0x42, 0xd7, 0xda, 0x8a, 0x06, 0x00, 0xa9, 0x6f, 0x30, 0xbc, 0x16, 0x31, 0x38, 0xaa, 0xe3, 0x8d, 0xee, 0x4d, 0xb0, 0xfb, 0x0e, 0x4e }; /* Constants used in generating K1, K2, K3 from a Key for AES_XCBC_MAC * State defined in RFC 3566 */ STATIC Cpa8U aesXcbcKeySeed[LAC_SYM_QAT_XCBC_STATE_SIZE] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, }; STATIC Cpa8U aesCmacKeySeed[LAC_HASH_CMAC_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /* Hash Algorithm specific structure */ STATIC lac_sym_qat_hash_alg_info_t md5Info = {LAC_HASH_MD5_DIGEST_SIZE, LAC_HASH_MD5_BLOCK_SIZE, md5InitialState, LAC_HASH_MD5_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha1Info = {LAC_HASH_SHA1_DIGEST_SIZE, LAC_HASH_SHA1_BLOCK_SIZE, sha1InitialState, LAC_HASH_SHA1_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha224Info = {LAC_HASH_SHA224_DIGEST_SIZE, LAC_HASH_SHA224_BLOCK_SIZE, sha224InitialState, LAC_HASH_SHA224_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha256Info = {LAC_HASH_SHA256_DIGEST_SIZE, LAC_HASH_SHA256_BLOCK_SIZE, sha256InitialState, LAC_HASH_SHA256_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha384Info = {LAC_HASH_SHA384_DIGEST_SIZE, LAC_HASH_SHA384_BLOCK_SIZE, sha384InitialState, LAC_HASH_SHA384_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha512Info = {LAC_HASH_SHA512_DIGEST_SIZE, LAC_HASH_SHA512_BLOCK_SIZE, sha512InitialState, LAC_HASH_SHA512_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha3_224Info = { LAC_HASH_SHA3_224_DIGEST_SIZE, LAC_HASH_SHA3_224_BLOCK_SIZE, sha3_224InitialState, LAC_HASH_SHA3_224_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha3_256Info = { LAC_HASH_SHA3_256_DIGEST_SIZE, LAC_HASH_SHA3_256_BLOCK_SIZE, sha3_256InitialState, LAC_HASH_SHA3_256_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha3_384Info = { LAC_HASH_SHA3_384_DIGEST_SIZE, LAC_HASH_SHA3_384_BLOCK_SIZE, sha3_384InitialState, LAC_HASH_SHA3_384_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sha3_512Info = { LAC_HASH_SHA3_512_DIGEST_SIZE, LAC_HASH_SHA3_512_BLOCK_SIZE, sha3_512InitialState, LAC_HASH_SHA3_512_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t sm3Info = { LAC_HASH_SM3_DIGEST_SIZE, LAC_HASH_SM3_BLOCK_SIZE, sm3InitialState, LAC_HASH_SM3_STATE_SIZE }; STATIC lac_sym_qat_hash_alg_info_t polyInfo = { LAC_HASH_POLY_DIGEST_SIZE, LAC_HASH_POLY_BLOCK_SIZE, NULL, /* initial state */ LAC_HASH_POLY_STATE_SIZE }; STATIC lac_sym_qat_hash_alg_info_t xcbcMacInfo = { LAC_HASH_XCBC_MAC_128_DIGEST_SIZE, LAC_HASH_XCBC_MAC_BLOCK_SIZE, aesXcbcKeySeed, LAC_SYM_QAT_XCBC_STATE_SIZE}; STATIC lac_sym_qat_hash_alg_info_t aesCmacInfo = { LAC_HASH_CMAC_DIGEST_SIZE, LAC_HASH_CMAC_BLOCK_SIZE, aesCmacKeySeed, LAC_SYM_QAT_CMAC_STATE_SIZE }; STATIC lac_sym_qat_hash_alg_info_t aesCcmInfo = { LAC_HASH_AES_CCM_DIGEST_SIZE, LAC_HASH_AES_CCM_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t aesGcmInfo = { LAC_HASH_AES_GCM_DIGEST_SIZE, LAC_HASH_AES_GCM_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t kasumiF9Info = { LAC_HASH_KASUMI_F9_DIGEST_SIZE, LAC_HASH_KASUMI_F9_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t snow3gUia2Info = { LAC_HASH_SNOW3G_UIA2_DIGEST_SIZE, LAC_HASH_SNOW3G_UIA2_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t aesCbcMacInfo = { LAC_HASH_AES_CBC_MAC_DIGEST_SIZE, LAC_HASH_AES_CBC_MAC_BLOCK_SIZE, NULL, 0}; STATIC lac_sym_qat_hash_alg_info_t zucEia3Info = { LAC_HASH_ZUC_EIA3_DIGEST_SIZE, LAC_HASH_ZUC_EIA3_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t zuc256mac32Info = { LAC_HASH_ZUC_256_MAC_32_DIGEST_SIZE, LAC_HASH_ZUC_256_MAC_32_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t zuc256mac64Info = { LAC_HASH_ZUC_256_MAC_64_DIGEST_SIZE, LAC_HASH_ZUC_256_MAC_64_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t zuc256mac128Info = { LAC_HASH_ZUC_256_MAC_128_DIGEST_SIZE, LAC_HASH_ZUC_256_MAC_128_BLOCK_SIZE, NULL, /* initial state */ 0 /* state size */ }; STATIC lac_sym_qat_hash_alg_info_t aesCmacWatInfo = { LAC_HASH_CMAC_BLOCK_SIZE, LAC_HASH_CMAC_DIGEST_SIZE, NULL, /* initial state */ 0 /* state size */ }; /* Hash QAT specific structures */ STATIC lac_sym_qat_hash_qat_info_t md5Config = {ICP_QAT_HW_AUTH_ALGO_MD5, LAC_HASH_MD5_BLOCK_SIZE, ICP_QAT_HW_MD5_STATE1_SZ, ICP_QAT_HW_MD5_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha1Config = {ICP_QAT_HW_AUTH_ALGO_SHA1, LAC_HASH_SHA1_BLOCK_SIZE, ICP_QAT_HW_SHA1_STATE1_SZ, ICP_QAT_HW_SHA1_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha224Config = {ICP_QAT_HW_AUTH_ALGO_SHA224, LAC_HASH_SHA224_BLOCK_SIZE, ICP_QAT_HW_SHA224_STATE1_SZ, ICP_QAT_HW_SHA224_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha256Config = {ICP_QAT_HW_AUTH_ALGO_SHA256, LAC_HASH_SHA256_BLOCK_SIZE, ICP_QAT_HW_SHA256_STATE1_SZ, ICP_QAT_HW_SHA256_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha384Config = {ICP_QAT_HW_AUTH_ALGO_SHA384, LAC_HASH_SHA384_BLOCK_SIZE, ICP_QAT_HW_SHA384_STATE1_SZ, ICP_QAT_HW_SHA384_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha512Config = {ICP_QAT_HW_AUTH_ALGO_SHA512, LAC_HASH_SHA512_BLOCK_SIZE, ICP_QAT_HW_SHA512_STATE1_SZ, ICP_QAT_HW_SHA512_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha3_224Config = { ICP_QAT_HW_AUTH_ALGO_SHA3_224, LAC_HASH_SHA3_224_BLOCK_SIZE, ICP_QAT_HW_SHA3_224_STATE1_SZ, ICP_QAT_HW_SHA3_224_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha3_256Config = { ICP_QAT_HW_AUTH_ALGO_SHA3_256, LAC_HASH_SHA3_256_BLOCK_SIZE, ICP_QAT_HW_SHA3_256_STATE1_SZ, ICP_QAT_HW_SHA3_256_STATE2_SZ, }; STATIC lac_sym_qat_hash_qat_info_t sha3_384Config = { ICP_QAT_HW_AUTH_ALGO_SHA3_384, LAC_HASH_SHA3_384_BLOCK_SIZE, ICP_QAT_HW_SHA3_384_STATE1_SZ, ICP_QAT_HW_SHA3_384_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sha3_512Config = { ICP_QAT_HW_AUTH_ALGO_SHA3_512, LAC_HASH_SHA3_512_BLOCK_SIZE, ICP_QAT_HW_SHA3_512_STATE1_SZ, ICP_QAT_HW_SHA3_512_STATE2_SZ}; STATIC lac_sym_qat_hash_qat_info_t sm3Config = { ICP_QAT_HW_AUTH_ALGO_SM3, LAC_HASH_SM3_BLOCK_SIZE, ICP_QAT_HW_SM3_STATE1_SZ, ICP_QAT_HW_SM3_STATE2_SZ }; STATIC lac_sym_qat_hash_qat_info_t polyConfig = {ICP_QAT_HW_AUTH_ALGO_POLY, LAC_HASH_POLY_BLOCK_SIZE, 0, 0}; STATIC lac_sym_qat_hash_qat_info_t xcbcMacConfig = { ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC, 0, ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ, LAC_SYM_QAT_XCBC_STATE_SIZE }; STATIC lac_sym_qat_hash_qat_info_t aesCmacConfig = { ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC, 0, ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ, LAC_SYM_QAT_CMAC_STATE_SIZE }; STATIC lac_sym_qat_hash_qat_info_t aesCcmConfig = { ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC, 0, ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ, ICP_QAT_HW_AES_CBC_MAC_KEY_SZ + ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ }; STATIC lac_sym_qat_hash_qat_info_t aesGcmConfig = { ICP_QAT_HW_AUTH_ALGO_GALOIS_128, 0, ICP_QAT_HW_GALOIS_128_STATE1_SZ, ICP_QAT_HW_GALOIS_H_SZ + ICP_QAT_HW_GALOIS_LEN_A_SZ + ICP_QAT_HW_GALOIS_E_CTR0_SZ }; STATIC lac_sym_qat_hash_qat_info_t kasumiF9Config = { ICP_QAT_HW_AUTH_ALGO_KASUMI_F9, 0, ICP_QAT_HW_KASUMI_F9_STATE1_SZ, ICP_QAT_HW_KASUMI_F9_STATE2_SZ }; STATIC lac_sym_qat_hash_qat_info_t snow3gUia2Config = { ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2, 0, ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ, ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ }; STATIC lac_sym_qat_hash_qat_info_t aesCbcMacConfig = { ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC, 0, ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ, ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ }; STATIC lac_sym_qat_hash_qat_info_t zucEia3Config = { ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3, 0, ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ, ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ }; STATIC lac_sym_qat_hash_qat_info_t zuc256mac32Config = { ICP_QAT_HW_AUTH_ALGO_ZUC_256_MAC_32, 0, ICP_QAT_HW_ZUC_256_MAC_32_STATE1_SZ, ICP_QAT_HW_ZUC_256_STATE2_SZ }; STATIC lac_sym_qat_hash_qat_info_t zuc256mac64Config = { ICP_QAT_HW_AUTH_ALGO_ZUC_256_MAC_64, 0, ICP_QAT_HW_ZUC_256_MAC_64_STATE1_SZ, ICP_QAT_HW_ZUC_256_STATE2_SZ }; STATIC lac_sym_qat_hash_qat_info_t zuc256mac128Config = { ICP_QAT_HW_AUTH_ALGO_ZUC_256_MAC_128, 0, ICP_QAT_HW_ZUC_256_MAC_128_STATE1_SZ, ICP_QAT_HW_ZUC_256_STATE2_SZ }; STATIC lac_sym_qat_hash_defs_t zuc256Mac32HashDefs = { &zuc256mac32Info, &zuc256mac32Config }; STATIC lac_sym_qat_hash_defs_t zuc256Mac64HashDefs = { &zuc256mac64Info, &zuc256mac64Config }; STATIC lac_sym_qat_hash_defs_t zuc256Mac128HashDefs = { &zuc256mac128Info, &zuc256mac128Config }; STATIC lac_sym_qat_hash_qat_info_t aes192CmacConfig = { ICP_QAT_HW_AUTH_ALGO_AES_192_CMAC, 0, ICP_QAT_HW_AES_CMAC_STATE1_SZ, ICP_QAT_HW_AES_192_CMAC_STATE2_SZ }; STATIC lac_sym_qat_hash_qat_info_t aes256CmacConfig = { ICP_QAT_HW_AUTH_ALGO_AES_256_CMAC, 0, ICP_QAT_HW_AES_CMAC_STATE1_SZ, ICP_QAT_HW_AES_256_CMAC_STATE2_SZ }; STATIC lac_sym_qat_hash_defs_t aes192MacHashDefs = { &aesCmacWatInfo, &aes192CmacConfig }; STATIC lac_sym_qat_hash_defs_t aes256MacHashDefs = { &aesCmacWatInfo, &aes256CmacConfig }; /* Array of mappings between algorithm and info structure * This array is used to populate the lookup table */ STATIC lac_sym_qat_hash_def_map_t lacHashDefsMapping[] = { { CPA_CY_SYM_HASH_MD5, { &md5Info, &md5Config } }, { CPA_CY_SYM_HASH_SHA1, { &sha1Info, &sha1Config } }, { CPA_CY_SYM_HASH_SHA224, { &sha224Info, &sha224Config } }, { CPA_CY_SYM_HASH_SHA256, { &sha256Info, &sha256Config } }, { CPA_CY_SYM_HASH_SHA384, { &sha384Info, &sha384Config } }, { CPA_CY_SYM_HASH_SHA512, { &sha512Info, &sha512Config } }, { CPA_CY_SYM_HASH_SHA3_224, { &sha3_224Info, &sha3_224Config } }, { CPA_CY_SYM_HASH_SHA3_256, { &sha3_256Info, &sha3_256Config } }, { CPA_CY_SYM_HASH_SHA3_384, { &sha3_384Info, &sha3_384Config } }, { CPA_CY_SYM_HASH_SHA3_512, { &sha3_512Info, &sha3_512Config } }, { CPA_CY_SYM_HASH_POLY, { &polyInfo, &polyConfig } }, { CPA_CY_SYM_HASH_SM3, { &sm3Info, &sm3Config } }, { CPA_CY_SYM_HASH_AES_XCBC, { &xcbcMacInfo, &xcbcMacConfig } }, { CPA_CY_SYM_HASH_AES_CMAC, { &aesCmacInfo, &aesCmacConfig } }, { CPA_CY_SYM_HASH_AES_CCM, { &aesCcmInfo, &aesCcmConfig } }, { CPA_CY_SYM_HASH_AES_GCM, { &aesGcmInfo, &aesGcmConfig } }, { CPA_CY_SYM_HASH_KASUMI_F9, { &kasumiF9Info, &kasumiF9Config } }, { CPA_CY_SYM_HASH_SNOW3G_UIA2, { &snow3gUia2Info, &snow3gUia2Config } }, { CPA_CY_SYM_HASH_AES_GMAC, { &aesGcmInfo, &aesGcmConfig } }, { CPA_CY_SYM_HASH_ZUC_EIA3, { &zucEia3Info, &zucEia3Config } }, { CPA_CY_SYM_HASH_AES_CBC_MAC, { &aesCbcMacInfo, &aesCbcMacConfig } }, }; /* * LacSymQat_HashLookupInit */ CpaStatus LacSymQat_HashLookupInit(CpaInstanceHandle instanceHandle) { Cpa32U entry = 0; Cpa32U numEntries = 0; Cpa32U arraySize = 0; CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymHashAlgorithm hashAlg = CPA_CY_SYM_HASH_NONE; sal_service_t *pService = (sal_service_t *)instanceHandle; lac_sym_qat_hash_defs_t **pLacHashLookupDefs; arraySize = (LAC_HASH_ALG_END + 1) * sizeof(lac_sym_qat_hash_defs_t *); /* Size round up for performance */ arraySize = LAC_ALIGN_POW2_ROUNDUP(arraySize, LAC_64BYTE_ALIGNMENT); status = LAC_OS_MALLOC(&pLacHashLookupDefs, arraySize); if (CPA_STATUS_SUCCESS != status) { return status; } LAC_OS_BZERO(pLacHashLookupDefs, arraySize); numEntries = sizeof(lacHashDefsMapping) / sizeof(lac_sym_qat_hash_def_map_t); /* initialise the hash lookup definitions table so that the algorithm * can be used to index into the table */ for (entry = 0; entry < numEntries; entry++) { hashAlg = lacHashDefsMapping[entry].hashAlgorithm; pLacHashLookupDefs[hashAlg] = &(lacHashDefsMapping[entry].hashDefs); } if (SAL_SERVICE_TYPE_COMPRESSION == pService->type) { ((sal_compression_service_t *)pService) ->pDcChainService->pLacHashLookupDefs = pLacHashLookupDefs; } else { ((sal_crypto_service_t *)pService)->pLacHashLookupDefs = pLacHashLookupDefs; } return status; } /* * LacSymQat_HashAlgLookupGet */ void LacSymQat_HashAlgLookupGet(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, lac_sym_qat_hash_alg_info_t **ppHashAlgInfo, Cpa32U authKeyLenInBytes, Cpa32U digestResultLenInBytes) { sal_service_t *pService = (sal_service_t *)instanceHandle; lac_sym_qat_hash_defs_t **pLacHashLookupDefs; if (SAL_SERVICE_TYPE_COMPRESSION == pService->type) { pLacHashLookupDefs = ((sal_compression_service_t *)pService) ->pDcChainService->pLacHashLookupDefs; } else { pLacHashLookupDefs = ((sal_crypto_service_t *)pService)->pLacHashLookupDefs; } LAC_ENSURE_NOT_NULL(ppHashAlgInfo); LAC_ENSURE(pLacHashLookupDefs[hashAlgorithm] != NULL, "hashInfo entry should not be NULL\n"); LAC_ENSURE(pLacHashLookupDefs[hashAlgorithm]->algInfo != NULL, "hash alg Info should not be NULL\n"); *ppHashAlgInfo = pLacHashLookupDefs[hashAlgorithm]->algInfo; if ((hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) && (authKeyLenInBytes == ICP_QAT_HW_ZUC_256_KEY_SZ)) { if (digestResultLenInBytes == LAC_HASH_ZUC_256_MAC_32_DIGEST_SIZE) { *ppHashAlgInfo = &zuc256mac32Info; } else if (digestResultLenInBytes == LAC_HASH_ZUC_256_MAC_64_DIGEST_SIZE) { *ppHashAlgInfo = &zuc256mac64Info; } else { *ppHashAlgInfo = &zuc256mac128Info; } } else if ((hashAlgorithm == CPA_CY_SYM_HASH_AES_CMAC) && (authKeyLenInBytes != ICP_QAT_HW_AES_128_KEY_SZ)) { *ppHashAlgInfo = &aesCmacWatInfo; } } /* * LacSymQat_HashDefsLookupGet */ void LacSymQat_HashDefsLookupGet(CpaInstanceHandle instanceHandle, CpaCySymHashAlgorithm hashAlgorithm, lac_sym_qat_hash_defs_t **ppHashDefsInfo, Cpa32U authKeyLenInBytes, Cpa32U digestResultLenInBytes) { sal_service_t *pService = (sal_service_t *)instanceHandle; lac_sym_qat_hash_defs_t **pLacHashLookupDefs; if (SAL_SERVICE_TYPE_COMPRESSION == pService->type) { pLacHashLookupDefs = ((sal_compression_service_t *)pService) ->pDcChainService->pLacHashLookupDefs; } else { pLacHashLookupDefs = ((sal_crypto_service_t *)pService)->pLacHashLookupDefs; } LAC_ENSURE_NOT_NULL(ppHashDefsInfo); LAC_ENSURE(pLacHashLookupDefs[hashAlgorithm] != NULL, "hashInfo should not be NULL\n"); LAC_ENSURE(pLacHashLookupDefs[hashAlgorithm]->algInfo != NULL, "hash algInfo should not be NULL\n"); LAC_ENSURE(pLacHashLookupDefs[hashAlgorithm]->qatInfo != NULL, "hash qatInfo should not be NULL\n"); *ppHashDefsInfo = pLacHashLookupDefs[hashAlgorithm]; if ((hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) && (authKeyLenInBytes == ICP_QAT_HW_ZUC_256_KEY_SZ)) { if (digestResultLenInBytes == LAC_HASH_ZUC_256_MAC_32_DIGEST_SIZE) { *ppHashDefsInfo = &zuc256Mac32HashDefs; } else if (digestResultLenInBytes == LAC_HASH_ZUC_256_MAC_64_DIGEST_SIZE) { *ppHashDefsInfo = &zuc256Mac64HashDefs; } else { *ppHashDefsInfo = &zuc256Mac128HashDefs; } } else if (hashAlgorithm == CPA_CY_SYM_HASH_AES_CMAC) { if (authKeyLenInBytes == ICP_QAT_HW_AES_192_KEY_SZ) { *ppHashDefsInfo = &aes192MacHashDefs; } else if (authKeyLenInBytes == ICP_QAT_HW_AES_256_KEY_SZ) { *ppHashDefsInfo = &aes256MacHashDefs; } } } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/crypto/sym/qat/lac_sym_qat_key.c000066400000000000000000000236371503624047500324410ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_sym_qat_key.c Interfaces for populating the symmetric qat key * structures * * @ingroup LacSymQatKey * *****************************************************************************/ #include "cpa.h" #include "lac_mem.h" #include "icp_qat_fw_la.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "lac_list.h" #include "lac_sal_types.h" #include "lac_sym_qat_key.h" #include "lac_sym_hash_defs.h" void LacSymQat_KeySslRequestPopulate( icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, Cpa32U generatedKeyLenInBytes, Cpa32U labelLenInBytes, Cpa32U secretLenInBytes, Cpa32U iterations) { /* Rounded to nearest 8 byte boundary */ Cpa8U outLenRounded = 0; LAC_ENSURE_NOT_NULL(pKeyGenReqHdr); LAC_ENSURE_NOT_NULL(pKeyGenReqMid); outLenRounded = LAC_ALIGN_POW2_ROUNDUP(generatedKeyLenInBytes, LAC_QUAD_WORD_IN_BYTES); pKeyGenReqMid->u.secret_lgth_ssl = (Cpa16U)secretLenInBytes; pKeyGenReqMid->u1.s1.output_lgth_ssl = outLenRounded; pKeyGenReqMid->u1.s1.label_lgth_ssl = (Cpa8U)labelLenInBytes; pKeyGenReqMid->u2.iter_count = (Cpa8U)iterations; pKeyGenReqMid->u3.resrvd2 = 0; pKeyGenReqMid->resrvd3 = 0; /* Set up the common LA flags */ pKeyGenReqHdr->comn_hdr.service_cmd_id = ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE; pKeyGenReqHdr->comn_hdr.resrvd1 = 0; } void LacSymQat_KeyTlsRequestPopulate( icp_qat_fw_la_key_gen_common_t *pKeyGenReqParams, Cpa32U generatedKeyLenInBytes, Cpa32U labelInfo, Cpa32U secretLenInBytes, Cpa8U seedLenInBytes, icp_qat_fw_la_cmd_id_t cmdId) { LAC_ENSURE_NOT_NULL(pKeyGenReqParams); pKeyGenReqParams->u1.s3.output_lgth_tls = LAC_ALIGN_POW2_ROUNDUP(generatedKeyLenInBytes, LAC_QUAD_WORD_IN_BYTES); /* For TLS u param of auth_req_params is set to secretLen */ pKeyGenReqParams->u.secret_lgth_tls = (Cpa16U)secretLenInBytes; switch (cmdId) { case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: pKeyGenReqParams->u2.hkdf_ikm_length = (Cpa8U)secretLenInBytes; pKeyGenReqParams->u3.resrvd2 = 0; break; case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: pKeyGenReqParams->u1.hkdf.info_length = (Cpa8U)labelInfo; break; case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: pKeyGenReqParams->u2.hkdf_ikm_length = (Cpa8U)secretLenInBytes; pKeyGenReqParams->u1.hkdf.info_length = (Cpa8U)labelInfo; break; case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: /* Num of Labels */ pKeyGenReqParams->u1.hkdf_label.num_labels = (Cpa8U)labelInfo; pKeyGenReqParams->u3.hkdf_num_sublabels = CPA_CY_HKDF_KEY_MAX_LABEL_COUNT; break; case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: pKeyGenReqParams->u2.hkdf_ikm_length = (Cpa8U)secretLenInBytes; /* Num of Labels */ pKeyGenReqParams->u1.hkdf_label.num_labels = (Cpa8U)labelInfo; pKeyGenReqParams->u3.hkdf_num_sublabels = CPA_CY_HKDF_KEY_MAX_LABEL_COUNT; break; default: pKeyGenReqParams->u1.s3.label_lgth_tls = (Cpa8U)labelInfo; pKeyGenReqParams->u2.tls_seed_length = seedLenInBytes; pKeyGenReqParams->u3.resrvd2 = 0; break; } pKeyGenReqParams->resrvd3 = 0; } void LacSymQat_KeyMgfRequestPopulate( icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, Cpa8U seedLenInBytes, Cpa16U maskLenInBytes, Cpa8U hashLenInBytes) { LAC_ENSURE_NOT_NULL(pKeyGenReqHdr); LAC_ENSURE_NOT_NULL(pKeyGenReqMid); pKeyGenReqHdr->comn_hdr.service_cmd_id = ICP_QAT_FW_LA_CMD_MGF1; pKeyGenReqMid->u.mask_length = LAC_ALIGN_POW2_ROUNDUP(maskLenInBytes, LAC_QUAD_WORD_IN_BYTES); pKeyGenReqMid->u1.s2.hash_length = hashLenInBytes; pKeyGenReqMid->u1.s2.seed_length = seedLenInBytes; } void LacSymQat_KeySslKeyMaterialInputPopulate( sal_service_t *pService, icp_qat_fw_la_ssl_key_material_input_t *pSslKeyMaterialInput, void *pSeed, Cpa64U labelPhysAddr, void *pSecret) { LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pSslKeyMaterialInput->seed_addr, pSeed); pSslKeyMaterialInput->label_addr = labelPhysAddr; LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pSslKeyMaterialInput->secret_addr, pSecret); } void LacSymQat_KeyTlsKeyMaterialInputPopulate( sal_service_t *pService, icp_qat_fw_la_tls_key_material_input_t *pTlsKeyMaterialInput, void *pSeed, Cpa64U labelPhysAddr) { LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pTlsKeyMaterialInput->seed_addr, pSeed); pTlsKeyMaterialInput->label_addr = labelPhysAddr; } void LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( sal_service_t *pService, icp_qat_fw_la_hkdf_key_material_input_t *pTlsHKDFKeyMaterialInput, CpaCyKeyGenHKDFOpData *pKeyGenTlsHKDFOpData, Cpa64U subLabelPhysAddr, icp_qat_fw_la_cmd_id_t cmdId) { switch (cmdId) { case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pTlsHKDFKeyMaterialInput->ikm_addr, pKeyGenTlsHKDFOpData->secret); break; case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pTlsHKDFKeyMaterialInput->labels_addr, pKeyGenTlsHKDFOpData->info); break; case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pTlsHKDFKeyMaterialInput->ikm_addr, pKeyGenTlsHKDFOpData->secret); pTlsHKDFKeyMaterialInput->labels_addr = pTlsHKDFKeyMaterialInput->ikm_addr + ((LAC_ARCH_UINT)&pKeyGenTlsHKDFOpData->info - (LAC_ARCH_UINT)&pKeyGenTlsHKDFOpData->secret); break; case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: pTlsHKDFKeyMaterialInput->sublabels_addr = subLabelPhysAddr; LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pTlsHKDFKeyMaterialInput->labels_addr, pKeyGenTlsHKDFOpData->label); break; case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: pTlsHKDFKeyMaterialInput->sublabels_addr = subLabelPhysAddr; LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( (*pService), pTlsHKDFKeyMaterialInput->ikm_addr, pKeyGenTlsHKDFOpData->secret); pTlsHKDFKeyMaterialInput->labels_addr = pTlsHKDFKeyMaterialInput->ikm_addr + ((LAC_ARCH_UINT)&pKeyGenTlsHKDFOpData->label - (LAC_ARCH_UINT)&pKeyGenTlsHKDFOpData->secret); break; default: break; } } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/000077500000000000000000000000001503624047500251455ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_compression.c000066400000000000000000002370541503624047500305240ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_compression.c * * @ingroup SalCtrl * * @description * This file contains the sal implementation for compression. * *****************************************************************************/ /* QAT-API includes */ #include "cpa.h" #include "cpa_dc.h" /* Osal includes */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_cfg.h" #include "icp_adf_accel_mgr.h" #include "icp_adf_poll.h" #include "icp_adf_debug.h" #include "icp_qat_hw.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_common.h" #include "lac_mem_pools.h" #include "sal_statistics.h" #include "lac_list.h" #include "icp_sal_poll.h" #include "sal_types_compression.h" #include "dc_session.h" #include "dc_datapath.h" #include "dc_stats.h" #include "dc_capabilities.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "sal_instances.h" #include "sal_string_parse.h" #include "sal_service_state.h" #include "lac_buffer_desc.h" #include "icp_qat_fw_comp.h" #include "icp_qat_hw_20_comp_defs.h" #include "icp_sal_versions.h" #include "lac_sw_responses.h" #ifndef ICP_DC_ONLY #include "dc_chain.h" #define CHAINING_CAPABILITY_MASK 0x1FFF0000 #endif #define MAX_BANK_NUM 1024 /* * Prints statistics for a compression instance */ STATIC int SalCtrl_CompresionDebug(void *private_data, char *data, int size, int offset) { sal_compression_service_t *pCompressionService = (sal_compression_service_t *)private_data; CpaStatus status = CPA_STATUS_SUCCESS; CpaDcStats dcStats = {0}; Cpa32S len = 0; status = cpaDcGetStats(pCompressionService, &dcStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaDcGetStats returned error\n"); return (-1); } /* Engine Info */ if (NULL != pCompressionService->debug_file) { len += snprintf(data + len, size - len, SEPARATOR BORDER " Statistics for Instance %24s | \n" SEPARATOR, pCompressionService->debug_file->name); } /* Perform Info */ len += snprintf( data + len, size - len, BORDER " DC comp Requests: %16llu " BORDER "\n" BORDER " DC comp Request Errors: %16llu " BORDER "\n" BORDER " DC comp Completed: %16llu " BORDER "\n" BORDER " DC comp Completed Errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dcStats.numCompRequests, (long long unsigned int)dcStats.numCompRequestsErrors, (long long unsigned int)dcStats.numCompCompleted, (long long unsigned int)dcStats.numCompCompletedErrors); /* Perform Info */ snprintf(data + len, size - len, BORDER " DC decomp Requests: %16llu " BORDER "\n" BORDER " DC decomp Request Errors: %16llu " BORDER "\n" BORDER " DC decomp Completed: %16llu " BORDER "\n" BORDER " DC decomp Completed Errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dcStats.numDecompRequests, (long long unsigned int)dcStats.numDecompRequestsErrors, (long long unsigned int)dcStats.numDecompCompleted, (long long unsigned int)dcStats.numDecompCompletedErrors); return 0; } /* Disabling memory pool when the device is in error state */ STATIC void SalCtrl_DcMemPoolDisable(sal_service_t *service) { sal_compression_service_t *pCompService = (sal_compression_service_t *)service; if (pCompService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { Lac_MemPoolDisable(pCompService->compression_mem_pool); } else { Lac_MemPoolDisable(pCompService->decompression_mem_pool); } return; } STATIC void SalCtrl_DcUpdatePoolsBusy(sal_service_t *service) { CpaBoolean isInstanceStarted = service->isInstanceStarted; sal_compression_service_t *pCompService = (sal_compression_service_t *)service; if (CPA_TRUE == isInstanceStarted) { if (pCompService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { LacSwResp_IncNumPoolsBusy(pCompService->compression_mem_pool); } else { LacSwResp_IncNumPoolsBusy(pCompService->decompression_mem_pool); } } return; } /* Generates dummy responses when the device is in error state */ STATIC CpaStatus SalCtrl_DcGenResponses(sal_compression_service_t *dc_handle) { CpaStatus status = CPA_STATUS_RETRY; if (dc_handle->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { status = LacSwResp_GenResp(dc_handle->compression_mem_pool, dc_handle->generic_service_info.type); } else { status = LacSwResp_GenResp(dc_handle->decompression_mem_pool, dc_handle->generic_service_info.type); } if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR1("Failed to generate SW responses with status %d\n", status); } return status; } STATIC CpaStatus SalCtrl_DcCheckRespInstance(sal_service_t *service) { sal_compression_service_t *dc_handle = (sal_compression_service_t *)service; icp_comms_trans_handle trans_hndTable[DC_NUM_RX_RINGS]; sal_service_t *gen_handle = NULL; gen_handle = &(dc_handle->generic_service_info); switch (gen_handle->type) { case SAL_SERVICE_TYPE_COMPRESSION: trans_hndTable[0] = dc_handle->trans_handle_compression_rx; break; case SAL_SERVICE_TYPE_DECOMPRESSION: trans_hndTable[0] = dc_handle->trans_handle_decompression_rx; break; default: LAC_LOG_ERROR("The instance handle is the wrong type"); return CPA_STATUS_FAIL; } return icp_adf_check_RespInstance(trans_hndTable, DC_NUM_RX_RINGS); } STATIC CpaStatus SalCtr_DcInstInit(icp_accel_dev_t *device, sal_service_t *service, char *serviceName) { char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; CpaStatus status = CPA_STATUS_SUCCESS; char *section = icpGetProcessName(); Cpa32S strSize = 0; Cpa16U bankNum = 0; /* Get Config Info: Accel Num, bank Num, packageID, coreAffinity, nodeAffinity and response mode */ pCompressionService->acceleratorNum = (Cpa16U)device->accelId; status = Sal_StringParsing(serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_RING_BANK_NUM, temp_string); LAC_CHECK_STATUS(status); status = icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); return status; } pCompressionService->bankNum = (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); bankNum = pCompressionService->bankNum; if (bankNum > MAX_BANK_NUM) { return CPA_STATUS_FAIL; } status = Sal_StringParsing(serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_POLL_MODE, temp_string); LAC_CHECK_STATUS(status); status = icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); return status; } pCompressionService->isPolled = (Cpa8U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); #ifdef KERNEL_SPACE /* Kernel instances do not support epoll mode */ if (SAL_RESP_EPOLL_CFG_FILE == pCompressionService->isPolled) { LAC_LOG_ERROR_PARAMS( "IsPolled %u is not supported for kernel instance %s", pCompressionService->isPolled, temp_string); return CPA_STATUS_FAIL; } #endif #ifndef KERNEL_SPACE /* User instances only support poll and epoll mode */ if (SAL_RESP_POLL_CFG_FILE != pCompressionService->isPolled && SAL_RESP_EPOLL_CFG_FILE != pCompressionService->isPolled) { LAC_LOG_ERROR_PARAMS("IsPolled %u is not supported for " "user instance %s", pCompressionService->isPolled, temp_string); return CPA_STATUS_FAIL; } #endif status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_DEV_PKG_ID, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", ADF_DEV_PKG_ID); return status; } pCompressionService->pkgID = (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_DEV_NODE_ID, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", ADF_DEV_NODE_ID); return status; } pCompressionService->nodeAffinity = (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); /* In case of interrupt instance, use the bank affinity set by adf_ctl * Otherwise, use the instance affinity for backwards compatibility */ if (SAL_RESP_POLL_CFG_FILE != pCompressionService->isPolled) { /* Next need to read the [AcceleratorX] section of the config file */ status = Sal_StringParsing(SAL_CFG_ACCEL_SEC, pCompressionService->acceleratorNum, "", temp_string2); LAC_CHECK_STATUS(status); status = Sal_StringParsing(SAL_CFG_ETRMGR_BANK, bankNum, SAL_CFG_ETRMGR_CORE_AFFINITY, temp_string); LAC_CHECK_STATUS(status); } else { strSize = snprintf(temp_string2, sizeof(temp_string2), "%s", section); LAC_CHECK_PARAM_RANGE(strSize, 1, sizeof(temp_string2)); status = Sal_StringParsing( serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_ETRMGR_CORE_AFFINITY, temp_string); LAC_CHECK_STATUS(status); } status = icp_adf_cfgGetParamValue( device, temp_string2, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); return status; } pCompressionService->coreAffinity = (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); return status; } STATIC void SalCtrl_DcDebugCleanup(icp_accel_dev_t *device, sal_service_t *service) { sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; if (CPA_TRUE == pStatsCollection->bStatsEnabled) { /* Clean stats */ if (NULL != pCompressionService->debug_file) { LAC_OS_FREE(pCompressionService->debug_file->name); LAC_OS_FREE(pCompressionService->debug_file); pCompressionService->debug_file = NULL; } } } STATIC void SalCtrl_DcDebugShutdown(icp_accel_dev_t *device, sal_service_t *service) { sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; SalCtrl_DcDebugCleanup(device, service); pCompressionService->generic_service_info.stats = NULL; } STATIC void SalCtrl_DcDebugRestarting(icp_accel_dev_t *device, sal_service_t *service) { SalCtrl_DcDebugCleanup(device, service); } STATIC CpaStatus SalCtrl_DcDebugInit(icp_accel_dev_t *device, sal_service_t *service, char *serviceName) { char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char *instance_name = NULL; sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; CpaStatus status = CPA_STATUS_SUCCESS; char *section = icpGetProcessName(); if (CPA_TRUE == pStatsCollection->bStatsEnabled) { /* Get instance name for stats */ status = LAC_OS_MALLOC(&instance_name, ADF_CFG_MAX_VAL_LEN_IN_BYTES); LAC_CHECK_STATUS(status); status = Sal_StringParsing( serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_NAME, temp_string); if (CPA_STATUS_SUCCESS != status) { LAC_OS_FREE(instance_name); return status; } status = icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); LAC_OS_FREE(instance_name); return status; } snprintf( instance_name, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%s", adfGetParam); status = LAC_OS_MALLOC(&pCompressionService->debug_file, sizeof(debug_file_info_t)); if (CPA_STATUS_SUCCESS != status) { LAC_OS_FREE(instance_name); return status; } osalMemSet( pCompressionService->debug_file, 0, sizeof(debug_file_info_t)); pCompressionService->debug_file->name = instance_name; pCompressionService->debug_file->seq_read = SalCtrl_CompresionDebug; pCompressionService->debug_file->private_data = pCompressionService; pCompressionService->debug_file->parent = pCompressionService->generic_service_info.debug_parent_dir; } pCompressionService->generic_service_info.stats = pStatsCollection; return status; } STATIC CpaStatus SalCtrl_GetDcConcurrentReqNum(char *string1, char *section, char *string2, sal_compression_service_t *pCompressionService, Cpa32U *pNumDcConcurrentReq, icp_accel_dev_t *device) { char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; CpaStatus status = CPA_STATUS_SUCCESS; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; Cpa32U numDcConcurrentReq = 0; /* get num concurrent requests from config file */ status = Sal_StringParsing(string1, pCompressionService->generic_service_info.instance, string2, temp_string); LAC_CHECK_STATUS(status); status = icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); return status; } numDcConcurrentReq = (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); if (CPA_STATUS_FAIL == validateConcurrRequest(numDcConcurrentReq)) { LAC_LOG_ERROR("Invalid NumConcurrentDcRequests, valid " "values {64, 128, 256, 512, .. 32768, 65536}"); return CPA_STATUS_FAIL; } *pNumDcConcurrentReq = numDcConcurrentReq; return status; } CpaStatus SalCtrl_CompressionInit(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numCompConcurrentReq = 0; char compMemPool[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; Cpa32U msgSize = 0; char *section = NULL; char *serviceName = NULL; char *memPoolName = NULL; lac_memory_pool_id_t *poolID = NULL; icp_comms_trans_handle trans_handle_tx = NULL; icp_comms_trans_handle trans_handle_rx = NULL; #ifndef ICP_DC_ONLY sal_dc_chain_service_t *pChainService = NULL; #endif SAL_SERVICE_GOOD_FOR_INIT(pCompressionService); pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_INITIALIZING; section = icpGetProcessName(); if (pStatsCollection == NULL) { return CPA_STATUS_FAIL; } /* Get Config Info: Accel Num, bank Num, packageID, coreAffinity, nodeAffinity and response mode */ pCompressionService->acceleratorNum = 0; pCompressionService->compression_mem_pool = LAC_MEM_POOL_INIT_POOL_ID; pCompressionService->decompression_mem_pool = LAC_MEM_POOL_INIT_POOL_ID; pCompressionService->trans_handle_compression_tx = NULL; pCompressionService->trans_handle_compression_rx = NULL; pCompressionService->trans_handle_decompression_tx = NULL; pCompressionService->trans_handle_decompression_rx = NULL; pCompressionService->debug_file = NULL; /* Initialise device specific compression data */ status = SalCtrl_SetDCCaps(&pCompressionService->dc_capabilities, device->deviceType, device->dcExtendedFeatures, (fw_caps_t *)&device->fw_caps); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to set capabilities"); return status; } switch (service->type) { case SAL_SERVICE_TYPE_COMPRESSION: serviceName = SAL_CFG_DC; memPoolName = SAL_CFG_MEMPOOL; poolID = &pCompressionService->compression_mem_pool; trans_handle_tx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_compression_tx); trans_handle_rx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_compression_rx); break; case SAL_SERVICE_TYPE_DECOMPRESSION: if (!pCompressionService->dc_capabilities.deviceData .decompressionServiceSupported) { LAC_LOG_ERROR( "Capabilities not enabled for decompression service"); return CPA_STATUS_FAIL; } serviceName = SAL_CFG_DECOMP; memPoolName = SAL_CFG_DECOMP_MEMPOOL; poolID = &pCompressionService->decompression_mem_pool; trans_handle_tx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_decompression_tx); trans_handle_rx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_decompression_rx); break; default: LAC_LOG_ERROR("Invalid service type"); return CPA_STATUS_FAIL; } status = SalCtr_DcInstInit(device, service, serviceName); LAC_CHECK_STATUS(status); if (SAL_RESP_POLL_CFG_FILE == pCompressionService->isPolled) { rx_resp_type = ICP_RESP_TYPE_POLL; } if (SalCtrl_GetDcConcurrentReqNum(serviceName, section, SAL_CFG_RING_DC_SIZE, pCompressionService, &numCompConcurrentReq, device)) { LAC_LOG_ERROR1("Failed to get ConcurrentReqNum for %s Service\n", serviceName); return CPA_STATUS_FAIL; } /* ADF does not allow us to completely fill the ring for batch requests */ pCompressionService->maxNumCompConcurrentReq = (numCompConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); /* 1. Create transport handles */ status = Sal_StringParsing(serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_RING_DC_TX, temp_string); LAC_CHECK_STATUS(status); msgSize = LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transCreateHandle(device, ICP_TRANS_TYPE_ETR, section, pCompressionService->acceleratorNum, pCompressionService->bankNum, temp_string, lac_getRingType(SAL_RING_TYPE_DC), NULL, ICP_RESP_TYPE_NONE, numCompConcurrentReq, msgSize, trans_handle_tx); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to create %s TX handle", serviceName); goto cleanup; } status = Sal_StringParsing(serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_RING_DC_RX, temp_string); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to parse %sRingRx string", serviceName); goto cleanup; } msgSize = LAC_QAT_DC_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transCreateHandle( device, ICP_TRANS_TYPE_ETR, section, pCompressionService->acceleratorNum, pCompressionService->bankNum, temp_string, lac_getRingType(SAL_RING_TYPE_NONE), (icp_trans_callback)dcCompression_ProcessCallback, rx_resp_type, numCompConcurrentReq, msgSize, trans_handle_rx); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to create %s RX handle", serviceName); goto cleanup; } /* 2. Allocates memory pools */ status = Sal_StringParsing(SAL_CFG_COMP, pCompressionService->generic_service_info.instance, memPoolName, compMemPool); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to parse %s string\n", memPoolName); goto cleanup; } status = Lac_MemPoolCreate(poolID, compMemPool, (numCompConcurrentReq + 1), sizeof(dc_compression_cookie_t), LAC_64BYTE_ALIGNMENT, CPA_TRUE, pCompressionService->nodeAffinity); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to create %s memory pool\n", serviceName); goto cleanup; } /* Init compression/decompression statistics */ status = dcStatsInit(pCompressionService); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to initialize %s statistics\n", serviceName); goto cleanup; } /* Initialize Data Compression/Decompression Cookies */ Lac_MemPoolInitDcCookies(*poolID); status = SalCtrl_DcDebugInit(device, service, serviceName); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to initialize %s debugfs\n", serviceName); goto cleanup; } pCompressionService->pDcChainService = NULL; #ifndef ICP_DC_ONLY #ifndef KERNEL_SPACE /* Only init Chaining service if loaded FW supports chaining */ if ((CHAINING_CAPABILITY_MASK & device->dcExtendedFeatures) && (SAL_SERVICE_TYPE_COMPRESSION == pCompressionService->generic_service_info.type)) { status = LAC_OS_MALLOC(&pChainService, sizeof(sal_dc_chain_service_t)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to allocate chain service\n"); goto cleanup; } LAC_OS_BZERO(pChainService, sizeof(sal_dc_chain_service_t)); status = dcChainServiceInit(pCompressionService, pChainService); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to init chain service\n"); goto cleanup; } } #endif #endif pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_INITIALIZED; return status; cleanup: if (*(icp_comms_trans_handle *)trans_handle_tx) { icp_adf_transReleaseHandle(*(icp_comms_trans_handle *)trans_handle_tx); } if (*(icp_comms_trans_handle *)trans_handle_rx) { icp_adf_transReleaseHandle(*(icp_comms_trans_handle *)trans_handle_rx); } if (LAC_MEM_POOL_INIT_POOL_ID != *poolID) { Lac_MemPoolDestroy(*poolID); } SalCtrl_DcDebugShutdown(device, service); #ifndef ICP_DC_ONLY if (NULL != pChainService) { LAC_OS_FREE(pChainService); } #endif return status; } CpaStatus SalCtrl_CompressionStart(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; if (SAL_SERVICE_STATE_INITIALIZED != pCompressionService->generic_service_info.state) { LAC_LOG_ERROR("Not in the correct state to call start\n"); return CPA_STATUS_FAIL; } /**************************************************************/ /* Obtain Extended Features. I.e. Compress And Verify */ /**************************************************************/ pCompressionService->generic_service_info.dcExtendedFeatures = device->dcExtendedFeatures; pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_RUNNING; return status; } CpaStatus SalCtrl_CompressionStop(icp_accel_dev_t *device, sal_service_t *service) { sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; if (SAL_SERVICE_STATE_RUNNING != pCompressionService->generic_service_info.state) { LAC_LOG_ERROR("Not in the correct state to call stop"); return CPA_STATUS_FAIL; } pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_SHUTTING_DOWN; return CPA_STATUS_SUCCESS; } CpaStatus SalCtrl_CompressionShutdown(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; if ((SAL_SERVICE_STATE_INITIALIZED != pCompressionService->generic_service_info.state) && (SAL_SERVICE_STATE_SHUTTING_DOWN != pCompressionService->generic_service_info.state) && (SAL_SERVICE_STATE_RESTARTING != pCompressionService->generic_service_info.state)) { LAC_LOG_ERROR("Not in the correct state to call shutdown"); return CPA_STATUS_FAIL; } if (SAL_SERVICE_TYPE_COMPRESSION == service->type) { Lac_MemPoolDestroy(pCompressionService->compression_mem_pool); status = icp_adf_transReleaseHandle( pCompressionService->trans_handle_compression_tx); LAC_CHECK_STATUS(status); status = icp_adf_transReleaseHandle( pCompressionService->trans_handle_compression_rx); LAC_CHECK_STATUS(status); } else if (SAL_SERVICE_TYPE_DECOMPRESSION == service->type) { Lac_MemPoolDestroy(pCompressionService->decompression_mem_pool); status = icp_adf_transReleaseHandle( pCompressionService->trans_handle_decompression_tx); LAC_CHECK_STATUS(status); status = icp_adf_transReleaseHandle( pCompressionService->trans_handle_decompression_rx); LAC_CHECK_STATUS(status); } if (CPA_TRUE == pStatsCollection->bDcStatsEnabled) { if (NULL != pCompressionService->debug_file) { /* Clean stats */ LAC_OS_FREE(pCompressionService->debug_file->name); LAC_OS_FREE(pCompressionService->debug_file); pCompressionService->debug_file = NULL; } } pCompressionService->generic_service_info.stats = NULL; dcStatsFree(pCompressionService); #ifndef ICP_DC_ONLY if (NULL != pCompressionService->pDcChainService) { dcChainServiceShutdown(pCompressionService, pCompressionService->pDcChainService); LAC_OS_FREE(pCompressionService->pDcChainService); } #endif SalCtrl_DcDebugShutdown(device, service); pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_SHUTDOWN; return status; } CpaStatus SalCtrl_CompressionRestarting(icp_accel_dev_t *device, sal_service_t *service) { sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; CpaStatus status = CPA_STATUS_SUCCESS; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; if ((SAL_SERVICE_STATE_RUNNING != pCompressionService->generic_service_info.state) && (SAL_SERVICE_STATE_ERROR != pCompressionService->generic_service_info.state)) { LAC_LOG_ERROR("Not in the correct state to call restarting\n"); return CPA_STATUS_FAIL; } if (SAL_SERVICE_TYPE_COMPRESSION == service->type) { status = icp_adf_transResetHandle( pCompressionService->trans_handle_compression_tx); LAC_CHECK_STATUS(status); status = icp_adf_transResetHandle( pCompressionService->trans_handle_compression_rx); LAC_CHECK_STATUS(status); } else if (SAL_SERVICE_TYPE_DECOMPRESSION == service->type) { status = icp_adf_transResetHandle( pCompressionService->trans_handle_decompression_tx); LAC_CHECK_STATUS(status); status = icp_adf_transResetHandle( pCompressionService->trans_handle_decompression_rx); LAC_CHECK_STATUS(status); } if (CPA_TRUE == pStatsCollection->bDcStatsEnabled) { /* Free debug file */ LAC_OS_FREE(pCompressionService->debug_file->name); LAC_OS_FREE(pCompressionService->debug_file); pCompressionService->debug_file = NULL; } #ifndef ICP_DC_ONLY if (NULL != pCompressionService->pDcChainService) { dcChainServiceShutdown(pCompressionService, pCompressionService->pDcChainService); LAC_OS_FREE(pCompressionService->pDcChainService); } #endif SalCtrl_DcDebugRestarting(device, service); pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_RESTARTING; dcStatsReset(pCompressionService); return CPA_STATUS_SUCCESS; } CpaStatus SalCtrl_CompressionRestarted(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numCompConcurrentReq = 0; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; Cpa32U msgSize = 0; char *section = NULL; char *serviceName = NULL; lac_memory_pool_id_t poolID = LAC_MEM_POOL_INIT_POOL_ID; icp_comms_trans_handle trans_handle_tx = NULL; icp_comms_trans_handle trans_handle_rx = NULL; #ifndef ICP_DC_ONLY sal_dc_chain_service_t *pChainService = NULL; #endif SAL_SERVICE_GOOD_FOR_RESTARTED(pCompressionService); section = icpGetProcessName(); if (pStatsCollection == NULL) { return CPA_STATUS_FAIL; } /* Get Config Info: Accel Num, bank Num, packageID, coreAffinity, nodeAffinity and response mode */ pCompressionService->acceleratorNum = 0; pCompressionService->debug_file = NULL; /* Initialise device specific compression data */ status = SalCtrl_SetDCCaps(&pCompressionService->dc_capabilities, device->deviceType, device->dcExtendedFeatures, (fw_caps_t *)&device->fw_caps); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to set capabilities"); return status; } switch (service->type) { case SAL_SERVICE_TYPE_COMPRESSION: serviceName = SAL_CFG_DC; poolID = pCompressionService->compression_mem_pool; trans_handle_tx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_compression_tx); trans_handle_rx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_compression_rx); break; case SAL_SERVICE_TYPE_DECOMPRESSION: serviceName = SAL_CFG_DECOMP; poolID = pCompressionService->decompression_mem_pool; trans_handle_tx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_decompression_tx); trans_handle_rx = (icp_comms_trans_handle *)&( pCompressionService->trans_handle_decompression_rx); break; default: LAC_LOG_ERROR("Invalid service type"); return CPA_STATUS_FAIL; } status = SalCtr_DcInstInit(device, service, serviceName); LAC_CHECK_STATUS(status); if (SAL_RESP_POLL_CFG_FILE == pCompressionService->isPolled) { rx_resp_type = ICP_RESP_TYPE_POLL; } if (SalCtrl_GetDcConcurrentReqNum(serviceName, section, SAL_CFG_RING_DC_SIZE, pCompressionService, &numCompConcurrentReq, device)) { LAC_LOG_ERROR1("Failed to get ConcurrentReqNum for %s service\n", serviceName); status = CPA_STATUS_FAIL; goto cleanup; } /* ADF does not allow us to completely fill the ring for batch requests */ pCompressionService->maxNumCompConcurrentReq = (numCompConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); /* 1. Create transport handles */ status = Sal_StringParsing(serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_RING_DC_TX, temp_string); LAC_CHECK_STATUS(status); msgSize = LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transReinitHandle(device, ICP_TRANS_TYPE_ETR, section, pCompressionService->acceleratorNum, pCompressionService->bankNum, temp_string, lac_getRingType(SAL_RING_TYPE_DC), NULL, ICP_RESP_TYPE_NONE, numCompConcurrentReq, msgSize, trans_handle_tx); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to create %s TX handle", serviceName); goto cleanup; } status = Sal_StringParsing(serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_RING_DC_RX, temp_string); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to parse %sRingRx string", serviceName); goto cleanup; } msgSize = LAC_QAT_DC_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transReinitHandle( device, ICP_TRANS_TYPE_ETR, section, pCompressionService->acceleratorNum, pCompressionService->bankNum, temp_string, lac_getRingType(SAL_RING_TYPE_NONE), (icp_trans_callback)dcCompression_ProcessCallback, rx_resp_type, numCompConcurrentReq, msgSize, trans_handle_rx); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to create %s RX handle", serviceName); goto cleanup; } /* Enabling memory pool for generating dummy response */ Lac_MemPoolEnable(poolID); status = SalCtrl_DcDebugInit(device, service, serviceName); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR1("Failed to initialize %s debugfs\n", serviceName); goto cleanup; } pCompressionService->pDcChainService = NULL; #ifndef ICP_DC_ONLY #ifndef KERNEL_SPACE /* Only init Chaining service if loaded FW supports chaining */ if ((CHAINING_CAPABILITY_MASK & device->dcExtendedFeatures)) { status = LAC_OS_MALLOC(&pChainService, sizeof(sal_dc_chain_service_t)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to allocate chain service\n"); goto cleanup; } LAC_OS_BZERO(pChainService, sizeof(sal_dc_chain_service_t)); status = dcChainServiceInit(pCompressionService, pChainService); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to init chain service\n"); goto cleanup; } } #endif #endif pCompressionService->generic_service_info.dcExtendedFeatures = device->dcExtendedFeatures; pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_RUNNING; /* Initialize Data Compression/Decompression Cookies */ Lac_MemPoolInitDcCookies(poolID); return status; cleanup: if (*(icp_comms_trans_handle *)trans_handle_tx) { icp_adf_transReleaseHandle(*(icp_comms_trans_handle *)trans_handle_tx); } if (*(icp_comms_trans_handle *)trans_handle_rx) { icp_adf_transReleaseHandle(*(icp_comms_trans_handle *)trans_handle_rx); } if (LAC_MEM_POOL_INIT_POOL_ID != poolID) { Lac_MemPoolDestroy(poolID); } #ifndef ICP_DC_ONLY if (NULL != pChainService) { LAC_OS_FREE(pChainService); } #endif return status; } CpaStatus SalCtrl_CompressionError(icp_accel_dev_t *device, sal_service_t *service) { sal_compression_service_t *pCompressionService = (sal_compression_service_t *)service; CpaStatus status = CPA_STATUS_SUCCESS; SalCtrl_DcMemPoolDisable(service); SalCtrl_DcUpdatePoolsBusy(service); /* Considering the detachment of the VFs, the device is still alive and * can generate responses normally. After the state of the service is * set to ERROR, if it goes to the function to check responses in such * cases, it will indicate there are some responses on the ring. However, * icp_sal_DcPollInstance() function will only call * SalCtrl_DcGenResponses() to generate dummy responses not poll the * instance with icp_adf_pollInstance() as the service has been set to * ERROR. So adding a judgment condition here to avoid to check the * response ring again. */ if (SAL_SERVICE_STATE_ERROR != pCompressionService->generic_service_info.state) { status = SalCtrl_DcCheckRespInstance(service); /* The polling functions would be prevented to poll due to * SAL_RUNNING_CHECK check which may cause missing retrieving in-flight * responses. Hence the error status is only set after there are no * remained responses on the response ring. */ if (CPA_STATUS_SUCCESS == status) { pCompressionService->generic_service_info.state = SAL_SERVICE_STATE_ERROR; } } return status; } CpaStatus cpaDcGetStatusText(const CpaInstanceHandle dcInstance, const CpaStatus errStatus, Cpa8S *pStatusText) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pStatusText); #endif #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, %d, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, errStatus, (LAC_ARCH_UINT)pStatusText); #endif switch (errStatus) { case CPA_STATUS_SUCCESS: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_SUCCESS); break; case CPA_STATUS_FAIL: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FAIL); break; case CPA_STATUS_RETRY: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RETRY); break; case CPA_STATUS_RESOURCE: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RESOURCE); break; case CPA_STATUS_INVALID_PARAM: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_INVALID_PARAM); break; case CPA_STATUS_FATAL: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FATAL); break; case CPA_STATUS_UNSUPPORTED: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_UNSUPPORTED); break; default: status = CPA_STATUS_INVALID_PARAM; break; } return status; } CpaStatus cpaDcGetNumIntermediateBuffers(CpaInstanceHandle dcInstance, Cpa16U *pNumBuffers) { CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; dc_capabilities_t *pDcCapabilities = NULL; if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); } else { insHandle = dcInstance; } #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); LAC_CHECK_NULL_PARAM(pNumBuffers); #endif pService = (sal_compression_service_t *)insHandle; /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; *pNumBuffers = pDcCapabilities->numInterBuffs; #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx[%d])\n", (LAC_ARCH_UINT)insHandle, (LAC_ARCH_UINT)pNumBuffers, *pNumBuffers); #endif return CPA_STATUS_SUCCESS; } CpaStatus cpaDcStartInstance(CpaInstanceHandle instanceHandle, Cpa16U numBuffers, CpaBufferList **pIntermediateBufferPtrsArray) { icp_qat_addr_width_t *pInterBuffPtrsArray = NULL; icp_qat_addr_width_t pArrayBufferListDescPhyAddr = 0; icp_qat_addr_width_t bufListDescPhyAddr; icp_qat_addr_width_t bufListAlignedPhyAddr; CpaFlatBuffer *pClientCurrFlatBuffer = NULL; icp_buffer_list_desc_t *pBufferListDesc = NULL; icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; icp_accel_dev_t *dev = NULL; CpaStatus status = CPA_STATUS_SUCCESS; sal_compression_service_t *pService = NULL; CpaInstanceHandle insHandle = NULL; Cpa16U bufferIndex = 0; Cpa32U numFlatBuffers = 0; Cpa64U clientListSize = 0; CpaBufferList *pClientCurrentIntermediateBuffer = NULL; dc_capabilities_t *pDcCapabilities = NULL; /* Check parameters */ #ifdef ICP_PARAM_CHECK Cpa32U bufferIndex2 = 0; CpaBufferList **pTempIntermediateBufferPtrsArray; Cpa64U lastClientListSize = 0; #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { insHandle = dcGetFirstHandle(); } else { insHandle = instanceHandle; } LAC_CHECK_NULL_PARAM(insHandle); pService = (sal_compression_service_t *)insHandle; dev = icp_adf_getAccelDevByAccelId(pService->acceleratorNum); if (NULL == dev) { LAC_LOG_ERROR("Can not find device for the instance\n"); return CPA_STATUS_FAIL; } pService = (sal_compression_service_t *)insHandle; if (NULL == pIntermediateBufferPtrsArray) { pService->generic_service_info.isInstanceStarted = CPA_TRUE; /* Increment dev ref counter and return - DRAM is not used */ icp_adf_qaDevGet(dev); return CPA_STATUS_SUCCESS; } if (0 == numBuffers) { pService->generic_service_info.isInstanceStarted = CPA_TRUE; /* Increment dev ref counter and return - DRAM is not used */ icp_adf_qaDevGet(dev); return CPA_STATUS_SUCCESS; } /* Retrieve capabilities */ pDcCapabilities = &pService->dc_capabilities; /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); if ((numBuffers > 0) && (NULL == pIntermediateBufferPtrsArray)) { LAC_LOG_ERROR("Invalid Intermediate Buffers Array pointer\n"); return CPA_STATUS_INVALID_PARAM; } /* Check number of intermediate buffers allocated by user */ if ((pDcCapabilities->numInterBuffs != numBuffers)) { LAC_LOG_ERROR("Invalid number of buffers\n"); return CPA_STATUS_INVALID_PARAM; } pTempIntermediateBufferPtrsArray = pIntermediateBufferPtrsArray; for (bufferIndex = 0; bufferIndex < numBuffers; bufferIndex++) { if (NULL == *pTempIntermediateBufferPtrsArray) { LAC_LOG_ERROR( "Intermediate Buffer - Invalid Buffer List pointer\n"); return CPA_STATUS_INVALID_PARAM; } if (NULL == (*pTempIntermediateBufferPtrsArray)->pBuffers) { LAC_LOG_ERROR("Intermediate Buffer - Invalid Flat Buffer " "descriptor pointer\n"); return CPA_STATUS_INVALID_PARAM; } if (NULL == (*pTempIntermediateBufferPtrsArray)->pPrivateMetaData) { LAC_LOG_ERROR("Intermediate Buffer - Invalid Private MetaData " "descriptor pointer\n"); return CPA_STATUS_INVALID_PARAM; } clientListSize = 0; for (bufferIndex2 = 0; bufferIndex2 < (*pTempIntermediateBufferPtrsArray)->numBuffers; bufferIndex2++) { if ((0 != (*pTempIntermediateBufferPtrsArray) ->pBuffers[bufferIndex2] .dataLenInBytes) && NULL == (*pTempIntermediateBufferPtrsArray) ->pBuffers[bufferIndex2] .pData) { LAC_LOG_ERROR( "Intermediate Buffer - Invalid Flat Buffer pointer\n"); return CPA_STATUS_INVALID_PARAM; } clientListSize += (*pTempIntermediateBufferPtrsArray) ->pBuffers[bufferIndex2] .dataLenInBytes; } if (bufferIndex != 0) { if (lastClientListSize != clientListSize) { LAC_LOG_ERROR("SGLs have to be of the same size\n"); return CPA_STATUS_INVALID_PARAM; } } else { lastClientListSize = clientListSize; } pTempIntermediateBufferPtrsArray++; } SAL_CHECK_ADDR_TRANS_SETUP(insHandle); #endif /* Allocate array of physical pointers to icp_buffer_list_desc_t */ status = LAC_OS_CAMALLOC(&pInterBuffPtrsArray, (numBuffers * sizeof(icp_qat_addr_width_t)), LAC_64BYTE_ALIGNMENT, pService->nodeAffinity); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Can not allocate Intermediate Buffers array\n"); return status; } /* Get physical address of the intermediate buffer pointers array */ pArrayBufferListDescPhyAddr = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_INTERNAL( &pService->generic_service_info, pInterBuffPtrsArray)); pService->pInterBuffPtrsArray = pInterBuffPtrsArray; pService->pInterBuffPtrsArrayPhyAddr = pArrayBufferListDescPhyAddr; /* Get the full size of the buffer list */ /* Assumption: all the SGLs allocated by the user have the same size */ clientListSize = 0; for (bufferIndex = 0; (Cpa32U)bufferIndex < (*pIntermediateBufferPtrsArray)->numBuffers; bufferIndex++) { clientListSize += ((*pIntermediateBufferPtrsArray) ->pBuffers[bufferIndex] .dataLenInBytes); } pService->minInterBuffSizeInBytes = clientListSize; for (bufferIndex = 0; bufferIndex < numBuffers; bufferIndex++) { /* Get pointer to the client Intermediate Buffer List (CpaBufferList) */ pClientCurrentIntermediateBuffer = *pIntermediateBufferPtrsArray; /* Get number of flat buffers in the buffer list */ numFlatBuffers = pClientCurrentIntermediateBuffer->numBuffers; /* Get pointer to the client array of CpaFlatBuffers */ pClientCurrFlatBuffer = pClientCurrentIntermediateBuffer->pBuffers; /* Calculate Physical address of current private SGL */ bufListDescPhyAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( (*pService), pClientCurrentIntermediateBuffer->pPrivateMetaData); if (bufListDescPhyAddr == 0) { LAC_LOG_ERROR( "Unable to get the physical address of the metadata\n"); return CPA_STATUS_FAIL; } /* Align SGL physical address */ bufListAlignedPhyAddr = LAC_ALIGN_POW2_ROUNDUP( bufListDescPhyAddr, ICP_DESCRIPTOR_ALIGNMENT_BYTES); /* Set physical address of the Intermediate Buffer SGL in the SGLs array */ *pInterBuffPtrsArray = LAC_MEM_CAST_PTR_TO_UINT64(bufListAlignedPhyAddr); /* Calculate (virtual) offset to the buffer list descriptor */ pBufferListDesc = (icp_buffer_list_desc_t *)((LAC_ARCH_UINT) pClientCurrentIntermediateBuffer ->pPrivateMetaData + (LAC_ARCH_UINT)(bufListAlignedPhyAddr - bufListDescPhyAddr)); /* Set number of flat buffers in the physical Buffer List descriptor */ pBufferListDesc->numBuffers = numFlatBuffers; /* Go past the Buffer List descriptor to the list of buffer descriptors */ pCurrFlatBufDesc = (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); /* Loop for each flat buffer in the SGL */ while (0 != numFlatBuffers) { /* Set length of the current flat buffer */ pCurrFlatBufDesc->dataLenInBytes = pClientCurrFlatBuffer->dataLenInBytes; /* Set physical address of the flat buffer */ pCurrFlatBufDesc->phyBuffer = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( (*pService), pClientCurrFlatBuffer->pData)); if (pCurrFlatBufDesc->phyBuffer == 0) { LAC_LOG_ERROR("Unable to get the physical address of the flat" " buffer\n"); return CPA_STATUS_FAIL; } pCurrFlatBufDesc++; pClientCurrFlatBuffer++; numFlatBuffers--; } pIntermediateBufferPtrsArray++; pInterBuffPtrsArray++; } pService->generic_service_info.isInstanceStarted = CPA_TRUE; /* Increment dev ref counter */ icp_adf_qaDevGet(dev); return CPA_STATUS_SUCCESS; } CpaStatus cpaDcStopInstance(CpaInstanceHandle instanceHandle) { CpaInstanceHandle insHandle = NULL; icp_accel_dev_t *dev = NULL; sal_compression_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG1("Called with params (0x%lx)\n", (LAC_ARCH_UINT)instanceHandle); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { insHandle = dcGetFirstHandle(); } else { insHandle = instanceHandle; } LAC_CHECK_NULL_PARAM(insHandle); pService = (sal_compression_service_t *)insHandle; /* Free Intermediate Buffer Pointers Array */ if (pService->pInterBuffPtrsArray != NULL) { LAC_OS_CAFREE(pService->pInterBuffPtrsArray); pService->pInterBuffPtrsArray = 0; } pService->pInterBuffPtrsArrayPhyAddr = 0; dev = icp_adf_getAccelDevByAccelId(pService->acceleratorNum); if (NULL == dev) { LAC_LOG_ERROR("Can not find device for the instance\n"); return CPA_STATUS_FAIL; } pService->generic_service_info.isInstanceStarted = CPA_FALSE; /* Decrement dev ref counter */ icp_adf_qaDevPut(dev); return CPA_STATUS_SUCCESS; } CpaStatus cpaDcGetNumInstances(Cpa16U *pNumInstances) { return Lac_GetDcNumInstancesByType(CPA_ACC_SVC_TYPE_DATA_COMPRESSION, pNumInstances); } CpaStatus cpaDcGetInstances(Cpa16U numInstances, CpaInstanceHandle *dcInstances) { return Lac_GetDcInstancesByType( CPA_ACC_SVC_TYPE_DATA_COMPRESSION, numInstances, dcInstances); } CpaStatus cpaDcInstanceGetInfo2(const CpaInstanceHandle instanceHandle, CpaInstanceInfo2 *pInstanceInfo2) { sal_compression_service_t *pCompressionService = NULL; CpaInstanceHandle insHandle = NULL; icp_accel_dev_t *dev = NULL; CpaStatus status = CPA_STATUS_SUCCESS; char keyStr[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = { '\0' }; char valStr[CPA_INST_NAME_SIZE] = { '\0' }; char *section = NULL; char *serviceName = NULL; Cpa32S strSize = 0; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pInstanceInfo2); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { insHandle = dcGetFirstHandle(); } else { insHandle = instanceHandle; } LAC_CHECK_NULL_PARAM(insHandle); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); LAC_CHECK_NULL_PARAM(pInstanceInfo2); LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); snprintf((char *)pInstanceInfo2->vendorName, CPA_INST_VENDOR_NAME_SIZE, "%s", SAL_INFO2_VENDOR_NAME); pInstanceInfo2->vendorName[CPA_INST_VENDOR_NAME_SIZE - 1] = '\0'; snprintf((char *)pInstanceInfo2->swVersion, CPA_INST_SW_VERSION_SIZE, "Version %d.%d", SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER); pInstanceInfo2->swVersion[CPA_INST_SW_VERSION_SIZE - 1] = '\0'; /* Note we can safely read the contents of the compression service instance here because icp_adf_getAccelDevByCapabilities() only returns devs that have started */ pCompressionService = (sal_compression_service_t *)insHandle; if (pCompressionService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { pInstanceInfo2->accelerationServiceType = CPA_ACC_SVC_TYPE_DATA_COMPRESSION; serviceName = SAL_CFG_DC; } else { pInstanceInfo2->accelerationServiceType = CPA_ACC_SVC_TYPE_DATA_DECOMPRESSION; serviceName = SAL_CFG_DECOMP; } pInstanceInfo2->physInstId.packageId = pCompressionService->pkgID; pInstanceInfo2->physInstId.acceleratorId = pCompressionService->acceleratorNum; pInstanceInfo2->physInstId.executionEngineId = 0; pInstanceInfo2->physInstId.busAddress = icp_adf_getBusAddress(pInstanceInfo2->physInstId.acceleratorId); /* set coreAffinity to zero before use */ LAC_OS_BZERO(pInstanceInfo2->coreAffinity, sizeof(pInstanceInfo2->coreAffinity)); CPA_BITMAP_BIT_SET(pInstanceInfo2->coreAffinity, pCompressionService->coreAffinity); pInstanceInfo2->nodeAffinity = pCompressionService->nodeAffinity; if (CPA_TRUE == pCompressionService->generic_service_info.isInstanceStarted) { pInstanceInfo2->operState = CPA_OPER_STATE_UP; } else { pInstanceInfo2->operState = CPA_OPER_STATE_DOWN; } pInstanceInfo2->requiresPhysicallyContiguousMemory = CPA_TRUE; if (SAL_RESP_POLL_CFG_FILE == pCompressionService->isPolled || SAL_RESP_EPOLL_CFG_FILE == pCompressionService->isPolled) { pInstanceInfo2->isPolled = CPA_TRUE; } else { pInstanceInfo2->isPolled = CPA_FALSE; } pInstanceInfo2->isOffloaded = CPA_TRUE; /* Get the instance name and part name from the config file */ dev = icp_adf_getAccelDevByAccelId(pCompressionService->acceleratorNum); if (NULL == dev) { LAC_LOG_ERROR("Can not find device for the instance\n"); LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); return CPA_STATUS_FAIL; } snprintf((char *)pInstanceInfo2->partName, CPA_INST_PART_NAME_SIZE, SAL_INFO2_PART_NAME, dev->deviceName); pInstanceInfo2->partName[CPA_INST_PART_NAME_SIZE - 1] = '\0'; section = icpGetProcessName(); status = Sal_StringParsing(serviceName, pCompressionService->generic_service_info.instance, SAL_CFG_NAME, keyStr); LAC_CHECK_STATUS(status); status = icp_adf_cfgGetParamValue(dev, section, keyStr, valStr); LAC_CHECK_STATUS(status); strSize = strnlen(valStr, sizeof(valStr)); LAC_CHECK_PARAM_RANGE(strSize, 1, CPA_INST_NAME_SIZE); snprintf((char *)pInstanceInfo2->instName, CPA_INST_NAME_SIZE, "%.*s", CPA_INST_NAME_SIZE - 1, valStr); strSize = strnlen(valStr, sizeof(valStr)) + strnlen(section, LAC_USER_PROCESS_NAME_MAX_LEN) + 1; LAC_CHECK_PARAM_RANGE(strSize, 1, CPA_INST_ID_SIZE); snprintf((char *)pInstanceInfo2->instID, CPA_INST_ID_SIZE, "%s_%s", section, valStr); return CPA_STATUS_SUCCESS; } CpaStatus cpaDcQueryCapabilities( CpaInstanceHandle dcInstance, CpaDcInstanceCapabilities *pInstanceCapabilities) { CpaInstanceHandle insHandle = NULL; sal_compression_service_t *pService = NULL; dc_capabilities_t *pDcCapabilities = NULL; dc_extd_ftrs_t *pExtendedFtrs = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)dcInstance, (LAC_ARCH_UINT)pInstanceCapabilities); #endif if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { insHandle = dcGetFirstHandle(); if (NULL == insHandle) { LAC_LOG_ERROR("Can not get the instance\n"); return CPA_STATUS_FAIL; } } else { insHandle = dcInstance; } pService = (sal_compression_service_t *)insHandle; /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); LAC_CHECK_NULL_PARAM(pInstanceCapabilities); #endif pDcCapabilities = &pService->dc_capabilities; osalMemSet(pInstanceCapabilities, 0, sizeof(CpaDcInstanceCapabilities)); /* Set compression capabilities */ if (pService->generic_service_info.type == SAL_SERVICE_TYPE_COMPRESSION) { if (pDcCapabilities->lz4.supported == CPA_TRUE) { if (pDcCapabilities->lz4.dirMask & DC_CAPS_COMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATELESS) { pInstanceCapabilities->statelessLZ4Compression = CPA_TRUE; } if (pDcCapabilities->lz4.dirMask & DC_CAPS_DECOMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATELESS) { pInstanceCapabilities->statelessLZ4Decompression = CPA_TRUE; } if (pDcCapabilities->lz4.dirMask & DC_CAPS_DECOMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATEFUL) { pInstanceCapabilities->statefulLZ4Decompression = CPA_TRUE; } pInstanceCapabilities->checksumXXHash32 = pDcCapabilities->lz4.checksumXXHash32; } if (pDcCapabilities->lz4s.supported == CPA_TRUE) { if (pDcCapabilities->lz4s.dirMask & DC_CAPS_COMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATELESS) { pInstanceCapabilities->statelessLZ4SCompression = CPA_TRUE; } pInstanceCapabilities->checksumXXHash32 = pDcCapabilities->lz4s.checksumXXHash32; } if (pDcCapabilities->deflate.supported == CPA_TRUE) { if (pDcCapabilities->deflate.dirMask & DC_CAPS_COMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATEFUL) { pInstanceCapabilities->statefulDeflateCompression = CPA_TRUE; } if (pDcCapabilities->deflate.dirMask & DC_CAPS_DECOMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATEFUL) { pInstanceCapabilities->statefulDeflateDecompression = CPA_TRUE; } if (pDcCapabilities->deflate.dirMask & DC_CAPS_COMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATELESS) { pInstanceCapabilities->statelessDeflateCompression = CPA_TRUE; } if (pDcCapabilities->deflate.dirMask & DC_CAPS_DECOMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATELESS) { pInstanceCapabilities->statelessDeflateDecompression = CPA_TRUE; } } } /* Set decompression capabilities */ else { if (pDcCapabilities->lz4.supported == CPA_TRUE) { if (pDcCapabilities->lz4.dirMask & DC_CAPS_DECOMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATELESS) { pInstanceCapabilities->statelessLZ4Decompression = CPA_TRUE; } pInstanceCapabilities->statefulLZ4Decompression = CPA_FALSE; pInstanceCapabilities->checksumXXHash32 = pDcCapabilities->lz4.checksumXXHash32; } if (pDcCapabilities->deflate.supported == CPA_TRUE) { if (pDcCapabilities->deflate.dirMask & DC_CAPS_DECOMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATEFUL) { pInstanceCapabilities->statefulDeflateDecompression = CPA_FALSE; } if (pDcCapabilities->deflate.dirMask & DC_CAPS_DECOMPRESSION && pDcCapabilities->sessState & DC_CAPS_STATELESS) { pInstanceCapabilities->statelessDeflateDecompression = CPA_TRUE; } } } pInstanceCapabilities->integrityCrcs = pDcCapabilities->crcIntegrity.checkCRC32; pInstanceCapabilities->integrityCrcs64b = pDcCapabilities->crcIntegrity.checkCRC64; pInstanceCapabilities->endOfLastBlock = pDcCapabilities->endOfLastBlock; pInstanceCapabilities->checksumCRC32 = (CpaBoolean)(pDcCapabilities->checksum & DC_CAPS_CRC32); if (pDcCapabilities->checksum & DC_CAPS_ADLER32) { pInstanceCapabilities->checksumAdler32 = CPA_TRUE; } #ifndef ICP_DC_DYN_NOT_SUPPORTED pInstanceCapabilities->dynamicHuffman = CPA_TRUE; #else pInstanceCapabilities->dynamicHuffman = CPA_FALSE; #endif pInstanceCapabilities->precompiledHuffman = pDcCapabilities->deflate.precompiledHuffman; pInstanceCapabilities->dynamicHuffmanBufferReq = pDcCapabilities->deflate.dynamicHuffmanBufferReq; pInstanceCapabilities->autoSelectBestHuffmanTree = pDcCapabilities->asb.supported; pExtendedFtrs = (dc_extd_ftrs_t *)&(((sal_service_t *)insHandle)->dcExtendedFeatures); pInstanceCapabilities->batchAndPack = pDcCapabilities->batchAndPack; pInstanceCapabilities->compressAndVerify = pDcCapabilities->cnv.supported; pInstanceCapabilities->compressAndVerifyStrict = pDcCapabilities->cnv.strict; pInstanceCapabilities->compressAndVerifyAndRecover = pDcCapabilities->cnv.recovery; /* Set chaining capabilities */ #ifndef ICP_DC_ONLY if (pExtendedFtrs->is_chain_compress_then_hash) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_COMPRESS_THEN_HASH); } if (pExtendedFtrs->is_chain_compress_then_encrypt) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT); } if (pExtendedFtrs->is_chain_compress_then_hash_encrypt) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_COMPRESS_THEN_HASH_ENCRYPT); } if (pExtendedFtrs->is_chain_compress_then_encrypt_hash) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT_HASH); } if (pExtendedFtrs->is_chain_compress_then_aead) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_COMPRESS_THEN_AEAD); } if (pExtendedFtrs->is_chain_hash_then_compress) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_HASH_THEN_COMPRESS); } if (pExtendedFtrs->is_chain_hash_verify_then_decompress) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_HASH_VERIFY_THEN_DECOMPRESS); } if (pExtendedFtrs->is_chain_decrypt_then_decompress) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_DECRYPT_THEN_DECOMPRESS); } if (pExtendedFtrs->is_chain_hash_verify_decrypt_then_decompress) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_HASH_VERIFY_DECRYPT_THEN_DECOMPRESS); } if (pExtendedFtrs->is_chain_decrypt_hash_verify_then_decompress) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_DECRYPT_HASH_VERIFY_THEN_DECOMPRESS); } if (pExtendedFtrs->is_chain_aead_then_decompress) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS); } if (pExtendedFtrs->is_chain_decompress_then_hash_verify) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_DECOMPRESS_THEN_HASH_VERIFY); } if (pExtendedFtrs->is_chain_compress_then_aead_then_hash) { CPA_BITMAP_BIT_SET(pInstanceCapabilities->dcChainCapInfo, CPA_DC_CHAIN_COMPRESS_THEN_AEAD_THEN_HASH); } #endif return CPA_STATUS_SUCCESS; } CpaStatus cpaDcSetAddressTranslation(const CpaInstanceHandle instanceHandle, CpaVirtualToPhysical virtual2Physical) { sal_service_t *pService = NULL; CpaInstanceHandle insHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)virtual2Physical); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { insHandle = dcGetFirstHandle(); } else { insHandle = instanceHandle; } /* Check parameters */ #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(insHandle); /* Ensure this is a compression or a decompression instance */ SAL_CHECK_INSTANCE_TYPE( insHandle, (SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION)); LAC_CHECK_NULL_PARAM(virtual2Physical); #endif pService = (sal_service_t *)insHandle; pService->virt2PhysClient = virtual2Physical; return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup cpaDcCommon * Data compression specific polling function which polls a DC instance. *****************************************************************************/ CpaStatus icp_sal_DcPollInstance(CpaInstanceHandle instanceHandle_in, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_SUCCESS; sal_compression_service_t *dc_handle = NULL; sal_service_t *gen_handle = NULL; icp_comms_trans_handle trans_hndTable[DC_NUM_RX_RINGS]; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { dc_handle = (sal_compression_service_t *)dcGetFirstHandle(); } else { dc_handle = (sal_compression_service_t *)instanceHandle_in; } LAC_CHECK_NULL_PARAM(dc_handle); gen_handle = &(dc_handle->generic_service_info); /* * From the instanceHandle we must get the trans_handle and send * down to adf for polling. * Populate our trans handle table with the appropriate handles. */ switch (gen_handle->type) { case SAL_SERVICE_TYPE_COMPRESSION: trans_hndTable[0] = dc_handle->trans_handle_compression_rx; break; case SAL_SERVICE_TYPE_DECOMPRESSION: trans_hndTable[0] = dc_handle->trans_handle_decompression_rx; break; default: LAC_LOG_ERROR("The instance handle is the wrong type"); return CPA_STATUS_FAIL; } if ((Sal_ServiceIsInError(dc_handle))) { LAC_LOG_DEBUG("PollDcInstance: generate dummy responses\n"); status = SalCtrl_DcGenResponses(dc_handle); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR("Failed to generate SW responses for DC\n"); } return status; } SAL_RUNNING_CHECK(dc_handle); /* Call adf to do the polling. */ status = icp_adf_pollInstance(trans_hndTable, DC_NUM_RX_RINGS, response_quota); return status; } /* Polling DC instances' memory pool in progress of all banks for one device */ STATIC CpaStatus SalCtrl_DcService_GenResponses(sal_list_t **services) { CpaInstanceHandle dcInstance = NULL; sal_list_t *sal_service = NULL; sal_compression_service_t *dc_handle = NULL; CpaStatus status = CPA_STATUS_SUCCESS; LAC_CHECK_NULL_PARAM(services); sal_service = *services; while (sal_service) { dcInstance = (void *)SalList_getObject(sal_service); dc_handle = (sal_compression_service_t *)dcInstance; LAC_CHECK_NULL_PARAM(dc_handle); status = SalCtrl_DcGenResponses(dc_handle); if (CPA_STATUS_SUCCESS != status) { break; } sal_service = SalList_next(sal_service); } return status; } CpaStatus SalCtrl_DcDevErr_GenResponses(icp_accel_dev_t *accel_dev, Cpa32U enabled_services) { sal_t *service_container = NULL; CpaStatus status = CPA_STATUS_SUCCESS; service_container = accel_dev->pSalHandle; if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_DcService_GenResponses( &service_container->compression_services); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to generate dummy responses for Data " "Compression service"); return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_DcService_GenResponses( &service_container->decompression_services); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to generate dummy responses for Data " "Decompression service"); return status; } } return status; } /** ****************************************************************************** * @ingroup cpaDcCommon *****************************************************************************/ CpaStatus cpaDcInstanceSetNotificationCb( const CpaInstanceHandle instanceHandle, const CpaDcInstanceNotificationCbFunc pInstanceNotificationCb, void *pCallbackTag) { CpaStatus status = CPA_STATUS_SUCCESS; sal_service_t *gen_handle = instanceHandle; #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pInstanceNotificationCb, (LAC_ARCH_UINT)pCallbackTag); #endif LAC_CHECK_NULL_PARAM(gen_handle); gen_handle->notification_cb = pInstanceNotificationCb; gen_handle->cb_tag = pCallbackTag; return status; } CpaInstanceHandle dcGetFirstHandle(void) { CpaStatus status = CPA_STATUS_SUCCESS; static icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES] = {0}; CpaInstanceHandle dcInst = NULL; icp_accel_dev_t *dev_addr = NULL; sal_t *base_addr = NULL; sal_list_t *list_temp = NULL; Cpa16U i, num_dc = 0; /* Only need 1 dev with compression enabled - so check all devices */ status = icp_adf_getAllAccelDevByServices( (SERV_TYPE_DC | SERV_TYPE_DECOMP), adfInsts, &num_dc); if ((0 == num_dc) || (CPA_STATUS_SUCCESS != status)) { LAC_LOG("No compression devices enabled in the system\n"); return dcInst; } for (i = 0; i < num_dc; i++) { dev_addr = (icp_accel_dev_t *)adfInsts[i]; if (NULL != dev_addr) { base_addr = dev_addr->pSalHandle; if (NULL != base_addr) { list_temp = base_addr->compression_services; if (NULL != list_temp) { dcInst = SalList_getObject(list_temp); break; } list_temp = base_addr->decompression_services; if (NULL != list_temp) { dcInst = SalList_getObject(list_temp); break; } } } } return dcInst; } CpaStatus icp_sal_DcGetFileDescriptor(CpaInstanceHandle instanceHandle, int *fd) { sal_compression_service_t *dc_handle = NULL; sal_service_t *gen_handle = NULL; int dc_fd = -1; int ret = 0; dc_handle = (sal_compression_service_t *)instanceHandle; LAC_CHECK_NULL_PARAM(dc_handle); SAL_RUNNING_CHECK(dc_handle); gen_handle = &(dc_handle->generic_service_info); if (SAL_RESP_EPOLL_CFG_FILE != dc_handle->isPolled) { return CPA_STATUS_UNSUPPORTED; } switch (gen_handle->type) { case SAL_SERVICE_TYPE_COMPRESSION: ret = icp_adf_transGetFdForHandle( dc_handle->trans_handle_compression_rx, &dc_fd); break; case SAL_SERVICE_TYPE_DECOMPRESSION: ret = icp_adf_transGetFdForHandle( dc_handle->trans_handle_decompression_rx, &dc_fd); break; default: LAC_LOG_ERROR("The instance handle is the wrong type"); ret = CPA_STATUS_FAIL; break; } if (ret != CPA_STATUS_SUCCESS) { return CPA_STATUS_FAIL; } else { *fd = dc_fd; return CPA_STATUS_SUCCESS; } } CpaStatus icp_sal_DcPutFileDescriptor(CpaInstanceHandle instanceHandle, int fd) { sal_compression_service_t *dc_handle = NULL; sal_service_t *gen_handle = NULL; dc_handle = (sal_compression_service_t *)instanceHandle; LAC_CHECK_NULL_PARAM(dc_handle); SAL_RUNNING_CHECK(dc_handle); gen_handle = &(dc_handle->generic_service_info); if (!((SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_DECOMPRESSION) & gen_handle->type)) { LAC_LOG_ERROR("The instance handle is the wrong type"); return CPA_STATUS_FAIL; } if (SAL_RESP_EPOLL_CFG_FILE != dc_handle->isPolled) { return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_compression_capabilities.c000066400000000000000000000275641503624047500332400ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_compression_capabilities.c * * @defgroup SalCtrl_SetDCCaps for different devices * * @ingroup SalCtrl_SetDCCaps * * @description * Set capabilities based on device type for all devices * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa_dc_chain.h" #include "icp_qat_fw_comp.h" #include "icp_qat_hw_20_comp_defs.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "sal_types_compression.h" #include "dc_session.h" /* DEBUG */ #ifdef ICP_DEBUG #undef STATIC /* When DEBUG is set STATIC evaluates to nothing. */ #define STATIC #else /* otherwise it evaluates to the static keyword */ #define STATIC static #endif STATIC void SalCtrl_Set4xxxDcExtendedCapabilities( dc_capabilities_t *pDcCapabilities, fw_caps_t *fw_caps) { pDcCapabilities->checksum = ((fw_caps->cksum_algos & DC_CAPS_CRC32) | (fw_caps->cksum_algos & DC_CAPS_ADLER32) | ((fw_caps->cksum_algos & DC_CAPS_ADLER32) << DC_CAPS_XXHASH32_OFFSET)); pDcCapabilities->deflate.supported = (fw_caps->comp_algos & DC_CAPS_DEFLATE_SUPPORTED); pDcCapabilities->deflate.dynamicHuffmanBufferReq = LAC_SHIFT_RIGHT((fw_caps->deflate_caps & DC_CAPS_DYNAMIC_HUFF_BUFF_REQ), DC_CAPS_DYNAMIC_HUFF_OFFSET); pDcCapabilities->deflate.programmableCrc64 = LAC_SHIFT_RIGHT( (fw_caps->cksum_algos & DC_CAPS_PCRC), DC_CAPS_PCRC_OFFSET); pDcCapabilities->lz4.supported = LAC_SHIFT_RIGHT( (fw_caps->comp_algos & DC_CAPS_LZ4_SUPPORTED), DC_CAPS_LZ4_OFFSET); pDcCapabilities->lz4.checksumXXHash32 = LAC_SHIFT_RIGHT( (fw_caps->cksum_algos & DC_CAPS_ADLER32), DC_CAPS_ADLER32_OFFSET); pDcCapabilities->lz4.programmableCrc64 = LAC_SHIFT_RIGHT( (fw_caps->cksum_algos & DC_CAPS_PCRC), DC_CAPS_PCRC_OFFSET); pDcCapabilities->lz4s.supported = LAC_SHIFT_RIGHT( (fw_caps->comp_algos & DC_CAPS_LZ4S_SUPPORTED), DC_CAPS_LZ4S_OFFSET); pDcCapabilities->lz4s.checksumXXHash32 = LAC_SHIFT_RIGHT( (fw_caps->cksum_algos & DC_CAPS_ADLER32), DC_CAPS_ADLER32_OFFSET); pDcCapabilities->lz4s.programmableCrc64 = LAC_SHIFT_RIGHT( (fw_caps->cksum_algos & DC_CAPS_PCRC), DC_CAPS_PCRC_OFFSET); } STATIC void SalCtrl_Set4xxxDcCapabilities(dc_capabilities_t *pDcCapabilities, Cpa32U dcExtendedFeatures, fw_caps_t *fw_caps) { dc_extd_ftrs_t *pExtendedFtrs = (dc_extd_ftrs_t *)&(dcExtendedFeatures); memset(pDcCapabilities, 0, sizeof(dc_capabilities_t)); /* Set compression HW capabilitities */ pDcCapabilities->deviceData.translatorOverflow = CPA_TRUE; pDcCapabilities->deviceData.oddByteDecompNobFinal = CPA_TRUE; pDcCapabilities->deviceData.enableDmm = CPA_TRUE; pDcCapabilities->deviceData.minOutputBuffSize = DC_DEST_BUFFER_STA_MIN_SIZE_GEN4; pDcCapabilities->deviceData.minOutputBuffSizeDynamic = DC_DEST_BUFFER_DYN_MIN_SIZE_GEN4; pDcCapabilities->deviceData.useDevRam = ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; pDcCapabilities->deviceData.highestHwCompressionDepth = ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_9; pDcCapabilities->deviceData.uncompressedDataSupported = CPA_TRUE; pDcCapabilities->deviceData.hw_gen = DC_CAPS_GEN4_HW; pDcCapabilities->deviceData.compressionServiceSupported = CPA_TRUE; pDcCapabilities->dcDeflateBound = dcDeflateBoundGen4; pDcCapabilities->dcLZ4Bound = dcLZ4BoundGen4; pDcCapabilities->dcLZ4SBound = dcLZ4SBoundGen4; pDcCapabilities->dcCompHwBlockPopulate = dcCompHwBlockPopulateGen4; pDcCapabilities->dcNsCompHwBlockPopulate = dcCompHwBlockPopulateGen4; /* Set generic capabilities */ pDcCapabilities->sessState = DC_CAPS_STATELESS; pDcCapabilities->checksum = (DC_CAPS_CRC32 | DC_CAPS_ADLER32 | DC_CAPS_XXHASH32); pDcCapabilities->numInterBuffs = 0; pDcCapabilities->endOfLastBlock = CPA_TRUE; pDcCapabilities->storedBlockGeneration = CPA_TRUE; pDcCapabilities->reportParityError = CPA_TRUE; pDcCapabilities->asb.supported = CPA_TRUE; /* Set data integrity capabilities */ pDcCapabilities->crcIntegrity.supported = CPA_TRUE; pDcCapabilities->crcIntegrity.checkCRC64 = CPA_TRUE; /* Set CNV capabilities */ pDcCapabilities->cnv.supported = (dcExtendedFeatures & DC_CNV_EXTENDED_CAPABILITY); pDcCapabilities->cnv.recovery = LAC_SHIFT_RIGHT((dcExtendedFeatures & DC_CNVNR_EXTENDED_CAPABILITY), DC_CAPS_CNVNR_EXTENDED_OFFSET); pDcCapabilities->cnv.errorInjection = CPA_TRUE; pDcCapabilities->cnv.strict = CPA_TRUE; /* Set deflate capabilities */ DC_CAPS_DEFLATE_TYPE_SUPPORT_SET(pDcCapabilities->deflate.typeSupport, DC_CAPS_DEFLATE_TYPE_STATIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); DC_CAPS_DEFLATE_TYPE_SUPPORT_SET(pDcCapabilities->deflate.typeSupport, DC_CAPS_DEFLATE_TYPE_DYNAMIC, DC_CAPS_DEFLATE_TYPE_SUPPORTED); pDcCapabilities->deflate.supported = CPA_TRUE; pDcCapabilities->deflate.dirMask = (DC_CAPS_COMPRESSION | DC_CAPS_DECOMPRESSION); pDcCapabilities->deflate.inflateContextSize = DC_INFLATE_CONTEXT_SIZE; pDcCapabilities->deflate.dynamicHuffmanBufferReq = CPA_TRUE; pDcCapabilities->deflate.internalHuffmanMem = CPA_TRUE; pDcCapabilities->deflate.bypassIncompleteFileErr = CPA_TRUE; pDcCapabilities->deflate.historyBufferSize = CPA_DC_WINSIZE_32K; pDcCapabilities->deflate.zerolengthRequests = CPA_TRUE; pDcCapabilities->deflate.validWindowSizeMaskCompression = DC_32K_WINDOW_MASK; pDcCapabilities->deflate.validWindowSizeMaskDecompression = DC_4K_WINDOW_MASK | DC_8K_WINDOW_MASK | DC_16K_WINDOW_MASK | DC_32K_WINDOW_MASK; pDcCapabilities->deflate.programmableCrc64 = CPA_TRUE; pDcCapabilities->deflate.hashThenCompressSupported = (Cpa8U)pExtendedFtrs->is_chain_hash_then_compress; /* Set lz4 capabilities */ pDcCapabilities->lz4.supported = CPA_TRUE; pDcCapabilities->lz4.dirMask = (DC_CAPS_COMPRESSION | DC_CAPS_DECOMPRESSION); pDcCapabilities->lz4.decompContextSize = DC_LZ4_DECOMP_CONTEXT_SIZE; pDcCapabilities->lz4.checksumXXHash32 = CPA_TRUE; pDcCapabilities->lz4.blockIndependence = CPA_TRUE; pDcCapabilities->lz4.accumulateXXHash = CPA_TRUE; pDcCapabilities->lz4.maxBlockSize = (DC_CAPS_LZ4_64K | DC_CAPS_LZ4_256K | DC_CAPS_LZ4_1M | DC_CAPS_LZ4_4M); pDcCapabilities->lz4.historyBufferSize = CPA_DC_WINSIZE_32K; pDcCapabilities->lz4.zerolengthRequests = CPA_TRUE; pDcCapabilities->lz4.validWindowSizeMaskCompression = DC_32K_WINDOW_MASK; pDcCapabilities->lz4.validWindowSizeMaskDecompression = DC_4K_WINDOW_MASK | DC_8K_WINDOW_MASK | DC_16K_WINDOW_MASK | DC_32K_WINDOW_MASK; pDcCapabilities->lz4.programmableCrc64 = CPA_TRUE; /* Set lz4s capabilities */ pDcCapabilities->lz4s.supported = CPA_TRUE; pDcCapabilities->lz4s.dirMask = DC_CAPS_COMPRESSION; pDcCapabilities->lz4s.checksumXXHash32 = CPA_TRUE; pDcCapabilities->lz4s.minMatch = (DC_CAPS_LZ4S_3B | DC_CAPS_LZ4S_4B); pDcCapabilities->lz4s.historyBufferSize = CPA_DC_WINSIZE_32K; pDcCapabilities->lz4s.zerolengthRequests = CPA_TRUE; pDcCapabilities->lz4s.validWindowSizeMaskCompression = DC_32K_WINDOW_MASK; pDcCapabilities->lz4s.programmableCrc64 = CPA_TRUE; /* Overwrite default capabilities with capabilities returned * from firmware if available. */ if (fw_caps->is_fw_caps) { SalCtrl_Set4xxxDcExtendedCapabilities(pDcCapabilities, fw_caps); } } /* Sets device specific information needed by compression service */ CpaStatus SalCtrl_SetDCCaps(dc_capabilities_t *pDcCapabilities, int device_type, Cpa32U dcExtendedFeatures, fw_caps_t *fw_caps) { CpaStatus ret = CPA_STATUS_SUCCESS; switch (device_type) { /* 401XX and 402XX hardware share the same device type. All 3 * devices 401XX, 402XX and 420XX share the same device capabilities * as 4XXX. */ case DEVICE_4XXX: case DEVICE_4XXXVF: case DEVICE_420XX: case DEVICE_420XXVF: SalCtrl_Set4xxxDcCapabilities( pDcCapabilities, dcExtendedFeatures, fw_caps); break; default: LAC_LOG_ERROR1("Unknown device type! - %u\n", device_type); ret = CPA_STATUS_FAIL; break; } return ret; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_create_services.c000066400000000000000000000166341503624047500313300ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_create_services.c * * @defgroup SalCtrl Service Access Layer Controller * * @ingroup SalCtrl * * @description * This file contains the main function to create a specific service. * *****************************************************************************/ #include "cpa.h" #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "Osal.h" #include "lac_list.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "icp_qat_fw_la.h" #include "lac_sym_qat.h" #include "sal_types_compression.h" #include "lac_sal_types_crypto.h" #include "icp_adf_init.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" CpaStatus SalCtrl_ServiceCreate(sal_service_type_t serviceType, Cpa32U instance, sal_service_t **ppInst) { #ifndef ICP_DC_ONLY sal_crypto_service_t *pCrypto_service = NULL; #endif sal_compression_service_t *pCompression_service = NULL; switch ((sal_service_type_t)serviceType) { #ifndef ICP_DC_ONLY case SAL_SERVICE_TYPE_CRYPTO_ASYM: case SAL_SERVICE_TYPE_CRYPTO_SYM: case SAL_SERVICE_TYPE_CRYPTO: { pCrypto_service = osalMemAlloc(sizeof(sal_crypto_service_t)); if (NULL == pCrypto_service) { LAC_LOG_ERROR("Failed to allocate crypto service memory"); *(ppInst) = NULL; return CPA_STATUS_RESOURCE; } /* Zero memory */ osalMemSet(pCrypto_service, 0, sizeof(sal_crypto_service_t)); pCrypto_service->generic_service_info.type = (sal_service_type_t)serviceType; pCrypto_service->generic_service_info.state = SAL_SERVICE_STATE_UNINITIALIZED; pCrypto_service->generic_service_info.instance = instance; pCrypto_service->generic_service_info.init = SalCtrl_CryptoInit; pCrypto_service->generic_service_info.start = SalCtrl_CryptoStart; pCrypto_service->generic_service_info.stop = SalCtrl_CryptoStop; pCrypto_service->generic_service_info.shutdown = SalCtrl_CryptoShutdown; pCrypto_service->generic_service_info.error = SalCtrl_CryptoError; pCrypto_service->generic_service_info.restarting = SalCtrl_CryptoRestarting; pCrypto_service->generic_service_info.restarted = SalCtrl_CryptoRestarted; *(ppInst) = &(pCrypto_service->generic_service_info); return CPA_STATUS_SUCCESS; } #endif case SAL_SERVICE_TYPE_COMPRESSION: case SAL_SERVICE_TYPE_DECOMPRESSION: { pCompression_service = osalMemAlloc(sizeof(sal_compression_service_t)); if (NULL == pCompression_service) { LAC_LOG_ERROR("Failed to allocate compression service memory"); *(ppInst) = NULL; return CPA_STATUS_RESOURCE; } /* Zero memory */ osalMemSet( pCompression_service, 0, sizeof(sal_compression_service_t)); pCompression_service->generic_service_info.type = (sal_service_type_t)serviceType; pCompression_service->generic_service_info.state = SAL_SERVICE_STATE_UNINITIALIZED; pCompression_service->generic_service_info.instance = instance; pCompression_service->generic_service_info.init = SalCtrl_CompressionInit; pCompression_service->generic_service_info.start = SalCtrl_CompressionStart; pCompression_service->generic_service_info.stop = SalCtrl_CompressionStop; pCompression_service->generic_service_info.shutdown = SalCtrl_CompressionShutdown; pCompression_service->generic_service_info.error = SalCtrl_CompressionError; pCompression_service->generic_service_info.restarting = SalCtrl_CompressionRestarting; pCompression_service->generic_service_info.restarted = SalCtrl_CompressionRestarted; *(ppInst) = &(pCompression_service->generic_service_info); return CPA_STATUS_SUCCESS; } default: { LAC_LOG_ERROR("Not a valid service type"); (*ppInst) = NULL; return CPA_STATUS_FAIL; } } } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_crypto.c000066400000000000000000004157111503624047500275010ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file sal_crypto.c Instance handling functions for crypto * * @ingroup SalCtrl * ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ /* QAT-API includes */ #include "cpa.h" #include "cpa_types.h" #include "cpa_cy_common.h" #include "cpa_cy_im.h" #include "cpa_cy_drbg.h" #include "cpa_cy_ln.h" #include "cpa_cy_dh.h" #include "cpa_cy_dsa.h" #include "cpa_cy_rsa.h" #include "cpa_cy_ec.h" #include "cpa_cy_ecdh.h" #include "cpa_cy_ecdsa.h" #include "cpa_cy_prime.h" #include "cpa_cy_key.h" #include "cpa_cy_sym.h" /* Osal includes */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_cfg.h" #include "icp_adf_accel_mgr.h" #include "icp_adf_poll.h" #include "icp_adf_debug.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_sw_responses.h" #include "sal_statistics.h" #include "lac_common.h" #include "lac_list.h" #include "lac_hooks.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym.h" #include "lac_sym_key.h" #include "lac_sym_hash.h" #include "lac_sym_cb.h" #include "lac_sym_stats.h" #include "lac_pke_utils.h" #include "lac_pke_qat_comms.h" #include "lac_ec.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "sal_string_parse.h" #include "sal_service_state.h" #include "icp_sal_poll.h" #include "lac_sync.h" #include "lac_sym_qat.h" #include "icp_sal_versions.h" #include "dc_chain.h" #define MAX_CY_RX_RINGS 2 #define TH_CY_RX_0 0 #define TH_CY_RX_1 1 #define DOUBLE_INCR 2 #define NUM_CRYPTO_SYM_RX_RINGS 1 #define NUM_CRYPTO_ASYM_RX_RINGS 1 #ifdef KERNEL_SPACE #define ASYM_NOT_SUPPORTED #endif CpaStatus Lac_GetCyInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U numInstances, CpaInstanceHandle *pInstances); CpaStatus Lac_GetCyNumInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *pNumInstances); STATIC CpaInstanceHandle Lac_CryptoGetFirstHandle(void) { CpaInstanceHandle instHandle; instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); if (!instHandle) { instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); if (!instHandle) { instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); } } return instHandle; } STATIC CpaStatus SalCtrl_AsymGetFileDescriptor(sal_crypto_service_t *crypto_handle, int *fd) { int ret = 0; int fd_asym = -1; if (NULL == crypto_handle->trans_handle_asym_rx) { return CPA_STATUS_FAIL; } ret = icp_adf_transGetFdForHandle(crypto_handle->trans_handle_asym_rx, &fd_asym); if (ret != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("Error getting file descriptor for asym instance"); return CPA_STATUS_FAIL; } *fd = fd_asym; return CPA_STATUS_SUCCESS; } STATIC CpaStatus SalCtrl_SymGetFileDescriptor(sal_crypto_service_t *crypto_handle, int *fd) { int ret = 0; int fd_sym = -1; if (NULL == crypto_handle->trans_handle_sym_rx) { return CPA_STATUS_FAIL; } ret = icp_adf_transGetFdForHandle(crypto_handle->trans_handle_sym_rx, &fd_sym); if (ret != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("Error getting file descriptor for sym instance"); return CPA_STATUS_FAIL; } *fd = fd_sym; return CPA_STATUS_SUCCESS; } STATIC CpaStatus SalCtrl_CyGetFileDescriptor(sal_crypto_service_t *crypto_handle, int *fd) { CpaStatus ret_sym = CPA_STATUS_SUCCESS; CpaStatus ret_asym = CPA_STATUS_SUCCESS; int fd_sym = -1; int fd_asym = -1; ret_sym = SalCtrl_SymGetFileDescriptor(crypto_handle, &fd_sym); ret_asym = SalCtrl_AsymGetFileDescriptor(crypto_handle, &fd_asym); if (ret_sym != CPA_STATUS_SUCCESS || ret_asym != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("Error getting file descriptor for crypto instance"); return CPA_STATUS_FAIL; } /* They should always be the same. Otherwise, return error */ if (fd_sym != fd_asym) { LAC_LOG_ERROR("Symmetric and asymmetric crypto cannot be used" " within the same instance across different bundles"); return CPA_STATUS_FAIL; } *fd = fd_sym; return CPA_STATUS_SUCCESS; } #ifndef ASYM_NOT_SUPPORTED STATIC void SalCtrl_AsymMemPoolDisable(sal_crypto_service_t *pCryptoService) { Lac_MemPoolDisable(pCryptoService->lac_pke_req_pool); } #endif STATIC void SalCtrl_SymMemPoolDisable(sal_crypto_service_t *pCryptoService) { Lac_MemPoolDisable(pCryptoService->lac_sym_cookie_pool); } STATIC void SalCtrl_CyMemPoolDisable(sal_service_t *service) { sal_service_type_t svc_type = service->type; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; switch (svc_type) { #ifndef ASYM_NOT_SUPPORTED case SAL_SERVICE_TYPE_CRYPTO_ASYM: SalCtrl_AsymMemPoolDisable(pCryptoService); break; #endif case SAL_SERVICE_TYPE_CRYPTO_SYM: SalCtrl_SymMemPoolDisable(pCryptoService); break; case SAL_SERVICE_TYPE_CRYPTO: #ifndef ASYM_NOT_SUPPORTED SalCtrl_AsymMemPoolDisable(pCryptoService); #endif SalCtrl_SymMemPoolDisable(pCryptoService); break; default: break; } return; } STATIC void SalCtrl_CyUpdatePoolsBusy(sal_service_t *service) { sal_service_type_t svc_type = service->type; CpaBoolean isInstanceStarted = service->isInstanceStarted; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; if (CPA_TRUE == isInstanceStarted) { switch (svc_type) { #ifndef ASYM_NOT_SUPPORTED case SAL_SERVICE_TYPE_CRYPTO_ASYM: LacSwResp_IncNumPoolsBusy(pCryptoService->lac_pke_req_pool); break; #endif case SAL_SERVICE_TYPE_CRYPTO_SYM: LacSwResp_IncNumPoolsBusy(pCryptoService->lac_sym_cookie_pool); break; case SAL_SERVICE_TYPE_CRYPTO: #ifndef ASYM_NOT_SUPPORTED LacSwResp_IncNumPoolsBusy(pCryptoService->lac_pke_req_pool); #endif LacSwResp_IncNumPoolsBusy(pCryptoService->lac_sym_cookie_pool); break; default: break; } } return; } STATIC CpaStatus SalCtrl_CyGenResponseCrypto(sal_crypto_service_t *crypto_handle) { CpaStatus status = CPA_STATUS_RETRY; #ifndef ASYM_NOT_SUPPORTED CpaStatus asymStatus = CPA_STATUS_RETRY; #endif status = LacSwResp_GenResp(crypto_handle->lac_sym_cookie_pool, SAL_SERVICE_TYPE_CRYPTO_SYM); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR1("Failed to generate SYM SW responses with status %d\n", status); } #ifndef ASYM_NOT_SUPPORTED else { asymStatus = LacSwResp_GenResp(crypto_handle->lac_pke_req_pool, SAL_SERVICE_TYPE_CRYPTO_ASYM); if ((CPA_STATUS_SUCCESS != asymStatus) && (CPA_STATUS_RETRY != asymStatus)) { LAC_LOG_ERROR1( "Failed to generate ASYM SW responses with status %d\n", asymStatus); status = asymStatus; } else { if (CPA_STATUS_SUCCESS == status || CPA_STATUS_SUCCESS == asymStatus) status = CPA_STATUS_SUCCESS; } } #endif return status; } /* Generates dummy responses when the device is in error state */ STATIC CpaStatus SalCtrl_CyGenResponses(sal_crypto_service_t *crypto_handle, sal_service_t *gen_handle) { CpaStatus status = CPA_STATUS_RETRY; switch (gen_handle->type) { #ifndef ASYM_NOT_SUPPORTED case SAL_SERVICE_TYPE_CRYPTO_ASYM: status = LacSwResp_GenResp(crypto_handle->lac_pke_req_pool, gen_handle->type); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR1( "Failed to generate ASYM SW responses with status %d\n", status); } break; #endif case SAL_SERVICE_TYPE_CRYPTO_SYM: status = LacSwResp_GenResp(crypto_handle->lac_sym_cookie_pool, gen_handle->type); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR1( "Failed to generate SYM SW responses with status %d\n", status); } break; case SAL_SERVICE_TYPE_CRYPTO: status = SalCtrl_CyGenResponseCrypto(crypto_handle); break; default: break; } return status; } STATIC CpaStatus SalCtrl_CyCheckRespInstance(sal_service_t *service) { sal_crypto_service_t *crypto_handle = (sal_crypto_service_t *)service; icp_comms_trans_handle trans_hndTable[MAX_CY_RX_RINGS]; Cpa32U num_rx_rings = 0; switch (service->type) { case SAL_SERVICE_TYPE_CRYPTO_ASYM: trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_asym_rx; num_rx_rings = 1; break; case SAL_SERVICE_TYPE_CRYPTO_SYM: trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; num_rx_rings = 1; break; case SAL_SERVICE_TYPE_CRYPTO: trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; trans_hndTable[TH_CY_RX_1] = crypto_handle->trans_handle_asym_rx; num_rx_rings = MAX_CY_RX_RINGS; break; default: break; } return icp_adf_check_RespInstance(trans_hndTable, num_rx_rings); } #ifndef ASYM_NOT_SUPPORTED /* Function to release the asym handles. */ STATIC CpaStatus SalCtrl_AsymReleaseTransHandle(sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus ret_status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; if (NULL != pCryptoService->trans_handle_asym_tx) { status = icp_adf_transReleaseHandle(pCryptoService->trans_handle_asym_tx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (NULL != pCryptoService->trans_handle_asym_rx) { status = icp_adf_transReleaseHandle(pCryptoService->trans_handle_asym_rx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } return ret_status; } /* Function to reset the asym handles. */ STATIC CpaStatus SalCtrl_AsymResetTransHandle(sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus ret_status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; if (NULL != pCryptoService->trans_handle_asym_tx) { status = icp_adf_transResetHandle(pCryptoService->trans_handle_asym_tx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (NULL != pCryptoService->trans_handle_asym_rx) { status = icp_adf_transResetHandle(pCryptoService->trans_handle_asym_rx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } return ret_status; } #endif /* Function to release the sym handles. */ STATIC CpaStatus SalCtrl_SymReleaseTransHandle(sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus ret_status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; if (NULL != pCryptoService->trans_handle_sym_tx) { status = icp_adf_transReleaseHandle(pCryptoService->trans_handle_sym_tx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (NULL != pCryptoService->trans_handle_sym_rx) { status = icp_adf_transReleaseHandle(pCryptoService->trans_handle_sym_rx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } return ret_status; } /* Function to reset the sym handles. */ STATIC CpaStatus SalCtrl_SymResetTransHandle(sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus ret_status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; if (NULL != pCryptoService->trans_handle_sym_tx) { status = icp_adf_transResetHandle(pCryptoService->trans_handle_sym_tx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (NULL != pCryptoService->trans_handle_sym_rx) { status = icp_adf_transResetHandle(pCryptoService->trans_handle_sym_rx); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } return ret_status; } #ifndef ASYM_NOT_SUPPORTED /* * @ingroup sal_crypto * Frees resources (memory and transhandles) if allocated * * @param[in] pCryptoService Pointer to asym service instance * @retval SUCCESS if transhandles released * successfully */ STATIC CpaStatus SalCtrl_AsymFreeResources(sal_crypto_service_t *pCryptoService) { CpaStatus status = CPA_STATUS_SUCCESS; /* Free memory pools if not NULL */ Lac_MemPoolDestroy(pCryptoService->lac_pke_align_pool); Lac_MemPoolDestroy(pCryptoService->lac_pke_req_pool); Lac_MemPoolDestroy(pCryptoService->lac_ec_pool); Lac_MemPoolDestroy(pCryptoService->lac_prime_pool); /* Free the statistics */ LacDh_StatsFree(pCryptoService); LacDsa_StatsFree(pCryptoService); LacRsa_StatsFree(pCryptoService); LacEc_StatsFree(pCryptoService); LacPrime_StatsFree(pCryptoService); LacLn_StatsFree(pCryptoService); /* Free transport handles */ status = SalCtrl_AsymReleaseTransHandle((sal_service_t *)pCryptoService); return status; } /* * @ingroup sal_crypto * Resets resources (memory and transhandles) * * @param[in] pCryptoService Pointer to asym service instance * @retval SUCCESS if transhandles released * successfully */ STATIC CpaStatus SalCtrl_AsymResetResources(sal_crypto_service_t *pCryptoService) { /* Reset the statistics */ LacDh_StatsReset(pCryptoService); LacDsa_StatsReset(pCryptoService); LacRsa_StatsReset(pCryptoService); LacEc_StatsReset(pCryptoService); LacPrime_StatsReset(pCryptoService); LacLn_StatsReset(pCryptoService); /* Reset transport handles */ return SalCtrl_AsymResetTransHandle((sal_service_t *)pCryptoService); } #endif /* * @ingroup sal_crypto * Frees resources (memory and transhandles) if allocated * * @param[in] pCryptoService Pointer to sym service instance * @retval SUCCESS if transhandles released * successfully. */ STATIC CpaStatus SalCtrl_SymFreeResources(sal_crypto_service_t *pCryptoService) { CpaStatus status = CPA_STATUS_SUCCESS; /* Free memory pools if not NULL */ Lac_MemPoolDestroy(pCryptoService->lac_sym_cookie_pool); /* Free key stats */ LacSymKey_StatsFree(pCryptoService); /* Free misc memory if allocated */ /* Frees memory allocated for Hmac precomputes */ LacSymHash_HmacPrecompShutdown(pCryptoService); /* Free memory allocated for key labels Also clears key stats */ LacSymKey_Shutdown(pCryptoService); /* Free hash lookup table if allocated */ if (NULL != pCryptoService->pLacHashLookupDefs) { LAC_OS_FREE(pCryptoService->pLacHashLookupDefs); } /* Free statistics */ LacSym_StatsFree(pCryptoService); /* Free transport handles */ status = SalCtrl_SymReleaseTransHandle((sal_service_t *)pCryptoService); return status; } /* * @ingroup sal_crypto * Resets resources (memory and transhandles) * * @param[in] pCryptoService Pointer to sym service instance * @retval SUCCESS if transhandles released * successfully. */ STATIC CpaStatus SalCtrl_SymResetResources(sal_crypto_service_t *pCryptoService) { LacSymKey_StatsReset(pCryptoService); /* Reset transport handles */ return SalCtrl_SymResetTransHandle((sal_service_t *)pCryptoService); } #ifndef ASYM_NOT_SUPPORTED /** *********************************************************************** * @ingroup SalCtrl * This macro verifies that the status is _SUCCESS * If status is not _SUCCESS then Asym Instance resources are * freed before the function returns the error * * @param[in] status status we are checking * * @return void status is ok (CPA_STATUS_SUCCESS) * @return status The value in the status parameter is an error one * ****************************************************************************/ #define LAC_CHECK_STATUS_ASYM_INIT(status) \ do \ { \ if (CPA_STATUS_SUCCESS != status) \ { \ SalCtrl_AsymFreeResources(pCryptoService); \ return status; \ } \ } while (0) #endif /** *********************************************************************** * @ingroup SalCtrl * This macro verifies that the status is _SUCCESS * If status is not _SUCCESS then Sym Instance resources are * freed before the function returns the error * * @param[in] status status we are checking * * @return void status is ok (CPA_STATUS_SUCCESS) * @return status The value in the status parameter is an error one * ****************************************************************************/ #define LAC_CHECK_STATUS_SYM_INIT(status) \ do \ { \ if (CPA_STATUS_SUCCESS != status) \ { \ SalCtrl_SymFreeResources(pCryptoService); \ return status; \ } \ } while (0) #ifndef ASYM_NOT_SUPPORTED /* Function that creates the Asym Handles. */ STATIC CpaStatus SalCtrl_AsymCreateTransHandle(icp_accel_dev_t *device, sal_service_t *service, Cpa32U numAsymRequests, char *section) { CpaStatus status = CPA_STATUS_SUCCESS; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; Cpa32U msgSize = 0; if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { rx_resp_type = ICP_RESP_TYPE_POLL; } section = icpGetProcessName(); /* Parse Asym ring details first */ status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_ASYM_TX, temp_string); /* Need to free resources in case not _SUCCESS from here */ LAC_CHECK_STATUS_ASYM_INIT(status); msgSize = LAC_QAT_ASYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transCreateHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumAsym, temp_string, lac_getRingType(SAL_RING_TYPE_A_ASYM), NULL, ICP_RESP_TYPE_NONE, numAsymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_asym_tx)); LAC_CHECK_STATUS_ASYM_INIT(status); status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_ASYM_RX, temp_string); LAC_CHECK_STATUS_ASYM_INIT(status); msgSize = LAC_QAT_ASYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transCreateHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumAsym, temp_string, lac_getRingType(SAL_RING_TYPE_NONE), LacPke_MsgCallback, rx_resp_type, numAsymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_asym_rx)); LAC_CHECK_STATUS_ASYM_INIT(status); return status; } /* Function that reinitializes the Asym Handles after restart. */ STATIC CpaStatus SalCtrl_AsymReinitTransHandle(icp_accel_dev_t *device, sal_service_t *service, Cpa32U numAsymRequests, char *section) { CpaStatus status = CPA_STATUS_SUCCESS; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; Cpa32U msgSize = 0; if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { rx_resp_type = ICP_RESP_TYPE_POLL; } section = icpGetProcessName(); /* Parse Asym ring details first */ status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_ASYM_TX, temp_string); /* Need to free resources in case not _SUCCESS from here */ LAC_CHECK_STATUS_ASYM_INIT(status); msgSize = LAC_QAT_ASYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transReinitHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumAsym, temp_string, lac_getRingType(SAL_RING_TYPE_A_ASYM), NULL, ICP_RESP_TYPE_NONE, numAsymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_asym_tx)); LAC_CHECK_STATUS_ASYM_INIT(status); status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_ASYM_RX, temp_string); LAC_CHECK_STATUS_ASYM_INIT(status); msgSize = LAC_QAT_ASYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transReinitHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumAsym, temp_string, lac_getRingType(SAL_RING_TYPE_NONE), LacPke_MsgCallback, rx_resp_type, numAsymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_asym_rx)); LAC_CHECK_STATUS_ASYM_INIT(status); return status; } #endif /* Function that creates the Sym Handles. */ STATIC CpaStatus SalCtrl_SymCreateTransHandle(icp_accel_dev_t *device, sal_service_t *service, Cpa32U numSymRequests, char *section) { CpaStatus status = CPA_STATUS_SUCCESS; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; Cpa32U msgSize = 0; if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { rx_resp_type = ICP_RESP_TYPE_POLL; } section = icpGetProcessName(); /* Parse Sym ring details */ status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_SYM_TX, temp_string); /* Need to free resources in case not _SUCCESS from here */ LAC_CHECK_STATUS_SYM_INIT(status); msgSize = LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transCreateHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumSym, temp_string, lac_getRingType(SAL_RING_TYPE_A_SYM_HI), NULL, ICP_RESP_TYPE_NONE, numSymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_sym_tx)); LAC_CHECK_STATUS_SYM_INIT(status); status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_SYM_RX, temp_string); LAC_CHECK_STATUS_SYM_INIT(status); msgSize = LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transCreateHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumSym, temp_string, lac_getRingType(SAL_RING_TYPE_NONE), (icp_trans_callback)LacSymQat_SymRespHandler, rx_resp_type, numSymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_sym_rx)); LAC_CHECK_STATUS_SYM_INIT(status); return status; } /* Function that reinitializes the Sym Handles after restart. */ STATIC CpaStatus SalCtrl_SymReinitTransHandle(icp_accel_dev_t *device, sal_service_t *service, Cpa32U numSymRequests, char *section) { CpaStatus status = CPA_STATUS_SUCCESS; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; Cpa32U msgSize = 0; if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { rx_resp_type = ICP_RESP_TYPE_POLL; } section = icpGetProcessName(); /* Parse Sym ring details */ status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_SYM_TX, temp_string); /* Need to free resources in case not _SUCCESS from here */ LAC_CHECK_STATUS_SYM_INIT(status); msgSize = LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transReinitHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumSym, temp_string, lac_getRingType(SAL_RING_TYPE_A_SYM_HI), NULL, ICP_RESP_TYPE_NONE, numSymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_sym_tx)); LAC_CHECK_STATUS_SYM_INIT(status); status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_RING_SYM_RX, temp_string); LAC_CHECK_STATUS_SYM_INIT(status); msgSize = LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = icp_adf_transReinitHandle( device, ICP_TRANS_TYPE_ETR, section, pCryptoService->acceleratorNum, pCryptoService->bankNumSym, temp_string, lac_getRingType(SAL_RING_TYPE_NONE), (icp_trans_callback)LacSymQat_SymRespHandler, rx_resp_type, numSymRequests, msgSize, (icp_comms_trans_handle *)&(pCryptoService->trans_handle_sym_rx)); LAC_CHECK_STATUS_SYM_INIT(status); return status; } STATIC int SalCtrl_CryptoDebug(void *private_data, char *data, int size, int offset) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U len = 0; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)private_data; switch (offset) { case SAL_STATS_SYM: { CpaCySymStats64 symStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bSymStatsEnabled) { break; } status = cpaCySymQueryStats64(pCryptoService, &symStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCySymQueryStats64 returned error\n"); return 0; } /* Engine Info */ len += snprintf( data + len, size - len, SEPARATOR BORDER " Statistics for Instance %24s |\n" BORDER " Symmetric Stats " BORDER "\n" SEPARATOR, pCryptoService->debug_file->name); /* Session Info */ len += snprintf( data + len, size - len, BORDER " Sessions Initialized: %16llu " BORDER "\n" BORDER " Sessions Removed: %16llu " BORDER "\n" BORDER " Session Errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)symStats.numSessionsInitialized, (long long unsigned int)symStats.numSessionsRemoved, (long long unsigned int)symStats.numSessionErrors); /* Session info */ snprintf( data + len, size - len, BORDER " Symmetric Requests: %16llu " BORDER "\n" BORDER " Symmetric Request Errors: %16llu " BORDER "\n" BORDER " Symmetric Completed: %16llu " BORDER "\n" BORDER " Symmetric Completed Errors: %16llu " BORDER "\n" BORDER " Symmetric Verify Failures: %16llu " BORDER "\n", (long long unsigned int)symStats.numSymOpRequests, (long long unsigned int)symStats.numSymOpRequestErrors, (long long unsigned int)symStats.numSymOpCompleted, (long long unsigned int)symStats.numSymOpCompletedErrors, (long long unsigned int)symStats.numSymOpVerifyFailures); break; } case SAL_STATS_DSA: { CpaCyDsaStats64 dsaStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bDsaStatsEnabled) { ++offset; break; } status = cpaCyDsaQueryStats64(pCryptoService, &dsaStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyDsaQueryStats4 returned error\n"); return 0; } /* engine info */ len += snprintf( data + len, size - len, SEPARATOR BORDER " DSA Stats " BORDER "\n" SEPARATOR); /* p parameter generation requests */ len += snprintf( data + len, size - len, BORDER " DSA P Param Gen Requests-Succ: %16llu " BORDER "\n" BORDER " DSA P Param Gen Requests-Err: %16llu " BORDER "\n" BORDER " DSA P Param Gen Completed-Succ: %16llu " BORDER "\n" BORDER " DSA P Param Gen Completed-Err: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dsaStats.numDsaPParamGenRequests, (long long unsigned int)dsaStats.numDsaPParamGenRequestErrors, (long long unsigned int)dsaStats.numDsaPParamGenCompleted, (long long unsigned int) dsaStats.numDsaPParamGenCompletedErrors); /* g parameter generation requests */ len += snprintf( data + len, size - len, BORDER " DSA G Param Gen Requests-Succ: %16llu " BORDER "\n" BORDER " DSA G Param Gen Requests-Err: %16llu " BORDER "\n" BORDER " DSA G Param Gen Completed-Succ: %16llu " BORDER "\n" BORDER " DSA G Param Gen Completed-Err: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dsaStats.numDsaGParamGenRequests, (long long unsigned int)dsaStats.numDsaGParamGenRequestErrors, (long long unsigned int)dsaStats.numDsaGParamGenCompleted, (long long unsigned int) dsaStats.numDsaGParamGenCompletedErrors); /* y parameter generation requests */ snprintf( data + len, size - len, BORDER " DSA Y Param Gen Requests-Succ: %16llu " BORDER "\n" BORDER " DSA Y Param Gen Requests-Err: %16llu " BORDER "\n" BORDER " DSA Y Param Gen Completed-Succ: %16llu " BORDER "\n" BORDER " DSA Y Param Gen Completed-Err: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dsaStats.numDsaYParamGenRequests, (long long unsigned int)dsaStats.numDsaYParamGenRequestErrors, (long long unsigned int)dsaStats.numDsaYParamGenCompleted, (long long unsigned int) dsaStats.numDsaYParamGenCompletedErrors); break; } case SAL_STATS_DSA2: { CpaCyDsaStats64 dsaStats = {0}; status = cpaCyDsaQueryStats64(pCryptoService, &dsaStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyDsaQueryStats4 returned error\n"); return 0; } /* r sign requests */ len += snprintf( data + len, size - len, BORDER " DSA R Sign Requests-Succ: %16llu " BORDER "\n" BORDER " DSA R Sign Request-Err: %16llu " BORDER "\n" BORDER " DSA R Sign Completed-Succ: %16llu " BORDER "\n" BORDER " DSA R Sign Completed-Err: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dsaStats.numDsaRSignRequests, (long long unsigned int)dsaStats.numDsaRSignRequestErrors, (long long unsigned int)dsaStats.numDsaRSignCompleted, (long long unsigned int)dsaStats.numDsaRSignCompletedErrors); /* s sign requests */ len += snprintf( data + len, size - len, BORDER " DSA S Sign Requests-Succ: %16llu " BORDER "\n" BORDER " DSA S Sign Request-Err: %16llu " BORDER "\n" BORDER " DSA S Sign Completed-Succ: %16llu " BORDER "\n" BORDER " DSA S Sign Completed-Err: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dsaStats.numDsaSSignRequests, (long long unsigned int)dsaStats.numDsaSSignRequestErrors, (long long unsigned int)dsaStats.numDsaSSignCompleted, (long long unsigned int)dsaStats.numDsaSSignCompletedErrors); /* rs sign requests */ len += snprintf( data + len, size - len, BORDER " DSA RS Sign Requests-Succ: %16llu " BORDER "\n" BORDER " DSA RS Sign Request-Err: %16llu " BORDER "\n" BORDER " DSA RS Sign Completed-Succ: %16llu " BORDER "\n" BORDER " DSA RS Sign Completed-Err: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dsaStats.numDsaRSSignRequests, (long long unsigned int)dsaStats.numDsaRSSignRequestErrors, (long long unsigned int)dsaStats.numDsaRSSignCompleted, (long long unsigned int)dsaStats.numDsaRSSignCompletedErrors); /* verify requests */ snprintf( data + len, size - len, BORDER " DSA Verify Requests-Succ: %16llu " BORDER "\n" BORDER " DSA Verify Request-Err: %16llu " BORDER "\n" BORDER " DSA Verify Completed-Succ: %16llu " BORDER "\n" BORDER " DSA Verify Completed-Err: %16llu " BORDER "\n" BORDER " DSA Verify Completed-Failure: %16llu " BORDER "\n", (long long unsigned int)dsaStats.numDsaVerifyRequests, (long long unsigned int)dsaStats.numDsaVerifyRequestErrors, (long long unsigned int)dsaStats.numDsaVerifyCompleted, (long long unsigned int)dsaStats.numDsaVerifyCompletedErrors, (long long unsigned int)dsaStats.numDsaVerifyFailures); break; } case SAL_STATS_RSA: { CpaCyRsaStats64 rsaStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bRsaStatsEnabled) { break; } status = cpaCyRsaQueryStats64(pCryptoService, &rsaStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyRsaQueryStats64 returned error\n"); return 0; } /* Engine Info */ len += snprintf( data + len, size - len, SEPARATOR BORDER " RSA Stats " BORDER "\n" SEPARATOR); /* rsa keygen Info */ len += snprintf( data + len, size - len, BORDER " RSA Key Gen Requests: %16llu " BORDER "\n" BORDER " RSA Key Gen Request Errors %16llu " BORDER "\n" BORDER " RSA Key Gen Completed: %16llu " BORDER "\n" BORDER " RSA Key Gen Completed Errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)rsaStats.numRsaKeyGenRequests, (long long unsigned int)rsaStats.numRsaKeyGenRequestErrors, (long long unsigned int)rsaStats.numRsaKeyGenCompleted, (long long unsigned int)rsaStats.numRsaKeyGenCompletedErrors); /* rsa enc Info */ len += snprintf( data + len, size - len, BORDER " RSA Encrypt Requests: %16llu " BORDER "\n" BORDER " RSA Encrypt Request Errors: %16llu " BORDER "\n" BORDER " RSA Encrypt Completed: %16llu " BORDER "\n" BORDER " RSA Encrypt Completed Errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)rsaStats.numRsaEncryptRequests, (long long unsigned int)rsaStats.numRsaEncryptRequestErrors, (long long unsigned int)rsaStats.numRsaEncryptCompleted, (long long unsigned int)rsaStats.numRsaEncryptCompletedErrors); /* rsa dec Info */ snprintf( data + len, size - len, BORDER " RSA Decrypt Requests: %16llu " BORDER "\n" BORDER " RSA Decrypt Request Errors: %16llu " BORDER "\n" BORDER " RSA Decrypt Completed: %16llu " BORDER "\n" BORDER " RSA Decrypt Completed Errors: %16llu " BORDER "\n", (long long unsigned int)rsaStats.numRsaDecryptRequests, (long long unsigned int)rsaStats.numRsaDecryptRequestErrors, (long long unsigned int)rsaStats.numRsaDecryptCompleted, (long long unsigned int)rsaStats.numRsaDecryptCompletedErrors); break; } case SAL_STATS_DH: { CpaCyDhStats64 dhStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bDhStatsEnabled) { break; } status = cpaCyDhQueryStats64(pCryptoService, &dhStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyDhQueryStats returned error\n"); return 0; } len += snprintf( data + len, size - len, SEPARATOR BORDER " Diffie Hellman Stats " BORDER "\n" SEPARATOR); /* perform Info */ len += snprintf( data + len, size - len, BORDER " DH Phase1 Key Gen Requests: %16llu " BORDER "\n" BORDER " DH Phase1 Key Gen Request Err: %16llu " BORDER "\n" BORDER " DH Phase1 Key Gen Completed: %16llu " BORDER "\n" BORDER " DH Phase1 Key Gen Completed Err:%16llu " BORDER "\n" SEPARATOR, (long long unsigned int)dhStats.numDhPhase1KeyGenRequests, (long long unsigned int)dhStats.numDhPhase1KeyGenRequestErrors, (long long unsigned int)dhStats.numDhPhase1KeyGenCompleted, (long long unsigned int) dhStats.numDhPhase1KeyGenCompletedErrors); snprintf( data + len, size - len, BORDER " DH Phase2 Key Gen Requests: %16llu " BORDER "\n" BORDER " DH Phase2 Key Gen Request Err: %16llu " BORDER "\n" BORDER " DH Phase2 Key Gen Completed: %16llu " BORDER "\n" BORDER " DH Phase2 Key Gen Completed Err:%16llu " BORDER "\n", (long long unsigned int)dhStats.numDhPhase2KeyGenRequests, (long long unsigned int)dhStats.numDhPhase2KeyGenRequestErrors, (long long unsigned int)dhStats.numDhPhase2KeyGenCompleted, (long long unsigned int) dhStats.numDhPhase2KeyGenCompletedErrors); break; } case SAL_STATS_KEYGEN: { CpaCyKeyGenStats64 keyStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bKeyGenStatsEnabled) { break; } status = cpaCyKeyGenQueryStats64(pCryptoService, &keyStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyKeyGenQueryStats64 returned error\n"); return 0; } /* Key Gen stats */ len += snprintf( data + len, size - len, SEPARATOR BORDER " Key Stats " BORDER "\n" SEPARATOR); len += snprintf( data + len, size - len, BORDER " SSL Key Requests: %16llu " BORDER "\n" BORDER " SSL Key Request Errors: %16llu " BORDER "\n" BORDER " SSL Key Completed %16llu " BORDER "\n" BORDER " SSL Key Complete Errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)keyStats.numSslKeyGenRequests, (long long unsigned int)keyStats.numSslKeyGenRequestErrors, (long long unsigned int)keyStats.numSslKeyGenCompleted, (long long unsigned int)keyStats.numSslKeyGenCompletedErrors); len += snprintf( data + len, size - len, BORDER " TLS Key Requests: %16llu " BORDER "\n" BORDER " TLS Key Request Errors: %16llu " BORDER "\n" BORDER " TLS Key Completed %16llu " BORDER "\n" BORDER " TLS Key Complete Errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)keyStats.numTlsKeyGenRequests, (long long unsigned int)keyStats.numTlsKeyGenRequestErrors, (long long unsigned int)keyStats.numTlsKeyGenCompleted, (long long unsigned int)keyStats.numTlsKeyGenCompletedErrors); snprintf( data + len, size - len, BORDER " MGF Key Requests: %16llu " BORDER "\n" BORDER " MGF Key Request Errors: %16llu " BORDER "\n" BORDER " MGF Key Completed %16llu " BORDER "\n" BORDER " MGF Key Complete Errors: %16llu " BORDER "\n", (long long unsigned int)keyStats.numMgfKeyGenRequests, (long long unsigned int)keyStats.numMgfKeyGenRequestErrors, (long long unsigned int)keyStats.numMgfKeyGenCompleted, (long long unsigned int)keyStats.numMgfKeyGenCompletedErrors); break; } case SAL_STATS_LN: { CpaCyLnStats64 lnStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bLnStatsEnabled) { break; } status = cpaCyLnStatsQuery64(pCryptoService, &lnStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyLnStatsQuery64 returned error\n"); return 0; } /* Engine Info */ len += snprintf( data + len, size - len, SEPARATOR BORDER " LN ModExp/ModInv Stats " BORDER "\n" SEPARATOR); /* Large Number Modular Exponentationstats operations stats */ len += snprintf( data + len, size - len, BORDER " LN ModEXP successful requests: %16llu " BORDER "\n" BORDER " LN ModEXP requests with error: %16llu " BORDER "\n" BORDER " LN ModEXP completed operations: %16llu " BORDER "\n" BORDER " LN ModEXP not completed-errors: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)lnStats.numLnModExpRequests, (long long unsigned int)lnStats.numLnModExpRequestErrors, (long long unsigned int)lnStats.numLnModExpCompleted, (long long unsigned int)lnStats.numLnModExpCompletedErrors); /* Large Number Modular Inversion operations stats */ snprintf( data + len, size - len, BORDER " LN ModINV successful requests: %16llu " BORDER "\n" BORDER " LN ModINV requests with error: %16llu " BORDER "\n" BORDER " LN ModINV completed operations: %16llu " BORDER "\n" BORDER " LN ModINV not completed-errors: %16llu " BORDER "\n", (long long unsigned int)lnStats.numLnModInvRequests, (long long unsigned int)lnStats.numLnModInvRequestErrors, (long long unsigned int)lnStats.numLnModInvCompleted, (long long unsigned int)lnStats.numLnModInvCompletedErrors); break; } case SAL_STATS_PRIME: { CpaCyPrimeStats64 primeStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bPrimeStatsEnabled) { break; } status = cpaCyPrimeQueryStats64(pCryptoService, &primeStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyPrimeQueryStats64 returned error\n"); return 0; } /* Engine Info */ len += snprintf( data + len, size - len, SEPARATOR BORDER " PRIME Stats " BORDER "\n" SEPARATOR); /* Parameter generation requests - PRIME stats */ snprintf( data + len, size - len, BORDER " PRIME successful requests: %16llu " BORDER "\n" BORDER " PRIME failed requests: %16llu " BORDER "\n" BORDER " PRIME successfully completed: %16llu " BORDER "\n" BORDER " PRIME failed completion: %16llu " BORDER "\n" BORDER " PRIME completed - not a prime: %16llu " BORDER "\n", (long long unsigned int)primeStats.numPrimeTestRequests, (long long unsigned int)primeStats.numPrimeTestRequestErrors, (long long unsigned int)primeStats.numPrimeTestCompleted, (long long unsigned int)primeStats.numPrimeTestCompletedErrors, (long long unsigned int)primeStats.numPrimeTestFailures); break; } case SAL_STATS_ECC: { CpaCyEcStats64 ecStats = {0}; if (CPA_TRUE != pCryptoService->generic_service_info.stats->bEccStatsEnabled) { offset += DOUBLE_INCR; break; } status = cpaCyEcQueryStats64(pCryptoService, &ecStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyEcQueryStats64 returned error\n"); return 0; } len += snprintf( data + len, size - len, SEPARATOR BORDER " EC Stats " BORDER "\n" SEPARATOR); len += snprintf( data + len, size - len, BORDER " EC Pt Multiply Requests-Succ: %16llu " BORDER "\n" BORDER " EC Pt Multiply Request-Err: %16llu " BORDER "\n" BORDER " EC Pt Multiply Completed-Succ: %16llu " BORDER "\n" BORDER " EC Pt Multiply Completed-Err: %16llu " BORDER "\n" BORDER " EC Pt Multiply Output Invalid: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)ecStats.numEcPointMultiplyRequests, (long long unsigned int)ecStats.numEcPointMultiplyRequestErrors, (long long unsigned int)ecStats.numEcPointMultiplyCompleted, (long long unsigned int) ecStats.numEcPointMultiplyCompletedError, (long long unsigned int) ecStats.numEcPointMultiplyCompletedOutputInvalid); snprintf( data + len, size - len, BORDER " EC Pt Verify Requests-Succ: %16llu " BORDER "\n" BORDER " EC Pt Verify Request-Err: %16llu " BORDER "\n" BORDER " EC Pt Verify Completed-Succ: %16llu " BORDER "\n" BORDER " EC Pt Verify Completed-Err: %16llu " BORDER "\n" BORDER " EC Pt Verify Output Invalid: %16llu " BORDER "\n", (long long unsigned int)ecStats.numEcPointVerifyRequests, (long long unsigned int)ecStats.numEcPointVerifyRequestErrors, (long long unsigned int)ecStats.numEcPointVerifyCompleted, (long long unsigned int)ecStats.numEcPointVerifyCompletedErrors, (long long unsigned int) ecStats.numEcPointVerifyCompletedOutputInvalid); break; } case SAL_STATS_ECDH: { CpaCyEcdhStats64 ecdhStats = {0}; status = cpaCyEcdhQueryStats64(pCryptoService, &ecdhStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyEcdhQueryStats64 returned error\n"); return 0; } len += snprintf( data + len, size - len, SEPARATOR BORDER " ECDH Stats " BORDER "\n" SEPARATOR); snprintf( data + len, size - len, BORDER " ECDH Pt Multiply Requests-Succ: %16llu " BORDER "\n" BORDER " ECDH Pt Multiply Request-Err: %16llu " BORDER "\n" BORDER " ECDH Pt Multiply Completed-Succ:%16llu " BORDER "\n" BORDER " ECDH Pt Multiply Completed-Err: %16llu " BORDER "\n" BORDER " ECDH Output Invalid: %16llu " BORDER "\n", (long long unsigned int)ecdhStats.numEcdhPointMultiplyRequests, (long long unsigned int) ecdhStats.numEcdhPointMultiplyRequestErrors, (long long unsigned int)ecdhStats.numEcdhPointMultiplyCompleted, (long long unsigned int) ecdhStats.numEcdhPointMultiplyCompletedError, (long long unsigned int) ecdhStats.numEcdhRequestCompletedOutputInvalid); break; } case SAL_STATS_ECDSA: { CpaCyEcdsaStats64 ecdsaStats = {0}; status = cpaCyEcdsaQueryStats64(pCryptoService, &ecdsaStats); if (status != CPA_STATUS_SUCCESS) { LAC_LOG_ERROR("cpaCyEcdsaQueryStats64 returned error\n"); return 0; } len += snprintf( data + len, size - len, SEPARATOR BORDER " ECDSA Stats " BORDER "\n" SEPARATOR); len += snprintf( data + len, size - len, BORDER " ECDSA Sign R Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign R Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign R Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign R Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign R Output Invalid: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)ecdsaStats.numEcdsaSignRRequests, (long long unsigned int)ecdsaStats.numEcdsaSignRRequestErrors, (long long unsigned int)ecdsaStats.numEcdsaSignRCompleted, (long long unsigned int)ecdsaStats.numEcdsaSignRCompletedErrors, (long long unsigned int) ecdsaStats.numEcdsaSignRCompletedOutputInvalid); len += snprintf( data + len, size - len, BORDER " ECDSA Sign S Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign S Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign S Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign S Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign S Output Invalid: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)ecdsaStats.numEcdsaSignSRequests, (long long unsigned int)ecdsaStats.numEcdsaSignSRequestErrors, (long long unsigned int)ecdsaStats.numEcdsaSignSCompleted, (long long unsigned int)ecdsaStats.numEcdsaSignSCompletedErrors, (long long unsigned int) ecdsaStats.numEcdsaSignSCompletedOutputInvalid); len += snprintf( data + len, size - len, BORDER " ECDSA Sign RS Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Sign RS Output Invalid: %16llu " BORDER "\n" SEPARATOR, (long long unsigned int)ecdsaStats.numEcdsaSignRSRequests, (long long unsigned int)ecdsaStats.numEcdsaSignRSRequestErrors, (long long unsigned int)ecdsaStats.numEcdsaSignRSCompleted, (long long unsigned int) ecdsaStats.numEcdsaSignRSCompletedErrors, (long long unsigned int) ecdsaStats.numEcdsaSignRSCompletedOutputInvalid); snprintf( data + len, size - len, BORDER " ECDSA Verify Requests-Succ: %16llu " BORDER "\n" BORDER " ECDSA Verify Request-Err: %16llu " BORDER "\n" BORDER " ECDSA Verify Completed-Succ: %16llu " BORDER "\n" BORDER " ECDSA Verify Completed-Err: %16llu " BORDER "\n" BORDER " ECDSA Verify Output Invalid: %16llu " BORDER "\n", (long long unsigned int)ecdsaStats.numEcdsaVerifyRequests, (long long unsigned int)ecdsaStats.numEcdsaVerifyRequestErrors, (long long unsigned int)ecdsaStats.numEcdsaVerifyCompleted, (long long unsigned int) ecdsaStats.numEcdsaVerifyCompletedErrors, (long long unsigned int) ecdsaStats.numEcdsaVerifyCompletedOutputInvalid); break; } default: { snprintf(data + len, size - len, SEPARATOR); return 0; } } return ++offset; } STATIC CpaStatus SalCtrl_GetCyConcurrentReqNum(char *string1, char *section, char *string2, sal_crypto_service_t *pCryptoService, Cpa32U *pNumCyConcurrentReq, icp_accel_dev_t *device) { CpaStatus status = CPA_STATUS_SUCCESS; char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; Cpa32U numCyConcurrentReq = 0; /* get num concurrent requests from config file */ status = Sal_StringParsing(string1, pCryptoService->generic_service_info.instance, string2, temp_string); LAC_CHECK_STATUS(status); status = icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); return status; } numCyConcurrentReq = (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); if (CPA_STATUS_FAIL == validateConcurrRequest(numCyConcurrentReq)) { LAC_LOG_ERROR("Invalid NumConcurrentAsymRequests, valid " "values {64, 128, 256, 512, .. 32768, 65536}"); return CPA_STATUS_FAIL; } *pNumCyConcurrentReq = numCyConcurrentReq; return status; } #ifndef ASYM_NOT_SUPPORTED STATIC CpaStatus SalCtrl_AsymInit(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numAsymConcurrentReq = 0; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; char *section = icpGetProcessName(); /* get num concurrent requests from config file */ if (CPA_STATUS_SUCCESS != SalCtrl_GetCyConcurrentReqNum(SAL_CFG_CY, section, SAL_CFG_RING_ASYM_SIZE, pCryptoService, &numAsymConcurrentReq, device)) { LAC_LOG_ERROR("Failed to get NumConcurrentAsymRequests"); return CPA_STATUS_FAIL; } /* Create transport handles */ status = SalCtrl_AsymCreateTransHandle( device, service, numAsymConcurrentReq, section); LAC_CHECK_STATUS(status); /* Allocates memory pools */ pCryptoService->lac_pke_align_pool = LAC_MEM_POOL_INIT_POOL_ID; status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_ASYM_RESIZE_POOL, temp_string); LAC_CHECK_STATUS_ASYM_INIT(status); status = Lac_MemPoolCreate( &pCryptoService->lac_pke_align_pool, temp_string, (((numAsymConcurrentReq + 1)) * LAC_PKE_BUFFERS_PER_OP_MAX), LAC_BITS_TO_BYTES(LAC_MAX_OP_SIZE_IN_BITS), LAC_64BYTE_ALIGNMENT, CPA_FALSE, pCryptoService->nodeAffinity); LAC_CHECK_STATUS_ASYM_INIT(status); /* Allocate pke request memory pool */ pCryptoService->lac_pke_req_pool = LAC_MEM_POOL_INIT_POOL_ID; status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_ASYM_REQ_POOL, temp_string); LAC_CHECK_STATUS_ASYM_INIT(status); status = Lac_MemPoolCreate( &(pCryptoService->lac_pke_req_pool), temp_string, (((numAsymConcurrentReq + 1)) * LAC_PKE_MAX_CHAIN_LENGTH), sizeof(lac_pke_qat_req_data_t), LAC_64BYTE_ALIGNMENT, CPA_TRUE, pCryptoService->nodeAffinity); LAC_CHECK_STATUS_ASYM_INIT(status); /* Allocate prime memory pool */ pCryptoService->lac_prime_pool = LAC_MEM_POOL_INIT_POOL_ID; status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_ASYM_PRIME_POOL, temp_string); LAC_CHECK_STATUS_ASYM_INIT(status); status = Lac_MemPoolCreate(&pCryptoService->lac_prime_pool, temp_string, (numAsymConcurrentReq * 2 + 1), (sizeof(CpaFlatBuffer) * (LAC_PRIME_MAX_MR + 1)), LAC_64BYTE_ALIGNMENT, CPA_FALSE, pCryptoService->nodeAffinity); LAC_CHECK_STATUS_ASYM_INIT(status); /* Allocate EC memory pool */ pCryptoService->lac_ec_pool = LAC_MEM_POOL_INIT_POOL_ID; status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_ASYM_EC_MEM_POOL, temp_string); LAC_CHECK_STATUS_ASYM_INIT(status); status = Lac_MemPoolCreate(&pCryptoService->lac_ec_pool, temp_string, ((numAsymConcurrentReq + 1)), ((LAC_EC_NUM_CONCAT_INPUTS * LAC_EC_SIZE_BYTES_MAX) + sizeof(CpaFlatBuffer)), LAC_64BYTE_ALIGNMENT, CPA_FALSE, pCryptoService->nodeAffinity); LAC_CHECK_STATUS_ASYM_INIT(status); /* Clear Key stats and allocate memory of SSL and TLS labels These labels are initialised to standard values */ #ifdef QAT_LEGACY_ALGORITHMS /* Init DH stats */ status = LacDh_Init(pCryptoService); LAC_CHECK_STATUS_ASYM_INIT(status); #endif #ifdef QAT_LEGACY_ALGORITHMS /* Init Dsa stats */ status = LacDsa_Init(pCryptoService); LAC_CHECK_STATUS_ASYM_INIT(status); #endif /* Init Ec stats */ status = LacEc_Init(pCryptoService); LAC_CHECK_STATUS_ASYM_INIT(status); /* Init Ln Stats */ status = LacLn_Init(pCryptoService); LAC_CHECK_STATUS_ASYM_INIT(status); /* Init Prime stats */ status = LacPrime_Init(pCryptoService); LAC_CHECK_STATUS_ASYM_INIT(status); /* Init Rsa Stats */ status = LacRsa_Init(pCryptoService); LAC_CHECK_STATUS_ASYM_INIT(status); /* Build Flow ID for all pke request sent on this instance */ pCryptoService->pkeFlowId = (LAC_PKE_FLOW_ID_TAG | (pCryptoService->acceleratorNum << LAC_PKE_ACCEL_ID_BIT_POS) | (pCryptoService->executionEngine << LAC_PKE_SLICE_ID_BIT_POS)); /* For all asym requests fill out known data */ Lac_MemPoolInitAsymCookies(pCryptoService->lac_pke_req_pool, pCryptoService); return status; } STATIC CpaStatus SalCtrl_AsymReinit(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numAsymConcurrentReq = 0; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; char *section = icpGetProcessName(); /* get num concurrent requests from config file */ if (CPA_STATUS_SUCCESS != SalCtrl_GetCyConcurrentReqNum(SAL_CFG_CY, section, SAL_CFG_RING_ASYM_SIZE, pCryptoService, &numAsymConcurrentReq, device)) { LAC_LOG_ERROR("Failed to get NumConcurrentAsymRequests"); return CPA_STATUS_FAIL; } /* Create transport handles */ status = SalCtrl_AsymReinitTransHandle( device, service, numAsymConcurrentReq, section); LAC_CHECK_STATUS(status); /* Enables memory pools for allocation */ Lac_MemPoolEnable(pCryptoService->lac_pke_req_pool); /* Build Flow ID for all pke request sent on this instance */ pCryptoService->pkeFlowId = (LAC_PKE_FLOW_ID_TAG | (pCryptoService->acceleratorNum << LAC_PKE_ACCEL_ID_BIT_POS) | (pCryptoService->executionEngine << LAC_PKE_SLICE_ID_BIT_POS)); /* For all asym requests fill out known data */ Lac_MemPoolInitAsymCookies(pCryptoService->lac_pke_req_pool, pCryptoService); return status; } #endif STATIC CpaStatus SalCtrl_SymInit(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numSymConcurrentReq = 0; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; char *section = icpGetProcessName(); /* Set default value of HMAC mode */ pCryptoService->qatHmacMode = ICP_QAT_HW_AUTH_MODE1; /* Register callbacks for the symmetric services * (Hash, Cipher, Algorithm-Chaining) (returns void)*/ LacSymCb_CallbacksRegister(); /* Get num concurrent requests from config file */ if (CPA_STATUS_SUCCESS != SalCtrl_GetCyConcurrentReqNum(SAL_CFG_CY, section, SAL_CFG_RING_SYM_SIZE, pCryptoService, &numSymConcurrentReq, device)) { LAC_LOG_ERROR("Failed to get NumConcurrentSymRequests"); return CPA_STATUS_FAIL; } /* ADF does not allow us to completely fill the ring for batch requests */ pCryptoService->maxNumSymReqBatch = (numSymConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); /* Create transport handles */ status = SalCtrl_SymCreateTransHandle( device, service, numSymConcurrentReq, section); LAC_CHECK_STATUS(status); /* Allocates memory pools */ /* Create and initialise symmetric cookie memory pool */ pCryptoService->lac_sym_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID; status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_SYM_POOL, temp_string); LAC_CHECK_STATUS_SYM_INIT(status); /* Note we need twice (i.e. <<1) the number of sym cookies to support sym ring pairs (and some, for partials) */ status = Lac_MemPoolCreate( &pCryptoService->lac_sym_cookie_pool, temp_string, ((numSymConcurrentReq + numSymConcurrentReq + 1) << 1), sizeof(lac_sym_cookie_t), LAC_64BYTE_ALIGNMENT, CPA_TRUE, pCryptoService->nodeAffinity); LAC_CHECK_STATUS_SYM_INIT(status); /* For all sym cookies fill out the physical address of data that will be set to QAT */ Lac_MemPoolInitSymCookiesPhyAddr(pCryptoService->lac_sym_cookie_pool, pCryptoService); /* Clear stats */ status = LacSymKey_StatsInit(pCryptoService); LAC_CHECK_STATUS_SYM_INIT(status); /* Clears Key stats and allocate memory of SSL and TLS labels These labels are initialised to standard values */ status = LacSymKey_Init(pCryptoService); LAC_CHECK_STATUS_SYM_INIT(status); /* Initialises the hash lookup table*/ status = LacSymQat_Init(pCryptoService); LAC_CHECK_STATUS_SYM_INIT(status); /* Fills out content descriptor for precomputes and registers the hash precompute callback */ status = LacSymHash_HmacPrecompInit(pCryptoService); LAC_CHECK_STATUS_SYM_INIT(status); /* Init the Sym stats */ status = LacSym_StatsInit(pCryptoService); LAC_CHECK_STATUS_SYM_INIT(status); return status; } STATIC CpaStatus SalCtrl_SymReinit(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numSymConcurrentReq = 0; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; char *section = icpGetProcessName(); /* Register callbacks for the symmetric services * (Hash, Cipher, Algorithm-Chaining) (returns void)*/ LacSymCb_CallbacksRegister(); /* Get num concurrent requests from config file */ if (CPA_STATUS_SUCCESS != SalCtrl_GetCyConcurrentReqNum(SAL_CFG_CY, section, SAL_CFG_RING_SYM_SIZE, pCryptoService, &numSymConcurrentReq, device)) { LAC_LOG_ERROR("Failed to get NumConcurrentSymRequests"); return CPA_STATUS_FAIL; } /* ADF does not allow us to completely fill the ring for batch requests */ pCryptoService->maxNumSymReqBatch = (numSymConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); /* Create transport handles */ status = SalCtrl_SymReinitTransHandle( device, service, numSymConcurrentReq, section); LAC_CHECK_STATUS(status); /* Enables memory pools for allocation */ Lac_MemPoolEnable(pCryptoService->lac_sym_cookie_pool); /* For all sym cookies fill out the physical address of data that will be set to QAT */ Lac_MemPoolInitSymCookiesPhyAddr(pCryptoService->lac_sym_cookie_pool, pCryptoService); return status; } STATIC void SalCtrl_DebugCleanup(icp_accel_dev_t *device, sal_service_t *service) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; if (CPA_TRUE == pStatsCollection->bStatsEnabled) { /* Clean stats */ if (NULL != pCryptoService->debug_file) { LAC_OS_FREE(pCryptoService->debug_file->name); LAC_OS_FREE(pCryptoService->debug_file); pCryptoService->debug_file = NULL; } } } STATIC void SalCtrl_DebugShutdown(icp_accel_dev_t *device, sal_service_t *service) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; SalCtrl_DebugCleanup(device, service); pCryptoService->generic_service_info.stats = NULL; } STATIC void SalCtrl_DebugRestarting(icp_accel_dev_t *device, sal_service_t *service) { SalCtrl_DebugCleanup(device, service); } STATIC CpaStatus SalCtrl_DebugInit(icp_accel_dev_t *device, sal_service_t *service) { char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char *instance_name = NULL; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; sal_statistics_collection_t *pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; CpaStatus status = CPA_STATUS_SUCCESS; char *section = icpGetProcessName(); if (CPA_TRUE == pStatsCollection->bStatsEnabled) { /* Get instance name for stats */ status = LAC_OS_MALLOC(&instance_name, ADF_CFG_MAX_VAL_LEN_IN_BYTES); LAC_CHECK_STATUS(status); status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_NAME, temp_string); if (CPA_STATUS_SUCCESS != status) { LAC_OS_FREE(instance_name); return status; } status = icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); LAC_OS_FREE(instance_name); return status; } snprintf( instance_name, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%s", adfGetParam); status = LAC_OS_MALLOC(&pCryptoService->debug_file, sizeof(debug_file_info_t)); if (CPA_STATUS_SUCCESS != status) { LAC_OS_FREE(instance_name); return status; } osalMemSet(pCryptoService->debug_file, 0, sizeof(debug_file_info_t)); pCryptoService->debug_file->name = instance_name; pCryptoService->debug_file->seq_read = SalCtrl_CryptoDebug; pCryptoService->debug_file->private_data = pCryptoService; pCryptoService->debug_file->parent = pCryptoService->generic_service_info.debug_parent_dir; } pCryptoService->generic_service_info.stats = pStatsCollection; return status; } STATIC CpaStatus SalCtrl_GetBankNum(icp_accel_dev_t *device, Cpa32U inst, char *section, char *bank_name, Cpa16U *bank) { char adfParamValue[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char adfParamName[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; CpaStatus status = CPA_STATUS_SUCCESS; status = Sal_StringParsing(SAL_CFG_CY, inst, bank_name, adfParamName); LAC_CHECK_STATUS(status); status = icp_adf_cfgGetParamValue(device, section, adfParamName, adfParamValue); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", adfParamName); return status; } *bank = (Cpa16U)Sal_Strtoul(adfParamValue, NULL, SAL_CFG_BASE_DEC); return status; } STATIC CpaStatus SalCtr_InstInit(icp_accel_dev_t *device, sal_service_t *service) { char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; CpaStatus status = CPA_STATUS_SUCCESS; char *section = icpGetProcessName(); Cpa32S strSize = 0; /* Get Config Info: Accel Num, bank Num, packageID, coreAffinity, nodeAffinity and response mode */ pCryptoService->acceleratorNum = (Cpa16U)device->accelId; switch (service->type) { case SAL_SERVICE_TYPE_CRYPTO_ASYM: status = SalCtrl_GetBankNum( device, pCryptoService->generic_service_info.instance, section, "BankNumberAsym", &pCryptoService->bankNumAsym); if (CPA_STATUS_SUCCESS != status) return status; break; case SAL_SERVICE_TYPE_CRYPTO_SYM: status = SalCtrl_GetBankNum( device, pCryptoService->generic_service_info.instance, section, "BankNumberSym", &pCryptoService->bankNumSym); if (CPA_STATUS_SUCCESS != status) return status; break; case SAL_SERVICE_TYPE_CRYPTO: status = SalCtrl_GetBankNum( device, pCryptoService->generic_service_info.instance, section, "BankNumberAsym", &pCryptoService->bankNumAsym); if (CPA_STATUS_SUCCESS != status) return status; status = SalCtrl_GetBankNum( device, pCryptoService->generic_service_info.instance, section, "BankNumberSym", &pCryptoService->bankNumSym); if (CPA_STATUS_SUCCESS != status) return status; break; default: return CPA_STATUS_FAIL; } status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_POLL_MODE, temp_string); LAC_CHECK_STATUS(status); status = icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); return status; } pCryptoService->isPolled = (Cpa8U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); #ifdef KERNEL_SPACE /* Kernel instances do not support epoll mode */ if (SAL_RESP_EPOLL_CFG_FILE == pCryptoService->isPolled) { LAC_LOG_ERROR_PARAMS( "IsPolled %u is not supported for kernel instance %s", pCryptoService->isPolled, temp_string); return CPA_STATUS_FAIL; } #endif #ifndef KERNEL_SPACE /* User instances only support poll and epoll mode */ if (SAL_RESP_POLL_CFG_FILE != pCryptoService->isPolled && SAL_RESP_EPOLL_CFG_FILE != pCryptoService->isPolled) { LAC_LOG_ERROR_PARAMS("IsPolled %u is not supported for " "user instance %s", pCryptoService->isPolled, temp_string); return CPA_STATUS_FAIL; } #endif status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_DEV_PKG_ID, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", ADF_DEV_PKG_ID); return status; } pCryptoService->pkgID = (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_DEV_NODE_ID, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", ADF_DEV_NODE_ID); return status; } pCryptoService->nodeAffinity = (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); /* In case of interrupt instance, use the bank affinity set by adf_ctl * Otherwise, use the instance affinity for backwards compatibility */ if (SAL_RESP_POLL_CFG_FILE != pCryptoService->isPolled) { /* Next need to read the [AcceleratorX] section of the config file */ status = Sal_StringParsing(SAL_CFG_ACCEL_SEC, pCryptoService->acceleratorNum, "", temp_string2); LAC_CHECK_STATUS(status); if (service->type == SAL_SERVICE_TYPE_CRYPTO_ASYM) status = Sal_StringParsing(SAL_CFG_ETRMGR_BANK, pCryptoService->bankNumAsym, SAL_CFG_ETRMGR_CORE_AFFINITY, temp_string); else /* For cy service, asym bank and sym bank will set the same core affinity. So Just read one*/ status = Sal_StringParsing(SAL_CFG_ETRMGR_BANK, pCryptoService->bankNumSym, SAL_CFG_ETRMGR_CORE_AFFINITY, temp_string); LAC_CHECK_STATUS(status); } else { strSize = snprintf(temp_string2, sizeof(temp_string2), "%s", section); LAC_CHECK_PARAM_RANGE(strSize, 1, sizeof(temp_string2)); status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_ETRMGR_CORE_AFFINITY, temp_string); LAC_CHECK_STATUS(status); } status = icp_adf_cfgGetParamValue( device, temp_string2, temp_string, adfGetParam); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", temp_string); return status; } pCryptoService->coreAffinity = (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); /* No Execution Engine in DH895xcc, so make sure it is zero */ pCryptoService->executionEngine = 0; return status; } /* This function: * 1. Creates sym and asym transport handles * 2. Allocates memory pools required by sym and asym services .* 3. Clears the sym and asym stats counters * 4. In case service asym or sym is enabled then this function * only allocates resources for these services. i.e if the * service asym is enabled then only asym transport handles * are created and vice versa. */ CpaStatus SalCtrl_CryptoInit(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; sal_service_type_t svc_type = service->type; SAL_SERVICE_GOOD_FOR_INIT(pCryptoService); pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_INITIALIZING; /* Set up the instance parameters such as bank number, * coreAffinity, pkgId and node affinity etc */ status = SalCtr_InstInit(device, service); LAC_CHECK_STATUS(status); SalCtrl_CyQueryCapabilities(service, &pCryptoService->capInfo); /* Create debug directory for service */ status = SalCtrl_DebugInit(device, service); LAC_CHECK_STATUS(status); switch (svc_type) { #ifndef ASYM_NOT_SUPPORTED case SAL_SERVICE_TYPE_CRYPTO_ASYM: status = SalCtrl_AsymInit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); return status; } break; #endif case SAL_SERVICE_TYPE_CRYPTO_SYM: status = SalCtrl_SymInit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); return status; } break; case SAL_SERVICE_TYPE_CRYPTO: #ifndef ASYM_NOT_SUPPORTED status = SalCtrl_AsymInit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); return status; } #endif status = SalCtrl_SymInit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); #ifndef ASYM_NOT_SUPPORTED SalCtrl_AsymFreeResources(pCryptoService); #endif return status; } break; default: LAC_LOG_ERROR("Invalid service type\n"); status = CPA_STATUS_FAIL; break; } pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_INITIALIZED; return status; } CpaStatus SalCtrl_CryptoStart(icp_accel_dev_t *device, sal_service_t *service) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; CpaStatus status = CPA_STATUS_SUCCESS; if (pCryptoService->generic_service_info.state != SAL_SERVICE_STATE_INITIALIZED) { LAC_LOG_ERROR("Not in the correct state to call start\n"); return CPA_STATUS_FAIL; } pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_RUNNING; return status; } CpaStatus SalCtrl_CryptoStop(icp_accel_dev_t *device, sal_service_t *service) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; if (SAL_SERVICE_STATE_RUNNING != pCryptoService->generic_service_info.state) { LAC_LOG_ERROR("Not in the correct state to call stop"); } pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_SHUTTING_DOWN; return CPA_STATUS_SUCCESS; } CpaStatus SalCtrl_CryptoShutdown(icp_accel_dev_t *device, sal_service_t *service) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; CpaStatus status = CPA_STATUS_SUCCESS; sal_service_type_t svc_type = service->type; if ((SAL_SERVICE_STATE_INITIALIZED != pCryptoService->generic_service_info.state) && (SAL_SERVICE_STATE_SHUTTING_DOWN != pCryptoService->generic_service_info.state) && (SAL_SERVICE_STATE_RESTARTING != pCryptoService->generic_service_info.state)) { LAC_LOG_ERROR("Not in the correct state to call shutdown\n"); return CPA_STATUS_FAIL; } /* Free memory and transhandles */ switch (svc_type) { #ifndef ASYM_NOT_SUPPORTED case SAL_SERVICE_TYPE_CRYPTO_ASYM: if (SalCtrl_AsymFreeResources(pCryptoService)) { status = CPA_STATUS_FAIL; } break; #endif case SAL_SERVICE_TYPE_CRYPTO_SYM: if (SalCtrl_SymFreeResources(pCryptoService)) { status = CPA_STATUS_FAIL; } break; case SAL_SERVICE_TYPE_CRYPTO: #ifndef ASYM_NOT_SUPPORTED if (SalCtrl_AsymFreeResources(pCryptoService)) { status = CPA_STATUS_FAIL; } #endif if (SalCtrl_SymFreeResources(pCryptoService)) { status = CPA_STATUS_FAIL; } break; default: LAC_LOG_ERROR("Invalid service type\n"); status = CPA_STATUS_FAIL; break; } SalCtrl_DebugShutdown(device, service); pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_SHUTDOWN; return status; } CpaStatus SalCtrl_CryptoError(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; LAC_CHECK_NULL_PARAM(service); SalCtrl_CyMemPoolDisable(service); SalCtrl_CyUpdatePoolsBusy(service); /* Considering the detachment of the VFs, the device is still alive and * can generate responses normally. After the state of the service is * set to ERROR, if it goes to the function to check responses in such * cases, it will indicate there are some responses on the ring. However, * icp_sal_CyPollInstance() function will only call * SalCtrl_CyGenResponses() to generate dummy responses not poll the * instance with icp_adf_pollInstance() as the service has been set to * ERROR. So adding a judgment condition here to avoid to check the * response ring again. */ if (SAL_SERVICE_STATE_ERROR != pCryptoService->generic_service_info.state) { status = SalCtrl_CyCheckRespInstance(service); /* The polling functions would be prevented to poll due to * SAL_RUNNING_CHECK check which may cause missing retrieving in-flight * responses. Hence the error status is only set after there are no * remained responses on the response ring. */ if (CPA_STATUS_SUCCESS == status) { pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_ERROR; } } return status; } CpaStatus SalCtrl_CryptoRestarting(icp_accel_dev_t *device, sal_service_t *service) { sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; CpaStatus status = CPA_STATUS_SUCCESS; sal_service_type_t svc_type = service->type; if ((SAL_SERVICE_STATE_RUNNING != pCryptoService->generic_service_info.state) && (SAL_SERVICE_STATE_ERROR != pCryptoService->generic_service_info.state)) { LAC_LOG_ERROR("Not in the correct state to call restarting\n"); return CPA_STATUS_FAIL; } switch (svc_type) { #ifndef ASYM_NOT_SUPPORTED case SAL_SERVICE_TYPE_CRYPTO_ASYM: if (SalCtrl_AsymResetResources(pCryptoService)) { status = CPA_STATUS_FAIL; } break; #endif case SAL_SERVICE_TYPE_CRYPTO_SYM: if (SalCtrl_SymResetResources(pCryptoService)) { status = CPA_STATUS_FAIL; } break; case SAL_SERVICE_TYPE_CRYPTO: #ifndef ASYM_NOT_SUPPORTED if (SalCtrl_AsymResetResources(pCryptoService)) { status = CPA_STATUS_FAIL; } #endif if (SalCtrl_SymResetResources(pCryptoService)) { status = CPA_STATUS_FAIL; } break; default: LAC_LOG_ERROR("Invalid service type\n"); status = CPA_STATUS_FAIL; break; } SalCtrl_DebugRestarting(device, service); pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_RESTARTING; return status; } CpaStatus SalCtrl_CryptoRestarted(icp_accel_dev_t *device, sal_service_t *service) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; sal_service_type_t svc_type = service->type; SAL_SERVICE_GOOD_FOR_RESTARTED(pCryptoService); pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_INITIALIZING; /* Set up the instance parameters such as bank number, * coreAffinity, pkgId and node affinity etc */ status = SalCtr_InstInit(device, service); LAC_CHECK_STATUS(status); SalCtrl_CyQueryCapabilities(service, &pCryptoService->capInfo); /* Create debug directory for service */ status = SalCtrl_DebugInit(device, service); LAC_CHECK_STATUS(status); switch (svc_type) { #ifndef ASYM_NOT_SUPPORTED case SAL_SERVICE_TYPE_CRYPTO_ASYM: status = SalCtrl_AsymReinit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); return status; } break; #endif case SAL_SERVICE_TYPE_CRYPTO_SYM: status = SalCtrl_SymReinit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); return status; } break; case SAL_SERVICE_TYPE_CRYPTO: #ifndef ASYM_NOT_SUPPORTED status = SalCtrl_AsymReinit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); return status; } #endif status = SalCtrl_SymReinit(device, service); if (CPA_STATUS_SUCCESS != status) { SalCtrl_DebugShutdown(device, service); #ifndef ASYM_NOT_SUPPORTED SalCtrl_AsymFreeResources(pCryptoService); #endif return status; } break; default: SalCtrl_DebugShutdown(device, service); LAC_LOG_ERROR("Invalid service type\n"); status = CPA_STATUS_FAIL; break; } pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_RUNNING; return status; } void SalCtrl_CyQueryCapabilities(sal_service_t *pGenericService, CpaCyCapabilitiesInfo *pCapInfo) { osalMemSet(pCapInfo, 0, sizeof(CpaCyCapabilitiesInfo)); if (SAL_SERVICE_TYPE_CRYPTO == pGenericService->type || SAL_SERVICE_TYPE_CRYPTO_SYM == pGenericService->type) { pCapInfo->symSupported = CPA_TRUE; if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN) { pCapInfo->extAlgchainSupported = CPA_TRUE; } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_HKDF) { pCapInfo->hkdfSupported = CPA_TRUE; } } if (SAL_SERVICE_TYPE_CRYPTO == pGenericService->type || SAL_SERVICE_TYPE_CRYPTO_ASYM == pGenericService->type) { if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_KPT) { /* Enable KPT only when KPT capability is set */ pCapInfo->kptSupported = CPA_TRUE; } else { #ifdef ASYM_NOT_SUPPORTED pCapInfo->dhSupported = CPA_FALSE; pCapInfo->dsaSupported = CPA_FALSE; pCapInfo->rsaSupported = CPA_FALSE; pCapInfo->ecSupported = CPA_FALSE; pCapInfo->ecdhSupported = CPA_FALSE; pCapInfo->ecdsaSupported = CPA_FALSE; pCapInfo->keySupported = CPA_FALSE; pCapInfo->lnSupported = CPA_FALSE; pCapInfo->primeSupported = CPA_FALSE; pCapInfo->ecEdMontSupported = CPA_FALSE; #else #ifdef QAT_LEGACY_ALGORITHMS pCapInfo->dhSupported = CPA_TRUE; pCapInfo->dsaSupported = CPA_TRUE; #else pCapInfo->dhSupported = CPA_FALSE; pCapInfo->dsaSupported = CPA_FALSE; #endif pCapInfo->rsaSupported = CPA_TRUE; pCapInfo->ecSupported = CPA_TRUE; pCapInfo->ecdhSupported = CPA_TRUE; pCapInfo->ecdsaSupported = CPA_TRUE; pCapInfo->keySupported = CPA_TRUE; pCapInfo->lnSupported = CPA_TRUE; pCapInfo->primeSupported = CPA_TRUE; if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_ECEDMONT) { pCapInfo->ecEdMontSupported = CPA_TRUE; } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM2) { pCapInfo->ecSm2Supported = CPA_TRUE; } else { pCapInfo->ecSm2Supported = CPA_FALSE; } #endif } } pCapInfo->drbgSupported = CPA_FALSE; pCapInfo->nrbgSupported = CPA_FALSE; pCapInfo->randSupported = CPA_FALSE; } CpaStatus SalCtrl_CySymQueryCapabilities(sal_service_t *pGenericService, CpaCySymCapabilitiesInfo *pCapInfo) { LAC_CHECK_NULL_PARAM(pGenericService); LAC_CHECK_NULL_PARAM(pCapInfo); osalMemSet(pCapInfo, '\0', sizeof(CpaCySymCapabilitiesInfo)); /* An asym crypto instance does not support sym service */ if (SAL_SERVICE_TYPE_CRYPTO_ASYM == pGenericService->type) { return CPA_STATUS_SUCCESS; } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_CIPHER) { #ifdef QAT_LEGACY_ALGORITHMS CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_ECB); #endif CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_NULL); CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CBC); CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CTR); CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_XTS); } /* Report hashes supported if capability supports authentication. This * is also used for a compression instance (DC Chaining) to determine if * DC Chaining supports hash operations. */ if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_AUTHENTICATION) { #ifdef QAT_LEGACY_ALGORITHMS CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA1); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA224); #endif CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA256); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA384); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA512); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_XCBC); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CMAC); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CBC_MAC); } if ((pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_CIPHER) && (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_AUTHENTICATION)) { /* When one of the following cipher algorithms is used, the elements of * the CpaCySymHashAlgorithm enum MUST be used to set up the related * CpaCySymHashSetupData structure in the session context. * CPA_CY_SYM_CIPHER_AES_CCM * CPA_CY_SYM_CIPHER_AES_GCM */ CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CCM); CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_GCM); /* When one of the following hash algorithms is used, the elements of * the CpaCySymCipherAlgorithm enum MUST be used to set up the related * CpaCySymCipherSetupData structure in the session context. * CPA_CY_SYM_HASH_AES_CCM * CPA_CY_SYM_HASH_AES_GCM * CPA_CY_SYM_HASH_AES_GMAC */ CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CCM); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GCM); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GMAC); } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_ZUC) { CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_ZUC_EEA3); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_ZUC_EIA3); } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_SHA3) { CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256); } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_CHACHA_POLY) { CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_POLY); CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_CHACHA); } pCapInfo->partialPacketSupported = CPA_TRUE; if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SHA3_EXT) { #ifdef QAT_LEGACY_ALGORITHMS CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_224); #endif CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_384); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_512); } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM3) { CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SM3); } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM4) { #ifdef QAT_LEGACY_ALGORITHMS CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_SM4_ECB); #endif CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_SM4_CBC); CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_SM4_CTR); } if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_WIRELESS_CRYPTO_EXT) { #ifdef QAT_LEGACY_ALGORITHMS CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_F8); #endif CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_SNOW3G_UEA2); CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SNOW3G_UIA2); } return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyGetStatusText(const CpaInstanceHandle instanceHandle, CpaStatus errStatus, Cpa8S *pStatusText) { CpaStatus status = CPA_STATUS_SUCCESS; #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, %d, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, errStatus, (LAC_ARCH_UINT)pStatusText); #endif LAC_CHECK_NULL_PARAM(pStatusText); switch (errStatus) { case CPA_STATUS_SUCCESS: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_SUCCESS); break; case CPA_STATUS_FAIL: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FAIL); break; case CPA_STATUS_RETRY: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RETRY); break; case CPA_STATUS_RESOURCE: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RESOURCE); break; case CPA_STATUS_INVALID_PARAM: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_INVALID_PARAM); break; case CPA_STATUS_FATAL: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FATAL); break; case CPA_STATUS_UNSUPPORTED: LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_UNSUPPORTED); break; default: status = CPA_STATUS_INVALID_PARAM; break; } return status; } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyStartInstance(CpaInstanceHandle instanceHandle_in) { CpaInstanceHandle instanceHandle = NULL; icp_accel_dev_t *dev = NULL; sal_crypto_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG1("Called with params (0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_CryptoGetFirstHandle(); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_NULL_PARAM(instanceHandle); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); pService = (sal_crypto_service_t *)instanceHandle; dev = icp_adf_getAccelDevByAccelId(pService->acceleratorNum); if (NULL == dev) { LAC_LOG_ERROR("Can not find device for the instance\n"); return CPA_STATUS_FAIL; } pService->generic_service_info.isInstanceStarted = CPA_TRUE; /* Increment dev ref counter */ icp_adf_qaDevGet(dev); return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyStopInstance(CpaInstanceHandle instanceHandle_in) { CpaInstanceHandle instanceHandle = NULL; icp_accel_dev_t *dev = NULL; sal_crypto_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG1("Called with params (0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_CryptoGetFirstHandle(); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_NULL_PARAM(instanceHandle); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); pService = (sal_crypto_service_t *)instanceHandle; dev = icp_adf_getAccelDevByAccelId(pService->acceleratorNum); if (NULL == dev) { LAC_LOG_ERROR("Can not find device for the instance\n"); return CPA_STATUS_FAIL; } pService->generic_service_info.isInstanceStarted = CPA_FALSE; /* Decrement dev ref counter */ icp_adf_qaDevPut(dev); return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyInstanceSetNotificationCb( const CpaInstanceHandle instanceHandle, const CpaCyInstanceNotificationCbFunc pInstanceNotificationCb, void *pCallbackTag) { CpaStatus status = CPA_STATUS_SUCCESS; sal_service_t *gen_handle = instanceHandle; #ifdef ICP_TRACE LAC_LOG3("Called with params (0x%lx, 0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle, (LAC_ARCH_UINT)pInstanceNotificationCb, (LAC_ARCH_UINT)pCallbackTag); #endif LAC_CHECK_NULL_PARAM(gen_handle); gen_handle->notification_cb = pInstanceNotificationCb; gen_handle->cb_tag = pCallbackTag; return status; } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyGetNumInstances(Cpa16U *pNumInstances) { return Lac_GetCyNumInstancesByType(CPA_ACC_SVC_TYPE_CRYPTO, pNumInstances); } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyGetInstances(Cpa16U numInstances, CpaInstanceHandle *pCyInstances) { return Lac_GetCyInstancesByType( CPA_ACC_SVC_TYPE_CRYPTO, numInstances, pCyInstances); } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyInstanceGetInfo(const CpaInstanceHandle instanceHandle_in, struct _CpaInstanceInfo *pInstanceInfo) { CpaInstanceHandle instanceHandle = NULL; sal_crypto_service_t *pCryptoService = NULL; sal_service_t *pGenericService = NULL; Cpa8U name[CPA_INST_NAME_SIZE] = "Intel(R) DH89XXCC instance number: %02x, type: Crypto"; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pInstanceInfo); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_CryptoGetFirstHandle(); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_NULL_PARAM(instanceHandle); LAC_CHECK_NULL_PARAM(pInstanceInfo); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); pCryptoService = (sal_crypto_service_t *)instanceHandle; pInstanceInfo->type = CPA_INSTANCE_TYPE_CRYPTO; /* According to cpa.h instance state is initialized and ready for use * or shutdown. Therefore need to map our running state to initialised * or shutdown */ if (SAL_SERVICE_STATE_RUNNING == pCryptoService->generic_service_info.state) { pInstanceInfo->state = CPA_INSTANCE_STATE_INITIALISED; } else { pInstanceInfo->state = CPA_INSTANCE_STATE_SHUTDOWN; } pGenericService = (sal_service_t *)instanceHandle; snprintf((char *)pInstanceInfo->name, CPA_INST_NAME_SIZE, (char *)name, pGenericService->instance); pInstanceInfo->name[CPA_INST_NAME_SIZE - 1] = '\0'; snprintf((char *)pInstanceInfo->version, CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES, "%d.%d", CPA_CY_API_VERSION_NUM_MAJOR, CPA_CY_API_VERSION_NUM_MINOR); pInstanceInfo->version[CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES - 1] = '\0'; return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyInstanceGetInfo2(const CpaInstanceHandle instanceHandle_in, CpaInstanceInfo2 *pInstanceInfo2) { CpaInstanceHandle instanceHandle = NULL; sal_crypto_service_t *pCryptoService = NULL; icp_accel_dev_t *dev = NULL; CpaStatus status = CPA_STATUS_SUCCESS; char keyStr[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = {0}; char valStr[CPA_INST_NAME_SIZE] = { 0 }; char *section = NULL; Cpa32S strSize = 0; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pInstanceInfo2); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_CryptoGetFirstHandle(); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_NULL_PARAM(instanceHandle); LAC_CHECK_NULL_PARAM(pInstanceInfo2); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); pInstanceInfo2->accelerationServiceType = CPA_ACC_SVC_TYPE_CRYPTO; snprintf((char *)pInstanceInfo2->vendorName, CPA_INST_VENDOR_NAME_SIZE, "%s", SAL_INFO2_VENDOR_NAME); pInstanceInfo2->vendorName[CPA_INST_VENDOR_NAME_SIZE - 1] = '\0'; snprintf((char *)pInstanceInfo2->swVersion, CPA_INST_SW_VERSION_SIZE, "Version %d.%d", SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER); pInstanceInfo2->swVersion[CPA_INST_SW_VERSION_SIZE - 1] = '\0'; /* Note we can safely read the contents of the crypto service instance here because icp_adf_getAllAccelDevByCapabilities() only returns devs that have started */ pCryptoService = (sal_crypto_service_t *)instanceHandle; pInstanceInfo2->physInstId.packageId = pCryptoService->pkgID; pInstanceInfo2->physInstId.acceleratorId = pCryptoService->acceleratorNum; pInstanceInfo2->physInstId.executionEngineId = pCryptoService->executionEngine; pInstanceInfo2->physInstId.busAddress = icp_adf_getBusAddress(pInstanceInfo2->physInstId.acceleratorId); /* set coreAffinity to zero before use */ LAC_OS_BZERO(pInstanceInfo2->coreAffinity, sizeof(pInstanceInfo2->coreAffinity)); CPA_BITMAP_BIT_SET(pInstanceInfo2->coreAffinity, pCryptoService->coreAffinity); pInstanceInfo2->nodeAffinity = pCryptoService->nodeAffinity; if (CPA_TRUE == pCryptoService->generic_service_info.isInstanceStarted) { pInstanceInfo2->operState = CPA_OPER_STATE_UP; } else { pInstanceInfo2->operState = CPA_OPER_STATE_DOWN; } pInstanceInfo2->requiresPhysicallyContiguousMemory = CPA_TRUE; if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled || SAL_RESP_EPOLL_CFG_FILE == pCryptoService->isPolled) { pInstanceInfo2->isPolled = CPA_TRUE; } else { pInstanceInfo2->isPolled = CPA_FALSE; } pInstanceInfo2->isOffloaded = CPA_TRUE; /* Get the instance name and part name*/ dev = icp_adf_getAccelDevByAccelId(pCryptoService->acceleratorNum); if (NULL == dev) { LAC_LOG_ERROR("Can not find device for the instance\n"); LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); return CPA_STATUS_FAIL; } snprintf((char *)pInstanceInfo2->partName, CPA_INST_PART_NAME_SIZE, SAL_INFO2_PART_NAME, dev->deviceName); pInstanceInfo2->partName[CPA_INST_PART_NAME_SIZE - 1] = '\0'; status = Sal_StringParsing(SAL_CFG_CY, pCryptoService->generic_service_info.instance, SAL_CFG_NAME, keyStr); LAC_CHECK_STATUS(status); section = icpGetProcessName(); status = icp_adf_cfgGetParamValue(dev, section, keyStr, valStr); LAC_CHECK_STATUS(status); strSize = strnlen(valStr, sizeof(valStr)); LAC_CHECK_PARAM_RANGE(strSize, 1, CPA_INST_NAME_SIZE); snprintf((char *)pInstanceInfo2->instName, CPA_INST_NAME_SIZE, "%.*s", CPA_INST_NAME_SIZE - 1, valStr); strSize = strnlen(valStr, sizeof(valStr)) + strnlen(section, LAC_USER_PROCESS_NAME_MAX_LEN) + 1; LAC_CHECK_PARAM_RANGE(strSize, 1, CPA_INST_ID_SIZE); snprintf((char *)pInstanceInfo2->instID, CPA_INST_ID_SIZE, "%s_%s", section, valStr); return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCyQueryCapabilities(const CpaInstanceHandle instanceHandle_in, CpaCyCapabilitiesInfo *pCapInfo) { /* Verify Instance exists */ CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCapInfo); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_CryptoGetFirstHandle(); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_NULL_PARAM(instanceHandle); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(pCapInfo); *pCapInfo = ((sal_crypto_service_t *)instanceHandle)->capInfo; return CPA_STATUS_SUCCESS; } CpaStatus cpaCySymQueryCapabilities(const CpaInstanceHandle instanceHandle_in, CpaCySymCapabilitiesInfo *pCapInfo) { CpaInstanceHandle instanceHandle = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)pCapInfo); #endif /* Verify Instance exists */ if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); if (!instanceHandle) { instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); } } else { instanceHandle = instanceHandle_in; } LAC_CHECK_NULL_PARAM(instanceHandle); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); return SalCtrl_CySymQueryCapabilities((sal_service_t *)instanceHandle, pCapInfo); } /** ****************************************************************************** * @ingroup cpaCyCommon *****************************************************************************/ CpaStatus cpaCySetAddressTranslation(const CpaInstanceHandle instanceHandle_in, CpaVirtualToPhysical virtual2physical) { CpaInstanceHandle instanceHandle = NULL; sal_service_t *pService = NULL; #ifdef ICP_TRACE LAC_LOG2("Called with params (0x%lx, 0x%lx)\n", (LAC_ARCH_UINT)instanceHandle_in, (LAC_ARCH_UINT)virtual2physical); #endif if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { instanceHandle = Lac_CryptoGetFirstHandle(); } else { instanceHandle = instanceHandle_in; } LAC_CHECK_NULL_PARAM(instanceHandle); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); LAC_CHECK_NULL_PARAM(virtual2physical); pService = (sal_service_t *)instanceHandle; pService->virt2PhysClient = virtual2physical; return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup cpaCyCommon * Crypto specific polling function which polls a crypto instance. *****************************************************************************/ CpaStatus icp_sal_CyPollInstance(CpaInstanceHandle instanceHandle_in, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *crypto_handle = NULL; sal_service_t *gen_handle = NULL; icp_comms_trans_handle trans_hndTable[MAX_CY_RX_RINGS]; Cpa32U num_rx_rings = 0; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { crypto_handle = (sal_crypto_service_t *)Lac_CryptoGetFirstHandle(); } else { crypto_handle = (sal_crypto_service_t *)instanceHandle_in; } LAC_CHECK_NULL_PARAM(crypto_handle); SAL_CHECK_INSTANCE_TYPE(crypto_handle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); gen_handle = &(crypto_handle->generic_service_info); if ((Sal_ServiceIsInError(crypto_handle))) { LAC_LOG_DEBUG("PollCyInstance: generate dummy responses\n"); status = SalCtrl_CyGenResponses(crypto_handle, gen_handle); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR("Failed to generate SW responses for CY\n"); } return status; } SAL_RUNNING_CHECK(crypto_handle); /* * From the instanceHandle we must get the trans_handle and send * down to adf for polling. * Populate our trans handle table with the appropriate handles. */ switch (gen_handle->type) { case SAL_SERVICE_TYPE_CRYPTO_ASYM: trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_asym_rx; num_rx_rings = 1; break; case SAL_SERVICE_TYPE_CRYPTO_SYM: trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; num_rx_rings = 1; break; case SAL_SERVICE_TYPE_CRYPTO: trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; trans_hndTable[TH_CY_RX_1] = crypto_handle->trans_handle_asym_rx; num_rx_rings = MAX_CY_RX_RINGS; break; default: break; } /* Call adf to do the polling. */ status = icp_adf_pollInstance(trans_hndTable, num_rx_rings, response_quota); return status; } /* ****************************************************************************** * @ingroup cpaCyCommon * Crypto specific polling function which polls a symmetric instance. *****************************************************************************/ CpaStatus icp_sal_CyPollSymRing(CpaInstanceHandle instanceHandle_in, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *crypto_handle = NULL; icp_comms_trans_handle trans_hndTable[NUM_CRYPTO_SYM_RX_RINGS] = {0}; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { crypto_handle = (sal_crypto_service_t *)Lac_GetFirstHandle( SAL_SERVICE_TYPE_CRYPTO_SYM); } else { crypto_handle = (sal_crypto_service_t *)instanceHandle_in; } LAC_CHECK_NULL_PARAM(crypto_handle); SAL_CHECK_INSTANCE_TYPE( crypto_handle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM)); SAL_RUNNING_CHECK(crypto_handle); /* * From the instanceHandle we must get the trans_handle and send * down to adf for polling. * Populate trans handle table with the appropriate handle. */ trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; /* Call adf to do the polling. */ status = icp_adf_pollInstance( trans_hndTable, NUM_CRYPTO_SYM_RX_RINGS, response_quota); return status; } /* ****************************************************************************** * @ingroup cpaCyCommon * Crypto specific polling function which polls an asymmetric instance. *****************************************************************************/ CpaStatus icp_sal_CyPollAsymRing(CpaInstanceHandle instanceHandle_in, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_SUCCESS; sal_crypto_service_t *crypto_handle = NULL; sal_service_t *gen_handle = NULL; icp_comms_trans_handle trans_hndTable[NUM_CRYPTO_ASYM_RX_RINGS] = {0}; if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { crypto_handle = (sal_crypto_service_t *)Lac_GetFirstHandle( SAL_SERVICE_TYPE_CRYPTO_ASYM); } else { crypto_handle = (sal_crypto_service_t *)instanceHandle_in; } LAC_CHECK_NULL_PARAM(crypto_handle); SAL_CHECK_INSTANCE_TYPE( crypto_handle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM)); gen_handle = &(crypto_handle->generic_service_info); if ((Sal_ServiceIsInError(crypto_handle))) { LAC_LOG_DEBUG("Generate dummy responses\n"); status = SalCtrl_CyGenResponses(crypto_handle, gen_handle); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR("Failed to generate dummy Responses\n"); } return status; } SAL_RUNNING_CHECK(crypto_handle); /* * From the instanceHandle we must get the trans_handle and send * down to adf for polling. * Populate trans handle table with the appropriate handle. */ trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_asym_rx; /* Call adf to do the polling. */ status = icp_adf_pollInstance( trans_hndTable, NUM_CRYPTO_ASYM_RX_RINGS, response_quota); return status; } /* Polling CY instances' memory pool in progress of all banks for one device */ STATIC CpaStatus Lac_CyService_GenResponses(sal_list_t **services) { CpaInstanceHandle cyInstHandle = NULL; sal_list_t *sal_service = NULL; sal_crypto_service_t *crypto_handle = NULL; sal_service_t *gen_handle = NULL; CpaStatus status = CPA_STATUS_SUCCESS; LAC_CHECK_NULL_PARAM(services); sal_service = *services; while (sal_service) { cyInstHandle = (void *)SalList_getObject(sal_service); crypto_handle = (sal_crypto_service_t *)cyInstHandle; LAC_CHECK_NULL_PARAM(crypto_handle); gen_handle = &(crypto_handle->generic_service_info); status = SalCtrl_CyGenResponses(crypto_handle, gen_handle); if (CPA_STATUS_SUCCESS != status) { break; } sal_service = SalList_next(sal_service); } return status; } CpaStatus SalCtrl_CyDevErr_GenResponses(icp_accel_dev_t *accel_dev, Cpa32U enabled_services) { sal_t *service_container = NULL; CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus symStatus = CPA_STATUS_SUCCESS; service_container = accel_dev->pSalHandle; if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = Lac_CyService_GenResponses(&service_container->asym_services); if (CPA_STATUS_SUCCESS != status && CPA_STATUS_RETRY != status) { LAC_LOG_ERROR( "Failed to generate dummy responses for asym service"); return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { symStatus = Lac_CyService_GenResponses(&service_container->sym_services); if (CPA_STATUS_SUCCESS != symStatus && CPA_STATUS_RETRY != symStatus) { LAC_LOG_ERROR("Failed to generate dummy responses for sym service"); return symStatus; } if (CPA_STATUS_SUCCESS == status || CPA_STATUS_SUCCESS == symStatus) status = CPA_STATUS_SUCCESS; } else if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = Lac_CyService_GenResponses(&service_container->crypto_services); if (CPA_STATUS_SUCCESS != status && CPA_STATUS_RETRY != status) { LAC_LOG_ERROR( "Failed to generate dummy responses for crypto service"); return status; } } return status; } /* Returns the handle to the first asym crypto instance */ STATIC CpaInstanceHandle Lac_GetFirstAsymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], Cpa16U num_dev) { icp_accel_dev_t *dev_addr = NULL; sal_t *base_addr = NULL; sal_list_t *list_temp = NULL; CpaInstanceHandle cyInst = NULL; Cpa16U i = 0; for (i = 0; i < num_dev; i++) { dev_addr = (icp_accel_dev_t *)adfInsts[i]; base_addr = dev_addr->pSalHandle; if ((NULL != base_addr) && (NULL != base_addr->asym_services)) { list_temp = base_addr->asym_services; cyInst = SalList_getObject(list_temp); break; } } return cyInst; } /* Returns the handle to the first sym crypto instance */ STATIC CpaInstanceHandle Lac_GetFirstSymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], Cpa16U num_dev) { icp_accel_dev_t *dev_addr = NULL; sal_t *base_addr = NULL; sal_list_t *list_temp = NULL; CpaInstanceHandle cyInst = NULL; Cpa16U i = 0; for (i = 0; i < num_dev; i++) { dev_addr = (icp_accel_dev_t *)adfInsts[i]; base_addr = dev_addr->pSalHandle; if ((NULL != base_addr) && (NULL != base_addr->sym_services)) { list_temp = base_addr->sym_services; cyInst = SalList_getObject(list_temp); break; } } return cyInst; } /* Returns the handle to the first crypto instance * Note that the crypto instance in this case supports * both asym and sym services */ STATIC CpaInstanceHandle Lac_GetFirstCyHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], Cpa16U num_dev) { icp_accel_dev_t *dev_addr = NULL; sal_t *base_addr = NULL; sal_list_t *list_temp = NULL; CpaInstanceHandle cyInst = NULL; Cpa16U i = 0; for (i = 0; i < num_dev; i++) { dev_addr = (icp_accel_dev_t *)adfInsts[i]; base_addr = dev_addr->pSalHandle; if ((NULL != base_addr) && (NULL != base_addr->crypto_services)) { list_temp = base_addr->crypto_services; cyInst = SalList_getObject(list_temp); break; } } return cyInst; } CpaInstanceHandle Lac_GetFirstHandle(sal_service_type_t svc_type) { CpaStatus status = CPA_STATUS_SUCCESS; static icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES] = {0}; CpaInstanceHandle cyInst = NULL; Cpa16U num_cy_dev = 0; Cpa32U capabilities = 0; char *service = NULL; switch (svc_type) { case SAL_SERVICE_TYPE_CRYPTO_ASYM: capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; service = "asym"; break; case SAL_SERVICE_TYPE_CRYPTO_SYM: capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; service = "sym"; break; case SAL_SERVICE_TYPE_CRYPTO: capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; capabilities |= ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; service = "cy"; break; default: LAC_LOG_ERROR("Invalid service type\n"); return NULL; } /* Only need 1 dev with crypto enabled - so check all devices*/ status = icp_adf_getAllAccelDevByEachCapability( capabilities, adfInsts, &num_cy_dev); if ((0 == num_cy_dev) || (CPA_STATUS_SUCCESS != status)) { LAC_LOG1("No %s devices enabled in the system\n", service); return NULL; } switch (svc_type) { case SAL_SERVICE_TYPE_CRYPTO_ASYM: /* Try to find an asym only instance first */ cyInst = Lac_GetFirstAsymHandle(adfInsts, num_cy_dev); /* Try to find a cy instance since it also supports asym */ if (NULL == cyInst) { cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); } break; case SAL_SERVICE_TYPE_CRYPTO_SYM: /* Try to find a sym only instance first */ cyInst = Lac_GetFirstSymHandle(adfInsts, num_cy_dev); /* Try to find a cy instance since it also supports sym */ if (NULL == cyInst) { cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); } break; case SAL_SERVICE_TYPE_CRYPTO: /* Try to find a cy instance */ cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); break; default: LAC_LOG_ERROR("Invalid service type!\n"); break; } if (NULL == cyInst) { LAC_LOG_ERROR("No remaining crypto instances available\n"); } return cyInst; } CpaStatus icp_sal_CyGetFileDescriptor(CpaInstanceHandle instanceHandle, int *fd) { sal_crypto_service_t *crypto_handle = NULL; sal_service_t *gen_handle = NULL; CpaStatus status = CPA_STATUS_SUCCESS; crypto_handle = (sal_crypto_service_t *)instanceHandle; /* Make sure that we zero file descriptor * in case of error or unsupported. */ LAC_CHECK_NULL_PARAM(fd); *fd = 0; LAC_CHECK_NULL_PARAM(crypto_handle); SAL_RUNNING_CHECK(crypto_handle); if (SAL_RESP_EPOLL_CFG_FILE != crypto_handle->isPolled) { return CPA_STATUS_UNSUPPORTED; } gen_handle = &(crypto_handle->generic_service_info); switch (gen_handle->type) { case SAL_SERVICE_TYPE_CRYPTO: { status = SalCtrl_CyGetFileDescriptor(crypto_handle, fd); break; } case SAL_SERVICE_TYPE_CRYPTO_ASYM: { status = SalCtrl_AsymGetFileDescriptor(crypto_handle, fd); break; } case SAL_SERVICE_TYPE_CRYPTO_SYM: { status = SalCtrl_SymGetFileDescriptor(crypto_handle, fd); break; } default: LAC_LOG_ERROR("The instance handle is the wrong type"); return CPA_STATUS_FAIL; } return status; } CpaStatus icp_sal_CyPutFileDescriptor(CpaInstanceHandle instanceHandle, int fd) { sal_crypto_service_t *crypto_handle = NULL; crypto_handle = (sal_crypto_service_t *)instanceHandle; LAC_CHECK_NULL_PARAM(crypto_handle); SAL_RUNNING_CHECK(crypto_handle); SAL_CHECK_INSTANCE_TYPE(instanceHandle, (SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_ASYM | SAL_SERVICE_TYPE_CRYPTO_SYM)); if (SAL_RESP_EPOLL_CFG_FILE != crypto_handle->isPolled) { return CPA_STATUS_UNSUPPORTED; } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_ctrl_services.c000066400000000000000000002036401503624047500310240ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_ctrl_services.c * * @ingroup SalCtrl * * @description * This file contains the core of the service controller implementation. * *****************************************************************************/ /* QAT-API includes */ #include "cpa.h" #include "cpa_cy_key.h" #include "cpa_cy_ln.h" #include "cpa_cy_dh.h" #include "cpa_cy_dsa.h" #include "cpa_cy_rsa.h" #include "cpa_cy_ec.h" #include "cpa_cy_prime.h" #include "cpa_cy_sym.h" #include "cpa_dc.h" /* Osal includes */ #include "Osal.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_accel_devices.h" #include "icp_adf_cfg.h" #include "icp_adf_init.h" #include "icp_adf_accel_mgr.h" #include "icp_adf_debug.h" /* SAL includes */ #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_sw_responses.h" #include "lac_list.h" #include "lac_hooks.h" #include "sal_string_parse.h" #include "lac_sym.h" #include "lac_sym_key.h" #include "lac_common.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_qat.h" #include "lac_sal_types.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "icp_sal_versions.h" #include "sal_misc_error_stats.h" #include "icp_qat_fw_comp.h" #define SAL_USER_SPACE_START_TIMEOUT_MS 120000 #define MAX_SUBSYSTEM_RETRY 64 #define ASYM_SERVICE "asym" #define SYM_SERVICE "sym" #define CY_SERVICE "cy" #define DECOMP_SERVICE "decomp" #define DC_SERVICE "dc" #define INLINE_SERVICE "inline" static char *subsystem_name = "SAL"; /**< Name used by ADF to identify this component. */ #ifndef ICP_DC_ONLY static char *cy_dir_name = CY_SERVICE; static char *asym_dir_name = ASYM_SERVICE; static char *sym_dir_name = SYM_SERVICE; #endif static char *dc_dir_name = DC_SERVICE; static char *decomp_dir_name = DECOMP_SERVICE; /**< Stats dir names. */ static char *ver_file_name = "version"; static subservice_registation_handle_t sal_service_reg_handle; static inline const char *get_sku_info(enum dev_sku_info info) { switch (info) { case DEV_SKU_1: return "SKU1"; case DEV_SKU_2: return "SKU2"; case DEV_SKU_3: return "SKU3"; case DEV_SKU_4: return "SKU4"; case DEV_SKU_VF: return "SKUVF"; case DEV_SKU_UNKNOWN: default: break; } return "Unknown SKU"; } /**< Data structure used by ADF to keep a reference to this component. */ /* * @ingroup SalCtrl * @description * This function is used to parse the results from ADF * in response to ServiceEnabled query.The results are * semi-colon separated. Internally, the bitmask represented * by the enabled_service is used to track which features are enabled. * * @context * This functions is called from the SalCtrl_ServiceEventInit function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device pointer to icp_accel_dev_t structure * @param[in] pEnabledServices pointer to memory where enabled services will * be written. * @retval Status */ CpaStatus SalCtrl_GetEnabledServices(icp_accel_dev_t *device, Cpa32U *pEnabledServices) { CpaStatus status = CPA_STATUS_SUCCESS; char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; char *token = NULL; char *running = NULL; *pEnabledServices = 0; osalMemSet(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, "ServicesEnabled", param_value); if (CPA_STATUS_SUCCESS == status) { running = param_value; token = strsep(&running, ";"); while (NULL != token) { do { #ifndef ICP_DC_ONLY if (strncmp(token, ASYM_SERVICE, strlen(ASYM_SERVICE)) == 0) { *pEnabledServices |= SAL_SERVICE_TYPE_CRYPTO_ASYM; break; } if (strncmp(token, SYM_SERVICE, strlen(SYM_SERVICE)) == 0) { *pEnabledServices |= SAL_SERVICE_TYPE_CRYPTO_SYM; break; } if (strncmp(token, CY_SERVICE, strlen(CY_SERVICE)) == 0) { *pEnabledServices |= SAL_SERVICE_TYPE_CRYPTO; break; } #endif if (strncmp(token, DECOMP_SERVICE, strlen(DECOMP_SERVICE)) == 0) { *pEnabledServices |= SAL_SERVICE_TYPE_DECOMPRESSION; break; } if (strncmp(token, DC_SERVICE, strlen(DC_SERVICE)) == 0) { *pEnabledServices |= SAL_SERVICE_TYPE_COMPRESSION; break; } if (strncmp(token, INLINE_SERVICE, strlen(INLINE_SERVICE)) == 0) { *pEnabledServices |= SAL_SERVICE_TYPE_INLINE; break; } LAC_LOG_ERROR("Error parsing enabled services from ADF\n"); return CPA_STATUS_FAIL; } while (0); token = strsep(&running, ";"); } } else { LAC_LOG_ERROR("Failed to get enabled services from ADF"); } return status; } /* * @ingroup SalCtrl * @description * This function is used to check whether a service is enabled * * @context * This functions is called from the SalCtrl_ServiceEventInit function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * param[in] enabled_services It is the bitmask for the enabled services * param[in] service It is the service we want to check for */ CpaBoolean SalCtrl_IsServiceEnabled(Cpa32U enabled_services, sal_service_type_t service) { return (CpaBoolean)((enabled_services & (Cpa32U)(service)) != 0); } /* * @ingroup SalCtrl * @description * This function is used to check whether enabled services has associated * hardware capability support * * @context * This functions is called from the SalCtrl_ServiceEventInit function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * param[in] device A pointer to an icp_accel_dev_t * param[in] enabled_services It is the bitmask for the enabled services */ CpaStatus SalCtrl_GetSupportedServices(icp_accel_dev_t *device, Cpa32U enabled_services) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U capabilitiesMask = 0; status = icp_adf_getAccelDevCapabilities(device, &capabilitiesMask); if (CPA_STATUS_SUCCESS == status) { #ifndef ICP_DC_ONLY if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) || !(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { LAC_LOG_ERROR("Device does not support Crypto service"); status = CPA_STATUS_FAIL; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { LAC_LOG_ERROR("Device does not support Asym service"); status = CPA_STATUS_FAIL; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) { LAC_LOG_ERROR("Device does not support Sym service"); status = CPA_STATUS_FAIL; } } #endif if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION)) { LAC_LOG_ERROR("Device does not support Compression service"); status = CPA_STATUS_FAIL; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { if (!(device->services & SERV_TYPE_DECOMP)) { LAC_LOG_ERROR("Device does not support DeComp only service"); status = CPA_STATUS_FAIL; } } } return status; } /************************************************************************* * @ingroup SalCtrl * @description * This function is used to check if a service is supported * on the device. The key difference between this and * SalCtrl_GetSupportedServices() is that the latter treats it as * an error if the service is unsupported. * * @context * This can be called anywhere. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * param[in] device * param[in] service service or services to check * *************************************************************************/ CpaBoolean SalCtrl_IsServiceSupported(icp_accel_dev_t *device, sal_service_type_t service_to_check) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U capabilitiesMask = 0; CpaBoolean service_supported = CPA_TRUE; if (!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_CRYPTO)) && !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_CRYPTO_ASYM)) && !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_CRYPTO_SYM)) && !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_COMPRESSION)) && !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_DECOMPRESSION))) { LAC_LOG_ERROR("Invalid service type"); service_supported = CPA_FALSE; } status = icp_adf_getAccelDevCapabilities(device, &capabilitiesMask); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Can't get device capabilities so default"); return CPA_FALSE; } #ifndef ICP_DC_ONLY if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_CRYPTO)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) || !(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { LAC_LOG_DEBUG("Device does not support Crypto service"); service_supported = CPA_FALSE; } } if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { LAC_LOG_DEBUG("Device does not support Asym service"); service_supported = CPA_FALSE; } } if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_CRYPTO_SYM)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) { LAC_LOG_DEBUG("Device does not support Sym service"); service_supported = CPA_FALSE; } } #endif if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_COMPRESSION)) { if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION)) { LAC_LOG_DEBUG("Device does not support Compression service"); service_supported = CPA_FALSE; } } if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, SAL_SERVICE_TYPE_DECOMPRESSION)) { if (!(device->services & SERV_TYPE_DECOMP)) { LAC_LOG_DEBUG("Device does not support Decompression service"); service_supported = CPA_FALSE; } } return service_supported; } /* * @ingroup SalCtrl * @description * This function is used to retrieve how many instances are * to be configured for process specific service. * * @context * This functions is called from the SalCtrl_ServiceEventInit function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device A pointer to an icp_accel_dev_t * @param[in] key Represents the parameter's name we want to query * @param[out] pCount Pointer to memory where num instances will be stored * @retval status returned status from ADF or _FAIL if number of instances * is out of range for the device. */ STATIC CpaStatus SalCtrl_GetInstanceCount(icp_accel_dev_t *device, char *key, Cpa32U *pCount) { CpaStatus status = CPA_STATUS_FAIL; char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; osalMemSet(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); status = icp_adf_cfgGetParamValue(device, icpGetProcessName(), key, param_value); if (CPA_STATUS_SUCCESS == status) { *pCount = (Cpa32U)(Sal_Strtoul(param_value, NULL, SAL_CFG_BASE_DEC)); if (*pCount > SAL_MAX_NUM_INSTANCES_PER_DEV) { LAC_LOG_ERROR("num instances out of range"); status = CPA_STATUS_FAIL; } } return status; } /************************************************************************** * @ingroup SalCtrl * @description * This function calls the shutdown function on all the * service instances. * It also frees all service instance memory allocated at Init. * * @context * This function is called from the SalCtrl_ServiceEventShutdown * function. * * @assumptions * params[in] should not be NULL * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] services A pointer to the container of services * @param[in] dbg_dir A pointer to the debug directory * @param[in] svc_type The type of the service instance * ****************************************************************************/ STATIC CpaStatus SalCtrl_ServiceShutdown(icp_accel_dev_t *device, sal_list_t **services, debug_dir_info_t **debug_dir, sal_service_type_t svc_type) { CpaStatus status = CPA_STATUS_SUCCESS; sal_service_t *inst = (sal_service_t *)SalList_getObject(*services); #ifndef KERNEL_SPACE Sal_CleanMiscErrStats(inst); #endif /* Call Shutdown function for each service instance */ SAL_FOR_EACH(*services, sal_service_t, device, shutdown, status); if (*debug_dir) { LAC_OS_FREE(*debug_dir); *debug_dir = NULL; } /* Free Sal services controller memory */ SalList_free(services); return status; } /************************************************************************* * @ingroup SalCtrl * @description * This function is used to initialise the service instances. * It allocates memory for service instances and invokes the * Init function on them. * * @context * This function is called from the SalCtrl_ServiceEventInit function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] services A pointer to the container of services * @param[in] dbg_dir A pointer to the debug directory * @param[in] dbg_dir_name Name of the debug directory * @param[in] tail_list SAL's list of services * @param[in] instance_count Number of instances * @param[in] svc_type The type of the service instance * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceInit(icp_accel_dev_t *device, sal_list_t **services, debug_dir_info_t **dbg_dir, char *dbg_dir_name, sal_list_t *tail_list, Cpa32U instance_count, sal_service_type_t svc_type) { CpaStatus status = CPA_STATUS_SUCCESS; sal_service_t *pInst = NULL; Cpa32U i = 0; debug_dir_info_t *debug_dir = NULL; #ifndef KERNEL_SPACE sal_statistics_collection_t *pStats = (sal_statistics_collection_t *)device->pQatStats; #endif status = LAC_OS_MALLOC(&debug_dir, sizeof(debug_dir_info_t)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to allocate memory for debug dir"); return status; } debug_dir->name = dbg_dir_name; debug_dir->parent = NULL; for (i = 0; i < instance_count; i++) { status = SalCtrl_ServiceCreate(svc_type, i, &pInst); if (CPA_STATUS_SUCCESS != status) { break; } pInst->debug_parent_dir = debug_dir; pInst->capabilitiesMask = device->accelCapabilitiesMask; pInst->isGen4 = IS_QAT_GEN4(device->deviceType); pInst->isGen4_2 = IS_QAT_GEN4_2(device->deviceType); pInst->ns_isCnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX; if (pInst->isGen4) { pInst->optimisedCurveSupport = CPA_TRUE; } status = SalList_add(services, &tail_list, pInst); if (CPA_STATUS_SUCCESS != status) { osalMemFree(pInst); break; } } if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to allocate all instances"); LAC_OS_FREE(debug_dir); debug_dir = NULL; SalList_free(services); return status; } #ifndef KERNEL_SPACE status = Sal_InitMiscErrStats(pStats); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to Initialize Misc Error Stats"); LAC_OS_FREE(debug_dir); SalList_free(services); return status; } #endif /* Call init function for each service instance */ SAL_FOR_EACH(*services, sal_service_t, device, init, status); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to initialise all service instances"); /* shutdown all instances initialised before error */ SAL_FOR_EACH_STATE(*services, sal_service_t, device, shutdown, SAL_SERVICE_STATE_INITIALIZED); LAC_OS_FREE(debug_dir); debug_dir = NULL; #ifndef KERNEL_SPACE Sal_CleanMiscErrStats(pInst); #endif SalList_free(services); return status; } /* initialize the debug directory for relevant service */ *dbg_dir = debug_dir; return status; } /************************************************************************** * @ingroup SalCtrl * @description * This function calls the start function on all the service instances. * * @context * This function is called from the SalCtrl_ServiceEventStart function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] services A pointer to the container of services * **************************************************************************/ STATIC CpaStatus SalCtrl_ServiceStart(icp_accel_dev_t *device, sal_list_t *services) { CpaStatus status = CPA_STATUS_SUCCESS; /* Call Start function for each service instance */ SAL_FOR_EACH(services, sal_service_t, device, start, status); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to start all instances"); /* stop all instances started before error */ SAL_FOR_EACH_STATE( services, sal_service_t, device, stop, SAL_SERVICE_STATE_RUNNING); return status; } return status; } /**************************************************************************** * @ingroup SalCtrl * @description * This function calls the stop function on all the * service instances. * * @context * This function is called from the SalCtrl_ServiceEventStop function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] services A pointer to the container of services * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceStop(icp_accel_dev_t *device, sal_list_t *services) { CpaStatus status = CPA_STATUS_SUCCESS; /* Call Stop function for each service instance */ SAL_FOR_EACH(services, sal_service_t, device, stop, status); return status; } /**************************************************************************** * @ingroup SalCtrl * @description * This function calls the error handling function on all the * service instances. * * @context * This function is called from the SalCtrl_ServiceEventError function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] services A pointer to the container of services * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceError(icp_accel_dev_t *device, sal_list_t *services) { CpaStatus status = CPA_STATUS_SUCCESS; sal_list_t *curr_element = services; sal_service_t *service = NULL; /* Call error function for each service instance */ SAL_FOR_EACH(services, sal_service_t, device, error, status); if (!icp_adf_isDevInError(device)) { while (NULL != curr_element) { service = (sal_service_t *)SalList_getObject(curr_element); if (service->notification_cb) { service->notification_cb( service, service->cb_tag, CPA_INSTANCE_EVENT_FATAL_ERROR); } curr_element = SalList_next(curr_element); } } return status; } /**************************************************************************** * @ingroup SalCtrl * @description * This function calls the restarting event handling function on all * the service instances. * * @context * This function is called from the SalCtrl_ServiceEventRestarting * function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] device An icp_accel_dev_t* type * @param[in] services A pointer to the container of services * @param[in] dbg_dir A pointer to the debug directory * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceRestarting(icp_accel_dev_t *device, sal_list_t *services, debug_dir_info_t **debug_dir) { CpaStatus status = CPA_STATUS_SUCCESS; sal_list_t *curr_element = services; sal_service_t *service = NULL; if (*debug_dir) { LAC_OS_FREE(*debug_dir); *debug_dir = NULL; } while (NULL != curr_element) { service = (sal_service_t *)SalList_getObject(curr_element); if (service->notification_cb) { service->notification_cb( service, service->cb_tag, CPA_INSTANCE_EVENT_RESTARTING); } curr_element = SalList_next(curr_element); } /* Call restarting function for each service instance */ SAL_FOR_EACH(services, sal_service_t, device, restarting, status); return status; } /**************************************************************************** * @ingroup SalCtrl * @description * This function calls the restarted handling function on all the * service instances. * * @context * This function is called from the SalCtrl_ServiceEventRestarted function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] device An icp_accel_dev_t* type * @param[in] services A pointer to the container of services * @param[in] dbg_dir A pointer to the debug directory * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceRestarted(icp_accel_dev_t *device, sal_list_t **services, debug_dir_info_t **dbg_dir, char *dbg_dir_name, sal_list_t *tail_list, Cpa32U instance_count, sal_service_type_t svc_type) { CpaStatus status = CPA_STATUS_SUCCESS; debug_dir_info_t *debug_dir = NULL; sal_list_t *curr_element = *services; sal_service_t *service = NULL; status = LAC_OS_MALLOC(&debug_dir, sizeof(debug_dir_info_t)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to allocate memory for debug dir"); return status; } debug_dir->name = dbg_dir_name; debug_dir->parent = NULL; while (NULL != curr_element) { service = (sal_service_t *)SalList_getObject(curr_element); service->debug_parent_dir = debug_dir; if (CPA_TRUE == service->isInstanceStarted) { icp_adf_qaDevGet(device); } curr_element = SalList_next(curr_element); } /* Call restarted function for each service instance */ SAL_FOR_EACH(*services, sal_service_t, device, restarted, status); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to restart all service instances"); return status; } curr_element = *services; while (NULL != curr_element) { service = (sal_service_t *)SalList_getObject(curr_element); if (service->notification_cb) { service->notification_cb( service, service->cb_tag, CPA_INSTANCE_EVENT_RESTARTED); } curr_element = SalList_next(curr_element); } /* initialize the debug directory for relevant service */ *dbg_dir = debug_dir; return status; } /* * @ingroup SalCtrl * @description * This function is used to print hardware and software versions in proc * filesystem entry via ADF Debug interface * * @context * This functions is called from proc filesystem interface * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] private_data A pointer to a private data passed to the * function while adding a debug file. * @param[out] data Pointer to a buffer where version information * needs to be printed to. * @param[in] size Size of a buffer pointed by data. * @param[in] offset Offset in a debug file * * @retval 0 This function always returns 0 */ STATIC int SalCtrl_VersionDebug(void *private_data, char *data, int size, int offset) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U len = 0; icp_accel_dev_t *device = (icp_accel_dev_t *)private_data; char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; len += snprintf(data + len, size - len, SEPARATOR BORDER " Hardware and Software versions for device %d " BORDER "\n" SEPARATOR, device->accelId); osalMemSet(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_HW_REV_ID_KEY, param_value); LAC_CHECK_STATUS(status); len += snprintf(data + len, size - len, " Hardware Version: %s %s \n", param_value, get_sku_info(device->sku)); osalMemSet(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_UOF_VER_KEY, param_value); LAC_CHECK_STATUS(status); len += snprintf(data + len, size - len, " Firmware Version: %s \n", param_value); #ifndef ICP_DC_ONLY osalMemSet(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_MMP_VER_KEY, param_value); LAC_CHECK_STATUS(status); len += snprintf(data + len, size - len, " MMP Version: %s \n", param_value); #endif len += snprintf(data + len, size - len, " Driver Version: %d.%d.%d \n", SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER); osalMemSet(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); status = icp_adf_cfgGetParamValue(device, LAC_CFG_SECTION_GENERAL, ICP_CFG_LO_COMPATIBLE_DRV_KEY, param_value); LAC_CHECK_STATUS(status); len += snprintf(data + len, size - len, " Lowest Compatible Driver: %s \n", param_value); len += snprintf(data + len, size - len, " QuickAssist API CY Version: %d.%d \n", CPA_CY_API_VERSION_NUM_MAJOR, CPA_CY_API_VERSION_NUM_MINOR); len += snprintf(data + len, size - len, " QuickAssist API DC Version: %d.%d \n", CPA_DC_API_VERSION_NUM_MAJOR, CPA_DC_API_VERSION_NUM_MINOR); snprintf(data + len, size - len, SEPARATOR); return 0; } /************************************************************************** * @ingroup SalCtrl * @description * This function calls the shutdown function on all the service * instances. It also frees all service instance memory * allocated at Init. * * @context * This function is called from the SalCtrl_ServiceEventHandler function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] enabled_services Services enabled by user * ****************************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventShutdown(icp_accel_dev_t *device, Cpa32U enabled_services) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus ret_status = CPA_STATUS_SUCCESS; sal_t *service_container = (sal_t *)device->pSalHandle; if (NULL == service_container) { LAC_LOG_ERROR("Private data is NULL"); return CPA_STATUS_FATAL; } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = SalCtrl_ServiceShutdown(device, &service_container->crypto_services, &service_container->cy_dir, SAL_SERVICE_TYPE_CRYPTO); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = SalCtrl_ServiceShutdown(device, &service_container->asym_services, &service_container->asym_dir, SAL_SERVICE_TYPE_CRYPTO_ASYM); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { status = SalCtrl_ServiceShutdown(device, &service_container->sym_services, &service_container->sym_dir, SAL_SERVICE_TYPE_CRYPTO_SYM); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_ServiceShutdown(device, &service_container->compression_services, &service_container->dc_dir, SAL_SERVICE_TYPE_COMPRESSION); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_ServiceShutdown(device, &service_container->decompression_services, &service_container->decomp_dir, SAL_SERVICE_TYPE_DECOMPRESSION); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } /* This condition is only met for aysm;asym;dc or asym;asym;decomp configurations. * In such cases, service_container->crypto_services may be initialized if * the function Lac_GetCyNumInstancesByType is invoked with CPA_ACC_SVC_TYPE_CRYPTO * as the first parameter. * To ensure all allocated structures are properly cleaned up, the SalList_free * operation should be executed for crypto_services during the Service Shutdown phase. */ if (SalCtrl_IsServiceEnabled(enabled_services,SAL_SERVICE_TYPE_CRYPTO_SYM) && SalCtrl_IsServiceEnabled(enabled_services,SAL_SERVICE_TYPE_CRYPTO_ASYM) && !SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { SalList_free(&service_container->crypto_services); } if (service_container->ver_file) { LAC_OS_FREE(service_container->ver_file); service_container->ver_file = NULL; } /* Free container also */ osalMemFree(service_container); device->pSalHandle = NULL; return ret_status; } /************************************************************************* * @ingroup SalCtrl * @description * This function is used to initialize the service instances. * It first checks (via ADF query) which services are enabled in the * system and the number of each services. * It then invokes the init function on them which creates the * instances and allocates memory for them. * * @context * This function is called from the SalCtrl_ServiceEventHandler function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] enabled_services Services enabled by user * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventInit(icp_accel_dev_t *device, Cpa32U enabled_services) { sal_t *service_container = NULL; CpaStatus status = CPA_STATUS_SUCCESS; sal_list_t *tail_list = NULL; Cpa32U instance_count = 0; status = SalCtrl_GetSupportedServices(device, enabled_services); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to get supported services"); return status; } service_container = osalMemAlloc(sizeof(sal_t)); if (NULL == service_container) { LAC_LOG_ERROR("Failed to allocate service memory"); return CPA_STATUS_RESOURCE; } device->pSalHandle = service_container; service_container->asym_services = NULL; service_container->sym_services = NULL; service_container->crypto_services = NULL; service_container->compression_services = NULL; service_container->decompression_services = NULL; service_container->asym_dir = NULL; service_container->sym_dir = NULL; service_container->cy_dir = NULL; service_container->dc_dir = NULL; service_container->decomp_dir = NULL; service_container->ver_file = NULL; status = LAC_OS_MALLOC(&service_container->ver_file, sizeof(debug_file_info_t)); if (CPA_STATUS_SUCCESS != status) { osalMemFree(service_container); return status; } osalMemSet(service_container->ver_file, 0, sizeof(debug_file_info_t)); service_container->ver_file->name = ver_file_name; service_container->ver_file->seq_read = SalCtrl_VersionDebug; service_container->ver_file->private_data = device; service_container->ver_file->parent = NULL; #ifndef ICP_DC_ONLY if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = SalCtrl_GetInstanceCount( device, "NumberAsymInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceInit(device, &service_container->asym_services, &service_container->asym_dir, asym_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_CRYPTO_ASYM); if (CPA_STATUS_SUCCESS != status) { goto err_init; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { status = SalCtrl_GetInstanceCount( device, "NumberSymInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceInit(device, &service_container->sym_services, &service_container->sym_dir, sym_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_CRYPTO_SYM); if (CPA_STATUS_SUCCESS != status) { goto err_init; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = SalCtrl_GetInstanceCount( device, "NumberCyInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceInit(device, &service_container->crypto_services, &service_container->cy_dir, cy_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_CRYPTO); if (CPA_STATUS_SUCCESS != status) { goto err_init; } } #endif if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_GetInstanceCount( device, "NumberDcInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceInit(device, &service_container->compression_services, &service_container->dc_dir, dc_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_COMPRESSION); if (CPA_STATUS_SUCCESS != status) { goto err_init; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_GetInstanceCount( device, "NumberDecompInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceInit(device, &service_container->decompression_services, &service_container->decomp_dir, decomp_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_DECOMPRESSION); if (CPA_STATUS_SUCCESS != status) { goto err_init; } } return status; err_init: SalCtrl_ServiceEventShutdown(device, enabled_services); return status; } /**************************************************************************** * @ingroup SalCtrl * @description * This function calls the stop function on all the service instances. * * @context * This function is called from the SalCtrl_ServiceEventHandler function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] enabled_services Enabled services by user * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventStop(icp_accel_dev_t *device, Cpa32U enabled_services) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus ret_status = CPA_STATUS_SUCCESS; sal_t *service_container = device->pSalHandle; if (service_container == NULL) { LAC_LOG_ERROR("Private data is NULL"); return CPA_STATUS_FATAL; } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = SalCtrl_ServiceStop(device, service_container->asym_services); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { status = SalCtrl_ServiceStop(device, service_container->sym_services); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = SalCtrl_ServiceStop(device, service_container->crypto_services); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_ServiceStop(device, service_container->compression_services); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_ServiceStop(device, service_container->decompression_services); if (CPA_STATUS_SUCCESS != status) { ret_status = status; } } return ret_status; } /************************************************************************** * @ingroup SalCtrl * @description * This function calls the start function on all the service instances. * * @context * This function is called from the SalCtrl_ServiceEventHandler function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] enabled_services Enabled services by user * **************************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventStart(icp_accel_dev_t *device, Cpa32U enabled_services) { CpaStatus status = CPA_STATUS_SUCCESS; sal_t *service_container = device->pSalHandle; if (service_container == NULL) { LAC_LOG_ERROR("Private data is NULL"); return CPA_STATUS_FATAL; } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = SalCtrl_ServiceStart(device, service_container->asym_services); if (CPA_STATUS_SUCCESS != status) { goto err_start; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { status = SalCtrl_ServiceStart(device, service_container->sym_services); if (CPA_STATUS_SUCCESS != status) { goto err_start; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = SalCtrl_ServiceStart(device, service_container->crypto_services); if (CPA_STATUS_SUCCESS != status) { goto err_start; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_ServiceStart(device, service_container->compression_services); if (CPA_STATUS_SUCCESS != status) { goto err_start; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_ServiceStart( device, service_container->decompression_services); if (CPA_STATUS_SUCCESS != status) { goto err_start; } } return status; err_start: SalCtrl_ServiceEventStop(device, enabled_services); return status; } /************************************************************************* * @ingroup SalCtrl * @description * This function calls the error function on all the service instances * * @context * This function is called from the SalCtrl_ServiceEventHandler function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] enabled_services Services enabled by user * *************************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventError(icp_accel_dev_t *device, Cpa32U enabled_services) { CpaStatus status = CPA_STATUS_SUCCESS; sal_t *service_container = device->pSalHandle; if (service_container == NULL) { LAC_LOG_ERROR("Private data is NULL"); return CPA_STATUS_FATAL; } LacSwResp_InitNumPoolsBusy(); if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = SalCtrl_ServiceError(device, service_container->asym_services); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { status = SalCtrl_ServiceError(device, service_container->sym_services); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = SalCtrl_ServiceError(device, service_container->crypto_services); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_ServiceError(device, service_container->compression_services); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_ServiceError( device, service_container->decompression_services); if (CPA_STATUS_SUCCESS != status) { return status; } } if (0 != LacSwResp_GetNumPoolsBusy()) { status = CPA_STATUS_RETRY; } return status; } /************************************************************************** * @ingroup SalCtrl * @description * This function calls the restarting function on all the service * instances. It cleans some service instance resources. * * @context * This function is called from the SalCtrl_ServiceEventHandler function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] device An icp_accel_dev_t* type * @param[in] enabled_services Services enabled by user * ****************************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventRestarting(icp_accel_dev_t *device, Cpa32U enabled_services) { CpaStatus status = CPA_STATUS_SUCCESS; sal_t *service_container = device->pSalHandle; if (service_container == NULL) { LAC_LOG_ERROR("Private data is NULL"); return CPA_STATUS_FATAL; } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = SalCtrl_ServiceRestarting(device, service_container->asym_services, &service_container->asym_dir); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { status = SalCtrl_ServiceRestarting(device, service_container->sym_services, &service_container->sym_dir); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = SalCtrl_ServiceRestarting(device, service_container->crypto_services, &service_container->cy_dir); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_ServiceRestarting(device, service_container->compression_services, &service_container->dc_dir); if (CPA_STATUS_SUCCESS != status) { return status; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_ServiceRestarting(device, service_container->decompression_services, &service_container->decomp_dir); if (CPA_STATUS_SUCCESS != status) { return status; } } if (service_container->ver_file) { LAC_OS_FREE(service_container->ver_file); service_container->ver_file = NULL; } return status; } /************************************************************************** * @ingroup SalCtrl * @description * This function calls the restarted function on all the service * instances. It reinitializes the instance resources. * * @context * This function is called from the SalCtrl_ServiceEventHandler function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * @param[in] device An icp_accel_dev_t* type * @param[in] enabled_services Services enabled by user * ****************************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventRestarted(icp_accel_dev_t *device, Cpa32U enabled_services) { sal_t *service_container = NULL; CpaStatus status = CPA_STATUS_SUCCESS; sal_list_t *tail_list = NULL; Cpa32U instance_count = 0; status = SalCtrl_GetSupportedServices(device, enabled_services); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to get supported services"); return status; } service_container = device->pSalHandle; service_container->asym_dir = NULL; service_container->sym_dir = NULL; service_container->cy_dir = NULL; service_container->dc_dir = NULL; service_container->decomp_dir = NULL; service_container->ver_file = NULL; status = LAC_OS_MALLOC(&service_container->ver_file, sizeof(debug_file_info_t)); if (CPA_STATUS_SUCCESS != status) { goto err_restarted; } osalMemSet(service_container->ver_file, 0, sizeof(debug_file_info_t)); service_container->ver_file->name = ver_file_name; service_container->ver_file->seq_read = SalCtrl_VersionDebug; service_container->ver_file->private_data = device; service_container->ver_file->parent = NULL; #ifndef ICP_DC_ONLY if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM)) { status = SalCtrl_GetInstanceCount( device, "NumberAsymInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceRestarted(device, &service_container->asym_services, &service_container->asym_dir, asym_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_CRYPTO_ASYM); if (CPA_STATUS_SUCCESS != status) { goto err_restarted; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM)) { status = SalCtrl_GetInstanceCount( device, "NumberSymInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceRestarted(device, &service_container->sym_services, &service_container->sym_dir, sym_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_CRYPTO_SYM); if (CPA_STATUS_SUCCESS != status) { goto err_restarted; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { status = SalCtrl_GetInstanceCount( device, "NumberCyInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceRestarted(device, &service_container->crypto_services, &service_container->cy_dir, cy_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_CRYPTO); if (CPA_STATUS_SUCCESS != status) { goto err_restarted; } } #endif if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION)) { status = SalCtrl_GetInstanceCount( device, "NumberDcInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceRestarted(device, &service_container->compression_services, &service_container->dc_dir, dc_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_COMPRESSION); if (CPA_STATUS_SUCCESS != status) { goto err_restarted; } } if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { status = SalCtrl_GetInstanceCount( device, "NumberDecompInstances", &instance_count); if (CPA_STATUS_SUCCESS != status) { instance_count = 0; } status = SalCtrl_ServiceRestarted(device, &service_container->decompression_services, &service_container->decomp_dir, decomp_dir_name, tail_list, instance_count, SAL_SERVICE_TYPE_DECOMPRESSION); if (CPA_STATUS_SUCCESS != status) { goto err_restarted; } } return status; err_restarted: SalCtrl_ServiceEventStop(device, enabled_services); SalCtrl_ServiceEventShutdown(device, enabled_services); return status; } /************************************************************************* * @ingroup SalCtrl * @description * This function is the events handler registered with ADF * for the QA API services (cy, dc) - kernel and user * * @context * This function is called from an ADF context. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] device An icp_accel_dev_t* type * @param[in] event Event from ADF * @param[in] param Parameter used for back compatibility * ***********************************************************************/ STATIC CpaStatus SalCtrl_ServiceEventHandler(icp_accel_dev_t *device, enum adf_event event, void *param) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus stats_status = CPA_STATUS_SUCCESS; Cpa32U enabled_services = 0; status = SalCtrl_GetEnabledServices(device, &enabled_services); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to get enabled services"); return status; } switch (event) { case ADF_EVENT_INIT: { /* In case there is no QAT SAL needs to call InitStats */ if (NULL == device->pQatStats) { status = SalStatistics_InitStatisticsCollection(device); } if (CPA_STATUS_SUCCESS != status) { return status; } status = SalCtrl_ServiceEventInit(device, enabled_services); break; } case ADF_EVENT_START: { status = SalCtrl_ServiceEventStart(device, enabled_services); break; } case ADF_EVENT_STOP: { status = SalCtrl_ServiceEventStop(device, enabled_services); break; } case ADF_EVENT_SHUTDOWN: { status = SalCtrl_ServiceEventShutdown(device, enabled_services); stats_status = SalStatistics_CleanStatisticsCollection(device); if (CPA_STATUS_SUCCESS != status || CPA_STATUS_SUCCESS != stats_status) { return CPA_STATUS_FAIL; } break; } case ADF_EVENT_ERROR: { status = SalCtrl_ServiceEventError(device, enabled_services); break; } case ADF_EVENT_RESTARTING: { status = SalCtrl_ServiceEventRestarting(device, enabled_services); break; } case ADF_EVENT_RESTARTED: { status = SalCtrl_ServiceEventRestarted(device, enabled_services); break; } default: status = CPA_STATUS_SUCCESS; break; } return status; } CpaStatus SalCtrl_AdfServicesRegister(void) { /* Fill out the global sal_service_reg_handle structure */ sal_service_reg_handle.subserviceEventHandler = SalCtrl_ServiceEventHandler; /* Set subsystem name to globally defined name */ sal_service_reg_handle.subsystem_name = subsystem_name; return icp_adf_subsystemRegister(&sal_service_reg_handle); } CpaStatus SalCtrl_AdfServicesUnregister(void) { return icp_adf_subsystemUnregister(&sal_service_reg_handle); } CpaStatus SalCtrl_AdfServicesStartedCheck(void) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U retry_num = 0; CpaBoolean state = CPA_FALSE; do { state = icp_adf_isSubsystemStarted(&sal_service_reg_handle); retry_num++; } while ((CPA_FALSE == state) && (retry_num < MAX_SUBSYSTEM_RETRY)); if (CPA_FALSE == state) { LAC_LOG_ERROR("Sal Ctrl failed to start in given time\n"); status = CPA_STATUS_FAIL; } return status; } CpaStatus validateConcurrRequest(Cpa32U numConcurrRequests) { Cpa32U baseReq = SAL_64_CONCURR_REQUESTS; if (SAL_64_CONCURR_REQUESTS > numConcurrRequests) { LAC_LOG_ERROR("Invalid numConcurrRequests, " "it is less than min value"); return CPA_STATUS_FAIL; } while (SAL_MAX_CONCURR_REQUESTS >= baseReq) { if (baseReq != numConcurrRequests) { baseReq = baseReq << 1; } else { break; } } if (SAL_MAX_CONCURR_REQUESTS < baseReq) { LAC_LOG_ERROR("Invalid baseReg, it is greater than max value"); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_dc_chain.c000066400000000000000000000245051503624047500277060ustar00rootroot00000000000000 /**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_dc_chain.c * * @ingroup SalCtrl * * @description * This file contains the sal implementation of dc_chain. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "cpa_dc.h" #include "icp_qat_fw.h" #include "icp_qat_fw_comp.h" #include "icp_qat_hw.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "dc_session.h" #include "dc_datapath.h" #include "dc_chain.h" #include "lac_mem_pools.h" #include "sal_types_compression.h" #include "lac_buffer_desc.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "sal_string_parse.h" #include "lac_sym.h" /* * @ingroup Dc_Chaining * Frees resources (memory and transhandles) if allocated * * @param[in] pChainService Pointer to chaining service instance * * @retval none. */ STATIC void dcChainService_FreeResources(sal_dc_chain_service_t *pChainService) { /* 1. Free memory pools if not NULL */ Lac_MemPoolDestroy(pChainService->lac_sym_cookie_pool); pChainService->lac_sym_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID; Lac_MemPoolDestroy(pChainService->dc_chain_cookie_pool); pChainService->dc_chain_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID; Lac_MemPoolDestroy(pChainService->dc_chain_serv_resp_pool); pChainService->dc_chain_serv_resp_pool = LAC_MEM_POOL_INIT_POOL_ID; /* Free hash lookup table if allocated */ if (NULL != pChainService->pLacHashLookupDefs) { LAC_OS_FREE(pChainService->pLacHashLookupDefs); pChainService->pLacHashLookupDefs = NULL; } } /** *********************************************************************** * @ingroup Dc_Chaining * This macro verifies that the status is _SUCCESS * If status is not _SUCCESS then Chaining Instance resources are * freed before the function returns the error * * @param[in] status status we are checking * * ******************************************************************************/ #define LAC_CHECK_STATUS_DC_CHAIN_INIT(status) \ do \ { \ if (CPA_STATUS_SUCCESS != status) \ { \ dcChainService_FreeResources(pChainService); \ return status; \ } \ } while (0) /** ***************************************************************************** * @ingroup Dc_Chaining * Initialize chaining service * * @description * Initialize chaining service * * @param[in,out] pCompService Compression service * @param[out] pChainService Chaining service * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed to find device * *****************************************************************************/ CpaStatus dcChainServiceInit(sal_compression_service_t *pCompService, sal_dc_chain_service_t *pChainService) { CpaStatus status = CPA_STATUS_SUCCESS; char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; Cpa32U numCompConcurrentReq = 0; Cpa32U rspSize = 0; /* Chaining service is attached to compression service, the number of * concurrent requests is based on compression concurrent requests */ numCompConcurrentReq = pCompService->maxNumCompConcurrentReq + SAL_BATCH_SUBMIT_FREE_SPACE + 1; pCompService->pDcChainService = NULL; pChainService->lac_sym_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID; pChainService->dc_chain_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID; pChainService->dc_chain_serv_resp_pool = LAC_MEM_POOL_INIT_POOL_ID; pChainService->pLacHashLookupDefs = NULL; status = Sal_StringParsing(SAL_CFG_DC, pCompService->generic_service_info.instance, SAL_CFG_SYM_POOL, temp_string); LAC_CHECK_STATUS(status); status = Lac_MemPoolCreate(&pChainService->lac_sym_cookie_pool, temp_string, numCompConcurrentReq, sizeof(lac_sym_bulk_cookie_t), LAC_64BYTE_ALIGNMENT, CPA_FALSE, pCompService->nodeAffinity); LAC_CHECK_STATUS_DC_CHAIN_INIT(status); /* Enable only ICP_QAT_HW_AUTH_MODE1 mode for hash operation */ pChainService->qatHmacMode = ICP_QAT_HW_AUTH_MODE1; status = Sal_StringParsing(SAL_CFG_DC, pCompService->generic_service_info.instance, SAL_CFG_CHAIN_COOKIE_POOL, temp_string); LAC_CHECK_STATUS_DC_CHAIN_INIT(status); status = Lac_MemPoolCreate(&pChainService->dc_chain_cookie_pool, temp_string, numCompConcurrentReq, sizeof(dc_chain_cookie_t), LAC_64BYTE_ALIGNMENT, CPA_FALSE, pCompService->nodeAffinity); LAC_CHECK_STATUS_DC_CHAIN_INIT(status); rspSize = LAC_QAT_DC_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; status = Sal_StringParsing(SAL_CFG_DC, pCompService->generic_service_info.instance, SAL_CFG_CHAIN_DESC_POOL, temp_string); LAC_CHECK_STATUS_DC_CHAIN_INIT(status); status = Lac_MemPoolCreate(&pChainService->dc_chain_serv_resp_pool, temp_string, numCompConcurrentReq * DC_CHAIN_MAX_LINK, rspSize, LAC_64BYTE_ALIGNMENT, CPA_FALSE, pCompService->nodeAffinity); LAC_CHECK_STATUS_DC_CHAIN_INIT(status); pCompService->pDcChainService = pChainService; status = LacSymQat_HashLookupInit(pCompService); LAC_CHECK_STATUS_DC_CHAIN_INIT(status); return status; } /** ***************************************************************************** * @ingroup Dc_Chaining * Shutdown chaining service * * @description * Shutdown chaining service * * @param[in,out] pCompService Compression service * @param[in] pChainService Chaining service * * @retval none * *****************************************************************************/ void dcChainServiceShutdown(sal_compression_service_t *pCompService, sal_dc_chain_service_t *pChainService) { /* Free resources allocated for chaining */ /* pChainService will be freed in SalCtrl_CompressionShutdown */ dcChainService_FreeResources(pChainService); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_instances.c000066400000000000000000000642541503624047500301520ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_instances.c * * @defgroup SalCtrl Service Access Layer Controller * * @ingroup SalCtrl * * @description * This file contains generic functions to get instances of a specified * service type. Note these are complementary to the already existing * service-specific functions. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ /* QAT-API includes */ #include "cpa.h" #ifndef ICP_DC_ONLY #include "cpa_cy_common.h" #include "cpa_cy_im.h" #endif #include "cpa_dc.h" /* Osal includes */ #include "Osal.h" /* ADF includes */ #include "icp_accel_devices.h" #include "icp_adf_accel_mgr.h" /* SAL includes */ #include "lac_mem.h" #include "lac_list.h" #include "lac_sal_types.h" #include "lac_sal_types_crypto.h" #include "sal_instances.h" #ifndef ICP_DC_ONLY STATIC void Lac_ConstructCyServicesfromSymAsym(sal_list_t **sym_services, sal_list_t **asym_services, sal_list_t **crypto_services) { sal_crypto_service_t* asym_item = NULL; sal_crypto_service_t* sym_item = NULL; if (*crypto_services == NULL && *sym_services != NULL && *asym_services != NULL) { asym_item = (sal_crypto_service_t *)osalMemAlloc(sizeof(sal_crypto_service_t)); osalMemCopy(asym_item, SalList_getObject(*asym_services), sizeof(sal_crypto_service_t) ); sym_item = (sal_crypto_service_t*) SalList_getObject(*sym_services); asym_item->generic_service_info.type = SAL_SERVICE_TYPE_CRYPTO; asym_item->pSymDpCb = sym_item->pSymDpCb; asym_item->bankNumSym = sym_item->bankNumSym; asym_item->maxNumSymReqBatch = sym_item->maxNumSymReqBatch; asym_item->trans_handle_sym_rx = sym_item->trans_handle_sym_rx; asym_item->trans_handle_sym_tx = sym_item->trans_handle_sym_tx; asym_item->lac_sym_cookie_pool = sym_item->lac_sym_cookie_pool; asym_item->constantsLookupTables = sym_item->constantsLookupTables; asym_item->capInfo.symSupported = sym_item->capInfo.symSupported; asym_item->capInfo.symDpSupported = sym_item->capInfo.symDpSupported; asym_item->pLacSymStatsArr = sym_item->pLacSymStatsArr; asym_item->pTlsLabel = sym_item->pTlsLabel; asym_item->pSslLabel = sym_item->pSslLabel; asym_item->pTlsHKDFSubLabel = sym_item->pTlsHKDFSubLabel; asym_item->pLacHashLookupDefs = sym_item->pLacHashLookupDefs; SalList_add(crypto_services, crypto_services, asym_item); *asym_services = NULL; *sym_services = NULL; } } /** ****************************************************************************** * @ingroup SalCtrl * @description * Get the total number of either sym, asym or cy instances *****************************************************************************/ CpaStatus Lac_GetCyNumInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *pNumInstances) { CpaStatus status = CPA_STATUS_SUCCESS; icp_accel_dev_t **pAdfInsts = NULL; icp_accel_dev_t *dev_addr = NULL; sal_t *base_addr = NULL; sal_list_t *list_temp = NULL; Cpa16U num_accel_dev = 0; Cpa16U num_inst = 0; Cpa16U i = 0; Cpa32U accel_capability = 0; char *service = NULL; LAC_CHECK_NULL_PARAM(pNumInstances); *pNumInstances = 0; switch (accelerationServiceType) { case CPA_ACC_SVC_TYPE_CRYPTO_ASYM: accel_capability = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; service = "asym"; break; case CPA_ACC_SVC_TYPE_CRYPTO_SYM: accel_capability = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; service = "sym"; break; case CPA_ACC_SVC_TYPE_CRYPTO: accel_capability = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; service = "cy"; break; default: LAC_LOG_ERROR("Invalid service type\n"); return CPA_STATUS_INVALID_PARAM; } /* Get the number of accel_dev in the system */ status = icp_adf_getNumInstances(&num_accel_dev); LAC_CHECK_STATUS(status); /* Allocate memory to store addr of accel_devs */ pAdfInsts = osalMemAlloc(num_accel_dev * sizeof(icp_accel_dev_t *)); if (NULL == pAdfInsts) { LAC_LOG_ERROR("Failed to allocate dev instance memory"); return CPA_STATUS_RESOURCE; } num_accel_dev = 0; status = icp_adf_getAllAccelDevByCapabilities( accel_capability, pAdfInsts, &num_accel_dev); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR_PARAMS("No support for service %s\n", service); osalMemFree(pAdfInsts); return status; } for (i = 0; i < num_accel_dev; i++) { dev_addr = pAdfInsts[i]; if (NULL == dev_addr || NULL == dev_addr->pSalHandle) { continue; } base_addr = dev_addr->pSalHandle; /* Meeting these conditions indicates an imbalance in the number of * instances between SYM and ASYM. Given that we have only 4 ring pairs, * this scenario occurs only for sym;asym;dc and sym;asym;decomp * configurations. * The table below outlines the expected number of instances per * service (for these 2 configurations): * sym | asym | (dc or decomp) | cy * 1 | 2 | 1 | 1 * When CPA_ACC_SVC_TYPE_CRYPTO is requested, the number of CY instances * is always 1 for these 2 configurations. Therefore, we handle this * situation separately and proceed to the next accel_dev. */ if(CPA_ACC_SVC_TYPE_CRYPTO == accelerationServiceType && base_addr->sym_services != NULL && base_addr->asym_services != NULL && base_addr->crypto_services == NULL) { num_inst++; continue; } if (CPA_ACC_SVC_TYPE_CRYPTO == accelerationServiceType) { list_temp = base_addr->crypto_services; while (NULL != list_temp) { num_inst++; list_temp = SalList_next(list_temp); } } if (CPA_ACC_SVC_TYPE_CRYPTO_ASYM == accelerationServiceType || CPA_ACC_SVC_TYPE_CRYPTO == accelerationServiceType) { list_temp = base_addr->asym_services; if ((NULL == list_temp) && (CPA_ACC_SVC_TYPE_CRYPTO != accelerationServiceType)) { list_temp = base_addr->crypto_services; } while (NULL != list_temp) { num_inst++; list_temp = SalList_next(list_temp); } } if (CPA_ACC_SVC_TYPE_CRYPTO_SYM == accelerationServiceType || CPA_ACC_SVC_TYPE_CRYPTO == accelerationServiceType) { list_temp = base_addr->sym_services; if ((NULL == list_temp) && (CPA_ACC_SVC_TYPE_CRYPTO != accelerationServiceType)) { list_temp = base_addr->crypto_services; } while (NULL != list_temp) { num_inst++; list_temp = SalList_next(list_temp); } } } *pNumInstances = num_inst; osalMemFree(pAdfInsts); #ifdef ICP_TRACE if (NULL != pNumInstances) { LAC_LOG2("Called with params (0x%lx[%d])\n", (LAC_ARCH_UINT)pNumInstances, *pNumInstances); } else { LAC_LOG1("Called with params (0x%lx)\n", (LAC_ARCH_UINT)pNumInstances); } #endif return status; } /** ****************************************************************************** * @ingroup SalCtrl * @description * Get either sym, asym or cy instance *****************************************************************************/ CpaStatus Lac_GetCyInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U numInstances, CpaInstanceHandle *pInstances) { CpaStatus status = CPA_STATUS_SUCCESS; icp_accel_dev_t **pAdfInsts = NULL; icp_accel_dev_t *dev_addr = NULL; sal_list_t *sym_services = NULL; sal_list_t *asym_services = NULL; sal_list_t **crypto_services = NULL; sal_list_t *list_temp = NULL; Cpa16U num_accel_dev = 0; Cpa16U num_allocated_instances = 0; Cpa16U index = 0; Cpa16U i = 0; Cpa32U accel_capability = 0; char *service = NULL; #ifdef ICP_TRACE LAC_LOG3("Called with params (%d ,%d, 0x%lx)\n", accelerationServiceType, numInstances, (LAC_ARCH_UINT)pInstances); #endif LAC_CHECK_NULL_PARAM(pInstances); if (0 == numInstances) { LAC_INVALID_PARAM_LOG("NumInstances is 0"); return CPA_STATUS_INVALID_PARAM; } switch (accelerationServiceType) { case CPA_ACC_SVC_TYPE_CRYPTO_ASYM: accel_capability = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; service = "asym"; break; case CPA_ACC_SVC_TYPE_CRYPTO_SYM: accel_capability = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; service = "sym"; break; case CPA_ACC_SVC_TYPE_CRYPTO: accel_capability = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; service = "cy"; break; default: LAC_LOG_ERROR("Invalid service type\n"); return CPA_STATUS_INVALID_PARAM; } /* Get the number of instances */ status = Lac_GetCyNumInstancesByType(accelerationServiceType, &num_allocated_instances); if (CPA_STATUS_SUCCESS != status) { return status; } if (numInstances > num_allocated_instances) { LAC_LOG_ERROR1("Only %d instances available", num_allocated_instances); return CPA_STATUS_RESOURCE; } /* Get the number of accel devices in the system */ status = icp_adf_getNumInstances(&num_accel_dev); LAC_CHECK_STATUS(status); /* Allocate memory to store addr of accel_devs */ pAdfInsts = osalMemAlloc(num_accel_dev * sizeof(icp_accel_dev_t *)); if (NULL == pAdfInsts) { LAC_LOG_ERROR("Failed to allocate dev instance memory"); return CPA_STATUS_RESOURCE; } num_accel_dev = 0; status = icp_adf_getAllAccelDevByCapabilities( accel_capability, pAdfInsts, &num_accel_dev); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR_PARAMS("No support for service %s\n", service); osalMemFree(pAdfInsts); return status; } for (i = 0; i < num_accel_dev; i++) { dev_addr = pAdfInsts[i]; /* Note dev_addr cannot be NULL here as numInstances = 0 * is not valid and if dev_addr = NULL then index = 0 (which * is less than numInstances and status is set to _RESOURCE * above */ if (NULL == dev_addr->pSalHandle) { continue; } sym_services = ((sal_t*)dev_addr->pSalHandle)->sym_services; asym_services = ((sal_t*)dev_addr->pSalHandle)->asym_services; crypto_services = &((sal_t*)dev_addr->pSalHandle)->crypto_services; if (CPA_ACC_SVC_TYPE_CRYPTO == accelerationServiceType) { Lac_ConstructCyServicesfromSymAsym(&sym_services, &asym_services, crypto_services); list_temp = *crypto_services; while (NULL != list_temp) { if (index > (numInstances - 1)) break; pInstances[index] = SalList_getObject(list_temp); list_temp = SalList_next(list_temp); index++; } } if (CPA_ACC_SVC_TYPE_CRYPTO_ASYM == accelerationServiceType || CPA_ACC_SVC_TYPE_CRYPTO == accelerationServiceType) { list_temp = asym_services; if ((NULL == list_temp) && (CPA_ACC_SVC_TYPE_CRYPTO != accelerationServiceType)) { list_temp = *crypto_services; } while (NULL != list_temp) { if (index > (numInstances - 1)) break; pInstances[index] = SalList_getObject(list_temp); list_temp = SalList_next(list_temp); index++; } } if (CPA_ACC_SVC_TYPE_CRYPTO_SYM == accelerationServiceType || CPA_ACC_SVC_TYPE_CRYPTO == accelerationServiceType) { list_temp = sym_services; if ((NULL == list_temp) && (CPA_ACC_SVC_TYPE_CRYPTO != accelerationServiceType)) { list_temp = *crypto_services; } while (NULL != list_temp) { if (index > (numInstances - 1)) break; pInstances[index] = SalList_getObject(list_temp); list_temp = SalList_next(list_temp); index++; } } } osalMemFree(pAdfInsts); return status; } #endif static CpaStatus GetServiceInfoByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *servType, char *service, size_t size) { switch (accelerationServiceType) { case CPA_ACC_SVC_TYPE_DATA_COMPRESSION: *servType = SERV_TYPE_DC; strncpy(service, "dc", size); break; case CPA_ACC_SVC_TYPE_DATA_DECOMPRESSION: *servType = SERV_TYPE_DECOMP; strncpy(service, "decomp", size); break; default: LAC_LOG_ERROR("Invalid service type"); return CPA_STATUS_INVALID_PARAM; } return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup SalCtrl * @description * Get the total number of either Compression or decompression instances *****************************************************************************/ CpaStatus Lac_GetDcNumInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *pNumInstances) { CpaStatus status = CPA_STATUS_SUCCESS; icp_accel_dev_t **pAdfInsts = NULL; icp_accel_dev_t *dev_addr = NULL; sal_t *base_addr = NULL; sal_list_t *list_temp = NULL; Cpa16U num_accel_dev = 0, num_accel_dev_valid = 0; Cpa16U num_inst = 0; Cpa16U i = 0; Cpa16U servType = 0; char service[ADF_CFG_MAX_STR_LEN] = { '\0' }; #ifdef ICP_TRACE LAC_LOG1("Called with params (0x%lx)\n", (LAC_ARCH_UINT)pNumInstances); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pNumInstances); #endif *pNumInstances = 0; status = GetServiceInfoByType( accelerationServiceType, &servType, service, sizeof(service)); LAC_CHECK_STATUS(status); /* Get the number of accel_dev in the system */ status = icp_adf_getNumInstances(&num_accel_dev); LAC_CHECK_STATUS(status); if (num_accel_dev == 0) { LAC_LOG_ERROR("Accel devices are not available"); return CPA_STATUS_RESOURCE; } /* Allocate memory to store addr of accel_devs */ pAdfInsts = osalMemAlloc(num_accel_dev * sizeof(icp_accel_dev_t *)); if (NULL == pAdfInsts) { LAC_LOG_ERROR("Failed to allocate device instance memory"); return CPA_STATUS_RESOURCE; } status = icp_adf_getAllAccelDevByServices( servType, pAdfInsts, &num_accel_dev_valid); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR_PARAMS("No support for service %s", service); osalMemFree(pAdfInsts); return status; } for (i = 0; i < num_accel_dev_valid; i++) { dev_addr = pAdfInsts[i]; if (NULL == dev_addr || NULL == dev_addr->pSalHandle) { continue; } base_addr = dev_addr->pSalHandle; if (CPA_ACC_SVC_TYPE_DATA_COMPRESSION == accelerationServiceType) { /* This case supports compression services */ list_temp = base_addr->compression_services; } else { /* This case supports decompression services */ list_temp = base_addr->decompression_services; } while (NULL != list_temp) { num_inst++; list_temp = SalList_next(list_temp); } } *pNumInstances = num_inst; osalMemFree(pAdfInsts); #ifdef ICP_TRACE if (NULL != pNumInstances) { LAC_LOG2("Called with params (0x%lx[%d])\n", (LAC_ARCH_UINT)pNumInstances, *pNumInstances); } #endif return status; } /** ****************************************************************************** * @ingroup SalCtrl * @description * Get either Compression & decompression instance *****************************************************************************/ CpaStatus Lac_GetDcInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U numInstances, CpaInstanceHandle *pInstances) { CpaStatus status = CPA_STATUS_SUCCESS; icp_accel_dev_t **pAdfInsts = NULL; icp_accel_dev_t *dev_addr = NULL; sal_t *base_addr = NULL; sal_list_t *list_temp = NULL; Cpa16U num_accel_dev = 0, num_accel_dev_valid = 0; Cpa16U num_allocated_instances = 0; Cpa16U index = 0; Cpa16U i = 0; Cpa16U servType = 0; char service[ADF_CFG_MAX_STR_LEN] = { '\0' }; #ifdef ICP_TRACE LAC_LOG3("Called with params (%d ,%d, 0x%lx)\n", accelerationServiceType, numInstances, (LAC_ARCH_UINT)pInstances); #endif #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pInstances); #endif if (0 == numInstances) { LAC_INVALID_PARAM_LOG("NumInstances is 0"); return CPA_STATUS_INVALID_PARAM; } status = GetServiceInfoByType( accelerationServiceType, &servType, service, sizeof(service)); LAC_CHECK_STATUS(status); /* Get the number of instances */ status = Lac_GetDcNumInstancesByType(accelerationServiceType, &num_allocated_instances); if (CPA_STATUS_SUCCESS != status) { return status; } if (numInstances > num_allocated_instances) { LAC_LOG_ERROR1("Only %d instances available", num_allocated_instances); return CPA_STATUS_RESOURCE; } /* Get the number of accel devices in the system */ status = icp_adf_getNumInstances(&num_accel_dev); LAC_CHECK_STATUS(status); if (num_accel_dev == 0) { LAC_LOG_ERROR("Accel devices are not available"); return CPA_STATUS_RESOURCE; } /* Allocate memory to store addr of accel_devs */ pAdfInsts = osalMemAlloc(num_accel_dev * sizeof(icp_accel_dev_t *)); if (NULL == pAdfInsts) { LAC_LOG_ERROR("Failed to allocate dev instance memory"); return CPA_STATUS_RESOURCE; } status = icp_adf_getAllAccelDevByServices( servType, pAdfInsts, &num_accel_dev_valid); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR_PARAMS("No support for service %s", service); osalMemFree(pAdfInsts); return status; } for (i = 0; i < num_accel_dev_valid; i++) { dev_addr = pAdfInsts[i]; if (NULL == dev_addr || NULL == dev_addr->pSalHandle) { continue; } base_addr = dev_addr->pSalHandle; if (CPA_ACC_SVC_TYPE_DATA_COMPRESSION == accelerationServiceType) { /* This case supports compression services */ list_temp = base_addr->compression_services; } else { /* This case supports decompression services */ list_temp = base_addr->decompression_services; } while (NULL != list_temp) { if (index > (numInstances - 1)) break; pInstances[index] = SalList_getObject(list_temp); list_temp = SalList_next(list_temp); index++; } } osalMemFree(pAdfInsts); return status; } /** ****************************************************************************** * @ingroup SalCtrl *****************************************************************************/ CpaStatus cpaGetNumInstances( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *pNumInstances) { LAC_CHECK_NULL_PARAM(pNumInstances); switch (accelerationServiceType) { #ifndef ICP_DC_ONLY case CPA_ACC_SVC_TYPE_CRYPTO_ASYM: case CPA_ACC_SVC_TYPE_CRYPTO_SYM: case CPA_ACC_SVC_TYPE_CRYPTO: return Lac_GetCyNumInstancesByType(accelerationServiceType, pNumInstances); #endif case CPA_ACC_SVC_TYPE_DATA_COMPRESSION: case CPA_ACC_SVC_TYPE_DATA_DECOMPRESSION: return Lac_GetDcNumInstancesByType(accelerationServiceType, pNumInstances); case CPA_ACC_SVC_TYPE_PATTERN_MATCH: case CPA_ACC_SVC_TYPE_RAID: case CPA_ACC_SVC_TYPE_XML: LAC_LOG_ERROR("Unsupported service type\n"); return CPA_STATUS_UNSUPPORTED; default: LAC_LOG_ERROR("Invalid service type\n"); *pNumInstances = 0; return CPA_STATUS_INVALID_PARAM; } } /** ****************************************************************************** * @ingroup SalCtrl *****************************************************************************/ CpaStatus cpaGetInstances( const CpaAccelerationServiceType accelerationServiceType, Cpa16U numInstances, CpaInstanceHandle *pInstances) { LAC_CHECK_NULL_PARAM(pInstances); switch (accelerationServiceType) { #ifndef ICP_DC_ONLY case CPA_ACC_SVC_TYPE_CRYPTO_ASYM: case CPA_ACC_SVC_TYPE_CRYPTO_SYM: case CPA_ACC_SVC_TYPE_CRYPTO: return Lac_GetCyInstancesByType( accelerationServiceType, numInstances, pInstances); #endif case CPA_ACC_SVC_TYPE_DATA_COMPRESSION: case CPA_ACC_SVC_TYPE_DATA_DECOMPRESSION: return Lac_GetDcInstancesByType( accelerationServiceType, numInstances, pInstances); case CPA_ACC_SVC_TYPE_PATTERN_MATCH: case CPA_ACC_SVC_TYPE_RAID: case CPA_ACC_SVC_TYPE_XML: LAC_LOG_ERROR("Unsupported service type\n"); return CPA_STATUS_UNSUPPORTED; default: LAC_LOG_ERROR("Invalid service type\n"); return CPA_STATUS_INVALID_PARAM; } } /** ****************************************************************************** * @ingroup SalCtrl *****************************************************************************/ CpaStatus cpaAllocInstance(const CpaAccelerationServiceType serviceType, const CpaInstanceAllocPolicy policy, CpaInstanceHandle *pInstanceHandle) { return CPA_STATUS_UNSUPPORTED; } /** ****************************************************************************** * @ingroup SalCtrl *****************************************************************************/ CpaStatus cpaFreeInstance(CpaInstanceHandle instanceHandle) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_list.c000066400000000000000000000125501503624047500271260ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_list.c * * @ingroup SalCtrl * * List implementations for SAL * *****************************************************************************/ #include "lac_mem.h" #include "lac_list.h" CpaStatus SalList_add(sal_list_t **list, sal_list_t **tail, void *pObj) { CpaStatus status = CPA_STATUS_SUCCESS; sal_list_t *new_element = NULL; if (NULL == *list) { /* First element in list */ *list = osalMemAlloc(sizeof(sal_list_t)); if (NULL == *list) { LAC_LOG_ERROR("Failed to allocate memory for list"); status = CPA_STATUS_RESOURCE; } if (CPA_STATUS_SUCCESS == status) { (*list)->next = NULL; (*list)->pObj = pObj; *tail = *list; } } else { /* add to tail of the list */ new_element = osalMemAlloc(sizeof(sal_list_t)); if (NULL == new_element) { LAC_LOG_ERROR("Failed to allocate memory for list"); status = CPA_STATUS_RESOURCE; } if (CPA_STATUS_SUCCESS == status) { new_element->pObj = pObj; new_element->next = NULL; (*tail)->next = new_element; *tail = new_element; } } return status; } void *SalList_getObject(sal_list_t *list) { if (list == NULL) { return NULL; } return list->pObj; } void SalList_delObject(sal_list_t **list) { if (*list == NULL) { return; } (*list)->pObj = NULL; return; } void *SalList_next(sal_list_t *list) { return list->next; } void SalList_free(sal_list_t **list) { sal_list_t *next_element = NULL; void *pObj = NULL; while (NULL != (*list)) { next_element = SalList_next(*list); pObj = SalList_getObject((*list)); LAC_OS_FREE(pObj); LAC_OS_FREE(*list); *list = next_element; } } void SalList_del(sal_list_t **head_list, sal_list_t **pre_list, sal_list_t *list) { void *pObj = NULL; if ((NULL == *head_list) || (NULL == *pre_list) || (NULL == list)) { return; } if (*head_list == list) { /* delete the first node in list */ *head_list = list->next; } else { (*pre_list)->next = list->next; } pObj = SalList_getObject(list); LAC_OS_FREE(pObj); LAC_OS_FREE(list); return; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/ctrl/sal_rl_stubs.c000066400000000000000000000141671503624047500300160ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_rl_stubs.c * * @ingroup SalCtrl * * @description * These functions specify the API for rate limiting, setting with * respect to device, instance and queue pair. * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ /* QAT-API includes */ #include "cpa_rl.h" CpaStatus cpaGetDevRlPropertiesHandle(Cpa16U devIdx, const CpaAccelerationServiceType srvType, CpaRlPropertiesHandle *handle, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaRlPropGetNumInterfaces(const CpaRlPropertiesHandle handle, Cpa32U *totalSlaInterfaces, Cpa32U *remSlaInterfaces, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaGetDevRlPropSlaCir(const CpaRlPropertiesHandle handle, Cpa32U *totalCir, Cpa32U *remCir, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaGetDevRlPropSlaPir(const CpaRlPropertiesHandle handle, Cpa32U *totalPir, Cpa32U *totalAssignedPir, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaGetInstanceRlSlaPir(const CpaInstanceHandle handle, Cpa32U *pirSetting, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaGetInstanceRlSlaCir(const CpaInstanceHandle handle, Cpa32U *cirSetting, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaRlGetQpNumHandles(Cpa32U devIdx, CpaAccelerationServiceType svcType, Cpa8U *numHandles, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaRlGetQpHandles(Cpa32U devIdx, CpaAccelerationServiceType svcType, CpaRlQpHandle *handles, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaSetRlSla(CpaRlQpHandle handle, CpaUserSla *sla, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaDeleteRlSla(CpaRlQpHandle handle, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaGetRlSla(const CpaRlQpHandle handle, CpaUserSla *sla, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaEnableRateLimiting(Cpa32U devIdx, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } CpaStatus cpaDisableRateLimiting(Cpa32U devIdx, CpaRlError *rlError) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/device/000077500000000000000000000000001503624047500254405ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/device/sal_dev_info.c000066400000000000000000000164461503624047500302470ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file dev_info.c * * @defgroup cpaDev * * @description * This file contains implementation of functions for device level APIs * *****************************************************************************/ /* Osal includes */ #include "Osal.h" /* QAT-API includes */ #include "cpa_dev.h" #include "icp_accel_devices.h" #include "adf_user_cfg.h" #include "lac_common.h" #include "icp_adf_cfg.h" #include "lac_sal_types.h" #include "icp_adf_accel_mgr.h" #include "icp_platform.h" #include "sal_string_parse.h" #include "adf_devmgr.h" #include "lac_sal.h" CpaStatus cpaGetNumDevices(Cpa16U *numDevices) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(numDevices); #endif return icp_adf_getNumInstances(numDevices); } CpaStatus cpaGetDeviceInfo(Cpa16U device, CpaDeviceInfo *deviceInfo) { CpaStatus status = CPA_STATUS_SUCCESS; icp_accel_dev_t *pDevice = NULL; Cpa16U numDevicesAvail = 0; Cpa32U capabilitiesMask = 0; Cpa32U enabledServices = 0; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(deviceInfo); #endif icp_adf_getNumInstances(&numDevicesAvail); /* Check if the application is not attempting to access a * device that does not exist. */ if (0 == numDevicesAvail) { LAC_LOG_ERROR("Failed to retrieve number of devices!"); return CPA_STATUS_FAIL; } if (device >= numDevicesAvail) { LAC_LOG_ERROR1("Invalid device access! Number of devices " "available: %d", numDevicesAvail); return CPA_STATUS_FAIL; } /* Clear the entire capability structure before initialising it */ osalMemSet(deviceInfo, sizeof(CpaDeviceInfo), 0x00); /* Bus/Device/Function should be 0xFF until initialised */ deviceInfo->bdf = 0xffff; pDevice = icp_adf_getAccelDevByAccelId(device); if (NULL == pDevice) { LAC_LOG_ERROR("Failed to retrieve device"); return CPA_STATUS_FAIL; } /* Device of interest is found, retrieve the information for it */ deviceInfo->sku = pDevice->sku; deviceInfo->deviceId = pDevice->pciDevId; deviceInfo->bdf = icp_adf_cfgGetBusAddress(pDevice->accelId); deviceInfo->numaNode = pDevice->numa_node; deviceInfo->isVf = pDevice->isVf; status = SalCtrl_GetEnabledServices(pDevice, &enabledServices); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to retrieve enabled services!"); return status; } status = icp_adf_getAccelDevCapabilities(pDevice, &capabilitiesMask); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to retrieve accel capabilities mask!"); return status; } /* Determine if Compression service is enabled */ if (enabledServices & SAL_SERVICE_TYPE_COMPRESSION) { deviceInfo->dcEnabled = (((capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION) != 0) ? CPA_TRUE : CPA_FALSE); } /* Determine if Inline service is enabled */ if (enabledServices & SAL_SERVICE_TYPE_INLINE) { deviceInfo->inlineEnabled = (((capabilitiesMask & ICP_ACCEL_CAPABILITIES_INLINE) != 0) ? CPA_TRUE : CPA_FALSE); } /* Determine if Crypto service is enabled */ if (enabledServices & SAL_SERVICE_TYPE_CRYPTO) { deviceInfo->cySymEnabled = (((capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) ? CPA_TRUE : CPA_FALSE); deviceInfo->cyAsymEnabled = (((capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) != 0) ? CPA_TRUE : CPA_FALSE); } /* Determine if Crypto Sym service is enabled */ if (enabledServices & SAL_SERVICE_TYPE_CRYPTO_SYM) { deviceInfo->cySymEnabled = (((capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) ? CPA_TRUE : CPA_FALSE); } /* Determine if Crypto Asym service is enabled */ if (enabledServices & SAL_SERVICE_TYPE_CRYPTO_ASYM) { deviceInfo->cyAsymEnabled = (((capabilitiesMask & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) != 0) ? CPA_TRUE : CPA_FALSE); } deviceInfo->deviceMemorySizeAvailable = pDevice->deviceMemAvail; return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/000077500000000000000000000000001503624047500256245ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_buffer_desc.h000066400000000000000000000431371503624047500310730ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_buffer_desc.h * * @defgroup LacBufferDesc Buffer Descriptors * * @ingroup LacCommon * * Functions which handle updating a user supplied buffer with the QAT * descriptor representation. * ***************************************************************************/ /***************************************************************************/ #ifndef LAC_BUFFER_DESC_H #define LAC_BUFFER_DESC_H /*************************************************************************** * Include header files ***************************************************************************/ #include "cpa.h" #include "icp_buffer_desc.h" #include "cpa_cy_sym.h" #include "lac_common.h" /** ******************************************************************************* * @ingroup LacBufferDesc * Write the buffer descriptor in QAT friendly format. * * @description * Updates the Meta Data associated with the pUserBufferList CpaBufferList * This function will also return the (aligned) physical address * associated with this CpaBufferList. * * @param[in] pUserBufferList A pointer to the buffer list to * create the meta data for the QAT. * @param[out] pBufferListAlignedPhyAddr The pointer to the aligned physical * address. * @param[in] isPhysicalAddress Type of address * @param[in] pService Pointer to generic service * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListDescWrite(const CpaBufferList *pUserBufferList, Cpa64U *pBufferListAlignedPhyAddr, CpaBoolean isPhysicalAddress, sal_service_t *pService); /** ******************************************************************************* * @ingroup LacBufferDesc * Write the buffer descriptor in QAT friendly format. * * @description * Updates the Meta Data associated with the pUserBufferList CpaBufferList * This function will also return the (aligned) physical address * associated with this CpaBufferList. Zero length buffers are allowed. * Should be used for CHA-CHA-POLY and GCM algorithms. * * @param[in] pUserBufferList A pointer to the buffer list to * create the meta data for the QAT. * @param[out] pBufferListAlignedPhyAddr The pointer to the aligned physical * address. * @param[in] isPhysicalAddress Type of address * @param[in] pService Pointer to generic service * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( const CpaBufferList *pUserBufferList, Cpa64U *pBufferListAlignedPhyAddr, CpaBoolean isPhysicalAddress, sal_service_t *pService); /** ******************************************************************************* * @ingroup LacBufferDesc * Write the buffer descriptor in QAT friendly format. * * @description * Updates the Meta Data associated with the pUserBufferList CpaBufferList * This function will also return the (aligned) physical address * associated with this CpaBufferList and the total data length of the * buffer list. Zero length buffers are allowed. * Should be used with HW devices supporting zero length payloads. * * @param[in] pUserBufferList A pointer to the buffer list to * create the meta data for the QAT. * @param[out] pBufferListAlignedPhyAddr The pointer to the aligned physical * address. * @param[in] isPhysicalAddress Type of address * @param[out] totalDataLenInBytes The pointer to the total data length * of the buffer list * @param[in] pService Pointer to generic service * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListDescWriteAllow0BuffGetSize( const CpaBufferList *pUserBufferList, Cpa64U *pBufferListAlignedPhyAddr, CpaBoolean isPhysicalAddress, Cpa64U *totalDataLenInBytes, sal_service_t *pService); /** ******************************************************************************* * @ingroup LacBufferDesc * Write the buffer descriptor in QAT friendly format. * * @description * Updates the Meta Data associated with the PClientList CpaBufferList * This function will also return the (aligned) physical address * associated with this CpaBufferList and the total data length of the * buffer list. * * @param[in] pUserBufferList A pointer to the buffer list to * create the meta data for the QAT. * @param[out] pBufListAlignedPhyAddr The pointer to the aligned physical * address. * @param[in] isPhysicalAddress Type of address * @param[out] totalDataLenInBytes The pointer to the total data length * of the buffer list * @param[in] pService Pointer to generic service * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListDescWriteAndGetSize( const CpaBufferList *pUserBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, Cpa64U *totalDataLenInBytes, sal_service_t *pService); /** ******************************************************************************* * @ingroup LacBufferDesc * Write the buffer descriptor in QAT friendly format with the addition * of a dictionary buffer included at the start. * * @description * Updates the meta data associated with the pUserBufferList CpaBufferList * This function will also return the (aligned) physical address * associated with this CpaBufferList. * * @param[in] pUserBufferList A pointer to the buffer list to * create the meta data for the QAT. * @param[in] pDictionaryBufferList A pointer to the buffer list whose * flat buffers will be added at the start * of the meta data for the dictionary * data. * @param[out] pBufListAlignedPhyAddr The pointer to the aligned physical * address. * @param[in] isPhysicalAddress Type of address * @param[out] totalDataLenInBytes The pointer to the total data length * of the buffer list including the * length of the dictionary. * @param[in] pService Pointer to generic service * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListDescWriteWithDictAndGetSize( const CpaBufferList *pUserBufferList, const CpaBufferList *pDictionaryBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, Cpa64U *totalDataLenInBytes, sal_service_t *pService); /** ******************************************************************************* * @ingroup LacBufferDesc * Ensure the CpaFlatBuffer is correctly formatted. * * @description * Ensures the CpaFlatBuffer is correctly formatted * This function will also return the total size of the buffers * in the scatter gather list. * * @param[in] pUserFlatBuffer A pointer to the flat buffer to * validate. * @param[out] pPktSize The total size of the packet. * @param[in] alignmentShiftExpected The expected alignment shift of each * of the elements of the scatter gather * * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks * @retval CPA_STATUS_SUCCESS Function executed successfully * *****************************************************************************/ CpaStatus LacBuffDesc_FlatBufferVerify( const CpaFlatBuffer *pUserFlatBuffer, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected); /** ******************************************************************************* * @ingroup LacBufferDesc * Ensure the CpaFlatBuffer is correctly formatted. * This function will allow a size of zero bytes to any of the Flat * buffers. * * @description * Ensures the CpaFlatBuffer is correctly formatted * This function will also return the total size of the buffers * in the scatter gather list. * * @param[in] pUserFlatBuffer A pointer to the flat buffer to * validate. * @param[out] pPktSize The total size of the packet. * @param[in] alignmentShiftExpected The expected alignment shift of each * of the elements of the scatter gather * * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks * @retval CPA_STATUS_SUCCESS Function executed successfully * *****************************************************************************/ CpaStatus LacBuffDesc_FlatBufferVerifyNull( const CpaFlatBuffer *pUserFlatBuffer, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected); /** ******************************************************************************* * @ingroup LacBufferDesc * Ensure the CpaBufferList is correctly formatted. * * @description * Ensures the CpaBufferList pUserBufferList is correctly formatted * including the user supplied metaData. * This function will also return the total size of the buffers * in the scatter gather list. * * @param[in] pUserBufferList A pointer to the buffer list to * validate. * @param[out] pPktSize The total size of the buffers in the * scatter gather list. * @param[in] alignmentShiftExpected The expected alignment shift of each * of the elements of the scatter gather * list. * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks * @retval CPA_STATUS_SUCCESS Function executed successfully * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListVerify( const CpaBufferList *pUserBufferList, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected); /** ******************************************************************************* * @ingroup LacBufferDesc * Ensure the CpaBufferList is correctly formatted ignoring metadata. * * @description * Ensures the CpaBufferList pUserBufferList is correctly formatted * excluding the user supplied meta data. * This function will also return the total size of the buffers * in the scatter gather list. * * @param[in] pUserBufferList A pointer to the buffer list to * validate. * @param[out] pPktSize The total size of the buffers in the * scatter gather list. * @param[in] alignmentShiftExpected The expected alignment shift of each * of the elements of the scatter gather * list. * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks * @retval CPA_STATUS_SUCCESS Function executed successfully * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListVerifyNoMetadata( const CpaBufferList *pUserBufferList, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected); /** ******************************************************************************* * @ingroup LacBufferDesc * Ensure the CpaBufferList is correctly formatted. * * @description * Ensures the CpaBufferList pUserBufferList is correctly formatted * including the user supplied metaData. * This function will also return the total size of the buffers * in the scatter gather list. * * @param[in] pUserBufferList A pointer to the buffer list to * validate. * @param[out] pPktSize The total size of the buffers in the * scatter gather list. * @param[in] alignmentShiftExpected The expected alignment shift of each * of the elements of the scatter gather * list. * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks * @retval CPA_STATUS_SUCCESS Function executed successfully * *****************************************************************************/ CpaStatus LacBuffDesc_BufferListVerifyNull( const CpaBufferList *pUserBufferList, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected); /** ******************************************************************************* * @ingroup LacBufferDesc * Get the total size of a CpaBufferList. * * @description * This function returns the total size of the buffers * in the scatter gather list. * * @param[in] pUserBufferList A pointer to the buffer list to * calculate the total size for. * @param[out] pPktSize The total size of the buffers in the * scatter gather list. * *****************************************************************************/ void LacBuffDesc_BufferListTotalSizeGet(const CpaBufferList *pUserBufferList, Cpa64U *pPktSize); /** ******************************************************************************* * @ingroup LacBufferDesc * Zero some of the CpaBufferList. * * @description * Zero a section of data within the CpaBufferList from an offset for * a specific length. * * @param[in] pBuffList A pointer to the buffer list to * zero an area of. * @param[in] offset Number of bytes from start of buffer to where * to start zeroing. * * @param[in] lenToZero Number of bytes that will be set to zero * after the call to this function. *****************************************************************************/ void LacBuffDesc_BufferListZeroFromOffset(CpaBufferList *pBuffList, Cpa32U offset, Cpa32U lenToZero); #endif /* LAC_BUFFER_DESC_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_common.h000066400000000000000000001447331503624047500301200ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_common.h Common macros * * @defgroup Lac Look Aside Crypto LLD Doc * *****************************************************************************/ /** ***************************************************************************** * @defgroup LacCommon LAC Common * Common code for Lac which includes init/shutdown, memory, logging and * hooks. * * @ingroup Lac * *****************************************************************************/ /***************************************************************************/ #ifndef LAC_COMMON_H #define LAC_COMMON_H /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" #include "lac_log.h" #include "cpa_cy_common.h" #include "icp_adf_init.h" #include "Osal.h" #include "cpa_cy_im.h" #ifndef ICP_KERNEL64_USER32 #ifdef __x86_64__ #define LAC_ARCH_UINT Cpa64U #define LAC_ARCH_INT Cpa64S #else #define LAC_ARCH_UINT Cpa32U #define LAC_ARCH_INT Cpa32S #endif #else /* ICP_KERNEL64_USER32 */ #ifdef USER_SPACE #define LAC_ARCH_UINT Cpa32U #define LAC_ARCH_INT Cpa32S #else #define LAC_ARCH_UINT Cpa64U #define LAC_ARCH_INT Cpa64S #endif #endif /* ***************************************************************************** * Max range values for some primitive param checking ***************************************************************************** */ /**< Maximum number of instances */ #define SAL_MAX_NUM_INSTANCES_PER_DEV 512 #define SAL_DEFAULT_RING_SIZE 256 /**< Default ring size */ #define SAL_64_CONCURR_REQUESTS 64 #define SAL_128_CONCURR_REQUESTS 128 #define SAL_256_CONCURR_REQUESTS 256 #define SAL_512_CONCURR_REQUESTS 512 #define SAL_1024_CONCURR_REQUESTS 1024 #define SAL_2048_CONCURR_REQUESTS 2048 #define SAL_4096_CONCURR_REQUESTS 4096 #define SAL_MAX_CONCURR_REQUESTS 65536 /**< Valid options for the num of concurrent requests per ring pair read from the config file. These values are used to size the rings */ #define SAL_BATCH_SUBMIT_FREE_SPACE 2 /**< For data plane batch submissions ADF leaves 2 spaces free on the ring */ /* ****************************************************************************** * Some common settings for QA API queries ****************************************************************************** */ #define SAL_INFO2_VENDOR_NAME "Intel(R)" /**< @ingroup LacCommon * Name of vendor of this driver */ #define SAL_INFO2_PART_NAME "%s with Intel(R) QuickAssist Technology" /**< @ingroup LacCommon */ /* ******************************************************************************** * User process name defines and functions ******************************************************************************** */ #define LAC_USER_PROCESS_NAME_MAX_LEN 32 /**< @ingroup LacCommon * Max length of user process name */ #define LAC_KERNEL_PROCESS_NAME "KERNEL_QAT" /**< @ingroup LacCommon * Default name for kernel process */ /* ******************************************************************************** * response mode indicator from Config file ******************************************************************************** */ #define SAL_RESP_POLL_CFG_FILE 1 #define SAL_RESP_EPOLL_CFG_FILE 2 /* * @ingroup LacCommon * @description * This function sets the process name * * @context * This functions is called from module_init or from user space process * initialization function * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * param[in] processName Process name to be set */ CpaStatus icpSetProcessName(const char *processName); /* * @ingroup LacCommon * @description * This function gets the process name * * @context * This functions is called from LAC context * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * */ char *icpGetProcessName(void); /* Sections of the config file */ #define LAC_CFG_SECTION_GENERAL "GENERAL" #define LAC_CFG_SECTION_INTERNAL "INTERNAL" /* ******************************************************************************** * Debug Macros and settings ******************************************************************************** */ /* DEBUG */ #ifdef ICP_DEBUG #undef STATIC #undef INLINE #define STATIC #define INLINE /**< @ingroup LacCommon * When DEBUG is set STATIC/INLINE evaluates to nothing. */ #else #define STATIC static #define INLINE inline /**< @ingroup LacCommon * otherwise it evaluates to the static/inline keyword */ #endif #define SEPARATOR "+--------------------------------------------------+\n" /**< @ingroup LacCommon * separator used for printing stats to standard output*/ #define BORDER "|" /**< @ingroup LacCommon * separator used for printing stats to standard output*/ /** ***************************************************************************** * @ingroup LacCommon * Component state * * @description * This enum is used to indicate the state that the component is in. Its * purpose is to prevent components from being initialised or shutdown * incorrectly. * *****************************************************************************/ typedef enum { LAC_COMP_SHUT_DOWN = 0, /**< Component in the Shut Down state */ LAC_COMP_SHUTTING_DOWN, /**< Component in the Process of Shutting down */ LAC_COMP_INITIALISING, /**< Component in the Process of being initialised */ LAC_COMP_INITIALISED, /**< Component in the initialised state */ } lac_comp_state_t; /** ******************************************************************************* * @ingroup LacCommon * This macro checks if a parameter is NULL * * @param[in] param Parameter * * @return CPA_STATUS_INVALID_PARAM Parameter is NULL * @return void Parameter is not NULL ******************************************************************************/ #define LAC_CHECK_NULL_PARAM(param) \ do \ { \ if (NULL == (param)) \ { \ LAC_INVALID_PARAM_LOG(#param " is NULL"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This macro checks if a parameter is within a specified range * * @param[in] param Parameter * @param[in] min Parameter must be greater than OR equal to *min * @param[in] max Parameter must be less than max * * @return CPA_STATUS_INVALID_PARAM Parameter is outside range * @return void Parameter is within range ******************************************************************************/ #define LAC_CHECK_PARAM_RANGE(param, min, max) \ do \ { \ if (((param) < (min)) || ((param) >= (max))) \ { \ LAC_INVALID_PARAM_LOG(#param " is outside valid range"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This assert checks if an param is zero. * This will be compiled out for non debug releases * ******************************************************************************/ #define LAC_ASSERT_NOT_ZERO(param) \ LAC_ASSERT((0 == (param)), "Parameter " #param " is not zero.\n") /** ******************************************************************************* * @ingroup LacCommon * This checks if a param is 8 byte aligned. * ******************************************************************************/ #define LAC_CHECK_8_BYTE_ALIGNMENT(param) \ do \ { \ if ((Cpa64U)param % 8 != 0) \ { \ LAC_INVALID_PARAM_LOG(#param " is NOT 8 byte ALIGNED"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This checks if a parameter is 16 byte aligned. * ******************************************************************************/ #define LAC_CHECK_16_BYTE_ALIGNMENT(param) \ do \ { \ if ((Cpa64U)param % 16 != 0) \ { \ LAC_INVALID_PARAM_LOG(#param " is NOT 16 byte ALIGNED"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This checks if a param is 64 byte aligned. * ******************************************************************************/ #define LAC_CHECK_64_BYTE_ALIGNMENT(param) \ do \ { \ if ((LAC_ARCH_UINT)param % 64 != 0) \ { \ LAC_INVALID_PARAM_LOG(#param " is NOT 64byte ALIGNED"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This checks if a statement is true * ******************************************************************************/ #define LAC_CHECK_STATEMENT(param) \ do \ { \ if ((param)) \ { \ LAC_INVALID_PARAM_LOG(#param " is invalid"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This checks if a statement is true. * ******************************************************************************/ #define LAC_CHECK_STATEMENT_LOG(param, log, ...) \ do \ { \ if ((param)) \ { \ LAC_LOG_ERROR_PARAMS(log, __VA_ARGS__); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This assert checks if a param is set to be Lite. * This will be compiled out for non debug releases * ******************************************************************************/ #define LAC_ASSERT_LITE(param) \ LAC_ASSERT((CPA_TRUE == (param)), \ "Parameter " #param " is not set to be Lite.\n") /** ******************************************************************************* * @ingroup LacCommon * This macro returns the size of the buffer list structure given the * number of elements in the buffer list - note: only the sizeof the * buffer list structure is returned. * * @param[in] numBuffers The number of flatbuffers in a buffer list * * @return size of the buffer list structure ******************************************************************************/ #define LAC_BUFFER_LIST_SIZE_GET(numBuffers) \ (sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer))) /** ******************************************************************************* * @ingroup LacCommon * This macro checks that a flatbuffer is valid i.e. that it is not * null and the data it points to is not null * * @param[in] pFlatBuffer Pointer to flatbuffer * * @return CPA_STATUS_INVALID_PARAM Invalid flatbuffer pointer * @return void flatbuffer is ok ******************************************************************************/ #define LAC_CHECK_FLAT_BUFFER(pFlatBuffer) \ do \ { \ LAC_CHECK_NULL_PARAM((pFlatBuffer)); \ LAC_CHECK_NULL_PARAM((pFlatBuffer)->pData); \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This macro verifies that the status is ok i.e. equal to CPA_STATUS_SUCCESS * * @param[in] status status we are checking * * @return void status is ok (CPA_STATUS_SUCCESS) * @return status The value in the status parameter is an error one * ******************************************************************************/ #define LAC_CHECK_STATUS(status) \ do \ { \ if (CPA_STATUS_SUCCESS != (status)) \ { \ return status; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This macro verifies that the status is ok i.e. equal to CPA_STATUS_SUCCESS * and prints a message and returns if it is not equal. * * @param[in] status status we are checking * @param[in] log message to print if status is not CPA_STATUS_SUCCESS * * @return void status is ok (CPA_STATUS_SUCCESS) * @return status The value in the status parameter is an error one * ******************************************************************************/ #define LAC_CHECK_STATUS_LOG(status, log, ...) \ do \ { \ if (CPA_STATUS_SUCCESS != (status)) \ { \ LAC_LOG_ERROR_PARAMS(log, __VA_ARGS__); \ return status; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This macro verifies that the Instance Handle is valid. * * @param[in] instanceHandle Instance Handle * * @return CPA_STATUS_INVALID_PARAM Parameter is NULL * @return void Parameter is not NULL * ******************************************************************************/ #define LAC_CHECK_INSTANCE_HANDLE(instanceHandle) \ do \ { \ if (NULL == (instanceHandle)) \ { \ LAC_INVALID_PARAM_LOG(#instanceHandle " is NULL"); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This macro verifies that the address translation routine is set up * correctly for the given instance * * @param[in] instanceHandle Instance Handle * * @return CPA_STATUS_FAIL Address translation set up incorrectly * @return void Address translation set up correctly * ******************************************************************************/ #ifdef KERNEL_SPACE #define SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle) #else #define SAL_CHECK_ADDR_TRANS_SETUP(instanceHandle) \ do \ { \ sal_service_t *pGenericService = NULL; \ pGenericService = (sal_service_t *)instanceHandle; \ if (NULL == pGenericService->virt2PhysClient) \ { \ switch (pGenericService->type) \ { \ case SAL_SERVICE_TYPE_CRYPTO: \ LAC_LOG_ERROR1( \ "Address translation function not set for CY" \ " instance %d", \ pGenericService->instance); \ break; \ case SAL_SERVICE_TYPE_COMPRESSION: \ LAC_LOG_ERROR1( \ "Address translation function not set for DC" \ " instance %d", \ pGenericService->instance); \ break; \ case SAL_SERVICE_TYPE_QAT: \ LAC_LOG_ERROR1( \ "Address translation function not set for QAT" \ " instance %d", \ pGenericService->instance); \ break; \ case SAL_SERVICE_TYPE_UNKNOWN: \ default: \ LAC_LOG_ERROR1("Address translation function not set for" \ " unknown instance %d", \ pGenericService->instance); \ break; \ } \ return CPA_STATUS_FAIL; \ } \ } while (0) #endif /** ******************************************************************************* * @ingroup LacCommon * Checks capability for a crypto service instance. * * @description * This macro checks one specific service like RSA's capability for a * symmetric /asymmetric service instance. * * @param[in] instanceHandle Instance handler of the target service * instance. * @param[in] capa Capability to be checked. * * @return CPA_STATUS_UNSUPPORTED Capability is not supported on this instance * @return void Check passed ******************************************************************************/ #define SAL_CHECK_INSTANCE_CRYPTO_CAPABILITY(instanceHandle, capa) \ do \ { \ CpaCyCapabilitiesInfo *pCyCapInfo; \ pCyCapInfo = &((sal_crypto_service_t *)instanceHandle)->capInfo; \ if (!pCyCapInfo->capa##Supported) \ { \ LAC_LOG_ERROR1("Capability %s is not supported", #capa); \ return CPA_STATUS_UNSUPPORTED; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This macro copies a string from one location to another * * @param[out] pDestinationBuffer Pointer to destination buffer * @param[in] pSource Pointer to source buffer * ******************************************************************************/ #define LAC_COPY_STRING(pDestinationBuffer, pSource) \ do \ { \ memcpy(pDestinationBuffer, pSource, (sizeof(pSource) - 1)); \ pDestinationBuffer[(sizeof(pSource) - 1)] = '\0'; \ } while (0) /** ******************************************************************************* * @ingroup LacCommon * This macro fills a memory zone with ZEROES * * @param[in] pBuffer Pointer to buffer * @param[in] count Buffer length * * @return void * ******************************************************************************/ #define LAC_OS_BZERO(pBuffer, count) osalMemSet(pBuffer, 0, count); /** ******************************************************************************* * @ingroup LacCommon * This macro calculates the position of the given member in a struct * Only for use on a struct where all members are of equal size to map * the struct member position to an array index * * @param[in] structType the struct * @param[in] member the member of the given struct * ******************************************************************************/ #define LAC_IDX_OF(structType, member) \ (offsetof(structType, member) / sizeof(((structType *)0)->member)) /* ******************************************************************************** * Alignment, Bid define and Bit Operation Macros ******************************************************************************** */ #define LAC_BIT31_SET 0x80000000 /**< bit 31 == 1 */ #define LAC_BIT7_SET 0x80 /**< bit 7 == 1 */ #define LAC_BIT6_SET 0x40 /**< bit 6 == 1 */ #define LAC_BIT5_SET 0x20 /**< bit 5 == 1 */ #define LAC_BIT4_SET 0x10 /**< bit 4 == 1 */ #define LAC_BIT3_SET 0x08 /**< bit 3 == 1 */ #define LAC_BIT2_SET 0x04 /**< bit 2 == 1 */ #define LAC_BIT1_SET 0x02 /**< bit 1 == 1 */ #define LAC_BIT0_SET 0x01 /**< bit 0 == 1 */ #define LAC_NUM_BITS_IN_BYTE (8) /**< @ingroup LacCommon * Number of bits in a byte */ #define LAC_LONG_WORD_IN_BYTES (4) /**< @ingroup LacCommon * Number of bytes in an IA word */ #define LAC_QUAD_WORD_IN_BYTES (8) /**< @ingroup LacCommon * Number of bytes in a QUAD word */ #define LAC_QAT_MAX_MSG_SZ_LW (32) /**< @ingroup LacCommon * Maximum size in Long Words for a QAT message */ /** ***************************************************************************** * @ingroup LacCommon * Alignment shift requirements of a buffer. * * @description * This enum is used to indicate the alignment shift of a buffer. * All alignments are to power of 2 * *****************************************************************************/ typedef enum lac_aligment_shift_s { LAC_NO_ALIGNMENT_SHIFT = 0, /**< No alignment shift (to a power of 2)*/ LAC_8BYTE_ALIGNMENT_SHIFT = 3, /**< 8 byte alignment shift (to a power of 2)*/ LAC_16BYTE_ALIGNMENT_SHIFT = 4, /**< 16 byte alignment shift (to a power of 2)*/ LAC_64BYTE_ALIGNMENT_SHIFT = 6, /**< 64 byte alignment shift (to a power of 2)*/ LAC_4KBYTE_ALIGNMENT_SHIFT = 12, /**< 4k byte alignment shift (to a power of 2)*/ } lac_aligment_shift_t; /** ***************************************************************************** * @ingroup LacCommon * Alignment of a buffer. * * @description * This enum is used to indicate the alignment requirements of a buffer. * *****************************************************************************/ typedef enum lac_aligment_s { LAC_NO_ALIGNMENT = 0, /**< No alignment */ LAC_1BYTE_ALIGNMENT = 1, /**< 1 byte alignment */ LAC_8BYTE_ALIGNMENT = 8, /**< 8 byte alignment*/ LAC_64BYTE_ALIGNMENT = 64, /**< 64 byte alignment*/ LAC_4KBYTE_ALIGNMENT = 4096, /**< 4k byte alignment */ } lac_aligment_t; /** ***************************************************************************** * @ingroup LacCommon * Size of a buffer. * * @description * This enum is used to indicate the required size. * The buffer must be a multiple of the required size. * *****************************************************************************/ typedef enum lac_expected_size_s { LAC_NO_LENGTH_REQUIREMENTS = 0, /**< No requirement for size */ LAC_4KBYTE_MULTIPLE_REQUIRED = 4096, /**< 4k multiple requirement for size */ } lac_expected_size_t; #define LAC_OPTIMAL_ALIGNMENT_SHIFT LAC_64BYTE_ALIGNMENT_SHIFT /**< @ingroup LacCommon * optimal alignment to a power of 2 */ #define LAC_SHIFT_8 (1 << LAC_8BYTE_ALIGNMENT_SHIFT) /**< shift by 8 bits */ #define LAC_SHIFT_24 \ ((1 << LAC_8BYTE_ALIGNMENT_SHIFT) + (1 << LAC_16BYTE_ALIGNMENT_SHIFT)) /**< shift by 24 bits */ #define LAC_MAX_16_BIT_VALUE ((1 << 16) - 1) /**< @ingroup LacCommon * maximum value a 16 bit type can hold */ /** ******************************************************************************* * @ingroup LacCommon * This macro can be used to avoid an unused variable warning from the * compiler * * @param[in] variable unused variable * ******************************************************************************/ #define LAC_UNUSED_VARIABLE(x) (void)(x) /** ******************************************************************************* * @ingroup LacCommon * This macro checks if an address is aligned to the specified power of 2 * Returns 0 if alignment is ok, or non-zero otherwise * * @param[in] address the address we are checking * * @param[in] alignment the byte alignment to check (specified as power of 2) * ******************************************************************************/ #define LAC_ADDRESS_ALIGNED(address, alignment) \ (!((LAC_ARCH_UINT)(address) & ((1 << (alignment)) - 1))) /** ******************************************************************************* * @ingroup LacCommon * This macro rounds up a number to a be a multiple of the alignment when * the alignment is a power of 2. * * @param[in] num Number * @param[in] align Alignment (must be a power of 2) * ******************************************************************************/ #define LAC_ALIGN_POW2_ROUNDUP(num, align) (((num) + (align)-1) & ~((align)-1)) /** ******************************************************************************* * @ingroup LacCommon * This macro generates a bit mask to select a particular bit * * @param[in] bitPos Bit position to select * ******************************************************************************/ #define LAC_BIT(bitPos) (0x1 << (bitPos)) /** ******************************************************************************* * @ingroup LacCommon * This macro converts a size in bits to the equivalent size in bytes, * using a bit shift to divide by 8 * * @param[in] x size in bits * ******************************************************************************/ #define LAC_BITS_TO_BYTES(x) ((x) >> 3) /** ******************************************************************************* * @ingroup LacCommon * This macro converts a size in bytes to the equivalent size in bits, * using a bit shift to multiply by 8 * * @param[in] x size in bytes * ******************************************************************************/ #define LAC_BYTES_TO_BITS(x) ((x) << 3) /** ******************************************************************************* * @ingroup LacCommon * This macro converts a size in bytes to the equivalent size in longwords, * using a bit shift to divide by 4 * * @param[in] x size in bytes * ******************************************************************************/ #define LAC_BYTES_TO_LONGWORDS(x) ((x) >> 2) /** ******************************************************************************* * @ingroup LacCommon * This macro converts a size in longwords to the equivalent size in bytes, * using a bit shift to multiply by 4 * * @param[in] x size in long words * ******************************************************************************/ #define LAC_LONGWORDS_TO_BYTES(x) ((x) << 2) /** ******************************************************************************* * @ingroup LacCommon * This macro converts a size in bytes to the equivalent size in quadwords, * using a bit shift to divide by 8 * * @param[in] x size in bytes * ******************************************************************************/ #define LAC_BYTES_TO_QUADWORDS(x) (((x) >> 3) + (((x) % 8) ? 1 : 0)) /** ******************************************************************************* * @ingroup LacCommon * This macro converts a size in quadwords to the equivalent size in bytes, * using a bit shift to multiply by 8 * * @param[in] x size in quad words * ******************************************************************************/ #define LAC_QUADWORDS_TO_BYTES(x) ((x) << 3) /* ******************************************************************************* * Assert Macros ******************************************************************************* */ /* LAC_ASSERT usage: call with a boolean condition and text to be logged if * that condition fails */ /** ******************************************************************************* * @ingroup LacCommon * This macro checks a condition and if the condition is false, logs an * error message for debug releases but gets compiled out for non-debug * releases * @note * For debug releases osal needs to be compiled with OSAL_ENSURE_ON defined * * @param[in] condition condition to check * @param[in] errorText Text to printed if condition is false * ******************************************************************************/ #define LAC_ASSERT(condition, errorText) OSAL_ENSURE((condition), (errorText)) /** ******************************************************************************* * @ingroup LacCommon * This macro checks a condition and if the condition is false, logs an * error message for debug releases but gets compiled out for non-debug * releases * * @param[in] condition condition to check * @param[in] errorText Text to printed if condition is false * ******************************************************************************/ #define LAC_ENSURE(condition, errorText) LAC_ASSERT((condition), (errorText)) /** ******************************************************************************* * @ingroup LacCommon * This macro checks a condition and if the condition is false, logs an * error message for debug releases and returns from current function * * @param[in] condition condition to check * @param[in] errorText Text to printed if condition is false * ******************************************************************************/ #define LAC_ENSURE_RETURN_VOID(condition, errorText) \ OSAL_ENSURE_JUST_RETURN((condition), (errorText)) /** ******************************************************************************* * @ingroup LacCommon * This assert checks if an address is not null. * This will be compiled out for non debug releases * * @param[in] address the address we are checking * ******************************************************************************/ #define LAC_ASSERT_NOT_NULL(address) \ LAC_ASSERT((NULL != (address)), "Parameter " #address " is null.\n") /** ******************************************************************************* * @ingroup LacCommon * This assert checks if an address is not null. * This will be compiled out for non debug releases * * @param[in] address the address we are checking * ******************************************************************************/ #define LAC_ENSURE_NOT_NULL(address) LAC_ASSERT_NOT_NULL(address) /** ******************************************************************************* * @ingroup LacCommon * This macro checks if a parameter is within a specified range * * @param[in] param Parameter * @param[in] min Parameter must be greater than OR equal to *min * @param[in] max Parameter must be less than max * ******************************************************************************/ #define LAC_ENSURE_RANGE(param, min, max) \ LAC_ASSERT(((param >= (min)) && (param < (max))), \ #param " is outside valid range\n") /** ******************************************************************************* * @ingroup LacCommon * This assert checks if an address is quad word aligned and is not null. * This will be compiled out for non debug releases * * @param[in] address the address we are checking * ******************************************************************************/ #define LAC_QAT_ALIGNED_ASSERT(address) \ LAC_ASSERT(((NULL != (address)) && \ (LAC_ADDRESS_ALIGNED((address), LAC_8BYTE_ALIGNMENT_SHIFT))), \ "Parameter " #address " is not correctly aligned for QAT.\n") /** ******************************************************************************* * @ingroup LacCommon * This assert checks if an address is quad word aligned and is not null. * This will be compiled out for non debug releases * * @param[in] address the address we are checking * ******************************************************************************/ #define LAC_QAT_ALIGNED_ENSURE(address) LAC_QAT_ALIGNED_ASSERT(address) /******************************************************************************/ /* ******************************************************************************* * Mutex Macros ******************************************************************************* */ /** ******************************************************************************* * @ingroup LacCommon * This macro tries to acquire a mutex and returns the status * * @param[in] pLock Pointer to Lock * @param[in] timeout Timeout * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with Mutex ******************************************************************************/ #define LAC_LOCK_MUTEX(pLock, timeout) \ ((OSAL_SUCCESS != osalMutexLock((pLock), (timeout))) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro unlocks a mutex and returns the status * * @param[in] pLock Pointer to Lock * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with Mutex ******************************************************************************/ #define LAC_UNLOCK_MUTEX(pLock) \ ((OSAL_SUCCESS != osalMutexUnlock((pLock))) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro initialises a mutex and returns the status * * @param[in] pLock Pointer to Lock * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with Mutex ******************************************************************************/ #define LAC_INIT_MUTEX(pLock) \ ((OSAL_SUCCESS != osalMutexInit((pLock))) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro destroys a mutex and returns the status * * @param[in] pLock Pointer to Lock * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with Mutex ******************************************************************************/ #define LAC_DESTROY_MUTEX(pLock) \ ((OSAL_SUCCESS != osalMutexDestroy((pLock))) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro calls a trylock on a mutex * * @param[in] pLock Pointer to Lock * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with Mutex ******************************************************************************/ #define LAC_TRYLOCK_MUTEX(pLock) \ ((OSAL_SUCCESS != osalMutexTryLock((pLock), OSAL_WAIT_NONE)) \ ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /* ******************************************************************************* * Semaphore Macros ******************************************************************************* */ /** ******************************************************************************* * @ingroup LacCommon * This macro waits on a semaphore and returns the status * * @param[in] sid The semaphore * @param[in] timeout Timeout * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with semaphore ******************************************************************************/ #define LAC_WAIT_SEMAPHORE(sid, timeout) \ ((OSAL_SUCCESS != osalSemaphoreWait(&sid, (timeout))) \ ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro checks a semaphore and returns the status * * @param[in] sid The semaphore * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with semaphore ******************************************************************************/ #define LAC_CHECK_SEMAPHORE(sid) \ ((OSAL_SUCCESS != osalSemaphoreTryWait(&sid)) ? CPA_STATUS_RETRY \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro post a semaphore and returns the status * * @param[in] sid The semaphore * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with semaphore ******************************************************************************/ #define LAC_POST_SEMAPHORE(sid) \ ((OSAL_SUCCESS != osalSemaphorePost(&sid)) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro initialises a semaphore and returns the status * * @param[in] sid The semaphore * @param[in] semValue Initial semaphore value * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with semaphore ******************************************************************************/ #define LAC_INIT_SEMAPHORE(sid, semValue) \ ((OSAL_SUCCESS != osalSemaphoreInit(&sid, semValue)) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /** ******************************************************************************* * @ingroup LacCommon * This macro destroys a semaphore and returns the status * * @param[in] sid The semaphore * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Error with semaphore ******************************************************************************/ #define LAC_DESTROY_SEMAPHORE(sid) \ ((OSAL_SUCCESS != osalSemaphoreDestroy(&sid)) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) /* ******************************************************************************* * Spinlock Macros ******************************************************************************* */ #ifdef ENABLE_SPINLOCK typedef OsalLock lac_lock_t; #define LAC_SPINLOCK_INIT(lock) \ ((OSAL_SUCCESS != osalLockInit(lock, TYPE_IGNORE)) ? CPA_STATUS_RESOURCE \ : CPA_STATUS_SUCCESS) #define LAC_SPINLOCK(lock) (void)osalLockBh(lock) #define LAC_SPINUNLOCK(lock) (void)osalUnlockBh(lock) #define LAC_SPINLOCK_DESTROY(lock) #else typedef OsalMutex lac_lock_t; #define LAC_SPINLOCK_INIT LAC_INIT_MUTEX #define LAC_SPINLOCK(lock) LAC_LOCK_MUTEX(lock, OSAL_WAIT_FOREVER) #define LAC_SPINUNLOCK LAC_UNLOCK_MUTEX #define LAC_SPINLOCK_DESTROY(lock) LAC_DESTROY_MUTEX(lock) #endif #define LAC_CONST_PTR_CAST(castee) ((void *)(LAC_ARCH_UINT)(castee)) #define LAC_CONST_VOLATILE_PTR_CAST(castee) ((void *)(LAC_ARCH_UINT)(castee)) /* Type of ring */ #define SAL_RING_TYPE_NONE 0 #define SAL_RING_TYPE_A_SYM_HI 1 #define SAL_RING_TYPE_A_SYM_LO 2 #define SAL_RING_TYPE_A_ASYM 3 #define SAL_RING_TYPE_B_SYM_HI 4 #define SAL_RING_TYPE_B_SYM_LO 5 #define SAL_RING_TYPE_B_ASYM 6 #define SAL_RING_TYPE_DC 7 #define SAL_RING_TYPE_ADMIN 8 #define SAL_RING_TYPE_TRNG 9 /* Maps Ring Service to generic service type */ static inline icp_adf_ringInfoService_t lac_getRingType(int type) { switch (type) { case SAL_RING_TYPE_NONE: return ICP_ADF_RING_SERVICE_0; case SAL_RING_TYPE_A_SYM_HI: return ICP_ADF_RING_SERVICE_1; case SAL_RING_TYPE_A_SYM_LO: return ICP_ADF_RING_SERVICE_2; case SAL_RING_TYPE_A_ASYM: return ICP_ADF_RING_SERVICE_3; case SAL_RING_TYPE_B_SYM_HI: return ICP_ADF_RING_SERVICE_4; case SAL_RING_TYPE_B_SYM_LO: return ICP_ADF_RING_SERVICE_5; case SAL_RING_TYPE_B_ASYM: return ICP_ADF_RING_SERVICE_6; case SAL_RING_TYPE_DC: return ICP_ADF_RING_SERVICE_7; case SAL_RING_TYPE_ADMIN: return ICP_ADF_RING_SERVICE_8; case SAL_RING_TYPE_TRNG: return ICP_ADF_RING_SERVICE_9; default: return ICP_ADF_RING_SERVICE_0; } return ICP_ADF_RING_SERVICE_0; } /* Maps generic service type to Ring Service type */ static inline int lac_getServiceType(icp_adf_ringInfoService_t type) { switch (type) { case ICP_ADF_RING_SERVICE_0: return SAL_RING_TYPE_NONE; case ICP_ADF_RING_SERVICE_1: return SAL_RING_TYPE_A_SYM_HI; case ICP_ADF_RING_SERVICE_2: return SAL_RING_TYPE_A_SYM_LO; case ICP_ADF_RING_SERVICE_3: return SAL_RING_TYPE_A_ASYM; case ICP_ADF_RING_SERVICE_4: return SAL_RING_TYPE_B_SYM_HI; case ICP_ADF_RING_SERVICE_5: return SAL_RING_TYPE_B_SYM_LO; case ICP_ADF_RING_SERVICE_6: return SAL_RING_TYPE_B_ASYM; case ICP_ADF_RING_SERVICE_7: return SAL_RING_TYPE_DC; case ICP_ADF_RING_SERVICE_8: return SAL_RING_TYPE_ADMIN; default: return SAL_RING_TYPE_NONE; } return SAL_RING_TYPE_NONE; } #endif /* LAC_COMMON_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_hooks.h000066400000000000000000000326001503624047500277400ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ******************************************************************************* * @file lac_hooks.h * * @defgroup LacHooks Hooks * * @ingroup LacCommon * * Component Init/Shutdown functions. These are: * - an init function which is called during the initialisation sequence, * - a shutdown function which is called by the overall shutdown function, * ******************************************************************************/ #ifndef LAC_HOOKS_H #define LAC_HOOKS_H /* ******************************************************************************** * Include public/global header files ******************************************************************************** */ #include "cpa.h" /* ******************************************************************************** * Include private header files ******************************************************************************** */ /******************************************************************************/ /** ******************************************************************************* * @ingroup LacHooks * This function initialises the Large Number (ModExp and ModInv) module * * @description * This function clears the Large Number statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacLn_Init(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function frees statistics array for Large Number module * * @description * This function frees statistics array for Large Number module * * @param[in] instanceHandle * ******************************************************************************/ void LacLn_StatsFree(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function resets statistics array for Large Number module * * @description * This function resets statistics array for Large Number module * * @param[in] instanceHandle * ******************************************************************************/ void LacLn_StatsReset(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function initialises the Prime module * * @description * This function clears the Prime statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacPrime_Init(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function frees the Prime module statistics array * * @description * This function frees the Prime module statistics array * * @param[in] instanceHandle * ******************************************************************************/ void LacPrime_StatsFree(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function resets the Prime module statistics array * * @description * This function resets the Prime module statistics array * * @param[in] instanceHandle * ******************************************************************************/ void LacPrime_StatsReset(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function initialises the DSA module * * @param[in] instanceHandle * * @description * This function clears the DSA statistics * ******************************************************************************/ CpaStatus LacDsa_Init(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function frees the DSA module statistics array * * @param[in] instanceHandle * * @description * This function frees the DSA statistics array * ******************************************************************************/ void LacDsa_StatsFree(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function resets the DSA module statistics array * * @param[in] instanceHandle * * @description * This function resets the DSA statistics array * ******************************************************************************/ void LacDsa_StatsReset(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function initialises the Diffie Hellmann module * * @description * This function initialises the Diffie Hellman statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacDh_Init(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function frees the Diffie Hellmann module statistics * * @description * This function frees the Diffie Hellmann module statistics * * @param[in] instanceHandle * ******************************************************************************/ void LacDh_StatsFree(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function resets the Diffie Hellmann module statistics * * @description * This function resets the Diffie Hellmann module statistics * * @param[in] instanceHandle * ******************************************************************************/ void LacDh_StatsReset(CpaInstanceHandle instanceHandle); /** ****************************************************************************** * @ingroup LacSymKey * This function registers the callback handlers to SSL/TLS and MGF, * allocates resources that are needed for the component * * @param[in] instanceHandle * * @retval CPA_STATUS_SUCCESS Status Success * @retval CPA_STATUS_FAIL General failure * @retval CPA_STATUS_RESOURCE Resource allocation failure * *****************************************************************************/ CpaStatus LacSymKey_Init(CpaInstanceHandle instanceHandle); /** ****************************************************************************** * @ingroup LacSymKey * This function frees up resources obtained by the key gen component * * @param[in] instanceHandle * * @retval CPA_STATUS_SUCCESS Status Success * *****************************************************************************/ CpaStatus LacSymKey_Shutdown(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function initialises the key gen statistics * * @description * This function initialises the key gen statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacSymKey_StatsInit(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function frees the key gen statistics * * @description * This function frees the key gen statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacSymKey_StatsFree(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function resets the key gen statistics * * @description * This function resets the key gen statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacSymKey_StatsReset(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function initialises the RSA module * * @description * This function clears the RSA statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacRsa_Init(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function frees the RSA module statistics * * @description * This function frees the RSA module statistics * * @param[in] instanceHandle * ******************************************************************************/ void LacRsa_StatsFree(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function resets the RSA module statistics * * @description * This function resets the RSA module statistics * * @param[in] instanceHandle * ******************************************************************************/ void LacRsa_StatsReset(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function initialises the EC module * * @description * This function clears the EC statistics * * @param[in] instanceHandle * ******************************************************************************/ CpaStatus LacEc_Init(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function frees the EC module stats array * * @description * This function frees the EC module stats array * * @param[in] instanceHandle * ******************************************************************************/ void LacEc_StatsFree(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacHooks * This function resets the EC module stats array * * @description * This function resets the EC module stats array * * @param[in] instanceHandle * ******************************************************************************/ void LacEc_StatsReset(CpaInstanceHandle instanceHandle); #endif /* LAC_HOOKS_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_list.h000066400000000000000000000164171503624047500276000ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_list.h * * @defgroup SalList * * @ingroup SalCtrl * * List structure and list functions. * ***************************************************************************/ #ifndef LAC_LIST_H #define LAC_LIST_H /** ***************************************************************************** * @ingroup SalList * * @description * List structure * *****************************************************************************/ typedef struct sal_list_s { struct sal_list_s *next; void *pObj; } sal_list_t; /** ******************************************************************************* * @ingroup SalList * Add a structure to tail of a list. * * @description * Adds pObj to the tail of list (if it exists). Allocates and sets a * new sal_list_t structure. * * @param[in] list Pointer to the head pointer of the list. * Can be NULL if no elements yet in list. * @param[in/out] tail Pointer to tail pointer of the list. * Can be NULL if no elements yet in list. * Is updated by the function to point to *tail of list if pObj has been successfully added. * @param[in] pObj Pointer to structure to add to tail of * the list. * @retval status * *****************************************************************************/ CpaStatus SalList_add(sal_list_t **list, sal_list_t **tail, void *pObj); /** ******************************************************************************* * @ingroup SalList * Delete an element from the list. * * @description * Delete an element from the list. * * @param[in/out] head_list Pointer to the head pointer of the list. * Can be NULL if no elements yet in list. * Is updated by the function * to point to list->next if head_list is *list. * @param[in/out] pre_list Pointer to the previous pointer of the *list. Can be NULL if no elements yet in list. * (*pre_list)->next is updated * by the function to point to list->next * @param[in] list Pointer to list. * *****************************************************************************/ void SalList_del(sal_list_t **head_list, sal_list_t **pre_list, sal_list_t *list); /** ******************************************************************************* * @ingroup SalList * Returns pObj element in list structure. * * @description * Returns pObj associated with sal_list_t structure. * * @param[in] list Pointer to list element. * @retval void* pObj member of list structure. * *****************************************************************************/ void *SalList_getObject(sal_list_t *list); /** ******************************************************************************* * @ingroup SalList * Set pObj to be NULL in the list. * * @description * Set pObj of a element in the list to be NULL. * * @param[in] list Pointer to list element. * *****************************************************************************/ void SalList_delObject(sal_list_t **list); /** ******************************************************************************* * @ingroup SalList * Returns next element in list structure. * * @description * Returns next associated with sal_list_t structure. * * @param[in] list Pointer to list element. * @retval void* next member of list structure. * *****************************************************************************/ void *SalList_next(sal_list_t *); /** ******************************************************************************* * @ingroup SalList * Frees memory associated with list structure. * * @description * Frees memory associated with list structure and the Obj pointed to by * the list. * * @param[in] list Pointer to list. * *****************************************************************************/ void SalList_free(sal_list_t **); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_log.h000066400000000000000000000557551503624047500274160ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_log.h * * @defgroup LacLog Log * * @ingroup LacCommon * * Logging Macros. These macros also log the function name they are called in. * ***************************************************************************/ /***************************************************************************/ #ifndef LAC_LOG_H #define LAC_LOG_H /*************************************************************************** * Include public/global header files ***************************************************************************/ #include "cpa.h" #include "Osal.h" #include "icp_accel_devices.h" #define LAC_OSAL_LOG osalLog #define LAC_OSAL_LOG_STRING osalLog #define LAC_OSAL_LOG_PARAMS osalStdLog #define _LAC_LOG_PARAM0_(level, log) \ (void)LAC_OSAL_LOG( \ level, OSAL_LOG_DEV_STDERR, "%s() - : " log "\n", __func__) /**< @ingroup LacLog * Internal macro that accepts no parameters in the string to be logged */ #define _LAC_LOG_PARAM1_(level, log, param1) \ (void)LAC_OSAL_LOG( \ level, OSAL_LOG_DEV_STDERR, "%s() - : " log "\n", __func__, param1) /**< @ingroup LacLog * Internal macro that accepts 1 parameter in the string to be logged */ #define _LAC_LOG_PARAM2_(level, log, param1, param2) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2) /**< @ingroup LacLog * Internal macro that accepts 2 parameters in the string to be logged */ #define _LAC_LOG_PARAM3_(level, log, param1, param2, param3) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2, \ param3) /**< @ingroup LacLog * Internal macro that accepts 3 parameters in the string to be logged */ #define _LAC_LOG_PARAM4_(level, log, param1, param2, param3, param4) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2, \ param3, \ param4) /**< @ingroup LacLog * Internal macro that accepts 4 parameters in the string to be logged */ #define _LAC_LOG_PARAM5_(level, log, param1, param2, param3, param4, param5) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2, \ param3, \ param4, \ param5) /**< @ingroup LacLog * Internal macro that accepts 5 parameters in the string to be logged */ #define _LAC_LOG_PARAM6_( \ level, log, param1, param2, param3, param4, param5, param6) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6) /**< @ingroup LacLog * Internal macro that accepts 6 parameters in the string to be logged */ #define _LAC_LOG_PARAM7_( \ level, log, param1, param2, param3, param4, param5, param6, param7) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7) /**< @ingroup LacLog * Internal macro that accepts 7 parameters in the string to be logged */ #define _LAC_LOG_PARAM8_(level, \ log, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7, \ param8) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7, \ param8) /**< @ingroup LacLog * Internal macro that accepts 8 parameters in the string to be logged */ #define _LAC_LOG_PARAM9_(level, \ log, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7, \ param8, \ param9) \ (void)LAC_OSAL_LOG(level, \ OSAL_LOG_DEV_STDERR, \ "%s() - : " log "\n", \ __func__, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7, \ param8, \ param9) /**< @ingroup LacLog * Internal macro that accepts 9 parameters in the string to be logged */ #define _LAC_LOG_STRING_PARAM1_(level, log, param1) \ (void)LAC_OSAL_LOG_STRING( \ level, OSAL_LOG_DEV_STDERR, "%s() - : " log "\n", __func__, param1) /**< @ingroup LacLog * Internal macro that accepts 1 parameter in the string to be logged */ #define _LAC_LOG_PARAMS_(log, ...) \ (void)LAC_OSAL_LOG_PARAMS( \ "[error] %s() - : " log "\n", __func__, __VA_ARGS__) /**< @ingroup LacLog * Internal macro that accepts 1 parameter in the string to be logged */ /************************** Lac Invalid Param Macros **************************/ #define LAC_INVALID_PARAM_LOG(log) \ _LAC_LOG_PARAM0_(OSAL_LOG_LVL_ERROR, "Invalid API Param - " log) /**< @ingroup LacLog * Invalid parameter log macro. Has the prefix "[error]" */ #define LAC_INVALID_PARAM_LOG1(log, param1) \ _LAC_LOG_PARAM1_(OSAL_LOG_LVL_ERROR, "Invalid API Param - " log, param1) /**< @ingroup LacLog * Invalid parameter log macro. Has the prefix "[error]" and also * (1 parameter in the string to be logged). */ #define LAC_INVALID_PARAM_LOG2(log, param1, param2) \ _LAC_LOG_PARAM2_( \ OSAL_LOG_LVL_ERROR, "Invalid API Param - " log, param1, param2) /**< @ingroup LacLog * Invalid parameter log macro. Has the prefix "[error]" and also accepts * 2 parameters in the string to be logged. */ /************************** Lac UnSupported Param Macros ****************/ #define LAC_UNSUPPORTED_PARAM_LOG(log) \ _LAC_LOG_PARAM0_(OSAL_LOG_LVL_ERROR, "UnSupported API Param - " log) /**< @ingroup LacLog * * UnSupported parameter log macro. Has the prefix "[error]" */ /************************** Lac Logging Macros **************************/ #define LAC_LOG(log) _LAC_LOG_PARAM0_(OSAL_LOG_LVL_USER, log) /**< @ingroup LacLog * Log a string with no prefix */ #define LAC_LOG1(log, param1) _LAC_LOG_PARAM1_(OSAL_LOG_LVL_USER, log, param1) /**< @ingroup LacLog * Log a string with no prefix * (1 parameter in the string to be logged). */ #define LAC_LOG2(log, param1, param2) \ _LAC_LOG_PARAM2_(OSAL_LOG_LVL_USER, log, param1, param2) /**< @ingroup LacLog * Log a string with no prefix * (2 parameter in the string to be logged). */ #define LAC_LOG3(log, param1, param2, param3) \ _LAC_LOG_PARAM3_(OSAL_LOG_LVL_USER, log, param1, param2, param3) /**< @ingroup LacLog * Log a string with no prefix * (3 parameters in the string to be logged). */ #define LAC_LOG4(log, param1, param2, param3, param4) \ _LAC_LOG_PARAM4_(OSAL_LOG_LVL_USER, log, param1, param2, param3, param4) /**< @ingroup LacLog * Log a string with no prefix * (4 parameters in the string to be logged). */ #define LAC_LOG5(log, param1, param2, param3, param4, param5) \ _LAC_LOG_PARAM5_( \ OSAL_LOG_LVL_USER, log, param1, param2, param3, param4, param5) /**< @ingroup LacLog * Log a string with no prefix * (5 parameters in the string to be logged). */ #define LAC_LOG6(log, param1, param2, param3, param4, param5, param6) \ _LAC_LOG_PARAM6_(OSAL_LOG_LVL_USER, \ log, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6) /**< @ingroup LacLog * Log a string with no prefix * (6 parameters in the string to be logged). */ #define LAC_LOG7(log, param1, param2, param3, param4, param5, param6, param7) \ _LAC_LOG_PARAM7_(OSAL_LOG_LVL_USER, \ log, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7) /**< @ingroup LacLog * Log a string with no prefix * (7 parameters in the string to be logged). */ #define LAC_LOG8( \ log, param1, param2, param3, param4, param5, param6, param7, param8) \ _LAC_LOG_PARAM8_(OSAL_LOG_LVL_USER, \ log, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7, \ param8) /**< @ingroup LacLog * Log a string with no prefix * (8 parameters in the string to be logged). */ #define LAC_LOG9(log, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7, \ param8, \ param9) \ _LAC_LOG_PARAM9_(OSAL_LOG_LVL_USER, \ log, \ param1, \ param2, \ param3, \ param4, \ param5, \ param6, \ param7, \ param8, \ param9) /**< @ingroup LacLog * Log a string with no prefix * (9 parameters in the string to be logged). */ /************************** Lac Error Log Macros **************************/ #define LAC_LOG_ERROR(log) _LAC_LOG_PARAM0_(OSAL_LOG_LVL_ERROR, log) /**< @ingroup LacLog * Log an error with the prefix "[error]" */ #define LAC_LOG_ERROR1(log, param1) \ _LAC_LOG_PARAM1_(OSAL_LOG_LVL_ERROR, log, param1) /**< @ingroup LacLog * Log an error with the prefix "[error]" * (1 parameter in the string to be logged). */ #define LAC_LOG_ERROR2(log, param1, param2) \ _LAC_LOG_PARAM2_(OSAL_LOG_LVL_ERROR, log, param1, param2) /**< @ingroup LacLog * Log an error with the prefix "[error]" * (2 parameters in the string to be logged). */ #define LAC_LOG_STRING_ERROR1(log, param1) \ _LAC_LOG_STRING_PARAM1_(OSAL_LOG_LVL_ERROR, log, param1) /**< @ingroup LacLog * Log an error with the prefix "[error]" * (1 parameter in the string to be logged). */ #define LAC_LOG_ERROR_PARAMS(log, ...) _LAC_LOG_PARAMS_(log, __VA_ARGS__) /**< @ingroup LacLog * Log an error with the prefix "[error]" * with more than 2 params */ /************************** Lac Debug Macros **************************/ #ifdef ICP_DEBUG #define LAC_LOG_DEBUG(log) _LAC_LOG_PARAM0_(OSAL_LOG_LVL_DEBUG1, log) /**< @ingroup LacLog * Log a message with the prefix "[debug]" */ #define LAC_LOG_DEBUG1(log, param1) \ _LAC_LOG_PARAM1_(OSAL_LOG_LVL_DEBUG1, log, param1) /**< @ingroup LacLog * Log a message with the prefix "[debug]" * (1 parameter in the string to be logged). */ #define LAC_LOG_DEBUG2(log, param1, param2) \ _LAC_LOG_PARAM2_(OSAL_LOG_LVL_DEBUG1, log, param1, param2) /**< @ingroup LacLog * Log a message with the prefix "[debug]" (2 parameters in the string to be logged). */ #else #define LAC_LOG_DEBUG(log) #define LAC_LOG_DEBUG1(log, param1) #define LAC_LOG_DEBUG2(log, param1, param2) #endif /* ICP_DEBUG */ #define LAC_LOG_BLOCK 0 #define LAC_LOG_PARTIAL_REQUEST 1 #define LAC_LOG_REQUEST 2 #define LAC_LOG_RESPONSE 3 #define LAC_LOG_MSG_ANY_SERVICE 0 #define LAC_LOG_MSG_SYMCYBULK 1 #define LAC_LOG_MSG_SYMCYTRNG 2 #define LAC_LOG_MSG_SYMCYKEY 3 #define LAC_LOG_MSG_PKE 4 #define LAC_LOG_MSG_DC 5 void LacLogMsg_SetConfig(icp_accel_dev_t *device); void set_osal_log_debug_level(void); #endif /* LAC_LOG_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_mem.h000066400000000000000000000702471503624047500274040ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_mem.h * * @defgroup LacMem Memory * * @ingroup LacCommon * * Memory re-sizing functions and memory accessor macros. * ***************************************************************************/ #ifndef LAC_MEM_H #define LAC_MEM_H /*************************************************************************** * Include header files ***************************************************************************/ #include "cpa.h" #include "Osal.h" #include "qae_mem.h" #include "lac_common.h" /** ******************************************************************************* * @ingroup LacMem * These macros are used to Endian swap variables from IA to QAT. * * @param[out] x The variable to be swapped. * * @retval none ******************************************************************************/ #if (LAC_BYTE_ORDER == __LITTLE_ENDIAN) #define LAC_MEM_WR_64(x) OSAL_HOST_TO_NW_64(x) #define LAC_MEM_WR_32(x) OSAL_HOST_TO_NW_32(x) #define LAC_MEM_WR_16(x) OSAL_HOST_TO_NW_16(x) #define LAC_MEM_RD_64(x) OSAL_NW_TO_HOST_64(x) #define LAC_MEM_RD_32(x) OSAL_NW_TO_HOST_32(x) #define LAC_MEM_RD_16(x) OSAL_NW_TO_HOST_16(x) #else #define LAC_MEM_WR_64(x) (x) #define LAC_MEM_WR_32(x) (x) #define LAC_MEM_WR_16(x) (x) #define LAC_MEM_RD_64(x) (x) #define LAC_MEM_RD_32(x) (x) #define LAC_MEM_RD_16(x) (x) #endif #define LAC_MEM_SYSTEM_PAGE_SIZE OSAL_PAGE_SIZE /**< @ingroup LacMem * Size of the OS PAGE size as defined by OSAL */ /* ******************************************************************************* * Shared Memory Macros (memory accessible by Acceleration Engines, e.g. QAT) ******************************************************************************* */ /** ******************************************************************************* * @ingroup LacMem * This macro can be used to write to a variable that will be read by the * QAT. The macro will automatically detect the size of the target variable and * will select the correct method for performing the write. The data is cast to * the type of the field that it will be written to. * This macro swaps data if required. * * @param[out] var The variable to be written. Can be a field of a struct. * * @param[in] data The value to be written. Will be cast to the size of the * target. * * @retval none ******************************************************************************/ #define LAC_MEM_SHARED_WRITE_SWAP(var, data) \ do \ { \ switch (sizeof(var)) \ { \ case 1: \ (var) = (Cpa8U)(data); \ break; \ case 2: \ (var) = (Cpa16U)(data); \ (var) = LAC_MEM_WR_16(((Cpa16U)var)); \ break; \ case 4: \ (var) = (Cpa32U)(data); \ (var) = LAC_MEM_WR_32(((Cpa32U)var)); \ break; \ case 8: \ (var) = (Cpa64U)(data); \ (var) = (Cpa32U)LAC_MEM_WR_64(((Cpa64U)var)); \ break; \ default: \ break; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacMem * This macro can be used to read a variable that was written by the QAT. * The macro will automatically detect the size of the data to be read and will * select the correct method for performing the read. The value read from the * variable is cast to the size of the data type it will be stored in. * This macro swaps data if required. * * @param[in] var The variable to be read. Can be a field of a struct. * * @param[out] data The variable to hold the result of the read. Data read * will be cast to the size of this variable * * @retval none ******************************************************************************/ #define LAC_MEM_SHARED_READ_SWAP(var, data) \ do \ { \ switch (sizeof(var)) \ { \ case 1: \ (data) = (var); \ break; \ case 2: \ (data) = LAC_MEM_RD_16(((Cpa16U)var)); \ break; \ case 4: \ (data) = LAC_MEM_RD_32(((Cpa32U)var)); \ break; \ case 8: \ (data) = LAC_MEM_RD_64(((Cpa64U)var)); \ break; \ default: \ break; \ } \ } while (0) /** ******************************************************************************* * @ingroup LacMem * This macro can be used to write a pointer to a QAT request. The fields * for pointers in the QAT request and response messages are always 64 bits * * @param[out] var The variable to be written to. Can be a field of a struct. * * @param[in] data The value to be written. Will be cast to size of target * variable * * @retval none ******************************************************************************/ /* cast pointer to scalar of same size of the native pointer */ #define LAC_MEM_SHARED_WRITE_FROM_PTR(var, data) \ ((var) = (Cpa64U)(LAC_ARCH_UINT)(data)) /* Note: any changes to this macro implementation should also be made to the * similar LAC_MEM_CAST_PTR_TO_UINT64 macro */ /** ******************************************************************************* * @ingroup LacMem * This macro can be used to read a pointer from a QAT response. The fields * for pointers in the QAT request and response messages are always 64 bits * * @param[in] var The variable to be read. Can be a field of a struct. * * @param[out] data The variable to hold the result of the read. Data read * will be cast to the size of this variable * * @retval none ******************************************************************************/ /* Cast back to native pointer */ #define LAC_MEM_SHARED_READ_TO_PTR(var, data) \ ((data) = (void *)(LAC_ARCH_UINT)(var)) /** ******************************************************************************* * @ingroup LacMem * This macro safely casts a pointer to a Cpa64U type. * * @param[in] pPtr The pointer to be cast. * * @retval pointer cast to Cpa64U ******************************************************************************/ #define LAC_MEM_CAST_PTR_TO_UINT64(pPtr) ((Cpa64U)(pPtr)) /** ******************************************************************************* * @ingroup LacMem * This macro converts from a virtual address to a physical address for * internally allocated memory. * * @param[in] pGenService Pointer to sal_service_t structure. * @param[in] pVirtAddr The address to be converted. * * @retval The converted physical address ******************************************************************************/ #ifdef USER_SPACE #define LAC_OS_VIRT_TO_PHYS_INTERNAL(pGenService, pVirtAddr) \ ((SalMem_virt2PhysInternal(pVirtAddr, (void *)pGenService))) #else #define LAC_OS_VIRT_TO_PHYS_INTERNAL(pGenService, pVirtAddr) \ (OSAL_MMU_VIRT_TO_PHYS(pVirtAddr)) #endif /** ******************************************************************************* * @ingroup LacMem * This macro should be called on all externally allocated memory it calls * SalMem_virt2PhysExternal function which allows a user * to set the virt2phys function used by an instance. * Defaults to osal virt to phys for kernel. * * @param[in] genService Generic sal_service_t structure. * @param[in] pVirtAddr The address to be converted. * * @retval The converted physical address ******************************************************************************/ #define LAC_OS_VIRT_TO_PHYS_EXTERNAL(genService, pVirtAddr) \ ((SalMem_virt2PhysExternal(pVirtAddr, &(genService)))) /** ******************************************************************************* * @ingroup LacMem * This macro can be used to write an address variable that will be read by * the QAT. The macro will perform the necessary virt2phys address translation * This macro is to be used on memory allocated externally by the user. It calls * the user supplied virt2phys address translation. * * @param[in] pService The pointer to the service * @param[out] var The address variable to write. Can be a field of a struct * @param[in] pPtr The pointer variable to containing the address to be * written * * @retval none ******************************************************************************/ #define LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(pService, var, pPtr) \ do \ { \ Cpa64U physAddr = 0; \ physAddr = LAC_MEM_CAST_PTR_TO_UINT64( \ LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService, pPtr)); \ var = physAddr; \ } while (0) /* ******************************************************************************* * OS Memory Macros ******************************************************************************* */ /** ******************************************************************************* * @ingroup LacMem * This function and associated macro allocates the memory for the given * size and stores the address of the memory allocated in the pointer. * * @param[out] ppMemAddr address of pointer where address will be stored * @param[in] sizeBytes the size of the memory to be allocated. * * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory * @retval CPA_STATUS_SUCCESS Macro executed successfully * ******************************************************************************/ static __inline CpaStatus LacMem_OsMemAlloc(void **ppMemAddr, Cpa32U sizeBytes) { *ppMemAddr = osalMemAlloc(sizeBytes); if (NULL == *ppMemAddr) { return CPA_STATUS_RESOURCE; } return CPA_STATUS_SUCCESS; } /** ******************************************************************************* * @ingroup LacMem * This function and associated macro allocates the contiguous * memory for the given * size and stores the address of the memory allocated in the pointer. * * @param[out] ppMemAddr address of pointer where address will be stored * @param[in] sizeBytes the size of the memory to be allocated. * @param[in] alignmentBytes the alignment * @param[in] node node to allocate from * * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory * @retval CPA_STATUS_SUCCESS Macro executed successfully * ******************************************************************************/ static __inline CpaStatus LacMem_OsContigAlignMemAlloc(void **ppMemAddr, Cpa32U sizeBytes, Cpa32U alignmentBytes, Cpa32U node) { #if defined(ICP_PARAM_CHECK) if ((alignmentBytes & (alignmentBytes - 1)) != 0) /* if is not power of 2 */ { *ppMemAddr = NULL; LAC_INVALID_PARAM_LOG("alignmentBytes MUST be the power of 2;\r\n"); return CPA_STATUS_INVALID_PARAM; } #endif #ifdef KERNEL_SPACE *ppMemAddr = osalMemAllocContiguousNUMA(sizeBytes, node, alignmentBytes); #else *ppMemAddr = qaeMemAllocNUMA(sizeBytes, node, alignmentBytes); #endif if (NULL == *ppMemAddr) { return CPA_STATUS_RESOURCE; } return CPA_STATUS_SUCCESS; } /** ******************************************************************************* * @ingroup LacMem * Macro from the LacMem_OsMemAlloc function * ******************************************************************************/ #define LAC_OS_MALLOC(ppMemAddr, sizeBytes) \ LacMem_OsMemAlloc((void *)(ppMemAddr), (sizeBytes)) /** ******************************************************************************* * @ingroup LacMem * Macro from the LacMem_OsContigAlignMemAlloc function * ******************************************************************************/ #define LAC_OS_CAMALLOC(ppMemAddr, sizeBytes, alignmentBytes, node) \ LacMem_OsContigAlignMemAlloc( \ (void *)ppMemAddr, sizeBytes, alignmentBytes, node) /** ******************************************************************************* * @ingroup LacMem * Macro for declaration static const unsigned int constant. One provides * the compilation time computation with the highest bit set in the * sizeof(TYPE) value. The constant is being put by the linker by default in * .rodata section * * E.g. Statement LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t) * results in following entry: * static const unsigned int highest_bit_of_lac_mem_blk_t = 3 * * CAUTION! * Macro is prepared only for type names NOT-containing ANY * special characters. Types as amongst others: * - void * * - unsigned long * - unsigned int * are strictly forbidden and will result in compilation error. * Use typedef to provide one-word type name for MACRO's usage. ******************************************************************************/ #define LAC_DECLARE_HIGHEST_BIT_OF(TYPE) \ static const unsigned int highest_bit_of_##TYPE = \ (sizeof(TYPE) & 0x80000000 ? 31 : \ (sizeof(TYPE) & 0x40000000 ? 30 : \ (sizeof(TYPE) & 0x20000000 ? 29 : \ (sizeof(TYPE) & 0x10000000 ? 28 : \ (sizeof(TYPE) & 0x08000000 ? 27 : \ (sizeof(TYPE) & 0x04000000 ? 26 : \ (sizeof(TYPE) & 0x02000000 ? 25 : \ (sizeof(TYPE) & 0x01000000 ? 24 : \ (sizeof(TYPE) & 0x00800000 ? 23 : \ (sizeof(TYPE) & 0x00400000 ? 22 : \ (sizeof(TYPE) & 0x00200000 ? 21 : \ (sizeof(TYPE) & 0x00100000 ? 20 : \ (sizeof(TYPE) & 0x00080000 ? 19 : \ (sizeof(TYPE) & 0x00040000 ? 18 : \ (sizeof(TYPE) & 0x00020000 ? 17 : \ (sizeof(TYPE) & 0x00010000 ? 16 : \ (sizeof(TYPE) & 0x00008000 ? 15 : \ (sizeof(TYPE) & 0x00004000 ? 14 : \ (sizeof(TYPE) & 0x00002000 ? 13 : \ (sizeof(TYPE) & 0x00001000 ? 12 : \ (sizeof(TYPE) & 0x00000800 ? 11 : \ (sizeof(TYPE) & 0x00000400 ? 10 : \ (sizeof(TYPE) & 0x00000200 ? 9 : \ (sizeof(TYPE) & 0x00000100 ? 8 : \ (sizeof(TYPE) & 0x00000080 ? 7 : \ (sizeof(TYPE) & 0x00000040 ? 6 : \ (sizeof(TYPE) & 0x00000020 ? 5 : \ (sizeof(TYPE) & 0x00000010 ? 4 : \ (sizeof(TYPE) & 0x00000008 ? 3 : \ (sizeof(TYPE) & 0x00000004 ? 2 : \ (sizeof(TYPE) & 0x00000002 ? 1 : \ (sizeof(TYPE) & 0x00000001 ? 0 : 32) ))))))))))))))))/*16*/))))))))))))))) /* 31 */ /** ******************************************************************************* * @ingroup LacMem * This function and associated macro frees the memory at the given address * and resets the pointer to NULL * * @param[out] ppMemAddr address of pointer where mem address is stored. * If pointer is NULL, the function will exit silently * * @retval void * ******************************************************************************/ static __inline void LacMem_OsMemFree(void **ppMemAddr) { if (NULL != *ppMemAddr) { osalMemFree(*ppMemAddr); *ppMemAddr = NULL; } } /** ******************************************************************************* * @ingroup LacMem * This function and associated macro frees the contiguous memory at the * given address and resets the pointer to NULL * * @param[out] ppMemAddr address of pointer where mem address is stored. * If pointer is NULL, the function will exit silently * * @retval void * ******************************************************************************/ static __inline void LacMem_OsContigAlignMemFree(void **ppMemAddr) { if (NULL != *ppMemAddr) { #ifdef KERNEL_SPACE osalMemFreeNUMA(*ppMemAddr); #else qaeMemFreeNUMA(ppMemAddr); #endif *ppMemAddr = NULL; } } #define LAC_OS_FREE(pMemAddr) LacMem_OsMemFree((void *)&pMemAddr) #define LAC_OS_CAFREE(pMemAddr) LacMem_OsContigAlignMemFree((void *)&pMemAddr) /** ******************************************************************************* * @ingroup LacMem * Copies user data to a working buffer of the correct size (required by * PKE services) * * @description * This function produces a correctly sized working buffer from the input * user buffer. If the original buffer is too small a new buffer shall * be allocated and memory is copied (left padded with zeros to the * required length). * * The returned working buffer is guaranteed to be of the desired size for * QAT. * * When this function is called pInternalMem describes the user_buffer and * when the function returns pInternalMem describes the working buffer. * This is because pInternalMem describes the memory that will be sent to * QAT. * * The caller must keep the original buffer pointer. The allocated buffer * is freed (as necessary) using icp_LacBufferRestore(). * * @param[in] instanceHandle Handle to crypto instance so pke_resize mem pool * can be located * @param[in] pUserBuffer Pointer on the user buffer * @param[in] userLen length of the user buffer * @param[in] workingLen length of the working (correctly sized) buffer * @param[in/out] pInternalMem pointer to boolean if CPA_TRUE on input then * user_buffer is internally allocated memory * if false then it is externally allocated. * This value gets updated by the function * if the returned pointer references internally * allocated memory. * * @return a pointer to the working (correctly sized) buffer or NULL if the * allocation failed * * @note the working length cannot be smaller than the user buffer length * * @warning the working buffer may be the same or different from the original * user buffer; the caller should make no assumptions in this regard * * @see icp_LacBufferRestore() * ******************************************************************************/ Cpa8U *icp_LacBufferResize(CpaInstanceHandle instanceHandle, Cpa8U *pUserBuffer, Cpa32U userLen, Cpa32U workingLen, CpaBoolean *pInternalMemory); /** ******************************************************************************* * @ingroup LacMem * Restores a user buffer * * @description * This function restores a user buffer and releases its * corresponding working buffer. The working buffer, assumed to be * previously obtained using icp_LacBufferResize(), is freed as necessary. * * The contents are copied in the process. * * @note the working length cannot be smaller than the user buffer length * * @param[out] pUserBuffer Pointer on the user buffer * @param[in] userLen length of the user buffer * @param[in] pWorkingBuffer Pointer on the working buffer * @param[in] workingLen working buffer length * @param[in] copyBuf if set _TRUE the data in the workingBuffer * will be copied to the userBuffer before the * workingBuffer is freed. * * @return the status of the operation * * @see icp_LacBufferResize() * ******************************************************************************/ CpaStatus icp_LacBufferRestore(Cpa8U *pUserBuffer, Cpa32U userLen, Cpa8U *pWorkingBuffer, Cpa32U workingLen, CpaBoolean copyBuf); /** ******************************************************************************* * @ingroup LacMem * Uses an instance specific user supplied virt2phys function to convert a * virtual address to a physical address. * * @description * Uses an instance specific user supplied virt2phys function to convert a * virtual address to a physical address. A client of QA API can set the * virt2phys function for an instance by using the * cpaXxSetAddressTranslation() function. If the client does not set the * virt2phys function and the instance is in kernel space then OS specific * virt2phys function will be used. In user space the virt2phys function * MUST be set by the user. * * @param[in] pVirtAddr the virtual addr to be converted * @param[in] pServiceGen Pointer on the sal_service_t structure * so client supplied virt2phys function can be * called. * * @return the physical address * ******************************************************************************/ CpaPhysicalAddr SalMem_virt2PhysExternal(void *pVirtAddr, void *pServiceGen); /** ******************************************************************************* * @ingroup LacMem * Convert a virtual address to a physical address using internal function. * * @description * Convert a virtual address to a physical address using internal function. * * @param[in] pVirtAddr the virtual addr to be converted * @param[in] pServiceGen Pointer on the sal_service_t structure * * @return the physical address * ******************************************************************************/ CpaPhysicalAddr SalMem_virt2PhysInternal(void *pVirtAddr, void *pServiceGen); #endif /* LAC_MEM_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_mem_pools.h000066400000000000000000000376411503624047500306210ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_mem_pools.h * * @defgroup LacMemPool Memory Pool Mgmt * * @ingroup LacCommon * * Memory Pool creation and mgmt functions * * @lld_start * @lld_overview * This component is designed as a set of utility functions for the * creation of pre-allocated memory pools. Each pool will be created using OS * memory with a user specified number of elements, element size and element * alignment(alignment is at byte granularity). * @lld_dependencies * These utilities rely on OSAL for locking mechanisms and memory allocation * @lld_initialisation * Pool creation needs to be done by each component. There is no specific * initialisation required for this feature. * @lld_module_algorithms * The following is a diagram of how the memory is laid out for each block * in a pool. Each element must be aligned on the boundary requested for in the * create call. In order to hide the management of the pools from the user, * the memory block data is hidden prior to the * data pointer. This way it can be accessed easily on a free call with pointer * arithmetic. The Padding at the start is simply there for alignment and is * unused in the pools. * * ------------------------------------------------------- * * |Padding |lac_mem_blk_t | client memory | * * @lld_process_context * @lld_end ***************************************************************************/ /** ******************************************************************************* * @ingroup LacMemPool * * ******************************************************************************/ /***************************************************************************/ #ifndef LAC_MEM_POOLS_H #define LAC_MEM_POOLS_H #include "cpa.h" #include "lac_common.h" #ifdef __LP64__ typedef unsigned int atomic_int __attribute__((mode(TI))); #else typedef unsigned int atomic_int __attribute__((mode(DI))); #endif typedef union { struct { unsigned long ctr; void *ptr; }; atomic_int atomic; } pointer_t; typedef struct { volatile pointer_t top; } lock_free_stack_t; typedef LAC_ARCH_UINT lac_memory_pool_id_t; /**< @ingroup LacMemPool * Pool ID type to be used by all clients */ /**< @ingroup LacMemPool * This structure is used to link each memory block in the created pool * together and contain the necessary information for deletion of the block */ typedef struct lac_mem_blk_s { struct lac_mem_blk_s *pNext; /**< link to next block in the pool */ CpaPhysicalAddr physDataPtr; /**< physical address of data pointer for client */ void *pMemAllocPtr; /**< virtual address of the memory block actually allocated */ CpaBoolean isInUse; /**< indicates if the pool item is in use */ struct lac_mem_pool_hdr_s *pPoolID; /**< identifier of the pool that this block was allocated from */ Cpa64U opaque; /**< opaque data */ } lac_mem_blk_t; typedef struct lac_memblk_bucket_s { lac_mem_blk_t **mem_blk; Cpa32U startIndex; /**< records the start index of the array */ Cpa32U numBucketBlks; /**< the number of used memblk */ Cpa32U numBlksInRing; /**< the number of memblk which has been put in the ring */ } lac_memblk_bucket_t; #define LAC_MEM_POOLS_NAME_SIZE 16 /**< @ingroup LacMemPool * 16 bytes including '\\0' terminator to prevent padding in the structure */ /**< @ingroup LacMemPool * This structure is used to manage each pool created using this utility * feature. The client will maintain a pointer (identifier) to the created * structure per pool. */ typedef struct lac_mem_pool_hdr_s { lock_free_stack_t stack; char poolName[LAC_MEM_POOLS_NAME_SIZE]; /*16 bytes of a pool name */ /**< up to 16 bytes of a pool name */ unsigned int numElementsInPool; /**< number of elements in the Pool */ unsigned int blkSizeInBytes; /**< Block size in bytes */ unsigned int blkAlignmentInBytes; /**< block alignment in bytes */ lac_mem_blk_t **trackBlks; /* An array of mem block pointers to track the allocated entries in pool */ volatile size_t availBlks; /* Number of blocks available for allocation in this pool */ CpaBoolean active; /* Indicate the pool is available for allocation */ OsalAtomic sync; /* Prevent concurrent access to the pool */ } lac_mem_pool_hdr_t; #define LAC_MEM_POOL_BLK_GET_OPAQUE(entry) \ (((lac_mem_blk_t *)((LAC_ARCH_UINT)entry - sizeof(lac_mem_blk_t)))->opaque) #define LAC_MEM_POOL_BLK_SET_OPAQUE(entry, value) \ (((lac_mem_blk_t *)((LAC_ARCH_UINT)entry - sizeof(lac_mem_blk_t))) \ ->opaque = value) #define LAC_MEM_POOL_VIRT_TO_PHYS(pVirtAddr) \ (((lac_mem_blk_t *)((LAC_ARCH_UINT)pVirtAddr - sizeof(lac_mem_blk_t))) \ ->physDataPtr) /**< @ingroup LacMemPool * macro for retrieving the physical address of the memory block. */ #define LAC_MEM_POOL_INIT_POOL_ID 0 /**< @ingroup LacMemPool * macro which defines the valid initialisation value for a pool ID. This is * used as a level of abstraction for the user of this interface */ /** ******************************************************************************* * @ingroup LacMemPool * This function creates a memory pool containing a specified number of * elements of specific size and byte alignment. This function is not reentrant * or thread safe and is only intended to be called during initialisation. * * @blocking * Yes * @reentrant * No * @threadSafe * No * @param[out] poolID on successful creation of a pool this will * be the ID used for all subsequent accesses * @param[in] poolName The name of the memory pool * @param[in] numElementsInPool number of elements to provision in the pool * @param[in] blkSizeInBytes size in bytes of each element in the pool * @param[in] blkAlignmentInBytes byte alignment required for each element * @param[in] trackMemory track the memory in use by this pool * @param[in] node node to allocate from * * @retval CPA_STATUS_INVALID_PARAM invalid input parameter * @retval CPA_STATUS_RESOURCE error in provisioning resources * @retval CPA_STATUS_SUCCESS function executed successfully * ******************************************************************************/ CpaStatus Lac_MemPoolCreate(lac_memory_pool_id_t *poolID, char *poolName, unsigned int numElementsInPool, unsigned int blkSizeInBytes, unsigned int blkAlignmentInBytes, CpaBoolean trackMemory, Cpa32U node); /** ******************************************************************************* * @ingroup LacMemPool * This function will destroy the memory pool in it's current state. All memory * blocks which have been returned to the memory pool will be de-allocated and * the pool indetifier will be freed and assigned to NULL. It is the * responsibility of the pool creators to return all memory before a destroy or * memory will be leaked. * * @blocking * Yes * @reentrant * No * @threadSafe * No * @param[in] poolID Pointer to the memory pool to destroy * ******************************************************************************/ void Lac_MemPoolDestroy(lac_memory_pool_id_t poolID); /** ******************************************************************************* * @ingroup LacMemPool * This function enables the allocation of a block from a previously created * memory pool. * * @blocking * No * @reentrant * No * @threadSafe * No * @param[in] poolID Pointer to the memory pool to enable. * ******************************************************************************/ void Lac_MemPoolEnable(lac_memory_pool_id_t poolID); /** ******************************************************************************* * @ingroup LacMemPool * This function prevents the allocation of a block from a previously created * memory pool. * * @blocking * No * @reentrant * No * @threadSafe * No * @param[in] poolID Pointer to the memory pool to disable. * ******************************************************************************/ void Lac_MemPoolDisable(lac_memory_pool_id_t poolID); /** ******************************************************************************* * @ingroup LacMemPool * This function allocates a block from the pool which has been previously * created. It does not check the validity of the pool Id prior to accessing the * pool. It is up to the calling code to ensure the value is correct. * * @blocking * Yes * @reentrant * Yes * @threadSafe * Yes * @param[in] poolID ID of the pool to allocate memory from * * @retval pointer to the memory which has been allocated from the pool * ******************************************************************************/ void *Lac_MemPoolEntryAlloc(lac_memory_pool_id_t poolID); /** ******************************************************************************* * @ingroup LacMemPool * This function de-allocates the memory passed in back to the pool from which * it was allocated. * * @blocking * Yes * @reentrant * Yes * @threadSafe * Yes * @param[in] entry memory address of the block to be freed * ******************************************************************************/ void Lac_MemPoolEntryFree(void *entry); /** ******************************************************************************* * @ingroup LacMemPool * This function returns the number of available entries in a particular pool * * @blocking * No * @reentrant * No * @threadSafe * No * @param[in] poolID ID of the pool * * @retval number of elements left for allocation from the pool * ******************************************************************************/ unsigned int Lac_MemPoolAvailableEntries(lac_memory_pool_id_t poolID); /** ******************************************************************************* * @ingroup LacMemPool * This function displays the stats associated with the memory pools * * @blocking * No * @reentrant * No * @threadSafe * No * ******************************************************************************/ void Lac_MemPoolStatsShow(void); /** ******************************************************************************* * @ingroup LacMemPool * This function initialises the physical addresses of the symmetric cookie * * @blocking * No * @reentrant * No * @threadSafe * No * @param[in] poolID ID of the pool * @param[in] instanceHandle instanceHandle * * @retval CPA_STATUS_FAIL function failed * @retval CPA_STATUS_SUCCESS function executed successfully * ******************************************************************************/ CpaStatus Lac_MemPoolInitSymCookiesPhyAddr(lac_memory_pool_id_t poolID, CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacMemPool * This function populates all PKE requests with instance constant parameters * * @blocking * No * @reentrant * No * @threadSafe * No * @param[in] poolID ID of the pool * @param[in] instanceHandle instanceHandle * * @retval CPA_STATUS_FAIL function failed * @retval CPA_STATUS_SUCCESS function executed successfully * ******************************************************************************/ CpaStatus Lac_MemPoolInitAsymCookies(lac_memory_pool_id_t poolID, CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup LacMemPool * This function setting the opaque field in each cookie buffer to * ICP_ADF_INVALID_SEND_SEQ. * * @blocking * No * @reentrant * No * @threadSafe * No * @param[in] poolID ID of the pool * * @retval CPA_STATUS_FAIL function failed * @retval CPA_STATUS_SUCCESS function executed successfully * ******************************************************************************/ CpaStatus Lac_MemPoolInitDcCookies(lac_memory_pool_id_t poolID); /** ******************************************************************************* * @ingroup LacMemPool * This function gets the sync lock of the memory pool to prevent concurrent * access to it. * * @blocking * Yes * @reentrant * No * @threadSafe * Yes * @param[in] poolID ID of the pool * * @retval CPA_FALSE function failed * @retval CPA_TRUE function executed successfully * ******************************************************************************/ CpaBoolean Lac_MemPoolTestAndGet(lac_memory_pool_id_t poolID); #endif /*LAC_MEM_POOLS_H*/ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_sal.h000066400000000000000000000671421503624047500274050ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file lac_sal.h * * @defgroup SalCtrl Service Access Layer Controller * * @ingroup SalCtrl * * @description * These functions are the functions to be executed for each state * of the state machine for each service. * *****************************************************************************/ #ifndef LAC_SAL_H #define LAC_SAL_H #include "cpa_cy_im.h" #include "cpa_cy_sym.h" /** ******************************************************************************* * @ingroup SalCtrl * @description * This function allocates memory for a specific instance type. * Zeros this memory and sets the generic service section of * the instance memory. * * @context * This function is called from the generic services init. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] service The type of the service to be created * (e.g. CRYPTO) * @param[in] instance_num The logical instance number which will * run the service * @param[out] pObj Pointer to specific service instance memory * @retVal CPA_STATUS_SUCCESS Instance memory successfully allocated * @retVal CPA_STATUS_RESOURCE Instance memory not successfully allocated * @retVal CPA_STATUS_FAIL Unsupported service type * *****************************************************************************/ CpaStatus SalCtrl_ServiceCreate(sal_service_type_t service, Cpa32U instance_num, sal_service_t **pObj); /** ******************************************************************************* * @ingroup SalCtl * @description * This macro goes through the 'list' passed in as a parameter. For each * element found in the list, it performs a cast to the type of the element * given by the 'type' parameter. Finally, it calls the function given by * the 'function' parameter, passing itself and the device as parameters. * * In case of error (i.e. 'function' does not return _SUCCESS or _RETRY) * processing of the 'list' elements will stop and the status_ret will be * updated. * * In case of _RETRY status_ret will be updated but the 'list' * will continue to be processed. _RETRY is only expected when * 'function' is stop. * * @context * This macro is used by both the service and qat event handlers. * * @assumptions * None * @sideEffects * None * * @param[in] list The list of services or qats as a type of list_t * @param[in] type It identifies the type of the object inside the * list: service or qat * @param[in] device The ADF accelerator handle for the device * @param[in] function The function pointer to call * @param[in/out] status_ret If an error occurred (i.e. status returned from * function is not _SUCCESS) then status_ret is * overwritten with status returned from function. * *****************************************************************************/ #define SAL_FOR_EACH(list, type, device, function, status_ret) \ do \ { \ sal_list_t *curr_element = list; \ CpaStatus status_temp = CPA_STATUS_SUCCESS; \ type *process = NULL; \ while (NULL != curr_element) \ { \ process = (type *)SalList_getObject(curr_element); \ status_temp = process->function(device, process); \ if ((CPA_STATUS_SUCCESS != status_temp) && \ (CPA_STATUS_RETRY != status_temp)) \ { \ status_ret = status_temp; \ break; \ } \ else \ { \ if (CPA_STATUS_RETRY == status_temp) \ { \ status_ret = status_temp; \ } \ } \ curr_element = SalList_next(curr_element); \ } \ } while (0) /** ******************************************************************************* * @ingroup SalCtl * @description * This macro goes through the 'list' passed in as a parameter. For each * element found in the list, it performs a cast to the type of the element * given by the 'type' parameter. Finally, it checks the state of the * element and if it is in state 'state_check' then it calls the * function given by the 'function' parameter, passing itself * and the device as parameters. * If the element is not in 'state_check' it returns from the macro. * * In case of error (i.e. 'function' does not return _SUCCESS) * processing of the 'list' elements will continue. * * @context * This macro is used by both the service and qat event handlers. * * @assumptions * None * @sideEffects * None * * @param[in] list The list of services or qats as a type of list_t * @param[in] type It identifies the type of the object * inside the list: service or qat * @param[in] device The ADF accelerator handle for the device * @param[in] function The function pointer to call * @param[in] state_check The state to check for * *****************************************************************************/ #define SAL_FOR_EACH_STATE(list, type, device, function, state_check) \ do \ { \ sal_list_t *curr_element = list; \ type *process = NULL; \ while (NULL != curr_element) \ { \ process = (type *)SalList_getObject(curr_element); \ if (process->state == state_check) \ { \ process->function(device, process); \ } \ else \ { \ break; \ } \ curr_element = SalList_next(curr_element); \ } \ } while (0) #ifndef ICP_DC_ONLY /************************************************************************* * @ingroup SalCtrl * @description * This function is used to initialize an instance of crypto service. * It creates a crypto instance's memory pools. It calls ADF to create * its required transport handles. It calls the sub crypto service init * functions. Resets the stats. * * @context * This function is called from the SalCtrl_ServiceEventInit function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A crypto instance * *************************************************************************/ CpaStatus SalCtrl_CryptoInit(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to start an instance of crypto service. * It sends the first messages to FW on its crypto instance transport * handles. For asymmetric crypto it verifies the header on the downloaded * MMP library. * * @context * This function is called from the SalCtrl_ServiceEventStart function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A crypto instance * *************************************************************************/ CpaStatus SalCtrl_CryptoStart(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to stop an instance of crypto service. * It checks for in-flight messages to the FW. If no messages are pending * it returns success. If messages are pending it returns retry. * * @context * This function is called from the SalCtrl_ServiceEventStop function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A crypto instance * *************************************************************************/ CpaStatus SalCtrl_CryptoStop(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to shutdown an instance of crypto service. * It frees resources allocated at initialisation - e.g. frees the * memory pools and ADF transport handles. * * @context * This function is called from the SalCtrl_ServiceEventShutdown function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A crypto instance * *************************************************************************/ CpaStatus SalCtrl_CryptoShutdown(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to notify instances that an error occurred. * * @context * This function is called from the SalCtrl_ServiceEventError function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A crypto instance * *************************************************************************/ CpaStatus SalCtrl_CryptoError(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to reset an instance of crypto service. * It cleans resources allocated at initialisation - e.g. cleans the * memory pools and ADF transport handles. * * @context * This function is called from the SalCtrl_ServiceEventRestarting function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A crypto instance * *************************************************************************/ CpaStatus SalCtrl_CryptoRestarting(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to reinitialize an instance of crypto service. * It reinitialzes resources allocated at initialisation - e.g. reinitializes * the memory pools and ADF transport handles. * * @context * This function is called from the SalCtrl_ServiceEventRestarted function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A crypto instance * *************************************************************************/ CpaStatus SalCtrl_CryptoRestarted(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function sets the capability info of crypto instances. * * @context * This function is called from the cpaCyQueryCapabilities and * LacSymSession_ParamCheck function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] service A sal_service_t* type * @param[in] cyCapabilityInfo A CpaCyCapabilitiesInfo* type * *************************************************************************/ void SalCtrl_CyQueryCapabilities(sal_service_t *pGenericService, CpaCyCapabilitiesInfo *pCapInfo); /************************************************************************* * @ingroup SalCtrl * @description * This function sets the capability info of crypto sym instances. * * @context * This function is called from the cpaCySymQueryCapabilities API and * other internal functions. * * @assumptions * None * @sideEffects * None * @reentrant * No * * @param[in] pGenericService A sal_service_t* type * @param[in] pCapInfo A CpaCyCapabilitiesInfo* type * *************************************************************************/ CpaStatus SalCtrl_CySymQueryCapabilities(sal_service_t *pGenericService, CpaCySymCapabilitiesInfo *pCapInfo); #endif /************************************************************************* * @ingroup SalCtrl * @description * This function is used to initialize an instance of compression service. * It creates a compression instance's memory pools. It calls ADF to create * its required transport handles. It zeros an instances stats. * * @context * This function is called from the SalCtrl_ServiceEventInit function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A compression instance * *************************************************************************/ CpaStatus SalCtrl_CompressionInit(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to start an instance of compression service. * * @context * This function is called from the SalCtrl_ServiceEventStart function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A compression instance * *************************************************************************/ CpaStatus SalCtrl_CompressionStart(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to stop an instance of compression service. * It checks for in-flight messages to the FW. If no messages are pending * it returns success. If messages are pending it returns retry. * * @context * This function is called from the SalCtrl_ServiceEventStop function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A compression instance * *************************************************************************/ CpaStatus SalCtrl_CompressionStop(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to shutdown an instance of compression service. * It frees resources allocated at initialisation - e.g. frees the * memory pools and ADF transport handles. * * @context * This function is called from the SalCtrl_ServiceEventShutdown function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A compression instance * *************************************************************************/ CpaStatus SalCtrl_CompressionShutdown(icp_accel_dev_t *device, sal_service_t *service); CpaStatus SalCtrl_CompressionError(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to reset(clean) an instance of compression * service. It cleans resources allocated at initialisation - e.g. cleans the * memory pools and ADF transport handles. * * @context * This function is called from the SalCtrl_ServiceEventRestarting function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A compression instance * *************************************************************************/ CpaStatus SalCtrl_CompressionRestarting(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to reinitialize an instance of compression * service. It reinitializes resources allocated at initialisation - e.g. * initializes the memory pools and ADF transport handles. * * @context * This function is called from the SalCtrl_ServiceEventRestarted function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No (ADF ensures that this function doesn't need to be thread safe) * * @param[in] device An icp_accel_dev_t* type * @param[in] service A compression instance * *************************************************************************/ CpaStatus SalCtrl_CompressionRestarted(icp_accel_dev_t *device, sal_service_t *service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to get the number of services enabled * from the config table. * * @context * This function is called from the SalCtrl_QatInit * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * param[in] device An icp_accel_dev_t* type * param[in] pEnabledServices pointer to a variable used to store * the enabled services * *************************************************************************/ CpaStatus SalCtrl_GetEnabledServices(icp_accel_dev_t *device, Cpa32U *pEnabledServices); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to check if a service is enabled * * @context * This function is called from the SalCtrl_QatInit * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * param[in] enabled_services * param[in] service * *************************************************************************/ CpaBoolean SalCtrl_IsServiceEnabled(Cpa32U enabled_services, sal_service_type_t service); /************************************************************************* * @ingroup SalCtrl * @description * This function is used to check if a service is supported on the device * The key difference between this and SalCtrl_GetSupportedServices() is * that the latter treats it as an error if the service is unsupported. * * @context * This can be called anywhere. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * param[in] device * param[in] service service or services to check * *************************************************************************/ CpaBoolean SalCtrl_IsServiceSupported(icp_accel_dev_t *device, sal_service_type_t service); /** ******************************************************************************* * @ingroup LacMemPool * This function searches DC memory pool of the whole device to find all * inflight requests and extract the callback functions from opaque data to * generate dummy responses. * * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] accel_dev A pointer to the acceleration device * @param[in] enabled_services Enabled service for DC /Crypto * * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_FATAL A serious error has occurred. * @retval CPA_STATUS_SUCCESS function executed successfully. * @retval CPA_STATUS_RETRY function retried to generate response. * ******************************************************************************/ CpaStatus SalCtrl_DcDevErr_GenResponses(icp_accel_dev_t *accel_dev, Cpa32U enabled_services); #ifndef ICP_DC_ONLY /** ******************************************************************************* * @ingroup LacMemPool * This function searches crypto memory pool of the whole device to find all * inflight requests and extract the callback functions from opaque data to * generate dummy responses. * * @blocking * Yes * @reentrant * No * @threadSafe * Yes * * @param[in] accel_dev A pointer to the acceleration device * @param[in] enabled_services Enabled service for DC /Crypto * * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_FATAL A serious error has occurred. * @retval CPA_STATUS_SUCCESS function executed successfully. * ******************************************************************************/ CpaStatus SalCtrl_CyDevErr_GenResponses(icp_accel_dev_t *accel_dev, Cpa32U enabled_services); #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_sal_ctrl.h000066400000000000000000000122621503624047500304220ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sal_ctrl.h * * @ingroup SalCtrl * * Functions to register and deregister qat and service controllers with ADF. * ***************************************************************************/ #ifndef LAC_SAL_CTRL_H #define LAC_SAL_CTRL_H /******************************************************************* * @ingroup SalCtrl * @description * This function is used to check whether the service component * has been successfully started. * * @context * This function is called from the icp_sal_userStart() function. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * ******************************************************************/ CpaStatus SalCtrl_AdfServicesStartedCheck(void); /******************************************************************* * @ingroup SalCtrl * @description * This function is used to check whether the user's parameter * for concurrent request is valid. * * @context * This function is called when crypto or compression is init * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * ******************************************************************/ CpaStatus validateConcurrRequest(Cpa32U numConcurrRequests); /******************************************************************* * @ingroup SalCtrl * @description * This function is used to register adf services * * @context * This function is called from do_userStart() function * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * ******************************************************************/ CpaStatus SalCtrl_AdfServicesRegister(void); /******************************************************************* * @ingroup SalCtrl * @description * This function is used to unregister adf services. * * @context * This function is called from do_userStart() function * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * ******************************************************************/ CpaStatus SalCtrl_AdfServicesUnregister(void); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_sal_types.h000066400000000000000000000250541503624047500306250ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sal_types.h * * @ingroup SalCtrl * * Generic instance type definitions of SAL controller * ***************************************************************************/ #ifndef LAC_SAL_TYPES_H #define LAC_SAL_TYPES_H #include "lac_sync.h" #include "lac_list.h" #include "icp_accel_devices.h" #include "sal_statistics.h" #include "icp_adf_debug.h" #define SAL_CFG_BASE_DEC 10 #define SAL_CFG_BASE_HEX 16 /** ***************************************************************************** * @ingroup SalCtrl * Instance States * * @description * An enumeration containing the possible states for an instance. * *****************************************************************************/ typedef enum sal_service_state_s { SAL_SERVICE_STATE_UNINITIALIZED = 0, SAL_SERVICE_STATE_INITIALIZING, SAL_SERVICE_STATE_INITIALIZED, SAL_SERVICE_STATE_RUNNING, SAL_SERVICE_STATE_SHUTTING_DOWN, SAL_SERVICE_STATE_SHUTDOWN, SAL_SERVICE_STATE_RESTARTING, SAL_SERVICE_STATE_ERROR, SAL_SERVICE_STATE_END } sal_service_state_t; /** ***************************************************************************** * @ingroup SalCtrl * Service Instance Types * * @description * An enumeration containing the possible types for a service. * *****************************************************************************/ typedef enum { SAL_SERVICE_TYPE_UNKNOWN = 0, /* symmetric and asymmetric crypto service */ SAL_SERVICE_TYPE_CRYPTO = 1, /* legacy compression service (includes both compression and decompression directions) */ SAL_SERVICE_TYPE_COMPRESSION = 2, /* inline service */ SAL_SERVICE_TYPE_INLINE = 4, /* asymmetric crypto only service*/ SAL_SERVICE_TYPE_CRYPTO_ASYM = 8, /* symmetric crypto only service*/ SAL_SERVICE_TYPE_CRYPTO_SYM = 16, /* QAT service */ SAL_SERVICE_TYPE_QAT = 32, /* decompression only service */ SAL_SERVICE_TYPE_DECOMPRESSION = 64 } sal_service_type_t; /** ***************************************************************************** * @ingroup SalCtrl * Generic Instance Container * * @description * Contains all the common information across the different instances. * *****************************************************************************/ typedef struct sal_service_s { sal_service_type_t type; /**< Service type (e.g. SAL_SERVICE_TYPE_CRYPTO)*/ Cpa8U state; /**< Status of the service instance (e.g. SAL_SERVICE_STATE_INITIALIZED) */ Cpa32U instance; /**< Instance number */ CpaVirtualToPhysical virt2PhysClient; /**< Function pointer to client supplied virt_to_phys */ CpaStatus (*init)(icp_accel_dev_t *device, struct sal_service_s *service); /**< Function pointer for instance INIT function */ CpaStatus (*start)(icp_accel_dev_t *device, struct sal_service_s *service); /**< Function pointer for instance START function */ CpaStatus (*stop)(icp_accel_dev_t *device, struct sal_service_s *service); /**< Function pointer for instance STOP function */ CpaStatus (*shutdown)(icp_accel_dev_t *device, struct sal_service_s *service); /**< Function pointer for instance SHUTDOWN function */ CpaStatus (*error)(icp_accel_dev_t *device, struct sal_service_s *service); /**< Function pointer for instance ERROR function */ CpaStatus (*restarting)(icp_accel_dev_t *device, struct sal_service_s *service); /**< Function pointer for instance RESTARTING function */ CpaStatus (*restarted)(icp_accel_dev_t *device, struct sal_service_s *service); /**< Function pointer for instance RESTARTED function */ CpaCyInstanceNotificationCbFunc notification_cb; /**< Function pointer for instance restarting handler */ void *cb_tag; /**< Restarting handler priv data */ sal_statistics_collection_t *stats; /**< Pointer to device statistics configuration */ void *debug_parent_dir; /**< Pointer to parent proc dir entry */ Cpa32U capabilitiesMask; /**< Capabilities mask of the device */ Cpa32U dcExtendedFeatures; /**< Bit field of features. I.e. Compress And Verify */ CpaBoolean isInstanceStarted; /**< True if user called StartInstance on this instance */ CpaBoolean isGen4; /* True if the device is qat_4xxx or qat_4xxxvf */ CpaBoolean isGen4_2; /* True if the device is qat_420xx or qat_420xxvf */ CpaBoolean optimisedCurveSupport; /* True if optimised curves are supported */ CpaBoolean ns_isCnvErrorInjection; /** < Cnv Error Injection simulation is enabled. * This var is needed in the instance as there is no session * structure available to store it for the NS case. */ } sal_service_t; /** ***************************************************************************** * @ingroup SalCtrl * SAL structure * * @description * Contains lists to crypto and compression instances. * *****************************************************************************/ typedef struct sal_s { sal_list_t *crypto_services; /**< Container of sal_crypto_service_t */ sal_list_t *asym_services; /**< Container of sal_asym_service_t */ sal_list_t *sym_services; /**< Container of sal_sym_service_t */ sal_list_t *compression_services; /**< Container of sal_compression_service_t */ sal_list_t *decompression_services; /**< Container of sal_compression_service_t for decomp only service */ debug_dir_info_t *cy_dir; /**< Container for crypto proc debug */ debug_dir_info_t *asym_dir; /**< Container for asym proc debug */ debug_dir_info_t *sym_dir; /**< Container for sym proc debug */ debug_dir_info_t *dc_dir; /**< Container for data compression proc debug */ debug_dir_info_t *decomp_dir; /**< Container for decompression only proc debug */ debug_file_info_t *ver_file; /**< Container for version debug file */ } sal_t; /** ***************************************************************************** * @ingroup SalCtrl * SAL debug structure * * @description * Service debug handler * *****************************************************************************/ typedef struct sal_service_debug_s { icp_accel_dev_t *accel_dev; debug_file_info_t debug_file; } sal_service_debug_t; /** ******************************************************************************* * @ingroup SalCtrl * This macro verifies that the right service type has been passed in. * * @param[in] pService pointer to service instance * @param[in] service_type service type to check againstx. * * @return CPA_STATUS_FAIL Parameter is incorrect type * ******************************************************************************/ #define SAL_CHECK_INSTANCE_TYPE(pService, service_type) \ do \ { \ sal_service_t *pGenericService = NULL; \ pGenericService = (sal_service_t *)pService; \ if (!(service_type & pGenericService->type)) \ { \ LAC_LOG_ERROR("The instance handle is the wrong type"); \ return CPA_STATUS_FAIL; \ } \ } while (0) #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_sal_types_crypto.h000066400000000000000000000210531503624047500322200ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sal_types_crypto.h * * @ingroup SalCtrl * * Generic crypto instance type definition * ***************************************************************************/ #ifndef LAC_SAL_TYPES_CRYPTO_H_ #define LAC_SAL_TYPES_CRYPTO_H_ #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_qat_constants_table.h" #include "lac_sym_key.h" #include "cpa_cy_sym_dp.h" #include "cpa_cy_im.h" #include "icp_adf_debug.h" #include "lac_sal_types.h" #include "icp_adf_transport.h" #include "lac_mem_pools.h" #define LAC_PKE_FLOW_ID_TAG 0xFFFFFFFC #define LAC_PKE_ACCEL_ID_BIT_POS 1 #define LAC_PKE_SLICE_ID_BIT_POS 0 /** ***************************************************************************** * @ingroup SalCtrl * Crypto specific Service Container * * @description * Contains information required per crypto service instance. * *****************************************************************************/ typedef struct sal_crypto_service_s { sal_service_t generic_service_info; /**< An instance of the Generic Service Container */ lac_memory_pool_id_t lac_sym_cookie_pool; /**< Memory pool ID used for symmetric operations */ lac_memory_pool_id_t lac_ec_pool; /**< Memory pool ID used for asymmetric operations */ lac_memory_pool_id_t lac_prime_pool; /**< Memory pool ID used for asymmetric operations */ lac_memory_pool_id_t lac_pke_req_pool; /**< Memory pool ID used for asymmetric operations */ lac_memory_pool_id_t lac_pke_align_pool; /**< Memory pool ID used for asymmetric operations */ OsalAtomic *pLacSymStatsArr; /**< pointer to an array of atomic stats for symmetric */ OsalAtomic *pLacKeyStats; /**< pointer to an array of atomic stats for key */ OsalAtomic *pLacDhStatsArr; /**< pointer to an array of atomic stats for DH */ OsalAtomic *pLacDsaStatsArr; /**< pointer to an array of atomic stats for Dsa */ OsalAtomic *pLacRsaStatsArr; /**< pointer to an array of atomic stats for Rsa */ OsalAtomic *pLacEcStatsArr; /**< pointer to an array of atomic stats for Ecc */ OsalAtomic *pLacEcdhStatsArr; /**< pointer to an array of atomic stats for Ecc DH */ OsalAtomic *pLacEcdsaStatsArr; /**< pointer to an array of atomic stats for Ecc DSA */ OsalAtomic *pLacEcsm2StatsArr; /**< pointer to an array of atomic stats for Ecc SM2 */ OsalAtomic *pLacPrimeStatsArr; /**< pointer to an array of atomic stats for prime */ OsalAtomic *pLacLnStatsArr; /**< pointer to an array of atomic stats for large number */ OsalAtomic *pLacDrbgStatsArr; /**< pointer to an array of atomic stats for DRBG */ icp_qat_hw_auth_mode_t qatHmacMode; /**< Hmac Mode */ Cpa32U pkeFlowId; /**< Flow ID for all pke requests from this instance - identifies accelerator and execution engine to use */ icp_comms_trans_handle trans_handle_sym_tx; icp_comms_trans_handle trans_handle_sym_rx; icp_comms_trans_handle trans_handle_asym_tx; icp_comms_trans_handle trans_handle_asym_rx; Cpa32U maxNumSymReqBatch; /**< Maximum number of requests that can be placed on the sym tx ring for any one batch request (DP api) */ Cpa16U acceleratorNum; Cpa16U bankNumAsym; Cpa16U bankNumSym; Cpa16U pkgID; Cpa8U isPolled; Cpa8U executionEngine; Cpa32U coreAffinity; Cpa32U nodeAffinity; /**< Config Info */ CpaCySymDpCbFunc pSymDpCb; /**< Sym DP Callback */ lac_sym_qat_hash_defs_t **pLacHashLookupDefs; /**< table of pointers to standard defined information for all hash algorithms. We support an extra hash algo that is not exported by cy api which is why we need the extra +1 */ lac_sym_qat_constants_t constantsLookupTables; Cpa8U **ppHmacContentDesc; /**< table of pointers to CD for Hmac precomputes - used at session init */ Cpa8U *pSslLabel; /**< pointer to memory holding the standard SSL label ABBCCC.. */ lac_sym_key_tls_labels_t *pTlsLabel; /**< pointer to memory holding the 4 standard TLS labels */ lac_sym_key_tls_hkdf_sub_labels_t *pTlsHKDFSubLabel; /**< pointer to memory holding the 4 HKDFLabels sublabels */ debug_file_info_t *debug_file; /**< Statistics handler */ CpaCyCapabilitiesInfo capInfo; /* Cryptographic Capabilities Info */ } sal_crypto_service_t; /************************************************************************* * @ingroup cpaCyCommon * @description * This function returns a valid asym/sym/crypto instance handle for the * system if it exists. When requesting an instance handle of type sym or * asym, if either is not found then a crypto instance handle is returned * if found, since a crypto handle supports both sym and asym services. * Similarly when requesting a crypto instance handle, if it is not found * then an asym or sym crypto instance handle is returned. * * @performance * To avoid calling this function the user of the QA api should not use * instanceHandle = CPA_INSTANCE_HANDLE_SINGLE. * * @context * This function is called whenever instanceHandle = * CPA_INSTANCE_HANDLE_SINGLE at the QA Cy api. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @param[in] svc_type Type of crypto service requested. * * @retval Pointer to first crypto instance handle or NULL if no crypto * instances in the system. * *************************************************************************/ CpaInstanceHandle Lac_GetFirstHandle(sal_service_type_t svc_type); #endif /*LAC_SAL_TYPES_CRYPTO_H_*/ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_sw_responses.h000066400000000000000000000154111503624047500313500ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sw_responses.h * * @defgroup LacSwResponses Management for software responses * * @ingroup LacCommon * * Busy memory pools calculation functions and dummy responses generation * functions. * * @lld_start * @lld_overview * This component is designed as a set of utility functions for the * generation of dummy responses and calculation of memory pools which contain * in-flight requests. If the memory pools contain in-flight requests, they * will be named as busy memory pools. * @lld_dependencies * These utilities rely on OSAL for locking mechanisms and memory * allocation. It also depends on the implementation of the memory pool. * @lld_initialization * The initialization of the number of busy memory pools should be done * prior to the increment. * * @lld_process_context * @lld_end ***************************************************************************/ /** ******************************************************************************* * @ingroup LacSwResponses * * ******************************************************************************/ /***************************************************************************/ #ifndef LAC_SW_RESPONSES_H #define LAC_SW_RESPONSES_H #include "lac_mem_pools.h" #include "lac_sal_types.h" /** ******************************************************************************* * @ingroup LacSwResponses * @description * This function increases the number of busy memory pools if the poolID's * memory pool is not full. * * @blocking * Yes * @reentrant * No * @threadSafe * No * ******************************************************************************/ void LacSwResp_IncNumPoolsBusy(lac_memory_pool_id_t poolID); /** ******************************************************************************* * @ingroup LacSwResponses * @description * This function initializes the number of busy memory pools to zero. This * function should be called prior to the calculation of busy memory pools. * * @blocking * Yes * @reentrant * No * @threadSafe * Yes * ******************************************************************************/ void LacSwResp_InitNumPoolsBusy(void); /** ******************************************************************************* * @ingroup LacSwResponses * @description * This function is used to get the number of busy memory pools. * * @blocking * Yes * @reentrant * No * @threadSafe * Yes * ******************************************************************************/ Cpa16U LacSwResp_GetNumPoolsBusy(void); /** ******************************************************************************* * @ingroup LacSwResponses * This function searches the DC /PKE request memory pool to find all inflight * requests and extracts the callback function from request data which will be * called to generate dummy responses. * * @blocking * Yes * @reentrant * No * @threadSafe * No * @param[in] lac_mem_pool The ID of the specific pool * @param[in] type SAL_SERVICE Type * * * @retval CPA_STATUS_FAIL The function failed to retrieve all the * in-flight requests in the memory pool. * @retval CPA_STATUS_SUCCESS function executed successfully * @retval CPA_STATUS_RESOURCE Error related to system resources. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * @retval CPA_STATUS_FATAL A serious error has occurred. * @retval CPA_STATUS_RETRY function retried to generate response. * ******************************************************************************/ CpaStatus LacSwResp_GenResp(lac_memory_pool_id_t lac_mem_pool, sal_service_type_t type); #endif /* LAC_SW_RESPONSES_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/lac_sync.h000066400000000000000000000402201503624047500275660ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sync.h * * @defgroup LacSync LAC synchronous * * @ingroup LacCommon * * Function prototypes and defines for synchronous support * ***************************************************************************/ #ifndef LAC_SYNC_H #define LAC_SYNC_H #include "cpa.h" #include "lac_mem.h" #include "Osal.h" /** ***************************************************************************** * @ingroup LacSync * * @description * LAC cookie for synchronous support * *****************************************************************************/ typedef struct lac_sync_op_data_s { OsalSemaphore sid; /**< Semaphore to signal */ CpaStatus status; /**< Output - Status of the QAT response */ CpaBoolean opResult; /**< Output - Verification of the operation/protocol status */ CpaBoolean complete; /**< Output - Operation is complete */ CpaBoolean canceled; /**< Output - Operation canceled */ } lac_sync_op_data_t; #define LAC_PKE_SYNC_CALLBACK_TIMEOUT (2000) /**< @ingroup LacSync * Timeout waiting for an async callbacks in msecs. * This is derived from the max latency of a PKE request + 1 sec */ #define LAC_SYM_SYNC_CALLBACK_TIMEOUT (300) /**< @ingroup LacSyn * Timeout for wait for symmetric response in msecs */ #define LAC_INIT_MSG_CALLBACK_TIMEOUT (1922) /**< @ingroup LacSyn * Timeout for wait for init messages response in msecs */ #define DC_SYNC_CALLBACK_TIMEOUT (2000) /**< @ingroup LacSyn * Timeout for wait for compression response in msecs */ #define LAC_SYN_INITIAL_SEM_VALUE (0) /**< @ingroup LacSyn * Initial value of the sync waiting semaphore */ /** ******************************************************************************* * @ingroup LacSync * This function allocates a sync op data cookie * and creates and initialises the OSAL semaphore * * @param[in] ppSyncCallbackCookie Pointer to synch op data * * @retval CPA_STATUS_RESOURCE Failed to allocate the memory for the cookie. * @retval CPA_STATUS_SUCCESS Success * ******************************************************************************/ static __inline CpaStatus LacSync_CreateSyncCookie( lac_sync_op_data_t **ppSyncCallbackCookie) { CpaStatus status = LAC_OS_MALLOC(ppSyncCallbackCookie, sizeof(lac_sync_op_data_t)); if (CPA_STATUS_SUCCESS == status) { status = LAC_INIT_SEMAPHORE((*ppSyncCallbackCookie)->sid, LAC_SYN_INITIAL_SEM_VALUE); (*ppSyncCallbackCookie)->complete = CPA_FALSE; (*ppSyncCallbackCookie)->canceled = CPA_FALSE; } if (CPA_STATUS_SUCCESS != status) { LAC_OS_FREE(*ppSyncCallbackCookie); } return status; } /** ******************************************************************************* * @ingroup LacSync * This macro frees a sync op data cookie and destroys the OSAL semaphore * * @param[in] ppSyncCallbackCookie Pointer to sync op data * * @return void ******************************************************************************/ static __inline CpaStatus LacSync_DestroySyncCookie( lac_sync_op_data_t **ppSyncCallbackCookie) { CpaStatus status = CPA_STATUS_SUCCESS; /* * If the operation has not completed, cancel it instead of destroying the * cookie. Otherwise, the callback might panic. In this case, the cookie * will leak, but it's better than a panic. */ if (!(*ppSyncCallbackCookie)->complete) { LAC_LOG_ERROR("Attempting to destroy an incomplete sync cookie\n"); (*ppSyncCallbackCookie)->canceled = CPA_TRUE; return CPA_STATUS_FAIL; } status = LAC_DESTROY_SEMAPHORE((*ppSyncCallbackCookie)->sid); LAC_OS_FREE(*ppSyncCallbackCookie); return status; } /** ***************************************************************************** * @ingroup LacSync * Function which will wait for a sync callback on a given cookie. * * @param[in] pSyncCallbackCookie Pointer to sync op data * @param[in] timeOut Time to wait for callback (msec) * @param[out] pStatus Status returned by the callback * @param[out] pOpStatus Operation status returned by callback. * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_SUCCESS Fail waiting for a callback * *****************************************************************************/ static __inline CpaStatus LacSync_WaitForCallback( lac_sync_op_data_t *pSyncCallbackCookie, Cpa32S timeOut, CpaStatus *pStatus, CpaBoolean *pOpStatus) { CpaStatus status = CPA_STATUS_SUCCESS; status = LAC_WAIT_SEMAPHORE(pSyncCallbackCookie->sid, timeOut); if (CPA_STATUS_SUCCESS == status) { *pStatus = pSyncCallbackCookie->status; if (NULL != pOpStatus) { *pOpStatus = pSyncCallbackCookie->opResult; } pSyncCallbackCookie->complete = CPA_TRUE; } return status; } /** ***************************************************************************** * @ingroup LacSync * Function which will check for a sync callback on a given cookie. * Returns whether the callback has happened or not, no timeout. * * @param[in] pSyncCallbackCookie Pointer to sync op data * @param[in] timeOut Time to wait for callback (msec) * @param[out] pStatus Status returned by the callback * @param[out] pOpStatus Operation status returned by callback. * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_FAIL Fail waiting for a callback * *****************************************************************************/ static __inline CpaStatus LacSync_CheckForCallback( lac_sync_op_data_t *pSyncCallbackCookie, CpaStatus *pStatus, CpaBoolean *pOpStatus) { CpaStatus status = CPA_STATUS_SUCCESS; status = LAC_CHECK_SEMAPHORE(pSyncCallbackCookie->sid); if (CPA_STATUS_SUCCESS == status) { *pStatus = pSyncCallbackCookie->status; if (NULL != pOpStatus) { *pOpStatus = pSyncCallbackCookie->opResult; } pSyncCallbackCookie->complete = CPA_TRUE; } return status; } /** ***************************************************************************** * @ingroup LacSync * Function which will mark a sync cookie as complete. * If it's known that the callback will not happen it's necessary * to call this, else the cookie can't be destroyed. * * @param[in] pSyncCallbackCookie Pointer to sync op data * * @retval CPA_STATUS_SUCCESS Success * @retval CPA_STATUS_FAIL Failed to mark as complete * *****************************************************************************/ static __inline CpaStatus LacSync_SetSyncCookieComplete( lac_sync_op_data_t *pSyncCallbackCookie) { CpaStatus status = CPA_STATUS_FAIL; if (NULL != pSyncCallbackCookie) { pSyncCallbackCookie->complete = CPA_TRUE; status = CPA_STATUS_SUCCESS; } return status; } /** ***************************************************************************** * @ingroup LacSync * Generic verify callback function. * @description * This function is used when the API is called in synchronous mode. * It's assumed the callbackTag holds a lac_sync_op_data_t type * and when the callback is received, this callback shall set the * status element of that cookie structure and kick the sid. * This function may be used directly as a callback function. * * @param[in] callbackTag Callback Tag * @param[in] status Status of callback * @param[out] pOpdata Pointer to the Op Data * @param[out] opResult Boolean to indicate the result of the operation * * @return void *****************************************************************************/ void LacSync_GenVerifyCb(void *callbackTag, CpaStatus status, void *pOpdata, CpaBoolean opResult); /** ***************************************************************************** * @ingroup LacSync * Generic flatbuffer callback function. * @description * This function is used when the API is called in synchronous mode. * It's assumed the callbackTag holds a lac_sync_op_data_t type * and when the callback is received, this callback shall set the * status element of that cookie structure and kick the sid. * This function may be used directly as a callback function. * * @param[in] callbackTag Callback Tag * @param[in] status Status of callback * @param[in] pOpdata Pointer to the Op Data * @param[out] pOut Pointer to the flat buffer * * @return void *****************************************************************************/ void LacSync_GenFlatBufCb(void *callbackTag, CpaStatus status, void *pOpdata, CpaFlatBuffer *pOut); /** ***************************************************************************** * @ingroup LacSync * Generic flatbuffer verify callback function. * @description * This function is used when the API is called in synchronous mode. * It's assumed the callbackTag holds a lac_sync_op_data_t type * and when the callback is received, this callback shall set the * status and opResult element of that cookie structure and * kick the sid. * This function may be used directly as a callback function. * * @param[in] callbackTag Callback Tag * @param[in] status Status of callback * @param[in] pOpdata Pointer to the Op Data * @param[out] opResult Boolean to indicate the result of the operation * @param[out] pOut Pointer to the flat buffer * * @return void *****************************************************************************/ void LacSync_GenFlatBufVerifyCb(void *callbackTag, CpaStatus status, void *pOpdata, CpaBoolean opResult, CpaFlatBuffer *pOut); /** ***************************************************************************** * @ingroup LacSync * Generic dual flatbuffer verify callback function. * @description * This function is used when the API is called in synchronous mode. * It's assumed the callbackTag holds a lac_sync_op_data_t type * and when the callback is received, this callback shall set the * status and opResult element of that cookie structure and * kick the sid. * This function may be used directly as a callback function. * * @param[in] callbackTag Callback Tag * @param[in] status Status of callback * @param[in] pOpdata Pointer to the Op Data * @param[out] opResult Boolean to indicate the result of the operation * @param[out] pOut0 Pointer to the flat buffer * @param[out] pOut1 Pointer to the flat buffer * * @return void *****************************************************************************/ void LacSync_GenDualFlatBufVerifyCb(void *callbackTag, CpaStatus status, void *pOpdata, CpaBoolean opResult, CpaFlatBuffer *pOut0, CpaFlatBuffer *pOut1); /** ***************************************************************************** * @ingroup LacSync * Generic wake up function. * @description * This function is used when the API is called in synchronous * mode. * It's assumed the callbackTag holds a lac_sync_op_data_t type * and when the callback is received, this callback shall set * the status element of that cookie structure and kick the * sid. * This function maybe called from an async callback. * * @param[in] callbackTag Callback Tag * @param[in] status Status of callback * * @return void *****************************************************************************/ void LacSync_GenWakeupSyncCaller(void *callbackTag, CpaStatus status); /** ***************************************************************************** * @ingroup LacSync * Generic wake up verify function. * @description * This function is used when the API is called in synchronous * mode. * It's assumed the callbackTag holds a lac_sync_op_data_t type * and when the callback is received, this callback shall set * the status element and the opResult of that cookie structure * and kick the sid. * This function maybe called from an async callback. * * @param[in] callbackTag Callback Tag * @param[in] status Status of callback * @param[out] opResult Boolean to indicate the result of the operation * * @return void *****************************************************************************/ void LacSync_GenVerifyWakeupSyncCaller(void *callbackTag, CpaStatus status, CpaBoolean opResult); #endif /* LAC_SYNC_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/sal_instances.h000066400000000000000000000070231503624047500306250ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef SAL_INSTANCES_H #define SAL_INSTANCES_H CpaStatus Lac_GetCyInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U numInstances, CpaInstanceHandle *pInstances); CpaStatus Lac_GetCyNumInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *pNumInstances); CpaStatus Lac_GetDcInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U numInstances, CpaInstanceHandle *pInstances); CpaStatus Lac_GetDcNumInstancesByType( const CpaAccelerationServiceType accelerationServiceType, Cpa16U *pNumInstances); #endif /* SAL_INSTANCES_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/sal_misc_error_stats.h000066400000000000000000000137611503624047500322260ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file sal_misc_error_stats.h * * @ingroup SalMiscErrStats * * The file contains functions handles miscellaneous error global counter * ***************************************************************************/ #ifndef SAL_MISC_ERR_STATS_H #define SAL_MISC_ERR_STATS_H #ifndef KERNEL_SPACE #define SAL_MISC_ERR_STATS_INC(err, service) \ do \ { \ if (ERR_CODE_MISC_ERROR == (Cpa8S)err && service) \ { \ Sal_IncMiscErrStats(service); \ } \ } while (0) #else #define SAL_MISC_ERR_STATS_INC(err, service) #endif /******************************************************************* * @ingroup SalMiscErrStats * @description * This function is used to increase misc error statistics. * * @param[in] pService pointer to service instance. * * @assumptions * Called when misc error reported by firmware. * @sideEffects * None * @reentrant * None * @threadSafe * Yes * ******************************************************************/ CpaStatus Sal_IncMiscErrStats(sal_service_t *pService); /******************************************************************* * @ingroup SalMiscErrStats * @description * This function is used to get the misc error statistics. * * @param[in] pService pointer to service instance. * @param[out] pMiscStats pointer to get misc counter. * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * ******************************************************************/ CpaStatus Sal_GetMiscErrStats(sal_service_t *pService, OsalAtomic *pMiscStats); /******************************************************************* * @ingroup SalMiscErrStats * @description * This function is used to initialise misc error statistics and * create misc error stats file. * * @param[in] pStats pointer to statistics instance. * * @assumptions * None * @sideEffects * None * @reentrant * None * @threadSafe * None * ******************************************************************/ CpaStatus Sal_InitMiscErrStats(sal_statistics_collection_t *pStats); /******************************************************************* * @ingroup SalMiscErrStats * @description * This function is used to clear misc error statistics and * remove the misc error stats file. * * @param[in] pService pointer to service instance. * * @assumptions * None * @sideEffects * None * @reentrant * Yes * @threadSafe * Yes * ******************************************************************/ CpaStatus Sal_CleanMiscErrStats(sal_service_t *pService); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/sal_qat_cmn_msg.h000066400000000000000000000232671503624047500311360ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_qat_cmn_msg.c * * @ingroup SalQatCmnMessage * * @description * Implementation for populating the common (across services) QAT structures. * *****************************************************************************/ #ifndef SAL_QAT_CMN_MSG_H #define SAL_QAT_CMN_MSG_H /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "lac_common.h" #include "icp_accel_devices.h" #include "Osal.h" #include "cpa_cy_sym.h" #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #include "icp_adf_transport.h" #include "icp_adf_transport_dp.h" #include "icp_qat_hw.h" #include "icp_qat_fw.h" #include "icp_qat_fw_la.h" /** ****************************************************************************** * @ingroup SalQatCmnMessage * content descriptor info structure * * @description * This structure contains generic information on the content descriptor * *****************************************************************************/ typedef struct sal_qat_content_desc_info_s { CpaPhysicalAddr hardwareSetupBlockPhys; /**< Physical address of hardware setup block of the content descriptor */ void *pData; /**< Virtual Pointer to the hardware setup block of the content descriptor */ Cpa8U hwBlkSzQuadWords; /**< Hardware Setup Block size in quad words */ } sal_qat_content_desc_info_t; /** ******************************************************************************* * @ingroup SalQatCmnMessage * Lookaside response handler function type * * @description * This type definition specifies the function prototype for handling the * response messages for a specific symmetric operation * * @param[in] lacCmdId Look Aside Command ID * * @param[in] pOpaqueData Pointer to Opaque Data * * @param[in] cmnRespFlags Common Response flags * * @return void * *****************************************************************************/ typedef void (*sal_qat_resp_handler_func_t)(icp_qat_fw_la_cmd_id_t lacCmdId, void *pOpaqueData, icp_qat_fw_comn_flags cmnRespFlags); /******************************************************************** * @ingroup SalQatMsg_CmnHdrWrite * * @description * This function fills in all fields in the icp_qat_fw_comn_req_hdr_t * section of the Request Msg. Build LW0 + LW1 - * service part of the request * * @param[in] pMsg Pointer to 128B Request Msg buffer * @param[in] serviceType Type of service request * @param[in] serviceCmdId ID for the type of service request * @param[in] cmnFlags Common request flags * @param[in] serviceCmdFlags Service command flags * @param[in] extServiceCmdFlags Extended service command flags * * @return * None * *****************************************/ void SalQatMsg_CmnHdrWrite(icp_qat_fw_comn_req_t *pMsg, icp_qat_fw_comn_request_id_t serviceType, uint8_t serviceCmdId, icp_qat_fw_comn_flags cmnFlags, icp_qat_fw_serv_specif_flags serviceCmdFlags, icp_qat_fw_ext_serv_specif_flags extServiceCmdFlags); /******************************************************************** * @ingroup SalQatMsg_CmnMidWrite * * @description * This function fills in all fields in the icp_qat_fw_comn_req_mid_t * section of the Request Msg and the corresponding SGL/Flat flag * in the Hdr. * * @param[in] pReq Pointer to 128B Request Msg buffer * @param[in] pOpaqueData Pointer to opaque data used by callback * @param[in] bufferFormat src and dst Buffers are either SGL or Flat format * @param[in] pSrcBuffer Address of source buffer * @param[in] pDstBuffer Address of destination buffer * @param[in] pSrcLength Length of source buffer * @param[in] pDstLength Length of destination buffer * * @assumptions * All fields in mid section are zero before fn is called * @return * None * *****************************************/ void SalQatMsg_CmnMidWrite(icp_qat_fw_la_bulk_req_t *pReq, const void *pOpaqueData, Cpa8U bufferFormat, Cpa64U srcBuffer, Cpa64U dstBuffer, Cpa32U srcLength, Cpa32U dstLength); /******************************************************************** * @ingroup SalQatMsg_ContentDescHdrWrite * * @description * This function fills in all fields in the * icp_qat_fw_comn_req_hdr_cd_pars_t section of the Request Msg. * * @param[in] pMsg Pointer to 128B Request Msg buffer. * @param[in] pContentDescInfo content descriptor info. * * @return * none * *****************************************/ void SalQatMsg_ContentDescHdrWrite( icp_qat_fw_comn_req_t *pMsg, const sal_qat_content_desc_info_t *pContentDescInfo); /******************************************************************** * @ingroup SalQatMsg_CtrlBlkSetToReserved * * @description * This function set the whole contrle block to a reserved state. * * @param[in] _pMsg Pointer to 128B Request Msg buffer. * * @return * none * *****************************************/ void SalQatMsg_CtrlBlkSetToReserved(icp_qat_fw_comn_req_t *_pMsg); /******************************************************************** * @ingroup SalQatMsg_transPutMsg * * @description * * * @param[in] trans_handle * @param[in] pqat_msg * @param[in] size_in_lws * @param[in] service * * @return * CpaStatus * *****************************************/ CpaStatus SalQatMsg_transPutMsg(icp_comms_trans_handle trans_handle, void *pqat_msg, Cpa32U size_in_lws, Cpa8U service, Cpa64U *seq_num); /******************************************************************** * @ingroup SalQatMsg_updateQueueTail * * @description * * * @param[in] trans_handle * * * @return * CpaStatus * *****************************************/ CpaStatus SalQatMsg_updateQueueTail(icp_comms_trans_handle trans_hnd); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/sal_service_state.h000066400000000000000000000221631503624047500315000ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file sal_service_state.h * * @defgroup SalServiceState * * @ingroup SalCtrl * * Checks state for generic service instance * ***************************************************************************/ #ifndef SAL_SERVICE_STATE_H_ #define SAL_SERVICE_STATE_H_ /** ******************************************************************************* * @ingroup SalServiceState * Check to see if the instance is in the running state * * @description * This function checks the state of an instance to see if it is in the * running state * * @param[in] instance Instance handle (assumes this is valid, i.e. checked * before this function is called) * @retval CPA_TRUE Instance in the RUNNING state * @retval CPA_FALSE Instance not in RUNNING state * *****************************************************************************/ CpaBoolean Sal_ServiceIsRunning(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup SalServiceState * Check to see if the instance is beign restarted * * @description * This function checks the state of an instance to see if the device it * uses is being restarted because of hardware error. * * @param[in] instance Instance handle (assumes this is valid, i.e. checked * before this function is called) * @retval CPA_TRUE Device the instance is using is restarting. * @retval CPA_FALSE Device the instance is running. * *****************************************************************************/ CpaBoolean Sal_ServiceIsRestarting(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup SalServiceState * Check to see if the instance is in error state * * @description * This function checks the state of an instance to see if the device it * uses is in an error state due to a hardware error * * @param[in] instance Instance handle (assumes this is valid, i.e. checked * before this function is called) * @retval CPA_TRUE Device the instance is using is in error state. * @retval CPA_FALSE Device the instance is not in error state. * *****************************************************************************/ CpaBoolean Sal_ServiceIsInError(CpaInstanceHandle instanceHandle); /** ******************************************************************************* * @ingroup SalServiceState * This macro checks if an instance is running. An error message is logged * if it is not in a running state. * * @return CPA_STATUS_FAIL Instance not in RUNNING state. * @return void Instance is in RUNNING state. ******************************************************************************/ #define SAL_RUNNING_CHECK(instanceHandle) \ do \ { \ if (unlikely(CPA_TRUE != Sal_ServiceIsRunning(instanceHandle))) \ { \ if (CPA_TRUE == Sal_ServiceIsRestarting(instanceHandle)) \ { \ return CPA_STATUS_RESTARTING; \ } \ LAC_LOG_ERROR("Instance not in a Running state"); \ return CPA_STATUS_FAIL; \ } \ } while (0) /** ******************************************************************************* * @ingroup SalServiceState * This macro checks if an instance is in a state to get init event. * * @return CPA_STATUS_FAIL Instance not in good state. * @return void Instance is in good state. ******************************************************************************/ #define SAL_SERVICE_GOOD_FOR_INIT(instanceHandle) \ do \ { \ sal_service_t *pService = (sal_service_t *)instanceHandle; \ if ((SAL_SERVICE_STATE_UNINITIALIZED != pService->state) && \ (SAL_SERVICE_STATE_RESTARTING != pService->state)) \ { \ LAC_LOG_ERROR("Not in the correct state to call init\n"); \ return CPA_STATUS_FAIL; \ } \ } while (0) /** ******************************************************************************* * @ingroup SalServiceState * This macro checks if an instance is in a state to get restarted event. * * @return CPA_STATUS_FAIL Instance not in good state. * @return void Instance is in good state. ******************************************************************************/ #define SAL_SERVICE_GOOD_FOR_RESTARTED(instanceHandle) \ do \ { \ sal_service_t *pService = (sal_service_t *)instanceHandle; \ if ((SAL_SERVICE_STATE_UNINITIALIZED != pService->state) && \ (SAL_SERVICE_STATE_RESTARTING != pService->state)) \ { \ LAC_LOG_ERROR("Not in the correct state to call restarted\n"); \ return CPA_STATUS_FAIL; \ } \ } while (0) #endif /* SAL_SERVICE_STATE_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/sal_statistics.h000066400000000000000000000222151503624047500310300ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_statistics.h * * @ingroup SalStats * * @description * Statistics related defines, structures and functions * *****************************************************************************/ #ifndef SAL_STATISTICS_H #define SAL_STATISTICS_H /* * Config values names for statistics */ #define SAL_STATS_CFG_ENABLED "statsGeneral" /**< Config value name for enabling/disabling statistics */ #define SAL_STATS_CFG_DC "statsDc" /**< Config value name for enabling/disabling Compression statistics */ #define SAL_STATS_CFG_DH "statsDh" /**< Config value name for enabling/disabling Diffie-Helman statistics */ #define SAL_STATS_CFG_DRBG "statsDrbg" /**< Config value name for enabling/disabling DRBG statistics */ #define SAL_STATS_CFG_DSA "statsDsa" /**< Config value name for enabling/disabling DSA statistics */ #define SAL_STATS_CFG_ECC "statsEcc" /**< Config value name for enabling/disabling ECC statistics */ #define SAL_STATS_CFG_KEYGEN "statsKeyGen" /**< Config value name for enabling/disabling Key Gen statistics */ #define SAL_STATS_CFG_LN "statsLn" /**< Config value name for enabling/disabling Large Number statistics */ #define SAL_STATS_CFG_PRIME "statsPrime" /**< Config value name for enabling/disabling Prime statistics */ #define SAL_STATS_CFG_RSA "statsRsa" /**< Config value name for enabling/disabling RSA statistics */ #define SAL_STATS_CFG_SYM "statsSym" /**< Config value name for enabling/disabling Symmetric Crypto statistics */ #define SAL_STATS_CFG_MISC "statsMisc" /**< Config value name for enabling/disabling Miscellaneous error statistics */ #define SAL_STATS_SYM 0 #define SAL_STATS_DSA 1 #define SAL_STATS_DSA2 2 #define SAL_STATS_RSA 3 #define SAL_STATS_DH 4 #define SAL_STATS_KEYGEN 5 #define SAL_STATS_LN 6 #define SAL_STATS_PRIME 7 #define SAL_STATS_ECC 8 #define SAL_STATS_ECDH 9 #define SAL_STATS_ECDSA 10 #define SAL_STATS_MISC 11 /**< Numeric values for crypto statistics */ #define SAL_STATISTICS_STRING_OFF "0" /**< String representing the value for disabled statistics */ /** ***************************************************************************** * @ingroup SalStats * Structure describing stats enabled/disabled in the system * * @description * Structure describing stats enabled/disabled in the system * *****************************************************************************/ typedef struct sal_statistics_collection_s { CpaBoolean bStatsEnabled; /**< If CPA_TRUE then statistics functionality is enabled */ CpaBoolean bDcStatsEnabled; /**< If CPA_TRUE then Compression statistics are enabled */ CpaBoolean bDhStatsEnabled; /**< If CPA_TRUE then Diffie-Helman statistics are enabled */ CpaBoolean bDsaStatsEnabled; /**< If CPA_TRUE then DSA statistics are enabled */ CpaBoolean bEccStatsEnabled; /**< If CPA_TRUE then ECC statistics are enabled */ CpaBoolean bKeyGenStatsEnabled; /**< If CPA_TRUE then Key Gen statistics are enabled */ CpaBoolean bLnStatsEnabled; /**< If CPA_TRUE then Large Number statistics are enabled */ CpaBoolean bPrimeStatsEnabled; /**< If CPA_TRUE then Prime statistics are enabled */ CpaBoolean bRsaStatsEnabled; /**< If CPA_TRUE then RSA statistics are enabled */ CpaBoolean bSymStatsEnabled; /**< If CPA_TRUE then Symmetric Crypto statistics are enabled */ CpaBoolean bMiscStatsEnabled; /**< If CPA_TRUE then Miscellaneous error statistics are enabled */ } sal_statistics_collection_t; /** ****************************************************************************** * @ingroup SalStats * * @description * Initializes structure describing which statistics * are enabled for the acceleration device. * * @param[in] device Pointer to an acceleration device structure * * @retval CPA_STATUS_SUCCESS Operation successful * @retval CPA_STATUS_INVALID_PARAM Invalid param provided * @retval CPA_STATUS_RESOURCE Memory alloc failed * @retval CPA_STATUS_FAIL Operation failed * ******************************************************************************/ CpaStatus SalStatistics_InitStatisticsCollection(icp_accel_dev_t *device); /** ****************************************************************************** * @ingroup SalStats * * @description * Cleans structure describing which statistics * are enabled for the acceleration device. * * @param[in] device Pointer to an acceleration device structure * * @retval CPA_STATUS_SUCCESS Operation successful * @retval CPA_STATUS_INVALID_PARAM Invalid param provided * @retval CPA_STATUS_FAIL Operation failed * ******************************************************************************/ CpaStatus SalStatistics_CleanStatisticsCollection(icp_accel_dev_t *device); #if defined(COUNTERS) && !defined(DISABLE_STATS) /* Type of the RSA request */ typedef enum { LAC_RSA_ENCRYPT_REQUEST = 1, LAC_RSA_DECRYPT_REQUEST, LAC_RSA_KEYGEN_REQUEST } rsa_request_type_t; /* Type of the DH request */ typedef enum { LAC_DH_PHASE1_REQUEST = 1, LAC_DH_PHASE2_REQUEST, } dh_request_type_t; /* Type of the DSA request */ typedef enum { LAC_DSA_GEN_P_REQUEST = 1, LAC_DSA_GEN_G_REQUEST, LAC_DSA_GEN_Y_REQUEST, LAC_DSA_SIGN_R_REQUEST, LAC_DSA_SIGN_S_REQUEST, LAC_DSA_SIGN_RS_REQUEST, LAC_DSA_VERIFY_REQUEST } dsa_request_type_t; /* Type of the ECSM2 request */ typedef enum { LAC_ECSM2_POINT_MULTIPLY_REQUEST = 1, LAC_ECSM2_GEN_POINT_MULTIPLY_REQUEST, LAC_ECSM2_POINT_VERIFY_REQUEST, LAC_ECSM2_SIGN_REQUEST, LAC_ECSM2_VERIFY_REQUEST, LAC_ECSM2_ENC_REQUEST, LAC_ECSM2_DEC_REQUEST, LAC_ECSM2_KEY_EXCHANGE_P1_REQUEST, LAC_ECSM2_KEY_EXCHANGE_P2_REQUEST } ecsm2_request_type_t; /* Type of the ECDSA request */ typedef enum { LAC_ECDSA_SIGN_R_REQUEST = 1, LAC_ECDSA_SIGN_S_REQUEST, LAC_ECDSA_SIGN_RS_REQUEST, LAC_ECDSA_VERIFY_REQUEST } ecdsa_request_type_t; /* Type of the ECC request */ typedef enum { LAC_ECC_POINT_MULTIPLY_REQUEST = 1, LAC_ECC_POINT_VERIFY_REQUEST, } ecc_request_type_t; /* Type of the Large Number request */ typedef enum { LAC_LN_MODEXP_REQUEST = 1, LAC_LN_MODINV_REQUEST, } ln_request_type_t; #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/sal_string_parse.h000066400000000000000000000144121503624047500313360ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_string_parse.h * * @defgroup SalStringParse * * @ingroup SalStringParse * * @description * This file contains string parsing functions * *****************************************************************************/ #ifndef SAL_STRING_PARSE_H #define SAL_STRING_PARSE_H /* Maximum size of the strings used by SAL */ #define SAL_CFG_MAX_VAL_LEN_IN_BYTES 64 #define SAL_CFG_DC "Dc" #define SAL_CFG_DECOMP "Decomp" #define SAL_CFG_CY "Cy" #define SAL_CFG_RING_BANK_NUM "BankNumber" #define SAL_CFG_ACCEL_SEC "Accelerator" #define SAL_CFG_ETRMGR_BANK "Bank" #define SAL_CFG_ETRMGR_CORE_AFFINITY "CoreAffinity" #define SAL_CFG_RING_DC_TX "RingTx" #define SAL_CFG_RING_DC_RX "RingRx" #define SAL_CFG_RING_ASYM_TX "RingAsymTx" #define SAL_CFG_RING_SYM_TX "RingSymTx" #define SAL_CFG_RING_ASYM_RX "RingAsymRx" #define SAL_CFG_RING_SYM_RX "RingSymRx" #define SAL_CFG_POLL_MODE "IsPolled" #define SAL_CFG_RING_SYM_SIZE "NumConcurrentSymRequests" #define SAL_CFG_RING_ASYM_SIZE "NumConcurrentAsymRequests" #define SAL_CFG_RING_DC_SIZE "NumConcurrentRequests" #define SAL_CFG_NAME "Name" #define SAL_CFG_COMP "COMP" #define SAL_CFG_MEMPOOL "MemPool" #define SAL_CFG_DECOMP_MEMPOOL "DecompMemPool" #define SAL_CFG_ASYM_RESIZE_POOL "AsymResizePool" #define SAL_CFG_ASYM_REQ_POOL "AsymReqPool" #define SAL_CFG_ASYM_PRIME_POOL "AsymPrimePool" #define SAL_CFG_ASYM_EC_MEM_POOL "AsymEcMemPool" #define SAL_CFG_ASYM_KPT_UNWRAP_CTX_MEM_POOL "AsymKptUnWrapCtxMemPool" #define SAL_CFG_SYM_POOL "SymPool" #define SAL_CFG_CHAIN_COOKIE_POOL "ChainCookiePool" #define SAL_CFG_CHAIN_DESC_POOL "ChainDescPool" /** ******************************************************************************* * @ingroup SalStringParse * Builds a string and store it in result * * @description * The result string will be the concatenation of string1, instanceNumber * and string2. The size of result has to be SAL_CFG_MAX_VAL_LEN_IN_BYTES. * We can't check this in this function, this is the user responsibility * * @param[in] string1 First string to concatenate * @param[in] instanceNumber Instance number * @param[in] string2 Second string to concatenate * @param[out] result Resulting string of concatenation * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed * *****************************************************************************/ CpaStatus Sal_StringParsing(char *string1, Cpa32U instanceNumber, char *string2, char *result); /** ******************************************************************************* * @ingroup SalStringParse * Convert a string to an unsigned long * * @description * Parses the string cp in the specified base, and returned it as an * unsigned long value. * * @param[in] cp String to be converted * @param[in] endp Pointer to the end of the string. This parameter * can also be NULL and will not be used in this case * @param[in] cfgBase Base to convert the string * * @retval The string converted to an unsigned long * *****************************************************************************/ Cpa64U Sal_Strtoul(const char *cp, char **endp, unsigned int cfgBase); #endif /* SAL_STRING_PARSE_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/include/sal_types_compression.h000066400000000000000000000171071503624047500324270ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file sal_types_compression.h * * @ingroup SalCtrl * * Generic compression instance type definition * ***************************************************************************/ #ifndef SAL_TYPES_COMPRESSION_H_ #define SAL_TYPES_COMPRESSION_H_ #include "cpa_dc.h" #include "cpa_dc_capabilities.h" #include "cpa_dc_dp.h" #include "lac_sal_types.h" #include "icp_qat_hw.h" #include "icp_buffer_desc.h" #include "lac_mem_pools.h" #include "icp_adf_transport.h" #include "lac_sym_qat_hash_defs_lookup.h" #include "lac_sym_qat_constants_table.h" #include "dc_capabilities.h" #define DC_NUM_RX_RINGS (1) /** ***************************************************************************** * @ingroup SalCtrl * Chaining specific Service Container * * @description * Contains information required per chaining service instance. * *****************************************************************************/ /* Parameters to provide chaining service */ typedef struct sal_dc_chain_service_s { lac_memory_pool_id_t lac_sym_cookie_pool; /**< Memory pool ID used for symmetric operations */ icp_qat_hw_auth_mode_t qatHmacMode; /**< Hmac Mode */ lac_sym_qat_hash_defs_t **pLacHashLookupDefs; /**< table of pointers to standard defined information for all hash * algorithms. We support an extra hash algo that is not exported by * cy API which is why we need the extra +1 */ lac_sym_qat_constants_t constantsLookupTables; /**< constant table of auth and cipher */ Cpa8U **ppHmacContentDesc; /**< table of pointers to content descriptor for Hmac precomputes * - used at session init */ lac_memory_pool_id_t dc_chain_cookie_pool; /**< Memory pool ID used for chaining operations */ lac_memory_pool_id_t dc_chain_serv_resp_pool; /**< Memory pool ID used for linked crypto and compression request * descriptor */ } sal_dc_chain_service_t; /** ***************************************************************************** * @ingroup SalCtrl * Compression specific Service Container * * @description * Contains information required per compression service instance. * *****************************************************************************/ typedef struct sal_compression_service_s { /* An instance of the Generic Service Container */ sal_service_t generic_service_info; /* Memory pool ID used for compression */ lac_memory_pool_id_t compression_mem_pool; /* Memory pool ID used for decompression */ lac_memory_pool_id_t decompression_mem_pool; /* Pointer to an array of atomic stats for compression */ OsalAtomic *pCompStatsArr; /* Size of the DRAM intermediate buffer in bytes */ Cpa64U minInterBuffSizeInBytes; /* Number of DRAM intermediate buffers */ Cpa16U numInterBuffs; /* Address of the array of DRAM intermediate buffers*/ icp_qat_addr_width_t *pInterBuffPtrsArray; CpaPhysicalAddr pInterBuffPtrsArrayPhyAddr; icp_comms_trans_handle trans_handle_compression_tx; icp_comms_trans_handle trans_handle_compression_rx; icp_comms_trans_handle trans_handle_decompression_tx; icp_comms_trans_handle trans_handle_decompression_rx; /* Maximum number of in flight requests */ Cpa32U maxNumCompConcurrentReq; /* Callback function defined for the DcDp API compression session */ CpaDcDpCallbackFn pDcDpCb; /* Config info */ Cpa16U acceleratorNum; Cpa16U bankNum; Cpa16U bankNumDecomp; Cpa16U pkgID; Cpa16U isPolled; Cpa32U coreAffinity; Cpa32U nodeAffinity; /* Statistics handler */ debug_file_info_t *debug_file; /* Chaining service */ sal_dc_chain_service_t *pDcChainService; /* Compression service capabilities */ dc_capabilities_t dc_capabilities; } sal_compression_service_t; /************************************************************************* * @ingroup SalCtrl * @description * This function returns a valid compression instance handle for the system * if it exists. * * @performance * To avoid calling this function the user of the QA api should not use * instanceHandle = CPA_INSTANCE_HANDLE_SINGLE. * * @context * This function is called whenever instanceHandle = * CPA_INSTANCE_HANDLE_SINGLE at the QA Dc api. * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * * @retval Pointer to first compression instance handle or NULL if no * compression instances in the system. * *************************************************************************/ CpaInstanceHandle dcGetFirstHandle(void); #endif /*SAL_TYPES_COMPRESSION_H_*/ qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/qat_comms/000077500000000000000000000000001503624047500261645ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/qat_comms/sal_qat_cmn_msg.c000066400000000000000000000242541503624047500314660ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file sal_qat_cmn_msg.h * * @defgroup SalQatCmnMessage * * @ingroup SalQatCmnMessage * * Interfaces for populating the common QAT structures for a lookaside * operation. * *****************************************************************************/ /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "cpa.h" /* ******************************************************************************* * Include private header files ******************************************************************************* */ #include "icp_accel_devices.h" #include "icp_qat_fw_la.h" #include "icp_qat_hw.h" #include "lac_common.h" #include "lac_mem.h" #include "lac_log.h" #include "sal_qat_cmn_msg.h" /******************************************************************** * @ingroup SalQatMsg_CmnHdrWrite * * @description * This function fills in all fields in the icp_qat_fw_comn_req_hdr_t * section of the Request Msg. Build LW0 + LW1 - * service part of the request * * @param[in] pMsg Pointer to 128B Request Msg buffer * @param[in] serviceType Type of service request * @param[in] serviceCmdId ID for the type of service request * @param[in] cmnFlags Common request flags * @param[in] serviceCmdFlags Service command flags * @param[in] extendedServCmdFlags Extended service command flags * @param[in] isGen4 use false for CPM 1.x, true for CPM2.0 * * @return * None * *****************************************/ void SalQatMsg_CmnHdrWrite(icp_qat_fw_comn_req_t *pMsg, icp_qat_fw_comn_request_id_t serviceType, uint8_t serviceCmdId, icp_qat_fw_comn_flags cmnFlags, icp_qat_fw_serv_specif_flags serviceCmdFlags, icp_qat_fw_ext_serv_specif_flags extServiceCmdFlags) { icp_qat_fw_comn_req_hdr_t *pHeader = &(pMsg->comn_hdr); /* LW0 */ pHeader->hdr_flags = ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET); pHeader->service_type = (uint8_t)serviceType; pHeader->service_cmd_id = serviceCmdId; pHeader->resrvd1 = 0; /* LW1 */ pHeader->comn_req_flags = cmnFlags; pHeader->serv_specif_flags = serviceCmdFlags; pHeader->extended_serv_specif_flags = extServiceCmdFlags; } /******************************************************************** * @ingroup SalQatCmnMessage * * @description * This function fills in all fields in the icp_qat_fw_comn_req_mid_t * section of the Request Msg and the corresponding SGL/Flat flag * in the Hdr. * * @param[in] pReq Pointer to 128B Request Msg buffer * @param[in] pOpaqueData Pointer to opaque data used by callback * @param[in] bufferFormat src and dst Buffers are either SGL or Flat * format * @param[in] pSrcBuffer Address of source buffer * @param[in] pDstBuffer Address of destination buffer * @param[in] pSrcLength Length of source buffer * @param[in] pDstLength Length of destination buffer * * @assumptions * All fields in mid section are zero before fn is called * @return * None * *****************************************/ void inline SalQatMsg_CmnMidWrite(icp_qat_fw_la_bulk_req_t *pReq, const void *pOpaqueData, Cpa8U bufferFormat, Cpa64U srcBuffer, Cpa64U dstBuffer, Cpa32U srcLength, Cpa32U dstLength) { icp_qat_fw_comn_req_mid_t *pMid = &(pReq->comn_mid); LAC_MEM_SHARED_WRITE_FROM_PTR(pMid->opaque_data, pOpaqueData); pMid->src_data_addr = srcBuffer; /* In place */ if (0 == dstBuffer) { pMid->dest_data_addr = srcBuffer; } /* Out of place */ else { pMid->dest_data_addr = dstBuffer; } pReq->comn_hdr.comn_req_flags &= (QAT_COMN_CD_FLD_TYPE_MASK << QAT_COMN_CD_FLD_TYPE_BITPOS); switch (bufferFormat) { case QAT_COMN_PTR_TYPE_SGL: /* Using ScatterGatherLists so set flag in header */ ICP_QAT_FW_COMN_PTR_TYPE_SET(pReq->comn_hdr.comn_req_flags, QAT_COMN_PTR_TYPE_SGL); /* Assumption: No need to set src and dest length in this case as * not used */ break; default: /* Using Flat buffers so set flag in header */ ICP_QAT_FW_COMN_PTR_TYPE_SET(pReq->comn_hdr.comn_req_flags, QAT_COMN_PTR_TYPE_FLAT); pMid->src_length = srcLength; pMid->dst_length = dstLength; break; } } /******************************************************************** * @ingroup SalQatMsg_ContentDescHdrWrite * * @description * This function fills in all fields in the * icp_qat_fw_comn_req_hdr_cd_pars_t section of the Request Msg. * * @param[in] pMsg Pointer to 128B Request Msg buffer. * @param[in] pContentDescInfo content descriptor info. * * @return * none * *****************************************/ void SalQatMsg_ContentDescHdrWrite( icp_qat_fw_comn_req_t *pMsg, const sal_qat_content_desc_info_t *pContentDescInfo) { icp_qat_fw_comn_req_hdr_cd_pars_t *pCd_pars = &(pMsg->cd_pars); pCd_pars->s.content_desc_addr = pContentDescInfo->hardwareSetupBlockPhys; pCd_pars->s.content_desc_params_sz = pContentDescInfo->hwBlkSzQuadWords; pCd_pars->s.content_desc_resrvd1 = 0; pCd_pars->s.content_desc_hdr_resrvd2 = 0; pCd_pars->s.content_desc_resrvd3 = 0; } /******************************************************************** * @ingroup SalQatMsg_CtrlBlkSetToReserved * * @description * This function sets the whole control block to a reserved state. * * @param[in] _pMsg Pointer to 128B Request Msg buffer. * * @return * none * *****************************************/ void SalQatMsg_CtrlBlkSetToReserved(icp_qat_fw_comn_req_t *pMsg) { icp_qat_fw_comn_req_cd_ctrl_t *pCd_ctrl = &(pMsg->cd_ctrl); osalMemSet(pCd_ctrl, 0, sizeof(icp_qat_fw_comn_req_cd_ctrl_t)); } /******************************************************************** * @ingroup SalQatMsg_transPutMsg * * @description * * * @param[in] trans_handle * @param[in] pqat_msg * @param[in] size_in_lws * @param[in] service * * @return * CpaStatus * *****************************************/ CpaStatus SalQatMsg_transPutMsg(icp_comms_trans_handle trans_handle, void *pqat_msg, Cpa32U size_in_lws, Cpa8U service, Cpa64U *seq_num) { return icp_adf_transPutMsg(trans_handle, pqat_msg, size_in_lws, seq_num); } CpaStatus SalQatMsg_updateQueueTail(icp_comms_trans_handle trans_handle) { CpaStatus status; status = icp_adf_updateQueueTail(trans_handle); return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/000077500000000000000000000000001503624047500253415ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/lac_buffer_desc.c000066400000000000000000000571201503624047500306000ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_buffer_desc.c Utility functions for setting buffer descriptors * * @ingroup LacBufferDesc * *****************************************************************************/ /* ******************************************************************************* * Include header files ******************************************************************************* */ #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "icp_adf_init.h" #include "lac_list.h" #include "lac_sal_types.h" #ifndef ICP_DC_DYN_NOT_SUPPORTED #include "icp_buffer_desc.h" #endif #include "lac_mem.h" #include "cpa_cy_common.h" #include "dc_session.h" #include "dc_datapath.h" #include "sal_misc_error_stats.h" /* ******************************************************************************* * Define public/global function definitions ******************************************************************************* */ /* Invalid physical address value */ #define INVALID_PHYSICAL_ADDRESS 0 #define MAX_SGL_BUFFERS 256 /* Indicates what type of buffer writes need to be performed */ typedef enum lac_buff_write_op_e { WRITE_NORMAL = 0, WRITE_AND_GET_SIZE, WRITE_AND_ALLOW_ZERO_BUFFER, WRITE_ALLOW_0_BUFF_GET_SIZE, } lac_buff_write_op_t; /* This function implements the buffer description writes for the traditional * APIs */ STATIC CpaStatus LacBuffDesc_CommonBufferListDescWrite(const CpaBufferList *pUserBufferList, const CpaBufferList *pDictBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, Cpa64U *totalDataLenInBytes, sal_service_t *pService, lac_buff_write_op_t operationType) { Cpa32U numBuffers = 0; Cpa32U dictNumBuffers = 0; icp_qat_addr_width_t bufListDescPhyAddr = 0; icp_qat_addr_width_t bufListAlignedPhyAddr = 0; CpaFlatBuffer *pCurrClientFlatBuffer = NULL; icp_buffer_list_desc_t *pBufferListDesc = NULL; icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; Cpa64U internalDataLenInBytes = 0; LAC_ENSURE_NOT_NULL(pUserBufferList); LAC_ENSURE_NOT_NULL(pUserBufferList->pBuffers); LAC_ENSURE_NOT_NULL(pUserBufferList->pPrivateMetaData); LAC_ENSURE_NOT_NULL(pBufListAlignedPhyAddr); if (WRITE_AND_GET_SIZE == operationType || WRITE_ALLOW_0_BUFF_GET_SIZE == operationType) { LAC_ENSURE_NOT_NULL(totalDataLenInBytes); *totalDataLenInBytes = 0; } /* * Get the physical address of this descriptor - need to offset by the * alignment restrictions on the buffer descriptors */ bufListDescPhyAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( (*pService), pUserBufferList->pPrivateMetaData); if (INVALID_PHYSICAL_ADDRESS == bufListDescPhyAddr) { LAC_LOG_ERROR("Unable to get the physical address of the metadata\n"); return CPA_STATUS_FAIL; } bufListAlignedPhyAddr = LAC_ALIGN_POW2_ROUNDUP( bufListDescPhyAddr, ICP_DESCRIPTOR_ALIGNMENT_BYTES); pBufferListDesc = (icp_buffer_list_desc_t *)(LAC_ARCH_UINT)( (LAC_ARCH_UINT)pUserBufferList->pPrivateMetaData + ((LAC_ARCH_UINT)bufListAlignedPhyAddr - (LAC_ARCH_UINT)bufListDescPhyAddr)); /* Go past the Buffer List descriptor to the list of buffer descriptors */ pCurrFlatBufDesc = (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); if (pDictBufferList != NULL) { numBuffers = pDictBufferList->numBuffers; pCurrClientFlatBuffer = pDictBufferList->pBuffers; if (numBuffers >= MAX_SGL_BUFFERS) { LAC_LOG_ERROR("Max SGL buffers exceeded\n"); return CPA_STATUS_FAIL; } if (0 == numBuffers) { LAC_LOG_ERROR("Zero buffer requests are not allowed for " "dictionary APIs\n"); return CPA_STATUS_FAIL; } while (0 != numBuffers) { pCurrFlatBufDesc->dataLenInBytes = pCurrClientFlatBuffer->dataLenInBytes; /* Calculate the total data length in bytes */ internalDataLenInBytes += pCurrClientFlatBuffer->dataLenInBytes; /* Check if a physical address is provided in the function. If not * we need to convert it to a physical one */ if (CPA_TRUE == isPhysicalAddress) { pCurrFlatBufDesc->phyBuffer = LAC_MEM_CAST_PTR_TO_UINT64( (LAC_ARCH_UINT)(pCurrClientFlatBuffer->pData)); } else { pCurrFlatBufDesc->phyBuffer = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( (*pService), pCurrClientFlatBuffer->pData)); if (INVALID_PHYSICAL_ADDRESS == pCurrFlatBufDesc->phyBuffer) { LAC_LOG_ERROR("Unable to get the physical address of the " "client buffer\n"); return CPA_STATUS_FAIL; } } pCurrFlatBufDesc++; pCurrClientFlatBuffer++; numBuffers--; } dictNumBuffers += pDictBufferList->numBuffers; } pBufferListDesc->numBuffers = pUserBufferList->numBuffers + dictNumBuffers; numBuffers = pUserBufferList->numBuffers; pCurrClientFlatBuffer = pUserBufferList->pBuffers; if (pBufferListDesc->numBuffers >= MAX_SGL_BUFFERS) { LAC_LOG_ERROR("Max SGL buffers exceeded\n"); return CPA_STATUS_FAIL; } if (0 == numBuffers) { if (pDictBufferList != NULL || (WRITE_AND_ALLOW_ZERO_BUFFER != operationType && WRITE_ALLOW_0_BUFF_GET_SIZE != operationType)) { LAC_LOG_ERROR("Zero length buffer requests are not allowed for " "this operation\n"); return CPA_STATUS_FAIL; } else { /* Defining zero length buffers is useful for example if running * zero length hash. In the case where there are zero buffers within * the BufList it is required by firmware that the number is set to * 1 but the phyBuffer and dataLenInBytes are set to NULL. */ pBufferListDesc->numBuffers = 1; pCurrFlatBufDesc->dataLenInBytes = 0; pCurrFlatBufDesc->phyBuffer = 0; } } while (0 != numBuffers) { pCurrFlatBufDesc->dataLenInBytes = pCurrClientFlatBuffer->dataLenInBytes; /* Calculate the total data length in bytes */ internalDataLenInBytes += pCurrClientFlatBuffer->dataLenInBytes; /* Check if providing a physical address in the function. If not we * need to convert it to a physical one */ if (CPA_TRUE == isPhysicalAddress) { pCurrFlatBufDesc->phyBuffer = LAC_MEM_CAST_PTR_TO_UINT64( (LAC_ARCH_UINT)(pCurrClientFlatBuffer->pData)); } else { pCurrFlatBufDesc->phyBuffer = LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( (*pService), pCurrClientFlatBuffer->pData)); if (WRITE_AND_ALLOW_ZERO_BUFFER != operationType && WRITE_ALLOW_0_BUFF_GET_SIZE != operationType) { if (INVALID_PHYSICAL_ADDRESS == pCurrFlatBufDesc->phyBuffer) { LAC_LOG_ERROR("Unable to get the physical address of the " "client buffer\n"); return CPA_STATUS_FAIL; } } } pCurrFlatBufDesc++; pCurrClientFlatBuffer++; numBuffers--; } if (pDictBufferList != NULL && internalDataLenInBytes > DC_BUFFER_MAX_SIZE) { LAC_LOG_ERROR("Total data length including dictionary has exceeded " "max limits\n"); return CPA_STATUS_FAIL; } *pBufListAlignedPhyAddr = bufListAlignedPhyAddr; if (WRITE_AND_GET_SIZE == operationType || WRITE_ALLOW_0_BUFF_GET_SIZE == operationType) { *totalDataLenInBytes = internalDataLenInBytes; } return CPA_STATUS_SUCCESS; } /* This function implements the buffer description writes for the traditional * APIs Zero length buffers are allowed, should be used for CHA-CHA-POLY and * GCM algorithms */ CpaStatus LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( const CpaBufferList *pUserBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, sal_service_t *pService) { return LacBuffDesc_CommonBufferListDescWrite(pUserBufferList, NULL, pBufListAlignedPhyAddr, isPhysicalAddress, NULL, pService, WRITE_AND_ALLOW_ZERO_BUFFER); } /* This function does the same processing as * LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer but also * calculates the total length in bytes of the buffer list. */ CpaStatus LacBuffDesc_BufferListDescWriteAllow0BuffGetSize( const CpaBufferList *pUserBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, Cpa64U *totalDataLenInBytes, sal_service_t *pService) { return LacBuffDesc_CommonBufferListDescWrite(pUserBufferList, NULL, pBufListAlignedPhyAddr, isPhysicalAddress, totalDataLenInBytes, pService, WRITE_ALLOW_0_BUFF_GET_SIZE); } /* This function implements the buffer description writes for the traditional * APIs */ CpaStatus LacBuffDesc_BufferListDescWrite(const CpaBufferList *pUserBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, sal_service_t *pService) { return LacBuffDesc_CommonBufferListDescWrite(pUserBufferList, NULL, pBufListAlignedPhyAddr, isPhysicalAddress, NULL, pService, WRITE_NORMAL); } /* This function does the same processing as LacBuffDesc_BufferListDescWrite * but calculate as well the total length in bytes of the buffer list. */ CpaStatus LacBuffDesc_BufferListDescWriteAndGetSize( const CpaBufferList *pUserBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, Cpa64U *totalDataLenInBytes, sal_service_t *pService) { return LacBuffDesc_CommonBufferListDescWrite(pUserBufferList, NULL, pBufListAlignedPhyAddr, isPhysicalAddress, totalDataLenInBytes, pService, WRITE_AND_GET_SIZE); } /* This function does the same processing as * LacBuffDesc_BufferListDescWriteAndGetSize but includes an extra * dictionary buffer at the start of the meta data. */ CpaStatus LacBuffDesc_BufferListDescWriteWithDictAndGetSize( const CpaBufferList *pUserBufferList, const CpaBufferList *pDictionaryBufferList, Cpa64U *pBufListAlignedPhyAddr, CpaBoolean isPhysicalAddress, Cpa64U *totalDataLenInBytes, sal_service_t *pService) { return LacBuffDesc_CommonBufferListDescWrite(pUserBufferList, pDictionaryBufferList, pBufListAlignedPhyAddr, isPhysicalAddress, totalDataLenInBytes, pService, WRITE_AND_GET_SIZE); } CpaStatus LacBuffDesc_FlatBufferVerify( const CpaFlatBuffer *pUserFlatBuffer, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected) { LAC_CHECK_NULL_PARAM(pUserFlatBuffer); LAC_CHECK_NULL_PARAM(pUserFlatBuffer->pData); if (0 == pUserFlatBuffer->dataLenInBytes) { LAC_INVALID_PARAM_LOG("FlatBuffer empty"); return CPA_STATUS_INVALID_PARAM; } /* Expected alignment */ if (LAC_NO_ALIGNMENT_SHIFT != alignmentShiftExpected) { if (!LAC_ADDRESS_ALIGNED(pUserFlatBuffer->pData, alignmentShiftExpected)) { LAC_INVALID_PARAM_LOG1( "FlatBuffer not aligned as expected." " Expected alignment %lu Bytes.", (unsigned long)(1 << alignmentShiftExpected)); return CPA_STATUS_INVALID_PARAM; } } /* Update the total size of the packet. This function being called in a loop * for an entire buffer list we need to increment the value */ *pPktSize += pUserFlatBuffer->dataLenInBytes; return CPA_STATUS_SUCCESS; } CpaStatus LacBuffDesc_FlatBufferVerifyNull( const CpaFlatBuffer *pUserFlatBuffer, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected) { LAC_CHECK_NULL_PARAM(pUserFlatBuffer); LAC_ENSURE_NOT_NULL(pPktSize); if (0 != pUserFlatBuffer->dataLenInBytes) { LAC_CHECK_NULL_PARAM(pUserFlatBuffer->pData); } /* Expected alignment */ if (LAC_NO_ALIGNMENT_SHIFT != alignmentShiftExpected) { if (!LAC_ADDRESS_ALIGNED(pUserFlatBuffer->pData, alignmentShiftExpected)) { LAC_INVALID_PARAM_LOG1( "FlatBuffer not aligned as expected." " Expected alignment %lu Bytes.", (unsigned long)(1 << alignmentShiftExpected)); return CPA_STATUS_INVALID_PARAM; } } /* Update the total size of the packet. This function being called in a loop * for an entire buffer list we need to increment the value */ *pPktSize += pUserFlatBuffer->dataLenInBytes; return CPA_STATUS_SUCCESS; } CpaStatus LacBuffDesc_BufferListVerify( const CpaBufferList *pUserBufferList, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected) { CpaFlatBuffer *pCurrClientFlatBuffer = NULL; Cpa32U numBuffers = 0; CpaStatus status = CPA_STATUS_SUCCESS; LAC_CHECK_NULL_PARAM(pUserBufferList); LAC_CHECK_NULL_PARAM(pUserBufferList->pBuffers); LAC_ENSURE_NOT_NULL(pPktSize); LAC_CHECK_NULL_PARAM(pUserBufferList->pPrivateMetaData); numBuffers = pUserBufferList->numBuffers; if (0 == pUserBufferList->numBuffers) { LAC_INVALID_PARAM_LOG("Number of Buffers"); return CPA_STATUS_INVALID_PARAM; } pCurrClientFlatBuffer = pUserBufferList->pBuffers; *pPktSize = 0; while (0 != numBuffers && status == CPA_STATUS_SUCCESS) { status = LacBuffDesc_FlatBufferVerify( pCurrClientFlatBuffer, pPktSize, alignmentShiftExpected); pCurrClientFlatBuffer++; numBuffers--; } return status; } CpaStatus LacBuffDesc_BufferListVerifyNoMetadata( const CpaBufferList *pUserBufferList, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected) { CpaFlatBuffer *pCurrClientFlatBuffer = NULL; Cpa32U numBuffers = 0; CpaStatus status = CPA_STATUS_SUCCESS; LAC_CHECK_NULL_PARAM(pUserBufferList); LAC_CHECK_NULL_PARAM(pUserBufferList->pBuffers); LAC_ENSURE_NOT_NULL(pPktSize); numBuffers = pUserBufferList->numBuffers; if (0 == pUserBufferList->numBuffers) { LAC_INVALID_PARAM_LOG("Number of buffers"); return CPA_STATUS_INVALID_PARAM; } pCurrClientFlatBuffer = pUserBufferList->pBuffers; *pPktSize = 0; while (0 != numBuffers && status == CPA_STATUS_SUCCESS) { status = LacBuffDesc_FlatBufferVerify( pCurrClientFlatBuffer, pPktSize, alignmentShiftExpected); pCurrClientFlatBuffer++; numBuffers--; } return status; } CpaStatus LacBuffDesc_BufferListVerifyNull( const CpaBufferList *pUserBufferList, Cpa64U *pPktSize, lac_aligment_shift_t alignmentShiftExpected) { CpaFlatBuffer *pCurrClientFlatBuffer = NULL; Cpa32U numBuffers = 0; CpaStatus status = CPA_STATUS_SUCCESS; LAC_CHECK_NULL_PARAM(pUserBufferList); LAC_CHECK_NULL_PARAM(pUserBufferList->pBuffers); LAC_ENSURE_NOT_NULL(pPktSize); LAC_CHECK_NULL_PARAM(pUserBufferList->pPrivateMetaData); numBuffers = pUserBufferList->numBuffers; if (0 == numBuffers) { LAC_INVALID_PARAM_LOG("Number of Buffers"); return CPA_STATUS_INVALID_PARAM; } pCurrClientFlatBuffer = pUserBufferList->pBuffers; *pPktSize = 0; while (0 != numBuffers && status == CPA_STATUS_SUCCESS) { status = LacBuffDesc_FlatBufferVerifyNull( pCurrClientFlatBuffer, pPktSize, alignmentShiftExpected); pCurrClientFlatBuffer++; numBuffers--; } return status; } /** ****************************************************************************** * @ingroup LacBufferDesc *****************************************************************************/ void LacBuffDesc_BufferListTotalSizeGet(const CpaBufferList *pUserBufferList, Cpa64U *pPktSize) { CpaFlatBuffer *pCurrClientFlatBuffer = NULL; Cpa32U numBuffers = 0; LAC_ENSURE_NOT_NULL(pUserBufferList); LAC_ENSURE_NOT_NULL(pPktSize); LAC_ENSURE_NOT_NULL(pUserBufferList->pBuffers); pCurrClientFlatBuffer = pUserBufferList->pBuffers; numBuffers = pUserBufferList->numBuffers; *pPktSize = 0; while (0 != numBuffers) { *pPktSize += pCurrClientFlatBuffer->dataLenInBytes; pCurrClientFlatBuffer++; numBuffers--; } } void LacBuffDesc_BufferListZeroFromOffset(CpaBufferList *pBuffList, Cpa32U offset, Cpa32U lenToZero) { Cpa32U zeroLen = 0, sizeLeftToZero = 0; Cpa64U currentBufferSize = 0; CpaFlatBuffer *pBuffer = NULL; Cpa8U *pZero = NULL; pBuffer = pBuffList->pBuffers; /* Take a copy of total length to zero. */ sizeLeftToZero = lenToZero; while (sizeLeftToZero > 0) { currentBufferSize = pBuffer->dataLenInBytes; /* check where to start zeroing */ if (offset >= currentBufferSize) { /* Need to get to next buffer and reduce * offset size by data len of buffer */ offset = offset - pBuffer->dataLenInBytes; pBuffer++; } else { /* Start to Zero from this position */ pZero = (Cpa8U *)pBuffer->pData + offset; /* Need to calculate the correct number of bytes to zero * for this iteration and for this location. */ if (sizeLeftToZero >= pBuffer->dataLenInBytes) { /* The size to zero is spanning buffers, zeroLen in * this case is from pZero (position) to end of buffer. */ zeroLen = pBuffer->dataLenInBytes - offset; } else { /* zeroLen is set to sizeLeftToZero, then check if zeroLen and * the offset is greater or equal to the size of the buffer, if * yes, adjust the zeroLen to zero out the remainder of this * buffer. */ zeroLen = sizeLeftToZero; if ((zeroLen + offset) >= pBuffer->dataLenInBytes) { zeroLen = pBuffer->dataLenInBytes - offset; } } /* end inner else */ osalMemSet((void *)pZero, 0, zeroLen); sizeLeftToZero = sizeLeftToZero - zeroLen; /* offset is no longer required as any data left to zero is now * at the start of the next buffer. set offset to zero and move on * the buffer pointer to the next buffer. */ offset = 0; pBuffer++; } /* end outer else */ } /* end while */ } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/lac_lock_free_stack.h000066400000000000000000000107051503624047500314520ustar00rootroot00000000000000#ifndef LAC_LOCK_FREE_STACK_H_1 #define LAC_LOCK_FREE_STACK_H_1 /******************************************************************************* * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * @lac_lock_free_stack.h * * This file provides a lock-free stack implementation. * There is an assumption that effective virtual address size is 57-bit, * which is true for Linux user space applications in 32/64-bit modes. * Stack is usable on 48-bit and 57-bit platforms. * ******************************************************************************/ #ifndef KERNEL_SPACE #include #include #include #endif #include "lac_mem_pools.h" static inline lac_mem_blk_t *pop(lock_free_stack_t *stack) { pointer_t old_top; pointer_t new_top; lac_mem_blk_t *next; do { old_top.atomic = stack->top.atomic; next = old_top.ptr; if (NULL == next) return next; new_top.ptr = next->pNext; new_top.ctr = old_top.ctr + 1; } while (!__sync_bool_compare_and_swap( &stack->top.atomic, old_top.atomic, new_top.atomic)); return next; } static inline void push(lock_free_stack_t *stack, lac_mem_blk_t *val) { pointer_t new_top; pointer_t old_top; do { old_top.atomic = stack->top.atomic; val->pNext = old_top.ptr; new_top.ptr = val; new_top.ctr = old_top.ctr + 1; } while (!__sync_bool_compare_and_swap( &stack->top.atomic, old_top.atomic, new_top.atomic)); } static inline lock_free_stack_t _init_stack(void) { lock_free_stack_t stack = {{{0}}}; return stack; } static inline lac_mem_blk_t *top(lock_free_stack_t *stack) { pointer_t old_top = stack->top; lac_mem_blk_t *next = old_top.ptr; return next; } #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/lac_log_message.c000066400000000000000000000145441503624047500306210ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_log_message.c Utility functions for logging contents of Msgs on * IA-FW interface * * @ingroup LacLog * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "lac_common.h" #include "lac_mem.h" #include "icp_adf_cfg.h" #include "icp_adf_transport.h" #include "icp_adf_transport_dp.h" #include "icp_accel_devices.h" #include "sal_statistics.h" #include "sal_string_parse.h" #include "icp_adf_debug.h" #include "lac_sal_types.h" /* ******************************************************************************* * Define public/global function definitions ******************************************************************************* */ /** ***************************************************************************** * @ingroup LacLog *****************************************************************************/ /* ******************************************************************************* * Local functions ******************************************************************************* */ /** ***************************************************************************** * @ingroup lac_log_message * LacLogMsg_writeToDmesg() * * @description * Log the message to dmesg * * @param[in/out] pBlock * @param[in/out] size_in_lws * @param[in/out] block_type * * @retval CpaStatus * *****************************************************************************/ /** ***************************************************************************** * @ingroup lac_log_message * set_osal_log_debug_level() * * @description * * * @retval None * *****************************************************************************/ Cpa64U conf_osal_log_level_debug = 0; void set_osal_log_debug_level(void) { Cpa64U previous_level = 0; if (conf_osal_log_level_debug > 0) { /* enable output from LAC_LOG_DEBUG */ /* LAC_LOG_LVL_DEBUG1 = 6, DEBUG2=7, DEBUG3=8 */ osalLogLevelSet(conf_osal_log_level_debug); } else { /*don't change the conf level, just print it. */ previous_level = osalLogLevelSet(0); osalLogLevelSet(previous_level); } } /** ***************************************************************************** * @ingroup lac_log_message * LacLogMsg_SetConfig() * * @description * * @param[in/out] device * * @retval None * *****************************************************************************/ void LacLogMsg_SetConfig(icp_accel_dev_t *device) { char paramValue[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; CpaStatus status = CPA_STATUS_SUCCESS; status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, "osal_log_level_debug", paramValue); if (status == CPA_STATUS_SUCCESS) { Cpa64U new_level = 0; new_level = Sal_Strtoul(paramValue, NULL, SAL_CFG_BASE_DEC); if ((new_level >= 1) && (new_level <= 3)) { /* enable output from LAC_LOG_DEBUG - filtered out by default*/ /* LAC_LOG_LVL_DEBUG1 = 6, DEBUG2=7, DEBUG3=8 */ conf_osal_log_level_debug = new_level + 5; } } set_osal_log_debug_level(); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/lac_mem.c000066400000000000000000000215011503624047500271010ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_mem.c Implementation of Memory Functions * * @ingroup LacMem * *****************************************************************************/ /* ******************************************************************************* * Include header files ******************************************************************************* */ #include "Osal.h" #include "cpa.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_debug.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_common.h" #include "lac_pke_utils.h" #include "lac_log.h" #include "lac_sym.h" #include "lac_list.h" #include "lac_sym_qat.h" #include "icp_qat_fw_la.h" #include "lac_sal_types_crypto.h" #ifdef KERNEL_SPACE #include "qdm.h" #endif /* ******************************************************************************** * Static Variables ******************************************************************************** */ #define MAX_BUFFER_SIZE (LAC_BITS_TO_BYTES(4096)) /**< @ingroup LacMem * Maximum size of the buffers used in the resize function */ /* ******************************************************************************* * Define public/global function definitions ******************************************************************************* */ /** * @ingroup LacMem */ Cpa8U *icp_LacBufferResize(CpaInstanceHandle instanceHandle, Cpa8U *pUserBuffer, Cpa32U userLen, Cpa32U workingLen, CpaBoolean *pInternalMemory) { Cpa8U *pWorkingBuffer = NULL; Cpa32U padSize = 0; sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)instanceHandle; if ((userLen > 0) && (NULL == pUserBuffer)) { LAC_LOG_ERROR("pUserBuffer parameter is NULL"); return NULL; } /* shouldn't trim the user buffer */ if (workingLen < userLen) { LAC_LOG_ERROR2( "Cannot trim input buffer from %u to %u", userLen, workingLen); return NULL; } padSize = workingLen - userLen; /* check size */ if (padSize > 0) { do { pWorkingBuffer = (Cpa8U *)Lac_MemPoolEntryAlloc( pCryptoService->lac_pke_align_pool); if (NULL == pWorkingBuffer) { LAC_LOG_ERROR("Failed to allocate pWorkingBuffer"); return NULL; } else if ((void *)CPA_STATUS_RETRY == pWorkingBuffer) { osalYield(); } } while ((void *)CPA_STATUS_RETRY == pWorkingBuffer); /* Zero MSB of buffer */ LAC_OS_BZERO(pWorkingBuffer, padSize); /* Copy from user buffer to internal buffer */ if (userLen) { memcpy(pWorkingBuffer + padSize, pUserBuffer, userLen); } /* Indicate that internally allocated memory is being sent to QAT */ *pInternalMemory = CPA_TRUE; return pWorkingBuffer; } /* if (padSize > 0) ... */ return pUserBuffer; } /** * @ingroup LacMem */ CpaStatus icp_LacBufferRestore(Cpa8U *pUserBuffer, Cpa32U userLen, Cpa8U *pWorkingBuffer, Cpa32U workingLen, CpaBoolean copyBuf) { Cpa32U padSize = 0; /* NULL is a valid value for working buffer as this function may be * called to clean up in an error case where all the resize operations * were not completed */ if (NULL == pWorkingBuffer) { return CPA_STATUS_SUCCESS; } if (workingLen < userLen) { LAC_LOG_ERROR("Invalid buffer sizes"); return CPA_STATUS_INVALID_PARAM; } if (pUserBuffer != pWorkingBuffer) { if (CPA_TRUE == copyBuf) { /* Copy from internal buffer to user buffer */ padSize = workingLen - userLen; memcpy(pUserBuffer, pWorkingBuffer + padSize, userLen); } Lac_MemPoolEntryFree(pWorkingBuffer); } return CPA_STATUS_SUCCESS; } /** * @ingroup LacMem */ CpaPhysicalAddr SalMem_virt2PhysExternal(void *pVirtAddr, void *pServiceGen) { sal_service_t *pService = (sal_service_t *)pServiceGen; if (NULL != pService->virt2PhysClient) { return pService->virt2PhysClient(pVirtAddr); } else { /* Use internal OSAL virt to phys */ /* Ok for kernel space probably should not use for user */ return LAC_OS_VIRT_TO_PHYS_INTERNAL(pServiceGen, pVirtAddr); } } #ifdef USER_SPACE /** * @ingroup LacMem */ CpaPhysicalAddr SalMem_virt2PhysInternal(void *pVirtAddr, void *pServiceGen) { return (CpaPhysicalAddr)qaeVirtToPhysNUMA(pVirtAddr); } #endif size_t icp_sal_iommu_get_remap_size(size_t size) { #if (defined(USER_SPACE) || defined(_WIN64)) return osalIOMMUgetRemappingSize(size); #else int pages = size % PAGE_SIZE ? size / PAGE_SIZE + 1 : size / PAGE_SIZE; size_t new_size = (pages * PAGE_SIZE); return new_size; #endif } CpaStatus icp_sal_iommu_map(Cpa64U phaddr, Cpa64U iova, size_t size) { #if (defined(USER_SPACE) || defined(_WIN64)) return osalIOMMUMap((UINT64)phaddr, (UINT64)iova, size) == 0 ? CPA_STATUS_SUCCESS : CPA_STATUS_FAIL; #else void *virt_addr = phys_to_virt(phaddr); return qdm_iommu_map((void *)(LAC_ARCH_UINT)iova, virt_addr, size) == 0 ? CPA_STATUS_SUCCESS : CPA_STATUS_FAIL; #endif } CpaStatus icp_sal_iommu_unmap(Cpa64U iova, size_t size) { #if (defined(USER_SPACE) || defined(_WIN64)) return osalIOMMUUnmap((UINT64)iova, size) == 0 ? CPA_STATUS_SUCCESS : CPA_STATUS_FAIL; #else return qdm_iommu_unmap(iova, size) == 0 ? CPA_STATUS_SUCCESS : CPA_STATUS_FAIL; #endif } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/lac_mem_pools.c000066400000000000000000000445271503624047500303320ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_mem_pools.c * * @ingroup LacMemPool * * Memory Pool creation and mgmt function implementations * ***************************************************************************/ #include "cpa.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_debug.h" #include "lac_log.h" #include "lac_lock_free_stack.h" #include "lac_mem_pools.h" #include "lac_mem.h" #include "lac_common.h" #include "cpa_dc.h" #include "dc_session.h" #include "dc_datapath.h" #include "icp_qat_fw_comp.h" #include "icp_buffer_desc.h" #include "Osal.h" #ifndef ICP_DC_ONLY #include "lac_pke_qat_comms.h" #include "lac_sym.h" #endif #ifdef KERNEL_SPACE #define ASYM_NOT_SUPPORTED #endif #define LAC_MEM_POOLS_NUM_SUPPORTED 32000 /**< @ingroup LacMemPool * Number of mem pools supported */ static lac_mem_pool_hdr_t *lac_mem_pools[LAC_MEM_POOLS_NUM_SUPPORTED] = {NULL}; /**< @ingroup LacMemPool * Array of pointers to the mem pool header structure */ LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t); /**< @ingroup LacMemPool * local constant for quickening computation of additional space allocated * for holding lac_mem_blk_t container-structure */ /** ******************************************************************************* * @ingroup LacMemPool * This function cleans up a mem pool. ******************************************************************************/ void Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID); static inline Cpa32U Lac_MemPoolGetElementRealSize(Cpa32U blkSizeInBytes, Cpa32U blkAlignmentInBytes) { Cpa32U addSize = (blkAlignmentInBytes >= sizeof(lac_mem_blk_t) ? blkAlignmentInBytes : 1 << (highest_bit_of_lac_mem_blk_t + 1)); return blkSizeInBytes + addSize; } CpaBoolean Lac_MemPoolTestAndGet(lac_memory_pool_id_t poolID) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; return osalAtomicDecAndTest(&(pPoolID->sync)); } CpaStatus Lac_MemPoolCreate( lac_memory_pool_id_t *pPoolID, char *poolName, unsigned int numElementsInPool, /*Number of elements*/ unsigned int blkSizeInBytes, /*Block Size in bytes*/ unsigned int blkAlignmentInBytes, /*Block alignment (bytes)*/ CpaBoolean trackMemory, Cpa32U node) { unsigned int poolSearch = 0; unsigned int counter = 0; lac_mem_blk_t *pMemBlkCurrent = NULL; void *pMemBlk = NULL; if (pPoolID == NULL) { LAC_LOG_ERROR("Invalid Pool ID param"); return CPA_STATUS_INVALID_PARAM; /*Error*/ } /* Find First available Pool return error otherwise */ while (lac_mem_pools[poolSearch] != NULL) { poolSearch++; if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) { LAC_LOG_ERROR("No more memory pools available for allocation"); return CPA_STATUS_FAIL; } } /* Allocate a Pool header */ if (CPA_STATUS_SUCCESS != LAC_OS_MALLOC(&lac_mem_pools[poolSearch], sizeof(lac_mem_pool_hdr_t))) { LAC_LOG_ERROR("Unable to allocate memory for creation of the pool"); return CPA_STATUS_RESOURCE; /*Error*/ } osalMemSet(lac_mem_pools[poolSearch], 0, sizeof(lac_mem_pool_hdr_t)); /* Copy in Pool Name */ if (poolName != NULL) { snprintf(lac_mem_pools[poolSearch]->poolName, LAC_MEM_POOLS_NAME_SIZE, "%s", poolName); } else { LAC_OS_FREE(lac_mem_pools[poolSearch]); lac_mem_pools[poolSearch] = NULL; LAC_LOG_ERROR("Invalid Pool Name pointer"); return CPA_STATUS_INVALID_PARAM; /*Error*/ } /* Allocate table for tracking memory blocks */ if (CPA_TRUE == trackMemory) { if (CPA_STATUS_SUCCESS != LAC_OS_MALLOC(&(lac_mem_pools[poolSearch]->trackBlks), (sizeof(lac_mem_blk_t *) * numElementsInPool))) { LAC_OS_FREE(lac_mem_pools[poolSearch]); lac_mem_pools[poolSearch] = NULL; LAC_LOG_ERROR( "Unable to allocate memory for tracking memory blocks"); return CPA_STATUS_RESOURCE; /*Error*/ } } else { lac_mem_pools[poolSearch]->trackBlks = NULL; } lac_mem_pools[poolSearch]->availBlks = 0; lac_mem_pools[poolSearch]->stack = _init_stack(); /* Calculate alignment needed for allocation */ for (counter = 0; counter < numElementsInPool; counter++) { CpaPhysicalAddr physAddr = 0; /* realSize is computed for allocation of blkSize bytes + additional capacity for lac_mem_blk_t structure storage due to the some OSes (BSD) limitations for memory alignment to be power of 2; sizeof(lac_mem_blk_t) is being round up to the closest power of 2 - optimised towards the least CPU overhead but at additional memory cost */ Cpa32U realSize = Lac_MemPoolGetElementRealSize(blkSizeInBytes, blkAlignmentInBytes); Cpa32U addSize = realSize - blkSizeInBytes; if (CPA_STATUS_SUCCESS != LAC_OS_CAMALLOC(&pMemBlk, realSize, blkAlignmentInBytes, node)) { Lac_MemPoolCleanUpInternal(lac_mem_pools[poolSearch]); lac_mem_pools[poolSearch] = NULL; LAC_LOG_ERROR("Unable to allocate contiguous chunk of memory"); return CPA_STATUS_RESOURCE; } /* Calcaulate various offsets */ physAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( NULL, (void *)((LAC_ARCH_UINT)pMemBlk + addSize)); /* physAddr is now already aligned to the greater power of 2: blkAlignmentInBytes or sizeof(lac_mem_blk_t) round up We safely put the structure right before the blkSize real data block */ pMemBlkCurrent = (lac_mem_blk_t *)(((LAC_ARCH_UINT)(pMemBlk)) + addSize - sizeof(lac_mem_blk_t)); pMemBlkCurrent->physDataPtr = physAddr; pMemBlkCurrent->pMemAllocPtr = pMemBlk; pMemBlkCurrent->pPoolID = lac_mem_pools[poolSearch]; pMemBlkCurrent->isInUse = CPA_FALSE; pMemBlkCurrent->pNext = NULL; push(&lac_mem_pools[poolSearch]->stack, pMemBlkCurrent); /* Store allocated memory pointer */ if (lac_mem_pools[poolSearch]->trackBlks != NULL) { (lac_mem_pools[poolSearch]->trackBlks[counter]) = (lac_mem_blk_t *)pMemBlkCurrent; } __sync_add_and_fetch(&lac_mem_pools[poolSearch]->availBlks, 1); (lac_mem_pools[poolSearch])->numElementsInPool = counter + 1; } /* Set Pool details in the header */ (lac_mem_pools[poolSearch])->blkSizeInBytes = blkSizeInBytes; (lac_mem_pools[poolSearch])->blkAlignmentInBytes = blkAlignmentInBytes; (lac_mem_pools[poolSearch])->active = CPA_TRUE; osalAtomicSet(1, (OsalAtomic *)&((lac_mem_pools[poolSearch])->sync)); /* Set the Pool ID output parameter */ *pPoolID = (LAC_ARCH_UINT)(lac_mem_pools[poolSearch]); /* Success */ return CPA_STATUS_SUCCESS; } void Lac_MemPoolEnable(lac_memory_pool_id_t poolID) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; if (NULL == pPoolID) { LAC_LOG_ERROR("Invalid Pool ID"); return; } pPoolID->active = CPA_TRUE; osalAtomicSet(1, (OsalAtomic *)&(pPoolID->sync)); return; } void Lac_MemPoolDisable(lac_memory_pool_id_t poolID) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; if (NULL == pPoolID) { LAC_LOG_ERROR("Invalid Pool ID"); return; } pPoolID->active = CPA_FALSE; return; } void *Lac_MemPoolEntryAlloc(lac_memory_pool_id_t poolID) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; lac_mem_blk_t *pMemBlkCurrent = NULL; #ifdef ICP_DEBUG /* Explicitly removing NULL PoolID check for speed */ if (pPoolID == NULL) { LAC_LOG_ERROR("Invalid Pool ID"); return NULL; } #endif /* ICP_DEBUG */ if (unlikely(pPoolID->active == CPA_FALSE)) return NULL; /* Remove block from pool */ pMemBlkCurrent = pop(&pPoolID->stack); if (NULL == pMemBlkCurrent) { return (void *)CPA_STATUS_RETRY; } __sync_sub_and_fetch(&pPoolID->availBlks, 1); pMemBlkCurrent->isInUse = CPA_TRUE; return (void *)((LAC_ARCH_UINT)(pMemBlkCurrent) + sizeof(lac_mem_blk_t)); } void Lac_MemPoolEntryFree(void *pEntry) { lac_mem_blk_t *pMemBlk = NULL; #ifdef ICP_DEBUG /* Explicitly NULL pointer check */ if (pEntry == NULL) { LAC_LOG_ERROR("Memory Handle NULL"); return; } #endif /*ICP_DEBUG*/ pMemBlk = (lac_mem_blk_t *)((LAC_ARCH_UINT)pEntry - sizeof(lac_mem_blk_t)); pMemBlk->isInUse = CPA_FALSE; push(&pMemBlk->pPoolID->stack, pMemBlk); __sync_add_and_fetch(&pMemBlk->pPoolID->availBlks, 1); } void Lac_MemPoolDestroy(lac_memory_pool_id_t poolID) { unsigned int poolSearch = 0; lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; if (pPoolID != NULL) { /*Remove entry from table*/ while (lac_mem_pools[poolSearch] != pPoolID) { poolSearch++; if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) { LAC_LOG_ERROR("Invalid Pool ID submitted"); return; } } lac_mem_pools[poolSearch] = NULL; /*Remove handle from pool*/ Lac_MemPoolCleanUpInternal(pPoolID); } } void Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID) { lac_mem_blk_t *pCurrentBlk = NULL; void *pFreePtr = NULL; Cpa32U count = 0; if (pPoolID->trackBlks == NULL) { pCurrentBlk = pop(&pPoolID->stack); while (pCurrentBlk != NULL) { /* Free Data Blocks */ pFreePtr = pCurrentBlk->pMemAllocPtr; pCurrentBlk = pop(&pPoolID->stack); LAC_OS_CAFREE(pFreePtr); } } else { for (count = 0; count < pPoolID->numElementsInPool; count++) { pFreePtr = (pPoolID->trackBlks[count])->pMemAllocPtr; LAC_OS_CAFREE(pFreePtr); } LAC_OS_FREE(pPoolID->trackBlks); } LAC_OS_FREE(pPoolID); } unsigned int Lac_MemPoolAvailableEntries(lac_memory_pool_id_t poolID) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; if (pPoolID == NULL) { LAC_LOG_ERROR("Invalid Pool ID"); return 0; } return pPoolID->availBlks; } void Lac_MemPoolStatsShow(void) { unsigned int index = 0; osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, SEPARATOR BORDER " Memory Pools Stats\n" SEPARATOR); while (index < LAC_MEM_POOLS_NUM_SUPPORTED) { if (lac_mem_pools[index] != NULL) { osalLog(OSAL_LOG_LVL_USER, OSAL_LOG_DEV_STDOUT, BORDER " Pool Name: %s \n" BORDER " Active status: %10s \n" BORDER " No. Elements in Pool: %10u \n" BORDER " Element Size in Bytes: %10u \n" BORDER " Alignment in Bytes: %10u \n" BORDER " No. Available Blocks: %10zu \n" SEPARATOR, lac_mem_pools[index]->poolName, lac_mem_pools[index]->active ? "TRUE" : "FALSE", lac_mem_pools[index]->numElementsInPool, lac_mem_pools[index]->blkSizeInBytes, lac_mem_pools[index]->blkAlignmentInBytes, lac_mem_pools[index]->availBlks); } index++; } } CpaStatus Lac_MemPoolInitDcCookies(lac_memory_pool_id_t poolID) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; lac_mem_blk_t *pCurrentBlk = NULL; Cpa32U count = 0; if (NULL == pPoolID) { LAC_LOG_ERROR("Invalid Pool ID"); return CPA_STATUS_FAIL; } if (pPoolID->trackBlks != NULL) { for (count = 0; count < pPoolID->numElementsInPool; count++) { pCurrentBlk = pPoolID->trackBlks[count]; pCurrentBlk->opaque = ICP_ADF_INVALID_SEND_SEQ; } } return CPA_STATUS_SUCCESS; } #ifndef ICP_DC_ONLY static void Lac_MemPoolInitSymCookies(lac_sym_cookie_t *pSymCookie, CpaInstanceHandle instanceHandle) { pSymCookie->keyContentDescDevAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( instanceHandle, pSymCookie->u.keyCookie.contentDesc); pSymCookie->keyHashStateBufferDevAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( instanceHandle, pSymCookie->u.keyCookie.hashStateBuffer); pSymCookie->keySslKeyInputDevAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( instanceHandle, &(pSymCookie->u.keyCookie.u.sslKeyInput)); pSymCookie->keyTlsKeyInputDevAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( instanceHandle, &(pSymCookie->u.keyCookie.u.tlsKeyInput)); } CpaStatus Lac_MemPoolInitSymCookiesPhyAddr(lac_memory_pool_id_t poolID, CpaInstanceHandle instanceHandle) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; lac_sym_cookie_t *pSymCookie = NULL; lac_mem_blk_t *pCurrentBlk = NULL; if (NULL == pPoolID) { LAC_LOG_ERROR("Invalid Pool ID"); return CPA_STATUS_FAIL; } if (pPoolID->trackBlks == NULL) { pCurrentBlk = top(&pPoolID->stack); while (pCurrentBlk != NULL) { pSymCookie = (lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + sizeof(lac_mem_blk_t)); pCurrentBlk = pCurrentBlk->pNext; Lac_MemPoolInitSymCookies(pSymCookie, instanceHandle); } } else { Cpa32U count = 0; for (count = 0; count < pPoolID->numElementsInPool; count++) { pCurrentBlk = pPoolID->trackBlks[count]; pCurrentBlk->opaque = ICP_ADF_INVALID_SEND_SEQ; pSymCookie = (lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + sizeof(lac_mem_blk_t)); Lac_MemPoolInitSymCookies(pSymCookie, instanceHandle); } } return CPA_STATUS_SUCCESS; } #ifndef ASYM_NOT_SUPPORTED CpaStatus Lac_MemPoolInitAsymCookies(lac_memory_pool_id_t poolID, CpaInstanceHandle instanceHandle) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; lac_mem_blk_t *pCurrentBlk = NULL; Cpa8U *pAsymReq = NULL; if (NULL == pPoolID) { LAC_LOG_ERROR("Invalid Pool ID"); return CPA_STATUS_FAIL; } if (pPoolID->trackBlks == NULL) { pCurrentBlk = top(&pPoolID->stack); while (pCurrentBlk != NULL) { pAsymReq = (Cpa8U *)((LAC_ARCH_UINT)(pCurrentBlk) + sizeof(lac_mem_blk_t)); pCurrentBlk = pCurrentBlk->pNext; LacPke_InitAsymRequest(pAsymReq, instanceHandle); } } else { Cpa32U count = 0; for (count = 0; count < pPoolID->numElementsInPool; count++) { pCurrentBlk = pPoolID->trackBlks[count]; pCurrentBlk->opaque = ICP_ADF_INVALID_SEND_SEQ; pAsymReq = (Cpa8U *)((LAC_ARCH_UINT)(pCurrentBlk) + sizeof(lac_mem_blk_t)); LacPke_InitAsymRequest(pAsymReq, instanceHandle); } } return CPA_STATUS_SUCCESS; } #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/lac_sw_responses.c000066400000000000000000000216771503624047500310730ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file lac_sw_responses.c * * @ingroup LacSwResponses * * Calculation of memory pools which contain in-flight requests function * implementations. The memory pools which contain in-flight requests will * be named as busy memory pools. * ***************************************************************************/ #include "cpa.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "lac_lock_free_stack.h" #include "lac_mem_pools.h" #include "lac_mem.h" #include "lac_common.h" #include "lac_session.h" #include "lac_sym_cb.h" #include "Osal.h" #ifndef ICP_DC_ONLY #include "lac_pke_qat_comms.h" #endif #ifdef KERNEL_SPACE #define ASYM_NOT_SUPPORTED #endif #include "dc_datapath.h" static OsalAtomic lac_sw_resp_num_pools_busy = ATOMIC_INIT(0); /**< @ingroup LacSwResponses * Number of busy memory pools */ void LacSwResp_IncNumPoolsBusy(lac_memory_pool_id_t poolID) { lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; if (pPoolID->availBlks != pPoolID->numElementsInPool) { osalAtomicInc(&lac_sw_resp_num_pools_busy); } return; } Cpa16U LacSwResp_GetNumPoolsBusy(void) { return (Cpa16U)osalAtomicGet(&lac_sw_resp_num_pools_busy); } void LacSwResp_InitNumPoolsBusy(void) { osalAtomicSet(0, &lac_sw_resp_num_pools_busy); } #ifndef ICP_DC_ONLY #ifndef ASYM_NOT_SUPPORTED /** ******************************************************************************* * @ingroup LacSwResponses * This function creates a bucket with in-order memblks. ******************************************************************************/ STATIC lac_memblk_bucket_t *LacSwResp_MemBlkBucketCreate(lac_mem_pool_hdr_t *pPoolID) { lac_mem_blk_t *pCurrentBlk = NULL; lac_mem_blk_t **pBucketBlk = NULL; lac_memblk_bucket_t *pBucket = NULL; Cpa32U i = 0; Cpa64U opaque = 0; Cpa32U numBlksUsed = 0; Cpa64U seq = ICP_ADF_INVALID_SEND_SEQ; numBlksUsed = pPoolID->numElementsInPool - pPoolID->availBlks; if (0 == numBlksUsed) { return NULL; } pBucket = osalMemAlloc(sizeof(lac_memblk_bucket_t)); if (!pBucket) { LAC_LOG_ERROR("Failed to allocate memory for pBucket."); return NULL; } osalMemSet(pBucket, 0, sizeof(lac_memblk_bucket_t)); pBucket->mem_blk = (lac_mem_blk_t **)osalMemAlloc(sizeof(lac_mem_blk_t *) * numBlksUsed); if (!pBucket->mem_blk) { osalMemFree(pBucket); LAC_LOG_ERROR("Failed to allocate memory for mem_blk."); return NULL; } pBucket->numBucketBlks = numBlksUsed; pBucket->numBlksInRing = 0; pBucketBlk = pBucket->mem_blk; osalMemSet(pBucketBlk, 0, sizeof(lac_mem_blk_t *) * numBlksUsed); while (i < pPoolID->numElementsInPool) { pCurrentBlk = pPoolID->trackBlks[i++]; if (CPA_TRUE != pCurrentBlk->isInUse) { continue; } opaque = pCurrentBlk->opaque; if (ICP_ADF_INVALID_SEND_SEQ == opaque) { pCurrentBlk->isInUse = CPA_FALSE; push(&pCurrentBlk->pPoolID->stack, pCurrentBlk); __sync_add_and_fetch(&pCurrentBlk->pPoolID->availBlks, 1); continue; } pBucket->numBlksInRing++; pBucketBlk[opaque % numBlksUsed] = pCurrentBlk; if (opaque < seq) { seq = opaque; pBucket->startIndex = opaque % numBlksUsed; } } return pBucket; } /** ******************************************************************************* * @ingroup LacSwResponses * This function frees the bucket with memblks containing in-flight requests. ******************************************************************************/ STATIC void LacSwResp_MemBlkBucketDestroy(lac_memblk_bucket_t *pBucket) { if (NULL == pBucket) { return; } if (NULL != pBucket->mem_blk) { osalMemFree(pBucket->mem_blk); } osalMemFree(pBucket); return; } STATIC CpaStatus LacSwResp_GenRespMsgCallback(lac_memblk_bucket_t *pBucket, sal_service_type_t type) { CpaStatus status = CPA_STATUS_RETRY; switch (type) { case SAL_SERVICE_TYPE_COMPRESSION: case SAL_SERVICE_TYPE_DECOMPRESSION: status = dcCompression_SwRespMsgCallback(pBucket); break; case SAL_SERVICE_TYPE_CRYPTO_SYM: status = LacSym_SwRespMsgCallback(pBucket); break; case SAL_SERVICE_TYPE_CRYPTO_ASYM: status = LacPke_SwRespMsgCallback(pBucket); break; default: break; } return status; } CpaStatus LacSwResp_GenResp(lac_memory_pool_id_t lac_mem_pool, sal_service_type_t type) { CpaStatus status = CPA_STATUS_RETRY; lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)lac_mem_pool; lac_memblk_bucket_t *pBucket; if (NULL == pPoolID || CPA_TRUE == pPoolID->active) { LAC_LOG_ERROR("Invalid pPoolID or active status!"); return CPA_STATUS_INVALID_PARAM; } if (Lac_MemPoolTestAndGet(lac_mem_pool)) { if (pPoolID->numElementsInPool < pPoolID->availBlks) { LAC_LOG_ERROR("Invalid availBlks!"); return CPA_STATUS_FATAL; } if (pPoolID->numElementsInPool == pPoolID->availBlks) { return CPA_STATUS_RETRY; } if (NULL == pPoolID->trackBlks) { LAC_LOG_ERROR("Invalid trackBlks!"); return CPA_STATUS_FAIL; } pBucket = LacSwResp_MemBlkBucketCreate(pPoolID); if (NULL == pBucket) { LAC_LOG_ERROR("Failed to create pBucket!"); return CPA_STATUS_RESOURCE; } status = LacSwResp_GenRespMsgCallback(pBucket, type); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { LAC_LOG_ERROR("Failed to generate dummy responses!"); } LacSwResp_MemBlkBucketDestroy(pBucket); } return status; } #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/lac_sync.c000066400000000000000000000154121503624047500273030ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file lac_sync.c Utility functions containing synchronous callback support * functions * * @ingroup LacSync * *****************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "lac_sync.h" #include "lac_common.h" /* ******************************************************************************* * Define public/global function definitions ******************************************************************************* */ /** ***************************************************************************** * @ingroup LacSync *****************************************************************************/ void LacSync_GenWakeupSyncCaller(void *pCallbackTag, CpaStatus status) { lac_sync_op_data_t *pSc = (lac_sync_op_data_t *)pCallbackTag; if (pSc != NULL) { if (pSc->canceled) { LAC_LOG_ERROR("Synchronous operation cancelled\n"); return; } pSc->status = status; LAC_POST_SEMAPHORE(pSc->sid); } } /** ***************************************************************************** * @ingroup LacSync *****************************************************************************/ void LacSync_GenVerifyWakeupSyncCaller(void *pCallbackTag, CpaStatus status, CpaBoolean opResult) { lac_sync_op_data_t *pSc = (lac_sync_op_data_t *)pCallbackTag; if (pSc != NULL) { if (pSc->canceled) { LAC_LOG_ERROR("Synchronous operation cancelled\n"); return; } pSc->status = status; pSc->opResult = opResult; LAC_POST_SEMAPHORE(pSc->sid); } } /** ***************************************************************************** * @ingroup LacSync *****************************************************************************/ void LacSync_GenVerifyCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean opResult) { LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); } /** ***************************************************************************** * @ingroup LacSync *****************************************************************************/ void LacSync_GenFlatBufCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { LacSync_GenWakeupSyncCaller(pCallbackTag, status); } /** ***************************************************************************** * @ingroup LacSync *****************************************************************************/ void LacSync_GenFlatBufVerifyCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean opResult, CpaFlatBuffer *pOut) { LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); } /** ***************************************************************************** * @ingroup LacSync *****************************************************************************/ void LacSync_GenDualFlatBufVerifyCb(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaBoolean opResult, CpaFlatBuffer *pOut0, CpaFlatBuffer *pOut1) { LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/sal_misc_error_stats.c000066400000000000000000000120731503624047500317310ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_misc_error_stats.c * * @defgroup SalMiscErrorStats Sal Miscellaneous Error Statistics * * @ingroup SalMiscErrorStats * * @description * This file contains implementation of Miscellaneous error statistic related *functions * *****************************************************************************/ #include "cpa.h" #include "lac_common.h" #include "lac_mem.h" #include "icp_adf_cfg.h" #include "icp_accel_devices.h" #include "sal_statistics.h" #include "icp_adf_user_proxy.h" #include "icp_adf_debug.h" #include "lac_sal_types.h" #include "lac_sal.h" STATIC OsalAtomic *numMiscError; /* @ingroup SalMiscErrorStats */ CpaStatus Sal_IncMiscErrStats(sal_service_t *pService) { if (!pService) { LAC_LOG_ERROR("Invalid Parameter.\n"); return CPA_STATUS_INVALID_PARAM; } if (numMiscError && CPA_TRUE == pService->stats->bMiscStatsEnabled) { osalAtomicInc(numMiscError); } return CPA_STATUS_SUCCESS; } /* @ingroup SalMiscErrorStats */ CpaStatus Sal_GetMiscErrStats(sal_service_t *pService, OsalAtomic *pMiscStats) { if (!pService || !pMiscStats) { LAC_LOG_ERROR("Invalid Parameter.\n"); return CPA_STATUS_INVALID_PARAM; } if (numMiscError && CPA_TRUE == pService->stats->bMiscStatsEnabled) { *(Cpa64U *)pMiscStats = osalAtomicGet(numMiscError); } else { return CPA_STATUS_RESOURCE; } return CPA_STATUS_SUCCESS; } /* @ingroup SalMiscErrorStats */ CpaStatus Sal_InitMiscErrStats(sal_statistics_collection_t *pStats) { CpaStatus status = CPA_STATUS_SUCCESS; if (!numMiscError && pStats && CPA_TRUE == pStats->bStatsEnabled) { icp_adf_mmap_misc_counter((Cpa64U **)&numMiscError); } return status; } /* @ingroup SalMiscErrorStats */ CpaStatus Sal_CleanMiscErrStats(sal_service_t *pService) { CpaStatus status = CPA_STATUS_SUCCESS; if (numMiscError && pService && pService->stats && CPA_TRUE == pService->stats->bMiscStatsEnabled) { icp_adf_unmap_misc_counter((Cpa64U *)numMiscError); numMiscError = NULL; } return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/sal_service_state.c000066400000000000000000000103211503624047500312010ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** *************************************************************************** * @file sal_service_state.c Service state checks * * @ingroup SalServiceState * ***************************************************************************/ /* ******************************************************************************* * Include public/global header files ******************************************************************************* */ #include "cpa.h" #include "lac_list.h" #include "icp_accel_devices.h" #include "icp_adf_debug.h" #include "lac_sal_types.h" #include "sal_service_state.h" CpaBoolean Sal_ServiceIsRunning(CpaInstanceHandle instanceHandle) { sal_service_t *pService = (sal_service_t *)instanceHandle; if (SAL_SERVICE_STATE_RUNNING == pService->state) { return CPA_TRUE; } return CPA_FALSE; } CpaBoolean Sal_ServiceIsRestarting(CpaInstanceHandle instanceHandle) { sal_service_t *pService = (sal_service_t *)instanceHandle; if (SAL_SERVICE_STATE_RESTARTING == pService->state) { return CPA_TRUE; } return CPA_FALSE; } CpaBoolean Sal_ServiceIsInError(CpaInstanceHandle instanceHandle) { sal_service_t *pService = (sal_service_t *)instanceHandle; if (SAL_SERVICE_STATE_ERROR == pService->state) { return CPA_TRUE; } return CPA_FALSE; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/sal_statistics.c000066400000000000000000000217251503624047500305450ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_statistics.c * * @defgroup SalStats Sal Statistics * * @ingroup SalStats * * @description * This file contains implementation of statistic related functions * *****************************************************************************/ #include "cpa.h" #include "lac_common.h" #include "lac_mem.h" #include "icp_adf_cfg.h" #include "icp_accel_devices.h" #include "sal_statistics.h" #include "icp_adf_debug.h" #include "lac_sal_types.h" #include "lac_sal.h" /** ****************************************************************************** * @ingroup SalStats * Reads from the config file if the given statistic is enabled * * @description * Reads from the config file if the given statistic is enabled * * @param[in] device Pointer to an acceleration device structure * @param[in] statsName Name of the config value to read the value from * @param[out] pIsEnabled Pointer to a variable where information if the * given stat is enabled or disabled will be stored * * @retval CPA_STATUS_SUCCESS Operation successful * @retval CPA_STATUS_INVALID_PARAM Invalid param provided * @retval CPA_STATUS_FAIL Operation failed * ******************************************************************************/ STATIC CpaStatus SalStatistics_GetStatEnabled(icp_accel_dev_t *device, const char *statsName, CpaBoolean *pIsEnabled) { CpaStatus status = CPA_STATUS_SUCCESS; char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pIsEnabled); LAC_CHECK_NULL_PARAM(statsName); #endif status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, statsName, param_value); if (CPA_STATUS_SUCCESS != status) { if (!strncmp(statsName, SAL_STATS_CFG_MISC, sizeof(SAL_STATS_CFG_MISC))) { *pIsEnabled = CPA_FALSE; return CPA_STATUS_SUCCESS; } LAC_LOG_STRING_ERROR1("Failed to get %s from configuration file", statsName); return status; } if (0 == strncmp(param_value, SAL_STATISTICS_STRING_OFF, sizeof(SAL_STATISTICS_STRING_OFF))) { *pIsEnabled = CPA_FALSE; } else { *pIsEnabled = CPA_TRUE; } return status; } /* @ingroup SalStats */ CpaStatus SalStatistics_InitStatisticsCollection(icp_accel_dev_t *device) { CpaStatus status = CPA_STATUS_SUCCESS; sal_statistics_collection_t *pStatsCollection = NULL; Cpa32U enabled_services = 0; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(device); #endif status = LAC_OS_MALLOC(&pStatsCollection, sizeof(sal_statistics_collection_t)); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to allocate memory for statistic.\n"); return status; } LAC_OS_BZERO(pStatsCollection, sizeof(sal_statistics_collection_t)); device->pQatStats = pStatsCollection; status = SalStatistics_GetStatEnabled( device, SAL_STATS_CFG_ENABLED, &pStatsCollection->bStatsEnabled); LAC_CHECK_STATUS(status); pStatsCollection->bDcStatsEnabled = CPA_FALSE; pStatsCollection->bDhStatsEnabled = CPA_FALSE; pStatsCollection->bDsaStatsEnabled = CPA_FALSE; pStatsCollection->bEccStatsEnabled = CPA_FALSE; pStatsCollection->bKeyGenStatsEnabled = CPA_FALSE; pStatsCollection->bLnStatsEnabled = CPA_FALSE; pStatsCollection->bPrimeStatsEnabled = CPA_FALSE; pStatsCollection->bRsaStatsEnabled = CPA_FALSE; pStatsCollection->bSymStatsEnabled = CPA_FALSE; pStatsCollection->bMiscStatsEnabled = CPA_FALSE; if (CPA_FALSE == pStatsCollection->bStatsEnabled) return status; /* What services are enabled */ status = SalCtrl_GetEnabledServices(device, &enabled_services); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to get enabled services\n"); return CPA_STATUS_FAIL; } /* Check if the compression service is enabled */ if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_COMPRESSION) || SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_DECOMPRESSION)) { pStatsCollection->bDcStatsEnabled = CPA_TRUE; } /* Check if the asym service is enabled */ if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_ASYM) || SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) { pStatsCollection->bDhStatsEnabled = CPA_TRUE; pStatsCollection->bDsaStatsEnabled = CPA_TRUE; pStatsCollection->bEccStatsEnabled = CPA_TRUE; pStatsCollection->bKeyGenStatsEnabled = CPA_TRUE; pStatsCollection->bLnStatsEnabled = CPA_TRUE; pStatsCollection->bPrimeStatsEnabled = CPA_TRUE; pStatsCollection->bRsaStatsEnabled = CPA_TRUE; } /* Check if the sym service is enabled */ if (SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO_SYM) || SalCtrl_IsServiceEnabled(enabled_services, SAL_SERVICE_TYPE_CRYPTO)) pStatsCollection->bSymStatsEnabled = CPA_TRUE; /*Check if any of the service is enabled*/ if (SalCtrl_IsServiceEnabled( enabled_services, SAL_SERVICE_TYPE_COMPRESSION | SAL_SERVICE_TYPE_CRYPTO | SAL_SERVICE_TYPE_CRYPTO_SYM | SAL_SERVICE_TYPE_CRYPTO_ASYM)) pStatsCollection->bMiscStatsEnabled = CPA_TRUE; return status; } /* @ingroup SalStats */ CpaStatus SalStatistics_CleanStatisticsCollection(icp_accel_dev_t *device) { sal_statistics_collection_t *pStatsCollection = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(device); #endif pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; LAC_OS_FREE(pStatsCollection); device->pQatStats = NULL; return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/sal_string_parse.c000066400000000000000000000107251503624047500310510ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_string_parse.c * * @ingroup SalStringParse * * @description * This file contains string parsing functions for both user space and kernel * space * *****************************************************************************/ #include "cpa.h" #include "lac_mem.h" #include "sal_string_parse.h" CpaStatus Sal_StringParsing(char *string1, Cpa32U instanceNumber, char *string2, char *result) { char instNumStr[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; LAC_ASSERT_NOT_NULL(string1); LAC_ASSERT_NOT_NULL(string2); snprintf(instNumStr, SAL_CFG_MAX_VAL_LEN_IN_BYTES, "%u", instanceNumber); if ((strnlen(string1, SAL_CFG_MAX_VAL_LEN_IN_BYTES) + strnlen(instNumStr, SAL_CFG_MAX_VAL_LEN_IN_BYTES) + strnlen(string2, SAL_CFG_MAX_VAL_LEN_IN_BYTES) + 1) > SAL_CFG_MAX_VAL_LEN_IN_BYTES) { LAC_LOG_ERROR("Size of result too small\n"); return CPA_STATUS_FAIL; } LAC_OS_BZERO(result, SAL_CFG_MAX_VAL_LEN_IN_BYTES); snprintf(result, SAL_CFG_MAX_VAL_LEN_IN_BYTES, "%s%u%s", string1, instanceNumber, string2); return CPA_STATUS_SUCCESS; } Cpa64U Sal_Strtoul(const char *cp, char **endp, unsigned int cfgBase) { Cpa64U ulResult = 0; #ifdef KERNEL_SPACE ulResult = (Cpa64U)simple_strtoull(cp, endp, cfgBase); #else ulResult = strtoull(cp, endp, cfgBase); #endif return ulResult; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/sal_user_process.c000066400000000000000000000112341503624047500310610ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_user_process.c * * @ingroup SalUserProcess * * @description * This file contains implementation of functions to set/get user process * name * *****************************************************************************/ #include "lac_common.h" #ifndef KERNEL_SPACE #include "icp_adf_user_proxy.h" #endif static char lacProcessName[LAC_USER_PROCESS_NAME_MAX_LEN] = LAC_KERNEL_PROCESS_NAME; /**< Process name used to obtain values from correct section of config file. */ /* * @ingroup LacCommon * @description * This function sets the process name * * @context * This functions is called from module_init or from user space process * initialisation function * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * No * * param[in] processName Process name to be set */ CpaStatus icpSetProcessName(const char *processName) { #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(processName); if (strnlen(processName, LAC_USER_PROCESS_NAME_MAX_LEN) == LAC_USER_PROCESS_NAME_MAX_LEN) { LAC_LOG_ERROR1("Process name too long, maximum process name is %d", LAC_USER_PROCESS_NAME_MAX_LEN - 1); return CPA_STATUS_FAIL; } #endif snprintf(lacProcessName, LAC_USER_PROCESS_NAME_MAX_LEN, "%s", processName); return CPA_STATUS_SUCCESS; } /* * @ingroup LacCommon * @description * This function gets the process name * * @context * This functions is called from LAC context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * */ char *icpGetProcessName(void) { return lacProcessName; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/common/utils/sal_versions.c000066400000000000000000000207731503624047500302250ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_versions.c * * @ingroup SalVersions * * @description * This file contains implementation of functions used to obtain version * information * *****************************************************************************/ #include "cpa.h" #include "Osal.h" #include "icp_accel_devices.h" #include "icp_adf_accel_mgr.h" #include "icp_adf_cfg.h" #include "lac_common.h" #include "icp_sal_versions.h" #define ICP_SAL_VERSIONS_ALL_CAP_MASK 0xFFFFFFFF /**< Mask used to get all devices from ADF */ /** ******************************************************************************* * @ingroup SalVersions * Fills in the version info structure * @description * This function obtains hardware and software information associated with * a given device and fills in the version info structure * * @param[in] device Pointer to the device for which version information * is to be obtained. * @param[out] pVerInfo Pointer to a structure that will hold version * information * * @context * This function might sleep. It cannot be executed in a context that * does not permit sleeping. * @assumptions * The system has been started * @sideEffects * None * @blocking * No * @reentrant * No * @threadSafe * Yes * * @return CPA_STATUS_SUCCESS Operation finished successfully * @return CPA_STATUS_FAIL Operation failed * *****************************************************************************/ STATIC CpaStatus SalVersions_FillVersionInfo(icp_accel_dev_t *device, icp_sal_dev_version_info_t *pVerInfo) { CpaStatus status = CPA_STATUS_SUCCESS; char hwVersion[ICP_SAL_VERSIONS_HW_VERSION_SIZE] = { '\0' }; char fwVersion[ICP_SAL_VERSIONS_FW_VERSION_SIZE] = { '\0' }; char mmpVersion[ICP_SAL_VERSIONS_MMP_VERSION_SIZE] = { '\0' }; Cpa32S strSize = 0; osalMemSet(pVerInfo, 0, sizeof(icp_sal_dev_version_info_t)); pVerInfo->devId = device->accelId; status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_HW_REV_ID_KEY, hwVersion); LAC_CHECK_STATUS(status); strSize = strnlen(hwVersion, sizeof(hwVersion)); LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_HW_VERSION_SIZE); snprintf((char *)pVerInfo->hardwareVersion, ICP_SAL_VERSIONS_HW_VERSION_SIZE, "%.*s", ICP_SAL_VERSIONS_HW_VERSION_SIZE - 1, hwVersion); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_UOF_VER_KEY, fwVersion); LAC_CHECK_STATUS(status); strSize = strnlen(fwVersion, sizeof(fwVersion)); LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_FW_VERSION_SIZE); snprintf((char *)pVerInfo->firmwareVersion, ICP_SAL_VERSIONS_FW_VERSION_SIZE, "%.*s", ICP_SAL_VERSIONS_FW_VERSION_SIZE - 1, fwVersion); status = icp_adf_cfgGetParamValue( device, LAC_CFG_SECTION_GENERAL, ADF_MMP_VER_KEY, mmpVersion); LAC_CHECK_STATUS(status); strSize = strnlen(mmpVersion, sizeof(mmpVersion)); LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_MMP_VERSION_SIZE); snprintf((char *)pVerInfo->mmpVersion, ICP_SAL_VERSIONS_MMP_VERSION_SIZE, "%.*s", ICP_SAL_VERSIONS_MMP_VERSION_SIZE - 1, mmpVersion); snprintf((char *)pVerInfo->softwareVersion, ICP_SAL_VERSIONS_SW_VERSION_SIZE, "%d.%d.%d", SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER); return status; } CpaStatus icp_sal_getDevVersionInfo(Cpa32U devId, icp_sal_dev_version_info_t *pVerInfo) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa16U numInstances = 0; icp_accel_dev_t **pAccel_dev = NULL; Cpa16U num_accel_dev = 0, index = 0; icp_accel_dev_t *pDevice = NULL; #ifdef ICP_PARAM_CHECK LAC_CHECK_NULL_PARAM(pVerInfo); #endif status = icp_adf_getNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Error while getting number of devices\n"); return CPA_STATUS_FAIL; } #ifdef ICP_PARAM_CHECK if (devId >= ADF_MAX_DEVICES) { LAC_LOG_ERROR("Invalid devId\n"); return CPA_STATUS_INVALID_PARAM; } #endif pAccel_dev = osalMemAlloc(numInstances * sizeof(icp_accel_dev_t *)); if (NULL == pAccel_dev) { LAC_LOG_ERROR("Failed to allocate dev instance memory\n"); return CPA_STATUS_RESOURCE; } /* Get ADF to return all accel_devs */ status = icp_adf_getAllAccelDevByCapabilities( ICP_SAL_VERSIONS_ALL_CAP_MASK, pAccel_dev, &num_accel_dev); if (CPA_STATUS_SUCCESS == status) { for (index = 0; index < num_accel_dev; index++) { pDevice = (icp_accel_dev_t *)pAccel_dev[index]; if (pDevice->accelId == devId) { status = SalVersions_FillVersionInfo(pDevice, pVerInfo); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Error while filling in version info\n"); } break; } } if (index == num_accel_dev) { LAC_LOG_ERROR1("Device %d not found or not started\n", devId); status = CPA_STATUS_FAIL; } } else { LAC_LOG_ERROR("Error while getting devices"); } osalMemFree(pAccel_dev); return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/000077500000000000000000000000001503624047500250305ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/000077500000000000000000000000001503624047500262515ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/000077500000000000000000000000001503624047500276745ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_bundles.h000066400000000000000000000153651503624047500330140ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef ADF_IO_BUNDLES_H #define ADF_IO_BUNDLES_H #include "icp_accel_devices.h" struct adf_io_user_bundle { unsigned int device_minor; /**< Device minor number */ int fd; /**< File descriptor associated to the bundle */ void *ptr; /**< Pointer to a memory region that contains the bundle CSRs */ void *priv; /**< Pointer to a private structure which depends on the implementation */ int number; /** Bundle number */ }; /** * @ingroup adf_io * * @description * Given as input the id of an accelerator and a bundle number, this * function allocates and returns a pointer to the adf_io_user_bundle * structure associated to that bundle in that accelerator. * * @param[in] accelid Id of the accelerator. * @param[in] bundle_nr Id of the bundle. * * @retval Pointer to adf_io_user_bundle structure if the function executed * successfully. * @retval NULL if the function failed. */ struct adf_io_user_bundle *adf_io_get_bundle_from_accelid(int accelid, int bundle_nr); /** * @ingroup adf_io * * @description * Checks if the accelerator dev_id exists in the system. * * @param[in] dev_id Id of the accelerator to check. * * @retval 0 The accelerator dev_id is not present. * @retval 1 The accelerator dev_id is present in the system. */ int adf_io_accel_dev_exist(int dev_id); /** * @ingroup adf_io * * @description * Given as input the id of an accelerator, allocates an icp_accel_dev_t * structure and populates it with the parameters associated to the * requested accelerator. * * @param[in,out] accel_dev Pointer to a pointer to an icp_accel_dev_t * structure. In case of success *accel_dev is * populated with a pointer to an allocated * icp_accel_dev_t structure otherwise it is * set to NULL. * @param[in] dev_id If of the accelerator. * * @retval 0 The function executed successfully. * An icp_accel_dev_t structure has been allocated * and returned through the accel_dev in-out * parameter. * @retval -ENOMEM The function failed allocating memory. * @retval -EINVAL The function failed due to an invalid dev_id. * @retval -1 The function failed due to internal communication * with external modules ie qatmgr. */ int adf_io_create_accel(icp_accel_dev_t **accel_dev, int dev_id); /** * @ingroup adf_io * * @description * Checks if accelerator with given id exists and reinitialises *accel_dev * with the parameters associated to the requested accelerator. * * @param[in,out] accel_dev Pointer to a pointer to an icp_accel_dev_t * structure. In case of success *accel_dev is * reinitialised with a icp_accel_dev_t structure * content related to given accelerator * * @param[in] dev_id Id of the accelerator. * * @retval 0 The function executed successfully. * An icp_accel_dev_t structure has been updated * and returned through the accel_dev in-out * parameter. * @retval -EINVAL The function failed due to an invalid dev_id. */ int adf_io_reinit_accel(icp_accel_dev_t **accel_dev, int dev_id); /** * @ingroup adf_io * * @description * Frees an icp_accel_dev_t allocated using adf_io_create_accel. * * @param[in] accel_dev Pointer to an icp_accel_dev_t structure to be * freed. */ void adf_io_destroy_accel(icp_accel_dev_t *accel_dev); /** * @ingroup adf_io * * @description * Frees an adf_io_user_bundle structure allocated though * adf_io_get_bundle_from_accelid. * * @param[in] bundle Pointer to an adf_io_user_bundle structure to * be freed. */ void adf_io_free_bundle(struct adf_io_user_bundle *bundle); /** * @ingroup adf_io * * @description * Populates the fields of an adf_io_user_bundle structure based * on the accel_dev. * * @param[in] accel_dev Pointer to an icp_accel_dev_t structure. * @param[out] bundle Pointer to a user allocate adf_io_user_bundle * structure. * * @retval 0 The function executed successfully. * @retval -EINVAL The function failed due to an invalid parameter. */ int adf_io_populate_bundle(icp_accel_dev_t *accel_dev, struct adf_io_user_bundle *bundle); /** * @ingroup adf_io * * @description * Send restarting complete message from vf to pf * * @param[in] accel_dev Pointer to an icp_accel_dev_t structure. */ void adf_io_vf2pf_notify_restarting_complete(icp_accel_dev_t *accel_dev); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_cfg.h000066400000000000000000000204771503624047500321170ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * @file adf_io_cfg.h * * @defgroup adf_io * * @description * This file contains defines the low level API of the configuration * module in adf user. * *****************************************************************************/ #ifndef ADF_IO_CFG #define ADF_IO_CFG #include "cpa.h" #include "icp_accel_devices.h" /* * Error code for functions which return variable of Cpa32S type */ #define ADF_IO_OPERATION_FAIL_CPA32S -1 /* * Error code for functions which return variable of Cpa16U type */ #define ADF_IO_OPERATION_FAIL_U16 0xFFFF /** * @ingroup adf_io * * @description * This function returns the number of acceleration devices that * are addressable by the current user space process. * * @param[in] num_devices Pointer to integer allocated by the caller. * This location will be updated by this function * with the number of available devices. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM An invalid parameter was passed as input * to the function. * @retval CPA_STATUS_UNSUPPORTED This function is not supported for given * target platform. */ CpaStatus adf_io_getNumDevices(unsigned int *num_devices); /** * @ingroup adf_io * * @description * This function returns the value of a configured parameter for * a particular accelerator. * * @param[in] accel_dev Pointer to an icp_accel_dev_t structure. * @param[in] pSection Null terminated string that contains the section * name associated to the parameter. * @param[in] pParamName Null terminated string that contains the parameter * to query. * @param[out] pParamValue Pointer to a string allocated by the caller * of size ADF_CFG_MAX_VAL_LEN_IN_BYTES. If the * function is successful, this will contain the * value of the parameter queried. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_INVALID_PARAM An invalid parameter was passed as input * to the function. * @retval CPA_STATUS_FAIL Function failed. This might occur if * the requested parameter is not present * in the database. */ CpaStatus adf_io_cfgGetParamValue(icp_accel_dev_t *accel_dev, const char *pSection, const char *pParamName, char *pParamValue); /** * @ingroup adf_io * * @description * This function returns the domain address associated to an accelerator. * * @param[in] accelId Id of the accelerator. * * @retval Cpa32S Domain address of the accelerator. * @retval -1 Function failed. */ Cpa32S adf_io_cfgGetDomainAddress(Cpa16U accelId); /** * @ingroup adf_io * * @description * This function returns the Bus Device Function (BDF) encoded in two * bytes associated to an accelerator. * * @param[in] accelId Id of the accelerator. * * @retval Cpa16U Bus Device Function of the accelerator. * @retval 0xFFFF Function failed. */ Cpa16U adf_io_cfgGetBusAddress(Cpa16U accelId); /** * @ingroup adf_io * * @description * This function checks if user process section * exists in device cfg. * * @param[in] dev_id Id of the accelerator device to be checked. * @param[out] pSectionPresent Pointer to the check result. * @retval 0 Function executed successfully, the result is * present in *pSectionPresent. * @retval < 0 Function failed. */ int adf_io_cfgCheckUserSection(int dev_id, uint8_t *pSectionPresent); /** * @ingroup adf_io * * @description * This function resets the accelerator device. * * @param[in] accelId Id of the accelerator device to be reset. * * @retval CPA_STATUS_SUCCESS Function executed successfully, the device * has been reset. * @retval CPA_STATUS_UNSUPPORTED This function is not supported. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_RETRY Device is busy and reset is not possible. */ CpaStatus adf_io_reset_device(Cpa32U accelId); /** * @ingroup adf_io * * @description * This function checks if there is an available device * * @retval CPA_TRUE At least one device is available. * @retval CPA_FALSE No available devices found. */ CpaBoolean adf_io_isDeviceAvailable(void); /** * @ingroup adf_io * * @description * Function returns the number of PFs in the system * * @retval Cpa16U The number of PFs. */ Cpa16U adf_io_getNumPfs(void); /** * @ingroup adf_io * * @description * Populates a pre-allocated list of PF info, only returned if the process * has privileges to access the QAT debugfs/sysfs entries. * * @param[out] pPfInfo Pre-allocated list of PF info, the size of * this should match the number of PFs on * the platform. * * @retval CPA_STATUS_FAIL No PFs detected. * @retval CPA_STATUS_SUCCESS Function executed successfully. */ CpaStatus adf_io_getPfInfo(icp_accel_pf_info_t *pPfInfo); /** * @ingroup adf_io * * @description * Function checks the status of the firmware/hardware * * @param[in] accelId Id of the accelerator device. * * @retval CPA_STATUS_UNSUPPORTED This function is not supported. * @retval CPA_STATUS_FAIL Device is Non-Responsive. * @retval CPA_STATUS_SUCCESS Device is Alive. */ CpaStatus adf_io_getHeartBeatStatus(Cpa32U packageId); #ifdef ICP_HB_FAIL_SIM /** * @ingroup adf_io * * @description * Function helps simulate heartbeat failure * * @param[in] accelId Id of the accelerator device. * * @retval CPA_STATUS_UNSUPPORTED This function is not supported. * @retval CPA_STATUS_FAIL Failure simulation failed for device. * @retval CPA_STATUS_SUCCESS Failure simulation successful for device. */ CpaStatus adf_io_heartbeatSimulateFailure(Cpa32U packageId); #endif #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_ring.h000066400000000000000000000072251503624047500323130ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef ADF_IO_RING #define ADF_IO_RING #include "cpa.h" #include "adf_dev_ring_ctl.h" /** * @ingroup adf_io * * @description * Reserves a ring in a given accel_id and bank. * * @param[in] accel_id Id of the accelerator. * @param[in] bank_nr Id of the bank. * @param[in] ring_nr If of the ring to be reserved. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. */ CpaStatus adf_io_reserve_ring(Cpa16U accel_id, Cpa16U bank_nr, Cpa16U ring_nr); /** * @ingroup adf_io * * @description * Releases a ring in a given accel_id and bank. * * @param[in] accel_id Id of the accelerator. * @param[in] bank_nr Id of the bank. * @param[in] ring_nr If of the ring to be released. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. */ CpaStatus adf_io_release_ring(Cpa16U accel_id, Cpa16U bank_nr, Cpa16U ring_nr); /** * @ingroup adf_io * * @description * Enables a ring represented by an adf_dev_ring_handle_t structure. * * @param[in] ring Pointer to an adf_dev_ring_handle_t structure to * be enabled. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. */ CpaStatus adf_io_enable_ring(adf_dev_ring_handle_t *ring); /** * @ingroup adf_io * * @description * Disabled a ring represented by an adf_dev_ring_handle_t structure. * * @param[in] ring Pointer to an adf_dev_ring_handle_t structure to * be disabled. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. */ CpaStatus adf_io_disable_ring(adf_dev_ring_handle_t *ring); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/include/adf_io_user_proxy.h000066400000000000000000000115521503624047500335710ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /** ***************************************************************************** * @file adf_io_user_proxy.h * * @defgroup adf_io * * @description * This file contains defines the low level API of the adf user proxy * in user space. * *****************************************************************************/ #ifndef ADF_IO_USER_PROXY_H #define ADF_IO_USER_PROXY_H #include "cpa.h" #include "icp_accel_devices.h" /** * @ingroup adf_io * * @description * This function checks if a user space process with a given name can * be started and returns the name of the process to be used when calling * adf_io_userProxyInit(). * * @param[in] name_in Process name that the user wants to start. * @param[in] name_tml_len Size of the buffer pointed by name_in. * @param[out] name Buffer containing the process name to start. * @param[out] name_len Size of the buffer pointed by name. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Provided argument is invalid. */ CpaStatus adf_io_userProcessToStart(char const *const name_in, size_t name_tml_len, char *name, size_t name_len); /** * @ingroup adf_io * * @description * This function is used to initialize the io specific layer of the * ADF proxy in user space. * It takes a process name as a parameter. Caller should check if * such process name is not already started using * icp_adf_userProcessStarted function. * * @param[in] name Process name that the user wants to start. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Provided argument is invalid. * @retval CPA_STATUS_RESOURCE Init mutex for process lock fails. */ CpaStatus adf_io_userProxyInit(char const *const name); /** * @ingroup adf_io * * @description * This function is used to stop the io specific layer of the * ADF proxy in user space. */ void adf_io_userProcessStop(void); /** * @ingroup adf_io * * @description * This function is used to shutdown the io specific layer of the * ADF proxy in user space. */ void adf_io_userProxyShutdown(void); /** * @ingroup adf_io * * @description * This function is used to reset the data structures used by the * io specific layer of the ADF proxy in user space. * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_RESOURCE Init mutex for process lock fails. */ CpaStatus adf_io_resetUserProxy(void); /* * adf_io_pollProxyEvent * * Description: * check if there is any event for given device id * * Returns: * CPA_FALSE there are no reported events * CPA_TRUE there are reported events */ CpaBoolean adf_io_pollProxyEvent(Cpa32U *dev_id, enum adf_event *event); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/000077500000000000000000000000001503624047500272145ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_cfg.c000066400000000000000000000614501503624047500323070ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #include #include #include #include #include "adf_kernel_types.h" #include "adf_io_cfg.h" #include "cpa.h" #include "icp_accel_devices.h" #include "icp_platform.h" #include "qat_mgr.h" #include "qat_log.h" #include "adf_vfio_pf.h" #define HEARTBEAT_DIR "/sys/kernel/debug/qat_%s_%s/heartbeat/" #define STATIC static #define HB_STATUS_FILE HEARTBEAT_DIR "status" #define HB_SIM_FILE HEARTBEAT_DIR "inject_error" #define HB_ALIVE "0" #define HB_SIM_FAIL "1\n" CpaStatus adf_io_getNumDevices(unsigned int *num_devices) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; int ret; ICP_CHECK_FOR_NULL_PARAM(num_devices); *num_devices = ADF_MAX_DEVICES; ret = qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_NUM_DEVICES); if (ret) { *num_devices = 0; return CPA_STATUS_FAIL; } if (rsp.num_devices <= ADF_MAX_DEVICES) *num_devices = rsp.num_devices; return CPA_STATUS_SUCCESS; } STATIC CpaStatus cfg_getValueFromDeviceInfo(const Cpa32U accelId, const char *pParamName, char *pParamValue, struct qatmgr_msg_rsp *rsp) { char temp_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { '\0' }; int len = 0; ICP_CHECK_FOR_NULL_PARAM(pParamName); ICP_CHECK_FOR_NULL_PARAM(pParamValue); ICP_CHECK_FOR_NULL_PARAM(rsp); bool dc_enabled = rsp->device_info.services & SERV_TYPE_DC; bool decomp_enabled = rsp->device_info.services & SERV_TYPE_DECOMP; bool sym_enabled = rsp->device_info.services & SERV_TYPE_SYM; bool asym_enabled = rsp->device_info.services & SERV_TYPE_ASYM; bool cy_enabled = (SERV_TYPE_CY == (rsp->device_info.services & SERV_TYPE_CY)); if (!ICP_STRNCMP_CONST(pParamName, "Device_Max_Banks")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.max_banks); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "Device_Capabilities_Mask")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "0x%x", rsp->device_info.capability_mask); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "Device_DcExtendedFeatures")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "0x%x", rsp->device_info.extended_capabilities); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "ServicesEnabled")) { if (dc_enabled) len += snprintf(temp_str + len, sizeof(temp_str) - len, "dc"); if (decomp_enabled) len += snprintf(temp_str + len, sizeof(temp_str) - len, "%sdecomp", len ? ";" : ""); if (!dc_enabled && !decomp_enabled && cy_enabled) { len += snprintf( temp_str + len, sizeof(temp_str) - len, "%scy", len ? ";" : ""); } else { if (sym_enabled) len += snprintf(temp_str + len, sizeof(temp_str) - len, "%ssym", len ? ";" : ""); if (asym_enabled) len += snprintf(temp_str + len, sizeof(temp_str) - len, "%sasym", len ? ";" : ""); } snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%s", temp_str); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "statsGeneral")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "1"); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "Device_PkgId")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.pkg_id); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "Device_NodeId")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.node_id); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "HW_RevId")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "N/A"); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "Firmware_UofVer")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "N/A"); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "Firmware_MmpVer")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "N/A"); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "NumberCyInstances")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.num_cy_instances); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "NumberSymInstances")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.num_sym_instances); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "NumberAsymInstances")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.num_asym_instances); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "NumberDcInstances")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.num_dc_instances); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(pParamName, "NumberDecompInstances")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->device_info.num_decomp_instances); return CPA_STATUS_SUCCESS; } ADF_ERROR("Unsupported config parameter %s\n", pParamName); return CPA_STATUS_FAIL; } STATIC CpaStatus cfg_getDcDecompInstanceValue(const Cpa32U accelId, const char *pParamName, char *pParamValue, struct qatmgr_msg_rsp *rsp, enum serv_type type) { const char *name; struct ring_info instance_info = { 0 }; ICP_CHECK_FOR_NULL_PARAM(pParamName); ICP_CHECK_FOR_NULL_PARAM(pParamValue); ICP_CHECK_FOR_NULL_PARAM(rsp); /* pParamName can be either Dc or * Decomp. * For example, configuration param for BankNumber for Dc service * with instance number zero will be Dc0BankNumber and for Decomp * will be Decomp0BankNumber. * First 2 characters will be skipped for Dc service and 6 characters * will be skipped for Decomp service to get the config param names. */ if (type == SERV_TYPE_DC) { name = pParamName + strlen("Dc"); instance_info = rsp->instance_info.dc; } else { name = pParamName + strlen("Decomp"); instance_info = rsp->instance_info.decomp; } while (*name >= '0' && *name <= '9') name++; if (!ICP_STRNCMP_CONST(name, "BankNumber")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", instance_info.bank_number); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "IsPolled")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", instance_info.is_polled); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "CoreAffinity")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", instance_info.core_affinity); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "NumConcurrentRequests")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", instance_info.num_concurrent_requests); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "RingTx")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", instance_info.ring_tx); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "RingRx")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", instance_info.ring_rx); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "Name")) { if (CPA_INST_NAME_SIZE <= strnlen(rsp->name, sizeof(rsp->name))) { ADF_ERROR("Failed to copy config parameter %s (\"%s\")\n", pParamName, pParamValue); return CPA_STATUS_FAIL; } snprintf(pParamValue, CPA_INST_NAME_SIZE, "%.*s", CPA_INST_NAME_SIZE - 1, rsp->name); return CPA_STATUS_SUCCESS; } ADF_ERROR("Unsupported config parameter %s\n", pParamName); return CPA_STATUS_FAIL; } STATIC CpaStatus cfg_getCyInstanceValue(const Cpa32U accelId, const char *pParamName, char *pParamValue, struct qatmgr_msg_rsp *rsp) { const char *name; ICP_CHECK_FOR_NULL_PARAM(pParamName); ICP_CHECK_FOR_NULL_PARAM(pParamValue); ICP_CHECK_FOR_NULL_PARAM(rsp); /* Skip past the Cy part of the parameter name */ name = pParamName + 2; while (*name >= '0' && *name <= '9') name++; if (!ICP_STRNCMP_CONST(name, "BankNumber")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.sym.bank_number); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "BankNumberAsym")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.asym.bank_number); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "BankNumberSym")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.sym.bank_number); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "IsPolled")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.is_polled); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "CoreAffinity")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.sym.core_affinity); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "NumConcurrentAsymRequests")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.asym.num_concurrent_requests); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "NumConcurrentSymRequests")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.sym.num_concurrent_requests); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "RingSymTx")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.sym.ring_tx); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "RingAsymTx")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.asym.ring_tx); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "RingSymRx")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.sym.ring_rx); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "RingAsymRx")) { snprintf(pParamValue, ADF_CFG_MAX_VAL_LEN_IN_BYTES, "%u", rsp->instance_info.cy.asym.ring_rx); return CPA_STATUS_SUCCESS; } if (!ICP_STRNCMP_CONST(name, "Name")) { if (CPA_INST_NAME_SIZE <= strnlen(rsp->name, sizeof(rsp->name))) { ADF_ERROR("Failed to copy config parameter %s (\"%s\")\n", pParamName, pParamValue); return CPA_STATUS_FAIL; } snprintf(pParamValue, CPA_INST_NAME_SIZE, "%.*s", CPA_INST_NAME_SIZE - 1, rsp->name); return CPA_STATUS_SUCCESS; } ADF_ERROR("Unsupported config parameter %s\n", pParamName); return CPA_STATUS_FAIL; } CpaStatus adf_io_cfgGetParamValue(icp_accel_dev_t *accel_dev, const char *pSection, const char *pParamName, char *pParamValue) { struct qatmgr_msg_req req = { 0 }; enum serv_type type; unsigned serv_num; Cpa16U msg_type; /* Cache previous responses */ static __thread Cpa32U c_accelId = UINT32_MAX; static __thread enum serv_type c_serv_type; static __thread Cpa16U c_serv_num = UINT16_MAX; static __thread struct qatmgr_msg_rsp rsp = { 0 }; ICP_CHECK_FOR_NULL_PARAM(accel_dev); ICP_CHECK_FOR_NULL_PARAM(pSection); ICP_CHECK_FOR_NULL_PARAM(pParamName); ICP_CHECK_FOR_NULL_PARAM(pParamValue); // NOTE: this should improve performance due to cashing also number of // instances if (ICP_STRNCMP_CONST(pSection, "GENERAL") == 0 || !ICP_STRNCMP_CONST_NO_NULL(pParamName, "Number")) { /* * All general section parameters and number of instances * are handled in QATMGR_MSGTYPE_DEVICE_INFO message */ if (accel_dev->accelId != c_accelId || rsp.hdr.type != QATMGR_MSGTYPE_DEVICE_INFO) { req.device_num = accel_dev->accelId; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_DEVICE_INFO)) { ADF_ERROR("Failed to get DEVICE_INFO response from qatmgr\n"); c_accelId = UINT32_MAX; return CPA_STATUS_FAIL; } } c_accelId = accel_dev->accelId; return cfg_getValueFromDeviceInfo( accel_dev->accelId, pParamName, pParamValue, &rsp); } if (!ICP_STRNCMP_CONST_NO_NULL(pParamName, "Dc") || !ICP_STRNCMP_CONST_NO_NULL(pParamName, "Cy") || !ICP_STRNCMP_CONST_NO_NULL(pParamName, "Decomp")) { if (sscanf(pParamName, "Dc%u", &serv_num) == 1) type = SERV_TYPE_DC; else if (sscanf(pParamName, "Decomp%u", &serv_num) == 1) type = SERV_TYPE_DECOMP; else if (sscanf(pParamName, "Cy%u", &serv_num) == 1) type = SERV_TYPE_CY; else { ADF_ERROR("Unknown config parameter %s\n", pParamName); return CPA_STATUS_FAIL; } if (strstr(pParamName, "Name")) msg_type = QATMGR_MSGTYPE_INSTANCE_NAME; else msg_type = QATMGR_MSGTYPE_INSTANCE_INFO; if (msg_type != rsp.hdr.type || type != c_serv_type || serv_num != c_serv_num || accel_dev->accelId != c_accelId) { req.inst.type = type; req.inst.num = serv_num; req.inst.device_num = accel_dev->accelId; if (qatmgr_query(&req, &rsp, msg_type)) { ADF_ERROR("Failed to get INSTANCE_INFO response from qatmgr\n"); c_accelId = UINT32_MAX; return CPA_STATUS_FAIL; } c_serv_type = type; c_serv_num = serv_num; c_accelId = accel_dev->accelId; } if (type == SERV_TYPE_DC || type == SERV_TYPE_DECOMP) return cfg_getDcDecompInstanceValue( accel_dev->accelId, pParamName, pParamValue, &rsp, type); else return cfg_getCyInstanceValue( accel_dev->accelId, pParamName, pParamValue, &rsp); } ADF_ERROR("Unsupported config parameter %s\n", pParamName); return CPA_STATUS_FAIL; } Cpa32S adf_io_cfgGetDomainAddress(Cpa16U accelId) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; unsigned node, b, d, f; req.device_num = accelId; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_DEVICE_ID)) { ADF_ERROR("Failed to get DEVICE_INFO response from qatmgr\n"); return ADF_IO_OPERATION_FAIL_CPA32S; } if (sscanf(rsp.device_id, "%x:%x:%x.%x", &node, &b, &d, &f) != 4) { ADF_ERROR("Failed to parse BDF from \"%s\"\n", rsp.device_id); } return node; } Cpa16U adf_io_cfgGetBusAddress(Cpa16U accelId) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; unsigned n, b, d, f; unsigned bdf = ADF_IO_OPERATION_FAIL_U16; req.device_num = accelId; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_DEVICE_ID)) { ADF_ERROR("Failed to get DEVICE_INFO response from qatmgr\n"); return ADF_IO_OPERATION_FAIL_U16; } if (sscanf(rsp.device_id, "%x:%x:%x.%x", &n, &b, &d, &f) != 4) { ADF_ERROR("Failed to parse BDF from \"%s\"\n", rsp.device_id); } else { bdf = (f & 0x7) + ((d & 0x1F) << 3) + ((b & 0xFF) << 8); } return bdf; } CpaStatus adf_io_reset_device(Cpa32U accelId) { return CPA_STATUS_UNSUPPORTED; } /* * icp_adf_cfgCheckUserSection * check if user process section exists in device cfg */ int adf_io_cfgCheckUserSection(int dev_id, uint8_t *pSectionPresent) { *pSectionPresent = 1; return 0; } CpaBoolean adf_io_isDeviceAvailable(void) { struct qatmgr_transport *t_mgr = NULL; t_mgr = get_transport_mgr(); return t_mgr->qat_mgr_is_dev_available(); } Cpa16U adf_io_getNumPfs(void) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_NUM_PF_DEVS)) { ADF_ERROR("Failed to get NUM_PF_DEVS response from qatmgr\n"); return ADF_IO_OPERATION_FAIL_U16; } return rsp.num_devices; } CpaStatus adf_io_getPfInfo(icp_accel_pf_info_t *pPfInfo) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; Cpa16U pf_number, i; icp_accel_pf_info_t *p; ICP_CHECK_FOR_NULL_PARAM(pPfInfo); pf_number = adf_io_getNumPfs(); if (pf_number == ADF_IO_OPERATION_FAIL_U16) { ADF_ERROR("No PFs found, assuming running inside VM!\n"); return CPA_STATUS_RESOURCE; } for (i = 0; i < pf_number; i++) { req.device_num = i; p = pPfInfo + i; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_PF_DEV_INFO)) { ADF_ERROR("Failed to get PF_DEV_INFO response from qatmgr\n"); return CPA_STATUS_FAIL; } memcpy(p, &rsp.pf_info, sizeof(rsp.pf_info)); } return CPA_STATUS_SUCCESS; } CpaStatus adf_io_getHeartBeatStatus(Cpa32U packageId) { char devName[ADF_CFG_MAX_STR_LEN] = { '\0' }; char *buff = NULL; char device_id[DEVICE_NAME_SIZE] = { '\0' }; size_t lineSize = 0; FILE *fp = NULL; CpaStatus ret_status = CPA_STATUS_SUCCESS; struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; if (packageId == VM_PACKAGE_ID_NONE) { ADF_ERROR("This API is not supported on a VM"); return CPA_STATUS_UNSUPPORTED; } req.device_num = packageId; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_PF_DEV_INFO)) { ADF_ERROR("Failed to get PF_DEV_INFO response from qatmgr\n"); return CPA_STATUS_FAIL; } snprintf(device_id, sizeof(device_id), "%04x:%02x:%02x.%01x", rsp.pf_info.domain, BDF_BUS(rsp.pf_info.bdf), BDF_DEV(rsp.pf_info.bdf), BDF_FUN(rsp.pf_info.bdf)); /* Open /sys/kernel/debug//heartbeat/status */ if (snprintf(devName, ADF_CFG_MAX_STR_LEN, HB_STATUS_FILE, rsp.pf_info.device_gen, device_id) < 0) { ADF_ERROR("Failed to build device path %s\n", devName); return CPA_STATUS_FAIL; } fp = fopen(devName, "r"); if (NULL == fp) { ADF_ERROR("No heartbeat directory found, " "you may need to update your QAT kernel driver\n"); return CPA_STATUS_UNSUPPORTED; } if (getline(&buff, &lineSize, fp) <= 0) { ret_status = CPA_STATUS_FAIL; goto cleanup; } if (ICP_STRNCMP_CONST_NO_NULL(buff, HB_ALIVE)) ret_status = CPA_STATUS_FAIL; cleanup: free(buff); fclose(fp); return ret_status; } #ifdef ICP_HB_FAIL_SIM CpaStatus adf_io_heartbeatSimulateFailure(Cpa32U packageId) { char devName[ADF_CFG_MAX_STR_LEN] = { 0 }; char device_id[DEVICE_NAME_SIZE]; int fp = 0; struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; if (packageId == VM_PACKAGE_ID_NONE) { ADF_ERROR("This API is not supported on a VM"); return CPA_STATUS_UNSUPPORTED; } req.device_num = packageId; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_PF_DEV_INFO)) { ADF_ERROR("Failed to get PF_DEV_INFO response from qatmgr\n"); return CPA_STATUS_FAIL; } snprintf(device_id, sizeof(device_id), "%04x:%02x:%02x.%01x", rsp.pf_info.domain, BDF_BUS(rsp.pf_info.bdf), BDF_DEV(rsp.pf_info.bdf), BDF_FUN(rsp.pf_info.bdf)); /* Open /sys/kernel/debug//heartbeat/inject_error */ if (snprintf(devName, ADF_CFG_MAX_STR_LEN, HB_SIM_FILE, rsp.pf_info.device_gen, device_id) < 0) { ADF_ERROR("Failed to build device path %s\n", devName); return CPA_STATUS_FAIL; } fp = open(devName, O_WRONLY); if (0 > fp) { ADF_ERROR("No heartbeat directory found, " "you may need to update your QAT kernel driver\n"); return CPA_STATUS_UNSUPPORTED; } if (write(fp, HB_SIM_FAIL, strlen(HB_SIM_FAIL)) < 0) { close(fp); ADF_ERROR("Failed to inject error\n"); return CPA_STATUS_FAIL; } close(fp); return CPA_STATUS_SUCCESS; } #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_ring.c000066400000000000000000000100461503624047500325020ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #include "cpa.h" #include "adf_platform_common.h" #include "adf_platform_acceldev_common.h" #include "adf_dev_ring_ctl.h" #include "adf_io_ring.h" #include "icp_platform.h" #define STATIC static STATIC inline void update_ring(Cpa32U *csr_base_addr, Cpa32U bank_offset, Cpa32U bank_ring_mask, Cpa32U arb_mask) { Cpa32U arben, arben_tx, arben_rx; Cpa32U shift; ICP_CHECK_FOR_NULL_PARAM_VOID(csr_base_addr); shift = __builtin_popcount(arb_mask); arben_tx = bank_ring_mask & arb_mask; arben_rx = (bank_ring_mask >> shift) & arb_mask; arben = arben_tx & arben_rx; ICP_ADF_CSR_WR( csr_base_addr, bank_offset + ICP_RING_CSR_RING_SRV_ARB_EN, arben); } CpaStatus adf_io_reserve_ring(Cpa16U accel_id, Cpa16U bank_nr, Cpa16U ring_nr) { return CPA_STATUS_SUCCESS; } CpaStatus adf_io_release_ring(Cpa16U accel_id, Cpa16U bank_nr, Cpa16U ring_nr) { return CPA_STATUS_SUCCESS; } CpaStatus adf_io_enable_ring(adf_dev_ring_handle_t *ring) { Cpa32U bank_ring_mask; ICP_CHECK_FOR_NULL_PARAM(ring); /* For ring configured in UQ mode, the request ring CSRs are internally * managed by HW and will not be accessible by SW */ if (!ring->csr_addr || !ring->bank_data || !ring->accel_dev) return CPA_STATUS_FAIL; bank_ring_mask = ring->bank_data->ring_mask; bank_ring_mask |= 1 << ring->ring_num; update_ring(ring->csr_addr, ring->bank_offset, bank_ring_mask, ring->accel_dev->arb_mask); return CPA_STATUS_SUCCESS; } CpaStatus adf_io_disable_ring(adf_dev_ring_handle_t *ring) { Cpa32U bank_ring_mask; ICP_CHECK_FOR_NULL_PARAM(ring); /* For ring configured in UQ mode, the request ring CSRs are internally * managed by HW and will not be accessible by SW */ if (!ring->csr_addr || !ring->bank_data || !ring->accel_dev) return CPA_STATUS_FAIL; bank_ring_mask = ring->bank_data->ring_mask; bank_ring_mask &= ~(1 << ring->ring_num); update_ring(ring->csr_addr, ring->bank_offset, bank_ring_mask, ring->accel_dev->arb_mask); return CPA_STATUS_SUCCESS; } adf_common_user_bundles.c000066400000000000000000000273721503624047500341700ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "cpa.h" #include "icp_platform.h" #include "adf_user.h" #include "adf_kernel_types.h" #include "adf_user_cfg.h" #include "adf_pfvf_vf_msg.h" #include "adf_io_cfg.h" #include "vfio_lib.h" #include "qat_mgr.h" #include "qat_log.h" #include "qae_mem.h" #define STATIC static void adf_io_free_bundle(struct adf_io_user_bundle *bundle) { struct qatmgr_transport *t_mgr = NULL; t_mgr = get_transport_mgr(); t_mgr->adf_free_bundle(bundle); } void adf_vfio_free_bundle(struct adf_io_user_bundle *bundle) { if (bundle) ICP_FREE(bundle); } struct adf_io_user_bundle *adf_io_get_bundle_from_accelid(int accelid, int bundle_nr) { struct adf_io_user_bundle *bundle = NULL; bundle = ICP_ZALLOC_GEN(sizeof(*bundle)); if (!bundle) { ADF_ERROR("failed to allocate bundle structure\n"); return NULL; } bundle->number = bundle_nr; return bundle; } int adf_io_populate_bundle(icp_accel_dev_t *accel_dev, struct adf_io_user_bundle *bundle) { struct qatmgr_transport *t_mgr = NULL; int ret = -1; t_mgr = get_transport_mgr(); ret = t_mgr->adf_populate_bundle(accel_dev, bundle); return ret; } int adf_vfio_populate_bundle(icp_accel_dev_t *accel_dev, struct adf_io_user_bundle *bundle) { vfio_dev_info_t *vfio_dev; uintptr_t addr; ICP_CHECK_FOR_NULL_PARAM_RET_CODE(accel_dev, -EINVAL); ICP_CHECK_FOR_NULL_PARAM_RET_CODE(bundle, -EINVAL); vfio_dev = accel_dev->ioPriv; if (!vfio_dev) return -EINVAL; if (vfio_dev->pcs.bar[0].ptr == NULL || vfio_dev->pcs.bar[0].size == 0) return -EINVAL; addr = (uintptr_t)vfio_dev->pcs.bar[0].ptr + (8192 * bundle->number); bundle->ptr = (void *)addr; return 0; } STATIC int adf_populate_accel_dev(int dev_id, icp_accel_dev_t *accel_dev, struct qatmgr_transport *t_mgr) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; int device_name_len; ICP_CHECK_FOR_NULL_PARAM(accel_dev); memset(accel_dev, '\0', sizeof(*accel_dev)); /* Get device information */ req.device_num = dev_id; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_DEVICE_INFO)) return -EIO; accel_dev->accelId = rsp.device_info.device_num; accel_dev->maxNumBanks = rsp.device_info.max_banks; accel_dev->accelCapabilitiesMask = rsp.device_info.capability_mask; accel_dev->cipherCapabilitiesMask = 0U; accel_dev->hashCapabilitiesMask = 0U; accel_dev->asymCapabilitiesMask = 0U; accel_dev->dcExtendedFeatures = rsp.device_info.extended_capabilities; if (rsp.device_info.fw_caps.is_fw_caps) { accel_dev->fw_caps.comp_algos = rsp.device_info.fw_caps.comp_algos; accel_dev->fw_caps.cksum_algos = rsp.device_info.fw_caps.cksum_algos; accel_dev->fw_caps.deflate_caps = rsp.device_info.fw_caps.deflate_caps; accel_dev->fw_caps.lz4_caps = rsp.device_info.fw_caps.lz4_caps; accel_dev->fw_caps.lz4s_caps = rsp.device_info.fw_caps.lz4s_caps; accel_dev->fw_caps.is_fw_caps = 1; } accel_dev->services = rsp.device_info.services; accel_dev->numa_node = rsp.device_info.node_id; accel_dev->deviceType = rsp.device_info.device_type; accel_dev->arb_mask = rsp.device_info.arb_mask; accel_dev->maxNumRingsPerBank = rsp.device_info.max_rings_per_bank; accel_dev->pciDevId = rsp.device_info.device_pci_id; accel_dev->isVf = CPA_TRUE; accel_dev->ringMode = rsp.device_info.ring_mode; /* Below two are not supported for now */ accel_dev->sku = 0; accel_dev->deviceMemAvail = 0; device_name_len = strnlen(rsp.device_info.device_name, sizeof(rsp.device_info.device_name)); if (device_name_len < sizeof(accel_dev->deviceName)) { snprintf(accel_dev->deviceName, sizeof(accel_dev->deviceName), "%.*s", (int)sizeof(accel_dev->deviceName) - 1, rsp.device_info.device_name); } else { return -EINVAL; } return 0; } int adf_io_accel_dev_exist(int dev_id) { if (adf_io_cfgGetBusAddress(dev_id) == ADF_IO_OPERATION_FAIL_U16) return 0; else return 1; } static int vfio_container_fd = 0; int get_vfio_fd(void) { return vfio_container_fd; } int adf_io_create_accel(icp_accel_dev_t **accel_dev, int dev_id) { struct qatmgr_transport *t_mgr = NULL; int status = -1; ICP_CHECK_FOR_NULL_PARAM(accel_dev); t_mgr = get_transport_mgr(); *accel_dev = ICP_ZALLOC_GEN(sizeof(**accel_dev)); if (!*accel_dev) return -ENOMEM; status = t_mgr->adf_create_accel(*accel_dev, dev_id, t_mgr); if (status < 0) { ICP_FREE(*accel_dev); *accel_dev = NULL; } return status; } int adf_vfio_create_accel(icp_accel_dev_t *accel_dev, int dev_id, struct qatmgr_transport *t_mgr) { int status = -1; struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; char vfio_file[QATMGR_MAX_STRLEN]; char device_id[QATMGR_MAX_STRLEN]; int ret; int group_fd; int pci_did; vfio_dev_info_t *vfio_dev; vfio_dev = ICP_ZALLOC_GEN(sizeof(*vfio_dev)); if (!vfio_dev) { return -ENOMEM; } if (adf_populate_accel_dev(dev_id, accel_dev, t_mgr)) goto accel_fail; accel_dev->ioPriv = vfio_dev; /* Get device identifier */ req.device_num = dev_id; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_DEVICE_ID)) goto accel_fail; snprintf(device_id, sizeof(device_id), "%s", rsp.device_id); /* Get vfio device file name */ if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_VFIO_FILE)) goto accel_fail; if (sizeof(vfio_file) <= strnlen(rsp.vfio_file.name, sizeof(rsp.vfio_file.name))) { goto accel_fail; } snprintf(vfio_file, sizeof(vfio_file), "%.*s", (int)(sizeof(vfio_file) - 1), rsp.vfio_file.name); group_fd = rsp.vfio_file.fd; pci_did = accel_dev->pciDevId; ret = open_vfio_dev(vfio_file, device_id, group_fd, pci_did, vfio_dev); if (ret) { ADF_ERROR("Open vfio file %s failed!\n", vfio_file); goto accel_fail; } vfio_container_fd = vfio_dev->vfio_container_fd; ret = qaeRegisterDevice(vfio_container_fd); if (ret) { close(vfio_dev->vfio_group_fd); goto accel_fail; } adf_vf2pf_notify_init(&vfio_dev->pfvf); return 0; accel_fail: ICP_FREE(vfio_dev); return status; } int adf_io_reinit_accel(icp_accel_dev_t **accel_dev, int dev_id) { struct qatmgr_transport *t_mgr = NULL; int status = -1; if (!accel_dev) return -ENOMEM; if (!*accel_dev) return -ENOMEM; t_mgr = get_transport_mgr(); status = t_mgr->adf_reinit_accel(*accel_dev, dev_id, t_mgr); if (status < 0) { ICP_FREE(*accel_dev); *accel_dev = NULL; } return status; } int adf_vfio_reinit_accel(icp_accel_dev_t *accel_dev, int dev_id, struct qatmgr_transport *t_mgr) { void *pSalHandle = NULL; void *pQatStats = NULL; void *banks = NULL; vfio_dev_info_t *vfio_dev = NULL; if (!accel_dev->ioPriv) return -ENOMEM; pSalHandle = accel_dev->pSalHandle; pQatStats = accel_dev->pQatStats; banks = accel_dev->banks; vfio_dev = (vfio_dev_info_t *)accel_dev->ioPriv; if (adf_populate_accel_dev(dev_id, accel_dev, t_mgr)) goto accel_fail; accel_dev->pSalHandle = pSalHandle; accel_dev->pQatStats = pQatStats; accel_dev->banks = banks; accel_dev->ioPriv = vfio_dev; return 0; accel_fail: qaeUnregisterDevice(vfio_dev->vfio_container_fd); close_vfio_dev(vfio_dev); ICP_FREE(vfio_dev); return -1; } void adf_io_destroy_accel(icp_accel_dev_t *accel_dev) { struct qatmgr_transport *t_mgr = NULL; ICP_CHECK_FOR_NULL_PARAM_VOID(accel_dev); t_mgr = get_transport_mgr(); t_mgr->adf_destroy_accel(accel_dev); } void adf_vfio_destroy_accel(icp_accel_dev_t *accel_dev) { vfio_dev_info_t *vfio_dev; if (!accel_dev->ioPriv) goto free_accel; vfio_dev = accel_dev->ioPriv; adf_vf2pf_notify_shutdown(&vfio_dev->pfvf); qaeUnregisterDevice(vfio_dev->vfio_container_fd); close_vfio_dev(vfio_dev); ICP_FREE(vfio_dev); free_accel: ICP_FREE(accel_dev); } /* For vfio device, after handling the RESTARTING event, qatlib needs to * send RESTARTING_COMPLETE msg to kernel. The kernel checks if all VFs * which map to the same recovering PF have completed RAS flows. * After sending RESTARTING_COMPLETE msg, qatlib should close vfio * dev immediately. Once the kernel receives the RESTARTING_COMPLETE, it * disables sriov and VF/vfio devices disappear. */ void adf_io_vf2pf_notify_restarting_complete(icp_accel_dev_t *accel_dev) { vfio_dev_info_t *vfio_dev = NULL; ICP_CHECK_FOR_NULL_PARAM_VOID(accel_dev); if (!accel_dev->ioPriv) return; vfio_dev = accel_dev->ioPriv; adf_vf2pf_notify_restarting_complete(&vfio_dev->pfvf); qaeUnregisterDevice(vfio_dev->vfio_container_fd); close_vfio_dev(accel_dev->ioPriv); /* This function is triggered by the RESTARTING event * detected by pollProxyEvent. * If the time interval to the next pollProxyEvent is too short * the VF devices may still be active, that would be misinterpreted * that the reset is already complete. * To prevent this add a sleep time here. * This helps qatlib to make sure that next pollProxyEvent call * happens after the kernel has disabled sriov. */ sleep(1); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_common_user_proxy.c000066400000000000000000000211661503624047500337670ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #include #include #include #include "cpa.h" #include "qat_mgr.h" #include "vfio_lib.h" #include "adf_pfvf_vf_msg.h" #include "adf_io_user_proxy.h" #include "adf_io_bundles.h" #include "icp_platform.h" #include "adf_kernel_types.h" #include "icp_accel_devices.h" #include "icp_adf_accel_mgr.h" #include "qae_mem.h" static char currentProcess[QATMGR_MAX_STRLEN]; /* reopen_vfio_dev uses open_vfio_dev to check if the VF has been re-attached * and to re-open the vfio dev. When qatlib sends RESTARTING_COMPLETE msg * to kernel, then it closes the vfio device, otherwise vfio-pci may * block kernel RAS recovery flow as the device appears in use. * Once the vfio device is re-opened, register dev to usdm and re-init * the adf_pfvf_dev_data. */ STATIC int reopen_vfio_dev(vfio_dev_info_t *vfio_dev, int accelId, int pciDevId) { int status = -1; struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; char vfio_file[QATMGR_MAX_STRLEN]; char device_id[QATMGR_MAX_STRLEN]; int group_fd; int vfio_container_fd; ICP_CHECK_FOR_NULL_PARAM(vfio_dev); /* Get device identifier */ req.device_num = accelId; if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_DEVICE_ID)) goto exit; snprintf(device_id, sizeof(device_id), "%s", rsp.device_id); /* Get vfio device file name */ if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_VFIO_FILE)) goto exit; snprintf(vfio_file, sizeof(vfio_file), "%s", rsp.vfio_file.name); group_fd = rsp.vfio_file.fd; if (open_vfio_dev(vfio_file, device_id, group_fd, pciDevId, vfio_dev)) { ADF_DEBUG("Open vfio file %s failed!\n", vfio_file); goto exit; } vfio_container_fd = vfio_dev->vfio_container_fd; if (qaeRegisterDevice(vfio_container_fd)) { close(vfio_dev->vfio_group_fd); goto exit; } adf_vf2pf_check_compat_version(&(vfio_dev->pfvf)); adf_vf2pf_notify_init(&vfio_dev->pfvf); status = 0; exit: return status; } CpaStatus adf_io_userProcessToStart(char const *const name_in, size_t name_tml_len, char *name, size_t name_len) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; int ret; qatmgr_transport_init(); ret = qatmgr_open(); if (ret) return CPA_STATUS_FAIL; ICP_CHECK_FOR_NULL_PARAM(name_in); ICP_CHECK_FOR_NULL_PARAM(name); snprintf(req.name, sizeof(req.name), "%s", name_in); if (qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_SECTION_GET)) { goto error; } if (ADF_CFG_MAX_SECTION_LEN_IN_BYTES <= strnlen(rsp.name, sizeof(rsp.name))) { goto error; } snprintf( name, name_len, "%.*s", ADF_CFG_MAX_SECTION_LEN_IN_BYTES - 1, rsp.name); return CPA_STATUS_SUCCESS; error: qatmgr_close(); return CPA_STATUS_FAIL; } CpaStatus adf_io_userProxyInit(char const *const name) { ICP_CHECK_FOR_NULL_PARAM(name); if (strnlen(name, QATMGR_MAX_STRLEN) >= QATMGR_MAX_STRLEN) { return CPA_STATUS_FAIL; } snprintf(currentProcess, QATMGR_MAX_STRLEN, "%s", name); return CPA_STATUS_SUCCESS; } void adf_io_userProcessStop(void) { struct qatmgr_msg_req req = { 0 }; struct qatmgr_msg_rsp rsp = { 0 }; assert(sizeof(req.name) == sizeof(currentProcess)); snprintf(req.name, sizeof(req.name), "%s", currentProcess); qatmgr_query(&req, &rsp, QATMGR_MSGTYPE_SECTION_PUT); memset(currentProcess, 0, QATMGR_MAX_STRLEN); qatmgr_close(); } void adf_io_userProxyShutdown(void) { } CpaStatus adf_io_resetUserProxy(void) { int ret; ret = qatmgr_close(); if (ret) return CPA_STATUS_FAIL; return CPA_STATUS_SUCCESS; } /* pollProxyEvent function plays an important role during RAS reset/ * recovery flow. It should be called by an application thread. * RAS recovery flow requires that the SAL layer handles three key events: * FATAL_ERROR, RESTARTING and RESTARTED. * * When kernel detects some fatal errors (like HB failed), it sends a * FATAL_ERROR event. Qatlib handles FATAL_ERROR by cleaning the ring pair, * stopping polling the response ring, and changing instance status to error. * * qatlib handles RESTARTING by cleaning the transport layer, changing * instance status to restarting and sending RESTARTING_COMPLETE msg * to kernel. This triggers the kernel to disable sriov, reset PF, then * re-enable sriov. During this period, VF/vfio device disappears and the * communication between kernel and qatlib is cut off. * This could last for a few seconds. * reopen_vfio_dev checks if the communication path can be restored. * As the RESTARTED message may not be received from the PF due to this * loss of communication, this function simulates receipt of this event * based on the path being restored. */ CpaBoolean adf_vfio_poll_proxy_event(Cpa32U *dev_id, enum adf_event *event) { Cpa16U i; Cpa16U msg_type = 0xFFFF; vfio_dev_info_t *vfio_dev; icp_accel_dev_t *accel_tb[ADF_MAX_DEVICES]; Cpa16U num_instances; ICP_CHECK_FOR_NULL_PARAM_RET_CODE(dev_id, CPA_FALSE); ICP_CHECK_FOR_NULL_PARAM_RET_CODE(event, CPA_FALSE); icp_adf_getNumInstances(&num_instances); icp_adf_getInstances(num_instances, &accel_tb[0]); for (i = 0; i < num_instances; ++i) { /* If device is in restarting state, check whether * VF re-attached and reopen vfio dev */ if (icp_adf_isDevInRestarting(accel_tb[i])) { /* If reopen_vfio_dev failed, means VF is not * re-attached yet, then keep polling. */ if (reopen_vfio_dev(accel_tb[i]->ioPriv, accel_tb[i]->accelId, accel_tb[i]->pciDevId)) continue; msg_type = ADF_PF2VF_MSGTYPE_RESTARTED; } else { vfio_dev = accel_tb[i]->ioPriv; msg_type = adf_check_pf2vf_notification(&vfio_dev->pfvf); } if (msg_type == ADF_PF2VF_MSGTYPE_RESTARTING) { *event = ADF_EVENT_RESTARTING; *dev_id = accel_tb[i]->accelId; return CPA_TRUE; } if (msg_type == ADF_PF2VF_MSGTYPE_FATAL_ERROR) { *event = ADF_EVENT_ERROR; *dev_id = accel_tb[i]->accelId; return CPA_TRUE; } if (msg_type == ADF_PF2VF_MSGTYPE_RESTARTED) { *event = ADF_EVENT_RESTARTED; *dev_id = accel_tb[i]->accelId; return CPA_TRUE; } } return CPA_FALSE; } CpaBoolean adf_io_pollProxyEvent(Cpa32U *dev_id, enum adf_event *event) { struct qatmgr_transport *t_mgr = NULL; t_mgr = get_transport_mgr(); return t_mgr->adf_io_poll_proxy_event(dev_id, event); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_msg.h000066400000000000000000000223051503624047500320100ustar00rootroot00000000000000/* * Do not modify, this file was taken from internal kernel sources. * To update, copy new version from kernel sources and: * 1. Add this comment * 2. Remove BUILD_BUG_ON from bottom of file * 3. Reformat using correct tool * linux/user/src/vfio/adf_pfvf_msg.h */ /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) */ /* Copyright(c) 2015 - 2020 Intel Corporation */ #ifndef ADF_PFVF_MSG_H #define ADF_PFVF_MSG_H /* * PF<->VF Gen2 Messaging format * * The PF has an array of 32-bit PF2VF registers, one for each VF. The * PF can access all these registers while each VF can access only the one * register associated with that particular VF. * * The register functionally is split into two parts: * The bottom half is for PF->VF messages. In particular when the first * bit of this register (bit 0) gets set an interrupt will be triggered * in the respective VF. * The top half is for VF->PF messages. In particular when the first bit * of this half of register (bit 16) gets set an interrupt will be triggered * in the PF. * * The remaining bits within this register are available to encode messages. * and implement a collision control mechanism to prevent concurrent use of * the PF2VF register by both the PF and VF. * * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 * _______________________________________________ * | | | | | | | | | | | | | | | | | * +-----------------------------------------------+ * \___________________________/ \_________/ ^ ^ * ^ ^ | | * | | | VF2PF Int * | | Message Origin * | Message Type * Message-specific Data/Reserved * * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 * _______________________________________________ * | | | | | | | | | | | | | | | | | * +-----------------------------------------------+ * \___________________________/ \_________/ ^ ^ * ^ ^ | | * | | | PF2VF Int * | | Message Origin * | Message Type * Message-specific Data/Reserved * * Message Origin (Should always be 1) * A legacy out-of-tree QAT driver allowed for a set of messages not supported * by this driver; these had a Message Origin of 0 and are ignored by this * driver. * * When a PF or VF attempts to send a message in the lower or upper 16 bits, * respectively, the other 16 bits are written to first with a defined * IN_USE_BY pattern as part of a collision control scheme (see adf_iov_putmsg). * * * PF<->VF Gen4 Messaging format * * Similarly to the gen2 messaging format, 32-bit long registers are used for * communication between PF and VFs. However, each VF and PF share a pair of * 32-bits register to avoid collisions: one for PF to VF messages and one * for VF to PF messages. * * Both the Interrupt bit and the Message Origin bit retain the same position * and meaning, although non-system messages are now deprecated and not * expected. * * 31 30 9 8 7 6 5 4 3 2 1 0 * _______________________________________________ * | | | . . . | | | | | | | | | | | * +-----------------------------------------------+ * \_____________________/ \_______________/ ^ ^ * ^ ^ | | * | | | PF/VF Int * | | Message Origin * | Message Type * Message-specific Data/Reserved * * For both formats, the message reception is acknowledged by lowering the * interrupt bit on the register where the message was sent. */ struct pfvf_message { u32 data : 24; u32 type : 8; }; /* PF->VF messages */ enum pf2vf_msgtype { ADF_PF2VF_MSGTYPE_RESTARTING = 0x01, ADF_PF2VF_MSGTYPE_VERSION_RESP = 0x02, ADF_PF2VF_MSGTYPE_BLKMSG_RESP = 0x03, ADF_PF2VF_MSGTYPE_FATAL_ERROR = 0x04, ADF_PF2VF_MSGTYPE_RESTARTED = 0x05, /* Do not use messages which start from 0x10 to 1.x as 1.x only use * * 4 bits as message types. Hence they are only applicable to 2.0 */ ADF_PF2VF_MSGTYPE_RP_RESET_RESP = 0x10, }; /* VF->PF messages */ enum vf2pf_msgtype { ADF_VF2PF_MSGTYPE_INIT = 0x03, ADF_VF2PF_MSGTYPE_SHUTDOWN = 0x04, ADF_VF2PF_MSGTYPE_VERSION_REQ = 0x05, ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ = 0x06, ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ = 0x07, ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ = 0x08, ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ = 0x09, ADF_VF2PF_MSGTYPE_RESTARTING_COMPLETE = 0x0a, /* Do not use messages which start from 0x10 to 1.x as 1.x only use * * 4 bits as message types. Hence they are only applicable to 2.0 */ ADF_VF2PF_MSGTYPE_RP_RESET = 0x10, }; /* VF/PF compatibility version. */ enum pfvf_compatibility_version { /* Support for extended capabilities */ ADF_PFVF_COMPAT_CAPABILITIES = 0x02, /* In-use pattern cleared by receiver */ ADF_PFVF_COMPAT_FAST_ACK = 0x03, /* Ring to service mapping support for non-standard mappings */ ADF_PFVF_COMPAT_RING_TO_SVC_MAP = 0x04, /* Fallback compat. Added RESTARTING_COMPLETE & RESTARTED messages */ ADF_PFVF_COMPAT_FALLBACK = 0x05, /* Reference to the latest version */ ADF_PFVF_COMPAT_THIS_VERSION = 0x05, }; /* PF->VF Version Request/Response */ struct pfvf_compat_message { u32 version : 8; u32 compat : 2; u32 : 14; u32 type : 8; }; enum pf2vf_compat_response { ADF_PF2VF_VF_COMPATIBLE = 0x1, ADF_PF2VF_VF_INCOMPATIBLE = 0x2, ADF_PF2VF_VF_COMPAT_UNKNOWN = 0x3, }; /* PF->VF Ring Reset Response */ struct pfvf_reset_rings_resp { u32 result : 8; u32 : 16; u32 type : 8; }; enum ring_reset_result { RPRESET_SUCCESS = 0x1, RPRESET_NOT_SUPPORTED = 0x2, RPRESET_INVAL_BANK = 0x3, RPRESET_TIMEOUT = 0x4, }; /* VF->PF Ring Reset Request */ struct pfvf_reset_rings_req { u32 rings : 16; u32 : 8; u32 type : 8; }; /* PF->VF Block Responses */ struct pf2vf_blkmsg_resp { u32 blk_resp : 2; u32 data : 8; u32 : 14; u32 type : 8; }; enum pf2vf_blkmsg_resp_type { ADF_PF2VF_BLKMSG_RESP_TYPE_DATA = 0x00, ADF_PF2VF_BLKMSG_RESP_TYPE_CRC = 0x01, ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR = 0x02, }; /* PF->VF Block Error Code */ enum pf2vf_blkmsg_error { ADF_PF2VF_INVALID_BLOCK_TYPE = 0x00, ADF_PF2VF_INVALID_BYTE_NUM_REQ = 0x01, ADF_PF2VF_PAYLOAD_TRUNCATED = 0x02, ADF_PF2VF_UNSPECIFIED_ERROR = 0x03, }; /* VF->PF Block Requests */ struct vf2pf_blkmsg_req_small { u32 blk_type : 4; u32 byte_num : 5; u32 crc : 1; u32 : 14; u32 type : 8; }; struct vf2pf_blkmsg_req_medium { u32 blk_type : 3; u32 byte_num : 6; u32 crc : 1; u32 : 14; u32 type : 8; }; struct vf2pf_blkmsg_req_large { u32 blk_type : 2; u32 byte_num : 7; u32 crc : 1; u32 : 14; u32 type : 8; }; #define ADF_VF2PF_SMALL_PAYLOAD_SIZE 30 #define ADF_VF2PF_MEDIUM_PAYLOAD_SIZE 62 #define ADF_VF2PF_LARGE_PAYLOAD_SIZE 126 /* PF->VF Block Request Types * 0..15 - 32 byte message * 16..23 - 64 byte message * 24..27 - 128 byte message */ enum vf2pf_blkmsg_req_type { ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY = 0x02, ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP = 0x03, }; #define ADF_VF2PF_MIN_SMALL_MESSAGE_TYPE 0 #define ADF_VF2PF_MAX_SMALL_MESSAGE_TYPE 15 #define ADF_VF2PF_MIN_MEDIUM_MESSAGE_TYPE 16 #define ADF_VF2PF_MAX_MEDIUM_MESSAGE_TYPE 23 #define ADF_VF2PF_MIN_LARGE_MESSAGE_TYPE 24 #define ADF_VF2PF_MAX_LARGE_MESSAGE_TYPE 27 struct pfvf_blkmsg_header { u8 version; u8 payload_size; } __packed; #define PFVF_BLKMSG_HEADER_SIZE (sizeof(struct pfvf_blkmsg_header)) #define PFVF_BLKMSG_MSG_SIZE(blkmsg) \ (PFVF_BLKMSG_HEADER_SIZE + blkmsg->hdr.payload_size) #define PFVF_BLKMSG_PAYLOAD_SIZE(blkmsg) \ (sizeof(blkmsg) - PFVF_BLKMSG_HEADER_SIZE) /* PF->VF Block message header bytes */ #define PFVF_BLKMSG_VERSION_BYTE 0 #define PFVF_BLKMSG_LEN_BYTE 1 /* PF/VF Capabilities message values */ enum blkmsg_capabilities_versions { ADF_PFVF_CAPABILITIES_V1_VERSION = 0x01, ADF_PFVF_CAPABILITIES_V2_VERSION = 0x02, ADF_PFVF_CAPABILITIES_V3_VERSION = 0x03, ADF_PFVF_CAPABILITIES_V4_VERSION = 0x04, }; struct capabilities_v1 { struct pfvf_blkmsg_header hdr; u32 ext_dc_caps; } __packed; struct capabilities_v2 { struct pfvf_blkmsg_header hdr; u32 ext_dc_caps; u32 capabilities; } __packed; struct capabilities_v3 { struct pfvf_blkmsg_header hdr; u32 ext_dc_caps; u32 capabilities; u32 frequency; } __packed; struct capabilities_v4 { struct pfvf_blkmsg_header hdr; u32 ext_dc_caps; u32 capabilities; u32 frequency; u16 comp_algos; u16 cksum_algos; u32 deflate_caps; u16 lz4_caps; u16 lz4s_caps; u16 resrvd; } __packed; /* PF/VF Ring to service mapping values */ enum blkmsg_ring_to_svc_versions { ADF_PFVF_RING_TO_SVC_VERSION = 0x01, }; struct ring_to_svc_map_v1 { struct pfvf_blkmsg_header hdr; u16 map; } __packed; #endif /* ADF_PFVF_MSG_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_proto.c000066400000000000000000000344711503624047500323670ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #include "adf_platform_common.h" #include "adf_pfvf_proto.h" #include "icp_platform.h" #include "qat_log.h" #ifndef BIT #define BIT(n) (1 << n) #endif #define ADF_PFVF_INT BIT(0) #define ADF_PFVF_MSGORIGIN_SYSTEM BIT(1) #define ADF_PFVF_GEN4_MSGTYPE_SHIFT 2 #define ADF_PFVF_GEN4_MSGTYPE_MASK 0x3F #define ADF_PFVF_GEN4_MSGDATA_SHIFT 8 #define ADF_PFVF_GEN4_MSGDATA_MASK 0xFFFFFF #define ADF_PFVF_GEN4_PF2VF_CSR_ADDR_OFFSET 0x1008 #define ADF_PFVF_GEN4_VF2PF_CSR_ADDR_OFFSET 0x100C /* How long to wait for far side to acknowledge receipt */ #define ADF_PFVF_MSG_ACK_DELAY_US 5 #define ADF_PFVF_MSG_ACK_MAX_RETRIES 500 /* If CSR is busy, how long to delay before retrying */ #define ADF_PFVF_MSG_COLL_RETRY_DELAY 5 #define ADF_PFVF_MSG_COLL_MAX_RETRIES 3 /* How long to wait for a response from the other side * and how often to retry when there is no response */ #define ADF_PFVF_MSG_RESP_TIMEOUT 100 #define ADF_PFVF_MSG_RESP_RETRIES 5 struct adf_pfvf_dev_data adf_init_pfvf_dev_data(void *pmiscbar_addr, int dev_id) { struct adf_pfvf_dev_data dev = { 0 }; if (pmiscbar_addr == NULL) { return dev; } dev.pmiscbar_addr = pmiscbar_addr; dev.dev_id = dev_id; dev.local_csr_offset = ADF_PFVF_GEN4_VF2PF_CSR_ADDR_OFFSET; dev.remote_csr_offset = ADF_PFVF_GEN4_PF2VF_CSR_ADDR_OFFSET; dev.type_shift = ADF_PFVF_GEN4_MSGTYPE_SHIFT; dev.data_shift = ADF_PFVF_GEN4_MSGDATA_SHIFT; dev.type_mask = ADF_PFVF_GEN4_MSGTYPE_MASK; dev.data_mask = ADF_PFVF_GEN4_MSGDATA_MASK; return dev; } static int adf_pfvf_msg_ack_timed_out(struct adf_pfvf_dev_data *dev, uint32_t *last, uint32_t int_bit) { int count = 0; ICP_CHECK_FOR_NULL_PARAM(dev); ICP_CHECK_FOR_NULL_PARAM(last); for (; count < ADF_PFVF_MSG_ACK_MAX_RETRIES; ++count) { usleep(ADF_PFVF_MSG_ACK_DELAY_US); *last = ICP_ADF_CSR_RD(dev->pmiscbar_addr, dev->local_csr_offset); if (!((*last) & int_bit)) return 0; } return 1; } static int adf_pfvf_gen4_send(struct adf_pfvf_dev_data *dev, struct pfvf_message msg) { int ret = 0; uint32_t raw_msg; ICP_CHECK_FOR_NULL_PARAM(dev); raw_msg = (msg.type << dev->type_shift) | (msg.data << dev->data_shift); raw_msg |= ADF_PFVF_INT | ADF_PFVF_MSGORIGIN_SYSTEM; ICP_ADF_CSR_WR(dev->pmiscbar_addr, dev->local_csr_offset, raw_msg); if (adf_pfvf_msg_ack_timed_out(dev, &raw_msg, ADF_PFVF_INT)) { qat_log(LOG_LEVEL_INFO, "ACK not received from remote\n"); ret = -EIO; } return ret; } int adf_send_vf2pf_msg(struct adf_pfvf_dev_data *dev, struct pfvf_message msg) { if (dev == NULL) { qat_log(LOG_LEVEL_ERROR, "PF2VF dev is null\n"); return -EINVAL; } if ((msg.type & dev->type_mask) != msg.type) { qat_log(LOG_LEVEL_ERROR, "PF2VF message type 0x%X out of range\n", msg.type); return -EINVAL; } if ((msg.data & dev->data_mask) != msg.data) { qat_log(LOG_LEVEL_ERROR, "PF2VF message data 0x%X out of range\n", msg.data); return -EINVAL; } return adf_pfvf_gen4_send(dev, msg); } struct pfvf_message adf_pfvf_gen4_recv(struct adf_pfvf_dev_data *dev) { uint32_t val; struct pfvf_message msg = { 0 }; if (dev == NULL) { return msg; } /* Read message from the CSR */ val = ICP_ADF_CSR_RD(dev->pmiscbar_addr, dev->remote_csr_offset); /* We can now acknowledge the message reception by clearing the interrupt * bit */ if (val & ADF_PFVF_INT) { ICP_ADF_CSR_WR( dev->pmiscbar_addr, dev->remote_csr_offset, val & ~ADF_PFVF_INT); msg.type = (val >> dev->type_shift) & dev->type_mask; msg.data = (val >> dev->data_shift) & dev->data_mask; } return msg; } struct pfvf_message adf_recv_pf2vf_msg(struct adf_pfvf_dev_data *dev) { return adf_pfvf_gen4_recv(dev); } int adf_send_vf2pf_req(struct adf_pfvf_dev_data *dev, struct pfvf_message req, struct pfvf_message *resp) { unsigned long timeout = ADF_PFVF_MSG_RESP_TIMEOUT; unsigned long retries = 0; int err; int response_received = 0; int status = -EIO; ICP_CHECK_FOR_NULL_PARAM(dev); ICP_CHECK_FOR_NULL_PARAM(resp); do { err = adf_send_vf2pf_msg(dev, req); if (err) { qat_log(LOG_LEVEL_INFO, "Failed to send request msg to PF\n"); return err; } usleep(timeout); *resp = adf_recv_pf2vf_msg(dev); if ((*resp).type != 0) { response_received = 1; status = 0; } } while (!response_received && retries++ < ADF_PFVF_MSG_RESP_RETRIES); return status; } STATIC int adf_vf2pf_blkmsg_data_req(struct adf_pfvf_dev_data *dev, uint8_t type, uint8_t byte, uint8_t *data, uint8_t is_crc) { struct pfvf_message req = { 0 }; struct pf2vf_blkmsg_resp resp; uint16_t max_payload_size; int err; ICP_CHECK_FOR_NULL_PARAM(dev); ICP_CHECK_FOR_NULL_PARAM(data); /* Build the block message */ if (type <= ADF_VF2PF_MAX_SMALL_MESSAGE_TYPE) { struct vf2pf_blkmsg_req_small *msg = (struct vf2pf_blkmsg_req_small *)&req; msg->type = ADF_VF2PF_MSGTYPE_SMALL_BLOCK_REQ; msg->blk_type = type; msg->byte_num = byte; msg->crc = is_crc; max_payload_size = ADF_VF2PF_SMALL_PAYLOAD_SIZE; } else if (type <= ADF_VF2PF_MAX_MEDIUM_MESSAGE_TYPE) { struct vf2pf_blkmsg_req_medium *msg = (struct vf2pf_blkmsg_req_medium *)&req; msg->type = ADF_VF2PF_MSGTYPE_MEDIUM_BLOCK_REQ; msg->blk_type = type - ADF_VF2PF_MIN_MEDIUM_MESSAGE_TYPE; msg->byte_num = byte; msg->crc = is_crc; max_payload_size = ADF_VF2PF_MEDIUM_PAYLOAD_SIZE; } else if (type <= ADF_VF2PF_MAX_LARGE_MESSAGE_TYPE) { struct vf2pf_blkmsg_req_large *msg = (struct vf2pf_blkmsg_req_large *)&req; msg->type = ADF_VF2PF_MSGTYPE_LARGE_BLOCK_REQ; msg->blk_type = type - ADF_VF2PF_MIN_LARGE_MESSAGE_TYPE; msg->byte_num = byte; msg->crc = is_crc; max_payload_size = ADF_VF2PF_LARGE_PAYLOAD_SIZE; } else { qat_log(LOG_LEVEL_ERROR, "Invalid message type %d\n", type); return -EINVAL; } if (byte >= max_payload_size + PFVF_BLKMSG_HEADER_SIZE) { qat_log(LOG_LEVEL_ERROR, "Invalid byte index %d for message type %d\n", byte, type); return -EINVAL; } err = adf_send_vf2pf_req(dev, req, (struct pfvf_message *)&resp); if (err) return err; if (resp.blk_resp == ADF_PF2VF_BLKMSG_RESP_TYPE_ERROR) { qat_log(LOG_LEVEL_ERROR, "Error in blk message response\n"); return -EIO; } *data = resp.data; return 0; } static int adf_vf2pf_blkmsg_get_byte(struct adf_pfvf_dev_data *dev, uint8_t type, uint8_t index, uint8_t *data) { return adf_vf2pf_blkmsg_data_req(dev, type, index, data, 0); } static int adf_vf2pf_blkmsg_get_crc(struct adf_pfvf_dev_data *dev, uint8_t type, uint8_t bytes, uint8_t *crc) { return adf_vf2pf_blkmsg_data_req(dev, type, bytes - 1, crc, 1); } /* CRC Calculation */ #define ADF_CRC8_INIT_VALUE 0xFF static const unsigned char pfvf_crc8_table[] = { 0x00, 0x97, 0xB9, 0x2E, 0xE5, 0x72, 0x5C, 0xCB, 0x5D, 0xCA, 0xE4, 0x73, 0xB8, 0x2F, 0x01, 0x96, 0xBA, 0x2D, 0x03, 0x94, 0x5F, 0xC8, 0xE6, 0x71, 0xE7, 0x70, 0x5E, 0xC9, 0x02, 0x95, 0xBB, 0x2C, 0xE3, 0x74, 0x5A, 0xCD, 0x06, 0x91, 0xBF, 0x28, 0xBE, 0x29, 0x07, 0x90, 0x5B, 0xCC, 0xE2, 0x75, 0x59, 0xCE, 0xE0, 0x77, 0xBC, 0x2B, 0x05, 0x92, 0x04, 0x93, 0xBD, 0x2A, 0xE1, 0x76, 0x58, 0xCF, 0x51, 0xC6, 0xE8, 0x7F, 0xB4, 0x23, 0x0D, 0x9A, 0x0C, 0x9B, 0xB5, 0x22, 0xE9, 0x7E, 0x50, 0xC7, 0xEB, 0x7C, 0x52, 0xC5, 0x0E, 0x99, 0xB7, 0x20, 0xB6, 0x21, 0x0F, 0x98, 0x53, 0xC4, 0xEA, 0x7D, 0xB2, 0x25, 0x0B, 0x9C, 0x57, 0xC0, 0xEE, 0x79, 0xEF, 0x78, 0x56, 0xC1, 0x0A, 0x9D, 0xB3, 0x24, 0x08, 0x9F, 0xB1, 0x26, 0xED, 0x7A, 0x54, 0xC3, 0x55, 0xC2, 0xEC, 0x7B, 0xB0, 0x27, 0x09, 0x9E, 0xA2, 0x35, 0x1B, 0x8C, 0x47, 0xD0, 0xFE, 0x69, 0xFF, 0x68, 0x46, 0xD1, 0x1A, 0x8D, 0xA3, 0x34, 0x18, 0x8F, 0xA1, 0x36, 0xFD, 0x6A, 0x44, 0xD3, 0x45, 0xD2, 0xFC, 0x6B, 0xA0, 0x37, 0x19, 0x8E, 0x41, 0xD6, 0xF8, 0x6F, 0xA4, 0x33, 0x1D, 0x8A, 0x1C, 0x8B, 0xA5, 0x32, 0xF9, 0x6E, 0x40, 0xD7, 0xFB, 0x6C, 0x42, 0xD5, 0x1E, 0x89, 0xA7, 0x30, 0xA6, 0x31, 0x1F, 0x88, 0x43, 0xD4, 0xFA, 0x6D, 0xF3, 0x64, 0x4A, 0xDD, 0x16, 0x81, 0xAF, 0x38, 0xAE, 0x39, 0x17, 0x80, 0x4B, 0xDC, 0xF2, 0x65, 0x49, 0xDE, 0xF0, 0x67, 0xAC, 0x3B, 0x15, 0x82, 0x14, 0x83, 0xAD, 0x3A, 0xF1, 0x66, 0x48, 0xDF, 0x10, 0x87, 0xA9, 0x3E, 0xF5, 0x62, 0x4C, 0xDB, 0x4D, 0xDA, 0xF4, 0x63, 0xA8, 0x3F, 0x11, 0x86, 0xAA, 0x3D, 0x13, 0x84, 0x4F, 0xD8, 0xF6, 0x61, 0xF7, 0x60, 0x4E, 0xD9, 0x12, 0x85, 0xAB, 0x3C }; static uint8_t adf_pfvf_crc(uint8_t start_crc, uint8_t *buf, uint8_t len) { uint8_t crc = start_crc; ICP_CHECK_FOR_NULL_PARAM(buf); while (len-- > 0) crc = pfvf_crc8_table[(crc ^ *buf++) & 0xff]; return crc; } uint8_t adf_pfvf_calc_blkmsg_crc(uint8_t *buf, uint8_t buf_len) { return adf_pfvf_crc(ADF_CRC8_INIT_VALUE, buf, buf_len); } int adf_send_vf2pf_blkmsg_req(struct adf_pfvf_dev_data *dev, uint8_t type, uint8_t *buffer, uint16_t *buffer_len) { uint8_t remote_crc; uint8_t local_crc; uint16_t index; uint16_t msg_len; int ret; ICP_CHECK_FOR_NULL_PARAM(dev); ICP_CHECK_FOR_NULL_PARAM(buffer); ICP_CHECK_FOR_NULL_PARAM(buffer_len); if (type > ADF_VF2PF_MAX_LARGE_MESSAGE_TYPE) { qat_log(LOG_LEVEL_ERROR, "Invalid message type %d\n", type); return -EINVAL; } if (*buffer_len < PFVF_BLKMSG_HEADER_SIZE) { qat_log(LOG_LEVEL_ERROR, "Buffer size too small for a block message\n"); return -EINVAL; } ret = adf_vf2pf_blkmsg_get_byte( dev, type, PFVF_BLKMSG_VERSION_BYTE, &buffer[PFVF_BLKMSG_VERSION_BYTE]); if (ret) return ret; if (0 == buffer[PFVF_BLKMSG_VERSION_BYTE]) { qat_log(LOG_LEVEL_ERROR, "Invalid version 0 received for block request %u\n", type); return -EFAULT; } ret = adf_vf2pf_blkmsg_get_byte( dev, type, PFVF_BLKMSG_LEN_BYTE, &buffer[PFVF_BLKMSG_LEN_BYTE]); if (ret) return ret; if (0 == buffer[PFVF_BLKMSG_LEN_BYTE]) { qat_log(LOG_LEVEL_ERROR, "Invalid size 0 received for block request %u\n", type); return -EFAULT; } /* We need to pick the minimum since there is no way to request a * specific version. As a consequence any scenario is possible: * - PF has a newer (longer) version which doesn't fit in the buffer * - VF expects a newer (longer) version, so we must not ask for * bytes in excess * - PF and VF share the same version, no problem */ msg_len = PFVF_BLKMSG_HEADER_SIZE + buffer[PFVF_BLKMSG_LEN_BYTE]; if (*buffer_len < msg_len) { qat_log(LOG_LEVEL_INFO, "Truncating block type %d response from %d to %d bytes\n", type, msg_len, *buffer_len); msg_len = *buffer_len; } /* Get the payload */ for (index = PFVF_BLKMSG_HEADER_SIZE; index < msg_len; index++) { ret = adf_vf2pf_blkmsg_get_byte(dev, type, index, &buffer[index]); if (ret) return ret; } ret = adf_vf2pf_blkmsg_get_crc(dev, type, msg_len, &remote_crc); if (ret) return ret; local_crc = adf_pfvf_calc_blkmsg_crc(buffer, msg_len); if (local_crc != remote_crc) { qat_log(LOG_LEVEL_ERROR, "CRC error on msg type %d. Local %02X, remote %02X\n", type, local_crc, remote_crc); return -EIO; } *buffer_len = msg_len; return 0; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_proto.h000066400000000000000000000121061503624047500323630ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #ifndef ADF_PFVF_PROTO_H #define ADF_PFVF_PROTO_H #include "adf_kernel_types.h" #include "adf_pfvf_msg.h" struct fw_caps { uint16_t comp_algos; uint16_t cksum_algos; uint32_t deflate_caps; uint16_t lz4_caps; uint16_t lz4s_caps; uint8_t is_fw_caps; }; struct adf_pfvf_dev_data { void *pmiscbar_addr; uint32_t dev_id; uint32_t local_csr_offset; uint32_t remote_csr_offset; uint32_t type_shift; uint32_t data_shift; uint32_t type_mask; uint32_t data_mask; uint8_t pfvf_initialized; uint32_t compat_version; uint32_t frequency; uint32_t ext_dc_caps; struct fw_caps fw_caps; uint32_t capabilities; uint32_t ring_to_svc_map; }; /** * @ingroup adf_vf2pf * * @description * This function fills adf_pfvf_dev_data structure for given device. * * @param[in] pmiscbar_addr Address of PMISC BAR base * @param[in] dev_id PCI device id * * @retval struct adf_pfvf_dev_data initialized for given device. */ struct adf_pfvf_dev_data adf_init_pfvf_dev_data(void *pmiscbar_addr, int dev_id); /** * @ingroup adf_vf2pf * * @description * This function sends message from VF to PF and waits for ACK from PF. * * @param[in] dev Pointer to VF's pfvf data struct. * @param[in] msg Message to be sent to PF. * * @retval 0 Function executed successfully. * @retval -EINVAL Provided argument is invalid. * @retval -EIO Timed out waiting for ACK from PF. */ int adf_send_vf2pf_msg(struct adf_pfvf_dev_data *dev, struct pfvf_message msg); /** * @ingroup adf_vf2pf * * @description * This function sends request from VF to PF and waits for PF response. * * @param[in] dev Pointer to VF's pfvf data struct. * @param[in] req Request message to be sent to PF. * @param[out] resp Response message from PF. * * @retval 0 Function executed successfully. * @retval -EINVAL Provided argument is invalid. * @retval -EIO Timed out waiting for ACK or response message from PF. */ int adf_send_vf2pf_req(struct adf_pfvf_dev_data *dev, struct pfvf_message req, struct pfvf_message *resp); /** * @ingroup adf_vf2pf * * @description * This function sends block message request from VF to PF and waits for PF * response. * * @param[in] dev Pointer to VF's pfvf data struct. * @param[in] type Type of request to be sent. * @param[out] buffer Buffer for receiving payload from PF. * @param[in/out] buffer_len Size of buffer in bytes/size of received * payload. * * @retval 0 Function executed successfully. * @retval -EINVAL Provided argument is invalid. * @retval -EIO Timed out waiting for response message from PF or received * incorrect data (CRC mismatch). */ int adf_send_vf2pf_blkmsg_req(struct adf_pfvf_dev_data *dev, uint8_t type, uint8_t *buffer, uint16_t *buffer_len); /** * @ingroup adf_vf2pf * * @description * This function receives message from PF. * * @param[in] dev Pointer to VF's pfvf data struct. * * @retval pfvf_message struct with type set to 0 No pending message from PF. */ struct pfvf_message adf_recv_pf2vf_msg(struct adf_pfvf_dev_data *dev); #endif /* ADF_PFVF_PROTO_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_vf_msg.c000066400000000000000000000260031503624047500324750ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #include #include #include "adf_pfvf_vf_msg.h" #include "icp_platform.h" #include "qat_log.h" #define VF2PF_UNKNOWN -1 #define VF2PF_AVAILABLE 1 #define VF2PF_NOT_AVAILABLE 0 /* At the beginning we assume PF driver does not support PFVF. * If first init notification will be ACKed, VF2PF support will be marked as * available. Any further error in communication will disable it again. * Newer version received, fallthrough to handle the known parts. */ static int vf2pf_available = VF2PF_UNKNOWN; STATIC void adf_set_vf2pf_available(int available) { /* VF2PF error at first attempt of communication, assuming PF driver has no * PFVF support */ if (vf2pf_available == VF2PF_UNKNOWN && available == VF2PF_NOT_AVAILABLE) { qat_log(LOG_LEVEL_INFO, "PF has not support for PFVF\n"); } else if (vf2pf_available == VF2PF_AVAILABLE && available == VF2PF_NOT_AVAILABLE) { qat_log(LOG_LEVEL_ERROR, "Error in PF2VF communication, disabling PFVF\n"); } vf2pf_available = available; } int adf_vf2pf_available() { if (vf2pf_available == VF2PF_NOT_AVAILABLE) { qat_log(LOG_LEVEL_INFO, "VF2PF is not available\n"); return 0; } return 1; } int adf_vf2pf_notify_init(struct adf_pfvf_dev_data *dev) { struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_INIT }; ICP_CHECK_FOR_NULL_PARAM(dev); if (!adf_vf2pf_available()) return -EIO; if (adf_send_vf2pf_msg(dev, msg)) { qat_log(LOG_LEVEL_INFO, "Failed to send Init event to PF\n"); adf_set_vf2pf_available(VF2PF_NOT_AVAILABLE); return -EFAULT; } vf2pf_available = VF2PF_AVAILABLE; dev->pfvf_initialized = 1; return 0; } void adf_vf2pf_notify_shutdown(struct adf_pfvf_dev_data *dev) { ICP_CHECK_FOR_NULL_PARAM_VOID(dev); struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_SHUTDOWN }; if (!adf_vf2pf_available()) return; if (dev->pfvf_initialized) { if (adf_send_vf2pf_msg(dev, msg)) { qat_log(LOG_LEVEL_ERROR, "Failed to send Shutdown event to PF\n"); adf_set_vf2pf_available(VF2PF_NOT_AVAILABLE); } else dev->pfvf_initialized = 0; } } void adf_vf2pf_notify_restarting_complete(struct adf_pfvf_dev_data *dev) { ICP_CHECK_FOR_NULL_PARAM_VOID(dev); struct pfvf_message msg = { .type = ADF_VF2PF_MSGTYPE_RESTARTING_COMPLETE }; if (!adf_vf2pf_available()) return; if (dev->pfvf_initialized) { if (adf_send_vf2pf_msg(dev, msg)) { qat_log(LOG_LEVEL_ERROR, "Failed to send Restarting complete event to PF\n"); adf_set_vf2pf_available(VF2PF_NOT_AVAILABLE); } else dev->pfvf_initialized = 0; } } int adf_vf2pf_check_compat_version(struct adf_pfvf_dev_data *dev) { int ret; struct pfvf_compat_message resp; struct pfvf_compat_message compat_req = { .type = ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ, .version = ADF_PFVF_COMPAT_THIS_VERSION, }; struct pfvf_message req; ICP_CHECK_FOR_NULL_PARAM(dev); if (!adf_vf2pf_available()) return -EIO; /* memcpy between pfvf_compat_message and pfvf_message to prevent * strict-aliasing warnings */ memcpy(&req, &compat_req, sizeof(req)); ret = adf_send_vf2pf_req(dev, req, (struct pfvf_message *)&resp); if (ret) { qat_log(LOG_LEVEL_INFO, "Failed to send Compatibility Version Request\n"); adf_set_vf2pf_available(VF2PF_NOT_AVAILABLE); return ret; } if (resp.type != ADF_PF2VF_MSGTYPE_VERSION_RESP) { qat_log(LOG_LEVEL_ERROR, "PFVF expecting Version Response, received msg type %u\n", resp.type); return -EFAULT; } if (resp.compat != ADF_PF2VF_VF_COMPATIBLE) { if (resp.compat == ADF_PF2VF_VF_COMPAT_UNKNOWN) { /* The PF driver has an older compat version than qatlib so it’s up * to qatlib to decide if it can work with the PF or not. The intree * kernel on gen4 started with ADF_PFVF_COMPAT_RING_TO_SVC_MAP * so no need to handle earlier versions. Note, earlier kernels * would not have responded to COMPAT message, qatlib doesn’t treat * them as incompatible, instead works with them based on assuming * default config. */ if (resp.version >= ADF_PFVF_COMPAT_RING_TO_SVC_MAP && resp.version < ADF_PFVF_COMPAT_THIS_VERSION) { qat_log(LOG_LEVEL_INFO, "Running in compatibility mode\n"); qat_log(LOG_LEVEL_INFO, " PF version %d, VF version %d\n", resp.version, compat_req.version); } else { qat_log(LOG_LEVEL_ERROR, "VF version %d is incompatible with PF version %d\n", compat_req.version, resp.version); return -EFAULT; } } else { qat_log(LOG_LEVEL_ERROR, "PF version %d is incompatible with VF version %d\n", resp.version, compat_req.version); return -EFAULT; } } dev->compat_version = resp.version; return 0; } int adf_vf2pf_get_ring_to_svc(struct adf_pfvf_dev_data *dev) { struct ring_to_svc_map_v1 rts_map_msg = { { 0 }, }; uint16_t len = sizeof(rts_map_msg); ICP_CHECK_FOR_NULL_PARAM(dev); if (!adf_vf2pf_available()) return -EIO; if (dev->compat_version < ADF_PFVF_COMPAT_RING_TO_SVC_MAP) /* Use already set default mappings */ return -EFAULT; if (adf_send_vf2pf_blkmsg_req(dev, ADF_VF2PF_BLKMSG_REQ_RING_SVC_MAP, (uint8_t *)&rts_map_msg, &len)) { qat_log(LOG_LEVEL_ERROR, "Failed to get block message response\n"); adf_set_vf2pf_available(VF2PF_NOT_AVAILABLE); return -EFAULT; } if (len < sizeof(struct ring_to_svc_map_v1)) { qat_log(LOG_LEVEL_ERROR, "RING_TO_SVC message truncated to %d bytes\n", len); return -EFAULT; } /* Only v1 at present */ dev->ring_to_svc_map = rts_map_msg.map; return 0; } int adf_vf2pf_get_capabilities(struct adf_pfvf_dev_data *dev) { struct capabilities_v4 cap_msg = { { 0 }, }; uint16_t len = sizeof(cap_msg); int ret = 0; ICP_CHECK_FOR_NULL_PARAM(dev); if (!adf_vf2pf_available()) return -EIO; if (dev->compat_version < ADF_PFVF_COMPAT_CAPABILITIES) { /* The PF is too old to support the extended capabilities */ return -EFAULT; } if (adf_send_vf2pf_blkmsg_req( dev, ADF_VF2PF_BLKMSG_REQ_CAP_SUMMARY, (uint8_t *)&cap_msg, &len)) { qat_log(LOG_LEVEL_ERROR, "Failed to get CAP_SUMMARY response\n"); adf_set_vf2pf_available(VF2PF_NOT_AVAILABLE); return -EFAULT; } switch (cap_msg.hdr.version) { default: /* Newer version received, fallthrough to handle the know parts */ case ADF_PFVF_CAPABILITIES_V4_VERSION: if (len >= sizeof(struct capabilities_v4)) { dev->fw_caps.comp_algos = cap_msg.comp_algos; dev->fw_caps.cksum_algos = cap_msg.cksum_algos; dev->fw_caps.deflate_caps = cap_msg.deflate_caps; dev->fw_caps.lz4_caps = cap_msg.lz4_caps; dev->fw_caps.lz4s_caps = cap_msg.lz4s_caps; dev->fw_caps.is_fw_caps = 1; } else { qat_log(LOG_LEVEL_ERROR, "Could not get firmware capabilities\n"); ret = -EFAULT; } case ADF_PFVF_CAPABILITIES_V3_VERSION: if (len >= sizeof(struct capabilities_v3)) { dev->frequency = cap_msg.frequency; } else { qat_log(LOG_LEVEL_ERROR, "Could not get frequency\n"); ret = -EFAULT; } case ADF_PFVF_CAPABILITIES_V2_VERSION: if (len >= sizeof(struct capabilities_v2)) { dev->capabilities = cap_msg.capabilities; } else { qat_log(LOG_LEVEL_ERROR, "Could not get capabilities\n"); ret = -EFAULT; } case ADF_PFVF_CAPABILITIES_V1_VERSION: if (len >= sizeof(struct capabilities_v1)) { dev->ext_dc_caps = cap_msg.ext_dc_caps; } else { qat_log(LOG_LEVEL_ERROR, "CAPABILITIES message truncated to %d bytes\n", len); ret = -EFAULT; } } return ret; } int adf_check_pf2vf_notification(struct adf_pfvf_dev_data *dev) { struct pfvf_message msg; ICP_CHECK_FOR_NULL_PARAM(dev); msg = adf_recv_pf2vf_msg(dev); return msg.type; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_pfvf_vf_msg.h000066400000000000000000000114471503624047500325100ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #ifndef ADF_PFVF_VF_MSG_H #define ADF_PFVF_VF_MSG_H #include "adf_pfvf_proto.h" /** * @ingroup adf_vf2pf * * @description * This function sends init message notification from VF to PF. * * @param[in] dev Pointer to VF's pfvf data struct. * * @retval 0 Function executed successfully. * @retval -EFAULT Function failed. */ int adf_vf2pf_notify_init(struct adf_pfvf_dev_data *dev); /** * @ingroup adf_vf2pf * * @description * This function sends shutdown message notification from VF to PF. * * @param[in] dev Pointer to VF's pfvf data struct. */ void adf_vf2pf_notify_shutdown(struct adf_pfvf_dev_data *dev); /** * @ingroup adf_vf2pf * * @description * This function sends restarting complete message from VF to PF. * * @param[in] dev Pointer to VF's pfvf data struct. */ void adf_vf2pf_notify_restarting_complete(struct adf_pfvf_dev_data *dev); /** * @ingroup adf_vf2pf * * @description * This function sends compatibility version request message and waits for * response. Received compatiility version will be set in VF's pfvf data struct. * * @param[in] dev Pointer to VF's pfvf data struct. * * @retval 0 Received "compatible" response. * @retval -EFAULT Received unexpected response or received "incompatible" * response * @retval -EINVAL Provided incorrect parameters * @retval -EIO Timed out waiting for PF response */ int adf_vf2pf_check_compat_version(struct adf_pfvf_dev_data *dev); /** * @ingroup adf_vf2pf * * @description * This function sends capabilities request message and waits for response. * Received data (capabilities, extended DC capabilities and frequency) * will be set in VF's pfvf data struct. * * @param[in] dev Pointer to VF's pfvf data struct. * * @retval 0 Function executed successfully. * @retval -EFAULT Timed out waiting for PF response or received incorrect * response */ int adf_vf2pf_get_capabilities(struct adf_pfvf_dev_data *dev); /** * @ingroup adf_vf2pf * * @description * This function sends ring to service request message and waits for * response. Received rint to service mapping will be set in VF's pfvf data * struct. * * @param[in] dev Pointer to VF's pfvf data struct. * * @retval 0 Function executed successfully. * @retval -EFAULT Timed out waiting for PF response or received incorrect * response */ int adf_vf2pf_get_ring_to_svc(struct adf_pfvf_dev_data *dev); /** * @ingroup adf_vf2pf * * @description * This function check for notifications from PF. * * @param[in] dev Pointer to VF's pfvf data struct. * * @retval notification type 0 if there was no notification from PF, * otherwise type of received message. */ int adf_check_pf2vf_notification(struct adf_pfvf_dev_data *dev); /** * @ingroup adf_vf2pf * * @description * This function check if VF2PF communication is available. * * @retval 0 VF2PF is not available * @retval 1 VF2PF is available */ int adf_vf2pf_available(); #endif /* ADF_PFVF_VF_MSG_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_vfio_pf.c000066400000000000000000000121731503624047500316260ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #include #include #include #include #include #include #include "adf_kernel_types.h" #include "cpa.h" #include "icp_accel_devices.h" #include "icp_platform.h" #include "qat_mgr.h" #include "qat_log.h" #define DEVVFIO_DIR "/sys/bus/pci/drivers" #define DEVICE_NAME_LENGTH 5 static int filter_pf_in_use(const struct dirent *entry) { unsigned node, bus, dev, func; /* Deduce the entry is a PF if the name has 4 parts in format n:b:d.f */ if (sscanf(entry->d_name, "%x:%x:%x.%x", &node, &bus, &dev, &func) != 4) return 0; return 1; } static int is_qat_dev_present(char *dev_name) { int i = 0; int status = -1; struct dirent **namelist = NULL; int32_t number_of_dev = 0; number_of_dev = scandir(DEVVFIO_DIR, &namelist, NULL, alphasort); if (number_of_dev < 0) { return status; } for (i = 0; i < number_of_dev; i++) { if (strncmp(namelist[i]->d_name, dev_name, DEVICE_NAME_LENGTH) == 0) { status = 0; break; } } for (i = 0; i < number_of_dev; i++) { free(namelist[i]); } free(namelist); return status; } Cpa32S adf_vfio_init_pfs_info(icp_accel_pf_info_t *pf_info, size_t pf_info_len) { unsigned domain, bus, dev, func; struct dirent **namelist; int32_t i, j, number_of_pfs = 0, total_no_pfs = 0; int status = CPA_STATUS_FAIL; char dev_path[QATMGR_MAX_STRLEN] = { '\0' }; char *device_name = NULL; ICP_CHECK_FOR_NULL_PARAM(pf_info); for (j = 0; j < device_names_size; j++) { device_name = device_names[j]; status = is_qat_dev_present(device_name); if (status == CPA_STATUS_SUCCESS) { snprintf( dev_path, sizeof(dev_path), "%s/%s", DEVVFIO_DIR, device_name); number_of_pfs = scandir(dev_path, &namelist, &filter_pf_in_use, alphasort); /* This shows scandir dir failed. */ if (number_of_pfs < 0) { ADF_ERROR("Failed to scan directory %s\n", DEVVFIO_DIR); return CPA_STATUS_FAIL; } total_no_pfs += number_of_pfs; if (pf_info_len < total_no_pfs) { ADF_ERROR("Given pf info array length is too small for %d " "number of PFs\n", number_of_pfs); for (i = 0; i < number_of_pfs; i++) { free(namelist[i]); } free(namelist); return CPA_STATUS_INVALID_PARAM; } for (i = 0; i < number_of_pfs; i++) { sscanf(namelist[i]->d_name, "%x:%x:%x.%x", &domain, &bus, &dev, &func); pf_info[i].pkg_id = i; pf_info[i].domain = domain; pf_info[i].bdf = ((0xFF & bus) << 8) + ((0x1F & dev) << 3) + (0x07 & func); strncpy( pf_info[i].device_gen, device_name, ADF_DEVICE_TYPE_LENGTH); free(namelist[i]); } free(namelist); } } return total_no_pfs; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/adf_vfio_pf.h000066400000000000000000000045101503624047500316270ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #ifndef ADF_VFIO_PF_H #define ADF_VFIO_PF_H #include "cpa_types.h" #include "icp_accel_devices.h" /** * @description * Scans qat driver sysfs entries for PFs. * * @param pf_info Pointer to array of icp_accel_pf_info_t structs. * @param pf_info_len PF array length. * * @retval Number of PFs if the function executed successfully. * @retval CPA_STATUS_INVALID_PARAM if function failed. */ Cpa32S adf_vfio_init_pfs_info(icp_accel_pf_info_t *pf_info, size_t pf_info_len); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_log.c000066400000000000000000000055251503624047500310150ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #include #include #include "qat_log.h" #ifdef ICP_DEBUG int debug_level = LOG_LEVEL_DEBUG; #else int debug_level = LOG_LEVEL_ERROR; #endif static int pr_err(const char *fmt, va_list args) { return vfprintf(stderr, fmt, args); } static int pr_info(const char *fmt, va_list args) { int ret; if (debug_level < LOG_LEVEL_INFO) return 1; ret = vprintf(fmt, args); return ret; } static int pr_dbg(const char *fmt, va_list args) { int ret; if (debug_level < LOG_LEVEL_DEBUG) return 1; ret = vprintf(fmt, args); return ret; } int qat_log(int log_level, const char *fmt, ...) { va_list args; int ret = 1; va_start(args, fmt); switch (log_level) { case LOG_LEVEL_ERROR: ret = pr_err(fmt, args); break; case LOG_LEVEL_INFO: ret = pr_info(fmt, args); break; case LOG_LEVEL_DEBUG: ret = pr_dbg(fmt, args); break; } va_end(args); return ret; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_log.h000066400000000000000000000050551503624047500310200ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef QAT_LOG_H #define QAT_LOG_H extern int debug_level; #define LOG_LEVEL_ERROR 0 #define LOG_LEVEL_INFO 1 #define LOG_LEVEL_DEBUG 2 int qat_log(int log_level, const char *fmt, ...); #ifdef ADF_ERROR #undef ADF_ERROR #endif #define ADF_ERROR(format, args...) \ qat_log(LOG_LEVEL_ERROR, "err: %s: " format, (__func__), ##args) #ifdef ADF_DEBUG #undef ADF_DEBUG #endif #define ADF_DEBUG(format, args...) \ qat_log(LOG_LEVEL_DEBUG, "debug: %s: " format, (__func__), ##args) #define ADF_INFO(format, args...) \ qat_log(LOG_LEVEL_INFO, "info: %s: " format, (__func__), ##args) #endif /* QAT_LOG_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr.h000066400000000000000000000342501503624047500310230ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef QAT_MGR_H #define QAT_MGR_H #include #include #include #include "icp_sal_versions.h" #include "icp_accel_devices.h" #include "adf_pfvf_proto.h" #include "adf_io_bundles.h" /* The running qatlib/qatmgr pair must be from the same package. * There's no requirement for backwards compatibility if * versions are different. As all requests are initiated * by qatlib only qatmgr should need to check the version in hdr. * However checking is done in qatlib to catch incompatibilities if paired * with an earlier qatmgr version created before this check was added. */ #define THIS_LIB_VERSION \ (uint16_t)((SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER << 8) + \ SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER) #define VER_STR_LEN 12 #define VER_STR(n, str) (snprintf(str, VER_STR_LEN, "%d.%d", n >> 8, n & 0xff)) /* Socket interface to the QAT manager */ #define QATMGR_SOCKET "/run/qat/qatmgr.sock" /* Message types */ #define QATMGR_MSGTYPE_SECTION_GET 1 #define QATMGR_MSGTYPE_SECTION_PUT 2 #define QATMGR_MSGTYPE_NUM_DEVICES 3 #define QATMGR_MSGTYPE_DEVICE_INFO 4 #define QATMGR_MSGTYPE_DEVICE_ID 5 #define QATMGR_MSGTYPE_RESERVED 6 #define QATMGR_MSGTYPE_INSTANCE_INFO 7 #define QATMGR_MSGTYPE_INSTANCE_NAME 8 #define QATMGR_MSGTYPE_VFIO_FILE 9 #define QATMGR_MSGTYPE_NUM_PF_DEVS 10 #define QATMGR_MSGTYPE_PF_DEV_INFO 11 #define QATMGR_MSGTYPE_UNKNOWN 998 #define QATMGR_MSGTYPE_BAD 999 #define QATMGR_MAX_STRLEN 256 #define DEVICE_NAME_SIZE 64 #define VFIO_FILE_SIZE 32 #define MAX_INSTANCES 16 #define MAX_SERVICES 5 #define RPS_PER_4XXX_VF 4 #define INSTANCES_PER_DEVICE RPS_PER_4XXX_VF #define VM_PACKAGE_ID_NONE 0xFFFF #ifndef MAX #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) #endif #define MAX_PAYLOAD_SIZE \ MAX(sizeof(struct qatmgr_msg_req), sizeof(struct qatmgr_msg_rsp)) #define MAX_DEVS 512 /* Below definitions are dependent on kernel drivers for creating the same * mapping */ #define RING_PAIR_SHIFT 3 #define SVC_MASK 0x7 #define CFG_SERV_RING_PAIR_0_SHIFT 0 #define CFG_SERV_RING_PAIR_1_SHIFT 3 #define CFG_SERV_RING_PAIR_2_SHIFT 6 #define CFG_SERV_RING_PAIR_3_SHIFT 9 #ifndef ENABLE_DC #define DEFAULT_RING_TO_SRV_MAP \ (ASYM | SYM << CFG_SERV_RING_PAIR_1_SHIFT | \ ASYM << CFG_SERV_RING_PAIR_2_SHIFT | SYM << CFG_SERV_RING_PAIR_3_SHIFT) #else #define DEFAULT_RING_TO_SRV_MAP \ (COMP | DECOMP << CFG_SERV_RING_PAIR_1_SHIFT | \ COMP << CFG_SERV_RING_PAIR_2_SHIFT | \ DECOMP << CFG_SERV_RING_PAIR_3_SHIFT) #endif #define INTEL_VENDOR_ID 0x8086 #define MAX_NUM_CONCURRENT_REQUEST 512 #define PF_INFO_UNINITIALISED (-1) #define ADDITIONAL_BUF_LEN 2 #define STR_FORMAT_SPECIFIER_LEN 4 #define NUM_STR_FORMAT_SPECIFIER 2 extern char *device_names[]; extern int device_names_size; /* enum must be in alignment with the one defined by the kernel drivers */ enum cfg_service_type { UNUSED = 0, CRYPTO, COMP, SYM, ASYM, DECOMP, USED }; struct qatmgr_msg_hdr { uint16_t len; uint16_t version; uint16_t type; uint16_t filler; }; struct qatmgr_msg_req { struct qatmgr_msg_hdr hdr; union { /* QATMGR_MSGTYPE_SECTION_PUT */ /* QATMGR_MSGTYPE_NUM_DEVICES */ /* QATMGR_MSGTYPE_NUM_PF_DEVS */ /* No data */ /* QATMGR_MSYPE_SECTION_GET */ char name[QATMGR_MAX_STRLEN]; /* QATMGR_MSGTYPE_DEVICE_INFO */ /* QATMGR_MSGTYPE_DEVICE_ID */ /* QATMGR_MSGTYPE_VFIO_FILE */ /* QATMGR_MSGTYPE_PF_DEV_INFO */ uint16_t device_num; /* QATMGR_MSGTYPE_INSTANCE_INFO */ /* QATMGR_MSGTYPE_INSTANCE_NAME */ struct { enum serv_type type; uint16_t num; uint16_t device_num; } inst; }; }; struct ring_info { uint16_t accelid; uint16_t bank_number; uint16_t is_polled; uint16_t core_affinity; uint16_t num_concurrent_requests; uint16_t ring_tx; uint16_t ring_rx; }; struct fw_caps_qat { uint16_t comp_algos; uint16_t cksum_algos; uint32_t deflate_caps; uint16_t lz4_caps; uint16_t lz4s_caps; uint8_t is_fw_caps; }; struct qatmgr_msg_rsp { struct qatmgr_msg_hdr hdr; union { /* QATMGR_MSGTYPE_UNKNOWN */ /* QATMGR_MSGTYPE_SECTION_PUT */ /* No data */ /* QATMGR_MSGTYPE_BAD */ char error_text[QATMGR_MAX_STRLEN]; /* QATMGR_MSGTYPE_SECTION_GET */ /* QATMGR_MSGTYPE_INSTANCE_NAME */ char name[QATMGR_MAX_STRLEN]; union { /* QATMGR_MSGTYPE_VFIO_FILE*/ struct { int16_t fd; char name[QATMGR_MAX_STRLEN]; } vfio_file; }; /* QATMGR_MSGTYPE_NUM_DEVICES */ /* QATMGR_MSGTYPE_NUM_PF_DEVS */ uint16_t num_devices; /* QATMGR_MSGTYPE_DEVICE_INFO */ struct { uint16_t device_num; uint16_t device_type; uint16_t device_pci_id; uint32_t capability_mask; uint32_t extended_capabilities; struct fw_caps_qat fw_caps; uint16_t max_banks; uint16_t max_rings_per_bank; uint16_t arb_mask; uint16_t ring_mode; uint16_t services; int16_t pkg_id; uint16_t node_id; uint16_t num_cy_instances; uint16_t num_sym_instances; uint16_t num_asym_instances; uint16_t num_dc_instances; uint16_t num_decomp_instances; char device_name[DEVICE_NAME_SIZE]; } device_info; /* QATMGR_MSGTYPE_DEVICE_ID */ char device_id[QATMGR_MAX_STRLEN]; /* QATMGR_MSGTYPE_INSTANCE_INFO */ struct { union { struct { struct ring_info sym; struct ring_info asym; } cy; struct ring_info dc; struct ring_info decomp; }; /* For Sym, Asym, Dc or Decomp IsPolled */ int is_polled; } instance_info; /* QATMGR_MSGTYPE_PF_DEV_INFO */ icp_accel_pf_info_t pf_info; }; }; struct qatmgr_section_data { char section_name[QATMGR_MAX_STRLEN]; char base_name[QATMGR_MAX_STRLEN]; unsigned long assigned_id; int num_devices; struct qatmgr_device_data *device_data; }; struct qatmgr_device_data { char device_id[DEVICE_NAME_SIZE]; /* BDF or mdev uuid */ char device_file[DEVICE_NAME_SIZE]; /* /dev/vfio/ */ int group_fd; int accelid; char name[DEVICE_NAME_SIZE]; int node; int max_banks; int max_rings_per_bank; int arb_mask; uint16_t ring_mode; uint64_t accel_capabilities; uint64_t extended_capabilities; struct fw_caps_qat fw_caps; int device_type; uint16_t pci_id; /* PF index, describes which device it comes from */ int16_t pkg_id; uint16_t services; /* This includes all cy instances whether asym-only, sym-only or sym+asym */ int num_cy_inst; int num_sym_inst; int num_asym_inst; /* dc-only, decomp only or dc+decomp */ int num_dc_inst; int num_decomp_inst; struct qatmgr_instance_data *dc_instance_data; struct qatmgr_instance_data *decomp_instance_data; struct qatmgr_cy_instance_data *cy_instance_data; }; struct qatmgr_instance_data { char name[QATMGR_MAX_STRLEN]; int accelid; enum serv_type service_type; int bank_number; int ring_tx; int ring_rx; int is_polled; int num_concurrent_requests; int core_affinity; }; struct qatmgr_cy_instance_data { struct qatmgr_instance_data asym; struct qatmgr_instance_data sym; }; struct qatmgr_dev_data { unsigned bdf; union { char vfio_file[VFIO_FILE_SIZE]; }; int group_fd; unsigned devid; int numa_node; }; struct qatmgr_cpu_data { int idx; int *cpu; int cores_in_node; }; /* Cache of PF capabilities */ struct pf_capabilities { uint32_t pf; uint32_t ext_dc_caps; uint32_t capabilities; struct fw_caps fw_caps; uint32_t ring_to_svc_map; struct pf_capabilities *next; }; struct qatmgr_transport { int (*adf_build_sconfig)(void); bool (*qat_mgr_is_dev_available)(void); int (*adf_create_accel)(icp_accel_dev_t *accel_dev, int dev_id, struct qatmgr_transport *t_mgr); int (*adf_reinit_accel)(icp_accel_dev_t *accel_dev, int dev_id, struct qatmgr_transport *t_mgr); void (*adf_free_bundle)(struct adf_io_user_bundle *bundle); int (*adf_populate_bundle)(icp_accel_dev_t *accel_dev, struct adf_io_user_bundle *bundle); void (*adf_destroy_accel)(icp_accel_dev_t *accel_dev); CpaBoolean (*adf_io_poll_proxy_event)(Cpa32U *dev_id, enum adf_event *event); }; int qatmgr_query(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, uint16_t type); int qatmgr_open(void); int qatmgr_close(void); #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define BDF_DOMAIN(bdf) (bdf >> 16) #define BDF_BUS(bdf) (bdf >> 8 & 0xFF) #define BDF_DEV(bdf) (bdf >> 3 & 0x1F) #define BDF_FUN(bdf) (bdf & 0x7) /* This is the PF BDF shifted >>8 and used as an index for hashing and for * capability caching. */ #define PF(bdf) (BDF_BUS(bdf) + (BDF_DOMAIN(bdf) << 8)) #define GET_BDF(domain, bus, dev, func) \ ((domain << 16) + ((0xFF & bus) << 8) + ((0x1F & dev) << 3) + (0x07 & func)) void qat_mgr_cleanup_cfg(void); int qat_mgr_get_vfio_dev_list(unsigned *num_devices, struct qatmgr_dev_data *dev_list, const unsigned list_size, int keep_fd); int qat_mgr_vfio_build_data(const struct qatmgr_dev_data dev_list[], const int num_devices, int policy, int static_cfg); bool qat_mgr_is_vfio_dev_available(void); int handle_message(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, char **section_name, unsigned long id, int *index); int release_section(int index, unsigned long id, char *name, size_t name_len); int init_section_data_mutex(void); int destroy_section_data_mutex(void); int open_file_with_link_check(const char *filename, int flags); DIR *open_dir_with_link_check(const char *dirname); int is_qat_device(int device_id); int init_cpu_data(); void free_cpu_data(); struct pf_capabilities *find_pf_capabilities(uint32_t pf); void add_pf_capabilities(struct pf_capabilities *caps); char *qat_device_name(int device_id); int qat_device_type(int device_id); int get_num_instances(struct qatmgr_device_data *device, const unsigned devid, const uint32_t ring_to_svc_map, const uint16_t num_instances); int calculate_bank_number(const enum cfg_service_type instance_service, const int inst_idx, const uint32_t ring_to_svc_map, const uint16_t num_instances); int get_core_affinity(int node); void qatmgr_transport_init(void); void set_num_pfs(int32_t num_pf_devices); int32_t get_num_pfs(void); void set_num_section_data(int num_sec_data); void set_section_data(struct qatmgr_section_data *sec_data); struct qatmgr_transport *get_transport_mgr(void); int adf_vfio_build_sconfig(void); int adf_vfio_create_accel(icp_accel_dev_t *accel_dev, int dev_id, struct qatmgr_transport *t_mgr); int adf_vfio_reinit_accel(icp_accel_dev_t *accel_dev, int dev_id, struct qatmgr_transport *t_mgr); void adf_vfio_free_bundle(struct adf_io_user_bundle *bundle); int adf_vfio_populate_bundle(icp_accel_dev_t *accel_dev, struct adf_io_user_bundle *bundle); void adf_vfio_destroy_accel(icp_accel_dev_t *accel_dev); CpaBoolean adf_vfio_poll_proxy_event(Cpa32U *dev_id, enum adf_event *event); #endif /* QAT_MGR_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr_client.c000066400000000000000000000276301503624047500323600ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /****************************************************************************** * @file qat_mgr_client.c * * @description * Implements the qat manager client side. It provides functions to open * a connection to the manager and exchanging messages. *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "icp_platform.h" #include "qat_log.h" #include "qat_mgr.h" #define QAT_ENV_POLICY "QAT_POLICY" #define MAX_DEVS_NO_POLICY 6 #define MAX_DEVS_STATIC_CFG 256 static int qatmgr_sock = -1; static OsalMutex qatmgr_mutex; static struct qatmgr_transport transport_mgr = { 0 }; static int qat_transport_mgr_init = 0; /* * This array does not need to be global, it is only used locally to * adf_vfio_build_sconfig(). * However, it is global to avoid excessive use of stack memory and potential * stack-overflow in this function. */ static struct qatmgr_dev_data dev_list[MAX_DEVS]; static int qatmgr_socket_open(struct qatmgr_transport *t_mgr) { struct sockaddr_un sockaddr; int ret = 0; if (qatmgr_sock > 0) { qat_log(LOG_LEVEL_ERROR, "Failed to open socket\n"); return -1; } qatmgr_sock = socket(AF_UNIX, SOCK_STREAM, 0); if (qatmgr_sock < 0) { qat_log(LOG_LEVEL_ERROR, "Failed to create socket\n"); return -1; } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sun_family = AF_UNIX; snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s", QATMGR_SOCKET); ret = connect(qatmgr_sock, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); if (ret < 0) { qat_log(LOG_LEVEL_INFO, "Failed to connect to QAT manager\n"); close(qatmgr_sock); qatmgr_sock = -1; return -1; } if (OSAL_SUCCESS != osalMutexInit(&qatmgr_mutex)) { close(qatmgr_sock); qatmgr_sock = -1; return -1; } return 0; } int adf_vfio_build_sconfig(void) { int ret; char *env; long long devs = -1; unsigned n; int i, j; char *fin; env = getenv(QAT_ENV_POLICY); if (env) { devs = strtoll(env, &fin, 10); if (errno == ERANGE || *fin != 0 || devs < 0 || devs > MAX_DEVS) { qat_log(LOG_LEVEL_ERROR, "Invalid environment value \"%s\"\n", env); return -EINVAL; } } /* If QAT_POLICY is not set, reserve all devices but then use only * the first MAX_DEVS_NO_POLICY * If QAT_POLICY is set to 0, enumerate all devices without reserving * them (qat_mgr_build_data might fail when devices are opened) * if QAT_POLICY is set to >0, reserve the first n devices */ if (devs < 0) ret = qat_mgr_get_vfio_dev_list(&n, dev_list, MAX_DEVS, 1); else if (devs == 0) ret = qat_mgr_get_vfio_dev_list(&n, dev_list, MAX_DEVS, 0); else ret = qat_mgr_get_vfio_dev_list(&n, dev_list, devs, 1); if (ret) return ret; /* If no device is found return an error */ if (n == 0) { qat_log(LOG_LEVEL_ERROR, "No device found\n"); return -ENODEV; } /* Avoid using all devices if policy is not set */ if (n > MAX_DEVS_NO_POLICY && devs < 0) { for (i = 0, j = 0; i < n; i++) { if (dev_list[i].group_fd > 0 && j < MAX_DEVS_NO_POLICY) { j++; } else if (dev_list[i].group_fd > 0) { close(dev_list[i].group_fd); dev_list[i].group_fd = -1; } } devs = j; } for (i = 0; i < n; i++) { qat_log(LOG_LEVEL_INFO, "Device %d, %X, %04x:%02x:%02x.%01x\n", i, dev_list[i].bdf, BDF_DOMAIN(dev_list[i].bdf), BDF_BUS(dev_list[i].bdf), BDF_DEV(dev_list[i].bdf), BDF_FUN(dev_list[i].bdf)); } if (devs < 0) devs = n; if ((ret = qat_mgr_vfio_build_data(dev_list, n, devs, 1))) return ret; return 0; } int qatmgr_open(void) { int ret; struct qatmgr_transport *t_mgr = NULL; t_mgr = get_transport_mgr(); ret = qatmgr_socket_open(t_mgr); if (ret) { qat_log(LOG_LEVEL_INFO, "Build static configuration\n"); ret = t_mgr->adf_build_sconfig(); if (!ret) { /** mutex isn't needed for static path but client use * common qat_mgr_lib code which is used also by qatmgr * where mutex is needed * so it should be initialized to make lib working properly **/ ret = init_section_data_mutex(); } } return ret; } int qatmgr_close(void) { if (qatmgr_sock <= 0) { qat_log(LOG_LEVEL_DEBUG, "Cleanup static configuration\n"); qat_mgr_cleanup_cfg(); destroy_section_data_mutex(); return 0; } close(qatmgr_sock); qatmgr_sock = -1; if (osalMutexDestroy(&qatmgr_mutex) == OSAL_FAIL) return -1; return 0; } int qatmgr_query(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, uint16_t type) { int size_tx = 0; int size_rx = 0; ssize_t numchars; static int index = -1; pid_t pid = getpid(); static char *section_name = NULL; ICP_CHECK_FOR_NULL_PARAM_RET_CODE(req, -1); ICP_CHECK_FOR_NULL_PARAM_RET_CODE(rsp, -1); switch (type) { case QATMGR_MSGTYPE_SECTION_GET: case QATMGR_MSGTYPE_SECTION_PUT: size_tx = strnlen(req->name, sizeof(req->name) - 1) + 1; break; case QATMGR_MSGTYPE_NUM_DEVICES: case QATMGR_MSGTYPE_NUM_PF_DEVS: size_tx = 0; break; case QATMGR_MSGTYPE_DEVICE_INFO: case QATMGR_MSGTYPE_DEVICE_ID: case QATMGR_MSGTYPE_VFIO_FILE: case QATMGR_MSGTYPE_PF_DEV_INFO: size_tx = sizeof(req->device_num); break; case QATMGR_MSGTYPE_INSTANCE_INFO: case QATMGR_MSGTYPE_INSTANCE_NAME: size_tx = sizeof(req->inst); break; default: qat_log( LOG_LEVEL_ERROR, "Unknown qat manager message type %d\n", type); return -1; } req->hdr.type = type; req->hdr.version = THIS_LIB_VERSION; req->hdr.len = sizeof(req->hdr) + size_tx; if (qatmgr_sock < 0) return handle_message(req, rsp, §ion_name, pid, &index); osalMutexLock(&qatmgr_mutex, OSAL_WAIT_FOREVER); numchars = write(qatmgr_sock, req, req->hdr.len); if (numchars != req->hdr.len) { qat_log(LOG_LEVEL_ERROR, "Failed write to qatmgr socket %lu, expected %u\n", numchars, req->hdr.len); osalMutexUnlock(&qatmgr_mutex); return -1; } numchars = read(qatmgr_sock, rsp, sizeof(*rsp)); osalMutexUnlock(&qatmgr_mutex); if (rsp->hdr.version != THIS_LIB_VERSION) { char qatlib_ver_str[VER_STR_LEN]; char qatmgr_ver_str[VER_STR_LEN]; VER_STR(rsp->hdr.version, qatmgr_ver_str); VER_STR(THIS_LIB_VERSION, qatlib_ver_str); qat_log( LOG_LEVEL_ERROR, "This qatlib v%s received response from incompatible qatmgr v%s\n", qatlib_ver_str, qatmgr_ver_str); return -1; } if (rsp->hdr.type != type) { if (rsp->hdr.type == QATMGR_MSGTYPE_BAD) qat_log(LOG_LEVEL_ERROR, "Bad qatmgr response to request %d, %s\n", req->hdr.type, rsp->error_text); else qat_log(LOG_LEVEL_ERROR, "Unexpected qatmgr response %d to request %d\n", rsp->hdr.type, req->hdr.type); return -1; } switch (type) { case QATMGR_MSGTYPE_SECTION_GET: case QATMGR_MSGTYPE_INSTANCE_NAME: size_rx = strnlen(rsp->name, sizeof(rsp->name)); break; case QATMGR_MSGTYPE_VFIO_FILE: size_rx = sizeof(rsp->vfio_file.fd) + strnlen(rsp->vfio_file.name, sizeof(rsp->vfio_file.name)); break; case QATMGR_MSGTYPE_SECTION_PUT: size_rx = 0; break; case QATMGR_MSGTYPE_NUM_DEVICES: case QATMGR_MSGTYPE_NUM_PF_DEVS: size_rx = sizeof(rsp->num_devices); break; case QATMGR_MSGTYPE_DEVICE_INFO: size_rx = sizeof(rsp->device_info); break; case QATMGR_MSGTYPE_DEVICE_ID: size_rx = strnlen(rsp->device_id, sizeof(rsp->device_id)); break; case QATMGR_MSGTYPE_PF_DEV_INFO: size_rx = sizeof(rsp->pf_info); break; case QATMGR_MSGTYPE_INSTANCE_INFO: size_rx = sizeof(rsp->instance_info); break; default: qat_log( LOG_LEVEL_ERROR, "Unknown qat manager message type %d\n", type); return -1; } if (numchars < sizeof(rsp->hdr) + size_rx) { qat_log(LOG_LEVEL_ERROR, "Failed to read from qatmgr socket, %lu expected %lu\n", numchars, sizeof(rsp->hdr) + size_rx); return -1; } return 0; } void qatmgr_transport_init(void) { qat_transport_mgr_init = 1; transport_mgr.adf_build_sconfig = adf_vfio_build_sconfig; transport_mgr.qat_mgr_is_dev_available = qat_mgr_is_vfio_dev_available; transport_mgr.adf_create_accel = adf_vfio_create_accel; transport_mgr.adf_reinit_accel = adf_vfio_reinit_accel; transport_mgr.adf_free_bundle = adf_vfio_free_bundle; transport_mgr.adf_populate_bundle = adf_vfio_populate_bundle; transport_mgr.adf_destroy_accel = adf_vfio_destroy_accel; transport_mgr.adf_io_poll_proxy_event = adf_vfio_poll_proxy_event; } struct qatmgr_transport *get_transport_mgr(void) { if (!qat_transport_mgr_init) qatmgr_transport_init(); return &transport_mgr; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/qat_mgr_lib.c000066400000000000000000001347151503624047500316530ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #include #include #include "icp_platform.h" #include "qat_log.h" #include "qat_mgr.h" #include "adf_vfio_pf.h" #include #define QAT_4XXXVF_DEVICE_ID 0x4941 #define QAT_4XXX_DEVICE_ID 0x4940 #define QAT_401XXVF_DEVICE_ID 0x4943 #define QAT_402XXVF_DEVICE_ID 0x4945 #define QAT_402XX_DEVICE_ID 0x4944 #define QAT_420XXVF_DEVICE_ID 0x4947 #define QAT_420XX_DEVICE_ID 0x4946 #define ADDITIONAL_BUF_LEN 2 #define STATIC static STATIC struct qatmgr_section_data *section_data = NULL; STATIC int num_section_data = 0; icp_accel_pf_info_t pf_data[ADF_MAX_PF_DEVICES] = { 0 }; STATIC int32_t num_pfs = PF_INFO_UNINITIALISED; static struct qatmgr_cpu_data *cpu_data = NULL; static int num_nodes = 0; static int num_cpus = 0; STATIC pthread_mutex_t section_data_mutex; /* message name within array should live at index determined by its * allocated memory */ static const char *qatmgr_msgtype_str[] = { "QATMGR_MSGTYPE_UNKNOWN", /* string for unknown msg*/ "QATMGR_MSGTYPE_SECTION_GET", /* string for get section msg*/ "QATMGR_MSGTYPE_SECTION_PUT", /* string for put section msg*/ "QATMGR_MSGTYPE_NUM_DEVICES", /* string for num devices msg*/ "QATMGR_MSGTYPE_DEVICE_INFO", /* string for device info msg*/ "QATMGR_MSGTYPE_DEVICE_ID", /* string for device id msg*/ "QATMGR_MSGTYPE_RESERVED", /* string for reserved msg*/ "QATMGR_MSGTYPE_INSTANCE_INFO", /* string for instance info msg*/ "QATMGR_MSGTYPE_INSTANCE_NAME", /* string for instance name msg*/ "QATMGR_MSGTYPE_VFIO_FILE", /* string for vfio file path msg*/ "QATMGR_MSGTYPE_NUM_PF_DEVS ", /* string for pf number msg*/ "QATMGR_MSGTYPE_PF_DEV_INFO", /* string for pf device info msg*/ }; #define QATMGR_MSGTYPES_STR_MAX \ (sizeof(qatmgr_msgtype_str) / sizeof(qatmgr_msgtype_str[0]) - 1) char *device_names[] = { "4xxx", "420xx" }; int device_names_size = sizeof(device_names) / sizeof(device_names[0]); struct pf_capabilities *pf_capabilities_head = NULL; int32_t get_num_pfs(void) { return num_pfs; } void set_num_pfs(int32_t num_pf_devices) { num_pfs = num_pf_devices; } void set_num_section_data(int num_sec_data) { num_section_data = num_sec_data; } void set_section_data(struct qatmgr_section_data *sec_data) { section_data = sec_data; } struct pf_capabilities *find_pf_capabilities(uint32_t pf) { struct pf_capabilities *current = pf_capabilities_head; while (current) { if (current->pf == pf) return current; current = current->next; } return NULL; } void add_pf_capabilities(struct pf_capabilities *caps) { caps->next = pf_capabilities_head; pf_capabilities_head = caps; } static void cleanup_capabilities_cache() { struct pf_capabilities *current = pf_capabilities_head; struct pf_capabilities *next; while (current) { next = current->next; free(current); current = next; } pf_capabilities_head = NULL; } int is_qat_device(int device_id) { switch (device_id) { case QAT_4XXXVF_DEVICE_ID: case QAT_4XXX_DEVICE_ID: case QAT_401XXVF_DEVICE_ID: case QAT_402XXVF_DEVICE_ID: case QAT_402XX_DEVICE_ID: case QAT_420XXVF_DEVICE_ID: case QAT_420XX_DEVICE_ID: return 1; default: return 0; } return 0; } int qat_device_type(int device_id) { switch (device_id) { case QAT_4XXXVF_DEVICE_ID: case QAT_401XXVF_DEVICE_ID: case QAT_402XXVF_DEVICE_ID: return DEVICE_4XXXVF; case QAT_420XXVF_DEVICE_ID: return DEVICE_420XXVF; case QAT_420XX_DEVICE_ID: return DEVICE_420XX; case QAT_4XXX_DEVICE_ID: case QAT_402XX_DEVICE_ID: return DEVICE_4XXX; default: return 0; } return 0; } char *qat_device_name(int device_id) { switch (device_id) { case QAT_4XXXVF_DEVICE_ID: return "4xxxvf"; case QAT_401XXVF_DEVICE_ID: return "401xxvf"; case QAT_402XXVF_DEVICE_ID: return "402xxvf"; case QAT_420XXVF_DEVICE_ID: return "420xxvf"; case QAT_420XX_DEVICE_ID: return "420xx"; case QAT_4XXX_DEVICE_ID: return "4xxx"; case QAT_402XX_DEVICE_ID: return "402xx"; default: return "unknown"; } } int init_section_data_mutex() { if (pthread_mutex_init(§ion_data_mutex, NULL) != 0) { return -1; } return 0; } int destroy_section_data_mutex() { if (pthread_mutex_destroy(§ion_data_mutex)) { return -1; } return 0; } void free_cpu_data() { int i; if (cpu_data) { for (i = 0; i < num_nodes; i++) { if (cpu_data[i].cpu) { free(cpu_data[i].cpu); cpu_data[i].cpu = NULL; cpu_data[i].idx = 0; cpu_data[i].cores_in_node = 0; } } free(cpu_data); cpu_data = NULL; num_nodes = 0; } } void qat_mgr_cleanup_cfg(void) { /* Allocated memory: section data[num_section_data - 1] section_data[i].device_data[section_data[i].num_devices - 1] section_data[i].device_data[j].xx_instance_data */ struct qatmgr_section_data *section; struct qatmgr_device_data *device; int i, j; if (section_data) { section = section_data; for (i = 0; i < num_section_data; i++, section++) { device = section->device_data; if (!device) continue; for (j = 0; j < section->num_devices; j++, device++) { if (device->dc_instance_data) { free(device->dc_instance_data); device->dc_instance_data = NULL; } if (device->decomp_instance_data) { free(device->decomp_instance_data); device->decomp_instance_data = NULL; } if (device->cy_instance_data) { free(device->cy_instance_data); device->cy_instance_data = NULL; } } free(section_data[i].device_data); section_data[i].device_data = NULL; } free(section_data); section_data = NULL; num_section_data = 0; } free_cpu_data(); cleanup_capabilities_cache(); } int open_file_with_link_check(const char *filename, int flags) { int fd; struct stat buf; fd = open(filename, flags | O_NOFOLLOW); if (fd < 0) { qat_log(LOG_LEVEL_INFO, "Open failed on %s\n", filename); return fd; } if (0 != fstat(fd, &buf)) { qat_log(LOG_LEVEL_ERROR, "Stat failed on %s\n", filename); close(fd); fd = -1; return fd; } if (buf.st_nlink > 1) { qat_log(LOG_LEVEL_ERROR, "Detected hardlink for %s\n", filename); close(fd); fd = -1; return fd; } return fd; } DIR *open_dir_with_link_check(const char *dirname) { int fd; DIR *dir; fd = open(dirname, O_RDONLY | O_DIRECTORY); if (fd < 0) { qat_log(LOG_LEVEL_ERROR, "1: Cannot open %s\n", dirname); return NULL; } dir = fdopendir(fd); if (NULL == dir) { close(fd); qat_log(LOG_LEVEL_ERROR, "2: Cannot open %s\n", dirname); return NULL; } return dir; } /* Calculate bank number for different device configurations. Note, this depends on corresponding mapping done by kernel driver. */ int calculate_bank_number(const enum cfg_service_type instance_service, const int inst_idx, const uint32_t ring_to_svc_map, const uint16_t num_instances) { int i, serv_type, serv_found = 0; /* Search for the matching service type in ring_to_svc_map */ for (i = 0; i < num_instances; i++) { serv_type = (ring_to_svc_map >> (i * RING_PAIR_SHIFT)) & SVC_MASK; if (instance_service == serv_type) { if (serv_found == inst_idx) { return i; } serv_found++; } } return -1; } static int init_cpu_node(int node) { int i = 0; for (i = 0; i < num_cpus; i++) { cpu_data[node].cpu[i] = i; } cpu_data[node].cores_in_node = num_cpus; cpu_data[node].idx = 0; return 0; } static int init_cpu_node_numa(int node) { int i = 0; int j = 0; int err = 0; struct bitmask *cpus; cpus = numa_allocate_cpumask(); if (!cpus) { return -1; } err = numa_node_to_cpus(node, cpus); if (err) { numa_bitmask_free(cpus); return -1; } for (i = 0; i < cpus->size; i++) { if (numa_bitmask_isbitset(cpus, i)) { cpu_data[node].cpu[j++] = i; } } cpu_data[node].cores_in_node = j; cpu_data[node].idx = 0; numa_bitmask_free(cpus); return 0; } static int init_cpu_node_data(int node) { int ret; cpu_data[node].cpu = calloc(num_cpus, sizeof(int)); if (!cpu_data[node].cpu) { return -ENOMEM; } if (num_nodes > 1) { ret = init_cpu_node_numa(node); } else { ret = init_cpu_node(node); } return ret; } /** * Get next available cpu for given node. */ int get_core_affinity(int node) { int cpu = 0; int index = 0; int cores_in_node = 0; index = cpu_data[node].idx; cores_in_node = cpu_data[node].cores_in_node; cpu = cpu_data[node].cpu[index]; cpu_data[node].idx = (index + 1) % cores_in_node; return cpu; } int init_cpu_data() { int ret = 0; int i; num_cpus = get_nprocs(); if (numa_available() < 0) { num_nodes = 1; qat_log(LOG_LEVEL_DEBUG, "No NUMA nodes detected.\n"); } else { num_nodes = numa_max_node() + 1; qat_log(LOG_LEVEL_DEBUG, "Detected %d NUMA nodes.\n", num_nodes); } cpu_data = calloc(num_nodes, sizeof(struct qatmgr_cpu_data)); if (!cpu_data) { qat_log(LOG_LEVEL_ERROR, "Unable to allocate cpu mapping data.\n"); return -ENOMEM; } for (i = 0; i < num_nodes; i++) { ret = init_cpu_node_data(i); if (ret) { qat_log(LOG_LEVEL_ERROR, "Unable to initialize cpu mapping data.\n"); free_cpu_data(); return -EAGAIN; } } return 0; } int get_num_instances(struct qatmgr_device_data *device, const unsigned devid, const uint32_t ring_to_svc_map, const uint16_t num_instances) { int serv_type, i; for (i = 0; i < num_instances; i++) { serv_type = (ring_to_svc_map >> (i * RING_PAIR_SHIFT)) & SVC_MASK; switch (serv_type) { case SYM: if (device->accel_capabilities & ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) { device->services |= SERV_TYPE_SYM; device->num_sym_inst++; } break; case ASYM: if (device->accel_capabilities & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) { device->services |= SERV_TYPE_ASYM; device->num_asym_inst++; } break; case COMP: if (device->accel_capabilities & ICP_ACCEL_CAPABILITIES_COMPRESSION) { device->services |= SERV_TYPE_DC; device->num_dc_inst++; } break; case DECOMP: if (device->accel_capabilities & ICP_ACCEL_CAPABILITIES_COMPRESSION) { device->services |= SERV_TYPE_DECOMP; device->num_decomp_inst++; } break; case UNUSED: break; default: return -1; } } /* The num_cy_inst variable corresponds to the number of SYM or ASYM * instances if only one of those services is enabled. If both services are * enabled and the number of SYM and ASYM instances is equal, as in the * "sym;asym" scenario, num_cy_inst will reflect both the number of SYM and * ASYM instances. However, this logic is limited in the 3 concurrent * service scenarios introduced in Gen6, where "sym;asym;dc" and * "sym;asym;decomp" configurations enable an unequal number of SYM and ASYM * instances. This scenario is not supported with the current QATlib * implementation. Therefore, in these cases, num_cy_instances is assigned * the minimum value from the number of SYM and ASYM instances, and the * additional ASYM instance is not used. */ if (device->num_sym_inst == 0) device->num_cy_inst = device->num_asym_inst; else if (device->num_asym_inst == 0) device->num_cy_inst = device->num_sym_inst; else device->num_cy_inst = (device->num_sym_inst > device->num_asym_inst) ? device->num_sym_inst : device->num_asym_inst; return 0; } STATIC void dump_message(void *ptr, char *text) { struct qatmgr_msg_req *req = ptr; int payload_size; uint8_t *payload; int i; if (debug_level < 2) return; ICP_CHECK_FOR_NULL_PARAM_VOID(ptr); ICP_CHECK_FOR_NULL_PARAM_VOID(text); printf("%s\n", text); printf("Message type %hu\n", (unsigned short int)(req->hdr.type)); if (req->hdr.type > 0 && req->hdr.type <= QATMGR_MSGTYPES_STR_MAX) printf("Message name %s\n", qatmgr_msgtype_str[req->hdr.type]); printf(" length %d\n", req->hdr.len); payload_size = req->hdr.len - sizeof(req->hdr); payload = (uint8_t *)req + sizeof(req->hdr); if (payload_size > 0 && payload_size <= MAX_PAYLOAD_SIZE) { printf(" Payload: "); for (i = 0; i < payload_size; i++, payload++) { printf("%02X ", *payload); if (i % 16 == 0) printf("\n"); } printf("\n"); } else { qat_log( LOG_LEVEL_ERROR, "Message payload size (%d) out of range. Max payload size is %lu\n", payload_size, MAX_PAYLOAD_SIZE); } } #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) static void err_msg(struct qatmgr_msg_rsp *rsp, char *text) { ICP_CHECK_FOR_NULL_PARAM_VOID(rsp); ICP_CHECK_FOR_NULL_PARAM_VOID(text); rsp->hdr.type = QATMGR_MSGTYPE_BAD; rsp->hdr.version = THIS_LIB_VERSION; snprintf(rsp->error_text, sizeof(rsp->error_text), "%s", text); rsp->hdr.len = sizeof(rsp->hdr) + ICP_ARRAY_STRLEN_SANITIZE(rsp->error_text) + 1; } static void build_msg_header(struct qatmgr_msg_rsp *rsp, int type, int payload_size) { ICP_CHECK_FOR_NULL_PARAM_VOID(rsp); rsp->hdr.type = type; rsp->hdr.version = THIS_LIB_VERSION; rsp->hdr.len = sizeof(rsp->hdr) + payload_size; } STATIC int handle_get_num_devices(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, int index) { struct qatmgr_section_data *section; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); if (req->hdr.len != sizeof(req->hdr)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (index < 0 || index >= num_section_data) { qat_log(LOG_LEVEL_ERROR, "Bad index\n"); err_msg(rsp, "Invalid index"); return -1; } section = section_data + index; rsp->num_devices = section->num_devices; build_msg_header(rsp, QATMGR_MSGTYPE_NUM_DEVICES, sizeof(rsp->num_devices)); dump_message(rsp, "Response"); return 0; } STATIC int handle_get_device_info(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, int index) { struct qatmgr_section_data *section; unsigned device_num; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); if (req->hdr.len != sizeof(req->hdr) + sizeof(req->device_num)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (index < 0 || index >= num_section_data) { qat_log(LOG_LEVEL_ERROR, "Bad index\n"); err_msg(rsp, "Invalid index"); return -1; } section = section_data + index; device_num = req->device_num; if (device_num >= section->num_devices) { qat_log(LOG_LEVEL_ERROR, "Invalid device %d >= %d\n", device_num, section->num_devices); err_msg(rsp, "Invalid device number"); return -1; } rsp->device_info.device_num = device_num; rsp->device_info.device_type = section->device_data[device_num].device_type; snprintf(rsp->device_info.device_name, sizeof(rsp->device_info.device_name), "%s", section->device_data[device_num].name); rsp->device_info.capability_mask = section->device_data[device_num].accel_capabilities; rsp->device_info.extended_capabilities = section->device_data[device_num].extended_capabilities; rsp->device_info.max_banks = section->device_data[device_num].max_banks; rsp->device_info.max_rings_per_bank = section->device_data[device_num].max_rings_per_bank; rsp->device_info.arb_mask = section->device_data[device_num].arb_mask; rsp->device_info.ring_mode = section->device_data[device_num].ring_mode; rsp->device_info.services = section->device_data[device_num].services; rsp->device_info.pkg_id = section->device_data[device_num].pkg_id; rsp->device_info.node_id = section->device_data[device_num].node; rsp->device_info.device_pci_id = section->device_data[device_num].pci_id; rsp->device_info.num_cy_instances = section->device_data[device_num].num_cy_inst; rsp->device_info.num_sym_instances = section->device_data[device_num].num_sym_inst; rsp->device_info.num_asym_instances = section->device_data[device_num].num_asym_inst; rsp->device_info.num_dc_instances = section->device_data[device_num].num_dc_inst; rsp->device_info.num_decomp_instances = section->device_data[device_num].num_decomp_inst; if (section->device_data[device_num].fw_caps.is_fw_caps) { rsp->device_info.fw_caps.comp_algos = section->device_data[device_num].fw_caps.comp_algos; rsp->device_info.fw_caps.cksum_algos = section->device_data[device_num].fw_caps.cksum_algos; rsp->device_info.fw_caps.deflate_caps = section->device_data[device_num].fw_caps.deflate_caps; rsp->device_info.fw_caps.lz4_caps = section->device_data[device_num].fw_caps.lz4_caps; rsp->device_info.fw_caps.lz4s_caps = section->device_data[device_num].fw_caps.lz4s_caps; rsp->device_info.fw_caps.is_fw_caps = 1; } build_msg_header(rsp, QATMGR_MSGTYPE_DEVICE_INFO, sizeof(rsp->device_info)); dump_message(rsp, "Response"); return 0; } STATIC int handle_get_device_id(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, int index) { struct qatmgr_section_data *section; struct qatmgr_device_data *device_data; unsigned device_num; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); if (req->hdr.len != sizeof(req->hdr) + sizeof(req->device_num)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (index < 0 || index >= num_section_data) { qat_log(LOG_LEVEL_ERROR, "Bad index\n"); err_msg(rsp, "Invalid index"); return -1; } section = section_data + index; device_num = req->device_num; if (device_num >= section->num_devices) { qat_log(LOG_LEVEL_ERROR, "Invalid device %d\n", device_num); err_msg(rsp, "Invalid device number"); return -1; } device_data = section->device_data; device_data += device_num; rsp->hdr.type = QATMGR_MSGTYPE_DEVICE_ID; rsp->hdr.version = THIS_LIB_VERSION; snprintf( rsp->device_id, sizeof(rsp->device_id), "%s", device_data->device_id); build_msg_header(rsp, QATMGR_MSGTYPE_DEVICE_ID, ICP_ARRAY_STRLEN_SANITIZE(rsp->device_id) + 1); dump_message(rsp, "Response"); return 0; } static int handle_get_vfio_name(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, int index) { struct qatmgr_section_data *section; struct qatmgr_device_data *device_data; unsigned device_num; size_t len; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); if (req->hdr.len != sizeof(req->hdr) + sizeof(req->device_num)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (index < 0 || index >= num_section_data) { qat_log(LOG_LEVEL_ERROR, "Bad index\n"); err_msg(rsp, "Invalid index"); return -1; } section = section_data + index; device_num = req->device_num; if (device_num >= section->num_devices) { qat_log(LOG_LEVEL_ERROR, "Invalid device %d\n", device_num); err_msg(rsp, "Invalid device number"); return -1; } device_data = section->device_data; device_data += device_num; rsp->hdr.type = QATMGR_MSGTYPE_VFIO_FILE; rsp->hdr.version = THIS_LIB_VERSION; rsp->vfio_file.fd = device_data->group_fd; snprintf(rsp->vfio_file.name, sizeof(rsp->vfio_file.name), "%.*s", DEVICE_NAME_SIZE, device_data->device_file); len = ICP_ARRAY_STRLEN_SANITIZE(rsp->vfio_file.name); build_msg_header( rsp, QATMGR_MSGTYPE_VFIO_FILE, sizeof(rsp->vfio_file.fd) + len + 1); dump_message(rsp, "Response"); return 0; } STATIC int handle_get_instance_name(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, int index) { struct qatmgr_section_data *section; struct qatmgr_device_data *device; int instance_type; int instance_num; int device_num; char *inst_name; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); if (req->hdr.len != sizeof(req->hdr) + sizeof(req->inst)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (index < 0 || index >= num_section_data) { qat_log(LOG_LEVEL_ERROR, "Bad index\n"); err_msg(rsp, "Invalid index"); return -1; } section = section_data + index; instance_type = req->inst.type; instance_num = req->inst.num; device_num = req->inst.device_num; device = section->device_data + device_num; if (device_num >= section->num_devices) { qat_log(LOG_LEVEL_ERROR, "Invalid device number %d for section %d\n", device_num, index); err_msg(rsp, "Invalid device number"); return -1; } if (instance_type == SERV_TYPE_DC) { if (instance_num >= device->num_dc_inst) { qat_log(LOG_LEVEL_ERROR, "Bad dc instance number %d for device %d\n", instance_num, device_num); err_msg(rsp, "Invalid DC instance number"); return -1; } snprintf(rsp->name, sizeof(rsp->name), "%s", device->dc_instance_data[instance_num].name); build_msg_header(rsp, QATMGR_MSGTYPE_INSTANCE_NAME, ICP_ARRAY_STRLEN_SANITIZE(rsp->name) + 1); } else if (instance_type == SERV_TYPE_DECOMP) { if (instance_num >= device->num_decomp_inst) { qat_log(LOG_LEVEL_ERROR, "Bad decomp instance number %d for device %d\n", instance_num, device_num); err_msg(rsp, "Invalid Decomp instance number"); return -1; } snprintf(rsp->name, sizeof(rsp->name), "%s", device->decomp_instance_data[instance_num].name); build_msg_header(rsp, QATMGR_MSGTYPE_INSTANCE_NAME, ICP_ARRAY_STRLEN_SANITIZE(rsp->name) + 1); } else if (instance_type == SERV_TYPE_CY) { if (instance_num >= device->num_cy_inst) { qat_log(LOG_LEVEL_ERROR, "Bad cy instance number %d for device %d\n", instance_num, device_num); err_msg(rsp, "Invalid CY instance number"); return -1; } /* When CY only or SYM;ASYM only is enabled, cpaCyInstanceGetInfo2() * will return the same instance name for SYM and ASYM. * SERV_TYPE_CY_DECOMP and SERV_TYPE_CY_DC do not apply to this logic, * because we have 2 CY instances created, but only 1 of them will have * SYM info. In this case we have to get the instance name from ASYM * part of both CY instances. */ switch (device->services) { case SERV_TYPE_ASYM: case SERV_TYPE_ASYM_DC: case SERV_TYPE_ASYM_DECOMP: case SERV_TYPE_CY_DC: case SERV_TYPE_CY_DECOMP: case SERV_TYPE_ASYM_DC_DECOMP: inst_name = device->cy_instance_data[instance_num].asym.name; break; default: inst_name = device->cy_instance_data[instance_num].sym.name; } snprintf(rsp->name, sizeof(rsp->name), "%s", inst_name); build_msg_header(rsp, QATMGR_MSGTYPE_INSTANCE_NAME, ICP_ARRAY_STRLEN_SANITIZE(rsp->name) + 1); } else if (instance_type == SERV_TYPE_SYM) { if (instance_num >= device->num_sym_inst) { qat_log(LOG_LEVEL_ERROR, "Bad cy.sym instance number %d for device %d\n", instance_num, device_num); err_msg(rsp, "Invalid SYM instance number"); return -1; } snprintf(rsp->name, sizeof(rsp->name), "%s", device->cy_instance_data[instance_num].sym.name); build_msg_header(rsp, QATMGR_MSGTYPE_INSTANCE_NAME, ICP_ARRAY_STRLEN_SANITIZE(rsp->name) + 1); } else if (instance_type == SERV_TYPE_ASYM) { if (instance_num >= device->num_asym_inst) { qat_log(LOG_LEVEL_ERROR, "Bad cy.asym instance number %d for device %d\n", instance_num, device_num); err_msg(rsp, "Invalid ASYM instance number"); return -1; } snprintf(rsp->name, sizeof(rsp->name), "%s", device->cy_instance_data[instance_num].asym.name); build_msg_header(rsp, QATMGR_MSGTYPE_INSTANCE_NAME, ICP_ARRAY_STRLEN_SANITIZE(rsp->name) + 1); } else { qat_log( LOG_LEVEL_ERROR, "unsupported instance type %d\n", instance_type); err_msg(rsp, "Unknown instance type"); return -1; } dump_message(rsp, "Response"); return 0; } /* Function to populate instance data */ static void populate_instance_info(struct qatmgr_instance_data *instance_data, struct ring_info *info) { info->accelid = instance_data->accelid; info->bank_number = instance_data->bank_number; info->is_polled = instance_data->is_polled; info->core_affinity = instance_data->core_affinity; info->num_concurrent_requests = instance_data->num_concurrent_requests; info->ring_tx = instance_data->ring_tx; info->ring_rx = instance_data->ring_rx; } STATIC int handle_get_instance_info(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, int index) { struct qatmgr_section_data *section; struct qatmgr_device_data *device; struct qatmgr_instance_data *instance_data; struct qatmgr_cy_instance_data *cy_instance_data; int instance_type; int instance_num; int device_num; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); if (req->hdr.len != sizeof(req->hdr) + sizeof(req->inst)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (index < 0 || index >= num_section_data) { qat_log(LOG_LEVEL_ERROR, "Bad index\n"); err_msg(rsp, "Invalid index"); return -1; } section = section_data + index; instance_type = req->inst.type; instance_num = req->inst.num; device_num = req->inst.device_num; device = section->device_data + device_num; if (device_num >= section->num_devices) { qat_log(LOG_LEVEL_ERROR, "Invalid device number %d for section %d\n", device_num, index); err_msg(rsp, "Invalid device number"); return -1; } switch (instance_type) { case SERV_TYPE_DC: if (instance_num >= device->num_dc_inst) { qat_log(LOG_LEVEL_ERROR, "Bad dc instance number %d for device %d\n", instance_num, device_num); err_msg(rsp, "Invalid dc instance number"); return -1; } instance_data = device->dc_instance_data + instance_num; populate_instance_info(instance_data, &rsp->instance_info.dc); break; case SERV_TYPE_DECOMP: if (instance_num >= device->num_decomp_inst) { qat_log(LOG_LEVEL_ERROR, "Bad decomp instance number %d for device %d\n", instance_num, device_num); err_msg(rsp, "Invalid decomp instance number"); return -1; } instance_data = device->decomp_instance_data + instance_num; populate_instance_info(instance_data, &rsp->instance_info.decomp); break; case SERV_TYPE_CY: if (instance_num >= device->num_cy_inst) { qat_log(LOG_LEVEL_ERROR, "Bad cy instance number %d for section %d\n", instance_num, index); err_msg(rsp, "Invalid cy instance number"); return -1; } cy_instance_data = device->cy_instance_data + instance_num; /* for CyxIsPolled CY only and SYM only this param is taken from sym * instance but for ASYM only from asym service. */ switch (device->services) { case SERV_TYPE_ASYM: case SERV_TYPE_ASYM_DC: case SERV_TYPE_ASYM_DECOMP: case SERV_TYPE_CY_DC: case SERV_TYPE_CY_DECOMP: case SERV_TYPE_ASYM_DC_DECOMP: rsp->instance_info.is_polled = cy_instance_data->asym.is_polled; break; default: rsp->instance_info.is_polled = cy_instance_data->sym.is_polled; } instance_data = &cy_instance_data->sym; populate_instance_info(instance_data, &rsp->instance_info.cy.sym); instance_data = &cy_instance_data->asym; populate_instance_info(instance_data, &rsp->instance_info.cy.asym); break; case SERV_TYPE_SYM: if (instance_num >= device->num_sym_inst) { qat_log(LOG_LEVEL_ERROR, "Bad cy.sym instance number %d for section %d\n", instance_num, index); err_msg(rsp, "Invalid sym instance number"); return -1; } cy_instance_data = device->cy_instance_data + instance_num; instance_data = &cy_instance_data->sym; populate_instance_info(instance_data, &rsp->instance_info.cy.sym); break; case SERV_TYPE_ASYM: if (instance_num >= device->num_asym_inst) { qat_log(LOG_LEVEL_ERROR, "Bad cy.asym instance number %d for section %d\n", instance_num, index); err_msg(rsp, "Invalid asym instance number"); return -1; } cy_instance_data = device->cy_instance_data + instance_num; instance_data = &cy_instance_data->asym; populate_instance_info(instance_data, &rsp->instance_info.cy.asym); break; default: qat_log(LOG_LEVEL_ERROR, "Unsupported instance type %d\n", instance_type); err_msg(rsp, "Unknown instance type"); return -1; } build_msg_header( rsp, QATMGR_MSGTYPE_INSTANCE_INFO, sizeof(rsp->instance_info)); dump_message(rsp, "Response"); return 0; } int release_section(int index, unsigned long id, char *name, size_t name_len) { ICP_CHECK_FOR_NULL_PARAM(name); /* * In standalone mode, id is the process id of the client. In managed * mode, id is actually the thread id of the qatmgr thread handling the * socket for a specific client process, so it can be considered a proxy * for the client process id. */ if (index < 0 || index >= num_section_data) { qat_log(LOG_LEVEL_ERROR, "Invalid section index %d for process %lu, section %s\n", index, id, name); return -1; } if (name_len != ICP_ARRAY_STRLEN_SANITIZE(section_data[index].section_name) || ICP_STRNCMP_CONST(name, section_data[index].section_name)) { qat_log(LOG_LEVEL_ERROR, "Incorrect section name %s, expected %s\n", name, section_data[index].section_name); return -1; } if (section_data[index].assigned_id != id) { qat_log(LOG_LEVEL_ERROR, "Incorrect process %lu for section %s. Expected %lu\n", id, name, section_data[index].assigned_id); return -1; } qat_log(LOG_LEVEL_DEBUG, "Released section %s\n", name); section_data[index].assigned_id = 0; return 0; } STATIC int get_section(unsigned long id, char **derived_section_name) { int i; int assigned = 0; if (pthread_mutex_lock(§ion_data_mutex)) { qat_log(LOG_LEVEL_ERROR, "Unable to lock section_data mutex\n"); return -2; } for (i = 0; i < num_section_data; i++) { if (section_data[i].assigned_id) continue; /* Assigned to another process */ section_data[i].assigned_id = id; assigned = 1; break; } if (pthread_mutex_unlock(§ion_data_mutex)) { qat_log(LOG_LEVEL_ERROR, "Unable to unlock section_data mutex\n"); return -2; } if (assigned) { qat_log( LOG_LEVEL_DEBUG, "Got section %s\n", section_data[i].section_name); if (derived_section_name) *derived_section_name = section_data[i].section_name; return i; } return -1; } STATIC int handle_section_request(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, char **section_name, unsigned long id_to_assign, int *index) { int sec; char *derived_name; static pid_t pid = 0; int name_buf_size; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); ICP_CHECK_FOR_NULL_PARAM(index); if (req->hdr.len != sizeof(req->hdr) + ICP_ARRAY_STRLEN_SANITIZE(req->name) + 1) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (pid != getpid()) { pid = getpid(); *index = -1; if (*section_name) free(*section_name); *section_name = NULL; } if (*section_name != NULL || *index != -1) { qat_log(LOG_LEVEL_ERROR, "Section already allocated\n"); err_msg(rsp, "Section already allocated"); return -1; } sec = get_section(id_to_assign, &derived_name); if (sec < 0) { qat_log(LOG_LEVEL_ERROR, "Couldn't get section %s\n", req->name); if (sec == -2) err_msg(rsp, "Internal error"); else err_msg(rsp, "No section available"); return sec; } *index = sec; rsp->hdr.type = QATMGR_MSGTYPE_SECTION_GET; rsp->hdr.version = THIS_LIB_VERSION; snprintf(rsp->name, sizeof(rsp->name), "%s", derived_name); rsp->hdr.len = sizeof(rsp->hdr) + ICP_ARRAY_STRLEN_SANITIZE(rsp->name) + 1; name_buf_size = ICP_ARRAY_STRLEN_SANITIZE(rsp->name) + ADDITIONAL_BUF_LEN; *section_name = malloc(name_buf_size); if (!*section_name) { qat_log(LOG_LEVEL_ERROR, "Memory allocation failed\n"); err_msg(rsp, "malloc failed"); return -1; } qat_log(LOG_LEVEL_DEBUG, "Allocated section %s at %p\n", rsp->name, *section_name); if (name_buf_size < strnlen(rsp->name, sizeof(rsp->name))) { qat_log(LOG_LEVEL_ERROR, "Failed to copy section name\n"); free(*section_name); return -1; } snprintf(*section_name, name_buf_size, "%s", rsp->name); dump_message(rsp, "Response"); return 0; } STATIC int handle_section_release(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, char **section_name, unsigned long id, int *index) { ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); ICP_CHECK_FOR_NULL_PARAM(index); ICP_CHECK_FOR_NULL_PARAM(section_name); if (req->hdr.len != sizeof(req->hdr) + ICP_ARRAY_STRLEN_SANITIZE(req->name) + 1) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); if (*section_name == NULL) { qat_log(LOG_LEVEL_ERROR, "Section not allocated\n"); err_msg(rsp, "Section not allocated"); return -1; } if (release_section( *index, id, req->name, ICP_ARRAY_STRLEN_SANITIZE(req->name))) { err_msg(rsp, "Failed to release section"); } else { qat_log(LOG_LEVEL_DEBUG, "Section %s released\n", req->name); build_msg_header(rsp, QATMGR_MSGTYPE_SECTION_PUT, 0); if (*section_name) { free(*section_name); *section_name = NULL; *index = -1; } } dump_message(rsp, "Response"); return 0; } static int handle_get_num_pf_devices(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp) { int32_t num_devices; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); if (req->hdr.len != sizeof(req->hdr)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); num_devices = get_num_pfs(); if (num_devices == PF_INFO_UNINITIALISED) { num_devices = adf_vfio_init_pfs_info( pf_data, sizeof(pf_data) / sizeof(pf_data[0])); set_num_pfs(num_devices); } if (num_devices < 0 || num_devices > ADF_MAX_PF_DEVICES) { err_msg(rsp, "Unable to init pfs info"); qat_log(LOG_LEVEL_ERROR, "Invalid number Pfs\n"); return -1; } /* num_devices will be a positive number and less then ADF_MAX_PF_DEVICES */ rsp->num_devices = num_devices; build_msg_header(rsp, QATMGR_MSGTYPE_NUM_PF_DEVS, sizeof(rsp->num_devices)); dump_message(rsp, "Response"); return 0; } static int handle_get_pf_device_info(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp) { uint16_t device_num; int32_t num_devices; ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); /* Use header + additional info length to retrieve PF device information */ if (req->hdr.len != sizeof(req->hdr) + sizeof(req->device_num)) { qat_log(LOG_LEVEL_ERROR, "Bad length\n"); err_msg(rsp, "Inconsistent length"); return -1; } dump_message(req, "Request"); num_devices = get_num_pfs(); if (num_devices == PF_INFO_UNINITIALISED) { num_devices = adf_vfio_init_pfs_info( pf_data, sizeof(pf_data) / sizeof(pf_data[0])); set_num_pfs(num_devices); } if (num_devices < 0 || num_devices > ADF_MAX_PF_DEVICES) { err_msg(rsp, "Unable to init pfs info"); qat_log(LOG_LEVEL_ERROR, "Invalid number Pfs\n"); return -1; } device_num = req->device_num; if (device_num >= num_devices) { qat_log(LOG_LEVEL_ERROR, "Invalid device number %d from %d devices\n", device_num, num_devices); err_msg(rsp, "Invalid device number"); return -1; } memcpy(&rsp->pf_info, &pf_data[device_num], sizeof(rsp->pf_info)); build_msg_header(rsp, QATMGR_MSGTYPE_PF_DEV_INFO, sizeof(rsp->pf_info)); dump_message(rsp, "Response"); return 0; } int handle_message(struct qatmgr_msg_req *req, struct qatmgr_msg_rsp *rsp, char **section_name, unsigned long id, int *index) { ICP_CHECK_FOR_NULL_PARAM(req); ICP_CHECK_FOR_NULL_PARAM(rsp); ICP_CHECK_FOR_NULL_PARAM(index); ICP_CHECK_FOR_NULL_PARAM(section_name); memset(&(rsp->device_info.fw_caps), '\0', sizeof(rsp->device_info.fw_caps)); if (req->hdr.version != THIS_LIB_VERSION) { char qatlib_ver_str[VER_STR_LEN]; char qatmgr_ver_str[VER_STR_LEN]; VER_STR(req->hdr.version, qatlib_ver_str); VER_STR(THIS_LIB_VERSION, qatmgr_ver_str); qat_log(LOG_LEVEL_ERROR, "qatmgr v%s received msg from incompatible qatlib v%s\n", qatmgr_ver_str, qatlib_ver_str); err_msg(rsp, "Incompatible. qatmgr received msg vX from qatlib vY\n"); return -1; } switch (req->hdr.type) { case QATMGR_MSGTYPE_SECTION_GET: return handle_section_request(req, rsp, section_name, id, index); case QATMGR_MSGTYPE_SECTION_PUT: return handle_section_release(req, rsp, section_name, id, index); case QATMGR_MSGTYPE_NUM_DEVICES: return handle_get_num_devices(req, rsp, *index); case QATMGR_MSGTYPE_DEVICE_INFO: return handle_get_device_info(req, rsp, *index); case QATMGR_MSGTYPE_DEVICE_ID: return handle_get_device_id(req, rsp, *index); case QATMGR_MSGTYPE_INSTANCE_INFO: return handle_get_instance_info(req, rsp, *index); case QATMGR_MSGTYPE_INSTANCE_NAME: return handle_get_instance_name(req, rsp, *index); case QATMGR_MSGTYPE_VFIO_FILE: return handle_get_vfio_name(req, rsp, *index); case QATMGR_MSGTYPE_NUM_PF_DEVS: return handle_get_num_pf_devices(req, rsp); case QATMGR_MSGTYPE_PF_DEV_INFO: return handle_get_pf_device_info(req, rsp); default: err_msg(rsp, "Unknown message"); } return -1; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_lib.c000066400000000000000000000240461503624047500311570ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "adf_pfvf_vf_msg.h" #include "vfio_lib.h" #include "icp_platform.h" #include "qat_log.h" static int container_fd = -1; static int container_fd_ref = 0; #define VFIO_GET_REGION_ADDR(x) ((uint64_t)x << 40ULL) /* PMISC BAR number */ #define ADF_PMISC_BAR 1 static int pci_vfio_set_command(int dev_fd, int command, bool op) { uint16_t reg; int ret; ret = pread(dev_fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + PCI_COMMAND); if (ret != sizeof(reg)) { ADF_ERROR("Cannot read command from PCI config space!\n"); return -1; } if (op) /* set the bit */ reg |= command; else reg &= ~(command); ret = pwrite(dev_fd, ®, sizeof(reg), VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + PCI_COMMAND); if (ret != sizeof(reg)) { ADF_ERROR("Cannot write command to PCI config space!\n"); return -1; } return 0; } static void init_bar(pcs_t *pcs) { ICP_CHECK_FOR_NULL_PARAM_VOID(pcs); memset(pcs, 0, sizeof(pcs_t)); } static void add_bar(pcs_t *pcs, void *ptr, const size_t size) { size_t idx = 0; ICP_CHECK_FOR_NULL_PARAM_VOID(pcs); ICP_CHECK_FOR_NULL_PARAM_VOID(ptr); idx = pcs->nr_bar; if (idx >= MAX_BAR_NR) { ADF_ERROR("add_bar: invalid idx %lu\n", idx); return; } pcs->bar[idx].ptr = ptr; pcs->bar[idx].size = size; pcs->nr_bar += 1; } static void remove_and_close_group(vfio_dev_info_t *dev) { int ret = 0; ICP_CHECK_FOR_NULL_PARAM_VOID(dev); ret = ioctl( dev->vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, dev->vfio_container_fd); if (ret) { ADF_ERROR("VFIO_GROUP_UNSET_CONTAINER ioctl failed\n"); } if (container_fd_ref) --container_fd_ref; close(dev->vfio_group_fd); dev->vfio_group_fd = -1; if (!container_fd_ref) { close(container_fd); container_fd = -1; } } int open_vfio_dev(const char *vfio_file, const char *bdf, int group_fd, unsigned int pci_id, vfio_dev_info_t *dev) { int i; int ret; int already_enabled = 0; static pid_t pid = 0; struct vfio_group_status group_status = { .argsz = sizeof(group_status) }; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; ICP_CHECK_FOR_NULL_PARAM_RET_CODE(dev, -1); ICP_CHECK_FOR_NULL_PARAM_RET_CODE(vfio_file, -1); ICP_CHECK_FOR_NULL_PARAM_RET_CODE(bdf, -1); init_bar(&dev->pcs); if (container_fd >= 0 && pid != getpid()) { /* Child process inherited fd from parent */ close(container_fd); container_fd = -1; container_fd_ref = 0; } if (container_fd < 0) { /* Create a new container */ container_fd = open("/dev/vfio/vfio", O_RDWR); pid = getpid(); ret = ioctl(container_fd, VFIO_GET_API_VERSION); if (VFIO_API_VERSION != ret) { ADF_ERROR("VFIO_GET_API_VERSION ioctl failed\n"); return -1; } ret = ioctl(container_fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU); if (!ret) { ADF_ERROR("VFIO_CHECK_EXTENSION ioctl failed\n"); return -1; } } else { already_enabled = 1; } dev->vfio_container_fd = container_fd; if (group_fd >= 0) { dev->vfio_group_fd = group_fd; } else { dev->vfio_group_fd = open(vfio_file, O_RDWR); if (dev->vfio_group_fd < 0) { ADF_DEBUG("Cannot open %s\n", vfio_file); return -1; } } /* Test the group is viable and available */ ret = ioctl(dev->vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status); if (ret) { ADF_ERROR("VFIO_GROUP_GET_STATUS ioctl failed\n"); close(dev->vfio_group_fd); return -1; } if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) { ADF_ERROR("Group is not viable (ie, not all devices bound for vfio)\n"); close(dev->vfio_group_fd); return -1; } /* Add the group to the container */ ret = ioctl( dev->vfio_group_fd, VFIO_GROUP_SET_CONTAINER, &dev->vfio_container_fd); if (ret) { ADF_ERROR("VFIO_GROUP_SET_CONTAINER ioctl failed\n"); close(dev->vfio_group_fd); return -1; } container_fd_ref++; if (!already_enabled) { if (strstr(vfio_file, "noiommu")) ret = ioctl(dev->vfio_container_fd, VFIO_SET_IOMMU, VFIO_NOIOMMU_IOMMU); else ret = ioctl(dev->vfio_container_fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); if (ret) { ADF_ERROR("VFIO_SET_IOMMU ioctl failed\n"); remove_and_close_group(dev); return -1; } } /* Get a file descriptor for the device */ dev->vfio_dev_fd = ioctl(dev->vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD, bdf); if (dev->vfio_dev_fd < 0) { ADF_DEBUG("VFIO_GROUP_GET_DEVICE_FD ioctl failed\n"); remove_and_close_group(dev); return -1; } if (pci_vfio_set_command(dev->vfio_dev_fd, PCI_COMMAND_MEMORY, true)) { ADF_ERROR("Cannot enable memory access!\n"); close(dev->vfio_dev_fd); remove_and_close_group(dev); return -1; } /* Test and setup the device */ ret = ioctl(dev->vfio_dev_fd, VFIO_DEVICE_GET_INFO, &device_info); if (ret) { ADF_ERROR("VFIO_DEVICE_GET_INFO ioctl failed\n"); close(dev->vfio_dev_fd); remove_and_close_group(dev); return -1; } for (i = 0; i < device_info.num_regions; i++) { struct vfio_region_info reg = { .argsz = sizeof(reg) }; reg.index = i; /* Setup mappings... read/write offsets, mmaps * For PCI devices, config space is a region */ ret = ioctl(dev->vfio_dev_fd, VFIO_DEVICE_GET_REGION_INFO, ®); if (ret) { if (!reg.size) { ADF_DEBUG("VFIO_DEVICE_GET_REGION_INFO ioctl failed, " "detected zero sized region, " "unimplemented PCI BAR possible\n"); } else { ADF_ERROR("VFIO_DEVICE_GET_REGION_INFO ioctl failed\n"); } } /* skip non-mmapable BARs */ if ((reg.flags & VFIO_REGION_INFO_FLAG_MMAP) == 0) { continue; } if (reg.flags & VFIO_REGION_INFO_FLAG_WRITE) { void *ptr = mmap(NULL, reg.size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->vfio_dev_fd, reg.offset); if (MAP_FAILED != ptr) { add_bar(&dev->pcs, ptr, reg.size); } } } if (pci_vfio_set_command(dev->vfio_dev_fd, PCI_COMMAND_MASTER, true)) { ADF_ERROR("Fail to set BME.\n"); close_vfio_dev(dev); return -1; } /* Init VF2PF communication */ dev->pfvf = adf_init_pfvf_dev_data(dev->pcs.bar[ADF_PMISC_BAR].ptr, pci_id); return 0; } void close_vfio_dev(vfio_dev_info_t *dev) { int idx; pcs_t *pcs; int ret = 0; ICP_CHECK_FOR_NULL_PARAM_VOID(dev); pcs = &dev->pcs; for (idx = pcs->nr_bar - 1; idx >= 0; idx--) { ret = munmap(pcs->bar[idx].ptr, pcs->bar[idx].size); if (ret) { ADF_ERROR("close_vfio_dev : munmap error for idx = %d\n", idx); } } pcs->nr_bar = 0; pci_vfio_set_command(dev->vfio_dev_fd, PCI_COMMAND_MEMORY, false); pci_vfio_set_command(dev->vfio_dev_fd, PCI_COMMAND_MASTER, false); close(dev->vfio_dev_fd); dev->vfio_dev_fd = -1; remove_and_close_group(dev); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_lib.h000066400000000000000000000047321503624047500311640ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef VFIO_LIB_H #define VFIO_LIB_H #include "adf_pfvf_proto.h" /* Common typedefs */ #define MAX_BAR_NR (0x10) typedef struct { size_t nr_bar; struct { void *ptr; size_t size; } bar[MAX_BAR_NR]; } pcs_t; typedef struct { int vfio_container_fd; int vfio_dev_fd; int vfio_group_fd; pcs_t pcs; struct adf_pfvf_dev_data pfvf; } vfio_dev_info_t; /* Function prototypes */ int open_vfio_dev(const char *vfio_file, const char *bdf, int group_fd, unsigned int pci_id, vfio_dev_info_t *dev); void close_vfio_dev(vfio_dev_info_t *dev); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/adf_io/vfio/vfio_mgr_lib.c000066400000000000000000001323241503624047500320230ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ #include #include #include #include #include "adf_pfvf_vf_msg.h" #include "icp_accel_devices.h" #include "icp_platform.h" #include "qat_log.h" #include "qat_mgr.h" #include "vfio_lib.h" #include "adf_vfio_pf.h" #define IOMMUGROUP_DEV_DIR "/sys/kernel/iommu_groups/%.*s/devices/" #define DEVVFIO_DIR "/dev/vfio" #define DEVICE_FILE IOMMUGROUP_DEV_DIR "%.*s/device" #define VENDOR_FILE IOMMUGROUP_DEV_DIR "%.*s/vendor" #define NUMA_NODE IOMMUGROUP_DEV_DIR "%.*s/numa_node" #define SYSFS_VF_DIR "/sys/bus/pci/devices" #define SYSFS_VF_UEVENT "physfn/uevent" #define PCI_DEV_SLOT_NAME "PCI_SLOT_NAME" #define PF_DEVICE_FORMAT PCI_DEV_SLOT_NAME"=%s" #define VFIO_ENTRY "vfio" #define VFIO_NOIOMMU "noiommu-" extern icp_accel_pf_info_t pf_data[ADF_MAX_PF_DEVICES]; /* * Instead of the default sort order * 3d:01.0, 3d:01.1, ... 3d:02.7, 3f:01.0 ... 3f:02.7, da:01.0 ... da:02.7 * we want all the equivalent device/function entries for each of the PF * devices together to facilitate getting devices for policy 0. * 3d:01.0, 3f:01.0, da:01.0, 3d:01.1 ... */ static int bdf_compare(const void *a, const void *b) { struct qatmgr_dev_data *dev_a = (struct qatmgr_dev_data *)a; struct qatmgr_dev_data *dev_b = (struct qatmgr_dev_data *)b; if (BDF_FUN(dev_a->bdf) < BDF_FUN(dev_b->bdf)) return -1; if (BDF_FUN(dev_a->bdf) > BDF_FUN(dev_b->bdf)) return 1; if (BDF_DEV(dev_a->bdf) < BDF_DEV(dev_b->bdf)) return -1; if (BDF_DEV(dev_a->bdf) > BDF_DEV(dev_b->bdf)) return 1; if (BDF_BUS(dev_a->bdf) > BDF_BUS(dev_b->bdf)) return 1; if (BDF_BUS(dev_a->bdf) < BDF_BUS(dev_b->bdf)) return -1; return 0; } /* Filter the dot(.) entries from the given file path */ static int filter_vfio_files(const struct dirent *entry) { return entry->d_name[0] != '.'; } int qat_mgr_get_vfio_dev_list(unsigned *num_devices, struct qatmgr_dev_data *dev_list, const unsigned list_size, int keep_fd) { struct dirent **devvfio_dir; struct dirent **sysdevice_dir; FILE *sysfile; int sysfile_fd; struct dirent *vfio_entry; struct dirent *device_entry; int num_devs = 0; unsigned device, vendor; char filename[256]; char devices_dir_name[256]; int vfiofile = -1; char *bdfname; unsigned domain, bus, dev, func; int found = 0; int numa_node; uint32_t vfio_dir_name_len = 0, device_dir_name_len = 0; uint32_t buf_size = 0, str_len = 0; int num_vfio_group, num_vfio_device, i, j; char *vfio_file_name = NULL; if (!dev_list || !list_size || !num_devices) return -EINVAL; *num_devices = 0; num_vfio_group = scandir(DEVVFIO_DIR, &devvfio_dir, filter_vfio_files, alphasort); if (num_vfio_group < 0) { return -EIO; } /* For each entry in /dev/vfio/ */ for (i = 0; i < num_vfio_group; i++) { vfio_entry = devvfio_dir[i]; /* /dev/vfio/vfio is special entry, should be skipped */ if (!ICP_STRNCMP_CONST(vfio_entry->d_name, VFIO_ENTRY)) continue; /* * A vfio device may be visible but not available. * It might, for example, be assigned to a virtual machine. * Alternatively, it could be used by another process using * a static configuration. * In either case, if the device cannot be opened, it should be * excluded from the list. */ buf_size = sizeof(filename) - (sizeof(DEVVFIO_DIR) - 1) - 1; str_len = strnlen(vfio_entry->d_name, sizeof(vfio_entry->d_name)); if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy device file name\n"); continue; } snprintf(filename, sizeof(filename), DEVVFIO_DIR "/%.*s", VFIO_FILE_SIZE - 1, vfio_entry->d_name); vfiofile = open_file_with_link_check(filename, O_RDWR); if (vfiofile < 0) continue; if (!keep_fd) { close(vfiofile); vfiofile = -1; } /* * For noiommu, the file name has the format of noiommu- in * /dev/vfio. Remove the noiommu- prefix when accessing * /sys/kernel/iommu-groups// directory. */ vfio_file_name = vfio_entry->d_name; if (!ICP_STRNCMP(vfio_file_name, VFIO_NOIOMMU, strlen(VFIO_NOIOMMU))) vfio_file_name = vfio_entry->d_name + strlen(VFIO_NOIOMMU); /* open dir /sys/kernel/iommu_groups//devices/ */ buf_size = sizeof(devices_dir_name) - (sizeof(IOMMUGROUP_DEV_DIR) - 1) + STR_FORMAT_SPECIFIER_LEN; if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy device directory name\n"); if (vfiofile != -1) { close(vfiofile); } continue; } snprintf(devices_dir_name, sizeof(devices_dir_name), IOMMUGROUP_DEV_DIR, VFIO_FILE_SIZE - 1, vfio_file_name); num_vfio_device = scandir( devices_dir_name, &sysdevice_dir, filter_vfio_files, alphasort); if (num_vfio_device < 0) { if (vfiofile != -1) { close(vfiofile); } continue; } found = 0; /* For each device in this group. Should only be one. */ for (j = 0; j < num_vfio_device; j++) { device_entry = sysdevice_dir[j]; /* Open /sys/kernel/iommu_groups//devices//device */ vfio_dir_name_len = strnlen(vfio_entry->d_name, sizeof(vfio_entry->d_name)); device_dir_name_len = strnlen(device_entry->d_name, sizeof(device_entry->d_name)); buf_size = sizeof(filename) - (sizeof(DEVICE_FILE) - 1) + (NUM_STR_FORMAT_SPECIFIER * STR_FORMAT_SPECIFIER_LEN); str_len = vfio_dir_name_len + device_dir_name_len; if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy device file name\n"); break; } snprintf(filename, sizeof(filename), DEVICE_FILE, VFIO_FILE_SIZE, vfio_file_name, (buf_size - VFIO_FILE_SIZE - 1), device_entry->d_name); sysfile_fd = open_file_with_link_check(filename, O_RDONLY); if (sysfile_fd < 0) break; sysfile = fdopen(sysfile_fd, "r"); if (!sysfile) { close(sysfile_fd); break; } device = 0; if (fscanf(sysfile, "%x", &device) != 1) { qat_log(LOG_LEVEL_INFO, "Failed to read device from %s\n", filename); /* * If the fscanf fails, the check of device ids below will fail * and break out of the loop at that point. */ } fclose(sysfile); qat_log(LOG_LEVEL_INFO, "Checking %s\n", filename); if (!is_qat_device(device)) break; buf_size = sizeof(filename) - (sizeof(VENDOR_FILE) - 1) + (NUM_STR_FORMAT_SPECIFIER * STR_FORMAT_SPECIFIER_LEN); if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy vendor file name\n"); break; } snprintf(filename, sizeof(filename), VENDOR_FILE, VFIO_FILE_SIZE, vfio_file_name, (buf_size - VFIO_FILE_SIZE - 1), device_entry->d_name); sysfile_fd = open_file_with_link_check(filename, O_RDONLY); if (sysfile_fd < 0) break; sysfile = fdopen(sysfile_fd, "r"); if (!sysfile) { qat_log(LOG_LEVEL_ERROR, "Failed to open %s\n", filename); close(sysfile_fd); break; } vendor = 0; if (fscanf(sysfile, "%x", &vendor) != 1) { qat_log(LOG_LEVEL_ERROR, "Failed to read vendor from %s\n", filename); /* * If the fscanf fails, the check of vendor id below will fail * and break out of the loop at that point. */ } fclose(sysfile); if (vendor != INTEL_VENDOR_ID) break; /* Extract the BDF from the file name */ bdfname = basename(device_entry->d_name); if (sscanf(bdfname, "%x:%x:%x.%x", &domain, &bus, &dev, &func) != 4) { qat_log(LOG_LEVEL_ERROR, "Failed to scan BDF string\n"); break; } dev_list[num_devs].bdf = GET_BDF(domain, bus, dev, func); buf_size = sizeof(dev_list[num_devs].vfio_file) - (sizeof(DEVVFIO_DIR) - 1) - 1; str_len = strnlen(vfio_entry->d_name, sizeof(vfio_entry->d_name)); if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy device file name\n"); break; } snprintf(dev_list[num_devs].vfio_file, sizeof(dev_list[num_devs].vfio_file), DEVVFIO_DIR "/%.*s", buf_size - 1, vfio_entry->d_name); if (j + 1 < num_vfio_device) { qat_log(LOG_LEVEL_INFO, "Multiple vfio devices in group %s. Ignored\n", vfio_entry->d_name); break; } buf_size = sizeof(filename) - (sizeof(NUMA_NODE) - 1) + (NUM_STR_FORMAT_SPECIFIER * STR_FORMAT_SPECIFIER_LEN); if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy Numa node\n"); break; } snprintf(filename, sizeof(filename), NUMA_NODE, VFIO_FILE_SIZE, vfio_file_name, (buf_size - VFIO_FILE_SIZE - 1), device_entry->d_name); sysfile_fd = open_file_with_link_check(filename, O_RDONLY); if (sysfile_fd < 0) break; sysfile = fdopen(sysfile_fd, "r"); if (!sysfile) { qat_log(LOG_LEVEL_ERROR, "Failed to open %s\n", filename); close(sysfile_fd); break; } numa_node = 0; if (fscanf(sysfile, "%d", &numa_node) != 1) { qat_log(LOG_LEVEL_ERROR, "Failed to read numa node from %s\n", filename); } fclose(sysfile); /* numa_node may be reported as -1 on VM */ if (numa_node < 0) numa_node = 0; dev_list[num_devs].numa_node = numa_node; found = 1; dev_list[num_devs].devid = device; if (keep_fd) dev_list[num_devs].group_fd = vfiofile; else dev_list[num_devs].group_fd = -1; num_devs++; break; } for (j = 0; j < num_vfio_device; j++) { free(sysdevice_dir[j]); } free(sysdevice_dir); if (!found && vfiofile != -1) { close(vfiofile); } if (num_devs >= list_size) break; } for (i = 0; i < num_vfio_group; i++) { free(devvfio_dir[i]); } free(devvfio_dir); *num_devices = num_devs; if (!num_devs) qat_log(LOG_LEVEL_ERROR, "No devices found\n"); qsort(dev_list, *num_devices, sizeof(dev_list[0]), bdf_compare); return 0; } STATIC int qat_mgr_get_device_capabilities( struct qatmgr_device_data *device_data, int dev_id, bool *compatible, uint32_t *ext_dc_caps, uint32_t *capabilities, uint32_t *ring_to_svc_map) { int ret; vfio_dev_info_t vfio_dev; *compatible = CPA_TRUE; ret = open_vfio_dev(device_data->device_file, device_data->device_id, device_data->group_fd, dev_id, &vfio_dev); if (ret) { qat_log(LOG_LEVEL_ERROR, "Cannot open vfio device\n"); return ret; } ret = adf_vf2pf_check_compat_version(&vfio_dev.pfvf); if (ret) { close_vfio_dev(&vfio_dev); device_data->group_fd = -1; if (adf_vf2pf_available()) { qat_log(LOG_LEVEL_ERROR, "Comms incompatible between VF and PF\n"); *compatible = CPA_FALSE; } return ret; } ret = adf_vf2pf_get_ring_to_svc(&vfio_dev.pfvf); if (ret) { qat_log(LOG_LEVEL_ERROR, "Cannot query device ring to service map\n"); close_vfio_dev(&vfio_dev); device_data->group_fd = -1; return ret; } else { /* Some earlier kernels returned an invalid map of 0. It's more robust * to assume the default map in this case. */ if (vfio_dev.pfvf.ring_to_svc_map == 0) { vfio_dev.pfvf.ring_to_svc_map = DEFAULT_RING_TO_SRV_MAP; qat_log( LOG_LEVEL_DEBUG, "Kernel reported ring_to_svc_map of 0, so assume default\n"); } } ret = adf_vf2pf_get_capabilities(&vfio_dev.pfvf); if (ret) { qat_log(LOG_LEVEL_ERROR, "Cannot query device capabilities\n"); close_vfio_dev(&vfio_dev); device_data->group_fd = -1; return ret; } *ext_dc_caps = vfio_dev.pfvf.ext_dc_caps; *capabilities = vfio_dev.pfvf.capabilities; *ring_to_svc_map = vfio_dev.pfvf.ring_to_svc_map; if (vfio_dev.pfvf.fw_caps.is_fw_caps) { device_data->fw_caps.comp_algos = vfio_dev.pfvf.fw_caps.comp_algos; device_data->fw_caps.cksum_algos = vfio_dev.pfvf.fw_caps.cksum_algos; device_data->fw_caps.deflate_caps = vfio_dev.pfvf.fw_caps.deflate_caps; device_data->fw_caps.lz4_caps = vfio_dev.pfvf.fw_caps.lz4_caps; device_data->fw_caps.lz4s_caps = vfio_dev.pfvf.fw_caps.lz4s_caps; device_data->fw_caps.is_fw_caps = 1; } close_vfio_dev(&vfio_dev); device_data->group_fd = -1; return 0; } static uint16_t bdf_pf(const unsigned vf_bdf) { uint16_t pf_bdf = 0; unsigned int domain, bus, dev, func; FILE *fp = NULL; char dev_path[QATMGR_MAX_STRLEN] = { '\0' }; char dev_info[QATMGR_MAX_STRLEN] = { '\0' }; char pci_slot_name[DEVICE_NAME_SIZE] = { '\0' }; snprintf(dev_path, sizeof(dev_path), "%s/%04x:%02x:%02x.%1x/%s", SYSFS_VF_DIR, BDF_DOMAIN(vf_bdf), BDF_BUS(vf_bdf), BDF_DEV(vf_bdf), BDF_FUN(vf_bdf), SYSFS_VF_UEVENT); fp = fopen(dev_path, "r"); if (fp == NULL) { qat_log( LOG_LEVEL_ERROR, "Failed to open VF sysfs file : %s\n", dev_path); return 0; } while (fgets(dev_info, sizeof(dev_info), fp) != NULL) { if (strstr(dev_info, PCI_DEV_SLOT_NAME) != NULL) { sscanf(dev_info, PF_DEVICE_FORMAT, pci_slot_name); sscanf(pci_slot_name, "%x:%x:%x.%x", &domain, &bus, &dev, &func); pf_bdf = ((0xFF & bus) << 8) + ((0x1F & dev) << 3) + (0x07 & func); break; } } fclose(fp); return pf_bdf; } /** * Search for PF index from pf_info data for given vf_bdf * returns 0 on success and -1 on failure. If pf_info array * is empty (if qatlib is running inside VM) then assigns max value of pkg_id * and returns 0 */ static int get_pkg_id(unsigned vf_bdf, int32_t *vf_pkg_id) { int32_t pkg_id = 0; uint16_t pf_bdf = 0; uint16_t domain; int32_t num_pfs; num_pfs = get_num_pfs(); if (!num_pfs) { *vf_pkg_id = VM_PACKAGE_ID_NONE; return 0; } /* get PF BDF id using VF BDF id */ pf_bdf = bdf_pf(vf_bdf); if (!pf_bdf) return -1; domain = BDF_DOMAIN(vf_bdf); for (pkg_id = 0; pkg_id < num_pfs; pkg_id++) { if (pf_data[pkg_id].bdf == pf_bdf && pf_data[pkg_id].domain == domain) { *vf_pkg_id = pkg_id; return 0; } } return -1; } int qat_mgr_vfio_build_data(const struct qatmgr_dev_data dev_list[], const int num_vf_devices, int policy, int static_cfg) { int i, j, k; struct qatmgr_section_data *section; struct qatmgr_instance_data *dc_inst; struct qatmgr_instance_data *decomp_inst; struct qatmgr_cy_instance_data *cy_inst; struct qatmgr_device_data *device_data; int num_vf_groups; int vf_idx = 0; int num_vfs_this_section; int pf = 0; unsigned devid; char pf_str[10]; ENTRY pf_entry = { pf_str, NULL }; int pfs_per_vf_group[ADF_MAX_DEVICES] = { 0 }; uint32_t ext_dc_caps, capabilities; uint32_t ring_to_svc_map; bool compatible; bool vm = false; int ret; struct pf_capabilities *cached_capabilities; int section_num_sym_inst = 0; int section_num_asym_inst = 0; int section_num_dc_inst = 0; int32_t vf_pkg_id = 0; int section_num_decomp_inst = 0; int32_t num_pfs; int num_section_data = 0; if (!num_vf_devices) return -EINVAL; num_pfs = get_num_pfs(); if (num_pfs == PF_INFO_UNINITIALISED) { num_pfs = adf_vfio_init_pfs_info(pf_data, sizeof(pf_data) / sizeof(pf_data[0])); set_num_pfs(num_pfs); } if (num_pfs < 0 || num_pfs > ADF_MAX_PF_DEVICES) { qat_log(LOG_LEVEL_ERROR, "Invalid number Pfs\n"); return -1; } if (!num_pfs) { vm = true; qat_log(LOG_LEVEL_DEBUG, "Unable to find pfs in the system, assuming " "qat_mgr_lib is running inside VM\n"); } ret = init_cpu_data(); if (ret) { return ret; } /* * A VF group is a set of VFs with the same device/function * but from different PFs. * The dev_list is sorted so that each VF in a group are consecutive. * We know we have a new group when we find a PF that already exists in * the first group. */ if (!static_cfg) { num_vf_groups = 1; /* Create hash table for mapping devices */ if (hcreate(ADF_MAX_DEVICES) == 0) { qat_log(LOG_LEVEL_ERROR, "Error while creating hash table\n"); free_cpu_data(); return -ENOMEM; } /* Count VF groups */ for (i = 0; i < num_vf_devices; i++) { /* Convert PF address to int - take node into account */ pf = PF(dev_list[i].bdf); /* Convert address to string to use as hash table key */ snprintf(pf_str, sizeof(pf_str), "%d", pf); /* Check if pf is already in the hash table */ if (hsearch(pf_entry, FIND) != NULL) { /* Device already in hash table - increment vf groups */ num_vf_groups++; /* Need to create new hash table */ hdestroy(); if (hcreate(ADF_MAX_DEVICES) == 0) { qat_log(LOG_LEVEL_ERROR, "Error while creating hash table\n"); free_cpu_data(); return -ENOMEM; } } pfs_per_vf_group[num_vf_groups - 1]++; /* Insert device to hash table */ if (hsearch(pf_entry, ENTER) == NULL) { qat_log(LOG_LEVEL_ERROR, "No space left in hash table\n"); free_cpu_data(); return -ENOMEM; } } qat_log(LOG_LEVEL_DEBUG, "num_vf_groups %d\n", num_vf_groups); /* Destroy hash table */ hdestroy(); /* * For policy 0, each process will get a VF from each PF so there can * be a max of num_vf_groups processes. * For policy , each process will get VFs so there can be * a max of num_vf_devices / processes. */ if (policy == 0) { num_section_data = num_vf_groups; } else { num_section_data = num_vf_devices / policy; } if (num_section_data <= 0) { qat_log(LOG_LEVEL_ERROR, "Policy %d is greater than the number of " "available devices %d\n", policy, num_vf_devices); free_cpu_data(); return -EINVAL; } qat_log(LOG_LEVEL_DEBUG, "num_section_data %d\n", num_section_data); } else if (num_vf_devices >= policy) { num_section_data = 1; } else { qat_log(LOG_LEVEL_ERROR, "Policy %d is incompatible with the number of " "available devices %d\n", policy, num_vf_devices); free_cpu_data(); return -EINVAL; } section = calloc(num_section_data, sizeof(struct qatmgr_section_data)); if (!section) { qat_log(LOG_LEVEL_ERROR, "Malloc failed for section data\n"); free_cpu_data(); return -EAGAIN; } set_section_data(section); set_num_section_data(num_section_data); for (i = 0; i < num_section_data; i++, section++) { snprintf(section->section_name, sizeof(section->section_name), "SSL_INT_%d", i); snprintf(section->base_name, sizeof(section->base_name), "SSL"); section->assigned_id = 0; if (policy) { num_vfs_this_section = policy; if (num_vfs_this_section > num_vf_devices - vf_idx) num_vfs_this_section = num_vf_devices - vf_idx; } else { /* * Policy 0, one VF from each different PF. * Use cached number of PFs. */ num_vfs_this_section = pfs_per_vf_group[i]; } section->num_devices = num_vfs_this_section; /* Create device data */ section->device_data = calloc(num_vfs_this_section, sizeof(struct qatmgr_device_data)); if (!section->device_data) { qat_log(LOG_LEVEL_ERROR, "Malloc failed for device data\n"); qat_mgr_cleanup_cfg(); return -EAGAIN; } section_num_sym_inst = 0; section_num_asym_inst = 0; section_num_dc_inst = 0; section_num_decomp_inst = 0; device_data = section->device_data; for (j = 0; j < num_vfs_this_section; j++, device_data++, vf_idx++) { ring_to_svc_map = DEFAULT_RING_TO_SRV_MAP; qat_log(LOG_LEVEL_DEBUG, "section %d, BDF %X\n", i, dev_list[vf_idx].bdf); snprintf(device_data->device_id, sizeof(device_data->device_id), "%04x:%02x:%02x.%01x", BDF_DOMAIN(dev_list[vf_idx].bdf), BDF_BUS(dev_list[vf_idx].bdf), BDF_DEV(dev_list[vf_idx].bdf), BDF_FUN(dev_list[vf_idx].bdf)); snprintf(device_data->device_file, sizeof(device_data->device_file), "%.*s", VFIO_FILE_SIZE, dev_list[vf_idx].vfio_file); device_data->group_fd = dev_list[vf_idx].group_fd; device_data->accelid = j; device_data->node = dev_list[vf_idx].numa_node; device_data->ring_mode = ADF_RING_WQ_MODE; if (get_pkg_id(dev_list[vf_idx].bdf, &vf_pkg_id)) { qat_log(LOG_LEVEL_ERROR, "Failed to find pkg_id for the device\n"); qat_mgr_cleanup_cfg(); return -EAGAIN; } /* since sample code uses package id for gathering info from devices * this overrides pkg id to accel id if qatlib is running on VM */ if (vf_pkg_id == VM_PACKAGE_ID_NONE) { vf_pkg_id = device_data->accelid; } device_data->pkg_id = vf_pkg_id; devid = dev_list[vf_idx].devid; device_data->max_banks = 4; device_data->max_rings_per_bank = 2; device_data->arb_mask = 0x01; #ifndef ENABLE_DC device_data->accel_capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC | ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | ICP_ACCEL_CAPABILITIES_CIPHER | ICP_ACCEL_CAPABILITIES_AUTHENTICATION | ICP_ACCEL_CAPABILITIES_CRYPTO_SHA3 | ICP_ACCEL_CAPABILITIES_SHA3_EXT | ICP_ACCEL_CAPABILITIES_HKDF | ICP_ACCEL_CAPABILITIES_ECEDMONT | ICP_ACCEL_CAPABILITIES_CHACHA_POLY | ICP_ACCEL_CAPABILITIES_AESGCM_SPC | ICP_ACCEL_CAPABILITIES_AES_V2; device_data->extended_capabilities = 0x0; #else /* For Legacy Chaining we set the following * AUTHENTICATION and Bit 21 * Bit 21 used to enabling the hash then compress * chaining support. */ device_data->accel_capabilities = ICP_ACCEL_CAPABILITIES_COMPRESSION | ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY64 | ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION | ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION | ICP_ACCEL_CAPABILITIES_AUTHENTICATION | ICP_ACCEL_CAPABILITIES_CRYPTO_SHA3 | ICP_ACCEL_CAPABILITIES_SHA3_EXT; device_data->extended_capabilities = BIT(21) | BIT(0); #endif /** * Send query to get capabilities from PF. * qat_mgr_get_device_capabilities will open device, initialize * VF2PF communication, query capabilities and close device. * * Before first query, we don't know if PF is supporting VF2PF (1st * call to adf_vf2pf_available will report availability of VF2PF), * in case where PF is not supporting VF2PF, consecutive calls to * adf_vf2pf_available will report lack of VF2PF and hardcoded * "fallback" capabilities defined above will be used. */ cached_capabilities = NULL; if (!vm) { /** * If running on a host, it can be assumed that all devices with * the same domain+bus are VFs from the same PF and so have the * same capabilities. So it's an optimization to query the * capabilities of only one VF and cache them to populate the * other VFs. */ pf = PF(dev_list[vf_idx].bdf); cached_capabilities = find_pf_capabilities(pf); } if (cached_capabilities) { device_data->accel_capabilities = cached_capabilities->capabilities; device_data->extended_capabilities = cached_capabilities->ext_dc_caps; if (cached_capabilities->fw_caps.is_fw_caps) { device_data->fw_caps.comp_algos = cached_capabilities->fw_caps.comp_algos; device_data->fw_caps.cksum_algos = cached_capabilities->fw_caps.cksum_algos; device_data->fw_caps.deflate_caps = cached_capabilities->fw_caps.deflate_caps; device_data->fw_caps.lz4_caps = cached_capabilities->fw_caps.lz4_caps; device_data->fw_caps.lz4s_caps = cached_capabilities->fw_caps.lz4s_caps; device_data->fw_caps.is_fw_caps = cached_capabilities->fw_caps.is_fw_caps; } ring_to_svc_map = cached_capabilities->ring_to_svc_map; } else if (adf_vf2pf_available()) { ret = qat_mgr_get_device_capabilities(device_data, devid, &compatible, &ext_dc_caps, &capabilities, &ring_to_svc_map); if (0 == ret) { /* * Override the ecEdMont capability * reported by the kernel. The reason for this is that * some kernel drivers don't report this capability * even though it is present in all devices that have asym. */ if (capabilities & ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC) capabilities |= ICP_ACCEL_CAPABILITIES_ECEDMONT; /* * QAT silicon is not spec compliant for ZUC-256, due to * late changes to that spec. So prevent it from being used. */ capabilities &= ~ICP_ACCEL_CAPABILITIES_ZUC_256; device_data->accel_capabilities = capabilities; device_data->extended_capabilities = ext_dc_caps; } else if (!compatible) { qat_log(LOG_LEVEL_ERROR, "Detected not compatible PF driver\n"); qat_mgr_cleanup_cfg(); return ret; } if (0 == ret && !vm) { cached_capabilities = calloc(1, sizeof(struct pf_capabilities)); if (!cached_capabilities) { qat_log(LOG_LEVEL_ERROR, "Malloc failed for capabilities cache\n"); qat_mgr_cleanup_cfg(); return -EAGAIN; } cached_capabilities->pf = pf; cached_capabilities->capabilities = capabilities; cached_capabilities->ext_dc_caps = ext_dc_caps; cached_capabilities->ring_to_svc_map = ring_to_svc_map; if (device_data->fw_caps.is_fw_caps) { cached_capabilities->fw_caps.comp_algos = device_data->fw_caps.comp_algos; cached_capabilities->fw_caps.cksum_algos = device_data->fw_caps.cksum_algos; cached_capabilities->fw_caps.deflate_caps = device_data->fw_caps.deflate_caps; cached_capabilities->fw_caps.lz4_caps = device_data->fw_caps.lz4_caps; cached_capabilities->fw_caps.lz4s_caps = device_data->fw_caps.lz4s_caps; cached_capabilities->fw_caps.is_fw_caps = 1; } add_pf_capabilities(cached_capabilities); } } snprintf(device_data->name, sizeof(device_data->name), "%s", qat_device_name(devid)); device_data->device_type = qat_device_type(devid); device_data->pci_id = devid; /* Populate service configuration for a device and * determine the number of instances per device */ ret = get_num_instances( device_data, devid, ring_to_svc_map, INSTANCES_PER_DEVICE); if (ret) { qat_log(LOG_LEVEL_ERROR, "Detected unknown service\n"); qat_mgr_cleanup_cfg(); return -1; } if (device_data->num_dc_inst) { /* Create DC instance data */ device_data->dc_instance_data = calloc(device_data->num_dc_inst, sizeof(struct qatmgr_instance_data)); if (!device_data->dc_instance_data) { qat_log(LOG_LEVEL_ERROR, "Malloc failed for dc instance data\n"); qat_mgr_cleanup_cfg(); return -EAGAIN; } } if (device_data->num_decomp_inst) { /* Create decompression instance data */ device_data->decomp_instance_data = calloc(device_data->num_decomp_inst, sizeof(struct qatmgr_instance_data)); if (!device_data->decomp_instance_data) { qat_log( LOG_LEVEL_ERROR, "Memory allocation failed for decomp instance data\n"); qat_mgr_cleanup_cfg(); return -EAGAIN; } } /* SYM and ASYM are stored inside CY instance data */ if (device_data->num_cy_inst) { device_data->cy_instance_data = calloc(device_data->num_cy_inst, sizeof(struct qatmgr_cy_instance_data)); if (!device_data->cy_instance_data) { qat_log(LOG_LEVEL_ERROR, "Malloc failed for cy instance data\n"); qat_mgr_cleanup_cfg(); return -EAGAIN; } } /* populate instance data */ cy_inst = device_data->cy_instance_data; for (k = 0; k < device_data->num_asym_inst; k++, cy_inst++) { snprintf(cy_inst->asym.name, sizeof(cy_inst->asym.name), "asym%d", section_num_asym_inst++); cy_inst->asym.accelid = device_data->accelid; cy_inst->asym.service_type = SERV_TYPE_ASYM; cy_inst->asym.bank_number = calculate_bank_number( ASYM, k, ring_to_svc_map, INSTANCES_PER_DEVICE); if (cy_inst->asym.bank_number < 0) { qat_log(LOG_LEVEL_ERROR, "Cannot find bank number for asym instance\n"); qat_mgr_cleanup_cfg(); return -1; } cy_inst->asym.ring_tx = 0; cy_inst->asym.ring_rx = 1; cy_inst->asym.is_polled = 1; cy_inst->asym.num_concurrent_requests = 64; cy_inst->asym.core_affinity = get_core_affinity(device_data->node); } cy_inst = device_data->cy_instance_data; for (k = 0; k < device_data->num_sym_inst; k++, cy_inst++) { snprintf(cy_inst->sym.name, sizeof(cy_inst->sym.name), "sym%d", section_num_sym_inst++); cy_inst->sym.accelid = device_data->accelid; cy_inst->sym.service_type = SERV_TYPE_SYM; cy_inst->sym.bank_number = calculate_bank_number( SYM, k, ring_to_svc_map, INSTANCES_PER_DEVICE); if (cy_inst->sym.bank_number < 0) { qat_log(LOG_LEVEL_ERROR, "Cannot find bank number for sym instance\n"); qat_mgr_cleanup_cfg(); return -1; } cy_inst->sym.ring_tx = 0; cy_inst->sym.ring_rx = 1; cy_inst->sym.is_polled = 1; cy_inst->sym.num_concurrent_requests = 512; cy_inst->sym.core_affinity = get_core_affinity(device_data->node); } dc_inst = device_data->dc_instance_data; for (k = 0; k < device_data->num_dc_inst; k++, dc_inst++) { snprintf(dc_inst->name, sizeof(dc_inst->name), "dc%d", section_num_dc_inst++); dc_inst->accelid = device_data->accelid; dc_inst->service_type = SERV_TYPE_DC; dc_inst->bank_number = calculate_bank_number( COMP, k, ring_to_svc_map, INSTANCES_PER_DEVICE); if (dc_inst->bank_number < 0) { qat_log(LOG_LEVEL_ERROR, "Cannot find bank number for dc instance\n"); qat_mgr_cleanup_cfg(); return -1; } dc_inst->ring_tx = 0; dc_inst->ring_rx = 1; dc_inst->is_polled = 1; dc_inst->num_concurrent_requests = MAX_NUM_CONCURRENT_REQUEST; dc_inst->core_affinity = get_core_affinity(device_data->node); } /* This will execute only if decomp configuration service * is enabled. If not then num_decomp_inst must be zero.*/ decomp_inst = device_data->decomp_instance_data; for (k = 0; k < device_data->num_decomp_inst; k++, decomp_inst++) { snprintf(decomp_inst->name, sizeof(decomp_inst->name), "decomp%d", section_num_decomp_inst++); decomp_inst->accelid = device_data->accelid; decomp_inst->service_type = SERV_TYPE_DECOMP; decomp_inst->bank_number = calculate_bank_number( DECOMP, k, ring_to_svc_map, INSTANCES_PER_DEVICE); decomp_inst->ring_tx = 0; decomp_inst->ring_rx = 1; decomp_inst->is_polled = 1; decomp_inst->num_concurrent_requests = MAX_NUM_CONCURRENT_REQUEST; decomp_inst->core_affinity = get_core_affinity(device_data->node); } } } return 0; } bool qat_mgr_is_vfio_dev_available(void) { struct dirent **devvfio_dir; struct dirent **sysdevice_dir; struct dirent *vfio_entry; struct dirent *device_entry; FILE *sysfile; int sysfile_fd; char devices_dir_name[256]; bool dev_found = false; char filename[256]; unsigned int device; uint32_t vfio_dir_name_len, device_dir_name_len; uint32_t buf_size = 0, str_len = 0; int num_vfio_group, num_vfio_device, i, j; char *vfio_file_name = NULL; num_vfio_group = scandir(DEVVFIO_DIR, &devvfio_dir, filter_vfio_files, alphasort); if (num_vfio_group < 0) { return false; } /* For each entry in /dev/vfio/ */ for (i = 0; i < num_vfio_group; i++) { vfio_entry = devvfio_dir[i]; /* If any QAT device was found, quit immediately */ if (dev_found) break; /* /dev/vfio/vfio is special entry, should be skipped */ if (!ICP_STRNCMP_CONST(vfio_entry->d_name, VFIO_ENTRY)) continue; /* * For noiommu, the file name has the format of noiommu- in * /dev/vfio. Remove the noiommu- prefix when accessing * /sys/kernel/iommu-groups// directory. */ vfio_file_name = vfio_entry->d_name; if (!ICP_STRNCMP(vfio_file_name, VFIO_NOIOMMU, strlen(VFIO_NOIOMMU))) vfio_file_name = vfio_entry->d_name + strlen(VFIO_NOIOMMU); /* open dir /sys/kernel/iommu_groups//devices/ */ buf_size = sizeof(devices_dir_name) - (sizeof(IOMMUGROUP_DEV_DIR) - 1) + STR_FORMAT_SPECIFIER_LEN; str_len = strnlen(vfio_entry->d_name, sizeof(vfio_entry->d_name)); if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy device file name\n"); continue; } snprintf(devices_dir_name, sizeof(devices_dir_name), IOMMUGROUP_DEV_DIR, buf_size - 1, vfio_file_name); num_vfio_device = scandir( devices_dir_name, &sysdevice_dir, filter_vfio_files, alphasort); if (num_vfio_device < 0) { continue; } /* For each device in this group. Should only be one. */ for (j = 0; j < num_vfio_device; j++) { device_entry = sysdevice_dir[j]; /* Open /sys/kernel/iommu_groups//devices//device */ vfio_dir_name_len = strnlen(vfio_entry->d_name, sizeof(vfio_entry->d_name)); device_dir_name_len = strnlen(device_entry->d_name, sizeof(device_entry->d_name)); buf_size = sizeof(filename) - (sizeof(DEVICE_FILE) - 1) + (NUM_STR_FORMAT_SPECIFIER * STR_FORMAT_SPECIFIER_LEN); str_len = vfio_dir_name_len + device_dir_name_len; if (buf_size <= str_len) { qat_log(LOG_LEVEL_ERROR, "Failed to copy device file name\n"); break; } snprintf(filename, sizeof(filename), DEVICE_FILE, VFIO_FILE_SIZE, vfio_file_name, (buf_size - VFIO_FILE_SIZE - 1), device_entry->d_name); sysfile_fd = open_file_with_link_check(filename, O_RDONLY); if (sysfile_fd < 0) break; sysfile = fdopen(sysfile_fd, "r"); if (!sysfile) { close(sysfile_fd); break; } device = 0; if (fscanf(sysfile, "%x", &device) != 1) { qat_log(LOG_LEVEL_INFO, "Failed to read device from %s\n", filename); /* * If the fscanf fails, the check of device ids below will fail * and we will check next dev. */ } fclose(sysfile); qat_log(LOG_LEVEL_INFO, "Checking %s\n", filename); if (is_qat_device(device)) { dev_found = true; break; } } for (j = 0; j < num_vfio_device; j++) { free(sysdevice_dir[j]); } free(sysdevice_dir); } for (i = 0; i < num_vfio_group; i++) { free(devvfio_dir[i]); } free(devvfio_dir); return dev_found; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/000077500000000000000000000000001503624047500264535ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_dev_ring_ctl.h000066400000000000000000000100541503624047500320750ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef ADF_DEV_RING_CTL_H #define ADF_DEV_RING_CTL_H #define OSAL_DEV_DRV_COMMON_H #include #include #include #define EMPTY_RING_SIG_BYTE 0x7f #define EMPTY_RING_SIG_WORD 0x7f7f7f7f #define BYTESPERWORD 4 typedef struct adf_dev_bank_handle_s { uint32_t accel_num; uint32_t bank_number; unsigned int bank_offset; /* offset from base addr (bank_sz * bank_nu) */ uint32_t interrupt_mask; uint32_t pollingMask; void *user_bank_lock; uint16_t tx_rings_mask; uint16_t ring_mask; /* enabled rings */ uint32_t *csr_addr; uint32_t *csr_addr_shadow; void *bundle; struct adf_dev_ring_handle_s **rings; /* ring handle for this banks */ uint32_t num_rings_per_bank; /* maximum number of rings per bank */ int refs; /* reference count */ } adf_dev_bank_handle_t; typedef struct adf_dev_ring_handle_s { icp_accel_dev_t *accel_dev; icp_transport_type trans_type; char *service_name; uint32_t service_name_len; char *section_name; uint32_t section_name_len; uint32_t accel_num; uint32_t bank_num; uint32_t bank_offset; /* offset from base addr (bank_sz * bank_nu) */ uint32_t ring_num; uint32_t ring_size; uint32_t message_size; uint64_t send_seq; /* packet sequence number */ adf_ring_queue_mode_t ringMode; icp_adf_ringInfoService_t info; icp_trans_callback callback; icp_resp_deliv_method resp; /* Result Parameters */ void *ring_virt_addr; uint64_t ring_phys_base_addr; uint32_t interrupt_user_mask; uint32_t pollingMask; uint32_t is_wireless : 1; adf_dev_bank_handle_t *bank_data; /* userspace shadow values */ void *user_lock; uint32_t head; uint32_t tail; uint32_t space; uint32_t modulo; uint32_t ringResponseQuota; int64_t pollingInProgress; Cpa32U *in_flight; uint32_t max_requests_inflight; uint32_t coal_write_count; uint32_t min_resps_per_head_write; /* the offset of the actual csr tail */ uint32_t csrTailOffset; uint32_t *csr_addr; } adf_dev_ring_handle_t; #define IS_RING_IN_WQ_MODE(ring) ((ring)->ringMode == ADF_RING_WQ_MODE) #endif /* ADF_DEV_RING_CTL_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_devmgr.h000066400000000000000000000121771503624047500307320ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /****************************************************************************** * @file adf_devmgr.h * * @description * This is the header file for the ADF Accelerated Device Manager. * This file contains function prototypes to manage and access devices. * *****************************************************************************/ #ifndef ADF_DEVMGR_H #define ADF_DEVMGR_H /****************************************************************************** * Include public/global header files ******************************************************************************/ #include "cpa.h" #include "icp_accel_devices.h" /* Device get & put commands */ #define DEV_PUT_CMD 0 #define DEV_GET_CMD 1 /****************************************************************************** * Section for interface function prototypes ******************************************************************************/ /****************************************************************************** * @description * Add a new accelerator to the Accelerator Table * *****************************************************************************/ CpaStatus adf_devmgrAddAccelDev(icp_accel_dev_t *pAccel_dev); /****************************************************************************** * @description * Remove an accelerator structure from the Accelerator Table * *****************************************************************************/ CpaStatus adf_devmgrRemoveAccelDev(icp_accel_dev_t *pAccel_dev); /****************************************************************************** * @description * Get the head of the Accelerator Table structure * *****************************************************************************/ CpaStatus adf_devmgrGetAccelHead(icp_accel_dev_t **pAccel_dev); /****************************************************************************** * @description * Check the accel table for a structure that contains the PCI device * Returns a pointer to the accelerator structure or NULL if not found. * *****************************************************************************/ icp_accel_dev_t *adf_devmgrGetAccelDev(void *pdev); /****************************************************************************** * @description * Gets the accel_dev structure based on accelId * Returns a pointer to the accelerator structure or NULL if not found. * *****************************************************************************/ icp_accel_dev_t *adf_devmgrGetAccelDevByAccelId(Cpa32U accelId); /****************************************************************************** * @description * Checks if there is an acceleration device with the given accelId * in the system * *****************************************************************************/ CpaStatus adf_devmgrVerifyAccelId(Cpa32U accelId); /****************************************************************************** * @description * * Initialise that accel table *****************************************************************************/ CpaStatus adf_devmgrInit(void); /****************************************************************************** * @description * * Uninitialise that accel table *****************************************************************************/ void adf_devmgrExit(void); #endif /* ADF_DEVMGR_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_init.h000066400000000000000000000120401503624047500303760ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /****************************************************************************** * @file adf_init.h * * @description * This header file that contains the prototypes and definitions required * for ADF initialisation. * *****************************************************************************/ #ifndef ADF_INIT_H #define ADF_INIT_H #include "icp_accel_devices.h" /* * Initialisation value for the adfModuleId, a value of 0 implies ADF has * not registered the version information with the DCC component. */ #define VERSION_INFO_UNREGISTERED 0 /* * This macro sets the specified bit in status to 1 * i.e. set the bit */ #define SET_STATUS_BIT(status, bit) status |= (1 << bit) /* * This macro sets the specified bit in status to 0 * i.e. clears the bit */ #define CLEAR_STATUS_BIT(status, bit) status &= ~(1 << bit) /* * This macro checks if the specified bit in status is set or not. */ #define BIT_IS_SET(status, bit) (status & (1 << bit)) /* * Pending time in ms that ADF will sleep before sending shutdown * when a subsystem return pending on stop */ #define PENDING_DELAY 100 /** ***************************************************************************** * @description * This function will initialise the AEs, map the firmware, * send an init event to the subservice and call adf_subsystemStart. * *****************************************************************************/ CpaStatus adf_subsystemInit(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function will download the Ucode, start the AEs and send * a start event to the subservices * *****************************************************************************/ CpaStatus adf_subsystemStart(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function will load the firmware, patch the previously loaded * symbols and send a start event to the subservices * *****************************************************************************/ CpaStatus adf_subsystemResume(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function will stop the subcomponents in the system, * and free resources for ISR and firmware loading that have been allocated * *****************************************************************************/ CpaStatus adf_subsystemStop(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This is a wrapper function to adf_subsystemStop called when the OS * issues a suspend. * *****************************************************************************/ CpaStatus adf_subsystemSuspend(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function will shutdown the subcomponents in the system. * *****************************************************************************/ CpaStatus adf_subsystemShutdown(icp_accel_dev_t *accel_dev); #endif /* ADF_INIT_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_platform.h000066400000000000000000000043331503624047500312650ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_platform.h * * @description * The file includes platform specific headers * *****************************************************************************/ #ifndef ADF_PLATFORM_H #define ADF_PLATFORM_H #include "adf_platform_common.h" #include "adf_platform_acceldev_common.h" #endif /* ADF_PLATFORM_H */ adf_platform_acceldev_common.h000066400000000000000000000215201503624047500344010ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_platform_acceldev_common.h * * @description * This file contains the platform specific macros for DH89xxCC that are * common for PF and VF * *****************************************************************************/ #ifndef ADF_PLATFORM_ACCELDEV_COMMON_H #define ADF_PLATFORM_ACCELDEV_COMMON_H /***************************************************************************** * Define Constants and Macros *****************************************************************************/ /* Coalesced Interrupt Enable */ #define ETR_CSR_INTR_COL_CTL_ENABLE 0x80000000 /* Ring Csrs offsets */ #define ICP_RING_CSR_RING_CONFIG 0x000 #define ICP_RING_CSR_RING_LBASE 0x040 #define ICP_RING_CSR_RING_UBASE 0x080 #define ICP_RING_CSR_RING_HEAD_OFFSET 0x0C0 #define ICP_RING_CSR_RING_TAIL_OFFSET 0x100 #define ICP_RING_CSR_RING_STAT 0x140 #define ICP_RING_CSR_UO_STAT 0x148 #define ICP_RING_CSR_E_STAT 0x14C #define ICP_RING_CSR_NE_STAT 0x150 #define ICP_RING_CSR_NF_STAT 0x154 #define ICP_RING_CSR_F_STAT 0x158 #define ICP_RING_CSR_C_STAT 0x15C #define ICP_RING_CSR_INT_EN 0x16C #define ICP_RING_CSR_INT_COL_EN 0x17C #define ICP_RING_CSR_INT_COL_CTL 0x180 #define ICP_RING_CSR_FLAG_AND_COL_EN 0x184 #define ICP_RING_CSR_RING_SRV_ARB_EN 0x19C /* RingConfig CSR Parameter Watermark Offsets */ #define RING_CONFIG_NEAR_FULL_WM 0x0A #define RING_CONFIG_NEAR_EMPTY_WM 0x05 /* Default RingConfig is Nearly Full = Full and Nearly Empty = Empty */ #define BUILD_RING_CONFIG(size) \ ((ICP_RING_NEAR_WATERMARK_0 << RING_CONFIG_NEAR_FULL_WM) | \ (ICP_RING_NEAR_WATERMARK_0 << RING_CONFIG_NEAR_EMPTY_WM) | size) /* Response Ring Configuration */ #define BUILD_RESP_RING_CONFIG(size, watermark_nf, watermark_ne) \ ((watermark_nf << RING_CONFIG_NEAR_FULL_WM) | \ (watermark_ne << RING_CONFIG_NEAR_EMPTY_WM) | size) /* All Ring Base Addresses are 64 byte aligned, thus * bits[43:0] of the RingBase register correspond to * bits[49:6] of the Rings Memory Address. */ #define BUILD_RING_BASE_ADDR(addr, size) \ ((addr >> 6) & (0xFFFFFFFFFFFFFFFFULL << size)) /* CSR read/write macros */ #define READ_CSR_RING_CONFIG(bank_offset, ring) \ ICP_ADF_CSR_RD(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_CONFIG + (ring << 2)) #define READ_CSR_RING_HEAD(bank_offset, ring) \ ICP_ADF_CSR_RD(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_HEAD_OFFSET + (ring << 2)) #define READ_CSR_RING_TAIL(bank_offset, ring) \ ICP_ADF_CSR_RD(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_TAIL_OFFSET + (ring << 2)) #define READ_CSR_E_STAT(bank_offset) \ ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_E_STAT) #define READ_CSR_E_STAT_EXT(csr_base_addr, bank_offset) \ ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_E_STAT) #define READ_CSR_NE_STAT(bank_offset) \ ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_NE_STAT) #define READ_CSR_NF_STAT(bank_offset) \ ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_NF_STAT) #define READ_CSR_F_STAT(bank_offset) \ ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_F_STAT) #define READ_CSR_INT_EN(bank_offset) \ ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_INT_EN) #define WRITE_CSR_RING_CONFIG(bank_offset, ring, value) \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_CONFIG + (ring << 2), \ value) #define WRITE_CSR_RING_BASE(bank_offset, ring, value) \ do \ { \ Cpa32U l_base = 0, u_base = 0; \ l_base = (Cpa32U)(value & 0xFFFFFFFF); \ u_base = (Cpa32U)((value & 0xFFFFFFFF00000000ULL) >> 32); \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_LBASE + (ring << 2), \ l_base); \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_UBASE + (ring << 2), \ u_base); \ } while (0) static inline Cpa64U read_base(Cpa32U *csr_base_addr, Cpa32U bank_offset, Cpa32U ring) { Cpa32U l_base = ICP_ADF_CSR_RD( csr_base_addr, bank_offset + ICP_RING_CSR_RING_LBASE + (ring << 2)); Cpa32U u_base = ICP_ADF_CSR_RD( csr_base_addr, bank_offset + ICP_RING_CSR_RING_UBASE + (ring << 2)); Cpa64U addr = (l_base & 0xFFFFFFFF); addr |= ((((Cpa64U)u_base) << 32) & 0xFFFFFFFF00000000ULL); return addr; } #define WRITE_CSR_RING_HEAD(csr_base_addr, bank_offset, ring, value) \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_HEAD_OFFSET + (ring << 2), \ value) #define WRITE_CSR_RING_TAIL(csr_base_addr, bank_offset, ring, value) \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_TAIL_OFFSET + (ring << 2), \ value) #define WRITE_CSR_INT_COL_EN(bank_offset, value) \ ICP_ADF_CSR_WR(csr_base_addr, bank_offset + ICP_RING_CSR_INT_COL_EN, value) #define WRITE_CSR_INT_COL_EN_EXT(csr_base_addr, bank_offset, value) \ ICP_ADF_CSR_WR(csr_base_addr, bank_offset + ICP_RING_CSR_INT_COL_EN, value) #define WRITE_CSR_INT_COL_CTL(bank_offset, value) \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_INT_COL_CTL, \ ETR_CSR_INTR_COL_CTL_ENABLE | value) #define WRITE_CSR_INT_FLAG_AND_COL(bank_offset, value) \ ICP_ADF_CSR_WR( \ csr_base_addr, bank_offset + ICP_RING_CSR_FLAG_AND_COL_EN, value) #endif /* ADF_PLATFORM_ACCELDEV_COMMON_H */ adf_platform_acceldev_gen4.h000066400000000000000000000125711503624047500337540ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_platform_acceldev_gen4.h * * @description * This file contains the platform specific macros for GEN4 that are * common for PF and VF * *****************************************************************************/ #ifndef ADF_PLATFORM_ACCELDEV_GEN4_H #define ADF_PLATFORM_ACCELDEV_GEN4_H #include "icp_accel_devices.h" /***************************************************************************** * Define Constants and Macros *****************************************************************************/ /* Ring Csrs offsets */ #define ICP_RING_CSR_RING_CONFIG_GEN4 0x1000 #define ICP_RING_CSR_RING_LBASE_GEN4 0x1040 #define ICP_RING_CSR_RING_UBASE_GEN4 0x1080 #define ICP_RING_CSR_RING_STAT_GEN4 0x0140 #define CSR_RING_STAT_RL_EXCEPTION_MASK (0x1UL << 10) #define CSR_RING_STAT_RL_HALT_MASK (0x1UL << 9) /* Ring Base Address */ #define BUILD_RING_BASE_ADDR_GEN4(addr, size) \ (((addr >> 6) & (0xFFFFFFFFFFFFFFFFULL << size)) << 6) /* CSR read/write macros */ #define READ_CSR_RING_CONFIG_GEN4(csr_base_addr, bank_offset, ring) \ ICP_ADF_CSR_RD(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_CONFIG_GEN4 + (ring << 2)) #define WRITE_CSR_RING_CONFIG_GEN4(csr_base_addr, bank_offset, ring, value) \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_CONFIG_GEN4 + (ring << 2), \ value) #define WRITE_CSR_RING_BASE_GEN4(csr_base_addr, bank_offset, ring, value) \ do \ { \ Cpa32U l_base = 0, u_base = 0; \ l_base = (Cpa32U)(value & 0xFFFFFFFF); \ u_base = (Cpa32U)((value & 0xFFFFFFFF00000000ULL) >> 32); \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_LBASE_GEN4 + \ (ring << 2), \ l_base); \ ICP_ADF_CSR_WR(csr_base_addr, \ bank_offset + ICP_RING_CSR_RING_UBASE_GEN4 + \ (ring << 2), \ u_base); \ } while (0) #define READ_CSR_RING_STATUS_GEN4(csr_base_addr, bank_offset) \ ICP_ADF_CSR_RD(csr_base_addr, (bank_offset) + ICP_RING_CSR_RING_STAT_GEN4) static inline Cpa64U read_base_gen4(Cpa32U *csr_base_addr, Cpa32U bank_offset, Cpa32U ring) { Cpa32U l_base = ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_RING_LBASE_GEN4 + (ring << 2)); Cpa32U u_base = ICP_ADF_CSR_RD(csr_base_addr, bank_offset + ICP_RING_CSR_RING_UBASE_GEN4 + (ring << 2)); Cpa64U addr = (l_base & 0xFFFFFFFF); addr |= ((((Cpa64U)u_base) << 32) & 0xFFFFFFFF00000000ULL); return addr; } #endif /* ADF_PLATFORM_ACCELDEV_GEN4_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_platform_common.h000066400000000000000000000333741503624047500326440ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_platform_common.h * * @description * This file contains the macros common to supported platform(s). * *****************************************************************************/ #ifndef ADF_PLATFORM_COMMON_H #define ADF_PLATFORM_COMMON_H /* Number of Rings Per Bank */ #define ICP_ETR_MAX_RINGS_PER_BANK 16 #define ICP_ADF_BYTES_PER_WORD 4 /* Ring size values. Name reflects num bytes, value is for RingBufferSize field * in RingConfig CSR */ #define ICP_RINGSIZE_64 0x00 #define ICP_RINGSIZE_128 0x01 #define ICP_RINGSIZE_256 0x02 #define ICP_RINGSIZE_512 0x03 #define ICP_RINGSIZE_KILO_1 0x04 #define ICP_RINGSIZE_KILO_2 0x05 #define ICP_RINGSIZE_KILO_4 0x06 #define ICP_RINGSIZE_KILO_8 0x07 #define ICP_RINGSIZE_KILO_16 0x08 #define ICP_RINGSIZE_KILO_32 0x09 #define ICP_RINGSIZE_KILO_64 0x0A #define ICP_RINGSIZE_KILO_128 0x0B #define ICP_RINGSIZE_KILO_256 0x0C #define ICP_RINGSIZE_KILO_512 0x0D #define ICP_RINGSIZE_MEG_1 0x0E #define ICP_RINGSIZE_MEG_2 0x0F #define ICP_RINGSIZE_MEG_4 0x10 /* Ring Near Full/Empty watermarks values */ #define ICP_RING_NEAR_WATERMARK_0 0x00 #define ICP_RING_NEAR_WATERMARK_4 0x01 #define ICP_RING_NEAR_WATERMARK_8 0x02 #define ICP_RING_NEAR_WATERMARK_16 0x03 #define ICP_RING_NEAR_WATERMARK_32 0x04 #define ICP_RING_NEAR_WATERMARK_64 0x05 #define ICP_RING_NEAR_WATERMARK_128 0x06 #define ICP_RING_NEAR_WATERMARK_256 0x07 #define ICP_RING_NEAR_WATERMARK_512 0x08 #define ICP_RING_NEAR_WATERMARK_KILO_1 0x09 #define ICP_RING_NEAR_WATERMARK_KILO_2 0x0A #define ICP_RING_NEAR_WATERMARK_KILO_4 0x0B #define ICP_RING_NEAR_WATERMARK_KILO_8 0x0C #define ICP_RING_NEAR_WATERMARK_KILO_16 0x0D #define ICP_RING_NEAR_WATERMARK_KILO_32 0x0E #define ICP_RING_NEAR_WATERMARK_KILO_64 0x0F #define ICP_RING_NEAR_WATERMARK_KILO_128 0x10 #define ICP_RING_NEAR_WATERMARK_KILO_256 0x11 /* Bundle size */ #define ICP_BUNDLE_SIZE 0x1000 /* For coalescing based on number of messages define the required ring message * count, and the limits on the allowed thresholds. */ #define ICP_NUM_COAL_MSG_CNT 256 #define ICP_NUM_COAL_MSG_MIN_USED 2 #define ICP_NUM_COAL_MSG_MIN_FREE 8 /* Interrupt source values */ #define INT_SRC_N_FULL_TRUE 2 #define INT_SRC_EMPTY_FALSE 4 #define INT_SRC_N_EMPTY_FALSE 5 /* Defines for the IAIntSrcSel register setup */ #define IAINTSRCSEL_REG_MAX_RING_IN_REG 7 #define IAINTSRCSEL_REG_RINGS_PER_REG 8 #define IAINTSRCSEL_REG_BITSPERRING 4 #define IAINTSRCSEL_REG_IRQ_MODE_BIT 3 #define IAINTSRCSEL_REG_RING_VAL_MASK 0xF /* Modulo shifts for different ring sizes */ #define MODULO_SHIFT_FOR_64 6 #define MODULO_SHIFT_FOR_128 7 #define MODULO_SHIFT_FOR_256 8 #define MODULO_SHIFT_FOR_512 9 #define MODULO_SHIFT_FOR_1K 10 #define MODULO_SHIFT_FOR_2K 11 #define MODULO_SHIFT_FOR_4K 12 #define MODULO_SHIFT_FOR_8K 13 #define MODULO_SHIFT_FOR_16K 14 #define MODULO_SHIFT_FOR_32K 15 #define MODULO_SHIFT_FOR_64K 16 #define MODULO_SHIFT_FOR_128K 17 #define MODULO_SHIFT_FOR_256K 18 #define MODULO_SHIFT_FOR_512K 19 #define MODULO_SHIFT_FOR_1M 20 #define MODULO_SHIFT_FOR_2M 21 #define MODULO_SHIFT_FOR_4M 22 /* Ring size conversion - only for use with ICP_RINGSIZE_xxx cfg values above */ #define ICP_ET_SIZE_TO_BYTES(size) (64 << (size)) /* Ring watermark conversion */ #define ICP_ET_WATERMARK_TO_BYTES(wm) ((wm == 0) ? 0 : (4 << (wm - 1))) /* Default ring size */ #define ICP_ET_DEFAULT_RING_SIZE ICP_RINGSIZE_KILO_16 /* Default modulo shift - must correspond to the default ring size */ #define ICP_ET_DEFAULT_MODULO_SHIFT MODULO_SHIFT_FOR_16K #define ADF_MSG_SIZE_64_BYTES 64 #define ADF_MSG_SIZE_128_BYTES 128 /* Default message size in bytes */ #define ICP_ET_DEFAULT_MSG_SIZE ADF_MSG_SIZE_64_BYTES /* Minimum ring free space is the size of one msg on the ring plus this value */ #define ICP_ET_RING_MIN_FREE_SPACE_ADDON 1 /* Set the response quota to a high number. */ #define ICP_NO_RESPONSE_QUOTA 10000 /* Translates from a ringNum (integer) to a ringmaskId (bit mask) */ #define RING_NUMBER_TO_ID(ring_num) (1 << ring_num) /* * Internal parameter to describe user polling method in kernel space. * This must be set to a value higher than the max icp_resp_deliv_method. * and less than the width of the Cpa32U type. */ #define ADF_RESP_TYPE_USER_POLL 31 /* Number of responses we need to get before we update the head * in a Rx ring. NOTE: this needs to be smaller than * min ring size - 8 msg for NF threshold. */ #define MIN_RESPONSES_PER_HEAD_WRITE 32 /* * Fast message copy functions for userspace * * There are several versions of fast memcpy, i.e. adf_memcpyxx_yy * xx refers to arch, i.e.64bit or 32bit * yy refers to number of bytes copied from src to dst, i.e. 64 or 128 bytes */ #ifdef __x86_64__ #define adf_memcpy64_64(dst, src) \ do \ { \ __asm__ __volatile__("mov %0, %%rsi \n" \ "mov %1, %%rdi \n" \ "movdqu (%%rsi), %%xmm0 \n" \ "movdqu 16(%%rsi), %%xmm1 \n" \ "movdqu 32(%%rsi), %%xmm2 \n" \ "movdqu 48(%%rsi), %%xmm3 \n" \ "movdqu %%xmm0, (%%rdi) \n" \ "movdqu %%xmm1, 16(%%rdi) \n" \ "movdqu %%xmm2, 32(%%rdi) \n" \ "movdqu %%xmm3, 48(%%rdi) \n" \ : /* no output */ \ : "r"(src), "r"(dst) \ : "%esi", "%edi"); \ } while (0); #define adf_memcpy64_128(dst, src) \ do \ { \ __asm__ __volatile__("mov %0, %%rsi \n" \ "mov %1, %%rdi \n" \ "movdqu (%%rsi), %%xmm0 \n" \ "movdqu 16(%%rsi), %%xmm1 \n" \ "movdqu 32(%%rsi), %%xmm2 \n" \ "movdqu 48(%%rsi), %%xmm3 \n" \ "movdqu 64(%%rsi), %%xmm4 \n" \ "movdqu 80(%%rsi), %%xmm5 \n" \ "movdqu 96(%%rsi), %%xmm6 \n" \ "movdqu 112(%%rsi), %%xmm7 \n" \ "movdqu %%xmm0, (%%rdi) \n" \ "movdqu %%xmm1, 16(%%rdi) \n" \ "movdqu %%xmm2, 32(%%rdi) \n" \ "movdqu %%xmm3, 48(%%rdi) \n" \ "movdqu %%xmm4, 64(%%rdi) \n" \ "movdqu %%xmm5, 80(%%rdi) \n" \ "movdqu %%xmm6, 96(%%rdi) \n" \ "movdqu %%xmm7, 112(%%rdi) \n" \ : /* no output */ \ : "r"(src), "r"(dst) \ : "%esi", "%edi"); \ } while (0); #define adf_memcpy64 adf_memcpy64_64 #define adf_memcpy128 adf_memcpy64_128 #else /* * 32bit versions of fast memcpy */ #define adf_memcpy32_64(dst, src) \ do \ { \ __asm__ __volatile__("mov %0, %%esi \n" \ "mov %1, %%edi \n" \ "movdqu (%%esi), %%xmm0 \n" \ "movdqu 16(%%esi), %%xmm1 \n" \ "movdqu 32(%%esi), %%xmm2 \n" \ "movdqu 48(%%esi), %%xmm3 \n" \ "movdqu %%xmm0, (%%edi) \n" \ "movdqu %%xmm1, 16(%%edi) \n" \ "movdqu %%xmm2, 32(%%edi) \n" \ "movdqu %%xmm3, 48(%%edi) \n" \ : /* no output */ \ : "r"(src), "r"(dst) \ : "%esi", "%edi"); \ } while (0); #define adf_memcpy32_128(dst, src) \ do \ { \ __asm__ __volatile__("mov %0, %%esi \n" \ "mov %1, %%edi \n" \ "movdqu (%%esi), %%xmm0 \n" \ "movdqu 16(%%esi), %%xmm1 \n" \ "movdqu 32(%%esi), %%xmm2 \n" \ "movdqu 48(%%esi), %%xmm3 \n" \ "movdqu 64(%%esi), %%xmm4 \n" \ "movdqu 80(%%esi), %%xmm5 \n" \ "movdqu 96(%%esi), %%xmm6 \n" \ "movdqu 112(%%esi), %%xmm7 \n" \ "movdqu %%xmm0, (%%edi) \n" \ "movdqu %%xmm1, 16(%%edi) \n" \ "movdqu %%xmm2, 32(%%edi) \n" \ "movdqu %%xmm3, 48(%%edi) \n" \ "movdqu %%xmm4, 64(%%edi) \n" \ "movdqu %%xmm5, 80(%%edi) \n" \ "movdqu %%xmm6, 96(%%edi) \n" \ "movdqu %%xmm7, 112(%%edi) \n" \ : /* no output */ \ : "r"(src), "r"(dst) \ : "%esi", "%edi"); \ } while (0); #define adf_memcpy64 adf_memcpy32_64 #define adf_memcpy128 adf_memcpy32_128 #endif /* modulo function that doesn't use slow divide operation */ static inline unsigned int modulo(unsigned int data, unsigned int shift) { unsigned int div = data >> shift; unsigned int mult = div << shift; return data - mult; } /* Ring controller CSR Accessor Macros */ /* CSR write macro */ #define ICP_ADF_CSR_WR(csrAddr, csrOffset, val) \ (void)((*((volatile Cpa32U *)(((Cpa8U *)csrAddr) + csrOffset)) = (val))) /* CSR read macro */ #define ICP_ADF_CSR_RD(csrAddr, csrOffset) \ (*((volatile Cpa32U *)(((Cpa8U *)csrAddr) + csrOffset))) #endif /* ADF_PLATFORM_COMMON_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_user.h000066400000000000000000000104101503624047500304100ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef ADF_USER_H #define ADF_USER_H #include "adf_io_bundles.h" #include enum adf_device_type { DEV_UNKNOWN = 0, DEV_DH895XCC, DEV_DH895XCCVF, DEV_C62X, DEV_C62XVF, DEV_C3XXX, DEV_C3XXXVF, DEV_D15XX, DEV_D15XXVF }; enum adf_cfg_val_type { ADF_DEC, ADF_HEX, ADF_STR }; enum adf_device_heartbeat_status { DEV_HB_UNRESPONSIVE = 0, DEV_HB_ALIVE, DEV_HB_UNSUPPORTED }; struct adf_dev_heartbeat_status_ctl { uint32_t device_id; enum adf_device_heartbeat_status status; }; struct adf_dev_miscellaneous_stats { uint64_t misc_counter; }; #define ADF_CTL_IOC_MAGIC 'a' #define IOCTL_GET_NUM_DEVICES _IOW(ADF_CTL_IOC_MAGIC, 4, int32_t) #define IOCTL_HEARTBEAT_ACCEL_DEV \ _IOW(ADF_CTL_IOC_MAGIC, 15, struct adf_dev_heartbeat_status_ctl) #ifdef QAT_HB_FAIL_SIM #define IOCTL_HEARTBEAT_SIM_FAIL _IOW(ADF_CTL_IOC_MAGIC, 99, uint32_t) #endif #define IOCTL_STATUS_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 3, uint32_t) #define IOCTL_GET_CFG_VAL \ _IOW(ADF_CTL_IOC_MAGIC, 5, struct adf_user_cfg_ctl_data) #define IOCTL_RESET_ACCEL_DEV \ _IOW(ADF_CTL_IOC_MAGIC, 10, struct adf_user_cfg_ctl_data) struct adf_dev_status_info { enum adf_device_type type; uint32_t accel_id; uint32_t instance_id; uint8_t num_ae; uint8_t num_accel; uint8_t num_logical_accel; uint8_t banks_per_accel; uint8_t state; uint8_t bus; uint8_t dev; uint8_t fun; char name[MAX_DEVICE_NAME_SIZE]; uint32_t node_id; int domain; }; struct adf_user_cfg_key_val { char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES]; char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; union { struct adf_user_cfg_key_val *next; uint64_t padding3; }; enum adf_cfg_val_type type; }; struct adf_user_cfg_section { char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES]; union { struct adf_user_cfg_key_val *params; uint64_t padding1; }; union { struct adf_user_cfg_section *next; uint64_t padding3; }; }; struct adf_user_cfg_ctl_data { union { struct adf_user_cfg_section *config_section; uint64_t padding; }; uint32_t device_id; }; int32_t adf_init_devices(void); CpaStatus adf_proxy_get_devices(void); int32_t adf_cleanup_devices(void); #endif /* end of include guard: ADF_USER_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_arbiter.h000066400000000000000000000067301503624047500321320ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_user_arbiter.h * * @description * This file contains the arbiter related interfaces * *****************************************************************************/ #ifndef ADF_USER_ARBITER_H #define ADF_USER_ARBITER_H #include #include #define ICP_ARB_REG_SLOT 0x1000 #define ICP_ARB_RINGSRVARBEN_OFFSET_START 0x19C #define READ_CSR_ARB_RINGSRVARBEN(csr_base_addr, index) \ ICP_ADF_CSR_RD(csr_base_addr, \ ICP_ARB_RINGSRVARBEN_OFFSET_START + \ ICP_ARB_REG_SLOT * index) #define WRITE_CSR_ARB_RINGSRVARBEN(csr_base_addr, index, value) \ ICP_ADF_CSR_WR(csr_base_addr, \ ICP_ARB_RINGSRVARBEN_OFFSET_START + \ ICP_ARB_REG_SLOT * index, \ value) static __inline__ void adf_update_ring_arb_enable(adf_dev_ring_handle_t *ring) { int32_t status; /* Lock the register to enable/disable arbiter */ status = ICP_MUTEX_LOCK(ring->bank_data->user_bank_lock); if (status) { ADF_ERROR("Failed to lock bank with error %d\n", status); return; } WRITE_CSR_ARB_RINGSRVARBEN( ring->csr_addr, 0, ring->bank_data->ring_mask & 0xFF); ICP_MUTEX_UNLOCK(ring->bank_data->user_bank_lock); } #define adf_update_ring_arb_disable adf_update_ring_arb_enable #endif /* ADF_USER_ARBITER_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_cfg.h000066400000000000000000000045121503624047500312350ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #ifndef ADF_USER_CFG_H #define ADF_USER_CFG_H #include "icp_accel_devices.h" CpaStatus icp_adf_cfgGetParamValue(icp_accel_dev_t *accel_dev, const char *section, const char *param, char *value); Cpa16U icp_adf_cfgGetBusAddress(Cpa16U accelId); Cpa32S icp_adf_cfgGetDomainAddress(Cpa16U accelId); int icp_adf_cfgCheckUserSection(int dev_id, uint8_t *pSectionPresent); #endif /* end of include guard: ADF_USER_CFG_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_init.h000066400000000000000000000101271503624047500314400ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /****************************************************************************** * @file adf_user_init.h * * @description * This header file that contains the prototypes and definitions required * for ADF userspace initialisation. * *****************************************************************************/ #ifndef ADF_USER_INIT_H #define ADF_USER_INIT_H #include "icp_accel_devices.h" /** ***************************************************************************** * @description * This function will initialise the registered subcomponents. * *****************************************************************************/ CpaStatus adf_user_subsystemInit(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function will send a start event to the subcomponents * *****************************************************************************/ CpaStatus adf_user_subsystemStart(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function stops the registered subcomponents. * *****************************************************************************/ CpaStatus adf_user_subsystemStop(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function will shutdown the subcomponents in the system. * *****************************************************************************/ CpaStatus adf_user_subsystemShutdown(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function sends a resume event to registered subcomponents. * *****************************************************************************/ CpaStatus adf_user_subsystemResume(icp_accel_dev_t *accel_dev); /** ***************************************************************************** * @description * This function sends a suspend event to registered subcomponents. * *****************************************************************************/ CpaStatus adf_user_subsystemSuspend(icp_accel_dev_t *accel_dev); #endif /* ADF_USER_INIT_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_ring.h000066400000000000000000000075601503624047500314430ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_user_uio_ring.h * * @description * This file contains the ring related interfaces * *****************************************************************************/ #ifndef ADF_USER_RING_H #define ADF_USER_RING_H #include int32_t adf_init_ring(adf_dev_ring_handle_t *ring, adf_dev_bank_handle_t *bank, uint32_t ring_num, uint32_t *csr_base_addr, uint32_t num_msgs, uint32_t msg_size, int nodeid); int32_t adf_reinit_ring(adf_dev_ring_handle_t *ring, adf_dev_bank_handle_t *bank, uint32_t ring_num, uint32_t *csr_base_addr, uint32_t num_msgs, uint32_t msg_size, int nodeid); void adf_cleanup_ring(adf_dev_ring_handle_t *ring); void adf_reset_ring(adf_dev_ring_handle_t *ring); int32_t adf_ring_freebuf(adf_dev_ring_handle_t *ring); CpaStatus adf_user_put_msg(adf_dev_ring_handle_t *ring, uint32_t *inBuf, uint64_t *seq_num); /* * adf_user_check_ring_error * * Description * Function checks if the rp_exception or rp_halt bits are set in RINGSTAT * register * * Return value * -EINVAL if pRingHandle is NULL * -EINTR if the rp_exception bit is set * -EL2HLT if the rp_halt bit is set * -EFAULT if the RINGSTAT rp_exception is not supported * 0 if the rp_exception bit is not set */ int32_t adf_user_check_ring_error(adf_dev_ring_handle_t *pRingHandle); CpaBoolean adf_user_check_resp_ring(adf_dev_ring_handle_t *ring); CpaStatus adf_user_notify_msgs_poll(adf_dev_ring_handle_t *ring); int32_t adf_user_get_inflight_requests(adf_dev_ring_handle_t *ring, uint32_t *maxInflightRequests, uint32_t *numInflightRequests); #endif /* ADF_USER_RING_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/adf_user_transport.h000066400000000000000000000065151503624047500325370ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /****************************************************************************** * @file adf_user_transport.h * * @description * User space transport functions *****************************************************************************/ #ifndef ADF_USER_TRANSPORT_H #define ADF_USER_TRANSPORT_H #include "adf_dev_ring_ctl.h" /* * adf_user_unmap_rings * * Description * Function unmaps all rings allocated for a given device */ CpaStatus adf_user_unmap_rings(icp_accel_dev_t *accel_dev); /* * adf_pollRing * * Description * Internal functions which polls * a polling ring. This function does not check * to see if the ring is a polling ring or * if the ring exists. * */ CpaStatus adf_pollRing(icp_accel_dev_t *accel_dev, adf_dev_ring_handle_t *pRingHandle, Cpa32U response_quota); /* * adf_user_transport_init * * Description * Function initializes internal transport data */ CpaStatus adf_user_transport_init(icp_accel_dev_t *accel_dev); /* * adf_user_transport_reinit * * Description * Function reinitializes internal transport data */ CpaStatus adf_user_transport_reinit(icp_accel_dev_t *accel_dev); /* * adf_user_transport_exit * * Description * Function deinitializes internal transport data */ CpaStatus adf_user_transport_exit(icp_accel_dev_t *accel_dev); /* * adf_user_transport_clean * * Description * Function clean internal transport data */ CpaStatus adf_user_transport_clean(icp_accel_dev_t *accel_dev); #endif /* ADF_USER_TRANSPORT_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/icp_platform.h000066400000000000000000000472211503624047500313110ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file icp_platform.h * * @description * This file contains the common macros and includes OS platform * specific includes * *****************************************************************************/ #ifndef ICP_PLATFORM_H #define ICP_PLATFORM_H #include "icp_platform_user.h" /************************************************************ * OS Agnostic MACROS ************************************************************/ #ifndef SUCCESS #define SUCCESS 0 #endif #ifndef FAIL #define FAIL 1 #endif #ifdef ICP_PARAM_CHECK #define ICP_CHECK_FOR_NULL_PARAM(param) \ do \ { \ if (NULL == param) \ { \ ADF_ERROR("%s(): invalid param: %s\n", __FUNCTION__, #param); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) #define ICP_CHECK_FOR_NULL_PARAM_VOID(param) \ do \ { \ if (NULL == param) \ { \ ADF_ERROR("%s(): invalid param: %s\n", __FUNCTION__, #param); \ return; \ } \ } while (0) #define ICP_CHECK_PARAM_RANGE(param, min, max) \ do \ { \ if (param > max || param < min) \ { \ ADF_ERROR("%s(): invalid param: %s\n", __FUNCTION__, #param); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) #define ICP_CHECK_PARAM_LT_MAX(param, max) \ do \ { \ if (param >= max) \ { \ ADF_ERROR("%s(): invalid param: %s\n", __FUNCTION__, #param); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) #define ICP_CHECK_PARAM_GT_MIN(param, min) \ do \ { \ if (param <= min) \ { \ ADF_ERROR("%s(): invalid param: %s\n", __FUNCTION__, #param); \ return CPA_STATUS_INVALID_PARAM; \ } \ } while (0) #define ICP_CHECK_FOR_NULL_PARAM_RET_CODE(param, code) \ do \ { \ if (NULL == param) \ { \ ADF_ERROR("%s(): invalid param: %s\n", __FUNCTION__, #param); \ return code; \ } \ } while (0) #else #define ICP_CHECK_FOR_NULL_PARAM(param) #define ICP_CHECK_FOR_NULL_PARAM_VOID(param) #define ICP_CHECK_PARAM_RANGE(param, min, max) #define ICP_CHECK_PARAM_LT_MAX(param, max) #define ICP_CHECK_PARAM_GT_MIN(param, min) #define ICP_CHECK_FOR_NULL_PARAM_RET_CODE(param, code) #endif #define ICP_CHECK_STATUS(status) \ do \ { \ if (CPA_STATUS_SUCCESS != (status)) \ { \ return status; \ } \ } while (0) #define ICP_CHECK_STATUS_AND_LOG(status, format, args...) \ do \ { \ if (CPA_STATUS_SUCCESS != status) \ { \ ADF_ERROR(format, args); \ return CPA_STATUS_FAIL; \ } \ } while (0) #define ICP_CHECK_STATUS_AND_LOG_NORETURN(status, format, args...) \ do \ { \ if (CPA_STATUS_SUCCESS != status) \ { \ ADF_ERROR(format, args); \ } \ } while (0) /* Macro to try to find an element in a linked list. * The Macro compares pointer values between the pointer and the list * to determine if the pointer is in the list. */ #define ICP_FIND_ELEMENT_IN_LIST(elementtofind, listhead, status) \ do \ { \ if (NULL == listhead) \ { \ status = CPA_STATUS_FAIL; \ } \ while (listhead != NULL) \ { \ if (listhead == elementtofind) \ { \ status = CPA_STATUS_SUCCESS; \ break; \ } \ else \ { \ listhead = listhead->pNext; \ } \ } \ } while (0) /* Macro for adding an element to the tail of a doubly linked list */ /* The currentptr tracks the tail, and the headptr tracks the head */ #define ICP_ADD_ELEMENT_TO_END_OF_LIST(elementtoadd, currentptr, headptr) \ do \ { \ if (NULL == currentptr) \ { \ currentptr = elementtoadd; \ elementtoadd->pNext = NULL; \ elementtoadd->pPrev = NULL; \ headptr = currentptr; \ } \ else \ { \ elementtoadd->pPrev = currentptr; \ currentptr->pNext = elementtoadd; \ elementtoadd->pNext = NULL; \ currentptr = elementtoadd; \ } \ } while (0) /* currentptr is not used in this case since we don't track the tail */ #define ICP_ADD_ELEMENT_TO_HEAD_OF_LIST(elementtoadd, currentptr, headptr) \ do \ { \ if (NULL == headptr) \ { \ elementtoadd->pNext = NULL; \ elementtoadd->pPrev = NULL; \ headptr = elementtoadd; \ } \ else \ { \ elementtoadd->pPrev = NULL; \ elementtoadd->pNext = headptr; \ headptr->pPrev = elementtoadd; \ headptr = elementtoadd; \ } \ } while (0) #define ICP_REMOVE_ELEMENT_FROM_LIST(elementtoremove, currentptr, headptr) \ do \ { \ /* If the previous pointer is not NULL */ \ if (NULL != elementtoremove->pPrev) \ { \ elementtoremove->pPrev->pNext = elementtoremove->pNext; \ if (elementtoremove->pNext) \ { \ elementtoremove->pNext->pPrev = elementtoremove->pPrev; \ } \ else \ { \ /* Move the tail pointer backwards */ \ currentptr = elementtoremove->pPrev; \ } \ } \ else if (NULL != elementtoremove->pNext) \ { \ /* Remove the head pointer */ \ elementtoremove->pNext->pPrev = NULL; \ /* Hence move the head forward */ \ headptr = elementtoremove->pNext; \ } \ else \ { \ /* Remove the final entry in the list */ \ currentptr = NULL; \ headptr = NULL; \ } \ } while (0) /* Macro to free a linked list */ #define ICP_FREE_LIST(current_ptr) \ do \ { \ if (NULL != current_ptr) \ { \ while (NULL != current_ptr->pNext) \ { \ current_ptr = current_ptr->pNext; \ ICP_FREE(current_ptr->pPrev); \ } \ ICP_FREE(current_ptr); \ } \ } while (0) /* Logging macros */ #ifndef QAT_XEN_PLATFORM extern char *icp_module_name; #else char *icp_module_name = "XEN"; #endif #define ADF_PRINT(format, args...) printk(format, ##args) #define ADF_ERROR(format, args...) \ osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDERR, "%s: %s: " format, \ icp_module_name, (__func__), ##args) #ifdef _DEBUG_ #define ADF_DEBUG(format, args...) \ do \ { \ osalLog(OSAL_LOG_LVL_DEBUG1, OSAL_LOG_DEV_STDOUT, "%s: %s: " format, \ icp_module_name, (__func__), ##args); \ } while (0) #else /*_DEBUG_*/ #define ADF_DEBUG(format, args...) \ do \ { \ } while (0) #endif /*_DEBUG_*/ /* memory management */ #define ICP_MEMCPY(d, s, len) osalMemCopy(d, s, len) #define ICP_MEMSET(d, s, len) osalMemSet(d, s, len) /* string manipulation */ #define ICP_STRNCMP strncmp #define ICP_STRCMP strcmp #define ICP_STRNCPY strncpy #define ICP_STRNLEN strnlen #define ICP_MAX_STR_LEN (0x7F) #define ICP_STRNCMP_CONST(_ptr, _cnst) (strncmp(_ptr, _cnst, sizeof(_cnst))) #define ICP_STRNCMP_CONST_NO_NULL(_ptr, _cnst) \ (strncmp(_ptr, _cnst, sizeof(_cnst) - 1)) #define ICP_ARRAY_STRLEN_SANITIZE(_arg) \ ({ \ int retval; \ retval = strnlen(_arg, sizeof(_arg)); \ if (retval == sizeof(_arg)) \ _arg[--retval] = 0; \ retval; \ }) #define ICP_STRLCPY(dst, src, dstsize) \ ({ \ if ((dst != NULL) && (src != NULL) && (dstsize > 0)) \ snprintf(dst, dstsize, "%s", src); \ }) /* time */ #define ICP_GET_TIME osalTimeGet #define ICP_VIRT_TO_PHYS(addr) OSAL_MMU_VIRT_TO_PHYS(addr) /* locking */ #define ICP_SPINLOCK OsalLock #define ICP_SPINLOCK_INIT(ptr) osalLockInit(ptr, TYPE_IGNORE) #define ICP_SPINLOCK_LOCK osalLock #define ICP_SPINLOCK_UNLOCK osalUnlock #define ICP_SPINLOCK_LOCK_BH osalLockBh #define ICP_SPINLOCK_UNLOCK_BH osalUnlockBh #define ICP_SPINLOCK_LOCK_IRQ osalLockIrqSave #define ICP_SPINLOCK_UNLOCK_IRQ osalUnlockIrqRestore #define ICP_SPINLOCK_UNINIT osalLockDestroy #define ICP_MUTEX OsalMutex #define ICP_MUTEX_INIT osalMutexInit #define ICP_MUTEX_LOCK(ptr) osalMutexLock(ptr, OSAL_WAIT_FOREVER) #define ICP_MUTEX_LOCK_INTERRUPTIBLE(ptr) osalMutexLock(ptr, OSAL_WAIT_FOREVER) #define ICP_MUTEX_TRYLOCK osalMutexTryLock #define ICP_MUTEX_UNLOCK osalMutexUnlock #define ICP_MUTEX_UNINIT osalMutexDestroy #endif /* ICP_PLATFORM_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/include/icp_platform_user.h000066400000000000000000000115411503624047500323430ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file icp_platform_user.h * * @description * This file contains user space specific macros * *****************************************************************************/ #ifndef ICP_PLATFORM_USER_H #define ICP_PLATFORM_USER_H /* *********************************************************** * USER SPACE MACROS ************************************************************/ #include #include #include #include #include #include #include #include #include "Osal.h" #include #include "cpa.h" #define VOLATILE volatile #define KERN_ERR "" #define KERN_INFO "" #define ICP_MDELAY sleep #define ICP_SSLEEP sleep /* string conversion */ #define ICP_STRTOL strtol #define ICP_STRTOUL strtoul #define ICP_STRTOULL strtoull #define printk printf /* memory */ #define ICP_MALLOC_GEN(size) malloc(size) #define ICP_FREE(ptr) \ do \ { \ if (ptr) \ { \ free(ptr); \ ptr = NULL; \ } \ } while (0) #define ICP_ZALLOC_GEN(size) calloc(1, size) #define ICP_MALLOC_ATOMIC(size) malloc(size) #ifndef STATIC #define STATIC static #endif #ifndef INLINE #define INLINE inline #endif #define ICP_MMAP(addr, len, prot, flags, fd, offset) \ mmap(addr, len, prot, flags, fd, offset) #define ICP_MUNMAP(addr_v, len) munmap(addr_v, len) #define ICP_READ(fd, buf, count) read(fd, buf, count) #define ICP_MSLEEP(msecs) \ do \ { \ if (msecs < 1000) \ { \ usleep(1000 * msecs); \ } \ else \ { \ sleep(msecs / 1000); \ } \ } while (0) #define ICP_USLEEP(x) usleep(x) #define ICP_ISDIGIT isdigit #define ICP_ISSPACE isspace #endif /* ICP_PLATFORM_USER_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/000077500000000000000000000000001503624047500254375ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/adf_process_proxy.c000066400000000000000000000215211503624047500313350ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /****************************************************************************** * @file adf_process_proxy.c * * @description * User space interface to ADF in kernel space *****************************************************************************/ #include #include #include #include #include #include #include #include #include #ifdef QAT_WITH_LIBUDEV #include #include #endif #include "cpa.h" #include "icp_accel_devices.h" #include "icp_platform.h" #include "adf_platform.h" #include "adf_kernel_types.h" #include "icp_adf_init.h" #include "icp_adf_accel_mgr.h" #include "icp_adf_transport.h" #include "adf_user_init.h" #include "adf_user_transport.h" #include "adf_init.h" #include "adf_user.h" #include "adf_user_cfg.h" #include "adf_io_user_proxy.h" #define EVENT_MAX_LEN 20 #define ACCELID_MAX_LEN 5 /* * Time to sleep between each loop iteration in monitor devices func */ #ifdef QAT_WITH_LIBUDEV STATIC struct udev *udev; STATIC struct udev_monitor *mon; #endif /* * Proxy init counter */ STATIC Cpa16U init_ctr = 0; /* * Process proxy running state */ STATIC OsalAtomic process_proxy_status = 0; /* * icp_adf_resetUserProxy * * Description: * Function to reset the ADF proxy status in user space. * It resets proxy status and related parameters. * * CPA_STATUS_SUCCESS on resetting ADF proxy status * CPA_STATUS_RESOURCE when mutex init fails */ CpaStatus icp_adf_resetUserProxy(void); /* * adf_process_proxy_stop * Sets the process proxy running state to stopped */ STATIC INLINE void adf_process_proxy_stop(void) { osalAtomicSet(0, &process_proxy_status); } /* * adf_process_proxy_start * Sets the process proxy running state to started */ STATIC INLINE void adf_process_proxy_start(void) { osalAtomicSet(1, &process_proxy_status); } STATIC INLINE Cpa32U adf_process_proxy_running(void) { return (Cpa32U)osalAtomicGet(&process_proxy_status); } #ifdef QAT_WITH_LIBUDEV STATIC CpaStatus adf_event_monitor_create(void) { int ret = CPA_STATUS_SUCCESS; udev = udev_new(); if (!udev) { ADF_ERROR("Can't create udev\n"); ret = CPA_STATUS_FAIL; } if (ret == CPA_STATUS_SUCCESS) { mon = udev_monitor_new_from_netlink(udev, "udev"); if (!mon) { ADF_ERROR("Can't create udev monitor\n"); ret = CPA_STATUS_FAIL; } } if (ret == CPA_STATUS_SUCCESS) { if (udev_monitor_filter_add_match_subsystem_devtype(mon, "pci", NULL)) { ADF_ERROR("Can't add udev match filter\n"); ret = CPA_STATUS_FAIL; } } if (ret == CPA_STATUS_SUCCESS) { if (udev_monitor_enable_receiving(mon)) { ADF_ERROR("Can't bind monitor to event source\n"); ret = CPA_STATUS_FAIL; } } if (ret != CPA_STATUS_SUCCESS) { if (mon) udev_monitor_unref(mon); mon = NULL; if (udev) udev_unref(udev); udev = NULL; } return ret; } void adf_event_monitor_delete(void) { if (mon) { udev_monitor_unref(mon); mon = NULL; } if (udev) { udev_unref(udev); udev = NULL; } } #endif /* * adf_process_proxy_init * Init process proxy and connect to kernel space. * For every acceleration device in the system open * events and rings interface and start event listening threads */ STATIC CpaStatus adf_process_proxy_init(void) { if (adf_process_proxy_running()) { ADF_ERROR("Proxy already running\n"); return CPA_STATUS_FAIL; } #ifdef QAT_WITH_LIBUDEV if (adf_event_monitor_create() != CPA_STATUS_SUCCESS) return CPA_STATUS_FAIL; #endif adf_process_proxy_start(); if (adf_init_devices()) { ADF_ERROR("Error initializing devices\n"); return CPA_STATUS_FAIL; } return adf_proxy_get_devices(); } /* * adf_process_proxy_shutdown * User space proxy is shutting down. Close and clean all opened devices */ static __inline__ CpaStatus adf_process_proxy_shutdown() { #ifdef QAT_WITH_LIBUDEV adf_event_monitor_delete(); #endif return adf_cleanup_devices(); } /* * icp_adf_userProxyInit * This function is called by the application to bring the proxy up & running * Every userspace process has to call it to be able to create rings * and receive events. */ CpaStatus icp_adf_userProxyInit(char const *const name) { CpaStatus status = CPA_STATUS_FAIL; ICP_CHECK_FOR_NULL_PARAM(name); /* Allow the user to call init just once */ if (init_ctr) { ADF_ERROR("User proxy already initialized\n"); return status; } init_ctr = 1; /* Connect to kernel space. */ status = adf_process_proxy_init(); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("adf_process_proxy_init failed\n"); return status; } status = adf_io_userProxyInit(name); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Init adf_io proxy failed\n"); return status; } return status; } /* * icp_adf_userProxyShutdown * This function is called by the application to shutdown the proxy */ CpaStatus icp_adf_userProxyShutdown(void) { CpaStatus status = CPA_STATUS_SUCCESS; adf_process_proxy_stop(); status = adf_process_proxy_shutdown(); init_ctr = 0; adf_io_userProxyShutdown(); return status; } /* * icp_adf_userProcessToStart * * This function checks if an user space process with a given name has * already been started. * Returns: * False - process with a given name is not started. I.e. it is safe * to start one. * True - process is started or couldn't figure out if it is started. */ CpaStatus icp_adf_userProcessToStart(char const *const name_tml, char *name) { int name_len; int ret; /* Validate process name */ if (!name_tml || !name) { ADF_ERROR("Invalid pointer\n"); return CPA_STATUS_FAIL; } name_len = strnlen(name_tml, ADF_CFG_MAX_SECTION_LEN_IN_BYTES + 1); if (name_len + 1 > ADF_CFG_MAX_SECTION_LEN_IN_BYTES || 0 == name_len) { ADF_ERROR("Invalid Process name\n"); return CPA_STATUS_FAIL; } ret = adf_io_userProcessToStart( name_tml, name_len, name, ADF_CFG_MAX_SECTION_LEN_IN_BYTES); if (ret) { ADF_ERROR("Failed to start %s\n", name_tml); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } /* * icp_adf_userProcessStop * * This function stops the user process. */ void icp_adf_userProcessStop(void) { adf_io_userProcessStop(); } /* * icp_adf_getBusAddress * * This function gets the bdf of the device. */ Cpa16U icp_adf_getBusAddress(Cpa16U accelId) { return icp_adf_cfgGetBusAddress(accelId); } /* * icp_adf_resetUserProxy * * Function to reset the ADF proxy status in user space. */ CpaStatus icp_adf_resetUserProxy(void) { init_ctr = 0; osalAtomicSet(0, &process_proxy_status); return adf_io_resetUserProxy(); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_ETring_mgr_dp.c000066400000000000000000000231151503624047500321750ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_ETring_mgr_dp.c * * @description * ET Ring Manager for data plane * *****************************************************************************/ #include "cpa.h" #include "icp_platform.h" #include "icp_accel_devices.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "adf_platform.h" #include "adf_dev_ring_ctl.h" extern inline unsigned int modulo(unsigned int data, unsigned int shift); /* * icp_adf_getQueueMemory * Data plane support function - returns the pointer to next message on the ring * or NULL if there is not enough space. */ void icp_adf_getQueueMemory(icp_comms_trans_handle trans_hnd, Cpa32U numberRequests, void **pCurrentQatMsg) { adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_hnd; Cpa32U **targetAddr = (Cpa32U **)pCurrentQatMsg; Cpa32U in_flight; /* Check if there is enough space in the ring */ in_flight = *pRingHandle->in_flight + numberRequests; if (in_flight > pRingHandle->max_requests_inflight) { *targetAddr = NULL; return; } *pRingHandle->in_flight = in_flight; /* We have enough space - get the address of next message */ *targetAddr = (Cpa32U *)(((UARCH_INT)pRingHandle->ring_virt_addr) + pRingHandle->tail); } /* * icp_adf_getSingleQueueAddr * Data plane support function - returns the pointer to next message on the ring * or NULL if there is not enough space - it also updates the shadow tail copy. */ void icp_adf_getSingleQueueAddr(icp_comms_trans_handle trans_hnd, void **pCurrentQatMsg) { adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_hnd; Cpa32U **targetAddr = (Cpa32U **)pCurrentQatMsg; Cpa32U in_flight; /* Check if there is enough space in the ring */ in_flight = *pRingHandle->in_flight + 1; if (in_flight > pRingHandle->max_requests_inflight) { *targetAddr = NULL; return; } *pRingHandle->in_flight = in_flight; /* We have enough space - get the address of next message */ *targetAddr = (Cpa32U *)(((UARCH_INT)pRingHandle->ring_virt_addr) + pRingHandle->tail); /* Update the shadow tail */ pRingHandle->tail = modulo((pRingHandle->tail + pRingHandle->message_size), pRingHandle->modulo); } /* * icp_adf_getQueueNext * Data plane support function - increments the tail pointer and returns * the pointer to next message on the ring. */ void icp_adf_getQueueNext(icp_comms_trans_handle trans_hnd, void **pCurrentQatMsg) { adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_hnd; Cpa32U **targetAddr = (Cpa32U **)pCurrentQatMsg; /* Increment tail to next message */ pRingHandle->tail = modulo((pRingHandle->tail + pRingHandle->message_size), pRingHandle->modulo); /* Get the address of next message */ *targetAddr = (Cpa32U *)(((UARCH_INT)pRingHandle->ring_virt_addr) + pRingHandle->tail); } /* * icp_adf_getDpInflightRequests * Data plane function to fetch in-flight and max in-flight request counts * for the given trans_handle. */ void icp_adf_getDpInflightRequests(icp_comms_trans_handle trans_hnd, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests) { adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_hnd; *numInflightRequests = *pRingHandle->in_flight; *maxInflightRequests = pRingHandle->max_requests_inflight; } /* * icp_adf_wq_updateQueueTail * Data plane support function - Writes the tail shadow copy to the device. */ STATIC CpaStatus icp_adf_wq_updateQueueTail(adf_dev_ring_handle_t *pRingHandle) { WRITE_CSR_RING_TAIL(pRingHandle->csr_addr, pRingHandle->bank_offset, pRingHandle->ring_num, pRingHandle->tail); pRingHandle->csrTailOffset = pRingHandle->tail; return CPA_STATUS_SUCCESS; } /* * icp_adf_updateQueueTail * Data plane support function - Writes the tail shadow copy to the device. */ CpaStatus icp_adf_updateQueueTail(icp_comms_trans_handle trans_hnd) { adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_hnd; return icp_adf_wq_updateQueueTail(pRingHandle); } /* * icp_adf_isRingEmpty * Data plane support function - check if the ring is empty */ CpaBoolean icp_adf_isRingEmpty(icp_comms_trans_handle trans_hnd) { Cpa32U mask = 0; adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_hnd; Cpa32U *csr_base_addr = ((Cpa32U *)pRingHandle->csr_addr); mask = READ_CSR_E_STAT(pRingHandle->bank_offset); mask = ~mask; if (mask & (1 << (pRingHandle->ring_num))) { return CPA_FALSE; } return CPA_TRUE; } /* * icp_adf_pollQueue * Data plane support function - Poll messages from the queue. */ CpaStatus icp_adf_pollQueue(icp_comms_trans_handle trans_hnd, Cpa32U response_quota) { adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_hnd; Cpa32U msg_counter = 0; volatile Cpa32U *msg = NULL; if (response_quota == 0) { response_quota = ICP_NO_RESPONSE_QUOTA; } /* point to where the next message should be */ msg = (Cpa32U *)(((UARCH_INT)pRingHandle->ring_virt_addr) + pRingHandle->head); /* If there are valid messages then process them */ while ((*msg != EMPTY_RING_SIG_WORD) && (msg_counter < response_quota)) { /* Invoke the callback for the message */ pRingHandle->callback((Cpa32U *)msg); /* Mark the message as processed */ *msg = EMPTY_RING_SIG_WORD; /* Advance the head offset and handle wraparound */ pRingHandle->head = modulo((pRingHandle->head + pRingHandle->message_size), pRingHandle->modulo); msg_counter++; /* Point to where the next message should be */ msg = (Cpa32U *)(((UARCH_INT)pRingHandle->ring_virt_addr) + pRingHandle->head); } /* Update the head CSR if any messages were processed */ if (msg_counter > 0) { *pRingHandle->in_flight -= msg_counter; /* Coalesce head writes to reduce impact of MMIO write */ if (msg_counter > pRingHandle->coal_write_count) { pRingHandle->coal_write_count = pRingHandle->min_resps_per_head_write; if (IS_RING_IN_WQ_MODE(pRingHandle)) { WRITE_CSR_RING_HEAD(pRingHandle->csr_addr, pRingHandle->bank_offset, pRingHandle->ring_num, pRingHandle->head); } } else { /* Not enough responses have been processed to warrant the cost * of a head write. Updating the count for the next time. */ pRingHandle->coal_write_count -= msg_counter; } } else { return CPA_STATUS_RETRY; } return CPA_STATUS_SUCCESS; } /* * icp_adf_queueDataToSend * Data-plane support function - Indicates if there is data on the ring to be * sent. This should only be called on request rings. If the function returns * true then it is ok to call icp_adf_updateQueueTail() function on this ring. */ CpaBoolean icp_adf_queueDataToSend(icp_comms_trans_handle trans_hnd) { adf_dev_ring_handle_t *ringData = (adf_dev_ring_handle_t *)trans_hnd; if (ringData->tail != ringData->csrTailOffset) return CPA_TRUE; else return CPA_FALSE; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_cfg.c000066400000000000000000000056101503624047500302140ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #include "cpa.h" #include "adf_io_cfg.h" #include "icp_adf_accel_mgr.h" CpaStatus icp_adf_cfgGetParamValue(icp_accel_dev_t *accel_dev, const char *pSection, const char *pParamName, char *pParamValue) { return adf_io_cfgGetParamValue( accel_dev, pSection, pParamName, pParamValue); } Cpa32S icp_adf_cfgGetDomainAddress(Cpa16U accelId) { return adf_io_cfgGetDomainAddress(accelId); } Cpa16U icp_adf_cfgGetBusAddress(Cpa16U accelId) { return adf_io_cfgGetBusAddress(accelId); } /* * icp_adf_cfgCheckUserSection * check if user process section exists in device cfg */ int icp_adf_cfgCheckUserSection(int dev_id, uint8_t *pSectionPresent) { return adf_io_cfgCheckUserSection(dev_id, pSectionPresent); } CpaStatus icp_adf_resetDevice(Cpa32U accelId) { if (!icp_adf_isDevIdValid(accelId)) { return CPA_STATUS_FAIL; } return adf_io_reset_device(accelId); } CpaBoolean icp_adf_isDeviceAvailable(void) { return adf_io_isDeviceAvailable(); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_device.c000066400000000000000000000630211503624047500307140ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #include #include #include #include #include #include "adf_io_user_proxy.h" #include "icp_adf_user_proxy.h" #include "adf_user.h" #include "adf_user_cfg.h" #include "adf_io_cfg.h" #include "adf_io_bundles.h" #define ADF_DEV_EVENT_TIMEOUT 10 typedef struct adf_event_node_s { enum adf_event event; OsalTimeval start; /* record the start time of the event */ struct adf_event_node_s *next; } adf_event_node_t; typedef struct adf_event_queue_s { adf_event_node_t *head; adf_event_node_t *tail; } adf_event_queue_t; STATIC adf_event_queue_t adf_event_queue[ADF_MAX_DEVICES] = { { 0 } }; /* * User space copy of acceleration devices */ STATIC icp_accel_dev_t *accel_tbl[ADF_MAX_DEVICES] = { 0 }; /* * Need to keep track of what device is currently in error */ STATIC char accel_dev_error_stat[ADF_MAX_DEVICES] = { 0 }; /* * Need to keep track of what device is currently in restarting */ STATIC char accel_dev_restarting_state[ADF_MAX_DEVICES] = { '\0' }; /* * Mutex guarding access to accel_tbl on exit */ STATIC OsalMutex accel_tbl_mutex; /* * Number of acceleration devices */ STATIC Cpa16U num_of_instances = 0; /* * icp_adf_getNumDevices * This function is used to determine the number of devices */ CpaStatus icp_adf_getNumDevices(Cpa32U *num_devices) { return adf_io_getNumDevices(num_devices); } /* * icp_adf_isDevIdValid * Check if a device id is valid */ CpaBoolean icp_adf_isDevIdValid(Cpa32U dev_id) { if (dev_id >= ADF_MAX_DEVICES) return CPA_FALSE; if (NULL == accel_tbl[dev_id]) return CPA_FALSE; return CPA_TRUE; } int32_t adf_cleanup_device(int32_t dev_id) { int32_t stat = 0; icp_accel_dev_t *dev; if (osalMutexLock(&accel_tbl_mutex, OSAL_WAIT_FOREVER)) { ADF_ERROR("Failed to lock mutex \n"); return -1; } if (accel_tbl[dev_id] == NULL) { osalMutexUnlock(&accel_tbl_mutex); return 0; } dev = accel_tbl[dev_id]; stat = adf_user_transport_exit(dev); adf_io_destroy_accel(accel_tbl[dev_id]); accel_tbl[dev_id] = NULL; num_of_instances--; osalMutexUnlock(&accel_tbl_mutex); return stat; } int32_t adf_clean_device(int32_t dev_id) { int32_t stat = 0; icp_accel_dev_t *dev; if (ICP_MUTEX_LOCK(&accel_tbl_mutex)) { ADF_ERROR("Failed to lock mutex \n"); return -1; } dev = accel_tbl[dev_id]; stat = adf_user_transport_clean(dev); ICP_MUTEX_UNLOCK(&accel_tbl_mutex); return stat; } int32_t adf_cleanup_devices(void) { int32_t i; for (i = 0; i < ADF_MAX_DEVICES; i++) { if (adf_cleanup_device(i) != 0) { osalMutexDestroy(&accel_tbl_mutex); ADF_ERROR("Failed to cleanup device %d\n", i); return -1; } } osalMutexDestroy(&accel_tbl_mutex); return 0; } int32_t adf_init_devices(void) { int32_t i = 0; if (OSAL_SUCCESS != ICP_MUTEX_INIT(&accel_tbl_mutex)) { ADF_ERROR("Mutex init failed for accel_tbl_mutex\n"); return CPA_STATUS_RESOURCE; } for (i = 0; i < ADF_MAX_DEVICES; i++) { accel_tbl[i] = NULL; } return 0; } /* * adf_stop_system * Sets the user proxy running state to stopped */ STATIC INLINE void adf_stop_system(icp_accel_dev_t *accel_dev) { accel_dev->adfSubsystemStatus = 0; } /* * adf_start_system * Sets the user proxy running state to started */ STATIC INLINE void adf_start_system(icp_accel_dev_t *accel_dev) { accel_dev->adfSubsystemStatus = 1; } /* * adf_event_queue_is_empty * Returns CPA_TRUE if the event queue for this device * is empty. */ STATIC CpaBoolean adf_event_queue_is_empty(Cpa32U accelId) { return (NULL == adf_event_queue[accelId].head); } /* * adf_event_queue_head * Gets the head of the queue but won't dequeue it. * The caller must ensure that the event queue is * not empty. */ STATIC void adf_event_queue_head(Cpa32U accelId, enum adf_event *event, OsalTimeval *event_start) { *event = adf_event_queue[accelId].head->event; event_start->secs = adf_event_queue[accelId].head->start.secs; } /* * adf_event_enqueue * Enqueues a event node to the tail of a queue. */ STATIC CpaStatus adf_event_enqueue(Cpa32U accelId, enum adf_event event) { adf_event_queue_t *queue = &adf_event_queue[accelId]; adf_event_node_t *node = NULL; node = (adf_event_node_t *)osalMemAlloc(sizeof(adf_event_node_t)); if (!node) { ADF_ERROR("Failed to allocate memory - adf_event_node_t\n"); return CPA_STATUS_RESOURCE; } node->event = event; node->next = NULL; osalTimeGet(&node->start); if (!queue->head) { queue->head = node; } if (!queue->tail) { queue->tail = node; } else { queue->tail->next = node; queue->tail = node; } return CPA_STATUS_SUCCESS; } /* * adf_event_dequeue * Dequeues the head of the queue and free it. */ STATIC void adf_event_dequeue(Cpa32U accelId, enum adf_event event) { adf_event_queue_t *queue = &adf_event_queue[accelId]; adf_event_node_t *node = queue->head; if (!adf_event_queue_is_empty(accelId)) { if (queue->head == queue->tail) { queue->head = NULL; queue->tail = NULL; } else { queue->head = queue->head->next; } osalMemFree(node); } } STATIC int adf_proxy_get_dev_events(int dev_id); STATIC int32_t adf_proxy_get_device(int dev_id); STATIC int32_t adf_proxy_restart_device(int dev_id); /* * subsystem_notify * Forwards the event to each registered subsystem * The caller must ensure a valid accelId variable */ STATIC CpaStatus subsystem_notify(Cpa32U accelId, Cpa32U event) { CpaStatus stat = CPA_STATUS_SUCCESS; CpaStatus stat_proxy = CPA_STATUS_SUCCESS; CpaStatus stat_restart = CPA_STATUS_SUCCESS; icp_accel_dev_t *accel_dev; accel_dev = accel_tbl[accelId]; if (!accel_dev) return CPA_STATUS_INVALID_PARAM; switch (event) { case ADF_EVENT_INIT: stat = adf_user_subsystemInit(accel_dev); break; case ADF_EVENT_START: stat = adf_user_subsystemStart(accel_dev); adf_start_system(accel_dev); break; case ADF_EVENT_STOP: adf_stop_system(accel_dev); stat = adf_user_subsystemStop(accel_dev); break; case ADF_EVENT_SHUTDOWN: stat = adf_user_subsystemShutdown(accel_dev); /* Close user proxy for given device */ stat_proxy = adf_cleanup_device(accel_dev->accelId); break; case ADF_EVENT_RESTARTING: accel_dev_restarting_state[accel_dev->accelId] = 1; adf_stop_system(accel_dev); stat = adf_subsystemRestarting(accel_dev); stat_proxy = adf_clean_device(accel_dev->accelId); adf_io_vf2pf_notify_restarting_complete(accel_dev); break; case ADF_EVENT_RESTARTED: accel_dev_restarting_state[accel_dev->accelId] = 0; stat_restart = adf_proxy_restart_device(accelId); if (CPA_STATUS_SUCCESS == stat_restart) { adf_start_system(accel_tbl[accelId]); } accel_dev_error_stat[accelId] = 0; break; case ADF_EVENT_ERROR: /* accel_dev_error_stat is set after calling adf_subsystemError * to prevent repeated fatal error event notifications to the * application. * This may occur if the event error is being replayed as a * result of status retry. */ stat = adf_subsystemError(accel_dev); accel_dev_error_stat[accel_dev->accelId] = 1; break; default: stat = CPA_STATUS_INVALID_PARAM; } if (CPA_STATUS_SUCCESS != stat_proxy) { ADF_ERROR("Failed to close process proxy\n"); } if (CPA_STATUS_SUCCESS != stat_restart) { ADF_ERROR("Failed to restart device\n"); stat = stat_restart; } return stat; } /* * adf_poll_enqueued_events * Poll events from the queue and notify * connected subsystems */ STATIC void adf_poll_enqueued_events(void) { enum adf_event event; Cpa32U accelId; OsalTimeval event_start; OsalTimeval event_curr; Cpa32U event_time; CpaStatus stat = CPA_STATUS_SUCCESS; for (accelId = 0; accelId < ADF_MAX_DEVICES; accelId++) { while (!adf_event_queue_is_empty(accelId)) { adf_event_queue_head(accelId, &event, &event_start); stat = subsystem_notify(accelId, event); /* In the case of a device error, if the instance * is not being polled, software responses will not * be generated for the in-flight requests. */ osalTimeGet(&event_curr); event_time = event_curr.secs - event_start.secs; if (CPA_STATUS_SUCCESS == stat || event_time > ADF_DEV_EVENT_TIMEOUT) { adf_event_dequeue(accelId, event); } else if (CPA_STATUS_RETRY == stat) { break; } } } } STATIC int32_t adf_proxy_get_device(int dev_id) { int32_t err; uint8_t is_section_present = 0; if ((dev_id >= ADF_MAX_DEVICES) || (NULL != accel_tbl[dev_id])) return 0; /* Invalid dev_id or Already created. */ if (!adf_io_accel_dev_exist(dev_id)) return 0; err = icp_adf_cfgCheckUserSection(dev_id, &is_section_present); if (err) return err; if (!is_section_present) /* If user section is not present in dev_id cfg, then * don't populate accel_tbl[dev_id] as it is redundant. */ return 0; err = adf_io_create_accel(&accel_tbl[dev_id], dev_id); if (err) return err; err = adf_user_transport_init(accel_tbl[dev_id]); if (0 != err) { goto adf_proxy_get_device_init_failed; } adf_proxy_get_dev_events(dev_id); num_of_instances++; return 0; adf_proxy_get_device_init_failed: adf_io_destroy_accel(accel_tbl[dev_id]); accel_tbl[dev_id] = NULL; return err; } STATIC int32_t adf_proxy_restart_device(int dev_id) { int32_t err; if ((dev_id >= ADF_MAX_DEVICES)) return 0; /* Invalid dev_id or Already created. */ if (!adf_io_accel_dev_exist(dev_id)) return 0; if (adf_io_reinit_accel(&accel_tbl[dev_id], dev_id)) { err = ENOMEM; goto adf_proxy_restart_device_exit; } err = adf_user_transport_reinit(accel_tbl[dev_id]); if (0 != err) { goto adf_proxy_restart_device_init_failed; } err = adf_subsystemRestarted(accel_tbl[dev_id]); if (0 != err) { goto adf_proxy_restart_device_init_failed; } return 0; adf_proxy_restart_device_init_failed: adf_user_transport_exit(accel_tbl[dev_id]); adf_io_destroy_accel(accel_tbl[dev_id]); accel_tbl[dev_id] = NULL; adf_proxy_restart_device_exit: return err; } STATIC int adf_proxy_get_dev_events(int dev_id) { enum adf_event event[] = { ADF_EVENT_INIT, ADF_EVENT_START }; size_t i = 0; if (accel_tbl[dev_id] != NULL) { for (i = 0; i < sizeof(event) / sizeof(event[0]); i++) { subsystem_notify(dev_id, event[i]); } } return 0; } CpaStatus adf_proxy_get_devices(void) { int32_t ctr = 0; Cpa32U num_dev = 0; if (icp_adf_getNumDevices(&num_dev)) return CPA_STATUS_FAIL; for (ctr = 0; ctr < num_dev; ctr++) { if (adf_proxy_get_device(ctr)) { ADF_ERROR("adf_proxy_get_device error ctr\n"); return CPA_STATUS_FAIL; } } return CPA_STATUS_SUCCESS; } CpaStatus icp_adf_userFindNewDevices(void) { return adf_proxy_get_devices(); } CpaStatus icp_adf_pollDeviceEvents(void) { Cpa32U accelId; enum adf_event event; CpaStatus stat; adf_poll_enqueued_events(); while (adf_io_pollProxyEvent(&accelId, &event)) { if (accelId >= ADF_MAX_DEVICES) { ADF_ERROR("Invalid accelId (%d) from event poll\n", accelId); continue; } if (!accel_tbl[accelId]) /* accel_tbl[accelId] is populated only if the accelId cfg has the * user process section started by the application, else it will * continue to be NULL. So, events on this accelId can be ignored. */ continue; if (adf_event_queue_is_empty(accelId)) { stat = subsystem_notify(accelId, event); if (CPA_STATUS_RETRY == stat) { stat = adf_event_enqueue(accelId, event); if (CPA_STATUS_SUCCESS != stat) { ADF_ERROR("Failed to enqueue the event\n"); } } } else { stat = adf_event_enqueue(accelId, event); if (CPA_STATUS_SUCCESS != stat) { ADF_ERROR("Failed to enqueue the event\n"); } } } return CPA_STATUS_SUCCESS; } /* * * icp_adf_qaDevGet * * Function increments the device usage counter. * */ void icp_adf_qaDevGet(icp_accel_dev_t *pAccelDev) { __sync_fetch_and_add(&pAccelDev->usageCounter, 1); } /* * * icp_adf_qaDevGet * * Function decrements the device usage counter. * */ void icp_adf_qaDevPut(icp_accel_dev_t *pAccelDev) { __sync_fetch_and_sub(&pAccelDev->usageCounter, 1); } /* * adf_devmgrGetAccelDevByAccelId * Check the accel table for a structure that contains the correct * accel ID. If the accelId is found return the pointer to the accelerator * structure. * Returns a pointer to the accelerator structure or NULL if not found. */ icp_accel_dev_t *adf_devmgrGetAccelDevByAccelId(Cpa32U accelId) { icp_accel_dev_t **ptr = accel_tbl; Cpa16U i = 0; for (i = 0; i < ADF_MAX_DEVICES; i++, ptr++) { if (NULL != *ptr) { if ((*ptr)->accelId == accelId) { return *ptr; } } } return NULL; } /* * icp_adf_getAccelDevByAccelId * Same as adf_devmgrGetAccelDevByAccelId() but for external use * structure. * Returns a pointer to the accelerator structure or NULL if not found. */ icp_accel_dev_t *icp_adf_getAccelDevByAccelId(Cpa32U accelId) { return adf_devmgrGetAccelDevByAccelId(accelId); } /* * icp_adf_isDevInError * Check if device is in error state. */ CpaBoolean icp_adf_isDevInError(icp_accel_dev_t *accel_dev) { return (CpaBoolean)accel_dev_error_stat[accel_dev->accelId]; } /* * icp_adf_isDevInRestarting * Check if device is in restarting state. */ CpaBoolean icp_adf_isDevInRestarting(icp_accel_dev_t *accel_dev) { return (CpaBoolean)accel_dev_restarting_state[accel_dev->accelId]; } CpaStatus icp_adf_userGetNumPfs(Cpa16U *pNumPFs) { Cpa16U number_pfs; ICP_CHECK_FOR_NULL_PARAM(pNumPFs); number_pfs = adf_io_getNumPfs(); if (number_pfs == ADF_IO_OPERATION_FAIL_U16) { ADF_ERROR("Failed to get number PFs\n"); *pNumPFs = 0; return CPA_STATUS_FAIL; } *pNumPFs = number_pfs; return CPA_STATUS_SUCCESS; } CpaStatus icp_adf_userGetPfInfo(icp_accel_pf_info_t *pPf_info) { return adf_io_getPfInfo(pPf_info); } CpaStatus icp_adf_userCheckDevice(Cpa32U packageId) { return adf_io_getHeartBeatStatus(packageId); } /* This function can be used to check if the heartbeat capability is supported * in qat device. Also, it checks heartbeat capability for multiple devices * available in the system. It will not return unsupported or failure as soon * as one device does not have heartbeat capabilities, it allows for other * devices to check if heartbeat capability is supported. */ CpaStatus icp_adf_userCheckAllDevices(void) { Cpa16U number_pfs, i; CpaStatus res = CPA_STATUS_FAIL; CpaBoolean all_unsup = CPA_TRUE; CpaBoolean any_dev = CPA_FALSE; int num_dev_fail = 0; if (icp_adf_userGetNumPfs(&number_pfs) != CPA_STATUS_SUCCESS) { ADF_ERROR("Failed to get number PFs\n"); return CPA_STATUS_FAIL; } for (i = 0; i < number_pfs; i++) { any_dev = CPA_TRUE; res = adf_io_getHeartBeatStatus(i); if (CPA_STATUS_UNSUPPORTED != res) { all_unsup = CPA_FALSE; if (CPA_STATUS_SUCCESS != res) { num_dev_fail++; ADF_ERROR("Device Check failed for " "device %d\n", i); } } } if (CPA_TRUE == any_dev && CPA_TRUE == all_unsup) return CPA_STATUS_UNSUPPORTED; else if (number_pfs == num_dev_fail) return CPA_STATUS_FAIL; else return CPA_STATUS_SUCCESS; } #ifdef ICP_HB_FAIL_SIM CpaStatus icp_adf_heartbeatSimulateFailure(Cpa32U packageId) { return adf_io_heartbeatSimulateFailure(packageId); } #endif /* * icp_adf_mmap_misc_counter * Function get the mmap address for miscellaneous counter */ CpaStatus icp_adf_mmap_misc_counter(Cpa64U **miscCounter) { CpaStatus ret = CPA_STATUS_SUCCESS; Cpa32U size = 0; void *addr = NULL; ICP_CHECK_FOR_NULL_PARAM(miscCounter); int fd = open(ADF_CTL_DEVICE_NAME, O_RDWR); if (fd < 0) return CPA_STATUS_UNSUPPORTED; size = getpagesize(); addr = ICP_MMAP( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); if (!addr || addr == MAP_FAILED) { close(fd); return CPA_STATUS_FAIL; } *miscCounter = &((struct adf_dev_miscellaneous_stats *)addr)->misc_counter; close(fd); return ret; } /* * icp_adf_ummap_misc_counter * Function unmap micellaneous counter */ CpaStatus icp_adf_unmap_misc_counter(Cpa64U *miscCounter) { Cpa32U size = getpagesize(); ICP_CHECK_FOR_NULL_PARAM(miscCounter); int ret = munmap(miscCounter, size); if (ret < 0) return CPA_STATUS_FAIL; return CPA_STATUS_SUCCESS; } /* * icp_adf_getNumInstances * Return the number of acceleration devices it the system. */ CpaStatus icp_adf_getNumInstances(Cpa16U *pNumInstances) { ICP_CHECK_FOR_NULL_PARAM(pNumInstances); *pNumInstances = num_of_instances; return CPA_STATUS_SUCCESS; } /* * icp_adf_getInstances * Return table of acceleration instances it the system. */ CpaStatus icp_adf_getInstances(Cpa16U numInstances, icp_accel_dev_t **pCyInstances) { Cpa16U i = 0, x = 0; ICP_CHECK_FOR_NULL_PARAM(pCyInstances); if (numInstances > num_of_instances) { /* Too many acceleration devices requested */ ADF_ERROR("Too many instances of accel device requested\n"); return CPA_STATUS_FAIL; } for (i = 0; i < ADF_MAX_DEVICES; i++) { if (NULL != accel_tbl[i]) { pCyInstances[x++] = (icp_accel_dev_t *)accel_tbl[i]; } } return CPA_STATUS_SUCCESS; } /* * icp_adf_getAccelDevByCapabilities * Returns a started accel device that implements * the capabilities specified in capabilitiesMask. */ CpaStatus icp_adf_getAccelDevByCapabilities(Cpa32U capabilitiesMask, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances) { icp_accel_dev_t **ptr = accel_tbl; ICP_CHECK_FOR_NULL_PARAM(pAccel_devs); ICP_CHECK_FOR_NULL_PARAM(pNumInstances); Cpa16U i = 0; *pNumInstances = 0; for (i = 0; i < ADF_MAX_DEVICES; i++, ptr++) { if (NULL != *ptr) { if ((*ptr)->accelCapabilitiesMask & capabilitiesMask) { if ((*ptr)->adfSubsystemStatus) { *pAccel_devs = (icp_accel_dev_t *)*ptr; *pNumInstances = 1; return CPA_STATUS_SUCCESS; } } } } return CPA_STATUS_FAIL; } /* * icp_adf_getAllAccelDevByCapabilities * Returns table of accel devices that are started and that implement * at least one of the capabilities specified in capabilitiesMask. */ CpaStatus icp_adf_getAllAccelDevByCapabilities(Cpa32U capabilitiesMask, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances) { icp_accel_dev_t **ptr = accel_tbl; ICP_CHECK_FOR_NULL_PARAM(pAccel_devs); ICP_CHECK_FOR_NULL_PARAM(pNumInstances); Cpa16U i = 0; *pNumInstances = 0; for (i = 0; i < ADF_MAX_DEVICES; i++, ptr++) { if (NULL != *ptr) { if ((*ptr)->accelCapabilitiesMask & capabilitiesMask) { if ((*ptr)->adfSubsystemStatus) { pAccel_devs[(*pNumInstances)++] = (icp_accel_dev_t *)*ptr; } } } } return CPA_STATUS_SUCCESS; } /* * icp_adf_getAllAccelDevByServices * Returns table of accel devices that are started and that implement * at least one of the capabilities specified in services. */ CpaStatus icp_adf_getAllAccelDevByServices(Cpa16U servType, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances) { icp_accel_dev_t **ptr = accel_tbl; Cpa16U i = 0; ICP_CHECK_FOR_NULL_PARAM(pAccel_devs); ICP_CHECK_FOR_NULL_PARAM(pNumInstances); *pNumInstances = 0; for (i = 0; i < ADF_MAX_DEVICES; i++, ptr++) { if (NULL != *ptr) { if ((*ptr)->services & servType) { if ((*ptr)->adfSubsystemStatus) { pAccel_devs[(*pNumInstances)++] = (icp_accel_dev_t *)*ptr; } } } } return CPA_STATUS_SUCCESS; } /* * icp_amgr_getAllAccelDevByEachCapabilities * Returns table of accel devices that are started and implement * each of the capabilities specified in capabilitiesMask. */ CpaStatus icp_adf_getAllAccelDevByEachCapability(Cpa32U capabilitiesMask, icp_accel_dev_t **pAccel_devs, Cpa16U *pNumInstances) { icp_accel_dev_t **ptr = accel_tbl; ICP_CHECK_FOR_NULL_PARAM(pAccel_devs); ICP_CHECK_FOR_NULL_PARAM(pNumInstances); Cpa16U i = 0; *pNumInstances = 0; for (i = 0; i < ADF_MAX_DEVICES; i++, ptr++) { if (NULL != *ptr) { Cpa32U enabled_caps = (*ptr)->accelCapabilitiesMask & capabilitiesMask; if (enabled_caps == capabilitiesMask) { if ((*ptr)->adfSubsystemStatus) { pAccel_devs[(*pNumInstances)++] = (icp_accel_dev_t *)*ptr; } } } } return CPA_STATUS_SUCCESS; } /* * icp_adf_getAccelDevCapabilities * Returns accel devices capabilities specified in capabilitiesMask. */ CpaStatus icp_adf_getAccelDevCapabilities(icp_accel_dev_t *accel_dev, Cpa32U *pCapabilitiesMask) { icp_accel_dev_t *pAccelDev = NULL; ICP_CHECK_FOR_NULL_PARAM(accel_dev); ICP_CHECK_FOR_NULL_PARAM(pCapabilitiesMask); pAccelDev = accel_dev; *pCapabilitiesMask = pAccelDev->accelCapabilitiesMask; return CPA_STATUS_SUCCESS; } /* * adf_devmgrGetAccelHead * Sets the AccelDev to the head of the accelerator table. * Note: This function returns pointer to acceleration table * unlike the same function in kernelspace where is returns * pointer to list head. */ CpaStatus adf_devmgrGetAccelHead(icp_accel_dev_t **pAccelDev) { ICP_CHECK_FOR_NULL_PARAM(pAccelDev); *pAccelDev = (icp_accel_dev_t *)accel_tbl; return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_init.c000066400000000000000000000563571503624047500304360ustar00rootroot00000000000000/****************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /****************************************************************************** * @file adf_user_init.c * * @description * This file contains the subcomponent module initialisation code * for the Acceleration Driver Framework (ADF). * *****************************************************************************/ #include "cpa.h" #include "icp_platform.h" #include "icp_adf_init.h" #include "adf_init.h" #include "adf_user_init.h" #include "adf_devmgr.h" /* * The subsystem_table variable described the current position of the * tail of the list, this will also be the newest entry to the list. * * The subsystem_table_head contains the pointer to the head of the list. */ STATIC subservice_registation_handle_t *pSubsystemTable = NULL; STATIC subservice_registation_handle_t *pSubsystemTableHead = NULL; STATIC ICP_MUTEX subsystemTableLock = { 0 }; char *icp_module_name = "ADF_UIO_PROXY"; /* Slepping time before subsystem is started */ #define SLEEP_TIME 50000 /* Loop times before subsystem is started */ #define SLEEP_TIMES 10000000 Cpa32U userStartSleepTime = SLEEP_TIME; Cpa32U userStartSleepLoops = SLEEP_TIMES; STATIC void set_sleep_time(Cpa32U sleep_time, Cpa32U sleep_loops) { userStartSleepTime = sleep_time; userStartSleepLoops = sleep_loops; } /* * adf_subsystemAdd * Add a new subsystem structure to the subsystem Table */ STATIC inline CpaStatus adf_subsystemAdd( subservice_registation_handle_t *subsystem) { CpaStatus status = CPA_STATUS_FAIL; subservice_registation_handle_t *subsystem_hdl = NULL; ICP_CHECK_FOR_NULL_PARAM(subsystem); subsystem_hdl = pSubsystemTableHead; if (0 == subsystemTableLock) { if (OSAL_SUCCESS != ICP_MUTEX_INIT(&subsystemTableLock)) { ADF_ERROR("Mutex init failed for subsystemTableLock\n"); return CPA_STATUS_RESOURCE; } set_sleep_time(SLEEP_TIME, SLEEP_TIMES); } ICP_MUTEX_LOCK(&subsystemTableLock); /* Search the linked list for the subsystem */ ICP_FIND_ELEMENT_IN_LIST(subsystem, subsystem_hdl, status); if (CPA_STATUS_SUCCESS == status) { ADF_ERROR("subservice %s already in table.\n", subsystem->subsystem_name); ICP_MUTEX_UNLOCK(&subsystemTableLock); return CPA_STATUS_FAIL; } ICP_ADD_ELEMENT_TO_END_OF_LIST( subsystem, pSubsystemTable, pSubsystemTableHead); ICP_MUTEX_UNLOCK(&subsystemTableLock); return CPA_STATUS_SUCCESS; } /* * adf_subsystemRemove * Remove the subsystem structure from the subsystem Table */ STATIC inline CpaStatus adf_subsystemRemove( subservice_registation_handle_t *subsystem) { subservice_registation_handle_t *subsystem_hdl = NULL; CpaStatus status = CPA_STATUS_FAIL; ICP_CHECK_FOR_NULL_PARAM(subsystem); subsystem_hdl = pSubsystemTableHead; ICP_MUTEX_LOCK(&subsystemTableLock); ICP_FIND_ELEMENT_IN_LIST(subsystem, subsystem_hdl, status); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("subservice %s not found.\n", subsystem->subsystem_name); ICP_MUTEX_UNLOCK(&subsystemTableLock); return CPA_STATUS_FAIL; } else { ADF_DEBUG("subservice in table - removing.\n"); } ICP_REMOVE_ELEMENT_FROM_LIST( subsystem, pSubsystemTable, pSubsystemTableHead); ICP_MUTEX_UNLOCK(&subsystemTableLock); if (0 != subsystemTableLock && NULL == pSubsystemTableHead) { ICP_MUTEX_UNINIT(&subsystemTableLock); } return CPA_STATUS_SUCCESS; } /* * icp_adf_subsystemRegister * Register a new subsystem. */ CpaStatus icp_adf_subsystemRegister( subservice_registation_handle_t *subsystem_hdl) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U i = 0; ICP_CHECK_FOR_NULL_PARAM(subsystem_hdl); status = adf_subsystemAdd(subsystem_hdl); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to add subsystem to the linked list.\n"); return CPA_STATUS_FAIL; } for (i = 0; i < ADF_MAX_DEVICES; i++) { /* Initialising the masks during the subsystem registration * and prior to init. */ CLEAR_STATUS_BIT(subsystem_hdl->subsystemStatus[i].subsystemInitBit, 0); CLEAR_STATUS_BIT(subsystem_hdl->subsystemStatus[i].subsystemStartBit, 0); CLEAR_STATUS_BIT(subsystem_hdl->subsystemStatus[i].subsystemFailedBit, 0); } return CPA_STATUS_SUCCESS; } /* * do_shutdown * Function sends a shutdown event to a subsystem. */ STATIC CpaStatus do_shutdown(icp_accel_dev_t *accel_dev, subservice_registation_handle_t *subsystem_hdl) { CpaStatus status = CPA_STATUS_FAIL; ICP_CHECK_FOR_NULL_PARAM(subsystem_hdl); ICP_CHECK_FOR_NULL_PARAM(accel_dev); ICP_CHECK_PARAM_LT_MAX(accel_dev->accelId, ADF_MAX_DEVICES - 1); /* Shutdown the subsystem if required */ if (BIT_IS_SET( subsystem_hdl->subsystemStatus[accel_dev->accelId].subsystemInitBit, 0)) { /* Send shutdown event */ ADF_DEBUG("Sending event %d to %s\n", ADF_EVENT_SHUTDOWN, subsystem_hdl->subsystem_name); status = subsystem_hdl->subserviceEventHandler( accel_dev, ADF_EVENT_SHUTDOWN, NULL); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to shutdown subservice %s\n", subsystem_hdl->subsystem_name); } else { CLEAR_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemInitBit, 0); } } return status; } /* * icp_adf_subsystemUnregister * Unregister a subsystem that is about to be removed. * If the system is initialised and started it will be stopped first. */ CpaStatus icp_adf_subsystemUnregister( subservice_registation_handle_t *subsystem_hdl) { CpaStatus status = CPA_STATUS_FAIL; icp_accel_dev_t *accel_dev = NULL; icp_accel_dev_t **accel_tbl = NULL; Cpa32U sleepflag = 0, i = 0; ICP_CHECK_FOR_NULL_PARAM(subsystem_hdl); status = adf_devmgrGetAccelHead(&accel_dev); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to get accel head.\n"); return status; } accel_tbl = (icp_accel_dev_t **)accel_dev; for (i = 0; i < ADF_MAX_DEVICES; i++) { if (NULL != *accel_tbl) { /* Stop the subsystem if required */ if (BIT_IS_SET(subsystem_hdl->subsystemStatus[(*accel_tbl)->accelId] .subsystemStartBit, 0)) { ADF_DEBUG("Sending event %d to %s\n", ADF_EVENT_STOP, subsystem_hdl->subsystem_name); status = subsystem_hdl->subserviceEventHandler( (*accel_tbl), ADF_EVENT_STOP, NULL); if (CPA_STATUS_SUCCESS != status) { if (CPA_STATUS_RETRY == status) { sleepflag++; CLEAR_STATUS_BIT( subsystem_hdl ->subsystemStatus[(*accel_tbl)->accelId] .subsystemStartBit, 0); ADF_DEBUG("Received pending from subservice %s.\n", subsystem_hdl->subsystem_name); } else { ADF_ERROR("Failed to stop subservice %s for dev %d\n", subsystem_hdl->subsystem_name, (*accel_tbl)->accelId); } } else { CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[(*accel_tbl)->accelId] .subsystemStartBit, 0); } } } accel_tbl++; } /* sleep for PENDING_DELAY msecs before calling shutdown. */ if (sleepflag) { ICP_MSLEEP(PENDING_DELAY); } accel_tbl = (icp_accel_dev_t **)accel_dev; for (i = 0; i < ADF_MAX_DEVICES; i++) { if (NULL != *accel_tbl) { status = do_shutdown((*accel_tbl), subsystem_hdl); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to shutdown subservice %s.\n", subsystem_hdl->subsystem_name); ADF_DEBUG("Removing subservice from the subservice table.\n"); } } accel_tbl++; } return adf_subsystemRemove(subsystem_hdl); } /* * adf_user_subsystemInit * This function initiates the initialisation of all sub-component modules. * Sub-component initialisation involves initing the AEs, allocating * interrupt resources, loading the firmware and sending an INIT event to * the subservice. */ CpaStatus adf_user_subsystemInit(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_FAIL; subservice_registation_handle_t *subsystem_hdl = pSubsystemTableHead; while (NULL != subsystem_hdl) { ADF_DEBUG("Sending event %d to %s\n", ADF_EVENT_INIT, subsystem_hdl->subsystem_name); CLEAR_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemFailedBit, 0); status = subsystem_hdl->subserviceEventHandler( accel_dev, ADF_EVENT_INIT, NULL); if (CPA_STATUS_SUCCESS == status) { SET_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemInitBit, 0); } else { ADF_ERROR("Failed to initialise Subservice %s\n", subsystem_hdl->subsystem_name); SET_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemFailedBit, 0); return status; } subsystem_hdl = subsystem_hdl->pNext; } return status; } /* * adf_user_subsystemStart * This function sends a start event to the registered subcomponents */ CpaStatus adf_user_subsystemStart(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_FAIL; subservice_registation_handle_t *subsystem_hdl = pSubsystemTableHead; while (NULL != subsystem_hdl) { ADF_DEBUG("Sending event %d to %s\n", ADF_EVENT_START, subsystem_hdl->subsystem_name); status = subsystem_hdl->subserviceEventHandler( accel_dev, ADF_EVENT_START, NULL); if (CPA_STATUS_SUCCESS == status) { SET_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0); } else { ADF_ERROR("Failed to start Subservice %s\n", subsystem_hdl->subsystem_name); SET_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemFailedBit, 0); return status; } subsystem_hdl = subsystem_hdl->pNext; } return status; } /* * adf_user_subsystemStop * This function sends a stop event to the registered subcomponents */ CpaStatus adf_user_subsystemStop(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_FAIL; subservice_registation_handle_t *subsystem_hdl = pSubsystemTableHead; Cpa32U sleepflag = 0; while (NULL != subsystem_hdl) { if (BIT_IS_SET(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0)) { status = subsystem_hdl->subserviceEventHandler( accel_dev, ADF_EVENT_STOP, NULL); if (CPA_STATUS_SUCCESS != status) { if (CPA_STATUS_RETRY == status) { sleepflag++; CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0); ADF_DEBUG("Pending received from %s\n", subsystem_hdl->subsystem_name); } else { ADF_ERROR("Failed to stop subservice %s.\n", subsystem_hdl->subsystem_name); } } else { CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0); } } subsystem_hdl = subsystem_hdl->pNext; } /* * If a pending was received need to return pending. */ if ((CPA_STATUS_SUCCESS == status) && sleepflag) { status = CPA_STATUS_RETRY; } return status; } /* * adf_user_subsystemShutdown * This function sends a shutdown event to the registered subcomponents */ CpaStatus adf_user_subsystemShutdown(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_FAIL; subservice_registation_handle_t *subsystem_hdl = pSubsystemTableHead; while (NULL != subsystem_hdl) { if (BIT_IS_SET(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemInitBit, 0)) { ADF_DEBUG("Sending event %d to %s\n", ADF_EVENT_SHUTDOWN, subsystem_hdl->subsystem_name); status = subsystem_hdl->subserviceEventHandler( accel_dev, ADF_EVENT_SHUTDOWN, NULL); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to shutdown Subservice %s\n", subsystem_hdl->subsystem_name); } else { CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemInitBit, 0); } } subsystem_hdl = subsystem_hdl->pNext; } return status; } /* * icp_adf_isSubsystemStarted * Function returns true if the service is started */ CpaBoolean icp_adf_isSubsystemStarted( subservice_registation_handle_t *subsystem_hdl) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean ret = CPA_FALSE; icp_accel_dev_t *accel_dev = NULL; icp_accel_dev_t **accel_tbl = NULL; Cpa32U i = 0, ctr = 0, wait_ctr = 0; ICP_CHECK_FOR_NULL_PARAM(subsystem_hdl); status = adf_devmgrGetAccelHead(&accel_dev); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to get accel head.\n"); return ret; } accel_tbl = (icp_accel_dev_t **)accel_dev; ICP_USLEEP(SLEEP_TIME); for (i = 0; i < ADF_MAX_DEVICES; i++) { if (NULL != *accel_tbl) { /* If the device is started in the system * need to wait till the subsystem is started * for this device or */ while (!BIT_IS_SET( subsystem_hdl->subsystemStatus[i].subsystemStartBit, 0)) { ICP_USLEEP(SLEEP_TIME); wait_ctr++; if (BIT_IS_SET( subsystem_hdl->subsystemStatus[i].subsystemFailedBit, 0)) { return CPA_FALSE; } if (wait_ctr > SLEEP_TIMES) { ctr--; break; } } ctr++; } accel_tbl++; } ret = (ctr > 0) ? CPA_TRUE : CPA_FALSE; return ret; } /* * Function sends restarting event to all subsystems. * This function should be used by error handling funct. only */ CpaStatus adf_subsystemRestarting(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_SUCCESS; subservice_registation_handle_t *subsystem_hdl = pSubsystemTableHead; Cpa32U retryflag = 0; ICP_CHECK_PARAM_LT_MAX(accel_dev->accelId, ADF_MAX_DEVICES - 1); while (NULL != subsystem_hdl) { enum adf_event event = ADF_EVENT_RESTARTING; ADF_DEBUG( "Sending event %d to %s\n", event, subsystem_hdl->subsystem_name); if (BIT_IS_SET(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0)) { status = subsystem_hdl->subserviceEventHandler(accel_dev, event, NULL); if (CPA_STATUS_SUCCESS != status) { if (CPA_STATUS_RETRY == status) { retryflag++; CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0); CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemInitBit, 0); ADF_DEBUG("Pending received from %s\n", subsystem_hdl->subsystem_name); } else { ADF_ERROR("Failed to restart subservice %s.\n", subsystem_hdl->subsystem_name); } } else { CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0); CLEAR_STATUS_BIT( subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemInitBit, 0); } } subsystem_hdl = subsystem_hdl->pNext; } /* * If a pending was received need to return pending. */ if ((CPA_STATUS_SUCCESS == status) && retryflag) { status = CPA_STATUS_RETRY; } return status; } /* * Function sends restarted event to all subsystems. * This function should be used by error handling funct. only */ CpaStatus adf_subsystemRestarted(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_SUCCESS; subservice_registation_handle_t *subsystem_hdl = pSubsystemTableHead; ICP_CHECK_FOR_NULL_PARAM(accel_dev); ICP_CHECK_PARAM_LT_MAX(accel_dev->accelId, ADF_MAX_DEVICES - 1); while (NULL != subsystem_hdl) { enum adf_event event = ADF_EVENT_RESTARTED; ADF_DEBUG( "Sending event %d to %s\n", event, subsystem_hdl->subsystem_name); status = subsystem_hdl->subserviceEventHandler(accel_dev, event, NULL); if (CPA_STATUS_FAIL == status) { ADF_ERROR("Failed to restart subservice %s.\n", subsystem_hdl->subsystem_name); } else { CLEAR_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemFailedBit, 0); SET_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemInitBit, 0); SET_STATUS_BIT(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0); } subsystem_hdl = subsystem_hdl->pNext; } return CPA_STATUS_SUCCESS; } /* * Function sends error event to all subsystems. * This function should be used by error handling funct. only */ CpaStatus adf_subsystemError(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U pendingflag = 0; subservice_registation_handle_t *subsystem_hdl = pSubsystemTableHead; ICP_CHECK_PARAM_LT_MAX(accel_dev->accelId, ADF_MAX_DEVICES - 1); while (NULL != subsystem_hdl) { enum adf_event event = ADF_EVENT_ERROR; ADF_DEBUG( "Sending event %d to %s\n", event, subsystem_hdl->subsystem_name); if (BIT_IS_SET(subsystem_hdl->subsystemStatus[accel_dev->accelId] .subsystemStartBit, 0)) { status = subsystem_hdl->subserviceEventHandler(accel_dev, event, NULL); if (CPA_STATUS_FAIL == status) { ADF_ERROR("Failed to send error event to %s.\n", subsystem_hdl->subsystem_name); } else if (CPA_STATUS_RETRY == status) { pendingflag++; ADF_DEBUG("Pending received from %s\n", subsystem_hdl->subsystem_name); } } subsystem_hdl = subsystem_hdl->pNext; } if ((CPA_STATUS_SUCCESS == status) && pendingflag) { status = CPA_STATUS_RETRY; } return status; } /* * Function to reset subsystem table head, the pointer * to the head of the list and lock. */ CpaStatus icp_adf_resetSubsystemTable(void) { pSubsystemTable = NULL; pSubsystemTableHead = NULL; if (0 == subsystemTableLock) { if (OSAL_SUCCESS != ICP_MUTEX_INIT(&subsystemTableLock)) { ADF_ERROR("Mutex init failed for subsystemTabl lock\n"); return CPA_STATUS_RESOURCE; } } return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_ring.c000066400000000000000000000431731503624047500304220ustar00rootroot00000000000000/*************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************/ #include #include #include #include "adf_user_ring.h" #include "adf_user_cfg.h" #include #include #include #include #include #include #include "adf_io_ring.h" static void *mem_alloc(Cpa32U size, Cpa32U node, Cpa32U alignment, adf_dev_ring_handle_t *ring) { return qaeMemAllocNUMA(size, node, alignment); } static void mem_free(void **ptr, adf_dev_ring_handle_t *ring) { qaeMemFreeNUMA(ptr); } static uint32_t validateRingSize(uint32_t num_msgs_on_ring, uint32_t msg_size_in_bytes, uint32_t *modulo_value) { const uint32_t size_in_bytes = num_msgs_on_ring * msg_size_in_bytes; const uint32_t max_ring_bytes = ICP_ET_SIZE_TO_BYTES(ICP_RINGSIZE_MEG_4); uint32_t size_config = 0; uint32_t kbytes = 0; uint32_t k_size = 0; if (0 >= num_msgs_on_ring || 0 >= msg_size_in_bytes || 0 != modulo(msg_size_in_bytes, 4)) { ADF_ERROR("Invalid Input: Num messages on ring=%d, " "Msg size(bytes)=%d. Using 16K\n", num_msgs_on_ring, msg_size_in_bytes); /* use default ring size */ size_config = ICP_RINGSIZE_KILO_16; *modulo_value = MODULO_SHIFT_FOR_16K; } else if (max_ring_bytes >= size_in_bytes) { /* under range will auto give minimum size or valid range calculate the highest bit set first right shift to smallest ring size */ kbytes = ((size_in_bytes - 1) >> MODULO_SHIFT_FOR_1K); while (kbytes > 0) { kbytes = kbytes >> 1; k_size++; } size_config = ICP_RINGSIZE_KILO_1 + k_size; *modulo_value = MODULO_SHIFT_FOR_1K + k_size; } else { /* larger than supported maximum */ /* set for maximum size */ size_config = ICP_RINGSIZE_MEG_4; *modulo_value = MODULO_SHIFT_FOR_4M; } return size_config; } static int adf_reserve_ring(adf_dev_bank_handle_t *bank, uint32_t ring_number) { int status = -1; if (NULL == bank->user_bank_lock) { ADF_ERROR("user_bank_lock is not initialized\n"); return status; } status = ICP_MUTEX_LOCK(bank->user_bank_lock); if (status) { ADF_ERROR("Failed to lock bank with error %d\n", status); return status; } if (!(bank->ring_mask & (1 << ring_number))) { bank->ring_mask |= (1 << ring_number); } else status = -EBUSY; ICP_MUTEX_UNLOCK(bank->user_bank_lock); return status; } static void adf_unreserve_ring(adf_dev_bank_handle_t *bank, uint32_t ring_number) { int status; status = ICP_MUTEX_LOCK(bank->user_bank_lock); if (status) { ADF_ERROR("Failed to lock bank with error %d\n", status); return; } bank->ring_mask &= ~(1 << ring_number); ICP_MUTEX_UNLOCK(bank->user_bank_lock); } CpaStatus adf_user_put_msg(adf_dev_ring_handle_t *ring, uint32_t *inBuf, uint64_t *seq_num) { CpaStatus status = CPA_STATUS_SUCCESS; uint32_t *targetAddr; int64_t flight; ICP_CHECK_FOR_NULL_PARAM(ring); ICP_CHECK_FOR_NULL_PARAM(inBuf); ICP_CHECK_FOR_NULL_PARAM(ring->accel_dev); #ifndef ICP_WITHOUT_QP_SUBMISSION_LOCK status = ICP_MUTEX_LOCK(ring->user_lock); if (status) { ADF_ERROR("Failed to lock bank with error %d\n", status); return CPA_STATUS_FAIL; } #endif /* Check if there is enough space in the ring */ flight = __sync_add_and_fetch(ring->in_flight, 1); if (flight > ring->max_requests_inflight) { __sync_sub_and_fetch(ring->in_flight, 1); status = CPA_STATUS_RETRY; goto adf_user_put_msg_exit; } targetAddr = (uint32_t *)(((UARCH_INT)ring->ring_virt_addr) + ring->tail); if (ring->message_size == ADF_MSG_SIZE_64_BYTES) { adf_memcpy64(targetAddr, inBuf); } else if (ring->message_size == ADF_MSG_SIZE_128_BYTES) { adf_memcpy128(targetAddr, inBuf); } else { status = CPA_STATUS_FAIL; goto adf_user_put_msg_exit; } if (IS_RING_IN_WQ_MODE(ring)) { /* Update shadow copy values */ ring->tail = modulo((ring->tail + ring->message_size), ring->modulo); /* and the config space of the device */ WRITE_CSR_RING_TAIL( ring->csr_addr, ring->bank_offset, ring->ring_num, ring->tail); } ring->csrTailOffset = ring->tail; if (NULL != seq_num) *seq_num = ring->send_seq; ring->send_seq++; adf_user_put_msg_exit: #ifndef ICP_WITHOUT_QP_SUBMISSION_LOCK ICP_MUTEX_UNLOCK(ring->user_lock); #endif return status; } int32_t adf_user_check_ring_error(adf_dev_ring_handle_t *ring) { uint8_t *csr_base_addr = NULL; uint32_t ring_stat = 0; device_type_t deviceType; ICP_CHECK_FOR_NULL_PARAM(ring); deviceType = ring->accel_dev->deviceType; /* if generation is not supporting ring error reporting assume there was no * error */ if (IS_QAT_GEN2(deviceType)) return 0; csr_base_addr = ((uint8_t *)ring->csr_addr); ring_stat = READ_CSR_RING_STATUS_GEN4(csr_base_addr, ring->bank_offset); if (ring_stat & CSR_RING_STAT_RL_EXCEPTION_MASK) return -EINTR; if (ring_stat & CSR_RING_STAT_RL_HALT_MASK) return -EL2HLT; return 0; } /* * Check function used for response rings. It will check the response rings * until the number of in-flight requests to determine whether there is * responses remained on the response ring. */ CpaBoolean adf_user_check_resp_ring(adf_dev_ring_handle_t *ring) { int32_t num_checked_msg = 0; int32_t cur_head = ring->head; volatile uint32_t *msg = NULL; while (num_checked_msg < *ring->in_flight) { msg = (uint32_t *)(((UARCH_INT)ring->ring_virt_addr) + cur_head); if (EMPTY_RING_SIG_WORD != *msg) { return CPA_FALSE; } cur_head = modulo((cur_head + ring->message_size), ring->modulo); num_checked_msg++; } return CPA_TRUE; } /* * Notify function used for polling. Messages are read until the ring is * empty or the response quota has been fulfilled. * If the response quota is zero, messages are read until the ring is drained. */ CpaStatus adf_user_notify_msgs_poll(adf_dev_ring_handle_t *ring) { volatile uint32_t *msg = NULL; uint32_t msg_counter = 0, response_quota; response_quota = (ring->ringResponseQuota != 0) ? ring->ringResponseQuota : ICP_NO_RESPONSE_QUOTA; /* point to where the next message should be */ msg = (uint32_t *)(((UARCH_INT)ring->ring_virt_addr) + ring->head); /* If there are valid messages then process them */ while ((*msg != EMPTY_RING_SIG_WORD) && (msg_counter < response_quota)) { /* Invoke the callback for the message */ ring->callback((uint32_t *)msg); /* Mark the message as processed */ *msg = EMPTY_RING_SIG_WORD; /* Advance the head offset and handle wraparound */ ring->head = modulo((ring->head + ring->message_size), ring->modulo); msg_counter++; /* Point to where the next message should be */ msg = (uint32_t *)(((UARCH_INT)ring->ring_virt_addr) + ring->head); } /* Update the head CSR if any messages were processed */ if (msg_counter > 0) { /* May need to do this earlier to prevent perf impact in multi-threaded * scenarios */ __sync_sub_and_fetch(ring->in_flight, msg_counter); /* Coalesce head writes to reduce impact of MMIO write, except if * interrupt method is enabled cause otherwise it would keep triggering * new interrupts over and over again */ if (msg_counter > ring->coal_write_count || ICP_RESP_TYPE_IRQ == ring->resp) { ring->coal_write_count = ring->min_resps_per_head_write; if (IS_RING_IN_WQ_MODE(ring)) { WRITE_CSR_RING_HEAD(ring->csr_addr, ring->bank_offset, ring->ring_num, ring->head); } } else { /* Not enough responses have been processed to warrant the cost * of a head write. Updating the count for the next time. */ ring->coal_write_count -= msg_counter; } } else { return CPA_STATUS_RETRY; } return CPA_STATUS_SUCCESS; } static void adf_populate_ring_config(adf_dev_ring_handle_t *ring, adf_dev_bank_handle_t *bank, uint32_t ring_size_cfg) { uint64_t ring_base_cfg, ring_config; uint8_t nearly_full_wm = ICP_RING_NEAR_WATERMARK_512; uint8_t nearly_empty_wm = ICP_RING_NEAR_WATERMARK_0; uint32_t *csr_base_addr = ring->csr_addr; device_type_t deviceType; deviceType = ring->accel_dev->deviceType; if (bank->tx_rings_mask & (1 << ring->ring_num)) { ring_config = BUILD_RING_CONFIG(ring_size_cfg); } else { ring_config = BUILD_RESP_RING_CONFIG( ring_size_cfg, nearly_full_wm, nearly_empty_wm); } if (!IS_QAT_GEN2(deviceType)) { ring_base_cfg = BUILD_RING_BASE_ADDR_GEN4(ring->ring_phys_base_addr, ring_size_cfg); WRITE_CSR_RING_BASE_GEN4( csr_base_addr, ring->bank_offset, ring->ring_num, ring_base_cfg); WRITE_CSR_RING_CONFIG_GEN4( csr_base_addr, ring->bank_offset, ring->ring_num, ring_config); } else { ring_base_cfg = BUILD_RING_BASE_ADDR(ring->ring_phys_base_addr, ring_size_cfg); WRITE_CSR_RING_BASE(ring->bank_offset, ring->ring_num, ring_base_cfg); WRITE_CSR_RING_CONFIG(ring->bank_offset, ring->ring_num, ring_config); } } static int32_t adf_init_ring_internal(adf_dev_ring_handle_t *ring, adf_dev_bank_handle_t *bank, uint32_t ring_num, uint32_t *csr_base_addr, uint32_t num_msgs, uint32_t msg_size, int nodeid) { uint32_t modulo = 0; uint32_t ring_size_cfg = validateRingSize(num_msgs, msg_size, &modulo); uint32_t ring_size_bytes = ICP_ET_SIZE_TO_BYTES(ring_size_cfg); uint32_t max_space = ring_size_bytes; ICP_CHECK_FOR_NULL_PARAM(ring->accel_dev); /* Exclusive access to one ring */ if (adf_reserve_ring(bank, ring_num)) { ADF_ERROR( "Ring [%u:%u] existed already\n", bank->bank_number, ring_num); return -EBUSY; } ring->head = 0; ring->tail = 0; ring->send_seq = 0; ring->bank_data = bank; /* Now the bank offset is 0 because we get the band's offset */ ring->bank_offset = 0; ring->ring_num = ring_num; ring->csr_addr = csr_base_addr; ring->message_size = msg_size; ring->modulo = modulo; ring->ring_size = ring_size_bytes; ICP_MEMSET(ring->ring_virt_addr, EMPTY_RING_SIG_BYTE, ring_size_bytes); ring->min_resps_per_head_write = ((max_space / msg_size) >> 1 > MIN_RESPONSES_PER_HEAD_WRITE) ? MIN_RESPONSES_PER_HEAD_WRITE : (max_space / msg_size) >> 1; ring->max_requests_inflight = num_msgs - 1; if (IS_RING_IN_WQ_MODE(ring)) { adf_populate_ring_config(ring, bank, ring_size_cfg); } adf_io_enable_ring(ring); return 0; } int32_t adf_init_ring(adf_dev_ring_handle_t *ring, adf_dev_bank_handle_t *bank, uint32_t ring_num, uint32_t *csr_base_addr, uint32_t num_msgs, uint32_t msg_size, int nodeid) { uint32_t modulo = 0; uint32_t ring_size_cfg = validateRingSize(num_msgs, msg_size, &modulo); uint32_t ring_size_bytes = ICP_ET_SIZE_TO_BYTES(ring_size_cfg); int32_t status = 0; ring->ring_virt_addr = mem_alloc(ring_size_bytes, nodeid, ring_size_bytes, ring); if ((NULL == ring->ring_virt_addr)) { ADF_ERROR("Unable to get ringbuf(v:%p) for rings in bank(%lu)\n", ring->ring_virt_addr, (unsigned long)ring->ring_num); return -ENOMEM; } ring->ring_phys_base_addr = qaeVirtToPhysNUMA(ring->ring_virt_addr); if (0 == ring->ring_phys_base_addr) { ADF_ERROR("Unable to get ringbuf(p:%p) for rings in bank(%lu)\n", (void *)ring->ring_phys_base_addr, (unsigned long)ring->ring_num); mem_free(&ring->ring_virt_addr, ring); return -ENOMEM; } status = adf_init_ring_internal( ring, bank, ring_num, bank->csr_addr, num_msgs, msg_size, nodeid); if (status) { mem_free(&ring->ring_virt_addr, ring); return status; } return 0; } int32_t adf_reinit_ring(adf_dev_ring_handle_t *ring, adf_dev_bank_handle_t *bank, uint32_t ring_num, uint32_t *csr_base_addr, uint32_t num_msgs, uint32_t msg_size, int nodeid) { return adf_init_ring_internal( ring, bank, ring_num, bank->csr_addr, num_msgs, msg_size, nodeid); } int32_t adf_ring_freebuf(adf_dev_ring_handle_t *ring) { if (ring->ring_virt_addr) { /* Clean the ring before freeing*/ osalMemZeroExplicit(ring->ring_virt_addr, ring->ring_size); mem_free(&ring->ring_virt_addr, ring); ring->ring_virt_addr = NULL; } return 0; } static void adf_clean_ring(adf_dev_ring_handle_t *ring) { uint32_t *csr_base_addr = ring->csr_addr; ICP_CHECK_FOR_NULL_PARAM_VOID(ring->accel_dev); device_type_t deviceType = ring->accel_dev->deviceType; adf_io_disable_ring(ring); if (IS_RING_IN_WQ_MODE(ring)) { /* Clear CSR configuration */ if (!IS_QAT_GEN2(deviceType)) { WRITE_CSR_RING_CONFIG_GEN4( csr_base_addr, ring->bank_offset, ring->ring_num, 0); WRITE_CSR_RING_BASE_GEN4( csr_base_addr, ring->bank_offset, ring->ring_num, 0); } else { WRITE_CSR_RING_CONFIG(ring->bank_offset, ring->ring_num, 0); WRITE_CSR_RING_BASE(ring->bank_offset, ring->ring_num, 0); } } adf_unreserve_ring(ring->bank_data, ring->ring_num); } void adf_cleanup_ring(adf_dev_ring_handle_t *ring) { adf_clean_ring(ring); if (ring->ring_virt_addr) { osalMemZeroExplicit(ring->ring_virt_addr, ring->ring_size); mem_free(&ring->ring_virt_addr, ring); } } void adf_reset_ring(adf_dev_ring_handle_t *ring) { uint32_t *csr_addr_shadow = ring->bank_data->csr_addr_shadow; adf_clean_ring(ring); if (ring->ring_virt_addr) { ICP_MEMSET(ring->ring_virt_addr, EMPTY_RING_SIG_BYTE, ring->ring_size); } ring->csr_addr = csr_addr_shadow; } int32_t adf_user_get_inflight_requests(adf_dev_ring_handle_t *ring, uint32_t *maxInflightRequests, uint32_t *numInflightRequests) { int32_t status = 0; status = ICP_MUTEX_LOCK(ring->user_lock); if (OSAL_SUCCESS != status) { ADF_ERROR("Failed to lock bank with error %d\n", status); return -1; } *numInflightRequests = *ring->in_flight; *maxInflightRequests = ring->max_requests_inflight; ICP_MUTEX_UNLOCK(ring->user_lock); return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/qat_direct/io/adf_user_transport_ctrl.c000066400000000000000000001463601503624047500325450ustar00rootroot00000000000000/***************************************************************************** * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *****************************************************************************/ /***************************************************************************** * @file adf_user_transport_ctrl.c * * @description * Transport Controller for user space * *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "lac_sal_types.h" #include "lac_sal.h" #include "cpa.h" #include "icp_platform.h" #include "icp_accel_devices.h" #include "icp_adf_accel_mgr.h" #include "adf_kernel_types.h" #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "adf_platform.h" #include "adf_dev_ring_ctl.h" #include "adf_user_transport.h" #include "icp_adf_init.h" #include "adf_devmgr.h" #include "adf_io_bundles.h" #include "adf_io_ring.h" #include "adf_user_ring.h" #include "adf_user_arbiter.h" #include "adf_user_cfg.h" STATIC Cpa32U *ringInflights[ADF_MAX_DEVICES] = { NULL }; extern void *adf_get_bank_base_addr(int accelId, int bankid, uint32_t *offset, uint32_t *size); adf_dev_bank_handle_t *get_banks(icp_accel_dev_t *dev) { return dev->banks; } STATIC CpaStatus init_rings_from_bank(icp_accel_dev_t *accel_dev, adf_dev_bank_handle_t *bank) { uint32_t size = 0; size = sizeof(adf_dev_ring_handle_t *) * (accel_dev->maxNumRingsPerBank); bank->rings = ICP_MALLOC_GEN(size); if (NULL == bank->rings) { return CPA_STATUS_FAIL; } ICP_MEMSET(bank->rings, 0, size); return CPA_STATUS_SUCCESS; } CpaStatus init_bank_from_accel(icp_accel_dev_t *accel_dev, adf_dev_bank_handle_t *bank) { struct adf_io_user_bundle *bundle = NULL; bundle = adf_io_get_bundle_from_accelid(accel_dev->accelId, bank->bank_number); if (NULL == bundle) return CPA_STATUS_FAIL; if (adf_io_populate_bundle(accel_dev, bundle)) { adf_io_free_bundle(bundle); return CPA_STATUS_FAIL; } bank->csr_addr = (uint32_t *)bundle->ptr; bank->csr_addr_shadow = (uint32_t *)ICP_MALLOC_GEN(ICP_BUNDLE_SIZE); if (NULL == bank->csr_addr_shadow) { adf_io_free_bundle(bundle); return CPA_STATUS_FAIL; } ICP_MEMSET(bank->csr_addr_shadow, 0, ICP_BUNDLE_SIZE); bank->bundle = bundle; /* allocate ring handles for this bank */ if (CPA_STATUS_SUCCESS != init_rings_from_bank(accel_dev, bank)) { adf_io_free_bundle(bundle); ICP_FREE(bank->csr_addr_shadow); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } STATIC CpaStatus reinit_bank_from_accel(icp_accel_dev_t *accel_dev, adf_dev_bank_handle_t *bank) { struct adf_io_user_bundle *bundle = NULL; bundle = adf_io_get_bundle_from_accelid(accel_dev->accelId, bank->bank_number); if (NULL == bundle) { return CPA_STATUS_FAIL; } if (adf_io_populate_bundle(accel_dev, bundle)) { adf_io_free_bundle(bundle); return CPA_STATUS_FAIL; } bank->csr_addr = (uint32_t *)bundle->ptr; ICP_MEMSET(bank->csr_addr_shadow, 0, ICP_BUNDLE_SIZE); bank->bundle = bundle; /* allocate ring handles for this bank */ if (CPA_STATUS_SUCCESS != init_rings_from_bank(accel_dev, bank)) { adf_io_free_bundle(bank->bundle); bank->bundle = NULL; return CPA_STATUS_FAIL; } bank->num_rings_per_bank = accel_dev->maxNumRingsPerBank; return CPA_STATUS_SUCCESS; } static void adf_proxy_set_bank_default_info(icp_accel_dev_t *dev) { adf_dev_bank_handle_t *banks = dev->banks; int32_t i; for (i = 0; i < dev->maxNumBanks; i++, banks++) { banks->bank_number = i; banks->bank_offset = 0; banks->tx_rings_mask = 0xff; banks->ring_mask = 0; } } STATIC CpaStatus adf_proxy_populate_bank_ring_info(icp_accel_dev_t *accel_dev) { adf_dev_bank_handle_t *bankHandler; Cpa32U *inflight; Cpa32U numOfBanksPerDevice = 0; Cpa32U size = 0; Cpa32U device_id = 0; device_id = accel_dev->accelId; numOfBanksPerDevice = accel_dev->maxNumBanks; /* allocate bank handler array */ size = sizeof(adf_dev_bank_handle_t) * numOfBanksPerDevice; bankHandler = ICP_MALLOC_GEN(size); if (NULL == bankHandler) { ADF_ERROR("Failed to allocate memory - bankHandler\n"); return CPA_STATUS_FAIL; } ICP_MEMSET(bankHandler, 0, size); accel_dev->banks = bankHandler; adf_proxy_set_bank_default_info(accel_dev); /* allocate ring in-flight array ring put/get optimization */ size = sizeof(*inflight) * (accel_dev->maxNumRingsPerBank >> 1) * numOfBanksPerDevice; inflight = ICP_MALLOC_GEN(size); if (NULL == inflight) { ADF_ERROR("Failed to allocate memory - ringInflights\n"); ICP_FREE(accel_dev->banks); return CPA_STATUS_FAIL; } ringInflights[device_id] = inflight; return CPA_STATUS_SUCCESS; } STATIC CpaStatus adf_proxy_populate_device_info(icp_accel_dev_t *accel_dev) { return adf_proxy_populate_bank_ring_info(accel_dev); } STATIC void adf_proxy_repopulate_bank_ring_info(icp_accel_dev_t *accel_dev) { adf_proxy_set_bank_default_info(accel_dev); } STATIC void adf_proxy_repopulate_device_info(icp_accel_dev_t *accel_dev) { adf_proxy_repopulate_bank_ring_info(accel_dev); } void adf_proxy_depopulate_bank_ring_info(icp_accel_dev_t *accel_dev) { Cpa32U device_id = 0; device_id = accel_dev->accelId; ICP_FREE(accel_dev->banks); ICP_FREE(ringInflights[device_id]); } void adf_proxy_depopulate_device_info(icp_accel_dev_t *accel_dev) { adf_proxy_depopulate_bank_ring_info(accel_dev); } STATIC INLINE int adf_dev_bank_handle_get(adf_dev_bank_handle_t *bank) { return __sync_fetch_and_add(&bank->refs, 1); } STATIC INLINE int adf_dev_bank_handle_put(adf_dev_bank_handle_t *bank) { return __sync_fetch_and_sub(&bank->refs, 1); } STATIC INLINE int adf_dev_bank_handle_check(adf_dev_bank_handle_t *bank) { return __sync_val_compare_and_swap(&bank->refs, 0, 0); } /* * Check and free the ring and bundle * This function is used to free the bundle and ring in the bank * handle when the reference count is set as ZERO. */ STATIC void adf_free_bundle(adf_dev_bank_handle_t *bank) { if (0 != adf_dev_bank_handle_check(bank)) { return; } if (bank->rings) { ICP_FREE(bank->rings); bank->rings = NULL; } if (bank->bundle) { adf_io_free_bundle(bank->bundle); bank->bundle = NULL; } if (bank->csr_addr_shadow) { ICP_FREE(bank->csr_addr_shadow); bank->csr_addr_shadow = NULL; } } STATIC void adf_clean_bundle(adf_dev_bank_handle_t *bank) { if (0 == adf_dev_bank_handle_check(bank)) { ICP_FREE(bank->rings); bank->csr_addr = bank->csr_addr_shadow; adf_io_free_bundle(bank->bundle); bank->bundle = NULL; bank->rings = NULL; } } STATIC CpaStatus adf_populate_ring_info_internal(adf_dev_ring_handle_t *pRingHandle, icp_accel_dev_t *accel_dev, icp_transport_type trans_type, icp_trans_callback callback, const char *section, const char *service_name, const Cpa32U accel_nr, const Cpa32U bank_nr, icp_resp_deliv_method resp, const icp_adf_ringInfoService_t info, const Cpa32U num_msgs, const Cpa32U msg_size, int ring_rnum) { size_t len = 0; Cpa32U in_flight_index = 0; pRingHandle->is_wireless = 0; pRingHandle->ringResponseQuota = 0; pRingHandle->coal_write_count = 0; pRingHandle->csrTailOffset = 0; pRingHandle->accel_dev = accel_dev; pRingHandle->trans_type = trans_type; len = ICP_STRNLEN(service_name, ICP_MAX_STR_LEN) + 1; memcpy(pRingHandle->service_name, service_name, len); pRingHandle->service_name_len = len; len = ICP_STRNLEN(section, ICP_MAX_STR_LEN) + 1; memcpy(pRingHandle->section_name, section, len); pRingHandle->section_name_len = len; pRingHandle->callback = callback; pRingHandle->accel_num = accel_nr; pRingHandle->bank_num = bank_nr; pRingHandle->resp = resp; pRingHandle->info = info; if (ICP_RESP_TYPE_POLL == resp) { /* Set the polling mask for this ring handle. */ pRingHandle->pollingMask = 1 << ring_rnum; } else if (ICP_RESP_TYPE_IRQ == resp) { /* epoll rings are also polled, so we need to set both * their polling and interrupt mask */ pRingHandle->pollingMask = 1 << ring_rnum; pRingHandle->interrupt_user_mask = 1 << ring_rnum; } else if (ICP_RESP_TYPE_NONE != resp) { ADF_ERROR("Not implemented yet\n"); return CPA_STATUS_FAIL; } /* To save size we are going to reuse the ring space var * to pass down the ring num_msgs. space is in bytes * and is only used later in the msg put and get logic. * num_msgs is used only to allocate appropriate * memory for the ring and is not subsequently stored */ pRingHandle->space = num_msgs; pRingHandle->message_size = msg_size; pRingHandle->ring_num = ring_rnum; /* request and response ring will share the same index */ if (pRingHandle->ring_num < accel_dev->maxNumRingsPerBank / 2) { in_flight_index = ((accel_dev->maxNumRingsPerBank * pRingHandle->bank_num) >> 1) + pRingHandle->ring_num; } else { in_flight_index = ((accel_dev->maxNumRingsPerBank * pRingHandle->bank_num) >> 1) + (pRingHandle->ring_num - accel_dev->maxNumRingsPerBank / 2); } /* Initialise the pRingHandle in-flight */ pRingHandle->in_flight = ringInflights[accel_dev->accelId] + in_flight_index; *pRingHandle->in_flight = 0; /* Initialise the pRingHandle atomic flag. */ osalAtomicSet(1, (OsalAtomic *)&(pRingHandle->pollingInProgress)); return CPA_STATUS_SUCCESS; } STATIC CpaStatus adf_populate_ring_info(adf_dev_ring_handle_t *pRingHandle, icp_accel_dev_t *accel_dev, icp_transport_type trans_type, icp_trans_callback callback, const char *section, const char *service_name, const Cpa32U accel_nr, const Cpa32U bank_nr, icp_resp_deliv_method resp, const icp_adf_ringInfoService_t info, const Cpa32U num_msgs, const Cpa32U msg_size, int ring_rnum) { size_t len = 0; len = ICP_STRNLEN(service_name, ICP_MAX_STR_LEN) + 1; pRingHandle->service_name = ICP_MALLOC_GEN(len); if (NULL == pRingHandle->service_name) { ADF_ERROR("unable to allocate service buffer\n"); return CPA_STATUS_FAIL; } len = ICP_STRNLEN(section, ICP_MAX_STR_LEN) + 1; pRingHandle->section_name = ICP_MALLOC_GEN(len); if (NULL == pRingHandle->section_name) { ICP_FREE(pRingHandle->service_name); ADF_ERROR("unable to allocate section name buffer\n"); return CPA_STATUS_FAIL; } pRingHandle->user_lock = ICP_MALLOC_GEN(sizeof(ICP_MUTEX)); if (!pRingHandle->user_lock) { ICP_FREE(pRingHandle->service_name); ICP_FREE(pRingHandle->section_name); ADF_ERROR("Could not alloc memory for ring lock\n"); return CPA_STATUS_FAIL; } if (OSAL_SUCCESS != ICP_MUTEX_INIT(pRingHandle->user_lock)) { ICP_FREE(pRingHandle->service_name); ICP_FREE(pRingHandle->section_name); ICP_FREE(pRingHandle->user_lock); ADF_ERROR("Mutex init failed for user_lock\n"); return CPA_STATUS_RESOURCE; } if (CPA_STATUS_SUCCESS != adf_populate_ring_info_internal(pRingHandle, accel_dev, trans_type, callback, section, service_name, accel_nr, bank_nr, resp, info, num_msgs, msg_size, ring_rnum)) { ICP_FREE(pRingHandle->service_name); ICP_FREE(pRingHandle->section_name); ICP_MUTEX_UNINIT(pRingHandle->user_lock); ICP_FREE(pRingHandle->user_lock); ADF_ERROR("Failed to populate the ring info\n"); return CPA_STATUS_FAIL; }; return CPA_STATUS_SUCCESS; } STATIC CpaStatus adf_repopulate_ring_info(adf_dev_ring_handle_t *pRingHandle, icp_accel_dev_t *accel_dev, icp_transport_type trans_type, icp_trans_callback callback, const char *section, const char *service_name, const Cpa32U accel_nr, const Cpa32U bank_nr, icp_resp_deliv_method resp, const icp_adf_ringInfoService_t info, const Cpa32U num_msgs, const Cpa32U msg_size, int ring_rnum) { return adf_populate_ring_info_internal(pRingHandle, accel_dev, trans_type, callback, section, service_name, accel_nr, bank_nr, resp, info, num_msgs, msg_size, ring_rnum); } /* * Create a transport handle * The function sends ioctl request to adf user proxy to create * a ring and then mmaps it to userspace memory. If it is a response * ring and there is no reading thread running for the device * the function creates one. */ CpaStatus icp_adf_transCreateHandle(icp_accel_dev_t *accel_dev, icp_transport_type trans_type, const char *section, const Cpa32U accel_nr, const Cpa32U bank_nr, const char *service_name, const icp_adf_ringInfoService_t info, icp_trans_callback callback, icp_resp_deliv_method resp, const Cpa32U num_msgs, const Cpa32U msg_size, icp_comms_trans_handle *trans_handle) { CpaStatus status = CPA_STATUS_SUCCESS; adf_dev_ring_handle_t *pRingHandle = NULL; Cpa32U ring_number = 0; ICP_CHECK_FOR_NULL_PARAM(accel_dev); ICP_CHECK_FOR_NULL_PARAM(trans_handle); adf_dev_bank_handle_t *banks = accel_dev->banks; adf_dev_bank_handle_t *bank = &banks[bank_nr]; int nodeid = accel_dev->numa_node; int ring_rnum = 0; char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { '\0' }; /* here init the bank: get a free bundle from UIO and mmap it * It's not suitable to put it into device init stage, * for at that time, we don't know which device the user will be use */ if (NULL == bank->bundle) { ICP_MUTEX_LOCK(bank->user_bank_lock); if (0 > init_bank_from_accel(accel_dev, bank)) { ICP_MUTEX_UNLOCK(bank->user_bank_lock); return CPA_STATUS_FAIL; } ICP_MUTEX_UNLOCK(bank->user_bank_lock); } if (CPA_STATUS_SUCCESS == icp_adf_cfgGetParamValue(accel_dev, section, service_name, val)) { ring_rnum = strtoul(val, NULL, 10); if ((ring_rnum < 0) || (ring_rnum >= accel_dev->maxNumRingsPerBank)) { ADF_ERROR("Invalid ring num\n"); adf_free_bundle(bank); return CPA_STATUS_FAIL; } } else { adf_free_bundle(bank); return CPA_STATUS_FAIL; } /* Reserve the ring in the kernel driver */ if (CPA_STATUS_SUCCESS != adf_io_reserve_ring(accel_dev->accelId, bank_nr, ring_rnum)) { adf_free_bundle(bank); return CPA_STATUS_FAIL; } /* allocate and setup ring handle structure */ pRingHandle = ICP_MALLOC_GEN(sizeof(adf_dev_ring_handle_t)); if (NULL == pRingHandle) { ADF_ERROR("unable to allocate pRingHandle buffer\n"); if (CPA_STATUS_SUCCESS != adf_io_release_ring(accel_dev->accelId, bank_nr, ring_rnum)) { ADF_ERROR("Failed to release the ring \n"); } adf_free_bundle(bank); return CPA_STATUS_FAIL; } ICP_MEMSET(pRingHandle, 0, sizeof(adf_dev_ring_handle_t)); if (CPA_STATUS_SUCCESS != adf_populate_ring_info(pRingHandle, accel_dev, trans_type, callback, section, service_name, accel_nr, bank_nr, resp, info, num_msgs, msg_size, ring_rnum)) { ICP_FREE(pRingHandle); if (CPA_STATUS_SUCCESS != adf_io_release_ring(accel_dev->accelId, bank_nr, ring_rnum)) { ADF_ERROR("Failed to release the ring \n"); } adf_free_bundle(bank); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != adf_init_ring(pRingHandle, bank, ring_rnum, bank->csr_addr, num_msgs, msg_size, nodeid)) { ADF_ERROR("adf_init_ring failed\n"); ICP_FREE(pRingHandle->section_name); ICP_FREE(pRingHandle->service_name); ICP_FREE(pRingHandle->user_lock); ICP_FREE(pRingHandle); if (CPA_STATUS_SUCCESS != adf_io_release_ring(accel_dev->accelId, bank_nr, ring_rnum)) { ADF_ERROR("Failed to release the ring \n"); } adf_free_bundle(bank); return CPA_STATUS_FAIL; } adf_dev_bank_handle_get(bank); *trans_handle = (icp_comms_trans_handle *)pRingHandle; status = icp_adf_transGetRingNum(*trans_handle, &ring_number); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("icp_adf_transGetRingNum failed\n"); icp_adf_transReleaseHandle(*trans_handle); *trans_handle = NULL; return CPA_STATUS_FAIL; } /* callback has been overwritten in kernelspace * so have to set it to the userspace callback again */ pRingHandle->callback = callback; (bank->rings)[ring_rnum] = pRingHandle; banks[pRingHandle->bank_num].interrupt_mask |= pRingHandle->interrupt_user_mask; banks[pRingHandle->bank_num].pollingMask |= pRingHandle->pollingMask; /* Configure interrupts in the hardware only for epoll mode */ if (ICP_RESP_TYPE_IRQ == resp) { uint32_t *csr_base_addr = pRingHandle->csr_addr; WRITE_CSR_INT_COL_EN(pRingHandle->bank_offset, banks[pRingHandle->bank_num].interrupt_mask); } return CPA_STATUS_SUCCESS; } CpaStatus icp_adf_transReinitHandle(icp_accel_dev_t *accel_dev, icp_transport_type trans_type, const char *section, const Cpa32U accel_nr, const Cpa32U bank_nr, const char *service_name, const icp_adf_ringInfoService_t info, icp_trans_callback callback, icp_resp_deliv_method resp, const Cpa32U num_msgs, const Cpa32U msg_size, icp_comms_trans_handle *trans_handle) { CpaStatus status = CPA_STATUS_SUCCESS; adf_dev_ring_handle_t *pRingHandle = NULL; Cpa32U ring_number = 0; ICP_CHECK_FOR_NULL_PARAM(accel_dev); ICP_CHECK_FOR_NULL_PARAM(trans_handle); adf_dev_bank_handle_t *banks = accel_dev->banks; adf_dev_bank_handle_t *bank = &banks[bank_nr]; int nodeid = accel_dev->numa_node; int ring_rnum = 0; char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { '\0' }; pRingHandle = *trans_handle; /* here init the bank: get a free bundle from UIO and mmap it * It's not suitable to put it into device init stage, * for at that time, we don't know which device the user will be use */ if (NULL == bank->bundle) { ICP_MUTEX_LOCK(bank->user_bank_lock); if (CPA_STATUS_SUCCESS != reinit_bank_from_accel(accel_dev, bank)) { ICP_MUTEX_UNLOCK(bank->user_bank_lock); goto trans_reinit_handle_failed; } ICP_MUTEX_UNLOCK(bank->user_bank_lock); } adf_dev_bank_handle_get(bank); if (CPA_STATUS_SUCCESS == icp_adf_cfgGetParamValue(accel_dev, section, service_name, val)) { ring_rnum = strtoul(val, NULL, 10); if ((ring_rnum < 0) || (ring_rnum >= accel_dev->maxNumRingsPerBank)) { ADF_ERROR("Invalid ring num\n"); goto trans_reinit_handle_failed; } } else { goto trans_reinit_handle_failed; } /* Reserve the ring in the kernel driver */ if (CPA_STATUS_SUCCESS != adf_io_reserve_ring(accel_dev->accelId, bank_nr, ring_rnum)) { goto trans_reinit_handle_failed; } if (CPA_STATUS_SUCCESS != adf_repopulate_ring_info(pRingHandle, accel_dev, trans_type, callback, section, service_name, accel_nr, bank_nr, resp, info, num_msgs, msg_size, ring_rnum)) { goto trans_reinit_handle_failed; } if (CPA_STATUS_SUCCESS != adf_reinit_ring(pRingHandle, bank, ring_rnum, bank->csr_addr, num_msgs, msg_size, nodeid)) { ADF_ERROR("adf_init_ring failed\n"); goto trans_reinit_handle_failed; } pRingHandle->accel_dev = accel_dev; *trans_handle = (icp_comms_trans_handle *)pRingHandle; status = icp_adf_transGetRingNum(*trans_handle, &ring_number); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("icp_adf_transGetRingNum failed\n"); goto trans_reinit_handle_failed; } /* callback has been overwritten in kernelspace * so have to set it to the userspace callback again */ pRingHandle->callback = callback; (bank->rings)[ring_rnum] = pRingHandle; banks[pRingHandle->bank_num].interrupt_mask |= pRingHandle->interrupt_user_mask; banks[pRingHandle->bank_num].pollingMask |= pRingHandle->pollingMask; /* Configure interrupts in the hardware only for epoll mode */ if (ICP_RESP_TYPE_IRQ == resp) { uint32_t *csr_base_addr = pRingHandle->csr_addr; WRITE_CSR_INT_COL_EN(pRingHandle->bank_offset, banks[pRingHandle->bank_num].interrupt_mask); } return CPA_STATUS_SUCCESS; trans_reinit_handle_failed: icp_adf_transReleaseHandle(*trans_handle); *trans_handle = NULL; return CPA_STATUS_FAIL; } STATIC CpaStatus icp_adf_transCleanHandle(icp_comms_trans_handle trans_handle) { int ret = 0; icp_accel_dev_t *accel_dev = NULL; adf_dev_ring_handle_t *pRingHandle = NULL; adf_dev_bank_handle_t *pbanks = NULL; Cpa32U ring_number; ICP_CHECK_FOR_NULL_PARAM(trans_handle); pRingHandle = (adf_dev_ring_handle_t *)trans_handle; ICP_CHECK_FOR_NULL_PARAM(pRingHandle->accel_dev); accel_dev = pRingHandle->accel_dev; ret = icp_adf_transGetRingNum(pRingHandle, &ring_number); if (CPA_STATUS_SUCCESS != ret) { ADF_ERROR("icp_adf_transGetRingNum failed\n"); return ret; } pbanks = accel_dev->banks; /* update user process IRQ mask * Every time userspace ring gets a message it reads it from the ring * and as the last step needs to enable the IRQ for the ring so * the driver could get notifications that there is data on the ring. * So this is important to keep the IRQ mask up to date */ pbanks[pRingHandle->bank_num].interrupt_mask &= (~(1 << pRingHandle->ring_num)); pbanks[pRingHandle->bank_num].pollingMask &= (~(1 << pRingHandle->ring_num)); /* send the request down to the kernel. * NOTE: Don't send release_handle if the kernel proxy is not running * The proxy down there will cleanup the rings anyway. * */ ret = adf_io_release_ring( accel_dev->accelId, pRingHandle->bank_num, pRingHandle->ring_num); if (CPA_STATUS_SUCCESS != ret) { ADF_ERROR("Failed to release the ring \n"); } return ret; } /* * Release a transport handle * The function sends ioctl request to adf user proxy to release a ring */ CpaStatus icp_adf_transReleaseHandle(icp_comms_trans_handle trans_handle) { icp_accel_dev_t *accel_dev = NULL; adf_dev_ring_handle_t *pRingHandle = NULL; adf_dev_bank_handle_t *pbanks = NULL; CpaStatus status = CPA_STATUS_SUCCESS; ICP_CHECK_FOR_NULL_PARAM(trans_handle); pRingHandle = (adf_dev_ring_handle_t *)trans_handle; ICP_CHECK_FOR_NULL_PARAM(pRingHandle->accel_dev); accel_dev = pRingHandle->accel_dev; status = icp_adf_transCleanHandle(trans_handle); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("icp_adf_transCleanHandle failed \n"); } adf_cleanup_ring(pRingHandle); if (NULL != pRingHandle->service_name) { ICP_FREE(pRingHandle->service_name); ICP_FREE(pRingHandle->section_name); } if (NULL != pRingHandle->user_lock) { ICP_MUTEX_UNINIT(pRingHandle->user_lock); ICP_FREE(pRingHandle->user_lock); } pbanks = accel_dev->banks; if (NULL != pbanks) { pbanks = pbanks + pRingHandle->bank_num; if (NULL != pbanks->rings) { pbanks->rings[pRingHandle->ring_num] = NULL; adf_dev_bank_handle_put(pbanks); } adf_free_bundle(pbanks); } ICP_FREE(pRingHandle); return status; } /* * Reset a transport handle * The function resets some of the contents of the ring and also sends * ioctl request to adf user proxy to release a ring */ CpaStatus icp_adf_transResetHandle(icp_comms_trans_handle trans_handle) { icp_accel_dev_t *accel_dev = NULL; adf_dev_ring_handle_t *pRingHandle = NULL; adf_dev_bank_handle_t *pbanks = NULL; CpaStatus status = CPA_STATUS_SUCCESS; ICP_CHECK_FOR_NULL_PARAM(trans_handle); pRingHandle = (adf_dev_ring_handle_t *)trans_handle; ICP_CHECK_FOR_NULL_PARAM(pRingHandle->accel_dev); accel_dev = pRingHandle->accel_dev; status = icp_adf_transCleanHandle(trans_handle); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("icp_adf_transCleanHandle failed \n"); } adf_reset_ring(pRingHandle); if (NULL != pRingHandle->service_name) { ICP_MEMSET(pRingHandle->service_name, 0, strnlen(pRingHandle->service_name, ICP_MAX_STR_LEN) + 1); ICP_MEMSET(pRingHandle->section_name, 0, strnlen(pRingHandle->section_name, ICP_MAX_STR_LEN) + 1); } pbanks = accel_dev->banks; if (NULL != pbanks) { pbanks = pbanks + pRingHandle->bank_num; if (NULL != pbanks->rings) { pbanks->rings[pRingHandle->ring_num] = NULL; adf_dev_bank_handle_put(pbanks); adf_clean_bundle(pbanks); } } return status; } /* * Returns ring number for the trans handle */ CpaStatus icp_adf_transGetRingNum(icp_comms_trans_handle trans_handle, Cpa32U *ringNum) { adf_dev_ring_handle_t *pRingHandle = NULL; ICP_CHECK_FOR_NULL_PARAM(trans_handle); pRingHandle = (adf_dev_ring_handle_t *)trans_handle; ICP_CHECK_FOR_NULL_PARAM(pRingHandle->accel_dev); *ringNum = (pRingHandle->bank_num * pRingHandle->accel_dev->maxNumRingsPerBank) + pRingHandle->ring_num; return CPA_STATUS_SUCCESS; } /* * Put a message on the transport handle */ CpaStatus icp_adf_transPutMsg(icp_comms_trans_handle trans_handle, Cpa32U *inBuf, Cpa32U bufLen, Cpa64U *seq_num) { adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_handle; ICP_CHECK_FOR_NULL_PARAM(trans_handle); ICP_CHECK_PARAM_RANGE(bufLen * ICP_ADF_BYTES_PER_WORD, pRingHandle->message_size, pRingHandle->message_size); return adf_user_put_msg(pRingHandle, inBuf, seq_num); } /* * icp_adf_getInflightRequests * Function to fetch in-flight and max in-flight request counts for the * given trans_handle. */ CpaStatus icp_adf_getInflightRequests(icp_comms_trans_handle trans_handle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests) { CpaStatus status = CPA_STATUS_SUCCESS; adf_dev_ring_handle_t *pRingHandle = (adf_dev_ring_handle_t *)trans_handle; ICP_CHECK_FOR_NULL_PARAM(trans_handle); status = adf_user_get_inflight_requests( pRingHandle, maxInflightRequests, numInflightRequests); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("adf_user_get_inflight_requests failed with %d status\n", status); } return status; } /* * adf_user_unmap_rings * Device is going down - unmap all rings allocated for this device */ CpaStatus adf_user_unmap_rings(icp_accel_dev_t *accel_dev) { CpaStatus stat = CPA_STATUS_SUCCESS; adf_dev_ring_handle_t *pRingHandle = NULL; adf_dev_bank_handle_t *bank = NULL; int i = 0, l = 0; bank = accel_dev->banks; for (i = 0; i < accel_dev->maxNumBanks; i++) { if (NULL == bank->rings) continue; for (l = 0; l < accel_dev->maxNumRingsPerBank; l++) { pRingHandle = (bank->rings)[i]; if (pRingHandle) adf_ring_freebuf(pRingHandle); } } return stat; } /* * Internal functions which performs all the * tasks necessary to poll a response ring. */ CpaStatus adf_pollRing(icp_accel_dev_t *accel_dev, adf_dev_ring_handle_t *pRingHandle, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_RETRY; /* Check to see if this ring is already being polled by * another core or thread. DecAndTest returns TRUE * only if pRingHandle->pollingInProgress was previously * equal to one and then sets the var to zero. While * pRingHandle->pollingInProgress is still zero no other * thread will be able to poll. pollingInProgress is * reset to one once the notify function is done. */ if (osalAtomicDecAndTest((OsalAtomic *)&(pRingHandle->pollingInProgress))) { /* Set the ring response quota. */ pRingHandle->ringResponseQuota = response_quota; status = adf_user_notify_msgs_poll(pRingHandle); osalAtomicSet(1, (OsalAtomic *)&(pRingHandle->pollingInProgress)); } return status; } /* * This function allows the user to poll the response rings of a given * bank to determine if any of the rings have messages that need to be * read. This method is used as an alternative to reading messages * via the ISR method. * N.B. response quota is per ring. */ CpaStatus icp_adf_pollBank(Cpa32U accelId, Cpa32U bank_number, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_RETRY; icp_accel_dev_t *accel_dev = NULL; adf_dev_bank_handle_t *bank = NULL; adf_dev_bank_handle_t *banks = NULL; adf_dev_ring_handle_t *pRingHandle = NULL; Cpa32U csrVal = 0; Cpa32U ringnum_in_bank = 0; Cpa32U stat_total = 0; /* Find the accel device associated with the accelId * passed in. */ accel_dev = adf_devmgrGetAccelDevByAccelId(accelId); if (!accel_dev) { ADF_ERROR("There is no accel device associated" " with this accel id.\n"); return CPA_STATUS_INVALID_PARAM; } ICP_CHECK_PARAM_LT_MAX(bank_number, accel_dev->maxNumBanks); banks = accel_dev->banks; bank = &banks[bank_number]; ICP_MUTEX_LOCK(bank->user_bank_lock); /* Read the ring status CSR to determine which rings are empty. */ csrVal = READ_CSR_E_STAT_EXT(bank->csr_addr, bank->bank_offset); /* Complement to find which rings have data to be processed. */ csrVal = ~csrVal; /* Return RETRY if the bank polling rings * are all empty. */ if (!(csrVal & bank->pollingMask)) { ICP_MUTEX_UNLOCK(bank->user_bank_lock); return CPA_STATUS_RETRY; } /* * Loop over all rings within this bank. * The ringHandles structure is global to all * rings hence while we loop over all rings in the * bank we use ring_number to get the global * RingHandle. */ for (ringnum_in_bank = 0; ringnum_in_bank < accel_dev->maxNumRingsPerBank; ringnum_in_bank++) { pRingHandle = (bank->rings)[ringnum_in_bank]; /* If this ring has not being created move to next ring. */ if (NULL == pRingHandle) { continue; } /* And with polling ring mask * If the there is no data on this ring move to the next one */ if (!(csrVal & pRingHandle->pollingMask)) { continue; } /* Poll the ring */ status = adf_pollRing(accel_dev, pRingHandle, response_quota); if (CPA_STATUS_SUCCESS == status) { stat_total++; } /* Re-enable interrupts in case we are using epoll mode */ if (ICP_RESP_TYPE_IRQ == pRingHandle->resp) { WRITE_CSR_INT_COL_EN_EXT( bank->csr_addr, pRingHandle->bank_offset, bank->interrupt_mask); } } /* Return SUCCESS if adf_pollRing returned SUCCESS at any stage */ ICP_MUTEX_UNLOCK(bank->user_bank_lock); if (stat_total) { return CPA_STATUS_SUCCESS; } return CPA_STATUS_RETRY; } /* * This function allows the user to poll all the response rings * belonging to a process per device. * This method is used as an alternative to the reading messages * via the ISR method. * N.B. response_quota is per ring. */ CpaStatus icp_adf_pollAllBanks(Cpa32U accelId, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_RETRY; icp_accel_dev_t *accel_dev = NULL; adf_dev_bank_handle_t *bank = NULL; adf_dev_bank_handle_t *banks = NULL; Cpa32U bank_num = 0; Cpa32U stat_total = 0; /* Find the accel device associated with the accelId * passed in. */ accel_dev = adf_devmgrGetAccelDevByAccelId(accelId); if (!accel_dev) { ADF_ERROR("There is no accel device associated" " with this accel id.\n"); return CPA_STATUS_INVALID_PARAM; } /* Loop over banks and call icp_adf_pollBank. */ banks = accel_dev->banks; for (bank_num = 0; bank_num < accel_dev->maxNumBanks; bank_num++) { bank = &(banks)[bank_num]; /* if there are no polling rings on this bank * continue to the next bank number. */ if (bank->pollingMask == 0) { continue; } status = icp_adf_pollBank(accelId, bank_num, response_quota); if (CPA_STATUS_SUCCESS == status) { stat_total++; } } /* Return SUCCESS if icp_adf_pollBank returned SUCCESS * at any stage. icp_adf_pollBank cannot * return fail in the above case. */ if (stat_total) { return CPA_STATUS_SUCCESS; } return CPA_STATUS_RETRY; } static CpaStatus SalCtrl_DevErr_GenResponses(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_RETRY; Cpa32U enabled_services = 0; status = SalCtrl_GetEnabledServices(accel_dev, &enabled_services); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to get supported services\n"); return status; } ADF_DEBUG("Pollbank: generate dummy responses\n"); status = SalCtrl_DcDevErr_GenResponses(accel_dev, enabled_services); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to generate DC responses by polling bank\n"); return status; } #ifndef ICP_DC_ONLY status = SalCtrl_CyDevErr_GenResponses(accel_dev, enabled_services); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to generate CY responses by polling bank\n"); return status; } #endif return status; } CpaStatus icp_sal_pollBank(Cpa32U accelId, Cpa32U bank_number, Cpa32U response_quota) { return icp_adf_pollBank(accelId, bank_number, response_quota); } /* * This function allows the user to poll all the response rings * belonging to a process per device. * This method is used as an alternative to the reading messages * via the ISR method. * N.B. response_quota is per ring. */ CpaStatus icp_sal_pollAllBanks(Cpa32U accelId, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_RETRY; icp_accel_dev_t *accel_dev = NULL; /* Find the accel device associated with the accelId * passed in. */ accel_dev = adf_devmgrGetAccelDevByAccelId(accelId); if (!accel_dev) { ADF_ERROR("There is no accel device associated" " with this accel id.\n"); return CPA_STATUS_INVALID_PARAM; } if (icp_adf_isDevInError(accel_dev)) { status = SalCtrl_DevErr_GenResponses(accel_dev); if (CPA_STATUS_SUCCESS != status) { ADF_ERROR("Failed to generate dummy responses for banks\n"); } return status; } status = icp_adf_pollAllBanks(accelId, response_quota); return status; } /* * This will set the fd of the UIO device this instance * handler is using. If more than one transaction handler * are ever present, this will need to be refactored to * return the appropriate fd of the appropriate bank */ CpaStatus icp_adf_transGetFdForHandle(icp_comms_trans_handle trans_hnd, int *fd) { int local_fd = -1; adf_dev_ring_handle_t *ring_handle = (adf_dev_ring_handle_t *)trans_hnd; struct adf_io_user_bundle *bundle = (struct adf_io_user_bundle *)ring_handle->bank_data->bundle; local_fd = bundle->fd; if (local_fd >= 0) { *fd = local_fd; return CPA_STATUS_SUCCESS; } else { return CPA_STATUS_FAIL; } } /* * This function allows the user to poll the response ring. The * ring number to be polled is supplied by the user via the * trans handle for that ring. The trans_hnd is a pointer * to an array of trans handles. This ring is * only polled if it contains data. * This method is used as an alternative to the reading messages * via the ISR method. * This function will return RETRY if the ring is empty. */ CpaStatus icp_adf_pollInstance(icp_comms_trans_handle *trans_hnd, Cpa32U num_transHandles, Cpa32U response_quota) { CpaStatus status = CPA_STATUS_RETRY; adf_dev_ring_handle_t *ring_hnd = NULL; adf_dev_ring_handle_t *ring_hnd_first = NULL; Cpa8U *csr_base_addr = NULL; Cpa32U i = 0; Cpa32U stat_total = 0; ICP_CHECK_FOR_NULL_PARAM(trans_hnd); ring_hnd_first = (adf_dev_ring_handle_t *)trans_hnd[0]; if (!ring_hnd_first) { return CPA_STATUS_FAIL; } ICP_MUTEX_LOCK(ring_hnd_first->user_lock); csr_base_addr = (Cpa8U *)ring_hnd_first->csr_addr; for (i = 0; i < num_transHandles; i++) { ring_hnd = (adf_dev_ring_handle_t *)trans_hnd[i]; if (!ring_hnd) { ICP_MUTEX_UNLOCK(ring_hnd_first->user_lock); return CPA_STATUS_FAIL; } /* And with polling ring mask. If the * polling ring has no data move to the * next ring handle.*/ if (!ring_hnd->pollingMask) { continue; } /* Poll the ring. */ status = adf_pollRing(ring_hnd->accel_dev, ring_hnd, response_quota); if (CPA_STATUS_SUCCESS == status) { stat_total++; } /* Re-enable interrupts in case we are using epoll mode */ if (ICP_RESP_TYPE_IRQ == ring_hnd->resp) { WRITE_CSR_INT_COL_EN(ring_hnd->bank_offset, ring_hnd->bank_data->interrupt_mask); } } ICP_MUTEX_UNLOCK(ring_hnd_first->user_lock); /* If any of the rings in the instance had data and was polled * return SUCCESS. */ if (stat_total) { return CPA_STATUS_SUCCESS; } return CPA_STATUS_RETRY; } /* * This function allows the caller to check whether the response ring is empty * or not. The ring number to be polled is supplied by the user via the trans * handle for that ring. The trans_hnd is a pointer to an array of trans * handles. * This function will return RETRY if the ring is not empty. */ CpaStatus icp_adf_check_RespInstance(icp_comms_trans_handle *trans_hnd, Cpa32U num_transHandles) { CpaBoolean is_ring_empty = CPA_TRUE; adf_dev_ring_handle_t *ring_hnd = NULL; Cpa32U i = 0; ICP_CHECK_FOR_NULL_PARAM(trans_hnd); for (i = 0; i < num_transHandles; i++) { ring_hnd = (adf_dev_ring_handle_t *)trans_hnd[i]; if (!ring_hnd) { return CPA_STATUS_FAIL; } /* The ring is polled only when it is set as poll mode. */ if (!ring_hnd->pollingMask) { continue; } is_ring_empty = adf_user_check_resp_ring(ring_hnd); if (CPA_FALSE == is_ring_empty) { return CPA_STATUS_RETRY; } } return CPA_STATUS_SUCCESS; } /* * This function allows the user to check ring error bit status */ CpaStatus icp_adf_checkRingError(icp_comms_trans_handle *trans_hnd, Cpa32U num_transHandles) { CpaStatus status = CPA_STATUS_SUCCESS; adf_dev_ring_handle_t *ring_hnd = NULL; adf_dev_ring_handle_t *ring_hnd_first = NULL; Cpa32U i = 0; Cpa32S res; ICP_CHECK_FOR_NULL_PARAM(trans_hnd); ring_hnd_first = (adf_dev_ring_handle_t *)trans_hnd[0]; if (!ring_hnd_first) { return CPA_STATUS_SUCCESS; } ICP_MUTEX_LOCK(ring_hnd_first->user_lock); for (i = 0; i < num_transHandles; i++) { ring_hnd = (adf_dev_ring_handle_t *)trans_hnd[i]; if (!ring_hnd->pollingMask) { continue; } res = adf_user_check_ring_error(ring_hnd); if (res == -EINTR || res == -EL2HLT) { status = CPA_STATUS_FAIL; break; } } ICP_MUTEX_UNLOCK(ring_hnd_first->user_lock); return status; } /* * Function initializes internal transport data */ CpaStatus adf_user_transport_init(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; Cpa32S x = 0; adf_dev_bank_handle_t *bank = NULL; adf_dev_bank_handle_t *banks = NULL; ICP_CHECK_FOR_NULL_PARAM(accel_dev); status = adf_proxy_populate_device_info(accel_dev); if (CPA_STATUS_SUCCESS != status) { return status; } banks = accel_dev->banks; for (i = 0; i < accel_dev->maxNumBanks; i++) { bank = &banks[i]; bank->user_bank_lock = ICP_MALLOC_GEN(sizeof(ICP_MUTEX)); if (!bank->user_bank_lock) { ADF_ERROR("Could not alloc memory for bank mutex\n"); for (x = i - 1; x >= 0; x--) { bank = &banks[x]; ICP_MUTEX_UNINIT(bank->user_bank_lock); ICP_FREE(bank->user_bank_lock); } adf_proxy_depopulate_device_info(accel_dev); return CPA_STATUS_FAIL; } if (OSAL_SUCCESS != ICP_MUTEX_INIT(bank->user_bank_lock)) { ADF_ERROR("Mutex init failed for user_bank_lock\n"); for (x = i; x >= 0; x--) { bank = &banks[x]; ICP_MUTEX_UNINIT(bank->user_bank_lock); ICP_FREE(bank->user_bank_lock); } adf_proxy_depopulate_device_info(accel_dev); return CPA_STATUS_RESOURCE; } } return status; } /* * Function reinitializes internal transport data */ CpaStatus adf_user_transport_reinit(icp_accel_dev_t *accel_dev) { Cpa32U i = 0; adf_dev_bank_handle_t *bank = NULL; adf_dev_bank_handle_t *banks = NULL; ICP_CHECK_FOR_NULL_PARAM(accel_dev); adf_proxy_repopulate_device_info(accel_dev); banks = accel_dev->banks; for (i = 0; i < accel_dev->maxNumBanks; i++) { bank = &banks[i]; if (OSAL_SUCCESS != ICP_MUTEX_INIT(bank->user_bank_lock)) { ADF_ERROR("Mutex init failed for user_bank_lock\n"); return CPA_STATUS_RESOURCE; } } return CPA_STATUS_SUCCESS; } /* * Function deinitializes internal transport data */ CpaStatus adf_user_transport_exit(icp_accel_dev_t *accel_dev) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; adf_dev_bank_handle_t *bank = NULL; adf_dev_bank_handle_t *banks = NULL; ICP_CHECK_FOR_NULL_PARAM(accel_dev); banks = accel_dev->banks; for (i = 0; i < accel_dev->maxNumBanks; i++) { bank = &(banks)[i]; if (NULL != bank->bundle) { adf_io_free_bundle(bank->bundle); bank->bundle = NULL; } if (bank->user_bank_lock) { ICP_MUTEX_UNINIT(bank->user_bank_lock); ICP_FREE(bank->user_bank_lock); } ICP_FREE(bank->rings); } adf_proxy_depopulate_device_info(accel_dev); return status; } /* * Function cleans internal transport data */ CpaStatus adf_user_transport_clean(icp_accel_dev_t *accel_dev) { Cpa32U i = 0; Cpa32U device_id = 0; adf_dev_bank_handle_t *bank = NULL; adf_dev_bank_handle_t *banks = NULL; ICP_CHECK_FOR_NULL_PARAM(accel_dev); device_id = accel_dev->accelId; banks = accel_dev->banks; for (i = 0; i < accel_dev->maxNumBanks; i++) { bank = &(banks)[i]; if (NULL != bank->bundle) { adf_io_free_bundle(bank->bundle); bank->bundle = NULL; } if ((bank->user_bank_lock) && (*(ICP_MUTEX *)(bank->user_bank_lock))) { ICP_MUTEX_UNINIT(bank->user_bank_lock); } ICP_FREE(bank->rings); } ICP_MEMSET(ringInflights[device_id], 0, sizeof(Cpa32U) * (accel_dev->maxNumRingsPerBank >> 1) * accel_dev->maxNumBanks); return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/000077500000000000000000000000001503624047500251645ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/README.txt000066400000000000000000000313261503624047500266670ustar00rootroot00000000000000/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ =============================================================================== Intel(r) DH895xCC Sample Code for Security Applications on Intel(r) QuickAssist(r) Technology Intel(r) C6xx Sample Code for Security Applications on Intel(r) QuickAssist(r) Technology Intel(r) C3xxx Sample Code for Security Applications on Intel(r) QuickAssist(r) Technology Intel(r) D15xx Sample Code for Security Applications on Intel(r) QuickAssist(r) Technology Intel(r) C4xxx Sample Code for Security Applications on Intel(r) QuickAssist(r) Technology February, 2020 =============================================================================== Reference ========= - Intel(r) Communications Chipset 89xx Series Software for Linux* Getting Started Guide - Intel(r) QuickAssist Technology Software for Linux* - Getting Started Guide - appropriate HW version - Intel(r) QuickAssist Technology Software for Linux* - Programmer's Guide - appropriate HW version =============================================================================== Installing and Running the Security Sample Performance Tests =============================================================================== 1) General This is how to generate and run sample code for security on Linux. Note that Performance sample code is available only for Linux. The autoconf script is used to build the sample code and driver. The output of which is created in /quickassist/lookaside/access_layer/src/sample_code/build The following autoconf instructions are used to install driver cd / ./configure make uninstall make install The following autoconf instruction is used to install sample code make samples-install To build and install sample code in SRIOV environment The following autoconf instructions are used to install driver and samplecode in host machine ./configure --enable-icp-sriov=host make install make samples-install The following autoconf instructions are used to install driver and samplecode in guest machine ./configure --enable-icp-sriov=guest make install make samples-install Note: Refer to the relevant Getting Started Guide for Virtualization instructions The autoconf automatically performs building sample code. The Calgary Corpus files are installed at the location defined in =============================================================================== 2) Performance Samplecode Execution Instructions To run this performance sample code, on Linux use the following command in user space to execute the user space app ./cpa_sample_code NOTE: All OS security components must be initialized before attempting to run the module. The following tests will then run: Cipher Encrypt AES128-CBC: 100000* operations per crypto instance of packet sizes 64, 128, 256, 204, 512, 1024, 1152, 2048, 4096, IMIX** Algorithm Chaining- AES128-CBC HMAC-SHA1: 100000 operations per crypto instance of packet sizes 64, 128, 256, 204, 512, 1024, 1152, 2048, 4096, IMIX** Cipher Encrypt AES256-CBC: 100000* operations per crypto instance of packet sizes 64, 128, 256, 204, 512, 1024, 1152, 2048, 4096, IMIX** Algorithm Chaining- AES256-CBC HMAC-SHA512: 100000 operations per crypto instance of packet sizes 64, 128, 256, 204, 512, 1024, 1152, 2048, 4096, IMIX** Algorithm Chaining- AES256-CBC HMAC-AES-XCBC: 100000 operations per crypto instance of packet sizes 64, 128, 256, 204, 512, 1024, 1152, 2048, 4096, IMIX** RSA CRT Decrypt 1024, 2048 and 4096 bit: 10000 operations each DH 180bit exponent with 1024, 2048 and 4096 bit modulus DSA L/N Pair of 1024/160 bit: 10000 operations ECDSA 192 bit binary nist curve: 10000 operations Deflate Compression/Decompression Level 1 & 3 on the the Calgary Corpus using 8182 byte buffers. 64k decompression of zlib compresses data if the USE_ZLIB option is set Once the test has completed, "Sample Code Complete" is displayed. *Note the number of operations sent is on a per thread basis. The number of threads is controlled by the lower of: the number of cores the number of crypto instance Based on platform default value for above parameters are configured in driver configuration file **IMIX is a mixture of packet sizes 40%-64Byte 20%-752Byte 35% 1504Byte 5%-8892Byte. of the total submissions The throughput and operations per second output maybe inaccurate for less than 100000 and 10000 submissions per thread for symmetric and asymmetric respectively. By default the sample code is set to submit the minimum number of submissions required for an accurate output. If sample code is to be used to get reliable performance measures one of the following needs to be applied prior to running sample code tests: o Intel SpeedStep(r) Technology needs to be disabled in BIOS =============================================================================== 3) Performance Module Control cpa_sample_code user space application supports optional parameters for controlling which tests run and how many iterations of each test are executed. These optional parameters are passed during module loading. Example: ./cpa_sample_code signOfLife=1 runTests=64 signOfLife parameter is set the minimum number iterations to be executed with below values cyNumBuffers cySymLoops cyAsymLoops dcLoops cySymLoops is the number of iterations of Symmetric operations to be executed, which affects the running time of the following tests a) All Algorithm Chaining tests b) All Cipher Encrypt tests c) Hash HMAC-SHA1 cyAsymLoops is the number of iterations of Asymmetric operations to be executed, which affects the running time of the following tests a) RSA CRT Decrypt b) DSA c) ECDSA d) DH dcLoops is the number of iterations of Compression operations to be executed. The runTests parameter is a bit masked variable used to control which tests are to be executed. runTests=1 Run symmetric tests. runTests=2 Run RSA test. runTests=4 Run DSA test. runTests=8 Run ECDSA test. runTests=16 Run DH test runTests=32 Run Stateless Compression test. runTests=63 Run all tests. (default) runTests=32 runStateful=1 Run both stateful and stateless compression test. runTests=32 runStateful=1 useCnv=1 Run CNV test. runTests=1024 Run SM2 test. runTests=2048 Run SM3&4 test. The current default is runTests=63, run all tests. The default configFileVer=2 is currently the only supported mode of operation. If the wrong version of config file is used the sample code will issue an error message and fail to find any logical instances. getLatency is an optional parameter which will enable Latency measurement. Currently latency measurement is supported only for symmetric cipher i.e. runTest=1 and Compression tests i.e. runTest=32. If signOfLife parameter is passed, latency will not be captured. Example: ./cpa_sample_code runTests=1 getLatency=1 getOffloadCost is an optional parameter which will enable computation of offload cost. The cost is measured in the number of CPU cycles consumed and the results may vary from platform to plarform as Cost Of Offload (COO) is platform dependent. If signOfLife parameter is passed, COO will not be captured. Example: ./cpa_sample_code runTests=32 getOffloadCost=1 Note: getLatency and getOffloadCost are mutually exclusive i.e. Only one can be enabled for a particular invocation of cpa_sample_code application. The measurement should be performed with just one active sample code thread. i.e.NumberCyInstances and NumberDcInstances should be set to 1 in the driver configuration file under SSL section. Also only one device should be active at the time of measurement. Results may vary depending on platform settings like CPU energy savings, turbo boost, etc. It is not recommended to run latency or COO inside of VM as the results might be affected by hypervisor policies. Both getLatency and getOffloadCost are added to give an idea about the Latency and COO, however because of the range of factors which can impact the values, those should be taken with considerations. useStaticPrime is an optional parameter with default of 1(on), which indicates whether RSA performance test execution should use prepared primes during parameter generation or generate primes at runtime. Note this value has no bearing on the eventual performance metrics presented upon completion of RSA tests. singleInstThread is an optional parameter with default value 0. If set to 1, the tests will be executed using a single instance. Example: ./cpa_sample_code runTests=32 singleInstThread=1 =============================================================================== 4) Known Issues This is sample code and all invalid cases are not fully covered. Legal/Disclaimers =================== INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL(R) PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER, AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT. Intel products are not intended for use in medical, life saving, life sustaining, critical control or safety systems, or in nuclear facility applications. Intel may make changes to specifications and product descriptions at any time, without notice. (C) Intel Corporation 2018 * Other names and brands may be claimed as the property of others. =============================================================================== qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/busy_loop/000077500000000000000000000000001503624047500271775ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/busy_loop/busy_loop.c000066400000000000000000000174151503624047500313660ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifdef USER_SPACE #include #include #include #else #include #include #include #include #include #endif #include "busy_loop.h" unsigned int useCpuid = 1; #ifdef USER_SPACE #define do_div(n, base) (n = n / base) #define PRINT(args...) \ { \ printf(args); \ } #else #define PRINT(args...) \ { \ printk(KERN_CONT args); \ } #endif #define SCALING_FACTOR (1000) uint32_t busyLoopCounter_g = 0; void setUseCpuid(unsigned int a); void testBusyLoop(uint32_t n); void testBusyLoop2(uint32_t n); void setBusyLoopCounter(uint32_t busyLoopCounter); #ifdef USER_SPACE void __attribute__((noinline)) busyLoop(uint32_t n, volatile uint32_t *var) { uint32_t k = 0; for (k = 0; k < n; k++) { (*var) = 1; } } unsigned long long __attribute__((noinline)) busyLoop2(uint32_t n, volatile uint32_t *var) { uint32_t k = 0; unsigned long long totalBusyLoopCycles = 0, startBusyLoop = 0, endBusyLoop = 0; busyLoopTimeStamp(); startBusyLoop = busyLoopTimeStamp(); for (k = 0; k < n; k++) { (*var) = 1; } endBusyLoop = busyLoopTimeStamp(); totalBusyLoopCycles = endBusyLoop - startBusyLoop; return totalBusyLoopCycles; } #else void busyLoop(uint32_t n, volatile uint32_t *var) { uint32_t k = 0; for (k = 0; k < n; k++) { (*var) = 1; } return; } unsigned long long busyLoop2(uint32_t n, volatile uint32_t *var) { uint32_t k = 0; unsigned long long totalBusyLoopCycles = 0, startBusyLoop = 0, endBusyLoop = 0; // busyLoopTimeStamp(); startBusyLoop = busyLoopTimeStamp(); for (k = 0; k < n; k++) { (*var) = 1; } endBusyLoop = busyLoopTimeStamp(); totalBusyLoopCycles = endBusyLoop - startBusyLoop; return totalBusyLoopCycles; } #endif void setUseCpuid(unsigned int a) { useCpuid = a; return; } void setBusyLoopCounter(uint32_t busyLoopCounter) { busyLoopCounter_g = busyLoopCounter; return; } unsigned long long getTimeStampTime(void) { unsigned int i = 0; unsigned long long totalBusyLoopCycles = 0, startBusyLoop = 0; for (i = 0; i < 0x10000; i++) { startBusyLoop = busyLoopTimeStamp(); totalBusyLoopCycles += busyLoopTimeStamp() - startBusyLoop; } totalBusyLoopCycles = totalBusyLoopCycles >> 16; return totalBusyLoopCycles; } unsigned long long getTimeStampTime2(void) { unsigned long long totalBusyLoopCycles = 0, startBusyLoop = 0; startBusyLoop = busyLoopTimeStamp(); totalBusyLoopCycles = busyLoopTimeStamp() - startBusyLoop; return totalBusyLoopCycles; } void testBusyLoop(uint32_t n) { uint32_t var = 0; uint32_t numBusyLoops = 0; unsigned long long totalBusyLoopCycles = 0, startBusyLoop = 0, endBusyLoop = 0; busyLoopTimeStamp(); startBusyLoop = busyLoopTimeStamp(); for (numBusyLoops = 0; numBusyLoops < n; numBusyLoops++) { busyLoop(busyLoopCounter_g, &var); } endBusyLoop = busyLoopTimeStamp(); totalBusyLoopCycles = endBusyLoop - startBusyLoop; #ifdef USER_SPACE PRINT("Total Cycles %llu\n", totalBusyLoopCycles); #else PRINT("Total Cycles %llu\n", totalBusyLoopCycles); #endif } void testBusyLoop2(uint32_t n) { uint32_t var = 0; uint32_t numBusyLoops = 0; unsigned long long totalBusyLoopCycles = 0; busyLoopTimeStamp(); for (numBusyLoops = 0; numBusyLoops < n; numBusyLoops++) { totalBusyLoopCycles += busyLoop2(busyLoopCounter_g, &var); } #ifdef USER_SPACE PRINT("Total Cycles %llu\n", totalBusyLoopCycles); #else PRINT("Total Cycles %llu\n", totalBusyLoopCycles); #endif } uint8_t withinMargin(uint32_t baseVal, uint32_t currentVal, uint32_t margin) { uint32_t difference = 0; if (currentVal >= baseVal) { return 1; } difference = baseVal - currentVal; difference *= SCALING_FACTOR; do_div(difference, baseVal); if (difference <= margin) { return 1; } return 0; } #ifdef KERNEL_SPACE EXPORT_SYMBOL(getTimeStampTime2); EXPORT_SYMBOL(useCpuid); EXPORT_SYMBOL(setUseCpuid); EXPORT_SYMBOL(getTimeStampTime); EXPORT_SYMBOL(testBusyLoop); EXPORT_SYMBOL(testBusyLoop2); EXPORT_SYMBOL(withinMargin); EXPORT_SYMBOL(setBusyLoopCounter); EXPORT_SYMBOL(busyLoop); EXPORT_SYMBOL(busyLoop2); EXPORT_SYMBOL(busyLoopCounter_g); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Sample Code"); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/busy_loop/busy_loop.h000066400000000000000000000150171503624047500313670ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef BUSY_LOOP_H #define BUSY_LOOP_H #ifdef USER_SPACE #include #else #include #include #include #include #include #include #include #include #endif #define BUSY_LOOP_INCREMENT (20) #define ERROR_MARGIN (1) #define PERCENT_TPUT_VARIANCE (1) #ifdef USER_SPACE void __attribute__((noinline)) busyLoop(uint32_t n, volatile uint32_t *var); unsigned long long __attribute__((noinline)) busyLoop2(uint32_t n, volatile uint32_t *var); #else void busyLoop(uint32_t n, volatile uint32_t *var); unsigned long long busyLoop2(uint32_t n, volatile uint32_t *var); #endif unsigned long long getTimeStampTime(void); unsigned long long getTimeStampTime2(void); extern uint32_t busyLoopCounter_g; extern unsigned int useCpuid; uint8_t withinMargin(uint32_t baseVal, uint32_t currentVal, uint32_t margin); #ifdef __x86_64__ static inline uint64_t busyLoopTimeStamp(void) { unsigned cycles_low, cycles_high; if (useCpuid) { unsigned cycles_low1, cycles_high1; #ifdef KERNEL_SPACE unsigned long flags; preempt_disable(); local_irq_save(flags); #endif __asm__ volatile("CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" : "=r"(cycles_high), "=r"(cycles_low)::"%rax", "%rbx", "%rcx", "%rdx"); __asm__ volatile("RDTSCP\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" "CPUID\n\t" : "=r"(cycles_high1), "=r"(cycles_low1)::"%rax", "%rbx", "%rcx", "%rdx"); __asm__ volatile("CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" : "=r"(cycles_high), "=r"(cycles_low)::"%rax", "%rbx", "%rcx", "%rdx"); __asm__ volatile("RDTSCP\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" "CPUID\n\t" : "=r"(cycles_high1), "=r"(cycles_low1)::"%rax", "%rbx", "%rcx", "%rdx"); __asm__ volatile("CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" : "=r"(cycles_high), "=r"(cycles_low)::"%rax", "%rbx", "%rcx", "%rdx"); #ifdef KERNEL_SPACE raw_local_irq_restore(flags); preempt_enable(); #endif } else { __asm__ volatile("RDTSCP\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" : "=r"(cycles_high), "=r"(cycles_low)::"%rax", "%rbx", "%rcx", "%rdx"); } return (((uint64_t)cycles_high << 32) | cycles_low); } #else static inline uint64_t busyLoopTimeStamp(void) { return (uint64_t)0; } #endif /*__x64_64__*/ #endif /* End BUSY_LOOP_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/000077500000000000000000000000001503624047500273265ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/000077500000000000000000000000001503624047500302775ustar00rootroot00000000000000diffie_hellman_sample/000077500000000000000000000000001503624047500345075ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asymcpa_dh_sample.c000066400000000000000000000437651503624047500374510ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/diffie_hellman_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is a sample code that uses Diffie-Hellman APIs. * In order to use this algorithm, 3 elements have to be set: * - a prime number p (the modulus) * - a base g * - a random value x * * This sample code defines arbitrary values for p, g and x. * Phase 1. In this phase, the public value A=g^x mod p is calculated * Then, in a real implementation, this value has to be sent to another * party (B) that will send back its public value * Phase 2. Based on the public value returned by B, the prime number p * and x, the private key is calculated */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_dh.h" #include "cpa_sample_utils.h" #define TIMEOUT_MS 5000 /* 5 seconds*/ extern int gDebugParam; /* * Sample prime number for DH algorithm. This number may be 768, 1024, 1536, * 2048, 3072 or 4096 bits in length. */ static Cpa8U primeP_768[] = { 0xC7, 0x3B, 0x18, 0xB5, 0x71, 0xE1, 0xE0, 0x7C, 0x70, 0x66, 0x5F, 0xD8, 0x8B, 0xD9, 0xC2, 0x55, 0x3E, 0xD7, 0x09, 0x68, 0x80, 0xF2, 0x17, 0x1A, 0x7A, 0x6D, 0xC9, 0x24, 0xF2, 0x5C, 0x84, 0x7D, 0xB4, 0xC5, 0xA5, 0x40, 0x9A, 0x3F, 0xB7, 0xBD, 0xD4, 0xD0, 0xE6, 0xA0, 0x01, 0xC5, 0x1E, 0xA7, 0x60, 0x42, 0x2D, 0xF5, 0x16, 0xAF, 0x01, 0x6C, 0xF7, 0xA5, 0x73, 0xCF, 0x36, 0xB3, 0x6E, 0x5C, 0xE7, 0x2C, 0x18, 0x19, 0x5C, 0x21, 0x40, 0x1B, 0xF4, 0xD5, 0xD9, 0xF4, 0x46, 0x08, 0xDA, 0x84, 0x0B, 0x34, 0x8F, 0x80, 0xB9, 0x7C, 0x7B, 0xAF, 0x23, 0xEA, 0x6E, 0xF2, 0x45, 0x8C, 0xC0, 0x0B}; /* * Base of DH algorithm chosen by A. */ static Cpa8U baseG1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}; /* * Random value for DH algorithm chosen by A. It must match the * following condition: * * 0 < PrivateValueX < (PrimeP - 1) * * where PrimeP is the prime number (primeP_768, above). */ static Cpa8U privateValueX[] = { 0x00, 0x14, 0x34, 0x12, 0x93, 0xCE, 0xBF, 0x04, 0x7C, 0x87, 0x16, 0x37, 0xEB, 0xB8, 0x75, 0xF0, 0x69, 0x6D, 0xEA, 0x92, 0x5C, 0x3A, 0xDF, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CpaStatus dhSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing, * etc. In this example, the function only sets the complete variable * to indicate it has been called. */ static void asymCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { PRINT_DBG("CallBack function\n"); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("operation not a success, status = %d\n", status); } PRINT_DBG("asymCallback: status = %d\n", status); /** indicate the callback function has been executed, meaning that * cpaCyDhKeyGenPhase2Secret is completed*/ if (NULL != pCallbackTag) { COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /***************************************************************************** * Perform Diffie-Hellman phase 1 and 2 operations *****************************************************************************/ static CpaStatus sampleDhPerformOp(CpaInstanceHandle cyInstHandle) { CpaStatus status = CPA_STATUS_SUCCESS; /** callback data for function 1*/ void *pCallbackTagPh1 = (void *)1; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; void *pCallbackTagPh2 = (void *)&complete; /** Pointer that will contain the public value (returned by * cpaCyDhKeyGenPhase1) */ CpaFlatBuffer *pLocalOctetStringPV = NULL; /** Pointer that will contain the private key (returned by * cpaCyDhKeyGenPhase2) */ CpaFlatBuffer *pOctetStringSecretKey = NULL; CpaCyDhPhase2SecretKeyGenOpData *pCpaDhOpDataP2 = NULL; CpaCyDhPhase1KeyGenOpData *pCpaDhOpDataP1 = NULL; COMPLETION_INIT(&complete); // Initialize the completion variable // status = OS_MALLOC(&pCpaDhOpDataP1, sizeof(CpaCyDhPhase1KeyGenOpData)); /* * Allocate input buffers for phase 1 and copy data. Input to DH * phase 1 includes the prime (primeP), the base g (baseG) and * a random private value (privateValueX). */ if (CPA_STATUS_SUCCESS == status) { memset(pCpaDhOpDataP1, 0, sizeof(CpaCyDhPhase1KeyGenOpData)); pCpaDhOpDataP1->primeP.dataLenInBytes = sizeof(primeP_768); status = PHYS_CONTIG_ALLOC(&pCpaDhOpDataP1->primeP.pData, sizeof(primeP_768)); if (NULL != pCpaDhOpDataP1->primeP.pData) { memcpy( pCpaDhOpDataP1->primeP.pData, primeP_768, sizeof(primeP_768)); } } if (CPA_STATUS_SUCCESS == status) { pCpaDhOpDataP1->baseG.dataLenInBytes = sizeof(baseG1); status = PHYS_CONTIG_ALLOC(&pCpaDhOpDataP1->baseG.pData, sizeof(baseG1)); if (NULL != pCpaDhOpDataP1->baseG.pData) { memcpy(pCpaDhOpDataP1->baseG.pData, baseG1, sizeof(baseG1)); } } if (CPA_STATUS_SUCCESS == status) { pCpaDhOpDataP1->privateValueX.dataLenInBytes = sizeof(privateValueX); status = PHYS_CONTIG_ALLOC(&pCpaDhOpDataP1->privateValueX.pData, sizeof(privateValueX)); if (NULL != pCpaDhOpDataP1->privateValueX.pData) { memcpy(pCpaDhOpDataP1->privateValueX.pData, privateValueX, sizeof(privateValueX)); } } /* * Allocate output buffer for phase 1 (pLocalOctetStringPV). * This the the public value PV as described in PKCS#3. */ if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pLocalOctetStringPV, sizeof(CpaFlatBuffer)); if (CPA_STATUS_SUCCESS == status) { pLocalOctetStringPV->dataLenInBytes = pCpaDhOpDataP1->primeP.dataLenInBytes; status = PHYS_CONTIG_ALLOC(&pLocalOctetStringPV->pData, pLocalOctetStringPV->dataLenInBytes); } } // if (CPA_STATUS_SUCCESS == status) { /** Perform Diffie-Hellman Phase 1 operation */ PRINT_DBG("calling cpaCyDhKeyGenPhase1\n"); PRINT_DBG("Phase 1: generate the public value from the p, g and x\n"); // status = cpaCyDhKeyGenPhase1( cyInstHandle, NULL, /* synchronous mode */ pCallbackTagPh1, /* Opaque user data; */ pCpaDhOpDataP1, /* Structure containing p, g and x*/ pLocalOctetStringPV); /* Public value (function output) */ // if (CPA_STATUS_SUCCESS != status) { /* Not a success; could be a retry, a fail, an invalid param or * a resource issue */ PRINT_ERR("cpaCyDhKeyGenPhase1() not a success. (status = %d)\n", status); } } if (CPA_STATUS_SUCCESS == status) { /** Allocate memory for the pOctetStringSecretKey */ status = OS_MALLOC(&pOctetStringSecretKey, sizeof(CpaFlatBuffer)); if (CPA_STATUS_SUCCESS == status) { /** Set the data length */ pOctetStringSecretKey->dataLenInBytes = pCpaDhOpDataP1->primeP.dataLenInBytes; /** Allocate memory for the pOctetStringSecretKey pData*/ status = PHYS_CONTIG_ALLOC(&pOctetStringSecretKey->pData, pOctetStringSecretKey->dataLenInBytes); } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("In a typical application, the public value would be sent to " "B\n"); PRINT_DBG("and the remoteOctetvalue would be returned\n"); /** In a typical application, at this stage, the public information * (prime number, base and the public value that has just been * calculated by cpaCyDhKeyGenPhase1) would be sent to the other user. * As cpaCyDhKeyGenPhase1 runs in synchronous mode, it is sure that the * public value has been calculated. * The user would then send back a remoteOctet value. */ status = OS_MALLOC(&pCpaDhOpDataP2, sizeof(CpaCyDhPhase2SecretKeyGenOpData)); if (CPA_STATUS_SUCCESS == status) { memset(pCpaDhOpDataP2, 0, sizeof(CpaCyDhPhase2SecretKeyGenOpData)); pCpaDhOpDataP2->primeP.pData = pCpaDhOpDataP1->primeP.pData; pCpaDhOpDataP2->primeP.dataLenInBytes = pCpaDhOpDataP1->primeP.dataLenInBytes; pCpaDhOpDataP2->remoteOctetStringPV.pData = pLocalOctetStringPV->pData; pCpaDhOpDataP2->remoteOctetStringPV.dataLenInBytes = pLocalOctetStringPV->dataLenInBytes; pCpaDhOpDataP2->privateValueX.pData = pCpaDhOpDataP1->privateValueX.pData; pCpaDhOpDataP2->privateValueX.dataLenInBytes = pCpaDhOpDataP1->privateValueX.dataLenInBytes; /** Perform Diffie-Hellman Phase 2 operation */ PRINT_DBG("cpaCyDhKeyGenPhase2Secret\n"); PRINT_DBG("Phase 2: generate the private key\n"); // status = cpaCyDhKeyGenPhase2Secret( cyInstHandle, (const CpaCyGenFlatBufCbFunc)asymCallback, /* CB function*/ pCallbackTagPh2, /* pointer to the complete variable*/ pCpaDhOpDataP2, /* structure containing p, the public value & x*/ pOctetStringSecretKey); /* private key (output of the function)*/ // if (CPA_STATUS_SUCCESS != status) { /* Not a success; could be a retry, a fail, an invalid param or * a resource issue */ PRINT_ERR("cpaCyDhKeyGenPhase2Secret() not a success. " "(status = %d)\n", status); } } } /** wait until the completion of the operation*/ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCyDhKeyGenPhase2Secret\n"); status = CPA_STATUS_FAIL; } } /* Free Flat Buffers */ if (NULL != pLocalOctetStringPV) { PHYS_CONTIG_FREE(pLocalOctetStringPV->pData); } if (NULL != pOctetStringSecretKey) { PHYS_CONTIG_FREE(pOctetStringSecretKey->pData); } OS_FREE(pLocalOctetStringPV); OS_FREE(pOctetStringSecretKey); /* Free buffers */ if (NULL != pCpaDhOpDataP1) { PHYS_CONTIG_FREE(pCpaDhOpDataP1->primeP.pData); PHYS_CONTIG_FREE(pCpaDhOpDataP1->baseG.pData); PHYS_CONTIG_FREE(pCpaDhOpDataP1->privateValueX.pData); } OS_FREE(pCpaDhOpDataP1); OS_FREE(pCpaDhOpDataP2); COMPLETION_DESTROY(&complete); return status; } CpaStatus dhSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle cyInstHandle = NULL; /** Buffer for the stats*/ CpaCyDhStats64 dhStats = {0}; PRINT_DBG("start of Diffie-Hellman sample code\n"); /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleAsymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS != status) { return CPA_STATUS_FAIL; } /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); if (CPA_STATUS_SUCCESS != status) { cpaCyStopInstance(cyInstHandle); return CPA_STATUS_FAIL; } /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); /** Perform DH operations */ PRINT_DBG("calling sampleDhPerformOp\n"); status = sampleDhPerformOp(cyInstHandle); if (CPA_STATUS_SUCCESS != status) { /* Not a success; could be a retry, a fail, an invalid param or * a resource issue */ PRINT_ERR("sampleDhPerformOp not a success, status = %d\n", status); } if (CPA_STATUS_SUCCESS == status) { /** Query Diffie-Hellman statistics */ PRINT_DBG("cpaCyDhQueryStats\n"); status = cpaCyDhQueryStats64(cyInstHandle, &dhStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyDhQueryStats() failed. (status = %d)\n", status); status = CPA_STATUS_FAIL; } /** Print some stats*/ PRINT_DBG("Number of successful DH phase 1 key gen request: %llu\n", (unsigned long long)dhStats.numDhPhase1KeyGenRequests); /** Print some stats*/ PRINT_DBG("Number of successful DH phase 2 key gen request: %llu\n", (unsigned long long)dhStats.numDhPhase2KeyGenRequests); } /* Stop the polling thread */ sampleCyStopPolling(); /** Stop Cryptographic instance */ PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_dh_sample_user.c000066400000000000000000000100361503624047500404700ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/diffie_hellman_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_dh_sample_user.c * *****************************************************************************/ #include "cpa.h" #include "icp_sal_user.h" #include "cpa_sample_utils.h" extern CpaStatus dhSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting DH Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialise memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = dhSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nDH Sample Code App failed\n"); } else { PRINT_DBG("\nDH Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } ec_montedwds_sample/000077500000000000000000000000001503624047500342345ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asymcpa_ec_montedwds_sample.c000066400000000000000000000535551503624047500412540ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/ec_montedwds_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the asymmetric API, and * specifically using this API to perform a cpaCyEcMontEdwdsPointMultiply * operations. * It uses Twisted Edwards or Montgomery algorithm and curve 448 or 25519 to * perform generator multiplication or point multiplication operations. */ #include #include #include "cpa.h" #include "lac/cpa_cy_key.h" #include "cpa_cy_ec.h" #include "cpa_sample_utils.h" #if CY_API_VERSION_AT_LEAST(2, 3) #define TIMEOUT_MS 5000 /* 5 seconds */ extern int gDebugParam; /*************************************************************************** * Input and Output vectors for Public Key Encryption * Elliptic Curve (EC) operations. ***************************************************************************/ static Cpa8U edwards_448_kp_x[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x2f, 0x7d, 0x05, 0x80, 0xfd, 0x8e, 0x88, 0xf3, 0xfc, 0x8e, 0xcd, 0x47, 0xf4, 0x34, 0x99, 0xb0, 0x00, 0x0f, 0xaf, 0x1e, 0x84, 0xd0, 0xc2, 0x28, 0x37, 0x36, 0xc9, 0x91, 0xc4, 0xa6, 0x44, 0x47, 0xce, 0x4e, 0x8d, 0x8a, 0x6c, 0x74, 0x01, 0x0b, 0xaf, 0x72, 0x6e, 0xf2, 0x00, 0x06, 0xbc, 0xf1, 0xfa, 0x99, 0x0e, 0x7a, 0x82, 0x22, 0x87}; static Cpa8U edwards_448_kp_y[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x25, 0xe8, 0xaf, 0xbe, 0x1a, 0xfa, 0xd1, 0x6c, 0x0f, 0xe5, 0xf1, 0x3d, 0x78, 0xd6, 0x1b, 0x06, 0xc7, 0x46, 0x9b, 0x76, 0x24, 0xf1, 0xed, 0x78, 0x67, 0xe9, 0x80, 0x5d, 0xa7, 0x0e, 0x8a, 0x1f, 0x0e, 0xa7, 0x85, 0x24, 0x34, 0xa1, 0x1d, 0x6a, 0xd4, 0x6a, 0x61, 0xec, 0x87, 0xe7, 0x2c, 0xfd, 0x61, 0xb4, 0x59, 0x9b, 0x44, 0xd7, 0x5f}; static Cpa8U edwards_448_kp_k[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x79, 0xde, 0x16, 0x3f, 0xfe, 0x49, 0x98, 0x66, 0x1c, 0x2d, 0x46, 0xd9, 0xdf, 0x0f, 0xff, 0xa8, 0x6e, 0x5f, 0xe7, 0x18, 0xef, 0xc5, 0xa6, 0xca, 0x51, 0xe7, 0xe9, 0x58, 0xba, 0x02, 0x87, 0x18, 0x61, 0x23, 0xf9, 0xf0, 0xd3, 0x95, 0x7a, 0x43, 0x5c, 0x13, 0xb3, 0x65, 0xa5, 0xa1, 0x1f, 0x4c, 0x76, 0x3a, 0xc0, 0x71, 0x26, 0xae}; static Cpa8U edwards_448_kp_u[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xb1, 0xfe, 0xe3, 0x1d, 0x2a, 0x0e, 0x7c, 0x50, 0x08, 0x48, 0xbf, 0x8f, 0x55, 0x03, 0xc0, 0xe7, 0x5d, 0x62, 0x85, 0xdd, 0x25, 0x83, 0xf2, 0xde, 0x69, 0xba, 0xa5, 0x34, 0x4a, 0x79, 0x38, 0x77, 0x42, 0xab, 0x20, 0x80, 0xf5, 0xe0, 0x48, 0xac, 0xd4, 0x59, 0x95, 0xa0, 0x54, 0x53, 0x61, 0x7f, 0xf4, 0x33, 0x9b, 0xa4, 0xbb, 0x4f, 0x33}; static Cpa8U edwards_448_kp_v[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xc5, 0x7b, 0x02, 0x90, 0x55, 0x48, 0x1a, 0x04, 0xf5, 0x37, 0x78, 0x22, 0x54, 0xc5, 0xe9, 0x38, 0x10, 0x80, 0xca, 0x28, 0x56, 0xfe, 0x51, 0xfa, 0x91, 0x41, 0x44, 0x26, 0xec, 0x8e, 0xa3, 0xe3, 0xc7, 0x91, 0xf7, 0x75, 0x28, 0x7e, 0xa3, 0xd4, 0x63, 0xa7, 0x7c, 0x54, 0xd9, 0xbe, 0xff, 0x74, 0xb1, 0xf3, 0x96, 0xe6, 0x2e, 0x2d, 0x8b}; static Cpa8U montgomery_448_kg_k[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x90, 0x92, 0x36, 0xd3, 0xaf, 0x35, 0x96, 0x00, 0xd5, 0x41, 0xe6, 0x05, 0xd8, 0xb7, 0x98, 0x03, 0x35, 0xd1, 0x1a, 0xb4, 0xdc, 0xeb, 0xce, 0x27, 0x30, 0x5d, 0xef, 0x75, 0x01, 0xda, 0x8c, 0xed, 0x72, 0xca, 0xfc, 0xa3, 0x20, 0x59, 0x98, 0x41, 0xde, 0x0c, 0x70, 0x73, 0x9f, 0xd8, 0xad, 0x72, 0xa3, 0xe7, 0x4a, 0x48, 0xb8, 0x09, 0xf2}; static Cpa8U montgomery_448_kg_u[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x61, 0xb9, 0x75, 0x6f, 0xa4, 0x84, 0x07, 0x52, 0x25, 0x6f, 0xee, 0xa1, 0xcd, 0xdc, 0x40, 0xc0, 0x09, 0xe5, 0xfc, 0x3f, 0xad, 0x0d, 0x45, 0xfe, 0x44, 0xdd, 0x26, 0x4e, 0xd0, 0x8d, 0xe7, 0xdb, 0x4a, 0xdb, 0x66, 0xef, 0x65, 0x78, 0x82, 0xa6, 0xd3, 0xcd, 0x74, 0xb7, 0x29, 0xc0, 0x4c, 0x66, 0x9d, 0xdf, 0x77, 0x57, 0x0b, 0xec, 0x6e}; static Cpa8U montgomery_25519_kp_x[32] = { 0x62, 0x9d, 0x47, 0x54, 0x8a, 0x31, 0x49, 0xad, 0xa9, 0x6f, 0x66, 0x8e, 0x67, 0x49, 0x3a, 0x2a, 0x9c, 0x1e, 0xe4, 0xf5, 0x90, 0xb1, 0x18, 0xf9, 0xdf, 0x98, 0x01, 0x38, 0x4b, 0x47, 0xe4, 0x05}; static Cpa8U montgomery_25519_kp_k[32] = { 0x36, 0xd3, 0xe1, 0xe0, 0xde, 0x0c, 0x2e, 0x89, 0xaf, 0x97, 0x57, 0x05, 0x78, 0xaf, 0x81, 0xdb, 0x9e, 0xa9, 0x9b, 0xc4, 0xb1, 0xb1, 0x86, 0xfe, 0xa5, 0x7e, 0x16, 0x85, 0x86, 0xe4, 0x45, 0x88}; static Cpa8U montgomery_25519_kp_u[32] = { 0x1a, 0x0f, 0x77, 0x9c, 0xf1, 0xc8, 0x4a, 0x4b, 0x46, 0x23, 0x01, 0x28, 0x04, 0x5f, 0x5e, 0x41, 0x84, 0x29, 0xa7, 0x76, 0xba, 0xd8, 0xfb, 0x84, 0x37, 0x36, 0x4e, 0xc5, 0x18, 0x5d, 0x60, 0xe8}; static void ecMontEdwdsPointMultiplyPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { PRINT_DBG("Callback called with status = %d.\n", status); COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } static void printBuffer(const char *name, Cpa8U *buffer, Cpa32U bufferSize) { int i = 0; PRINT("%s\n", name); for (i = 0; i < bufferSize; i++) PRINT("%02x ", buffer[i]); PRINT("\n"); return; } static CpaStatus checkResult(const char *name, Cpa8U *buffer, Cpa8U *expected, Cpa32U bufferSize) { CpaStatus status = CPA_STATUS_SUCCESS; if (memcmp(buffer, expected, bufferSize) != 0) { PRINT_ERR("ERROR: %s doesn't match\n", name); printBuffer("ACTUAL:", buffer, bufferSize); printBuffer("EXPECTED:", expected, bufferSize); status = CPA_STATUS_FAIL; } else { PRINT("%s correct\n", name); } return status; } static CpaStatus ed448PointSamplePerform(CpaInstanceHandle cyInstHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean multiplyStatus = CPA_TRUE; CpaCyEcMontEdwdsPointMultiplyOpData *opData = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; Cpa8U *pointX; Cpa8U *pointY; Cpa8U *pointK; Cpa8U dataLenInBytes = 0; struct COMPLETION_STRUCT complete; COMPLETION_INIT(&complete); /* Set test vectors and buffer size */ PRINT_DBG("Edwards448pPerformOp\n"); pointX = edwards_448_kp_x; pointY = edwards_448_kp_y; pointK = edwards_448_kp_k; dataLenInBytes = sizeof(edwards_448_kp_k); /* Allocate memory for input and output buffers */ status = OS_MALLOC(&pXk, sizeof(CpaFlatBuffer)); if (CPA_STATUS_SUCCESS == status) { pXk->pData = NULL; pXk->dataLenInBytes = dataLenInBytes; status = OS_MALLOC(&pYk, sizeof(CpaFlatBuffer)); } if (CPA_STATUS_SUCCESS == status) { pYk->pData = NULL; pYk->dataLenInBytes = dataLenInBytes; status = PHYS_CONTIG_ALLOC_ALIGNED( &pXk->pData, dataLenInBytes, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC_ALIGNED( &pYk->pData, dataLenInBytes, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&opData, sizeof(CpaCyEcMontEdwdsPointMultiplyOpData)); } /* Prepare operation data */ if (CPA_STATUS_SUCCESS == status) { opData->generator = CPA_FALSE; opData->curveType = CPA_CY_EC_MONTEDWDS_ED448_TYPE; PHYS_CONTIG_ALLOC_ALIGNED( &opData->x.pData, dataLenInBytes, BYTE_ALIGNMENT_64); opData->x.dataLenInBytes = dataLenInBytes; PHYS_CONTIG_ALLOC_ALIGNED( &opData->y.pData, dataLenInBytes, BYTE_ALIGNMENT_64); opData->y.dataLenInBytes = dataLenInBytes; PHYS_CONTIG_ALLOC_ALIGNED( &opData->k.pData, dataLenInBytes, BYTE_ALIGNMENT_64); opData->k.dataLenInBytes = dataLenInBytes; /* Verify allocated memory */ if (!(opData->y.pData) || !(opData->x.pData) || !(opData->k.pData)) { status = CPA_STATUS_FAIL; } else { memcpy(opData->y.pData, pointY, dataLenInBytes); memcpy(opData->x.pData, pointX, dataLenInBytes); memcpy(opData->k.pData, pointK, dataLenInBytes); /* Perform operation */ PRINT_DBG("cpaCyEcMontEdwdsPointMultiply\n"); status = cpaCyEcMontEdwdsPointMultiply( cyInstHandle, ecMontEdwdsPointMultiplyPerformCallback, (void *)&complete, opData, &multiplyStatus, pXk, pYk); } } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyEcMontEdwdsPointMultiply failed. (status = %d)\n", status); } /* * We now wait until the polling thread to complete * the operation. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCyKeyGenTls\n"); status = CPA_STATUS_FAIL; } } /* * Data sanity */ if (CPA_STATUS_SUCCESS == status) { status = checkResult("edwards_448_kp_u", pXk->pData, edwards_448_kp_u, sizeof(edwards_448_kp_u)); if (CPA_STATUS_SUCCESS == status) { status = checkResult("edwards_448_kp_v", pYk->pData, edwards_448_kp_v, sizeof(edwards_448_kp_v)); } } COMPLETION_DESTROY(&complete); if (NULL != pXk) { PHYS_CONTIG_FREE(pXk->pData); OS_FREE(pXk); } if (NULL != pYk) { PHYS_CONTIG_FREE(pYk->pData); OS_FREE(pYk); } if (NULL != opData) { PHYS_CONTIG_FREE(opData->k.pData); PHYS_CONTIG_FREE(opData->y.pData); PHYS_CONTIG_FREE(opData->x.pData); OS_FREE(opData); } return status; } static CpaStatus curve448GeneratorSamplePerform(CpaInstanceHandle cyInstHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean multiplyStatus = CPA_TRUE; CpaCyEcMontEdwdsPointMultiplyOpData *opData = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; Cpa8U *pointK; Cpa8U dataLenInBytes = 0; struct COMPLETION_STRUCT complete; COMPLETION_INIT(&complete); /* Set test vectors and buffer size */ PRINT_DBG("Montgomery448gPerformOp\n"); pointK = montgomery_448_kg_k; dataLenInBytes = sizeof(montgomery_448_kg_k); /* Allocate memory for input and output buffers */ status = OS_MALLOC(&pXk, sizeof(CpaFlatBuffer)); if (CPA_STATUS_SUCCESS == status) { pXk->pData = NULL; pXk->dataLenInBytes = dataLenInBytes; status = OS_MALLOC(&pYk, sizeof(CpaFlatBuffer)); } if (CPA_STATUS_SUCCESS == status) { pYk->pData = NULL; pYk->dataLenInBytes = dataLenInBytes; status = PHYS_CONTIG_ALLOC_ALIGNED( &pXk->pData, dataLenInBytes, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC_ALIGNED( &pYk->pData, dataLenInBytes, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&opData, sizeof(CpaCyEcMontEdwdsPointMultiplyOpData)); } /* Prepare operation data */ if (CPA_STATUS_SUCCESS == status) { opData->generator = CPA_TRUE; opData->curveType = CPA_CY_EC_MONTEDWDS_CURVE448_TYPE; PHYS_CONTIG_ALLOC_ALIGNED( &opData->k.pData, dataLenInBytes, BYTE_ALIGNMENT_64); opData->k.dataLenInBytes = dataLenInBytes; /* Verify allocated memory */ if (!(opData->k.pData)) { status = CPA_STATUS_FAIL; } else { memcpy(opData->k.pData, pointK, dataLenInBytes); /* Perform operation */ PRINT_DBG("cpaCyEcMontEdwdsPointMultiply\n"); status = cpaCyEcMontEdwdsPointMultiply( cyInstHandle, ecMontEdwdsPointMultiplyPerformCallback, (void *)&complete, opData, &multiplyStatus, pXk, pYk); } } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyEcMontEdwdsPointMultiply failed. (status = %d)\n", status); } /* * We now wait until the polling thread to complete * the operation. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCyKeyGenTls\n"); status = CPA_STATUS_FAIL; } } /* * Data sanity */ if (CPA_STATUS_SUCCESS == status) { status = checkResult("montgomery_448_kg_u", pXk->pData, montgomery_448_kg_u, sizeof(montgomery_448_kg_u)); } COMPLETION_DESTROY(&complete); if (NULL != pXk) { PHYS_CONTIG_FREE(pXk->pData); OS_FREE(pXk); } if (NULL != pYk) { PHYS_CONTIG_FREE(pYk->pData); OS_FREE(pYk); } if (NULL != opData) { PHYS_CONTIG_FREE(opData->k.pData); OS_FREE(opData); } return status; } static CpaStatus curve25519PointSamplePerform(CpaInstanceHandle cyInstHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean multiplyStatus = CPA_TRUE; CpaCyEcMontEdwdsPointMultiplyOpData *opData = NULL; CpaFlatBuffer *pXk = NULL; CpaFlatBuffer *pYk = NULL; Cpa8U *pointX; Cpa8U *pointK; Cpa8U dataLenInBytes = 0; struct COMPLETION_STRUCT complete; COMPLETION_INIT(&complete); /* Set test vectors and buffer size */ PRINT_DBG("Montgomery25519pPerformOp\n"); pointX = montgomery_25519_kp_x; pointK = montgomery_25519_kp_k; dataLenInBytes = sizeof(montgomery_25519_kp_k); /* Allocate memory for input and output buffers */ status = OS_MALLOC(&pXk, sizeof(CpaFlatBuffer)); if (CPA_STATUS_SUCCESS == status) { pXk->pData = NULL; pXk->dataLenInBytes = dataLenInBytes; status = OS_MALLOC(&pYk, sizeof(CpaFlatBuffer)); } if (CPA_STATUS_SUCCESS == status) { pYk->pData = NULL; pYk->dataLenInBytes = dataLenInBytes; status = PHYS_CONTIG_ALLOC_ALIGNED( &pXk->pData, dataLenInBytes, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC_ALIGNED( &pYk->pData, dataLenInBytes, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&opData, sizeof(CpaCyEcMontEdwdsPointMultiplyOpData)); } /* Prepare operation data */ if (CPA_STATUS_SUCCESS == status) { opData->generator = CPA_FALSE; opData->curveType = CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE; PHYS_CONTIG_ALLOC_ALIGNED( &opData->x.pData, dataLenInBytes, BYTE_ALIGNMENT_64); opData->x.dataLenInBytes = dataLenInBytes; PHYS_CONTIG_ALLOC_ALIGNED( &opData->k.pData, dataLenInBytes, BYTE_ALIGNMENT_64); opData->k.dataLenInBytes = dataLenInBytes; /* Verify allocated memory */ if (!(opData->x.pData) || !(opData->k.pData)) { status = CPA_STATUS_FAIL; } else { memcpy(opData->x.pData, pointX, dataLenInBytes); memcpy(opData->k.pData, pointK, dataLenInBytes); /* Perform operation */ PRINT_DBG("cpaCyEcMontEdwdsPointMultiply\n"); status = cpaCyEcMontEdwdsPointMultiply( cyInstHandle, ecMontEdwdsPointMultiplyPerformCallback, (void *)&complete, opData, &multiplyStatus, pXk, pYk); } } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyEcMontEdwdsPointMultiply failed. (status = %d)\n", status); } /* * We now wait until the polling thread to complete * the operation. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCyKeyGenTls\n"); status = CPA_STATUS_FAIL; } } /* * Data sanity */ if (CPA_STATUS_SUCCESS == status) { status = checkResult("montgomery_25519_kp_u", pXk->pData, montgomery_25519_kp_u, sizeof(montgomery_25519_kp_u)); PHYS_CONTIG_FREE(opData->x.pData); } COMPLETION_DESTROY(&complete); if (NULL != pXk) { PHYS_CONTIG_FREE(pXk->pData); OS_FREE(pXk); } if (NULL != pYk) { PHYS_CONTIG_FREE(pYk->pData); OS_FREE(pYk); } if (NULL != opData) { PHYS_CONTIG_FREE(opData->k.pData); PHYS_CONTIG_FREE(opData->x.pData); OS_FREE(opData); } return status; } CpaStatus ecMontEdwdsSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle cyInstHandle = NULL; CpaInstanceInfo2 info = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleAsymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } status = cpaCyInstanceGetInfo2(cyInstHandle, &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Cannot get instance info\n"); return status; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS != status) { return status; } /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); status = ed448PointSamplePerform(cyInstHandle); status |= curve448GeneratorSamplePerform(cyInstHandle); status |= curve25519PointSamplePerform(cyInstHandle); /* Stop the polling thread */ sampleCyStopPolling(); /* Stop Cryptographic component */ PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ cpa_ec_montedwds_sample_user.c000066400000000000000000000103111503624047500422710ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/ec_montedwds_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_ec_montedwds_sample_user.c * *****************************************************************************/ #include "cpa.h" #include "icp_sal_user.h" #include "cpa_sample_utils.h" #if CY_API_VERSION_AT_LEAST(2, 3) extern CpaStatus ecMontEdwdsSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus status = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting elliptic curves Edwards,Montgomery sample code ...\n"); status = qaeMemInit(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)status; } status = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)status; } status = ecMontEdwdsSample(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("\nElliptic curves sample code failed\n"); } else { PRINT_DBG("\nElliptic curves sample code finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)status; } #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/000077500000000000000000000000001503624047500327205ustar00rootroot00000000000000cpa_big_num.c000066400000000000000000000273121503624047500352550ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/**************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /***************************************************************************** * @file cpa_big_num.c * * @description * This file contains functions used in big integer operations. All input * values are little endian integers. * *****************************************************************************/ #include "cpa_big_num.h" #if CY_API_VERSION_AT_LEAST(2, 3) /***************************************************************************** * @description * This function performs modulo operation using OpenSSL BIGNUM. * *****************************************************************************/ static void bigNumModFunc(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx) { BN_mod(r, a, m, ctx); } /***************************************************************************** * @description * This function performs modular inverse operation using OpenSSL BIGNUM. * *****************************************************************************/ static void bigNumModInvFunc(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx) { BN_mod_inverse(r, a, m, ctx); } /***************************************************************************** * @description * This function performs modular addition operation using OpenSSL BIGNUM. * *****************************************************************************/ static void bigNumModAddFunc(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx) { BN_mod_add(r, a, b, m, ctx); } /****************************************************************************** * @description * This function performs modular subtraction operation using OpenSSL * BIGNUM. * *****************************************************************************/ static void bigNumModSubFunc(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx) { BN_mod_sub(r, a, b, m, ctx); } /****************************************************************************** * @description * This function performs modular multiply operation using OpenSSL BIGNUM. * *****************************************************************************/ static void bigNumModMulFunc(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx) { BN_mod_mul(r, a, b, m, ctx); } /***************************************************************************** * @description * This function performs modular square power operation using OpenSSL * BIGNUM. * *****************************************************************************/ static void bigNumModSqrFunc(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx) { BN_mod_sqr(r, a, m, ctx); } /***************************************************************************** * @description * This function performs modular exponentiation operation using * OpenSSL BIGNUM. * *****************************************************************************/ static void bigNumModExpFunc(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx) { BN_mod_exp(r, a, b, m, ctx); } /***************************************************************************** * @description * Table of function pointers used in bigNum(). * *****************************************************************************/ static CpaBigNumFunc bigNumFunc[] = {bigNumModFunc, bigNumModInvFunc, bigNumModAddFunc, bigNumModSubFunc, bigNumModMulFunc, bigNumModSqrFunc, bigNumModExpFunc}; CpaStatus bigNum(CpaBigNumOp bigNumOp, CpaFlatBuffer *r_le, CpaFlatBuffer *a_le, CpaFlatBuffer *b_le, CpaFlatBuffer *m_le) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *r_be = NULL; /* Pointer to result in big endian */ Cpa8U *a_be = NULL; /* Pointer to input in big endian */ Cpa8U *b_be = NULL; /* Pointer to input in big endian */ Cpa8U *m_be = NULL; /* Pointer to input in big endian */ BIGNUM *bn_r = BN_new(); /* BIGNUM result */ BIGNUM *bn_a = BN_new(); /* BIGNUM input a */ BIGNUM *bn_b = BN_new(); /* BIGNUM input b */ BIGNUM *bn_m = BN_new(); /* BIGNUM input m */ Cpa32U bin_r_size = 0; /* Size of output buffer */ BN_CTX *bn_ctx = NULL; /* BIGNUM context pointer */ /* Check input data */ if (a_le->pData == NULL || m_le->pData == NULL) { PRINT_ERR("Input data error %p\n", m_le->pData); status = CPA_STATUS_INVALID_PARAM; goto exit; } if (a_le->dataLenInBytes == 0 || m_le->dataLenInBytes == 0) { PRINT_ERR("Input data length error: a_le->dataLenInBytes: %d, " "b_le->dataLenInBytes: %d\n", a_le->dataLenInBytes, m_le->dataLenInBytes); status = CPA_STATUS_INVALID_PARAM; goto exit; } if (b_le != NULL && b_le->dataLenInBytes == 0) { PRINT_ERR("b_le->dataLenInBytes %d\n", b_le->dataLenInBytes); status = CPA_STATUS_INVALID_PARAM; goto exit; } /* Alloc context */ bn_ctx = BN_CTX_new(); if (bn_ctx == NULL) { PRINT_ERR("BN_CTX_new ERROR!\n"); status = CPA_STATUS_FAIL; goto exit; } /* Alloc buffers for big endian values */ status = OS_MALLOC(&a_be, a_le->dataLenInBytes); if (b_le != NULL) status |= OS_MALLOC(&b_be, b_le->dataLenInBytes); status |= OS_MALLOC(&m_be, m_le->dataLenInBytes); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Memory alloc error"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /* Copy input from little endian to big endian buffers */ memcpy_reverse(a_be, a_le->pData, a_le->dataLenInBytes); if (b_le != NULL) memcpy_reverse(b_be, b_le->pData, b_le->dataLenInBytes); memcpy_reverse(m_be, m_le->pData, m_le->dataLenInBytes); /* Convert from bin to BIGNUM */ BN_bin2bn(a_be, a_le->dataLenInBytes, bn_a); if (b_le != NULL) BN_bin2bn(b_be, b_le->dataLenInBytes, bn_b); BN_bin2bn(m_be, m_le->dataLenInBytes, bn_m); /* Perform big number operation */ bigNumFunc[bigNumOp](bn_r, bn_a, bn_b, bn_m, bn_ctx); /* Get size of output buffer */ bin_r_size = BN_num_bytes(bn_r); /* Alloc buffer for output in big endian format */ if (bin_r_size == 0) { /* If result equals 0 alloc 1 byte and set it with zero */ status = OS_MALLOC(&r_be, 1); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Memory alloc error"); status = CPA_STATUS_FAIL; } else { bin_r_size = 1; *r_be = 0; } } else { status = OS_MALLOC(&r_be, bin_r_size); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Memory alloc error"); status = CPA_STATUS_FAIL; } else BN_bn2bin(bn_r, r_be); } } /* Alloc output buffer with little endian value and copy data */ if (CPA_STATUS_SUCCESS == status) { if (r_le->pData != NULL) { OS_FREE(r_le->pData); r_le->pData = NULL; } if (r_le->pData == NULL) { status = OS_MALLOC(&r_le->pData, bin_r_size); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("r_le->pData ALLOC ERROR!\n"); } if (CPA_STATUS_SUCCESS == status) { r_le->dataLenInBytes = bin_r_size; memcpy_reverse(r_le->pData, r_be, bin_r_size); } } /* Free memory */ OS_FREE(r_be); OS_FREE(a_be); if (b_be != NULL) OS_FREE(b_be); OS_FREE(m_be); BN_CTX_free(bn_ctx); exit: BN_free(bn_r); BN_free(bn_a); BN_free(bn_b); BN_free(bn_m); return status; } #endif cpa_big_num.h000066400000000000000000000124031503624047500352550ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/*************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /*************************************************************************** * @file cpa_big_num.h * * @description * This file contains definitions used in big integer operations. * ***************************************************************************/ #ifndef CPA_BIG_NUM_H #define CPA_BIG_NUM_H #include "cpa_eddsa_sample.h" #include #if CY_API_VERSION_AT_LEAST(2, 3) #define bigNumMod(R, A, M) bigNum(CPA_BIG_NUM_MOD_OP, R, A, NULL, M) #define bigNumModInv(R, A, M) bigNum(CPA_BIG_NUM_MOD_INV_OP, R, A, NULL, M) #define bigNumModAdd(R, A, B, M) bigNum(CPA_BIG_NUM_MOD_ADD_OP, R, A, B, M) #define bigNumModSub(R, A, B, M) bigNum(CPA_BIG_NUM_MOD_SUB_OP, R, A, B, M) #define bigNumModMul(R, A, B, M) bigNum(CPA_BIG_NUM_MOD_MUL_OP, R, A, B, M) #define bigNumModSqr(R, A, M) bigNum(CPA_BIG_NUM_MOD_SQR_OP, R, A, NULL, M) #define bigNumModExp(R, A, B, M) bigNum(CPA_BIG_NUM_MOD_EXP_OP, R, A, B, M) /* Supported big integer operations */ typedef enum _CpaBigNumOp { CPA_BIG_NUM_MOD_OP = 0, CPA_BIG_NUM_MOD_INV_OP, CPA_BIG_NUM_MOD_ADD_OP, CPA_BIG_NUM_MOD_SUB_OP, CPA_BIG_NUM_MOD_MUL_OP, CPA_BIG_NUM_MOD_SQR_OP, CPA_BIG_NUM_MOD_EXP_OP, } CpaBigNumOp; /* Declaration of big integer operation function */ typedef void ( *CpaBigNumFunc)(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m, BN_CTX *ctx); /***************************************************************************** * @description * This function performs big integer operations. * * @param[in] bigNumOp Type of big integer operation performed on a_le, b_le, * m_le, values. * @param[in] a_le Flatbuffer with little endian integer value * @param[in] b_le Flatbuffer with little endian integer value * @param[in] m_le Flatbuffer with little endian integer modulo value * * @param[out] r_le Flatbuffer with little endian integer result value * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter in. * *****************************************************************************/ CpaStatus bigNum(CpaBigNumOp bigNumOp, CpaFlatBuffer *r_le, CpaFlatBuffer *a_le, CpaFlatBuffer *b_le, CpaFlatBuffer *m_le); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ #endif cpa_ed_point_operations.c000066400000000000000000000466721503624047500377130ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/*************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /*************************************************************************** * @file cpa_ed_point_operations.c * * @description * This file contains functions used in point operations on Edwards 25519 * curve. * ***************************************************************************/ #include "cpa_ed_point_operations.h" #if CY_API_VERSION_AT_LEAST(2, 3) extern int gDebugParam; /* d of edwards25519 in little endian integer */ Cpa8U dFactor[32] = {0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, 0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52}; /* p of edwards25519 in little endian integer */ Cpa8U prime[32] = {0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}; /***************************************************************************** * @description * This function checks if B value is greater than A value * * @param[in] A pointer to flat buffer with little endian integer * @param[in] B pointer to flat buffer with little endian integer * * @retval CPA_STATUS_SUCCESS B value is greater or equals A value * @retval CPA_STATUS_FAIL B value is smaller than A value * @retval CPA_STATUS_INVALID_PARAM B dataLenInBytes is equal 0 * *****************************************************************************/ static CpaStatus checkIfSmaller(CpaFlatBuffer *A, CpaFlatBuffer *B) { CpaStatus status = CPA_STATUS_FAIL; Cpa32S i = 0; if (B->dataLenInBytes == 0) return CPA_STATUS_INVALID_PARAM; for (i = B->dataLenInBytes - 1; i >= 0; i--) { if (A->pData[i] > B->pData[i]) return CPA_STATUS_FAIL; else if (A->pData[i] < B->pData[i]) return CPA_STATUS_SUCCESS; } return status; } /***************************************************************************** * @description * This function checks if flat buffer integer value equals zero. * * @param[in] fb pointer to flat buffer with integer value * * @retval CPA_STATUS_SUCCESS Integer value equals zero * @retval CPA_STATUS_FAIL Integer value is greater than zero * *****************************************************************************/ static CpaStatus checkIfBufferEqZero(CpaFlatBuffer *fb) { Cpa32S i = 0; for (i = 0; i < fb->dataLenInBytes; i++) if (fb->pData[i] != 0) return CPA_STATUS_FAIL; return CPA_STATUS_SUCCESS; } /***************************************************************************** * @description * This function sets flat buffer integer value. * * @param[in] fb Pointer to flat buffer * @param[in] value Value to set in flat buffer * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ static CpaStatus setFlatBufferValue(CpaFlatBuffer *fb, Cpa8U value) { CpaStatus status = CPA_STATUS_FAIL; if (fb->pData != NULL) { OS_FREE(fb->pData); fb->pData = NULL; } status = OS_MALLOC(&fb->pData, sizeof(Cpa8U)); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); if (CPA_STATUS_SUCCESS == status) { fb->dataLenInBytes = sizeof(Cpa8U); fb->pData[0] = value; } return status; } void encodePoint(Cpa8U *pPointX, Cpa8U *pPointY, Cpa8U *encPoint) { /* Copy Y value */ memcpy(encPoint, pPointY, DATA_LEN); /* Set LSB from X to MSB Y */ if (CHK_BIT(pPointX[0], 0)) SET_BIT(encPoint[DATA_LEN - 1], 7); else CLR_BIT(encPoint[DATA_LEN - 1], 7); } CpaStatus decodePoint(Cpa8U *encPoint, Cpa8U *pPointX, Cpa8U *pPointY) { CpaStatus status = CPA_STATUS_FAIL; Cpa8U x_0 = 0; /* Least significant bit of X coordinate */ CpaFlatBuffer d = {0}; /* d value of Edwards 25519 curve */ CpaFlatBuffer p = {0}; /* p value of Edwards 25519 curve */ CpaFlatBuffer X = {0}; /* Decoded X coordinate */ CpaFlatBuffer Y = {0}; /* Decoded Y coordinate */ CpaFlatBuffer U = {0}; /* U factor */ CpaFlatBuffer V = {0}; /* V factor */ CpaFlatBuffer A = {0}; /* Temp value */ CpaFlatBuffer B = {0}; /* Temp value */ CpaFlatBuffer C = {0}; /* Temp value */ CpaFlatBuffer D = {0}; /* Temp value */ CpaFlatBuffer E = {0}; /* Temp value */ /* Init values d, p, Y */ status = copyToFlatBuffer(&d, dFactor, DATA_LEN); status |= copyToFlatBuffer(&p, prime, DATA_LEN); status |= copyToFlatBuffer(&Y, encPoint, DATA_LEN); if (CPA_STATUS_SUCCESS == status) { /* Least significant bit of the x-coordinate x_0 */ if (CHK_BIT(encPoint[DATA_LEN - 1], 7)) SET_BIT(x_0, 0); else CLR_BIT(x_0, 0); /* Clear most significant bit of Y coordinate */ CLR_BIT(Y.pData[DATA_LEN - 1], 7); /* If Y >= p decode fails */ status = checkIfSmaller(&Y, &p); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Y is >= p - Point decode fail\n"); } /* To recover the x-coordinate, the curve equation implies * (x^2) % p = ((y^2 - 1) / (d * y^2 + 1)) % p. Let u = y^2 - 1 and * v = d * y^2 + 1. To compute the square root of (u/v), the first step is * to compute the candidate root x = (u/v)^((p+3)/8). This can be done with * using a single modular powering for both the inversion of v and the * square root: x = ((u * (v^3)) * ((u * (v^7))^((p - 5) / 8))) % p */ /* U = (y^2 - 1) % p */ if (CPA_STATUS_SUCCESS == status) { status = bigNumModSqr(&A, &Y, &p); /* A = (A^2) % p */ status |= setFlatBufferValue(&E, 1); /* E = 1 */ status |= bigNumModSub(&U, &A, &E, &p); /* U = (A - E) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } /* V = (d * y^2 + 1) % p */ if (CPA_STATUS_SUCCESS == status) { status = bigNumModMul(&A, &d, &A, &p); /* A = (d * A) % p */ status |= bigNumModAdd(&V, &A, &E, &p); /* V = (A + E) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } /* A = (u * v^3) % p */ if (CPA_STATUS_SUCCESS == status) { status = setFlatBufferValue(&E, 3); /* E = 3 */ status |= bigNumModExp(&A, &V, &E, &p); /* A = (V^E) % p*/ status |= bigNumModMul(&A, &U, &A, &p); /* A = (U * A) % p*/ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } /* B = (u * v^7) % p */ if (CPA_STATUS_SUCCESS == status) { status = setFlatBufferValue(&E, 7); /* E = 7 */ status |= bigNumModExp(&B, &V, &E, &p); /* B = (V^E) % p */ status |= bigNumModMul(&B, &U, &B, &p); /* B = (U * B) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } /* C = ((p-5) / 8) % p */ if (CPA_STATUS_SUCCESS == status) { status = setFlatBufferValue(&E, 5); /* E = 5 */ status |= bigNumModSub(&C, &p, &E, &p); /* C = (p - E) % p */ status |= setFlatBufferValue(&E, 8); /* E = 8 */ status |= bigNumModInv(&D, &E, &p); /* D = (1/E) % p */ status |= bigNumModMul(&C, &C, &D, &p); /* C = (C * D) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } /* X = (A * B^C) % p */ if (CPA_STATUS_SUCCESS == status) { status = bigNumModExp(&D, &B, &C, &p); /* D = (B^C) % p */ status |= bigNumModMul(&X, &A, &D, &p); /* X = (A * D) %p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } /* If v * x^2 = u, x is a square root */ /* B = (v * x^2) % p; */ if (CPA_STATUS_SUCCESS == status) { status = bigNumModSqr(&A, &X, &p); /* A = (X^2) % p */ status |= bigNumModMul(&B, &V, &A, &p); /* B = (V * A) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } if (CPA_STATUS_SUCCESS == status) { /* Check if v * x^2 = u */ if (memcmp(B.pData, U.pData, U.dataLenInBytes)) { /* Check if If v * x^2 = -u is a square root */ status = setFlatBufferValue(&E, 0); /* E = 0 */ status |= bigNumModSub(&U, &E, &U, &p); /* U = (E - U) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); if (CPA_STATUS_SUCCESS == status && (memcmp(B.pData, U.pData, U.dataLenInBytes) == 0)) { /* set x <-- (x * 2^((p-1) /4)) % p, which is a square root*/ status = setFlatBufferValue(&E, 4); /* E = 4 */ status |= bigNumModInv(&C, &E, &p); /* C = (1/E) % p */ status |= setFlatBufferValue(&E, 1); /* E = 1 */ status |= bigNumModSub(&A, &p, &E, &p); /* A = (p - 1) % p */ status |= bigNumModMul(&A, &A, &C, &p); /* A = (A * C) % p */ status |= setFlatBufferValue(&E, 2); /* E = 2 */ status |= bigNumModExp(&D, &E, &A, &p); /* D = (2^A) % p */ status |= bigNumModMul(&X, &X, &D, &p); /* X = (X * D) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } else { PRINT_ERR("No square root - Point decode fail\n"); status = CPA_STATUS_FAIL; } } } /* If x = 0 and x_0 = 1, decoding fails */ if (CPA_STATUS_SUCCESS == status) { if (CPA_STATUS_SUCCESS == checkIfBufferEqZero(&X) && x_0 == 1) { PRINT_ERR("Point decode fail\n"); status = CPA_STATUS_FAIL; } } /* If x_0 != x % 2, set x <-- p - x */ if (CPA_STATUS_SUCCESS == status) { if ((CHK_BIT(X.pData[0], 0)) != x_0) { status = bigNumModSub(&X, &p, &X, &p); /* X = (p - X) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point decode failed\n"); } } /* Copy x and y to output buffers */ if (CPA_STATUS_SUCCESS == status) { memcpy(pPointX, X.pData, X.dataLenInBytes); memcpy(pPointY, Y.pData, Y.dataLenInBytes); } /* Free memory */ OS_FREE(d.pData); OS_FREE(p.pData); OS_FREE(X.pData); OS_FREE(Y.pData); OS_FREE(U.pData); OS_FREE(V.pData); OS_FREE(A.pData); OS_FREE(B.pData); OS_FREE(C.pData); OS_FREE(D.pData); OS_FREE(E.pData); return status; } CpaStatus addPoints(Cpa8U *pPointAx, Cpa8U *pPointAy, Cpa8U *pPointBx, Cpa8U *pPointBy, Cpa8U *pPointCx, Cpa8U *pPointCy) { CpaStatus status = CPA_STATUS_FAIL; /* Field values buffers */ CpaFlatBuffer d = {0}, p = {0}; /* Input/ Output values buffers */ CpaFlatBuffer Ax = {0}, Ay = {0}, Bx = {0}, By = {0}, Cx = {0}, Cy = {0}; /* Extended point values buffers */ CpaFlatBuffer X1 = {0}, Y1 = {0}, Z1 = {0}, T1 = {0}; CpaFlatBuffer X2 = {0}, Y2 = {0}, Z2 = {0}, T2 = {0}; CpaFlatBuffer X3 = {0}, Y3 = {0}, Z3 = {0}, T3 = {0}; /* Point addition temporary buffers */ CpaFlatBuffer A = {0}, B = {0}, C = {0}, D = {0}, E = {0}, F = {0}, G = {0}, H = {0}, I = {0}, J = {0}; /* Init field values */ status = copyToFlatBuffer(&d, dFactor, DATA_LEN); status |= copyToFlatBuffer(&p, prime, DATA_LEN); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point addition failed\n"); /* Init input points values */ if (CPA_STATUS_SUCCESS == status) { status = copyToFlatBuffer(&Ax, pPointAx, DATA_LEN); status |= copyToFlatBuffer(&Ay, pPointAy, DATA_LEN); status |= copyToFlatBuffer(&Bx, pPointBx, DATA_LEN); status |= copyToFlatBuffer(&By, pPointBy, DATA_LEN); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point addition failed\n"); } /* For point addition, a point (x,y) is represented in extended homogeneous * coordinates (X, Y, T, Z) and an extended affine point (x, y, xy) which is * equally written as (x, y, xy, 1). */ /* Set extended points values */ if (CPA_STATUS_SUCCESS == status) { status = copyToFlatBuffer(&X1, pPointAx, DATA_LEN); /* X1 = Ax */ status |= copyToFlatBuffer(&Y1, pPointAy, DATA_LEN); /* Y1 = Ay */ status |= bigNumModMul(&T1, &Ax, &Ay, &p); /* T1 = (Ax * Ay) % p */ status |= setFlatBufferValue(&Z1, 1); /* Z1 = 1 */ status |= copyToFlatBuffer(&X2, pPointBx, DATA_LEN); /* X2 = Bx */ status |= copyToFlatBuffer(&Y2, pPointBy, DATA_LEN); /* Y2 = By */ status |= bigNumModMul(&T2, &Bx, &By, &p); /* T2 = (Bx * By) % p */ status |= setFlatBufferValue(&Z2, 1); /* Z2 = 1 */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point addition failed\n"); } /* The formula for adding two points, (x3,y3) = (x1,y1)+(x2,y2), * on twisted Edwards curves with a=-1, square a, and non-square d. * It works for any pair of valid input points. * * A = (Y1-X1)*(Y2-X2) * B = (Y1+X1)*(Y2+X2) * C = T1*2*d*T2 * D = Z1*2*Z2 * E = B-A * F = D-C * G = D+C * H = B+A * X3 = E*F * Y3 = G*H * T3 = E*H * Z3 = F*G */ /* Add two extended points */ if (CPA_STATUS_SUCCESS == status) { status = bigNumModSub(&I, &Y1, &X1, &p); /* I = (Y1 - X1) % p */ status |= bigNumModSub(&J, &Y2, &X2, &p); /* J = (Y2 - X2) % p */ status |= bigNumModMul(&A, &I, &J, &p); /* A = (I * J) % p */ status |= bigNumModAdd(&I, &Y1, &X1, &p); /* I = (Y1 + X1) % p */ status |= bigNumModAdd(&J, &Y2, &X2, &p); /* J = (Y2 + X2) % p */ status |= bigNumModMul(&B, &I, &J, &p); /* B = (I * J) % p*/ status |= setFlatBufferValue(&I, 2); /* I = 2 */ status |= bigNumModMul(&J, &T1, &I, &p); /* J = (T1 * 2) % p; */ status |= bigNumModMul(&J, &J, &d, &p); /* J = (J * d) % p */ status |= bigNumModMul(&C, &J, &T2, &p); /* C = (J * T2) % p */ status |= bigNumModMul(&D, &Z1, &I, &p); /* D = (Z1 * 2) % p */ status |= bigNumModMul(&D, &D, &Z2, &p); /* D = (D * Z2) % p */ status |= bigNumModSub(&E, &B, &A, &p); /* E = (B - A) % p */ status |= bigNumModSub(&F, &D, &C, &p); /* F = (D - C) % p */ status |= bigNumModAdd(&G, &D, &C, &p); /* G = (D + C) % p */ status |= bigNumModAdd(&H, &B, &A, &p); /* H = (B + A) % p */ status |= bigNumModMul(&X3, &E, &F, &p); /* X3 = (E * F) % p */ status |= bigNumModMul(&Y3, &G, &H, &p); /* Y3 = (G * H) % p */ status |= bigNumModMul(&T3, &E, &H, &p); /* T3 = (E * H) % p*/ status |= bigNumModMul(&Z3, &F, &G, &p); /* Z3 = (F * G) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point addition failed\n"); } /* Decode points from extended notation x = X/Z, y = Y/Z */ if (CPA_STATUS_SUCCESS == status) { status = bigNumModInv(&Z3, &Z3, &p); /* Z3 = (1/Z3) % p */ status |= bigNumModMul(&Cx, &X3, &Z3, &p); /* Cx = (X3 * Z3) % p */ status |= bigNumModMul(&Cy, &Y3, &Z3, &p); /* Cy = (Y3 * Z3) % p */ if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Point addition failed\n"); } /* Copy values to output buffers */ if (CPA_STATUS_SUCCESS == status) { memcpy(pPointCx, Cx.pData, DATA_LEN); memcpy(pPointCy, Cy.pData, DATA_LEN); } /* Free memory */ OS_FREE(d.pData); OS_FREE(p.pData); OS_FREE(Ax.pData); OS_FREE(Ay.pData); OS_FREE(Bx.pData); OS_FREE(By.pData); OS_FREE(Cx.pData); OS_FREE(Cy.pData); OS_FREE(X1.pData); OS_FREE(Y1.pData); OS_FREE(T1.pData); OS_FREE(Z1.pData); OS_FREE(X2.pData); OS_FREE(Y2.pData); OS_FREE(T2.pData); OS_FREE(Z2.pData); OS_FREE(X3.pData); OS_FREE(Y3.pData); OS_FREE(T3.pData); OS_FREE(Z3.pData); OS_FREE(A.pData); OS_FREE(B.pData); OS_FREE(C.pData); OS_FREE(D.pData); OS_FREE(E.pData); OS_FREE(F.pData); OS_FREE(G.pData); OS_FREE(H.pData); OS_FREE(I.pData); OS_FREE(J.pData); return status; } #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ cpa_ed_point_operations.h000066400000000000000000000140061503624047500377020ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/** ***************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_ed_point_operations.h * * @description * This file contains declarations of functions used in Edwards 25519 curve * point operations. * *****************************************************************************/ #ifndef CPA_ED_POINT_OPERATIONS_H #define CPA_ED_POINT_OPERATIONS_H #include "cpa_eddsa_sample.h" #if CY_API_VERSION_AT_LEAST(2, 3) /***************************************************************************** * @description * This function takes X and Y coordinate and encodes point in a curve to * a single value. * * @param[in] pPointX Pointer to buffer with X coordinate of point on curve * @param[in] pPointY Pointer to buffer with Y coordinate of point on curve * * @param[out] encPoint Pointer to buffer with encoded point on a curve * *****************************************************************************/ void encodePoint(Cpa8U *pPointX, Cpa8U *pPointY, Cpa8U *encPoint); /***************************************************************************** * @description * This function takes encoded point value and retrieves X and Y * coordinate of point on a curve. * * @param[in] encPoint Pointer to buffer with encoded point on a curve * * @param[out] pPointX Pointer to buffer with X coordinate of point on curve * @param[out] pPointY Pointer to buffer with Y coordinate of point on curve * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ CpaStatus decodePoint(Cpa8U *encPoint, Cpa8U *pPointX, Cpa8U *pPointY); /***************************************************************************** * @description * This function takes two points A and B representend as Ax, Ay, Bx, By, * coordinate values and performs point addition on Edwards 25519 curve. * Result is point C represented in Cx and Cy coordinate values. Addition * is performed on extended homogeneous coordinates (X, Y, Z, T), * with x = X/Z, y = Y/Z, x * y = T/Z. Function work for any pair of valid * input points. * * @param[in] pPointAx Pointer to buffer with X coordinate of point A * @param[in] pPointAy Pointer to buffer with Y coordinate of point A * @param[in] pPointBx Pointer to buffer with X coordinate of point B * @param[in] pPointBy Pointer to buffer with X coordinate of point B * * @param[out] pPointCx Pointer to buffer with X coordinate of point C * @param[out] pPointCy Pointer to buffer with Y coordinate of point C * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ CpaStatus addPoints(Cpa8U *pPointAx, Cpa8U *pPointAy, Cpa8U *pPointBx, Cpa8U *pPointBy, Cpa8U *pPointCx, Cpa8U *pPointCy); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ #endif cpa_eddsa_sample.c000066400000000000000000000653041503624047500362610ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/** ***************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_eddsa_sample.c * * @description * This file contains functions that performs EDDSA operation. * Sample represents HashEdDSA on Edwards 25519 curve described * in RFC 8032. (https://tools.ietf.org/html/rfc8032) * *****************************************************************************/ #include "cpa_eddsa_sample.h" #if CY_API_VERSION_AT_LEAST(2, 3) extern int gDebugParam; CpaInstanceHandle cyInstHandle; /* Instance handle used in point multiply */ /* Order of Edwards 25519 curve */ static Cpa8U order[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; /* Base point X coordinate of Edwards 25519 curve */ static Cpa8U Bx[32] = {0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}; /* Base point Y coordinate of Edwards 25519 curve */ static Cpa8U By[32] = {0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}; /***************************************************************************** * @description * This function reduces scalar to field order value * * @param[in] fb Pointer to flat buffer with scalar value * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ static CpaStatus reduceScalar(CpaFlatBuffer *fb) { CpaStatus status = CPA_STATUS_SUCCESS; CpaFlatBuffer L = {0}; Cpa8U *data = NULL; /* Prepare L value flat buffer */ if (CPA_STATUS_SUCCESS == status) status = copyToFlatBuffer(&L, order, sizeof(order)); /* Reduce fb % L */ if (CPA_STATUS_SUCCESS == status) status = bigNumMod(fb, fb, &L); /* Align output buffer to DATA_LEN for QAT operations */ if (CPA_STATUS_SUCCESS == status && fb->dataLenInBytes < DATA_LEN) { status = OS_MALLOC(&data, DATA_LEN); if (CPA_STATUS_SUCCESS == status) { memset(data, 0, DATA_LEN); memcpy(data, fb->pData, fb->dataLenInBytes); OS_FREE(fb->pData); fb->pData = data; fb->dataLenInBytes = DATA_LEN; } } /* Free memory */ OS_FREE(L.pData); return status; } void memcpy_reverse(Cpa8U *dest, Cpa8U *src, Cpa32U src_len) { Cpa32U i = 0; Cpa32U j = 0; for (i = 0, j = src_len - 1; 0 < j + 1; j--, i++) dest[i] = src[j]; } CpaStatus copyToFlatBuffer(CpaFlatBuffer *fb, Cpa8U *input, Cpa32U inputLen) { CpaStatus status = CPA_STATUS_SUCCESS; if (fb->pData != NULL) { OS_FREE(fb->pData); fb->pData = NULL; } status = OS_MALLOC(&fb->pData, inputLen); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); if (CPA_STATUS_SUCCESS == status) { memcpy(fb->pData, input, inputLen); fb->dataLenInBytes = inputLen; } return status; } /***************************************************************************** * @description * This function performs scalar multiplication of a point on Edwards 25519 * curve. * * @param[in] pPointX Pointer to buffer with X coordinate in little endian * integer * @param[in] pPointY Pointer to buffer with Y coordinate in little endian * integer * @param[in] pScalar Pointer to buffer with scalar in little endian * integer * * @param[out] pGenPointX Pointer to buffer with X coordinate of multiplied * point in little endian integer * @param[out] pGenPointY Pointer to buffer with Y coordinate of multiplied * point in little endian integer * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ static CpaStatus pointMuliplication(Cpa8U *pPointX, Cpa8U *pPointY, Cpa8U *pScalar, Cpa8U *pGenPointX, Cpa8U *pGenPointY) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean multiplyStatus = CPA_TRUE; CpaCyEcMontEdwdsPointMultiplyOpData *pOpData = NULL; CpaFlatBuffer *pGenX = NULL; CpaFlatBuffer *pGenY = NULL; /* Allocate output flat buffers */ status = OS_MALLOC(&pGenX, sizeof(CpaFlatBuffer)); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Failed to allocate memory for pGenX\n"); else { pGenX->pData = NULL; pGenX->dataLenInBytes = DATA_LEN; } status = OS_MALLOC(&pGenY, sizeof(CpaFlatBuffer)); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Failed to allocate memory for pGenY\n"); else { pGenY->pData = NULL; pGenY->dataLenInBytes = DATA_LEN; } /* Alloc data for output buffers */ if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC_ALIGNED( &pGenX->pData, pGenX->dataLenInBytes, BYTE_ALIGNMENT_64); status |= PHYS_CONTIG_ALLOC_ALIGNED( &pGenY->pData, pGenY->dataLenInBytes, BYTE_ALIGNMENT_64); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); } /* Alloc and setup opData */ if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pOpData, sizeof(CpaCyEcMontEdwdsPointMultiplyOpData)); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); else { pOpData->generator = CPA_FALSE; pOpData->curveType = CPA_CY_EC_MONTEDWDS_ED25519_TYPE; pOpData->x.dataLenInBytes = DATA_LEN; pOpData->y.dataLenInBytes = DATA_LEN; pOpData->k.dataLenInBytes = DATA_LEN; } } /* Alloc x y k buffers and copy x y k values */ if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC_ALIGNED( &pOpData->x.pData, pOpData->x.dataLenInBytes, BYTE_ALIGNMENT_64); status |= PHYS_CONTIG_ALLOC_ALIGNED( &pOpData->y.pData, pOpData->y.dataLenInBytes, BYTE_ALIGNMENT_64); status |= PHYS_CONTIG_ALLOC_ALIGNED( &pOpData->k.pData, pOpData->k.dataLenInBytes, BYTE_ALIGNMENT_64); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); else { memcpy_reverse(pOpData->x.pData, pPointX, DATA_LEN); memcpy_reverse(pOpData->y.pData, pPointY, DATA_LEN); memcpy_reverse(pOpData->k.pData, pScalar, DATA_LEN); } } /* Perform point multiply */ if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCyEcMontEdwdsPointMultiply\n"); status = cpaCyEcMontEdwdsPointMultiply( cyInstHandle, NULL, NULL, pOpData, &multiplyStatus, pGenX, pGenY); } if (CPA_STATUS_SUCCESS != status) PRINT_ERR("cpaCyEcMontEdwdsPointMultiply failed. (status = %d)\n", status); /* Copy point to output buffer */ if (CPA_STATUS_SUCCESS == status) { memcpy_reverse(pGenPointX, pGenX->pData, pGenX->dataLenInBytes); memcpy_reverse(pGenPointY, pGenY->pData, pGenY->dataLenInBytes); } /* Free memory */ if (NULL != pOpData) { PHYS_CONTIG_FREE(pOpData->x.pData); PHYS_CONTIG_FREE(pOpData->y.pData); PHYS_CONTIG_FREE(pOpData->k.pData); OS_FREE(pOpData); } if (NULL != pGenX) { PHYS_CONTIG_FREE(pGenX->pData); OS_FREE(pGenX); } if (NULL != pGenY) { PHYS_CONTIG_FREE(pGenY->pData); OS_FREE(pGenY); } return status; } /***************************************************************************** * @description * This function performs public key generation for EdDSA. * * @param[in] privateKey Pointer to buffer with private key * * @param[out] publicKey Pointer to buffer with generated public key * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ static CpaStatus edDsaGenPubKey(Cpa8U *privateKey, Cpa8U *publicKey) { CpaStatus status = CPA_STATUS_FAIL; Cpa8U s[HASH_LEN] = {0}; Cpa8U publicKeyX[DATA_LEN] = {0}; Cpa8U publicKeyY[DATA_LEN] = {0}; PRINT_DBG("Generate public key\n"); /* Hash the 32-byte private key using SHA-512, storing the digest in a 64-octet large buffer */ status = osalHashSHA512Full(privateKey, s, DATA_LEN); /* Prune the buffer: The lowest three bits of the first octet are * cleared, the highest bit of the last octet is cleared, and the * second highest bit of the last octet is set */ if (CPA_STATUS_SUCCESS == status) { CLR_BIT(s[0], 0); CLR_BIT(s[0], 1); CLR_BIT(s[0], 2); SET_BIT(s[DATA_LEN - 1], 6); CLR_BIT(s[DATA_LEN - 1], 7); /* Perform a fixed-base scalar multiplication [s]B */ status = pointMuliplication(Bx, By, s, publicKeyX, publicKeyY); } /* The public key A is the encoding of the point [s]B. */ if (CPA_STATUS_SUCCESS == status) encodePoint(publicKeyX, publicKeyY, publicKey); return status; } /***************************************************************************** * @description * This function performs sign operation on HashEdDSA algorithm using * Edwards 25519 curve. * * @param[in] privateKey Pointer to buffer with private key * @param[in] messageHash Pointer to buffer with hash from a message to sign * * @param[out] signature Pointer to buffer with generated signature * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ static CpaStatus edDsaSign(Cpa8U *privateKey, Cpa8U *messageHash, Cpa8U *signature) { CpaStatus status = CPA_STATUS_FAIL; Cpa8U *dataToHash = NULL; /* Pointer to memory used in hash function */ CpaFlatBuffer L = {0}; /* Flat buffer to store field order value */ Cpa8U *PH_M = messageHash; /* Message hash (sha512) */ Cpa8U h[HASH_LEN] = {0}; /* Hash calculated from private key */ Cpa8U *prefix = 0; /* Pointer to prefix value */ CpaFlatBuffer k = {0}; /* Flat buffer to store k scalar value */ CpaFlatBuffer r = {0}; /* Flat buffer to store r scalar value */ CpaFlatBuffer s = {0}; /* Flat buffer to store s scalar value */ Cpa8U Ax[DATA_LEN] = {0}; /* A point X coordinate value */ Cpa8U Ay[DATA_LEN] = {0}; /* A point Y coordinate value */ Cpa8U A[DATA_LEN] = {0}; /* Encoded A point value */ Cpa8U Rx[DATA_LEN] = {0}; /* R point X coordinate value */ Cpa8U Ry[DATA_LEN] = {0}; /* R point Y coordinate value */ Cpa8U R[DATA_LEN] = {0}; /* Encoded R point value */ CpaFlatBuffer S = {0}; /* S signature value */ PRINT_DBG("Generate signature\n"); /* Hash the 32-byte private key using SHA-512, storing the digest in a 64-octet large buffer */ status = osalHashSHA512Full(privateKey, h, DATA_LEN); /* s scalar is first part of h */ if (CPA_STATUS_SUCCESS == status) status = copyToFlatBuffer(&s, h, DATA_LEN); if (CPA_STATUS_SUCCESS == status) { /* Prune the buffer: The lowest three bits of the first octet are * cleared, the highest bit of the last octet is cleared, and the * second highest bit of the last octet is set */ CLR_BIT(s.pData[0], 0); CLR_BIT(s.pData[0], 1); CLR_BIT(s.pData[0], 2); SET_BIT(s.pData[DATA_LEN - 1], 6); CLR_BIT(s.pData[DATA_LEN - 1], 7); /* Perform a fixed-base scalar multiplication [s]B */ status = pointMuliplication(Bx, By, s.pData, Ax, Ay); } if (CPA_STATUS_SUCCESS == status) { /* A is the encoding of the point [s]B. */ encodePoint(Ax, Ay, A); /* Let prefix denote the second half of the hash digest */ prefix = h + DATA_LEN; /* Alloc buffer for hash operation */ status = OS_MALLOC(&dataToHash, DATA_LEN + HASH_LEN); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); } /* Compute SHA-512(prefix || PH(M)), where M is the message to be signed. * Interpret the 64-octet digest as a little-endian integer r. */ /* Copy data to buffer */ if (CPA_STATUS_SUCCESS == status) { memmove(dataToHash, prefix, DATA_LEN); memcpy(dataToHash + DATA_LEN, PH_M, HASH_LEN); /* Alloc data for output */ r.dataLenInBytes = HASH_LEN; status = OS_MALLOC(&r.pData, r.dataLenInBytes); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); } /* Generate r scalar by performing hash operation */ if (CPA_STATUS_SUCCESS == status) status = osalHashSHA512Full(dataToHash, r.pData, DATA_LEN + HASH_LEN); /* Reduce r % L (field order) */ if (CPA_STATUS_SUCCESS == status) status = reduceScalar(&r); /* Compute the point [r]B. */ if (CPA_STATUS_SUCCESS == status) status = pointMuliplication(Bx, By, r.pData, Rx, Ry); /* Let the R be the encoding of this point. */ if (CPA_STATUS_SUCCESS == status) encodePoint(Rx, Ry, R); /* Compute SHA512(R || A || PH(M)), and interpret the 64-octet * digest as a little-endian integer k. */ if (CPA_STATUS_SUCCESS == status) { OS_FREE(dataToHash); status = OS_MALLOC(&dataToHash, sizeof(R) + sizeof(A) + HASH_LEN); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); } /* Copy R, A, PH_M to buffer for hash operation */ if (CPA_STATUS_SUCCESS == status) { memcpy(dataToHash, R, sizeof(R)); memcpy(dataToHash + sizeof(R), A, sizeof(A)); memcpy(dataToHash + sizeof(R) + sizeof(A), PH_M, HASH_LEN); k.dataLenInBytes = HASH_LEN; status = OS_MALLOC(&k.pData, k.dataLenInBytes); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); } /* Generate k scalar by performing hash operation */ if (CPA_STATUS_SUCCESS == status) status = osalHashSHA512Full( dataToHash, k.pData, sizeof(R) + sizeof(A) + HASH_LEN); /* Reduce k % L (field order) */ if (CPA_STATUS_SUCCESS == status) status = reduceScalar(&k); /* Compute S = (r + k * s) % L. */ if (CPA_STATUS_SUCCESS == status) { /* Prepare L value */ status = copyToFlatBuffer(&L, order, sizeof(order)); if (CPA_STATUS_SUCCESS == status) { status = bigNumModMul(&S, &k, &s, &L); /* S = k * s % L */ status |= bigNumModAdd(&S, &S, &r, &L); /* S = S + r % L */ } } /* Form the signature of the concatenation of R (32 octets) and the * little-endian encoding of S (32 octets; the three most significant bits * of the final octet are always zero). */ if (CPA_STATUS_SUCCESS == status) { memcpy(signature, R, sizeof(R)); memcpy(signature + DATA_LEN, S.pData, S.dataLenInBytes); } /* Free memory */ OS_FREE(dataToHash); OS_FREE(L.pData); OS_FREE(S.pData); OS_FREE(k.pData); OS_FREE(r.pData); OS_FREE(s.pData); return status; } /***************************************************************************** * @description * This function performs verification of HashEdDSA signature * on Edwards 25519 curve. * * @param[in] publicKey Pointer to buffer with public key * @param[in] messageHash Pointer to buffer with hash from signed message * @param[in] signature Pointer to buffer with message signature * * @retval CPA_STATUS_SUCCESS Signature verification passed * @retval CPA_STATUS_FAIL Signature verification failed * *****************************************************************************/ static CpaStatus edDsaVerify(Cpa8U *publicKey, Cpa8U *messageHash, Cpa8U *signature) { CpaStatus status = CPA_STATUS_FAIL; Cpa8U *dataToHash = NULL; /* Pointer to data used in hash function */ CpaFlatBuffer k = {0}; /* Flat buffer to store k scalar value */ Cpa8U *PH_M = messageHash; /* Hash form message (sha512) */ Cpa8U *S = signature + DATA_LEN; /* S signature scalar value */ Cpa8U *R = signature; /* Encoded R point value */ Cpa8U *A = publicKey; /* Encoded A point value */ Cpa8U Ax[DATA_LEN] = {0}; /* A point X coordinate value */ Cpa8U Ay[DATA_LEN] = {0}; /* A point Y coordinate value */ Cpa8U Rx[DATA_LEN] = {0}; /* R point X coordinate value */ Cpa8U Ry[DATA_LEN] = {0}; /* R point Y coordinate value */ Cpa8U V1x[DATA_LEN] = {0}; /* Verification point 1 X coordinate value */ Cpa8U V1y[DATA_LEN] = {0}; /* Verification point 1 Y coordinate value */ Cpa8U V2x[DATA_LEN] = {0}; /* Verification point 2 X coordinate value */ Cpa8U V2y[DATA_LEN] = {0}; /* Verification point 2 Y coordinate value */ PRINT_DBG("Verify signature\n"); /* Split the signature into two 32-octet halfes. Decode the first half as a * point R, and the second half as an integer S, in the range 0 <= s < L. * Decode the public key A */ /* Decode R point */ status = decodePoint(R, Rx, Ry); /* Decode A point */ if (CPA_STATUS_SUCCESS == status) status = decodePoint(A, Ax, Ay); /* Compute SHA512(R || A || PH(M)), and interpret the 64-octet digest as a * little-endian integer k. */ if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&dataToHash, (DATA_LEN * 2) + HASH_LEN); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); } /* Copy data for hash function */ if (CPA_STATUS_SUCCESS == status) { memcpy(dataToHash, R, DATA_LEN); memcpy(dataToHash + DATA_LEN, A, DATA_LEN); memcpy(dataToHash + (DATA_LEN * 2), PH_M, HASH_LEN); /* Alloc output buffer */ k.dataLenInBytes = HASH_LEN; status = OS_MALLOC(&k.pData, k.dataLenInBytes); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Memory alloc error\n"); } /* Generate k scalar by performing hash operation */ if (CPA_STATUS_SUCCESS == status) status = osalHashSHA512Full(dataToHash, k.pData, (DATA_LEN * 2) + HASH_LEN); /* Reduce k % field order */ if (CPA_STATUS_SUCCESS == status) status = reduceScalar(&k); /* Check the group equation [8][S]B = [8]R + [8][k]A'. It's * sufficient, but not required, to instead check [S]B = R + [k]A'. */ /* Compute verification point 1, V1 = [S]B */ if (CPA_STATUS_SUCCESS == status) status = pointMuliplication(Bx, By, S, V1x, V1y); /* Compute verification point 2, V2 = R + [k]A */ /* Compute the point [k]A */ if (CPA_STATUS_SUCCESS == status) status = pointMuliplication(Ax, Ay, k.pData, Ax, Ay); /* Perform point addition V2 = R + [k]A */ if (CPA_STATUS_SUCCESS == status) status = addPoints(Rx, Ry, Ax, Ay, V2x, V2y); /* Check if V1 = V2, [S]B = R + [k]A */ if (CPA_STATUS_SUCCESS == status) { if (memcmp(V1x, V2x, DATA_LEN) || memcmp(V1y, V2y, DATA_LEN)) { status = CPA_STATUS_FAIL; PRINT_ERR("Verification points do not match\n"); } } /* Free memory */ OS_FREE(dataToHash); OS_FREE(k.pData); return status; } /***************************************************************************** * @description * This function performs sign and verify operation using HashEdDSA on * Edwards 25519 curve. * * @retval CPA_STATUS_SUCCESS Sign and verify completed successfully. * @retval CPA_STATUS_FAIL Sign and verify failed. * *****************************************************************************/ CpaStatus ecMontEdwdsDsaPerform(void) { CpaStatus status = CPA_STATUS_FAIL; Cpa8U messageHash[HASH_LEN] = {0}; /* Buffer for hash from message */ Cpa8U publicKey[DATA_LEN] = {0}; /* Buffer for generated public key */ Cpa8U signature[DATA_LEN * 2] = {0}; /* Buffer for generated signature */ /* Random generated private key - RFC832 Edwards 25519 TEST SHA(abc) */ Cpa8U privateKey[DATA_LEN] = { 0x83, 0x3f, 0xe6, 0x24, 0x09, 0x23, 0x7b, 0x9d, 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e, 0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42}; char *message = "abc"; /* Message to sign - RFC832 Edwards 25519 TEST * SHA(abc) */ /* Hash message */ status = osalHashSHA512Full((Cpa8U *)message, messageHash, strlen(message)); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Hash message failed\n"); /* Generate public key */ if (CPA_STATUS_SUCCESS == status) { status = edDsaGenPubKey(privateKey, publicKey); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Public key generation failed\n"); else PRINT_DBG("Public Key generated successfully\n"); } /* Sign message */ if (CPA_STATUS_SUCCESS == status) { status = edDsaSign(privateKey, messageHash, signature); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Signature generation failed\n"); else PRINT_DBG("Signature generated successfully\n"); } /* Verify sign */ if (CPA_STATUS_SUCCESS == status) { status = edDsaVerify(publicKey, messageHash, signature); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("Signature verification failed\n"); else PRINT_DBG("Signature verified successfully\n"); } return status; } /***************************************************************************** * @description * This function gets instance handle and starts cryptographic * component used in sign and verify functions. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ CpaStatus ecMontEdwdsDsaSample(void) { CpaStatus status = CPA_STATUS_FAIL; /* Get instance handle */ sampleAsymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) return CPA_STATUS_FAIL; /* Start Cryptographic component */ status = cpaCyStartInstance(cyInstHandle); /* Set address translation */ if (CPA_STATUS_SUCCESS == status) { status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error set address translation\n"); return status; } } /* Start polling thread */ sampleCyStartPolling(cyInstHandle); /* Perform sign and verify */ status = ecMontEdwdsDsaPerform(); /* Stop the polling thread */ sampleCyStopPolling(); /* Stop Cryptographic component */ cpaCyStopInstance(cyInstHandle); return status; } #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ cpa_eddsa_sample.h000066400000000000000000000113501503624047500362560ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/** ***************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_eddsa_sample.h * * @description * This file contains declarations of functions used in EdDSA sample. * *****************************************************************************/ #ifndef CPA_EDDSA_SAMPLE_NUM_H #define CPA_EDDSA_SAMPLE_NUM_H #include "Osal.h" #include "cpa_cy_ec.h" #include "lac/cpa_cy_key.h" #include "cpa_sample_utils.h" #include "cpa_big_num.h" #include "cpa_ed_point_operations.h" #define DATA_LEN (32) #define HASH_LEN (64) #define SET_BIT(byte, bit) ((byte) |= (1 << (bit))) #define CLR_BIT(byte, bit) ((byte) &= ~((1) << (bit))) #define CHK_BIT(byte, bit) (!!((byte) & (1 << (bit)))) #if CY_API_VERSION_AT_LEAST(2, 3) /***************************************************************************** * @description * This function copies buffer to destination with reverse order of bytes. * * @param[in] src Pointer to source buffer * @param[in] src_len Source buffer length * * @param[out] dest Pointer to destination buffer * *****************************************************************************/ void memcpy_reverse(Cpa8U *dest, Cpa8U *src, Cpa32U src_len); /***************************************************************************** * @description * This function copies content of buffer into flat buffer. * * @param[in] input Pointer to source buffer * @param[in] inputLen Source buffer length * * @param[out] fb Pointer to flat buffer. * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *****************************************************************************/ CpaStatus copyToFlatBuffer(CpaFlatBuffer *fb, Cpa8U *input, Cpa32U inputLen); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ #endif cpa_eddsa_sample_user.c000066400000000000000000000102531503624047500373100ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/eddsa_sample/*************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /**************************************************************************** * @file cpa_ec_montedwds_sample_user.c * * @description * This file contains main function used in EDDSA sample. * ****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" #if CY_API_VERSION_AT_LEAST(2, 3) extern CpaStatus ecMontEdwdsDsaSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus status = CPA_STATUS_SUCCESS; if (argc > 1) gDebugParam = atoi(argv[1]); PRINT_DBG("Starting EDDSA sample code ...\n"); status = qaeMemInit(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to initialise memory driver\n"); return (int)status; } status = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)status; } status = ecMontEdwdsDsaSample(); if (CPA_STATUS_SUCCESS != status) PRINT_ERR("EDDSA sample code failed\n"); else PRINT_DBG("EDDSA code finished\n"); icp_sal_userStop(); qaeMemDestroy(); return (int)status; } #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/prime_sample/000077500000000000000000000000001503624047500327545ustar00rootroot00000000000000cpa_prime_sample.c000066400000000000000000000317251503624047500363510ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/prime_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that uses the primality testing APIs. A hard-coded * prime number is tested with four different algorithms: * * - GCD primality test * - Fermat primality test * - Miller-Rabin primality test. This test requires random numbers that are * also hardcoded here (see unsigned char MR[]) * - Lucas primality test */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_prime.h" #include "cpa_sample_utils.h" #define NB_MR_ROUNDS 2 #define TIMEOUT_MS 5000 /* 5 seconds*/ extern int gDebugParam; /* Sample prime number: we want to test the primality of this number */ static Cpa8U samplePrimeP_768[] = { 0xDF, 0x3A, 0xD3, 0x1F, 0x2B, 0x41, 0xC5, 0xE8, 0x36, 0x61, 0xAD, 0x36, 0x23, 0xDD, 0xD0, 0x47, 0x8A, 0xB5, 0x06, 0xAA, 0x96, 0x43, 0xC9, 0xD6, 0xC4, 0x5B, 0x43, 0x4C, 0xE7, 0x74, 0x47, 0xF6, 0x5A, 0xA9, 0x9A, 0xA1, 0x3D, 0x38, 0xAD, 0xC1, 0x7E, 0x7A, 0x6E, 0x31, 0x95, 0xB4, 0xD2, 0xF2, 0xD4, 0x6C, 0x6D, 0x87, 0x32, 0x52, 0xF8, 0xE9, 0xC8, 0xDF, 0x1D, 0xDA, 0x16, 0x1C, 0xCB, 0x2B, 0x2C, 0x1D, 0x32, 0x4D, 0x7C, 0x82, 0x8E, 0x29, 0xA6, 0x3F, 0xD9, 0x0C, 0xD4, 0xCE, 0x9E, 0x2D, 0x40, 0xC9, 0x2C, 0x9C, 0x0F, 0xBE, 0x5D, 0x6E, 0x68, 0x5A, 0xEB, 0x0F, 0x5D, 0xDF, 0xBF, 0x7D}; /* Concatenation of two 768 bit length random numbers. Each of these numbers * will be used for Miller-Rabin primality test and has to be greater than * 1 and smaller than the number to test - 1 */ static Cpa8U MR[] = { 0x00, 0x00, 0x18, 0xB5, 0x71, 0xE1, 0xE0, 0x7C, 0x70, 0x66, 0x5F, 0xD8, 0x8B, 0xD9, 0xC2, 0x55, 0x3E, 0xD7, 0x09, 0x68, 0x80, 0xF2, 0x17, 0x1A, 0x7A, 0x6D, 0xC9, 0x24, 0xF2, 0x5C, 0x84, 0x7D, 0xB4, 0xC5, 0xA5, 0x40, 0x9A, 0x3F, 0xB7, 0xBD, 0xD4, 0x66, 0x5F, 0xD8, 0x01, 0xC5, 0x1E, 0xA7, 0x60, 0x42, 0x2D, 0xF5, 0x16, 0xAF, 0x08, 0x6C, 0xF7, 0xA5, 0x73, 0xAB, 0x36, 0xB3, 0x6E, 0x5C, 0xE7, 0x8B, 0xD9, 0xC2, 0x3E, 0xD7, 0x09, 0x1B, 0xF4, 0xD5, 0xD9, 0xF4, 0x46, 0x08, 0xDA, 0x84, 0x0B, 0x34, 0x77, 0x80, 0xB9, 0x7C, 0x7B, 0xAF, 0x23, 0xEA, 0x6E, 0xF2, 0x45, 0x8C, 0xC0, 0x0B, 0x00, 0x00, 0x08, 0xB5, 0x71, 0xE1, 0xE0, 0x7C, 0x70, 0x66, 0x5F, 0xD8, 0x8B, 0xD9, 0xC2, 0x55, 0x3E, 0xD7, 0x09, 0x68, 0x80, 0xF2, 0x17, 0x1A, 0x7A, 0x6D, 0xC9, 0x24, 0xF2, 0x5C, 0x84, 0x7D, 0xB4, 0x7B, 0xAF, 0xCC, 0x9A, 0x3F, 0xB7, 0xBD, 0xD4, 0x66, 0x5F, 0xD8, 0x01, 0xC5, 0x1E, 0xA7, 0x60, 0x42, 0x2D, 0xF5, 0x16, 0xAF, 0x08, 0x6C, 0xF7, 0xA5, 0x73, 0xAB, 0x36, 0xB3, 0x6E, 0x5C, 0x3E, 0xD7, 0x09, 0x68, 0x80, 0xF2, 0x17, 0x1A, 0xF4, 0xD5, 0xD8, 0xF4, 0x46, 0x08, 0xDA, 0x84, 0x0B, 0x34, 0x77, 0x80, 0xB9, 0x7C, 0x7B, 0xAF, 0x23, 0xEA, 0x6E, 0xF2, 0x45, 0x8C, 0xC0, 0x00}; /* Forward declaration */ CpaStatus primeSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing, * etc. In this example, the function prints out the status of the * primality test, and sets the complete variable to indicate it has * been called. */ static void primeCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean testPassed) { PRINT_DBG("primeCallback, status = %d.\n", status); if (NULL == pOpData) { PRINT_ERR("pOpData is null, status = %d\n", status); return; } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("callback failed, status = %d\n", status); } PRINT_DBG("Result of the test: "); if (CPA_TRUE == testPassed) { /* these algorithms can not guarantee that the number is prime: we * can only say it is prime with a high probability */ PRINT_DBG("the number is probably a prime\n"); } else { PRINT_DBG("the number is not a prime: testPassed = %d\n", testPassed); } COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } /* * Perform a primality test operation on an hardcoded prime number */ static CpaStatus primePerformOp(CpaInstanceHandle cyInstHandle) { CpaStatus status = CPA_STATUS_SUCCESS; /** Default is false (meaning the number is not a prime), except if the * test explicitly says it is probably a prime */ CpaBoolean testPassed = CPA_FALSE; /* Prime buffer */ Cpa8U *pPrime = NULL; Cpa8U *pMR = NULL; struct COMPLETION_STRUCT complete; /** Structure containing the operational data */ CpaCyPrimeTestOpData *pPrimeTestOpData = NULL; PRINT_DBG("primePerformOp\n"); COMPLETION_INIT(&complete); status = PHYS_CONTIG_ALLOC(&pPrime, sizeof(samplePrimeP_768)); if (NULL != pPrime) { memcpy(pPrime, samplePrimeP_768, sizeof(samplePrimeP_768)); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pMR, sizeof(MR)); if (NULL != pMR) { memcpy(pMR, MR, sizeof(MR)); } } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pPrimeTestOpData, sizeof(CpaCyPrimeTestOpData)); } if (CPA_STATUS_SUCCESS == status) { /** Populate the structure containing the data about the number to test: * - the number of which we want to test the primality * - its length * - perform a GCD Primality Test * - perform a Fermat Primality Test * - number of Miller-Rabin rounds to perform (from 0 to 50) * - Miller-Rabin random numbers (one for each test) * - perform a Lucas Primality Test */ // pPrimeTestOpData->primeCandidate.pData = pPrime; pPrimeTestOpData->primeCandidate.dataLenInBytes = sizeof(samplePrimeP_768); pPrimeTestOpData->performGcdTest = CPA_TRUE; pPrimeTestOpData->performFermatTest = CPA_TRUE; pPrimeTestOpData->numMillerRabinRounds = NB_MR_ROUNDS; pPrimeTestOpData->millerRabinRandomInput.pData = pMR; pPrimeTestOpData->millerRabinRandomInput.dataLenInBytes = sizeof(MR); pPrimeTestOpData->performLucasTest = CPA_TRUE; status = cpaCyPrimeTest( cyInstHandle, (const CpaCyPrimeTestCbFunc)primeCallback, /* CB function */ (void *)&complete, /* callback tag */ pPrimeTestOpData, /* operation data */ &testPassed); /* return value: true if the number is probably a prime, false if it is not a prime */ } // if (CPA_STATUS_SUCCESS == status) { /** Wait until the callback function has been called*/ if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } /** Free all allocated structures before exit*/ PHYS_CONTIG_FREE(pPrime); PHYS_CONTIG_FREE(pMR); OS_FREE(pPrimeTestOpData); COMPLETION_DESTROY(&complete); return status; } CpaStatus primeSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle cyInstHandle = NULL; CpaCyPrimeStats64 primeStats = {0}; PRINT_DBG("start of Prime sample code\n"); /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleAsymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCyStartInstance() failed. (status = %d)\n", status); return status; } if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySetAddressTranslation() failed. (status = %d)\n", status); cpaCyStopInstance(cyInstHandle); return status; } } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); /** Perform Primality test operations */ status = primePerformOp(cyInstHandle); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("primePerformOp() failed. (status = %d)\n", status); sampleCyStopPolling(); cpaCyStopInstance(cyInstHandle); return status; } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCyPrimeQueryStats\n"); status = cpaCyPrimeQueryStats64(cyInstHandle, &primeStats); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCyPrimeQueryStats() failed. (status = %d)\n", status); sampleCyStopPolling(); cpaCyStopInstance(cyInstHandle); return status; } PRINT_DBG("Number of prime test requests: %llu\n", (unsigned long long)primeStats.numPrimeTestRequests); } /* Stop the polling thread */ sampleCyStopPolling(); /** Stop Cryptographic component */ PRINT_DBG("cpaCyStopInstance\n"); status = cpaCyStopInstance(cyInstHandle); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCyStopInstance() failed. (status = %d)\n", status); return status; } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_prime_sample_user.c000066400000000000000000000100401503624047500373720ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/asym/prime_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_prime_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus primeSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Prime Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = primeSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nPrime Sample Code App failed\n"); } else { PRINT_DBG("\nPrime Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/common/000077500000000000000000000000001503624047500306165ustar00rootroot00000000000000cpa_sample_utils.c000066400000000000000000000247451503624047500342430ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/common/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_utils.c * * @ingroup sampleCode * * @description * Defines functions to get an instance and poll an instance * ***************************************************************************/ #include "cpa_sample_utils.h" #include "cpa_dc.h" #include "cpa_cy_sym.h" #include "icp_sal_poll.h" /* * Maximum number of instances to query from the API */ #ifdef USER_SPACE #define MAX_INSTANCES 1024 #else #define MAX_INSTANCES 1 #endif #define UPPER_HALF_OF_REGISTER 32 #ifdef DO_CRYPTO static sampleThread gPollingThread; static volatile int gPollingCy = 0; #endif static sampleThread gPollingThreadDc; static volatile int gPollingDc = 0; #ifdef SC_ENABLE_DYNAMIC_COMPRESSION CpaDcHuffType huffmanType_g = CPA_DC_HT_FULL_DYNAMIC; #else CpaDcHuffType huffmanType_g = CPA_DC_HT_STATIC; #endif /* ************************************************************* * * Common instance functions * * ************************************************************* */ #ifdef DO_CRYPTO /* * This function returns a handle to an instance of the * API of the crypto service type. It does this by querying the API for all * instances of the desired type and returning the first such instance. */ static void sampleCryptoGetInstance(CpaAccelerationServiceType accelSrvType, CpaInstanceHandle *pInstHandle) { CpaInstanceHandle instHandles[MAX_INSTANCES]; Cpa16U numInstances = 0; CpaStatus status = CPA_STATUS_SUCCESS; *pInstHandle = NULL; status = cpaGetNumInstances(accelSrvType, &numInstances); if (0 == numInstances && (accelSrvType == CPA_ACC_SVC_TYPE_CRYPTO_SYM || accelSrvType == CPA_ACC_SVC_TYPE_CRYPTO_ASYM)) { accelSrvType = CPA_ACC_SVC_TYPE_CRYPTO; status = cpaGetNumInstances(accelSrvType, &numInstances); } if (numInstances > MAX_INSTANCES) { numInstances = MAX_INSTANCES; } if (0 == numInstances) { PRINT_ERR("No crypto instances found.\n"); } if (status == CPA_STATUS_SUCCESS) { status = cpaGetInstances(accelSrvType, numInstances, instHandles); if (status == CPA_STATUS_SUCCESS) *pInstHandle = instHandles[0]; } else { PRINT_ERR("Error while getting a crypto instance.\n"); } } void sampleSymGetInstance(CpaInstanceHandle *pSymInstHandle) { sampleCryptoGetInstance(CPA_ACC_SVC_TYPE_CRYPTO_SYM, pSymInstHandle); } void sampleAsymGetInstance(CpaInstanceHandle *pAsymInstHandle) { sampleCryptoGetInstance(CPA_ACC_SVC_TYPE_CRYPTO_ASYM, pAsymInstHandle); } void sampleCyGetInstance(CpaInstanceHandle *pCyInstHandle) { sampleCryptoGetInstance(CPA_ACC_SVC_TYPE_CRYPTO, pCyInstHandle); } void symSessionWaitForInflightReq(CpaCySymSessionCtx pSessionCtx) { /* Session reuse is available since Cryptographic API version 2.2 */ #if CY_API_VERSION_AT_LEAST(2, 2) CpaBoolean sessionInUse = CPA_FALSE; do { cpaCySymSessionInUse(pSessionCtx, &sessionInUse); } while (sessionInUse); #endif return; } #endif /* * This function polls a crypto instance. * */ #ifdef DO_CRYPTO static void sal_polling(CpaInstanceHandle cyInstHandle) { gPollingCy = 1; while (gPollingCy) { icp_sal_CyPollInstance(cyInstHandle, 0); OS_SLEEP(10); } sampleThreadExit(); } #endif /* * This function checks the instance info. If the instance is * required to be polled then it starts a polling thread. */ #ifdef DO_CRYPTO void sampleCyStartPolling(CpaInstanceHandle cyInstHandle) { CpaInstanceInfo2 info2 = {0}; CpaStatus status = CPA_STATUS_SUCCESS; status = cpaCyInstanceGetInfo2(cyInstHandle, &info2); if ((status == CPA_STATUS_SUCCESS) && (info2.isPolled == CPA_TRUE)) { /* Start thread to poll instance */ sampleThreadCreate( &gPollingThread, sal_polling, cyInstHandle, CPA_TRUE); } } #endif /* * This function stops the polling of a crypto instance. */ #ifdef DO_CRYPTO void sampleCyStopPolling(void) { gPollingCy = 0; OS_SLEEP(10); } #endif /* * This function returns a handle to an instance of the data * compression API. It does this by querying the API for all * instances and returning the first such instance. */ // void sampleDcGetInstance(CpaInstanceHandle *pDcInstHandle) { CpaInstanceHandle dcInstHandles[MAX_INSTANCES]; Cpa16U numInstances = 0; CpaStatus status = CPA_STATUS_SUCCESS; *pDcInstHandle = NULL; status = cpaDcGetNumInstances(&numInstances); if (numInstances >= MAX_INSTANCES) { numInstances = MAX_INSTANCES; } if ((status == CPA_STATUS_SUCCESS) && (numInstances > 0)) { status = cpaDcGetInstances(numInstances, dcInstHandles); if (status == CPA_STATUS_SUCCESS) *pDcInstHandle = dcInstHandles[0]; } if (0 == numInstances) { PRINT_ERR("No compression instances found.\n"); } } // /* * This function polls a compression instance. * */ static void sal_dc_polling(CpaInstanceHandle dcInstHandle) { gPollingDc = 1; while (gPollingDc) { icp_sal_DcPollInstance(dcInstHandle, 0); OS_SLEEP(10); } sampleThreadExit(); } /* * This function checks the instance info. If the instance is * required to be polled then it starts a polling thread. */ void sampleDcStartPolling(CpaInstanceHandle dcInstHandle) { CpaInstanceInfo2 info2 = {0}; CpaStatus status = CPA_STATUS_SUCCESS; status = cpaDcInstanceGetInfo2(dcInstHandle, &info2); if ((status == CPA_STATUS_SUCCESS) && (info2.isPolled == CPA_TRUE)) { /* Start thread to poll instance */ sampleThreadCreate( &gPollingThreadDc, sal_dc_polling, dcInstHandle, CPA_TRUE); } } /* * This function stops the thread polling the compression instance. */ void sampleDcStopPolling(void) { gPollingDc = 0; OS_SLEEP(10); } /* * This function reads the value of Time Stamp Counter (TSC) and * returns a 64-bit value. */ Cpa64U sampleCoderdtsc(void) { volatile unsigned long a, d; asm volatile("rdtsc" : "=a"(a), "=d"(d)); return (((Cpa64U)a) | (((Cpa64U)d) << UPPER_HALF_OF_REGISTER)); } /* * This function prints out a hexadecimal representation of bytes. */ void hexLog(Cpa8U *pData, Cpa32U numBytes, const char *caption) { int i = 0; if (NULL == pData) { return; } if (caption != NULL) { PRINT("\n=== %s ===\n", caption); } for (i = 0; i < numBytes; i++) { PRINT("%02X ", pData[i]); if (!((i + 1) % 12)) PRINT("\n"); } PRINT("\n"); } CpaPhysicalAddr virtAddrToDevAddr(void *pVirtAddr, CpaInstanceHandle instanceHandle, CpaAccelerationServiceType type) { CpaStatus status; CpaInstanceInfo2 instanceInfo = { 0 }; /* Get the address translation mode */ switch (type) { #ifdef DO_CRYPTO case CPA_ACC_SVC_TYPE_CRYPTO: status = cpaCyInstanceGetInfo2(instanceHandle, &instanceInfo); break; #endif case CPA_ACC_SVC_TYPE_DATA_COMPRESSION: status = cpaDcInstanceGetInfo2(instanceHandle, &instanceInfo); break; default: status = CPA_STATUS_UNSUPPORTED; } if (CPA_STATUS_SUCCESS != status) { return (CpaPhysicalAddr)(uintptr_t)NULL; } if (instanceInfo.requiresPhysicallyContiguousMemory) { return sampleVirtToPhys(pVirtAddr); } else { return (CpaPhysicalAddr)(uintptr_t)pVirtAddr; } }qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/000077500000000000000000000000001503624047500277145ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/000077500000000000000000000000001503624047500330355ustar00rootroot00000000000000cpa_chaining_sample.c000066400000000000000000000730441503624047500370760ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the dc chain API, * and specifically using this API to perform hash plus compression chain * operation. */ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_dc.h" #include "cpa_dc_chain.h" #include "cpa_sample_utils.h" #include "openssl/sha.h" #include "zlib.h" #include "cpa_chaining_sample_input.h" extern int gDebugParam; #define NUM_SESSIONS_TWO (2) #define SAMPLE_MAX_BUFF (1024) /* Used by ZLIB */ #define DEFLATE_DEF_WINBITS (15) /* Return digest length of hash algorithm */ #define GET_HASH_DIGEST_LENGTH(hashAlg) \ ({ \ int length; \ if (hashAlg == CPA_CY_SYM_HASH_SHA1) \ { \ length = 20; \ } \ else if (hashAlg == CPA_CY_SYM_HASH_SHA256) \ { \ length = 32; \ } \ else \ { \ length = 0; \ } \ length; \ }) static void dcChainFreeBufferList(CpaBufferList **testBufferList); /* Calculate software digest */ static inline CpaStatus calSWDigest(Cpa8U *msg, Cpa32U slen, Cpa8U *digest, Cpa32U dlen, CpaCySymHashAlgorithm hashAlg) { switch (hashAlg) { case CPA_CY_SYM_HASH_SHA1: return (SHA1(msg, slen, digest) == NULL) ? CPA_STATUS_FAIL : CPA_STATUS_SUCCESS; case CPA_CY_SYM_HASH_SHA256: return (SHA256(msg, slen, digest) == NULL) ? CPA_STATUS_FAIL : CPA_STATUS_SUCCESS; default: PRINT_ERR("Unsupported hash algorithm %d\n", hashAlg); return CPA_STATUS_UNSUPPORTED; } } /* Initialise a zlib stream */ static CpaStatus inflate_init(z_stream *stream) { int ret = 0; stream->zalloc = (alloc_func)0; stream->zfree = (free_func)0; stream->opaque = (voidpf)0; stream->next_in = Z_NULL; stream->next_out = Z_NULL; stream->avail_in = stream->avail_out = stream->total_out = 0; stream->adler = 0; ret = inflateInit2(stream, -DEFLATE_DEF_WINBITS); if (Z_OK != ret) { PRINT_ERR("Error in inflateInit2, ret = %d\n", ret); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } /* Decompress data on a zlib stream */ static CpaStatus inflate_decompress(z_stream *stream, const Cpa8U *src, Cpa32U slen, Cpa8U *dst, Cpa32U dlen) { int ret = 0; int flushFlag = Z_NO_FLUSH; stream->next_in = (Cpa8U *)src; stream->avail_in = slen; stream->next_out = (Cpa8U *)dst; stream->avail_out = dlen; ret = inflate(stream, flushFlag); if (ret < Z_OK) { PRINT_ERR("Error in inflate, ret = %d\n", ret); PRINT_ERR("stream->msg = %s\n", stream->msg); PRINT_ERR("stream->adler = %u\n", (unsigned int)stream->adler); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } /* Close zlib stream */ static void inflate_destroy(struct z_stream_s *stream) { inflateEnd(stream); } /* Copy multiple buffers data in buffer lists to flat buffer */ static void copyMultiFlatBufferToBuffer(CpaBufferList *pBufferListSrc, Cpa8U *pBufferDst) { int i = 0; int offset = 0; CpaFlatBuffer *pBuffers = pBufferListSrc->pBuffers; for (; i < pBufferListSrc->numBuffers; i++) { memcpy(pBufferDst + offset, pBuffers->pData, pBuffers->dataLenInBytes); offset += pBuffers->dataLenInBytes; pBuffers++; } } /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a packet, etc. In this example, the function only sets the * complete variable to indicate it has been called. */ // static void dcCallback(void *pCallbackTag, CpaStatus status) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /* indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } // /* Build dc chain buffer lists */ static CpaStatus dcChainBuildBufferList(CpaBufferList **testBufferList, Cpa32U numBuffers, Cpa32U bufferSize, Cpa32U bufferMetaSize) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBufferList *pBuffList = NULL; CpaFlatBuffer *pFlatBuff = NULL; Cpa32U curBuff = 0; Cpa8U *pMsg = NULL; /* * allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); status = OS_MALLOC(&pBuffList, bufferListMemSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error in allocating pBuffList\n"); return CPA_STATUS_FAIL; } pBuffList->numBuffers = numBuffers; if (bufferMetaSize) { status = PHYS_CONTIG_ALLOC(&pBuffList->pPrivateMetaData, bufferMetaSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error in allocating pBuffList->pPrivateMetaData\n"); OS_FREE(pBuffList); return CPA_STATUS_FAIL; } } else { pBuffList->pPrivateMetaData = NULL; } pFlatBuff = (CpaFlatBuffer *)(pBuffList + 1); pBuffList->pBuffers = pFlatBuff; while (curBuff < numBuffers) { pFlatBuff->pData = NULL; if (0 != bufferSize) { status = PHYS_CONTIG_ALLOC(&pMsg, bufferSize); if (CPA_STATUS_SUCCESS != status || NULL == pMsg) { PRINT_ERR("Error in allocating pMsg\n"); dcChainFreeBufferList(&pBuffList); return CPA_STATUS_FAIL; } memset(pMsg, 0, bufferSize); pFlatBuff->pData = pMsg; } pFlatBuff->dataLenInBytes = bufferSize; pFlatBuff++; curBuff++; } *testBufferList = pBuffList; return CPA_STATUS_SUCCESS; } /* Free dc chain buffer lists */ static void dcChainFreeBufferList(CpaBufferList **testBufferList) { CpaBufferList *pBuffList = *testBufferList; CpaFlatBuffer *pFlatBuff = NULL; Cpa32U curBuff = 0; if (NULL == pBuffList) { PRINT_ERR("testBufferList is NULL\n"); return; } pFlatBuff = pBuffList->pBuffers; while (curBuff < pBuffList->numBuffers) { if (NULL != pFlatBuff->pData) { PHYS_CONTIG_FREE(pFlatBuff->pData); pFlatBuff->pData = NULL; } pFlatBuff++; curBuff++; } if (NULL != pBuffList->pPrivateMetaData) { PHYS_CONTIG_FREE(pBuffList->pPrivateMetaData); pBuffList->pPrivateMetaData = NULL; } OS_FREE(pBuffList); *testBufferList = NULL; } /* * This function performs a dc chain operation. */ static CpaStatus dcChainingPerformOp(CpaInstanceHandle dcInstHandle, CpaDcSessionHandle sessionHdl) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferListSrc = NULL; CpaBufferList *pBufferListDst = NULL; CpaFlatBuffer *pFlatBuffer = NULL; Cpa32U bufferSize = 0; Cpa32U numBuffers = 1; Cpa8U *pDigestBuffer = NULL; CpaDcChainOpData chainOpData[2] = {{0}, {0}}; CpaDcOpData dcOpData = {0}; CpaCySymOpData cySymOpData = {0}; CpaDcChainRqResults chainResult = {0}; CpaDcChainOperations operation = CPA_DC_CHAIN_HASH_THEN_COMPRESS; CpaCySymHashAlgorithm hashAlg = CPA_CY_SYM_HASH_SHA256; Cpa8U numSessions = NUM_SESSIONS_TWO; struct COMPLETION_STRUCT complete; Cpa8U *pSWDigestBuffer = NULL; /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); PRINT_DBG("cpaDcBufferListGetMetaSize\n"); /* * Different implementations of the API require different * amounts of space to store meta-data associated with buffer * lists. We query the API to find out how much space the current * implementation needs, and then allocate space for the buffer * meta data, the buffer list, and for the buffer itself. */ // status = cpaDcBufferListGetMetaSize(dcInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error get meta size\n"); return CPA_STATUS_FAIL; } bufferSize = sampleDataSize; if (CPA_STATUS_SUCCESS == status) { status = dcChainBuildBufferList( &pBufferListSrc, numBuffers, bufferSize, bufferMetaSize); } /* copy source data into buffer */ if (CPA_STATUS_SUCCESS == status) { pFlatBuffer = (CpaFlatBuffer *)(pBufferListSrc + 1); memcpy(pFlatBuffer->pData, sampleData, bufferSize); } /* Allocate destination buffer the four times as source buffer */ if (CPA_STATUS_SUCCESS == status) { status = dcChainBuildBufferList( &pBufferListDst, numBuffers, 4 * bufferSize, bufferMetaSize); } /* Allocate digest result buffer to store hash value */ if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pDigestBuffer, GET_HASH_DIGEST_LENGTH(hashAlg)); } // if (CPA_STATUS_SUCCESS == status) { dcOpData.flushFlag = CPA_DC_FLUSH_FINAL; dcOpData.compressAndVerify = CPA_TRUE; dcOpData.compressAndVerifyAndRecover = CPA_TRUE; cySymOpData.packetType = CPA_CY_SYM_PACKET_TYPE_FULL; cySymOpData.hashStartSrcOffsetInBytes = 0; cySymOpData.messageLenToHashInBytes = bufferSize; cySymOpData.pDigestResult = pDigestBuffer; /* Set chaining operation data */ chainOpData[0].opType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainOpData[0].pCySymOp = &cySymOpData; chainOpData[1].opType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainOpData[1].pDcOp = &dcOpData; // status = cpaDcChainPerformOp(dcInstHandle, sessionHdl, pBufferListSrc, pBufferListDst, operation, numSessions, chainOpData, &chainResult, (void *)&complete); // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcChainPerformOp failed. (status = %d)\n", status); } /* * We now wait until the completion of the operation. This uses a macro * which can be defined differently for different OSes. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaDcChainPerformOp\n"); status = CPA_STATUS_FAIL; } } } /* * We now check the results */ if (CPA_STATUS_SUCCESS == status) { if (chainResult.dcStatus != CPA_DC_OK) { PRINT_ERR("Results dcStatus not as expected (dcStatus = %d)\n", chainResult.dcStatus); status = CPA_STATUS_FAIL; } else if (chainResult.cyStatus != CPA_DC_OK) { PRINT_ERR("Results cyStatus not as expected (cyStatus = %d)\n", chainResult.cyStatus); status = CPA_STATUS_FAIL; } else { PRINT_DBG("Data consumed %d\n", chainResult.consumed); PRINT_DBG("Data produced %d\n", chainResult.produced); PRINT_DBG("Crc32 checksum 0x%x\n", chainResult.crc32); } } /* Allocate digest result buffer for execution in software*/ if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSWDigestBuffer, GET_HASH_DIGEST_LENGTH(hashAlg)); } /* Use software to calculate digest and verify digest */ if (CPA_STATUS_SUCCESS == status) { status = calSWDigest(sampleData, bufferSize, pSWDigestBuffer, GET_HASH_DIGEST_LENGTH(hashAlg), hashAlg); if (CPA_STATUS_SUCCESS == status) { if (memcmp(pDigestBuffer, pSWDigestBuffer, GET_HASH_DIGEST_LENGTH(hashAlg))) { status = CPA_STATUS_FAIL; PRINT_ERR("Digest buffer does not match expected output\n"); } else { PRINT_DBG("Digest buffer matches expected output\n"); } } PHYS_CONTIG_FREE(pSWDigestBuffer); } /* Use zlib to decompress and verify integrity */ // if (CPA_STATUS_SUCCESS == status) { struct z_stream_s stream = {0}; Cpa8U *pDecompBuffer = NULL; Cpa8U *pHWCompBuffer = NULL; Cpa32U decompBufferLength = 0; Cpa32U compBufferLength = 0; status = inflate_init(&stream); if (CPA_STATUS_SUCCESS != status) { PRINT("zlib stream initialize failed"); } decompBufferLength = pBufferListSrc->numBuffers * pBufferListSrc->pBuffers->dataLenInBytes; compBufferLength = pBufferListDst->numBuffers * pBufferListDst->pBuffers->dataLenInBytes; if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pDecompBuffer, decompBufferLength); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pHWCompBuffer, compBufferLength); } if (CPA_STATUS_SUCCESS == status) { copyMultiFlatBufferToBuffer(pBufferListDst, pHWCompBuffer); } if (CPA_STATUS_SUCCESS == status) { status = inflate_decompress(&stream, pHWCompBuffer, compBufferLength, pDecompBuffer, decompBufferLength); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Decompress data on zlib stream failed\n"); } } if (CPA_STATUS_SUCCESS == status) { /* Compare with original Src buffer */ if (memcmp(pDecompBuffer, sampleData, bufferSize)) { status = CPA_STATUS_FAIL; PRINT_ERR("Decompressed Buffer does not match source buffer\n"); } else { PRINT_DBG("Decompressed Buffer matches source buffer\n"); } } inflate_destroy(&stream); PHYS_CONTIG_FREE(pHWCompBuffer); PHYS_CONTIG_FREE(pDecompBuffer); } // /* * At this stage, the callback function has returned, so it is * sure that the structures won't be needed any more. Free the * memory! */ COMPLETION_DESTROY(&complete); PHYS_CONTIG_FREE(pDigestBuffer); dcChainFreeBufferList(&pBufferListSrc); dcChainFreeBufferList(&pBufferListDst); return status; } /* * This is the main entry point for the sample data dc chain code. * demonstrates the sequence of calls to be made to the API in order * to create a session, perform one or more hash plus compression operations, * and * then tear down the session. */ CpaStatus dcChainSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceHandle dcInstHandle = NULL; CpaDcSessionHandle sessionHdl = NULL; CpaDcChainSessionSetupData chainSessionData[2] = {{0}, {0}}; CpaDcSessionSetupData dcSessionData = {0}; CpaCySymSessionSetupData cySessionData = {0}; Cpa32U sess_size = 0; CpaDcStats dcStats = {0}; CpaDcInstanceCapabilities cap = {0}; CpaBufferList **bufferInterArray = NULL; Cpa16U numInterBuffLists = 0; Cpa16U bufferNum = 0; Cpa32U buffMetaSize = 0; /* * In this simplified version of instance discovery, we discover * exactly one instance of a data compression service. */ sampleDcGetInstance(&dcInstHandle); if (dcInstHandle == NULL) { PRINT_ERR("Get instance failed\n"); return CPA_STATUS_FAIL; } /* Query Capabilities */ PRINT_DBG("cpaDcQueryCapabilities\n"); // status = cpaDcQueryCapabilities(dcInstHandle, &cap); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Query capabilities failed\n"); return status; } if (CPA_FALSE == CPA_BITMAP_BIT_TEST(cap.dcChainCapInfo, CPA_DC_CHAIN_HASH_THEN_COMPRESS)) { PRINT_ERR( "Hash + compress chained operation is not supported on logical " "instance.\n"); PRINT_ERR("Please ensure Chaining related settings are enabled in the " "device configuration " "file.\n"); return CPA_STATUS_FAIL; } if (!cap.statelessDeflateCompression || !cap.checksumCRC32 || !cap.checksumAdler32 || !cap.dynamicHuffman) { PRINT_ERR("Error: Unsupported functionality\n"); return CPA_STATUS_FAIL; } status = cpaDcBufferListGetMetaSize(dcInstHandle, 1, &buffMetaSize); if (CPA_STATUS_SUCCESS == status) { status = cpaDcGetNumIntermediateBuffers(dcInstHandle, &numInterBuffLists); } if (CPA_STATUS_SUCCESS == status && 0 != numInterBuffLists) { status = PHYS_CONTIG_ALLOC(&bufferInterArray, numInterBuffLists * sizeof(CpaBufferList *)); } for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum], sizeof(CpaBufferList)); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferInterArray[bufferNum]->pPrivateMetaData, buffMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum]->pBuffers, sizeof(CpaFlatBuffer)); } if (CPA_STATUS_SUCCESS == status) { /* Implementation requires an intermediate buffer approximately twice the size of the output buffer */ status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum]->pBuffers->pData, 2 * SAMPLE_MAX_BUFF); bufferInterArray[bufferNum]->numBuffers = 1; bufferInterArray[bufferNum]->pBuffers->dataLenInBytes = 2 * SAMPLE_MAX_BUFF; } } /* End numInterBuffLists */ if (CPA_STATUS_SUCCESS == status) { /* Set the address translation function for the instance */ status = cpaDcSetAddressTranslation(dcInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* Start dynamic data compression component */ PRINT_DBG("cpaDcStartInstance\n"); status = cpaDcStartInstance( dcInstHandle, numInterBuffLists, bufferInterArray); } // if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleDcStartPolling(dcInstHandle); /* * We now populate the fields of the session operational data and create * the session. Note that the size required to store a session is * implementation-dependent, so we query the API first to determine how * much memory to allocate, and then allocate that memory. */ // /* Initialize compression session data */ dcSessionData.compLevel = CPA_DC_L1; dcSessionData.compType = CPA_DC_DEFLATE; dcSessionData.huffType = CPA_DC_HT_FULL_DYNAMIC; dcSessionData.autoSelectBestHuffmanTree = CPA_DC_ASB_DISABLED; dcSessionData.sessDirection = CPA_DC_DIR_COMPRESS; dcSessionData.sessState = CPA_DC_STATELESS; dcSessionData.checksum = CPA_DC_CRC32; /* Initialize crypto session data */ cySessionData.sessionPriority = CPA_CY_PRIORITY_NORMAL; /* Hash operation on the source data */ cySessionData.symOperation = CPA_CY_SYM_OP_HASH; cySessionData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; cySessionData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN; cySessionData.hashSetupData.digestResultLenInBytes = GET_HASH_DIGEST_LENGTH(cySessionData.hashSetupData.hashAlgorithm); /* Place the digest result in a buffer unrelated to srcBuffer */ cySessionData.digestIsAppended = CPA_FALSE; /* Generate the digest */ cySessionData.verifyDigest = CPA_FALSE; /* Initialize chaining session data - hash + compression * chain operation */ chainSessionData[0].sessType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainSessionData[0].pCySetupData = &cySessionData; chainSessionData[1].sessType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainSessionData[1].pDcSetupData = &dcSessionData; /* Determine size of session context to allocate */ PRINT_DBG("cpaDcChainGetSessionSize\n"); status = cpaDcChainGetSessionSize(dcInstHandle, CPA_DC_CHAIN_HASH_THEN_COMPRESS, NUM_SESSIONS_TWO, chainSessionData, &sess_size); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session memory */ status = PHYS_CONTIG_ALLOC(&sessionHdl, sess_size); } /* Initialize the chaining session */ if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaDcChainInitSession\n"); status = cpaDcChainInitSession(dcInstHandle, sessionHdl, CPA_DC_CHAIN_HASH_THEN_COMPRESS, NUM_SESSIONS_TWO, chainSessionData, dcCallback); } // if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform chaining operation */ status = dcChainingPerformOp(dcInstHandle, sessionHdl); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("dcChainingPerformOp failed\n"); } /* * In a typical usage, the session might be used to compression * multiple buffers. In this example however, we can now * tear down the session. */ PRINT_DBG("cpaDcChainRemoveSession\n"); // status = cpaDcChainRemoveSession(dcInstHandle, sessionHdl); // /* Maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* * We can now query the statistics on the instance. * * Note that some implementations may also make the stats * available through other mechanisms, e.g. in the /proc * virtual filesystem. */ status = cpaDcGetStats(dcInstHandle, &dcStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetStats failed, status = %d\n", status); } else { PRINT_DBG("Number of compression operations completed: %llu\n", (unsigned long long)dcStats.numCompCompleted); } } /* * Free up memory, stop the instance, etc. */ /* Stop the polling thread */ sampleDcStopPolling(); PRINT_DBG("cpaDcStopInstance\n"); cpaDcStopInstance(dcInstHandle); /* Free session Context */ PHYS_CONTIG_FREE(sessionHdl); /* Free intermediate buffers */ if (bufferInterArray != NULL) { for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers->pData); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pPrivateMetaData); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]); } PHYS_CONTIG_FREE(bufferInterArray); } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_ERR("Sample code failed with status of %d\n", status); } return status; } cpa_chaining_sample_input.h000066400000000000000000000151121503624047500403120ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_chaining_sample_input.h * * @defgroup compression * * @ingroup sampleCode * * @description * Defines sample test data for Data Compression with Chaining. * ***************************************************************************/ #ifndef CPA_CHAINING_SAMPLE_INPUT_H #define CPA_CHAINING_SAMPLE_INPUT_H /* * Sample Data for Compression */ static Cpa8U sampleData[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xEE, 0xEE, 0xDE, 0xAD, 0xBB, 0xBF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4A, 0xCB, 0xBB}; static Cpa32U sampleDataSize = sizeof(sampleData); #endif cpa_chaining_sample_user.c000066400000000000000000000116421503624047500401300ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/chaining_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_chaining_sample_user.c * argv[1], 1 = Enable 0 = Disable -> gDebugParam * argv[2], 1 = Enable 0 = Disable -> useHardCodedCrc * argv[3], 1 = Enable 0 = Disable -> useXstorExtensions * By default gDebugParam and useHardCodedCrc are enabled. * By default useXstorExtensions is disabled. * Example to run, ./chaining_sample 1 0 0 *****************************************************************************/ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_dc.h" #include "cpa_dc_chain.h" #include "cpa_sample_utils.h" #include "icp_sal_user.h" int gDebugParam = 1; int useHardCodedCrc = 1; int useXstorExtensions = 0; extern CpaStatus dcChainSample(void); int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1 && argc < 5) { if (argc == 2) { gDebugParam = atoi(argv[1]); } else if (argc == 3) { gDebugParam = atoi(argv[1]); useHardCodedCrc = atoi(argv[2]); } else if (argc == 4) { gDebugParam = atoi(argv[1]); useHardCodedCrc = atoi(argv[2]); useXstorExtensions = atoi(argv[3]); } } PRINT_DBG("Starting Chaining Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } /* Legacy DC Chaining Sample Code */ stat = dcChainSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nLegacy DC Chaining Sample Code App failed\n"); } else { PRINT_DBG("\nLegacy DC Chaining Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/dc_dp_sample/000077500000000000000000000000001503624047500323265ustar00rootroot00000000000000cpa_dc_dp_sample.c000066400000000000000000000667201503624047500356630ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/dc_dp_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the data plane data * compression API, and specifically using this API to do stateless * compress an input buffer. * It will compress the data using deflate with dynamic huffman trees. */ #include "cpa.h" #include "cpa_dc_dp.h" #include "icp_sal_poll.h" #include "cpa_sample_utils.h" #include "cpa_sample_cnv_utils.h" extern int gDebugParam; #define SAMPLE_MAX_BUFF 1024 #define SINGLE_INTER_BUFFLIST 1 static Cpa8U sampleData[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xEE, 0xEE, 0xDE, 0xAD, 0xBB, 0xBF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4A, 0xCB, 0xBB}; /* ***************************************************************************** * Forward declaration ***************************************************************************** */ CpaStatus dcDpSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the operation has completed. * */ static void dcDpCallback(CpaDcDpOpData *pOpData) { pOpData->pCallbackTag = (void *)1; } /* * This function performs a compression operation. */ static CpaStatus compPerformOp(CpaInstanceHandle dcInstHandle, CpaDcSessionHandle sessionHdl, CpaDcHuffType huffType) { CpaStatus status = CPA_STATUS_SUCCESS; CpaPhysBufferList *pBufferListSrc = NULL; CpaPhysBufferList *pBufferListDst = NULL; CpaPhysBufferList *pBufferListDst2 = NULL; Cpa32U bufferSize = sizeof(sampleData); Cpa32U dstBufferSize = bufferSize; Cpa32U numBuffers = 0; Cpa32U bufferListMemSize = 0; Cpa8U *pSrcBuffer = NULL; Cpa8U *pSrcBuffer2 = NULL; Cpa8U *pDstBuffer = NULL; Cpa8U *pDst2Buffer = NULL; CpaDcDpOpData *pOpData = NULL; Cpa32U checksum = 0; #if defined(SC_BSD_UPSTREAM) CpaInstanceInfo2 info2 = { 0 }; #endif // numBuffers = 2; /* Size of CpaPhysBufferList and array of CpaPhysFlatBuffers */ bufferListMemSize = sizeof(CpaPhysBufferList) + (numBuffers * sizeof(CpaPhysFlatBuffer)); /* Allocate 8-byte aligned source buffer List */ status = PHYS_CONTIG_ALLOC_ALIGNED(&pBufferListSrc, bufferListMemSize, 8); if (CPA_STATUS_SUCCESS == status) { /* Allocate first data buffer to hold half the data */ status = PHYS_CONTIG_ALLOC(&pSrcBuffer, (sizeof(sampleData)) / 2); } if (CPA_STATUS_SUCCESS == status) { /* Allocate second data buffer to hold half the data */ status = PHYS_CONTIG_ALLOC(&pSrcBuffer2, (sizeof(sampleData)) / 2); } if (CPA_STATUS_SUCCESS == status) { /* copy source into buffer */ memcpy(pSrcBuffer, sampleData, sizeof(sampleData) / 2); memcpy(pSrcBuffer2, &(sampleData[sizeof(sampleData) / 2]), sizeof(sampleData) / 2); /* Build source bufferList */ pBufferListSrc->numBuffers = 2; pBufferListSrc->flatBuffers[0].dataLenInBytes = sizeof(sampleData) / 2; pBufferListSrc->flatBuffers[0].bufferPhysAddr = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pSrcBuffer, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pBufferListSrc->flatBuffers[1].dataLenInBytes = sizeof(sampleData) / 2; pBufferListSrc->flatBuffers[1].bufferPhysAddr = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pSrcBuffer2, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); // } /* Destination buffer size is set as sizeof(sampelData) for a * Deflate compression operation with DC_API_VERSION < 2.5. * cpaDcDeflateCompressBound API is used to get maximum output buffer size * for a Deflate compression operation with DC_API_VERSION >= 2.5 */ #if DC_API_VERSION_AT_LEAST(2, 5) status = cpaDcDeflateCompressBound( dcInstHandle, huffType, bufferSize, &dstBufferSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcDeflateCompressBound API failed. (status = %d)\n", status); return CPA_STATUS_FAIL; } #endif #if defined(SC_BSD_UPSTREAM) status = cpaDcInstanceGetInfo2(dcInstHandle, &info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInstanceGetInfo2 API failed. (status = %d)\n", status); return CPA_STATUS_FAIL; } #endif if (CPA_STATUS_SUCCESS == status) { /* Allocate destination buffer the same size as source buffer but in an SGL with 1 buffer */ bufferListMemSize = sizeof(CpaPhysBufferList) + sizeof(CpaPhysFlatBuffer); status = PHYS_CONTIG_ALLOC_ALIGNED(&pBufferListDst, bufferListMemSize, 8); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pDstBuffer, dstBufferSize); } if (CPA_STATUS_SUCCESS == status) { /* Build destination bufferList */ pBufferListDst->numBuffers = 1; pBufferListDst->flatBuffers[0].dataLenInBytes = dstBufferSize; pBufferListDst->flatBuffers[0].bufferPhysAddr = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pDstBuffer, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); // /* Allocate memory for operational data. Note this needs to be * 8-byte aligned, contiguous, resident in DMA-accessible * memory. */ status = PHYS_CONTIG_ALLOC_ALIGNED(&pOpData, sizeof(CpaDcDpOpData), 8); } if (CPA_STATUS_SUCCESS == status) { memset(pOpData, 0, sizeof(CpaDcDpOpData)); pOpData->bufferLenToCompress = sizeof(sampleData); pOpData->bufferLenForData = dstBufferSize; pOpData->dcInstance = dcInstHandle; pOpData->pSessionHandle = sessionHdl; pOpData->srcBuffer = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pBufferListSrc, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pOpData->srcBufferLen = CPA_DP_BUFLIST; pOpData->destBuffer = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pBufferListDst, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pOpData->destBufferLen = CPA_DP_BUFLIST; pOpData->sessDirection = CPA_DC_DIR_COMPRESS; INIT_DC_DP_CNV_OPDATA(pOpData); pOpData->thisPhys = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pOpData, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pOpData->pCallbackTag = (void *)0; // /** Enqueue and submit operation */ // status = cpaDcDpEnqueueOp(pOpData, CPA_TRUE); // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcDpEnqueueOp failed. (status = %d)\n", status); } } if (CPA_STATUS_SUCCESS == status) { /* Poll for responses if instance configured for polling. * Polling functions are implementation specific */ do { #if defined(SC_BSD_UPSTREAM) if (CPA_TRUE == info2.isPolled) #endif { status = icp_sal_DcPollDpInstance(dcInstHandle, 1); } } while ( ((CPA_STATUS_SUCCESS == status) || (CPA_STATUS_RETRY == status)) && (pOpData->pCallbackTag == (void *)0)); } /* * We now check the results */ if (CPA_STATUS_SUCCESS == status) { if (pOpData->responseStatus != CPA_STATUS_SUCCESS) { PRINT_ERR( "status from compression operation failed. (status = %d)\n", pOpData->responseStatus); status = CPA_STATUS_FAIL; } else { if (pOpData->results.status != CPA_DC_OK) { PRINT_ERR("Results status not as expected (status = %d)\n", pOpData->results.status); status = CPA_STATUS_FAIL; } else { PRINT_DBG("Data consumed %d\n", pOpData->results.consumed); PRINT_DBG("Data produced %d\n", pOpData->results.produced); PRINT_DBG("CRC checksum 0x%x\n", pOpData->results.checksum); } /* To compare the checksum with decompressed output */ checksum = pOpData->results.checksum; } } /* * We now ensure we can decompress to the original buffer. */ if (CPA_STATUS_SUCCESS == status) { /* Dst is now the Src buffer - update the length with amount of compressed data added to the buffer */ pBufferListDst->flatBuffers[0].dataLenInBytes = pOpData->results.produced; /* Allocate memory for new destination bufferList Dst2, we can use * stateless decompression here because in this scenario we know * that all transmitted data before compress was less than some * max size */ status = PHYS_CONTIG_ALLOC_ALIGNED(&pBufferListDst2, bufferListMemSize, 8); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pDst2Buffer, SAMPLE_MAX_BUFF); } if (CPA_STATUS_SUCCESS == status) { /* Build destination 2 bufferList */ pBufferListDst2->numBuffers = 1; pBufferListDst2->flatBuffers[0].dataLenInBytes = SAMPLE_MAX_BUFF; pBufferListDst2->flatBuffers[0].bufferPhysAddr = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pDst2Buffer, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); /** Can reuse prev OpData */ pOpData->bufferLenToCompress = pOpData->results.produced; pOpData->bufferLenForData = SAMPLE_MAX_BUFF; pOpData->dcInstance = dcInstHandle; pOpData->pSessionHandle = sessionHdl; pOpData->srcBuffer = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pBufferListDst, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pOpData->srcBufferLen = CPA_DP_BUFLIST; pOpData->destBuffer = virtAddrToDevAddr( (SAMPLE_CODE_UINT *)(uintptr_t)pBufferListDst2, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pOpData->destBufferLen = CPA_DP_BUFLIST; pOpData->sessDirection = CPA_DC_DIR_DECOMPRESS; INIT_DC_DP_CNV_OPDATA(pOpData); pOpData->thisPhys = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pOpData, dcInstHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pOpData->pCallbackTag = (void *)0; PRINT_DBG("cpaDcDpEnqueueOpBatch\n"); /** Enqueue symmetric operation */ status = cpaDcDpEnqueueOpBatch(1, &pOpData, CPA_TRUE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "cpaDcDpEnqueueOpBatch Decomp failed. (status = %d)\n", status); } } if (CPA_STATUS_SUCCESS == status) { /* Poll for responses if instance configured for polling. * Polling functions are implementation specific */ do { #if defined(SC_BSD_UPSTREAM) if (CPA_TRUE == info2.isPolled) #endif { status = icp_sal_DcPollDpInstance(dcInstHandle, 1); } } while (((CPA_STATUS_SUCCESS == status) || (CPA_STATUS_RETRY == status)) && (pOpData->pCallbackTag == (void *)0)); } /* * We now check the results */ if (CPA_STATUS_SUCCESS == status) { if (pOpData->responseStatus != CPA_STATUS_SUCCESS) { PRINT_ERR("status from decompression operation failed. (status " "= %d)\n", pOpData->responseStatus); status = CPA_STATUS_FAIL; } else { if (pOpData->results.status != CPA_DC_OK) { PRINT_ERR("Results status not as expected (status = %d)\n", pOpData->results.status); status = CPA_STATUS_FAIL; } else { PRINT_DBG("Data consumed %d\n", pOpData->results.consumed); PRINT_DBG("Data produced %d\n", pOpData->results.produced); PRINT_DBG("CRC checksum 0x%x\n", pOpData->results.checksum); /* Compare with original data */ if (0 == memcmp(pDst2Buffer, sampleData, sizeof(sampleData))) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_ERR("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } if (checksum == pOpData->results.checksum) { PRINT_DBG("Checksums match after compression and " "decompression\n"); } else { PRINT_ERR("Checksums does not match after compression " "and decompression\n"); status = CPA_STATUS_FAIL; } } } } } /* * Free the memory! */ PHYS_CONTIG_FREE(pOpData); PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pSrcBuffer2); PHYS_CONTIG_FREE(pBufferListSrc); PHYS_CONTIG_FREE(pDstBuffer); PHYS_CONTIG_FREE(pBufferListDst); PHYS_CONTIG_FREE(pDst2Buffer); PHYS_CONTIG_FREE(pBufferListDst2); return status; } /* * This is the main entry point for the sample data compression code. * demonstrates the sequence of calls to be made to the API in order * to create a session, perform one or more stateless compression operations, * and then tear down the session. */ CpaStatus dcDpSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaDcInstanceCapabilities cap = {0}; Cpa32U sess_size = 0; Cpa32U ctx_size = 0; CpaDcSessionHandle sessionHdl = NULL; CpaInstanceHandle dcInstHandle = NULL; CpaDcSessionSetupData sd = {0}; /* Variables required to setup the intermediate buffer */ CpaBufferList **bufferInterArray = NULL; Cpa16U numInterBuffLists = 0; Cpa16U bufferNum = 0; Cpa32U buffMetaSize = 0; /* * In this simplified version of instance discovery, we discover * exactly one instance of a data compression service. * Note this is the same as was done for "traditional" api. */ sampleDcGetInstance(&dcInstHandle); if (dcInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Query Capabilities */ PRINT_DBG("cpaDcQueryCapabilities\n"); status = cpaDcQueryCapabilities(dcInstHandle, &cap); if (status != CPA_STATUS_SUCCESS) { return status; } if (!cap.statelessDeflateCompression || !cap.statelessDeflateDecompression || !cap.checksumCRC32 || !cap.dynamicHuffman) { PRINT_ERR("Error: Unsupported functionality\n"); return CPA_STATUS_FAIL; } if (cap.dynamicHuffmanBufferReq) { status = cpaDcBufferListGetMetaSize(dcInstHandle, 1, &buffMetaSize); if (CPA_STATUS_SUCCESS == status) { status = cpaDcGetNumIntermediateBuffers(dcInstHandle, &numInterBuffLists); } if (CPA_STATUS_SUCCESS == status && 0 != numInterBuffLists) { status = PHYS_CONTIG_ALLOC( &bufferInterArray, numInterBuffLists * sizeof(CpaBufferList *)); } for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum], sizeof(CpaBufferList)); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferInterArray[bufferNum]->pPrivateMetaData, buffMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum]->pBuffers, sizeof(CpaFlatBuffer)); } if (CPA_STATUS_SUCCESS == status) { /* Implementation requires an intermediate buffer approximately twice the size of the output buffer */ status = PHYS_CONTIG_ALLOC( &bufferInterArray[bufferNum]->pBuffers->pData, 2 * SAMPLE_MAX_BUFF); bufferInterArray[bufferNum]->numBuffers = 1; bufferInterArray[bufferNum]->pBuffers->dataLenInBytes = 2 * SAMPLE_MAX_BUFF; } } /* End numInterBuffLists */ } /* * Set the address translation function for the instance */ status = cpaDcSetAddressTranslation(dcInstHandle, sampleVirtToPhys); if (CPA_STATUS_SUCCESS == status) { /* Start DataCompression component */ PRINT_DBG("cpaDcStartInstance\n"); status = cpaDcStartInstance( dcInstHandle, numInterBuffLists, bufferInterArray); } if (CPA_STATUS_SUCCESS == status) { /* Register callback function for the instance */ // status = cpaDcDpRegCbFunc(dcInstHandle, dcDpCallback); // } /* * We now populate the fields of the session operational data and create * the session. Note that the size required to store a session is * implementation-dependent, so we query the API first to determine how * much memory to allocate, and then allocate that memory. */ // if (CPA_STATUS_SUCCESS == status) { sd.compLevel = CPA_DC_L4; sd.compType = CPA_DC_DEFLATE; sd.huffType = huffmanType_g; /* If the implementation supports it, the session will be configured * to select static Huffman encoding over dynamic Huffman as * the static encoding will provide better compressibility. */ if (cap.autoSelectBestHuffmanTree) { #if DC_API_VERSION_AT_LEAST(3, 1) sd.autoSelectBestHuffmanTree = CPA_DC_ASB_ENABLED; #else sd.autoSelectBestHuffmanTree = CPA_DC_ASB_STATIC_DYNAMIC; #endif } else { sd.autoSelectBestHuffmanTree = CPA_DC_ASB_DISABLED; } sd.sessDirection = CPA_DC_DIR_COMBINED; sd.sessState = CPA_DC_STATELESS; #if (CPA_DC_API_VERSION_NUM_MAJOR == 1 && CPA_DC_API_VERSION_NUM_MINOR < 6) sd.deflateWindowSize = 7; #endif sd.checksum = CPA_DC_CRC32; /* Determine size of session context to allocate */ PRINT_DBG("cpaDcGetSessionSize\n"); status = cpaDcGetSessionSize(dcInstHandle, &sd, &sess_size, &ctx_size); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session memory */ status = PHYS_CONTIG_ALLOC(&sessionHdl, sess_size); } /* Initialize the Stateless session */ if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaDcDpInitSession\n"); status = cpaDcDpInitSession(dcInstHandle, sessionHdl, /* session memory */ &sd); /* session setup data */ } // if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform Compression operation */ status = compPerformOp(dcInstHandle, sessionHdl, sd.huffType); PRINT_DBG("cpaDcDpRemoveSession\n"); // sessionStatus = cpaDcDpRemoveSession(dcInstHandle, sessionHdl); // /* Maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } /* * Free up memory, stop the instance, etc. */ /* Free session Context */ PHYS_CONTIG_FREE(sessionHdl); PRINT_DBG("cpaDcStopInstance\n"); cpaDcStopInstance(dcInstHandle); /* Free intermediate buffers */ if (bufferInterArray != NULL) { for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers->pData); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pPrivateMetaData); } PHYS_CONTIG_FREE(bufferInterArray); } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_dc_dp_sample_user.c000066400000000000000000000076101503624047500367120ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/dc_dp_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus dcDpSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Data Plane Compression Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = dcDpSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nData Plane Compression Sample Code App failed\n"); } else { PRINT_DBG("\nData Plane Compression Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } stateless_multi_op_checksum_sample/000077500000000000000000000000001503624047500367775ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dccpa_dc_stateless_multi_op_checksum_sample.c000066400000000000000000000762611503624047500476120ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_multi_op_checksum_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the data compression API, * and specifically using this API to statelessly compress input buffers using * a cumulative checksum. * It will compress the data using deflate with dynamic huffman trees. */ #include "cpa.h" #include "cpa_dc.h" #include "cpa_sample_utils.h" extern int gDebugParam; #define SAMPLE_MAX_BUFF 512 #define TIMEOUT_MS 5000 /* 5 seconds */ #define SINGLE_BUFFER_PER_BUFFERLIST 1 #define SAMPLE_DATA_SIZE 1024 #define NUM_SAMPLE_DATA_BUFFERS (SAMPLE_DATA_SIZE / SAMPLE_MAX_BUFF) static Cpa8U sampleData[SAMPLE_DATA_SIZE] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xEE, 0xEE, 0xDE, 0xAD, 0xBB, 0xBF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4A, 0xCB, 0xBB, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xEE, 0xEE, 0xDE, 0xAD, 0xBB, 0xBF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4A, 0xCB, 0xBB}; /* ***************************************************************************** * Forward declaration ***************************************************************************** */ CpaStatus dcStatelessSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a packet, etc. In this example, the function only sets the * complete variable to indicate it has been called. */ static void dcCallback(void *pCallbackTag, CpaStatus status) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /* indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * This function performs a compression and decompress operation. */ static CpaStatus compPerformOp(CpaInstanceHandle dcInstHandle, CpaDcSessionHandle sessionHdl, CpaDcSessionSetupData sd) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBufferList bufferListSrcArray[NUM_SAMPLE_DATA_BUFFERS] = { { 0 } }; CpaBufferList bufferListDstArray[NUM_SAMPLE_DATA_BUFFERS] = { { 0 } }; CpaBufferList bufferListDstArray2[NUM_SAMPLE_DATA_BUFFERS] = { { 0 } }; Cpa32U srcBufferSize = SAMPLE_MAX_BUFF; Cpa32U dstBufferSize = srcBufferSize; Cpa32U numBuffers = NUM_SAMPLE_DATA_BUFFERS; Cpa32U bufferNum = 0; Cpa32U bufferMetaSize = 0; CpaDcOpData opData = {}; CpaDcRqResults dcResults; Cpa32U dataConsumed = 0; Cpa32U dataProduced = 0; Cpa32U checksum = 0; struct COMPLETION_STRUCT complete; INIT_OPDATA(&opData, CPA_DC_FLUSH_FINAL); /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); status = cpaDcBufferListGetMetaSize( dcInstHandle, SINGLE_BUFFER_PER_BUFFERLIST, &bufferMetaSize); for (bufferNum = 0; bufferNum < numBuffers; bufferNum++) { if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferListSrcArray[bufferNum].pPrivateMetaData, bufferMetaSize); bufferListSrcArray[bufferNum].numBuffers = 1; } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferListDstArray[bufferNum].pPrivateMetaData, bufferMetaSize); bufferListDstArray[bufferNum].numBuffers = 1; } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferListDstArray2[bufferNum].pPrivateMetaData, bufferMetaSize); bufferListDstArray2[bufferNum].numBuffers = 1; } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&bufferListSrcArray[bufferNum].pBuffers, sizeof(CpaFlatBuffer)); bufferListSrcArray[bufferNum].pBuffers->pData = NULL; } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&bufferListDstArray[bufferNum].pBuffers, sizeof(CpaFlatBuffer)); bufferListDstArray[bufferNum].pBuffers->pData = NULL; } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&bufferListDstArray2[bufferNum].pBuffers, sizeof(CpaFlatBuffer)); bufferListDstArray2[bufferNum].pBuffers->pData = NULL; } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferListSrcArray[bufferNum].pBuffers->pData, srcBufferSize); bufferListSrcArray[bufferNum].pBuffers->dataLenInBytes = srcBufferSize; } /* Destination buffer size is set as sizeof(sampelData) for a * Deflate compression operation with DC_API_VERSION < 2.5. * cpaDcDeflateCompressBound API is used to get maximum output buffer * size for a Deflate compression operation with DC_API_VERSION >= 2.5 */ #if DC_API_VERSION_AT_LEAST(2, 5) if (CPA_STATUS_SUCCESS == status) { status = cpaDcDeflateCompressBound( dcInstHandle, sd.huffType, srcBufferSize, &dstBufferSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "cpaDcDeflateCompressBound API failed. (status = %d)\n", status); status = CPA_STATUS_FAIL; break; } } #endif if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferListDstArray[bufferNum].pBuffers->pData, dstBufferSize); bufferListDstArray[bufferNum].pBuffers->dataLenInBytes = dstBufferSize; } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferListDstArray2[bufferNum].pBuffers->pData, srcBufferSize); bufferListDstArray2[bufferNum].pBuffers->dataLenInBytes = srcBufferSize; } if (CPA_STATUS_SUCCESS == status) { memcpy(bufferListSrcArray[bufferNum].pBuffers->pData, sampleData + (bufferNum * srcBufferSize), srcBufferSize); } } if (CPA_STATUS_SUCCESS == status) { // if (sd.checksum == CPA_DC_ADLER32) { /* Initialize checksum to 1 for Adler32 */ dcResults.checksum = 1; } else { /* Initialize checksum to 0 for CRC32 */ dcResults.checksum = 0; } // for (bufferNum = 0; bufferNum < numBuffers; bufferNum++) { PRINT_DBG("cpaDcCompressData2\n"); status = cpaDcCompressData2( dcInstHandle, sessionHdl, &bufferListSrcArray[bufferNum], /* source buffer list */ &bufferListDstArray[bufferNum], /* destination buffer list */ &opData, &dcResults, /* contains initialized checksum for first request * or * checksum from previous request */ (void *)&complete); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcCompressData2 failed. (status = %d)\n", status); break; } /* * We now wait until the completion of the operation. This uses a * macro * which can be defined differently for different OSes. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR( "timeout or interruption in cpaDcCompressData2\n"); status = CPA_STATUS_FAIL; } } /* * We now check the results */ if (dcResults.status != CPA_DC_OK) { PRINT_ERR("Results status not as expected (status = %d)\n", dcResults.status); status = CPA_STATUS_FAIL; break; } if (dcResults.consumed != bufferListSrcArray[bufferNum].pBuffers->dataLenInBytes) { PRINT_ERR("Not all data consumed !\n"); status = CPA_STATUS_FAIL; break; } dataConsumed += dcResults.consumed; dataProduced += dcResults.produced; bufferListDstArray[bufferNum].pBuffers->dataLenInBytes = dcResults.produced; } /* End for numBuffers */ } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Data consumed %d\n", dataConsumed); PRINT_DBG("Data produced %d\n", dataProduced); PRINT_DBG("Checksum 0x%x\n", dcResults.checksum); /* Reset counters and checksum */ dataConsumed = 0; dataProduced = 0; /* To compare the checksum with decompressed output */ checksum = dcResults.checksum; memset(&dcResults, 0, sizeof(CpaDcRqResults)); } if (CPA_STATUS_SUCCESS == status) { if (sd.checksum == CPA_DC_ADLER32) { /* Initialize checksum to 1 for Adler32 */ dcResults.checksum = 1; } else { /* Initialize checksum to 0 for CRC32 */ dcResults.checksum = 0; } for (bufferNum = 0; bufferNum < numBuffers; bufferNum++) { PRINT_DBG("cpaDcDecompressData2\n"); status = cpaDcDecompressData2( dcInstHandle, sessionHdl, &bufferListDstArray[bufferNum], /* source buffer list */ &bufferListDstArray2[bufferNum], /* destination buffer list */ &opData, &dcResults, /* contains initialized checksum for first request * or * checksum from previous request */ (void *)&complete); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcCompressData2 failed. (status = %d)\n", status); break; } /* * We now wait until the completion of the operation. This uses a * macro * which can be defined differently for different OSes. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR( "timeout or interruption in cpaDcDecompressData2\n"); status = CPA_STATUS_FAIL; } } /* * We now check the results */ if (dcResults.status != CPA_DC_OK) { PRINT_ERR("Results status not as expected (status = %d)\n", dcResults.status); status = CPA_STATUS_FAIL; break; } if (dcResults.consumed != bufferListDstArray[bufferNum].pBuffers->dataLenInBytes) { PRINT_ERR("Not all data consumed !\n"); status = CPA_STATUS_FAIL; break; } dataConsumed += dcResults.consumed; dataProduced += dcResults.produced; } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Data consumed %d\n", dataConsumed); PRINT_DBG("Data produced %d\n", dataProduced); PRINT_DBG("Checksum 0x%x\n", dcResults.checksum); for (bufferNum = 0; bufferNum < numBuffers; bufferNum++) { /* Compare with original Src buffer */ if (0 == memcmp(bufferListDstArray2[bufferNum].pBuffers->pData, bufferListSrcArray[bufferNum].pBuffers->pData, SAMPLE_MAX_BUFF)) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_ERR("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } } if (checksum == dcResults.checksum) { PRINT_DBG("Checksums match after compression and decompression\n"); } else { PRINT_ERR("Checksums does not match after compression and " "decompression\n"); status = CPA_STATUS_FAIL; } } for (bufferNum = 0; bufferNum < numBuffers; bufferNum++) { PHYS_CONTIG_FREE(bufferListSrcArray[bufferNum].pPrivateMetaData); PHYS_CONTIG_FREE(bufferListDstArray[bufferNum].pPrivateMetaData); PHYS_CONTIG_FREE(bufferListDstArray2[bufferNum].pPrivateMetaData); if (bufferListSrcArray[bufferNum].pBuffers != NULL) { PHYS_CONTIG_FREE(bufferListSrcArray[bufferNum].pBuffers->pData); OS_FREE(bufferListSrcArray[bufferNum].pBuffers); } if (bufferListDstArray[bufferNum].pBuffers != NULL) { PHYS_CONTIG_FREE(bufferListDstArray[bufferNum].pBuffers->pData); OS_FREE(bufferListDstArray[bufferNum].pBuffers); } if (bufferListDstArray2[bufferNum].pBuffers != NULL) { PHYS_CONTIG_FREE(bufferListDstArray2[bufferNum].pBuffers->pData); OS_FREE(bufferListDstArray2[bufferNum].pBuffers); } } COMPLETION_DESTROY(&complete); return status; } /* * This is the main entry point for the sample data compression code. * demonstrates the sequence of calls to be made to the API in order * to create a session, perform one or more stateless compression operations, * and then tear down the session. */ CpaStatus dcStatelessSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaDcInstanceCapabilities cap = {0}; CpaBufferList **bufferInterArray = NULL; Cpa16U numInterBuffLists = 0; Cpa16U bufferNum = 0; Cpa32U buffMetaSize = 0; Cpa32U sess_size = 0; Cpa32U ctx_size = 0; CpaDcSessionHandle sessionHdl = NULL; CpaInstanceHandle dcInstHandle = NULL; CpaDcSessionSetupData sd = {0}; CpaDcStats dcStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a data compression service. */ sampleDcGetInstance(&dcInstHandle); if (dcInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Query Capabilities */ PRINT_DBG("cpaDcQueryCapabilities\n"); status = cpaDcQueryCapabilities(dcInstHandle, &cap); if (status != CPA_STATUS_SUCCESS) { return status; } if (!cap.statelessDeflateCompression || !cap.statelessDeflateDecompression || !cap.checksumAdler32 || !cap.dynamicHuffman) { PRINT_DBG("Error: Unsupported functionality\n"); return CPA_STATUS_FAIL; } if (cap.dynamicHuffmanBufferReq) { status = cpaDcBufferListGetMetaSize(dcInstHandle, 1, &buffMetaSize); if (CPA_STATUS_SUCCESS == status) { status = cpaDcGetNumIntermediateBuffers(dcInstHandle, &numInterBuffLists); } if (CPA_STATUS_SUCCESS == status && 0 != numInterBuffLists) { status = PHYS_CONTIG_ALLOC( &bufferInterArray, numInterBuffLists * sizeof(CpaBufferList *)); } for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum], sizeof(CpaBufferList)); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferInterArray[bufferNum]->pPrivateMetaData, buffMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum]->pBuffers, sizeof(CpaFlatBuffer)); } if (CPA_STATUS_SUCCESS == status) { /* Implementation requires an intermediate buffer approximately twice the size of the output buffer */ status = PHYS_CONTIG_ALLOC( &bufferInterArray[bufferNum]->pBuffers->pData, 2 * SAMPLE_MAX_BUFF); bufferInterArray[bufferNum]->numBuffers = 1; bufferInterArray[bufferNum]->pBuffers->dataLenInBytes = 2 * SAMPLE_MAX_BUFF; } } /* End numInterBuffLists */ } if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaDcSetAddressTranslation(dcInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* Start DataCompression component */ PRINT_DBG("cpaDcStartInstance\n"); status = cpaDcStartInstance( dcInstHandle, numInterBuffLists, bufferInterArray); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependant. */ sampleDcStartPolling(dcInstHandle); /* * We now populate the fields of the session operational data and create * the session. Note that the size required to store a session is * implementation-dependent, so we query the API first to determine how * much memory to allocate, and then allocate that memory. */ sd.compLevel = CPA_DC_L4; sd.compType = CPA_DC_DEFLATE; sd.huffType = huffmanType_g; /* If the implementation supports it, the session will be configured * to select static Huffman encoding over dynamic Huffman as * the static encoding will provide better compressibility. */ if (cap.autoSelectBestHuffmanTree) { #if DC_API_VERSION_AT_LEAST(3, 1) sd.autoSelectBestHuffmanTree = CPA_DC_ASB_ENABLED; #else sd.autoSelectBestHuffmanTree = CPA_DC_ASB_STATIC_DYNAMIC; #endif } else { sd.autoSelectBestHuffmanTree = CPA_DC_ASB_DISABLED; } sd.sessDirection = CPA_DC_DIR_COMBINED; sd.sessState = CPA_DC_STATELESS; #if (CPA_DC_API_VERSION_NUM_MAJOR == 1 && CPA_DC_API_VERSION_NUM_MINOR < 6) sd.deflateWindowSize = 7; #endif sd.checksum = CPA_DC_CRC32; /* Determine size of session context to allocate */ PRINT_DBG("cpaDcGetSessionSize\n"); status = cpaDcGetSessionSize(dcInstHandle, &sd, &sess_size, &ctx_size); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session memory */ status = PHYS_CONTIG_ALLOC(&sessionHdl, sess_size); } /* Initialize the Stateless session */ if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaDcInitSession\n"); status = cpaDcInitSession( dcInstHandle, sessionHdl, /* session memory */ &sd, /* session setup data */ NULL, /* pContexBuffer not required for stateless operations */ dcCallback); /* callback function */ } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform Compression operation */ status = compPerformOp(dcInstHandle, sessionHdl, sd); /* * In a typical usage, the session might be used to compression * multiple buffers. In this example however, we can now * tear down the session. */ PRINT_DBG("cpaDcRemoveSession\n"); sessionStatus = cpaDcRemoveSession(dcInstHandle, sessionHdl); /* Maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* * We can now query the statistics on the instance. * * Note that some implementations may also make the stats * available through other mechanisms, e.g. in the /proc * virtual filesystem. */ status = cpaDcGetStats(dcInstHandle, &dcStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetStats failed, status = %d\n", status); } else { PRINT_DBG("Number of compression operations completed: %llu\n", (unsigned long long)dcStats.numCompCompleted); PRINT_DBG("Number of decompression operations completed: %llu\n", (unsigned long long)dcStats.numDecompCompleted); } } /* * Free up memory, stop the instance, etc. */ /* Stop the polling thread */ sampleDcStopPolling(); PRINT_DBG("cpaDcStopInstance\n"); cpaDcStopInstance(dcInstHandle); /* Free session Context */ PHYS_CONTIG_FREE(sessionHdl); /* Free intermediate buffer */ if (bufferInterArray != NULL) { for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers->pData); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pPrivateMetaData); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]); } PHYS_CONTIG_FREE(bufferInterArray); } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/000077500000000000000000000000001503624047500332645ustar00rootroot00000000000000cpa_dc_sample_user.c000066400000000000000000000101321503624047500371560ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_dc_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus dcStatelessSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Stateless Compression Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = dcStatelessSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nStateless Compression Sample Code App failed\n"); } else { PRINT_DBG("\nStateless Compression Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } cpa_dc_stateless_sample.c000066400000000000000000000660511503624047500402220ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/dc/stateless_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the data compression API, * and specifically using this API to statelessly compress an input buffer. It * will compress the data using deflate with dynamic huffman trees. */ #include "cpa.h" #include "cpa_dc.h" #include "cpa_sample_utils.h" extern int gDebugParam; #define SAMPLE_MAX_BUFF 1024 #define TIMEOUT_MS 5000 /* 5 seconds */ #define SINGLE_INTER_BUFFLIST 1 static Cpa8U sampleData[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4a, 0xcb, 0xbb, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xDE, 0xAD, 0xEE, 0xEE, 0xDE, 0xAD, 0xBB, 0xBF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xEF, 0xEF, 0xEF, 0x34, 0x53, 0x84, 0x68, 0x76, 0x34, 0x65, 0x36, 0x45, 0x64, 0xab, 0xd5, 0x27, 0x4A, 0xCB, 0xBB}; /* ***************************************************************************** * Forward declaration ***************************************************************************** */ CpaStatus dcStatelessSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a packet, etc. In this example, the function only sets the * complete variable to indicate it has been called. */ // static void dcCallback(void *pCallbackTag, CpaStatus status) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /* indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } // /* * This function performs a compression and decompress operation. */ static CpaStatus compPerformOp(CpaInstanceHandle dcInstHandle, CpaDcSessionHandle sessionHdl, CpaDcHuffType huffType) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMetaSrc = NULL; Cpa8U *pBufferMetaDst = NULL; Cpa8U *pBufferMetaDst2 = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferListSrc = NULL; CpaBufferList *pBufferListDst = NULL; CpaBufferList *pBufferListDst2 = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaDcOpData opData = {}; Cpa32U bufferSize = sizeof(sampleData); Cpa32U dstBufferSize = bufferSize; Cpa32U checksum = 0; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pDstBuffer = NULL; Cpa8U *pDst2Buffer = NULL; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ CpaDcRqResults dcResults; struct COMPLETION_STRUCT complete; INIT_OPDATA(&opData, CPA_DC_FLUSH_FINAL); /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); PRINT_DBG("cpaDcBufferListGetMetaSize\n"); /* * Different implementations of the API require different * amounts of space to store meta-data associated with buffer * lists. We query the API to find out how much space the current * implementation needs, and then allocate space for the buffer * meta data, the buffer list, and for the buffer itself. */ // status = cpaDcBufferListGetMetaSize(dcInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcBufferListGetMetaSize failed. (status = %d)\n", status); } /* Destination buffer size is set as sizeof(sampelData) for a * Deflate compression operation with DC_API_VERSION < 2.5. * cpaDcDeflateCompressBound API is used to get maximum output buffer size * for a Deflate compression operation with DC_API_VERSION >= 2.5 */ #if DC_API_VERSION_AT_LEAST(2, 5) status = cpaDcDeflateCompressBound( dcInstHandle, huffType, bufferSize, &dstBufferSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcDeflateCompressBound API failed. (status = %d)\n", status); return CPA_STATUS_FAIL; } #endif /* Allocate source buffer */ if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMetaSrc, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferListSrc, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } /* Allocate destination buffer the same size as source buffer */ if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMetaDst, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferListDst, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pDstBuffer, dstBufferSize); } // if (CPA_STATUS_SUCCESS == status) { /* copy source into buffer */ memcpy(pSrcBuffer, sampleData, sizeof(sampleData)); /* Build source bufferList */ pFlatBuffer = (CpaFlatBuffer *)(pBufferListSrc + 1); pBufferListSrc->pBuffers = pFlatBuffer; pBufferListSrc->numBuffers = 1; pBufferListSrc->pPrivateMetaData = pBufferMetaSrc; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; /* Build destination bufferList */ pFlatBuffer = (CpaFlatBuffer *)(pBufferListDst + 1); pBufferListDst->pBuffers = pFlatBuffer; pBufferListDst->numBuffers = 1; pBufferListDst->pPrivateMetaData = pBufferMetaDst; pFlatBuffer->dataLenInBytes = dstBufferSize; pFlatBuffer->pData = pDstBuffer; PRINT_DBG("cpaDcCompressData2\n"); // status = cpaDcCompressData2( dcInstHandle, sessionHdl, pBufferListSrc, /* source buffer list */ pBufferListDst, /* destination buffer list */ &opData, /* Operational data */ &dcResults, /* results structure */ (void *)&complete); /* data sent as is to the callback function*/ // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcCompressData2 failed. (status = %d)\n", status); } /* * We now wait until the completion of the operation. This uses a macro * which can be defined differently for different OSes. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaDcCompressData2\n"); status = CPA_STATUS_FAIL; } } /* * We now check the results */ if (CPA_STATUS_SUCCESS == status) { if (dcResults.status != CPA_DC_OK) { PRINT_ERR("Results status not as expected (status = %d)\n", dcResults.status); status = CPA_STATUS_FAIL; } else { PRINT_DBG("Data consumed %d\n", dcResults.consumed); PRINT_DBG("Data produced %d\n", dcResults.produced); PRINT_DBG("Adler checksum 0x%x\n", dcResults.checksum); } /* To compare the checksum with decompressed output */ checksum = dcResults.checksum; } } /* * We now ensure we can decompress to the original buffer. */ if (CPA_STATUS_SUCCESS == status) { /* Dst is now the Src buffer - update the length with amount of compressed data added to the buffer */ pBufferListDst->pBuffers->dataLenInBytes = dcResults.produced; /* Allocate memory for new destination bufferList Dst2, we can use * stateless decompression here because in this scenario we know * that all transmitted data before compress was less than some * max size */ if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMetaDst2, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferListDst2, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pDst2Buffer, SAMPLE_MAX_BUFF); } if (CPA_STATUS_SUCCESS == status) { /* Build destination 2 bufferList */ pFlatBuffer = (CpaFlatBuffer *)(pBufferListDst2 + 1); pBufferListDst2->pBuffers = pFlatBuffer; pBufferListDst2->numBuffers = 1; pBufferListDst2->pPrivateMetaData = pBufferMetaDst2; pFlatBuffer->dataLenInBytes = SAMPLE_MAX_BUFF; pFlatBuffer->pData = pDst2Buffer; PRINT_DBG("cpaDcDecompressData2\n"); // status = cpaDcDecompressData2( dcInstHandle, sessionHdl, pBufferListDst, /* source buffer list */ pBufferListDst2, /* destination buffer list */ &opData, &dcResults, /* results structure */ (void *)&complete); /* data sent as is to the callback function*/ // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcDecompressData2 failed. (status = %d)\n", status); } /* * We now wait until the completion of the operation. This uses a * macro * which can be defined differently for different OSes. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR( "timeout or interruption in cpaDcDecompressData2\n"); status = CPA_STATUS_FAIL; } } /* * We now check the results */ if (CPA_STATUS_SUCCESS == status) { if (dcResults.status != CPA_DC_OK) { PRINT_ERR( "Results status not as expected decomp (status = %d)\n", dcResults.status); status = CPA_STATUS_FAIL; } else { PRINT_DBG("Data consumed %d\n", dcResults.consumed); PRINT_DBG("Data produced %d\n", dcResults.produced); PRINT_DBG("Adler checksum 0x%x\n", dcResults.checksum); } /* Compare with original Src buffer */ if (0 == memcmp(pDst2Buffer, pSrcBuffer, sizeof(sampleData))) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_ERR("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } if (checksum == dcResults.checksum) { PRINT_DBG("Checksums match after compression and " "decompression\n"); } else { PRINT_ERR("Checksums does not match after compression and " "decompression\n"); status = CPA_STATUS_FAIL; } } } } /* * At this stage, the callback function has returned, so it is * sure that the structures won't be needed any more. Free the * memory! */ PHYS_CONTIG_FREE(pSrcBuffer); OS_FREE(pBufferListSrc); PHYS_CONTIG_FREE(pBufferMetaSrc); PHYS_CONTIG_FREE(pDstBuffer); OS_FREE(pBufferListDst); PHYS_CONTIG_FREE(pBufferMetaDst); PHYS_CONTIG_FREE(pDst2Buffer); OS_FREE(pBufferListDst2); PHYS_CONTIG_FREE(pBufferMetaDst2); COMPLETION_DESTROY(&complete); return status; } /* * This is the main entry point for the sample data compression code. * demonstrates the sequence of calls to be made to the API in order * to create a session, perform one or more stateless compression operations, * and then tear down the session. */ CpaStatus dcStatelessSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaDcInstanceCapabilities cap = {0}; CpaBufferList **bufferInterArray = NULL; Cpa16U numInterBuffLists = 0; Cpa16U bufferNum = 0; Cpa32U buffMetaSize = 0; Cpa32U sess_size = 0; Cpa32U ctx_size = 0; CpaDcSessionHandle sessionHdl = NULL; CpaInstanceHandle dcInstHandle = NULL; CpaDcSessionSetupData sd = {0}; CpaDcStats dcStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a data compression service. */ sampleDcGetInstance(&dcInstHandle); if (dcInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Query Capabilities */ PRINT_DBG("cpaDcQueryCapabilities\n"); // status = cpaDcQueryCapabilities(dcInstHandle, &cap); if (status != CPA_STATUS_SUCCESS) { return status; } if (!cap.statelessDeflateCompression || !cap.statelessDeflateDecompression || !cap.checksumAdler32 || !cap.dynamicHuffman) { PRINT_DBG("Error: Unsupported functionality\n"); return CPA_STATUS_FAIL; } if (cap.dynamicHuffmanBufferReq) { status = cpaDcBufferListGetMetaSize(dcInstHandle, 1, &buffMetaSize); if (CPA_STATUS_SUCCESS == status) { status = cpaDcGetNumIntermediateBuffers(dcInstHandle, &numInterBuffLists); } if (CPA_STATUS_SUCCESS == status && 0 != numInterBuffLists) { status = PHYS_CONTIG_ALLOC( &bufferInterArray, numInterBuffLists * sizeof(CpaBufferList *)); } for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum], sizeof(CpaBufferList)); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC( &bufferInterArray[bufferNum]->pPrivateMetaData, buffMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&bufferInterArray[bufferNum]->pBuffers, sizeof(CpaFlatBuffer)); } if (CPA_STATUS_SUCCESS == status) { /* Implementation requires an intermediate buffer approximately twice the size of the output buffer */ status = PHYS_CONTIG_ALLOC( &bufferInterArray[bufferNum]->pBuffers->pData, 2 * SAMPLE_MAX_BUFF); bufferInterArray[bufferNum]->numBuffers = 1; bufferInterArray[bufferNum]->pBuffers->dataLenInBytes = 2 * SAMPLE_MAX_BUFF; } } /* End numInterBuffLists */ } if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaDcSetAddressTranslation(dcInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* Start DataCompression component */ PRINT_DBG("cpaDcStartInstance\n"); status = cpaDcStartInstance( dcInstHandle, numInterBuffLists, bufferInterArray); } // if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleDcStartPolling(dcInstHandle); /* * We now populate the fields of the session operational data and create * the session. Note that the size required to store a session is * implementation-dependent, so we query the API first to determine how * much memory to allocate, and then allocate that memory. */ // sd.compLevel = CPA_DC_L4; sd.compType = CPA_DC_DEFLATE; sd.huffType = huffmanType_g; /* If the implementation supports it, the session will be configured * to select static Huffman encoding over dynamic Huffman as * the static encoding will provide better compressibility. */ if (cap.autoSelectBestHuffmanTree) { #if DC_API_VERSION_AT_LEAST(3, 1) sd.autoSelectBestHuffmanTree = CPA_DC_ASB_ENABLED; #else sd.autoSelectBestHuffmanTree = CPA_DC_ASB_STATIC_DYNAMIC; #endif } else { sd.autoSelectBestHuffmanTree = CPA_DC_ASB_DISABLED; } sd.sessDirection = CPA_DC_DIR_COMBINED; sd.sessState = CPA_DC_STATELESS; #if (CPA_DC_API_VERSION_NUM_MAJOR == 1 && CPA_DC_API_VERSION_NUM_MINOR < 6) sd.deflateWindowSize = 7; #endif sd.checksum = CPA_DC_ADLER32; /* Determine size of session context to allocate */ PRINT_DBG("cpaDcGetSessionSize\n"); status = cpaDcGetSessionSize(dcInstHandle, &sd, &sess_size, &ctx_size); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session memory */ status = PHYS_CONTIG_ALLOC(&sessionHdl, sess_size); } /* Initialize the Stateless session */ if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaDcInitSession\n"); status = cpaDcInitSession( dcInstHandle, sessionHdl, /* session memory */ &sd, /* session setup data */ NULL, /* pContexBuffer not required for stateless operations */ dcCallback); /* callback function */ } // if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform Compression operation */ status = compPerformOp(dcInstHandle, sessionHdl, sd.huffType); /* * In a typical usage, the session might be used to compression * multiple buffers. In this example however, we can now * tear down the session. */ PRINT_DBG("cpaDcRemoveSession\n"); // sessionStatus = cpaDcRemoveSession(dcInstHandle, sessionHdl); // /* Maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* * We can now query the statistics on the instance. * * Note that some implementations may also make the stats * available through other mechanisms, e.g. in the /proc * virtual filesystem. */ status = cpaDcGetStats(dcInstHandle, &dcStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetStats failed, status = %d\n", status); } else { PRINT_DBG("Number of compression operations completed: %llu\n", (unsigned long long)dcStats.numCompCompleted); PRINT_DBG("Number of decompression operations completed: %llu\n", (unsigned long long)dcStats.numDecompCompleted); } } /* * Free up memory, stop the instance, etc. */ /* Stop the polling thread */ sampleDcStopPolling(); PRINT_DBG("cpaDcStopInstance\n"); cpaDcStopInstance(dcInstHandle); /* Free session Context */ PHYS_CONTIG_FREE(sessionHdl); /* Free intermediate buffers */ if (bufferInterArray != NULL) { for (bufferNum = 0; bufferNum < numInterBuffLists; bufferNum++) { PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers->pData); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pBuffers); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]->pPrivateMetaData); PHYS_CONTIG_FREE(bufferInterArray[bufferNum]); } PHYS_CONTIG_FREE(bufferInterArray); } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/include/000077500000000000000000000000001503624047500307515ustar00rootroot00000000000000cpa_sample_cnv_utils.h000066400000000000000000000222151503624047500352370ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/include/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qat_compression_cnv_utils.h * * @defgroup compression * * @ingroup compression * * @description * Functions types and macros to determine CnV-E environment * Helper functions and macros to set the CnV flag in API * * ***************************************************************************/ #ifndef QAT_SAMPLE_CNV_UTILS_H_ #define QAT_SAMPLE_CNV_UTILS_H_ /* Common macro definitions */ #ifndef DC_API_VERSION_AT_LEAST #define DC_API_VERSION_AT_LEAST(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR > major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR >= minor)) #endif /* CNV with Recovery mode capability is present in DC API version 2.2 * and higher. */ #if DC_API_VERSION_AT_LEAST(2, 2) #define CNV(x) (x)->compressAndVerify #define SET_CNV(x, v) (CNV(x) = (v)) #define CNV_RECOVERY(x) (x)->compressAndVerifyAndRecover #define SET_CNV_RECOVERY(x, v) (CNV_RECOVERY(x) = v) #else #define CNV(x) CPA_FALSE #define SET_CNV(x, v) #define CNV_RECOVERY(x) CPA_FALSE #define SET_CNV_RECOVERY(x, v) #endif #define INIT_OPDATA(x, flag) \ do \ { \ (x)->flushFlag = (flag); \ SET_CNV(x, getCnVFlag()); \ SET_CNV_RECOVERY(x, getCnVnRFlag()); \ (x)->inputSkipData.skipMode = CPA_DC_SKIP_DISABLED; \ (x)->outputSkipData.skipMode = CPA_DC_SKIP_DISABLED; \ } while (0) #define INIT_DC_DP_CNV_OPDATA(x) \ do \ { \ SET_CNV(x, getCnVFlag()); \ SET_CNV_RECOVERY(x, getCnVnRFlag()); \ } while (0) static CpaBoolean getCnVFlag(void) __attribute__((unused)); static CpaBoolean getCnVnRFlag(void) __attribute__((unused)); static const char *getSampleCnVModeStr(void) __attribute__((unused)); static void getCnvFlagInternal(CpaBoolean *cnv, CpaBoolean *cnvnr); static void EvaluateSampleCnVFlag(const CpaDcInstanceCapabilities *const cap, CpaBoolean *cnv, CpaBoolean *cnvnr); static CpaStatus getSampleDcCapabilities( CpaDcInstanceCapabilities *capabilities); static CpaBoolean getCnVFlag(void) { static CpaBoolean cnvOpFlag; static CpaBoolean initialised = CPA_FALSE; if (initialised == CPA_FALSE) { getCnvFlagInternal(&cnvOpFlag, NULL); initialised = CPA_TRUE; } return cnvOpFlag; } static CpaBoolean getCnVnRFlag(void) { static CpaBoolean cnvnrOpFlag; static CpaBoolean initialised = CPA_FALSE; if (initialised == CPA_FALSE) { getCnvFlagInternal(NULL, &cnvnrOpFlag); initialised = CPA_TRUE; } return cnvnrOpFlag; } static const char *getSampleCnVModeStr(void) { static const char *cmpWithVer = "Compression with Verification"; static const char *cmpOnly = "Compression Only"; return (getCnVFlag() == CPA_TRUE ? cmpWithVer : cmpOnly); } static void getCnvFlagInternal(CpaBoolean *cnv, CpaBoolean *cnvnr) { CpaDcInstanceCapabilities cap = {0}; if (getSampleDcCapabilities(&cap) != CPA_STATUS_SUCCESS) { return EvaluateSampleCnVFlag(NULL, cnv, cnvnr); } return EvaluateSampleCnVFlag(&cap, cnv, cnvnr); } static void EvaluateSampleCnVFlag(const CpaDcInstanceCapabilities *const cap, CpaBoolean *cnv, CpaBoolean *cnvnr) { CpaBoolean fw_cnv_capable = CPA_FALSE; CpaBoolean cnv_loose_mode = CPA_FALSE; CpaBoolean cnvOpFlag = CPA_FALSE; CpaBoolean cnvnrOpFlag = CPA_FALSE; /* When capabilities are known, fill in the queried values */ if (cap != NULL) { fw_cnv_capable = CNV(cap); /* CNV mode capabilities is present in DC API version 2.1 and above */ #if DC_API_VERSION_AT_LEAST(2, 1) cnv_loose_mode = (cap->compressAndVerifyStrict != CPA_TRUE) ? CPA_TRUE : CPA_FALSE; #endif cnvnrOpFlag = CNV_RECOVERY(cap); } /* Determine the value of CompressAndVerify flag used by DP and * Traditional API depending on the FW CNV capability and CNV mode * of operation. The API will accept the submission of payload only * if this flag value is correct for the combination. * FW-CNV-CAPABLE MODE PERMITTED-OPERATION CNVFLAG * Y S CompressWithVerify CPA_TRUE * Y L Compress only CPA_FALSE * N S NONE NA * N L Compress only CPA_FALSE */ if (fw_cnv_capable == CPA_TRUE) { cnvOpFlag = (cnv_loose_mode == CPA_FALSE) ? CPA_TRUE : CPA_FALSE; } else { cnvOpFlag = CPA_FALSE; } /* CNV Recovery only possible when * CNV is enabled/present. */ if (cnvOpFlag == CPA_FALSE) { cnvnrOpFlag = CPA_FALSE; } if (cnv != NULL) *cnv = cnvOpFlag; if (cnvnr != NULL) *cnvnr = cnvnrOpFlag; return; } static CpaStatus getSampleDcCapabilities( CpaDcInstanceCapabilities *capabilities) { CpaStatus status; CpaInstanceHandle instHandle; Cpa16U numInstances = 0; /* Get the number of instances */ status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) return CPA_STATUS_FAIL; if (numInstances == 0) return CPA_STATUS_FAIL; status = cpaDcGetInstances(1, &instHandle); if (status != CPA_STATUS_SUCCESS) return CPA_STATUS_FAIL; status = cpaDcQueryCapabilities(instHandle, capabilities); if (CPA_STATUS_SUCCESS != status) return CPA_STATUS_FAIL; return CPA_STATUS_SUCCESS; } #endif /* QAT_SAMPLE_CNV_UTILS_H_ */ cpa_sample_utils.h000066400000000000000000000514461503624047500344010ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/include/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_utils.h * * @defgroup sampleUtils Macro and inline function definitions * * @ingroup sampleCode * * @description * Defines macros for printing and debugging, inline functions for memory * allocating and freeing and thread creation * ***************************************************************************/ #ifndef CPA_SAMPLE_UTILS_H #define CPA_SAMPLE_UTILS_H #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_dc.h" #ifdef DO_CRYPTO #include "cpa_cy_sym.h" #endif #include "cpa_sample_cnv_utils.h" #ifdef USER_SPACE /* User space utils */ #include #include #include #include #include #include /* Performance sample code mem utils */ #include "qae_mem.h" extern CpaDcHuffType huffmanType_g; extern CpaStatus qaeMemInit(void); extern void qaeMemDestroy(void); /* Threads */ typedef pthread_t sampleThread; /* Check for CY API version */ #define CY_API_VERSION_AT_LEAST(major, minor) \ (CPA_CY_API_VERSION_NUM_MAJOR > major || \ (CPA_CY_API_VERSION_NUM_MAJOR == major && \ CPA_CY_API_VERSION_NUM_MINOR >= minor)) /* Printing */ /**< Prints the name of the function and the arguments only if gDebugParam is * CPA_TRUE. */ #define PRINT_DBG(args...) \ do \ { \ if (CPA_TRUE == gDebugParam) \ { \ printf("%s(): ", __func__); \ printf(args); \ fflush(stdout); \ } \ } while (0) /**< Prints the arguments */ #ifndef PRINT #define PRINT(args...) \ do \ { \ printf(args); \ } while (0) #endif /**< Prints the name of the function and the arguments */ #ifndef PRINT_ERR #define PRINT_ERR(args...) \ do \ { \ printf("%s(): ", __func__); \ printf(args); \ } while (0) #endif /** ******************************************************************************* * @ingroup sampleUtils * Completion definitions * ******************************************************************************/ struct completion_struct { sem_t semaphore; }; /* Use semaphores to signal completion of events */ #define COMPLETION_STRUCT completion_struct #define COMPLETION_INIT(s) sem_init(&((s)->semaphore), 0, 0); #define COMPLETION_WAIT(s, timeout) (sem_wait(&((s)->semaphore)) == 0) #define COMPLETE(s) sem_post(&((s)->semaphore)) #define COMPLETION_DESTROY(s) sem_destroy(&((s)->semaphore)) #else /* Kernel space utils */ /* Kernel space utils */ #include #include #include #include #include #include #include #ifdef __x86_64__ #define SAMPLE_ADDR_LEN uint64_t #else #define SAMPLE_ADDR_LEN uint32_t #endif extern CpaDcHuffType huffmanType_g; /* Threads */ typedef struct task_struct *sampleThread; /* Check for CY API version */ #define CY_API_VERSION_AT_LEAST(major, minor) \ (CPA_CY_API_VERSION_NUM_MAJOR > major || \ (CPA_CY_API_VERSION_NUM_MAJOR == major && \ CPA_CY_API_VERSION_NUM_MINOR >= minor)) /* Printing */ /**< Prints the name of the function and the arguments only if gDebugParam is * CPA_TRUE. */ #define PRINT_DBG(args...) \ do \ { \ if (CPA_TRUE == gDebugParam) \ { \ printk("%s(): ", __func__); \ printk(KERN_CONT args); \ } \ } while (0) /**< Regular prints */ #ifndef PRINT #define PRINT(args...) \ do \ { \ printk(KERN_CONT args); \ } while (0) #endif /**< Prints the name of the function and the arguments */ #ifndef PRINT_ERR #define PRINT_ERR(args...) \ do \ { \ printk("%s(): ", __func__); \ printk(KERN_CONT args); \ } while (0) #endif /** ******************************************************************************* * @ingroup sampleUtils * Completion definitions * ******************************************************************************/ #define COMPLETION_STRUCT completion #define COMPLETION_INIT(c) init_completion(c) #define COMPLETION_WAIT(c, timeout) \ wait_for_completion_interruptible_timeout(c, timeout) #define COMPLETE(c) complete(c) #define COMPLETION_DESTROY(s) #endif #ifndef BYTE_ALIGNMENT_8 #define BYTE_ALIGNMENT_8 (8) #endif #ifndef BYTE_ALIGNMENT_64 #define BYTE_ALIGNMENT_64 (64) #endif /** ******************************************************************************* * @ingroup sampleUtils * This function and associated macro sleeps for ms milliseconds * * @param[in] ms sleep time in ms * * @retval none * ******************************************************************************/ static __inline CpaStatus sampleSleep(Cpa32U ms) { #ifdef USER_SPACE int ret = 0; struct timespec resTime, remTime; resTime.tv_sec = ms / 1000; resTime.tv_nsec = (ms % 1000) * 1000000; do { ret = nanosleep(&resTime, &remTime); resTime = remTime; } while ((ret != 0) && (errno == EINTR)); if (ret != 0) { PRINT_ERR("nanoSleep failed with code %d\n", ret); return CPA_STATUS_FAIL; } else { return CPA_STATUS_SUCCESS; } #else if (ms != 0) { set_current_state((long)TASK_INTERRUPTIBLE); schedule_timeout((ms * HZ) / 1000); } else { schedule(); } return CPA_STATUS_SUCCESS; #endif } /** ******************************************************************************* * @ingroup sampleUtils * Macro from the sampleSleep function * ******************************************************************************/ #define OS_SLEEP(ms) sampleSleep((ms)) /** ******************************************************************************* * @ingroup sampleUtils * This function and associated macro allocates the memory for the given * size and stores the address of the memory allocated in the pointer. * Memory allocated by this function is NOT guaranteed to be physically * contiguous. * * @param[out] ppMemAddr address of pointer where address will be stored * @param[in] sizeBytes the size of the memory to be allocated * * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory * @retval CPA_STATUS_SUCCESS Macro executed successfully * ******************************************************************************/ static __inline CpaStatus Mem_OsMemAlloc(void **ppMemAddr, Cpa32U sizeBytes) { #ifdef USER_SPACE *ppMemAddr = malloc(sizeBytes); if (NULL == *ppMemAddr) { return CPA_STATUS_RESOURCE; } return CPA_STATUS_SUCCESS; #else *ppMemAddr = kmalloc(sizeBytes, GFP_KERNEL); if (NULL == *ppMemAddr) { return CPA_STATUS_RESOURCE; } return CPA_STATUS_SUCCESS; #endif } /** ******************************************************************************* * @ingroup sampleUtils * This function and associated macro allocates the memory for the given * size for the given alignment and stores the address of the memory * allocated in the pointer. Memory allocated by this function is * guaranteed to be physically contiguous. * * @param[out] ppMemAddr address of pointer where address will be stored * @param[in] sizeBytes the size of the memory to be allocated * @param[in] alignment the alignment of the memory to be allocated *(non-zero) * * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory * @retval CPA_STATUS_SUCCESS Macro executed successfully * ******************************************************************************/ static __inline CpaStatus Mem_Alloc_Contig(void **ppMemAddr, Cpa32U sizeBytes, Cpa32U alignment) { #ifdef USER_SPACE /* Use perf sample code memory allocator */ /* In this sample all allocations are done from node=0 * This might not be optimal in a dual processor system. */ *ppMemAddr = qaeMemAllocNUMA(sizeBytes, 0, alignment); if (NULL == *ppMemAddr) { PRINT_ERR("Memory allocation Failed"); return CPA_STATUS_RESOURCE; } return CPA_STATUS_SUCCESS; #else void *pAlloc = NULL; uint32_t align = 0; pAlloc = kmalloc_node((sizeBytes + alignment + sizeof(void *)), GFP_KERNEL, 0); if (NULL == pAlloc) { return CPA_STATUS_RESOURCE; } *ppMemAddr = (Cpa8U *)pAlloc + sizeof(void *); align = ((SAMPLE_ADDR_LEN)(*ppMemAddr)) % alignment; *ppMemAddr = (Cpa8U *)*ppMemAddr + (alignment - align); *(SAMPLE_ADDR_LEN *)((Cpa8U *)*ppMemAddr - sizeof(void *)) = (SAMPLE_ADDR_LEN)pAlloc; return CPA_STATUS_SUCCESS; #endif } /** ******************************************************************************* * @ingroup sampleUtils * Macro from the Mem_OsMemAlloc function * ******************************************************************************/ #define OS_MALLOC(ppMemAddr, sizeBytes) \ Mem_OsMemAlloc((void *)(ppMemAddr), (sizeBytes)) /** ******************************************************************************* * @ingroup sampleUtils * Macro from the Mem_Alloc_Contig function * ******************************************************************************/ #define PHYS_CONTIG_ALLOC(ppMemAddr, sizeBytes) \ Mem_Alloc_Contig((void *)(ppMemAddr), (sizeBytes), 1) /** ******************************************************************************* * @ingroup sampleUtils * Aligned version of PHYS_CONTIG_ALLOC() macro * ******************************************************************************/ #define PHYS_CONTIG_ALLOC_ALIGNED(ppMemAddr, sizeBytes, alignment) \ Mem_Alloc_Contig((void *)(ppMemAddr), (sizeBytes), (alignment)) /** ******************************************************************************* * @ingroup sampleUtils * This function and associated macro frees the memory at the given address * and resets the pointer to NULL. The memory must have been allocated by * the function Mem_OsMemAlloc() * * @param[out] ppMemAddr address of pointer where mem address is stored. * If pointer is NULL, the function will exit silently * * @retval void * ******************************************************************************/ static __inline void Mem_OsMemFree(void **ppMemAddr) { #ifdef USER_SPACE if (NULL != *ppMemAddr) { free(*ppMemAddr); *ppMemAddr = NULL; } #else if (NULL != *ppMemAddr) { kfree(*ppMemAddr); *ppMemAddr = NULL; } #endif } /** ******************************************************************************* * @ingroup sampleUtils * This function and associated macro frees the memory at the given address * and resets the pointer to NULL. The memory must have been allocated by * the function Mem_Alloc_Contig(). * * @param[out] ppMemAddr address of pointer where mem address is stored. * If pointer is NULL, the function will exit silently * * @retval void * ******************************************************************************/ static __inline void Mem_Free_Contig(void **ppMemAddr) { #ifdef USER_SPACE if (NULL != *ppMemAddr) { qaeMemFreeNUMA(ppMemAddr); *ppMemAddr = NULL; } #else void *pAlloc = NULL; if (NULL != *ppMemAddr) { pAlloc = (void *)(*( (SAMPLE_ADDR_LEN *)((Cpa8U *)*ppMemAddr - sizeof(void *)))); kfree(pAlloc); *ppMemAddr = NULL; } #endif } /** ******************************************************************************* * @ingroup sampleUtils * Macro from the Mem_OsMemFree function * ******************************************************************************/ #define OS_FREE(pMemAddr) Mem_OsMemFree((void *)&pMemAddr) /** ******************************************************************************* * @ingroup sampleUtils * Macro from the Mem_Free_Contig function * ******************************************************************************/ #define PHYS_CONTIG_FREE(pMemAddr) Mem_Free_Contig((void *)&pMemAddr) #define _4K_PAGE_SIZE (4 * 1024) /** ******************************************************************************* * @ingroup sampleUtils * This function returns the physical address for a given virtual address. * In case of error 0 is returned. * * @param[in] virtAddr Virtual address * * @retval CpaPhysicalAddr Physical address or 0 in case of error * ******************************************************************************/ static __inline CpaPhysicalAddr sampleVirtToPhys(void *virtAddr) { #ifdef USER_SPACE return (CpaPhysicalAddr)qaeVirtToPhysNUMA(virtAddr); #else return (CpaPhysicalAddr)virt_to_phys(virtAddr); #endif } /** ******************************************************************************* * @ingroup sampleUtils * This function creates a thread * ******************************************************************************/ static __inline CpaStatus sampleThreadCreate(sampleThread *thread, void *funct, void *args, CpaBoolean thread_auto_detach) { #ifdef USER_SPACE if (pthread_create(thread, NULL, funct, args) != 0) { PRINT_ERR("Failed create thread\n"); return CPA_STATUS_FAIL; } if (CPA_TRUE == thread_auto_detach) { pthread_detach(*thread); } return CPA_STATUS_SUCCESS; #else *thread = kthread_create(funct, args, "SAMPLE_THREAD"); wake_up_process(*thread); return CPA_STATUS_SUCCESS; #endif } static __inline CpaStatus sampleThreadJoin(sampleThread *thread) { #ifdef USER_SPACE if (pthread_join(*thread, NULL) != 0) { PRINT_ERR("Failed join thread\n"); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } static __inline void sampleThreadExit(void) { #ifdef USER_SPACE pthread_exit(NULL); #endif } #ifdef DO_CRYPTO void sampleAsymGetInstance(CpaInstanceHandle *pAsymInstHandle); void sampleSymGetInstance(CpaInstanceHandle *pSymInstHandle); void sampleCyGetInstance(CpaInstanceHandle *pCyInstHandle); void sampleCyStartPolling(CpaInstanceHandle cyInstHandle); void sampleCyStopPolling(void); void symSessionWaitForInflightReq(CpaCySymSessionCtx pSessionCtx); #endif // DO_CRYPTO void sampleDcGetInstance(CpaInstanceHandle *pDcInstHandle); void sampleDcStartPolling(CpaInstanceHandle dcInstHandle); void sampleDcStopPolling(void); Cpa64U sampleCoderdtsc(void); void hexLog(Cpa8U *pData, Cpa32U numBytes, const char *caption); #ifdef __x86_64__ #define SAMPLE_CODE_UINT Cpa64U #define SAMPLE_CODE_INT Cpa64S #else #define SAMPLE_CODE_UINT Cpa32U #define SAMPLE_CODE_INT Cpa32S #endif // __x86_64__ /** ***************************************************************************** * @ingroup sampleUtils * * convert virtual address of a buffer to address that can be accessed by * the owner of the instance from device point of view. * * @param[in] pVirtAddr virtual address of the buffer * @param[in] instance crypto instance handle * @param[in] type service type * * @retval CpaPhysicalAddr address from device point of view, * or NULL if failed to convert * ****************************************************************************/ CpaPhysicalAddr virtAddrToDevAddr(void *pVirtAddr, CpaInstanceHandle instance, CpaAccelerationServiceType type); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/000077500000000000000000000000001503624047500301365ustar00rootroot00000000000000alg_chaining_sample/000077500000000000000000000000001503624047500340235ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/symcpa_algchaining_sample.c000066400000000000000000000411601503624047500406210ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/alg_chaining_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a "chained" cipher and hash * operation. It encrypts some sample text using the AES-256 algorithm in * AES-GCM mode, and then performs an AES-GCM hash on the ciphertext. */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" #define AES_BLOCK_SIZE 16 #define DIGEST_LENGTH 16 #define TIMEOUT_MS 5000 /* 5 seconds*/ extern int gDebugParam; /* AES key, 128 bits long */ static Cpa8U sampleCipherKey[] = {0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08}; /* Initialization vector */ static Cpa8U sampleCipherIv[] = {0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88}; /* Source data to encrypt */ static Cpa8U sampleAlgChainingSrc[] = {0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39}; /* Additional Authentication Data */ static Cpa8U sampleAddAuthData[] = {0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2}; /* Expected output of the operation */ static Cpa8U expectedOutput[] = {0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, /* Digest */ 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47}; CpaStatus algChainSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a decrypted packet, etc. In this example, the function only * sets the complete variable to indicate it has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /** indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform an algorithm chaining operation (cipher + hash) */ static CpaStatus algChainPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = sizeof(sampleAlgChainingSrc) + DIGEST_LENGTH; Cpa32U aadBuffSize = 0; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pIvBuffer = NULL; Cpa8U *pAadBuffer = NULL; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); /* get meta information size */ PRINT_DBG("cpaCyBufferListGetMetaSize\n"); status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pIvBuffer, sizeof(sampleCipherIv)); } if (CPA_STATUS_SUCCESS == status) { /* Allocate memory for AAD. For GCM this memory will hold the * additional authentication data and any padding to ensure total * size is a multiple of the AES block size */ aadBuffSize = sizeof(sampleAddAuthData); if (aadBuffSize % AES_BLOCK_SIZE) { aadBuffSize += AES_BLOCK_SIZE - (aadBuffSize % AES_BLOCK_SIZE); } status = PHYS_CONTIG_ALLOC(&pAadBuffer, aadBuffSize); } if (CPA_STATUS_SUCCESS == status) { /* copy source into buffer */ memcpy(pSrcBuffer, sampleAlgChainingSrc, sizeof(sampleAlgChainingSrc)); /* copy IV into buffer */ memcpy(pIvBuffer, sampleCipherIv, sizeof(sampleCipherIv)); /* Copy AAD into buffer */ memcpy(pAadBuffer, sampleAddAuthData, sizeof(sampleAddAuthData)); /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { // /** Populate the structure containing the operational data that is * needed to run the algorithm */ pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = sizeof(sampleCipherIv); pOpData->cryptoStartSrcOffsetInBytes = 0; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToCipherInBytes = sizeof(sampleAlgChainingSrc); pOpData->messageLenToHashInBytes = sizeof(sampleAlgChainingSrc); pOpData->pAdditionalAuthData = pAadBuffer; // /* pDigestResult does need need to be set as digestIsAppended was set at sessionInit */ } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_DBG("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } } } /* at this stage, the callback function has returned, so it is sure that * the structures won't be needed any more*/ PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pIvBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pAadBuffer); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } CpaStatus algChainSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_GCM; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_GCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAddAuthData); sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleCipherKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = sizeof(sampleCipherKey); /* The resulting MAC is to be placed immediately after the ciphertext */ sessionSetupData.digestIsAppended = CPA_TRUE; sessionSetupData.verifyDigest = CPA_FALSE; // /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymSessionCtxGetSize\n"); status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymInitSession\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOp(cyInstHandle, sessionCtx); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (long long unsigned int)symStats.numSymOpCompleted); } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_algchaining_sample_user.c000066400000000000000000000100701503624047500416530ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/alg_chaining_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_algchaining_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus algChainSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Alg Chain Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = algChainSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nAlg Chain Sample Code App failed\n"); } else { PRINT_DBG("\nAlg Chain Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ccm_sample/000077500000000000000000000000001503624047500322415ustar00rootroot00000000000000cpa_ccm_sample.c000066400000000000000000000501121503624047500352530ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ccm_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a CCM operation. For more information * on CCM please reference NIST publication SP800-38C "Recommendation for Block * Cipher Modes of Operation: the CCM Mode for Authentication and * Confidentiality" */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" #define DIGEST_LENGTH 4 #define AES_BLOCK_SIZE 16 #define B0_BLOCK_SIZE 16 #define ALEN_ENCODING_SIZE 2 #define TIMEOUT_MS 5000 /* 5 seconds*/ #define GEN_ENCRYPT_DIR 0 #define DECRYPT_VERIFY_DIR 1 extern int gDebugParam; /* Test vector from NIST SP 800-38C Example 1 */ static Cpa8U sampleKey[] = {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}; static Cpa8U sampleNonce[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; static Cpa8U sampleAssocData[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; static Cpa8U samplePayload[] = {0x20, 0x21, 0x22, 0x23}; static Cpa8U expectedOutput[] = {0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d}; CpaStatus algChainSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a decrypted packet, etc. In this example, the function checks * verifyResult returned and sets the complete variable to indicate * it has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (CPA_FALSE == verifyResult) { PRINT_ERR("Error verifyResult failed\n"); } if (NULL != pCallbackTag) { /** indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform an algorithm chaining operation */ static CpaStatus algChainPerformOpCCM(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, int dir) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = sizeof(samplePayload) + DIGEST_LENGTH; Cpa32U aadBuffSize = 0; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pIvBuffer = NULL; Cpa8U *pAadBuffer = NULL; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; COMPLETION_INIT(&complete); // Initialize the completion variable /* get meta information size */ PRINT_DBG("cpaCyBufferListGetMetaSize\n"); status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; /* copy source into buffer */ if (GEN_ENCRYPT_DIR == dir) { memcpy(pSrcBuffer, samplePayload, sizeof(samplePayload)); } else { memcpy(pSrcBuffer, expectedOutput, sizeof(expectedOutput)); } // /* Allocate memory to store IV. For CCM this is the counter block * ctr0 (size equal to AES block size). The implementation will * construct the ctr0 block given the nonce. Space for ctr0 must be * allocated here */ status = PHYS_CONTIG_ALLOC(&pIvBuffer, AES_BLOCK_SIZE); } if (CPA_STATUS_SUCCESS == status) { /* Allocate memory for AAD. For CCM this memory will hold the 16 byte * B0 block, the 2 bytes encoded length of associated data, the * associated data itself and any padding to ensure total size is * a multiple of the AES block size */ aadBuffSize = B0_BLOCK_SIZE + ALEN_ENCODING_SIZE + sizeof(sampleAssocData); if (aadBuffSize % AES_BLOCK_SIZE) { aadBuffSize += AES_BLOCK_SIZE - (aadBuffSize % AES_BLOCK_SIZE); } status = PHYS_CONTIG_ALLOC(&pAadBuffer, aadBuffSize); } // if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { // pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; /* Even though the iv buffer is 16 bytes the ivLenInBytes * is set to the length of the nonce. For CCM valid lengths * are in the range 7-13 */ pOpData->ivLenInBytes = sizeof(sampleNonce); pOpData->cryptoStartSrcOffsetInBytes = 0; pOpData->messageLenToCipherInBytes = sizeof(samplePayload); /* Notice for CCM hash offset and length are not required */ pOpData->pAdditionalAuthData = pAadBuffer; /* Populate pIv and pAdditionalAuthData buffers with nonce and assoc * data */ CPA_CY_SYM_CCM_SET_NONCE(pOpData, sampleNonce, sizeof(sampleNonce)); CPA_CY_SYM_CCM_SET_AAD( pOpData, sampleAssocData, sizeof(sampleAssocData)); // } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); /* pVerifyResult not required in async mode */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (GEN_ENCRYPT_DIR == dir) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG("Output matches expected output CCM encrypt\n"); } else { PRINT_ERR( "Output does not match expected output CCM encrypt\n"); status = CPA_STATUS_FAIL; } } else { if (0 == memcmp(pSrcBuffer, samplePayload, sizeof(samplePayload))) { PRINT_DBG("Output matches expected output CCM decrypt\n"); } else { PRINT_ERR( "Output does not match expected output CCM decrypt\n"); status = CPA_STATUS_FAIL; } } } } /* at this stage, the callback function has returned, so it is sure that * the structures won't be needed any more*/ PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pIvBuffer); PHYS_CONTIG_FREE(pAadBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } CpaStatus algChainSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; CpaCySymCapabilitiesInfo symCapInfo = { { 0 } }; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } status = cpaCySymQueryCapabilities(cyInstHandle, &symCapInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to query capabilities, status = %d\n", status); return status; } /* Check capabilities before running the test */ if ((!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_AES_CCM)) || (!CPA_BITMAP_BIT_TEST(symCapInfo.hashes, CPA_CY_SYM_HASH_AES_CCM))) { PRINT("AES-CCM algorithm chaining not supported on Instance\n"); return CPA_STATUS_UNSUPPORTED; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); PRINT_DBG("Generation-Encryption Process\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CCM; sessionSetupData.cipherSetupData.pCipherKey = sampleKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_CCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; /* Notice for CCM authKey and authKeyLen are not required this * information is provided by the cipherKey in cipherSetupData */ sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAssocData); /* For CCM digestAppended and digestVerify are not required. In * the encrypt direction digestAppended is CPA_TRUE and * digestVerify is CPA_FALSE */ // /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymSessionCtxGetSize CCM encrypt\n"); status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymInitSession CCM encrypt\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOpCCM(cyInstHandle, sessionCtx, GEN_ENCRYPT_DIR); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession CCM encrypt\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Decryption-Verification Process\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CCM; sessionSetupData.cipherSetupData.pCipherKey = sampleKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_CCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAssocData); // } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymInitSession CCM Decrypt\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOpCCM(cyInstHandle, sessionCtx, DECRYPT_VERIFY_DIR); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession CCM decrypt\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (unsigned long long)symStats.numSymOpCompleted); } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_ccm_sample_user.c000066400000000000000000000101031503624047500363050ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ccm_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_ccm_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus algChainSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting CCM Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = algChainSample(); if ((CPA_STATUS_SUCCESS != stat) && (CPA_STATUS_UNSUPPORTED != stat)) { PRINT_ERR("\nCCM Sample Code App failed\n"); } else { PRINT_DBG("\nCCM Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/cipher_sample/000077500000000000000000000000001503624047500327515ustar00rootroot00000000000000cpa_cipher_sample.c000066400000000000000000000404611503624047500365010ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/cipher_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a cipher encryption. It encrypts * some sample text using the AES algorithm in CTR mode. */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" extern int gDebugParam; #define TIMEOUT_MS 5000 /* 5 seconds */ /* AES key, 256 bits long */ static Cpa8U sampleCipherKey[] = {0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11,0x00}; /* Initialization vector */ static Cpa8U sampleCipherIv[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x11,0x11}; /* Source data to encrypt */ static Cpa8U sampleCipherSrc[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; /* Expected output of the operation */ static Cpa8U expectedOutput[] = {0xD4,0x8C,0x32,0xD2,0x3E,0x43,0xED,0x60,0xE3,0x91,0xB8,0x9B,0xB2,0x65,0x7E,0x48}; /* ***************************************************************************** * Forward declaration ***************************************************************************** */ CpaStatus cipherSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a decrypted packet, etc. In this example, the function only * sets the complete variable to indicate it has been called. */ // static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /* indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } // /* * This function performs a cipher operation. */ static CpaStatus cipherPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = sizeof(sampleCipherSrc); Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pIvBuffer = NULL; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; /* Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); PRINT_DBG("cpaCyBufferListGetMetaSize\n"); /* * Different implementations of the API require different * amounts of space to store meta-data associated with buffer * lists. We query the API to find out how much space the current * implementation needs, and then allocate space for the buffer * meta data, the buffer list, and for the buffer itself. We also * allocate memory for the initialization vector. We then * populate this memory with the required data. */ // status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pIvBuffer, sizeof(sampleCipherIv)); } // if (CPA_STATUS_SUCCESS == status) { /* copy source into buffer */ memcpy(pSrcBuffer, sampleCipherSrc, sizeof(sampleCipherSrc)); /* copy IV into buffer */ memcpy(pIvBuffer, sampleCipherIv, sizeof(sampleCipherIv)); /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { /* * Populate the structure containing the operational data needed * to run the algorithm: * - packet type information (the algorithm can operate on a full * packet, perform a partial operation and maintain the state or * complete the last part of a multi-part operation) * - the initialization vector and its length * - the offset in the source buffer * - the length of the source message */ // pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = sizeof(sampleCipherIv); pOpData->cryptoStartSrcOffsetInBytes = 0; pOpData->messageLenToCipherInBytes = sizeof(sampleCipherSrc); // } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); // status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } /* * We now wait until the completion of the operation. This uses a macro * which can be defined differently for different OSes. */ if (CPA_STATUS_SUCCESS == status) { // if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } // } /* * We now check that the output matches the expected output. */ if (CPA_STATUS_SUCCESS == status) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_DBG("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } } } /* * At this stage, the callback function has returned, so it is * sure that the structures won't be needed any more. Free the * memory! */ PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pIvBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } /* * This is the main entry point for the sample cipher code. It * demonstrates the sequence of calls to be made to the API in order * to create a session, perform one or more cipher operations, and * then tear down the session. */ CpaStatus cipherSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sessionCtxSize = 0; CpaCySymSessionCtx sessionCtx = NULL; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); // status = cpaCyStartInstance(cyInstHandle); // if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ // status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); // } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); /* * We now populate the fields of the session operational data and create * the session. Note that the size required to store a session is * implementation-dependent, so we query the API first to determine how * much memory to allocate, and then allocate that memory. */ // /* Populate the session setup structure for the operation required */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; sessionSetupData.symOperation = CPA_CY_SYM_OP_CIPHER; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CTR; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymSessionCtxGetSize\n"); status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } /* Initialize the Cipher session */ if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymInitSession\n"); status = cpaCySymInitSession(cyInstHandle, symCallback, /* callback function */ &sessionSetupData, /* session setup data */ sessionCtx); /* output of the function*/ } // if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform Cipher operation */ status = cipherPerformOp(cyInstHandle, sessionCtx); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* * In a typical usage, the session might be used to encipher * or decipher multiple buffers. In this example however, we * can now tear down the session. */ PRINT_DBG("cpaCySymRemoveSession\n"); // sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); // /* Maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* * We can now query the statistics on the instance. * * Note that some implementations may also make the stats * available through other mechanisms, e.g. in the /proc * virtual filesystem. */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats64 failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (unsigned long long)symStats.numSymOpCompleted); } } /* * Free up memory, stop the instance, etc. */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_cipher_sample_user.c000066400000000000000000000100461503624047500375330ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/cipher_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_cipher_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus cipherSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Cipher Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialise memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = cipherSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nCipher Sample Code App failed\n"); } else { PRINT_DBG("\nCipher Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/gcm_sample/000077500000000000000000000000001503624047500322455ustar00rootroot00000000000000cpa_gcm_sample.c000066400000000000000000000511471503624047500352740ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/gcm_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a GCM operation. For more information * on GCM please reference NIST publication SP800-38D "Recommendation for Block * Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC" */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" #define TAG_LENGTH 16 #define AES_BLOCK_SIZE 16 #define TIMEOUT_MS 5000 /* 5 seconds*/ #define GCM_ENCRYPT_DIRECTION 0 #define GCM_DECRYPT_DIRECTION 1 extern int gDebugParam; static Cpa8U sampleKey[] = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }; static Cpa8U sampleIv[] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; static Cpa8U sampleAddAuthData[] = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }; static Cpa8U samplePayload[] = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39 }; static Cpa8U expectedOutput[] = { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62, /* Tag */ 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }; CpaStatus algChainSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a decrypted packet, etc. In this example, the function checks * verifyResult returned and sets the complete variable to indicate * it has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (CPA_FALSE == verifyResult) { PRINT_ERR("Error verifyResult failed\n"); } if (NULL != pCallbackTag) { /** indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform an algorithm chaining operation */ static CpaStatus algChainPerformOpGCM(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, int dir) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = sizeof(samplePayload) + TAG_LENGTH; Cpa32U aadBuffSize = 0; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pIvBuffer = NULL; Cpa8U *pAadBuffer = NULL; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; COMPLETION_INIT(&complete); // Initialize the completion variable /* get meta information size */ PRINT_DBG("cpaCyBufferListGetMetaSize\n"); status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; /* copy source into buffer */ if (GCM_ENCRYPT_DIRECTION == dir) { memcpy(pSrcBuffer, samplePayload, sizeof(samplePayload)); } else { memcpy(pSrcBuffer, expectedOutput, sizeof(expectedOutput)); } // /* Allocate memory to store IV. For GCM this is the block J0 * (size equal to AES block size). If iv is 12 bytes the * implementation will construct the J0 block given the iv. * If iv is not 12 bytes then the user must construct the J0 * block and give this as the iv. In both cases space for J0 * must be allocated. */ status = PHYS_CONTIG_ALLOC(&pIvBuffer, AES_BLOCK_SIZE); } if (CPA_STATUS_SUCCESS == status) { /* Allocate memory for AAD. For GCM this memory will hold the * additional authentication data and any padding to ensure total * size is a multiple of the AES block size */ aadBuffSize = sizeof(sampleAddAuthData); if (aadBuffSize % AES_BLOCK_SIZE) { aadBuffSize += AES_BLOCK_SIZE - (aadBuffSize % AES_BLOCK_SIZE); } status = PHYS_CONTIG_ALLOC(&pAadBuffer, aadBuffSize); } // if (CPA_STATUS_SUCCESS == status) { memcpy(pAadBuffer, sampleAddAuthData, sizeof(sampleAddAuthData)); status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { if (12 == sizeof(sampleIv)) { // pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; /* In this example iv is 12 bytes. The implementation * will use the iv to generation the J0 block */ memcpy(pIvBuffer, sampleIv, sizeof(sampleIv)); pOpData->ivLenInBytes = sizeof(sampleIv); pOpData->cryptoStartSrcOffsetInBytes = 0; pOpData->messageLenToCipherInBytes = sizeof(samplePayload); /* For GCM hash offset and length are not required */ pOpData->pAdditionalAuthData = pAadBuffer; // } else { /* Need to generate J0 block see SP800-38D */ } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); /* pVerifyResult not required in async mode */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (GCM_ENCRYPT_DIRECTION == dir) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG("Output matches expected output GCM encrypt\n"); } else { PRINT_ERR( "Output does not match expected output GCM encrypt\n"); status = CPA_STATUS_FAIL; } } else { if (0 == memcmp(pSrcBuffer, samplePayload, sizeof(samplePayload))) { PRINT_DBG("Output matches expected output GCM decrypt\n"); } else { PRINT_ERR( "Output does not match expected output GCM decrypt\n"); status = CPA_STATUS_FAIL; } } } } /* at this stage, the callback function has returned, so it is sure that * the structures won't be needed any more*/ PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pIvBuffer); PHYS_CONTIG_FREE(pAadBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } CpaStatus algChainSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); PRINT_DBG("Authenticated Encryption\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_GCM; sessionSetupData.cipherSetupData.pCipherKey = sampleKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_GCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = TAG_LENGTH; /* For GCM authKey and authKeyLen are not required this information is provided by the cipherKey in cipherSetupData */ sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAddAuthData); /* Tag follows immediately after the region to hash */ sessionSetupData.digestIsAppended = CPA_TRUE; /* digestVerify is not required to be set. For GCM authenticated encryption this value is understood to be CPA_FALSE */ // /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymSessionCtxGetSize GCM encrypt\n"); status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymInitSession GCM encrypt\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOpGCM( cyInstHandle, sessionCtx, GCM_ENCRYPT_DIRECTION); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession GCM encrypt\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Authenticated Decryption\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_GCM; sessionSetupData.cipherSetupData.pCipherKey = sampleKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_GCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = TAG_LENGTH; /* For GCM authKey and authKeyLen are not required this information is provided by the cipherKey in cipherSetupData */ sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAddAuthData); /* Tag follows immediately after the region to hash */ sessionSetupData.digestIsAppended = CPA_TRUE; /* digestVerify is not required to be set. For GCM authenticated decryption this value is understood to be CPA_TRUE */ // } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymInitSession GCM Decrypt\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOpGCM( cyInstHandle, sessionCtx, GCM_DECRYPT_DIRECTION); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession GCM decrypt\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (unsigned long long)symStats.numSymOpCompleted); } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_gcm_sample_user.c000066400000000000000000000100351503624047500363210ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/gcm_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_gcm_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus algChainSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting GCM Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = algChainSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nGCM Sample Code App failed\n"); } else { PRINT_DBG("\nGCM Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_file_sample/000077500000000000000000000000001503624047500334215ustar00rootroot00000000000000cpa_hash_file_sample.c000066400000000000000000000454721503624047500376300ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_file_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a hash of a file using SHA256. * Note this program will only work with files greater than SAMPLE_BUFF_SIZE * (Output can be compared with sha256sum in linux) */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" #include #include extern int gDebugParam; /* The digest length must be less than or equal to sha256 digest length (32) for this example */ #define DIGEST_LENGTH 32 /* Size of the buffer sent to the api */ #define SAMPLE_BUFF_SIZE 4096 extern char *gFileName; typedef struct file_data_s { Cpa8U **pSrcData; Cpa32U *bufferSize; } file_data_t; /* * This function copies a file to memory */ CpaStatus sample_getFile(const char *filename, file_data_t *file_data) { FILE *srcFile = NULL; Cpa8U *pBuff = NULL; struct stat st = { 0 }; long file_size = 0; /* Get filesize */ if (0 != stat(filename, &st)) { PRINT_ERR("Could not get the file %s size\n", filename); return CPA_STATUS_FAIL; } file_size = st.st_size; /* Allocate memory for the file */ pBuff = (Cpa8U *)qaeMemAlloc(file_size); if (NULL == pBuff) { PRINT_ERR("Could not allocate memory for the file copy\n"); return CPA_STATUS_FAIL; } memset(pBuff, 0, file_size); /* Open the file */ srcFile = fopen((const char *)filename, "r"); if (NULL == (srcFile)) { PRINT_ERR("Could not open source file %s\n", filename); qaeMemFree((void **)&pBuff); return CPA_STATUS_FAIL; } /* Read the file */ *(file_data->bufferSize) = fread(pBuff, 1, file_size, srcFile); if (*(file_data->bufferSize) != file_size) { PRINT_ERR("Filesize doesn't match\n"); qaeMemFree((void **)&pBuff); fclose(srcFile); return CPA_STATUS_FAIL; } fclose(srcFile); *(file_data->pSrcData) = pBuff; return CPA_STATUS_SUCCESS; } /* Free the memory after getting the file and copying the data */ CpaStatus sample_freeFile(file_data_t *file_data) { qaeMemFree((void **)(file_data->pSrcData)); return CPA_STATUS_SUCCESS; } /* Forward declaration */ CpaStatus hashFileSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a hashed packet, etc. In this example, the function only * sets the complete variable to indicate it has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /** indicate that the function has been called*/ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform a hash operation */ static CpaStatus hashPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = SAMPLE_BUFF_SIZE; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pDigestBuffer = NULL; FILE *srcFile = NULL; int i = 0; CpaCySymCapabilitiesInfo symCapInfo = { 0 }; file_data_t inputData = { 0 }; CpaFlatBuffer inputBuffer = { 0 }; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT((&complete)); /* Open file */ srcFile = fopen(gFileName, "r"); if (NULL == srcFile) { PRINT_ERR("Cannot open file %s\n", gFileName); return CPA_STATUS_FAIL; } else { PRINT_DBG("Processing file %s\n", gFileName); } status = cpaCySymQueryCapabilities(cyInstHandle, &symCapInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to query capabilities, status = %d\n", status); fclose(srcFile); return status; } /* Check if partial packet support is available */ if (!symCapInfo.partialPacketSupported) { PRINT_DBG( "Partial packets are not supported, using full packets instead.\n"); inputData.bufferSize = &inputBuffer.dataLenInBytes; inputData.pSrcData = &inputBuffer.pData; status = sample_getFile(gFileName, &inputData); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("sample_getFile failed\n"); fclose(srcFile); return status; } bufferSize = inputBuffer.dataLenInBytes; } /* get meta information size */ PRINT_DBG("cpaCyBufferListGetMetaSize\n"); status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pDigestBuffer, DIGEST_LENGTH); } if (CPA_STATUS_SUCCESS == status) { /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { /* Check if partial packet processing is supported */ if (symCapInfo.partialPacketSupported) { // while (!feof(srcFile)) { /* read from file into src buffer */ pBufferList->pBuffers->dataLenInBytes = fread(pSrcBuffer, 1, SAMPLE_BUFF_SIZE, srcFile); /* If we have reached the end of file set the last partial flag */ if (feof(srcFile)) { pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL; } else { pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_PARTIAL; } pOpData->sessionCtx = sessionCtx; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = pBufferList->pBuffers->dataLenInBytes; pOpData->pDigestResult = pDigestBuffer; PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); break; } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT((&complete), TIMEOUT_MS)) { PRINT_ERR( "timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; break; } } } } else { /* Process as a single full packet if partial packets are not * supported */ memcpy(pSrcBuffer, inputBuffer.pData, inputBuffer.dataLenInBytes); pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->sessionCtx = sessionCtx; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = inputBuffer.dataLenInBytes; pOpData->pDigestResult = pDigestBuffer; PRINT_DBG("cpaCySymPerformOp\n"); status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT((&complete), TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } } } if (CPA_STATUS_SUCCESS == status) { /* Output Result */ printf("DIGEST: \n"); for (i = 0; i < DIGEST_LENGTH; i++) { if (i && (i % 16 == 0)) { printf("\n"); } printf("%02X", pDigestBuffer[i]); } printf("\n"); } fclose(srcFile); /* At this stage, the callback function should have returned, * so it is safe to free the memory */ PHYS_CONTIG_FREE(pSrcBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); PHYS_CONTIG_FREE(pDigestBuffer); OS_FREE(pOpData); if (NULL != inputData.pSrcData) { sample_freeFile(&inputData); } COMPLETION_DESTROY(&complete); return status; } /* * This is the main entry point for the sample cipher code. It * demonstrates the sequence of calls to be made to the API in order * to create a session, perform one or more hash operations, and * then tear down the session. */ CpaStatus hashFileSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionCtx sessionCtx = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); /* * We now populate the fields of the session operational data and create * the session. Note that the size required to store a session is * implementation-dependent, so we query the API first to determine how * much memory to allocate, and then allocate that memory. */ // /* populate symmetric session data structure * for a plain hash operation */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; sessionSetupData.symOperation = CPA_CY_SYM_OP_HASH; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; /* Place the digest result in a buffer unrelated to srcBuffer */ sessionSetupData.digestIsAppended = CPA_FALSE; /* Generate the digest */ sessionSetupData.verifyDigest = CPA_FALSE; // /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymSessionCtxGetSize\n"); status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the Hash session */ PRINT_DBG("cpaCySymInitSession\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform Hash operation */ status = hashPerformOp(cyInstHandle, sessionCtx); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (unsigned long long)symStats.numSymOpCompleted); } } /* Clean up */ /* Stop the polling thread */ sampleCyStopPolling(); /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_hash_file_sample_user.c000066400000000000000000000107561503624047500406630ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_file_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_hash_file_sample_user.c * *****************************************************************************/ #include #include #include "cpa_sample_utils.h" #include "icp_sal_user.h" char *gFileName = NULL; extern CpaStatus hashFileSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; char fileToHash[PATH_MAX] = {0}; size_t fileToHashLen; fileToHashLen = readlink("/proc/self/exe", fileToHash, sizeof(fileToHash)); /* Read in debug setting if present */ if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Hash File Sample Code App ...\n"); if (fileToHashLen <= 0) { PRINT_ERR("Failed to get path to binary to hash\n"); return (int)CPA_STATUS_FAIL; } gFileName = fileToHash; stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = hashFileSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nHash File Sample Code App failed\n"); } else { PRINT_DBG("\nHash File Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); gFileName = NULL; return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_sample/000077500000000000000000000000001503624047500324225ustar00rootroot00000000000000cpa_hash_sample.c000066400000000000000000000343671503624047500356330ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a hash operation. Some sample * text is hashed with SHA256 algorithm. */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" extern int gDebugParam; #define DIGEST_LENGTH 32 #define TIMEOUT_MS 5000 /* 5 seconds*/ /* source data to hash */ static Cpa8U vectorData[] = { 0xD7, 0x1B, 0xA4, 0xCA, 0xEC, 0xBD, 0x15, 0xE2, 0x52, 0x6A, 0x21, 0x0B, 0x81, 0x77, 0x0C, 0x90, 0x68, 0xF6, 0x86, 0x50, 0xC6, 0x2C, 0x6E, 0xED, 0x2F, 0x68, 0x39, 0x71, 0x75, 0x1D, 0x94, 0xF9, 0x0B, 0x21, 0x39, 0x06, 0xBE, 0x20, 0x94, 0xC3, 0x43, 0x4F, 0x92, 0xC9, 0x07, 0xAA, 0xFE, 0x7F, 0xCF, 0x05, 0x28, 0x6B, 0x82, 0xC4, 0xD7, 0x5E, 0xF3, 0xC7, 0x74, 0x68, 0xCF, 0x05, 0x28, 0x6B, 0x82, 0xC4, 0xD7, 0x5E, 0xF3, 0xC7, 0x74, 0x68, 0x80, 0x8B, 0x28, 0x8D, 0xCD, 0xCA, 0x94, 0xB8, 0xF5, 0x66, 0x0C, 0x00, 0x5C, 0x69, 0xFC, 0xE8, 0x7F, 0x0D, 0x81, 0x97, 0x48, 0xC3, 0x6D, 0x24}; /* expected result */ static Cpa8U digest[] = {0xA7, 0x0D, 0xAD, 0xE4, 0x5E, 0x90, 0x51, 0xC0, 0x02, 0xDF, 0xD0, 0x5E, 0xA0, 0x5A, 0xD8, 0x2C, 0x5E, 0x9F, 0x01, 0x5B, 0x8C, 0x64, 0xA2, 0x12, 0x52, 0x80, 0xFB, 0x21, 0x37, 0x5E, 0xA9, 0xCC}; /* Forward declaration */ CpaStatus hashSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a hashed packet, etc. In this example, the function only * sets the complete variable to indicate it has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /** indicate that the function has been called*/ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform a hash operation */ static CpaStatus hashPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = sizeof(vectorData) + DIGEST_LENGTH; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pDigestBuffer = NULL; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT((&complete)); /* get meta information size */ PRINT_DBG("cpaCyBufferListGetMetaSize\n"); status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { /* copy vector into buffer */ memcpy(pSrcBuffer, vectorData, sizeof(vectorData)); pDigestBuffer = pSrcBuffer + sizeof(vectorData); /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { // pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = sizeof(vectorData); pOpData->pDigestResult = pDigestBuffer; // } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT((&complete), TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (0 == memcmp(digest, pOpData->pDigestResult, DIGEST_LENGTH)) { PRINT_DBG("Digest matches expected output\n"); } else { PRINT_DBG("Digest does not match expected output\n"); status = CPA_STATUS_FAIL; } } } /* At this stage, the callback function should have returned, * so it is safe to free the memory */ PHYS_CONTIG_FREE(pSrcBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } /* * This is the main entry point for the sample cipher code. It * demonstrates the sequence of calls to be made to the API in order * to create a session, perform one or more hash operations, and * then tear down the session. */ CpaStatus hashSample(void) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionCtx sessionCtx = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); /* * We now populate the fields of the session operational data and create * the session. Note that the size required to store a session is * implementation-dependent, so we query the API first to determine how * much memory to allocate, and then allocate that memory. */ // /* populate symmetric session data structure * for a plain hash operation */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; sessionSetupData.symOperation = CPA_CY_SYM_OP_HASH; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; /* Place the digest result in a buffer unrelated to srcBuffer */ sessionSetupData.digestIsAppended = CPA_FALSE; /* Generate the digest */ sessionSetupData.verifyDigest = CPA_FALSE; // /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymSessionCtxGetSize\n"); status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the Hash session */ PRINT_DBG("cpaCySymInitSession\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform Hash operation */ status = hashPerformOp(cyInstHandle, sessionCtx); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (unsigned long long)symStats.numSymOpCompleted); } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_hash_sample_user.c000066400000000000000000000100561503624047500366560ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hash_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_hash_sample_user.c * *****************************************************************************/ #include #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus hashSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Hash Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialise memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = hashSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nHash Sample Code App failed\n"); } else { PRINT_DBG("\nHash Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/000077500000000000000000000000001503624047500324135ustar00rootroot00000000000000cpa_hkdf_sample.c000066400000000000000000000531571503624047500356130ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a HKDF based operations. * It performs HKDF Extract and Expand, and Extract and Expand Label operation * without and with sublabels (KEY and IV). */ #include "cpa.h" #include "lac/cpa_cy_key.h" #include "cpa_sample_utils.h" #if CY_API_VERSION_AT_LEAST(2, 3) #define TIMEOUT_MS 5000 /* 5 seconds */ /* * Test vectors from RFC 5869 * https://tools.ietf.org/html/rfc5869 */ /* Input Keying Material */ static Cpa8U sampleIkm[] = {0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B}; /* Output Keying Material, NOTE: truncated to 32 bytes */ static Cpa8U sampleOkm[] = {0x3C, 0xB2, 0x5F, 0x25, 0xFA, 0xAC, 0xD5, 0x7A, 0x90, 0x43, 0x4F, 0x64, 0xD0, 0x36, 0x2F, 0x2A, 0x2D, 0x2D, 0x0A, 0x90, 0xCF, 0x1A, 0x5A, 0x4C, 0x5D, 0xB0, 0x2D, 0x56, 0xEC, 0xC4, 0xC5, 0xBF}; /* Pseudorandom Key */ static Cpa8U samplePrk[] = {0x07, 0x77, 0x09, 0x36, 0x2C, 0x2E, 0x32, 0xDF, 0x0D, 0xDC, 0x3F, 0x0D, 0xC4, 0x7B, 0xBA, 0x63, 0x90, 0xB6, 0xC7, 0x3B, 0xB5, 0x0F, 0x9C, 0x31, 0x22, 0xEC, 0x84, 0x4A, 0xD7, 0xC2, 0xB3, 0xE5}; /* Salt */ static Cpa8U sampleSlt[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C}; /* Info */ static Cpa8U sampleInf[] = {0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9}; /* Expand and extarct label random input data */ static Cpa8U sampleSeedLabel[] = { 0x6f, 0x26, 0x15, 0xa1, 0x08, 0xc7, 0x02, 0xc5, 0x67, 0x8f, 0x54, 0xfc, 0x9d, 0xba, 0xb6, 0x97, 0x16, 0xc0, 0x76, 0x18, 0x9c, 0x48, 0x25, 0x0c, 0xeb, 0xea, 0xc3, 0x57, 0x6c, 0x36, 0x11, 0xba}; static Cpa8U sampleSecretLabel[] = { 0x35, 0x75, 0x4d, 0x42, 0xc9, 0x9c, 0xd5, 0x10, 0x80, 0x6f, 0x5a, 0xfa, 0x87, 0x0c, 0x44, 0xad, 0x98, 0x03, 0x96, 0x81, 0xa6, 0x18, 0xb2, 0xd4, 0xd0, 0x59, 0x1b, 0xd9, 0xd2, 0x77, 0x4d, 0x21}; static Cpa8U samplePrkExpected[] = { 0x9e, 0x9b, 0xc0, 0x58, 0x69, 0x09, 0x24, 0xb5, 0x6d, 0xe4, 0x34, 0x67, 0x75, 0x38, 0xec, 0x25, 0x9f, 0x61, 0x38, 0xd4, 0x55, 0x4d, 0x93, 0xa3, 0xe7, 0x09, 0xfc, 0xcc, 0xe8, 0x65, 0x93, 0x57}; static Cpa8U sampleLabel[] = { 0x00, 0x20, 0x12, 0x74, 0x6c, 0x73, 0x31, 0x33, 0x20, 0x73, 0x20, 0x68, 0x73, 0x20, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x20, 0xc7, 0x45, 0x3c, 0x9b, 0xf5, 0x6c, 0xff, 0x11, 0x28, 0x71, 0x66, 0x54, 0xfc, 0x74, 0xc4, 0x88, 0xaf, 0x38, 0x60, 0xae, 0xf7, 0xac, 0x98, 0x5a, 0x83, 0x5b, 0xde, 0x97, 0x82, 0xa4, 0xa6, 0x66}; static Cpa8U sampleExpandExpected[] = { 0xbf, 0x29, 0x72, 0xc5, 0x27, 0x66, 0x00, 0xcc, 0xbc, 0x58, 0x2d, 0x22, 0x6d, 0x5d, 0x63, 0x83, 0x4d, 0xb8, 0x3e, 0x49, 0x5d, 0x16, 0x35, 0x58, 0xf4, 0x00, 0xbf, 0x1a, 0x88, 0x17, 0x56, 0xe5}; static Cpa8U sampleKeyExpected[] = {0x10, 0x68, 0x5e, 0xe5, 0x2a, 0x2d, 0xcb, 0x25, 0x1c, 0x76, 0xe5, 0xa8, 0x51, 0x4e, 0x3e, 0x9d}; static Cpa8U sampleIvExpected[] = {0xec, 0x63, 0xaa, 0x6d, 0x39, 0xc2, 0xb9, 0x94, 0x80, 0x3d, 0x24, 0xd9}; extern int gDebugParam; CpaStatus hkdfSample(void); static void hkdfSampleCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /* indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } static void print_buffer(const char *name, Cpa8U *buffer, Cpa32U bufferSize) { int i = 0; PRINT("%s\n", name); for (i = 0; i < bufferSize; i++) PRINT("%02x ", buffer[i]); PRINT("\n"); return; } static CpaStatus checkResult(const char *name, Cpa8U *buffer, Cpa8U *expected, Cpa32U bufferSize) { CpaStatus status = CPA_STATUS_SUCCESS; if (memcmp(buffer, expected, sizeof(bufferSize)) != 0) { PRINT_ERR("ERROR: %s doesn't match\n", name); print_buffer("ACTUAL:", buffer, bufferSize); print_buffer("EXPECTED:", expected, bufferSize); status = CPA_STATUS_FAIL; } else { PRINT("%s correct\n", name); } return status; } static CpaStatus hkdfSampleExtractExpandLabelPerform( CpaInstanceHandle cyInstHandle) { CpaInstanceInfo2 instanceInfo2; CpaStatus status = CPA_STATUS_SUCCESS; CpaCyKeyGenHKDFOpData *pOpData = NULL; Cpa8U *pHkdfData = NULL; Cpa32U hkdfDataSize = sizeof(samplePrkExpected) + sizeof(sampleExpandExpected); Cpa32U offset = 0; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; CpaFlatBuffer hkdfOut; /* Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); status = PHYS_CONTIG_ALLOC(&pHkdfData, hkdfDataSize); if (CPA_STATUS_SUCCESS == status) { hkdfOut.pData = pHkdfData; hkdfOut.dataLenInBytes = hkdfDataSize; status = cpaCyInstanceGetInfo2(cyInstHandle, &instanceInfo2); } if (CPA_STATUS_SUCCESS == status) { PHYS_CONTIG_ALLOC_ALIGNED( &pOpData, sizeof(CpaCyKeyGenHKDFOpData), BYTE_ALIGNMENT_64); if (!pOpData) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { pOpData->hkdfKeyOp = CPA_CY_HKDF_KEY_EXTRACT_EXPAND_LABEL; pOpData->seedLen = sizeof(sampleSeedLabel); memcpy(pOpData->seed, sampleSeedLabel, sizeof(sampleSeedLabel)); pOpData->secretLen = sizeof(sampleSecretLabel); memcpy(pOpData->secret, sampleSecretLabel, sizeof(sampleSecretLabel)); pOpData->numLabels = 1; memcpy(pOpData->label[0].label, sampleLabel, sizeof(sampleLabel)); pOpData->label[0].labelLen = sizeof(sampleLabel); pOpData->label[0].sublabelFlag = 0x00; } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCyKeyGenTls3\n"); status = cpaCyKeyGenTls3(cyInstHandle, hkdfSampleCallback, (void *)&complete, pOpData, CPA_CY_HKDF_TLS_AES_128_GCM_SHA256, &hkdfOut); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyKeyGenTls failed. (status = %d)\n", status); } /* * We now wait until the polling thread to complete * the operation. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCyKeyGenTls\n"); status = CPA_STATUS_FAIL; } } /* * Data sanity */ if (CPA_STATUS_SUCCESS == status) { status = checkResult("PRK", hkdfOut.pData, samplePrkExpected, sizeof(samplePrkExpected)); } if (CPA_STATUS_SUCCESS == status) { offset += sizeof(samplePrkExpected); status = checkResult("LABEL", hkdfOut.pData + offset, sampleExpandExpected, sizeof(sampleExpandExpected)); } } /* * At this stage, the callback function has returned, so it is * sure that the structures won't be needed any more. Free the * memory! */ PHYS_CONTIG_FREE(pHkdfData); PHYS_CONTIG_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } static CpaStatus hkdfSampleExtractExpandLabelSublabelsPerform( CpaInstanceHandle cyInstHandle) { CpaInstanceInfo2 instanceInfo2; CpaStatus status = CPA_STATUS_SUCCESS; CpaCyKeyGenHKDFOpData *pOpData = NULL; Cpa8U *pHkdfData = NULL; Cpa32U offset = 0; Cpa32U hkdfDataSize = sizeof(samplePrkExpected) + sizeof(sampleExpandExpected) + sizeof(sampleKeyExpected) + sizeof(sampleIvExpected); /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; CpaFlatBuffer hkdfOut; /* Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); status = PHYS_CONTIG_ALLOC(&pHkdfData, hkdfDataSize); if (CPA_STATUS_SUCCESS == status) { hkdfOut.pData = pHkdfData; hkdfOut.dataLenInBytes = hkdfDataSize; status = cpaCyInstanceGetInfo2(cyInstHandle, &instanceInfo2); } if (CPA_STATUS_SUCCESS == status) { PHYS_CONTIG_ALLOC_ALIGNED( &pOpData, sizeof(CpaCyKeyGenHKDFOpData), BYTE_ALIGNMENT_64); if (!pOpData) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { pOpData->hkdfKeyOp = CPA_CY_HKDF_KEY_EXTRACT_EXPAND_LABEL; pOpData->seedLen = sizeof(sampleSeedLabel); memcpy(pOpData->seed, sampleSeedLabel, sizeof(sampleSeedLabel)); pOpData->secretLen = sizeof(sampleSecretLabel); memcpy(pOpData->secret, sampleSecretLabel, sizeof(sampleSecretLabel)); pOpData->numLabels = 1; memcpy(pOpData->label[0].label, sampleLabel, sizeof(sampleLabel)); pOpData->label[0].labelLen = sizeof(sampleLabel); pOpData->label[0].sublabelFlag = CPA_CY_HKDF_SUBLABEL_KEY; pOpData->label[0].sublabelFlag |= CPA_CY_HKDF_SUBLABEL_IV; } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCyKeyGenTls3\n"); status = cpaCyKeyGenTls3(cyInstHandle, hkdfSampleCallback, (void *)&complete, pOpData, CPA_CY_HKDF_TLS_AES_128_GCM_SHA256, &hkdfOut); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyKeyGenTls failed. (status = %d)\n", status); } /* * We now wait until the polling thread to complete * the operation. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCyKeyGenTls\n"); status = CPA_STATUS_FAIL; } } /* * Data sanity */ if (CPA_STATUS_SUCCESS == status) { status = checkResult("PRK", hkdfOut.pData, samplePrkExpected, sizeof(samplePrkExpected)); offset += sizeof(samplePrkExpected); } if (CPA_STATUS_SUCCESS == status) { status = checkResult("LABEL", hkdfOut.pData + offset, sampleExpandExpected, sizeof(sampleExpandExpected)); offset += sizeof(sampleExpandExpected); } if (CPA_STATUS_SUCCESS == status) { status = checkResult("KEY", hkdfOut.pData + offset, sampleKeyExpected, sizeof(sampleKeyExpected)); offset += sizeof(sampleKeyExpected); } if (CPA_STATUS_SUCCESS == status) { status = checkResult("IV", hkdfOut.pData + offset, sampleIvExpected, sizeof(sampleIvExpected)); } } /* * At this stage, the callback function has returned, so it is * sure that the structures won't be needed any more. Free the * memory! */ PHYS_CONTIG_FREE(pHkdfData); PHYS_CONTIG_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } static CpaStatus hkdfSampleExtractExpandPerform(CpaInstanceHandle cyInstHandle) { CpaInstanceInfo2 instanceInfo2; CpaStatus status = CPA_STATUS_SUCCESS; CpaCyKeyGenHKDFOpData *pOpData = NULL; Cpa8U *pHkdfData = NULL; Cpa32U hkdfDataSize = 64; Cpa32U offset = 0; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; CpaFlatBuffer hkdfOut; /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); status = PHYS_CONTIG_ALLOC(&pHkdfData, hkdfDataSize); if (CPA_STATUS_SUCCESS == status) { hkdfOut.pData = pHkdfData; hkdfOut.dataLenInBytes = hkdfDataSize; status = cpaCyInstanceGetInfo2(cyInstHandle, &instanceInfo2); } if (CPA_STATUS_SUCCESS == status) { PHYS_CONTIG_ALLOC_ALIGNED( &pOpData, sizeof(CpaCyKeyGenHKDFOpData), BYTE_ALIGNMENT_64); if (!pOpData) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { pOpData->hkdfKeyOp = CPA_CY_HKDF_KEY_EXTRACT_EXPAND; pOpData->numLabels = 0; pOpData->secretLen = sizeof(sampleIkm); memcpy(pOpData->secret, sampleIkm, pOpData->secretLen); pOpData->seedLen = sizeof(sampleSlt); memcpy(pOpData->seed, sampleSlt, pOpData->seedLen); pOpData->infoLen = sizeof(sampleInf); memcpy(pOpData->info, sampleInf, pOpData->infoLen); } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCyKeyGenTls3\n"); status = cpaCyKeyGenTls3(cyInstHandle, hkdfSampleCallback, (void *)&complete, pOpData, CPA_CY_HKDF_TLS_AES_128_GCM_SHA256, &hkdfOut); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyKeyGenTls failed. (status = %d)\n", status); } /* * We now wait until the polling thread to complete * the operation. */ if (CPA_STATUS_SUCCESS == status) { if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCyKeyGenTls\n"); status = CPA_STATUS_FAIL; } } /* * Data sanity */ if (CPA_STATUS_SUCCESS == status) { status = checkResult("PRK", hkdfOut.pData, samplePrk, sizeof(samplePrk)); offset += sizeof(samplePrk); } if (CPA_STATUS_SUCCESS == status) { status = checkResult( "OKM", hkdfOut.pData + offset, sampleOkm, sizeof(sampleOkm)); } } /* * At this stage, the callback function has returned, so it is * sure that the structures won't be needed any more. Free the * memory! */ PHYS_CONTIG_FREE(pHkdfData); PHYS_CONTIG_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } CpaStatus hkdfSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle cyInstHandle = NULL; CpaInstanceInfo2 info = {0}; CpaCyCapabilitiesInfo cyCap = { 0 }; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } status = cpaCyQueryCapabilities(cyInstHandle, &cyCap); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to query capabilities, status = %d\n", status); return status; } if (CPA_FALSE == cyCap.hkdfSupported) { PRINT("HKDF is not supported on this instance\n"); return CPA_STATUS_UNSUPPORTED; } status = cpaCyInstanceGetInfo2(cyInstHandle, &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Can not get instance info\n"); return status; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS != status) { return status; } /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); status = hkdfSampleExtractExpandPerform(cyInstHandle); status |= hkdfSampleExtractExpandLabelPerform(cyInstHandle); status |= hkdfSampleExtractExpandLabelSublabelsPerform(cyInstHandle); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ cpa_hkdf_sample_linux_kernel_module.c000066400000000000000000000076731503624047500417410ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_hkdf_sample_linux_kernel_module.c * *****************************************************************************/ #include "cpa_sample_utils.h" int gDebugParam = 1; module_param(gDebugParam, int, S_IRUGO); extern CpaStatus hkdfSample(void); static int hkdfInit(void) { CpaStatus stat = CPA_STATUS_SUCCESS; PRINT_DBG("Loading HKDF Sample Code Module ...\n"); stat = hkdfSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nHkdf Sample Code App failed\n"); } else { PRINT_DBG("\nHkdf Sample Code App finished\n"); } PRINT_DBG("\nRemoving Module - ignore insmod error\n"); /* module does not have any runtime functionality so remove it */ return -EAGAIN; } static void hkdfExit(void) { PRINT_DBG("Unloading Hkdf Sample Code Module ...\n"); } module_init(hkdfInit); module_exit(hkdfExit); MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Hkdf Sample Code"); cpa_hkdf_sample_user.c000066400000000000000000000115261503624047500366430ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/hkdf_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_hkdf_sample_user.c * *****************************************************************************/ #include "cpa.h" #include "icp_sal_user.h" #include "cpa_sample_utils.h" #if CY_API_VERSION_AT_LEAST(2, 3) extern CpaStatus hkdfSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus status = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } /* status = sampleDeviceStart("SSL", CFG_ALL_DEVICES, NUM_PROCESSES_DEFAULT, NUM_INSTANCES_DEFAULT, NUM_SYM_CONCURRENT_REQUESTS_DEFAULT, NUM_ASYM_CONCURRENT_REQUESTS_DEFAULT, LIMIT_DEVICE_ACCESS_DEFAULT); if(CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to start device(s)\n"); return (int) status; } */ PRINT_DBG("Starting HKDF sample code ...\n"); status = qaeMemInit(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)status; } status = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)status; } status = hkdfSample(); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_UNSUPPORTED != status)) { PRINT_ERR("\nHKDF sample code failed\n"); } else { PRINT_DBG("\nHKDF sample code finished\n"); } icp_sal_userStop(); qaeMemDestroy(); /* if(CPA_STATUS_SUCCESS != sampleDeviceStop(CFG_ALL_DEVICES)) { PRINT_ERR("Failed to stop device(s)\n"); } */ return (int)status; } #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ipsec_sample/000077500000000000000000000000001503624047500326025ustar00rootroot00000000000000cpa_ipsec_sample.c000066400000000000000000000554751503624047500361760ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ipsec_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform an IPSec like operation. * In this example we use the algorithm AES256-GCM + AES256-GCM */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" #define TIMEOUT_MS 5000 #define ICV_LENGTH 16 #define AES_BLOCK_SIZE 16 /* For IPSec outbound direction we encrypt the payload and then generate the ICV. For IPSec inbound direction we compare the ICV and decrypt the payload */ #define IPSEC_OUTBOUND_DIR 0 #define IPSEC_INBOUND_DIR 1 extern int gDebugParam; static Cpa8U sampleCipherKey[] = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }; static Cpa8U sampleCipherIv[] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; static Cpa8U sampleAddAuthData[] = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }; static Cpa8U sampleAuthKey[] = { 0xEE, 0xE2, 0x7B, 0x5B, 0x10, 0xFD, 0xD2, 0x58, 0x49, 0x77, 0xF1, 0x22, 0xD7, 0x1B, 0xA4, 0xCA, 0xEC, 0xBD, 0x15, 0xE2, 0x52, 0x6A, 0x21, 0x0B, 0x41, 0x4C, 0x41, 0x4E, 0xA1, 0xAA, 0x01, 0x3F }; static Cpa8U sampleEspHdrData[] = {0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x05}; static Cpa8U samplePayload[] = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39 }; static Cpa8U expectedOutput[] = { /* ESP header unmodified */ 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x05, /* IV unmodified */ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, /* Ciphertext */ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62, 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }; CpaStatus algChainSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a decrypted packet, etc. In this example, the function checks * verifyResult returned and sets the complete variable to indicate it * has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); /* For this implementation verifyResult is true by default. In the digest generate case verifyDigest will never be false. In the digest verify case verifyDigest can be false if digest verification fails */ if (CPA_FALSE == verifyResult) { PRINT_ERR("Callback verify result error\n"); } if (NULL != pCallbackTag) { /** indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform an algorithm chaining operation */ static CpaStatus algChainPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, int dir) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; /* buffer size includes space for hdr, iv, payload and icv */ Cpa32U bufferSize = sizeof(sampleEspHdrData) + sizeof(sampleCipherIv) + sizeof(samplePayload) + ICV_LENGTH; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pIvBuffer = NULL; Cpa32U aadBuffSize = 0; Cpa8U *pAadBuffer = NULL; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; /* * Initialize the completion variable which is used by the callback * function */ COMPLETION_INIT(&complete); /* get meta information size */ status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate memory for AAD. For GCM this memory will hold the * additional authentication data and any padding to ensure total * size is a multiple of the AES block size */ aadBuffSize = sizeof(sampleAddAuthData); if (aadBuffSize % AES_BLOCK_SIZE) { aadBuffSize += AES_BLOCK_SIZE - (aadBuffSize % AES_BLOCK_SIZE); } status = PHYS_CONTIG_ALLOC(&pAadBuffer, aadBuffSize); } if (CPA_STATUS_SUCCESS == status) { /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; /* copy source into buffer */ if (IPSEC_OUTBOUND_DIR == dir) { memcpy(pSrcBuffer, sampleEspHdrData, sizeof(sampleEspHdrData)); memcpy(pSrcBuffer + sizeof(sampleEspHdrData), sampleCipherIv, sizeof(sampleCipherIv)); memcpy(pSrcBuffer + (sizeof(sampleEspHdrData) + sizeof(sampleCipherIv)), samplePayload, sizeof(samplePayload)); } else { memcpy(pSrcBuffer, expectedOutput, sizeof(expectedOutput)); } pIvBuffer = pSrcBuffer + sizeof(sampleEspHdrData); memcpy(pAadBuffer, sampleAddAuthData, sizeof(sampleAddAuthData)); status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { if (IPSEC_OUTBOUND_DIR == dir) { // /** Populate the structure containing the operational data that is * needed to run the algorithm in outbound direction */ pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = sizeof(sampleCipherIv); pOpData->cryptoStartSrcOffsetInBytes = sizeof(sampleEspHdrData) + sizeof(sampleCipherIv); pOpData->messageLenToCipherInBytes = sizeof(samplePayload); pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = sizeof(sampleEspHdrData) + sizeof(sampleCipherIv) + sizeof(samplePayload); /* Even though ICV follows immediately after the region to hash digestIsAppended is set to false in this case due to errata number IXA00378322 */ pOpData->pDigestResult = pSrcBuffer + (sizeof(sampleEspHdrData) + sizeof(sampleCipherIv) + sizeof(samplePayload)); pOpData->pAdditionalAuthData = pAadBuffer; // } else { // /** Populate the structure containing the operational data that is * needed to run the algorithm in inbound direction */ pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = sizeof(sampleCipherIv); pOpData->cryptoStartSrcOffsetInBytes = sizeof(sampleEspHdrData) + sizeof(sampleCipherIv); pOpData->messageLenToCipherInBytes = bufferSize - (sizeof(sampleEspHdrData) + sizeof(sampleCipherIv) + ICV_LENGTH); pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = bufferSize - ICV_LENGTH; pOpData->pAdditionalAuthData = pAadBuffer; // } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); /* pVerifyResult not required in async mode */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (IPSEC_OUTBOUND_DIR == dir) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG( "Output matches expected output encrypt generate\n"); } else { PRINT_DBG("Output does not match expected output encrypt " "generate\n"); status = CPA_STATUS_FAIL; } } else { if (0 == memcmp(pSrcBuffer + (sizeof(sampleEspHdrData) + sizeof(sampleCipherIv)), samplePayload, sizeof(samplePayload))) { PRINT_DBG( "Output matches expected output decrypt verify\n"); } else { PRINT_DBG("Output does not match expected output decrypt " "verify\n"); status = CPA_STATUS_FAIL; } } } } /* at this stage, the callback function has returned, so it is sure that * the structures won't be needed any more*/ PHYS_CONTIG_FREE(pSrcBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); PHYS_CONTIG_FREE(pAadBuffer); COMPLETION_DESTROY(&complete); return status; } CpaStatus algChainSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { PRINT_DBG("No crypto instances available\n"); return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); PRINT_DBG("Encrypt-Generate ICV\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_GCM; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_GCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = ICV_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAddAuthData); sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleAuthKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = sizeof(sampleAuthKey); /* Even though ICV follows immediately after the region to hash digestIsAppended is set to false in this case due to errata number IXA00378322 */ sessionSetupData.digestIsAppended = CPA_FALSE; /* Generate the ICV in outbound direction */ sessionSetupData.verifyDigest = CPA_FALSE; // /* Determine size of session context to allocate */ status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOp(cyInstHandle, sessionCtx, IPSEC_OUTBOUND_DIR); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Decrypt-Verify ICV\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_GCM; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_GCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = ICV_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAddAuthData); sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleAuthKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = sizeof(sampleAuthKey); /* ICV follows immediately after the region to hash */ sessionSetupData.digestIsAppended = CPA_TRUE; /* Verify the ICV in the inbound direction */ sessionSetupData.verifyDigest = CPA_TRUE; // } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOp(cyInstHandle, sessionCtx, IPSEC_INBOUND_DIR); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operations completed: %llu\n", (unsigned long long)symStats.numSymOpCompleted); } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_ipsec_sample_user.c000066400000000000000000000102121503624047500372100ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ipsec_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_ipsec_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus algChainSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting IPSec Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } /* In this example the default config file is used. The user space section name is SSL */ stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = algChainSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nIPSec Sample Code App failed\n"); } else { PRINT_DBG("\nIPSec Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/000077500000000000000000000000001503624047500323005ustar00rootroot00000000000000cpa_sample_decrypt_user.c000066400000000000000000000120441503624047500372620ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "cpa.h" #include #include #include #include #include /* ************************************************************* * * On core crypto for SSL decrypt * * ************************************************************* */ CpaStatus sampleCodeAesCbcDecrypt(Cpa8U *pKey, Cpa32U keyLen, Cpa8U *pIv, Cpa8U *pIn, Cpa8U *pOut) { #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) int len; if ((!pIn) || (!pIv) || (!pKey)) return CPA_STATUS_FAIL; EVP_CIPHER_CTX *ctx; /* Create and initialise the context */ if (!(ctx = EVP_CIPHER_CTX_new())) { ERR_print_errors_fp(stderr); return CPA_STATUS_FAIL; } /* Set algorithm for decryption */ if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, NULL, NULL)) { ERR_print_errors_fp(stderr); goto exit; } /* Setting Initialization Vector length */ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) { ERR_print_errors_fp(stderr); goto exit; } /* Initializing key and IV */ if (!EVP_DecryptInit_ex(ctx, NULL, NULL, pKey, pIv)) { ERR_print_errors_fp(stderr); goto exit; } /*no padding */ if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) { ERR_print_errors_fp(stderr); goto exit; } /* Decrypt the message to the output buffer */ if (!EVP_DecryptUpdate(ctx, pOut, &len, pIn, 16)) { ERR_print_errors_fp(stderr); goto exit; } /* Free the cipher context */ EVP_CIPHER_CTX_free(ctx); return CPA_STATUS_SUCCESS; exit: EVP_CIPHER_CTX_free(ctx); return CPA_STATUS_FAIL; #else AES_KEY dec_key; int i = 0; int status = AES_set_decrypt_key(pKey, keyLen << 3, &dec_key); if (status == -1) { return CPA_STATUS_FAIL; } AES_decrypt(pIn, pOut, &dec_key); /* Xor with IV */ for (i = 0; i < 16; i++) { pOut[i] = pOut[i] ^ pIv[i]; } return CPA_STATUS_SUCCESS; #endif } cpa_ssl_sample.c000066400000000000000000000561271503624047500353650ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a SSL like operation. * In this example we use the algorithm aes256-cbc + sha256-hmac */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" #define MAC_LENGTH 32 #define TIMEOUT_MS 5000 /* 5 seconds*/ #define SSL_OUTBOUND_DIR 0 #define SSL_INBOUND_DIR 1 #define SESSION_SEQ_START 51 /* 8 byte seq, followed by header */ #define HDR_START 59 /* 5 byte header */ extern int gDebugParam; extern CpaStatus sampleCodeAesCbcDecrypt(Cpa8U *pKey, Cpa32U keyLen, Cpa8U *pIv, Cpa8U *pIn, Cpa8U *pOut); static Cpa8U sampleCipherKey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11}; static Cpa8U sampleCipherIv[] = {0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, 0x3d, 0x11, 0x59, 0x04}; static Cpa8U sampleAuthKey[] = { 0xEE, 0xE2, 0x7B, 0x5B, 0x10, 0xFD, 0xD2, 0x58, 0x49, 0x77, 0xF1, 0x22, 0xD7, 0x1B, 0xA4, 0xCA, 0xEC, 0xBD, 0x15, 0xE2, 0x52, 0x6A, 0x21, 0x0B, 0x41, 0x4C, 0x41, 0x4E, 0xA1, 0xAA, 0x01, 0x3F }; static Cpa8U sampleHdrData[] = {0x17, 0x01, 0x02, 0x00, 0x38}; static Cpa8U samplePayload[] = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57}; static Cpa8U expectedOutput[] = { 0xCF, 0x6A, 0x17, 0xF1, 0x87, 0x0D, 0x71, 0xC1, 0xBD, 0xC8, 0xF6, 0x26, 0x52, 0x44, 0xA9, 0x3B, 0x66, 0x74, 0x6D, 0xBC, 0x0A, 0xB4, 0xA3, 0x7E, 0xBA, 0x2C, 0x49, 0x80, 0x15, 0xF8, 0xC0, 0x49, 0x1B, 0xCF, 0x60, 0x7E, 0xE2, 0x4C, 0x77, 0xAC, 0x88, 0x97, 0xDC, 0xF7, 0xF3, 0xCB, 0xCA, 0xC7, 0xEC, 0x43, 0x11, 0xAD, 0x15, 0x6D, 0x25, 0x43, 0xAC, 0x9D, 0xCC, 0xBC, 0x02, 0xE4, 0x44, 0x93, 0x1C, 0xC0, 0x66, 0x6D, 0xD5, 0x69, 0xA5, 0xFF, 0xA8, 0xEC, 0xD4, 0x59, 0xF0, 0x8D, 0x9C, 0xCD, 0x49, 0x10, 0x8D, 0xAF, 0x56, 0xF5, 0x27, 0xD3, 0xA0, 0x29, 0x11, 0xE4, 0xCA, 0xBB, 0x96, 0xDB }; CpaStatus algChainSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a decrypted packet, etc. In this example, the function checks * the verifyResult returned and sets the complete variable to indicate * it has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (CPA_FALSE == verifyResult) { PRINT_ERR("Callback verify result error\n"); } if (NULL != pCallbackTag) { /** indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform an algorithm chaining operation */ static CpaStatus algChainPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, int dir) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = 0; /* 1 for combined head, including sessSeqNum and hdr, and the other for rest * of data */ Cpa32U numBuffers = 2; /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa32U SSL_CombinedHeadSize = 64; /* This is first record in data stream */ Cpa64U sessSeqNum = 0; Cpa8U padLen = 0; Cpa8U *pSrcBuffer = NULL; Cpa8U *pCombinedHeadBuffer = NULL; Cpa8U *pIvBuffer = NULL; int i = 0; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; COMPLETION_INIT(&complete); // Initialize the completion variable /* get meta information size */ status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { if (SSL_OUTBOUND_DIR == dir) { // bufferSize = sizeof(samplePayload) + MAC_LENGTH; /* bufferSize needs to be rounded up to a multiple of the AES block size */ padLen = 16 - bufferSize % 16; bufferSize += padLen; /* padLen excludes pad_length field */ padLen--; // } else { bufferSize = sizeof(expectedOutput); } status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pCombinedHeadBuffer, SSL_CombinedHeadSize); } if (CPA_STATUS_SUCCESS == status) { /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); // pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = numBuffers; pBufferList->pPrivateMetaData = pBufferMeta; /* Seq number */ pFlatBuffer->dataLenInBytes = SSL_CombinedHeadSize; pFlatBuffer->pData = pCombinedHeadBuffer; pFlatBuffer++; memcpy((char *)pCombinedHeadBuffer + SESSION_SEQ_START, &sessSeqNum, sizeof(sessSeqNum)); memcpy((char *)pCombinedHeadBuffer + HDR_START, sampleHdrData, sizeof(sampleHdrData)); /* Data */ pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; // /* copy source into buffer */ if (SSL_OUTBOUND_DIR == dir) { // memcpy(pSrcBuffer, samplePayload, sizeof(samplePayload)); /* Leave space for MAC but insert padding data */ for (i = 0; i <= padLen; i++) { pSrcBuffer[(sizeof(samplePayload) + MAC_LENGTH + i)] = padLen; } // } else { memcpy(pSrcBuffer, expectedOutput, sizeof(expectedOutput)); } status = PHYS_CONTIG_ALLOC(&pIvBuffer, sizeof(sampleCipherIv)); } if (CPA_STATUS_SUCCESS == status) { memcpy(pIvBuffer, sampleCipherIv, sizeof(sampleCipherIv)); status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if ((CPA_STATUS_SUCCESS == status) && (dir != SSL_OUTBOUND_DIR)) { // Cpa8U resBuff[16]; /* For decrypt direction need to decrypt the final block to determine the messageLenToHashInBytes */ status = sampleCodeAesCbcDecrypt(sampleCipherKey, sizeof(sampleCipherKey), (pSrcBuffer + (bufferSize - 32)), /* IV */ (pSrcBuffer + (bufferSize - 16)), /* src */ resBuff); /* dest */ /* padLen is the last byte decrypted incremented by one to * included the padLen block itself */ padLen = resBuff[15] + 1; // } if (CPA_STATUS_SUCCESS == status) { if (SSL_OUTBOUND_DIR == dir) { // pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = sizeof(sampleCipherIv); /* sequence number and header are not encrypted */ pOpData->cryptoStartSrcOffsetInBytes = SSL_CombinedHeadSize; pOpData->messageLenToCipherInBytes = bufferSize; pOpData->hashStartSrcOffsetInBytes = SESSION_SEQ_START; /* MAC to be calculated over sequence number, header and payload */ pOpData->messageLenToHashInBytes = sizeof(sessSeqNum) + sizeof(sampleHdrData) + sizeof(samplePayload); // } else { // pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = sizeof(sampleCipherIv); pOpData->cryptoStartSrcOffsetInBytes = SSL_CombinedHeadSize; pOpData->messageLenToCipherInBytes = bufferSize; pOpData->hashStartSrcOffsetInBytes = SESSION_SEQ_START; pOpData->messageLenToHashInBytes = sizeof(sessSeqNum) + sizeof(sampleHdrData) + bufferSize - MAC_LENGTH - padLen; // } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); /* pVerifyResult not required in async mode */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (SSL_OUTBOUND_DIR == dir) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG("Output matches expected generate encrypt\n"); } else { PRINT_DBG( "Output does not match expected generate encrypt\n"); status = CPA_STATUS_FAIL; } } else { if (0 == memcmp(pSrcBuffer, samplePayload, sizeof(samplePayload))) { PRINT_DBG( "Output matches expected output decrypt verify\n"); } else { PRINT_DBG("Output does not match expected output decrypt " "verify\n"); status = CPA_STATUS_FAIL; } } } } /* at this stage, the callback function has returned, so it is sure that * the structures won't be needed any more*/ PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pCombinedHeadBuffer); PHYS_CONTIG_FREE(pIvBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } CpaStatus algChainSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaCySymStats64 symStats = {0}; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { PRINT_DBG("No crypto instances available\n"); return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependant. */ sampleCyStartPolling(cyInstHandle); PRINT_DBG("Generate MAC - Encrypt\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CBC; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = MAC_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleAuthKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = sizeof(sampleAuthKey); /* MAC follows immediately after the region to hash */ sessionSetupData.digestIsAppended = CPA_TRUE; /* Generate the MAC in outbound direction */ sessionSetupData.verifyDigest = CPA_FALSE; // /* Determine size of session context to allocate */ status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOp(cyInstHandle, sessionCtx, SSL_OUTBOUND_DIR); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Decrypt-Verify MAC\n"); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CBC; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = MAC_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleAuthKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = sizeof(sampleAuthKey); /* MAC follows immediately after the region to hash */ sessionSetupData.digestIsAppended = CPA_TRUE; /* Verify the MAC in inbound direction */ sessionSetupData.verifyDigest = CPA_TRUE; // /* Initialize the session */ status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOp(cyInstHandle, sessionCtx, SSL_INBOUND_DIR); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (unsigned long long)symStats.numSymOpCompleted); } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_ssl_sample_user.c000066400000000000000000000100351503624047500364070ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/ssl_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_ssl_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus algChainSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting SSL Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = algChainSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nSSL Sample Code App failed\n"); } else { PRINT_DBG("\nSSL Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/symdp_sample/000077500000000000000000000000001503624047500326335ustar00rootroot00000000000000cpa_sym_dp_sample.c000066400000000000000000000430661503624047500364100ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/symdp_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric DP API, and * specifically using this API to perform a "chained" cipher and hash * operation. It encrypts some sample text using the AES-256 algorithm in * AES-GCM mode, and then performs an AES-GCM hash on the ciphertext. */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym_dp.h" #include "icp_sal_poll.h" #include "cpa_sample_utils.h" #define DIGEST_LENGTH 16 #define AES_BLOCK_SIZE 16 extern int gDebugParam; /* AES key, 256 bits long */ static Cpa8U sampleCipherKey[] = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08}; /* Initialization vector */ static Cpa8U sampleCipherIv[] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88}; /* Additional Authentication Data */ static Cpa8U sampleAddAuthData[] = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }; /* Source data to encrypt */ static Cpa8U sampleAlgChainingSrc[] = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39}; /* Expected output of the encryption operation with the specified * cipher (CPA_CY_SYM_CIPHER_AES_GCM), key (sampleCipherKey) and * initialization vector (sampleCipherIv) */ static Cpa8U expectedOutput[] = { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62, /* Digest */ 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }; CpaStatus symDpSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the operation has completed. * */ static void symDpCallback(CpaCySymDpOpData *pOpData, CpaStatus status, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); pOpData->pCallbackTag = (void *)1; } /* * Perform an algorithm chaining operation (cipher + hash) */ static CpaStatus symDpPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymDpOpData *pOpData = NULL; Cpa32U bufferSize = sizeof(sampleAlgChainingSrc) + DIGEST_LENGTH; Cpa8U *pSrcBuffer = NULL; Cpa8U *pIvBuffer = NULL; Cpa32U aadBuffSize = 0; Cpa8U *pAadBuffer = NULL; CpaInstanceInfo2 info2 = { 0 }; /* Allocate Src buffer */ status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); if (CPA_STATUS_SUCCESS == status) { /* Allocate IV buffer */ status = PHYS_CONTIG_ALLOC(&pIvBuffer, sizeof(sampleCipherIv)); } if (CPA_STATUS_SUCCESS == status) { /* Allocate memory for AAD. For GCM this memory will hold the * additional authentication data and any padding to ensure total * size is a multiple of the AES block size */ aadBuffSize = sizeof(sampleAddAuthData); if (aadBuffSize % AES_BLOCK_SIZE) { aadBuffSize += AES_BLOCK_SIZE - (aadBuffSize % AES_BLOCK_SIZE); } status = PHYS_CONTIG_ALLOC(&pAadBuffer, aadBuffSize); } if (CPA_STATUS_SUCCESS == status) { /* copy source into buffer */ memcpy(pSrcBuffer, sampleAlgChainingSrc, sizeof(sampleAlgChainingSrc)); /* copy IV into buffer */ memcpy(pIvBuffer, sampleCipherIv, sizeof(sampleCipherIv)); /* Copy AAD into buffer */ memcpy(pAadBuffer, sampleAddAuthData, sizeof(sampleAddAuthData)); /* Allocate memory for operational data. Note this needs to be * 8-byte aligned, contiguous, resident in DMA-accessible * memory. */ status = PHYS_CONTIG_ALLOC_ALIGNED(&pOpData, sizeof(CpaCySymDpOpData), 8); } if (CPA_STATUS_SUCCESS == status) { CpaPhysicalAddr pPhySrcBuffer; /** Populate the structure containing the operational data that is * needed to run the algorithm */ // pOpData->cryptoStartSrcOffsetInBytes = 0; pOpData->messageLenToCipherInBytes = sizeof(sampleAlgChainingSrc); pOpData->iv = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pIvBuffer, cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData->pIv = pIvBuffer; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = sizeof(sampleAlgChainingSrc); /* Even though MAC follows immediately after the region to hash digestIsAppended is set to false in this case due to errata number IXA00378322 */ pPhySrcBuffer = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pSrcBuffer, cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData->digestResult = pPhySrcBuffer + sizeof(sampleAlgChainingSrc); pOpData->instanceHandle = cyInstHandle; pOpData->sessionCtx = sessionCtx; pOpData->ivLenInBytes = sizeof(sampleCipherIv); pOpData->srcBuffer = pPhySrcBuffer; pOpData->srcBufferLen = bufferSize; pOpData->dstBuffer = pPhySrcBuffer; pOpData->dstBufferLen = bufferSize; pOpData->thisPhys = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pOpData, cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData->pCallbackTag = (void *)0; pOpData->additionalAuthData = virtAddrToDevAddr((SAMPLE_CODE_UINT *)(uintptr_t)pAadBuffer, cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData->pAdditionalAuthData = pAadBuffer; // } else { PRINT_ERR("Memory allocation failed. (status = %d)\n", status); PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pIvBuffer); PHYS_CONTIG_FREE(pAadBuffer); PHYS_CONTIG_FREE(pOpData); return status; } status = cpaCyInstanceGetInfo2(cyInstHandle, &info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymDpEnqueueOp\n"); /** Enqueue symmetric operation */ // status = cpaCySymDpEnqueueOp(pOpData, CPA_FALSE); // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpEnqueueOp failed. (status = %d)\n", status); } else { /* Can now enqueue other requests before submitting all requests to * the hardware. The cost of submitting the request to the hardware * is * then amortized across all enqueued requests. * In this simple example we have only 1 request to send */ PRINT_DBG("cpaCySymDpPerformOpNow\n"); /** Submit all enqueued symmetric operations to the hardware */ // status = cpaCySymDpPerformOpNow(cyInstHandle); // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpPerformOpNow failed. (status = %d)\n", status); } } } /* Can now enqueue more operations and/or do other work while * hardware processes the request. * In this simple example we have no other work to do * */ if (CPA_STATUS_SUCCESS == status) { /* Poll for responses. * Polling functions are implementation specific */ do { if (CPA_TRUE == info2.isPolled) { status = icp_sal_CyPollDpInstance(cyInstHandle, 1); } } while ( ((CPA_STATUS_SUCCESS == status) || (CPA_STATUS_RETRY == status)) && (pOpData->pCallbackTag == (void *)0)); } /* Check result */ if (CPA_STATUS_SUCCESS == status) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_ERR("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } } PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pIvBuffer); PHYS_CONTIG_FREE(pAadBuffer); PHYS_CONTIG_FREE(pOpData); return status; } CpaStatus symDpSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaInstanceInfo2 *info2 = NULL; status = OS_MALLOC(&info2, sizeof(CpaInstanceInfo2)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to allocate memory for info2"); return CPA_STATUS_FAIL; } /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { OS_FREE(info2); return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { status = cpaCyInstanceGetInfo2(cyInstHandle, info2); } #if !defined(SC_BSD_UPSTREAM) if (CPA_STATUS_SUCCESS == status) { if (info2->isPolled == CPA_FALSE) { status = CPA_STATUS_FAIL; PRINT_ERR("This sample code works only with instances " "configured in polling mode\n"); } } #endif if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* Register callback function for the instance */ // status = cpaCySymDpRegCbFunc(cyInstHandle, symDpCallback); // } if (CPA_STATUS_SUCCESS == status) { /* populate symmetric session data structure */ // sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_GCM; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_GCM; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(sampleAddAuthData); sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleCipherKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = sizeof(sampleCipherKey); /* Even though MAC follows immediately after the region to hash digestIsAppended is set to false in this case due to errata number IXA00378322 */ sessionSetupData.digestIsAppended = CPA_FALSE; sessionSetupData.verifyDigest = CPA_FALSE; /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymDpSessionCtxGetSize\n"); status = cpaCySymDpSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymDpInitSession\n"); status = cpaCySymDpInitSession(cyInstHandle, &sessionSetupData, sessionCtx); } #ifdef LAC_HW_PRECOMPUTES if (CPA_STATUS_SUCCESS == status && CPA_TRUE == info2->isPolled) { /* Poll for hw pre-compute responses. */ do { status = icp_sal_CyPollDpInstance(cyInstHandle, 0); } while (CPA_STATUS_SUCCESS != status); } #endif // if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = symDpPerformOp(cyInstHandle, sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymDpRemoveSession\n"); /* Wait for in-flight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); // sessionStatus = cpaCySymDpRemoveSession(cyInstHandle, sessionCtx); // /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); OS_FREE(info2); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_sym_dp_sample_user.c000066400000000000000000000075561503624047500374520ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/symdp_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ #include #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus symDpSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Sym Dp Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = symDpSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nSym Dp Sample Code App failed\n"); } else { PRINT_DBG("\nSym Dp Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/update_sample/000077500000000000000000000000001503624047500327615ustar00rootroot00000000000000cpa_sym_dp_update_sample.c000066400000000000000000000632631503624047500401010ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/update_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric DP API, and * specifically using this API to perform a "chained" cipher and hash * operation. It performs a SHA-256 hash on the ciphertext and then * encrypts some sample text using the AES-256 algorithm. It updates session * cipher key and auth key. It performs new cipher and hash operation * with new data. */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym_dp.h" #include "cpa_cy_sym.h" #include "icp_sal_poll.h" #include "cpa_sample_utils.h" #if CY_API_VERSION_AT_LEAST(2, 2) /* The digest length must be less than or equal length(4) for this example */ #define DIGEST_LENGTH 4 extern int gDebugParam; /* Initialization vector 64 bits long */ static const Cpa8U sampleIv[] = { 0x0F, 0x27, 0xDD, 0x05, 0x98, 0x58, 0xDE, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const Cpa8U updateIv[] = { 0x73, 0xDF, 0xFB, 0x1A, 0xE3, 0x26, 0x13, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* AES CCM, 128 bits long */ static Cpa8U sampleCipherKey[] = {0xB0, 0xFC, 0xBF, 0xE9, 0x4B, 0xFC, 0x91, 0xE4, 0x5B, 0xED, 0x56, 0x96, 0xE8, 0x11, 0x61, 0xA0}; static Cpa8U updateCipherKey[] = {0x23, 0x6A, 0xC9, 0xF3, 0x91, 0x63, 0x28, 0xC2, 0xDE, 0x73, 0xC7, 0xD7, 0x26, 0xFC, 0x70, 0x15}; /* Additional auth data 128 bits long */ static const Cpa8U additionalAuthData[] = {0xD7, 0xAE, 0x18, 0x44, 0xF7, 0xE7, 0x4A, 0x61, 0x10, 0x33, 0xA1, 0xF6, 0x08, 0x36, 0x0A, 0xAB}; static const Cpa8U updateAuthData[] = {0x2C, 0x37, 0x70, 0x63, 0x5F, 0x93, 0x04, 0xB6, 0xCE, 0xC7, 0xDD, 0x6F, 0x7E, 0x86, 0x61, 0x1D}; /* AES CCM, 512 bits long */ static Cpa8U sampleAuthKey[] = {0xD2, 0x3E, 0x6F, 0x12, 0x92, 0x1E, 0x51, 0x38, 0xED, 0x48, 0xCC, 0x25, 0x13, 0xF4, 0x78, 0x8F}; static Cpa8U updateAuthKey[] = {0xCE, 0xA4, 0x0F, 0x59, 0x9D, 0xA5, 0x0D, 0xA1, 0xEE, 0xE1, 0x3A, 0x8B, 0x3A, 0xAC, 0xAB, 0xAF}; /* Source data to encrypt 768 bits long */ static const Cpa8U sampleAlgChainingSrc[] = { 0x72, 0x09, 0x40, 0xDB, 0xD1, 0x40, 0x55, 0x47, 0x84, 0xB1, 0xAC, 0x8A, 0x87, 0x89, 0x7A, 0xAA, 0x1E, 0x87, 0xB1, 0x8D, 0xDC, 0x73, 0x94, 0x18, 0xC6, 0xD8, 0x00, 0x94, 0xBA, 0xCE, 0x77, 0x2C, 0xD7, 0xB7, 0x08, 0xA9, 0xF8, 0x5D, 0xF0, 0x7C, 0x0E, 0x9D, 0x06, 0x95, 0x26, 0x81, 0x3F, 0x45, 0x08, 0xF0, 0xD2, 0xE4, 0x63, 0x67, 0xFC, 0x2A, 0x3F, 0xFC, 0xBE, 0xF9, 0xCA, 0x35, 0x25, 0xA2, 0xED, 0x2D, 0x4B, 0xE5, 0x8A, 0x3B, 0x61, 0x98, 0xD8, 0x68, 0x2D, 0xFF, 0xE9, 0x6C, 0x44, 0xF1, 0x5C, 0x16, 0xD5, 0xC0, 0x7D, 0xD1, 0xEA, 0xBC, 0xCD, 0xA8, 0xB5, 0x98, 0xDD, 0xDB, 0x3A, 0xCA}; /* Update data to encrypt 1536 bits long */ static const Cpa8U updateAlgChainingSrc[] = { 0x7F, 0xD1, 0xF2, 0x23, 0x1E, 0x63, 0x9F, 0xA7, 0x34, 0xB4, 0x3D, 0x8E, 0x2C, 0x5E, 0x28, 0xE3, 0x85, 0xFB, 0x0C, 0xA7, 0x2F, 0x5F, 0x79, 0x19, 0x96, 0xC2, 0x33, 0x70, 0x97, 0x21, 0xF0, 0x1B, 0x45, 0x68, 0x90, 0x35, 0x27, 0x2F, 0xC6, 0x64, 0xDF, 0x32, 0xF8, 0x33, 0xC1, 0x2B, 0x49, 0x89, 0x2B, 0xD6, 0x0D, 0xA6, 0xA3, 0x5F, 0x2E, 0xF7, 0xE2, 0xEC, 0x94, 0xA8, 0x92, 0x0E, 0x94, 0xBF, 0x2F, 0xB8, 0x10, 0xAA, 0x60, 0x87, 0xFD, 0x1E, 0xCE, 0x5D, 0x5D, 0xAA, 0xEE, 0x5D, 0xBE, 0xF7, 0x60, 0x08, 0x27, 0x4A, 0xB1, 0x4C, 0x73, 0x11, 0xB8, 0x1B, 0x8E, 0x45, 0x4D, 0xA2, 0xBB, 0x5D, 0x4F, 0xCE, 0x8D, 0xB7, 0xB4, 0x04, 0x75, 0x49, 0xAC, 0x20, 0x20, 0xF5, 0x19, 0x0F, 0x46, 0xBB, 0x7A, 0x0A, 0x1C, 0xC1, 0x9A, 0x77, 0x88, 0x09, 0x75, 0x69, 0xC7, 0x29, 0xB6, 0x84, 0xB2, 0xFE, 0x3F, 0x96, 0xCB, 0x1C, 0x65, 0xD4, 0x91, 0x81, 0xDA, 0x3D, 0x97, 0xAD, 0x1A, 0x10, 0x50, 0xF5, 0x77, 0x38, 0x94, 0x92, 0x7A, 0x1F, 0xCA, 0xAD, 0xFC, 0x21, 0x9D, 0x52, 0x03, 0xD4, 0xC2, 0x7E, 0xDC, 0x34, 0x0F, 0xDA, 0x57, 0xD9, 0x71, 0x75, 0x98, 0xF4, 0x99, 0xBE, 0x7D, 0x6D, 0xB9, 0x4A, 0x5D, 0x18, 0x9F, 0x60, 0x5A, 0x5D, 0xAA, 0x83, 0x38, 0x6B, 0xBB, 0xAA, 0x38, 0x4A, 0xE4, 0x57}; /* Expected output of the algchain operation with the specified * cipher (CPA_CY_SYM_CIPHER_AES_CBC), hash (CPA_CY_SYM_HASH_SHA256), * key (sampleCipherKey), authKey (sampleAuthKey), initialization vector * (sampleIv) and additional authData (additionalAuthData) */ static const Cpa8U expectedOutput[] = { 0x3E, 0x4D, 0x3D, 0x44, 0xB3, 0x72, 0x24, 0x3F, 0xF1, 0xA1, 0xB3, 0x69, 0x0B, 0x8C, 0x3E, 0xCC, 0x98, 0xF8, 0xD2, 0x90, 0x31, 0xFE, 0xDE, 0x69, 0x58, 0x92, 0x1B, 0x53, 0xE5, 0x2E, 0xD9, 0x08, 0x07, 0xE0, 0x47, 0xE0, 0x4F, 0x22, 0x21, 0xBC, 0xD7, 0xCB, 0xC4, 0xC9, 0x02, 0xA6, 0xB1, 0xDC, 0xC4, 0x2A, 0xB7, 0x31, 0xFE, 0x03, 0xEB, 0xF3, 0xF8, 0xD5, 0xF4, 0x5F, 0x98, 0xBF, 0x04, 0x63, 0x4D, 0xE9, 0xC9, 0x33, 0x47, 0x71, 0xDD, 0x7B, 0xF3, 0x45, 0xD6, 0xD0, 0x8A, 0x56, 0xA6, 0x6B, 0x8C, 0xDB, 0x1B, 0x4E, 0x91, 0x2C, 0x0B, 0x6C, 0x76, 0x7E, 0x5A, 0x75, 0xC5, 0xF2, 0xF4, 0x99, 0x14, 0xDF, 0xB8, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Expected output of the algchain operation with the specified * cipher (CPA_CY_SYM_CIPHER_AES_CBC), hash (CPA_CY_SYM_HASH_SHA256), * key (updateCipherKey), authKey (updateAuthKey), initialization vector * (updateIv) and additional authData (updateAuthData) */ static const Cpa8U updateExpectedOutput[] = { 0xA1, 0x12, 0x6B, 0x61, 0xCF, 0x97, 0x4A, 0xC1, 0x59, 0x34, 0x6A, 0xD8, 0x2E, 0x32, 0xBA, 0x42, 0x05, 0xE3, 0xDD, 0x38, 0xE8, 0x27, 0x6B, 0x6D, 0xA5, 0x5A, 0x52, 0xB2, 0x1F, 0xEF, 0x76, 0x46, 0x23, 0x2B, 0xF9, 0xED, 0xF2, 0xD9, 0x9F, 0x02, 0xE9, 0xE8, 0xFA, 0xFE, 0x70, 0x9E, 0xE4, 0xE8, 0x14, 0x4F, 0xB0, 0x21, 0x8E, 0x16, 0xF7, 0xEE, 0x19, 0xC7, 0x84, 0xF5, 0x66, 0xD9, 0xD0, 0x58, 0x5B, 0xD5, 0x46, 0x02, 0xC2, 0xC8, 0x2C, 0x68, 0xAF, 0x1B, 0xFC, 0x30, 0xC6, 0x23, 0x51, 0xC6, 0xA4, 0x3F, 0x00, 0xB9, 0x9A, 0xE1, 0x18, 0x83, 0x73, 0xD1, 0x74, 0xD7, 0xAC, 0x0E, 0x6D, 0x5B, 0xF0, 0xE5, 0x35, 0x7F, 0xCE, 0x6D, 0x60, 0x56, 0x40, 0x4F, 0xFA, 0x20, 0x3B, 0xAF, 0xBE, 0x60, 0xE5, 0xF0, 0xC0, 0x11, 0xB4, 0xE1, 0xBB, 0xBF, 0x6B, 0x59, 0x1B, 0x1E, 0x99, 0x18, 0x13, 0x7D, 0x2B, 0x9A, 0x62, 0x7D, 0x2D, 0x98, 0x89, 0xED, 0xDD, 0x64, 0x25, 0x9F, 0x67, 0xD0, 0xDA, 0xA5, 0xE7, 0x5B, 0xC4, 0xA5, 0xD5, 0x08, 0xDB, 0x7D, 0x45, 0x67, 0x6E, 0x74, 0x83, 0xDA, 0x36, 0x8B, 0x6F, 0x10, 0xAB, 0xB6, 0x0B, 0x5A, 0xE7, 0x77, 0x0B, 0x1F, 0xAA, 0x4A, 0x1B, 0x1F, 0x4F, 0xF5, 0xBE, 0x88, 0xD1, 0x13, 0x92, 0x47, 0x4A, 0x5D, 0x4C, 0x8F, 0x58, 0x10, 0x16, 0xF4, 0xFB, 0x3A, 0xEE, 0x17, 0xA5, 0x95, 0x00 }; CpaStatus symDpUpdateSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the operation has completed. * */ static void symDpCallback(CpaCySymDpOpData *pOpData, CpaStatus status, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); pOpData->pCallbackTag = (void *)1; } /* * Perform session update */ static CpaStatus initSession(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx *sessionCtx, Cpa8U *pCipherKey, Cpa32U cipherKeyLen, Cpa8U *authKey, Cpa32U authKeyLen) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sessionCtxSize = 0; CpaCySymSessionSetupData sessionSetupData = {0}; /* populate symmetric session data structure */ // sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CBC; sessionSetupData.cipherSetupData.pCipherKey = pCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = cipherKeyLen; sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.authKey = authKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = authKeyLen; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = sizeof(additionalAuthData); sessionSetupData.digestIsAppended = CPA_TRUE; sessionSetupData.verifyDigest = CPA_FALSE; /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymDpSessionCtxGetSize\n"); status = cpaCySymDpSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymDpInitSession\n"); status = cpaCySymDpInitSession(cyInstHandle, &sessionSetupData, *sessionCtx); } // return status; } /* * Perform session update */ static CpaStatus updateSession(CpaCySymSessionCtx sessionCtx, Cpa8U *pCipherKey, Cpa8U *authKey) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymSessionUpdateData sessionUpdateData = {0}; PRINT_DBG("cpaCySymUpdateSession\n"); sessionUpdateData.flags = CPA_CY_SYM_SESUPD_CIPHER_KEY; sessionUpdateData.flags |= CPA_CY_SYM_SESUPD_AUTH_KEY; sessionUpdateData.pCipherKey = pCipherKey; sessionUpdateData.authKey = authKey; status = cpaCySymUpdateSession(sessionCtx, &sessionUpdateData); if (status != CPA_STATUS_SUCCESS) { PRINT_DBG("cpaCySymUpdateSession failed with status = %d.\n", status); } return status; } /* * Perform an algorithm chaining operation (cipher + hash) */ static CpaStatus symDpPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, const Cpa8U *pSrc, Cpa32U srcLen, const Cpa8U *pExpectedOutput, const Cpa8U *pIv, Cpa32U ivLen, const Cpa8U *pAdditionalAuth, Cpa32U additionalAuthLen) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymDpOpData *pOpData = NULL; Cpa32U bufferSize = srcLen + DIGEST_LENGTH; Cpa8U *pSrcBuffer = NULL; Cpa8U *pDstBuffer = NULL; Cpa8U *pIvBuffer = NULL; Cpa8U *pAdditionalAuthData = NULL; CpaInstanceInfo2 info2 = { 0 }; /* Allocate src buffer */ status = PHYS_CONTIG_ALLOC(&pSrcBuffer, srcLen); if (CPA_STATUS_SUCCESS == status) { /* Allocate dst buffer */ status = PHYS_CONTIG_ALLOC(&pDstBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate IV buffer */ status = PHYS_CONTIG_ALLOC(&pIvBuffer, ivLen); } if (CPA_STATUS_SUCCESS == status) { /* Allocate additionalAuthData buffer */ status = PHYS_CONTIG_ALLOC(&pAdditionalAuthData, sizeof(additionalAuthData)); } if (CPA_STATUS_SUCCESS == status) { /* Allocate memory for operational data. Note this needs to be * 8-byte aligned, contiguous, resident in DMA-accessible * memory. */ status = PHYS_CONTIG_ALLOC_ALIGNED(&pOpData, sizeof(CpaCySymDpOpData), 8); } if (CPA_STATUS_SUCCESS == status) { /* copy source into buffer */ memcpy(pSrcBuffer, pSrc, srcLen); /* copy IV into buffer */ memcpy(pIvBuffer, pIv, sizeof(sampleIv)); /* copy additional auth data into buffer */ memcpy(pAdditionalAuthData, pAdditionalAuth, additionalAuthLen); } else { PRINT_ERR("Memory allocation failed. (status = %d)\n", status); PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pDstBuffer); PHYS_CONTIG_FREE(pIvBuffer); PHYS_CONTIG_FREE(pAdditionalAuthData); PHYS_CONTIG_FREE(pOpData); return status; } status = cpaCyInstanceGetInfo2(cyInstHandle, &info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** Populate the structure containing the operational data that is * needed to run the algorithm */ pOpData->thisPhys = sampleVirtToPhys(pOpData); pOpData->instanceHandle = cyInstHandle; pOpData->sessionCtx = sessionCtx; pOpData->pCallbackTag = (void *)0; pOpData->cryptoStartSrcOffsetInBytes = 0; pOpData->messageLenToCipherInBytes = srcLen; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = srcLen; pOpData->digestResult = sampleVirtToPhys(pSrcBuffer) + srcLen; pOpData->iv = sampleVirtToPhys(pIvBuffer); pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = ivLen; pOpData->additionalAuthData = sampleVirtToPhys(pAdditionalAuthData); pOpData->pAdditionalAuthData = pAdditionalAuthData; pOpData->srcBuffer = sampleVirtToPhys(pSrcBuffer); pOpData->srcBufferLen = bufferSize; pOpData->dstBuffer = sampleVirtToPhys(pDstBuffer); pOpData->dstBufferLen = bufferSize; } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymDpEnqueueOp\n"); /** Enqueue symmetric operation */ // status = cpaCySymDpEnqueueOp(pOpData, CPA_FALSE); // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpEnqueueOp failed. (status = %d)\n", status); } else { /* Can now enqueue other requests before submitting all requests to * the hardware. The cost of submitting the request to the hardware * is * then amortized across all enqueued requests. * In this simple example we have only 1 request to send */ PRINT_DBG("cpaCySymDpPerformOpNow\n"); /** Submit all enqueued symmetric operations to the hardware */ // status = cpaCySymDpPerformOpNow(cyInstHandle); // if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpPerformOpNow failed. (status = %d)\n", status); } } } /* We can enqueue more operations and/or do other work while * hardware processes the request. * In this simple example we have no other work to do * */ if (CPA_STATUS_SUCCESS == status) { /* Poll for responses. * Polling functions are implementation specific */ do { if (CPA_TRUE == info2.isPolled) { status = icp_sal_CyPollDpInstance(cyInstHandle, 1); } } while ( ((CPA_STATUS_SUCCESS == status) || (CPA_STATUS_RETRY == status)) && (pOpData->pCallbackTag == (void *)0)); } /* Check result */ if (CPA_STATUS_SUCCESS == status) { if (0 == memcmp(pDstBuffer, pExpectedOutput, bufferSize)) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_ERR("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } } PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pDstBuffer); PHYS_CONTIG_FREE(pIvBuffer); PHYS_CONTIG_FREE(pAdditionalAuthData); PHYS_CONTIG_FREE(pOpData); return status; } CpaStatus symDpUpdateSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus sessionStatus = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; CpaInstanceHandle cyInstHandle = NULL; /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* Register callback function for the instance */ // status = cpaCySymDpRegCbFunc(cyInstHandle, symDpCallback); // } /* Init session with sampleCipherKey and sampleAuthKey */ sessionStatus = initSession(cyInstHandle, &sessionCtx, sampleCipherKey, sizeof(sampleCipherKey), sampleAuthKey, sizeof(sampleAuthKey)); if (CPA_STATUS_SUCCESS == sessionStatus) { /* Perform algchaining operation */ status = symDpPerformOp(cyInstHandle, sessionCtx, sampleAlgChainingSrc, sizeof(sampleAlgChainingSrc), expectedOutput, sampleIv, sizeof(sampleIv), additionalAuthData, sizeof(additionalAuthData)); /* Update the session with updateCipherKey and updateAuthKey*/ if (CPA_STATUS_SUCCESS == status) { status = updateSession(sessionCtx, updateCipherKey, updateAuthKey); } /* Perform algchaining operation with new src, iv, additional auth * data*/ if (CPA_STATUS_SUCCESS == status) { status = symDpPerformOp(cyInstHandle, sessionCtx, updateAlgChainingSrc, sizeof(updateAlgChainingSrc), updateExpectedOutput, updateIv, sizeof(updateIv), updateAuthData, sizeof(updateAuthData)); } } if (status == CPA_STATUS_SUCCESS) { status = sessionStatus; if (sessionStatus != CPA_STATUS_SUCCESS) { PRINT_DBG("CipherAlgorithm Not supported\n"); } } /* Clean up */ if (CPA_STATUS_SUCCESS == sessionStatus) { /* Wait for inflight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymDpRemoveSession\n"); // sessionStatus = cpaCySymDpRemoveSession(cyInstHandle, sessionCtx); // if (status == CPA_STATUS_SUCCESS) { status = sessionStatus; } /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); } /* Test end */ if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ cpa_sym_dp_update_sample_user.c000066400000000000000000000101111503624047500411170ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/update_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ #include #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus symDpUpdateSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { #if CY_API_VERSION_AT_LEAST(2, 2) CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting Sym Dp Update Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = symDpUpdateSample(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("\nSym Dp Update Sample Code App failed\n"); } else { PRINT_DBG("\nSym Dp Update Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; #else printf("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/zuc_sample/000077500000000000000000000000001503624047500323005ustar00rootroot00000000000000cpa_zuc_sample.c000066400000000000000000000454301503624047500353600ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/zuc_sample/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* * This is sample code that demonstrates usage of the symmetric API, and * specifically using this API to perform a ZUC operation. For more information * on ZUC please reference The ZUC-256 Stream Cipher " * http://www.is.cas.cn/ztzl2016/zouchongzhi/201801/W020180126529970733243.pdf" */ #include "cpa.h" #include "cpa_cy_im.h" #include "cpa_cy_sym.h" #include "cpa_sample_utils.h" #define DIGEST_LENGTH 16 #define TIMEOUT_MS 5000 /* 5 seconds*/ extern int gDebugParam; /* ZUC cipher key, 256 bits long */ static Cpa8U sampleCipherKey[] = { 0x7A, 0x8A, 0x5C, 0x43, 0x35, 0x87, 0x48, 0xE8, 0x3C, 0xFC, 0x05, 0x5B, 0xA7, 0xC1, 0x32, 0x72, 0xA1, 0x0A, 0xAE, 0x97, 0x92, 0x46, 0x62, 0xB9, 0x2C, 0xDF, 0xE4, 0x26, 0xAA, 0xD6, 0x09, 0x24}; /* Initialization vector */ static Cpa8U sampleCipherIv[] = { 0x24, 0xF0, 0x41, 0x1D, 0x2E, 0xA4, 0xAC, 0x7F, 0x63, 0x3E, 0xB7, 0x9F, 0xC3, 0x1C, 0xD1, 0x8D, 0xAF, 0xDD, 0x20, 0x80, 0xAE, 0x96, 0xAD, 0xFF}; /* ZUC authentication key, 256 bits long */ static Cpa8U sampleAuthKey[] = { 0xBF, 0xC1, 0xC4, 0x0F, 0x56, 0xE8, 0xC6, 0x53, 0x19, 0xA6, 0xBB, 0xEE, 0xF2, 0x96, 0x0A, 0xFD, 0x4C, 0xF6, 0x64, 0xA3, 0xFE, 0x0A, 0x2A, 0x8A, 0x14, 0x79, 0x67, 0xC0, 0xD3, 0xEC, 0xA4, 0x92}; /* Source data to encrypt */ static Cpa8U samplePayload[] = { 0x44, 0x09, 0xB5, 0xC3, 0xDD, 0x3E, 0x3D, 0x29, 0x09, 0xEF, 0x0E, 0x9F, 0xA6, 0xED, 0x0C, 0x92, 0xFD, 0xFD, 0xAD, 0x06, 0x88, 0x03, 0xE6, 0x98, 0x47, 0xD8, 0x5D, 0x9F, 0x34, 0x81, 0x0F, 0x79, 0x8B, 0xC5, 0x3C, 0x68, 0x03, 0x79, 0x91, 0x0C, 0x68, 0xA0, 0xAB, 0x0F, 0x8D, 0xB7, 0xA1, 0x8A, 0xB4, 0x4E, 0x90, 0x3D, 0x52, 0x77, 0xD5, 0x99, 0x4F, 0x32, 0x38, 0x84, 0xB3, 0x47, 0xFD, 0x3E, 0x0C, 0x39, 0xA6, 0x0F, 0xB3, 0x38, 0x1C, 0x1B, 0xD8, 0xC7, 0x2A, 0x65, 0x7F, 0xCC, 0xF0, 0x33, 0x1A, 0x80, 0x70, 0x6C, 0xF7, 0x45, 0x05, 0x47, 0x77, 0x3D, 0xCB, 0x2B, 0x85, 0xC8, 0x69, 0x91, 0x01, 0x10, 0xA1, 0xB4, 0x48, 0xBD, 0xD0, 0x20, 0x84, 0xFA, 0x85, 0x03, 0xC6, 0x75, 0x37, 0xE1, 0xF6, 0xA7, 0x4D, 0xED, 0xED, 0x53, 0x34, 0x64, 0x90, 0xFF, 0x8F, 0x15, 0xC7, 0xF9, 0xA7, 0xC9}; /* Expected output of the operation */ static Cpa8U expectedOutput[] = { 0x09, 0x5F, 0x1C, 0xF7, 0x08, 0x29, 0xC8, 0xED, 0x67, 0xF1, 0xAC, 0x29, 0xE1, 0x02, 0x2F, 0xA0, 0x1A, 0xC4, 0x8B, 0x72, 0x9B, 0xE9, 0xF0, 0xFD, 0x50, 0xE9, 0xBB, 0x73, 0x5B, 0xBA, 0x5C, 0x26, 0x32, 0xE8, 0x92, 0x98, 0xEC, 0xCB, 0x14, 0x85, 0x23, 0xF3, 0x5C, 0x5A, 0x4B, 0x79, 0xED, 0xD2, 0x57, 0xF8, 0xD6, 0xB3, 0x82, 0x1F, 0x44, 0x84, 0x9E, 0x7C, 0x09, 0xC7, 0xAC, 0x4D, 0x48, 0x62, 0xA6, 0xDB, 0x23, 0x14, 0x61, 0x2F, 0xB3, 0x17, 0x87, 0x21, 0x51, 0xD3, 0x63, 0x66, 0x22, 0xC9, 0x0F, 0xC9, 0x8F, 0xE4, 0x6B, 0x99, 0x63, 0x61, 0x57, 0xD5, 0x5D, 0xEE, 0xF7, 0x19, 0x8E, 0xCD, 0x45, 0xB5, 0xB3, 0x38, 0x81, 0x18, 0xE8, 0xA5, 0x45, 0xA1, 0x54, 0xF1, 0x47, 0x3D, 0xDE, 0x1A, 0x6A, 0x43, 0x78, 0x68, 0x30, 0x03, 0xF6, 0xF8, 0x46, 0x28, 0xC4, 0xC7, 0xE7, 0x1D, 0x64, 0xA4, 0xC3, 0xEE, 0xD1, 0x53, 0xD2, 0x17, 0x97, 0x3E, 0x9E, 0x3A, 0x58, 0x0C, 0x09, 0xE9, 0x82, 0xB5}; /* Association data */ static Cpa8U sampleAssocData[] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}; CpaStatus algChainSample(void); /* * Callback function * * This function is "called back" (invoked by the implementation of * the API) when the asynchronous operation has completed. The * context in which it is invoked depends on the implementation, but * as described in the API it should not sleep (since it may be called * in a context which does not permit sleeping, e.g. a Linux bottom * half). * * This function can perform whatever processing is appropriate to the * application. For example, it may free memory, continue processing * of a decrypted packet, etc. In this example, the function only * sets the complete variable to indicate it has been called. */ static void symCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { PRINT_DBG("Callback called with status = %d.\n", status); if (NULL != pCallbackTag) { /** indicate that the function has been called */ COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag); } } /* * Perform an algorithm chaining operation (cipher + hash) */ static CpaStatus algChainPerformOpZUC(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = sizeof(samplePayload) + DIGEST_LENGTH; Cpa32U aadBuffSize = sizeof(sampleAssocData); Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa8U *pIvBuffer = NULL; Cpa8U *pAadBuffer = NULL; CpaInstanceInfo2 instanceInfo2; /* The following variables are allocated on the stack because we block * until the callback comes back. If a non-blocking approach was to be * used then these variables should be dynamically allocated */ struct COMPLETION_STRUCT complete; COMPLETION_INIT(&complete); // Initialize the completion variable /* get meta information size */ PRINT_DBG("cpaCyBufferListGetMetaSize\n"); status = cpaCyBufferListGetMetaSize(cyInstHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize); } if (CPA_STATUS_SUCCESS == status) { status = OS_MALLOC(&pBufferList, bufferListMemSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize); } if (CPA_STATUS_SUCCESS == status) { status = PHYS_CONTIG_ALLOC(&pIvBuffer, sizeof(sampleCipherIv)); } if (CPA_STATUS_SUCCESS == status) { /* copy source into buffer */ memcpy(pSrcBuffer, samplePayload, sizeof(samplePayload)); /* copy IV into buffer */ memcpy(pIvBuffer, sampleCipherIv, sizeof(sampleCipherIv)); /* increment by sizeof(CpaBufferList) to get at the * array of flatbuffers */ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData)); } if (CPA_STATUS_SUCCESS == status) { aadBuffSize = sizeof(sampleAssocData); status = PHYS_CONTIG_ALLOC(&pAadBuffer, aadBuffSize); } if (CPA_STATUS_SUCCESS == status) { memcpy(pAadBuffer, sampleAssocData, sizeof(sampleAssocData)); } if (CPA_STATUS_SUCCESS == status) { status = cpaCyInstanceGetInfo2(cyInstHandle, &instanceInfo2); } if (CPA_STATUS_SUCCESS != status) { PRINT_DBG("sampleCodeCyGetNode error, status: %d\n", status); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { // /** Populate the structure containing the operational data that is * needed to run the algorithm */ pOpData->sessionCtx = sessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->pIv = pIvBuffer; pOpData->ivLenInBytes = sizeof(sampleCipherIv); pOpData->cryptoStartSrcOffsetInBytes = 0; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToCipherInBytes = sizeof(samplePayload); pOpData->messageLenToHashInBytes = sizeof(samplePayload); pOpData->pAdditionalAuthData = pAadBuffer; // /* pDigestResult does need need to be set as digestIsAppended was set at sessionInit */ } if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("cpaCySymPerformOp\n"); /** Perform symmetric operation */ status = cpaCySymPerformOp( cyInstHandle, (void *)&complete, /* data sent as is to the callback function*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* same src & dst for an in-place operation*/ NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status); } if (CPA_STATUS_SUCCESS == status) { /** wait until the completion of the operation*/ if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)) { PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)) { PRINT_DBG("Output matches expected output\n"); } else { PRINT_DBG("Output does not match expected output\n"); status = CPA_STATUS_FAIL; } } } /* at this stage, the callback function has returned, so it is sure that * the structures won't be needed any more*/ PHYS_CONTIG_FREE(pSrcBuffer); PHYS_CONTIG_FREE(pIvBuffer); PHYS_CONTIG_FREE(pAadBuffer); OS_FREE(pBufferList); PHYS_CONTIG_FREE(pBufferMeta); OS_FREE(pOpData); COMPLETION_DESTROY(&complete); return status; } CpaStatus algChainSample(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCySymSessionCtx sessionCtx = NULL; Cpa32U sessionCtxSize = 0; CpaInstanceHandle cyInstHandle = NULL; CpaCySymSessionSetupData sessionSetupData; CpaCySymStats64 symStats; CpaCySymCapabilitiesInfo symCapInfo = { { 0 } }; memset(&sessionSetupData, 0, sizeof(CpaCySymSessionSetupData)); memset(&symStats, 0, sizeof(CpaCySymStats64)); /* * In this simplified version of instance discovery, we discover * exactly one instance of a crypto service. */ sampleSymGetInstance(&cyInstHandle); if (cyInstHandle == NULL) { return CPA_STATUS_FAIL; } status = cpaCySymQueryCapabilities(cyInstHandle, &symCapInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to query capabilities, status = %d\n", status); return status; } /* Check capabilities before running the test */ if ((!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_ZUC_EEA3)) || (!CPA_BITMAP_BIT_TEST(symCapInfo.hashes, CPA_CY_SYM_HASH_ZUC_EIA3))) { PRINT("ZUC algorithm chaining not supported on Instance\n"); return CPA_STATUS_UNSUPPORTED; } /* Start Cryptographic component */ PRINT_DBG("cpaCyStartInstance\n"); status = cpaCyStartInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { /* * Set the address translation function for the instance */ status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys); } if (CPA_STATUS_SUCCESS == status) { /* * If the instance is polled start the polling thread. Note that * how the polling is done is implementation-dependent. */ sampleCyStartPolling(cyInstHandle); /* populate symmetric session data structure */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; // sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; sessionSetupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; sessionSetupData.cipherSetupData.cipherAlgorithm = CPA_CY_SYM_CIPHER_ZUC_EEA3; sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = sizeof(sampleCipherKey); sessionSetupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_ZUC_EIA3; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = DIGEST_LENGTH; sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleAuthKey; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = sizeof(sampleAuthKey); sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = 24; /* The resulting MAC is to be placed immediately after the ciphertext */ sessionSetupData.digestIsAppended = CPA_TRUE; sessionSetupData.verifyDigest = CPA_FALSE; // /* Determine size of session context to allocate */ PRINT_DBG("cpaCySymSessionCtxGetSize\n"); status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Allocate session context */ status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize); } if (CPA_STATUS_SUCCESS == status) { /* Initialize the session */ PRINT_DBG("cpaCySymInitSession\n"); status = cpaCySymInitSession( cyInstHandle, symCallback, &sessionSetupData, sessionCtx); } if (CPA_STATUS_SUCCESS == status) { CpaStatus sessionStatus = CPA_STATUS_SUCCESS; /* Perform algchaining operation */ status = algChainPerformOpZUC(cyInstHandle, sessionCtx); /* Wait for inflight requests before removing session */ symSessionWaitForInflightReq(sessionCtx); /* Remove the session - session init has already succeeded */ PRINT_DBG("cpaCySymRemoveSession\n"); sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx); /* maintain status of remove session only when status of all operations * before it are successful. */ if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } if (CPA_STATUS_SUCCESS == status) { /* Query symmetric statistics */ status = cpaCySymQueryStats64(cyInstHandle, &symStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status); } else { PRINT_DBG("Number of symmetric operation completed: %llu\n", (long long unsigned int)symStats.numSymOpCompleted); } } /* Clean up */ /* Free session Context */ PHYS_CONTIG_FREE(sessionCtx); /* Stop the polling thread */ sampleCyStopPolling(); PRINT_DBG("cpaCyStopInstance\n"); cpaCyStopInstance(cyInstHandle); if (CPA_STATUS_SUCCESS == status) { PRINT_DBG("Sample code ran successfully\n"); } else { PRINT_DBG("Sample code failed with status of %d\n", status); } return status; } cpa_zuc_sample_user.c000066400000000000000000000101771503624047500364160ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/functional/sym/zuc_sample/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ****************************************************************************** * @file cpa_zuc_sample_user.c * *****************************************************************************/ #include "cpa_sample_utils.h" #include "icp_sal_user.h" extern CpaStatus algChainSample(void); int gDebugParam = 1; int main(int argc, const char **argv) { CpaStatus stat = CPA_STATUS_SUCCESS; if (argc > 1) { gDebugParam = atoi(argv[1]); } PRINT_DBG("Starting ZUC Sample Code App ...\n"); stat = qaeMemInit(); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to initialize memory driver\n"); return (int)stat; } stat = icp_sal_userStartMultiProcess("SSL", CPA_FALSE); if (CPA_STATUS_SUCCESS != stat) { PRINT_ERR("Failed to start user process SSL\n"); qaeMemDestroy(); return (int)stat; } stat = algChainSample(); if ((CPA_STATUS_SUCCESS != stat) && (CPA_STATUS_UNSUPPORTED != stat)) { PRINT_ERR("\nZUC Sample Code App failed\n"); } else { PRINT_DBG("\nZUC Sample Code App finished\n"); } icp_sal_userStop(); qaeMemDestroy(); return (int)stat; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/000077500000000000000000000000001503624047500274655ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/000077500000000000000000000000001503624047500307555ustar00rootroot00000000000000qat_perf_buffer_utils.c000066400000000000000000000471621503624047500354260ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "qat_perf_buffer_utils.h" #include "cpa_cy_common.h" #include "cpa_dc.h" CpaStatus qatAllocateFlatBuffersInDpList(CpaPhysBufferList *list, Cpa32U node, Cpa32U numBuffers, Cpa32U bufferSize, Cpa32U alignment) { CpaStatus allocationStatus = CPA_STATUS_SUCCESS; Cpa32U i = 0; /* return fail if list is null*/ if (list == NULL) { PRINT_ERR("bufferList is null"); return CPA_STATUS_FAIL; } list->numBuffers = numBuffers; if (allocationStatus == CPA_STATUS_SUCCESS) { for (i = 0; i < numBuffers; i++) { /*this allocates a virtual ptr to physically contiguous memory. * Before being assigned to were its used it must be converted * to a physical address ptr using virt2phys conversion function*/ list->flatBuffers[i].bufferPhysAddr = (CpaPhysicalAddr)( uintptr_t)qaeMemAllocNUMA(bufferSize, node, alignment); if (NULL == (void *)(uintptr_t)list->flatBuffers[i].bufferPhysAddr) { PRINT_ERR("pBuffers[%u].pData allocation failed\n", i); allocationStatus = CPA_STATUS_FAIL; break; } list->flatBuffers[i].dataLenInBytes = bufferSize; } } // not able to allocate all memory, so free any that was allocated if (allocationStatus == CPA_STATUS_FAIL) { qatFreeFlatBuffersInDpList(list); } return allocationStatus; } CpaStatus qatFreeFlatBuffersInDpList(CpaPhysBufferList *list) { Cpa32U i = 0; CpaStatus allocationStatus = CPA_STATUS_SUCCESS; if (NULL == list) { PRINT_ERR("Cannot de-allocate: BufferList not allocated\n"); allocationStatus = CPA_STATUS_FAIL; } else { for (i = 0; i < list->numBuffers; i++) { if (NULL != (void *)(uintptr_t)list->flatBuffers[i].bufferPhysAddr) { qaeMemFreeNUMA((void **)&(list->flatBuffers[i].bufferPhysAddr)); if (NULL != (void *)(uintptr_t)list->flatBuffers[i].bufferPhysAddr) { PRINT("could not free pBuffers[%u].pData\n", i); allocationStatus = CPA_STATUS_FAIL; } } else { PRINT_ERR("pBuffers[%u].pData is already null\n", i); allocationStatus = CPA_STATUS_FAIL; } } } return allocationStatus; } CpaStatus qatAllocateFlatBuffersInList(CpaBufferList *list, Cpa32U node, Cpa32U bufferMetaSize, Cpa32U numBuffers, Cpa32U bufferSize, Cpa32U alignment) { CpaStatus allocationStatus = CPA_STATUS_SUCCESS; Cpa32U i = 0; /* return fail if list is null*/ if (list == NULL) { PRINT_ERR("bufferList is null"); return CPA_STATUS_FAIL; } list->pPrivateMetaData = qaeMemAllocNUMA(bufferMetaSize, node, alignment); if (NULL == list->pPrivateMetaData) { PRINT_ERR("pPrivateMetaData allocation failed\n"); allocationStatus = CPA_STATUS_FAIL; } if (allocationStatus == CPA_STATUS_SUCCESS) { list->numBuffers = numBuffers; list->pBuffers = qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * numBuffers, node, alignment); if (NULL == list->pBuffers) { PRINT_ERR("pBuffers allocation failed\n"); allocationStatus = CPA_STATUS_FAIL; } } if (allocationStatus == CPA_STATUS_SUCCESS) { for (i = 0; i < numBuffers; i++) { list->pBuffers[i].pData = qaeMemAllocNUMA(bufferSize, node, alignment); if (NULL == list->pBuffers[i].pData) { PRINT_ERR("pBuffers[%u].pData allocation failed\n", i); allocationStatus = CPA_STATUS_FAIL; break; } list->pBuffers[i].dataLenInBytes = bufferSize; } } // not able to allocate all memory, so free any that was allocated if (allocationStatus == CPA_STATUS_FAIL) { qatFreeFlatBuffersInList(list); } return allocationStatus; } CpaStatus qatFreeFlatBuffersInList(CpaBufferList *list) { Cpa32U i = 0; CpaStatus allocationStatus = CPA_STATUS_SUCCESS; if (NULL == list) { PRINT_ERR("Cannot de-allocate: BufferList not allocated\n"); allocationStatus = CPA_STATUS_FAIL; } else { for (i = 0; i < list->numBuffers; i++) { if ((NULL != list->pBuffers) && (NULL != list->pBuffers[i].pData)) { qaeMemFreeNUMA((void **)&(list->pBuffers[i].pData)); if (NULL != list->pBuffers[i].pData) { PRINT("could not free pBuffers[%u].pData\n", i); allocationStatus = CPA_STATUS_FAIL; } } else { PRINT_ERR("pBuffers[%u].pData is already null\n", i); allocationStatus = CPA_STATUS_FAIL; } } qaeMemFreeNUMA((void **)&(list->pBuffers)); if (NULL != list->pBuffers) { PRINT("could not free pBuffers\n"); allocationStatus = CPA_STATUS_FAIL; } if (NULL != list->pPrivateMetaData) { qaeMemFreeNUMA((void **)&(list->pPrivateMetaData)); if (NULL != list->pPrivateMetaData) { PRINT_ERR("could not free privateMetaData\n"); allocationStatus = CPA_STATUS_FAIL; } } } return allocationStatus; } CpaStatus qatPrintBuffListDetails(CpaBufferList *list) { Cpa32U i = 0; if (NULL != list) { PRINT("Addr %p, ", list); PRINT("numBuffers %u, ", list->numBuffers); PRINT("PrivateMetaData %p, ", (void *)list->pPrivateMetaData); PRINT("pBuffer addr: %p, ", list->pBuffers); if (NULL != list->pBuffers) { for (i = 0; i < list->numBuffers; i++) { if (NULL != list->pBuffers[i].pData) { PRINT( "pBuffer[%u].pData = %p, ", i, list->pBuffers[i].pData); PRINT("pBuffer[%u].dataLenInBytes = %u, ", i, list->pBuffers[i].dataLenInBytes); } } } PRINT("\n"); } else { PRINT("BufferList not allocated\n"); } return CPA_STATUS_SUCCESS; } void qatPrintFlatBuffer(CpaFlatBuffer *flatBuffer) { Cpa32U i = 0; if (NULL != flatBuffer) { for (i = 0; i < flatBuffer->dataLenInBytes; i++) { PRINT("%02x", flatBuffer->pData[i]); if (((i + 1) % 16) == 0) { PRINT("\n"); } else { PRINT(" "); } if (((i + 1) % 8) == 0 && ((i + 1) % 16) != 0) { PRINT("- "); } } PRINT("\n"); } else { PRINT("CpaFlatBuffer not allocated\n"); } return; } CpaStatus AllocArrayOfStructures(void **structureArrayPtr, Cpa32U numStructures, Cpa32U sizeOfStructure) { CpaStatus allocationStatus = CPA_STATUS_SUCCESS; Cpa64U *ptr = (Cpa64U *)*structureArrayPtr; if (ptr != NULL || numStructures == 0 || sizeOfStructure == 0) { PRINT_ERR("Invalid parameter passed into AllocArrayOfStructures\n"); PRINT_ERR("arrayPtr %p, numStructures %d, sizeOfStructure %d\n", ptr, numStructures, sizeOfStructure); allocationStatus = CPA_STATUS_FAIL; } else { *structureArrayPtr = qaeMemAlloc((size_t)sizeOfStructure * numStructures); if (*structureArrayPtr == NULL) { allocationStatus = CPA_STATUS_FAIL; } else { memset( *structureArrayPtr, 0, (size_t)sizeOfStructure * numStructures); } } return allocationStatus; } CpaStatus FreeArrayOfStructures(void **structureArrayPtr) { CpaStatus freeStatus = CPA_STATUS_SUCCESS; if (structureArrayPtr == NULL) { PRINT_ERR("Cannot de-allocate: BufferList not allocated\n"); freeStatus = CPA_STATUS_FAIL; } else { qaeMemFree(structureArrayPtr); if (NULL != *structureArrayPtr) { PRINT_ERR("could not free structure\n"); freeStatus = CPA_STATUS_FAIL; } } return freeStatus; } CpaStatus qatAllocateBuffersInDpLists(CpaPhysBufferList *arrayOfBufferLists, Cpa32U numberOfLists, Cpa32U numberOfBuffersPerList, Cpa32U testBufferSize, Cpa32U node, Cpa32U alignment) { Cpa32U i = 0; Cpa32S j = 0; CpaStatus allocationStatus = CPA_STATUS_SUCCESS; for (i = 0; i < numberOfLists; i++) { allocationStatus = qatAllocateFlatBuffersInDpList(&arrayOfBufferLists[i], node, numberOfBuffersPerList, testBufferSize, alignment); if (allocationStatus == CPA_STATUS_FAIL) { /*need to free any list that has already been successfully * allocated*/ for (j = i - 1; j >= 0; j--) { qatFreeFlatBuffersInDpList(&arrayOfBufferLists[j]); } break; } } return allocationStatus; } CpaStatus qatFreeBuffersInDpLists(CpaPhysBufferList *arrayOfBufferLists, Cpa32U numberOfLists) { Cpa32U counter = 0; CpaStatus freeStatus = CPA_STATUS_SUCCESS; for (counter = 0; counter < numberOfLists; counter++) { /*attempt to free all lists and capture any failed return status*/ if (CPA_STATUS_SUCCESS != qatFreeFlatBuffersInDpList(&arrayOfBufferLists[counter])) { freeStatus = CPA_STATUS_FAIL; } } return freeStatus; } CpaStatus freeBuffersInLists(CpaBufferList *arrayOfBufferLists, Cpa32U numberOfLists) { Cpa32U counter = 0; CpaStatus freeStatus = CPA_STATUS_SUCCESS; for (counter = 0; counter < numberOfLists; counter++) { /*attempt to free all lists and capture any failed return status*/ if (CPA_STATUS_SUCCESS != qatFreeFlatBuffersInList(&arrayOfBufferLists[counter])) { freeStatus = CPA_STATUS_FAIL; } } return freeStatus; } CpaStatus AllocateBuffersInLists(CpaBufferList *arrayOfBufferLists, Cpa32U numberOfLists, Cpa32U numberOfBuffersPerList, Cpa32U *testBufferSize, Cpa32U additionalBufferSize, Cpa32U metaSize, Cpa32U node, Cpa32U alignment) { Cpa32U i = 0; Cpa32S j = 0; CpaStatus allocationStatus = CPA_STATUS_SUCCESS; for (i = 0; i < numberOfLists; i++) { allocationStatus = qatAllocateFlatBuffersInList( &arrayOfBufferLists[i], node, metaSize, numberOfBuffersPerList, testBufferSize[i] + additionalBufferSize, alignment); if (allocationStatus == CPA_STATUS_FAIL) { /*need to free any list that has already been successfully * allocated*/ for (j = i - 1; j >= 0; j--) { qatFreeFlatBuffersInList(&arrayOfBufferLists[j]); } break; } } return allocationStatus; } CpaStatus allocateAndSetArrayOfPacketSizes(Cpa32U **pPacketSize, Cpa32U packetSize, Cpa32U numLists) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; Cpa32U packetMix[] = { BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_8992, BUFFER_SIZE_64, BUFFER_SIZE_1504}; Cpa32U mixIndex = sizeof(packetMix) / sizeof(Cpa32U); *pPacketSize = qaeMemAlloc(sizeof(Cpa32U) * numLists); if (NULL == *pPacketSize) { PRINT_ERR("Could not allocate memory for pPacketSize\n"); status = CPA_STATUS_FAIL; } else { if (packetSize == PACKET_IMIX) { /*we are testing IMIX so we copy buffer sizes from pre-allocated * array into symTestSetup.numBuffLists*/ for (i = 0; i < numLists; i++) { (*pPacketSize)[i] = packetMix[i % mixIndex]; } } else { /*we are testing a uniform bufferSize, so we set the bufferSize * array accordingly*/ for (i = 0; i < numLists; i++) { (*pPacketSize)[i] = packetSize; } } } return status; } /*copy the corpus that was read from file into memory in the setupScDcTest * function, into the CpaFlatBuffers that have been allocated*/ CpaStatus PopulateBuffers(CpaBufferList *arrayOfSrcBufferLists, Cpa32U numberOfLists, Cpa8U *corpusFilePtr, Cpa32U corpusFileSize, Cpa32U *testBufferSize) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *filePtr = NULL; Cpa32U copiedLen = 0; Cpa32U i = 0; filePtr = corpusFilePtr; /* Copy the data into Flat buffers */ for (i = 0; i < numberOfLists; i++) { if (arrayOfSrcBufferLists[i].pBuffers->pData == NULL) { PRINT_ERR("cannot copy to NULL ptr in pData\n"); return CPA_STATUS_FAIL; } if (corpusFilePtr == NULL) { generateRandomData(arrayOfSrcBufferLists[i].pBuffers->pData, testBufferSize[i]); } else { if ((corpusFileSize < testBufferSize[i]) || ((corpusFileSize - copiedLen) < testBufferSize[i])) { memcpy((arrayOfSrcBufferLists[i].pBuffers->pData), filePtr, (corpusFileSize - copiedLen)); continue; } memcpy((arrayOfSrcBufferLists[i].pBuffers->pData), filePtr, testBufferSize[i]); filePtr += testBufferSize[i]; copiedLen += testBufferSize[i]; } } return status; } CpaStatus copyBuffers(CpaBufferList *srcBufferListArray, CpaBufferList *copyBufferListArray, Cpa32U numberOfLists) { Cpa32U j = 0; for (j = 0; j < numberOfLists; j++) { memcpy((copyBufferListArray[j].pBuffers->pData), srcBufferListArray[j].pBuffers->pData, srcBufferListArray[j].pBuffers->dataLenInBytes); } return CPA_STATUS_SUCCESS; } CpaPhysicalAddr virtAddrToDevAddr(void *pVirtAddr, CpaInstanceHandle instanceHandle, CpaAccelerationServiceType type) { CpaStatus status; CpaInstanceInfo2 instanceInfo = {0}; /*get the addressTranslation mode*/ switch (type) { #ifdef DO_CRYPTO case CPA_ACC_SVC_TYPE_CRYPTO: status = cpaCyInstanceGetInfo2(instanceHandle, &instanceInfo); break; #endif case CPA_ACC_SVC_TYPE_DATA_COMPRESSION: status = cpaDcInstanceGetInfo2(instanceHandle, &instanceInfo); break; default: status = CPA_STATUS_UNSUPPORTED; } if (CPA_STATUS_SUCCESS != status) { return (CpaPhysicalAddr)(uintptr_t)NULL; } if (instanceInfo.requiresPhysicallyContiguousMemory) { return qaeVirtToPhysNUMA(pVirtAddr); } else { return (CpaPhysicalAddr)(uintptr_t)pVirtAddr; } } qat_perf_buffer_utils.h000066400000000000000000000577361503624047500354430ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file qat_perf_buffer_utils.h * * @ingroup sample_code * * @description * This file defines memory management functions for structures used * in the QuickAssist API such as CpaBufferLists, CpaFlatBuffers and other * structures * *****************************************************************************/ #ifndef CPA_SAMPLE_CODE_BUFFER_UTILS_H #define CPA_SAMPLE_CODE_BUFFER_UTILS_H #include "cpa_sample_code_utils_common.h" #define BYTE_ALIGNMENT_64 (64) #define PACKET_IMIX (0) #define BUFFER_SIZE_0 (0) #define BUFFER_SIZE_32 (32) #define BUFFER_SIZE_40 (40) #define BUFFER_SIZE_64 (64) #define BUFFER_SIZE_128 (128) #define BUFFER_SIZE_256 (256) #define BUFFER_SIZE_304 (304) #define BUFFER_SIZE_320 (320) #define BUFFER_SIZE_512 (512) #define BUFFER_SIZE_752 (752) #define BUFFER_SIZE_768 (768) #define BUFFER_SIZE_1024 (1024) #define BUFFER_SIZE_1152 (1152) #define BUFFER_SIZE_1280 (1280) #define BUFFER_SIZE_1504 (1504) #define BUFFER_SIZE_1536 (1536) #define BUFFER_SIZE_2048 (2048) #define BUFFER_SIZE_4096 (4096) #define BUFFER_SIZE_7680 (7680) #define BUFFER_SIZE_8192 (8192) #define BUFFER_SIZE_8992 (8992) #define BUFFER_SIZE_16384 (16384) #define BUFFER_SIZE_32768 (32768) #define BUFFER_SIZE_65536 (65536) /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description allocate the members of a CpaPhysBufferList * namely: cpaPhysFlatBuffers, and set the * number of FlatBuffers for this list * * @param[in] list CpaPhysBufferList * @param[in] node Numa node to allocate memory on * @param[in] numBuffers Amount of cpaFlatBuffers to be allocated * to this list * @param[in] bufferSize size of cpaFlatBuffers to be allocated * @param[in] alignment alignment of pBuffer, pMetaData and pData in * list * * @pre bufferList is already allocated * * @post all flatBuffers allocated. numBuffers is * set * * @retval CPA_STATUS_SUCCESS Function executed successfully all * memory was allocated * * @retval CPA_STATUS_FAIL No memory was allocated (any partial * allocated memory is free before return of * function ****************************************************************************/ CpaStatus qatAllocateFlatBuffersInDpList(CpaPhysBufferList *list, Cpa32U node, Cpa32U numBuffers, Cpa32U bufferSize, Cpa32U alignment); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description free all memory allocated by * qatAllocatePhysFlatBuffersInPhysList * * @param[in] list address of bufferList pointer to be freed * to this list * * @pre pointer to bufferList is allocated in memory * * @post all bufferList memory is freed * * @retval CPA_STATUS_SUCCESS all memory free * @retval CPA_STATUS_FAIL one or more parts of the list could * not be freed * ****************************************************************************/ CpaStatus qatFreeFlatBuffersInDpList(CpaPhysBufferList *list); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description allocate the members of a CpaBufferList * namely: cpaFlatBuffers, privateMetaData and * set the number of FlatBuffers for this list * * @param[in] list CpaBufferList * @param[in] node Numa node to allocate memory on * @param[in] bufferMetaSize size of private metaData to be allocated * @param[in] numBuffers Amount of cpaFlatBuffers to be allocated * to this list * @param[in] bufferSize size of cpaFlatBuffers to be allocated * @param[in] alignment alignment of pBuffer, pMetaData and pData in * list * * @pre bufferList is already allocated * * @post all flatBuffers and PrivateMetaData * allocated. numBuffers is set * * @retval CPA_STATUS_SUCCESS Function executed successfully all * memory was allocated * * @retval CPA_STATUS_FAIL No memory was allocated (any partial * allocated memory is free before return of * function ****************************************************************************/ CpaStatus qatAllocateFlatBuffersInList(CpaBufferList *list, Cpa32U node, Cpa32U bufferMetaSize, Cpa32U numBuffers, Cpa32U bufferSize, Cpa32U alignment); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description free all memory allocated by * qatAllocateFlatBuffersInList * * @param[in] list address of bufferList pointer to be freed * to this list * * @pre pointer to bufferList is allocated in memory * * @post all bufferList memory is freed * * @retval CPA_STATUS_SUCCESS all memory free * @retval CPA_STATUS_FAIL one or more parts of the list could * not be freed * ****************************************************************************/ CpaStatus qatFreeFlatBuffersInList(CpaBufferList *list); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description print out the contents of the buffer list * * @param[in] list address of bufferList to be printed * * @pre pointer to bufferList is allocated in memory * * @post all list information is printed to the * console * * @retval CPA_STATUS_SUCCESS this function only returns success * ****************************************************************************/ CpaStatus qatPrintBuffListDetails(CpaBufferList *list); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description print out the contents of the flat buffer * * @param[in] list address of CpaFlatBuffer to be printed * * @pre pointer to CpaFlatBuffer is allocated in * memory * * @post the buffer data is printed to the * console * ****************************************************************************/ void qatPrintFlatBuffer(CpaFlatBuffer *flatBuffer); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description allocate an array of structures, such as * bufferLists * * @param[in] structureArrayPtr pointer to pointer of structure to be * Allocated * @param[in] numStructures number of structures to be allocated * @param[in] sizeOfStructure size of the structure to be allocated * * @pre pointer to pointer structureArrayPtr is NULL * * @post an array of structures is allocated or * otherwise fail status is returned * * @retval CPA_STATUS_SUCCESS array of structures is allocated * @retval CPA_STATUS_FAIL could not allocate memory * ****************************************************************************/ CpaStatus AllocArrayOfStructures(void **structureArrayPtr, Cpa32U numStructures, Cpa32U sizeOfStructure); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description free an array of structures * * @param[in] structureArrayPtr pointer to pointer of structure to be * freed * * @pre pointer to pointer structureArrayPtr is not * NULL * * @post an array of structures is freed or * otherwise fail status is returned * * @retval CPA_STATUS_SUCCESS array of structures is freed * @retval CPA_STATUS_FAIL could not free memory * ****************************************************************************/ CpaStatus FreeArrayOfStructures(void **structureArrayPtr); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description free all CpaFlatBuffers and privateMetaData * in an array of lists * * @param[in] arrayOfBufferLists pointer to array of * cpaBufferLists * * @pre pointer to pointer arrayOfBufferLists is not * NULL, CpaPhysFlatBuffers has been allocated * * @post the internals of the CpaBufferLists have * been freed * * @retval CPA_STATUS_SUCCESS CpaPhysBufferLists is freed * @retval CPA_STATUS_FAIL could not free memory * ****************************************************************************/ CpaStatus qatFreeBuffersInDpLists(CpaPhysBufferList *arrayOfBufferLists, Cpa32U numberOfLists); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description allocate all CpaPhysFlatBuffers in an * array of lists * * @param[in] arrayOfBufferLists pointer to array of cpaPhysBufferLists * @param[in] numberOfLists number of lists in the array * @param[in] numberOfBuffersPerList number of CpaPhysFlatBuffers to be * allocated in each list * @param[in] testBufferSize size of each CpaPhysFlatBuffer * allocated * @param[in] node CPU node to allocate the memory on * @param[in] alignment alignment of the memory to allocation * * @pre pointer to pointer arrayOfBufferLists * is not NULL, CpaPhysFlatBuffers has * not been allocated * * @post the internals of the * CpaPhysBufferLists are allocated * * @retval CPA_STATUS_SUCCESS CpaPhysBufferLists internals are * allocated * @retval CPA_STATUS_FAIL could not allocate memory * ****************************************************************************/ CpaStatus qatAllocateBuffersInDpLists(CpaPhysBufferList *arrayOfBufferLists, Cpa32U numberOfLists, Cpa32U numberOfBuffersPerList, Cpa32U testBufferSize, Cpa32U node, Cpa32U alignment); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description free all CpaFlatBuffers and * privateMetaData in an array of lists * * @param[in] arrayOfBufferLists pointer to array of cpaBufferLists * * @pre pointer to pointer arrayOfBufferLists * is not NULL, CpaFlatBuffers and * provateMetaData has been allocated * * @post the internals of the CpaBufferLists * have been freed * * @retval CPA_STATUS_SUCCESS CpaBufferLists an privateMetaData is * freed * @retval CPA_STATUS_FAIL could not free memory * ****************************************************************************/ CpaStatus freeBuffersInLists(CpaBufferList *arrayOfBufferLists, Cpa32U numberOfLists); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description allocate all CpaFlatBuffers and * privateMetaData in an array of lists * * @param[in] arrayOfBufferLists pointer to array of cpaBufferLists * @param[in] numberOfLists number of lists in the array * @param[in] numberOfBuffersPerList number of CpaPhysFlatBuffers to be * allocated in each list * @param[in] testBufferSize size of each CpaPhysFlatBuffer * allocated * @param[in] additionalBufferSize additional buffer spaced that needs to * be allocated to store digest in the case * of crypto or expansion of data in the * case of compression of small buffers * @param[in] metaSize * @param[in] node CPU node to allocate the memory on * @param[in] alignment alignment of the memory to allocation * * @pre pointer to pointer arrayOfBufferLists * is not NULL, CpaFlatBuffers and * privateMetaData has been yet been * allocated * * @post the internals of the CpaBufferLists are * Allocated * * @retval CPA_STATUS_SUCCESS CpaBufferLists an privateMetaData are * Allocated * @retval CPA_STATUS_FAIL could not free memory * ****************************************************************************/ CpaStatus AllocateBuffersInLists(CpaBufferList *arrayOfSrcBufferLists, Cpa32U numberOfLists, Cpa32U numberOfBuffersPerList, Cpa32U *testBufferSize, Cpa32U additionalBufferSize, Cpa32U metaSize, Cpa32U node, Cpa32U alignment); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description allocate array of packetSizes, to * support mixing packet sizes * * @param[in] packetSize sizes to be set in array, when this * parameter is 0 the array is populated * with the IMIX * @param[in] numberOfLists numberOfLists to spread the packetSizes * over * * @pre numLists must be a multiple of 20 for * the IMIX * * @post packetSize array is populated with the * packetSize to be submitted for each * request * * @retval CPA_STATUS_SUCCESS CpaBufferLists an privateMetaData are * Allocated * @retval CPA_STATUS_FAIL could not free memory * ****************************************************************************/ CpaStatus allocateAndSetArrayOfPacketSizes(Cpa32U **pPacketSize, Cpa32U packetSize, Cpa32U numLists); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description populate the arrayOfSrcBufferLists with * data for compression or encryption * * @param[in] packetSize numberOfLists to be populated * @param[in] corpusFilePtr pointer to corpus file to be copied * into bufferLists, when this is NULL, * the buffers are populated with random * data * @param[in] testBufferSize size of BufferLists to be populated * * @pre buffersLists and there respective flat * buffers must be allocated with enough * space * * @post buffers contain the corpus data or * random data * * @retval CPA_STATUS_SUCCESS CpaBufferLists are populated * @retval CPA_STATUS_FAIL CpaBufferLists could not be populated * ****************************************************************************/ CpaStatus PopulateBuffers(CpaBufferList *arrayOfSrcBufferLists, Cpa32U numberOfLists, Cpa8U *corpusFilePtr, Cpa32U corpusFileSize, Cpa32U *testBufferSize); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description copy the contents from 1 bufferList to * another * * @param[in] srcBufferListArray source list to be copied * @param[in] copyBufferListArray destination of copied data * @param[in] numberOfLists number of lists to copy * * @pre buffersLists and there respective flat * buffers must be allocated with enough * space * * @post copyBufferListArray is a copy of * srcBufferListArray * * @retval CPA_STATUS_SUCCESS CpaBufferLists are copied * @retval CPA_STATUS_FAIL CpaBufferLists could not be copied * ****************************************************************************/ CpaStatus copyBuffers(CpaBufferList *srcBufferListArray, CpaBufferList *copyBufferListArray, Cpa32U numberOfLists); /** ***************************************************************************** * @file qat_perf_buffer_utils.c * * @ingroup sample_code * * @description convert virtual address of a buffer * to address that can be accessed by * the owner of the instance from * device point of view * * @param[in] pVirtAddr virtual address of the buffer * @param[in] instance crypto instance handle * @param[in] type service type * * @retval CpaPhysicalAddr address from device point of view, * or NULL if failed to convert * ****************************************************************************/ CpaPhysicalAddr virtAddrToDevAddr(void *pVirtAddr, CpaInstanceHandle instance, CpaAccelerationServiceType type); #endif /* CPA_SC_BUFFER_UTILS_H*/ qat_perf_cycles.h000066400000000000000000000543201503624047500342160ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description * This file contains inline functions used to measure cost of offload * *****************************************************************************/ #ifndef __QAT_PERF_CYCLES_H_ #define __QAT_PERF_CYCLES_H_ #include "icp_sal_poll.h" /* Global state of initialization */ static Cpa8U coo_initialized = CPA_FALSE; /* This is used to define a pointer to a function */ typedef CpaStatus (*coo_poll_func)(CpaInstanceHandle, Cpa32U); /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function is used to init coo values * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] size number of operations used to allocate * memory for coo values * * @retval CPA_STATUS_SUCCESS Coo is initialized and all memory was * allocated * * @retval CPA_STATUS_FAIL Coo is not initialized and memory is freed * before return of function * ****************************************************************************/ static inline void coo_init(perf_data_t *perf_data, Cpa64U size) { if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g) { perf_data->req_temp = 0; perf_data->cost_temp = 0; perf_data->req_count = 0; perf_data->req_cost_count = 0; perf_data->poll_cost_count = 0; perf_data->req_sum_cycles = 0; perf_data->req_cost_sum_cycles = 0; perf_data->poll_sum_cycles = 0; perf_data->poll_cost_sum_cycles = 0; coo_initialized = CPA_TRUE; } } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function is used reset coo values * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * ****************************************************************************/ static inline void coo_deinit(perf_data_t *perf_data) { if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g) { perf_data->req_temp = 0; perf_data->cost_temp = 0; perf_data->req_count = 0; perf_data->req_cost_count = 0; perf_data->poll_cost_count = 0; perf_data->req_sum_cycles = 0; perf_data->req_cost_sum_cycles = 0; perf_data->poll_sum_cycles = 0; perf_data->poll_cost_sum_cycles = 0; coo_initialized = CPA_FALSE; } } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function is used to retrieve timestamp * * @retval perf_cycles_t time stamp value * ****************************************************************************/ static inline perf_cycles_t coo_timestamp(void) { #ifdef __x86_64__ uint32_t cycles_high; uint32_t cycles_low; __asm__ volatile( "rdtscp\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" : "=r"(cycles_high), "=r"(cycles_low)::"%rax", "%rbx", "%rcx", "%rdx"); return (((perf_cycles_t)cycles_high << 32) | cycles_low); #else Cpa64U ts = 0; asm volatile("rdtsc" : "=A"(ts)); return ((perf_cycles_t)ts); #endif } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function is used to retrieve time stamp * before sending request * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * ****************************************************************************/ static inline void coo_req_start(perf_data_t *perf_data) { /* Start coo measure */ if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g && coo_initialized) perf_data->req_temp = coo_timestamp(); } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description This function takes a timestamp after * sending a request. The difference of start * and pause is stored in a sum in perf_data. * If request status is not equal to * CPA_STATUS_SUCCESS request coo value will * not be added to the sum. This call is used * to measure coo of several requests. The * value of req_count is not incremented. * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] status request status * ****************************************************************************/ static inline void coo_req_pause(perf_data_t *perf_data, CpaStatus status) { if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g && coo_initialized) { perf_cycles_t stop_timestamp = coo_timestamp(); /* End coo measure */ if (CPA_STATUS_SUCCESS == status) { /* Temporary sum used in overwrap check */ perf_cycles_t req_sum_temp = 0; perf_cycles_t cost_sum_temp = 0; /* Start coo cost measure */ perf_data->cost_temp = coo_timestamp(); /* Simulate call function coo_req_pause() */ if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g && coo_initialized) { perf_cycles_t cost_timestamp = coo_timestamp(); /* End coo cost measure */ /* Store coo cost value into cost_sum_temp and check for * overwrap */ cost_sum_temp = perf_data->req_cost_sum_cycles + (cost_timestamp - perf_data->cost_temp); if (cost_sum_temp < perf_data->req_cost_sum_cycles) PRINT_ERR("req_cost_sum_cycles overwrap!\n"); else perf_data->req_cost_sum_cycles = cost_sum_temp; } /* Calculate req coo value */ req_sum_temp = perf_data->req_sum_cycles + (stop_timestamp - perf_data->req_temp); /* Check for req sum overwrap */ if (req_sum_temp < perf_data->req_sum_cycles) PRINT_ERR("req_sum_cycles overwrap!\n"); else perf_data->req_sum_cycles = req_sum_temp; /* Reset temporary values */ perf_data->req_temp = 0; perf_data->cost_temp = 0; } else /* Reset request temporary value */ perf_data->req_temp = 0; } } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description This function takes a timestamp after * sending the request. The Difference * between start and pause is stored as sum in * perf_data. If request status is not equal to * CPA_STATUS_SUCCESS request coo value will * not be added to the sum. When measuring coo * of several requests, this function should * be called at the end of last measured * function in loop. * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] status request status * ****************************************************************************/ static inline void coo_req_stop(perf_data_t *perf_data, CpaStatus status) { if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g && coo_initialized) { perf_cycles_t stop_timestamp = coo_timestamp(); /* End coo measure */ if (CPA_STATUS_SUCCESS == status) { /* Temporary sum used in overwrap check */ perf_cycles_t req_sum_temp = 0; perf_cycles_t cost_sum_temp = 0; /* Start coo cost measure */ perf_data->cost_temp = coo_timestamp(); /* Simulate call function coo_req_stop() */ if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g && coo_initialized) { perf_cycles_t cost_timestamp = coo_timestamp(); /* End coo cost measure */ /* Store coo cost value into cost_sum_temp and check for * overwrap */ cost_sum_temp = perf_data->req_cost_sum_cycles + (cost_timestamp - perf_data->cost_temp); if (cost_sum_temp < perf_data->req_cost_sum_cycles) PRINT_ERR("req_cost_sum_cycles overwrap!\n"); else { perf_data->req_cost_sum_cycles = cost_sum_temp; perf_data->req_cost_count++; } } /* Calculate req coo value */ req_sum_temp = perf_data->req_sum_cycles + (stop_timestamp - perf_data->req_temp); /* Check for req sum overwrap */ if (req_sum_temp < perf_data->req_sum_cycles) PRINT_ERR("req_sum_cycles overwrap!\n"); else { perf_data->req_sum_cycles = req_sum_temp; perf_data->req_count++; } /* Reset temporary values */ perf_data->req_temp = 0; perf_data->cost_temp = 0; } else /* Reset request temporary value */ perf_data->req_temp = 0; } } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function performs polling on instance * and measures coo of polling. If polling * status is equal to CPA_STATUS_SUCCESS * poll value will be added to sum in perf * data. * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] func pointer to function used to perform polling * * @param[in] instance instance handle used in polling function * * @param[in] status pointer to status where polling function * will return value * ****************************************************************************/ static inline void coo_poll(perf_data_t *perf_data, coo_poll_func func, CpaInstanceHandle instance, CpaStatus *status) { if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g && coo_initialized) { /* Initialize local variables */ perf_cycles_t poll_start_timestamp = 0; perf_cycles_t poll_stop_timestamp = 0; /* Start coo measure */ poll_start_timestamp = coo_timestamp(); *status = func(instance, 0); poll_stop_timestamp = coo_timestamp(); /* End coo measure */ if (CPA_STATUS_SUCCESS == *status) { /* Initialize local variables */ perf_cycles_t cost_start_timestamp = 0; perf_cycles_t cost_stop_timestamp = 0; perf_cycles_t poll_sum_temp = 0; perf_cycles_t cost_sum_temp = 0; /* Start coo cost measure */ cost_start_timestamp = coo_timestamp(); cost_stop_timestamp = coo_timestamp(); /* End coo cost measure */ cost_sum_temp = perf_data->poll_cost_sum_cycles + (cost_stop_timestamp - cost_start_timestamp); if (cost_sum_temp < perf_data->poll_cost_sum_cycles) PRINT_ERR("poll_cost_sum_cycles overwrap!\n"); else { perf_data->poll_cost_sum_cycles = cost_sum_temp; perf_data->poll_cost_count++; } /* Add poll cycles value to poll_sum_temp */ poll_sum_temp = perf_data->poll_sum_cycles + (poll_stop_timestamp - poll_start_timestamp); /* Check for poll sum overwrap */ if (poll_sum_temp < perf_data->poll_sum_cycles) PRINT_ERR("poll_sum_cycles overwrap!\n"); else perf_data->poll_sum_cycles = poll_sum_temp; } } else *status = func(instance, 0); } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function id used to call coo_poll using * polling function in traditional mode for * crypto instances * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] instance instance handle used in polling function * * @param[in] status pointer to status where polling function * will return value * ****************************************************************************/ static inline void coo_poll_trad_cy(perf_data_t *perf_data, CpaInstanceHandle instance, CpaStatus *status) { coo_poll(perf_data, icp_sal_CyPollInstance, instance, status); } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function id used to call coo_poll using * polling function in traditional mode for * compression instances * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] instance instance handle used in polling function * * @param[in] status pointer to status where polling function * will return value * ****************************************************************************/ static inline void coo_poll_trad_dc(perf_data_t *perf_data, CpaInstanceHandle instance, CpaStatus *status) { coo_poll(perf_data, icp_sal_DcPollInstance, instance, status); } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function id used to call coo_poll using * polling function in data plane mode for * crypto instances * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] instance instance handle used in polling function * * @param[in] status pointer to status where polling function * will return value * ****************************************************************************/ static inline void coo_poll_dp_cy(perf_data_t *perf_data, CpaInstanceHandle instance, CpaStatus *status) { coo_poll(perf_data, icp_sal_CyPollDpInstance, instance, status); } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function id used to call coo_poll using * polling function in data plane mode for * compression instances * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @param[in] instance instance handle used in polling function * * @param[in] status pointer to status where polling function * will return value * ****************************************************************************/ static inline void coo_poll_dp_dc(perf_data_t *perf_data, CpaInstanceHandle instance, CpaStatus *status) { coo_poll(perf_data, icp_sal_DcPollDpInstance, instance, status); } /** ***************************************************************************** * @file qat_perf_cycles.h * * @ingroup sample_code * * @description Function performs average cost of offload * calculation using coo data stored in * perf_data * * @param[in] perf_data pointer to structure of performance data * used to store cyclecount values * * @retval CPA_STATUS_SUCCESS Cost of offload is calculated * @retval CPA_STATUS_FAIL Cost of offload is not calculated * ****************************************************************************/ static inline void coo_average(perf_data_t *perf_data) { if (CPA_CC_REQ_POLL_STAMP == iaCycleCount_g && coo_initialized) { /* Init local variables */ perf_cycles_t avg_req_cycles = 0; perf_cycles_t avg_req_cost_cycles = 0; perf_cycles_t avg_poll_cycles = 0; perf_cycles_t avg_poll_cost_cycles = 0; perf_cycles_t req_count = perf_data->req_count; perf_cycles_t req_cost_count = perf_data->req_cost_count; perf_cycles_t poll_cost_count = perf_data->poll_cost_count; perf_cycles_t req_sum_cycles = perf_data->req_sum_cycles; perf_cycles_t req_cost_sum_cycles = perf_data->req_cost_sum_cycles; perf_cycles_t poll_sum_cycles = perf_data->poll_sum_cycles; perf_cycles_t poll_cost_sum_cycles = perf_data->poll_cost_sum_cycles; /* Calculate average values */ if ((req_sum_cycles > 0) && (req_count > 0)) avg_req_cycles = req_sum_cycles / req_count; if ((req_cost_sum_cycles > 0) && (req_cost_count > 0)) avg_req_cost_cycles = req_cost_sum_cycles / req_cost_count; if ((poll_sum_cycles > 0) && (req_count > 0)) avg_poll_cycles = poll_sum_cycles / req_count; if ((poll_cost_sum_cycles > 0) && (poll_cost_count > 0)) avg_poll_cost_cycles = poll_cost_sum_cycles / poll_cost_count; /* Calculate coo value and store in perf data */ perf_data->offloadCycles = (avg_req_cycles - avg_req_cost_cycles) + (avg_poll_cycles - avg_poll_cost_cycles); } } #endif /* __QAT_PERF_CYCLES_H_ */ qat_perf_latency.c000066400000000000000000000335041503624047500343670ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "cpa_dc.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_framework.h" #include "qat_compression_main.h" #include "icp_sal_poll.h" #include "qat_perf_latency.h" #include "qat_perf_utils.h" #define MAX_LATENCY_COUNT (100) #define READ_ALL_RESPONSES (0) int latency_single_buffer_mode = 1; /* set to 1 for single buffer processing */ CpaCySymCipherDirection latencyCipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; #ifdef DO_CRYPTO extern CpaCySymCipherDirection cipherDirection_g; #endif /* This function is used for enabling debug when latency_g is set to true * for the build. Where a non-zero argument enables debug and a 0 disables it. */ void setLatencyDebug(int value) { latency_debug = value; PRINT("%s: latency_debug now %d\n", __FUNCTION__, latency_debug); } EXPORT_SYMBOL(setLatencyDebug); /* This function is used for ensuring only a single buffer at a time * is processed when latency_g is set to true for the build. * Where a non-zero argument enables this mode and a 0 disables it. */ CpaStatus setLatencySingleBufferMode(int value) { latency_single_buffer_mode = value; PRINT("%s: latency_single_buffer_mode now %d\n", __FUNCTION__, latency_single_buffer_mode); return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setLatencySingleBufferMode); /* This function is used for enable gathering of latency timings. * Where a non-zero argument enables this mode and a 0 disables it. */ CpaStatus enableLatencyMeasurements(int value) { latency_enable = value; PRINT("Latency computation %s\n", latency_enable != 0 ? "Enabled" : "Disabled"); return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(enableLatencyMeasurements); /* This function is used for allow other files to check if * latency testing is enabled. Return of a non-zero value * signifies that it is. */ int isLatencyEnabled(void) { return latency_enable; } EXPORT_SYMBOL(isLatencyEnabled); /* * The setupSymmetricDpTest() function has the encrypt / decrypt * direction hard coded to CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT. * This function overrides this for the builds in which latency_g * is set to true. * Use setLatencyCipherDirection() before calling setupCipherDpTest(). */ CpaCySymCipherDirection getLatencyCipherDirection(void) { return latencyCipherDirection; } EXPORT_SYMBOL(getLatencyCipherDirection); #ifdef DO_CRYPTO /* * The setupSymmetricDpTest() function has the encrypt / decrypt * direction hard coded to CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT. * This function overrides this for builds in which latency_g * is set to true. * Use setLatencyCipherDirection() before calling setupCipherDpTest(). */ void setLatencyCipherDirection(CpaCySymCipherDirection direction) { latencyCipherDirection = direction; cipherDirection_g = latencyCipherDirection; } EXPORT_SYMBOL(setLatencyCipherDirection); #endif CpaStatus qatFreeLatency(perf_data_t *performanceStats) { CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_FREE_MEM_AND_UPDATE_STATUS(performanceStats->response_times, status); QAT_PERF_FREE_MEM_AND_UPDATE_STATUS(performanceStats->start_times, status); return status; } CpaStatus qatInitLatency(perf_data_t *performanceStats, Cpa32U numberOfLists, Cpa32U numberOfLoops) { CpaStatus status = CPA_STATUS_SUCCESS; if (latency_enable) { QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(performanceStats, status); if (CPA_STATUS_SUCCESS == status) { if (performanceStats->numOperations > LATENCY_SUBMISSION_LIMIT) { PRINT_ERR("Error max submissions for latency must be <= %d\n", LATENCY_SUBMISSION_LIMIT); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /*countIncrement is how many submission are made between * each latency measurement. It is the total submission divided * by MAX_LATENCY_COUNT * * nextCount is used to keep track of when the next latency * measurement needs to be taken in relation to the total * submissions made * * latencyCount records the number of latency measurements taken * * start_time is an array to record time-stamp just before a * submission is made * * response_time array is a location to record time-stamp when a * response is received. The corresponding submit time is stored * in start_time at the same index into the array. * The difference reflects the latency time of that request * */ performanceStats->countIncrement = (numberOfLists * numberOfLoops) / MAX_LATENCY_COUNT; /* countIncreement is set to numberOfLists. since number of * times the latency is calculated is exceeding * MAX_LATENCY_COUNT. * */ if(performanceStats->countIncrement < numberOfLists) { performanceStats->countIncrement = numberOfLists; } performanceStats->nextCount = performanceStats->countIncrement; performanceStats->latencyCount = 0; performanceStats->response_times = qaeMemAlloc(sizeof(perf_cycles_t) * MAX_LATENCY_COUNT + 1); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS( performanceStats->response_times, status); if (CPA_STATUS_SUCCESS == status) { performanceStats->start_times = qaeMemAlloc( sizeof(perf_cycles_t) * MAX_LATENCY_COUNT + 1); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS( performanceStats->start_times, status); } } } if (CPA_STATUS_SUCCESS != status) { qatFreeLatency(performanceStats); } } return status; } CpaStatus qatStartLatencyMeasurement(perf_data_t *performanceStats, Cpa32U submissions) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; if (latency_enable) { QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(performanceStats, status); if (CPA_STATUS_SUCCESS == status) { i = performanceStats->latencyCount; if ((submissions + 1 == performanceStats->nextCount) && (i < MAX_LATENCY_COUNT)) { performanceStats->start_times[i] = sampleCodeTimestamp(); } } } return status; } CpaStatus qatLatencyPollForResponses(perf_data_t *performanceStats, Cpa32U submissions, CpaInstanceHandle instanceHandle, CpaBoolean instanceIsCrypto, CpaBoolean instanceIsDP) { CpaStatus status = CPA_STATUS_SUCCESS; if (latency_enable) { QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(performanceStats, status); if (CPA_STATUS_SUCCESS == status) { /* Have we been requested to process one buffer at a time. This * will result in no retries and so the best latency times. */ if (0 != latency_single_buffer_mode) { /* Must now wait until this buffer is processed by the CPM */ while (performanceStats->responses != submissions) { /* Keep polling until compression of the buffer completes * and dcPerformCallback() increments perfData->responses */ if (instanceIsCrypto) { #ifdef DO_CRYPTO if (instanceIsDP) { icp_sal_CyPollDpInstance(instanceHandle, READ_ALL_RESPONSES); } else { icp_sal_CyPollInstance(instanceHandle, READ_ALL_RESPONSES); } #else PRINT_ERR( "Crypto is not enabled. Polling is impossible.\n"); status = CPA_STATUS_FAIL; #endif } else { if (instanceIsDP) { icp_sal_DcPollDpInstance(instanceHandle, READ_ALL_RESPONSES); } else { icp_sal_DcPollInstance(instanceHandle, READ_ALL_RESPONSES); } } } } } } return status; } CpaStatus qatSummariseLatencyMeasurements(perf_data_t *performanceStats) { Cpa32U i = 0; CpaStatus status = CPA_STATUS_SUCCESS; if (latency_enable) { QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(performanceStats, status); if (CPA_STATUS_SUCCESS == status) { performanceStats->minLatency = MAX_LATENCY_LIMIT; /* Will be less than this */ performanceStats->maxLatency = 0; /* Will be more than this */ /* Let's accumulate in 'aveLatency' all the individual 'latency' * times. Typically, there should be MAX_LATENCY_COUNT of these. * We also calculate min/max so we can get a sense of the variance. */ for (i = 0; i < performanceStats->latencyCount; i++) { perf_cycles_t latency = performanceStats->response_times[i] - performanceStats->start_times[i]; performanceStats->aveLatency += latency; if (latency < performanceStats->minLatency) performanceStats->minLatency = latency; if (latency > performanceStats->maxLatency) performanceStats->maxLatency = latency; } if (performanceStats->latencyCount > 0) { /* Then scale down this accumulated value to get the average. * This will be reported by dcPrintStats() at the end of the * test */ do_div(performanceStats->aveLatency, performanceStats->latencyCount); } status = qatFreeLatency(performanceStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("error in freeing latency stats memory\n"); } } } return status; } qat_perf_latency.h000066400000000000000000000100441503624047500343660ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef QAT_PERF_LATENCY_H_ #define QAT_PERF_LATENCY_H_ #include "cpa_sample_code_framework.h" #include "cpa_cy_sym.h" extern int latency_single_buffer_mode; void setLatencyDebug(int value); CpaStatus setLatencySingleBufferMode(int value); CpaStatus enableLatencyMeasurements(int value); CpaCySymCipherDirection getLatencyCipherDirection(void); void setLatencyCipherDirection(CpaCySymCipherDirection direction); int isLatencyEnabled(void); CpaStatus qatFreeLatency(perf_data_t *performanceStats); CpaStatus qatInitLatency(perf_data_t *performanceStats, Cpa32U numberOfLists, Cpa32U numberOfLoops); CpaStatus qatStartLatencyMeasurement(perf_data_t *performanceStats, Cpa32U submissions); CpaStatus qatSummariseLatencyMeasurements(perf_data_t *performanceStats); CpaStatus qatLatencyPollForResponses(perf_data_t *performanceStats, Cpa32U submissions, CpaInstanceHandle instanceHandle, CpaBoolean instanceIsCrypto, CpaBoolean instanceIsDP); #endif qat_perf_sleeptime.c000066400000000000000000000224671503624047500347250ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "cpa_sample_code_dc_utils.h" #include "cpa_dc.h" #include "qat_compression_main.h" #include "qat_perf_sleeptime.h" #include "qat_sym_utils.h" void adjustSleeptime(perf_data_t *pPerfData, sleeptime_data_t *data, Cpa32U *compRate, Cpa32U *sleepTime, Cpa32U bufferSize) { CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(pPerfData, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(data, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(compRate, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(sleepTime, status); if (CPA_STATUS_SUCCESS == status) { data->loopResponses = pPerfData->responses - data->previousNoOfResponses; data->previousNoOfResponses = pPerfData->responses; data->endLoopTimestamp = sampleCodeTimestamp(); data->numOfCycles = data->endLoopTimestamp - data->startLoopTimestamp; data->loopRetries = pPerfData->retries - data->previousNoOfRetries; data->previousNoOfRetries = pPerfData->retries; /* take no. of responses for x no. of loops */ data->currentThroughput = getThroughput(data->loopResponses, bufferSize, data->numOfCycles); pPerfData->currentThroughput = data->currentThroughput; if (*sleepTime == 0 && data->firstRunFlag) { pPerfData->retries = 0; // clear tries as its adding unnecessary overhead data->firstRunFlag = 0; data->baseThroughput = data->currentThroughput; /* set different sleep time depending on packet size to safe some * number of loops packet size below MIN_PACKET_SIZE will get no * benefit from nanosleep function */ if (bufferSize >= QAT_COMP_MIN_PACKET_SIZE) { if (bufferSize <= QAT_COMP_LOW_SLEEPTIME_STATING_VALUE) { *sleepTime = QAT_COMP_LOW_SLEEPTIME_STATING_VALUE; } else { *sleepTime = QAT_COMP_HIGH_SLEEPTIME_STATING_VALUE; } } else { *sleepTime = QAT_COMP_DEFAULT_SLEEPTIME_STARTING_VALUE; } if (*compRate > 0) { /* check if passed throughput is not grater then base throughput * as it would be impossible to limit current throughput to * base. */ if (*compRate < (Cpa32U)data->baseThroughput) { data->desiredThroughput = *compRate; data->percentRate = QAT_COMP_SCALING_FACTOR - (data->desiredThroughput * QAT_COMP_SCALING_FACTOR / data->baseThroughput); } else { PRINT("Too large throughput passed , capped to: %d\n", data->baseThroughput); data->desiredThroughput = data->baseThroughput; *compRate = data->baseThroughput; data->percentRate = QAT_COMP_FIVE_PERCENT; } } else { data->desiredThroughput = data->baseThroughput; /*TO DO decide if different packet size need different % margin * e.g packetSize<= 8192 ? 50 : 35; */ data->percentRate = QAT_COMP_FIVE_PERCENT; } } /* check if currentThroughput is with n % of base when true increase * sleeptime, when false set limitFlagFound */ if (findSleeptimeMargin(data->baseThroughput, data->currentThroughput, data->percentRate) && data->limitFoundFlag == 0) { data->lowerBound = *sleepTime; *sleepTime = *sleepTime << 1; } else if (data->upperBound == 0) { data->limitFoundFlag = 1; data->upperBound = *sleepTime; } /*TO DO decide if need to check margin at this point as well * withinMargin(desiredThroughput,currentThroughput, packetSize <= 8192 * ? 30 : 6) != 1 */ if (data->upperBound != 0) { /* check for ERROR_MARGIN of throughput and adjust sleep time * accordingly increase if current throughput is higher then desired * decrease when margin is higher the x amount * Then take a average of both*/ if (data->currentThroughput >= data->desiredThroughput) { data->lowerBound = *sleepTime + 1; } else { if (findSleeptimeMargin( data->desiredThroughput, data->currentThroughput, (data->packetSize <= QAT_COMP_PACKET_SIZE_8K ? QAT_COMP_THREE_PERCENT : QAT_COMP_POINT_SIX_PERCENT)) == 1) { data->lowerBound = *sleepTime + 1; } else { data->upperBound = *sleepTime - 1; } } *sleepTime = (data->upperBound + data->lowerBound) / 2; } data->startLoopTimestamp = sampleCodeTimestamp(); } } void sleep_parsing(Cpa32U sleepTime) { Cpa32U sleepInterval, k = 0; sleepInterval = sleepTime; if (sleepTime < QAT_COMP_SLEEP_INTERVAL) { sleepNano(sleepTime); } else { /* divide sleeptime into 100k blocks for more accurate sleeptime */ for (k = 0; k < (sleepTime / QAT_COMP_SLEEP_INTERVAL); k++) { sleepNano(QAT_COMP_SLEEP_INTERVAL); sleepInterval -= QAT_COMP_SLEEP_INTERVAL; } if (sleepInterval != 0) { sleepNano(sleepInterval); } } } uint8_t findSleeptimeMargin(uint32_t baseVal, uint32_t currentVal, uint32_t margin) { uint32_t difference = 0; if (currentVal >= baseVal) { return 1; } difference = baseVal - currentVal; difference *= QAT_COMP_SCALING_FACTOR; do_div(difference, baseVal); if (difference <= margin) { return 1; } return 0; } qat_perf_sleeptime.h000066400000000000000000000137461503624047500347320ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef QAT_PERF_SLEEPTIME_H_ #define QAT_PERF_SLEEPTIME_H_ typedef struct sleeptime_data_s { Cpa32S baseThroughput, currentThroughput, desiredThroughput; Cpa32S packetSize; Cpa32U percentRate, previousNoOfResponses, previousNoOfRetries, loopRetries; Cpa32U firstRunFlag, upperBound, lowerBound, limitFoundFlag; perf_cycles_t numOfCycles; Cpa64U loopResponses; perf_cycles_t endLoopTimestamp; /* end TS for x no of loops */ perf_cycles_t startLoopTimestamp; /* start TS for x no of loops */ } sleeptime_data_t; /***************************************************************************** * @file qat_perf_sleeptime.h * * @ingroup sample_code * * @description * Function used by rate limiting feature to adjust sleeptime based on current * throughout measured. This function is called every n amount of loops, it will * start by increasing the sleeptime and once it will exceed the threshold * of the throughput it will decrease and self adjust in other words "fine tune" * * @param[in] pPerfData pointer to the performance stats *structure * @param[in] data pointer to the sleeptime_data_t *structure * @param[in] compRate pointer to compRate stored in setup *structure * @param[in] sleepTime pointer to sleepTime stored in setup *structure * @param[in] bufferSize bufferSize stored in setup structure * *****************************************************************************/ void adjustSleeptime(perf_data_t *pPerfData, sleeptime_data_t *data, Cpa32U *compRate, Cpa32U *sleepTime, Cpa32U bufferSize); /***************************************************************************** * @file qat_perf_sleeptime.h * * @ingroup sample_code * * @description * This function will divide global sleeptime value into 100k parts, * as it was discovered that there is a higher margin of error * with high sleeptime numbers * * @param[in] sleepTime bufferSize stored in setup structure * *****************************************************************************/ void sleep_parsing(Cpa32U sleepTime); /***************************************************************************** * @file qat_perf_sleeptime.h * * @ingroup sample_code * * @description * Reused function from old busy loop code it will calculate the % margin * between two passed parameters using integer math * * @param[in] baseVal baseValue to calculate margin * @param[in] currentVal value which will be calculate percentage * difference from base * @param[in] margin value of percentage margin in tens * e.g. 0.5% margin is 5 * 5% is 50 *****************************************************************************/ uint8_t findSleeptimeMargin(uint32_t baseVal, uint32_t currentVal, uint32_t margin); #endif qat_perf_utils.c000066400000000000000000000142201503624047500340620ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "qat_perf_utils.h" #include "cpa_sample_code_dc_perf.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_dc_utils.h" #include "qat_perf_latency.h" void qatPerfInitStats(perf_data_t *performanceStats, Cpa32U numLists, Cpa32U numLoops, Cpa32U pollingInterval) { /* Resetting only specific perf stats to 0, as some of the element in the * structure should not be reset * e.g. bytesConsumedPerLoop from compression when testing decompression*/ performanceStats->submissions = 0; performanceStats->responses = 0; performanceStats->retries = 0; performanceStats->pollRetries = 0; performanceStats->nextPoll = pollingInterval; performanceStats->sleepTime = 0; performanceStats->compRate = 0; performanceStats->currentThroughput = 0; performanceStats->pollCount = 0; performanceStats->overflow = 0; performanceStats->busyLoopCount = 0; if (!iaCycleCount_g) { performanceStats->busyLoopValue = 0; } else { performanceStats->bytesConsumedPerLoop = 0; performanceStats->bytesProducedPerLoop = 0; } performanceStats->cyclesPerBusyLoop = 0; performanceStats->offloadCycles = 0; performanceStats->totalBusyLoopCycles = 0; performanceStats->busyLoopResponses = 0; performanceStats->isIACycleCountProfiled = 0; performanceStats->response_process_time = 0; qatFreeLatency(performanceStats); performanceStats->numLoops = numLoops; performanceStats->numOperations = (Cpa64U)numLists * (Cpa64U)numLoops; return; } char *cpaStatusToString(CpaStatus status) { char *retString = NULL; switch (status) { case CPA_STATUS_RETRY: retString = "CPA_STATUS_RETRY"; break; case CPA_STATUS_RESTARTING: retString = "CPA_STATUS_RESTARTING"; break; case CPA_STATUS_UNSUPPORTED: retString = "CPA_STATUS_UNSUPPORTED"; break; case CPA_STATUS_FATAL: retString = "CPA_STATUS_FATAL"; break; case CPA_STATUS_INVALID_PARAM: retString = "CPA_STATUS_INVALID_PARAM"; break; case CPA_STATUS_RESOURCE: retString = "CPA_STATUS_RESOURCE"; break; case CPA_STATUS_FAIL: retString = "CPA_STATUS_FAIL"; break; case CPA_STATUS_SUCCESS: retString = "CPA_STATUS_SUCCESS"; break; default: retString = "CPA_STATUS_UNKNOWN"; } return (retString); } EXPORT_SYMBOL(cpaStatusToString); CpaStatus printDriverVersion(Cpa32U deviceNum) { icp_sal_dev_version_info_t qaVersionInfo = {.devId = 0, .softwareVersion = {0}}; if (CPA_STATUS_SUCCESS != icp_sal_getDevVersionInfo(deviceNum, &qaVersionInfo)) { PRINT_ERR("Could not get QA version information\n"); } else { PRINT("*** QA version information ***\n"); PRINT("device ID\t\t= %d\n", qaVersionInfo.devId); PRINT("software \t\t= %s\n", qaVersionInfo.softwareVersion); PRINT("*** END QA version information ***\n"); } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(printDriverVersion); qat_perf_utils.h000066400000000000000000000306711503624047500340770ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/common/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef QAT_PERF_UTILS_H_ #define QAT_PERF_UTILS_H_ #include "cpa.h" #include "cpa_sample_code_utils_common.h" #include "icp_sal_user.h" #include "icp_sal_versions.h" #include "cpa_cy_im.h" /*set status to fail if the ptr is null*/ #define QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(ptr, status) \ do \ { \ if (NULL == ptr) \ { \ PRINT_ERR("NULL ptr passed %s\n", #ptr); \ status = CPA_STATUS_FAIL; \ } \ } while (0) /*free memory of a pointer, set status to fail if the pointer * is no null after calling free*/ #define QAT_PERF_FREE_MEM_AND_UPDATE_STATUS(ptr, status) \ do \ { \ if (NULL != ptr) \ { \ qaeMemFree((void **)&ptr); \ if (NULL != ptr) \ { \ PRINT_ERR("Could not free memory\n"); \ status = CPA_STATUS_FAIL; \ } \ } \ } while (0) /*print function, line number and fail return code*/ #define QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS(str, status) \ do \ { \ if (CPA_STATUS_SUCCESS != status) \ { \ PRINT_ERR("%s error: status:%d\n", str, status); \ } \ } while (0) /*goto label if the ptr is null*/ #define QAT_PERF_CHECK_NULL_POINTER_AND_GOTO_LABEL(ptr, label) \ do \ { \ if (NULL == ptr) \ { \ PRINT_ERR("NULL ptr passed %s\n", #ptr); \ goto label; \ } \ } while (0) /*goto label if the parameter range is invalid */ #define QAT_PERF_CHECK_PARAM_RANGE_AND_GOTO_LABEL(param, min, max, label) \ do \ { \ if (((param) < (min)) || ((param) >= (max))) \ { \ PRINT_ERR("Invalid File size: %d\n", param); \ goto label; \ } \ } while (0) /*fail the test if something wrong before the sampleCodeBarrier and goto label*/ #define QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(setup, label) \ do \ { \ setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; \ sampleCodeBarrier(); \ goto label; \ } while (0) /*define a back off mechanism to stop performance operations constantly using * up 100% CPU.*/ #if defined(KERNEL_SPACE) /*set a context switch to allow OS re-schedule thread, it also allows other *threads CPU time on the same core*/ /*note the soft lockup can be compiled out of the kernel, if that is the case * this step is not needed*/ #define AVOID_SOFTLOCKUP \ \ do \ { \ yield(); \ \ } while (0) #ifndef AVOID_SOFTLOCKUP_POLL #define AVOID_SOFTLOCKUP_POLL AVOID_SOFTLOCKUP #endif #else /* defined(KERNEL_SPACE) */ /* FreeBSD scheduler is not handling "busy loops" as effective as Linux * especially in multi-thread environment where few polling threads * can be assigned to single CPU core. To avoid thread starvation * sched_yields has been replaced by usleep to balance CPU time more * equal across polling threads.*/ #define AVOID_SOFTLOCKUP_POLL \ do \ { \ if (cyPollingThreadsInterval_g) \ usleep(cyPollingThreadsInterval_g); \ else \ sched_yield(); \ } while (0) #define AVOID_SOFTLOCKUP \ do \ { \ sched_yield(); \ } while (0) #endif typedef enum sync_mode_s { SYNC = 0, ASYNC } sync_mode_t; /** ***************************************************************************** * @file qat_perf_utils.h * * @ingroup sample_code * * @description Initialize a sample_code perf_data_t structure * * @param[in] performanceStats ptr to perfStats to be initialized * * @param[in] numLists number of CpaBufferLists being used in * test * @param[in] numLoops number to resubmit numLists * * @param[in] pollingInterval how many request to be made for inline * polling mode before a poll for responses * is done * * @pre perfStats already allocated * * @post zero out perfStats structure, then set * perfStats->numLoops and * perfStats->numOperations = * numLoops * numLists * * @retval none *****************************************************************************/ void qatPerfInitStats(perf_data_t *performanceStats, Cpa32U numLists, Cpa32U numLoops, Cpa32U pollingInterval); /** ***************************************************************************** * @file qat_perf_utils.h * * * @ingroup sample_code * * @description Converts a CpaStatus return code to its readable string code * * @param[in] status CpaStatus code to be converted * * @retval human readable string of the equivalent status code *****************************************************************************/ char *cpaStatusToString(CpaStatus status); /** ***************************************************************************** * @file qat_perf_utils.h * * * @ingroup sample_code * * @description Copy data from src buffer to dst buffer * * @param[in] srcBufferListArray pointer to data to be copied * @param[in] dstBufferListArray pointer to where data is to be copied * * * @retval human readable string of the equivalent status code *****************************************************************************/ CpaStatus copyBuffers(CpaBufferList *srcBufferListArray, CpaBufferList *copyBufferListArray, Cpa32U numberOfLists); /** ***************************************************************************** * @file qat_perf_utils.h * * * @ingroup sample_code * * @description Print QAT driversion * * @param[in] deviceNum device Number * * * @retval human readable string of the equivalent status code *****************************************************************************/ CpaStatus printDriverVersion(Cpa32U deviceNum); #endif /* QAT_PERF_UTILS_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/000077500000000000000000000000001503624047500320265ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/calgary000066400000000000000000143164451503624047500334150ustar00rootroot00000000000000%A Abdou, I.E. %A Wong, K.Y. %D 1982 %T Analysis of linear interpolation schemes for bi-level image applications %J IBM J Research and Development %V 26 %P 667-680 %A Abell, R. %D 1981 %T Implementation of a Telidon system using Unix file structures %B The Telidon book %E D.Godfrey and E.Chang %I Press Porcepic %C Toronto, ON %P 203-209 %A Abut, H. %A Gray, R.M. %A Rebolledo, V. %D 1982 %T Vector quantization of speech and speech-like waveforms %J IEEE Trans Acoustics, Speech and Signal Processing %V Acoustics, Speech, and Signal Processing -30 %N 3 %P 423-435 %O June %K * %A Achugbue, J.O. %D 1981 %T On the line breaking problem in text formatting %J SIGOA Newsletter (Proc ACM Symposium on Text manipulation, Portland, Oregon) %V 2 %N 1/2 %P 117-121 %O Spring/Summer %A Adams, D.N. %D 1979 %T The hitchhiker's guide to the galaxy %I Pan %C London, England %A Adams, J.B. %D 1976 %T A probability model of medical reasoning and the MYCIN model %J Mathematical Biosciences %V 32 %P 177-186 %A Aho, A.V. %A Corasick, M.J. %D 1975 %T Efficient string matching: an aid to bibliographic search %J Comm ACM %V 18 %N 6 %P 333-340 %O June %A Aikins, J.S. %D 1983 %T Prototypical knowledge for expert systems %J Artificial Intelligence %V 20 %N 2 %P 163-210 %O February %K * %A Akers, G. %A Lennig, M. %D 1984 %T Intonation in text-to-speech synthesis: evaluation of algorithms %R Report %I Bell-Northern Research %C Verdun, QUE %K * %A Allebach, J.P. %A Liu, B. %D 1976 %T Analysis of halftone dot profile and aliasing in the discrete binary representation of images %J Optical Society of America %V 67 %N 9 %K * %A Allen, B.P. %A Wright, J.M. %D 1983 %T Integrating logic programs and schemata %J Proc 8th International Joint Conference on Artificial Intelligence %P 340-342 %A Allen, E.M. %D 1983 %T YAPS: yet another production system %R Report TR-1146 %I Maryland Artificial Intelligence Group, Computer Science Department, University of Maryland %C Maryland, MD %O December %K * %A Allen, J.F. %A Perrault, C.R. %D 1980 %T Analyzing intention in utterances %J Artificial Intelligence %V 15 %P 143-178 %K * %A Allen, J.F. %D 1984 %T Towards a general theory of action and time %J Artificial Intelligence %V 23 %P 123-154 %K * %A Almes, G.T. %A Black, A.P. %A Lazowska, E.L. %A Noe, J.D. %D 1985 %T The Eden system: a technical review %J IEEE Trans Software Engineering %V SE-11 %N 1 %P 43-59 %O January %K * %A Alvey, P. %D 1983 %T The problems of designing a medical expert system %J Proc Expert Systems 83 %I Churchill College %C Cambridge, England %P 30-42 %O December %K * %A Anderberg, M.R. %D 1973 %T Cluster analysis for applications %I Academic Press %C New York, NY %A Anderson, D.P. %A Hedin, R.C. %D 1982 %T Voice input/output module %J Voice Data Entry Systems Application Conference '82 %C San Mateo, CA %O September 21 %K * %A Anderson, J.R. %T Knowledge compilation: the general learning mechanism %K * %A Anderson, J.R. %A Reiser, B.J. %D 1985 %T The LISP tutor %J Byte %V 10 %N 4 %P 159-175 %O April %A Andreae, J.H. %D 1984 %T Numbers in the head %R Man-Machine Studies Progress Report UC-DSE/24 %P 5-28 %I Department of Electrical Engineering, University of Canterbury %C New Zealand %A Andreae, P.M. %D 1984 %T Constraint limited generalization: acquiring procedures from examples %J Proc American Association on Artificial Intelligence %C Austin, TX %O August %K * %A Andreae, P.M. %D 1984 %T Justified generalization: acquiring procedures from examples %R PhD Thesis %I Department of Electrical Engineering and Computer Science, MIT %A Andreae, P.M. %D 1986 %T Justified generalization %J Proc International Conference on Future Advances in Computing %C Christchurch, New Zealand %O February 17-21 %K * %A Andreka, H. %A Nemeti, I. %A Sain, I. %D 1982 %T A complete logic for reasoning about programs via nonstandard model theory I %J Theoretical Computer Science %V 17 %P 193-212 %K * %A Andreka, H. %A Nemeti, I. %A Sain, I. %D 1982 %T A complete logic for reasoning about programs via nonstandard model theory II %J Theoretical Computer Science %V 17 %P 259-278 %K * %A Andrew, A.M. %D 1981 %T Autopoiesis \(em allopoiesis interplay %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York, NY %P 157-166 %A Anon %D 1972 %T Holography and computer generated holograms %I Mills and Boom %C London, England %K * %A ANSI %D 1983 %T Videotex/Teletext presentation level protocol syntax (Draft) %I American National Standards Committee X3 -- Information Processing Systems, Technical Committee X3L2 -- Codes and character sets %C New York, NY %O June %A Anson, E. %D 1982 %T The device model of interaction %J Computer Graphics %V 16 %N 2 %P 107-114 %O July %K * %A Aoki, M. %D 1965 %T Optimal control of partially observable markovian systems %J J Franklin Institute %V 280 %N 5 %O November %K * %A Ascher, R.N. %A Nagy, G. %D 1974 %T A means for achieving a high degree of compaction on scan-digitized printed text %J IEEE Trans Computers %V C-23 %N 11 %P 1174-1179 %O November %K * %A Ash, W.L. %D 1981 %T MXEC: parallel processing with an advanced macro facility %J Comm ACM %V 24 %N 8 %P 502-509 %K * %A Ashby, W.R. %D 1960 %T Design for a brain: the origin of adaptive behavior %I Wiley %C New York, NY %O (second edition) %A Askwall, S. %D 1985 %T Computer supported reading vs reading text on paper: a comparison of two reading situations %J IJMMS %V 22 %N 4 %P 425-439 %O April %A Atkinson, H.H. %A Gargantini, I. %A Ramanath, M.V.S. %D 1984 %T Determination of the 3D border by repeated elimination of internal surfaces %J Computing %V 32 %P 279-295 %K * %A Attardi, G. %A Simi, M. %D 1982 %T Semantics of inheritance and attributions in the description system Omega %R AI Memo 642 %I MIT Artificial Intelligence Laboratory %O January %K * %A Axelrod, R. %D 1984 %T The evolution of cooperation %I Basic Books %C New York, NY %A Backer, D. %A Gano, S. %D 1982 %T Dynamically alterable videodisk displays %J Proc Graphics Interface 82 %C Toronto, ON %P 365- %O May 17-21 %A Baecker, R. %A Marcus, A. %D 1983 %T On enhancing the interface to the source code of computer programs %J Proc ACM CHI 83 Human Factors in Computing Systems %P 251-255 %C Boston, MA %O December 12-15 %K * %A Bailey, D. %D 1985 %T University of Salford Lisp/Prolog system %J Software -- Practice and Experience %V 15 %N 6 %P 595-609 %O June %K * %A Ball, G.H. %A Hall, D.J. %D 1965 %T ISODATA, a novel method of data analysis and pattern classification %R Report AD 699616 %I Stanford Research Institute %C Stanford, CA %A Bandyopadhyay, S. %A Hughes, J.G. %A Smith, F.J. %A Sen, K. %T A generalized scientific information system %R Report %I Computer Science Department, Queen's University of Belfast %C Belfast, Northern Ireland %K * %A Barber, G.R. %D 1981 %T Record of the workshop on research in office semantics %R AI Memo 620 %I MIT %O February %K * %A Barber, G.R. %D 1982 %T Office semantics %R PhD Thesis %I MIT %O February %A Barber, G.R. %D 1983 %T Supporting organizational problem solving with a workstation %J ACM Trans Office Information Systems %V 1 %N 1 %P 45-67 %O January %K * %A Barber, G.R. %A de\|Jong, P.S. %A Hewitt, C. %D 1983 %T Semantic support for work in organizations %R AI Memo 719 %I MIT Artificial Intelligence Laboratory %O April %K * %A Barnett, J.A. %D 1981 %T Computational methods for a mathematical theory of evidence %J Proc 7th International Joint Conference on Artificial Intelligence %P 868-875 %C Vancouver, BC %O August %A Barrow, H.G. %D 1979 %T Artificial intelligence: state of the art %R Technical Note 198 %I SRI International %C Menlo Park, CA %O October %A Barsky, B.A. %A Beatty, J.C. %D 1982 %T Varying the betas in beta-splines %R Report CS-82-49 %I University of Waterloo %O December %K * %A Barwise, J. %A Perry, J. %D 1983 %T Situations and attitudes %I MIT Press %C Cambridge, MA %A Barwise, J. %D 1985 %T The situation in logic II: conditionals and conditional information %R Report CSLI-85-21 %I Center for the study of language and information, Stanford University %C Stanford, CA %O January %K * %A Bates, E. %D 1979 %T The emergence of symbols %I Academic Press %A Beer, S. %D 1980 %R Preface to \fIAutopoiesis and cognition\fR (Maturana and Varela, 1980) %A Bell, T.C. %D 1985 %T Better OPM/L text compression %R Internal Report %I Computer Science Department, University of Canterbury %C Christchurch, New Zealand %K * %A Bell, T.C. %A Moffat, A.M. %D 1986 %T A note on the DMC data compression scheme %R Internal Report %I Computer Science Department, University of Canterbury %C Christchurch, New Zealand %A Bell, T.C. %D 1986 %T An introduction to text compression %R Internal Report %I Computer Science Department, University of Canterbury %C Christchurch, New Zealand %A Bellanger, M.G. %A Daguet, J.L. %A Lepagnol, G.P. %D 1974 %T Interpolation, extrapolation, and reduction of computation speed in digital filters %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-22 %N 4 %P 231-235 %O August %K * %A Benest, I.D. %A Jones, G. %D 1982 %T Computer emulation of books %J Proc IEE Conference Man-Machine Systems %P 267-271 %C Manchester, England %O July %A Benest, I.D. %A Potok, M.H.N. %D 1984 %T Wayfinding: an approach using signposting techniques %J Behaviour and Information Technology %V 3 %N 2 %P 99-107 %K * %A Bentley, J.L. %A Friedman, J.H. %D 1979 %T Data structures for range searching %J Computing Surveys %V 11 %N 4 %P 397-409 %O December %K * %A Bentley, J.L. %D 1980 %T Multidimensional divide-and-conquer %J Comm ACM %V 23 %N 4 %P 214-229 %K * %A Bentley, J.L. %A Sleator, D.D. %A Tarjan, R.E. %A Wei, V.K. %D 1986 %T A locally adaptive data compression scheme %J Comm ACM %V 29 %N 4 %P 320-330 %O April %A Berglund, E.J. %A Cheriton, D.R. %T Amaze -- A distributed multi-player game program using the Distributed V Kernel %K * %A Bewley, W.L. %A Roberts, T.L. %A Schroit, D. %A Verplank, W.L. %D 1983 %T Human factors testing in the design of Xerox's 8010 `Star' office workstation %J Proc ACM CHI 83 Human Factors in Computing Systems %P 72-77 %C Boston, MA %O December 12-15 %K * %A Bezdek, J.C. %D 1980 %T A convergence theorem for the fuzzy ISODATA clustering algorithms %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-2 %N 1 %P 1-8 %O January %K * %A Bibel, W. %D 1983 %T Matings in matrices %J Comm ACM %V 26 %N 11 %P 844-852 %O November %K * %A Biederman, I. %D 1985 %T Human image understanding: recent research and a theory %J Computer Vision, Graphics, and Image Processing %V 32 %N 1 %P 29-73 %O October. %A Bigelow, C. %A Day, D. %D 1983 %T Digital typography %J Scientific American %V 249 %N 2 %P 106-119 %O August %K * %A Bigelow, C. %D 1984 %T Principles of font design for the personal workstation %R Research Report %I Stanford University %K * %A Bigelow, C. %D 1986 %T Notes on typeface protection %K * %A Birkhoff, G. %D 1967 %T Lattice theory %I American Mathematical Society %C Providence, RI %A Birrell, A.D. %A Levin, R. %A Needham R.M. %A Schroeder, M.D. %D 1982 %T Grapevine: an exercise in distributed computing %J Comm ACM %V 25 %N 4 %P 260-274 %O April %K * %A Birtwistle, G.M. %A Dahl, O.J. %A Myhrhaug, B. %A Nygaard, K. %D 1973 %T Simula Begin %I Auerbach %C Philadelphia, PA %A Birtwistle, G. %A Cleary, J.G. %A Joyce, J. %A Liblong, B. %A Unger, B.W. %A Witten, I.H. %A Wyvill, B.L.M. %D 1984 %T A simulation environment %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 290-296 %O May %K KConference %A Blakeslee, T.R. %D 1980 %T The right brain %I MacMillan %C London, England %A Bobrow, D.G. %D 1985 %T If Prolog is the answer, what is the question? or What it takes to support AI programming paradigms %J IEEE Trans Software Engineering %V SE-11 %N 11 %P 1401-1408 %O November %K * %A Boehm-Davis, D.A. %A Fregly, A.M. %D 1983 %T Documentation of concurrent programs %J Proc ACM CHI 83 Human Factors in Computing Systems %P 256-261 %C Boston, MA %O December 12-15 %K * %A Bonham, M. %A Witten, I.H. %D 1984 %T Towards distributed document preparation with interactive and noninteractive viewing %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 365-372 %O May %K KConference %A Bonham, M. %A Witten, I.H. %D 1985 %T Towards distributed document preparation with interactive and noninteractive viewing %J Infor %V 23 %N 4 %P 365-388 %O November %K KJournal %A Bonham, M. %A Witten, I.H. %D 1985 %T More on `A large font virtual terminal interface: a software prosthesis for the visually impaired' %J Comm ACM %V 28 %N 11 %P 1236-1237 %O November %K KCorrespondence %A Bonham, M. %A Witten, I.H. %D 1985 %T Shape \(em a unifying concept in document layout %J Proc PROTEXT II -- Second International Conference on Text Processing Systems %I Boole Press %C Dublin, Ireland %P 126-132 %O October %K KConference %A Bonner, S. %A Shin, K. %D 1982 %T A comparative study of robot languages %J IEEE Computer %V 15 %N 12 %P 82-96 %A Boose, J.H. %D 1986 %T Rapid acquisition and combination of knowledge from multiple experts in the same domain %J Proc International Conference on Future Advances in Computing %C Christchurch, New Zealand %O February 17-21 %K * %A Booth, T.L. %D 1984 %T Computer education %J IEEE Computer %V 17 %N 10 %P 57-68 %O October %K * %A Borning, A. %D 1981 %T The programming language aspects of ThingLab, a constraint-oriented simulation laboratory %J ACM Trans Programming Languages and Systems %V 3 %N 4 %P 353-387 %O October %K * %A Bouachache, B. %D 1983 %T Wigner analysis of time-varying signals %B Signal processing II: Theories and applications %E H.W.Schussler %I Elsevier Science Publishers B.V. (North Holland) %P 703-706 %K * %A Bouachache, B. %A Rodriguez, F. %D 1984 %T Recognition of time-varying signals in the time-frequency domain by means of the Wigner distribution %J Proc International Circuits and Systems Symposium %K * %A Bouachache, B. %A Whitehouse, H.J. %D 1985 %T Seismic applications of the Wigner-Ville distribution %J Proc International Circuits and Systems Symposium %C San Jose, CA %O May 5 %K * %A Boulton, P.I.P. %A Lee, E.S. %D 1983 %T The performance of Hubnet %J Proc International Electrical, Electronics Conference %V 2 %P 450-453 %C Toronto, ON %O September 26-28 %K * %A Bower, G.H. %A Black, J.B. %D 1979 %T Scripts in memory for text %J Cognitive Psychology %V 11 %P 177-220 %K * %A Brachman, R.J. %D 1983 %T What IS-A is and isn't: an analysis of taxonomic links in semantic networks %J IEEE Computer %V 16 %N 10 %P 30-36 %O October %K * %A Brachman, R.J. %A Schmolze, J.G. %D 1985 %T An overview of the KL-ONE knowledge representation scheme %J Cognitive Science %V 9 %N ii %P 171-216 %K * %A Bramer, M.A.\0(Editor) %D 1985 %T Research and development in expert systems %I Cambridge University Press %C Cambridge, England %O (Proc 4th Conference of BCS Group on Expert Systems, December 1984) %A Bramwell, B. %D 1984 %T Browsing around a manual %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 438-442 %O May %K * %A Britton, B.K. %A Black, J.B.\0(Editors) %D 1985 %T Understanding expository text: a theoretical and practical handbook for analyzing explanatory text %I Erlbaum %C Hillsdale, NJ %A Brown, K.Q. %D 1979 %T Voroni diagrams from convex hulls %J Information Processing Letters %V 9 %N 5 %P 223-228 %O December %K * %A Brown, P.J. %D 1984 %T Interactive documentation %R Internal Report %I Computing Laboratory, University of Kent %O April %K * %A Brown, J.S. %A Burton, R.R. %D 1975 %T Multiple representations of knowledge for tutorial reasoning %B Representation of Learning %E D.G. Bobrow and A. Collins %I Academic Press %C New York, NY %A Brownston, L. %A Farrell, R. %A Kant, E. %A Martin, N. %D 1985 %T Programming expert systems in OPS-5: an introduction to rule-based programming %I Addison-Wesley %C Reading, MA %A Brunner, J. %D 1975 %T The shockwave rider %I Ballantine %C New York, NY %A Bruynooghs, M. %D 1982 %T Adding redundancy to obtain more reliable and more readable Prolog programs %J Proc 1st International Logic Programming Conference %C Marseille, France %P 129-133 %O September 14-17 %K * %A Bryant, J. %D 1979 %T On the clustering of multidimensional pictorial data %J Pattern Recognition %V 11 %P 115-125 %K * %A Buchman, C. %A Berry, D.M. %T An adaptation of the Unix DITROFF for formatting bidirectional text %I Computer Science Department, University of California %C Los Angeles, CA %K * %A Bundy, A. %A Silver, B. %A Plummer, D. %D 1985 %T An analytical comparison of some rule-learning programs %J Artificial Intelligence %V 27 %P 137-181 %A Bundy, A. %D 1983 %T The computer modelling of mathematical reasoning %A Academic Press %C London, England %A Burton, R.R. %A Brown, J.S. %D 1979 %T An investigation of computer coaching for informal learning activities %J IJMMS %V 11 %N 1 %P 5-24 %O January %A Bush, V. %D 1945 %T As we may think %J Atlantic Monthly %P 101 %O July %A Byrd, R.J. %A Smith, S.E. %A de\|Jong, S.P. %D 1982 %T An actor-based programming system %J Proc SIGOA Conference on Office Information Systems %P 67-78 %C Philadelphia, PA %O June 21-23 %K * %A Campbell, F.W. %A Robson, J.G. %D 1967 %T Application of fourier analysis to the visibility of gratings %J Physiol %N 197 %P 551-566 %I University of Cambridge %K * %A Cannon, W.B. %D 1932 %T The wisdom of the body %I London %A Carroll, J.B. %D 1967 %T On sampling from a lognormal model of word-frequency distribution %B Computational analysis of present-day American English %E Kucera, H. and Francis, W.N. %I Brown University Press %C Providence, RI %P 406-424 %K * %A Carroll, J.B. %D 1966 %T Word-frequency studies and the lognormal distribution %E E.M.Zale %B Proc Conference on Language and Language Behavior %I Appleton-Century-Crofts %C New York, NY %P 213-235 %K * %A Carroll, J.M. %A Thomas, J.C. %D 1982 %T Metaphor and the cognitive representation of computing systems %J IEEE Trans Systems, Man and Cybernetics %V SMC-12 %N 2 %P 107-116 %O March/April %K * %A Carter, K.A. %D 1984 %T The Rainbow workstation in brief/A window manager for the Rainbow workstation %R Rainbow Group Note %I Computer Laboratory, University of Cambridge %O May %K * %A Casey, R.G. %A Friedman, T.D. %A Wong, K.Y. %D 1982 %T Automatic scaling of digital fonts %J IBM J Research and Development %V 26 %P 657-666 %A Casey, R.G. %A Nagy, G. %D 1984 %T Decision tree design using a probabilistic model TJ IEEE Trans Information Theory %V IT-30 %N 1 %P 93-99 %O January %K * %A Cater, J.P. %D 1983 %T Electronically speaking: computer speech generation %I Howard W. Sams %C Indianapolis, IN %A Catmull, E. %D 1981 %T New frontiers in computer animation %J American Cinematographer %P 157-163 %O October %A Cendrowska, J. %A Bramer, M.A. %D 1984 %T A rational reconstruction of the Mycin consultation system %J IJMMS %V 20 %P 229-317 %A Chapanis, A. %D 1984 %T Taming and civilizing computers %B Computer culture: the scientific, intellectual, and social impact of the computer %E Heinz R. Pagels %I New York Academy of Sciences %C New York, NY %P 202-219 %K * %A Chazelle, B. %D 1983 %T A decision procedure for optimal polyhedron partitioning %J Information Processing Letters %V 16 %P 75-78 %O February 26 %K * %A Cheeseman, P. %D 1985 %T In defense of probability %J Proc 10th International Joint Conference on Artificial Intelligence %P 100R2-1009 %A Cheriton, D.R. %A Zwaenepoel, W. %D 1983 %T The distributed V kernel and its performance for diskless workstations %R Report No STAN-CS-83-973 %I Stanford University, Computer Science Department %C Stanford, CA %O July %K * %A Christodoulakis, S %A Faloutsos, C. %D 1984 %T Design considerations for a message file server %J IEEE Trans Software Engineering %V SE-10 %N 2 %P 201-210 %O March %K * %A Ciminiere, L. %A Valenzano, A. %D 1984 %T iAPX 432 hardware fault handling mechanisms %K * %A Clancey, W.J. %D 1979 %T Tutoring rules for guiding a case method dialogue %J IJMMS %V 11 %P 25-49 %K * %A Clancey, W.J. %D 1983 %T The epistemology of a rule-based expert system \(em a framework for explanation %J Artificial Intelligence %V 20 %P 215-251 %K * %A Clancey, W.J. %A Shortliffe, E.H. \0(Editors) %D 1984 %T Readings in medical artificial intelligence %I Addison-Wesley %C Reading, MA %A Clarkson, T. %T Eye position sensor %R Section 7 of a report %I King's College %C London, England %K * %A Cleary, J.G. %D 1979 %T Analysis of an algorithm for finding nearest neighbors in Euclidean space %J ACM Trans Mathematical Software %V 5 %N 2 %P 183-192 %O June %K * %A Cleary, J.G. %D 1984 %T Compact hash tables using bidirectional linear probing %J IEEE Trans Computers %V C-33 %N 9 %P 828-834 %O September %A Cleary, J.G. %A Darragh, J.J. %D 1984 %T A fast compact representation of trees using hash tables %R Research Report 83/162/20 %I Computer Science Department, University of Calgary %O Submitted to \fIIEEE Trans Computers\fP %A Cleary, J.G. %A Witten, I.H. %D in preparation %T Universal data compression %A Clocksin, W.A. %D 1984 %T Introduction to Prolog %B Artificial Intelligence: tools, techniques, and applications %E T.O'Shea and M.Eisenstadt %I Harper and Row %C New York, NY %A Codd, E.F. %D 1968 %T Cellular automata %I Academic Press %C London, England %A Codd, E.F. %D 1978 %T How about recently? %B Databases: Improving usability and responsiveness %E B. Shneiderman (Ed.) %I Academic Press %C New York, NY %P 3-28 %A Cohen, E.S. %A Smith, E.T. %A Iverson, L.A. %D 1985 %T Constraint-based tiled windows %R Research Report %I Computer Science Department, Carnegie-Mellon University %A Cohen, J. %D 1985 %T Describing Prolog by its interpretation and compilation %J Comm ACM %V 28 %N 12 %P 1311-1324 %O December %K * %A Colby, K.M. %D 1973 %T Simulations of belief systems %E R.C.Schank and K.M.Colby %B Computer models of thought and language %I Freeman %C San Francisco, CA %P 251-286 %A Colmaurer, A. %A Colmaurer, C. %D 1983 %T Prolog en 10 figures %J TSI %V 2 %N 4 %O July-August %K * %A Colmerauer, A. %D 1985 %T Prolog in 10 figures %J Comm ACM %V 28 %N 12 %P 1296-1310 %O December %K * %A Colmaurer, A. %T An interesting subset of natural language %K * %A Comer, D.E. %A Peterson, L.L. %T Conversation-based mail %J ACM Transactions on computer systems %V 4 %N 4 %O November %K * %A Computer\|Science\|Department %D 1983 %T CPSC Student Handbook %I University of Calgary %A Coombs, M. %A Alty, J. %D 1984 %T Expert systems: an alternative paradigm %J IJMMS %V 20 %N 1 %P 21-43 %O January %K * %A Corbett, C. %D 1983 %T MC nroff/troff macros reference manual %R Report EES-MMS-1983-2 %I Department of Electrical Engineering Science, University of Essex %C Colchester, Essex, UK %K * %A Corbett, C. %D 1983 %T Figure processing within nroff %J Presented at EUUG Meeting %C Dublin, Ireland %O September %K * %A Cormack, G.V. %A Horspool, R.N. %D 1984 %T Algorithms for adaptive Huffman codes %J Information Processing Letters %V 18 %N 3 %P 159-166 %O March %K * %A Cormack, G.V. %A Horspool, R.N. %D 1985 %T Data compression using dynamic Markov modelling %R Research Report %I Computer Science Department, University of Waterloo %O April; submitted to Comm ACM %K * %A Costigan, D.M. %D 1978 %T Electronic delivery of documents and graphics %I Van Nostrand Reinhold %C New York, NY %A Coulon, D. %A Kayser, D. %D 1979 %T Construction of natural language sentence acceptors by a supervised-learning technique %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-1 %N 1 %P 94-99 %O January %K * %A Cove, J.F. %A Walsh, B.C. %D 1988 %T A taxonomy of browsing %R Working Paper 85/2 %I Computer Science Department, University of Liverpool %O April %K * %A Cox, B.J. %D 1986 %T Object oriented programming %I Addison-Wesley %C Reading, MA %A Crochiere, R.E. %A Rabiner, L.R. %D 1975 %T Optimum FIR digital filter implementations for decimation, interpolation, and narrow-band filtering %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-23 %N 5 %P 444-456 %O October %K * %A Crochiere, R.E. %A Rabiner, L.R. %D 1976 %T Further considerations in the design of decimators and interpolators %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-24 %N 4 %P 296-311 %O August %K * %A Croft, W.B. %A Lefkowitz, L.S. %D 1984 %T Task support in an office system %J ACM Trans Office Information Systems %V 2 %N 3 %P 197-212 %O July %K * %A Croft, W.B. %D 1984 %T The role of context and adaptation in user interfaces %J IJMMS %V 21 %N 4 %P 283-292 %O October %A Csuri, C. %D 1974 %T Computer graphics and art %J Proc IEEE %O April %A Cuff, R.N. %D 1982 %T Database query using menus and natural language fragments %R PhD Thesis %I Man-Machine Systems Laboratory, Department of Electrical Engineering Science, University of Essex %C Colchester, Essex, UK %A Cuff, R.N. %D 1984 %T HERCULES: database query using natural language fragments %J Proc 3rd British National Conference on Database Systems %C Leeds %O July %K * %A Cullingford, R.E. %D 1978 %T Script application: computer understanding of newspaper stories %R PhD Thesis, Research Report 116 %I Yale University %A Cullingford, R.E. %A Krueger, M.W. %A Selfridge, M. %A Bienkowski, M.A. %D 1982 %T Automated explanations as a component of a computer-aided design system %J IEEE Trans Systems, Man and Cybernetics %V SMC-12 %N 2 %P 168-181 %O March/April %K * %A Cullingford, R.E. %A Pazzani, M.J. %D 1984 %T Word-meaning selection in multiprocess language understanding programs %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-6 %N 4 %P 493-509 %O July %K * %A Curry, G. %A Baer, L. %A Lipkie, D. %A Lee, B. %D 1982 %T Traits: an approach to multiple-inheritance subclassing %J ACM Conference on Office Information Systems %P 1-9 %O June %K * %A Damper, R.I. %A MacDonald, S.L. %D 1984 %T Template adaptation in speech recognition %J Proc Institute of Acoustics %V 6 %N 4 %P 293-299 %K * %A Damper, R.I. %A MacDonald, S.L. %D 1984 %T Statistical clustering procedures applied to low-cost speech recognition %J J Biomed Engineering %V 6 %P 265-271 %O October %K * %A Darragh, J.J. %A Witten, I.H. %A Cleary, J.G. %D 1983 %T Adaptive text compression to enhance a modem %R Research Report 83/132/21 %I Computer Science Department, University of Calgary %K KReport %A Davis, R. %D 1979 %T Interactive transfer of expertise: acquisition of new inference rules %J Artificial Intelligence %V 12 %N 2 %P 121-157 %K * %A Davis, R. %A Lenat, D.B. %D 1982 %T Knowledge-based systems in artificial intelligence %I McGraw Hill %C New York, NY %A Day, J.D. %A Zimmermann, H. %D 1983 %T The OSI reference model %J Proc IEEE %V 71 %N 12 %P 1334-1340 %O December %A Defude, B. %D 1984 %T Knowledge based systems versus thesaurus: an architecture problem about expert systems design %J Proc 3rd Joint BCS and ACM Symposium (King's College, Cambridge) %I Cambridge University Press %P 267-280 %O July %K * %A de\|Beaugrande, R. %D 1980 %T Text, discourse and process: towards a multidisciplinary science of texts %I Ablex Publishing Corporation %C Norwood, NJ %A de\|Jong, G. %D 1979 %T Prediction and substantiation: two processes that comprise understanding %J Proc International Joint Conference on Artificial Intelligence %C Tokyo, Japan %P 217-222 %O August %A de\|Jong, G. %D 1981 %T Generalizations based on explanations %J Proc IJCAI 81 %P 67-69 %K * %A de\|Jong, S.P. %D 1980 %T The system for business automation (SBA): a unified application development system %B Information Processing 80 %E S.H.Lavington %P 469-474 %I North Holland %K * %A de\|Leon, L. %A Harris, W.G. %A Evens, M. %D 1983 %T Is there really trouble with Unix? %J Proc ACM CHI 83 Human Factors in Computing Systems %P 125-129 %C Boston, MA %O December 12-15 %A Dietterich, T.G. %A Michalski, R.S. %D 1983 %T A comparative review of selected methods for learning from examples %B Machine learning %E R.S. Michalski, J.G. Carbonell, and T.M. Mitchell %I Tioga %P 41-81 %A Denning, P.J. %D 1982 %T Computer-based predictive writing %J Comm ACM %V 25 %N 5 %P 315-316 %O May %K * %A Denning, P.J. %D 1984 %T Educational ruminations %J Comm ACM %V 27 %N 10 %P 979-983 %O October %A Denning, P.J. %D 1985 %T The science of computing: what is Computer Science? %J American Scientist %V 73 %O January/February %K * %A Dewdney, A.K. %D 1984 %T Computer recreations %J Scientific American %V 250 %N 5 %P 14-22 %O May %A Downs, T. %A Cook, A.S. %A Rogers, G. %D 1984 %T A partitioning approach to yield estimation for large circuits and systems %J IEEE Trans Circuits and Systems %V CAS-31 %N 5 %P 472-485 %O May %K * %A Downs, T. %D 1985 %T An approach to the modeling of software testing with some applications %J IEEE Trans Software Engineering %V SE-11 %N 4 %P 375-386 %O April %K * %A Drummond, M. %D 1983 %T A proposal to study the cost-effectiveness of planning, acting, and sensing %R DAI Working paper %I Department of Artificial Intelligence, University of Edinburgh %K * %A Dubes, R. %A Jain, A.K. %D 1979 %T Validity studies in clustering methodologies %J Pattern Recognition %V 11 %P 225-254 %K * %A Duda, R. %A Gaschnig, J. %A Hart, P. %D 1979 %T Model design in the Prospector consultant system for mineral exploration %E D. Michie %B Expert systems in the microelectronic age %I Edinburgh University Press %K * %A Dumais, S. %A Landauer, T. %D 1982 %T Psychological investigations of natural terminology for command and query languages %B Directions in human/computer interactions %E Badre and Shneiderman %I Ablex Publishing Corporation %C Norwood, NJ %P 95-110 %A Dumais, S. %A Landauer, T. %D 1983 %T Using examples to describe categories %J Proc ACM CHI 83 Human Factors in Computing Systems %P 112-115 %C Boston, MA %O December 12-15 %K * %A Dunham, M.O. %A Gray, R.M. %D 1985 %T An algorithm for the design of labeled-transition finite-state vector quantization %J IEEE Trans Communications %V COM-33 %N 1 %P 83-89 %O January %K * %A Dyer, M.G. %D 1983 %T In-depth understanding %I MIT Press %C Cambridge, MA %A Dynkin, E.B. %D 1965 %T Controlled random sequences %J Theoretical Probability and its Applications %V X %N 1 %K * %A Eason, K.D. %A Damodaran, L %D 1979 %T Design procedures for user involvement and user support %J Infotech - Man Computer Communications %C London, England %A Edelsbrunner, H. %A Maurer, H.A. %D 1985 %T Finding extreme points in three dimensions and solving the post-office problem in the plane %J Information Processing Letters %V 21 %P 39-47 %O 10 July %K * %A Efron, B. %A Thisted, R. %D 1976 %T Estimating the number of unseen species: how many words did Shakespeare know? %J Biometrika %V 63 %N 3 %P 435-447 %K * %A Eisenstadt, E. %A Hasemar, T. %D 1985 %T An improved user interface for Prolog %E B.Shackel %B Human-Computer Interaction: Proceedings INTERACT 84 %I North Holland %P 109-113 %K * %A Ekeberg, O. %D 1986 %T Robust dictionary lookup using associative methods %R Research Report %I Computer Vision and Associative Pattern Processing Laboratory, Department of Computing Science, Royal Institute of Technology %C Stockholm, Sweden %K * %A Elias, P. %D 1955 %T Predictive coding: Part I and Part II %J IRE Trans Information Theory %V IT-1 %N 1 %P 16-33 %K * %A Elias, P. %D 1970 %T Bounds on performance of optimum quantizers %J IEEE Trans Information Theory %V IT-16 %N 2 %P 172-184 %O March %K * %A Elias, P. %D 1975 %T Universal codeword sets and representations of the integers %J IEEE Trans Information Theory %V IT-21 %N 2 %P 194-203 %O March %K * %A Elliott, S.J. %A Nelson, P.A. %D 1985 %T An algorithm for multichannel LMS adaptive filtering %R Research Report %I Institute of Sound and Vibration Research, University of Southampton %C Southampton, England %K * %A Ellis, C.A. %A Nutt, G.J. %D 1979 %T On the equivalence of office models %R Research Report SSL-79-8 %I Xerox PARC %O December %K * %A Ellis, C.A. %T Formal and informal models of office activity %R Research Report %I Xerox PARC %K * %A Ellis, C.A. %A Bernal, M. %D 1982 %T Officetalk-D: an experimental office information system %J Proc ACM Conference %P 131-140 %K * %A Embley, D.W. %A Nagy, G. %D 1981 %T Behavioral aspects of text editors %J Computing Surveys %V 13 %N 1 %P 33-70 %O March %K * %A Engel F.L. %A Andriessen J.J. %A Schmitz, H.J.R. %D 1983 %T What, where and whence: means for improving electronic data access %J IJMMS %V 18 %P 145-160 %A Englebart, D.C. %A English, W.K. %D 1968 %T A research center for augmenting human intellect %J Proc Fall Joint Computer Conference %V 33 %P 395-410 %I AFIPS Press %C Arlington, VA %A Ernvall, J. %A Nevalainen, O. %D 1984 %T Estimating the length of minimal spanning trees in compression of files %J BIT %V 24 %P 19-32 %K * %A Even, S. %A Rodeh, M. %D 1978 %T Economical encodings of commas between strings %J Comm ACM %V 21 %P 315-317 %O April %K * %A Even, S. %A Pratt, V. %A Rodeh, M. %D 1981 %T Linear algorithm for data compression via string matching %J J ACM %V 28 %N 1 %P 16-24 %O January %A Everitt, B. %D 1974 %T Cluster analysis %I Heineman %C London, England %A Fano, R.M. %D 1949 %T The transmission of information %R Technical Report 65 %I Research Laboratory of Electronics, MIT %C Cambridge, MA %A Feigenbaum, E.A. %A McCorduck, P. %D 1983 %T The fifth generation %I Addison-Wesley %C Reading, MA %A Ferrans, J.C. %D 1982 %T SEDL \(em a language for specifying integrity constraints on office forms %J SIGOA Newsletter (Proc SIGOA Conference on Office Information Systems) %V 3 %N 3/4 %P 123-130 %C Philadelphia, PA %O June 21-23 %K * %A Fikes, R. %A Kehler, T. %D 1985 %T The role of frame-based representation in reasoning %J Comm ACM %V 28 %N 9 %P 904-920 %O September %K * %A Filipski, A. %A Hanko, J. %D 1986 %T Making UNIX secure %J Byte %P 113-128 %O April %A Fillmore, C.J. %D 1968 %T The case for case %E E.Bach and R.T.Harms %B Universals in linguistic theory %P 1-88 %I Holt, Reinhart and Winston %C Chicago, IL %K * %A Finkel, R.A. %A Bentley, J.L. %D 1974 %T Quad trees -- a data structure for retrieval on composite keys %J Acta Informatica %V 4 %N 1 %P 1-9 %A Fischer, G. %A Lemke, A. %A Schwab, T. %D 1985 %T Knowledge-based help systems %J Proc Human Factors in Computer Systems %C San Francisco, CA %P 161-167 %O April %K * %A Fitter, M. %D 1979 %T Toward more natural interactive systems %J IJMMS %V 11 %P 339-350 %A Fogel, L.J. %A Owens, A.J. %A Walsh, M.J. %D 1966 %T Artificial intelligence through simulated evolution %I Wiley %A Foley, J.D. %A Wallace, V.L. %A Chan, P. %D 1984 %T The human factors of computer graphics interaction techniques %J IEEE Computer Graphics and Applications %V 4 %N 11 %P 13-48 %O November %K * %A Foster, J. %A Gray, R.M. %A Dunham, M.O. %D 1985 %T Finite-state vector quantization for waveform coding %J IEEE Trans Information Theory %V IT-31 %O May %A Freij, G.J. %A Cheetham, B.M.G. %D 1985 %T Improved sequential linear prediction by selective time-domain coefficient extraction %R Report %K * %A Friedman, J.H. %A Baskett, F. %A Shustek, L.J. %D 1975 %T An algorithm for finding nearest neighbors %J IEEE Trans Computers %V C-24 %P 1000-1006 %O October %K * %A Friedman, J.H. %A Bentley, J.L. %A Finkel, R.A. %D 1977 %T An algorithm for finding best matches in logarithmic expected time %J ACM Trans Mathematical Software %V 3 %N 3 %P 209-226 %O September %K * %A Fukunaga, K. %A Narendra, P.M. %D 1975 %T A branch and bound algorithm for computing \fIk\fP-nearest neighbors %J IEEE Trans Computers %V C-24 %P 750-753 %O July %K * %A Fulton, M.A. %T A social cognition research model for studying human-computer communication %R Research Report %I Oklahoma State University Business College %C Stillwater, OK %K * %A Gaines, B.R. %D 1976 %T On a danger in the assumption of causality %J IEEE Trans Systems, Man and Cybernetics %V SMC-6 %P 56-59 %A Gaines, B.R. %D 1981 %T Autopoiesis: some questions %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York, NY %P 145-154 %A Gaines, B.R. %D 1981 %T The technology of interaction -- dialog programming rules %J IJMMS %V 14 %N 1 %P 133-150 %O January %A Gaines, B.R. %D 1983 %T From word processing to image processing in office systems %J Proc International Electrical, Electronics Conference %V 2 %P 622-625 %C Toronto, ON %O September 26-28 %K * %A Gaines, B.R. %D 1984 %T Fundamentals of decision: probabilistic, possibilistic and other forms of uncertainty in decision analysis %J Studies in the Management Sciences %V 20 %P 47-65 %A Gaines, B.R. %D 1985 %T Expert systems and simulation in planning flexible manufacturing systems %J Proc Workshop on Coupling Symbolic and Numerical Computing in Expert Systems %I Boeing Computer Services AI Center %C Bellevue, WA %O August 27-29 %A Gaines, B.R. %D 1985 %T The design of expert systems for planning flexible manufacturing %R Research Report %I Computer Science Department, University of Calgary %A Gaines, B.R. %A Shaw, M.L.G %D 1986 %T Foundations of dialog engineering: the development of human-computer interaction Part II %J IJMMS %V 24 %N 2 %P 101-123 %O February %A Gaines, B.R. %D 1986 %T An overview of knowledge acquisition and transfer %J Proc AAAI Workshop on Knowledge Acquisition for Knowledge-based Systems %C Banff, AL %O November %A Galitz, W.O. %D 1980 %T Human factors in office automation %I Life Office Management Association %C Atlanta, GA %A Gardner, M. %T In which `monster' curves force redefinition of the word `curve' %J Scientific American %P 124-133 %K* %A Gargantini, I. %A Atkinson, H.H. %D 1984 %T Linear quadtrees: a blocking technique for contour filling %J Pattern Recognition %V 17 %N 3 %P 285-293 %K * %A Gargantini, I.A. %D 1983 %T Recent results on linear quadtrees and related techniques %R Report 111 %I Computer Science Department, University of Western Ontario %C London, ON %O December (to appear in \fIPattern recognition\fP) %K * %A Garudadri, H. %A Beddoes, M.P. %A Gilbert, J.H.V. %A Benguerel, A.P. %T Identification of invariant acoustic cues in stop consonants using the Wigner distribution %J %K * %A Garvey, T.D. %A Lowrance, J.D. %A Fischler, M.A. %D 1981 %T An inference technique for integrating knowledge from disparate sources %J Proc 7th International Joint Conference on Artificial Intelligence %P 319-325 %C Vancouver, BC %O August %K * %A Gehani, N.H. %D 1983 %T An electronic form system -- an experience in prototyping %J Software -- Practice and Experience %V 13 %P 479-486 %K * %A Gehani, N.H. %D 1983 %T High level form definition in office information systems %J Computer J %V 26 %N 1 %P 52-59 %K * %A Geller, V.J. %A Lesk, M.E. %D 1981 %T How users search: a comparison of menu and attribute retrieval systems on a library catalog %R Internal Report %I Bell Laboratories %K * %A Genesereth, M.R. %A Ginsberg, M.L. %D 1985 %T Logic programming %J Comm ACM %V 28 %N 9 %P 933-941 %O September %K * %A Genesereth, M.R. %A Ginsberg, M.L. %A Rosenschein, J.S. %D 1985 %T Solving the prisoner's dilemma %R Research Report STAN-CS-84-1032 %I Computer Science Department, Stanford University %C Stanford, CA %K * %A Giles, R. %D 1976 %T Lucasiewicz logic and fuzzy set theory %J IJMMS %V 8 %P 313-327 %A Ginsberg, M.L. %D 1985 %T Does probability have a place in non-monotonic reasoning? %J Proc IJCAI %P 107-110 %K * %A Georgeff, M. %A Lansky, A.L. %A Bessiere, P. %D 1985 %T A procedural logic %J Proc International Joint Conference on Artificial Intelligence %C Los Angeles, CA %O August %K * %A Gersham, A.V. %D 1982 %T A framework for conceptual analyzers %E W.G. Lenhert and M.H. Ringle %B Strategies for natural language processing %I Lawrence Erlbaum Associates %P 177-202 %A Gersho, A. %D 1979 %T Asymptotically optimal block quantization %J IEEE Trans Information Theory %V IT-25 %N 4 %P 373-380 %O July %K * %A Gevarter, W.B. %D 1983 %T An overview of computer-based natural language processing %R NASA Technical Memorandum 85635 %C Washington, DC %A Gevarter, W.B. %D 1983 %T Expert systems: limited but powerful %J IEEE Spectrum %P 39-45 %O August %A Gibbon, D. %A Richter, H.\0(Editors) %D 1984 %T Intonation, Accent and Rhythm %I de Gruyter %C Berlin %A Gibbs, R.W. %A Tenney, Y.J. %D 1980 %T The concept of scripts in understanding stories %J J Psycholinguistic Research %V 9 %N 3 %P 275-284 %K * %A Gibson, B. %A Wittig, R. %D 1983 %T The Develnet LAN: architecture and experience %J Proc International Electrical, Electronics Conference %V 1 %P 26-29 %C Toronto, ON %O September 26-28 %K * %A Girill, T.R. %A Luk, C.H. %D 1983 %T DOCUMENT: an interactive, online solution to four documentation problems %J Comm ACM %V 26 %N 5 %P 328-337 %O May %A Glinert, E.P. %A Tanimoto, S.L. %D 1984 %T Pict: an interactive graphical programming environment %J IEEE Computer %V 17 %N 11 %P 7-25 %O November %K * %A Glinert, E.P. %A Ladner, R.E. %D 1984 %T A large font virtual terminal interface %J Comm ACM %V 27 %N 7 %P 567-572 %O June %K * %A Godfrey, D. %A Chang, E.\0(Editors) %D 1981 %T The Telidon book %I Press Porcepic %C Toronto, ON %A Goldshlager, L.M. %D 1980 %T Short algorithms for space-filling curves %J Software -- Practice and Experience %V 11 %P 99-100 %O September %K * %A Good, D.I. %D 1982 %T The proof of a distributed system in Gypsy %R Technical Report 30 %I Institute for Computing Science, University of Texas at Austin %C Austin, TX %O September %K * %A Gordon, J. %A Shortliffe, E.H. %D 1984 %T The Dempster-Shafer theory of evidence %B Rule-based expert systems %E B.G.Buchanan and E.H.Shortliffe %I Addison-Wesley %C Reading, MA %P 272-292 %A Gordon, J. %A Shortliffe, E.H. %D 1985 %T A method for managing evidential reasoning in a hierarchical hypothesis space %J Artificial Intelligence %V 26 %P 323-357 %A Gosling, J.A. %D 1981 %T A redisplay algorithm %J SIGOA Newsletter (Proc ACM Symposium on Text manipulation) %C Portland, OR %V 2 %N 1/2 %P 123-129 %O Spring/Summer %A Gosling, J.A. %A Rosenthal, D.S.H. %D 1983 %T A network window-manager %R Report %I Information Technology Center, Carnegie-Mellon University %C Pittsburgh, PA %K * %A Grampp, F.T. %A Morris, R.H. %D 1984 %T UNIX operating system security %J Bell System Technical J %V 62 %N 8, part 2 %P 1649-1672 %O October %A Grasser, A.C. %D 1981 %T Prose comprehension beyond the word %I Springer-Verlag %C New York, NY %A Gray, R.M. %A Kieffer, J.C. %A Linde, Y. %D 1980 %T Locally optimal block quantizer design %J Information and Control %V 45 %P 178-198 %K * %A Gray, R.M. %D 1984 %T Hardware realization of waveform vector quantizers %J IEEE Trans %V SAC-2 %N 2 %A Green, M. %D 1982 %T Towards a user interface prototyping system %J Proc Graphics Interface 82 %P 37-45 %K * %A Greenberg, S. %D 1984 %T User modeling in interactive computer systems %R MSc Thesis %I Computer Science Department, University of Calgary %A Greenberg, S. %A Witten, I.H. %D 1984 %T Comparison of menu displays for ordered lists %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 464-469 %O May %K KConference %A Greenberg, S. %A Witten, I.H. %D 1985 %T Adaptive personalized interfaces -- a question of viability %J Behaviour and Information Technology %V 4 %N 1 %P 31-45 %O January-March %K KJournal %A Greenberg, S. %A Witten, I.H. %D 1985 %T Interactive end-user creation of workbench hierarchies within a window system %J Proc Canadian Information Processing Society Conference %C Montreal, QUE %P 408-416 %O May %K KConference %A Greenberg, S. %A Peterson, M. %A Witten, I.H. %D 1986 %T Issues and experiences in the design of a window management system %J Proc Canadian Information Processing Society Conference %C Edmonton, AL %P 33-44 %K KConference %A Grice, H.P. %D 1957 %T Meaning %J Philosophical Review %V LXVI %N 3 %P 377-388 %K * %A Grice, H.P. %D 1969 %T Utterer's meaning and intentions %J Philosophical Review %V LXXVIII %N 2 %P 147-177 %K * %A Grossner, C.P. %A Radhakrishnan, T. %A Pospiech, A. %D 1983 %T An integrated workstation for the visually handicapped %J IEEE Micro %P 8-16 %O June %K * %A Gullichsen, E. %A Chang, E. %D 1985 %T Generative design in architecture using an expert system %R Research Report %I Computer Science Department, University of Victoria %O February %K * %A Hagelbarger, D.W. %A Thompson, R.A. %D 1983 %T Experiments in teleterminal design %J IEEE Spectrum %P 40-45 %O October %K * %A Halbert, D.C. %D 1984 %T Programming by example %R Technical Report %I Xerox PARC, (Office Products Division) %C Palo Alto, CA %O December %A Hammond, P. %A Sergot, M. %D 1983 %T A Prolog shell for logic based expert systems %J Proc Expert Systems 83 %I Churchill College %C Cambridge, England %P 95-104 %O December %K * %A Hammond, P. %D 1984 %T Representation of DHSS regulations as a logic program %J Proc Expert Systems 83 %I Churchill College %C Cambridge, England %P 225-235 %O December %K * %A Hanson, S.J. %A Kraut, R.E. %A Farber, J.M. %D 1984 %T Interface design and multivariate analysis of UNIX command use %J ACM Trans Office Information Systems %V 2 %N 1 %O March %A Harrison, A.F. %A Bramson, R.M. %T The art of thinking %I Berkley Books %C New York, NY %K * %A Harth, E. %D 1982 %T Windows on the mind %I Harvester Press %C Brighton, Sussex %A Hartigan, J.A. %D 1975 %T Clustering algorithms %I Wiley %A Hartley, J. %D 1978 %T Designing instructional text %I Kogan Page %C London, England %A Hartley, J. %D 1982 %T Designing instructional text %E D.H. Jonassen %B The technology of text %I Educational Technology Publications %C Englewood Cliffs, NJ %A Hasling, D.W. %A Clancey, W.J. %A Rennels, G. %D 1984 %T Strategic explanations for a diagnostic consultation system %J IJMMS %V 20 %P 3-19 %K * %A Haugeland, J. %D 1979 %T Understanding natural language %V LXXVI %N 11 %P 619-632 %O November %K * %A Hayes, P. %T The naive physics manifesto %K * %A Hayes, P.J. %A Ball, E. %A Reddy, R. %D 1983 %T Breaking the man-machine communication barrier %J IEEE Computer %P 19-30 %O March %K * %A Hayes, P.J. %D 1984 %T Executable interface definitions using form-based interface abstractions %R Report CMS-CS-84-110 %I Computer Science Department, Carnegie-Mellon University %K * %A Hayes, P.J. %A Szekely, P.A. %A Lerner, R.A. %D 1985 %T Design alternatives for user interface management systems based on experience with Cousin %J Proc Human Factors in Computer Systems %C San Francisco, CA %P 169-175 %O April %K * %A Hayes, P.J. %A Lerner, R.A. %A Szekely, P.A. %T The COUSIN user interface project %K * %A Hayes-Roth, F. %D 1985 %T Rule-based systems %J Comm ACM %V 28 %N 9 %P 921-932 %O September %K * %A Hays, D.G. %D 1964 %T Dependency theory -- a formalism and some observations %J Language %V 40 %P 511-25 %A Heath, F.G. %A Foulk, P.W. %A Li, D.Y. %D 1984 %T Analysis and restructuring of concurrent systems using Prolog %J Proc IEEE Part E %V 131 %N 5 %P 169-176 %O September %K * %A Heckbert, P. %D 1982 %T Color image quantization for frame buffer display %J Proc SIGGRAPH 82 %C Boston, MA %P 297-307 %O July %K * %A Held, G. %D 1984 %T Data compression: techniques and applications %I Wiley %C New York, NY %A Hendrix, G.G %A Sacerdoti, E.D. %A Sagalowicz, D. %A Slocum, J. %D 1978 %T Developing a natural language interface to complex data %J ACM Trans Database Systems %V 3 %N 2 %O June %A Hester, J.H. %A Hirschberg, D.S. %D 1985 %T Self-organizing linear search %J Computing Surveys %V 17 %N 3 %P 295-311 %O September %A Hewitt, C. %D 1977 %T Viewing control structures as patterns of passing messages %J Artificial Intelligence %V 8 %P 323-364 %A Hewitt, C. %A de\|Jong, P.S. %D 1982 %T Open systems %R AI Memo 691 %I MIT Artificial Intelligence Laboratory %O December %K * %A Hewitt, C. %A de\|Jong, P.S. %D 1983 %T Analyzing the roles of descriptions and actions in open systems %R AI Memo 727 %I MIT Artificial Intelligence Laboratory %O April %K * %A Hewitt, C. %A de\|Jong, P.S. %D 1983 %T Message passing semantics as a foundation for reasoning in open systems %R Research Report %I MIT Artificial Intelligence Laboratory %O May %K * %A Hibbard, P. %D 1983 %T User manual for MINT -- the SPICE document preparation system %R Technical Report %I Computer Science Department, Carnegie-Mellon University %C Pittsburgh, PA %A Hilbert, D. %D 1891 %T Ueber die stetige Abbildung einer Linie auf ein Flachenstuck %J Math Annalen %V 38 %P 459-460 %K * %A Hill, D.R. %A Dohrn, C. %A Darragh, J. %A Esau, R. %A Levinson, D. %A Unger, B. %A Witten, I.H. %D 1984 %T Using speech output as a medium for human-computer dialogue %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 470-476 %O May %K KConference %A Hill, D.R. %A Witten, I.H. %A Neal, R. %A Lomow, G. %D 1984 %T Jecl and Hide: practical questions for the Jade user interface %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 373-380 %O May %K KConference %A Hiltz, S.R. %A Turoff, M. %D 1985 %T Structuring computer-mediated communication systems to avoid information overload %J CACM %V 28 %N 7 %P 680-689 %O July %A Hintikka, K.J. %D 1975 %T The intentions of intentionality %I D. Reidel %C Dordrecht, Holland %A Ho, C.S. %A Hong, Y.C. %A Kuo, T.S. %D 1986 %T A society model for office information systems %J ACM Trans Office Information Systems %V 4 %N 2 %P 104-137 %O April %K * %A Horspool, R.N. %A Cormack, G.V. %D 1984 %T A general-purpose data compression technique with practical computer applications %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 138-141 %O May %K * %A Horspool, R.N. %A Cormack, G.V. %D 1985 %T Comments on `Data compression using static Huffman code-decode tables' %O submitted to CACM, November 1985 %K * %A Horspool, R.N. %A Cormack, G.V. %D 1986 %T Dynamic Markov modelling -- a prediction technique %J Proc International Conference on the System Sciences %C Honolulu, HA %O January %K * %A Hosticka, B.J. %D 1985 %T Performance comparison of analog and digital circuits %J Proc IEEE %V 73 %N 1 %P 25-29 %O January %A Hou, H.S. %A Andrews, H.C. %D 1978 %T Cubic splines for image interpolation and digital filtering %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-26 %N 6 %P 508-517 %O December %K * %A Hovy, E.H. %T Integrating text planning and production in generation %J Proc IJCAI %P 848-851 %K * %A Hunter, R. %A Robinson, A.H. %D 1980 %T International digital facsimile coding standards %J Proc IEEE %V 68 %N 7 %P 854-867 %O July %K * %A Hutchings, E. %D 1983 %T The autonomous Viking %J Science %V 219 %P 803-808 %O February 18 %A Jackendoff, R. %D 1985 %T Semantics and cognition %I MIT Press %C Cambridge, MA %A Jakobsson, M. %D 1985 %T Compression of character strings by an adaptive dictionary %J BIT %V 25 %N 4 %P 593-603 %K * %A Jantsch, E. %D 1981 %T Autopoiesis: a central aspect of dissipative self-organization %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York, NY %P 65-88 %A Jarvis, J.F. %D 1984 %T Robotics %J IEEE Computer %P 283-292 %O October %K * %A Jarvis, R.A. %D 1983 %T Growing polyhedral obstacles for planning collision-free paths %J Australian Computer J %V 15 %N 3 %P 103-111 %O August %K * %A Jaynes, J. %D 1976 %T The origin of consciousness in the breakdown of the bicameral mind %I Houghton Mifflin %C Boston, MA %A Jefferson, D.R. %D 1985 %T Virtual time %J ACM Trans Programming Languages and Systems %V 7 %N 3 %P 404-425 %O July %K * %A Johnson, W.L. %A Soloway, E. %A Cutler, B. %A Draper, S.W. %D 1983 %T Bug catalogue: I %R Research Report %I Cognition and Programming Project, Computer Science Department, Yale University %O October %K * %A Jones, H. %D 1976 %T Stanley Morison displayed %I Frederick Muller %C London, England %A Jones, L.P. %A Iyengar, S.S. %D 1984 %T Space and time efficient virtual quadtrees %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-6 %N 2 %P 244-247 %O March %K * %A Kaczmarek, T. %A Mark, W. %A Sondheimer, N. %D 1983 %T The Consul/CUE interface: an integrated interactive environment %J Proc ACM CHI 83 Human Factors in Computing Systems %P 98-102 %C Boston, MA %O December 12-15 %K * %A Kaehler, T. %A Patterson, D. %D 1986 %T A taste of Smalltalk %I W.W. Norton %C New York, NY %A Kang, A.N.C. %A Lee, R.C.T. %A Chang, C-L. %A Chang, S-K. %D 1977 %T Storage reduction through minimal spanning trees and spanning forests %J IEEE Trans Computers %V C-26 %N 5 %P 425-434 %O May %K * %A Kawaguchi, E. %A Endo, T. %D 1980 %T On a method of binary-picture representation and its application to data compression %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-2 %N 1 %P 27-35 %O January %K * %A Kawaguchi, E. %A Endo, T. %A Matsunaga, J.I. %D 1983 %T Depth-first picture expression viewed from digital picture processing %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-5 %N 4 %P 373-384 %O July %K * %A Kelley, J.F. %A Chapanis, A. %D 1982 %T How professional persons keep their calendars: implications for computerization %J J Occupational Psychology %V 55 %P 241-256 %K * %A Kennedy, H.C.\0(Editor) %D 1980 %T Selected works of Guiseppe Peano %I Allen and Unwin %C Winchester, MA %A Keye, M. %D 1984 %T Technique for real time pitch period estimation %R Submitted to \fIElectronics Letters\fP %K * %A Kidd, A.L. %A Cooper, M.B. %D 1985 %T Man-machine interface issues in the construction and use of an expert system %J IJMMS %V 22 %P 91-102 %K * %A Kigger, J. %D 1984 %T The depth/breadth trade-off in the design of menu-driven user interfaces %J IJMMS %V 20 %A Klir, G.J. %A Parviz, B. %D 1985 %T General reconstruction characteristics of probabilistic and possibilistic systems %R Research Report %K * %A Knuth, D.E. %A Plass, M.F. %D 1981 %T Breaking paragraphs into lines %J Software -- Practice and Experience %V 11 %P 1119-1184 %A Knuth, D.E. %D 1983 %T The WEB system of structured documentation %R Report STAN-CS-83-980 %I Computer Science Department, University of Stanford %C Stanford, CA %A Knuth, D.E. %D 1984 %T Literate programming %J Computer J %V 27 %N 2 %P 97-111 %K * %A Kolata, G. %D 1986 %T Shakespeare's new poem: an ode to statistics %J Science %V 231 %P 335-336 %O 24 January %A Kolodner, J. %D 1983 %T Towards an understanding of the role of experience from novice to expert %J IJMMS %V 19 %K * %A Kolodner, J.L. %D 1983 %T Reconstructive memory: a computer model %J Cognitive Science %V 7 %P 281-328 %K * %A Kolodner, J.L. %D 1983 %T Maintaining organization in a dynamic long-term memory %J Cognitive Science %V 7 %P 243-280 %K * %A Konopasek, M. %A Jayaraman, S. %D 1984 %T Expert systems for personal computers: the TK!Solver approach %J Byte %P 137-156 %O May %K * %A Koontz, H. %A O'Donnell, C. %D 1972 %T Principles of management: an analysis of managerial functions %I McGraw Hill %A Korein, J. %A Badler, N. %D 1983 %T Temporal anti-aliasing in computer generated animation %J Computer Graphics %V 17 %N 3 %P 377-388 %O July %K * %A Kornfeld, W.A. %A Hewitt, C.E. %D 1981 %T The scientific community metaphor %J IEEE Trans Systems, Man and Cybernetics %V SMC-11 %N 1 %P 24-33 %O January %K * %A Kowalski, R. %D 1983 %T Logic for expert systems %J Proc Expert Systems 83 %I Churchill College %C Cambridge, England %P 80-93 %O December %K * %A Kraut, R.E. %A Hanson, S.J. %A Farber, J.M. %D 1983 %T Command use and interface design %J Proc ACM CHI 83 Human Factors in Computing Systems %P 120-123 %C Boston, MA %O December 12-15 %K * %A Klir, G.J. %D 1985 %T Architecture of systems problem solving %I Plenum Press %C New York, NY %A Kunin, J.S. %D 1982 %T Analysis and specification of office procedures %R PhD Thesis %I Department of Electrical Engineering and Computer Science, MIT %O February %A Lamb, M. %A Buckley, V. %D 1984 %T New techniques for gesture-based dialogue %J Proc 1st IFIP Conference on Human-Computer Interaction %C London, England %O 4-7 September %K * %A Langdon, G.G %D 1981 %T Tutorial on arithmetic coding %R Research Report RJ3128 %I IBM Research Laboratory %C San Jose, CA %K * %A Langdon, G.G %D 1984 %T An introduction to arithmetic coding %J IBM J Research and Development %V 28 %N 2 %P 135-149 %O March %K * %A Langdon, G.G %D 1983 %T A note on the Ziv-Lempel model for compressing individual sequences %J IEEE Trans Information Theory %V IT-30 %P 284-287 %O March %K * %A Langdon, G.G. %A Rissanen, J.J. %D 1983 %T A doubly-adaptive file compression algorithm %J IEEE Trans Communications %V COM-31 %N 11 %P 1253-1255 %O November %K * %A Langdon, G.G. %A Rissanen, J.J. %D 1982 %T A simple general binary source code %J IEEE Trans Information Theory %V IT-28 %P 800-803 %O September %A Langley, P. %D 1983 %T Learning search strategies through discrimination %J IJMMS %V 18 %P 513-541 %K * %A Lansky, A.L. %D 1985 %T Behavioral planning for multi-agent domains %R NSF Proposal %I SRI International %K * %A Latremouille, S. %A Lee, E. %D 1981 %T The design of videotex tree indexes: the use of descriptors and the enhancement of single index pages %J Telidon Behavioural Research %V 2 %I Department of Communications %O May %A Lauer, H.C. %A Needham, R.M. %D 1977 %T On the duality of operating system structures %J Operating Systems: Theory and Practice %K * %A Lazowska, E.D. %A Levy, H.M. %A Almes, G.T. %A Fischer, M.J. %A Fowler, R.J. %A Vestal, S.C. %D 1981 %T The architecture of the Eden system %J Proc Eighth Symposium on Operating System Principles %P 148-159 %C Pacific Grove, CA %O December %K * %A Lebowitz, M. %D 1980 %T Generalization and memory in an integrated understanding system %R PhD Thesis %I Yale University %C New Haven, CT %A Lebowitz, M. %D 1981 %T The nature of generalization in understanding %J Proc IJCAI 81 %P 348-353 %K * %A Lebowitz, M. %D 1983 %T Generalization from natural language text %J Cognitive Science %V 7 %P 1-40 %K * %A Lee, A. %A Lochovsky, F.H. %D 1983 %T Enhancing the usability of an office information system through direct manipulation %J Proc ACM CHI 83 Human Factors in Computing Systems %P 130-134 %C Boston, MA %O December 12-15 %K * %A Lee, D.T. %D 1982 %T On \fIk\fP-nearest neighbor Voroni diagrams in the plane %J IEEE Trans Computers %V C-31 %N 6 %P 478-487 %O June %K * %A Lee, D.T. %A Preparata, F.P. %D 1984 %T Computational geometry -- a survey %J IEEE Trans Computers %V C-33 %N 12 %P 1072-1101 %O December %A Lefebvre, V.A. %D 1977 %T The structure of awareness %I Sage Publications %C Beverly Hills, CA %O (english translation by A.Rapoport) %A Lehar, A.F. %A Stevens, R.J. %D 1984 %T High-speed manipulation of the color chromaticity of digital images %J IEEE Computer Graphics and Applications %P 34-39 %O February %K * %A Lehnert, W.G. %D 1977 %T A conceptual theory of question answering %J Proc International Joint Conference on Artificial Intelligence %I MIT %C Cambridge, MA %P 158-164 %O August %A Lehnert, W.G. %D 1978 %T The process of question answering %I Lawrence Erlbaum Associates %C Hillsdale, NJ %K * %A Lehnert, W.G. %A Dyer, M.G. %A Johnson, P.N. %A Yang, C.J. %A Harley, S. %D 1983 %T BORIS: an experiment in in-depth understanding of narratives %J Artificial Intelligence %V 20 %P 15-62 %K * %A Lemer, L. %D 1974 %T A.R.T.H.U.R. The life and opinions of a digital computer %I Harvester Press %C Sussex, England %A Lempel, A. %A Ziv, J. %T Compression of two-dimensional data %K * %A Lenat, D. %D 1983 %T The role of heuristics in learning by discovery: three case studies %B Machine learning %E R.S. Michalski, J.G. Carbonell, and T.M. Mitchell %I Tioga %P 243-306 %A Lenat, D.B. %A Sutherland, W.R. %A Gibbons, J. %D 1982 %T Heuristic search for new microcircuit structures: an application of artificial intelligence %J AI Magazine %P 17-33 %O Summer %K * %A Lenat, D.B. %D 1983 %T EURISKO: a program that learns new heuristics and domain concepts %J Artificial Intelligence %V 21 %P 61-98 %K * %A Lenat, D.B. %A Brown, J.S. %D 1984 %T Why AM and EURISKO appear to work %J Artificial Intelligence %V 23 %P 269-294 %A Lenat, D.B. %A Prakesh, M. %A Shepherd, M. %D 1986 %T CYC: using common sense knowledge to overcome brittleness and knowledge acquisition bottlenecks %J The AI Magazine %P 65-85 %O Winter %K * %A Lewis, J. %D 1963 %T Typography: basic principles. Influences and trends since the 19th century %I Van Nostrand Reinhold %C New York, NY %A Lewis, J.W. %D 1983 %T An effective graphics user interface for rules %J Proc ACM CHI 83 Human Factors in Computing Systems %P 139-143 %C Boston, MA %O December 12-15 %K * %A Lewis, J.M. %T Analysing the action of UNIX-users %D 1986 %O March %I University of Edinburgh, Department of Artificial Intelligence %K * %A Li, D.Y. %A Heath, F.G. %D 1983 %T ILEX: an intelligent relational database system %J Proc ACM Conference on Personal and Small Computers %C San Diego, CA %P 245-252 %O December %K * %A Liang, F.M. %D 1983 %T Word hy-phen-a-tion by com-put-er %R PhD Thesis %I Computer Science Department, Stanford University %C Stanford, CA %K * %A Lieberman, H. %D 1978 %T How to color in a coloring book %J Proc SIGGRAPH 78 %P 111-116 %K * %A Lieberman, H. %D 1984 %T Seeing what your programs are doing %J IJMMS %V 21 %N 4 %P 311-331 %O October %A Linde, Y. %A Buzo, A. %A Gray, R.M. %D 1980 %T An algorithm for vector quantizer design %J IEEE Trans Communications %V COM-28 %N 1 %P 84-95 %O January %K * %A Linington, P.F. %D 1983 %T Fundamentals of the layer service definitions and protocol specifications %J Proc IEEE %V 71 %N 12 %P 1341-1345 %O December %A Ljolje, A. %A Fallside, F. %D 1986 %T Synthesis of natural sounding pitch contours in isolated utterances using hidden Markov models %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-34 %N 5 %P 1074-1079 %O October %K * %A Lloyd, J.W. %D 1984 %T Foundations of logic programming %I Springer-Verlag %C Berlin %A Lowrance, R. %A Wagner, R.A. %D 1975 %T An extension of the string-to-string correction problem %J J ACM %V 22 %N 2 %P 177-183 %O April %K * %A Lozano-Perez, T. %A Wesley, M.A. %D 1979 %T An algorithm for planning collision-free paths among polyhedral obstacles %J Comm ACM %V 22 %N 10 %P 560-570 %O October %K * %A Lozano-Perez, T. %D 1981 %T Automatic planning of manipulator transfer movements %J IEEE Trans Systems, Man and Cybernetics %V SMC-11 %N 10 %P 681-698 %O October %A Lozano-Perez, T. %D 1983 %T Robot programming %J Proc IEEE %V 71 %N 7 %P 821-841 %O July %A Lu, M.I. %A Chen, C.F. %T Modified Huffman code %R Research Report %I Departmental of Electrical Engineering, Tatung Institute of Technology %C Taipei, Taiwan %K * %A Lynch, T.J. %D 1985 %T Data compression -- techniques and applications %I Lifetime Learning Publications %C Belmont, CA %A MacMillan, S.A. %D 1984 %T User models to personalize an intelligent agent %R PhD Thesis %I Stanford University %A MacQueen, J.B. %D 1967 %T Some methods for classification and analysis of multivariate observations %J Proc 5th Berkeley Symposium on Mathematical Statistics and Probability %V 1 %P 281-297 %A Maguire, M. %D 1982 %T An evaluation of published recommendations on the design of man-computer dialogues %J IJMMS %V 16 %N 3 %P 237-261 %O April %A Malcolm, M. %A Dyment, D. %D 1983 %T Experience designing the Waterloo Port user interface %J Proc ACM Conference on Personal and Small Computers %C San Diego, CA %P 168-175 %O December %K * %A Mannos, J.L. %A Sakrison, D.J. %D 1974 %T The effects of a visual fidelity criterion on the encoding of images %J IEEE Trans Information Theory %V IT-20 %N 4 %O July %K * %A Mantei, M. %D 1982 %T Disorientation behavior in person-computer interactions %R PhD Thesis %I University of Southern California %C Los Angeles, CA %A Maragos, P.A. %A Schafer, R.W. %A Mersereau, R.M. %D 1984 %T Two-dimensional linear prediction and its application to adaptive predictive coding of images %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-32 %N 6 %P 1213-1229 %O December %K * %A Marchetti, C. %D 1980 %T Society as a learning system: discovery, invention, and innovation cycles revisited %J Technological Forecasting and Social Change %V 18 %P 267-282 %K * %A Martin, T. %D 1980 %T Information retrieval %B Human interaction with computers %E Smith and Green %I Academic Press %C London, England %P 161-175 %A Maslow, A.H. %D 1954 %T Motivation and personality %I Harper and Row %C New York, NY %A Maslow, A.H. %D 1968 %T Toward a psychology of being %I Van Nostrand Reinhold %C New York, NY %O second edition %A Masrani, R. %A Keenan, T.P. %D 1984 %T Security and privacy in cellular telephone systems %J Proc AFIPS Conference on Computer Security %C Toronto, ON %O September %K * %A Masrani, R. %A Witten, I.H. %D 1984 %T Natural language processing in object-oriented Prolog %R Unpublished note %O September %A Mathews, M.V. %D 1969 %T The technology of computer music %I MIT Press %A Maturana, H.R. %D 1975 %T The organization of the living: a theory of the living organization %J IJMMS %V 7 %P 313-332 %A Maturana, H.R. %A Varela, F.J. %D 1980 %T Autopoiesis and cognition %I D. Reidel %C Dordrecht, Holland %A Mazer, M.S. %A Lochovsky, F.H. %D 1984 %T Logical routing specification in office information systems %J ACM Trans Office Information Systems %V 2 %N 4 %P 303-330 %O October %A McCarthy, J. %D 1980 %T Circumscription -- a form of non-monotonic reasoning %J Artificial Intelligence %V 13 %P 27-39 %K * %A McCracken, D.L. %A Akscyn, R.M. %D 1984 %T Experience with the ZOG human-computer interface system %J IJMMS %V 21 %N 4 %P 293-310 %O October %A McCulloch, W.S. %D 1954 %T Through the den of the metaphysician %J British J Philosophy of Science %V 5 %P 18-31 %A McDermott, J. %A Steele, B. %D 1981 %T Extending a knowledge-based system to deal with ad hoc constraints %J Proc 7th International Joint Conference on Artificial Intelligence %P 824-828 %A McDermott, J. %T Artificial intelligence meets natural stupidity %B Mind Design %E J. Haugeland %I MIT Press %C Cambridge, MA %P 143-160 %K * %A McDermott, J. %D 1982 %T A temporal logic for reasoning about processes and plans %J Cognitive Science %V 6 %P 101-155 %K * %A McDonald, D. %D 1977 %T Language generation: the linguistics component %J Proc International Joint Conference on Artificial Intelligence %P 142 %K * %A McDonald, D.D. %A Pustejovsky, J.D. %D 1985 %T Description-directed natural language generation %J Proc IJCAI %P 799-805 %K * %A McKeown, K.R. %A Wish, M. %A Matthews, K. %T Tailoring explanations for the user %J Proc IJCAI %P 794-798 %K * %A McLean, R.S. %D 1983 %T Ontario Ministry of Education specifies its microcomputer %J Proc 4th Canadian Symposium on Instructional Technology %C Winnipeg, MN %O October 19-21 %K * %A Meehan, J.R. %D 1977 %T TALESPIN, an interactive program that writes stories %J Proc 5th International Joint Conference on Artificial Intelligence %P 91-98 %A Mervis, C.B. %A Rosch, E. %D 1981 %T Categorization of natural objects %J Annual Review of Psychology %V 32 %P 89-115 %A Michaelsen, R.H. %A Michie, D. %A Boulanger, A. %D 1985 %T The technology of expert systems %J Byte %P 303-312 %O April %K * %A Miller, P.L. %D 1983 %T ATTENDING: critiquing a physician's management plan %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-5 %N 5 %P 449-461 %O September %K * %A Mitchell, T.M. %D 1982 %T Generalization as search %J Artificial Intelligence %V 18 %P 203-226 %K * %A Mitchell, T.M. %D 1983 %T Learning and problem solving %J Proc IJCAI 83 %P 1139-1151 %C Karlsruhe, W.Germany %O August %K * %A Moffat, A. %D 1986 %T Predictive text compression based on the future rather than the past %R Research Report %I Computer Science Department, University of Canterbury %C Christchurch, New Zealand %K * %A Moher, T.G. %D 1985 %T Estimating the distribution of software complexity \fIwithin\fP a program %J Proc Human Factors in Computer Systems %C San Francisco, CA %P 61-64 %O April %K * %A Mooney, R. %A de\|Jong, G. %T Learning schemata for natural language processing %J Proc IJCAI %P 681-687 %K * %A Morison, S. %D 1951 %T First principles of typography %I Cambridge University Press %C Cambridge, England %A Morrin, T.H. %D 1974 %T A black-white representation of a gray-scale picture %J IEEE Trans Computers %V C-23 %P 184-186 %O February %K * %A Morris, R. %A Cherry, L.L. %D 1975 %T Computer detection of typographical errors %J IEEE Trans Professional Communications %V PC-18 %N 1 %P 54-56 %O March %K * %A Morris, R. %A Thompson, K. %D 1979 %T Password security: a case history %J Comm ACM %V 22 %N 11 %P 594-597 %O November %K * %A Moses, J. %D 1971 %T Symbolic integration: the stormy decade %J Comm ACM %V 14 %N 8 %P 548-560 %A Mullen, J. %D 1984 %T Unlimited vocabulary speech synthesis with low data rates %J Electronics and Power %P 850-852 %O November/December %K * %A Mycielski, J. %D 1985 %T Can mathematics explain natural intelligence? %R Research Report UC-32 %I Los Alamos National Laboratory %C Los Alamos, NM %O July %K * %A Mycroft, A. %A O'Keefe, R.A. %D 1984 %T A polymorphic type system for Prolog %J Artificial Intelligence %V 23 %P 295-307 %K * %A Myers, B.A %D 1986 %T Visual programming, programming by example, and program visualization: a taxonomy %J Proc ACM CHI 86 Human Factors in Computing Systems %P 59-66 %C Boston, MA %O April 13-17 %K * %A Nagy, G. %A Wagle, S. %D 1979 %T Geographic data processing %J Computing Surveys %V 11 %N 2 %P 139-181 %O June %K * %A Nagy, G. %A Paton, K. %D 1982 %T Intelligent facsimile %P Proc Harvard Computer Graphics Week %I Graduate School of Design, Harvard University %K * %A Nagy, G. %D 1983 %T Candide's practical principles of experimental pattern recognition %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-5 %N 2 %P 199-200 %O March %K * %A Nagy, G. %D 1983 %T Optical scanning devices %J IEEE Computer %P 13-24 %O May %K * %A Nagy, G. %A Seth, S. %T Hierarchical image representation with application to optically scanned documents %R Discussion paper %K * %A Nagy, G. %D 1984 %T Advances in information extraction techniques %J Remote Sensing of Environment %V 15 %P 167-175 %K * %A Naiman, A. %D 1984 %T Some new ingredients for the cookbook approach to anti-aliased text %J Proc Graphics Interface 84 %I National Computer Graphics Association of Canada %P 99-108 %O May %A Nakatani, L.H. %A Rohrlich, J.A. %D 1983 %T Soft machines: A philosophy of user-computer interface design %J Proceedings Human Factors in Computer Systems %C Boston, MA %O December 12-15 %K * %A Nasanen, R. %D 1984 %T Visibility of halftone dot textures %J IEEE Trans Systems, Man and Cybernetics %V SMC-14 %N 6 %P 920-924 %O November/December %K * %A Nau, D.S. %D 1983 %T Expert computer systems %J IEEE Computer %V 16 %N 2 %P 63-85 %O February %A Neal, R.M. %A Lomow, G.A. %A Peterson, M.W. %A Unger, B.W. %A Witten, I.H. %D 1984 %T Inter-process communication in a distributed programming environment %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 361-364 %O May %K KConference %A Nelson, G.A. %A Pfeifer, L.L. %A Wood, R.C. %D 1972 %T High-speed octave band digital filtering %J IEEE Trans Audio and Electroacoustics %V AU-20 %P 58-65 %O March %K * %A Niblett, B.\0(Editor) %D 1980 %T Computer science and law %I Cambridge University Press %C Cambridge, England %A Nicol, R.C. %A Fenn, B.A. %A Turkington, R.D. %D 1980 %T Transmission techniques for picture viewdata %J Proc International Broadcasting Convention %K * %A Nicholson, R.T. %D 1985 %T Usage patterns in an integrated voice and data communications system %J ACM Trans Office Information Systems %V 3 %N 3 %P 307-314 %O July %A Nierstrasz, O.M. %D 1985 %T An object-oriented system %E D.Tsichritzis %B Office automation %I Springer-Verlag %C Berlin %P 167-189 %A Nilsson, N.J. %D 1986 %T Probabilistic logic %J Artificial Intelligence %V 28 %P 71-87 %A Nilsson, N.J. %D 1980 %T Principles of artificial intelligence %I Tioga %C Palo Alto, CA %A Nilsson, N.J. %D 1980 %T The interplay between experimental and theoretical methods in artificial intelligence %R Technical Note 229 %I SRI International %O September %K * %A Nilsson, N.J. %D 1981 %T Artificial intelligence: engineering, science, or slogan? %R Technical Note 248 %I SRI International %O July %K * %A Nix, R. %D 1983 %T Editing by example %R PhD Dissertation %I Computer Science Department, Yale University %C New Haven, CT %A Nix, R. %D 1984 %T Editing by example %J Proc 11th ACM Symposium on Principles of Programming Languages %C Salt Lake City, UT %P 186-195 %O January %A Noakes, P.D. %A Aish, R. %D 1984 %T A new peripheral for three-dimensional computer input %J IEEE Micro %V 4 %N 5 %P 26-35 %O October %A Nooteboom, S.G. %D 1983 %T The temporal organization of speech and the process of spoken-word recognition %J IPO Annual Progress Report %V 18 %P 32-36 %K * %A Norman, D.A. %D 1981 %T The trouble about Unix %J Datamation %V 27 %N 12 %P 139-150 %A Norman, D.A. %D 1984 %T Stages and levels in human-machine interaction %J IJMMS %V 21 %N 4 %P 365-375 %O October %A Norman, D.A. %A Draper, S.W.\0(Editors) %D 1986 %T User centered system design \(em new perspectives on human-computer interaction %I Lawrence Erlbaum Associates %C Hillsdale, NJ %A Norman, K.L. %A Weldon, L.J. %A Shneiderman, B. %D 1985 %T Cognitive representations of windows and multiple screen layouts of computer interfaces %R Research Report CAR-TR-123, CS-TR-1498 %I Computer Science Department, University of Maryland %O May %A Null, A. %D 1971 %T Space-filling curves or how to waste time with a plotter %J Software -- Practice and Experience %V 1 %P 403-410 %K * %A Oren, T.I. %A Brzozowski, J.A. %A Gilmore, P.C. %D 1982 %T Crisis in Canadian academic Computer Science: facts and recommendations %R Report prepared by the Executive Committee of Canadian Computer Science Departments Chairmen %O January %A O'Shea, T. %A Self, J. %D 1983 %T Learning and teaching with computers: artificial intelligence in education %I Prentice-Hall %C Englewood Cliffs, NJ %A O'Shea, T. %A Eisenstadt, M.\0(Editors) %D 1984 %T Artificial intelligence: tools, techniques, and applications %I Harper and Row %C New York, NY %A Ogawa, Y. %A Shima, K. %A Sugawara, T. %A Takagi, S. %D 1984 %T Knowledge representation and inference environment: KRINE -- an approach to integration of frame, Prolog and graphics %J Proc International Conference on Fifth Generation Computer Systems %I ICOT %P 643-651 %K * %A Pake, G.E. %D 1985 %T Research at Xerox PARC: a founder's assessment %J IEEE Spectrum %V 22 %N 10 %P 54-61 %O October %A Paliwal, K.K. %A Espeland, O. %D 1983 %T Some considerations about the shape of the window filter in an adaptive gradient lattice algorithm %R Report %I Division of Telecommunications, University of Trondheim %C Trondheim-NTH, Norway %K * %A Papamichalis, P.E. %D 1985 %T Markov-Huffman coding of LPC parameters %J IEEE Trans Acoustics, Speech and Signal Processing %C ASSP-33 %N 2 %P 451-453 %O April %A Park, O.C. %A Tennyson, R.D. %D 1983 %T Computer-based instructional systems for adaptive education: a review %J Contemporary Education Review %V 2 %N 2 %P 121-135 %O Fall %K * %A Parker-Rhodes, A.F. %D 1978 %T Inferential semantics %I Harvester Press %C Brighton, Sussex %A Patil, R.S. %A Szolovits, P. %A Schwartz, W.B. %D 1981 %T Causal understanding of patient illness in medical diagnosis %J Proc 7th International Joint Conference on Artificial Intelligence %P 893-899 %K * %A Patil, R.S. %A Szolovits, P. %A Schwartz, W.B. %T Information acquisition in diagnosis %J Proc International Joint Conference on Artificial Intelligence %P 345-348 %K * %A Patten, T. %D 1986 %T Interpreting systemic grammar as a computational representation: a problem solving approach to text generation %R PhD Thesis %I University of Edinburgh %A Paulus, E. %D 1980 %T The concept of the NN-error risk with respect to an arbitrary separating surface and its applications to clustering %J Proc IEEE Conference %K * %A Pavlidis, T. %D 1981 %T Contour filling in raster graphics %J ACM Computer Graphics %V 15 %N 3 %P 29-36 %O August %K * %A Pawlak, Z. %D 1982 %T Rough sets %J Int J Computer and Information Systems %V 11 %N 5 %P 341-356 %K * %A Pawlak, Z. %D 1985 %T Rough sets and fuzzy sets %J Fuzzy Sets and Systems %P 99-103 %K * %A Paxton, A.L %A Turner, E.J. %D 1984 %T The application of human factors to the needs of the novice computer user %J IJMMS %V 20 %N 2 %P 137-156 %O February %A Peano, G. %D 1890 %T Sur une courbe, qui remplit toute une aire plane %J Math Annalen %V 36 %P 157-160 %K * %A Pearl, J. %D 1985 %T Fusion, propagation, and structuring in Bayesian networks %R Technical Report CSD-850022 R-42, Revision I %I Cognitive Systems Laboratory, Computer Science Department, UCLA %O June %A Pearl, J. %D 1986 %T Fusion, propagation, and structuring in belief networks %J Artificial Intelligence %V 29 %N 3 %P 241-288 %O September %A Peng, X.T. %A Tu, X.C. %A Wang, P.Z. %D 1986 %T Studies on parametric fuzzy controllers %R Research Report %K * %A Pereiro, L.M. %A Nagr, R. %D 1984 %T Delta-Prolog: a distributed logic programming language %R Submitted to Int Conference on 5th Generation Systems %C Tokyo, Japan %O November %K * %A Perlman, G. %D 1981 %T Two papers in cognitive engineering: The design of an interface to a programming system, and MENUNIX: a menu-based interface to Unix (user manual) %R Research Report 8105 %I Center for Human Information Processing, University of California %C San Diego, CA %O November %K * %A Perlman, G. %D 1984 %T Natural artificial languages: low-level processes %J IJMMS %V 20 %N 4 %P 373-419 %O April %A Perry, T.S. %A Wallich, P. %D 1985 %T Inside the PARC: the `information architects' %J IEEE Spectrum %V 22 %N 10 %P 62-75 %O October %A Peters, A.M. %D 1983 %T The units of language acquisition %I Cambridge University Press %C Cambridge, England %A Phillips, J. %D 1983 %T Self-describing programming environments %R PhD Thesis %I Computer Science Department, Stanford University %C Stanford, CA %A Pierce, J.R. %D 1962 %T Symbols, signals and noise %I Hutchinson %C London, England %A Pike, R. %D 1983 %T Graphics in overlapping bitmap layers %J ACM Trans Graphics %V 2 %N 2 %P 135-160 %O April %K * %A Poggio, A. %A Garcia Luna Aceves, J.J. %A Craighill, E.J. %A Moran, D. %A Aguilar, L. %A Worthington, D. %A Hight, J. %D 1985 %T CCWS: a computer-based, multimedia information system %J IEEE Computer %V 18 %N 10 %P 92-103 %O October %A Poritz, A.B. %D 1982 %T Linear predictive hidden Markov models and the speech signal %J Proc %P 1291-1294 %K * %A Post, E. %D 1983 %T Real programmers don't use Pascal %J Datamation %P 263-265 %O July %K * %A Postel, J.B. %D 1980 %T Internetwork protocol approaches %J IEEE Trans Communications %V COM-28 %N 4 %P 604-611 %O April %K * %A Potmesil, M. %A Chakravarty, I. %D 1983 %T Modeling motion blur in computer-generated images %J ACM Computer Graphics %V 17 %N 3 %P 389-399 %O July %K * %A Poulton, A.S. %D 1983 %T Microcomputer speech synthesis and recognition %I Sigma Technical Press %C Wilmslow, Cheshire, UK %A Preucil, M. %A Sebela, Z. %D 1982 %T Computer-assisted simulation of a coal-mine winding system %J Proc 4th Formator Symposium on Mathematical Methods for the Analysis of Large-scale Systems %C Prague %P 391-404 %O May 18-21 %K * %A Prusinkiewicz, P. %A Christopher, M. %D 1984 %T Hologram-like transmission of pictures %R Technical Report CS-84-17 %I Computer Science Department, University of Regina %O November %K * %A Purvy, R. %A Farrell, J. %A Klose, P. %D 1983 %T The design of Star's records processing: data processing for the noncomputer professional %J ACM Trans Office Information Systems %V 1 %N 1 %P 3-24 %O January %K * %A Quinlan, J.R. %D 1983 %T Inferno: a cautious approach to uncertain inference %J Computer J %V 26 %N 3 %P 255-269 %A Qureshi, S.U.H. %D 1985 %T Adaptive equalization %J Proc IEEE %V 73 %N 9 %P 1349-1387 %O September %A Rabiner, L.R. %A Crochiere, R.E. %D 1975 %T A novel implementation for narrow-band FIR digital filters %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-23 %N 5 %P 457-464 %O October %K * %A Radhakrishnan, T. %A Grossner, C.P. %D 1985 %T Cuenet \(em a distributed computing facility %J IEEE Micro %P 42-52 %O February %K * %A Raeder, G. %D 1985 %T A survey of current graphical programming techniques %J IEEE Computer %V 18 %N 8 %P 11-25 %A Rashid, R.F. %D 1980 %T An interprocess communication facility for Unix %R Technical Report %I Computer Science Department, Carnegie-Mellon University %O February %A Rashid, R.F. %A Robertson, G.G. %D 1981 %T Accent: a communication oriented network operating system kernel %J Proc Eighth Symposium on Operating System Principles %P 64-75 %C Pacific Grove, CA %O December %A Rasmussen, J. %D 1983 %T Skills, rules, and knowledge; signals, signs, and symbols, and other distinctions in human performance models %J IEEE Trans Systems, Man and Cybernetics %V SMC-13 %N 3 %P 257-266 %O May/June %K * %A Rassbach, M.E. %D 1980 %T CLASSY: an adaptive clustering algorithm %J Proc IEEE Conference %P 442-444 %K * %A Rawlings, C. %A Fox, J. %D 1983 %T The UNIT package -- a critical appraisal of a frame-based knowledge representation system %J Proc Expert Systems 83 %I Churchill College %C Cambridge, England %P 15-29 %O December %K * %A Redell, D.D. %A White, J.E. %D 1983 %T Interconnecting electronic mail systems %J IEEE Computer %V 16 %N 9 %P 55-63 %O September %K * %A Reeds, J.A. %A Weinberger, P.J. %D 1984 %T File security and the UNIX system \fIcrypt\fP command %J Bell System Technical J %V 63 %N 8, part 2 %P 1673-1684 %O October %A Reichardt, J. %D 1971 %T The computer in art %I Studio Vista %C London, England %A Reiter, R. %D 1980 %T A logic for default reasoning %J Artificial Intelligence %V 13 %P 81-132 %K * %A Reynolds, J.K. %A Postel, J.B. %A Katz, A.R. %A Finn, G.C. %A DeSchon, A.L. %D 1985 %T The DARPA experimental multimedia mail system %J IEEE Computer %V 18 %N 10 %P 82-89 %O October %A Rich, C. %D 1982 %T Knowledge representation languages and predicate calculus: how to have your cake and eat it too %J Proc National Conference on Artificial Intelligence %P 193-196 %A Rich, E. %D 1984 %T The gradual expansion of artificial intelligence %J IEEE Computer %V 17 %N 5 %P 4-12 %O May %A Riesbeck, C.K. %D 1975 %T Conceptual analysis %B Conceptual information processing %E R.C.Schank %I North Holland %C Amsterdam %A Riesbeck, C.K. %D 1981 %T Failure-driven reminding for incremental learning %J Proc IJCAI 81 %P 115-120 %K * %A Riesbeck, C.K. %D 1982 %T Realistic language comprehension %E W.G. Lenhert and M.H. Ringle %B Strategies for natural language processing %I Lawrence Erlbaum Associates %P 37-54 %A Riesbeck, C.K. %D 1984 %T Knowledge reorganization and reasoning style %J IJMMS %V 20 %P 45-61 %K * %A Rissanen, J. %A Langdon, G.G. %T Arithmetic coding %J IBM J Research and Development %D 1979 %V 23 %N 2 %P 149-162 %O March %K * %A Rissanen, J. %D 1984 %T Complexity of strings in the class of Markov sources %R Research Report %I IBM Research Laboratory %C San Jose, CA %K * %A Rissanen, J. %D 1986 %T Stochastic complexity and sufficient statistics %R Research Report %A Ritchie, D.M. %D 1981 %T On the security of UNIX %R Programmers Manual for UNIX System III Volume II: Supplementary Documents %I Western Electric Corporation %A Ritchie, G.D. %A Hanna, F.K. %D 1984 %T AM: a case study in AI methodology %J Artificial Intelligence %V 23 %P 249-268 %K * %A Roberts, M.G. %D 1982 %T Local order estimating Markovian analysis for noiseless source coding and authorship identification %R PhD Thesis %I Stanford University %A Rogers, H. %D 1943 %T Paragraphs on printing %I William E. Rudges %C New York, NY %O re-published by Dover Publications, New York, 1979 %A Rosenthal, D.S.H. %D 1982 %T Managing graphical resources %J Computer Graphics %V 16 %N 4 %P 38-45 %O December %K * %A Ross, P. %A Jones, J. %A Millington, M. %D 1985 %T User modelling in command-driven computer systems %R DAI Research Paper No 264 %I Department of Artificial Intelligence, University of Edinburgh %K * %A Rouse, S.H. %A Rouse, W.B. %D 1980 %T Computer-based manuals for procedural information %J IEEE Trans Systems, Man and Cybernetics %V SMC-10 %N 8 %P 506-510 %O August %A Rowe, N.C. %D 1984 %T Modelling degrees of item interest for a general database query system %J IJMMS %V 20 %N 5 %P 421-443 %O May %K * %A Runciman, C. %A Thimbleby, H. %D 1986 %T Equal opportunity interactive systems %R Report %I Computer Science Department, University of York %C York %K * %A Rychener, M.D. %D 1979 %T A semantic network of production rules in a system for describing computer structures %J Proc 6th Joint Conference on Artificial Intelligence %P 738-743 %A Ryman, R. %A Singh, B. %D 1982 %T The Benesh notation computerized editor %J Proc Dance in Canada Conference %O June %A Sagan, H. %D 1986 %T Approximating polygons for Lebesgue's and Schoenberg's space filling curves %J American Mathematical Monthly %P 361-368 %O May %K * %A Sammut, C. %A Banerji, R. %D 1983 %T Hierarchical memories: an aid to concept learning %J Proc International Machine Learning Workshop %P 74-80 %I Allerton House %C Monticello, IL %O June 22-24 %K * %A Sammut, C. %A Banerji, R. %D 1986 %T Learning concepts by asking questions %B Machine learning Volume 2 %E R.S. Michalski, J.G. Carbonell, and T.M. Mitchell %I Morgan Kaufmann Inc %C Los Altos, CA %P 167-191 %K * %A Sandewall, E. %T A functional approach to non-monotonic logic %J Proc IJCAI %P 100-106 %K * %A Sakata, S. %A Ueda, T. %D 1985 %T A distributed interoffice mail system %J IEEE Computer %V 18 %N 10 %P 106-116 %O October %A Samet, H. %D 1983 %T A quadtree medial axis transform %J Comm ACM %V 26 %N 9 %P 680-693 %O September %A Samet, H. %D 1984 %T The quadtree and related hierarchical data structures %J Computing Surveys %V 16 %N 4 %P 187-260 %O June %A Santisteban, A. %D 1983 %T The perceptual color space of digital image display terminals %J IBM J Research and Development %V 27 %N 2 %P 127-132 %O March %K * %A Sawaragi, Y. %A Yoshikawa %D 1970 %T Discrete-time markovian decision processes with incomplete state observation %J The Annals of Mathematical Statistics %V 41 %N 1 %P 78-86 %K * %A Schank, R.C.\0(Editor) %D 1975 %T Conceptual information processing %I North Holland %A Schank, R.C. %A Abelson, R. %D 1977 %T Scripts, plans, goals and understanding %I Lawrence Erlbaum Associates %A Schank, R.C. %D 1980 %T Language and memory %J Cognitive Science %V 4 %P 243-284 %K * %A Schank, R.C. %A Slade, S. %T Advisory systems %K * %A Scharf, T.F. %D 1984 %T Sounding out speech synthesis %J Electronics and Power %P 847-849 %O November/December %K * %A Schroeder, M.E. %D 1969 %T Images from computers %J IEEE Spectrum %O March %K * %A Schulert, A.J. %A Rogers, G.T. %A Hamilton, J.A. %D 1985 %T ADM \(em a dialog manager %J Proc ACM CHI 85 Human Factors in Computing Systems %P 177-183 %O April %K * %A Searle, J.R. %D 1980 %T Minds, brains, and programs %J Behavioral and Brain Sciences %V 3 %P 417-457 %K * %A Searle, J.R. %D 1983 %T Intentionality %I Cambridge University Press %C Cambridge, England %A Seely\|Brown, J. %A Burton, R.R. %A Bell, A.G. %D 1975 %T SOPHIE \(em a step toward creating a reactive learning environment %J IJMMS %V 7 %N 5 %P 675-696 %O September %A Segre, A.M. %A Sherwood, B.A. %A Dickerson, W.B. %D 1983 %T An expert system for the production of phoneme strings from unmarked english text using machine induced rules %J Proc Association for Computational Linguistics %C Pisa, Italy %O September %K * %A Selim, S.Z. %A Ismail, M.A. %D 1984 %T \fIK\fP-means-type algorithms: a generalized convergence theorem and characterization of local optimality %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-6 %N 1 %P 81-87 %O January %K * %A Sergot, M. %T Prospects for representing the law as logic programs %B In Clark and Tarnlund's book %K * %A Seybold %D 1985 %T Apple Laserwriter %J Seybold Report on Publishing Systems %V 14 %N 9 %O January 28 %K * %A Shafer, G. %D 1976 %T A mathematical theory of evidence %I Princeton University Press %C Princeton, NJ %A Shamos, M.I. %A Hoey, D. %D 1975 %T Closest-point problems %J Proc 16th IEEE Symposium on Foundations of Computer Science %P 151-162 %O October %A Shamos, M.I. %D 1977 %T Computational geometry %I Springer-Verlag %C New York, NY %A Shannon, C.E. %D 1948 %T A mathematical theory of communication %J Bell System Technical J %V 27 %P 398-403 %O July %A Shannon, C.E. %D 1951 %T Presentation of a maze-solving machine %B Trans 8th Conference Josiah Macy Foundation %E H.von Foerster %C New York, NY %P 173-192 %A Shannon, C.E. %D 1951 %T Prediction and entropy of printed English %J Bell System Technical J %P 50-64 %O January %K * %A Shapiro, E. %D 1983 %T A subset of concurrent Prolog and its interpreter %R ICOT Technical Report TR-003 %O January %K * %A Shapiro, E. %D 1983 %T Systems programming in concurrent Prolog %R ICOT Technical Report TR-034 %O November %K * %A Shapiro, E. %A Takeuchi, A. %D 1983 %T Object oriented programming in concurrent Prolog %J New Generation Computing %V 1 %P 25-48 %K * %A Shaw, M.L.G. %A Gaines, B.R. %D 1983 %T Does the human component in the network have a protocol? %J Proc International Electrical, Electronics Conference %V 2 %P 546-549 %C Toronto, ON %O September 26-28 %K * %A Shaw, M.L.G %A Gaines, B.R. %D 1985 %T Knowledge engineering tools for expert systems %B Computer models for decision making %E G.Mitra %I North Holland %C Amsterdam %K * %A Shneiderman, B. %D 1984 %T Response time and display rate in human performance with computers %J Computing Surveys %V 16 %N 3 %P 265-285 %O September %A Shneiderman, B. %A Norman, K. %A Rogers, J. %A Arifin, R. %A Weldon, L. %D 1985 %T A multi-screen programmer work station based on the IBM PC %R Research Report %I Computer Science Department, University of Maryland %O April %A Shoch, J.F. %A Hupp, J.A. %D 1982 %T The `worm' programs \(em early experience with a distributed computation %J Comm ACM %V 25 %N 3 %P 172-180 %O March %K * %A Shoemake, K. %T Animating rotation with quaternion curves %D 1985 %J ACM %V 19 %N 3 %O July %K * %A Shortliffe, E.H. %A Buchanan, B.G. %D 1975 %T A model of inexact reasoning in medicine %J Mathematical Biosciences %V 23 %P 351-379 %A Shortliffe, E.H. %D 1976 %T Computer-based medical consultations: MYCIN %I Elsevier Science %C New York, NY %K * %A Shortliffe, E.H. %D 1980 %T Consultation systems for physicians: the role of artificial intelligence techniques %J Proc Canadian Society for Computational Studies of Intelligence %I University of Victoria %C Victoria, BC %K * %A Shrager, J.C. %T Invoking a beginner's aid process by recognizing DCL goals %D 1981 %R MSc Thesis %I University of Pennsylvania %A Shrager, J.C. %A Finin, T. %D 1982 %T An expert system that volunteers advice %J Proc National Conference on Artificial Intelligence %P 339-340 %K * %K * %A Shu, C.S. %D 1985 %T FORMAL: A forms-oriented visual-directed application development system %J IEEE Computer %V 18 %N 8 %P 38-49 %A Sierpinski, W. %D 1912 %T Sur une nouvelle courbe qui remplit toute une aire plaine %J Bull Acad Sci Cracovie %V Serie A %P 462-478 %K * %A Simons, G.L. %D 1980 %T Robots in industry %I National Computing Centre %C Manchester, England %A Simpson, R.J. %A Terrell, T.J. %D 1984 %T Digital filtering using the NEC PD7720 signal processor %J Microprocessing and Microprogramming %V 14 %P 67-78 %K * %A Sleeman, D. %D 1982 %T Assessing aspects of competence in basic algebra %B Intelligent Tutoring Systems %E D. Sleeman and J.S. Brown %I Academic Press %C London, England %P 185-200 %A Sloman, A. %A Croucher, M. %D 1981 %T Why robots will have emotions %J Proc 7th International Joint Conference on Artificial Intelligence %V 1 %P 197-202 %C Vancouver, BC %K * %A Smith, K. %D 1985 %T Watch out hackers, public encryption chips are coming %J Electronics Week %P 30-31 %O May 20 %K * %A Smith, R. %D 1979 %T Tint fill %J Proc ACM Conference %P 276-284 %K * %A Solomon, H. %D 1977 %T Data dependent clustering techniques %B Classification and clustering %E J. Van Ryzin %I Academic Press %C New York, NY %P 155-173 %A Southall, R. %D 1984 %T First principles of typographic design for document production %J TUGBOAT (TEX Users Group Newsletter) %V 5 %N 2 %P 79-90 %K * %A Sowa, J.F. %D 1983 %T Generating language from conceptual graphs %B Computational Linguistics %E N.Cercone %P 29-43 %I Pergamon %C Oxford, England %K * %A Sparck\|Jones, K. %D 1984 %T User models and expert systems %R Technical Report %I Computer Laboratory, University of Cambridge %C Cambridge, England %K * %A Spector, A.Z. %D 1982 %T Performing remote operations efficiently on a local computer network %J Comm ACM %V 25 %N 4 %P 246-260 %O April %K * %A Spencer, H. %D 1969 %T The visible word %I Lund Humphries %C London, England %A Stankovic, J.A. %D 1982 %T Software communication mechanisms: procedure call versus messages %J IEEE Computer %P 19-25 %O April %K * %A Stankovic, J.A. %D 1984 %T A perspective on distributed computer systems %J IEEE Trans Computers %V C-33 %N 12 %P 1102-1115 %O December %K * %A Staunstrup, J. %D 1982 %T Message passing communication versus procedure call communication %J Software -- Practice and Experience %V 12 %P 223-234 %K * %A Stefik, M. %D 1979 %T An examination of a frame-structured representation system %J Proc 6th International Conference on Artificial Intelligence %P 265-270 %K * %A Stefik, M. %A Conway, L. %D 1982 %T Towards the principled engineering of knowledge %J AI Magazine %P 4-16 %O Summer %K * %A Stefik, M. %A Bobrow, D.G. %A Mittal, S. %A Conway, L. %D 1983 %T Knowledge programming in LOOPS: report on an experimental course %J AI Magazine %P 3-13 %O Fall %K * %A Stefik, M.J. %A Bobrow, D.G. %A Kahn, K.M. %D 1986 %T Integrating access-oriented programming into a multiparadigm environment %J IEEE Software %P 10-18 %O January %K * %A Stefik, M.J. %A Bobrow, D.G. %D 1986 %T Object-oriented programming: themes and variations %J AI Magazine %V 6 %N 4 %P 40-62 %O Winter %A Stevens, M.E. %A Little, J.L. %D 1967 %T Automatic typographic-quality typesetting techniques: a state-of-the-art review %I National Bureau of Standards %A Stevens, R.J. %A Lehar, A.F. %A Preston, F.H. %D 1983 %T Manipulation and presentation of multi-dimensional image data using the Peano scan %J IEEE Trans Pattern Analysis and Machine Intelligence %P 520- %O September %A Stoffel, J.G. %A Moreland, J.F. %D 1981 %T A survey of electronic techniques for pictorial image reproduction %J IEEE Trans Communications %V COM-17 %N 12 %P 1898-1925 %O December %K * %A Stroustrup, B. %D 1984 %T The C++ programming language %R Computing Science Technical Report 108 %I Bell Laboratories %C Murray Hill, NJ %O January %K * %A Stroustrup, B. %D 1984 %T Data abstraction in C %R Computing Science Technical Report 109 %I Bell Laboratories %C Murray Hill, NJ %O January %K * %A Suchman, L.A. %D 1982 %T Toward a sociology of human-machine interaction: pragmatics of instruction-following %R Working Paper %I Xerox PARC, (Intelligent Systems Laboratory) %C Palo Alto, CA %A Suchman, L.A. %D 1982 %T Human-machine interaction and the idea of a self-explanatory machine %J Paper presented at the Annual Meeting of the American Anthropological Society %C Washington, DC %O December %K * %A Suchman, L.A. %D 1983 %T The role of common sense in interface design %B Office Automation: Jekyll or Hyde %E D.Marschall and J.Gregory %I Working Women Education Fund %C Cleveland, OH %P 96-102 %A Suchman, L.A. %D 1983 %T Office procedure as practical action: models of work and system design %J ACM Trans Office Information Systems %V 1 %N 4 %P 320-328 %O October %K * %A Suchman, L.A. %D 1985 %T Plans and situated actions: the problem of human-machine communication %R PhD Thesis %I Xerox PARC %C Palo Alto, CA %K * %A Sugeno, M. %A Nishida, M. %D 1984 %T Fuzzy control of model car %K * %A Summers, P.D. %A Grossman, D.D. %D 1984 %T XPROBE: an experimental system for programming robots by example %J Int J Robotics Research %V 3 %N 1 %P 25-39 %O Spring %A Sussman, G.J. %D 1975 %T A computer model of skill acquisition %I American Elsevier %C New York, NY %A Tannenbaum, A. %T Political history of UNIX %R Report %I MASSCOMP %C Westford, MA %K * %A Tanner, W. %D 1979 %T Industrial robots -- Volume 1: Fundamentals %I Society of Manufacturing Engineers %C Dearborn, MI %A Tennant, H.R. %A Ross, K.M. %A Thompson, C.W. %D 1983 %T Usable natural language interfaces through menu-based natural language understanding %J Proc ACM CHI 83 Human Factors in Computing Systems %P 154-160 %C Boston, MA %O December 12-15 %K * %A Test, J.A. %D 1982 %T The NUnix window system %R Internal Report %I Laboratory for Computer Science, MIT %C Cambridge, MA %K * %A Thimbleby, H. %D 1980 %T Dialogue determination %J IJMMS %V 13 %N 3 %P 295-304 %O October %A Thomsett, R. %D 1980 %T People and project management %I Yourden Press %C New York, NY %A Thompson, B.A. %A Thompson, W.A. %D 1985 %T Inside an expert system %J Byte %P 315-330 %O April %K * %A Thompson, K. %D 1984 %T Reflections on trusting trust %J Comm ACM %V 27 %N 8 %P 761-763 %O August %A Ting, D. %A Prasada, B. %D 1980 %T Digital processing techniques for encoding of graphics %J Proc IEEE %V 68 %N 7 %P 757-769 %O July %A Tokuda, H. %A Manning, E.G. %D 1983 %T An interprocess communication model for a distributed software testbed %J Proc ACM SIGCOMM 83 %I University of Texas %C Austin, TX %O March %K * %A Tokuda, H. %A Radia, S.P. %A Manning. E.G. %D 1983 %T Shoshin OS: a message-based operating system for a distributed software testbed %J Proc 16th Annual Hawaii International Conference on System Sciences %P 329-338 %K * %A Tou, I.T. %A Gonzalez, R.C. %D 1974 %T Pattern recognition principles %I Addison-Wesley %C Reading, MA %A Truin, P.G.M. %D 1983 %T The `speaking tablet' as an aid in the acquisition of reading skills by dyslexic children %J IPO Annual Progress Report %V 18 %P 79-84 %K * %A Tsichritzis, D.\0(Editor) %D 1983 %T Beta Gamma %R Technical Report CSRG-150 %I Computer Systems Research Group, University of Toronto %C Toronto, ON %A Tsichritzis, D. %D 1985 %T Objectworld %E D.Tsichritzis %B Office automation %I Springer-Verlag %C Berlin %P 379-398 %A Turkle, S. %D 1982 %T The subjective computer: a study in the psychology of personal computation %J Social Studies of Science %V 12 %N 2 %P 173-205 %K * %A Tyree, A. %D 1986 %T Expert systems and the law %J Current Affairs Bulletin %P 13-18 %P March %K * %A Ulichney, R.A. %A Troxel, D.E. %D 1982 %T Scaling binary images with the telescoping template %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-4 %N 3 %P 331-335 %A Umphress, D. %A Williams, G. %D 1985 %T Identity verification through keyboard characteristics %J IJMMS (submitted) %K * %A Unger, B. %A Birtwistle, G. %A Cleary, J. %A Hill, D. %A Lomow, G. %A Neal, R. %A Peterson, M. %A Witten, I.H. %A Wyvill, B. %D 1984 %T Jade: a simulation and software prototyping environment %J Proc Conference on Simulation in Strongly Typed Languages %C San Diego, CA %O February %K KConference %A Unger, B.W. %A Lomow, G.A. %A Birtwistle, G.. %D 1984 %T Simulation software and Ada %I Society for Computer Simulation %K * %A University\|of\|Chicago\|Press %D 1969 %T A manual of style %I University of Chicago %A Uribe, R.B. %D 1981 %T Modeling autopoiesis %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York, NY %P 51-62 %A Van\|Dijk, T.A. %A Kintsch, W. %D 1983 %T Strategies of discourse comprehension %I Academic Press %C New York, NY %A Van\|Lehn, K. %D 1983 %T Felicity conditions for human skill acquisition: validating an AI-based theory %R Research Report CIS-21 %I Xerox PARC %C Palo Alto, CA %O November %A Varela, F.J. %A Maturana, H.R. %A Uribe, R.B. %D 1974 %T Autopoiesis: the organization of living systems, its characterization and a model %J Biosystems %V 5 %P 187-196 %A Varela, F.J. %D 1979 %T Principles of biological autonomy %I North Holland %C New York, NY %A Varela, F.J. %D 1981 %T Describing the logic of the living %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York, NY %P 36-48 %A Wade, N. %D 1985 %T Literal pictures %J Word and Image %V 1 %N 3 %P 242-272 %O July-September %K * %A Wagner, R.A. %A Fischer, M.J. %D 1974 %T The string-to-string correction problem %J J ACM %V 21 %N 1 %P 168-173 %O January %K * %A Wall, R.S. %A Apon, A.W. %A Beal, J. %A Gately M.T. %A Oren, L.G. %D 1985 %T An evaluation of commercial expert system building tools %R Computer Science Laboratory Technical Report 85-30 %I Texas Instruments %C Dallas, TX %O November %K * %A Waltz, D.L. %D 1975 %T Natural language access to a large data base %J Advance papers of the International Joint Conference on Artificial Intelligence %I MIT %C Cambridge, MA %A Waterman, D.A. %D 1978 %T A rule-based approach to knowledge acquisition for man-machine interface programs %J IJMMS %V 10 %P 693-711 %K * %A Waters, R.C. %D 1985 %T The programmer's apprentice: a session with KBEmacs %J IEEE Trans Software Engineering %V SE-11 %N 11 %P 1296-1320 %O November %K * %A Webber, B.L. %A Nilsson, N.J. %D 1981 %T Readings in artificial intelligence %I Tioga %C Palo Alto, CA %A Weinreb, D. %A Moon, D. %D 1981 %T LISP machine manual %I Third edition %O March %A Weizenbaum, J. %D 1976 %T Computer power and human reason %I Freeman %C San Francisco, CA %A Welch, T.A. %D 1984 %T A technique for high-performance data compression %J IEEE Computer %V 17 %N 6 %P 8-19 %O June %K * %A Weyer, S.A. %D 1982 %T Searching for information in a dynamic book %R PhD Thesis %I School of Education, Stanford University %O (Also Report SCG-82-1, Xerox Parc) %A Whalen, T. %A Mason, C. %D 1981 %T The use of tree-structured index which contains three types of design defects %J Telidon Behavioural Research %V 2 %I Department of Communications %O May %A Whalen, T. %A Latremouille, S. %D 1981 %T The effectiveness of a tree-structured index when the existence of information is uncertain %J Telidon Behavioural Research %V 2 %I Department of Communications %O May %A Wijk, C.van %A Kempen, G. %D 1985 %T From sentence structure to intonation contour %E B.S.Muller %T Sprachsynthese: zur Synthese von naturlich gesprochener Sprache aus Texten und Konzepten %I Georg Olms Verlag %C Hildesheim %K * %A Wilensky, R. %A Arens, Y. %A Chin, D. %D 1984 %T Talking to Unix in English: an overview of UC %J Comm ACM %V 27 %N 6 %P 574-593 %O June %K * %A Wilkes, A.J. %A Singer, D.W. %A Gibbons, J.J. %A King, T.R. %A Robinson, P. %A Wiseman, N.E. %D 1984 %T The Rainbow workstation %J Computer J %V 27 %N 2 %O May %K * %A Wilkes, A.J. %A Wiseman, N.E. %D 1982 %T A soft-edged character set and its derivation %J Computer J %V 25 %N 1 %P 140-147 %O February %K * %A Wilkinson, W. %D 1980 %T Viewdata: The Prestel System %B Videotext: the coming revolution in home/office information retrieval %E Sigel, E. %I Harmony Books %C New York, NY %P 57-86 %A Wilks, Y. %D 1977 %T Good and bad arguments about semantic primitives %R Research Report %I Department of Artificial Intelligence, University of Edinburgh %O May %K * %A Wilks, Y. %D 1984 %T Beliefs, points of view and multiple environments %B Artificial and human intelligence %E A.Elithorn and R.Banerji %I Elsevier Science %P 147-171 %K * %A Willems, NJ %D 1983 %T STEP: A model of standard English intonation patterns %J IPO Annual Progress Report %V 18 %P 37-42 %K * %A Williams, G. %D 1984 %T The Apple Macintosh computer %J Byte %V 9 %N 2 %P 30-54 %O February %A Winograd, T. %D 1972 %T Understanding natural language %I Academic Press %C New York, NY %A Winograd, T. %D 1984 %T Moving the semantic fulcrum %R Report CSLI-84-18 %I Center for the study of language and information, Stanford University %C Stanford, CA %O December %K * %A Witten, I.H. %D 1983 %T The Department of Computer Science, University of Calgary %J Computer Science Association Newsletter %V 11 %N 1 %P 15-23 %O December %K KArticle %A Witten, I.H. %A Cleary, J.G. %D 1986 %T Foretelling the future by adaptive modeling %J Abacus %V 3 %N 3 %P 16-36 %O Spring %K KArticle %A Witten, I.H. %A Fremont, D. %D 1984 %T A student information service for a University Computer Science department %J Proc 15th Ontario Universities Computing Conference %I Lakehead University %C Thunder Bay, ON %O June %K KInvited %A Witten, I.H. %D 1985 %T Elements of computer typography %J IJMMS %V 23 %N 6 %P 623-687 %O December %K KJournal %A Witten, I.H. %A Bramwell, B. %D 1985 %T A system for interactive viewing of structured documents %J Comm ACM %V 28 %N 3 %P 280-288 %O March %K KJournal %A Witten, I.H. %D 1984 %T Dynamic documents %J Proc PROTEXT I -- First International Conference on Text Processing Systems %I Boole Press %C Dublin, Ireland %P 234-239 %O October %K KConference %A Witten, I.H. %A Greenberg, S. %D 1985 %T User interfaces for office systems %B Oxford Surveys in Information Technology Volume 2 %E P.I. Zorkoczy %I Oxford University Press %C Oxford, England %P 69-104 %K KJournal %A Witten, I.H. %D 1986 %T Making computers talk \(em an introduction to speech synthesis %I Prentice-Hall %C Englewood Cliffs, NJ %A Witten, I.H. %D 1987 %T Computer speech %B The Encyclopaedia of Physical Science and Technology, Volume 3 %E Robert A Meyers %I Academic Press %P 482-506 %K KInvited %A Witten, I.H. %A Bonham, M. %A Bramwell, B. %A Greenberg, S. %D in preparation %T Interacting with dynamic documents -- the new age of reading %R proposal submitted to MIT Press %A Witten, I.H. %D 1985 %T Selected topics in computer science I %R Report %I Institute of Information Processing, Graz, Austria %O November %K KReport %A Witten, I.H. %D 1986 %T Modeling behaviour sequences: principles, practice, prospects %J Proc International Conference on Future Advances in Computing %C Christchurch, New Zealand %O February 17-21 %K KConference %A Witten, I.H. %D 1986 %T In search of `autonomy' %J Proc International Conference on Future Advances in Computing %C Christchurch, New Zealand %O February 17-21 %K KConference %A Witten, I.H. %D 1986 %T Expert systems %J Man-Machine Studies %V UC-DSE %N 28 %P 5-65 %I University of Canterbury %C Christchurch, New Zealand %O May %K KArticle %A Witten, I.H. %D 1987 %T Thoughts on artificial intentionality %J Man-Machine Studies %V UC-DSE %N 9 %P 5-52 %I University of Canterbury %C Christchurch, New Zealand %O January %K KArticle %A Witten, I.H. %A Neal, R. %A Cleary, J.G. %D 1987 %T Arithmetic coding for data compression %J Comm ACM %V 30 %N 6 %P 520-540 %O June; reprinted in \fIC Gazette\fP, December 1987 %K KJournal %A Witten, I.H. %D 1987 %T A course on `expert systems' for electrical engineering students %J Proc ACM SIGCSE Technical Symposium on Computer Science Education %C St Louis, MO %P 257-260 %O February (published as SIGCSE Bulletin \fI19\fR(1)) %K KConference %A Wong, S.K.M %A Ziarko, W. %A Ye, R. Li %D 1985 %T Comparison of rough-set and statistical methods in inductive learning %R Technical Report CS-85-16 %I Computer Science Department, University of Regina %K * %A Wood, R.J. %D 1982 %T A window based display management system %R Internal Report %I University of Maryland %A Woods, W.A. %D 1973 %T Progress in natural language understanding -- an application to lunar geology %J Proc National Computer Conference %C Montvale, NJ %I AFIPS Press %A Woolf, B. %A McDonald, D.D. %D 1983 %T Human-computer discourse in the design of a Pascal tutor %J Proc ACM CHI 83 Human Factors in Computing Systems %P 230-234 %C Boston, MA %O December 12-15 %K * %A Woolf, B. %A McDonald, D.D. %D 1984 %T Building a computer tutor: design issues %J IEEE Computer %V 17 %N 9 %P 61-73 %O September %A Wright, W.E. %D 1977 %T Gravitational clustering %J Pattern Recognition %V 9 %P 151-166 %K * %A Wu, X. %A Witten, I.H. %D 1985 %T A fast \fIk-\fPmeans type clustering algorithm %R Research Report 85/197/10 %I Computer Science Department, University of Calgary %O June %A Wupit, A. %D 1983 %T Comparison of UNIX networks %J Proc ACM Conference on Personal and Small Computers %C San Diego, CA %P 99-108 %O December %A Wyvill, B.L.M. %D 1984 %T Three computer science plays: \fISquanderella\fP, \fIDigital Alice\fP, and \fITwenty eighty-four\fP %R Research Report %I Computer Science Department, University of Calgary %A Wyvill, B.L.M. %A Witten, I.H. %D 1984 %T Three computer science plays %R Research Report 84/184/42 %I Computer Science Department, University of Calgary %O December %K KReport %A Xerox\|Corp %D 1984 %T The role of electronic printing in the office of the future %R Executive Presentation II %K * %A Yankelovich, N. %A Meyrowitz, N. %A van Dam, A. %D 1985 %T Reading and writing the electronic book %J IEEE Computer %V 18 %N 10 %P 15-30 %O October %A Yoeli, M. %A Brzozowski, J.A. %D 1984 %T A mathematical model of digital CMOS networks %R Research Report CS-84-22 %I Computer Science Department, University of Waterloo %O August %K * %A Young, J.Z. %D 1978 %T Programs of the brain %I Oxford University Press %C Oxford, England %A Zaniolo, C. %D 1984 %T Object-oriented programming in Prolog %J Proc International Symposium on Logic Programming %C Atlantic City, NJ %P 265-270 %O February 6-9 %K * %A Zeleny, M. %D 1977 %T Self-organization of living systems: a formal model of autopoiesis %J Int J General Systems %V 4 %N 1 %P 13-28 %A Zeleny, M. %D 1978 %T Apl-autopoiesis: experiments in self-organization of complexity %B Progress in cybernetics and systems research III %E R.Trappl, G.J.Klir and L.Ricciardi %P 65-84 %I Hemisphere %C Washington, DC %A Zeleny, M.\0(Editor) %D 1981 %T Autopoiesis: a theory of living organization %I North Holland %C New York, NY %A Zeleny, M. %D 1981 %T What is autopoiesis? %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York, NY %P 4-17 %A Zimmermann, H. %D 1980 %T OSI reference model \(em the ISO model of architecture for open systems interconnection %J IEEE Trans Communications %P 425-432 %O April %A Zisman, M.M. %D 1977 %T Representation, specification, and automation of office procedures %R PhD Dissertation %I Wharton School, University of Pennsylvania %A Zissos, A.Y. %A Witten, I.H. %D 1985 %T User modelling for a computer coach: a case study %J IJMMS %V 23 %N 6 %P 729-750 %O December %K KJournal %A Ziv, J. %A Lempel, A. %D 1977 %T A universal algorithm for sequential data compression %J IEEE Trans Information Theory %V IT-23 %N 3 %P 337-343 %O May %K * %A Ziv, J. %A Lempel, A. %D 1978 %T Compression of individual sequences via variable-rate coding %J IEEE Trans Information Theory %V IT-24 %P 530-536 %O September %K *

DESCRIPTION OF FARMER OAK -- AN INCIDENT When Farmer Oak smiled, the corners of his mouth spread till they were within an unimportant distance of his ears, his eyes were reduced to chinks, and diverging wrinkles appeared round them, extending upon his countenance like the rays in a rudimentary sketch of the rising sun. His Christian name was Gabriel, and on working days he was a young man of sound judgment, easy motions, proper dress, and general good character. On Sundays he was a man of misty views, rather given to postponing, and hampered by his best clothes and umbrella : upon the whole, one who felt himself to occupy morally that vast middle space of Laodicean neutrality which lay between the Communion people of the parish and the drunken section, -- that is, he went to church, but yawned privately by the time the con+ gegation reached the Nicene creed,- and thought of what there would be for dinner when he meant to be listening to the sermon. Or, to state his character as it stood in the scale of public opinion, when his friends and critics were in tantrums, he was considered rather a bad man ; when they were pleased, he was rather a good man ; when they were neither, he was a man whose moral colour was a kind of pepper-and-salt mixture. Since he lived six times as many working-days as Sundays, Oak's appearance in his old clothes was most peculiarly his own -- the mental picture formed by his neighbours in imagining him being always dressed in that way. He wore a low-crowned felt hat, spread out at the base by tight jamming upon the head for security in high winds, and a coat like Dr. Johnson's ; his lower extremities being encased in ordinary leather leggings and boots emphatically large, affording to each foot a roomy apartment so constructed that any wearer might stand in a river all day long and know nothing of

damp -- their maker being a conscientious man who endeavoured to compensate for any weakness in his cut by unstinted dimension and solidity. Mr. Oak 'carried 'about him, by way of watch,+ what may be called a small silver clock; in other words, it was a watch as to shape and intention, and a small clock as to size. This instrument being several years older than Oak's grandfather, had the peculiarity of going either too fast or not at all. The smaller of its hands, too, occasionally slipped round on the pivot, and thus, though the minutes were told with precision, nobody could be quite certain of the hour they belonged to. The stopping peculiarity of his watch Oak remedied by thumps and shakes, and he escaped any evil consequences from the other two defects by constant comparisons with and observations of the sun and stars, and by pressing his face close to the glass of his neighbours' windows, till he could discern the hour marked by the green-faced timekeepers within. It may be mentioned that Oak's fob being difficult of access, by reason of its somewhat high situation in the waistband of his trousers (which also lay at a remote height under his waistcoat), the watch was as a necessity pulled out by throwing the body to one-side, compressing the- mouth and face to a mere mass of- ruddy flesh- on account -of the exertion, and drawing up the watch by its chain, like a bucket from a well. But some thoughtfull persons, who had seen him walking across one of his fields on a certain December morning -- sunny and exceedingly mild -- might have regarded Gabriel Oak in other aspects than these. In his face one might notice that many of the hues and curves of youth had tarried on to manhood: there even remained in his remoter crannies some relics of the boy. His height and breadth would have been sufficient to make his presence imposing, had they been exhibited with due consideration. But there is a way some men have, rural and urban alike, for which the mind is more responsible than flesh and sinew : it is a way of curtail+ ing their dimensions by their manner of showing them. And from a quiet modesty that would have become a vestal which seemed continually to impress upon him

that he had no great claim on the world's room, Oak walked unassumingly and with a faintly perceptible bend, yet distinct from a bowing of the shoulders. This may be said to be a defect in an individual if he depends for his valuation more upon his appearance than upon his capacity to wear well, which Oak did not. He had just reached the time of life at which " young' is ceasing to be the prefix of "man ' in speaking of one. He was at the brightest period of masculine growth, for his intellect and his emotions were clearly separated : he had passed the time during which the influence of youth indiscriminately mingles them in the character of impulse, and he had not yet arrived at the stage wherein they become united again, in the character of prejudice, by the influence of a wife and family. In short, he was twenty-eight, and a bachelor. The field he was in this morning sloped to a ridge called Norcombe Hill. Through a spur of this hill ran the highway between Emminster and Chalk+ Newton. Casually glancing over the hedge, Oak saw coming down the incline before him an ornamental spring waggon, painted yellow and gaily marked, drawn by two horses, a waggoner walking alongside bearing a whip perpendicularly. The waggon was laden with household goods and window plants, and on the apex of the whole sat a woman, 'young-'and attractive. Gabriel had not beheld the sight for more than half a minute, when the vehicle was brought to a standstill just beneath his eyes. " The tailboard of the waggon is gone, Miss,' said the waggoner. "Then I heard it fall,' said the girl, in a soft, though not particularly low voice. "I heard a noise I could not account for when we were coming up the hill.' "I'll run back.' + " Do,' she answered. + The sensible horses stood -- perfectly still, and the waggoner's steps sank fainter and fainter in the distance. The girl on the summit of the load sat motionless, surrounded by tables and chairs with their legs upwards, backed by an oak settle, and ornamented in front by pots of geraniums, myrtles, and cactuses, together with

a caged canary -- all probably from the windows of the house just vacated. There was also a cat in a willow basket, from the partly-opened lid of which she gazed with half-closed eyes, and affectionately-surveyed the small birds around. The handsome girl waited for some time idly in her place, and the only sound heard in the stillness-was -the hopping of the canary up-and down the perches of its prison. Then she looked attentively downwards. It was not at the bird, nor at the cat; it was at an oblong package tied in paper, and lying between them. She turned her head to learn if the waggoner were coming. He was not yet in sight; and her-eyes crept back to the package, her thoughts seeming to run 'upon what was inside it. At length she drew the article into her lap, and untied the paper covering; a small swing looking-glass was disclosed, in which she proceeded to survey herself attentively. She parted her lips and smiled. It was a fine morning, and the sun lighted up to a scarlet glow the crimson jacket she wore, and painted a soft lustre upon her bright face and dark hair. The myrtles, geraniums, and cactuses packed around her were fresh and green, and at such a leafless season they invested the whole concern of horses, waggon, furniture, and girl with a peculiar vernal charm. What possessed her to indulge in such a performance in the sight of the sparrows, blackbirds, and unperceived farmer who were alone its spectators, -- whether the smile began as a factitious one, to test her capacity in that art, -- nobody knows ; it ended certainly in a real smile. She blushed at herself, and seeing her reflection blush, blushed the more. The change from the customary spot and necessary occasion of such an act -- from the dressing hour in a bedroom to a time of travelling out of doors -- lent to the idle deed a novelty it did not intrinsically possess. The picture was a delicate one. Woman's prescriptive infirmity had stalked into the sunlight, which had clothed it in the freshness of an originality. A cynical inference was irresistitle by Gabriel Oak as he regarded the scene, generous though he fain would have been. There was no necessity whatever for her looking in the glass. She did not adjust her hat, or pat her

hair, or press a dimple into shape, or do one thing to signify that any such intention had been her motive in taking up the glass. She simply observed herself as a fair product of Nature in the feminine kind, her thoughts seeming to glide into far-off though likely dramas in which men would play a part -- vistas of probable triumphs -- the smiles being of a phase suggesting that hearts were imagined as lost and won. Still, this was but conjecture, and the whole series of actions was so idly put forth as to make it rash to assert that intention had any part in them at all. The waggoner's steps were heard returning. She put the glass in the paper, and the whole again into its place. When the waggon had passed on, Gabriel withdrew from his point of espial, and descending into the road, followed the vehicle to the turnpike-gate some way beyond the bottom of the hill, where the object of his contemplation now halted for the payment of toll. About twenty steps still remained between him and the gate, when he heard a dispute. lt was a difference con+ cerning twopence between the persons with the waggon and the man at the toll-bar. " Mis'ess's niece is upon the top of the things, and she says that's enough that I've offered ye, you great miser, and she won't pay any more.' These were the waggoner's words. "Very well ; then mis'ess's niece can't pass,' said the turnpike-keeper, closing the gate. Oak looked from one to the other of the disputants, and fell into a reverie. There was something in the tone of twopence remarkably insignificant. Threepence had a definite value as money -- it was an appreciable infringement on a day's wages, and, as such, a higgling matter ; but twopence -- -- " Here,' he said, stepping forward and handing twopence to the gatekeeper ; "let the young woman pass.' He looked up at her then; she heard his words, and looked down. Gabriel's features adhered throughout their form so exactly to the middle line between the beauty of St. John and the ugliness of Judas Iscariot, as represented in a window of the church he attended, that not a single lineament could be selected and called worthy either of distinction or notoriety. The redjacketed and dark+

haired maiden seemed to think so too, for she carelessly glanced over him, and told her man to drive on. She might have looked her thanks to Gabriel on a minute scale, but she did not speak them; more probably she felt none, for in gaining her a passage he had lost her her point, and we know how women take a favour of that kind. The gatekeeper surveyed the retreating vehicle. " That's a handsome maid ' he said to Oak " But she has her faults,' said Gabriel. " True, farmer. ' "And the greatest of them is -- well, what it is always.' " Beating people down ? ay, 'tis so.' "O no.' " What, then ? ' Gabriel, perhaps a little piqued by the comely traveller's indifference, glanced back to where he had witnessed her performance over the hedge, and said, " Vanity.'

NIGHT -- THE FLOCK -- AN INIERIOR -- ANOTHER INTERIOR IT was nearly midnight on the eve of St. Thomas"s, the shortest day in the year. A desolating wind wandered from the north over the hill whereon Oak had watched the yellow waggon and its occupant in the sunshine of a few days earlier. Norcombe Hill -- not far from lonely Toller-Down -- was one of the spots which suggest to a passer-by that he is in the presence of a shape approaching the indestructible as nearly as any to be found on earth. It was a featureless convexity of chalk and soil -- an ordinary specimen of those smoothly-outlined protuber+ ances of the globe which may remain undisturbed on some great day of confusion, when far grander heights and dizzy granite precipices topple down. The hill was covered on its northern side by an ancient and decaying plantation of beeches, whose upper verge formed a line over the crest, fringing its arched curve against the sky, like a mane. To-night these trees sheltered the southern slope from the keenest blasts, which smote the wood and floundered through it with a sound as of grumbling, or gushed over its crowning boughs in a weakened moan. The dry leaves in the ditch simmered and boiled in the same breezes, a tongue of air occasionally ferreting out a few, and sending them spinning across the grass. A group or two of the latest in date amongst the dead multitude had remained till this very mid-winter time on the twigs which bore them and in falling rattled against the trunks with smart taps: Betwenne this half-wooded, half naked hill, and the vague still horizon that its summit indistinctly com+ manded, was a mysterious sheet of fathomless shade -- the sounds from which suggested that what it con+ cealed bore some reduced resemblance to features here.

The thin grasses, more or less coating the hill, were touched by the wind in breezes of differing powers, and almost of differing natures -- one rubbing the blades heavily, another raking them piercingly, another brushing them like a soft broom. The instinctive act of human+ kind was to stand and listen, and learn how the trees to each other in the regular antiphonies of a cathedral choir; how hedges and other shapes to leeward them caught the note, lowering it to the tenderest sob; and how the hurrying gust then plunged into the south, to be heard no more. The sky was clear -- remarkably clear -- and the twinkling of all the stars seemed to be but throbs of one body, timed by a common pulse. The North Star was directly in the wind's eye, and since evening the Bear had swung round it outwardly to the east, till he was now at a right angle with the meridian. A difference of colour in the stars -- oftener read of than seen in England-was really perceptible here. The sovereign brilliancy of Sirius pierced the eye with a steely glitter, the star called Capella was yellow, Aldebaran and Betelgueux shone with a fiery red. To persons standing alone on a hill during a clear midnight such as this, the roll of the world eastward is almost a palpable movement. The sensation may be caused by the panoramic glide of the stars past earthly objects, which is perceptible in a few minutes of still+ ness, or by the better outlook upon space that a hill affords, or by the wind, or by the solitude ; but whatever be its origin, the impression of riding along is vivid and abiding. The poetry of motion is a phrase much in use, and to enjoy the epic form of that gratification it is necessary to stand on a hill at a small hour of the night, and, having first expanded with a sense of differ+ ence from the mass of civilised mankind, who are dreamwrapt and disregardful of all such proceedings at this time, long and quietly watch your stately progress through the stars. After such a nocturnal reconnoitre it is hard to get back to earth, and to believe that the consciousness of such majestic speeding is derived from a tiny human frame. Suddenly an unexpected series of sounds began to

be heard in this place up against the sky. They had a clearness which was to be found nowhere in the wind, and a sequence which was to be found nowhere in nature. They were the notes of Farmer Oak's flute. The tune was not floating unhindered into the open air : it seemed muffled in some way, and was altogether too curtailed in power to spread high or wide. It came from the direction of a small dark object under the plantation hedge -- a shepherd's hut -- now presenting an outline to which an uninitiated person might have been puzzled to attach either meaning or use. The image as a whole was that of a small Noah's Ark on a small Ararat, allowing the traditionary outlines and general form of the Ark which are followed by toy+ makers -- and by these means are established in men's imaginations among their firmest, because earliest im+ pressions -- to pass as an approximate pattern. The hut stood on little wheels, which raised its floor about a foot from the ground. Such shepherds' huts are dragged into the fields when the lambing season comes on, to shelter the shepherd in his- enforced nightly attendance. It was only latterly that people had begun to call Gabriel !Farmer' Oak. During the twelvemonth pre+ ceding this time he had been enabled by sustained efforts of industry and chronic good spirits to lease the small shepp farm of which Norcombe Hill was a portion, and stock it with two hundred sheep. Previously he had been a bailiff for a short time, and earlier still a shepherd only, having from his childhood assisted his father in tending the floeks of large proprietors, till old Gabriel sank to rest. This venture, unaided and alone, into the paths of farming as master and not as man, with an advance of sheep not yet paid for, was a critical juncture with Gabriel Oak, and he recognised his position clearly. The first movement in his new progress was the lambing of his ewes, and sheep having been his speciality from his "youth, he wisely refrained from deputing -- the task of tending them at this season to a hireling or a novice. The wind continued to beat-about the corners of the hut, but the flute-playing ceased. A rectangular space of light

appeared in the side of the hut, and in the opening the outline of Farmer Oak's figure. He carried a lantern in his hand, and closing the door behind him, came forward and busied himself about this nook of the field for nearly twenty minutes, the lantern light appear+ ing and disappearing here and there, and brightening him or darkening him as he stood before or behind it. Oak's motions, though they had a quiet-energy, were slow, and their deliberateness accorded well with his occupation. Fitness being the basis of beauty, nobody could-have denied that his steady swings and turns" in and- about the flock had elements of grace, Yet, although if occasion demanded he could do or think a thing with as mercurial a dash as can the men of towns who are more to the manner born, his special power, morally, physically, and mentally, was static, owing little or nothing to momentum as a rule. A close examination of the ground hereabout, even by the wan starlight only, revealed how a portion of what would have been casually called a wild slope had been appropriated by Farmer Oak for his great purpose this winter. Detached hurdles thatched with straw were stuck into the ground at various scattered points, amid and under which the whitish forms of his meek ewes moved and rustled. The ring of the sheep-bell, which had been silent during his absence, recommenced, in tones that had more mellowness than clearness, owing to an increasing growth of surrounding wool. This continued till Oak withdrew again from the flock. He -- returned to the hut, bringing in his arms a new-born lamb, consisting of four legs large enough for a full+ grown sheep, united by a seemingly inconsiderable mem+ brane about half the substance of the legs collectively, which constituted the animal's entire body just at present. The little speck of life he placed on a wisp of hay before the small stove, where a can of milk was simmer+ ing. Oak extinguished the lantern by blowing into it and then pinching the snuff, the cot being lighted by a candle suspended by a twisted wire. A rather hard couch, formed of a few corn sacks thrown carelessly down, covered half the floor of this little

habitation, and here the young man stretched himself along, loosened his woollen cravat, and closed his eyes. In about the time a person unaccustomed to bodily labour would have decided upon which side to lie, Farmer Oak was asleep. The inside of the hut, as it now presented itself, was cosy and alluring, and the scarlet handful of fire in addition to the candle, reflecting its own genial colour upon whatever it could reach, flung associations of enjoyment even over utensils and tools. In the corner stood the sheep-crook, and along a shelf at one side were ranged bottles and canisters of the simple prepara+ tions pertaining to ovine surgery and physic; spirits of wine, turpentine, tar, magnesia, ginger, and castor-oil being the chief. On a triangular shelf across the corner stood bread, bacon, cheese, and a cup for ale or cider, which was supplied from a flagon beneath. Beside the provisions lay the flute whose notes had lately been called forth by the lonely watcher to beguile a tedious hour. The house was ventilated by two round holes, like the lights of a ship's cabin, with wood slides+ The lamb, revived by the warmth' began to bleat' instant meaning, as expected sounds will. Passing from the profoundest sleep to the most alert wakefulness with the same ease that had accompanied the reverse operation, he looked at his watch, found that the hour+ hand had shifted again, put on his hat, took the lamb in his arms, and carried it into the darkness. After placing the little creature with its mother, he stood and carefully examined the sky, to ascertain the time of night from the altitudes of the stars. The Dog-star and Aldebaran, pointing to the restless Pleiades, were half-way up the Southern sky, and between them hung Orion, which gorgeous constellation never burnt more vividly than now, as it soared forth above the rim of the landscape. Castor and Pollux will the north-west; far away through the plantation Vega and Cassiopeia's chair stood daintily poised on the uppermost boughs.

"One o'clock,' said Gabriel. Being a man not without a frequent consciousness that there was some charm in this life he led, he stood still after looking at the sky as a useful instrument, and regarded it in an appreciative spirit, as a work of art superlatively beautiful. For a moment he seemed impressed with the speaking loneliness of the scene, or rather with the complete abstraction from all its compass of the sights and sounds of man. Human shapes,interferences, troubles, and joys were all as if they were not, and there seemed to be on the shaded hemisphere of the globe no sentient being save himself; he could fancy them all gone round to the sunny side. Occupied this, with eyes stretched afar, Oak gradually per+ ceived that what he had previously taken to be a star low down behind the outskirts of the plantation was in reality no such thing. It was an artificial light, almost close at hand. To find themselves utterly alone at night where company is desirable and expected makes some people fearful; but a case more trying by far to the nerves is to discover some mysterious companionship when intuition, sensation, memory, analogy, testimony, probability, induction -- every kind of evidence in the logician's list -- have united to persuade con+ sciousness that it is quite in isolation. Farmer Oak went towards the plantation and pushed through its lower boughs to the windy side. A dim mass under the slope reminded him that a shed occupied a place here, the site being a cutting into the slope of the hill, so that at its back part the roof was almost level with the ground. In front it was formed of board nailed to posts and covered with tar as apreservative. Through crevices in the roof and side spread streaks and spots of light, a combination of which made the radiance that had attracted him. Oak stepped up behind, where,leaning down upon the roof and putting his eye close to a hole, he could see into the interior clearly. The place contained two women and two cows. By the side of the latter a steaming bran-mash stood in a bucket. One of the women was past middle age. Her companion was ap+ parently young and graceful; he could form no decided opinion

upon her looks, her position being almost beneath his eye, so that he saw her in a bird's-eye view, as Milton's Satan first saw Paradise. She wore no bonnet or het, but had enveloped her+ self in a large cloak, which was carelessly flung over her head as a covering. "There, now we'll go home," said the elder of the two, resting her knuckles upon her hips, and looking at their goings-on as a whole. "I do hope Daisy will fetch round again now. I have never been more frightened in my life, but I don't mind break+ ing my rest if she recovers." The young woman, whose eyelids were apparently inclined to fall together on the smallest provocation of silence,yawned in sympathy. "I wish we were rich enough to pay a man to do these things," she said. "As we are not, we must do them ourselves," said the other; "for you must help me if you stay." "Well, my hat is gone, however," continued the younger. "It went over the hedge, I think. The idea of such a slight wind catching it." The cow standing erect was of the Devon breed, and was encased in a tight warm hide of rich Indian red, as absolutely uniform from eyes to tail as if the animal had been dipped in a dye of that colour, her long back being mathematically level. The other was spotted,grey and white. Beside her Oak now noticed a little calf about a day old, looking idiotically at the two women, which showed that it had not long been accustomed to the phenomenon of eyesight, and often turn+ ing to the lantern, which it apparently mistook for the moon. inherited instinct having as yet had little time for correction by experience. Between the sheep and the cows Lucina had been busy on Norcombe hill lately. "I think we had better send for some oatmeal," said the "Yes, aunt; and I'll ride over for it as soon as it is light. ' " But there's no side-saddle.'

"I can ride on the other : trust me.' Oak, upon hearing these remarks, became more curious to observe her features, but this prospect being denied him by the hooding efect of the cloak, and by his aerial position, he felt himself drawing upon his fancy for their details. In making even horizontal and clear inspections we colour and mould according to the warts within us whatever our eyes bring in. Had Gabriel been able from the first to get a distinct view of her + countenance, his estimate of it as very handsome or slightly so would have been as his soul required a divinity at the moment or was ready supplied with one. Having for some time known the want of a satisfactory form to fill an increasing void within him, his position moreover affording the widest scope for his fancy, he painted her a beauty. By one of those whimsical coincidences in which Nature, like a busy mother, seems to spare a moment from her unremitting labours to turn and make her children smile, the girl now dropped the cloak, and forth tumbled ropes of black hair over a red jacket. Oak knew her instantly as the heroine of the yellow waggon, myrtles, and looking-glass : prosily, as the woman who owed him twopence. They placed the calf beside its mother again, took up the lantern, and went out, the light sinking down the hill till it was no more than a nebula. Gabriel Oak returned to his flock.

A GIRL ON HORSEBACK -- CONVERSATION THE sluggish day began to break. Even its position terrestrially is one of the elements of a new interest, and for no particular reason save that the incident of the night had occurred there, Oak went again into the plantation. Lingering and musing here, he heard the steps of a horse at the foot of the hill, and soon there appeared in view an auburn pony with a girl on its back, ascending by the path leading past the cattle+ shed. She was the young woman of the night before. Gabriel instantly thought of the hat she had mentioned as having lost in the wind; possibly she had come to look for it. He hastily scanned the ditch and after walking about ten yards along it, found the hat among the leaves. Gabriel took it in his hand and returned to his hut. Here he ensconced himself, and peeped through the loophole in the direction of the riders approach. She came up and looked around -- then on the other side of the hedge. Gabriel was about to advance and restore the missing article when an unexpected per+ formance induced him to suspend the action for the present. The path, after passing the cowshed, bisected the plantation. It was not a bridle-path -- merely a pedestrian's track, and the boughs spread horizontally at a height not greater than seven feet above the ground, which made it impossible to ride erect beneath them. The girl, who wore no riding-habit, looked around for a moment, as if to assure herself that all humanity was out of view, then dexterously dropped backwards flat upon the pony's back, her head over its tail, her feet against its shoulders, and her eyes to the sky. The rapidity of her glide into this position was that of a kingfisher -- its noiselessness that of a hawk. Gabriel's eyes had scarcely been able to follow her. The tall lank pony seemed used to such doings, and ambled

along unconcerned. Thus she passed under the level boughs. The performer seemed quite at home anywhere between a horse's head and its tail, and the necessity for this abnormal attitude having ceased with the passage of the plantation, she began to adopt another, even more obviously convenient than the first. She had no side-saddle, and it was very apparent that a firm seat upon the smooth leather beneath her was un+ attainable sideways. Springing to her accustomed perpendicular like a bowed sapling, and satisfying her, self that nobody was in sight, she seated herself in the manner demanded by the saddle, though hardly expected of the woman, and trotted off in the direction of Tewnell Mill. Oak was amused, perhaps a little astonished, and hanging up the hat in his hut, went again among his ewes. An hour passed, the girl returned, properly seated now, with a bag of bran in front of her. On nearing the cattle-shed she was met by a boy bringing a milking-pail, who held the reins of the pony whilst she slid off. The boy led away the horse, leaving the pail with the young woman. Soon soft spirts alternating with loud spirts came in regular succession from within the shed, the obvious sounds of a person milking a cow. Gabriel took the lost hat in his hand, and waited beside the path she would follow in leaving the hill. She came, the pail in one hand, hanging against her knee. The left arm was extended as a balance, enough of it being shown bare to make Oak wish that the event ha happened in the summer, when the whole would have been revealed. There was a bright air and manner about her now, by which she seemed to imply that the desirability of her existence could not be questioned; and this rather saucy assumption failed in being offensive, because a beholder felt it to be, upon the whole, true. Like exceptional emphasis in the tone of a genius, that which would have made mediocrity ridiculous was an addition to recognised power. It was with some surprise that she saw Gabriel's face rising like the moon behind the hedge. The adjustment of the farmer's hazy conceptions of her

charms to the portrait of herself she now presented him with was less a diminuition than a difference. The starting-point selected by the judgment was. her height She seemed tall, but the pail was a small one, and the hedge diminutive; hence, making allowance for error by comparison with these, she could have been not above the height to be chosen by women as best. All features of consequence were severe and regular. It may have been observed by persons who go about the shires with eyes for beauty, that in Englishwoman a classically-formed face is seldom found to be united with a figure of the same pattern, the highly-finished features being generally too large for the remainder of the frame ; that a graceful and proportionate figure of eight heads usually goes off into random facial curves. Without throwing a Nymphean tissue over a milkmaid, let it be said that here criticism checked itself as out of place, and looked at her proportions with a long consciousness of pleasure. From the contours of her figure in its upper part, she must have had a beautiful neek and shoulders ; but since her infancy nobody had ever seen them. Had she been put into a low dress she would have run and thrust her head into a bush. Yet she was not a shy girl by any means; it was merely her instinct to draw the line dividing the seen from the unseen higher than they do it in towns. That the girl's thoughts hovered about her face and form as soon as she caught Oak's eyes conning the same page was natural, and almost certain. The self+ consciousness shown would have been vanity if a little more pronounced, dignity if a little less. Rays of male vision seem to have a tickling effect upon virgin faces in rural districts ; she brushed hers with her hand, as if Gabriel had been irritating its pink surface by actual touch, and the free air of her previous movements was reduced at the same time to a chastened phase of itself. Yet it was the man who blushed, the maid not at all. " I found a hat,' said Oak. " It is mine,' said she, and, from a sense of proportion, kept down to a small smile an inclination to laugh dis+ tinctly : "it flew away last night.' " One o'clock this morning ? '

" Well -- it was.' She was surprised. " How did you know ? ' she said. " I was here.' " You are Farmer Oak, are you not ? ' " That or thereabouts. I'm lately come to this place.' " A large farm ? ' she inquired, casting her eyes round, and swinging back her hair, which was black in the shaded hollows of its mass; but it being now an hour past sunrise, the rays touched its prominent curves with a colour of their own. " No ; not large. About a hundred.' (In speaking of farms the word "acres ' is omitted by the natives, by analogy to such old expressions as "a stag of ten.') ' "I wanted my hat this morning,' she went on. had to ride to Tewnell Mill.' "Yes you had.' "How do you know?' "I saw you! "Where?' she inquired, a misgiving bringing every muscle of her lineaments and frame to a standstill. "Here-going through the plantation, and all down the hill,' said Farmer Oak, with an aspect excessively knowing with regard to some matter in his mind, as he gazed at a remote point in the direction named, and then turned back to meet his colloquist's eyes. A perception caused him to withdraw his own eyes from hers as suddenly as if he had been caught in a theft. Recollection of the strange antics she had indulged in when passing through the trees, was suc+ ceeded in the girl by a nettled palpitation, and that' by a hot face. It was a time to see a woman redden who was not given to reddening s a rule; not a point in the milkmaid but was of the deepest rose-colour. From the Maiden's Blush, through all varieties of the Provence down to the Crimson Tuscany, the countenance of Oak's acquaintance quickly graduated ; whereupon he, in con+ siderateness, turned away his head. The sympathetic man still looked the other way, and wondered when she would recover coolness sufficient to justify him in facing her again. He heard what seemed to be the flitting of a

dead leaf upon the breeze, and looked. She had gone away. With an air between that of Tragedy and Comedy ! Gabriel returned to his work. Five mornings and evenings passed. The young woman came regularly to milk the healthy cow or to attend to the sick one, but never allowed her vision to stray in the direction of Oak's person. His want of tact had deeply offended her -- not by seeing what he could not help, but by letting her know that he had seen it. For, as without law there is no sin, without eyes there is no indecorum; and she appeared to feel that Gabriel's espial had made her an indecorous woman without her own connivance. It was food for great regret with him; it was also a contretemps which touched into life a latent heat he had experienced in that direction. The acquaintanceship might, however, have ended in a slow forgetting, but for an incident which occurred at the end of the same week. One afternoon it began to freeze, and the frost increased with evening, which drew on like a stealthy tightening of bonds. It was a time when in cottages the breath of the sleepers freezes to the sheets; when round the drawing-room fire of a thick-walled mansion the sitters' backs are cold, even whilst their faces are all aglow. Many a small bird went to bed supperless that night among the bare boughs. As the milking-hour drew near, Oak kept his usual watch upon the cowshed. At last he felt cold, and shaking an extra quantity of bedding round the yeaning ewes he entered the hut and heaped more fuel upon the stove. The wind came in at the bottom of the door, and to prevent it Oak laid a sack there and wheeled the cot round a little more to the south. Then the wind spouted in at a ventilating hole -- of which there was one on each side of the hut. Gabriel had always known that when the fire was lighted and the door closed one of these must be kept open -- that chosen being always on the side away from the wind. Closing the slide to windward, he turned to open the other; on second -- -thoughts the farmer con+ sidered that he would first sit down leaving both closed for a minute or two, till the temperature of the hut was a little raised. He sat down.

His head began to ache in an unwonted manner, and, fancying himself weary by reason of the broken rests of the preceding nights, Oak decided to get up, open the slide, and then allow himself to fall asleep. He fell asleep, however, without having performed the necessary preliminary. How long he remained unconseious Gabriel never knew. During the first stages of his return to percep+ tion peculiar deeds seemed to be in course of enactment. His dog was howling, his head was aching fearfully -- somebody was pulling him about, hands were loosening his neckerchief. On opening his eyes he found that evening had sunk to dusk in a strange manner of unexpectedness. The young girl with the remarkably pleasant lips and white teeth was beside him. More than this -- astonishingly more -- his head was upon her lap, his face and neck were disagreeably wet, and her fingers were unbuttoning his collar. "Whatever is the matter?' said Oak, vacantly. She seemed to experience mirth, but of too insignifi+ cant a kind to start enjoyment. "Nothing now', she answered, "since you are not dead It is a wonder you were not,suffocated in this hut of yours.' "Ah, the hut ! ' murmured Gabriel. "I gave ten pounds for that hut. But I'll sell it, and sit under thatched hurdles as they did in old times, curl up to sleep in a lock of straw! It played me nearly the same trick the other day .! ' Gabriel, by way of emphasis, brought down his fist upon the floor. "It was not exactly the fault of the hut,' she ob+ served in a tone which showed her to be that novelty among women -- one who finished a thought before beginning the sentence which was to convey it. " You should I think, have considered, and not have been so foolish as to leave the slides closed.' "Yes I suppose I should,' said Oak, absently. He was endeavouring to catch and appreciate the sensation of being thus with her, his head upon her dress, before the event passed on into the heap of bygone things. He wished she knew his impressions ; but he would as soon have thought of carrying an odour in a net as of attempting to convey the intangibilities

of his feeling in the coarse meshes of language. So he remained silent. She made him sit up, and then Oak began wiping his face and shaking himself like a Samson. "How can I thank 'ee ? ' he said at last, gratefully, some of the natural rusty red having returned to his face. " Oh, never mind that,' said the girl, smiling, and allowing her smile to hold good for Gabriel's next remark, whatever that might prove to be. "How did you find me?" "I heard your dog howling and scratching at the door of the hut when I came to the milking (it was so lucky, Daisy's milking is almost over for the season, and I shall not come here after this week or the next). The dog saw me, and jumped over to me, and laid hold of my skirt. I came across and looked round the hut the very first thing to see if the slides were closed. My uncle has a hut like this one, and I have heard him tell his shepherd not to go to sleep without leaving a slide open. I opened the door, and there you were like dead. I threw the milk over you, as there was no water, forgetting it was warm, and no use.' "I wonder if I should have died ? ' Gabriel said, in a low voice, which was rather meant to travel back to himself than to her. "O no," the girl replied. She seemed to prefer a less tragic probability ; to have saved a man from death 'involved talk that should harmonise with the dignity of such a deed -- and she shunned it. "I believe you saved my life, Miss -- -- I don!t know your name. I know your aunt's, but not yours.' " I would just as soon not tell it -- rather not. There is no reason either why I should, as you probably will never have much to do with me.' " Still, I should like to know.' " You can inquire at my aunt's -- she will tell you.' 'My name is Gabriel Oak.' "And mine isn't. You seem fond of yours in speaking it so decisively, Gabriel Oak.'

" You see, it is the only one I shall ever have, and I must make the most of it.' " I always think mine sounds odd and disagreeable.' "I should think you might soon get a new one.' "Mercy ! -- how many opinions you keep about you concerning other people, Gabriel Oak. "Well Miss-excuse the words-I thought you would like them But I can't match you I know in napping out my mind upon my tongue. I never was very clever in my inside. But I thank you. Come give me your hand!' She hesitated, somewhat disconcerted at Oak's old+ fashioned earnest conclusion. to a dialogue lightly carried on."Very well,' she said, and gave him her hand, compressing her lips to a demure impassivity. He held it but an instant, and in his fear of being too demonstrative, swerved to the opposite extreme, touching her fingers with the lightness of a small-hearted person. " I am sorry,' he said, the instant after. " What for?' "You may have it again if you like; there it is.' She gave him her hand again. Oak held it longer this time -- indeed, curiously long. "How soft it is -- being winter time, too -- not chapped or rough or anything!' he said. "There -- that's long enough,' said she, though with+ out pulling it away "But I suppose you are thinking you would like to kiss it? You may if you want to.' "I wasn't thinking of any such thing,' said Gabriel, simply ; "but I will' "That you won't!' She snatched back her hand. Gabriel felt himself guilty of another want of tact. "Now find out my name,' she said, teasingly; and withdrew.

GABRIEL'S RESOLVE -- THE VISIT -- THE MISTAKE THE only superiority in women that is tolerable to the rival sex is, as a rule, that of the unconscious kind ; but a superiority which recognizes itself may sometimes please by suggesting possibilities of capture to the subordinated man. This well-favoured and comely girl soon made appre+ ciable inroads upon the emotional constitution of young Farmer Oak. Love, being an extremely exacting usurer (a sense of exorbitant profit, spiritually, by an exchange of hearts, being at the bottom of pure passions, as that of exorbi+ tant profit, bodily or materially, is at the bottom of those of lower atmosphere), every morning Oak's feelings were as sensitive as the money-market in calculations upon his chances. His dog waited for his meals in a way so like that in which Oak waited for the girl's presence, that the farmer was quite struck with the resemblance, felt it lowering, and would not look at the dog. However, he continued to watch through the hedge for her regular coming, and thus his sentiments towards her were ideepened without any corresponding effect being produced upon herself. Oak had nothing finished and ready to say as yet, and not being able to frame love phrases which end where they begin ; passionate tales -- + -- -Full of sound and fury -- -signifting nothing -- + he said no word at all. By making inquiries he found that the girl's name was Bathsheba Everdene, and that the cow would go dry in about seven days. He dreaded the eight day. At last the eighth day came. The cow had ceased to give milk for that year, and Bathsheba Everdene came up the hill no more. Gabriel had reached a pitch of existence he never

could have anticipated a short time before. He liked saying 'Bathsheba' as a private enjoyment instead of whistling; turned over his taste to black hair, though he had sworn by brown ever since he was a boy, isolated himself till the space he filled in a possible strength in an actual weakness. Marriage transforms a distraction into a support, the power of which should be, and happily often is, in direct pro+ portion to the degree of imbecility it supplants. Oak began now to see light in this direction, and said to himself, "I'll make her my wife, or upon my soul I shall be good for nothing .! ' All this while he was perplexing himself about an errand on which he might consistently visit the cottage of Bathsheba's aunt. He found his opportunity in the death of a ewe, mother of a living lamb. On a day which had a summer face and a winter constitution-a fine January morning, when there was just enough blue sky visible to make cheerfully-disposed people wish for more, and an occasional gleam of silvery sunshine, Oak put the lamb into a respectable Sunday basket, and stalked across the fields to the house of Mrs. Hurst, the aunt -- George, the dog walking behind, with a countenance of great concern at the serious turn pastoral affairs seemed to be taking. Gabriel had watched the blue wood-smoke curling from the chimney with strange meditation. At evening he had fancifully traced it down the chimney to the spot of its origin -- seen the hearth and Bathsheba beside it -- beside it in her out-door dress; for the clothes she had worn on the hill were by association equally with her person included in the compass of his affection; they seemed at this early time of his love a necessary ingredient of the sweet mixture called Bath+ sheba Everdene. He had made a toilet of a nicely-adjusted kind -- of a nature between the carefully neat and the carelessly ornate -- of a degree between fine-market-day and wet+ Sunday selection. He thoroughly cleaned his silver watch-chain with whiting, put new lacing straps to his boots, looked to the brass eyelet-holes,

went to the inmost heart of the plantation for a new walking-stick, and trimmed it vigorously on his way back; took a new handkerchief from the bottom of his clothes-box, put on the light waistcoat patterned all over with sprigs of an elegant flower uniting the beauties of both rose and lily without the defects of either, and used all the hair-oil he possessed upon his usually dry, sandy, and inextricably curly hair, till he had deepened it to a splendidly novel colour, between that of guano and Roman cement, making it stick to his head like mace round a nutmeg, or wet seaweed round a boulder after the ebb. Nothing disturbed the stillness of the cottage save the chatter of a knot of sparrows on the eaves; one might fancy scandal and rumour to be no less the staple topic of these little coteries on roofs than of those under them. It seemed that the omen was an unpropitious one, for, as the rather untoward commence+ ment of Oak's overtures, just as he arrived by the garden gate, he saw a cat inside, going into various arched shapes and fiendish convulsions at the sight of his dog George. The dog took no notice , for he had arrived at an age at which all superfluous barking was cynically avoided as a waste of breath -- -in fact he never barked even at the sheep except to order, when it was done with an absolutely neutral countenance, as a sort of Com+ mination-service, which, though offensive, had to be gone through once now and then to frighten the flock for their own good. A voice came from behind some laurel-bushes into which the cat had run: "Poor dear! Did a nasty brute of a dog want to kill it; -- did he poor dear !' "I beg your pardon,' said Oak to the voice, 'but George was walking on behind me with a temper as mild as milk.' Almost before he had ceased speaking, Oak was seized with a misgiving as to whose ear was the recipient of his answer. Nobody appeared, and he heard the person retreat among the bushes. Gabriel meditated, and so deeply that he brought small furrows into his forehead by sheer force of reverie. Where the

issue of an interview is as likely to be a vast change for the worse as for the better, any initial difference from expectation causes nipping sensations of failure. Oak went up to the door a little abashed : his mental rehearsal and the reality had had no common grounds of opening. Bathsheba's aunt was indoors. " Will you tell Miss Everdene that somebody would be glad to speak to her ?'said Mr. Oak. (Calling one's self merely Some+ body, without giving a name, is not to be taken as an example of the ill-breeding of the rural world: it springs from a refined modesty, of which townspeople, with their cards and announcements, have no notion whatever.) Bathsheba was out. The voice had evidently been hers. " Will you come in, Mr. Oak ? ' "Oh, thank 'ee, said Gabriel, following her to the fireplace. "I've brought a lamb for Miss Everdene. I thought she might like one to rear; girls do.' " She might,' said Mrs. Hurst, musingly ; " though she's only a visitor here. If you will wait a minute, Bathsheba will be in.' " Yes, I will wait,' said Gabriel, sitting down. " The lamb isn't really the business I came about, Mrs. Hurst. In short, I was going to ask her if she'd like to be married.' "And were you indeed ?' " Yes. Because if she would, I should be very glad to marry her. D'ye know if she's got any other young man hanging about her at all ?' "Let me think," said Mrs. Hurst, poking the fire superfluously.... " Yes -- bless you, ever so many young men. You see, Farmer Oak, she's so good-looking, and an excellent scholar besides -- she was going to be a governess once, you know, only she was too wild. Not that her young men ever come here -- but, Lord, in the nature of women, she must have a dozen ! ' " That's unfortunate,' said Farmer Oak, contemplating a crack in the stone floor with sorrow. "I'm only an every-day sort of man, and my only chance was in being the first comer... , Well, there's no use in my waiting, for that was all I came about: so I'll take myself off home-along, Mrs. Hurst.' When Gabriel had gone about two hundred yards along the

down, he heard a "hoi-hoi .! " uttered behind him, in a piping note of more treble quality than that in which the exclamation usually embodies itself when shouted across a field. He looked round, and saw a girl racing after him, waving a white handkerchief. Oak stood still -- and the runner drew nearer. It was Bathsheba Everdene. Gabriel's colour deepened: hers was already deep, not, as it appeared, from emotion, but from running. "Farmer Oak -- I -- ' she said, pausing for want of breath pulling up in front of him with a slanted face and putting her hand to her side. "I have just called to see you ' said Gabriel, pending her further speech. "Yes-I know that,! she said panting like a robin, her face red and moist from her exertions, like a peony petal before the sun dries off the dew. "I didn't know you had come to ask to have me, or I should have come in from the garden instantly. I ran after you to say -- that my aunt made a mistake in sending you away from courting me -- -- -- ' Gabriel expanded."I'm sorry to have made you run so fast, my dear,' he said, with a grateful sense of favours to come. "Wait a bit till you've found your breath.' " -- It was quite a mistake-aunt's telling you I had a young man "already,'- Bathsheba went on. " I haven't a sweetheart at all -- and I never had one, and I thought that, as times go with women, it was such a pity to send you away thinking that I had several.' "Really and truly I am glad to hear that.!' said .= Farmer Oak, smiling one of his long special smiles, and blushing with gladness. He held out his hand to take hers, which, when she had eased her side by pressing it there, was prettily extended upon her bosom to still her loud-beating heart. Directly he seized it she put it behind her, so that it slipped through his fingers like an eel. " "I have a nice snug little farm,' said Gabriel, with half a degree less assurance than when he had seized her hand. "Yes ; you have.' "A man has advanced me money to begin with, but still, it

will soon be paid off and though I am only an every-day sort of man, I have got on a little since I was a boy.' Gabriel uttered "a little' in a tone to-show her that it was the complacent form of "a great deal.' He continued : " When we be married, I am quite sure I can work twice as hard as I do now.' He went forward and stretched out his arm again. Bathsheba had overtaken him at a point beside which stood a low stunted holly bush, now laden with red berries. Seeing his advance take the form of an attitude threatening a possible enclosure, if not compression, of her person, she edged off round the bush. " Why, Farmer Oak,' she said, over the top, looking at him with rounded eyes, "I never said I was going to marry you.' " Well -- that is a tale .! ' said Oak, with dismay. " To run after anybody like this, and then say you don"t want him ! ' "What I meant to tell you was only this,' she said eagerly, and yet half conscious of the absurdity of the position she had made for herself -- "that nobody has got me yet as a sweetheart, instead of my having a dozen, as my aunt said; I hate to be thought men's property in that way, though possibly I shall be had some day. Why, if I'd wanted you I shouldn't have run after you like this ; 'twould have'been the forwardest thing ! But there was no harm in 'hurrying to correct a piece of false news that had been told you.' "Oh, no -- no harm at all." But there is such a thing as being too generous in expressing a judgment impuls+ ively, and Oak added with a more appreciative sense of all the circumstances -- ' Well, I am not quite certain it was no harm.' "Indeed, I hadn't time to think before starting whether I wanted to marry or not, for you'd have been gone over the hill.' " Come,' said Gabriel, freshening again ; "think a minute or two. I'll wait a while, Miss Everdene. Will you marry me? Do, Bathsheba. I love you far more than common!' "I'll try to think,' she observed, rather more timor+ ously ; "if I can think out of doors; my mind spreads away so.' "But you can give a guess.'

"Then give me time.' Bathsheba looked thought+ fully into the distance, away from the direction in which Gabriel stood. "I can make you happy,' said he to the back of her head, across the bush. "You shallo have as piano in a year or two -- -farmers' wives are getting to have pianos now -- and I'll practise up the flute right well to play with you in the evenings.' " Yes ; I should like that.' "And have one of those little ten-pound" gigs for market -- and nice flowers, and birds -- cocks and hens I mean, because they be useful,' continued Gabriel, feeling balanced between poetry and practicality. "I should like it very much.' "And a frame for cucumbers -- like a gentlman and lady.' "Yes.' "And when the wedding was over, we'd have it put in the newspaper list of marriages.' " Dearly I should like that ! ' "And the babies in the births -- every man jack of 'em! And at home by the fire, whenever you look up, there I shall be -- and whenever I look up' there will be you.' "Wait wait and don't be improper .!' Her countenance fell, and she was silent awhile. He regarded the red berries between them over and over again, to such an extent, that holly seemed in his after life to be a cypher signifying a proposal of marriage. Bathsheba decisively turned to him. "No;' 'tis no use,' she said. 'I don't want to marry you. ' ' Try.' "I have tried hard all the time I've been thinking; for a marriage would be very nice in one sense. People would talk about me, and think I had won my battle, and I should feel triumphant, and' all that, But a husband -- -- ' - + " Well .! ' " Why, he'd always be there, as you say; whenever I looked up, there he'd be.' " Of course he would -- I, that is.'

" Well, what I mean is that I shouldn't mind being a bride at a wedding, if I could be one without having a husband. But since a woman can't show off in that way by herself, I shan't marry -- at least yet.' ' That's a terrible wooden story.' At this criticism of her statement Bathsheba made an addition to her dignity by a slight sweep away from him. "Upon my heart and soul, I don't know what a maid can say stupider than that,' said Oak. "But dearest,' he continued in a palliative voice, "don't be like it !.' Oak sighed a deep honest sigh -- none the less so in that, being like the sigh of a pine plantation, it was rather noticeable as a disturbance of the atmo+ sphere. " Why won't you have me ? ' he appealed, creeping round the holly to reach her side. " I cannot,' she said, retreating. "But why ?' he persisted, standing still at last in despair of ever reaching her, and facing over the bush. ' Because I don't love you.' " Yes, but -- -- ' She contracted a yawn to an inoffensive smallness, so that it was hardly ill-mannered at all. "I don't love you,' she said.' "But I love you -- and, as for myself, I am content to be liked.' " O Mr. Oak -- that's very fine ! You'd get to despise me.' "Never,' said Mr Oak, so earnestly that he seemed to be coming, by the forceof his words, straight through the bush and into her arms. "I shall do one thing in this life -- one thing certain -- that is, love you, and long for you, and keep wanting you till I die.' His voice had a genuine pathos now, and his large brown hands perceptibly trembled. "It seems dreadfully wrong not to have you when you feel so much!' she said with a little distress, and looking hopeleely around for some means of escape from her moral dilemma. " H(ow I wish I hadn't run after you!' However she seemed to have a short cut for getting back to cheerfulness, and set her face to signify archness. "It wouldn't do, Mr Oak. I want somebody to tame me; I am too independent ; and you would never be able to, I know.'

Oak cast his eyes down the field in a way implying that it was useless to attempt argument. " Mr. Oak,' she said, with luminous distinctness and common sense, " you are better off than I. I have hardly a penny in the world -- I am staying with my aunt for my bare sustenance. I am better educated than you -- and I don't love you a bit: that's my side of the case. Now yours: you are a farmer just begin+ ing; and you ought in common prudence, if you marry at all (which you should certainly not think of doing at present) to marry a woman with money, who would admiration. "That's the very thing I had been thinking myself !' he naively said. Farmer Oak had one-and-a-half Christian character istics too many to succeed with Bathsheba : his humility, and a superfluous moiety of honesty. Bathsheba was decidedly disconcerted, "Well, then, why did you come and disturb me?' she said, almost angrily, if not quite, an enlarging red spot rising in each cheek. " I can't do what I think would be -- would be -- -- ' " Right ? ' " No : wise.' " You have made an admission now, Mr. Oak,' she exclaimed, with even more hauteur, and rocking her head disdainfully. 'After that, do you think I could marry you? Not if I know it.' He broke in passionately ! "But don't mistake me like that! Because I am open enough to own what every man in my shoes would have thought of, you make your colours come up your face, and get crabbed with me. That about your not being good enough for me is nonsense. You speak like a lady -- all the parish notice it, and your uncle at Weatherbury is, I have heerd, a large farmer -- much larger than ever I shall be. May I call in the evening, or will you walk along with me o' Sundays? I don't want you to make-up your mind at once, if you'd rather not.'

" No -- no -- I cannot. Don't press me any more -- don't. I don't love you -- so 'twould be ridiculous,' she said, with a laugh. No man likes to see his emotions the sport of a merry-go-round of skittishness. " Very well,' said Oak, firmly, with the bearing of one who was going to give ' his days and nights to Ecclesiastes for ever. "Then I'll ask you no more.'

DEPARTURE OF BATHSHEBA -- A PASTORAL TRAGEDY THE news which one day reached Gabriel, that Bath+ sheba Everdene had left the neighbourhood, had an influence upon him which might have surprised any who never suspected that the more emphatic the renun+ ciation the less absolute its character. It may have been observed that there is no regula path for getting out of love as there is for getting in. Some people look upon marriage as a short cut that way, but it has been known to fail. Separation, which was the means that chance offered to Gabriel Oak by Bathsheba's disappearance though effectual with people of certain humours is apt to idealise the removcd object with others -- notably those whose affection, placid and regular as it may be flows deep and long. Oak belonged to the even-tempered order of humanity, and felt the secret fusion of himself in Bathsheba to be burning with a finer flame now that she was gone -- that was all. His incipient friendship with her aunt-had been nipped by the failure of his suit, and all that Oak learnt of Bathsheba's movements was done indirectly. It ap+ peared that she had gone to a place called Weatherbury, more than twenty miles off, but in what capacity -- whether as a visitor, or permanently, he could not discover. Gabriel had two dogs. George, the elder, exhibited an ebony-tipped nose, surrounded by a narrow margin of pink flesh, and a coat marked in random splotches approximating in colour to white and slaty grey ; but the grey, after years of sun and rain, had been scorched and washed out of the more prominent locks, leaving them of a reddish-brown, as if the blue component of the grey had faded, like the indigo from the same kind of colour in Turner's pictures. In substance it had originally been hair, but long contact with sheep seemed

to be turning it by degrees into wool of a poor quality and staple. This dog had originally belonged to a shepherd of inferior morals and dreadful temper, and the result was that George knew the exact degrees of condemnation signified by cursing and swearing of all descriptions better than the wickedest old man in the neighbourhood. Long experience had so precisely taught the animal the difference between such exclamations as 'Come in .! ' and 'D -- -- ye, come in !.' that he knew to a hair's breadth the rate of trotting back from the ewes' tails that each call involved, if a staggerer with the sheep crook was to be escaped. Though old, he was clever and trustworthy still. The young dog, George's son, might possibly have been the image of his mother, for there was not much resemblance between him and George. He was learn+ ing the sheep-keeping business, so as to follow on at the flock when the other should die, but had got no further than the rudiments as yet -- still finding an insuperable difculty in distinguishing between doing a thing well enough and doing it too well. So earnest and yet so wrong-headed was this young dog (he had no, name in particular, and answered with perfect readiness to any pleasant interjection), that if sent behind the flock to help them on, he did it so thoroughly that he would have chased them across the whole county with the greatest pleasure if not called off or reminded when to step by the example of old George. Thus much for the dogs. On the further side of Norcombe Hill was a chalk-pit, from which chalk had been drawn for generations, and spread over adjacent farms. Two hcdges converged upon it in the form of a V, but without quite meeting. The narrow opening left, which was immediately over the brow of the pit, was protected by a rough railing. One night, when Farmer Oak had returned to, his house, believing there would be no further necessity for his attendance on the down, he called as usual to the dogs, previously to shutting them up in the outhouse till next morning. Only one responded -- old George ; the other-could not be found, either in the house, lane, or garden. - Gabriel then remembered

that he had left the two dogs on the hill eating a dead lamb (a kind of meat he usually kept from them, except when other food-ran finished his meal, he went indoors to the luxury of a bed, which latterly he had only enjoyed on Sundays. It was a still, moist night. Just before dawn he was assisted in waking by the abnormal reverberation of familiar music. To the shepherd, the note of the sheep' chronic sound that only makes itself noticed by ceasing ever distant, that all is well in the fold. In the solemn This exceptional ringing may be caused in two ways -- + by the rapid feeding of the sheep bearing the bell, as when the flock breaks into new pasture, which gives it an intermittent rapidity, or by the sheep starting off in a run, when the sound has a regular palpitation. The experieced ear of Oak knew the sound he now' heard to be caused by the running of the flock with great velocity. He jumped out of bed, dressed, tore down the lane through a foggy dawn, and ascended the hill. The forward ewes were kept apart from those among which the fall of lambs would be later, there being two hundred of the latter class in Gabriel's flock. These two hundred seemed to have absolutely vanished from the hill. There were the fifty with their lambs, enclosed at the other end as he had left them, but the rest, forming the bulk of the flock, were nowhere. Gabriel called at the top of his voice the shepherd's call. " Ovey, ovey, ovey .! ' Not a single bleat. He went to the hedge -- a gap had been broken through it, and in the gap were the footprints of the sheep. Rather surprised to find them break fence at this season, yet putting it down instantly to their great fondness for ivy in winter-time, of which a great deal grew in the plantation, he followed through the hedge. They were not in the plantation. He called again : the valleys and farthest hills

resounded as when the sailors invoked the lost Hylas on the Mysian shore ; but no sheep. He passed through the trees and along the ridge of the hill. On the extreme summit, where the ends of the two converging hedges of which we have spoken were stopped short by meeting the brow of the chalk-pit, he saw the younger dog standing against the sky -- dark and motionless as Napoleon at St. Helena. A horrible conviction darted through Oak. With a sensation of bodily faintness he advanced : at one point the rails were broken through, and there he saw the footprints of his ewes. The dog came up, licked his hand, and made signs implying that he expected some great reward for signal services rendered. Oak looked over the precipice. The ewes lay dead and dying at its foot -- a heap of two hundred mangled careases, representing in their condition just now at least two hundred more. Oak was an intensely humane man: indeed, his humanity often tore in pieces any politic intentions of his which bordered on strategy, and carried him on as by gravitation. A shadow in his life had always been that his flock ended in mutton -- that a day came and found every shepherd an arrant traitor to his defenceless sheep. His first feeling now was one of pity for the untimely fate of these gentle ewes and their unborn lambs. It was a second to remember another phase of the matter. The sheep were not insured. All the savings of a frugal life had been dispersed at a blow ; his hopes of being an independent farmer were laid low -- possibly for ever. Gabriel's energies, patience, and industry had been so severely taxed during the years of his life between eighteen and eight-and-twenty, to reach his present stage of progress' that no more seemed to be left in him. He hands. Stupors, however, do not last for ever, and Farmer Oak recovered from his. It was as remarkable as it was characteristic that the one sentence he uttered was in thankfulness : -- 'Thank God I am not married : what would she have done in the poverty now coming upon me ! '

Oak raised his head, and wondering what he could do listlessly surveyed the scene. By the outer margin of the Pit was an oval pond, and over it hung the attenuated skeleton of a chrome-yellow moon which had only a few days to last -- the morning star dogging her on the left hand. The pool glittered like a dead man's eye, and as the world awoke a breeze blew, shaking and elongating the reflection of the moon without breaking it, and turning the image of the star to a phosphoric streak upon the water. All this Oak saw and remembered. As far as could be learnt it appeared that the poor young dog, still under the impression that since he was kept for running after sheep, the more he ran after them the better, had at the end of his meal off the dead lamb, which may have given him additional energy and spirits, collected all the ewes into a corner, driven the timid creatures through the hedge, across the upper field, and by main force of worrying had given them momentum enough to break down a portion of the rotten railing, and so hurled them over the edge. George's son had done his work so thoroughly that he was considered too good a workman to live, and was, in fact, taken and tragically shot at twelve o'clcck that same day -- another instance of the untoward fate which so often attends dogs and other philosophers who follow out a train of reasoning to its logical conclusion, and attempt perfectly consistent conduct in a world made up so largely of compromise. Gabriel's farm had been stocked by a dealer -- on the strength of Oak's promising look and character -- who was receiving a percentage from the farmer till such time as the advance should be cleared off Oak found+ that the value of stock, plant, and implements which were really his own would be about sufficient to pay his debts, leaving himself a free man with the clothes he stood up in, and nothing more.

THE FAIR -- THE JOURNEY -- THE FIRE TWO months passed away. We are brought on to a day in February, on which was held the yearly statute or hiring fair in the county-town of Casterbridge. At one end of the street stood from two to three hundred blithe and hearty labourers waiting upon Chance -- all men of the stamp to whom labour suggests nothing worse than a wrestle with gravitation, and pleasure nothing better than a renunciation of the same among these, carters and waggoners were distinguished by having a piece of whip-cord twisted round their hats; thatchers wore a fragment of woven straw; shepherds held their sheep-crooks in their hands; and thus the situation required was known to the hirers at a glance. In the crowd was an athletic young fellow of some+ what superior appearance to the rest -- in fact, his superiority was marked enough to lead several ruddy peasants standing by to speak to him inquiringly, as to a farmer, and to use 'Sir' as a finishing word. His answer always was, 'I am looking for a place myself -- a bailiff's. Do Ye know of anybody who wants one ?' Gabriel was paler now. His eyes were more medi+ tative, and his expression was more sad. He had passed through an ordeal of wretchedness which had given him more than it had taken away. He had sunk from his modest elevation as pastoral king into the very slime-pits of Siddim ; but there was left to him a digni+ fied calm he had never before known, and that indiffer+ ence to fate which, though it often makes a villain of a man, is the basis of his sublimity when it does not. And thus the abasement had been exaltation, and the loss gain. In the morning a regiment of cavalry had left the town, and a sergeant and his party had been beating up for recruits through the four streets. As the end of the day drew on, and

he found himself not hired, Gabriel almost wished that he had joined them, and gone off to serve his country. Weary of standing in the market+ place, and not much minding the kind of work he turned his hand to, he decided to offer himself in some other capacity than that of bailiff. All the farmers seemed to be wanting shepherds. Sheep-tending was Gabriel's speciality. Turning down an obscure street and entering an obscurer lane, he went up to a smith's shop. 'How long would it take you to make a shepherd's crook ? ' 'Twenty minutes.' 'How much ? ' 'Two shillings.' He sat on a bench and the crook was made, a stem being given him into the bargain. He then went to a ready-made clothes' shop, the owner of which had a large rural connection. As the crook had absorbed most of Gabriel's money, he attempted, and carried out, an exchange of his overcoat for a shepherd's regulation smock-frock. This transaction having been completed, he again hurried off to the centre of the town, and stood on the kerb of the pavement, as a shepherd, crook in hand. Now that Oak had turned himself into a shepherd, it seemed that bailifs were most in demand. However, two or three farmers noticed him and drew near. Dialogues followed, more or lessin the subjoined for: -- 'Where do you come from?' 'Norcombe.' 'That's a long way. 'Fifteen miles.' 'Who's farm were you upon last?' 'My own.' This reply invariably operated like a rumour of cholera. The inquring farmer would edge away and shake his head dubiously. Gabriel, like his dog, was too good to be trustworthy,. and he never made advance beyond this point. It is safer to accept any chance that offers itself, and

extemporize a procedure to fit it, than to get a good shepherd, but had laid himself out for anything in the whole cycle of labour that was required in the fair. It grew dusk. Some merry men were whistling and singing by the corn-exchange. Gabriel's hand, which had lain for some time idle in his smock-frock pocket, touched his flute which he carried there. Here was an opportunity for putting his dearly bought wisdom into practice. He drew out his flute and began to play Jockey to the Fair' in the style of a man who had never known moment's sorrow. Oak could pipe with Arcadian sweetness and the sound of the well-known notes cheered his own heart as well as those of the loungers. He played on with spirit, and in half an hour had earned in pence what was a small fortune to a destitute man. By making inquiries he learnt that there was another fair at Shottsford the next day. 'How far is Shottsford?' 'Ten miles t'other side of Weatherbury.' Weatherbury!. It was where Bathsheba had gone two months before. This information was like coming from night into noon. 'How far is it to Weatherbury ?' 'Five or six miles.' Bathsheba had probably left Weatherbury long before this time, but the place had enough interest attaching to it to lead Oak to choose Shottsford fair as his next field of inquiry, because it lay in the Weatherbury quarter. Moreover, the Weatherbury folk were by no means uninteresting intrinsically. If report spoke truly they were as hardy, merry, thriving, wicked a set as any in the whole county. Oak resolved to sleep at Weatherbury -- -that -- night on his way to Shottsford, and struck out at once -- into the -- high road which had been recommended as the direct route to the village in question. The road stretched through water-meadows traversed by little brooks, whose quivering surfaces were braided along their centres, and folded into creases at the sides; or, where the flow was more rapid, the stream was pied with spots of white froth,

which rode on in undisturbed serenity. On the higher levels the dead and dry carcases of leaves tapped the ground as they bowled along helter+ skelter upon the shoulders of the wind, and little birds in the hedges were rustling their feathers and tucking themselves in comfortably for the night, retaining their places if Oak kept moving, but flying away if he stopped to look at them. He passed by Yalbury-Wood where the game-birds were rising to their roosts, and heard the crack-voiced cock-pheasants' 'cu-uck, cuck,' and the wheezy whistle of the hens. By the time he had walked three or four miles every shape in the-landscape had assumed a uniform hue of blackness. He descended Yalbury Hill and could just discern ahead of him a waggon, drawn up under a great over-hanging tree by the roadside. On coming close, he found there were no horses attached to it, the spot being apparently quite deserted. The waggon, from its position, seemed to have been left there for the night, for beyond about half a truss of hay which was heaped in the bottom, it was quite empty. Gabriel sat down on the shafts of the vehicle and con+ sidered his position. He calculated that he had walked a very fair proportion of the journey; and having been on foot since daybreak, he felt tempted to lie down upon the hay in the waggon instead of pushing on to the village of Weatherbury, and having to pay for a lodging. Eating his las slices of bread and ham, and drinking from the bottle of cider he had taken the precaution to bring with him, he got into the lonely waggon. Here he spread half of the hay as a bed, and, as well as he could in the darkness, pulled the other half over him by way of bed-clothes, covering himself entirely, and feeling, physically, as comfortable as ever he had been in his life. Inward melancholy it was impossible for a man like Oak, introspective far beyond his neighbours, to banish quite, whilst conning the present. untoward page of his history. So, thinking of his misfortunes, amorous and pastoral he fell asleep, shepherds enjoying, in common with sailors, the privilege of being able to summon the god instead of having to wait for him.

On somewhat suddenly awaking after a sleep of whose length he had no idea, Oak found that the waggon was in motion. He was being carried along the road at a rate rather considerable for a vehicle without springs, and under circumstances of physical uneadiness, his head being dandled up and down on the bed of the waggon like a kettledrum-stick. He then dis+ tinguished voices in conversation, comig from the forpart of the waggon. His concern at this dilemma (which would have been alarm, had he been a thriving man; but -- misfortune is a fine opiate to personal terror) led him to peer cautiously from the hay, and the first sight he beheld was the stars above him. Charles's Wain was getting towards a right angle with the Pole star, and Gabriel concluded that it must be about nine o'clock -- in other words, that he had slept two hours. This small astronomical calculation was made without any positive effort, and whilst he was stealthily turning to discover, if possible, into whose hands he had fallen. Two figures were dimly visible in front, sitting with their legs outside the waggon, one of whom was driving. Gabriel soon found that this was the waggoner, and it appeared they had come from Casterbridge fair, like himself. A conversation was in progress, which continued thus : -- 'Be as 'twill, she's a fine handsome body as far's looks be concerned. But that's only the skin of the woman, and these dandy cattle be as-proud as a lucifer in their insides.' 'Ay -- so 'a do seem, Billy Smallbury -- so 'a do seem.' This utterance was very shaky by nature, and more so by circumstance, the jolting of the waggon not being+ without its effect upon the speaker's larynx. It came 'from the man who held the reins. 'She's a very vain feymell -- so 'tis said here and there.' 'Ah, now. If so be 'tis like that, I can't look her in the face. Lord, no : not I -- heh-heh-heh .! Such a shy man as I be.!' 'Yes -- she's very vain. 'Tis said that every night at going to bed she looks in the glass to put on her night+ cap properly.' 'And not a married woman. Oh, the world .! "And 'a can play the peanner, so 'tis said. Can play so clever

that 'a can make a psalm tune sound as well as the merriest loose song a man can wish for.' 'D'ye tell o't .! A happy time for us, and I feel quite a new man! And how do she play?' 'That I dson't know, Master Poorgrass.' On hearing these and other similar remarks, a wild thought flashed into Gabriel's mind that they might be speaking of Bathsheba. There were, however, no ground for retaining such a supposition, for the waggon, though going in the direction of Weatherbury, might be going beyond it, and the woman alluded to seemed to be the mistress of some estate. They were now apparently close upon Weatherbury and not to alarm the speakers unnecessarily, Gabriel slipped out of the waggon unseen. He turned to an opening in the hedge, which he found to be a gate, and mounting thereon, he sat meditating whether to seek a cheap lodging in the village, or to ensure a cheaper one by lying under some hay or corn-stack. The crunching jangle of the waggon died upon his ear. He was about to walk on, when he noticed on his left hand an unusual light -- + appearing about half a mile distant. Oak watched it, and the glow increased. Something was on fire. Gabriel again mounted the gate, and, leaping down on the other side upon what he found to be ploughed soil, made across the field in the exact direction of the fire. The blaze, enlarging in a double ratio by his approach and its own increase, showed him as he drew nearer the outlines of ricks beside it, lighted up to great distinctness. A rick-yard was the source of the fire. His weary face now began to be painted over with a rich orange glow, and the whole front of his smock+ frock and gaiters was covered with a dancing shadow pattern of thorn-twigs -- the light reaching him through a leafless intervening hedge -- and the metallic curve of his sheep-crook shone silver-bright in the same abound+ ing rays. He came up to the boundary fence, and stood to regain breath. It seemed as if the spot was unocupied by a living soul. The fire was issuing from a long straw-stack, which was so

far gone as to preclude a possibility of saving it. A rick burns differently from a house. As the wind blows the fire inwards, the portion in flames completely disappears like melting sugar, and the outline is lost to the eye. However, a hay or a wheat-rick, well put together, will resist combustion for a length of time, if it begins on the outside. This before Gabriel's eyes was a- rick of straw, loosely put together, and the flames darted into it with lightning swiftness. It glowed on the windward side, rising and falling in intensity, like the coal of a cigar. Then a superincumbent bundle rolled down, with a whisking noise ; flames elongated, and bent themselves about with a quiet roar, but no crackle. Banks of smoke went off horizontally at the back like passing clouds, and behind these burned hidden pyres, illuminating the semi-transparent sheet of smoke to a lustrous yellow uniformity. Individual straws in the foreground were consumed in a creeping movement of ruddy heat, as if they were knots of red worms, and above shone imaginary fiery faces, tongues hanging from lips, glaring eyes, and other impish forms, from which at intervals sparks flew in clusters like birds from a nest, Oak suddenly ceased from being a mere spectator by discovering the case to be more serious than he had at first imagined. A scroll of smoke blew aside and revealed to him a wheat-rick in startling juxtaposition with the decaying one, and behind this a series of others, composing the main corn produce of the farm; so that instead of the straw-stack standing, as he had imagined comparatively isolated, there was a regular connection between it and the remaining stacks of the group. Gabriel leapt over the hedge, and saw that he was not alone. The first man he came to was running about in a great hurry, as if his thoughts were several yards in advance of his body, which they could never drag on fast enough. 'O, man -- fire, fire ! A good master and a. bad servant is fire, fire .! -- I mane a bad servant and a good master O, Mark Clark -- come !- And you, Billy Smallbury -- and you, Maryann Money -- and you, Jan Coggan, and Matthew there!' Other figures now appeared behind this shouting man and among the smoke, and

Gabriel found that, far from being alone he was in a great company -- whose shadows danced merrily up and down, timed by the jigging of the flames, and not at all by their owners' movements. The assemblage -- -belonging to that class of society which casts its thoughts into the form of feeling, and its feelings into the form of commotion -- set to work with a remarkable confusion of purpose. 'Stop the draught under the wheat-rick!' cried Gabriel to those nearest to him. The corn stood on stone staddles, and between these, tongues of yellow hue from the burning straw licked and darted playfully. If the fire once got under this stack, all would be lost. 'Get a tarpaulin -- quick .! ' said Gabriel. A rick-cloth was brought, and they hung it like a curtain across the channel. The flames immediately ceased to go under the bottom of the corn-stack, and stood up vertical. 'Stand here with a bucket of water and keep the cloth wet,' said Gabriel again. The flames, now driven upwards, began to attack the angles of the huge roof covering the wheat-stack. 'A ladder,' cried Gabriel. 'The ladder was against the straw-rick and is burnt to a cinder,' said a spectre-like form in the smoke. Oak seized the cut ends of the sheaves, as if he were going to engage in the operation of ' reed-drawing,' and digging in his feet, and occasionally sticking in the stem of his sheep-crook, he clambered up the beetling face. He at once sat astride the very apex, and began with his crook to beat off the fiery fragments which had lodged thereon, shouting to the others to get him a bough and a ladder, and some water. Billy Smallbury -- one of the men who had been on the waggon -- by this time had found a ladder, which Mark Clark ascended, holding on beside Oak upon the thatch. The smoke at this corner was stifling, and Clark, a nimble fellow, having been handed a bucket of water, bathed Oak's face and sprinkled him generally, whilst Gabriel, now with a long beech-bough in one hand, in addition to his crook in the other, kept sweeping the stack and dislodging all fiery particles.

On the ground the groups of villagers were still occupied in doing all they could to keep down the conflagration, which was not much. They were all tinged orange, and backed up by shadows of varying pattern. Round the corner of the largest stack, out of the direct rays of the fire, stood a pony, bearing a young woman on its back. By her side was another woman, on foot. These two seemed to keep at a distance from the fire, that the horse might not beome restive. 'He's a shepherd,' said the woman on foot. 'Yes -- he is. See how his crook shines as he beats the rick with it. And his smock-frock is burnt in two holes, I declare.! A fine young shepherd he is too, ma'am.' ' Whose shepherd is he?' said the equestrian in a clear voice. 'Don't know, ma'am.' " Don't any of the others know ?' " Nobody at all -- I've asked 'em. Quite a stranger, they say.' The young woman on the pony rode out from the shade and looked anxiously around. "Do you think the barn is safe ?" she said. "D'ye think the barn is safe, Jan Coggan ?' said the second woman, passing on the question to the nearest man in that direction. "Safe -now -- leastwise I think so. If this rick had gone the barn would have followed. 'Tis- that bold shepherd up there that have done the most good -- he sitting on the top o' rick, whizzing his great long-arms about like a windmill.' " He does work hard,' said the young woman on horseback, looking up at Gabriel through her thick woollen veil. "I wish he was shepherd here. Don't any of you know his name.' "Never heard the man's name in my life, or seed his form afore.' The fire began to get worsted, and Gabriel's elevated position being no longer required of him, he made as if to descend. "Maryann,' said the girl on horseback, "go to him as he comes down, and say that the farmer wishes to thank him for the great service he has done.' Maryann stalked off towards the rick and met Oak at the foot of the ladder. She delivered ber message.

" Where is your master the farmer ?' asked Gabriel, kindling with the idea of getting employment that seemed to strike him now. " 'Tisn't a master ; 'tis a mistress, shepherd.' " A woman farmer ? ' "Ay, 'a b'lieve, and a rich one too .!' said a by" stander. " Lately 'a came here from a distance. Took on her uncle's farm, who died suddenly. Used to measure his money in half-pint cups. They say now that she've business in every bank in Casterbridge, and thinks no more of playing pitch-and-toss sovereign than you and I, do pitch-halfpenny -- not a bit in the world, shepherd.' "That's she, back there upon the pony,' said Mary+ ann ;"wi'her face a-covered up in that black cloth with holes in it.' Oak, his features smudged, grimy, and undiscoverable from the smoke and heat, his smock-frock burnt-into holes and dripping with water, the ash stem of his sheep+ crook charred six inches shorter, advansed with the humility stern adversity had thrust upon him up to the slight female form in the saddle. He lifted his hat with respect, and not without galantry: stepping close to her hanging feet he said in a hesitating voice, -- " Do you happen to want a shepherd, ma'am ? ' She lifted the wool veil tied round her face, and looked all astonishment. Gabriel and his cold-hearted darling, Bathsheba Everdene, were face to face. Bathsheba did not speak, and he mechanically repeated in an abashed and sad voice, -- " Do you want a shepherd, ma'am ? '

RECOGNITION -- A TIMID GIRL BATHSHEBA withdrew into the shade. She scarcely knew whether most to be amused at the singularity of the meeting, or to be concerned at its awkwardness. There was room for a little pity, also for a very little exultation : the former at his position, the latter at her own. Embarrassed she was not, and she" remembered Gabriel's declaration of love to her at Norcombe only to think she had nearly forgotten it. " Yes,' she murmured, putting on an air of dignity, and turning again to him with a little warmth of cheek ; " I do want a shepherd. But -- -- ' " He's the very man, ma'am,' said one of the villagers, quietly. Conviction breeds conviction. " Ay, that 'a is,' said a second, decisively. "The man, truly .! ' said a third, with heartiness." " He's all there ! ' said number four, fervidly." Then will you tell him to speak to the bailiff, said Bathsheba. All "was practical again now. A summer eve and loneliness would have been necessary to give the meeting its proper fulness of romance. the palpitation within his breast at discovering that this Ashtoreth of strange report was only a modification of Venus the well-known and admired, retired with him to talk over the necessary preliminaries of hiring. The fire before them wasted away. "Men,' said Bathsheba, " you shall take a little refreshment after this extra work. Will you come to the house ?' "We could knock in a bit and a drop a good deal freer, Miss,

if so be ye'd send it to Warren's Malthouse,' replied the spokesman. Bathsheba then rode off into the darkness, and the men straggled on to the village in twos and threes -- Oak and the bailiff being left by the rick alone. "And now,' said the bailiff, finally, "all is settled, I think, about your coming, and I am going home-along. Good-night to ye, shepherd.' " Can you get me a lodging ? ' inquired Gabriel. 'That I can't, indeed," he said, moving past Oak as a Christian edges past an offertory-plate when he does not mean to contribute. "If you follow on the road till you come to Warren's Malthouse, where they are all gone to have their snap of victuals, I daresay some of 'em will tell you of a place. Good-night to ye, shepherd.' The bailiff who showed this nervous dread of loving his neighbour as himself, went up the hill, and Oak walked on to the village, still astonished at the ren+ counter with Bathsheba, glad of his nearness to her, and perplexed at the rapidity with which the unpractised girl of Norcombe had developed into the supervising and cool woman here. But some women only require an emerg+ ency to make them fit for one. Obligcd, to some extent, to forgo dreaming in order to find the way, he reachcd the churchyard, and passed round it under the wall where several ancient trees grew. There was a wide margin of grass along here, and Gabriel's footsteps were deadened by its softness, even at this indurating period of the year. When abreast of a trunk which appeared to be the oldest of the old, he became aware that a figure was standing behind it. Gabriel did not pause in his walk, and in another moment he accidentally kicked a loose stone. The noise was enough to disturb the motionless stranger, who started and assumed a careless position. It was a slim girl, rather thinly clad. " Good-night to you,' said Gabriel, heartily. " Good-night,' said the girl to Gabriel. The voice was unexpectedly attractive ; it was "the low and

dulcet note suggestive of romance ; common in descriptions, rare in experience. 'I'll thank you to tell me if I'm in the way for Warren's Malthouse ? ' Gabriel resumed, primarily to gain the information, indirectly to get more of the music. "Quite right. It's at the bottom of the hill. And do you know -- -- ' The girl hesitated and then went on again. "Do you know how late they keep open the Buck's Head Inn?' She seemed" to be won by Gabriel's heartiness, as Gabriel had been won by her modulations. " I don't know where the Buck's Head is, or anything about it. Do you think of going there to-night ?' " Yes -- -- ' The woman again paused. There was no necessity for any continuance of speech, and the fact that she did add more seemed to proceed from an unconscious desire to show unconcern by making a remark, which is noticeable in the ingenuous when they are acting by stealth. " You are not a Weatherbury man ? ' she said, timorously. ' I am not. I am the new shepherd -- just arrived.' "Only a shepherd -- and you seem almost a farmer by your ways.' " Only a shepherd,' Gabriel repeated, in a dull cadence of finality. " His thoughts were directed to the past, his eyes to the feet of the girl; and for the first time he saw lying there a bundle of some sort. She may have perceived the direction of his face, for she said coaxingly, -- " You won't say anything in the parish about having seen me here, will you -- at least, not for a day or two ?' "I won't if you wish me not to,' said Oak. "Thank you, indeed,' the other replied.'I am rather poor, and I don't want people to know anything about me.' Then she was silent and shivered. 'You ought to have a cloak on such a cold night,' Gabriel observed. " I would advise 'ee to get indoors." "O no! Would you mind going on and leaving me ? I thank you much for what you have told me.' " I will go on,' he said ; adding hesitatingly, -- ' Since you are

not very well off, perhaps you would accept this trifle from me. It is only a shilling, but'it is all I have to spare.' ' Yes, I will take it,' said the stranger, gratefully. She extended her hand ; Gabriel his. In feeling for each other's palm in the gloom before the money could be passed, a minute incident occurred which told much. Gabriel's fingers alighted on the young woman's wrist. It was beating with a throb of tragic intensity. He had frequently felt the same quick, hard beat in the femoral artery of -- his lambs when overdriven. It suggested a consumption too great of a vitality which, to judge from her figure and stature, was already too little. "What is the matter ?' " Nothing.' 'But there is?' " No, no, no ! Let your having seen me be a.secret .! " ' Very well ; I will. Good-night, again.' " Good-night.' The young girl remained motionless by the tree, and Gabriel descended into the village of Weatherbury, or Lower Longpuddle as it was sometimes called. He fancied that he had felt himself in the penumbra of a very deep sadness when touching that slight and fragile creature. But wisdom lies in moderating mere impres+ sions, and Gabriel endeavoured to think little of this.

THE MALTHOUSE -- THE CHAT -- NEWS WARREN'S Malthouse was enclosed by an old wall inwrapped with ivy, and though not much of the exterior was visible at this hour, the character and purposes of the building were clearly enough shown by its outline upon the sky. From the walls an overhanging thatched roof sloped up to a point in the centre, upon which rose a small wooden lantern, fitted with louvre-boards on all the four sides, and from these openings a mist was dimly perceived to be escaping into the night air. There was no window in front ; but a square hole in the door was glazed with a single pane, through which red, comfortable rays now stretched out upon the ivied wall in front. Voices were to be heard inside. Oak's hand skimmed the surface of the door with fingers extended to an Elymas-the-Somerer pattern, till he found a leathern strap, which he pulled. This lifted a wooden latch, and the door swung open. The room inside was lighted only by the, ruddy glow from the kiln mouth, which shone over ,the floor with the streaming, horizontality of the setting sun, and threw upwards the shadows of all facial irregularities in those assembled around. The stone-flag floor was worn into a path from the doorway to the kiln, and into undula+ tions everywhere. A curved settle of unplaned oak stretched along one side, and in a remote corner was a small bed and bedstead, the owner and frequent occupier of which was the maltster. This aged man was now sitting opposite the fire, his frosty white hair and beard overgrowing his gnarled figure like the grey moss and lichen upon a leafless apple-tree. He wore breeches and the laced-up shoes called ankle-jacks; he kept his eyes fixed upon the fire.

Gabriel's nose was greeted by an atmosphere laden with the sweet smell of new malt. The conversation (which seemed to have been concerning the origin of the fire) immediately ceased, and every one ocularly criticised him to the degree expressed by contracting the flesh of their foreheads and looking at him with narrowed eye+ lids, as if he had been a light too strong for their sight. Several exclaimed meditatively, after this operation had been completed : -- "Oh, 'tis the new shepherd, 'a b'lieve.' "We thought we heard a hand pawing about the door for the bobbin, but weren't sure 'twere not a dead leaf blowed across,' said another. " Come in, shepherd ; sure ye be welcome, though we don't know yer name.' " Gabriel Oak, that's my name, neighbours.' The ancient maltster sitting in the midst turned up this -- his turning being as the turning of a rusty crane. "That's never Gable Oak's grandson over at Nor+ combe -- never !. ' he said, as a formula expressive of surprise, which nobody was supposed to take literally'. 'My father and my grandfather were old men of the name of Gabriel,' said the shepherd, placidly. "Thought I knowed the man's face as I seed him on the rick ! -- thought I did.! And where be ye trading o't to now, shepherd ? ' " I'm thinking of biding here,' said Mr. Oak. "Knowed yer grandfather for years and years !' continued the maltster, the words coming forth of their own accord as if the momentum previously imparted had been sufficient. 'Ah -- and did you! ' " Knowed yer grandmother.' 'And her too!' "Likewise knowed yer father when he was a child. Why, my boy Jacob there and your father were sworn brothers -- that they were sure -- weren't ye, Jacob ? ' "Ay, sure,' said his son, a young man about sixty+ five, with a semi-bald head and one tooth in the left centre of his upper jaw, which made much of itself by standing prominent, like a

milestone in a bank. 'But 'twas Joe had most to do with him. However, my son William must have knowed the very man afore us -- didn't ye, Billy, afore ye left Norcombe ? ' "No, 'twas Andrew,' said Jacob's son Billy, a child of forty, or thereabouts, who manifested the peculiarity of possessing a cheerful soul in a gloomy body, and whose whiskers were assuming a chinchilla shade here and there. "I can mind Andrew,' said Oak, 'as being a man in the place when I was quite a child.' "Ay -- the other day I and my youngest daughter, Liddy, were over at my grandson's christening,' continued Billy. ' We were talking about this very family, and 'twas only last Purification Day in this very world, when the use-money is gied away to the second-best poor folk, you know, shepherd, and I can mind the day because they all had to traypse up to the vestry -- yes, this very man's family.' ' Come, shepherd, and drink. 'Tis gape and swaller with us -- a drap of sommit, but not of much account,' said the maltster, removing from the fire his eyes, which were vermilion-red and bleared by gazing into it for so many years. "Take up the God-forgive" me, Jacob. See if 'tis warm, Jacoh.' Jacob stooped to the God-forgive-me, which was a two-handled tall mug standing in the ashes, cracked and charred with heat : it was rather furred with ex" traneous matter about the outside, especially in the crevices of the handles, the innermost curves of which may not have seen daylight for several years by reason of this encrustation thereon -- formed of ashes accident+ ally wetted with cider and baked hard; but to the mind of any sensible drinker the cup was no worse for that, being incontestably clean on the inside and about the rim. It may be observed that such a class of mug is called a God-forgive-me in Weatherbury and its vicinity for uncertain reasons ; probably because its size makes any given toper feel ashamed of himself when he sees its bottom in drinking it empty. Jacob, on receiving the order to see if the liquor was warm enough, placidly dipped his forefinger into it by way of thermometer, and having pronounced it nearly of the proper degree, raised the cup and very civilly attempted to dust some of the

ashes from the bottom with the skirt of his smock-frock, because Shepherd Oak was a stranger. "A clane cup for the shepherd,' said the maltster commandingly. "No -- not at all," said Gabriel, in a reproving tone of considerateness. "I never fuss about dirt in its pure state, and when I know what sort it is.' Taking the mug he drank an inch or more from the depth of its contents, and duly passed it to the next man. wouldn't think of giving such trouble to neighbours in washing up when there's so much work to be done in the world already,' continued Oak in a moister tone, after recovering from the stoppage of breath which is occasioned by pulls at large mugs. ' A right sensible man,' said Jacob. " True, true ; it can't be gainsaid!.' observed a brisk young man -- Mark Clark by name, a genial and pleasant gentleman, whom to meet anywhcre in your travels was to know, to know was to drink with, and to drink with was, unfortunately, to pay for. "And here's a mouthful of bread and bacon that mis'ess have sent, shepherd. The cider will go down better with a bit of victuals. Don't ye chaw quite close, shepherd, for I let the bacon fall in the road outside as I was bringing it along, and may be 'tis rather gritty. There, 'tis clane dirt; and we all know what that is, as you say, and you bain't a particular man we see, shepherd.' " True, true -- not at all,' said the friendly Oak. 'Don't let your teeth quite meet, and you won't feel the sandiness at all. Ah !. 'tis wonderful what can be done by contrivance .! ' " My own mind exactly, neighbour.' " Ah, he's his grandfer's own grandson .! -- his grandfer were just such a nice unparticular man !.' said the maltster. " Drink, Henry Fray -- drink,' magnanimously said Jan Coggan, a person who held Saint-Simonian notions of share and share alike where liquor was concerned, as the vessel showed signs of approaching him in its gradual revolution among them. Having at this moment reached the end of a wistful gaze

into mid-air, Henry did not refuse. He was a man of more than middle age, with eyebrows high up in his forehead, who laid it down that the law of the world was bad, with a long-suffering look through his listeners at the world alluded to, as it presented itself to his imagination. He always signed his name 'Henery' -- strenuously insisting upon that spelling, and if any passing schoolmaster ventured to remark that the second 'e' was superfluous and old-fashioned, he received the reply that ' H-e-n-e-r-y' was the name he was christened and the name he 'would stick to -- in the tone of one to whom orthographical differences were matters which had a great deal to do with personal character. Mr. Jan Coggan, who had passed the cup to Henery, was a crimson man with a spacious countenance, and private glimmer in his eye, whose name had appeared on the marriage register of Weatherbury and neighbour+ ing parishes as best man and chief witness in countless unions of the previous twenty years; he also very frequently filled the post of head godfather in baptisms of the subtly-jovial kind. " Come, Mark Clark -- come. Ther's plenty more in the barrel,' said Jan. "Ay -- that I will; 'tis my only doctor,' replied Mr. Clark, who, twenty years younger than Jan Coggan, revolved in the same orbit. He secreted mirth on all occasions for special discharge at popular parties. " Why, Joseph Poorgrass, ye han't had a drop! ' said Mr. Coggan to a self-conscious man in the background, thrusting the cup towards him. " Such a modest man as he is !. ' said Jacob Smallbury. " Why, ye've hardly had strength of eye enough to look in our young mis'ess's face, so I hear, Joseph ?' All looked at Joseph Poorgrass with pitying reproach. " No -- I've hardly looked at her at all,' simpered Joseph, reducing his body smaller whilst talking, apparently from a meek sense of undue prominence. "And when I seed her, 'twas nothing but blushes with me!' ' Poor feller,' said Mr. Clark. "'Tis a curious nature for a man,' said Jan Coggan.

" Yes,' continued Jdseph Poorgrass -- his shyness, which was so painful as a defect, filling him with a mild complacency now that it was regarded as an interesting study. " 'Twere blush, blush, blush with me every minute of the time, when she was speaking to me.' "I believe ye, Joseph Poorgrass, for we all know ye to be a very bashful man.' "'Tis a' awkward gift for a man, poor soul,' said the maltster. "And ye have suffered from it a long time, we know.' "Ay ever since I was a boy. Yes -- mother was concerned to her heart about it -- yes. But twas all nought.' "Did ye ever go into the world to try and stop it, Joseph Poorgrass ? ' "Oh ay, tried all sorts o' company. They took me to Greenhill Fair, and into a great gay jerry-go-nimble show, where there were women-folk riding round -- standing upon horses, with hardly anything on but their smocks; but it didn't cure me a morsel. And then I was put errand-man at the Women's Skittle Alley at the back of the Tailor's Arms in Casterbridge. 'Twas a horrible sinful situation, and a very curious place for a good man. I had to stand and look ba'dy people in the face from morning till night; but 'twas no use -- I was just as-bad as ever after all. Blushes hev been in the family for generations. There, 'tis a happy pro+ vidence that I be no worse.' " True,' said Jacob Smallbury, deepening his thoughts to a profounder view of the subject. "'Tis a thought to look at, that ye might have been worse; but even as you be, 'tis a very bad affliction for 'ee, Joseph. For ye see, shepherd, though 'tis very well for a woman, dang it all, 'tis awkward for a man like him, poor feller ? ' " 'Tis -- 'tis,' said Gabriel, recovering from a medita+ tion. " Yes, very awkward for the man.' " Ay, and he's very timid, too,' observed Jan Coggan. "Once he had been working late at Yalbury Bottom, and had had a drap of drink, and lost his way as he was coming home-along through Yalbury Wood, didn't ye, Master Poorgrass ? ' " No, no, no ; not that story !' expostulated the modest man, forcing a laugh to bury his concern.

" -- -- And so 'a lost himself quite,' continued Mr Coggan, with an impassive face, implying that a true narrative, like time and tide, must run its course and would respect no man. "And as he was coming along in the middle of the night, much afeared, and not able to find his way out of the trees nohow, 'a cried out, " Man-a-lost!. man-a-lost !." A owl in a tree happened to be crying "Whoo-whoo-whoo !" as owls do, you know, shepherd ' (Gabriel nodded), " and Joseph, all in a tremble, said, " Joseph Poorgrass, of Weatherbury, sir.!" "No, no, now -- that's too much! ' said the timid man, becoming a man of brazen courage all of a sudden. "I didn't say sir. I'll tike my oath I didn't say " Joseph Poorgrass o' Weatherbury, sir." No, no ; what's right is right, and I never said sir to the bird, knowing very well that no man of a gentleman's rank would be hollering there at that time o' night. " Joseph Poor+ grass of Weatherbury," -- that's every word I said, and I shouldn't ha' said that if 't hadn't been for Keeper Day's metheglin.... There, 'twas a merciful thing it ended where it did.' The question of which was right being tacitly waived by the company, Jan went on meditatively : -- "And he's the fearfullest man, bain't ye, Joseph? Ay, another time ye were lost by Lambing-Down Gate, weren't ye, Joseph ? ' "I was,' replied Poorgrass, as if there were some conditions too serious even for modesty to remember itself under, this being one. ' Yes ; that were the middle of the night, too. The gate would not open, try how he would, and knowing there was the Devil's hand in it, he kneeled down.' 'Ay,' said Joseph, acquiring confidence from the warmth of the fire, the cider, and a perception of the narrative capabilities of the experience alluded to. " My heart died within me, that time; but I kneeled down and said the Lord's Prayer, and then the Belie THE CHAT right through, and then the Ten Commandments, in earnest prayer. But no, the gate wouldn't open; and then I went on with Dearly Beloved Brethren, and, thinks I, this makes four, and 'tis all I know out of book, and if this don't do it nothing will, and I'm a lost man. Well, when I got to

Saying After Me, I rose from my knees and found the gate would open -- yes, neighbours, the gate opened the same as ever.' A meditation on the obvious inference wsas indulged in by all, and during its continuance each directed his vision into the ashpit, which glowed like a desert in the tropics under a vertical sun, shaping their eyes long and liny, partly because of the light, partly from the depth of the subject discussed. Gabriel broke the silence. "What sort of a place is this to live at, and what sort of a mis'ess is she to work under?' Gabriel's bosom thrilled gently as he thus slipped under the notice of the assembly the inner+ most subject of his heart. "We d' know little of her -- nothing. She only showed herself a few days ago. Her uncle was took bad, and the doctor was called with his world-wide skill; but he couldn't save the man. As I take it, she's going to keep on the farm. "That's abouyt the shape o't, 'a b'lieve,' said Jan uncle was a very fair sort of man. Did ye know en, be under 'em as under one here and there. Her uncle was a very fair sort of man. Did ye know 'en, shepherd -- a bachelor-man ? ' "Not at all.' "I used to go to his house a-courting my first wife, Charlotte, who was his dairymaid. Well, a very good+ hearted man were Farmer Everdene, and I being a respectable young fellow was allowed to call and see her and drink as much ale as I liked, but not to carry away any -- outside my skin I mane of course.' "Ay, ay, Jan Coggan; we know yer maning.' "And so you see 'twas beautiful ale, and I wished to value his kindness as much as I could, and not to be so ill-mannered as to drink only a thimbleful, which would have been insulting the man's generosity -- -- ' "True, Master Coggan, 'twould so,' corroborated Mark Clark. " -- -- And so I used to eat a lot of salt fish afore going, and then by the time I got there I were as dry as a lime-basket -- so thorough dry that that ale would slip down -- ah, 'twould slip down sweet! Happy times! heavenly times! Such lovely drunks as I used to have at that house! You can mind, Jacob? You used to go wi' me sometimes.'

"I can -- I can,' said Jacob. "That one, too, that we had at Buck's Head on a White Monday was a pretty tipple.' "'Twas. But for a wet of the better class, that brought you no nearer to the horned man than you were afore you begun, there was none like those in Farmer Everdene's kitchen. Not a single damn allowed; no, not a bare poor one, even at the most cheerful moment when all were blindest, though the good old word of sin thrown in here and there at such times is a great relief to a merry soul.' "True,' said the maltster. "Nater requires her swearing at the regular times, or she's not herself; and unholy exclamations is a necessity of life.' "But Charlotte,' continued Coggan -- "not a word of the sort would Charlotte allow, nor the smallest item of taking in vain.... Ay, poor Charlotte, I wonder if she had the good fortune to get into Heaven when 'a died!. But 'a was never much in luck's way, and perhaps 'a went downwards after all, poor soul.' "And did any of you know Miss Everdene's-father and mother?' inquired the shepherd, who found some difficulty in keeping the conversation in the desired channel. THE CHAT "I knew them a little,' said Jacob Smallbury; "but they were townsfolk, and didn't live here. They've been dead for years. Father, what sort of people were mis'ess' father and mother?' "Well,' said the maltster, "he wasn't much to look at; but she was a lovely woman. He was fond enough of her as his sweetheart.' "Used to kiss her scores and long-hundreds o times, so 'twas said,' observed Coggan. "He was very proud of her, too, when they were married, as I've been told,' said the maltster. "Ay,' said Coggan. "He admired her so much that he used to light the candle three time a night to look at her.' "Boundless love; I shouldn't have supposed it in the universe!' murmered Joseph Poorgrass, who habitually spoke on a large scale in his moral reflections. "Well, to be sure,' said Gabriel. "Oh, 'tis true enough. I knowed the man and woman both well. Levi Everdene -- that was the man's name, sure. ""Man,''

saith I in my hurry, but he were of a higher circle of life than that -- 'a was a gentleman+ tailor really, worth scores of pounds. And he became a very celebrated bankrupt two or three times.' "Oh, I thought he was quite a common man!.' said Joseph. "O no, no! That man failed for heaps of money; hundreds in gold and silver.' The maltster being rather short of breath, Mr. Coggan, after absently scrutinising a coal which had fallen among the ashes, took up the narrative, with a private twirl of his eye: -- "Well, now, you'd hardly believe it, but that man -- husbands alive, after a while. Understand' 'a didn't want to be fickle, but he couldn't help it. The poor feller were faithful and true enough to her in his wish, but his heart would rove, do what he would. He spoke to me in real tribulation about it once. ""Coggan,'' he said, ""I could never wish for a handsomer woman than I've got, but feeling she's ticketed as my lawful wife, I can't help my wicked heart wandering, do what I will.'' But at last I believe he cured it by making her take off her wedding-ring and calling her by her maiden name as they sat together after the shop was shut, and so 'a would get to fancy she was only his sweetheart, and not married to him at all. And as soon as he could thoroughly fancy he was doing wrong and committing the seventh, 'a got to like her as well as ever, and they lived on a perfect picture of mutel love.' "Well, 'twas a most ungodly remedy,' murmured Joseph Poorgrass; "but we ought to feel deep cheerful+ ness that a 'happy Providence kept it from being any worse. You see, he might have gone the bad road and given his eyes to unlawfulness entirely -- yes, gross un+ lawfulness, so to say it.' "You see,' said Billy Smallbury, "The man's will was to do right, sure enough, but his heart didn't chime in.' "He got so much better, that he was quite godly in his later years, wasn't he, Jan ?' said Joseph Poor+ grass. "He got himself confirmed over again in a more serious way, and took to saying ""Amen'' almost as loud as the clerk, and he liked to copy comforting verses from the tombstones. He used, too, to hold the money+ plate at Let Your Light so Shine, and stand

godfather to poor little come-by-chance children; and he kept a missionary' box upon his table to nab folks unawares when they called; yes, and he would-box the charity+ boys' ears, if they laughed in church, till they could hardly stand upright, and do other deeds of piety natural to the saintly inclined.' "Ay, at that time he thought of nothing but high things,' added Billy Smallbury. "One day Parson Thirdly met him and said, ""Good-Morning, Mister Everdene; 'tis THE CHAT a fine day!'' ""Amen'' said Everdene, quite absent+ like, thinking only of religion when he seed a parson+ "Their daughter was not at all a pretty chiel at that time,' said Henery Fray. "Never should have. thought she'd have growed up such a handsome body as she is.' "'Tis to be hoped her temper is as good as her face.' "Well, yes; but the baily will have most to do with the business and ourselves. Ah!' Henery gazed into the ashpit, and smiled volumes of ironical knowledge. "A queer Christian, like the Devil's head in a cowl, "He is,' said Henery, implying that irony must cease at a certain point. "Between we two, man and man, I believe that man would as soon tell a lie Sundays as working-days -- that I do so.' "Good faith, you do talk!' said Gabriel. "True enough,' said the man of bitter moods, looking round upon the company with the antithetic laughter that comes from a keener appreciation of the miseries of life than ordinary men are capable of. 'Ah, there's people of one sort, and people of another, but that man -- bless your souls!' Gabriel thought fit to change the subject. "You must be a very aged man, malter, to have sons growed mild and ancient' he remarked. "Father's so old that 'a can't mind his age, can ye, father?' interposed Jacob. "And he growled terrible crooked too, lately' Jacob continued, surveying his father's figure, which

was rather more bowed than his own. "Really one may say that father there is three-double.' "Crooked folk will last a long while,' said the maltster, grimly, and not in the best humour. "Shepherd would like to hear the pedigree of yer life, father -- wouldn't ye, shepherd ? "Ay that I should,' said Gabriel with the heartiness of a man who had longed to hear it for several months. "What may your age be, malter?' The maltster cleared his throat in an exaggerated form for emphasis, and elongating his gaze to the remotest point of the ashpit! said, in the slow speech justifiable when the importance of a subject is so generally felt that any mannerism must be tolerated in getting at it, "Well, I don't mind the year I were born in, but perhaps I can reckon up the places I've lived at, and so get it that way. I bode at Upper Long+ puddle across there' (nodding to the north) "till I were eleven. I bode seven at Kingsbere' (nodding to the east) "where I took to malting. I went therefrom to Norcombe, and malted there two-and-twenty years, and+ two-and-twenty years I was there turnip-hoeing and harvesting. Ah, I knowed that old place, Norcombe, years afore you were thought of, Master Oak' (Oak smiled sincere belief in the fact). "Then I malted at Dur+ nover four year, and four year turnip-hoeing; and I was fourteen times eleven months at Millpond St. Jude's ' (nodding north-west-by-north). "Old Twills wouldn't hire me for more than eleven months at a time, to keep me from being chargeable to the parish if so be I was disabled. Then I was three year at Mellstock, and I've been here one-and-thirty year come Candlemas. How much is that?" "Hundred and seventeen,' chuckled another old gentleman, given to mental arithmetic and little con+ versation, who had hitherto sat unobserved in a corner. "Well, then, that's my age,' said the maltster, em+ phatically. "O no, father!' said Jacob. "Your turnip-hoeing were in the summer and your malting in the winter of the same years, and ye don't ought to count-both halves father.'

"Chok' it all! I lived through the summers, didn't I? That's my question. I suppose ye'll say next I be no age at all to speak of?' "Sure we shan't,' said Gabriel, soothingly. "Ye be a very old aged person, malter,' attested Jan must have a wonderful talented constitution to be able to live so long, mustn't he, neighbours?' "True, true; ye must, malter, wonderful;' said the meeting unanimously. The maltster, being know pacified, was even generous enough to voluntarily disparage in a slight degree the virtue of having lived a great many years, by mentioning that the cup they were drinking out of was three years older than he. While the cup was being examined, the end of Gabriel Oak's flute became visible over his smock-frock I seed you blowing into a great flute by now at Caster+ bridge?' "You did,' said Gabriel, blushingh faintly. "I've been in great trouble, neighbours, and was driven to it. take it careless-like, shepherd and your time will come tired?' "Neither drum nor trumpet have I heard since Christmas,' said Jan Coggan. "Come, raise a tune, Master Oak!' "That I will,' said Gabriel, pulling out his flute and putting it together. "A poor tool, neighbours; but such as I can do ye shall have and welcome.' Oak then struck up "Jockey to the Fair,' and played that sparkling melody three times through accenting the notes in the third round in a most artistic and lively manner by bending his body in small jerks and tapping with his foot to beat time. "He can blow the flute very well -- that 'a can,' said a young married man, who having no individuality worth mentioning was known as "Susan Tall's husband.' He continued, "I'd as lief as not be able to blow into a flute as well-as that.'

"He's a clever man, and 'tis a true comfort for us to have such a shepherd,' murmured Joseph Poorgrass, in a soft cadence. "We ought to feel full o' thanksgiving that he's not a player of ba'dy songs 'instead of these merry tunes; for 'twould have been just as easy for God to have made the shepherd a loose low man -- a man of iniquity, so to speak it -- as what he is. Yes, for our wives' and daughters' sakes we should feel real thanks giving.' "True, true, -- real thanksgiving!' dashed in Mark Clark conclusively, not feeling it to be of any conse+ quence to his opinion that he had only heard about a word and three-quarters of what Joseph had said. "Yes,' added Joseph, beginning to feel like a man in the Bible; "for evil do thrive so in these times that ye may be as much deceived in the clanest shaved and whitest shirted man as in the raggedest tramp upon the turnpike, if I may term it so.' "Ay, I can mind yer face now, shepherd,' said Henery Fray, criticising Gabriel with misty eyes as he entered upon his second tune. "Yes -- now I see 'ee blowing into the flute I know 'ee to be the same man I see play at Casterbridge, for yer mouth were scrimped up and yer eyes a-staring out like a strangled man's -- just as they be now.' "'Tis a pity that playing the flute should make a man look such a scarecrow,' observed Mr. Mark Clark, with additional criticism of Gabriel's countenance, the latter person jerking out, with the ghastly grimace required by the instrument, the chorus of "Dame Durden! "I hope you don't mind that young man's bad manners in naming your features?' whispered Joseph to Gabriel. "Not at all,' said Mr. Oak. "For by nature ye be a very handsome man, shepherd,' continued Joseph Poorgrass, with winning sauvity. "Ay, that ye be, shepard,' said the company. "Thank you very much,' said Oak, in the modest tone good

manners demanded, thinking, however, that he would never let Bathsheba see him playing the flute; in this severe showing s discretion equal to that related to its sagacious inventress, the divine Minerva herself. "Ah, when I and my wife were married at Norcombe Church,' said the old maltster, not pleased at finding himself left out of the subject "we were called the handsomest couple in the neighbourhood -- everybody said so.' "Danged if ye bain't altered now, malter,' said a voice with the vigour natural to the enunciation of a remark+ ably evident truism. It came from the old man in the background, whose offensiveness and spiteful ways were barely atoned for by the occasional chuckle he con+ tributed to general laughs. "O no, no,' said Gabriel. "Don't ye play no more shepherd ' said Susan Tall's husband, the young married man who had spoken once before. "I must be moving and when there's tunes going on I seem as if hung in wires. If I thought after I'd left that music was still playing, and I not there, I should be quite melancholy-like.' "What's yer hurry then, Laban?' inquired Coggan+ "You used to bide as late as the latest.' "Well, ye see, neighbours, I was lately married to a woman, and she's my vocation now, and so ye see -- -- ' The young man hated lamely. "New Lords new laws, as the saying is, I suppose,' remarked Coggan. "Ay, 'a b'lieve -- ha, ha!' said Susan Tall's husband, in a tone intended to imply his habitual reception of jokes without minding them at all. The young man then wished them good-night and withdrew. Henery Fray was the first to follow. Then Gabriel arose and went off with Jan Coggan, who had offered him a lodging. A few minutes later, when the remaining ones were on their legs and about to depart, Fray came back again in a hurry. Flourishing his finger ominously he threw a gaze teeming with tidings just -- where his eye alighted by accident, which happened to be in Joseph Poorgrass's face.

"O -- what's the matter, what's the matter, Henery?' said Joseph, starting back. "What's a-brewing, Henrey?' asked Jacob and Mark Clark. "Baily Pennyways -- Baily Pennyways -- I said so; yes, I said so!' "What, found out stealing anything?' "Stealing it is. The news is, that after Miss Everdene got home she went out again to see all was safe, as she usually do, and coming in found Baily Pennyways creeping down the granary steps with half a a bushel of barley. She fleed at him like a cat -- never such a tomboy as she is -- of course I speak with closed doors?' "You do -- you do, Henery.' "She fleed at him, and, to cut a long story short, he owned to having carried off five sack altogether, upon her promising not to persecute him. Well, he's turned out neck and crop, and my question is, who's going to be baily now?' The question was such a profound one that Henery was obliged to drink there and then from the large cup till the bottom was distinctly visible inside. Before he had replaced it on the table, in came the young man, Susan Tall's husband, in a still greater hurry. "Have ye heard the news that's all over parish?' "About Baily Pennyways?' "But besides that?' "No -- not a morsel of it!' they replied, looking into the very midst of Laban Tall as if to meet his words half-way down his throat. "What a night of horrors!' murmured Joseph Poor+ grass, waving his hands spasmodically. "I've had the news-bell ringing in my left ear quite bad enough for a murder, and I've seen a magpie all alone!' "Fanny Robin -- Miss everdene's youngest servant -- can't be found. They've been wanting to lock up the door these two hours, but she isn't come in. And they don't know what to do about going to hed for fear of locking her out. They wouldn't be so concerned if she hadn't been noticed in such low spirits

these last few days, and Maryann d'think the beginning of a crowner's inquest has happened to the poor girl.' "O -- 'tis burned -- 'tis burned!' came from Joseph Poorgrass's dry lips. "No -- 'tis drowned!' said 'Tall. "Or 'tis her father's razor!' suggested Billy Smallbury, with a vivid sense of detail. "Well -- Miss Everdene wants to speak to one or two of us before we go to bed. What with this trouble about the baily, and now about the girl, mis'ess is almost wild.' They all hastened up the lane to the farmhouse, excepting the old maltster, whom neither news, fire, rain, nor thunder could draw from his hole. There, as the others' footsteps died away he sat down again and continued gazing as usual into the furnace with his red, bleared eyes. From the bedroom window above their heads Bath+ sheba's head and shoulders, robed in mystic white, were dimly seen extended into the air. "Are any of my men among you?' she said anxiously. "Yes, ma'am, several,' said Susan Tall's husband. "Tomorrow morning I wish two or three of you to make inquiries in the villages round if they have seen such a person as Fanny Robin. Do it quietly; there is no reason for alarm as yet. She must have left whilst we were all at the fire.' "I beg yer pardon, but had she any young man court+ ing her in the parish, ma'am?" asked Jacob Smallbury. "I don't know,' said Bathsheba. "I've never heard of any such thing, ma'am,' said two or three. "It is hardly likely, either,' continued Bathsheba. "For any lover of hers might have come to the house if he had been a respectable lad. The most mysterious matter connected with her absence -- indeed, the only thing which gives me serious alarm -- is that she was seen to go out of the house by Maryann with only her indoor working gown on -- not even a bonnet.' "And you mean, ma'am, excusing my words, that a young

woman would hardly go to see her young man without dressing up,' said Jacob, turning his mental vision upon past experiences. "That's true -- she would not, ma'am.' "She had, I think, a bundle, though I couldn't see very well,' said a female voice from another window, which seemed that of Maryann. "But she had no young man about here. Hers lives in Casterbridge, and I believe he's a soldier.' "Do you know his name?' Bathsheba said. "No, mistress; she was very close about it.' "Perhaps I might be able to find out if I went to Casterbridge barracks,' said William Smallbury. "Very well; if she doesn't return tomorrow, mind you go there and try to discover which man it is, and see him. I feel more responsible than I should if she had had any friends or relations alive. I do hope she has come to no harm through a man of that kind.... And then there's this disgraceful affair of the bailiff -- but I can't speak of him now.' Bathsheba had so many reasons for uneasiness that it seemed she did not think it worth while to dwell upon any particular one. "Do as I told you, then' she said in conclusion, closing the casement. "Ay, ay, mistress; we will,' they replied, and moved away. That night at Coggan's, Gabriel Oak, beneath the screen of closed eyelids, was busy with fancies, and full of movement, like a river flowing rapidly under its ice. Night had always been the time at which he saw Bath+ sheba most vividly, and through the slow hours of shadow he tenderly regarded her image now. It is rarely that the pleasures of the imagination will compen+ sate for the pain of sleeplessness, but they possibly did with Oak to-night, for the delight of merely seeing her effaced for the time his perception of the great differ+ ence between seeing and possessing. He also thought of Plans for fetching his few utensils and books from Norcombe. The Young Man's Best Companion, The Farrier's Sure Guide, The Veterinary Surgeon, Paradise Lost, The Pilgrim's Progress, Robinson Crusoe, Ash's Dictionary, the Walkingame's Arithmetic, constituted his library;

and though a limited series, it was one from which he had acquired more sound informa+ tion by diligent perusal than many a man of opportunities has done from a furlong of laden shelves.

THE HOMESTEAD -- A VISITOR -- HALF-CONFIDENCES By daylight, the Bower of Oak's new-found mistress, Bathsheba Everdene, presented itself as a hoary build+ ing, of the early stage of Classic Renaissance as regards its architecture, and of 'a proportion which told at a glance that, as is so frequently the case, it had once been the memorial hall upon a small estate around it, now altogether effaced as a distinct property, and merged in the vast tract of a non-resident landlord, which com+ prised several such modest demesnes. Fluted pilasters, worked from the solid stone, decorated its front, and above the roof the chimneys were panelled or columnar, some coped gables with finials and like features still retaining traces of their Gothic extraction. Soft Brown mosses, like faded velveteen, formed cushions upon the stone tiling, and tufts of the houseleek or sengreen sprouted from the eaves of the low surrounding buildings. A gravel walk leading from the door to the road in front was encrusted at the sides with more moss -- here it was a silver-green variety, the nut-brown of the gravel being visible to the width of only a foot or two in the centre. This circum+ stance, and the generally sleepy air of the whole prospect here, together with the animated and contrasting state of the reverse facade, suggested to the imagination that on the adaptation of the building for farming purposes the vital principle' of the house had turned round inside its body to face the other way. Reversals of this kind, strange deformities, tremendous paralyses, are often seen to be inflicted by trade upon edifices -- either individual or in the aggregate as streets and towns -- which were originally planned for pleasure alone. Lively voices were heard this morning in the upper rooms, the main staircase to which was of hard oak, the balusters, heavy as bed-posts, being turned and moulded in the quaint

fashion of their century, the handrail as stout as a parapet-top, and the stairs themselves con+ tinually twisting round like a person trying to look over his shoulder. Going up, the floors above were found to have a very irregular surface, rising to ridges, sinking into valley; and being just then uncarpeted, the face of the boards was seen to be eaten into innumerable the opening and shutting of every door a tremble followed every bustling movement, and a creak accom+ panied a walker about the house like a spirit, wherever+ he went. In the room from which the conversation proceeded, Bathsheba and her servant-companion, Liddy Small+ bury were to be discovered sitting upon the floor, and sorting a complication of papers, books, bottles, and rubbish spread out thereon -- remnants from the house+ hold stores of the late occupier. Liddy, the maltster's great-granddaughter, was about Bathsheba's equal in age, and her face was a prominent advertisement of the features' might have lacked in form was amply made up for by perfection of hue, which at this winter-time was the softened ruddiness on a surface of high rotundity and, like the presentations of those great colourists, it was a face which kept well back from the boundary between comeliness and the ideal. Though elastic in nature she was less daring than Bathsheba, and occa+ sionally showed some earnestness, which consisted half of genuine feeling, and half of mannerliness superadded by way of duty. Through a partly-opened door the noise of a scrubbing+ brush led up to the charwoman, Maryann Money, a person who for a face had a circular disc, furrowed less by age than by long gazes of perplexity at distant objects. To think of her was to get good-humoured; to speak of her was to raise the image of a dried Normandy pippin. "Stop your scrubbing a moment,' said Bathsheba through the door to her. "I hear something.' Maryann suspended the brush.

The tramp of a horse was apparent, approaching the front of the building. The paces slackened, turned in at the wicket, and, what was most unusual, came up the mossy path close to the door. The door was tapped with the end of a crop or stick. "What impertinence!' said Liddy, in a low voice. "To ride up the footpath like that! Why didn't he stop at the gate? Lord! "tis a gentleman! I see the top of his hat.' "Be quiet!' said Bathsheba. The further expression of Liddy's concern was con+ tinued by aspect instead of narrative. "Why doesn't Mrs. Coggan go to the door?' Bath+ sheba continued. Rat-tat-tat-tat, resounded more decisively from Bath+ sheba's oak. "Maryann, you go!' said she, fluttering under the onset ot a crowd of romantic possibilities. "O ma'am -- see, here's a mess!' The argument was unanswerable after a glance at Maryann. "Liddy -- you must,' said Bathsheba. Liddy held up her hands and arms, coated with dust from the rubbish they were sorting, and looked implor+ ingly at her mistress. "There -- -Mrs. Coggan is going!' said Bathsheba, exhaling her relief in the form of a long breath which had lain in her bosom a minute or more. The door opened, and a deep voice said -- "Is Miss Everdene at home?' "I'll see, sir,' said Mrs. Coggan, and in a minute appeared in the room. "Dear, what a thirtover place this world is!' con+ tinued Mrs. Coggan (a wholesome-looking lady who had a voice for each class of remark according to the emotion involved; who could toss a pancake or twirl a mop with the accuracy of pure mathematics, and who at this moment showed hands shaggy with frag+ ments of dough and arms encrusted with flour). "I am never up to my elbows, Miss, in making a pudding but one of two things do happen -- either my nose must needs begin

tickling, and I can't live without scratching A woman's dress being a part of her countenance, and any disorder in the one being of the same nature with a malformation or wound in the other, Bathsheba said at once -- "I can't see him in this state. Whatever shall I do?' Not-at-homes were hardly naturalized in Weatherbury farmhouses, so Liddy suggested -- "Say you're a fright with dust, and can't come down.' "Yes -- that sounds very well,' said Mrs. Coggan, critically. "Say I can't see him -- that will do.' Mrs. Coggan went downstairs, and returned the answer as requested, adding, however, on her own responsibility, "Miss is dusting bottles, sir, and is quite a object -- that's why 'tis.' "Oh, very well,' said the deep voice,' indifferently. "All I wanted to ask was, if anything had been heard of Fanny Robin?' "Nothing, sir -- but we may know to-night. William Smallbury is gone to Casterbridge, where her young man lives, as is supposed, and the other men be inquir+ ing about everywhere.' The horse's tramp then recommenced and -retreated, and the door closed. "Who is Mr. Boldwood?' said Bathsheba. "A gentleman-farmer at Little Weatherbury.' "Married?' "No, miss.' "How old is he?' "Forty, I should say -- very handsome -- rather stern+ looking -- and rich.' "What a bother this dusting is! I am always in some unfortunate plight or other;' Bathsheba said, complainingly. "Why should he inquire aboat Fanny?' "Oh, because, as she had no friends in her childhood, he took her and put her to school, and got her her place here under your uncle. He's a very kind man that way, but Lord -- there!' "What?' "Never was such a hopeless man for a woman! He's been

courted by sixes and sevens -- all the girls, gentle and simple, for miles round, have tried him. Jane Perkins worked at him for two months like a slave, and the two Miss Taylors spent a year upon him, and he cost Farmer Ives's daughter nights of tears and twenty pounds' worth of new clothes; but Lord -- the money might as well have been thrown out of the window.' A little boy came up at this moment and looked in upon them. This child was one of the Coggans who, with the Smallburys, were as common among the families of this district as the Avons and Derwents among our rivers. He always had a loosened tooth or a cut finger to show to particular friends, which he did with an air of being thereby elevated above the common herd of afflictionless humanity -- to which exhibition of congratulation as well as pity. "I've got a pen-nee!' said Master Coggan in a scanning measure. "Well -- who gave it you, Teddy?' said Liddy. "Mis-terr Bold-wood! He gave it to me for opening the gate.' "What did he say?' "He said "Where are you going, my little man?'' and I said, "To Miss Everdene's please;'' and he said, "She is a staid woman, isn't she, my little man?' and I said, ""Yes.''' "You naughty child! What did you say that for?' "Cause he gave me the penny!' "What a pucker evrything is in!' said Bathsheba, discontentedly when the child had gone. 'Get away, thing! You ought to be married by this time, and not here troubling me!' "Ay, mistress -- so I did. But what between the poor men I won't have, and the rich men who won't have me, I stand as a pelicon in the wilderness!' "Did anybody ever want to marry you miss?' Liddy ventured to ask when they were again alone. "Lots of 'em, i daresay.?' Bathsheba paused, as if about to refuse a reply, but the temptation to say yes, since it was really in her power was irresistible by aspiring virginity, in spite of her spleen at having been published as old.

"A man wanted to once,' she said, in a highly experi+ enced tone and the image of Gabriel Oak, as the farmer, rose before her. "How nice it must seem!' said Liddy, with the fixed features of mental realization. "And you wouldn't have him?' "He wasn't quite good enough for me.' "How sweet to be able to disdain, when most of us are glad to say, ""Thank you!'' I seem I hear it. ""No, sir -- I'm your better,'' or ""Kiss my foot, sir; my face is for mouths of consequence.'' And did you love him, miss?' "Oh, no. But I rather liked him.' "Do you now?' "Of course not -- what footsteps are those I hear?' Liddy looked from a back window into the courtyard behind, which was now getting low-toned and dim with the earliest films of night. A crooked file of men was approaching the back door. The whole string of trailing individuals advanced in the completest balance of inten+ tion, like the remarkable creatures known as Chain Salpae, which, distinctly organized in other respects, have one will common to a whole family. Some were, as usual, in snow-white smock-frocks of Russia duck, and some in whitey-brown ones of drabbet -- marked on the wrists, breasts, backs, and sleeves with honeycomb-work. Two or three womcn in pattens brought up the rear. "The Philistines be upon us,' said Liddy, making her nose white against the glass. "Oh, very well. Maryann, go down and keep them in the kitchen till I am dressed, and then show them in to me in the hall.'

HALF-AN-HOUR later Bathsheba, in finished dress, and followed by Liddy, entered the upper end of the old hall to find that her men had all deposited themselves on a long form and a settle at the lower extremity. She sat down at a table and opened th e time-book, pen in her hand, with a canvas money-bag beside her. From this she poured a small heap of coin. Liddy chose a position at her elbow and began to sew, sometimes pausing and looking round, or with the air of a privileged person, taking up one of the half-sovereigns lying before her and surveying it merely as a work of art, while strictly preventing her countenance from expressing any wish to possess it as money. "Now before I begin, men,' said Bathsheba, "I have two matters to speak of. The first is that the bailiff is dismissed for thieving, and that I have formed a resolu+ tion to have no bailiff at all, but to manage everything with my own head and hands.' The men breathed an audible breath of amazement. "The next matter is, have you heard anything of Fanny?' "Nothing, ma'am. "Have you done anything?' "I met Farmer Boldwood,' said Jacob Smallbury, 'and I went with him and two of his men, and dragged New+ mill Pond, but we found nothing.' "And the new shepherd have been to Buck's Head, by Yalbury, thinking she had gone there, but nobody had seed her,' said Laban Tall. "Hasn't William Smallbury been to Casterbridge?' "Yes, ma'am, but he's not yet come home. He promised to be back by six.' "It wants a quarter to six at present,' said Bathsheba,

looking at her watch. "I daresay he'll be in directly. Well, now then' -- she looked into the book -- "Joseph Poorgrass, are you there?' "Yes, sir -- ma'am I mane,' said the person addressed. "I be the personal name of Poorgrass.' "And what are you?' "Nothing in my own eye. In the eye of other people -- well, I don't say it; though public thought will out.' "What do you do on the farm?' "I do do carting things all the year, and in seed time I shoots the rooks and sparrows, and helps at pig-killing, sir.' "How much to you ?' "Please nine and ninepence and a good halfpenny where 'twas a bad one, sir -- ma'am I mane.' "Quite correct. Now here are ten shillings in addi+ tion as a small present, as I am a new comer.' Bathsheba blushed slightly at the sense of being generous in public, and Henery Fray, who had drawn up towards her chair, lifted his eyebrows and fingers to express amazement on a small scale. "How much do I owe you -- that man in the corner -- what's your name?' continued Bathsheba. "Matthew Moon, ma'am,' said a singular framework of clothes with nothing of any consequence inside them, which advanced with the toes in no definite direction forwards, but turned in or out as they chanced to swing. "Matthew Mark, did you say? -- speak out -- I shall not hurt you,' inquired the young farmer, kindly. "Matthew Moon mem' said Henery Fray, correct+ ingly, from behind her chair, to which point he had edged himself. "Matthew Moon,' murmured Bathsheba, turning her bright eyes to the book. "Ten and twopence halfpenny is the sum put down to you, I see?' "Yes, mis'ess,' said Matthew, as the rustle of wind among dead leaves. "Here it is and ten shillings. Now -the next -- Andrew Randle, you are a new man, I hear. How come you to leave your last farm?'

"P-p-p-p-p-pl-pl-pl-pl-l-l-l-l-ease, ma'am, p-p-p-p-pl-pl+ pl-pl-please, ma'am-please'm-please'm -- -- ' "'A's a stammering man, mem,' said Henery Fray in an undertone, "and they turned him away because the only time he ever did speak plain he said his soul was his own, and other iniquities, to the squire. "A can cuss, mem, as well as you or I, but 'a can't speak a common speech to save his life.' "Andrew Randle, here's yours -- finish thanking me in a day or two. Temperance Miller -- oh, here's another, Soberness -- both women I suppose?' "Yes'm. Here we be, 'a b'lieve,' was echoed in shrill unison. "What have you been doing?' "Tending thrashing-machine and wimbling haybonds, and saying ""Hoosh!'' to the cocks and hens when they go upon your seeds and planting Early Flourballs and Thompson's Wonderfuls with a dibble.' "Yes -- I see. Are they satisfactory women?' she inquired softly of Henery Fray. "O mem -- don't ask me! Yeilding women?' as scarlet a pair as ever was!' groaned Henery under his breath. "Sit down. "Who, mem?' "Sit down,' Joseph Poorgrass, in the background twitched, and his lips became dry with fear of some terrible conse+ quences, as he saw Bathsheba summarily speaking, and Henery slinking off to a corner. "Now the next. Laban Tall, you'll stay on working for me?' "For you or anybody that pays me well, ma'am,' replied the young married man. "True -- the man must live!' said a woman in the back quarter, who had just entered with clicking pattens. "What woman is that?" Bathsheba asked. "I be his lawful wife!' continued the voice with greater prominence of manner and tone. This lady called herself five-and-twenty, looked thirty, passed as thirty-five, and was forty. She was a woman who never, like some newly married, showed

conjugal tenderness in public, perhaps because she had none to show. "Oh, you are,' said Bathsheba. "Well, Laban, will you stay on ?' "Yes, he'll stay, ma'am!' said again the shrill tongue of Laban's lawful wife. "Well, he can speak for himself, I suppose.' "O Lord, not he, ma'am! A simple tool. Well enough, but a poor gawkhammer mortal,' the wife replied "Heh-heh-heh!' laughed the married man with a hideous effort of appreciation, for he was as irrepressibly good-humoured under ghastly snubs as a parliamentary candidate on the hustings. The names remaining were called in the same manner. "Now I think I have done with you,' said Bathsheba, closing the book and shaking back a stray twine of hair. "Has William Smallbury returned?' "No, ma'am.' "The new shepherd will want a man under him,' suggested Henery Fray, trying to make himself official again by a sideway approach towards her chair. "Oh -- he will. Who can he have?' "Young Cain Ball is a very good lad,' Henery said, "and Shepherd Oak don't mind his youth?' he added, turning with an apologetic smile to the shepherd, who had just appeared on the scene, and was now leaning against the doorpost with his arms folded. "No, I don't mind that,' said Gabriel. "How did Cain come by such a name?' asked Bathsheba. "Oh you see, mem, his pore mother, not being a Scripture-read woman made a mistake at his christening, thinking 'twas Abel killed Cain, and called en Cain, but 'twas too late, for the name could never be got rid of in the parish. "Tis very unfortunate for the boy.' "It is rather unfortunate.' "Yes. However, we soften it down as much as we can, and call him Cainey. Ah, pore widow-woman! she cried her heart

out about it almost. She was brought up by a very heathen father and mother, who never sent her to church or school, and it shows how the sins of the parents are visited upon the children, mem.' Mr. Fray here drew up his features to the mild degree of melancholy required when the persons involved in the given misfortune do not belong to your own family. "Very well then, Cainey Ball to be under-shepherd And you quite understand your duties? -- you I mean, Gabriel Oak?' "Quite well, I thank you Miss Everdene,' said Shepard Oak from the doorpost. "If I don't, I'll inquire.' Gabriel was rather staggered by the remark+ able coolness of her manner. Certainly nobody without previous information would have dreamt that Oak and the handsome woman before whom he stood had ever been other than strangers. But perhaps her air was the inevitable result of the social rise which had advanced her from a cottage to a large house and fields. The case is not unexampled in high places. When, in the writings of the later poets, Jove and his family are found to have moved from their cramped quarters on the peak of Olympus into the wide sky above it, their words show a proportionate increase of arrogance and reserve. Footsteps were heard in the passage, combining in their character the qualities both of weight and measure, rather at the expense of velocity. (All.) 'Here's Billy Smallbury come from Caster+ bridge.' ' And what's the news ? ' said Bathsheba, as William, after marching to the middle of the hall, took a hand+ kerchief from his hat and wiped his forehead from its centre to its remoter boundaries. 'I should have been sooner, miss,' he said, 'if it hadn't been for the weather.' He then stamped with each foot severely, and on looking down his boots were perceived to be clogged with snow. 'Come at last, is it ?' said Henery. " Well, what about Fanny ? ' said Bathsheba. "Well, ma'am, in round numbers, she's run away with the soldiers,' said William.

" No; not a steady girl like Fanny ! ' "I'll tell ye all particulars. When I got to Caster, bridge Barracks, they said, " The Eleventh Dragoon+ Guards be gone away, and new troops have come." The Eleventh left last week for Melchester and onwards. The Route came from Government like a thief in the night, as is his nature to, and afore the Eleventh knew it almost, they wem on the march. They passed near here.' Gabriel had listened with interest. 'I saw them go,' he said. ' Yes,' continued William, ' they pranced down the street playing "The Girl I Left Behind Me,' so 'tis said, in glorious notes of triumph. Every looker-on's inside shook with the blows of the great drum to his deepest vitals, and there was not a dry eye throughout the town among the public-house people and the name+ less women !.' 'But they're not gone to any war?' 'No, ma'am; but they be gone to take the places of them who may, which is very close connected. And so I said to myself, Fanny's young man was one of the regiment, and she's gone after him. There, ma'am, that's it in black and white.' Gabriel remained musing and said nothing, for he was in doubt. 'Well, we are not likely to know more to-night, at any rate,' said Bathsheba. 'But one of you had better run across to Farmer Boldwood's and tell him that much.' She then rose; but before retiring, addressed a few words to them with a pretty dignity, to which her mourning dress added a soberness that was hardly to be found in the words themselves. 'Now mind, you have a mistress instead of a master I don't yet know my powers or my talents in farming; but I shall do my best, and if you serve me well, so shall I serve you. Don't any unfair ones among you (if there are any such, but I hope not) suppose that because I'm a woman I don't understand the difference between bad goings-on and good.'

(All.) 'Nom!. (Liddy.) 'Excellent well said.' 'I shall be up before you are awake; I shall be afield before you are up ; and I shall have breakfasted before you are afield. In short, I shall astonish you all. (All.) 'Yes'm!' 'And so good-night.' (All.) 'Good-night, ma'am.' Then this small-thesmothete stepped from the table, and surged out of the hall, her black silk dress licking up a few straws and dragging them along with a scratch+ ing noise upon the floor. biddy, elevating her feelings to the occasion from a sense of grandeur, floated off behind Bathsheba with a milder dignity not entirely free from travesty, and the door was closed.

OUTSIDE THE BARRACKS -- SNOW -- A MEETING FOR dreariness nothing could surpass a prospect in the outskirts of a certain town and military station, many miles north of Weatherbury, at a later hour on this same snowy evening -- if that may be called a prospect of which the chief constituent was darkness. It was a night when sorrow may come to the brightest without causing any great sense of incongruity : when, with impressible persons, love becomes solicitous+ ness, hope sinks to misgiving, and faith to hope : when the exercise of memory does not stir feelings of regret at opportunities for ambition that have been passed by, and anticipation does not prompt to enterprise. The scene was a public path, bordered on the left hand by a river, behind which rose a high wall. On the right was a tract of land, partly meadow'and partly moor, reaching, at its remote verge, to a wide undulating uplan. The changes of the seasons are less obtrusive on spots of this kind than amid woodland scenery. Still, to a close observer, they are just as perceptible ; the difference is that their media of manifestation are less trite and familiar than such well-known ones as the bursting of the buds or the fall of the leaf. Many are not so stealthy and gradual as we may be apt to imagine in considering the general torpidity of a moor or waste. Winter, in coming to the country hereabout, advanced in well-marked stages, wherein might have been successively observed the retreat of the snakes, the transformation of the ferns, the filling of the pools, a rising of fogs, the embrowning by frost, the collapse of the fungi, and an obliteration by snow. This climax of the series had been reached to-night on the aforesaid moor, and for the first time in the season its

irregularities were forms without features ; suggestive of anything, proclaiming nothing, and without more character than that of being the limit of something else -- the lowest layer of a firmament of snow. From this chaotic skyful of crowding flakes the mead and moor momentarily received additional clothing, only to appear momentarily more naked thereby. The vast arch of cloud above was strangely low, and formed as it were the roof of a large dark cavern, gradually sinking in upon its floor; for the instinctive thought was that the snow lining the heavens and that encrusting the earth would soon unite into one mass without any intervening stratum of air at all. We turn our attention to the left-hand characteristics ; which were flatness in respect of the river, verticality in respect of the wall behind it, and darkness as to both. These features made up the mass. If anything could be darker than the sky, it was the wall, and if any thing could be gloomier than the wall it was the river beneath. The indistinct summit of the facade was notched and pronged by chimneys here and there, and upon its face were faintly signified the oblong shapes of windows, though only in the upper part. Below, down to the water's edge, the flat was unbroken by hole or projection. An indescribable succession of dull blows, perplexing in their regularity, sent their sound- with difficulty through the fluffy atmosphere. It was a neighbouring clock striking ten The bell was in the open air, and being overlaid with several inches of muffling snow, had lost its voiee for the time. About this hour the snow abated : ten flakes fell where twenty had fallen, then one had the room of ten. Not long after a form moved by the brink of the river. By its outline upon the colourless background, a close observer might have seen 'that it was small. This was all that was positively discoverable, though it seemed human. The shape went slowly along, but without much exertion, for the snow, though sudden, was not as yet more than two inches deep. At this time some words were spoken aloud : -- ' One. Two. 'Three. Four. Five.' Between each utterance the little shape advanced about half a dozen yards. It was evident now that the windows high

in the wall were being counted. The word 'Five' represented the fifth window from the end of the wall. Here the spot stopped, and dwindled smaller. The figure was stooping. Then a morsel of snow flew across the river towards the fifth window. It smacked against the wall at a point several yards from its mark. The throw was the idea of a man conjoined with the execution of a woman. No man who had ever seen bird, rabbit, or squirrel in his childhood, could possibly have thrown with such utter imbecility as was shown here. Another attempt, and another ; till by degrees the wall must have become pimpled with the adhering lumps of snow At last one fragment struck the fifth window. The river would have been; seen by day to be of that deep smooth sort which races middle and' sides with the same gliding precision, any irregularities of speed being immediately corrected by a small whirl+ pool. Nothing was heard in reply to the signal but the gurgle and cluck of one of these invisible wheels -- together with a few small sounds which a sad man would have called moans, and a happy man laughter -- caused by the flapping of the waters against trifling objects in other parts of the stream. The window was struck again in the same manner. Then a noise was heard, apparently produced by the opening of the window. This was followed by a voice from the same quarter. 'Who's there ? ' The tones were masculine, and not those of surprise. The high wall being that of a barrack, and marriage being looked upon with disfavour in the army, assigna+ tions and communications had probably been made across the river before tonight. "Is it Sergeant Troy?' said the blurred spot in the snow, tremulously. This person was so much like a mere shade upon the earth, and the other speaker so much a part of the building, that one would have said the wall was holding a conversation with the snow.

'Yes,' came suspiciously from the shadow. ' What girl are you ? ' 'O, Frank -- don't you know me ?' said the spot. 'Your wife, Fanny Robin.' ' Fanny !.' said the wall, in utter astonishment. 'Yes,' said the girl, with a half-suppressed gasp of emotion. There was something in the woman's tone which is not that of the wife, and there was a mannerin the man which is rarely a husband's. The dialogue went on: 'How did you come here ?' 'I asked which was your window. Forgive me !. ' "I did not expect you to-night. Indeed, I did not think you would come at all. It was a wonder you found me here. I am orderly to-morrow.' 'You said I was to come.' ' Well -- I said that you might.' 'Yes, I mean that I might. You are glad to see me, Frank ? ' ' O yes -- of course.' ' Can you -- come to me !.' 'My dear Fan, no .! The bugle has sounded, the barrack gates are closed, and I have no leave. We are all of us as good as in the county gaol till to-morrow morning.' ' Then I shan't see you till then .! ' The words- were in a faltering tone of disappointment. ' How did you get here from Weatherbury ? ' 'I walked -- some part of the way -- the rest by the carriers.' ' I am surprised.' ' Yes -- so am I. And Frank, when will it 'be ? ' ' What ? ' ' That you promised.' " I don't quite recollect.' '0 You do! Don't speak like that. It weighs me to the earth. It makes me say what ought to be said first by you.' ' Never mind -- say it.' '0, must I? -- it is, when shall we be married, Frank ? ' " Oh, I " see. Well -- you have to get proper clothes.' "I have money. Will it be by banns or license ?'

" Banns, I should think.' " And we live in two parishes.' "Do we ? What then?' "My lodgings are in St. Mary's, and this is not. So they will have to be published in both.' "Is that the law?' " Yes. O Frank -- you think me forward, I am afraid .! Don't, dear Frank -- will you -- for I love you so. And you said lots of times you would marry me, and and -- I -- I -- I -- -- ' "Don't cry, now! It is foolish. If i said so, of course I will.' 'And shall I put up the banns in my parish, and will you in yours?' "Yes' "To-morrow?' "Not tomorrow. We'll settle in a few days.' "You have the permission of the officers?' "No, not yet.' "O -- how is it? You said you almost had before you left Casterbridge.' "The fact is, I forgot to ask. Your coming like this I'll go away now. Will you qoDe,and seq be to-morroy is so sudden and unexpected.' "Yes -- yes -- it is. It was wrong of me to worry you. I'll go away now. Will you come and see me to-morrow, at Mrs. Twills's, in North Street? I don't like to come to the Barracks. There are bad women about, and they think me one.' "Quite,so. I'll come to you, my dean Good-night.' "Good-night, Frank -- good-night!' And the noise was again heard of a window closing The little spot moved away. When she passed the corner a subdued exclamation was heard inside the wall. "Ho -- ho -- Sergeant -- ho -- ho!' An expostulation followed, but it was indistinct; and it became lost amid a low peal of laughter, which was hardly distinguishable from the gurgle of the tiny whirlpools outside.

FARMERS -- A RULE -- IN EXCEPTION THE first public evidence of Bathsheba's decision to be a farmer in her own person and by proxy no more was her appearance the following market-day in. the cornmarket at Casterbridge. The low though extensive hall, supported by beams and pillars, and latterly dignified by-the name of Corn Ex+ change, was thronged with hot men who talked among each other in twos and threes, the speaker of the minute looking sideways into his auditor's face and concentrating his argument by a contraction of one eyelid during de+ livery. The greater number carried in their hands ground-ash saplings, using them partly as walking-sticks and partly for poking up pigs, sheep, neighbours with their backs turned, and restful things in general, which seemed to require such treatment in the course of their peregrinations. During conversations each subjected his sapling to great varieties of usage -- bending it round his back, forming an"arch of it between his two hands, overweighting it on the ground till it reached nearly a semicircle; or perhaps it was hastily tucked under the arm whilst the sample-bag was pulled forth and a hand+ ful of corn poured into the palm, which, after criticism, was flung upon the floor, an issue of events perfectly well known to half-a-dozen acute town-bred fowls which had as usual crept into the building unobserved, and waited the fulfilment of their anticipations with a high+ stretched neck and oblique eye. Among these heavy yeomen a feminine figure glided, the single one of her sex that the room contained. She was prettily and even daintily dressed. She moved between them as a chaise between carts, was heard after them as a romance after sermons, was felt among them like a breeze among furnaces. It had required a little determination -- far more than she had at

first imagined -- to take up a position here, for at her first entry the lumbering dialogues had ceased, nearly every face had been turned towards her, and those that were already turned rigidly fixed there. Two or three only of the farmers were personally known to Bathsheba, and to these she had made her way. But if she was to be the practical woman she had intended to show herself, business must be carried on, introductions or none, and she ultimately acquired con+ fidence enough to speak and reply boldly to men merely known to her by hearsay. Bathsheba too had her sample-bags, and by degrees adopted the professional pour into the hand -- holding up the grains in her narrow palm for inspection, in perfect Casterbridge manner. Something in the exact arch of her upper unbroken row of teeth, and in the keenly pointed corners of her red mouth when, with parted lips, she somewhat defiantly turned up her face to argue a point with a tall man, suggested that there was potentiality enough in that lithe slip of humanity for alarming exploits of sex, and daring enough to carry them out. But her eyes had a softness -- invariably a softness -- which, had they not been dark, would have seemed mistiness; as they were, it lowered an expression that might have been piercing to simple clearness, Strange to say of a woman in full bloom and vigor, she always allowed her interlocutors to finish their state+ ments before rejoining with hers. In arguing on prices, he held to her own firmly, as was natural in a dealer, and reduced theirs persistently, as was inevitable in a oman. But there was an elasticity in her firmness which removed it from obstinacy, as there was a naivete in her cheapening which saved it from meanness. Those of the farmers with whom she had no dealings by far the greater part) were continually asking each other, "Who is she?' The reply would be -- "Farmer Everdene's niece; took on Weatherbury Upper Farm; turned away the baily, and swears she'll do verything herself.' The other man would then shake his head.

"Yes, 'tis a pity she's so headstrong,' the first would say. "But we ought to be proud of her here -- she lightens up the old place. 'Tis such a shapely maid, however, that she'll soon get picked up.' It would be ungallant to suggest that the novelty of her engagement in such an occupation had almost as much to do with the magnetism as had the beauty of her face and movements. However, te interest was eneral, and this Saturday's debut in the forum, whatever it may have been to Bathsheba as the buying and selling farmer, was unquestionably a triumph to her as the maiden. Indeed, the sensation was so pronounced that her instinct on two or three occasions was merely to valk as a queen among these gods of the fallow, like a little sister of a little Jove, and"to neglect closing prices altogether. The numerous evidences of-her power to attract were only thrown into greater relief by a marked exception. Women seem to have eyes in their ribbons for such matters as these. Bathsheba, without looking within a right angle of him, was conscious of a black sheep among the flock. It perplexed her first. If there had been a respect+ able minority on either side, the case would have been most natural. If nobody had regarded her, she would have -- -taken the matter indifferently -- such cases had occurred. If eveybody, this man included, she would have taken it as a matter of course -- people had done so before. But the smallness of the exception made the mystery. She soon knew thus much of the recusant's appear+ ance. He was a gentlemanly man, with full and distinctly outlined Roman features, the prominences of which glowed in the sun with a bronze-like richness of tone. He was erect in attitude, and quiet in demeanour. One characteristic pre-eminently marked him -- dignity. Apparently he had some time ago reached that entrance to middle age at which a man's aspect naturally ceases to alter for the term of a dozen years or so; and, artificially, a woman't does likewise. Thirty-five and fifiy were his limits of variation -- he might have been either, or anywhere between the two. It may be said that married men of forty are usually ready

and generous enough to fling passing glances at any specimen of moderate beauty they may discern by the way. Probably, as with persons playing whist for love, the consciousness of a certain immunity under any circumstances from that worst possible ultimate, the having to pay, makes them unduly speculative. Bathsheba was convinced that this unmoved person was not a married man. When marketing was over, she rushed off to Liddy, who was waiting for her -- beside the yellowing in which they had driven to town. The horse was put in, and on they trotted Bathsheba's sugar, tea, and drapery parcels being packed behind, and expeessing in some indescribable manner, by their colour, shape, and general lineaments, that they were that youmg lady+ farmer's property, and the grocer's and drapers no more. " I've been through it, Liddy, and it is over. I shan't mind it again, for they will all have grown accustomed to seeing me there; but this morning it was as bad as being married -- eyes everywhere!' "I knowed it would. be,' Liddy said "Men be such a terrible class of society to look at a body.' "But there was one man who had more sense than to waste his time upon me.' The information was put in this form that Liddy might not for a moment suppose her mistress was at all piqued. "A very good-looking man,' she continued, "upright; about forty, I should think. Do you know at all who he could be?' Liddy couldn't think. "Can't you guess at all?' said Bathsheba with some disappointment. "I haven't a notion; besides, 'tis no difference, since he took less notice of you than any of the rest. Now, if he'd taken more, it would have mattered a great deal.' Bathsheba was suffering from the reverse feeling just then, and they bowled along in silence. A low carriage, bowling along still more rapidly behind a horse of un+ impeachable breed, overtook and passed them. "Why, there he is!' she said. Liddy looked. "That! That's Farmer Boldwood -- of course

'tis -- the man you couldn't see the other day when he called.' "Oh, Farmer Boldwood,' murmured Bathsheba, and looked at him as he outstripped them. The farmer had never turned his head once, but with eyes fixed on the most advanced point along the road, passed as uncon+ sciously and abstractedly as if Bathshea and her charms were thin air. "He's an interesting man -- don't you think so?' she remarked. "O yes, very. Everybody owns it,' replied Liddy. "I wonder why he is so wrapt up and indifferent, and seemingly so far away from all he sees around him,' "It is said -- but not known for certain -- that he met with some bitter disappointment when he was a young man and merry. A woman jilted him, they say.' "People always say that -- and we know very well women scarcely ever jilt men; 'tis the men who jilt us. I expect it is simply his nature to be so reserved.' "Simply his nature -- I expect so, miss -- nothing else in the world.' "Still, 'tis more romantic to think he has been served cruelly, poor thing'! Perhaps, after all, he has! I "Depend upon it he has. O yes, miss, he has! feel he must have.' "However, we are very apt to think extremes of people. I -- shouldn't wonder after all if it wasn't a little of both -- just between the two -- rather cruelly used and rather reserved.' "O dear no, miss -- I can't think it between the two!' "That's most likely.' "Well, yes, so it is. I am convinced it is most likely. You may -- take my word, miss, that that's what's the matter with him.' 

SORTES SANCTORUM -- THE VALENTINE IT was Sunday afternoon in the farmhouse, on the thirteenth of February. Dinner being over, Bathsheba, for want of a better companion, had asked Liddy to come and sit with her. The mouldy pile was dreary in winter-time before the candles were lighted and the shutters closed ; the atmosphere of the place seemed as old as the walls; every nook behind the furniture had a temperature of its own, for the fire was not kindled in this part of the house early in the day; and Bathsheba's new piano, which was an old one in other annals, looked particularly sloping and out of level on the warped floor before night threw a shade over its less prominent angles and hid the unpleasantness. Liddy, like a little brook, though shallow, was always rippling; her presence had not so much weight as to task thought, and yet enough to exercise it. On the table lay an old quarto Bible, bound in leather. Liddy looking at it said, -- "Did you ever find out, miss, who you are going to marry by means of the Bible and key ?, "Don't be so foolish, Liddy. As if such things could be.' " Well, there's a good deal in it, all the same.' ' Nonsense, child.' " And it makes your heart beat fearful. Some believe in it; some don't; I do.' "Very well, let's try it,' said Bathsheba, bounding from her seat with that total disregard of consistency which can be indulged in towards a dependent, and entering into the spirit of divination at once. 'Go and get the front door key.' Liddy fetched it. 'I wish it wasn't Sunday,' she said, on returning. ' Perhaps 'tis wrong.' ' What's right week days is right Sundays,' replied her mistress in a tone which was a proof in itself.

The book was opened -- the leaves, drab with age, being quite worn away at much-read verses by the fore' fingers "of unpractised readers in former days, where they were moved along under the line as an aid to the vision. The special verse in the Book of Ruth was sought out by Bathsheba, and the sublime words met her eye. They slightly thrilled and abashed her. It was Wisdom in the abstract facing Folly in the concrete. Folly in the concrete blushed, persisted in her intention, and placed the key on -the book. A rusty patch immediately upon the verse, caused by previous pressure of an iron substance thereon, told that this was not the first time the old volume had been used for the purpose. 'Now keep steady, and be silent,' said Bathsheba. The 'verse was repeated; the book turned round ; Bathsheba blushed guiltily. 'Who did you try ?' said Liddy curiously. 'I shall not tell you.' 'Did you notice Mr. Boldwood's doings in church this morning, miss ? 'Liddy continued, adumbrating by the remark the track her thoughts had taken. 'No, indeed,' said Bathsheba, with serene indifference " His pew is exactly opposite yours, miss.' "I know it.' "And you did not see his goings on !,' Certainly I did not, I tell you.' Liddy assumed a smaller physiognomy, and shut her lips decisively. This move was unexpected, and proportionately dis concerting. " What did he do?' Bathsheba said perforce. "Didn't turn his head to look at you once all the service. "Why should he?' again demanded her mistress, wearing a nettled look. "I didn't ask him to. 'Oh no. But everybody else was noticing you ; and it was odd he didn't. There, 'tis like him. Rich and gentlemanly, what does he care ? ' Bathsheba dropped into a silence intended to ex+ press that she had opinions on the matter too abstruse for Liddy's comprehension, rather than that she had nothing to say. "

Dear me -- I had nearly forgotten the valentine I bought yesterday,' she exclaimed at length. "Valentine ! who for, miss ? ' said Liddy. " Farmer Boldwood ?' It was the single name among all possible wrong ones that just at this moment seemed to Bathsheba more pertinent than the right. "Well, no. It is only for little Teddy Coggan. have promised him something, and this will be a pretty surprise for him. Liddy, you may as well bring me my desk and I'll direct it at once.' Bathsheba took from her desk a gorgeously illumin+ ated and embossed design in post-octavo, which had been "bought on the previous market-day at the chief stationer's in Casterbridge. In the eentre was a small oval enclosure ; this was left blank, that the sender might insert tender words more appropriate to the special occasion than any generalities by a printer could possibly be. " Here's a place for writing,' said Bathsheba. 'What shall I put ?' " Something of this sort, I should think', returned Liddy promptly : -- " The rose is red, The violet blue, Camation's sweet, And so are you.' " Yes, that shall be it. It just suits itself to a chubby+ faced child like him,' said Bathsheba. She ins.erted the words in a small though legible handwriting; enelosed the sheet in an envelope, and dipped her pen for the direction. "What fun it would be to send it to the stupid old Boldwood, and how he would wonder.! ' said the irrepressible Liddy, lifting her eyebrows, and indulging in an awful mirth on the verge of fear as she thought of the moral and social magnitude of the man contem+ plated. Bathsheba paused to regard the idea at full length. Boldwood's had begun to be a troublesome image -- a species of Daniel in her kingdom who persisted in kneeling eastward

when reason and common sense said that he might just as well follow suit with the rest, and afford her the official glance of admiration which cost nothing at all. She was far from being seriously concerned about his nonconformity. Still, it was faintly depressing that the most dignified and valuable man in the parish should withhold his eyes, and that a girl like Liddy should talk about it. So Liddy's idea was at first rather harassing than piquant. " No, I won't do that. He wouldn't see any humour in it.' " He'd worry to death,' said the persistent Liddy. " Really, I don't care particularly to send it to Teddy,' remarked her mistress. " He's rather a naughty child sometimes.' " Yes -- that he is.' " Let's toss as men do,' said Bathsheba, idly. 'Now then, head, Boldwood ; tail, Teddy. No, we won't toss money on a Sunday that would be tempting the devil indeed.' "Toss this hymn-book; there can't be no sinfulness in that, miss.' 'Very well. Open, Boldwood -- shut, Teddy. No; it's more likely to fall open. Open, Teddy -- shut, Boldwood.' The book went fluttering in the air and came down shut. Bathsheba, a small yawn upon her mouth, took the pen, and with off-hand serenity directed the missive to Boldwood. 'Now light a candle, Liddy. Which seal shall we use? Here's a unicorn's head -- there's nothing in that. What's this ? -- two doves -- no. It ought to be something extraodinary, ought it not, Lidd? Here's one with a motto -- I remember it is some funny one, but I can't read it. We'll try this, and if it doen't do we'll have another.' A large red seal was duly affixed. Bathsheba looked closely at the hot wax to discover the words. 'Capital!' she exclaimed, throwing down the letter frolicsomely. " 'Twould upset the solemnity of a parson

The same evening the letter was sent, and was duly returned to Weatherbury again in the morning. Of love as a spectacle Bathsheba had a fair knowledge; but of love subjectively she knew nothing.

EFFECT OF THE LETTER -- SUNRISE AT dusk, on the evening of St. Valentine's Day, Bold+ wood sat down to supper as usual, by a beaming fire of aged logs. Upon the matel-shelf before him was a time-piece, surmounted by a spread eagle, and upon the eagle's wings was the letter Bathsheba had sent. Here the bachelor's gaze was continually fastening itself, till the large red seal became as a blot of blood on the retina of his eye; and as he ate and drank he still read in fancy the words thereon, although they were too remote for his sight -- " MARRY ME.' The pert injunction was like those crystal substances which, colourless themselves, assume the tone of objects about them. Here, in the quiet of Boldwood's parlour, where everything that ,was not grave was extraneous, and where the atmosphere was that of a Puritan Sunday lasting all the week, the letter and its dictum changed' their tenor from the thoughtlessness of their origin to a deep solemnity, imbibed from their accessories now. Since the receipt of the missive in the morning, Boldwood had felt the symmetry of his existence to be slowly getting distorted in the direction of an ideal passion. The disturbance was as the first floating weed to Columbus -- the eontemptibly little suggesting possibilities of the infinitely great. The letter must have had an origin and a motive. That the latter was of the smallest magnitude com+ patible with its existence at all, Boldwood, of course, did not know. And such an explanation did not strike him as a possibility even. It is foreign to a mystified condition of mind to realize of the mystifier that the processes of approving a course suggested by circumstance, and of striking out a course from inner impulse, would look the same in the result. The vast difference between

starting a train of events, and direct+ ing into a particular groove a series already started, is rarely apparent to the person confounded by the issue. When Boldwood went to bed he placed the valen+ tine in the corner of the looking-glass. He was conscious of its presence, even when his back was turned upon it. It was the first time in Boldwood's life that such an event had occurred. The same fascination that caused him to think it an act which had a deliberate motive prevented him from regarding it as an impertinence. He looked again at the direction. The mysterious influences of night invested the writing with the presence of the unknown writer. Somebody's some woman's -- hand had travelled softly over the paper bearing his name ; her unrevealed eyes had watched every curve as she formed it ; her brain had seen him in imagination the while. Why should she have imagined him ? Her mouth -- were the lips red or pale, plump or creased? -- had curved itself to a certain expression as the pen went on -- the corners had moved with all their natural tremulousness : what had been the expression ? The vision of the woman writing, as a supplement to the words written, had no individuality. She was a misty shape, and well she might be, considering that her original was at that moment sound asleep and oblivious of all love and letter-writing under the sky. Whenever Boldwood dozed she took a form, and com+ paratively ceased to be a vision : when he awoke there was the letter justifying the dream. The moon shone to-night, and its light was not of a customary kind. His window admitted only a reflection of its rays, and the pale sheen had that reversed direction which snow gives, coming upward and lighting up his ceiling in an unnatural way, casting shadows in strange places, and putting lights where shadows had used to be. The substance of the epistle had occupied him but little in comparison with the fact of its arrival. He suddenly wondered if anything more might be found in the envelope than what he had withdrawn. He jumped out of bed in the weird light, took the letter, pulled out the flimsy sheet, shook the envelope -- searched it. Nothing more was there. Boldwood looked, as he

had a hundred times the preceding day, at the insistent red seal : " Marry me,' he said aloud. The solemn and reserved yeoman again closed the letter, and stuck it in the frame of the glass. In doing so he caught sight of his reflected features, wan in expression, and insubstantial in form. He saw how closely compressed was his mouth, and that his eyes were wide-spread and vacant. Feeling uneasy and dis+ satisfied with himself for this nervous excitability, he returned to bed. Then the dawn drew on. The full power of the clear heaven was not equal to that of a cloudy sky at noon, when Boldwood arose and dressed himself. He descended the stairs and went out towards the gate of a field to the east, leaning over which he paused and looked around. It was one of the usual slow sunrises of this time of the year, and the sky, pure violet in the zenith, was leaden to the northward, and murky to the east, where, over the snowy down or ewe-lease on Weatherbury Upper Farm, and apparently resting upon the ridge, the only half of the sun yet visible burnt rayless, like a red and flameless fire shining over a white hearthstone. The whole effect resembled a sunset as childhood resembles age. In other directions, the fields and sky were so much of one colour by the snow, that it was difficult in a hasty glance to tell whereabouts the horizon occurred ; and in general there was here, too, that before-mentioned preternatural inversion of light and shade which attends the prospect when the garish brightness commonly in the sky is found on the earth, and the shades of earth are in the sky. Over the west hung the wasting moon, now dull and greenish-yellow, like tarnished brass. Boldwood was listlessly noting how the frost had hardened and glazed the surface of the snow, till it shone in the red eastern light wit-h the polish of marble; how, in some portions of the slope, withered grass-bents, encased in icicles, bristled through the smooth wan coverlet in the twisted and curved shapes of old Venetian glass; and how the footprints of a few birds, which had hopped over the snow whilst it lay in the state of a soft fleece, were now frozen to a short perma+

nency. A half-muffled noise of light wheels interrupted him. Boldwood turned back into the road. It was the mail-cart -- a crazy, two-wheeled vehicle, hardly heavy enough to resist a puff of wind. The driver held out a letter. Boldwood seized it and opened it, ex+ pecting another anonymous one -- so greatly are people's ideas of probability a mere sense that precedent will repeat itself. "I don't think it is for you, sir,' said the man, when he saw Boldwood's action. "Though there is no name I think it is for your shepherd.' Boldwood looked then at the address -- To the New Shepherd, Weatherbury Farm, Near Casterbridge. "Oh -- what a mistake !. -- it is not mine. Nor is it for my shepherd. It is for Miss Everdene's.' You had better take it on to him -- Gabriel Oak -- and say I opencd it in mistake." At this moment, on the ridge, up against the blazing sky, a figure was visible, like the black snuff in the midst of a candle-flame. Then it moved and began to bustle about vigorously from place to place, carrying square skeleton masses, which were riddled by the same rays. A small figure on all fours followed behind. The tall form was that of Gabriel Oak ; the small one that of George ; the articles in course of transit were hurdles. 'Wait, 'said Boldwood. " That's the man on the hill. I'll take the letter to him myself." To Boldwood it was now no longer merely a letter to I another man. It was an opportunity. Exhibiting a face pregnant with intention, he entered the snowy field. Gabriel, at that minute, descended the hill towards the right. The glow stretched down in this direction now, and touched the distant roof of Warren's Malthouse whither the shepherd was apparently bent : Boldwood followed at a distance.

THE scarlet and orange light outside the malthouse did not penetrate to its interior, which was, as usual, lighted by a rival glow of similar hue, radiating from the hearth. The maltster, after having lain down in his clothes for a few hours, was now sitting beside a three-leggcd table, breakfasting of bread and bacon. This was eaten on the plateless system, which is performed by placing a slice of bread upon the table, the meat flat upon the bread, a mustard plaster upon the meat, and a pinch of salt upon the whole, then cutting them vertically downwards with a large pocket-knife till wood is reached, when the severed lamp is impaled on the knife, elevated, and sent the proper way of food. The maltster's lack of teeth appeared not to sensibly diminish his powers as a mill. He had been without them for so many years that toothlessness was felt less to be a defect than hard gums an acquisition. Indeed, he seemed to approach the grave as a hyperbolic curve approaches a stmight line -- less directly as he got nearer, till it was doubtful if he would ever reach it at all. In the ashpit was a heap of potatoes roasting, and a boiling pipkin of charred bread, callcd 'coffee,' for the benefit of whomsoever should call, for Warren's was a sort of clubhouse. used as an alternative to the in!. "I say, says I, we get a fine day, and then down comes a snapper at night,' was a remark now suddenly heard spreading into the malthouse from the door, which had been opened the previous moment. The form of Henery Fray advanced to the fire, stamping the snow from his boots when about half-way there. The speech and entry had not seemed to be at all an abrupt begin+ ning to the maltster, introductoy matter being often omitted in this neighbourhood, both from word and

deed, and the maltster having the same latitude allowed him, did not hurry to reply. He picked up a fragment of cheese, by pecking upon it with his knife, as a butcher picks up skewers. Henery appeared in a drab kerseymere great-coat, buttoned over his smock-frock, the white skirts of the latter being visible to the distance of about a foot below the coat-tails, which, when you got used to the style of dress, looked natural enough, and even ornamental -- it certainly was comfortable. Matthew Moon, Joseph Poorgrass, and other carters and waggoners followed at his heels, with great lanterns dangling from their hands, which showed that they had just come from the cart-horse stables, where they had been busily engaged since four o'clock that morning. "And how is she getting on without a baily?' the maltster inquired. Henery shook his head, and smiled one of the bitter smiles, dragging all the flesh of his forehead into a corrugated heap in the centre. " She'll rue it -- surely, surely ! ' he said " Benjy Pennyways were not a true man or an honest baily -- as big a betrayer as Joey Iscariot himself. But to think she can carr' on alone! ' He allowed his head to swing laterally three or four times in silence. " Never in all my creeping up -- never! ' This was recognized by all as the conclusion of some gloomy speech which had been expressed in thought alone during the shake of the head; Henery meanwhile retained several marks of despair upon his face, to imply that they would be required for use again directly he should go on speaking. 'All will be ruined, and ourselves too, or there's no meat in gentlemen's houses!' said Mark Clark. 'A headstrong maid, that's what she is -- and won't listen to no advice at all. Pride and vanity have ruined many a cobbler's dog. Dear, dear, when I think o' it, I sorrows like a man in travel ! ' 'True, Henery, you do, I've heard ye,' said Joseph Poorgrass in a voice of thorough attestation, and with a wire-drawn smile of misery. "'Twould do a martel man no harm to have what's under

her bonnet,' said Billy Smallbury, who had just entered, bearing his one tooth before him. "She can spaik real language, and must have some sense some+ where. Do ye foller me ?' "I do: but no baily -- I deserved that place,' wailed Henery, signifying wasted genius by gazing blankly at visions of a high destiny apparently visible to him on Billy Smallbury's smock-frock. " There, 'twas to be, I suppose. Your lot is your lot, and Scripture is nothing; for if you do good you don't get rewarded according to your works, but be cheated in some mean way out of your recompense.' "No, no; I don't agree with'ee there,' said Mark Clark. God's a perfect gentleman in that respect.' "Good works good pay, so to speak it,' attested Joseph Poorgrass. A short pause ensued, and as a sort of entr'acte Henery turned and blew out the lanterns, which the increase of daylight rendered no longer necessary even in the malthouse, with its one pane of glass. "I wonder what a farmer-woman can want with a harpsichord, dulcimer, pianner, or whatever 'tis they d'call it?' said the maltster. 'Liddy saith she've a new one.' "Got a pianner?' "Ay. Seems her old uncle's things were not good enough for her. She've bought all but everything new. There's heavy chairs for the stout, weak and wiry ones for the slender; great watches, getting on to the size of clocks, to stand upon the chimbley-piece.' Pictures, for the most part wonderful frames.' " And long horse-hair settles for the drunk, with horse+ hair pillows at each end,' said Mr. Clark. " Likewise looking-glasses for the pretty, and lying books for the wicked.' A firm loud tread was now heard stamping outside; the door was opened about six inches, and somebody on the other side exclaimed -- "Neighbours, have ye got room for a few new-born lambs?' " Ay, sure, shepherd,' said the conclave. The door was flung back till it kicked the wall and trembled from top to bottom with the blow. Mr. Oak appeared in the

entry with a steaming face, hay+ bands wound about his ankles to keep out the snow, a leather strap round his waist outside the smock-frock, and looking altogether an epitome of the world's health and vigour. Four lambs hung in various embarrassing attitudes over his shoulders, and the dog George, whom Gabriel had contrived to fetch from Norcombe, stalked solemnly behind. " Well, Shepherd Oak, and how's lambing this year, if I mid say it?' inquired Joseph Poorgrass. "Terrible trying," said Oak. "I've been wet through twice a-day, either in snow or rain, this last fortnight. Cainy and I haven't tined our eyes to-night.' "A good few twins, too, I hear ?' "Too many by half. Yes ; 'tis a very queer lambing this year. We shan't have done by Lady Day.' "And last year 'twer all over by Sexajessamine Sunday,' Joseph remarked. "Bring on the rest Cain,' said Gabriel, " and then run back to the ewes. I'll follow you soon.' Cainy Ball -- a cheery-faced young lad, with a small circular orifice by way of mouth, advanced and deposited two others, and retired as he was bidden. Oak lowered the lambs from their unnatural elevation, wrapped them in hay, and placed them round the fire. " We've no lambing-hut here, as I used to have at Norcombe,' said Gabriel, " and 'tis such a plague to bring the weakly ones to a house. If 'twasn't for your place here, malter, I don't know what I should do! this keen weather. And how is it with you to-day, malter? ' " Oh, neither sick nor sorry, shepherd ; 'but no younger.' " Ay -- I understand. "Sit down, Shepherd Oak', continued the ancient man of malt. " And how was the old place at Norcombe, when ye went for your dog? I should like to see the old familiar spot ; but faith, I shouldn't" know a soul there now.' " I suppose you wouldn't. 'Tis' altered very much.' "Is it true that Dicky Hill's wooden cider-house is pulled down?'

" O yes -- years ago, and Dicky's cottage just above it.' "Well, to be sure!, " Yes ; and Tompkins's old apple-tree is rooted that used to bear two hogsheads of cider; and no help from other trees.' 'Rooted? -- you don't say it! Ah! stirring times we live in -- stirring times.' "And you can mind the old well that used to be in the middle of the place? That's turned into a solid iron pump with a large stone trough, and all complete.' "Dear, dear -- how the face of nations alter, and what we live to see nowadays! Yes -- and 'tis the same here. They've been talking but now of the mis'ess's strange doings.' " What have you been saying about her?' inquired Oak, sharply turning to the rest, and getting very warm. " These middle-aged men have been pulling her over the coals for pride and vanity,' said Mark Clark; "but I say, let her have rope enough. Bless her pretty face shouldn't I like to do so -- upon her cherry lips!' The gallant Mark Clark here made a peculiar and well known sound with his own. " Mark,' said Gabriel, sternly, 'now you mind this ! none of that dalliance-talk -- that smack-and-coddle style of yours -- about Miss Everdene. I don't allow it. Do you hear? ' " With all my heart, as I've got no chance,' replied Mr. Clark, cordially. ' I suppose you've been speaking against her? ' said Oak, turning to Joseph Poorgrass with a very grim look. "No, no -- not a word I -- 'tis a real joyful thing that she's no worse, that's what I say,' said Joseph, trembling and blushing with terror. " Matthew just said -- -- ' " Matthew Moon, what have you been saying ? ' asked Oak. 'I? Why ye know I wouldn't harm a worm -- no, not one underground worm ?' said Matthew Moon, looking very uneasy. "Well, somebody has -- and look here, neighbours.' Gabriel, though one of the quietest and most gentle men on earth, rose to the occasion, with martial promptness and vigour. "That's my fist.' Here he placed his fist, rather smaller in size than a common loaf, in the mathemarical centre of the maltster's little table, and with it gave a bump or two thereon, as if

to ensure that their eyes all thoroughly took in the idea of fistiness before he went further. "Now -- the first man in the parish that I hear prophesying bad of our mistress, why' (here the fist was raised and let fall as T'hor might have done with his hammer in assaying it) -- "he'll smell and taste that -- or I'm a Dutchman.' All earnestly expressed by their features that their minds did not wander to Holland for a moment on account of this statement, but were deploring the difference which gave rise to the figure ; and Mark Clark cried "Hear, hear; just what I should ha' said.' The dog George looked up at the same time after the shepherd's menace, and though he understood English but imperfectly, began to growl. " Now, don't ye take on so, shepherd, and sit down!' said Henery, with a deprecating peacefulness equal to anything of the kind in Christianity. "We hear that ye bc a extraordinary good and clever man, shepherd,' said Joseph Poorgrass with considerable anxiety from behind the maltster's bed+ stead whither he had retired for safety. "'Tis a great thing to be clever, I'm sure,' he added, making move+ ments associated with states of mind rather than body ; " we wish we were, don't we, neighbours ? ' "Ay, that we do, sure,' said Matthew Moon, with a small anxious laugh towards Oak, to show how very friendly disposed he was likewise. " Who's been telling you I'm clever?' said Oak. "'Tis blowed about from pillar to post quite common,' said Matthew. " We hear that ye can tell the t1me as well by the stars as we can by the sun and moon, shepherd.' " Yes, I can do a little that way,' said Gabriel, as a man of medium sentiments on the subject. names upon their waggons almost like copper-plate, with beautiful flourishes, and great long tails. A excellent fine thing for ye to be such a clever man, shepherd. Joseph Poorgrass used to prent to Farmer James Everdene's waggons before you came, and 'a could never mind which way to turn the J's and E's -- could ye, Joseph?' Joseph shook his head to express how absolute was

the fact that he couldn't. "And so you used to do 'em the wrong way, like this, didn't ye, Joseph ?' Matthew marked on the dusty floor with his whip-handle LAMES "And how Farmer James would cuss, and call thee a fool, wouldn't he, Joseph, when 'a seed his name looking so inside-out-like ?' continued Matthew Moon with feeling. 'Ay -- 'a would,' said Joseph, meekly. " But, you see, I wasn't so much to blame, for them J's and E's be such trying sons o' witches for the memory to mind whether they face backward or forward ; and I always had such a forgetful memory, too.' "'Tis a bad afiction for ye, being such a man of calamities in other ways.' " Well, 'tis ; but a happy Providence ordered that it should be no worse, and I feel my thanks. As to shepherd, there, I'm sure mis'ess ought to have made ye her baily -- such a fitting man for't as you be.' "I don't mind owning that I expected it,' said Oak, frankly. ' Indeed, I hoped for the place. At the same time, Miss Everdene has a right to be own baily if she choose -- and to keep me down to be a common shepherd only.' Oak drew a slow breath, looked sadly into the bright ashpit, and seemed lost in thoughts not of the most hopeful hue. The genial warmth of the fire now began to stimulate the nearly lifeless lambs to bleat and move their limbs briskly upon the hay, and to recognize for the first time the fact that they were born. Their noise increased to a chorus of baas, upon which Oak pulled the milk-can from before the fire, and taking a small tea-pot from the pocket of his smock-frock, filled it with milk, and taught those of the helpless creatures which were not to be restored to their dams how to drink from the spout -- a trick they acquired with astonishing aptitude. "And she don't even let ye have the skins of the dead lambs, I hear?' resumed Joseph Poorgrass, his eyes lingering on the operations of Oak with the neces+ sary melancholy. "I don't have them,' said Gabriel. "Ye be very badly used, shepherd,' hazardcd Joseph again, in

the hope of getting Oak as an ally in lamenta+ tion after all. "I think she's took against ye -- that I do.' 'O no -- not at all,' replied Gabriel, hastily, and a sigh escaped him, which the deprivation of lamb skins could hardly have caused. Before any further remark had been added a shade darkened the door, and Boldwood entered the malthouse, bestowing upon each a nod of a quality between friendli+ ness and condescension. "Ah! Oak, I thought you were here,' he said. 'I met the mail-cart ten minutes ago, and a letter was put into my hand, which I opened without reading the address. I believe it is yours. You must excuse the accident please.' "O yes -- not a bit of difference, Mr. Boldwood -- not a bit,' said Gabriel, readily. He had not a corre+ spondent on earth, nor was there a possible letter coming to him whose contents the whole parish would not have been welcome to persue. Oak stepped aside, and read the following in an unknown hand: -- " DEAR FRIEND, -- I do not know your name, but l think these few lines will reach you, which I wrote to thank you for your kindness to me the night I left Weatherbury in a reckless way. I also return the money I owe you, which you will excuse my not keeping as a gift. All has ended well, and I am happy to say I am going to be married to the young man who has courted me for some time -- Sergeant Troy, of the 11th Dragoon Guards, now quartered in this town. He would, I know, object to my having received anything except as a loan, being a man of great respecta+ bility and high honour -- indeed, a nobleman by blood. "I should be much obliged to you if you would keep the contents of this letter a secret for the present, dear friend. We mean to surprise Weatherbury by coming there soon as husband and wife, though l blush to state it to one nearly a strangen The sergeant grew up in Weatherbury. Thank+ ing you again for your kindness, "I am, your sincere well-wisher, " FANNV ROBIN.' ' Have you read it, Mr. Boldwood?' said Gabriel; "if not, you had better do so. I know you are interested in Fanny Robin.'

Boldwood read the letter and looked grieved. "Fanny -- poor Fanny! the end she is so confident of has not yet come, she should remember -- and may never come. I see she gives no address.' "What sort of a man is this Sergeant Troy?' said Gabriel. "H'm -- I'm afraid not one to build much hope upon in such a case as this,' the farmer murmured, "though he's a clever fellow, and up to everything. A slight romance attaches to him, too. His mother was a French governess, and it seems that a secret attachment existed between her and the late Lord Severn. She was married to a poor medical man, and soon after an infant was horn; and while money was forthcoming all went on well. Unfortunately for her boy, his best friends died; and he got then a situation as second clerk at a lawyer's in Casterbridge. He stayed there for some time, and might have worked himself into a dignified position of some sort had he not indulged in the wild freak of enlisting. I have much doubt if ever little Fanny will surprise us in the way she mentions -- very much doubt A silly girl! -- silly girl!' The door was hurriedly burst open again, and in came running Cainy Ball out of breath, his mouth red and open, like the bell of a penny trumpet, from which he coughed with noisy vigour and great distension of face. "Now, Cain Ball,' said Oak, sternly, "why will you run so fast and lose your breath so? I'm always telling you of it.' 'Oh -- I -- a puff of mee breath -- went -- the -- wrong way, please, Mister Oak, and made me cough -- hok -- hok!' "Well -- what have you come for?' "I've run to tell ye,' said the junior shepherd, supporting his exhausted youthful frame against the doorpost, ' that you must come directly'. Two more ewes have twinned -- that's what's the matter, Shepherd Oak.' " Oh, that's it,' said Oak, jumping up, and dimissing for the present his thoughts on poor Fanny. " You are a good boy to run and tell me, Cain, and you shall smell a large plum pudding some day as a treat. But, before we go, Cainy, bring the tarpot, and we'll mark this lot and have done with 'em.'

Oak took from his illimitable pockets a marking iron, dipped it into the pot, and imprintcd on the buttocks of the infant sheep the initials of her he delighted to muse on -- "B. E.,' which signified to all the region round that henceforth the lambs belonged to Farmer Bathsheba Everdene, and to no one else. " Now, Cainy, shoulder your two, and off Good morning, Mr. Boldwood.' The shepherd lifted the sixteen large legs and four small bodies he had himself brought, and vanished with them in the direction of the lambing field hard by -- their frames being now in a sleek and hopeful state, pleasantly contrasting with their death's-door plight of hialf an hour before. Boldwood followed him a little way up the field, hesitated, and turned back. He followed him again with a last resolve, annihilating return. On approaching the nook in which the fold was constructed, the farmer drew out-his pocket-book, unfastened-it, and allowed it to lie open on his hand. A letter was revealed -- Bath+ sheba's. "I was going to ask you, Oak,' he said, with unreal carelessness, "if you know whose writing this is? ' Oak glanced into the book, and replied instantly, with a flushed face, " Miss Everdene's.' Oak had coloured simply at the consciousness of sounding her name. He now felt a strangely distressing qualm from a new thought. ' The letter could of course be no other than anonymous, or the inquiry would not have been necessary. Boldwood mistook his confusion : sensitive persons are always ready with their "Is it I ? ' in prefercnce to objective reasoning. " The question was perfectly fair,' he returned -- and there was something incongruous in the serious eamest+ ness with which he applied himself to an argument on a valentine. " You know it is always expected that privy inquiries will be made : that's where the -- fun lies.' If the word "fun' had been "torture,' it could not have been uttered with a more constrained and restless countenance than was Boldwood's then.' Soon parting from Gabriel, the lonely and reserved man returned to his house to breakfast -- feeling twinges of shame and regret at having so far exposed his mood by those fevered

questions to a stranger. He again placed the letter on the mantelpiece, and sat down to think of the circumstances attending it by the light of Gabriel's information. ALL SAINTS' AND ALL SOULS"

ALL SAINTS' AND ALL SOULS' ON a week-day morning a small congregation, con+ sisting mainly of women and girls, rose from its knees in the mouldy nave of a church called All Saints', in the distant barrack-town before mentioned, at the end of a service without a sermon. They were about to disperse, when a smart footstep, entering the porch and coming up the central passage, arrested their attention. The step echoed with a ring unusual in a church; it was the clink of spurs. Everybody looked. A young cavalry soldier in a red uniform, with the three chevrons of a sergeant upon his sleeve, strode up the aisle, with an embarrassment which was only the more marked by the intense vigour of his step, and by the deter+ mination upon his face to show none. A slight flush had mounted his cheek by the time he had run the gauntlet between these women ; but, passing on through the chancel arch, he never paused till he came close to the altar railing. Here for a moment he stood alone. The officiating curate, who had not yet doffed his surplice, perceived the new-comer, and followed him to the communion-space. He whispered to the soldier, and then beckoned to the clerk, who in his turn whispered to an elderly woman, apparently his wife, and they also went up the chancel steps. "'Tis a wedding!' murmured some of the women, brightening. " Let's wait!' The majority again sat down. There was a creaking of machinery behind, and some of the young ones turned their heads. From the interior face of the west wall of the tower projected a little canopy with a quarter-jack and small bcll beneath it, the automaton being driven by the same clock machinery that struck the large bell in the tower. Be+ tween the tower and the church was a close sereen, the door of which was kept shut during services, hiding this

grotesque clockwork from sight. At present, how+ ever, the door was open, and the egress of the jack, the blows on the bell, and the mannikin's retreat intc.the nook again, were visible to many, and audible through+ out the church. The jack had struck half-past eleven. " Where's the woman ?" whispered some of the spectators. The young sergeant stood still with the abnormal rigidity of the old pillars around. He faced the south+ east, and was as silent as he was still. The silence grew to be a noticeable thing as the minutes went on, and nobody else appeared, and not a soul moved. The rattle of the quarter-jack again from its niche, its blows for three-quarters, its fussy retreat, were almost painfully abrupt, and caused many of the congregation to start palpably. "I wonder where the woman is!' a voice whispered again. There began now that slight shifting of feet, that artificial coughing among several, which betrays a nervous suspense. At length there was a titter. But the soldier never moved. There he stood, his face to the south-east, upright as a column, his cap in his hand. The clock ticked on. The women threw off their nervousness, and titters and giggling became more frequent. Then came a dead silence. Every one was waiting for the end. Some persons may have noticed how extraordinarily the striking of quarters. seems to quicken the flight of time. It was hardly credible that the jack had not got wrong with the minutes when the rattle began again, the puppet emerged, and the four quarters were struck fitfully as before: One could al+ most be positive that there was a malicious leer upon the hideous creature's face, and a mischievous delight in its twitchings. Then, followed the dull and remote resonance of the twelve heavy strokes in the tower above. The women were impressed, and there was no giggle this time. The clergyman glided into the vestry, and the clerk vanished. The sergeant had not yet turned ; every woman in the church was waiting to see his face, and he appeared to know it. At last he did turn, and stalked resolutely down the nave, braving them all, with a compressed lip. Two bowed and toothless old

almsmen then looked at each other and chuckled, innocently enough ; but the sound had a strange weird effect in that place. Opposite to the church was a paved square, around which several overhanging wood buildings of old time cast a picturesque shade. The young man on leaving the door went to cross the square, when, in the middle, he met a little woman. The expression of her face, which had been one of intense anxiety, sank at the sight of his nearly to terror. " Well ? ' he said, in a suppressed passion, fixedly looking at her. " O, Frank -- I made a mistake! -- I thought that church with the spire was All Saints', and I was at the door at half-past eleven to a minute as you said. waited till a quarter to twelve, and found then that I was in All Souls'. But I wasn't much frightened, for I thought it could be to-morrow as well.' "You fool, for so fooling me! But say no more.' " Shall it be to-monow, Frank ? ' she asked blankly. "To-morrow !' and he gave vent to a hoarse laugh. "I don't go through that experience again for some time, I warrant you ! ' " But after all,' she expostulated in a trembling voice, "the mistake was not such a terrible thing! Now, dear Frank, when shall it be?' "Ah, when ? God knows !' he said, with a light irony, and turning from her walked rapidly away.

IN THE MARKET-PLACE ON Saturday Boldwood was in Casterbridge market house as usual, when the disturber of his dreams entered and became visible to him. Adam had awakened from his deep sleep, and behold! there was Eve. The farmer took courage, and for the first time really looked at her. Material causes and emotional effects are not to be arranged in regular equation. The result from capital employed in the production of any movement of a mental nature is sometimes as tremendous as the cause itself is absurdly minute. When women are in a freakish mood, their usual intuition, either from carelessness or inherent defect, seemingly fails to teaeh them this, and hence it was that Bathsheba was fated to be astonished today. Boldwood looked at her -- not slily, critically, or understandingly, but blankly at gaze, in the way a reaper looks up at a passing train -- as something foreign to his element, and but dimly understood. To Bold+ wood women had been remote phenomena rather than necessary complements -- comets of such uncertain aspeet, movement, and permanence, that whether their orbits were as geometrical, unchangeable, and as subject to laws as his own, or as absolutely erratic as they superficially appeared, he had not deemed it his duty to consider. He saw her black hair, her correct facial curves and profile, and the roundness of her chin and throat. He saw then the side of her eyelids, eyes, and lashes, and the shape of her ear. Next he noticed her figure, her skirt, and the very soles of her shoes. Boldwood thought her beautiful, but wondered whether he was right in his thought, for it seemed impossible that this romance in the flesh, if so sweet as he imagined, could have

been going on long without creating a commotion of delight among men, and pro+ voking more inquiry than Bathsheba had done, even though that was not a little. To the best of his judg+ ment neither nature nor art could improve this perfect one of an imperfect many. His heart began to move within him. Boldwood, it must be remembered, though forty years of age, had never before inspected a woman with the very centre and force of his glance; they had struck upon all his senses at wide angles. Was she really beautiful? He could not assure himself that his opinion was true even now. He fur+ tively said to a neighbour, 'Is Miss Everdene considered handsome?' "0 yes; she was a good deal 'notied the first time she came, if you remember. A very handsome girl indeed.' A man is never more credulous than in receiving favourable opinions on the beauty of a woman he is half, or quite, in love with; a mere child's word on the point has the weight of an R.A.'s. Boldwood was satisfied now. And this charming woman had in effect said to him, "Marry me.' Why should she have done that strange thing ? Boldwood's blindness to the difference between approving of what circumstances suggest, and originating what they do not suggest, was well matched by Bathsheba's insensibility to the possibly great issues of little beginnings. She was at this moment coolly dealing with a dashing young farmer, adding up accounts with him as indiffer+ ently as if his face had been the pages of a ledger. It was evident that such a nature as his had no attraction for a woman of Bathsheba's taste. But Boldwood grew hot down to his hands with an incipient jealousy; he trod for the first time the threshold of "the injured lover's hell.' His first impulse was to go and thrust himself between them. This could be done, but only in one way -- by asking to see a sample of her corn. Boldwood renounced the idea. He could not make the request; it was debasing loveliness to ask it to buy and sell, and jarred with his conceptions of her. All this time Bathsheba was conscious of having broken into that dignified stronghold at last. His eyes, she knew, were

following her everywhere. This was a triumph; and had it come naturally, such a triumph would have been the sweeter to her for this piquing delay. But it had been brought about by misdirected ingenuity, and she valued it only as she valued an artificial flower or a wax fruit. Being a woman with some good sense in reasoning on subjects wherein her heart was not involved, Bath+ sheba genuinely repented that a freak which had owed its existence as much to Liddy as to herself, should ever have been undertaken, to disturb the placidity of a man she respected too highly to deliberately tease. She that day nearly formed the intention of begging his pardon on the very next occasion of their meeting. The worst features of this arrangement were that, if he thought she ridiculed him, an apology would in+ crease the offence by being disbelieved; and if he thought she wanted him to woo her, it would read like additional evidence of her forwardness.

BOLDWOOD IN MEDITATION -- REGRET BOLDWOOD was tenant of what was called Little Weatherbury Farm, and his person was the nearest ap+ proach to aristocracy that this remoter quarter of the parish could boast of. Genteel strangers, whose god was their town, who might happen to be compelled to linger about this nook for a day, heard the sound of light wheels, and prayed to see good society, to the degree of a solitary lord, or squire at the very least, but it was only Mr. Boldwood going out for the day. They heard the sound of wheels yet once more, and were re-animated to expectancy : it was only Mr. Bold+ wood coming home again. His house stood recessed from the road, and the stables, which are to a farm what a fireplace is to a room, were behind, their lower portions being lost amid bushes of laurel. Inside the blue door, open half-way down, were to be seen at this time the backs and tails of half-a-dozen warm and contented horses standing in their stalls; and as thus viewed, they pre+ sented alternations of roan and bay, in shapes like a Moorish arch, the tail being a streak down the midst of each. Over these, and lost to the eye gazing in from the outer light, the mouths of the same animals could be heard busily sustaining the above-named warmth and plumpness by quantities of oats and hay. The restless and shadowy figure of a colt wandered about a loose-box at the end, whilst the steady grind of all the eaters was occasionally diversified by the rattle of a rope or the stamp of a foot. Pacing up and down at the heels of the animals was Farmer Boldwood himself. This place was his almonry and cloister in one : here, after looking to the feeding of his four-footed dependants, the celibate would walk and meditate of an evening till the moon's rays streamed in through the cobwebbed windows, or total darkness enveloped the scene.

His square-framed perpendicularity showed more fully now than in the crowd and bustle of the market-house. In this meditative walk his foot met the floor with heel and toe simultaneously, and his fine reddish-fleshed face was bent downwards just enough to render obscure the still mouth and the well-rounded though rather prominent and broad chin. A few clear and thread-like horizontal lines were the only interruption to the otherwise smooth surface of his large forehead. The phases of Boldwood's life were ordinary enough, but his was not an ordinary nature. That stillness, which struck casual observers more than anything else in his character and habit, and seemed so precisely like the rest of inanition, may have been the perfect balance of enormous antagonistic forces -- positives and negatives in fine adjustment. His equilibrium disturbed, he was in extremity at once. If an emotion possessed him at all, it ruled him; a feeling not mastering him was entirely latent. Stagnant or rapid, it was never slow. He was always hit mortally, or he was missed. He had no light and careless touches in his constitu+ tion, either for good or for evil. Stern in the outlines of action, mild in the details, he was serious throughout all. He saw no absurd sides to the follies of life, and thus, though not quite companionable in the eyes of merry men and scoffers, and those to whom all things show life as a jest, he was not intolerable to the earnest and those acquainted with grief. Being a man -who read all the dramas of life seriously, if he failed to please when they were comedies, there was no frivolous treat+ ment to reproach him for when they chanced to end tragically. Bathsheba was far from dreaming that the dark and silent shape upon which she had so carelessly thrown a seed was a hotbed of tropic intensity. Had she known Boldwood's moods, her blame would have been fearful, and the stain upon her heart ineradicable. Moreover, had she known her present power for good or evil over this man, she would have trembled at her responsibility. Luckily for her present, unluckily for her future tran+ quillity, her understanding had not yet told her what Boldwood was. Nobody knew entirely ; for though it was possible to form guesses concerning his wild 'capa+

bilities from old floodmarks faintly visible, he had never been seen at the high tides which caused them. Farmer Boldwood came to the stable-door and looked forth across the level fields. Beyond the first enclosure was a hedge, and on the other side of this a meadow belonging to Bathsheba's farm. It was now early spring -- the time of going to grass with the sheep, when they have the first feed of the meadows, before these are laid up for mowing. The wind, which had been blowing east for several weeks, had veered to the southward, and the middle of spring had come abruptly -- almost without a beginning. It was that period in the vernal quarter when we map suppose the Dryads to be waking for the season. The vegetable world begins to move and swell and the saps to rise, till in the completest silence of lone gardens and trackless plantations, where- everything seems -help+ less and still after the bond and slavery of frost, there are bustlings, strainings, united thrusts, and pulls-all+ together, in comparison with which the powerful tugs of cranes and pulleys in a noisy city are but. pigmy efforts. "Boldwood, looking into the distant meadows, saw there three figures. They were those of Miss' Everdene, Shepherd Oak, and Cainy Ball. When Bathsheba's figure shone upon the farmer's eyes it lighted him up as the moon lights up a great tower. A man's body is as the shell; or the tablet, of his soul, as he is reserved or ingenuous, overflowing or self-contained. There was a change in Boldwood's exterior from its former impassibleness ; and his face showed that he was now living outside his defences for the first time, and with a fearful sense of exposure. It is the usual experience of strong natures when they love. At last he arrived at a conclusion. It was to go across and inquire boldly of her. The insulation of his heart by reserve during these many years, without a channel of any kind for disposable emotion, had worked its effect. It has been observed more than once that the causes of love are chiefly

subjective, and Boldwood was a living testimony to the truth of the proposition. No mother existed to absorb his devotion, no sister for his tenderness, no idle ties for sense. He became surcharged with the compound, which was genuine lover's love. He approached the gate of the meadow. Beyond it the ground was melodious with ripples, and the sky with larks; the low bleating of the flock mingling with both. Mistress and man were engaged in the operation of making a lamb "take,' which is performed whenever an ewe has lost her own offspring, one of the twins of another ewe being given her as a substitute. Gabriel had skinned the dead lamb, and was tying the skin over the body of the live lamb, in the customary manner, whilst Bathsheba was holding open a little pen of four hurdles, into which the Mother and foisted lamb were driven, where they would remain till the old sheep conceived an affection for the young one. Bathsheba looked up at the completion of the manouvre, and saw the farmer by the gate, where he was overhung by a willow tree in full bloom. Gabriel, to whom her face was as the uncertain glory of an April day, was ever regardful of its faintest changes, and instantly discerned thereon the mark of some influence from without, in the form of a keenly self-conscious reddening. He also turned and beheld Boldwood. At onee connecting these signs with the letter Bold+ wood had shown him, Gabriel suspected her of some coquettish procedure begun by that means, and carried on since, he knew not how. Farmer Boldwood had read the pantomime denoting that they were aware of his presence, and the perception was as too much light turned upon his new sensibility. He was still in the road, and by moving on he hoped that neither would recognize that he had originally intended to enter the field. He passed by with an utter and overwhelming sensation of ignorance, shyness, and doubt. Perhaps in her manner there were signs that she wished to see him -- perhaps not -- he could not read a woman. The cabala of this erotic philosophy seemed to consist of the subtlest meanings expressed in misleading ways.

Every turn, look, word, and accent contained a mystery quite distinct from its obvious import, and not one had ever been pondered by him until now. As for Bathsheba, she was not deceived into the belief that Farmer Boldwood had walked by on business or in idleness. She collected the probabilities of the case, and concluded that she was herself responsible for Boldwood's appearance there. It troubled her much to see what a great flame a little Wildfire was likely to kindle. Bathsheba was no schemer for marriage, nor was she deliberately a trifler with the affections of men, and a censor's experience on seeing an actual flirt after observing her would have been a feeling of surprise that Bathsheba could be so different from such a one, and yet so like what a flirt is supposed to be. She resolved never again, by look or by sign, to interrupt the steady flow of this man's life. But a resolution to avoid an evil is seldom framed till the evil is so far advanced as to make avoidance impossible.

THE SHEEP-WASHING -- THE OFFER BOLDWOOD did eventually call upon her. She was not at home. " Of course not,' he murmured. In con+ templating Bathsheba as a woman, he had forgotten the accidents of her position as an agriculturist -- that being as much of a farmer, and as extensive a farmer, as himself, her probable whereabouts was out-of-dooTs at this time of the year. This, and the other oversights Boldwood was guilty of, were natural to the mood, and still more natural to the circumstances. The great aids to idealization in love were present here : occasional observation of her from a distance, and the absence of social intercourse with her -- visual familiarity, oral strangeness. The smaller human elements were kept out of sight ; the pettinesses that enter so largely into all earthly living and doing were disguised by the accident of lover and loved-one not being on visiting terms ; and there was hardly awakened a thought in Boldwood that sorry household realities appertained to her, or that she, like all others, had moments of commonplace, when to be least plainly seen was to be most prettily remembered. Thus a mild sort of apotheosis took place in his fancy, whilst she still lived and breathed within his own horizon, a troubled creature like himself. It was the end of May when the farmer determined to be no longer repulsed by trivialities or distracted by suspense. He had by this time grown used to being in love; the passion now startled him less even when it tortured him more, and he felt himself adequate to the situation. On inquiring for her at her house they had told him she was at the sheepwashing, and he went off to seek her there. The sheep-washing pool was a perfectly circular basin of brickwork in the meadows, full of the clearest water. To birds on the wing its glassy surface, reflecting the light sky, must have been

visible for miles around as a glistening Cyclops' eye in a green face. The grass about the margin at this season was a sight to remember long -- in a minor sort of way. Its activity in sucking the moisture from the rich damp sod. was almost a pro+ cess observable by the eye. The outskirts of this level water-meadow were diversified by rounded and hollow pastures, where just now every flower that was not a buttercup was a daisy. The river slid along noiselessly as a shade, the swelling reeds and sedge forming a flexible palisade upon its moist brink. To the north of the mead were trees, the leaves of which were new, soft, and moist, not yet having stiffened and darkened under summer sun and drought, their colour being yellow beside a green -- green beside a yellow. From the recesses of this knot of foliage the loud notes of three cuckoos were resounding through the still air. Boldwood went meditating down the slopes with his eyes on his boots, which the yellow pollen from the buttercups had bronzed in artistic gradations. A tribu+ tary of the main stream flowed through the basin of the pool by an inlet and outlet at opposite points of its diameter. Shepherd Oak, Jan Coggan, Moon, Poor+ grass, Cain Ball, and several others were assembled here, all dripping wet to the very roots of their hair, and Bathsheba was standing by in a new riding-habit -- the most elegant she had ever worn -- the reins of her horse being looped over her arm. Flagons of cider were rolling about upon the green. The meek sheep were pushed into the pool by Coggan and Matthew Moon, who stood by the lower hatch, immersed to their waists; then Gabriel, who stood on the brink, thrust them under as they swam along, with an instrument like a crutch, formed for the purpose, and also for assisting the exhausted animals when the wool became saturated and they began to sink. They were let out against the stream, and through the upper opening, all impurities flowing away below. Cainy Ball and Joseph, who performed this latter operation, were if possible wetter than the rest ; they resembled dolphins under a fountain, every protuberance and angle of their clothes dribbling forth a small rill.

Boldwood came close and bade her good-morning, with such constraint that she could not but think he had stepped across to the washing for its own sake, hoping not to find her there ; more, she fancied his brow severe and his eye slighting. Bathsheba immediately contrived to withdraw, and glided along by the river till she was a stone's throw off. She heard footsteps brushing the grass, and had a consciousness that love was encircling her like a perfume. Instead of turning or waiting, Bathsheba went further among the high sedges, but Boldwood seemed determined, and pressed on till they were completely past the bend of the river. Here, without being seen, they could hear the splashing and shouts of the washers above. "Miss Everdene!' said the farmer. She trembled, turned, and said 'Good morning.' His tone was so utterly removed from all she had expected as a beginning. It was lowness and quiet accentuated : an emphasis of deep meanings, their form, at the same time, being scarcely expressed. Silence has sometimes a remarkable power of showing itself as the disembodied soul of feeling wandering without its carcase, and it is then more impressive than speech. In the same way, to say a little is often to tell more than to say a great deal. Boldwood told everything in that word. As the conseiousness expands on learning that what was fancied to be the rumble of wheels is the reverbera+ tion of thunder, so did Bathsheba's at her intuitive conviction. 'I feel -- almost too much -- to think,' he said, with a solemn simplicity. "I have come to speak to you with+ out preface. My life is not my own since I have beheld you clearly, Miss Everdene -- I come to make you an offer of marriage.' Bathsheba tried to preserve an absolutely neutral countenance, and all the motion she made was that of closing lips which had previously been a little parted. "I am now forty-one years old,' he went on. "I may have been called a confirmed bachelor, and I was a confirmed bachelor. I had never any views of myself as a husband in my earlier days, nor have I made any calculation on the subject since I have been older. But we all change, and my change, in this matter,

came with seeing you. I have felt lately, more and more, that my present way of living is bad in every respect. Beyond all things, I want you as my wife.' "I feel, Mr. Boldwood, that though I respect you much, I do not feel -- what would justify me to -- in accepting your offer,' she stammered. This giving back of dignity for dignity seemed to open the sluices of feeling that Boldwood had as yet kept closed. " My life is a burden without you,' he exclaimed, in a low voice. "I want you -- I want you to let me say I love you again and again!' Bathsheba answered nothing, and the mare upon her arm seemed so impressed that instead of cropping the herbage she looked up. "I think and hope you care enough for me to listen to what I have to tell!" Bathsheba's momentary impulse at hearing this was to ask why he thought that, till she remembered that, far from being a conceited assumption on Boldwood's part, it was but the natural conclusion of serious reflec+ tion based on deceptive premises of her own offering. "I wish I could say courteous flatteries to you,' the farmer continued in an easier tone, " and put my rugged feeling into a graceful shape: but I have neither power nor patience to learn such things. I want you for my wife -- so wildly that no other feeling can abide in me; but I should not have spoken out had I not been led to hope.' "The valentine again! O that valentine!' she said to herself, but not a word to him. "If you can love me say so, Miss Everdene. If not -- don't say no!' "Mr. Boldwood, it is painful to have to say I am surprised, so that I don't know how to answer you with propriety and respect -- but am only just able to speak out my feeling -- I mean my meaning; that I am afraid I can't marry you, much as I respect you. You are too dignified for me to suit you, sir.' "But, Miss Everdene!' "I -- I didn't -- I know I ought never to have dreamt of sending

that valentine -- forgive me, sir -- it was a wanton thing which no woman with any self-respect should have done. If you will only pardon my thought+ lessness, I promise never to -- -- ' " No, no, no. Don't say thoughtlessness! Make me think it was something more -- that it was a sort of prophetic instinct -- the beginning of a feeling that you would like me. You torture me to say it was done in thoughtlessness -- I never thought of it in that light, and I can't endure it. Ah ! I wish I knew how to win you! but that I can't do -- I can only ask if I have already got you. If I have not, and it is not true that you have come unwittingly to me as I have to you, I can say no more.' "I have not fallen in love with you, Mr. Boldwood -- certainly I must say that.' She allowed a very small smile to creep for the first time over her serious face in saying this, and the white row of upper teeth, and keenly+ cut lips already noticed, suggested an idea of heartless+ ness, which was immediately contradicted by the pleasant eyes. "But you will just think -- in kindness and conde+ scension think -- if you cannot bear with me as a husband! I fear I am too old for you, but believe me I will take more care of you than would many a man of your own age. I will protect and cherish you with all my strength -- I will indeed! You shall have no cares -- be worried by no household affairs, and live quite at ease, Miss Everdene. The dairy superintendence shall be done by a man -- I can afford it will -- you shall never have so much as to look out of doors at haymaking time, or to think of weather in the harvest. I rather cling; to the chaise, because it is he same my poor father and mother drove, but if you don't like it I will sell it, and you shall have a pony-carriage of your own. I cannot say how far above every other idea and object on earth you seem to me -- nobody knows -- God only knows -- how much you are to me!' Bathsheba's heart was young, and it swelled with sympathy for the deep-natured man who spoke so simply. "Don't say it! don't! I cannot bear you to feel so much, and me to feel nothing. And I am afraid they will notice us, Mr. Boldwood. Will you let the matter rest now? I cannot think

collectedly. I did not know you were going to say this to me. 0, I am wicked to have made you suffer so!' She was frightened as well as agitated at his vehemence. "Say then, that you don't absolutely refuse. Do not quite refuse?' "I can do nothing. I cannot answer.' "I may speak to you again on the subject?' "Yes.' "I may think of you?' "Yes, I suppose you may think of me.' "And hope to obtain you?' "No -- do not hope! Let us go on.' "I will call upon you again to-morrow.' "No -- please not. Give me time.' "Yes -- I will give you any time,' he said earnestly and gratefully. "I am happier now.' "No -- I beg you! Don't be happier if happiness only comes from my agreeing. Be neutral, Mr. Bold+ wood! I must think.' "I will wait,' he said. And then she turned away. Boldwood dropped his gaze to the ground, and stood long like a man who did not know where he was. Realities then returned upon him like the pain of a wound received in an excitement which eclipses it, and he, too, then went on.

PERPLEXITy -- GRINDING THE SHEARS -- A QUARREL "HE is so disinterested and kind to offer me all that I can desire,' Bathsheba mused. Yet Farmer Boldwood, whether by nature kind or the reverse to kind, did not exercise kindness, here. The rarest offerings of the purest loves are but a self+ indulgence, and no generosity at all. Bathsheba, not being the least in love with him, was eventually able to look calmly at his offer. It was one which many women of her own station in the neighbour+ hood, and not a few of higher rank, would have been wild to accept and proud to publish. In every point of view, ranging from politic to passionate, it was desirable that she, a lonely girl, should marry, and marry this earnest, well-to-do, and respected man. He was close to her doors: his standing was sufficient: his qualities were even supererogatory. Had she felt, which she did not, any wish whatever for the married state in the abstract, she could not reasonably have rejected him, being a woman who frequently appealed to her under, standing for deliverance from her whims. Boldwood as a means to marriage was unexceptionable: she esteemed and liked him, yet she did not want him. It appears that ordinary men take wives because possession is not possible without marriage, and that ordinary women accept husbands because marriage is not possible with, out possession; with totally differing aims the method is the same on both sides. But the understood incentive on the woman's part was wanting here. Besides, Bath+ sheba's position as absolute mistress of a farm and house was a novel one, and the novelty had not yet begun to wear off. But a disquiet filled her which was somewhat to her credit, for it would have affected few. Beyond the men+ tioned reasons with which she combated her objections, she had a strong

feeling that, having been the one who began the game, she ought in honesty to accept the conse, quences. Still the reluctance remained. She said in the same breath that it would be ungenerous not to marry Boldwood, and that she couldn't do it to save her life. Bathsheba's was an impulsive nature under a delibera, tive aspect. An Elizabeth in brain and a Mary Stuart in spirit, she often performed actions of the greatest temerity with a manner of extreme discretion. Many of her thoughts were perfect syllogisms; unluckily they always remained thoughts. Only a few were irrational assumptions; but, unfortunately, they were the ones which most frequently grew into deeds. The next day to that of the declaration she found Gabriel Oak at the bottom of her garden, grinding his shears for the sheep-shearing. All the surrounding cottages were more or less scenes of the same operation; the scurr of whetting spread into the sky from all parts of the village as from an armury previous to a campaign. Peace and war kiss each other at their hours of prepara+ tion -- sickles, scythes, shears, and pruning-hooks, ranking with swords, bayonets, and lances, in their common necessity for point and edge. Cainy Ball turned the handle of Gabriel's grinstone, his head performing a melancoly see-saw up and down with each turn of the wheel. Oak stood somewhat as Eros is represented when in the act of sharpening his arrows: his figure slightly bent, the weight of his body thrown over on the shears, and his head balanced side+ ways, with a critical compression of the lips and contrac+ tion of the eyelids to crown the attitude. His mistress came up and looked upon them in silence for a minute or two; then she said -- "Cain, go to the lower mead and catch the bay mare. I'll turn the winch of the grindstone. I want to speak to you, Gabriel. Cain departed, and Bathsheba took the handle. Gabriel had glanced up in intense surprise, quelled its expression, and looked down again. Bathsheba turned the winch, and Gabriel applied the shears. The peculiar motion involved in turning a wheel has a wonderful tendency to benumb the mind. It is a sort of

attenuated variety of Ixion's punishment, and contributes a dismal chapter to the history of heavy, and the body's centre of gravity seems to settle by degrees in a leaden lump somewhere be+ tween the eyebrows and the crown. Bathsheba felt the unpleasant symptoms after two or three dozen turns. "Will you turn, Gabriel, and let me hold the shears?" she said. "My head is in a'whirl, and I can't talk. Gabriel turned. Bathsheba then began, with some awkwardness, allowing her thoughts to stray occasion+ ally from her story to attend to the shears, which required a little nicety in sharpening. "I wanted to ask you if the men made any observa+ tions on my going behind the sedge with Mr. Boldwood yesterday?' "Yes, they did,' said Gabriel. "You don't hold the shears right, miss -- I knew you wouldn't know the way -- hold like this.' He relinquished the winch, and inclosing her two hands completely i his own (taking each as we some+ times slasp a child's hand in teaching him to write), grasped the shears with her. "Incline the edge so,' he said. Hands and shears were inclined to suit the words, and held thus for a peculiarly long time by the in+ structor as he spoke. "That will do,' exclaimed Bathsheba. "Loose my hands. I won't have them held! Turn the winch.' Gabriel freed her hands quietly, retired to his handle, and the grinding went on. "Did the men think it odd?' she said again. "Odd was not the idea, miss.' "What did they say?' "That Farmer Boldwood's name and your own were likely to be flung over pulpit together before the year was out.' "I thought so by the look of them! Why, there's nothing in it. A more foolish remark was never made, and I want you to contradict it! that's what I came for.' Gabriel looked incredulous and sad, but between his moments of incredulity, relieved. "They must have heard our conversation,' she continued.

"Well, then, Bathsheba!' said Oak, stopping the handle, and gazing into her face with astonishment. "Miss Everdene, you mean," she said, with dignity. "I mean this, that if Mr. Boldwood really spoke of marriage, I bain't going to tell a story and say he didn't to please you. I have already tried to please you too much for my own good!' Hathsheba regarded him with round-eyed perplexity. She did not know whether to pity him for disappointed love of her, or to be angry with him for having got over it -- his tone being ambiguous. "I said I wanted you just to mention that it was not true I was going to be married to him,' she mur+ mured, with a slight decline in her assurance. "I can say that to them if you wish, Miss Everdene. And I could likewise give an opinion to 'ee on what you have done.' "I daresay. But I don't want your opinion.' "I suppose not,' said Gabriel bitterly, and going on with his turning, his words rising and falling in a regular swell and cadence as he stooped or rose with the winch, which directed them, according to his position, perpendiculary into the earth, or horizontally along the garden, his eyes being fixed on a leaf upon the ground. With Bathsheba a hastened act was a rash act; but, as does not always happen, time gained was prudence insured. It must be added, however, that time was very seldom gained. At this period the single opinion in the parish on herself and her doings that she valued as sounder than her own was Gabriel Oak's. And the outspoken honesty of his character was such- that on any subject even that of her love for, or marriage with, another man, the same disinter+ estedness of opinion might be calculated on, and be had for the asking. Thoroughly convinced of the impossibility of his own suit, a high resolve constrained him not to injure that of another. This is a lover's most stoical virtue, as the lack of it is a lover's most venial sin. Hnowing he would reply truly, she asked the question, painful as she must have known the sub+ ject would be. Such is the selfishness of some charm+ ing women. Perhaps it was some excuse for her thus torturing honesty to her own advantage, that she had

absolutely no other sound judgment within easy reach. "Well, what is your opinion of my conduct,' she said, quietly. "That it is unworthy of any thoughtful, and meek, and comely woman.' In an instant Bathsheba's face coloured with the angry crimson of a danby sunset. But she forbore to utter this feeling, and the reticence of her tongue only made the loquacity of her face the more notice+ able. The next thing Gabriel did was to make a mistake. "Perhaps you don't like the rudeness of my repri+ manding you, for I know it is rudeness; but I thought it would do good.' She instantly replied sarcastically -- "On the contrary, my opinion of you is so low, that I see in your abuse the praise of discerning people!' "I am glad you don't mind it, for I said it honestly and with every serious meaning.' "I see. But, unfortunately, when you try not to speak in jest you are amusing -- just as when you wish to avoid seriousness you sometimes say a sensible word It was a hard hit, but Bathsheba had unmistakably lost her temper, and on that account Gabriel had never in his life kept his own better. He said nothing. She then broke out -- "I may ask, I suppose, where in particular my unworthiness lies? In my not marrying you, perhaps! "Not by any means,' said Gabriel quietly. "I have long given up thinking of that matter.' "Or wishing it, I suppose,' she said; and it was apparent that she expected an unhesitating denial of this supposition. Whatever Gabriel felt, he coolly echoed her words -- "Or wishing it either.' A woman may be treated with a bitterness which is sweet to her, and with a rudeness which is not offensive. Bathsheba would have submitted to an indignant chastisement for her levity had Gabriel pro+ tested that he was loving her at the same time; the impetuosity of passion unrequited is bearable, even if it stings and anathematizes there is a triumph in the humiliation, and a tenderness in the strife. This was what she had been expecting, and what she had not got. To be lectured

because the lecturer saw her in the cold morning light of open-shuttered disillusion was exasperating. He had not finished, either. He continued in a more agitated voice: -- "My opinion is (since you ask it) that you are greatly to blame for playing pranks upon a man like Mr. Boldwood, merely as a pastime. Leading on a man you don't care for is not a praiseworthy action. And even, Miss Everdene, if you seriously inclined towards him, you might have let him find it out in some way of true loving-kindness, and not by sending him a valentine's letter.' Bathsheba laid down the shears. "I cannot allow any man to -- to criticise my private Conduct!' she exclaimed. "Nor will I for a minute. So you'll please leave the farm at the end of the week!' It may have been a peculiarity -- at any rate it was a fact -- that when Bathsheba was swayed by an emotion of an earthly sort her lower lip trembled: when by a refined emotion, her upper or heavenward one. Her nether lip quivered now. "Very well, so I will,' said Gabriel calmly. He had been held to her by a beautiful thread which it pained him to spoil by breaking, rather than by a chain he could not break. "I should be even better pleased to go at once,' he added. "Go at once then, in Heaven's name!' said she,her eyes flashing at his, though never meeting them. "Don't let me see your face any more.' "Very well, Miss Everdene -- so it shall be.' And he took his shears and went away from her in placid dignity, as Moses left the presence of Pharaoh.

TROUBLES IN THE FOLD -- A MESSAGE GABRIEL OAK had ceased to feed the Weatherbury flock for about four-and-twenty hours, when on Sunday afternoon the elderly gentlemen Joseph Poorgrass, Matthew Moon, Fray, and half-a-dozen others, came running up to the house of the mistress of the Upper Farm. "Whatever is the matter, men?' she said, meeting them at the door just as she was coming out on her way to church, and ceasing in a moment from the close compression of her two red lips, with which she had accompanied the exertion of pelling on a tight glove. "Sixty!' said Joseph Poorgrass. "Seventy!' said Moon. "Fifty-nine!' said Susan Tall's husband. " -- Sheep have broke fence,' said Fray. " -- And got into a field of young clover,' said Tall. " -- Young clover!' said Moon. " -- Clover!' said Joseph Poorgrass. "And they be getting blasted,' said Henery Fray. "That they be,' said Joseph. "And will all die as dead as nits, if they bain't got out and cured!'said Tall. Joseph's countenance was drawn into lines and puckers by his concern. Fray's forehead was wrinkled both perpendicularly and crosswise, after the pattern of a portcullis, expressive of a double despair. Laban Tall's lips were thin, and his face were rigid. Matthew's jaws sank, and his eyes turned whichever way the strongest muscle happened to pull them. "Yes,' said Joseph, "and I was sitting at home, looking for Ephesians, and says I to myself, "'Tis nothing but Corinthians and Thessalonians in this danged Testament,'' when

who should come in but Henery there: ""Joseph,'' he said, ""the sheep have With Bathsheba it was a moment when thought was blasted theirselves -- -''' With Bathsheba it was a moment when thought was speech and speech exclamation. Moreover, she had hardly recovered her equanimity since the disturbance which she had suffered from Oak's remarks. 'Thats enought -- that's enough! -- oh, you fools!' she cried, throwing the parasol and Prayer-book into the passage, and running out of doors in the direction signified. "To come to me, and not go and get them out directly! Oh, the stupid numskulls!' Her eyes were at their darkest and brightest now. Bathsheba's beauty belonged rather to the demonian than to the angelic school, she never looked so well as when she was angry -- and particularly when the effect was heightened by a rather dashing velvet dress, care+ fully put on before a glass. All the ancient men ran in a jumbled throng after her to the clover-field, Joseph sinking down in the midst when about half-way, like an individual withering in a world which was more and more insupportable. Having once received the stimulus that her presence always gave them they went round among the sheep with a will. The majority of the afflicted animals were lying down, and could not be stirred. These were bodily lifted out, and the others driven into the adjoining field. Here, after the lapse of a few minutes, several more fell down, and lay helpless and livid as the rest. Bathsheba, with a sad, bursting heart, looked at these primest specimens of her prime flock as they rolled there -- Swoln with wind and the rank mist they drew. Many of them foamed at the mouth, their breathing being quick and short, whilst the bodies of all were fearfully distended. "O, what can I do, what can I do!' said Bathsheba, helplessly. "Sheep are such unfortunate animals! -- there's always something happening to them! I never knew a flock pass a year without getting into some scrape or other.' "There's only one way of saving them,' said Tall.

"What way? Tell me quick!' "They must be pierced in the side with a thing made on purpose.' "Can you do it? Can I?' "No, ma'am. We can't, nor you neither. It must be done in a particular spot. If ye go to the right or left but an inch you stab the ewe and kill her. Not even a shepherd can do it, as a rule.' "Then they must die,' she said, in a resigned tone. "Only one man in the neighbourhood knows the way,' said Joseph, now just come up. "He could cure 'em all if he were here.' "Who is he? Let's get him!' "Shepherd Oak," said Matthew. "Ah, he's a clever man in talents!' "Ah, that he is so!' said Joseph Poorgrass. "True -- he's the man,' said Laban Tall. "How dare you name that man in my presence!' she said excitedly. "I told you never to allude to him, nor shall you if you stay with me. Ah!' she added, brighten+ ing, "Farmer Boldwood knows!' "0 no, ma'am' said Matthew. "Two of his store ewes got into some vetches t'other day, and were just like these. He sent a man on horseback here post-haste for Gable, and Gable went and saved 'em, Farmer Boldwood hev got the thing they do it with. 'Tis a holler pipe, with a sharp pricker inside. Isn't it, Joseph?' "Ay -- a holler pipe,' echoed Joseph. "That's what 'tis.' "Ay, sure -- that's the machine,' chimed in Henery Fray, reflectively, with an Oriental indifference to the flight of time. "Well," burst out Bathsheba, "don't stand there with your ""ayes'' and your ""sures,'' talking at me! Get somebody to cure the sheep instantly!' All then stalked or in eonsternation, to get some+ body as directed, without any idea of who it was to be. In a minute they had vanished through the gate,.and she stood alone with the dying flock. "Never will I send for him never!' she said firmly.

One of the ewes here contracted its muscles horribly, extended itself, and jumped high into the air. The leap was an astonishing one. The ewe fell heavily, and lay still. Bathsheba went up to it. The sheep was dead. "O, what shall I do -- what shall I do!' she again exclaimed, wringing her hands. "I won't send for him. No, I won't!' The most vigorous expression of a resolution does not always coinicide with the greatest vigour of the resolution itself. It is often flung out as a sort of prop to support a decaying conviction which, whilst strong, required no enunciation to prove it so. The "No, I won't' of Bathsheba meant virtually, "I think I must.' She followed her assistants through the gate, and lifted her hand to one of them. Laban answered to her signal. "Where is Oak staying?' "Across the valley at Nest Cottage!' "Jump on the bay mare, and ride across, and say he must return instantly -- that I say so.' Tall scrambled off to the field, and in two minutes was on Poll, the bay, bare-backed, and with only a halter by way of rein. He diminished down the hill. Bathsheba watched. So did all the rest. Tall cantered along the bridle-path through Sixteen Acres, Sheeplands, Middle Field The Flats, Cappel's Piece, shrank almost to a point, crossed the bridge, and ascended from the valley through Springmead and Whitepits on the other side. The cottage to which Gabriel had retired before taking his final departure from the locality was visible as a white spot on the opposite hill, backed by blue firs. Bathsheba walked up and down. The men entered the field and endeavoured to ease the anguish of the dumb creatures by rubbing them. Nothing availed. Bathsheba continued walking. The horse was seen descending the hill, and the wearisome series had to be repeated in reverse order: Whitepits, Springmead, Cappel's Piece, The Flats, Middle Field, Sheeplands, Sixteen Acres. She hoped Tall had had presence of mind enough to give the mare up to Gabriel, and return himself on foot. The rider neared them. It was Tall.

"O, what folly!' said Bathsheba. Gabriel was not visible anywhere. "Perhaps he is already gone!' she said. Tall came into the inclosure, and leapt off, his face tragic as Morton's after the battle of Shrewsbury. "Well?' said Bathsheba, unwilling to believe that her verbal lettre-de-cachet could possibly have miscarried. "He says beggars mustn't be choosers,' replied Laban. "What!' said the young farmer, opening her eyes and drawing in her breath for an outburst. Joseph Poorgrass retired a few steps behind a hurdle. "He says he shall not come onless you request en to come civilly and in a proper manner, as becomes any 'ooman begging a favour.' "Oh, oh, that's his answer! Where does he get his airs? Who am I, then, to be treated like that? Shall I beg to a man who has begged to me?' Another of the flock sprang into the air, and fell dead. The men looked grave, as if they suppressed opinion. Bathsheba turned aside, her eyes full of tears. The strait she was in through pride and shrewishness could not be disguised longer: she burst out crying bitterly; they all saw it; and she attempted no further concealment. "I wouldn't cry about it, miss,' said William Small+ bury, compassionately. "Why not ask him softer like? I'm sure he'd come then. Gable is a true man in that way.' Bathsheba checked her grief and wiped her eyes. "O, it is a wicked cruelty to me -- it is -- it is!' she murmured. "And he drives me to do what I wouldn't; yes, he does ! -- Tall, come indoors.' After this collapse, not very dignified for the head of an establishment, she went into the house, Tall at her heels. Here she sat down and hastily scribbled a note between the small convulsive sobs of convalescence which follow a fit of crying as a ground-swell follows a storm. The note was none the less polite for being written in a hurry. She held it at a distance, was about to fold it, then added these words at the bottom: -- "Do not desert me, Gabriel!'

She looked a little redder in refolding it, and closed her lips, as if thereby to suspend till too late the action of conscience in examining whether such strategy were justifiable. The note was despatched as the message had been, and Bathsheba waited indoors for the result. It was an anxious quarter of an hour that intervened between the messenger's departure and the sound of the horse's tramp again outside. She- could not watch this time, but, leaning over the old bureau at which she had written the letter, closed her eyes, as if to keep out both hope and fear. The case, however, was a promising one. Gabriel was not angry: he was simply neutral, although her first command had been so haughty. Such imperiousness would have damned a little less beauty; and on the other hand, such beauty would have redeemed a little less imperiousness. She went out when the horse was heard, and looked up. A mounted figure passed between her and the sky, and drew on towards the fleld of sheep, the rider turning his face in receding. Gabriel looked at her. It was a moment when a woman's eyes and tongue tell distinctly opposite tales. Bathsheba looked full of gratitude, and she said: -- "O, Gabriel, how could you serve me so unkindly!' Such a tenderly-shaped reproach for his previous delay was the one speech in the language that he could pardon for not being commendation of his readiness now. Gabriel murmured a confused reply, and hastened on. She knew from the look which sentence in her note had brought him. Bathsheba followed to the field. Gabriel was already among the turgid, prostrate forms. He had flung off his coat, rolled up his shirt-sleeves, and taken from his pocket the instrument of salvation. It was a small tube or trochar, with a lance passing down the inside; and Gabriel began to use it with a dexterity that would have graced a hospital surgeon. Passing his hand over the sheep's left flank, and selecting the proper point, he punctured the skin and rumen with the lance as it stood in the tube; then he suddenly withdrew the lance, retaining the tube in its place. A current of air rushed up the tube, forcible enough to have extinguished a candle held at the orifice. It has been said that mere ease after torment is de+ light for a time; and the countenances of these poor creatures expressed it now. Forty-nine operations were successfully performed. Owing to the great hurry necessitated by the far-gone state of some of the flock, Gabriel missed his aim in one case, and in one only -- striking wide of the mark, and inflicting a mortal blow at once upon the suffering ewe. Four had died; three recovered without an operation. The total number of sheep which had thus strayed and injured themselves so dangerously was fifty-seven. When the love-led man had ceased from his labours, Bathsheba came and looked him in the face. "Gabriel, will you stay on with me?' she, said, smiling winningly, and not troubling to bring her lips quite together again at the end, because there was going to be another smile soon. "I will,' said Gabriel. And she smiled on him again.

THE GREAT BARN AnD THE SHEEP-SHEARERS MEN thin away to insignificance and oblivion quite as often by not making the most of good spirits when they have them as by lacking good spirits when they are indispensable. Gabriel lately, for the first time since his prostration by misfortune, had been independent in thought and vigorous in action to a marked extent -- conditions which, powerless without an opportunity as an opportunity without them is barren, would have given him a sure lift upwards when the favourable-con+ junction should have occurred. But this incurable loitering beside Bathsheba Everdene stole his time ruinously. The spring tides were going by without floating him off, and the neap might soon come which could not. It was the first day of June, and the sheep-shearing season culminated, the landscape, even to the leanest pasture, being all health and colour. Every green was young, every pore was open, and every stalk was swollen with racing currents of juice. God was palpably present in the country, and the devil had gone with the world to town. Flossy catkins of the later kinds, fern-sprouts like bishops' croziers, the square-headed moschatel, the odd cuckoo-pint, -- like an apoplectic saint in a niche of malachite, -- snow-white ladies'-smocks, the toothwort, approximating to human flesh, the enchanter's night+ shade, and the black-petaled doleful-bells, were among the quainter objects of the vegetable world in and about Weatherbury at this teeming time; and of the animal, the metamorphosed figures of Mr. Jan Coggan, the master-shearer; the second and third shearers, who travelled in the exercise of their calling, and do not re+ quire definition by name; Henery Fray the fourth shearer, Susan Tall's husband the fifth, Joseph Poorgrass the sixth, young Cain Ball as assistant-shearer, and Gabriel Oak as general supervisor. None of these were clothed

to any extent worth mentioning, each appearing to have hit in the matter of raiment the decent mean between a high and low caste Hindoo. An angularity of lineament, and a fixity of facial machinery in general, proclaimed that serious work was the order of the day. They sheared in the great barn, called for the nonce the Shearing-barn, which on ground-plan resembled a church with transepts. It not only emulated the form of the neighbouring church of the parish, but vied with it in antiquity. Whether the barn had ever formed one of a group of conventual buildings nobody seemed to be aware; no trace of such surroundings remained. The vast porches at the sides, lofty enough to admit a waggon laden to its highest with corn in the sheaf, were spanned by heavy-pointed arches of stone, broadly and boldly cut, whose very simplicity was the origin of a grandeur not apparent in erections where more ornament has been attempted. The dusky, filmed, chestnut roof, braced and tied in by huge collars, curves, and diagonals, was far nobler in design, because more wealthy in material, than nine-tenths of those in our modern churches. Along each side wall was a range of striding buttresses, throwing deep shadows on the spaces between them, which were perforated by lancet openings, combining in their proportions the precise requirements both of beauty and ventilation. One could say about this barn, what could hardly be said of either the church or the castle, akin to it in age and style, that the purpose which had dictated its original erection was the same with that to which it was still applied. Unlike and superior to either of those two typical remnants of mediaevalism, the old barn embodied practices which had suffered no mutila+ tion at the hands of time. Here at least the spirit of the ancient builders was at one with the spirit of the modern beholder. Standing before this abraded pile, the eye regarded its present usage, the mind-dwelt upon its past history, with a satisfied sense of functional continuity throughout -- a feeling almost of gratitude, and quite of pride, at the permanence of the idea which had heaped it up. The fact that four centuries had neither proved it to be founded on a mistake,

inspired any hatred of its purpose, nor given rise to any reaction that had battered it down, invested this simple grey effort of old minds with a repose, if not a grandeur, which a too curious reflection was apt to disturb in its ecclesiastical and military compeers. For once medievalism and modernism had a common stand+ point. The lanccolate windows, the time-eaten arch+ stones and chamfers, the orientation of the axis, the misty chestnut work of the rafters, referred to no exploded fortifying art or worn-out religious creed. The defence and salvation of the body by daily bread is still a study, a religion, and a desire. To-day the large side doors were thrown open towards the sun to admit a bountiful light to the immediate spot of the shearers' operations, which was the wood threshing-floor in the centre, formed of thick oak, black with age and polished by the beating of flails for many generations, till it had grown as slippery and as rich in hue as the state-room floors of an Elizabethan mansion. Here the shearers knelt, the sun slanting in upon their bleached shirts, tanned arms, and the polished shears they flourished, causing these to bristle with a thousand rays strong enough to blind a weak-eyed man. Beneath them a captive sheep lay panting, quickening its pants as misgiving merged in terror, till it quivered like the hot landscape outside. This picture of to-day in its frame of four hundred years ago did not produce that marked contrast between ancient and modern which is implied by the contrast of date. In comparison with cities, Weatherbury was immutable. The citizen's Then is the rustic's Now. In London, twenty or thirty-years ago are old times; in Paris ten years, or five; in Weatherbury three or four score years were included in the mere present, and nothing less than a century set a mark on its face or tone. Five decades hardly modified the cut of a gaiter, the embroidery of a smock-frock, by the breadth of a hair. Ten generations failed to alter the turn of a single phrase. In these Wessex nooks the busy out+ sider's ancient times are only old; his old times are still new; his present is futurity. So the barn was natural to the shearers, and the shearers were in harmony with the barn. The spacious ends of the building, answering ecclesi+ astically

to nave and chancel extremities, were fenced off with hurdles, the sheep being all collected in a crowd within these two enclosures; and in one angle a catching+ pen was formed, in which three or four sheep were continuously kept ready for the shearers to seize without loss of time. In the background, mellowed by tawny shade, were the three women, Maryann Money, and Temperance and Soberness Miller, gathering up the fleeces and twisting ropes of wool with a wimble for tying them round. They were indifferently well assisted by the old maltster, who, when the malting season from October to April had passed, made himself useful upon any of the bordering farmsteads. "Behind all was Bathsheba, carefully watching the men to see that there was no cutting or wounding through carelessness, and that the animals were shorn close. Gabriel, who flitted and hovered under her bright eyes like a moth, did not shear continuously, half his time being spent in attending to the others and selecting the sheep for them. At the present moment he was engaged in handing round a mug of mild liquor, supplied from a barrel in the corner, and cut pieces of bread and cheese. Bathsheba, after throwing a glance here, a caution there, and lecturing one of the younger operators who had allowed his last finished sheep to go off among the flock without re-stamping it with her initials, came again to Gabriel, as he put down the luncheon to drag a frightened ewe to his shear-station, flinging it over upon its back with a dexterous twist of the arm He lopped off the tresses about its head, and opened up the neck and collar, his mistress quietly looking on: "She blushes at the insult,' murmured Bathsheba, watching the pink flush which arose and overspread the neck and shoulders of the ewe where they were left bare by the clicking shears -- a flush which was enviable, for its delicacy, by many queens of coteries, and would have been creditable, for its promptness, to any woman in the world. Poor Gabriel's soul was fed with a luxury of content by having her over him, her eyes critically regarding his skilful shears, which apparently were going to gather up a piece of the flesh at every close, and yet never did so. Like Guildenstern,

Oak was happy in that he was not over happy. He had no wish to converse with her: that his bright lady and himself formed one group, exclusively their own, and containing no others in the world, was enough. So the chatter was all on her side. There is a loquacity that tells nothing, which was Bathsheba's; and there is a silence which says much: that was Gabriel's. Full of this dim and temperate bliss, he went on to fling the ewe over upon her other side, covering her head with his knee, gradually running the shears line after line round her dewlap; thence about her flank and back, and finishing over the tail. "Well done, and done quickly!' said Bathsheba, looking at her watch as the last snip resounded. "How long, miss?' said Gabriel, wiping his brow. "Three-and-twenty minutes and a half since you took the first lock from its forehead. It is the first time that I have ever seen one done in less than half an hour.' The clean, sleek creature arose from its fleece -- how perfectly like Aphrodite rising from the foam should have been seen to be realized -- looking startled and shy at the loss of its garment, which lay on the floor in one soft cloud, united throughout, the portion visible being the inner surface only, which, never before exposed, was white as snow, and without flaw or blemish of the minutest kind. "Cain Ball!' "Yes, Mister Oak; here I be!' Cainy now runs forward with the tar-pot. "B. E.' is newly stamped upon the shorn skin, and away the simplc dam lcaps, panting, over the board into the shirtless flock outside. Then up comes Maryann; throws the loose locks into the middle of the fleece, rolls it up, and carries it into the background as three-and-a-half pounds of unadulterated warmth for the winter enjoy+ ment of persons unknown and far away, who will, however, never experience the superlative comfort derivable from the wool as it here exists, new and pure -- before the unctuousness of its nature whilst in a living state has dried, stiffened, and been washed out -- rendering it just now as superior to anything woollen as cream is superior to milk-and-water.

But heartless circumstance could not leave entire Gabriel's happiness of this morning. The rams, old ewes, and two-shear ewes had duly undergone their stripping, and the men were proceeding with the shear+ lings and hogs, when Oak's belief that she was going to stand pleasantly by and time him through another performance was painfully interrupted by Farmer Bold+ wood's appearance in the extremest corner of the barn. Nobody seemed to have perceived his entry, but there he certainly was. Boldwood always carried with him a social atmosphere of his own, which everybody felt who came near him; and the talk, which Bathsheba's presence had somewhat suppressed, was now totally suspended. He crossed over rowards Bathsheba, who turned to greet him with a carriage of perfect ease. He spoke to her in low tones, and she instinctively modulated her own to the same pitch, and her voice ultimately even caught the inflection of his. She was far from having a wish to appear mysteriously connected with him; but woman at the impressionable age gravitates to the larger body not only in her choice of words, which is apparent every day, but even in her shades of tone and humour, when the influence is great. What they conversed about was not audible to Gabriel, who was too independent to get near, though too concerned to disregard. The issue of their dialogue was the taking of her hand by the courteous farmer to help her over the spreading-board into the bright June sunlight outside. Standing beside the sheep already shorn, they went on talking again. Concerning the flock? Apparently not. Gabriel theorized, not without truth, that in quiet discussion of any matter within reach of the speakers' eyes, these are usually fixed upon it. Bathsheba demurely regarded a contemptible straw lying upon the ground, in a way which suggested less ovine criticism than womanly embarrassment. She became more or less red in the cheek, the blood wavering in uncertain flux and reflux over the sensitive space between ebb and flood. Gabriel sheared on, constrained and sad. She left Boldwood's side, and he walked up and down alone for nearly a quarter of an hour. Then she reappeared in her

new riding-habit of myrtle-green, which fitted her to the waist as a rind fits its fruit; and young Bob Coggan led -on -her mare, Boldwood fetching his own horse from the tree under which it had been tied. Oak's eyes could not forsake them; and in en+ deavouring to continue his shearing at the same time that he watched Boldwood's manner, he snipped the sheep in the groin. The animal plunged; Bathsheba instantly gazed towards it, and saw the blood. "O, Gabriel!' she exclaimed, with severe remon+ strance you who are so strict with the other men -- see what you are doing yourself!' To an outsider there was not much to complain of in this remark ; but to Oak, who "knew Bathsheba to be well aware that she herself was the cause of the poor ewe's wound, because she had wounded the ewe's shearer in a -- still more vital part, it had a sting which the abiding sense of his inferiority to both herself and Boldwood was not calculated to heal. But a manly resolve to recognize boldly that he had no longer a lover's interest in her, helped him oceasionally to conceal a feeling. " Bottle .! ' he shouted, in an unmoved voice of routine. Cainy Ball ran up, the wound was anointed, and the shearing continued. Boldwood gently tossed Bathsheba into the saddle, and before they turned away she again spoke out to Oak with the same dominative and tantalizing graciousness. "I am going now to see Mr. Boldwood's Leicesters. Take my place in the barn, Gabriel, and keep the men carefully to their work.' The horses' heads were put about, and they trotted away. Boldwood's deep attachment was a matter of great interest among all around him ; but, after having been pointed out for so many years as the perfect exemplar of thriving bachelorship, his lapse was an anticlimax somewhat resembling that of St. John Long's death by consumption in the midst of his proofs that it was not a fatal disease.

" That means matrimony,' said Temperance Miller, following them out of sight with her eyes. "I reckon that's the size o't,' said Coggan, working along without looking up. " Well, better wed over the mixen than over the moor,' said Laban Tall, turning his sheep. Henery Fray spoke, exhibiting miserable eyes at the same time: "I don't see why a maid should take a husband when she's bold enough to fight her own battles, and don't want a home ; for 'tis keeping another woman out. But let it be, for 'tis a pity he and she should trouble two houses.' As usual with decided characters, Bathsheba invari+ ably provoked the criticism of individuals like Henery Fray. Her emblazoned fault was to be too pronounced in her objections, and not sufficiently overt in her likings. We learn that it is not the rays which bodies absorb, but those which they reject, that give them the colours they are known by ; and win the same way people are specialized by their dislikes and antagonisms, whilst their goodwill is looked upon as no attribute at all. Henery continued in a more complaisant mood : "I once hinted my mind to her on a few things, as nearly as a battered frame dared to do 'so to such a froward piece. You all know, neighbours, what a man I be, and how I come down with my powerful words when my pride is boiling wi' scarn ?' " We do, we do, Henery.' " So I said, "" Mistress Everdene, there's places empty, and there's gifted men willing ; but the spite '' -- no. not the spite -- I didn't say spite -- ""but the villainy of the contrarikind,'' I said (meaning womankind), "" keeps 'em out.'' That wasn't too strong for her, say ? ' " Passably well put.' "Yes; and I would have said it, had death and salvation overtook me for it. Such is my spirit when I have a mind.' "A true man, and proud as a lucifer.' "You see the artfulness ? Why, 'twas about being baily really; but I didn't put it so plain that she could understand my meaning, so I could lay it on all the

stronger. That was my depth .! ... However, let her marry an she will. Perhaps 'tis high time. I believe Farmer Boldwood kissed her behind the spear-bed at the sheep-washing t'other day -- that I do.' " What a lie !.' said Gabriel. " Ah, neighbour Oak -- how'st know ? ' said, Henery, mildly. " Because she told me all that passed,' said Oak, with a pharisaical sense that he was not as other shearers in this matter. "Ye have a right to believe it,' said Henery, with dudgeon; "a very true right. But I mid see a little distance into things !. To be long-headed enough for a baily's place is a poor mere trifle -- yet a trifle more than nothing. However, I look round upon life quite cool. Do you heed me, neighbours ? My words, though made as simple as I can, mid be rather deep for some heads.' " O yes, Henery, we quite heed ye.' " A strange old piece, goodmen -- whirled about from here to yonder, as if I were nothing ! A little warped, too. But I have my depths; ha, and even my great depths ! I might gird at a certain shepherd, brain to brain. But no -- O no !.' " A strange old piece, ye say .! ' interposed the maltster, in a querulous voice. "At the same time ye be no old man worth naming -- no old man at all. Yer teeth bain't half gone yet ; and what's a old man's standing if se be his teeth bain't gone? Weren't I stale in wedlock afore ye were out of arms ? 'Tis a poor thing to be sixty, when there's people far past four-score -- a boast'weak as water.' It was the unvaying custom in Weatherbury to sink minor differences when the maltster had to be pacified. " Weak as-water .! yes,' said Jan Coggan.- "Malter, we feel ye to be a wonderful veteran man, and nobody can gainsay it.' " Nobody,' said Joseph Poorgrass. "Ye be a very rare old spectacle, malter, and we all admire ye for that gift. ' "Ay, and as a young man, when my senses were in prosperity, I was likewise liked by a good-few who knowed me,' said the maltster. " 'Ithout doubt you was -- 'ithout doubt.' The bent and hoary 'man was satisfied, and so apparently was Henery Frag. That matters should continue pleasant Maryann

spoke, who, what with her brown complexion, and the working wrapper of rusty linsey, had at present the mellow hue of an old sketch in oils -- notably some of Nicholas Poussin's: -- " Do anybody know of a crooked man, or a lame, or any second-hand fellow at all that would do for poor me ?' said Maryann. "A perfect one I don't expect to at my time of life. If I could hear of such a thing twould do me more good thantoast and ale.' Coggan furnished a suitable reply. Oak went on with his shearing, and said not another word. Pestilent moods had come, and teased away his quiet. Bathsheba had shown indications of anointing him above his fellows by installing him as the bailiff that the farm imperatively required. He did not covet the post relatively to the farm : in relation to herself, as beloved by him and unmarried to another, he had coveted it. His readings of her seemed now to be vapoury and indistinct. His lecture to her was, he thought, one of the absurdest mistakes. Far from coquetting with Boldwood, she had trifled with himself in thus feigning that she had trifled with another. He was inwardly convinced that, in accordance with the anticipations of his easy-going and worse-educated comrades, that day would see Boldwood the accepted husband of Miss Everdene. Gabriel at this time of his life had out+ grown the instinctive dislike which every Christian boy has for reading the Bible, perusing it now quite frequently, and he inwardly said, " ''I find more bitter than death the woman whose heart is snares and nets .! '' ' This was mere exclamation -- the froth of the storm. He adored Bathsheba just the same. " We workfolk shall have some lordly- junketing to-night,' said Cainy Ball, casting forth his thoughts in a new direction. "This morning I see'em making the great puddens in the milking-pails -- lumps of fat as big as yer thumb, Mister Oak ! I've never seed such splendid large knobs of fat before in the days of my life -- they never used to be bigger then a horse-bean. And there was a great black crock upon the brandise with his legs a-sticking out, but I dont know what was in within." 'And there's two bushels of biffins for apple-pies,' said Maryann.

"Well, I hope to do my duty by it all,' said Joseph Poorgrass, in a pleasant, masticating manner of anticipa+ tion. " Yes ; victuals and drink is a cheerful thing, and gives nerves to the nerveless, if the form of words may be used. 'Tis the gospel of the body, without which we perish, so to speak it.'

EVENTIDE -- A SECOND DECLARATION FOR the shearing-supper a long table was placed on the grass-plot beside the house, the end of the table being thrust over the sill of the wide parlour window and a foot or two into the room. Miss Everdene sat inside the window, facing down the table. She was thus at the head without mingling with the men. This evening Bathsheba was unusually excited, her red cheeks and lips contrasting lustrously with the mazy skeins of her shadowy hair. She seemed to expect assistance, and the seat at the bottom of the table was at her request left vacant until after they had begun and the duties appertaining to that end, which he did with great readiness. At this moment Mr. Boldwood came in at the gate, and crossed the green to Bathsheba at the window. He apologized for his lateness : his arrival was evidently by arrangement. " Gabriel,' said she, " will you move again, please, and let Mr. Boldwood come there ?' Oak moved in silence back to his original seat. The gentleman-farmer was dressed in cheerful style, in a new coat and white waistcoat, quite contrasting with his usual sober suits of grey. Inwardy, too, he was blithe, and consequently chatty to an exceptional degree. So also was Bathsheba now that he had come, though the uninvited presence of Pennyways, the bailiff who had been dismissed for theft, disturbed her equan+ imity for a while. Supper being ended, Coggan began on his own private account, without reference to listeners : -- l've lost my love and l care not, I've lost my love, and l care not; I shall soon have another

That's better than t'other! I've lost my love, and I care not. This lyric, when concluded, was received with a silently appreciative gaze at the table, implying that the performance, like a work by those established authors who are independent of notices in the papers, was a well-known delight which required no applause. "Now, Master Poorgass, your song!' said Coggan. "I be all but in liquor, and the gift is wanting in me,' said Joseph, diminishing himself. "Nonsense; wou'st never be so ungrateful, Joseph -- never!' said Coggan, expressing hurt feelings by an inflection of voice. "And mistress is looking hard at ye, as much as to say, ""Sing at once, Joseph Poor+ grass.'' ' "Faith, so she is; well, I must suffer it! ... Just eye my features, and see if the tell-tale blood overheats me much, neighbours?' "No, yer blushes be quite reasonable,' said Coggan. "I always tries to keep my colours from rising when a beauty's eyes get fixed on me,' said Joseph, differently; "but if so be 'tis willed they do, they must.' "Now, Joseph, your song, please,' said Bathsheba, from the window. "Well, really, ma'am,' he replied, in a yielding tone, "I don't know what to say. It would be a poor plain ballet of my own composure.' 'Hear, hear! ' said the supper-party. Poorgrass, thus assured, trilled forth a flickering yet commendable piece of sentiment, the tune of which consisted of the key-note and another, the latter being the sound chiefly dwelt upon. This was so successful that he rashly plunged into a second in the same breath, after a few false starts : -- I sow'-ed th'-e I sow'-ed I sow'-ed the'-e seeds' of love', I-it was' all' i'-in the'-e spring', I-in A'-pril', Ma'-ay, a'-nd sun'-ny' June', When sma'-all bi'-irds they' do' sing.

" Well put out of hand,' said Coggan, at the end of the verse. ' "" They do sing '' was a very taking paragraph.' "Ay; and there was a pretty place at "seeds of love,'' and 'twas well heaved out. Though "love '' is a nasty high corner when a man's voice is getting crazed. Next verse, Master Poorgrass.' But during this rendering young Bob Coggan ex+ hibited one of those anomalies which will afflict little people when other persons are particularly serious : in trying to check his laughter, he pushed down his throat as much of the tablecloth as he could get hold of, when, after continuing hermetically sealed for a short time, his mirth burst out through his nose. Joseph perceived it, and with hectic cheeks of indignation instantly ceased singing. Coggan boxed Bob's ears immediately. "Go on, Joseph -- go on, and never mind the young scamp,' said Coggan. "'Tis a very catching ballet. Now then again -- the next bar; I'll help ye to flourish up the shrill notes where yer wind is rather wheezy : -- O the wi'-il-lo'-ow tree' will' twist', And the wil'-low' tre'-ee wi'ill twine'. But the singer could not be set going again. Bob Coggan was sent home for his ill manners, and tran+ quility was restored by Jacob Smallbury, who volunteered a ballad as inclusive and interminable as that with which the worthy toper old Silenus amused on a similar occasion the swains Chromis and Mnasylus, and other jolly dogs of his day. It' was still the beaming time .of evening, though night was stealthily making itself visible low down upon the ground, the western lines of light taking the earth without alighting upon it to any extent, or illuminating the dead levels at all. The sun had crept round the tree as a last effort before death, and then began to sink, the shearers' lower parts becoming steeped in embrowning twilight, whilst their heads and shoulders were still enjoying day, touched with a yellow of self+ sustained brilliancy that seemed inherent rather than acquired. The sun went down in an ochreous mist; but they sat, and

talked on, and grew as merry as the gods in Homer's heaven. Bathsheba still remained enthroned inside the window, and occupied herself in knitting, from which she sometimes looked up to view the fading scene outside. The slow twilight expanded and enveloped them completely before the signs of moving were shown. Gabriel suddenly missed Farmer Boldwood from his place at the bottom of the table. How long he had been gone Oak did not know; but he had apparently withdrawn into the eneircling dusk. Whilst he was thinking of this, Liddy brought candles into the back part of the room overlooking the shearers, and their lively new flames shone down the table and over the men, and dispersed among the green shadows behind. Bathsheba's form, still in its original position, was now again distinct between their eyes and the light, which revealed that Boldwood had gone inside the room, and was sitting near her. Next came the question of the evening. Would Miss Everdene sing to them the song she always sang so charmingly -- " The Banks of Allan Water ' -- before they went home ? After a moment's consideration Bathsheba assented, beckoning to Gabriel, who hastened up into the coveted atmosphere. " Have you brought your flute ? " she whispered. " Yes, miss.' " Play to my singing, then.' She stood up in the window-opening, facing the men, the candles behind her, Gabriel on her right hand, immediately outside the sash-frame. Boldwood had drawn up on her left, within the room. Her singing was soft and rather tremulous at first, but it soon swelled to a steady clearness. Subsequent events caused one of the verses to be remembered for many months, and even years, by more than one of those who were gathered there : -- For his bride a soldier sought her, And a winning tongue had he : On the banks of Allan Water None was gay as she !.

In addition to the dulcet piping of Gabriel's flute, Boldwood supplied a bass in his customary profound voice, uttering his notes so softly, however, as to abstain entirely from making anything like an ordinary duet of the song ; they rather formed a rich unexplored shadow, which threw her tones into relief. The shearers reclined against each other as at suppers in the early ages of the world, and so silent and absorbed were they that her breathing could almost be heard between the bars ; and at the end of the ballad, when the last tone loitered on to an inexpressible close, there arose that buzz of pleasure which is the attar of applause. It is scarcely necessary to state that Gabriel could not avoid noting the farmer's bearing to-night towards their entertainer. Yet there was nothing exceptional in his actions beyond what appertained to his time of performing them. It was when the rest were all looking away that Boldwood observed her ; when they regarded her he turned aside; when they thanked or praised he was silent; when they were inattentive he murmured his thanks. The meaning lay in the difference between actions, none of which had any meaning of itself; and the necessity of being jealous, which lovers are troubled with, did not lead Oak to underestimate these signs. Bathsheba then wished them good-night, withdrew from the window, and retired to the back part of the room, Boldwood thereupon closing the sash and the shutters, and remaining inside with her. Oak wandered away under the quiet and scented trees. Recovering from the softer impressions produced by Bathsheba's voice, the shearers rose to leave, Coggan turning to Pennyways as he pushed back the bench to pass out : -- "I like to give praise where praise is due, and the man deserves it -- that 'a do so,' he remarked, looking at the worthy thief, as if he were the masterpiece of some world-renowned artist.

"I'm sure I should never have believed it if we hadn t proved it, so to allude,' hiccupped Joseph Poorgrass, " that every cup, every one of the best knives and forks, and every empty bottle be in their place as perfect now as at the beginning, and not one stole at all. "I'm sure I don't deserve half the praise you give me,' said the virtuous thief, grimly. " Well, I'll say this for Pennyways,' added Coggan, "that whenever he do really make up his mind to do a noble thing in the shape of a good action, as I could see by his face he. did to-night afore sitting down, he's generally able to carry it out. Yes, I'm proud to say. neighbours, that he's stole nothing at all. "Well,' -- 'tis an honest deed, and we thank ye for it, Pennyways,' said Joseph; to which opinion the remainder of the company subscribed unanimously. At this time of departure, when nothing more was visible of the inside of the parlour than a thin and still chink of light between the shutters, a passionate scene was in eourse of enactment there.' Miss Everdene and Boldwood were alone. Her cheeks had lost a great deal of their healthful fire from the very seriousness of her position ; but her eye was bright with the excitement of a triumph -- though it was a triumph which had rather been contemplated than desired. She was standing behind a low arm-chair, from which she had just risen, and he was kneeling in it -- inclining himself over its back towards her, and holding her hand in both his own. His body moved restlessly, and it was with what Keats daintily calls a too happy happiness. This unwonted abstraction by love of all dignity from a man of whom it had ever seemed the chief component, was, in its distressing incongruity, a pain to her which quenched much of the pleasure she derived from the proof that she was idolized. " I will try to love you,' she was saying, in a trembling voice quite unlike her usual self-confidence. " And if I can believe in any way that I shall make you a good wife I shall indeed be willing to marry you. But, Mr. Boldwood, hesitation on so high a matter is honourable in any woman, and I don't want to give a solemn promise to-night. I would rather ask you to wait a few weeks till I can see my situation better.' "But you have every reason to believe that then -- -- ' 'I have every reason to hope that at the end of the five or

six weeks, between this time and harvest, that you say you are going to be away from home, I shall be able to promise to be your wife,' she said, firmly. "But remember this distinctly, I don't promise yet.' "It is enough I don't ask more. I can wait on those dear words. And now, Miss Everdene, good+ night!' " Good-night,' she said, graciously -- almost tenderly; and Boldwood withdrew with a serene smile. Bathsheba knew more of him now ; he had entirely bared his heart before her, even until he had almost worn in her eyes the sorry look of a grand bird without the feathers that make it grand. She had been awe+ struck at her past temerity, and was struggling to make amends without thinking whether the sin quite deserved the penalty she was schooling herself to pay. To have brought all this about her ears was terrible; but after a while the situation was not without a fearful joy. The facility with which even the most timid woman some+ times acquire a relish for the dreadful when that is amalgamated with a little triumph, is marvellous.

THE SAME NIGHT -- THE FIR PLANTATION AMONG the multifarious duties which Bathsheba had voluntarily imposed upon herself by dispensing with the services of a bailiff, was the particular one of looking round the homestead before going to bed, to see that all was right and safe for the night. Gabriel had almost constantly preceded her in this tour every evening, watching her affairs as carefully as any specially appointed officer of surveillance could have done; but this tender devotion was to a great extent unknown to his mistress, and as much as was known was somewhat thanklessly received. Women are never tired of bewailing man's fickleness in love, but they only seem to snub his con+ stancy. As watching is best done invisibly, she usually carried a dark lantern in her hand, and every now and then turned on the light to examine nooks and corners with the coolness of a metropolitan policeman. This cool+ ness may have owed its existence not so much to her fearlessness of expected danger as to her freedom from the suspicion of any; her worst anticipated discovery being that a horse might not be well bedded, the fowls not all in, or a door not closed. This night the buildings were inspected as usual, and she went round to the farm paddock. Here the only sounds disturbing the stillness were steady munch+ ings of many mouths, and stentorian breathings from all but invisible noses, ending in snores and puffs like the blowing of bellows slowly. Then the munching would recommence, when the lively imagination might assist the eye to discern a group of pink-white nostrils, shaped as caverns, and very clammy and humid on their sur+ faces, not exactly pleasant to the touch until one got used to them; the mouths beneath having a great partiality for closing upon any loose end of Bathsheba's apparel which came within

reach of their tongues. Above each of these a still keener vision suggested a brown forehead and two staring though not unfriendly eyes, and above all a pair of whitish crescent-shaped horns like two particularly new moons, an occasional stolid " moo!' proclaiming beyond the shade of a doubt that these phenomena were the features and persons of Daisy, Whitefoot, Bonny-lass, Jolly-O, Spot, Twinkle-eye, etc., etc. -- the respectable dairy of Devon cows belonging to Bathsheba aforesaid. Her way back to the house was by a path through a young plantation of tapering firs, which had been planted some years earlier to shelter the premises from the north wind. By reason of the density of the interwoven foliage overhead, it was gloomy there at cloudless noontide, twilight in the evening, dark as midnight at dusk, and black as the ninth plague of Egypt at midnight. To describe the spot is to call it a vast, low, naturally formed hall, the plumy ceiling of which was supported by slender pillars of living wood, the floor being covered with a soft dun carpet of dead spikelets and mildewed cones, with a tuft of grass-blades here and there. This bit of the path was always the crux of the night's ramble, though, before starting, her apprehen+ sions of danger were not vivid enough to lead her to take a companion. Slipping along here covertly as Time, Bathsheba fancied she could hear footsteps enter+ ing the track at the opposite end. It was certainly a rustle of footsteps. Her own instantly fell as gently as snowflakes. She reassured herself by a remembrance that the path was public, and that the traveller was probably some villager returning home ; regetting, at the same time, that the meeting should be about to occur in' the darkest point of her route, even though only just outside her own door. The noise approached, came close, and a figure was apparently on the point of gliding past her when some+ thing tugged at her skirt and pinned it forcibly to the ground. The instantaneous check nearly threw Bath+ sheba off her balance. In recovering she struck against warm clothes and buttons. 'A rum start, upon my soul!' said a masculine voice, a foot or so above her head. 'Have I hurt you, mate?' "No,' said Bathsheba, attempting to shrink a way.

" We have got hitched together somehow, I think.' " Yes.' "Are you a woman ?' 'Yes.' "A lady, I should have said.' "It doesn't matter.' "I am a man.' "Oh!' Bathsheba softly tugged again, but to no purpose. "Is that a dark lantern you have ? I fancy so,' said the man. 'Yes.' "If you'll allow me I'll open it, and set you free.' A hand seized the lantern, the door was opened, the rays burst out from their prison, and Bathsheba beheld her position with astonishment. The man to whom she was hooked was brilliant in brass and scarlet. He was a soldier. His sudden appearance was to darkness what the sound of a trumpet is to silense. Gloom, the genius loci at all times hitherto, was now totally overthrown, less by the lantern-light than by what the lantern lighted. The contrast of this revelation with her anticipations of some sinister figure in sombre garb was so great that it had upon her the effect of a fairy transformation. It was immediately apparent that the military man's spur had become entangled in the gimp which decorated the skirt of her dress. He caught a view of her face. "I'll unfasten you in one moment, miss,' he said, with new-born gallantry. " O no -- I can do it, thank you,' she hastily replied, and stooped for the performance. The unfastening was not such a trifling affair. The rowel of the spur had so wound itself among the gimp cords in those few moments, that separation was likely to be a matter of time. He too stooped, and the lantern standing on the ground betwixt them threw the gleam from its open side among the fir-tree needles and the blades of long damp grass with the effect of a large glowworm. It radiated upwards into their

faces, and sent over half the planta+ tion gigantic shadows of both man and woman, each dusky shape becoming distorted and mangled upon the tree-trunks till it wasted to nothing. He looked hard into her eyes when she raised them for a moment; Bathsheba looked down again, for his gaze was too strong to be received point-blank with her own. But she had obliquely noticed that he was young and slim, and that he wore three chevrons upon his sleeve. Bathsheba pulled again. " You are a prisoner, miss; it is no use blinking the matter,' said the soldier, drily. " I must cut your dress if you are in such a hurry.' " Yes -- please do!' she exclaimed, helplessly. ' "It wouldn't be necessary if you could wait a moment;' and he unwound a cord from the little wheel. She withdrew her own hand, but, whether by accident or design, he touched it. Bathsheba was vexed; she hardly knew why. His unravelling went on, but it nevertheless seemed coming to no end. She looked at him again. 'Thank you for the sight of such a beautiful face!' said the young sergeant, without ceremony. She coloured with embarrassment. "'Twas un+ willingly shown,' she replied, stiffly, and with as much dignity -- which was very little -- as she could infuse into a position of captivity "I like you the better for that incivility, miss,' he said. " I should have liked -- I wish -- you had never shown yourself to me by intruding here!' She pulled again, and the gathers of her dress began to give way like liliputian musketry. " I deserve the chastisement your words give me. But why should such a fair and dutiful girl have such an aversion to her father's sex ? ' "Go on your way, please.' ' What, Beauty, and drag you after me ? Do but look; I never saw such a tangle!' 'O, 'tis shameful of you ; you have been making it worse on purpose to keep me here -- you have ! ' "Indeed, I don't think so,' said the sergeant, with a merry twinkle.

"I tell you you have!' she exclaimed, in high temper. I insist upon undoing it. Now, allow me!' "Certainly, miss; I am not of steel.' He added a sigh which had as much archness in it as a sigh could possess without losing its nature altogether. 'I am thankful for beauty, even when 'tis thrown to me like a bone to a dog. These moments will be over too soon!' She closed her lips in a determined silence. Bathsheba was revolving in her mind whether by a bold and desperate rush she could free herself at the risk of leaving her skirt bodily behind her. The thought was too dreadful. The dress -- which she had put on to appear stately at the supper -- was the head and front of her wardrobe ; not another in her stock became her so well. What woman in Bathsheba's position, not naturally timid, and within call of her retainers, would have bought escape from a dashing soldier at so dear a price ? "All in good time ; it will soon be done, I perceive,' said her cool friend. " This trifling provokes, and -- and -- -- ' " Not too cruel!' " -- Insults me.!' "It is done in order that I may have the pleasure of apologizing to so charming a woman, which I straightway do most humbly, madam,' he said, bowing low. Bathsheba really knew not what to say. "I've seen a good many women in my time, continued the young man in a murmur, and more thoughtfully than hitherto, critically regarding her bent head at the same time; "but I've never seen a woman so beautiful as you. Take it or leave it -- be offended or like it -- I don't care.' " Who are you, then, who can so well afford to despise opinion ? ' " No stranger. Sergeant Troy. I am staying in this place. -- There ! it is undone at last, you see. Your light fingers were more eager than mine. I wish it had been the knot of knots, which there's no untying !. ' This was worse and worse. She started up, and so did he.

How to decently get away from him -- that was her difficulty now. She sidled off inch by inch, the lantern in her hand, till she could see the redness of his coat no longer. " Ah, Beauty ; good-bye !. ' he said. She made no reply, and, reaching a distance of twenty or thirty yards, turned about, and ran indoors. Liddy had just retired to rest. In ascending to her own chamber, Bathsheba opened the girl's door an inch or two, and, panting, said -- " Liddy, is any soldier staying in the village -- sergeant somebody -- rather gentlemanly for a sergeant, and good looking -- a red coat with blue facings ?' 'No, miss ... No, I say; but really it might be Sergeant Troy home on furlough, though I have not seen him. He was here once in that way when the regiment was at Casterbridge.' " Yes; that's the name. Had he a moustache -- no whiskers or beard ?' " He had.' " What kind of a person is he ?' "O ! miss -- I blush to name it -- a gay man! But I know him to be very quick and trim, who might have made his thousands, like a squire. Such a clever young dand as he is! He's a doctor's son by name, which is a great deal; and he's an earl's son by nature!' " Which is a great deal more. Fancy! Is it true ? ' " Yes. And, he was brought up so well, and sent to Casterbridge Grammar School for years and years. Learnt all languages while he was there ; and it was said he got on so far that he could take down Chinese in shorthand ; but that I don't answer for, as it was only reported. However, he wasted his gifted lot, and listed a soldier; but even then he rose to be a sergeant without trying at all. Ah! such a blessing it is to be high-born ; nobility of blood will shine out even in the ranks and files. And is he really come home, miss ?" ' I believe so. Good-night, Liddy.' After all, how could a cheerful wearer of skirts be permanently offended with the man ? There are occasions when girls like Bathsheba will put up with a great deal of

unconventional behaviour. When they want to be praised, which is often, when they want to be mastered, which is sometimes ; and when they want no nonsense, which is seldom. Just now the first feeling was in the ascendant with Bathsheba, with a dash of the second. Moreover, by chance or by devilry, the ministrant was antecedently made interesting by being a handsome stranger who had evidently seen better days. So she could not clearly decide whether it was her opinion that he had insulted her or not. ' "Was ever anything so odd! ' she at last exclaimed to herself, in her own room. "And was ever anything so meanly done as what I did to to sulk away like that from a man who was only civil and kind!' Clearly she did not think his barefaced praise of her person an insult now. It was a fatal omission of Boldwood's that he had never once told her she was beautiful.

THE NEW ACQUAINTANCE DESCRIBED IDIOSYNCRASY and vicissitude had combined to stamp Sergeant Troy as an exceptional being. He was a man to whom memories were an in+ cumbrance, and anticipations a superfluity. Simply feeling, considering, and caring for what was before his eyes, he was vulnerable only in the present. His out+ look upon time was as a transient flash of the eye now and then : that projection of consciousness into days gone by and to come, which makes the past a synonym for the pathetic and the future a word for circum+ spection, was foreign to Troy. With him the past was yesterday ; the future, to-morrow ; never, the day after. On this account he might, in certain lights, have been regarded as one of the most fortunate of his order. For it may be argued with great plausibility that reminiscence is less an endowment than a disease, and that expectation in its only comfortable form -- that of absolute faith -- is practically an impossibility; whilst in the form of hope and the secondary compounds, patience, impatience, resolve, curiosity, it is a constant fluctuation between pleasure and pain. Sergeant Troy, being entirely innocent of the practice of expectation, was never disappointed. To set against this negative gain there may have been some positive losses from a certain narrowing of the higher tastes and sensations which it entailed. But limitation of the capacity is never recognized as a loss by the loser therefrom : in this attribute moral or aesthetic poverty contrasts plausibly with material, since those who suffer do not mind it, whilst those who mind it soon cease to suffer. It is not a denial of anything to have been always without it, and what Troy had never enjoyed he did not miss; but, being fully conscious that what sober

people missed he enjoyed, his capacity, though really less, seemed greater than theirs. He was moderately truthful towards men, but to women lied like a Cretan -- a system of ethics above all others calculated to win popularity at the first flush of admission into lively society ; and the possibility of the favour gained being transitory had reference only to the future. He never passed the line which divides the spruce vices from the ugly ; and hence, though his morals had hardly been applauded, disapproval of them" had fre+ quently been tempered with a smile. This treatment had led to his becoming a sort of regrater of other men's gallantries, to his own aggrandizement as a Corinthian, rather than to the moral profit of his hearers. His reason and his propensities had seldom any reciprocating influence, having separated by mutual consent long ago : thence it sometimes happened that, while his intentions were as honourable as could be wished, any particular deed formed a dark background which threw them into fine relief. The sergeant's vicious phases being the offspring of impulse, and his virtuous phases of cool meditation, the latter had a modest tendency to be oftener heard of than seen. Troy was full of activity, but his activities were less of a locomotive than a vegetative nature ; and, never being based upon any original choice of foundation or direc+ tion, they were exercised on whatever object chance might place in their way. Hence, whilst he sometimes reached the brilliant in speech because that -was spontaneous, he fell below the commonplace in action, from inability to guide incipient effort. He had a quick comprehension and considerable force of char+ acter ; but, being without the power to combine them, the comprehension became engaged with trivialities whilst waiting for the will to direct it, and the force wasted itself in useless grooves through unheeding the comprehension. He was a fairly well-educated man for one of middle class -- exceptionally well educated for a common soldier. He spoke fluently and unceasingly. He could in this way be one thing and seem another : for instance, he could speak of love and

think of dinner; call on the intend to owe. The wondrous power of flattery in passados at woman is a perception so universal as to be remarked upon by many people almost as automatically as they repeat a proverb, or say that they are Christians and the like, without thinking much of the enormous corollaries which spring from the proposition. Still less is it acted upon for the good of the complemental being alluded to. With the majority such an opinion is shelved with all those trite aphorisms which require some catastrophe to bring their tremendous meanings thoroughly home. When expressed with some amount of reflectiveness it seems co-ordinate with a belief that this flattery must be reasonable to be effective. It is to the credit of men that few attempt to settle the question by experi+ ment, and it is for their happiness, perhaps, that accident has never settled it for them. Nevertheless, that a male dissembler who by deluging her with untenable fictions charms the female wisely, may acquire powers reaching to the extremity of perdition, is a truth taught to many by unsought and wringing occurrences. And some profess to have attained to the same knowledge by experiment as aforesaid, and jauntily continue their indulgence in such experiments with terrible effect. Sergeant Troy was one. He had been known to observe casually that in dealing with womankind the only alternative to flattery was cursing and swearing. There was no third method. " Treat them fairly, and you are a lost man,' he would say. This philosopher's public appearance in Weatherbury promptly followed his arrival there. A week or two after the shearing, Bathsheba, feeling a nameless relief of spirits on account of Boldwood's absence, approached her hayfields and looked over the hedge towards the haymakers. They consisted in about equal proportions of gnarled and flexuous forms, the former being the men, the latter the women, who wore tilt bonnets covered with nankeen, which hung in a curtain upon their shoulders. Coggan and Mark Clark were mowing in a less forward meadow, Clark humming a tune to the strokes of his

scythe, to which Jan made no attempt to keep time with his. In the first mead they were already loading hay, the women raking it into cocks and windrows, and the men tossing it upon the waggon. From behind the waggon a bright scarlet spot emerged, and went on loading unconcernedly with the rest. It was the gallant sergeant, who had come hay+ making for pleasure ; and nobody could deny that he was doing the mistress of the farm real knight-service by this voluntary contribution of his labour at a busy time. As soon as she had entered the field Troy saw her, and sticking his pitchfork into the ground and picking up his crop or cane, he came forward. Bathsheba blushed with half-angry embarrassment, and adjusted her eyes as well as her feet to the direct line of her path.

SCENE ON THE VERGE OF THE HAY-MEAD 'AH, Miss Everdene!' said the sergeant, touching his diminutive cap. "Little did I think it was you I was speaking to the other night. And yet, if I had reflected, the "Queen of the Corn-market" (truth is truth at any hour of the day or night, and I heard you so named in Casterbridge yesterday), the "Queen of the Corn-market,'' I say, could be no other woman. I step across now to beg your forgiveness a thousand times for having been led by my feelings to express myself too strongly for a stranger. To be sure I am no stranger to the place -- I am Sergeant Troy, as I told you, and I have assisted your uncle in these fields no end of times when I was a lad. I have been doing the same for you today.' "I suppose I must thank you for that, Sergeant Troy,' said the Queen of the Corn-market, in an in+ differently grateful tone. The sergeant looked hurt and sad. "Indeed you must not, Miss Everdene,' he said. " Why could you think such a thing necessary ? ' "I am glad it is not.' " Why ? if I may ask without offence.' " Because I don't much want to thank you for any" thing.' "I am afraid I have made a hole with my tongue that my heart will never mend. O these intolerable times: that ill-luck should follow a man for honestly telling a woman she is beautiful.! 'Twas the most I said -- you must own that; and the least I could say -- that I own myself.' 'There is some talk I could do without more easily than money.' "Indeed. That remark is a sort of digression.' " No. It means that I would rather have your room than your company.'

"And I would rather have curses from you than kisses from any other woman ; so I'll stay here.' Bathsheba was absolutely speechless. And yet she could not help feeling that the assistance he was render+ ing forbade a harsh repulse. " Well,' continued Troy, "I suppose there is a praise which is rudeness, and that may be mine. At the same time there is a treatment which is injustice, and that may be yours. Because a plain blunt man, who has never been taught concealment, speaks out his mind without exactly intending it, he's to be snapped off like the son of a sinner.' "Indeed there's no such case between us,' she said, turning away. "I don't allow strangers to be bold and impudent -- even in praise of me.' " Ah -- it is not the fact but the method which offends you,' he said, carelessly. "But I have the sad satis+ faction of knowing that my words, whether pleasing or offensive, are unmistakably true. Would you have had me look at you, and tell my acquaintance that you are quite a common-place woman, to save you the embar+ rassment of being stared at if they come near you ? Not I. I couldn't tell any such ridiculous lie about a beauty to encourage a single woman in England in too excessive a modesty.' "It is all pretence -- what you are saying!' exclaimed Bathsheba, laughing in spite of herself at the sergeant's sly method. " You have a rare invention, Sergeant Troy. Why couldn't you have passed by me that night, and said nothing ? -- that was all I meant to reproach you for.' "Because I wasn't going to. Half the pleasure of a feeling lies in being able to express it on the spur of the moment, and I let out mine. It would have been just the same if you had been the reverse person -- ugly and old -- I should have exclaimed about it in the same way. ' " How long is it since you have been so afflicted with strong feeling, then ? ' " Oh, ever since I was big enough to know loveliness from deformity.'

"'Tis to be hoped your sense of the difference you speak of doesn't stop at faces, but extends to morals as well. ' 'I won't speak of morals or religion -- my own or anybody else's. Though perhaps I should have been a very good Christian if you pretty women hadn't made me an idolater.' Bathsheba moved on to hide the irrepressible dimp+ lings of merriment. Troy followed, whirling his crop. 'But -- Miss Everdene -- you do forgive me ? ' " Hardly. ' "Why ?' " You say such things.' "I said you were beautiful, and I'll say so still; for, by -- so you are !. The most beautiful ever I saw, or may I fall dead this instant! Why, upon my -- -- ' " Don't -- don't! I won't listen to you -- you are so profane!' she said, in a restless state between distress at hearing him and a penchant to hear more. "I again say you are a most fascinating woman. There's nothing remarkable in my saying so, is there? I'm sure the fact is evident enough. Miss Everdene, my opinion may be too forcibly let out to please you, and, for the matter of that, too insignificant to convince you, but surely it is honest, and why can't it be ex+ cused? ' "Because it -- it isn't a correct one,' she femininely murmured. " 0, fie -- fie-! Am I any worse for breaking the third of that Terrible Ten than you for breaking the ninth ?" "Well, it doesn't seem quite true to me that I am fascinating,' she replied evasively. ' Not so to you : then I say with all respect that, if so, it is owing to your modesty, Miss Everdene. But surely you must have been told by everybody of what everybody notices ? and you should take their words for it.' " They don't say so exactly.' " O yes, they must!' "Well, I mean to my face, as you do,' she went on, allowing

herself to be further lured into a conversation that intention had rigorously forbidden. "But you know they think so ?' "No -- that is -- I certainly have heard Liddy say they do, but -- -- ' She paused. Capitulation -- that was the purport of the simple reply, guarded as it was -- capitulation, unknown to her+ self. Never did a fragile tailless sentence convey a more perfect meaning. The careless sergeant smiled within himself, and probably too the devil smiled from a loop-hole in Tophet, for the moment was the turning+ point of a career. Her tone and mien signified beyond mistake that the seed which was to lift the foundation had taken root in the chink : the remainder was a mere question of time and natural changes. "There the truth comes out ! ' said the soldier, in reply. "Never tell me that a young lady can live in a buzz of admiration without knowing something about it. Ah,' well, Miss Everdene, you are -- pardon my blunt way -- you are rather an injury to our race than other+ wise. " How -- indeed ? ' she said, opening her eyes. "O, it is true enough. I may as well be hung for a sheep as a lamb (an old country saying, not of much account, but it will do for a rough soldier), and so I will speak my mind, regardless of your pleasure, and without hoping or intending to get your pardon. Why, Miss Everdene, it is in this manner that your good looks may do more. harm than good in the world.' The sergeant looked down the mead in critical abstrac+ ion. " Probably some one man on an average falls in' love, with each ordinary woman. She can marry him : he is content, and leads a useful life. Such women as you a hundred men always covet -- your eyes will be+ witch scores on scores into an unavailing fancy for you you can only marry one of that many. Out of these say twenty will endeavour to. drown the bitterness of espised love in drink ; twenty more will mope away their lives without a wish or attempt to make a mark in he world, because they have no ambition apart from their attachment to you ; twenty more -- the susceptible person

myself possibly among them -- will be always draggling after you, getting where they may just see you, doing desperate things. Men are such constant fools! The rest may try to get over their passion with more or less success. But all these men will be saddened. And not only those ninety-nine men, but the ninety-nine women they might have married are saddened with them. There's my tale. That's why I say that a woman so charming as yourself, Miss Ever+ dene, is hardly a blessing to her race.' The handsome sergeant's features were during this speech as rigid and stern as John Knox's in addressing his gay young queen. Seeing she made no reply, he said, "Do you read French ? ' "No; I began, but when I got to the verbs, father died,' she said simply. 'I do -- -when I have an opportunity, which latterly has not been often (my mother was a Parisienne) -- -and there's a proverb they have, Qui aime bien chatie bien -- "He chastens who loves well." Do you understand me? 'Ah!' she replied, and there was even a little tremu+ lousness in the usually cool girl's voice; 'if you can only fight half as winningly as you can talk, you are able to make a pleasure of a bayonet wound!' And then poor Bathsheba instanly perceived her slip in making this admission: in hastily trying to retrieve it, she went from bad to worse. 'Don't, however, suppose that I derive any pleasure from what you tell me.' 'I know you do not -- -I know it perfectly,' said Troy, with much hearty conviction on the exterior of his face: and altering the expression to moodiness; 'when a dozen men arfe ready to speak tenderly to you, and give the admiration you deserve without adding the warning you need, it stands to reason that my poor rough-and-ready mixture of praise and blame cannot convey much pleasure. Fool as I may be, I am not so conceited as to suppose that!' 'I think you -- -are conceited, nevertheless,' said Bathsheba, looking askance at a reed she was fitfully pulling with one hand, having lately grown feverish under the soldier's

system of procedure -- not because the nature of his cajolery was entirely unperceived, but because its vigour was overwelming. 'I would not own it to anybody esle -- nor do I exactly to you. Still, there might have been some self+ conceit in my foolish supposition the other night. I knew that what I said in admiration might be an opinion too often forced upon you to give any pleasure but I certainly did think that the kindness of your nature might prevent you judging an uncontrolled tongue harshly -- which you have done -- and thinking badly of me and wounding me this morning, when I am working hard to save your hay.' 'Well, you need not think more of that: perhaps you did not mean to be rude to me by speaking out your mind: indeed, I believe you did not,' said the shrewd woman, in painfully innocent earnest. 'And I thank you for giving help here. But -- -but mind you don't speak to me again in that way, or in any other, unless I speak to you.' 'O, Miss Bathsheba! That is to hard!' 'No, it isn't. Why is it?' 'You will never speak to me; for I shall not be here long. I am soon going back again to the miser+ able monotony of drill -- and perhaps our regiment will be ordered out soon. And yet you take away the one little ewe-lamb of plaesure that I have in this dull life of mine. Well, perhaps generosity is not a woman's most marked characteristic.' 'When are you going from here?' she asked, with some interest. 'In a month.' 'But how can it give you pleasure to speak to me?' 'Can you ask Miss Everdene -- knowing as you do -- what my offence is based on?' 'I you do care so much for a silly trifle of that kind, then, I don't mind doing it,' she uncertainly and doubtingly answered. 'But you can't really care for a word from me? you only say so -- I think you only say so.' 'that's unjust -- but I won't repeat the remark. I am too

gratified to get such a mark of your friendship at any price to cavil at the tone. I do Miss Everdene, care for it. You may think a man foolish to want a mere word -- just a good morning. Perhaps he is -- I don't know. But you have never been a man looking upon a woman, and that woman yourself.' " Well.' " Then you know nothing of what such an experience is like -- and Heaven forbid that you ever should!' "Nonsense, flatterer! What is it like? I am interested in knowing." "Put shortly, it is not being able to think, hear, or look in any direction except one without wretchedness, nor there without torture.' " Ah, sergeant, it won't do -- you are pretending ! ' she said, shaking her head. ' Your words are too dashing to be true.' "I am not, upon the honour of a soldier' "But why is it so? -- Of course I ask for mere pas+ time.' " Because you are so distracting -- and I am so distracted. ' " You look like it.' " I am indeed.' " Why, you only saw me the other night!' " That makes no difference. The lightning works in+ stantaneously. I loved you then, at once -- as I do now.' Bathsheba surveyed him curiously, from the feet upward, as high as she liked to venture her glance, which was not quite so high as his eyes. " You cannot and you don"t,' she said demurely. "There is-no such sudden feeling in people. I won't listen to you any longer. Hear me, I wish I knew what o'clock it is -- I am going -- I have wasted too much time here already!" The sergeant looked at his watch and told her. " What, haven't you a watch, miss?' he inquired. "I have not just at present -- I am about to get a new one.' "No. You shall be given one. Yes -- you shall. A gift, Miss Everdene -- a gift." And before she knew what the young -- man was intending, a heavy gold watch was in her hand.

"It is an unusually good one for a man like me to possess,' he quietly said. "That watch has a history. Press the spring and open the back.' She did so. 'What do you see?' 'A crest and a motto.' " A coronet with five points, and beneath, Cedit amor rebus -- "Love yields to circumstance." It's the motto of the Earls of Severn. That watch belonged to the last lord, and was given to my mother's husband, a medical man, for his use till I came of age, when it was to be given to me. It was all the fortune that ever I inherited. That watch has regulated imperial interests in its time -- the stately ceremonial, the courtly assigna+ tion, pompous travels, and lordly sleeps. Now it is yours. " But, Sergeant Troy, I cannot take this -- I cannot ! ' she exclaimed, with round-eyed wonder. " A gold watch ! What are you doing? Don't be such a dissembler!" The sergeant retreated to avoid receiving back his gift, which she held out persistently towards him. Bathsheba followed as he retired. "Keep it -- do, Miss Everdene -- keep it !' said the erratic child of impulse. " The fact of your possessing it makes it worth ten times as much to me. A more plebeian one will answer my purpose just as well, and the pleasure of knowing whose heart my old one beats against -- well, I won't speak of that. It is in far worthier hands than ever it has been in before.' "But indeed I can't have it!' she said, in a perfect simmer of distress. " O, how can you do such a thing ; that is if you really mean it! Give me your dead father's watch, and such a valuable one! You should not be so reckless, indeed, Sergeant Troy!' "I loved my father: good; but better, I love you more. That's how I can do it,' said the sergeant, with an intonation of such exquisite fidelity to nature that it. was evidently not all acted now. Her beauty, which, whilst it had been quiescent, he had praised in jest, had in its animated phases moved him to

earnest; and though his seriousness was less than she imagined, it was probably more than he imagined himself. Bathsheba was brimming with agitated bewilderment, and she said, in half-suspicious accents of feeling, "Can it be! 0, how can it be, that you care for me, and so suddenly,! You have seen so little of me: I may not be really so -- so nice-looking as I seem to you. Please, do take it ; O, do! I cannot and will not have it. Believe me, your generosity is too great. I have never done you a single kindness, and why should you be so kind to me?' A factitious reply had been again upon his lips, but it was again suspended, and he looked at her with an arrested eye. The truth was, that as she now stood -- excited, wild, and honest as the day -- her alluring beauty bore out so fully the epithets he had bestowed upon it that he was quite startled at his temerity in advancing them as false. He said mechanically, "Ah, why ?' and continued to look at her. "And my workfolk see me following you about the field, and are wondering. O, this is dreadful!' she went on, unconscious of the transmutation she was effecting. "I did not quite mean you to accept it at first, for it as my one poor patent of nobility,' he broke out, bluntly; "but, upon my soul, I wish you would now. Without any shamming, come! Don't deny me the happiness of wearing it for my sake ? But you are too lovely even to care to be kind as others are.' " No, no ; don"t say so !. I have reasons for reserve which I cannot explain.' " bet it be, then, let it be,' he said, receiving back the watch at last; "I must be leaving you now. And will you speak to me for these few weeks of my stay ? ' 'Indeed I will. Yet, I don't know if I will! O, why did you come and disturb me so !' "Perhaps in setting a gin, I have caught myself. Such things have happened. Well, will you let me work in your fields ? ' he coaxed. " Yes, I suppose so ; if it is any pleasure to you.' " Miss Everdene, I thank you. " No, no.'

'Good-bye!' The sergeant brought his hand to the cap on the slope of his head, saluted, and returned to the distant group of haymakers. Bathsheba could not face the haymakers now. Her heart erratically flitting hither and thither from per+ plexed excitement, hot, and almost tearful, she retreated homeward, murmuring, O, what have I done ! What does it mean ! I wish I knew how much of it was true!

HIVING THE BEES THE Weatherbury bees were late in their swarming this year. It was in the latter part of June, and the day after the interview with Troy in the hayfield, that Bathsheba was standing in her garden, watching a swarm in the air and guessing their probable settling place. Not only were they late this year, but unruly. Sometimes through+ out a whole season all the swarms would alight on the lowest attainable bough -- such as part of a currant-bush or espalier apple-tree ; next year they would, with just the same unanimity, make straight off to the uppermost member of some tall, gaunt costard, or quarrenden, and there defy all invaders who did not come armed with ladders and staves to take them. This was the case at present. Bathsheba's eyes, shaded by one hand, were following the ascending multitude against the unexplorable stretch of blue till they ultimately halted by one of the unwieldy trees spoken of. A process somewhat analogous to that of alleged formations of the universe, time and times ago, was observable. The bustling swarm had swept the sky in a scattered and uniform haze, which now thickened to a nebulous centre: this glided on to a bough and grew still denser, till it formed a solid black spot upon the light. The men and women being all busily engaged in saving the hay -- even Liddy had left the house for the purpose of lending a hand -- Bathsheba resolved to hive the bees herself, if possible. She had dressed the hive with herbs and honey, fetched a ladder, brush, and crook, made herself impregnable with armour of leather gloves, straw hat, and large gauze veil -- once green but now faded to snuff colour -- and ascended a dozen rungs of the ladder. At once she heard, not ten yards off, a voice that was beginning to have a strange power in agitating her.

"Miss Everdene, let me assist you ; you should not attempt such a thing alone.' Troy was just opening the garden gate. Bathsheba flung down the brush, crook, and empty hive, pulled the skirt of her dress tightly round her ankles in a tremendous flurry, and as well as she could slid down the ladder. By the time she reached the bottom Troy was there also, and he stooped to pick up the hive. "How fortunate I am to have dropped in at this moment!' exclaimed the sergeant. She found her voice in a minute. "What! and will you shake them in for me?' she asked, in what, for a defiant girl, was a faltering way; though, for a timid girl, it would have seemed a brave way enough. " Will I ! ' said Troy. " Why, of course I will. How blooming you are to-day ! ' Troy flung down his cane and put his foot on the ladder to ascend. "But you must have on the veil and gloves, or you'll be stung fearfully!' "Ah, yes. I must put on the veil and gloves. Will you kindly show me how to fix them properly?' 'And you must have the broad-brimmed hat, too ;, for your cap has no brim to keep the veil off, and they'd reach your face.' " The broad-brimmed hat, too, by all means.' So a whimsical fate ordered that her hat should be taken off -- veil and all attached -- and placed upon his head, Troy tossing his own into a gooseberry bush. Then the veil had to be tied at its lower edge round his collar and the gloves put on him. He looked such an extraordinary object in this guise that, flurried as she was, she could not avoid laughing outright. It was the removal of yet another stake from the palisade of cold manners which had kept him off Bathsheba looked on from the g:-ound whilst he was busy sweeping and shaking the bees from the tree, holding up the hive with the other hand for them to fall into. She made use of an unobserved minute whilst his attention was absorbed in the

operation to arrange her plumes a little. He came down holding the hive at arm's length, behind which trailed a cloud of bees. ' Upon my life,' said Troy, through the veil, ' holding up this hive makes one"s arm ache worse than a week of sword-exercise.' When the manoeuvre was complete he approached her. 'Would you be good enough to untie me and let me out? I am nearly stifled inside this silk cage.' To hide her embarrassment during the unwonted process of untying the string about his neck, she said : -- 'I have never seen that you spoke of.' 'What ?' 'The sword-exercise.' 'Ah ! would you like to ?' said Troy. Bathsheba hesitated. She had heard wondrous reports from time to time by dwellers in Weatherbury, who had by chance sojourned awhile in Casterbridge, near the barracks, of this strange and glorious perform+ ance, tlie sword-exercise. Men and boys who had peeped through chinks or over walls into the barrack+ yard returned with accounts of its being the most flashing affair conceivable ; accoutrements and weapons glistening like stars-here,there,around-yet all by rule and compass. So she said mildly what she felt strongly. 'Yes ; I should like to see it very much.' 'And so you shall; you shall see me go through it.' 'No! How?' 'Let me consider.' 'Not with a walking-stick -- I don't care to see that. lt must be a real sword.' 'Yes, I know; and I have no sword here; but I think I could get one by the evening. Now, will you do this?' 'O no, indeed !' said Bathsheba, blushing. ' Thank you very much, but I couldn't on any account. 'Surely you might? Nobody would know.' She shook her head, but with a weakened negation. ' If I were to,' she said, 'I must bring Liddy too. Might I not?'

Troy looked far away. 'I don't see why you want to bring her,' he said coldly. An unconscious look of assent in Bathsheba's eyes betrayed that something more than his coldness had made her also feel that Liddy Would be superfluous in the suggested scene. She had felt it, even whilst making the proposal. 'Well, I won't bring Liddy -- and I'll come. But only for a very short time,' she added; 'a very short time.' 'It will not take five minutes,' said Troy.

THE HOLLOW AMID THE FERNS THE hill opposite Bathsheba's dwelling extended, a mile off, into an uncultivated tract of land, dotted at this season with tall thickets of brake fern, plump and diaphanous from recent rapid growth, and radiant in hues of clear and untainted green. At eight o'clock this midsummer evening, whilst the bristling ball of gold in the west still swept the tips of the ferns with its long, luxuriant rays, a soft brushing+ by of garments might have been heard among them, and Bathsheba appeared in their midst, their soft, feathery arms caressing her up to her shoulders. She paused, turned, went back over the hill and half-way to her own door, whence she cast a farewell glance upon the spot she had just left, having resolved not to remain near the place after all. She saw a dim spot of artificial red moving round the shoulder of the rise. It disappeared on the other side. She waited one minute -- two minutes -- thought of Troy's disappointment at her non-fulfilment of a promised engagement, till she again ran along the field, clambered over the bank, and followed the original direction. She was now literally trembling and panting at this her temerity in such an errant undertaking; her breath came and went quickly, and her eyes shone with an in+ frequent light. Yet go she must. She reached the verge of a pit in the middle of the ferns. Troy stood in the bottom, looking up towards her. 'I heard you rustling through the fern before I saw you,' he said, coming up and giving her his hand to help her down the slope. The pit was a saucer-shaped concave, naturally formed, with a top diameter of about thirty feet, and shallow enough to allow the sunshine to reach their heads. Standing in the

centre, the sky overhead was met by a circular horizon of fern : this grew nearly to the bottom of the slope and then abruptly ceased. The middle within the belt of verdure was floored with a thick flossy carpet of moss and grass intermingled, so yielding that the foot was half-buried within it. 'Now,' said 'Troy, producing the sword, which, as he raised it into the sunlight, gleamed a sort of greeting, like a living thing, 'first, we have four right and four left cuts; four right and four left thrusts. Infantry cuts and guards are more interesting than ours, to my mind; but they are not so swashing. They have seven cuts and three thrusts. So much as a preliminary. Well, next, our cut one is as if you were sowing your corn -- so.' Bathsheba saw a sort of rainbow, upside down in the air, and Troy's arm was still again. 'Cut two, as if you were hedging -- so. Three, as if you were reaping -- so.' Four, as if you were threshing -- in that way. 'Then the same on the left. The thrusts are these : one, two, three, four, right ; one, two, three, four, left.' He repeated them. 'Have 'em again ?' he said. 'One, two -- -- ' She hurriedly interrupted : 'I'd rather not; though I don't mind your twos and fours; but your ones and threes are terrible !' 'Very well. I'll let you off the ones and threes. Next, cuts, points and guards altogether.' Troy duly exhibited them. 'Then there's pursuing practice, in this way.' He gave the movements as before. 'There, those are the stereotyped forms. The infantry have two most diabolical upward cuts, which we are too humane to use. Like this -- three, four.' 'How murderous and bloodthirsty !' 'They are rather deathy. Now I'll be more inter+ esting, and let you see some loose play -- giving all the cuts and points, infantry and cavalry, quicker than lightning, and as promiscuously -- with just enough rule to regulate instinct and yet not to fetter it. You are my antagonist, with this difference from real warfare, that I shall miss you every time by one hair's breadth, or perhaps two. Mind you don't flinch, whatever you do.'

'I'll be sure not to!' she said invincibly. He pointed to about a yard in front of him. Bathsheba's adventurous spirit was beginning to find some grains of relish in these highly novel proceedings. She took up her position as directed, facing Troy. 'Now just to learn whether you have pluck enough to let me do what I wish, I'll give you a preliminary test.' He flourished the sword by way of introduction number two, and the next thing of which she was conscious was that the point and blade of the sword were darting with a gleam towards her left side, just above her hip; then of their reappearance on her right side, emerging as it were from between her ribs, having apparently passed through her body. The third item of consciousness was that of seeing the same sword, perfectly clean and free from blood held vertically in Troy's hand (in the position technically called 'recover swords'). All was as quick as electricity. 'Oh!' she cried out in affright, pressing her hand to her side. ' Have you run me through ? -- no, you have not! Whatever have you done!' 'I have not touched you,' said Troy, quietly. 'It was mere sleight of hand. The sword passed behind you. Now you are not afraid, are you ? Because if you are l can't perform. I give my word that l will not only not hurt you, but not once touch you.' 'I don't think I am afraid. You are quite sure you will not hurt me ?' 'Quite sure.' "Is the sWord very sharp ?' 'O no -- only stand as still as a statue. Now !' In an instant the atmosphere was transformed to Bathsheba's eyes. Beams of light caught from the low sun's rays, above, around, in front of her, well-nigh shut out earth and heaven -- all emitted in the marvellous evolutions of Troy's reflecting blade, which seemed everywhere at once, and yet nowherre specially. These circling gleams were accompanied by a keen rush that was almost a whistling -- also springing

from all sides of her at once. In short, she was enclosed in a firmament of light, and of sharp hisses, resembling a sky-full of meteors close at hand. Never since the broadsword became the national weapon had there been more dexterity shown in its management than by the hands of Sergeant Troy, and never had he been in such splendid temper for the performance as now in the evening sunshine among the ferns with Bathsheba. It may safely be asserted with respect to the closeness of his cuts, that had it been possible for the edge of the sword to leave in the air a permanent substance wherever it flew past, the space left untouched would have been almost a mould of Bathsheba's figure. Behind the luminous streams of this aurora militaris, she could see the hue of Troy's sword arm, spread in a scarlet haze over the space covered by its motions, like a twanged harpstring, and behind all Troy himself, mostly facing her; sometimes, to show the rear cuts, half turned away, his eye nevertheless always keenly measuring her breadth and outline, and his lips tightly closed in sustained effort. Next, his movements lapsed slower, and she could see them individually. The hissing of the sword had ceased, and he stopped entirely. 'That outer loose lock of hair wants tidying, he said, before she had moved or spoken. 'Wait: I'll do it for you.' An arc of silver shone on her right side: the sword had descended. The lock droped to the ground. 'Bravely borne!' said Troy. 'You didn't flinch a shade's thickness. Wonderful in a woman!' 'It was because I didn't expect it. O, you have spoilt my hair!' 'Only once more.' 'No -- no! I am afraid of you -- indeed I am !' she cried. 'I won't touch you at all -- not even your hair. I am only going to kill that caterpillar settling on you. Now: still!' It appeared that a caterpillar had come from the fern and chosen the front of her bodice as his resting place. She saw the point glisten towards her bosom, and seemingly enter it. Bathsheba closed her eyes in the full persuasion that she was

killed at last. How+ ever, feeling just as usual, she opened them again. 'There it is, look,' said the sargeant, holding his sword before her eyes. The caterpillar was spitted upon its point. 'Why, it is magic!' said Bathsheba, amazed. 'O no -- dexterity. I merely gave point to your bosom where the caterpillar was, and instead of running you through checked the extension a thousandth of an inch short of your surface.' 'But how could you chop off a curl of my hair with a sword that has no edge?' THE HOLLOW AMID THE FERNS "No edge .! This sword will shave like a razor. Look here.' He touched the palm of his hand with the blade, and then, lifting it, showed her a thin shaving of scarf+ skin dangling therefrom. " But you said before beginning that it was blunt and couldn't cut me .!' 'That was to get you to stand still, and so make sure of your safety. The risk of injuring you through your moving was too great not to force me to tell you a fib to escape it.' She shuddered. 'I have been within an inch of my life, and didn't know it! ' 'More precisely speaking, you have been within half an inch of being pared alive two hundred and ninety-five tinies.' " Cruel, cruel, 'tis of you !. ' " You have been perfectly safe, nevertheless. My sword never errs.' And Troy returned the weapon to the scabbard. Bathsheba, overcome by a hundred tumultuous feel' ings resulting from the scene, abstractedly sat down on a tuft of heather. 'I must leave you now,' said Troy, softly. " And I'll venture to take and keep this in remembrance of you.' She saw him stoop to the grass, pick up the winding lock which he had severcd from her manifold tresses, twist it round his fingers, unfasten a button in the hreast of his coat, and carefully put it inside. She felt power+ less to withstand or deny him. He was altogether too much for her, and Bathsheba

seemed as one who, facing a reviving wind, finds it blow so strongly that it stops the breath. He drew near and said, 'I must be leaving you.' He drew nearer still. A minute later and she saw his scarlet form disappear amid the ferny thicket, almost in a flash, like a brand swiftly waved. That minute's interval had brought the blood beating into her face, set her stinging as if aflame to the very hollows oi her feet, and enlarged emotion to a compass which quite swamped thought. It had brought upon her a stroke resulting, as did that of Moses in Horeh, in a liquid stream -- here a stream of tears. She felt like one who has sinned a great sin. The circumstance had been the gentle dip of Troy's mouth downwards upon her own. He had kissed her, PARTICULARS OF A TWILIGHT WALK

PARTICULARS OF A TWILIGHT WALK WE now see the element of folly distinctly mingling with the many varying particulars which made up the character of Bathsheba Everdene. It was almost foreign to her intrinsic nature. Introduced as lymph on the dart of Eros, it eventually permeated and coloured her whole constitution. Bathsheba, though she had too much understanding to be entirely governed by her womanliness, had too much womanliness to use her understanding to the best advantage. Perhaps in no minor point does woman astonish her helpmate more than in the strange power she possesses of believing cajoleries that she knows to be false -- except, indeed, in that of being utterly sceptical on strictures that she knows to be true. Bathsheba loved Troy in the way that only self-reliant women love when they abandon their self-reliance. When a strong woman recklessly throws away her strength she is worse than a weak woman who has never had any strength to throw away. One source of her inadequacy is the novelty of the occasion. She has never had practice in making the best of such a condition. Weakness is doubly weak by being new. Bathsheba was not conscious of guile in this matter. Though in one sense a woman of the world, it was, after all, that world of daylight coteries and green carpets wherein cattle form the passing crowd and winds the busy hum ; where a quiet family of rabbits or hares lives on the other side of your party-wall, where your neigh+ bour is everybody in the tything, and where calculation formulated self-indulgence of bad, nothing at all. Had her utmost thoughts in this direction been distinctly worded (and by herself they never were), they would

only have amounted to such a matter as that she felt her impulses to be pleasanter guides than her discretion . Her love was entire as a child's, and though warm as summer it was fresh as spring. Her culpability lay in her making no attempt to control feeling by subtle and careful inquiry into consuences. She could show others the steep and thorny way, but 'reck'd not her own rede,' And Troy's deformities lay deep down from a woman's vision, whilst his embellishments were upon the verysurface; thus contrasting with homely Oak, whose defects were patent to the blindest, and whose vertues were as metals in a mine. The difference between love and respect was mark+ edly shown in her conduct. Bathsheba had spoken of her interest in Boldwood with the greatest freedom to Liddy, but she had only communed with her own heart concerning 'Troy'. All this infatuation Gabriel saw, and was troubled thereby from the time of his daily journey a-field to the time of his return, and on to the small hours of many a night. That he was not beloved had hitherto been his great that Bathsheba was getting into the toils was now a sorrow greater than the first, and one which nearly olbscured it. It was a result which paralleled the oft-quoted observation of Hippocrates concerning physical pains. That is a noble though perhaps an unpromising love PARTICULARS OF A TWILlGHT WALK which not even the fear of breeding aversion in the bosom of the one beloved can deter from combating his or her errors. Oak determined to speak to his mistress. He would base his appeal on what he considered her unfair treatment of Farmer Boldwood, now absent from home. An opportunity occurred one evening when she had gone for a short walk by a path through the neighbour+ ing cornfields. It was dusk when Oak, who had not been far a-field that day, took the same path and met her returning, quite pensively, as he thought. The wheat was now tall, and the path was narrow; thus the way was quite a sunken groove between the embowing thicket on either side. Two persons could not walk abreast

without damaging the crop, and Oak stood aside to let her pass. 'Oh, is it Gabriel?' she said. 'You are taking a walk too. Good-night.' "I thought I would come to meet you, as it is rather late," said Oak, turning and following at her heels when she had brushed somewhat quickly by him. "Thank you, indeed, but I am not very fearful.' " O no ; but there are bad characters about.' "I never meet them.' Now Oak, with marvellous ingenuity, had been going to introduce the gallant sergeant through the channel of "bad characters.' But all at once the scheme broke down, it suddenly occurring to him that this was rather a clumsy way, and too barefaced to begin with. He tried another preamble. "And as the man who would naturally come to meet you is away from home, too -- I mean Farmer Boldwood -- why, thinks I, I'll go,' he said. "Ah, yes.' She walked on without turning her head, and for many steps nothing further was heard from her quarter than the rustle of her dress against the heavy corn-ears. Then she resumed rather tartly -- 'I don't quite understand what you meant by saying that Mr. Boldwood would naturally come to meet me.' I meant on account of the wedding which they say is likely to take place between you and him, miss. For+ give my speaking plainly.' "They say what is not true,' she returned quickly. No marriage is likely to take place between us.' Gabriel now put forth his unobscured opinion, for the moment had come. " Well, Miss Everdene,' he said, "putting aside what people say, I never in my life saw any courting if his is not a courting of you." Bathsheba would probably have terminated the con' versation there and then by flatly forbidding the subject, had not her conscious weakness of position allured her to palter and argue in endeavours to better it.

"Since this subject has been mentioned,' she said very emphatically, 'I am glad of the opportunity of clearing up a mistake which is very common and very provoking. I didn't definitely promise Mr. Boldwood anything. I have never cared for him. I respect him, and he has urged me to marry him. But I have given him no distinct answer. As soon as he returns I shall do so; and the answer will be that I cannot think of marrying him.' 'People are full of mistakes, seemingly.' ' They are.' The other day they said you were trifling with him, and you almost proved that you were not; lately they have said that you be not, and you straightway begin to show -- -- ' That I am, I suppose you mean.' ' Well, I hope they speak the truth.' They do, but wrongly applied. I don't trifle with him ; but then, I have nothing to do with him.' Oak was unfortunately led on to speak of Boldwood's rival in a wrong tone to her after all. 'I wish you had never met that young Sergeant Troy, miss,' he sighed. PARTlCULARS OF A TWILIGHT WALK Bathsheba's steps became faintly spasmodic. " Why?' she asked. ' He is not good enough for 'ee.' "Did any one tell you to speak to me like this ?' " Nobody at all.' "Then it appears to me that Sergeant Troy does not concern us here,' she said, intractably. ' Yet I must say that Sergeant 'Troy is an educated man, and quite worthy of any woman. He is well born.' "His being higher in learning and birth than the ruck o' soldiers is anything but a proof of his worth. It show's his course to be down'ard.' "I cannot see what this has to do with our conversa+ tion. Mr. Troy's course is not by any means downward; and his superiority <1is>1 a proof of his worth .! ' "I believe him to have no conscience at all. And I cannot help begging you, miss, to have nothing to do with him. Listen to me this once -- only this once !. I don't say he's such

a bad man as I have fancied -- I pray to God he is not. But since we don't exactly know what he is, why not behave as if he <1might>1 be bad, simply for your own safety ? Don't trust him, mistress; I ask you not to trust him so.' " Why, pray ? ' "I like soldiers, but this one I do not like,' he said, sturdily. " His cleverness in his calling may have tempted him astray, and what is mirth to the neighbours is ruin to the woman. When he tries to talk to 'ee again, why not turn away with a short 'Good day' ; and when you see him coming one way, turn the other. When he says anything laughable, fail to see the point and don't smile, and speak of him before those who will report your talk as "that fantastical man,' or " that Sergeant What's-his-name." "That man of a family that has come to the dogs.' Don't be unmannerly towards en, but harmless-uncivil, and so get rid of the man.' No Christmas robin detained by a window-pane ever pulsed as did Bathsheba now. I say -- I say again -- that it doesn't become you to talk about him. Why he should be mentioned passes me quite . she exclaimed desperately. " I know this, th-th-that he is a thoroughly conscientious man -- blunt sometimes even to rudeness -- but always speaking his mind about you plain to your face .! ' "Oh.' "He is as good as anybody in this parish.! He is very particular, too, about going to church -- yes, he is.!' 'I am afraid nobody saw him there. I never did certainly.' ' The reason of that is,' she said eagerly, " that he goes in privately by the old tower door, just when the service commences, and sits at the back of the gallery. He told me so.' This supreme instance of Troy's goodness fell upon Gabriel ears like the thirteenth stroke of crazy clock. It was not only received with utter incredulity as re+ garded itself, but threw a doubt on all the assurances that had preceded it. Oak was grieved to find how entirely she trusted him. He brimmed with deep feeling as he replied in a steady voice, the

steadiness of which was spoilt by the palpable+ ness of his great effort to keep it so : -- ' You know, mistress, that I love you, and shall love you always. I only mention this to bring to your mind that at any rate I would wish to do you no harm : beyond that I put it aside. I have lost in the race for money and good things, and I am not such a fool as to pretend to 'ee now I am poor, and you have got alto+ gether above me. But Bathsheba, dear mistress, this I beg you to consider -- that, both to keep yourself well honoured among the workfolk, and in common generosity to an honourable man who loves you as well as I, you PARTICULARS OF A TWILIGHT WALK should be more discreet in your bearing towards this soldier.' " Don't, don't, don't !. ' she exclaimed, in a choking voice. "Are ye not more to me than my own affairs, and even life .! ' he went on. "Come, listen to me.! I am six years older than you, and Mr. Boldwood is ten years older than I, and consider -- I do beg of 'ee to consider before it is too late -- how safe you would be in his hands .! ' Oak's allusion to his own love for her lessened, to some extent, her anger at his interference ; but she could not really forgive him for letting his wish to marry her be eclipsed by his wish to do her good, any more than for his slighting treatment of Troy. "I wish you to go elsewhere,' she commanded, a paleness of face invisible to the eye being suggested by the trembling words. " Do not remain on this farm any longer. I don't want you -- I beg you to go !.' "That's nonsense,' said Oak, calmly. " This is the second time you have pretended to dismiss me; and what's the use o' it?' " Pretended !. You shall go, sir -- your lecturing I will not hear .! I am mistress here.' " Go, indeed -- what folly will you say next ? Treating me like Dick, Tom and Harry when you know that a short time ago my position was as good as yours !. Upon my life, Bathsheba, it is too barefaced. You know, too, that I can't go without putting things in such a strait as you wouldn't get out of

I can't tell when. Unless, indeed, you'll promise to have an understanding man as bailiff, or manager, or something. I'll go at once if you'll promise that.' 'I shall have no bailiff; I shall continue to be my own manager,' she said decisively. "Very well, then ; you should be thankful to me for biding. How would the farm go on with nobody to mind it but a woman? But mind this, I don't wish 'ee to feel you owe me anything. Not I. What I do, I do. Sometimes I say I should be as glad as a bird to leave the place -- for don't suppose I'm content to be a nobody. I was made for better things. However, I don't like to see your concerns going to ruin, as they must if you keep in this mind.... I hate taking my own measure so plain, but, upon my life, your provok+ ing ways make a man say what he wouldn't dream of at other times ! I own to being rather interfering. But you know well enough how it is, and who she is that I like too well, and feel too much like a fool about to be civil to her ! ' It is more than probable that she privately and un+ consciously respected him a little for this grim fidelity, which had been shown in his tone even more than in his words. At any rate she murmured something to the effect that he might stay if he wished. She said more distinctly, " Will you leave me alone now? I don't order it as a mistress -- I ask it as a woman, and I expect you not to be so uncourteous as to refuse.' " Certainly I will, Miss Everdene,' said Gabriel, gently. He wondered that the request should have come at this moment, for the strife was over, and they were on a most desolate hill, far from every human habitation, and the hour was getting late. He stood still and allowed her to get far ahead of him till he could only see her form upon the sky. A distressing explanation of this anxiety to be rid of him at that point now ensued. A figure apparently rose from the earth beside her. The shape beyond all doubt was Troy's. Oak would not be even a possible listener, and at once turned back till a good two hundred yards were between the lovers and himself.

Gabriel went home by way of the churchyard. In passing the tower he thought of what she had said about the sergeant's virtuous habit of entering the church un+ PARTICULARS OF A TWILIGHT WALK perceived at the beginning of service. Believing that the little gallery door alluded to was quite disused, he ascended the external flight of steps at the top of which it stood, and examined it. The pale lustre yet hanging in the north-western heaven was sufficient to show that a sprig of ivy had grown from the wall across the door to a length of more than a foot, delicately tying the panel to the stone jamb. It was a decisive proof that the door had not been opened at least since Troy came back to Weatherbury.

HOT CHEEKS AND TEARFUL EYES HALF an hour later Bathsheba entered her own house. There burnt upon her face when she met the light of the candles the flush and excitement which were little less than chronic with her now. The farewell words of Troy, who had accompanied her to the very door, still lingered in her ears. He had bidden her adieu for two days, which were so he stated, to be spent at Bath in visiting some friends. He had also kissed her a second time. It is only fair to Bathsheba to explain here a little fact which did not come to light till a long time after+ wards : that Troy's presentation of himself so aptly at the roadside this evening was not by any distinctly pre+ concerted arrangement. He had hinted -- she had forbidden; and it was only on the chance of his still coming that she had dismissed Oak, fearing a meeting between them just then. She now sank down into a chair, wild and perturbed by all these new and fevering sequences. Then she jumped up with a manner of decision, and fetched her desk from a side tahle. In three minutes, without pause or modification, she had written a letter to Boldwood, at his address beyond Casterbridge, saying mildly but firmly that she had well HOT CHEEKS AND TEARFUL EYES considered the whole subject he had brought before her and kindly given her time to decide upon; that her final decision was that she could not marry him. She had expressed to Oak an intention to wait till Boldwood came home before communicating to him her conclusive reply. But Bathsheba found that she could not wait. It was impossible to send this letter till the next day; yet to quell her uneasiness by getting it out of her hands, and so, as it were, setting the act in motion at once, she arose to take it to any one of the women who might be in the kitchen.

She paused in the passage. A dialogue was going on in the kitchen, and Bathsheba and Troy were the subject of it. "If he marry her, she'll gie up farming.' "Twill be a gallant life, but may bring some trouble between the mirth -- so say I.' "Well, I wish I had half such a husband.' Bathsheba had too much sense to mind seriously what her servitors said about her ; but too much womanly redundance of speech to leave alone what was said till it died the natural death of unminded things. She burst in upon them. "Who are you speaking of? ' she asked. There was a pause before anybody replied. At last Liddy said frankly, ' What was passing was a bit of a word about yourself, miss.' "I thought so .! Maryann and Liddy and Temper+ ance -- now I forbid you to suppose such things. You know I don't care the least for Mr. Troy -- not I. Every+ body knows how much I hate him. -- Yes,' repeated the froward young person, "<1hate>1 him .! ' " We know you do, miss,' said Liddy; "and so do we all.' " I hate him too,' said Maryann. " Maryann -- O you perjured woman !. How can you speak that wicked story ! ' said Bathsheba, excitedly. "You admired him from your heart only this morning in the very world, you did. Yes, Maryann, you know it ! ' 'Yes, miss, but so did you. He is a wild scamp now, and you are right to hate him." "He's <1not>1 a wild scamp.! How dare you to my face !. I have no right to hate him, nor you, nor anybody. But I am a silly woman.! What is it to me what he is ? You know it is nothing. I don't care for him ; I don"t mean to defend his good name, not I. Mind this, if any of you say a word against him you'll be dismissed instantly !. ' She flung down the letter and surged back into the parlour, with a big heart and tearful eyes, Liddy following her. 'O miss.!' said mild Liddy, looking pitifully into Bathsheba's face. "I am sorry we mistook you so .! did think you cared for him; but I see you don't now.' " Shut the door, Liddy.'

Liddy closed the door, and went on : ' People always say such foolery, miss. I'll make answer hencefor'ard, "Of course a lady like Miss Everdene can't love him;' I'll say it out in plain black and white.' Bathsheba burst out : 'O Liddy, are you such a simpleton ? Can't you read riddles ? Can't you see? Are you a woman yourself ? ' Liddy's clear eyes rounded with wonderment. ' Yes; you must be a blind thing, Liddy .! ' she said, in reckless abandonment and grief. "O, I love him to very distraction and misery and agony .! Don't be frightened at me, though perhaps I am enough to frighten any innocent woman. Come closer -- closer.' She put her arms round Liddy's neck. "I must let it out to somebody; it is wearing me away !. Don't you yet know enough of me to see through that miserable denial of mine? O God, what a lie it was !. Heaven and my Love forgive me. And don't you know that a woman who loves at all thinks nothing of perjury when it is HOT CHEEKS AND TEARFUL EYES balanced against her love ? There, go out of the room ; I want to be quite alone.' Liddy went towards the door. ' Liddy, come here. Solemnly swear to me that he's not a fast man; that it is all lies they say about him !.' 'Put, miss, how can I say he is not if -- -- ' "You graceless girl.! How can you have the cruel heart to repeat what they say? Unfeeling thing that you are.... But <1I'll>1 see if you or anybody else in the village, or town either, dare do such a thing .! ' She started off, pacing from fireplace to door, and back again. "No, miss. I don't -- I know it is not true !. ' said Liddy, frightened at Bathsheba's unwonted vehemence. I suppose you only agree with me like that to please me. But, Liddy, he <1cannot be>1 had, as is said. Do you hear? " ' Yes, miss, yes.' "And you don't believe he is?" 'I don't know what to say, miss,' said Liddy, be+ ginning to cry. "If I say No, you don"t believe me; and if I say Yes, you rage at me ! ' " Say you don't believe it -- say you don't ! '

'I don't believe him to be so had as they make out.' "He is not had at all.... My poor life and heart, how weak I am .! ' she moaned, in a relaxed, desultory way, heedless of Liddy's presence. "O, how I wish I had never seen him.! Loving is misery for women always. I shall never forgive God for making me a woman, and dearly am I beginning to pay for the honour of owning a pretty face.' She freshened and turned to Liddy suddenly. " Mind this, Lydia Smallbury, if you repeat anywhere a single word of what l have said to you inside this closed door, I'll never trust you, or love you, or have you with me a moment longer -- not a moment ! ' " I don't want to repeat anything,' said Liddy, with womanly dignity of a diminutive order; "but I don't wish to stay with you. And, if you please, I'll go at the end of the harvest, or this week, or to-day.... I don't see that I deserve to be put upon and stormed at for nothing ! ' concluded the small woman, bigly. " No, no, Liddy ; you must stay ! ' said Bathsheba, dropping from haughtiness to entreaty with capricious inconsequence. "You must not notice my being in a taking just now. You are not as a servant -- -you are a companion to me. Dear, dear -- I don't know what I am doing since this miserable ache o'! my heart has weighted and worn upon me so .! What shall I come to ! I suppose I shall get further and further into troubles. I wonder sometimes if I am doomed to die in the Union. I am friendless enough, God knows .! ' 'I won't notice anything, nor will I leave you ! " sobbed Liddy, impulsively putting up her lips to Bathsheba's, and kissing her. Then Bathsheba kissed Liddy, and all was smooth again. "I don't often cry, do I, Lidd ? but you have made tears come into my eyes,' she said, a smile shining through the moisture. "Try to think him a good man, won't you, dear Liddy ? ' "I will, miss, indeed.' "He is a sort of steady man in a wild way, you know. way. I am afraid that's how I am. And promise me to keep my secret -- do, Liddy.! And do not let them know that I have been crying

about him, because it will be dreadful for me, and no good to him, poor thing .!' "Death's head himself shan't wring it from me, mistress, if I've a mind to keep anything; and I'll always be your friend,' replied Liddy, emphatically, at the same time bringing a few more tears into her own eyes, not from any particular necessity, but from an artistic sense of making herself in keeping with the remainder of the HOT CHEEKS AND TEARFUL EYES picture, which seems to influence women at such times. "I think God likes us to be good friends, don't you ?' "Indeed I do.' "And, dear miss, you won"t harry me and storm at me, will you ? because you seem to swell so tall as a lion then, and it frightens me !. Do you know, I fancy you would be a match for any man when you are in one 0' your takings.' "Never.! do you ? ' said Bathsheba, slightly laughing, though somewhat seriously alarmed by this Amazonian picture of herself. "I hope I am not a bold sort of maid -- mannish ? ' she continued with some anxiety. "O no, not mannish; but so almighty womanish that 'tis getting on that way sometimes. Ah ! miss,' she said, after having drawn her breath very sadly in and sent it very sadly out, "I wish I had half your failing that way. 'Tis a great protection to a poor maid in these illegit'mate days !. '

BLAME -- FURY THE next evening Bathsheba, with the idea of getting out of the way of Mr. Boldwood in the event of his returning to answer her note in person, proceeded to fulfil an engagement made with Liddy some few hours earlier. Bathsheba's companion, as a gage of their reconciliation, had heen granted a week's holiday to visit her sister, who was married to a thriving hurdler and cattle-crib-maker living in a delightful labyrinth of hazel copse not far beyond Yalbury. The arrangement was that Miss Everdene should honour them by coming there for a day or two to inspect some ingenious con+ tnvances which this man of the woods had introduced into his wares. Leaving her instructions with Gabriel and Maryann, that they were to see everything carefully locked up for the night, she went out of the house just at the close of a timely thunder-shower, which had refined the air, and daintily bathed the coat of the land, though all beneath was dry as ever. Freshness was exhaled in an essence from the varied contours of bank and hollow, as if the earth breathed maiden breath; and the pleased birds were hymning to the scene. Before her, among the clouds, there was a contrast in the shape of lairs of fierce light which showed themselves in the neighbour+ hood of a hidden sun, lingering on to the farthest north+ west corner of the heavens that this midsummer season allowed. She had walked nearly two miles of her journey, watching how the day was retreating, and thinking how the time of deeds was quietly melting into the time of thought, to give place in its turn to the time of prayer and sleep, when she beheld advancing over Yalbury hill the very man she sought so anxiously to elude. Boldwood was stepping on, not with that quiet tread of reserved strength which was his customary

gait, in which he always seemed to be balancing two thoughts. His manner was stunned and sluggish now. Boldwood had for the first time been awakened to woman's privileges in tergiversation even when it involves another person's possible blight. That Bathsheba was a firm and positive girl, far less inconsequent than her fellows, had been the very lung of his hope ; for he had held that these qualities would lead her to adhere to a straight course for consistency's sake, and accept him, though her fancy might not flood him with the iridescent hues of uncritical love. But the argument now came back as sorry gleams from a broken mirror. The dis+ covery was no less a scourge than a surprise. He came on looking upon the ground, and did not see Bathsheba till they were less than a stone's throw apart. He looked up at the sound of her pit-pat, and his changed appearance sufficiently denoted to her the depth and strength of the feelings paralyzed by her letter. " Oh ; is it you, Mr. Boldwood ? ' she faltered, a guilty warmth pulsing in her face. Those who have the power of reproaching in silence may find it a means more effective than words. There are accents in the eye which are not on the tongue, and more tales come from pale lips than can enter an ear. It is both the grandeur and the pain of the remoter moods that they avoid the pathway of sound. Bold+ wood's look was unanswerable. Seeing she turned a little aside, he said, 'What, are you afraid of me?' " Why should you say that ? ' said Bathsheba. "I fancied you looked so,' said he. 'And it is most strange, because of its contrast with my feeling for you. She regained self-possession, fixed her eyes calmly, and waited. " You know what that feeling is,' continued Boldwood, deliberately. "A thing strong as death. No dismissal by a hasty letter affects that.' 'I wish you did not feel so strongly about me,' she murmured. "It is generous of you, and more than I deserve, but I must not hear it now.'

"Hear it? What do you think I have to say, then ? I am not to marry you, and thats enough. Your letter was excellently plain. I want you to hear nothing -- not I.' Bathsheba was unable to direct her will into any definite groove for freeing herself from this fearfully and was moving on. Boldwood walked up to her heavily and dully. "Bathsheba -- -darling -- -is it final indeed?' "Indeed it is.' "O, Bathsheba -- -have pity upon me!' Boldwood burst out. "God's sake, yes -- I am come to that low, lowest stage -- -to ask a woman for pity! Still, she is you -- -she is you.' Bathsheba commanded herself well. But she could hardly get a clear voice for what came instinctively to her lips: "There is little honour to the woman in that speech.' It was only whispered, for something unutter+ ably mournful no less than distressing in this spectacle of a man showing himself to be so entirely the vane of a passion enervated the feminine instinct for punctilios. BLAME "I am beyond myself about this, and am mad,' he said. "I am no stoic at all to he supplicating here ; but I do supplicate to you. I wish you knew what is in me of devotion to you ; but it is impossible, that. In bare human mercy to a lonely man, don't throw me off now !' 'I don't throw you off -- indeed, how can I ? I never had you.' In her noon-clear sense that she had never loved him she forgot for a moment her thoughtless angle on that day in February. 'But there was a time when you turned to me, before I thought of you ! I don't reproach you, for even now I feel that the ignorant and cold darkness that I should have lived in if you had not attracted me by that letter -- valentine you call it -- would have becn worse than my knowledge of you, though it has brought this misery. But, I say, there was a time when I knew nothing of you, and cared nothing for you, and yet you drew me on. And if you say you gave me no en+ couragement, I cannot but contradict you.'

"What you call encouragement was the childish game of an idle minute. I have bitterly repented of it -- ay, bitterly, and in tears. Can you still go on re+ minding me ?' 'I don't accuse you of it -- I deplore it. I took for earnest what you insist was jest, and now this that I pray to be jest you say is awful, wretched earnest. Our moods meet at wrong places. I wish your feeling was more like mine, or my feeling more like yours.! O, could I but have foreseen the torture that trifling trick was going to lead me into, how I should have cursed you ; but only having been able to see it since, I cannot do that, for I love you too well.! But it is weak, idle drivelling to go on like this.... Bathsheba, you are the first woman of any shade or nature that I have ever looked at to love, and it is the having been so near claiming you for my own that makes this denial so hard to bear. How nearly you promised me ! But I don't speak now to move your heart, and make you grieve because of my pain ; it is no use, that. I must bear it; my pain would get no less by paining you.' "But I do pity you -- deeply -- O so deeply .!' she earnestly said. "Do no such thing -- do no such thing. Your dear love, Bathsheba, is such a vast thing beside your pity, that the loss of your pity as well as your love is no great addition to my sorrow, nor does the gain of your pity make it sensibly less. O sweet -- how dearly you spoke to me behind the spear-bed at the washing-pool, and in the barn at the shearing, and that dearest last time in the evening at your home.! Where are your pleasant words all gone -- your earnest hope to be able to love me? Where is your firm conviction that you would get to care for me very much ? Really forgotten ? -- really ? ' She checked emotion, looked him quietly and clearly in the face, and said in her low, firm voice, " Mr. Bold+ wood, I promised you nothing. Would you have had me a woman of clay when you paid me that furthest, highest compliment a man can pay a woman -- telling her he loves her? I was bound to show some feeling, if l would not be a graceless shrew. Yet each of those pleasures was just for the day -- the day just for the

pleasure. How was I to know that what is a pastime to all other men was death to you ? Have reason, do, and think more kindly of me !' 'Well, never mind arguing -- never mind. One thing is sure: you were all but mine, and now you are not nearly mine. Everything is changed, and that by you alone, remember. You were nothing to me once, and I was contented; you are now nothing to me again, and how different the second nothing is from the first .! Would to God you had never taken me up, since it was only to throw me down .! ' FURY Bathsheba, in spite of her mettle, began to feel un+ mistakable signs that she was inherently the weaker vessel. She strove miserably against this feminity which would insist upon supplying unbidden emotions in stronger and stronger current. She had tried to elude agitation by fixing her mind on the trees, sky, any trivial object before her eyes, whilst his reproaches fell, but ingenuity could not save her now. "I did not take you up -- -surely I did not!' she answered as heroically as she could. " But don't be in this mood with me. I can endure being told I am in the wrong, if you will only tell it me gently! O sir, will you not kindly forgive me, and look at it cheerfully ? ' "Cheerfully! Can a man fooled to utter heart+ burning find a reason for being merry> If I have lost, how can I be as if I had won? Heavens you must be heartless quite ! Had I known what a fearfully bitter sweet this was to be, how would I have avoided you, and never seen you, and been deaf of you. I tell you all this, but what do you care! You don't care.' She returned silent and weak denials to his charges, and swayed her head desperately, as if to thrust away the words as they came showering ahout her ears from the lips of the trembling man in the climax of life, with his bronzed Roman face and fine frame. "Dearest, dearest, I am wavering even now between the two opposites of recklessly renouncing you, and labouring humbly for you again. Forget that you have said No, and let it be as it was !. Say, Bathsheba, that you only wrote that refusal to me in fun -- -come, say it to me!'

" It would be untrue, and painful to both of us. You overrate my capacity for love. I don't possess half the warmth of nature you believe me to have. An un+ protected childhood in a cold world has beaten gentle+ ness out of me.' He immediately said with more resentment: "That may be true, somewhat ; but ah, Miss Everdene, it won't do as a reason! You are not the cold woman you would have me believe. No, no .! It isn't because you have no feeling in you that you don't love me. You naturally would have me think so -- -you would hide from that you have a burning heart like mine. You have love enough, but it is turned into a new channel. I know where.' The swift music of her heart became hubbub now, and she throbbed to extremity. He was coming to Troy. He did then know what had occurred .! And the name fell from his lips the next moment. "Why did Troy not leave my treasure alone?' he asked, fiercely. "When I had no thought of injuring him, why did he force himself upon your notice.! Before he worried you your inclination was to have me; when next I should have come to you your answer would have been Yes. Can you deny it -- -I ask, can you deny it?' She delayed the reply, but was to honest to with hold it. ' I cannot,' she whispered. "I know you cannot. But he stole in in my absence and robbed me. Why did't he win you away before, when nobody would have been grieved? -- -when nobody would have been set tale-bearing. Now the people sneer at me -- -the very hills and sky seem to laugh at me till I blush shamefuly for my folly. I have lost my respect, my good name, my standing -- -lost it, never to get it again. Go and marry your man -- go on .! ' "O sir -- -Mr. Boldwood!' " You may as well. I have no further claim upon you. As for me, I had better go somewhere alone, and hide -- and pray. I loved a woman once. I am now ashamed. When I am dead they'll say, Miserable love-sick man that he was. Heaven -- -heaven -- -if I had got jilted secretly, and the dishonour not known, and my position FURY kept.! But no matter, it is

gone, and the woman not gained. Shame upon him -- shame .! ' His unreasonable anger terrified her, and she glided from him, without obviously moving, as she said, "I am only a girl -- do not speak to me so.!' "All the time you knew -- how very well you knew -- that your new freak was my misery. Dazzled by brass and scarlet -- O, Bathsheba -- this is woman's folly indeed .! ' She fired up at once. "You are taking too much upon yourself .! ' she said, veheniently. " Everybody is upon me -- everybody. It is unmanly to attack a woman so ! I have nobody in the world to fight my battles for me; but no mercy is shown. Yet if a thousand of you sneer and say things against me, I <1will>1 <1not>1 be put down !." " You'll chatter with him doubtless about me. Say to him, "Boldwood would have died for me.' Yes, and you have given way to him, knowing him to be not the man for you. He has kissed you -- claimed you as his. Do you hear -- he has kissed you. Deny it .! ' The most tragic woman is cowed by a tragic man, and although Boldwood was, in vehemence and glow, nearly her own self rendered into another sex, Bathsheba's cheek quivered. She gasped, ' Leave me, sir -- leave me !. I am nothing to you. Let me go on !.' "Deny that he has kissed you.' "I shall not.' " Ha -- then he has ! ' came hoarsely from the farmer. "He has," she said, slowly, and, in spite of her fear, defiantly. 'I am not ashamed to speak the truth.' "Then curse him; and curse him !. ' said Boldwood, breaking into a whispered fury. ' Whilst I would have given worlds to touch your hand, you have let a rake come in without right or ceremony and -- kiss you .! Heaven's mercy -- kiss you ! ... Ah, a time of his life shall come when he will have to repent, and think wretchedly of the pain he has caused another man ; and then may he ache, and wish, and curse, and yearn -- as I do now .! " 'Don't, don't, O, don't pray down evil upon him.! ' she

implored in a miserable cry. "Anything but that -- anything. O, be kind to him, sir, for I love him true .' Boldwood's ideas had reached that point of fusion at which outline and consistency entirely disappear. The impending night appeared to concentrate in his eye. He did not hear her at all now. "I'll punish him -- -by my soul, that will I.! I'll meet him, soldier or no, and I'll horsewhip the untimely stripling for this reckless theft of my one delight. If he were a hundred men I'd horsewhip him -- -- ' He dropped his voice suddenly and unnaturally. "Bath+ sheba, sweet, lost coquette, pardon me .! I've been blaming you, threatening you, behaving like a churl to you, when he's the greatest sinner. He stole your dear heart away with his unfathomable lies.! ... lt is a fortunate thing for him that he's gone back to his regiment -- -that he's away up the country, and not here! I hope he may not return here just yet. I pray God he may not come into my sight, for I may be tempted beyond myself. O, Bathsheba, keep him away -- yes, keep him away from me.!" For a moment Boldwood stood so inertly after this that his soul seemed to have been entirely exhaled with the breath of his passionate words. He turned his face away, and withdrew, and his form was soon covered over by the twilight as his footsteps mixed in with the low hiss of the leafy trees. Bathsheba, who had been standing motionless as a model all this latter time, flung her hands to her face, and wildly attempted to ponder on the exhibition which had just passed away. Such astounding wells of fevered feeling in a still man like Mr. Boldwood were incompre+ hensible, dreadful. Instead of being a man trained to repression he was -- what she had seen him. The force of the farmer's threats lay in their relation to a circumstance known at present only to herself: her lover was coming back to Weatherby in the course of the very next day or two. Troy had not returned to his distant barracks as Boldwood and others supposed, but had merely gone to visit

some acquaintance in Bath, and had yet a wek or more remaining to his furlough. She felt wretchedly certain that if he revisited her just at this nick of time, and came into contact with Boldwood,a fierce quarrel would be the consequence. She panted with solicitude when she thought of possible injury to Troy. The least spark would kindle the farmer's swift feelings of rage and jealousy; he would lose his self-mastery as he had this evening; Troy's blitheness might become aggressive; it might take the direction of derision, and Boldwood's anger might then take the direction of revenge. With almost a morbid dread of being thought a gushing girl, this guideless woman too well concealed from the world under a manner of carelessness the warm depths of her strong emotions. But now there was no reserve. In fer her distraction,instead of advancing further she walked up and down,beating the air with her fingers,pressing on her brow, and sobbing brokenly to herself. Then she sat down on a heap of stones by the wayside to think. There she remained long. Above the dark margin of the earth appeared foreshores and promontor+ ies of coppery cloud,bounding a green and pellucid expanse in the western sky. Amaranthine glosses came over them then, and the unresting world wheeled her round to a contrasting prospect eastward, in the shape of indecisive and palpitating stars. She gazed upon their silent throes amid the shades of space, but realised none at all. Her troubled spirit was far away with Troy.

NIGHT -- HORSES TRAMPING THE village of Weatherbury was quiet as the graveyard in its midst, and the living were lying welinigh as still as the dead. The church clock struck eleven. The air was so empty of other sounds that the whirr of the clock-work immediately before the strokes was distinct, and so was also the click of the same at their close. The notes flew forth with the usual blind obtuseness of inanimate things -- flapping and rebounding among walls, undulating against the scattered clouds, spreading through their interstices into unexplored miles of space. Bathsheba's crannied and mouldy halls were to-night occupied only by Maryann, Liddy being, as was stated, with her sister, whom Bathsheba had set out to visit. A few minutes after eleven had struck, Maryann turned in her bed with a sense of being disturbed. She was totally unconscious of the nature of the interruption to her sleep. It led to a dream, and the dream to an awakening, with an uneasy sensation that something had happened. She left her bed and looked out of the window. The paddock abutted on this end of the building, and in the paddock she could just discern by the uncertain gray a moving figure approaching the horse that was feeding there. The figure seized the horse by the forelock, and led it to the corner of the field. Here she could see some object which circum+ stances proved to be a vehicle for after a few minutes the horse down the road, mingled with the sound of light wheels. Two varieties only of humanity could have entered the paddock with the ghostiike glide of that mysterious figure. They were a woman and a gipsy man. A woman was out of the question in such an occupation at this hour, and the comer could be no less than a thief, who might probably have known the weakness of the house+ hold on this particular night, and have

chosen it on that account for his daring attempt. Moreover, to raise suspicion to conviction itself, there were gipsies in ! Weatherbury Bottom. Maryann, who had been afraid to shout in the robber's presence, having seen him depart had no fear. She hastily slipped on her clothes, stumped down the dis+ jointed staircase with its hundred creaks, ran to Coggan's, the nearest house, and raised an alarm. Coggan called Gabriel, who now again lodged in his house as at first, and together they went to the paddock. Beyond all doubt the horse was gone. " Hark .! ' said Gabriel. They listened. Distinct upon the stagnant air came the sounds of a trotting horse passing up Longpuddle Lane -- just beyond the gipsies' encampment in Weather+ bury Bottom. " That's our Dainty-i'll swear to her step,' said Jan. " Mighty me ! Won't mis'ess storm and call us stupids wen she comes back ! ' moaned Maryann. "How I wish it had happened when she was at home, and none of us had been answerable .! ' " We must ride after,' said Gabriel, decisively. be responsible to Miss Everdene for what we do. Yes, we'll follow. ' " Faith, I don't see how,' said Coggan. " All our horses are too heavy for that trick except little Poppet, and what's she between two of us?-if we only had that " pair over the hedge we might do something.' 'Which pair ? ' 'Mr Boldwood's Tidy and Moll.' " Then wait here till I come hither again,' said Gabriel. He ran down the hill towards Farmer Boldwood's. " Farmer Boldwood is not at home,' said Maryann. ",All the better,' said Coggan. "I know what he's gone for.' Less than five minutes brought up Oak again, running at the same pace, with two halters dangling from his hand, "Where did you find 'em ?" said Coggan, turning round and leaping upon the hedge without waiting for an answer. "Under the eaves. I knew where they were kept,' said Gabriel, following him. "Coggan, you can ride bare-backed ? there's no time to look for saddles.'

" Like a hero .! ' said Jan. 'Maryann, you go to hed,' Gabriel shouted to her from the top of the hedge. Springing down into Boldwood's pastures, each pocketed his halter to hide it from the horses, who, seeing the men empty-handed, docilely allowed them+ selves to he seized by the mane, when the halters were dexterously slipped on. Having neither bit nor bridle, Oak and Coggan extemporized the former by passing the rope in each case through the animal's mouth and looping it on the other side. Oak vaulted astride, and Coggan clambered up by aid of the hank, when they ascended to the gate and galloped off in the direction taken by Bathsheha's horse and the robber. Whose vehicle the horse had been harnessed to was a matter of some uncertainty. Weatherbury Bottom was reached in three or four minutes. They scanned the shady green patch by the roadside. The gipsies were gone. "The villains .! ' said Gabriel. 'Which way have they gone, I wonder ? ' 'Straight on, as sure as God made little apples,' said Jan. " Very well; we are better mounted, and must over+ discovered. The road-metal grew softer and more rain had wetted its surface to a somewhat plastic, but not muddy state. They came to cross-roads. Coggan suddenly pulled up Moll and slipped off. " What"s the matter ? ' said Gabriel. "We must try to track 'em, since we can't hear 'em,' said Jan, fumbling in his pockets. He struck a light, and held the match to the ground. The rain had been heavier here, and all foot and horse tracks made previous to the storm had been abraded and blurred by the drops, and they were now so many little scoops of water, which reflected the flame of the match like eyes. One set of tracks was fresh and had no water in them; one pair of ruts was also empty, and not small canals, like the cthers. The footprints forming this recent impression were full

of information as to pace ; they were in equidistant pairs, three or four feet apart, the right and left foot of each pair being exactly opposite one another. "Straight on !. ' Jan exclaimed. "Tracks like that mean a stiff gallop. No wonder we don't hear him. And the horse is harnessed-iook at the ruts. Ay, 'How do you know ?' "Old Jimmy Harris only shoed her last week, and I'd swear to his make among ten thousand.' "The rest of the gipsies must ha" gone on earlier, or some other way,' said Oak. " 'You saw there were no other tracks ? ' "True.' They rode along silently for a long weary time. Coggan carried an old pinchbeck repeater which he had inherited from some genius in his family; and it now struck one. He lighted another match, and ex+ amined the ground again. "'Tis a canter now,' he said, throwing away the light. 'A twisty', rickety pace for a gig. The fact is, they over+ drove her at starting ; we shall catch "em yet.' Again they hastened on, and entered Blackmore Vale. Coggan's watch struck one. When they looked again the hoof-marks were so spaced as to form a sort of zigzag if united, like the lamps along a street. " That's a trot, I know,' said Gabriel. "Only a trot now,' said Coggan, cheerfully. "We shall overtake him in time.' They pushed rapidly on for yet two or three miles. "Ah .! a moment,' said Jan. 'Let's see how she was driven up this hill. "Twill help us,' A light was promptly struck upon his gaiters as before, and the ex+ amination made, " Hurrah .! ' said Coggan. "She walked up here -- and well she might. We shall get them in two miles, for a crown.' They rode three, and listened. No sound was to be heard save a milipond trickling hoarsely through a hatch, and suggesting gloomy possibilities of drowning by juraping in. Gabriel dismounted when they came to a turning. The tracks were ahsolutely the only guide as to the direction that they now had, and great caution was necessary to avoid confusing them

with some others which had made their appearance lately. "What does this mean ? -- though I guess,' said Gabriel, looking up at Coggan as he moved the match over the ground about the turning. Coggan, who, no less than the panting horses, had latterly shown signs of weariness, again scrutinized the mystic characters. This time only three were of the regular horseshoe shape. Every fourth was a dot. HORSES TRAMPING He screwed up his face and emitted a long " whew-w-w !. ' " Lame,' said Oak. " Yes Dainty is lamed ; the near-foot-afore,' said Coggan slowly staring still at the footprints. " We'll push on,' said Gabriel, remounting his humid steed. Although the road along its greater part had been as good as any turnpike-road in the country, it was nomin+ ally only a byway. The last turning had brought them into the high road leading to Bath. Coggan recollected himself. "We shall have him now ! ' he exclaimed. " Where ? " ' Sherton Turnpike. The keeper of that gate is the sleepiest man between here and London -- Dan Randall. that's his name -- knowed en for years, when he was at Casterbridge gate. Between the lameness and the gate 'tis a done job.' was said until, against a shady background of foliage, five white bars were visible, crossing their route a little way ahead. " Hush -- we are almost close !. ' said Gabriel. "Amble on upon the grass,' said Coggan. The white bars were blotted out in the midst by a dark shape in front of them. The silence of this lonely time was pierced by an exclamation from that quarter. " Hoy-a-hoy ! Gate .! ' It appeared that there had been a previous call which they had not noticed, for on their close approach the door of the turnpike-house opened, and the keeper came out half-dressed, with a candle in his hand. The rays illumined the whole group. " Keep the gate close .! ' shouted Gabriel. " He has stolen the horse !. '

" Who ? ' said the turnpike-man. Gabriel looked at the driver of the gig, and saw a woman -- Bathsheba, his mistress. On hearing his voice she had turned her face away from the light. Coggan had, however, caught sight of her in the meanwhile. "Why, 'tis mistress-i'll take my oath .! ' he said, amazed. Bathsheba it certainly was, and she had by this time done the trick she could do so well in crises not of love, namely, mask a surprise by coolness of manner. ' Well, Gabriel,' she inquired quietly, ' where are you going ? ' ' We thought -- -- ' began Gabriel. Bath,' she said, taking for her own use the assurance that Gahriel lacked. 'An important matter made it necessary for me to give up my visit to liddy, and go off at once. What, then, were you following me ?' ' We thought the horse was stole.' " Weli-what a thing .! How very foolish of you not to know that I had taken the trap and horse. I could neither wake Maryann nor get into the house, though I hammered for ten minutes against her window-sill. Fortunately, I could get the key of the coach-house, so I troubled no one further. Didn't you think it might be me?" ' Why should we, miss ? ' " Perhaps not Why, those are never Farmer Bold+ wood's horses .! Goodness mercy .! what have you been " doing bringing trouble upon me in this way? What.! mustn't a lady move an inch from her door without being dogged like a thief?' 'But how was we to know, if you left no account of your doings ? ' expostulated Coggan, "and ladies don't " drive at these hours, miss, as a jineral rule of society.' "I did leave an account -- and you would have seen it in the morning. I wrote in chalk on the coach-house doors that I had come back for the horse and gig, and driven off; that I could arouse nobody, and should return soon.' " But you'll consider, ma'am, that we couldn't see that till it got daylight.' 'True,' she said, and though vexed at first she had too much

sense to blame them long or seriously for a devotion to her that was as valuable as it was rare. She added with a very pretty grace, ' Well, I really thank you heartily for taking all this trouble; but I wish you had borrowed anybody's horses but Mr. Boldwood's.' 'Dainty is lame, miss,' said Coggan. 'Can ye go on?' 'lt was only a stone in her shoe. I got down and pulled it out a hundred yards back. I can manage very well, thank you. I shall be in Bath by daylight. Will you now return, please?' She turned her head -- the gateman's candle shimmering upon her quick, clear eyes as she did so -- passed through the gate, and was soon wrapped in the embowering shades of mysterious summer boughs. Coggan and Gabriel put about their horses, and, fanned by the velvety air of this July night, retraced the road by which they had come. 'A strange vagary, this of hers, isn't it, Oak?' said Coggan, curiously. 'Yes,' said Gabriel, shortly. 'She won't be in Bath by no daylight!.' 'Coggan, suppose we keep this night's work as quiet as we can?' 'I am of one and the same mind.' 'Very well. We shall be home by three o'clock or so, and can creep into the parish like lambs.' Bathsheba's perturbed meditations by the roadside had ultimately evolved a conclusion that there were only two remedies for the present desperate state of affairs. The first was merely to keep Troy away from Weather+ bury till Boldwood's indignation had cooled; the second to listen to Oak's entreaties, and Boldwood's denuncia+ tions, and give up Troy altogether. Alas! Could she give up this new love -- induce him to renounce her by saying she did not like him -- could no more speak to him, and beg him, for her good, to end his furlough in Bath, and see her and Weather' bury no niore? It was a picture full of misery, but for a while she contemplated it firmly, allowing herself, nevertheless, as girls will, to

dwell upon the happy life she would have enjoyed had Troy been Boldwood, and the path of love the path of duty -- inflicting upon herself gratuit+ ous tortures by imagining him the lover of another woman after forgetting her; for she had penetrated Troy's nature so far as to estimate his tendencies pretty accurately, hut unfortunately loved him no less in thinking that he might soon cease to love her -- indeed, considerably more. She jumped to her feet. She would see him at once. Yes, she would implore him by word of mouth to assist her in this dilemma. A letter to keep him away could not reach him in time, even if he should be disposed to listen to it. Was Bathsheba altogether blind to the obvious fact that the support of a lover's arms is not of a kind best calculated to assist a resolve to renounce him? Or was she sophistically sensible, with a thrill of pleasure, that by adopting this course for getting rid of him she was ensuring a meeting with him, at any rate, once more? It was now dark, and the hour must have been nearly ten. The only way to accomplish her purpose was to give up her idea of visiting Liddy at Yalbury, return to Weatherbury Farm, put the horse into the gig, and drive at once to Bath. The scheme seemed at first impossible : the journey was a fearfully heavy one, even for a strong horse, at her own estimate; and she much underrated the distance. It was most venturesome for a woman, at night, and alone. But could she go on to Liddy's and leave things to take their course? No, no; anything but that. Bath+ sheba was full of a stimulating turbulence, beside which caution vainly' prayed for a hearing. she turned back towards the village. Her walk was slow, for she wished not to enter Weatherbury till the cottagers were in bed, and, par+ ticularly, till Boldwood was secure. Her plan was now to drive to Bath during the night, see Sergeant 'Troy in the morning before he set out to come to her, bid him farewell, and dismiss him: then to rest the horse thoroughly (herself to weep the while, she thought), starting early the next morning on her return journey. By this arrangement she could trot Dainty gently all the day, reach

Liddy at Yalbury in the evening, and come home to Weatherbury with her whenever they chose -- so nobody would know she had been to Bath at all. Such was Bathsheba's scheme. But in her topo+ graphical ignorance as a late comer to the place, slie misreckoned the distance of her journey as not much more than half what it really was. Her idea, however, she proceeded to carry out, with what initial success we have already seen.

IN THE SUN -- A HARBINGER A WEEK passed, and there were no tidings of Bath+ sheba; nor was there any explanation of her Gilpin's rig. Then a note came for Maryann, stating that the business which had called her mistress to Bath still detained her there; but that she hoped to return in the course of another week. Another week passed. The oat-harvest began, and all the men were a-field under a monochromatic Lammas sky, amid the trembling air and short shadows of noon. Indoors nothing was to be heard save the droning of blue-bottle flies; out-of-doors the whetting of scythes and the hiss of tressy oat-ears rubbing together as their perpendicular stalks of amber-yellow fell heavily to each swath. Every drop of moisture not in the men's bottles and flagons in the form of cider was raining as perspira+ tion from their foreheads and cheeks. Drought was everywhere else. They were about to withdraw for a while into the charitable shade of a tree in the fence, when Coggan saw a figure in a blue coat and brass buttons running to them across the field. 'I wonder who that is?' he said. 'I hope nothing is wrong about mistress,' said Maryann, who with some other women was tying the bundles (oats being always sheafed on this farm), 'but an unlucky token came to me indoors this morning. l went to unlock the door and dropped the key, and it fell upon the stone floor and broke into two pieces. Breaking a key is a dreadful bodement. I wish mis'ess was home.' ''Tis Cain Ball,' said Gabriel, pausing from whetting his reaphook. Oak was not bound by his agreement to assist in the corn-field; but the harvest month is an anxious time for

a farmer, and the corn was Bathsheba's, so he lent a hand. 'He's dressed up in his best clothes,' said Matthew Moon. 'He hev been away from home for a few days, since he's had that felon upon his finger; for 'a said, since I can't work I'll have a hollerday.' 'A good time for one -- a" excellent time,' said Joseph Poorgrass, straightening his back; for he, like some of the others, had a way of resting a while from his labour on such hot days for reasons preternaturally small; of which Cain Pall's advent on a week-day in his Sunday+ clothes was one of the first magnitude. ''Twas a bad leg allowed me to read the Pilgrim's Progress, and Mark Clark learnt AliFours in a whitlow.' 'Ay, and my father put his arm out of joint to have time to go courting,' said Jan Coggan, in an eclipsing tone, wiping his face with his shirt-sleeve and thrusting back his hat upon the nape of his neck. By this time Cainy was nearing the group of harvesters, and was perceived to be carrying a large slice of bread and ham in one hand, from which he took mouthfuls as he ran, the other being wrapped in a bandage. When he came close, his mouth assumed the bell shape, and he began to cough violently. 'Now, Cainy!.' said Gabriel, sternly. 'How many more times must I tell you to keep from running so fast when you be eating? You'll choke yourself some day, that's what you'll do, Cain Ball.' 'Hok-hok-hok.! 'replied Cain. 'A crumb of my victuals went the wrong way -- hok-hok!, That's what 'tis, Mister Oak.! And I've been visiting to Bath because I had a felon on my thumb; yes, and l've seen -- ahok-hok!' Directly Cain mentioned Bath, they all threw down their hooks and forks and drew round him. Un+ fortunately the erratic crumb did not improve his narrative powers, and a supplementary hindrance was that of a sneeze, jerking from his pocket his rather large watch, which dangled in front of the young man pendulum-wise.

'Yes,' he continued, directing his thoughts to Bath and letting his eyes follow, 'l've seed the world at last -- yes -- and I've seed our mis'ess -- ahok-hok-hok ! ' ' Bother the boy! ' said Gabriel. ' Something is always going the wrong way down your throat, so that you can't tell what's necessary to be told.' "Ahok !. there ! Please, Mister Oak, a gnat have just fleed into my stomach and brought the cough on again !. ' 'Yes, that's just it. Your mouth is always open, you young rascal .! ' ''Tis terrible bad to have a gnat fly down yer throat, pore boy !. ' said Matthew Moon. ' Well, at Bath you saw -- -- ' prompted Gabriel. 'I saw our mistress,' continued the junior shepherd, 'and a sojer, walking along. And bymeby they got closer and closer, and then they went arm-in-crook, like courting complete -- hok-hok ! like courting complete -- hok .! -- courting complete -- -- " Losing the thread of his narrative at this point simultaneously with his loss of breath, their informant looked up and down the field apparently for some clue to it. 'Well, I see our mis'ess and a soldier -- a-ha-a-wk .! ' A HARBlNGER !Damn the boy !' said Gabriel. !'Tis only my manner, Mister Oak, if ye'll excuse it,' said Cain Ball, looking reproachfully at Oak, with eyes drenched in their own dew. !Here's some cider for him -- that'll cure his throat,' said Jan Coggan, lifting a flagon of cider, pulling out the cork, and applying the hole to Cainy's mouth; Joseph Poorgrass in the meantime beginning to think apprehensively of the serious consequences that would follow Cainy Ball's strangulation in his cough, and the history of his Bath adventures dying with him. "For my poor self, I always say "please God ' afore I do anything,' said Joseph, in an unboastful voice ; " and so should you, Cain Ball. "Tis a great safeguard, and might perhaps save you from being choked to death some day.' Mr. Coggan poured the liquor with unstinted liber+ ality at the suffering Cain's circular mouth; half of it running down the

side of the flagon, and half of what reached his mouth running down outside his throat, and half of what ran in going the wrong way, and being coughed and sneezed around the persons of the gathered reapers in the form of a cider fog, which for a moment hung in the sunny air like a small exhalation. "There's a great clumsy sneeze ! Why can't ye have better manners, you young dog ! ' said Coggan, with+ drawing the flagon. "The cider went up my nose ! ' cried Cainy, as soon as he could speak; "and now 'tis gone down my neck, and into my poor dumb felon, and over my shiny buttons and all my best cloze ! ' "The poor lad's cough is terrible onfortunate,' said Matthew Moon. 'And a great history on hand, too. Bump his back, shepherd.' "'Tis my nater,' mourned Cain. "Mother says I always was so excitable when my feelings were worked up to a point!' " True, true,' said Joseph Poorgrass. "The Balls were always a very excitable family. I knowed the boy's grandfather -- a truly nervous and modest man, even to genteel refinery. 'Twas blush, blush with him, almost as much as 'tis with me -- not but that 'tis a fault in me !' "Not at all, Master Poorgrass,' said Coggan. " 'Tis a very noble quality in ye.' "Heh-heh ! well, I wish to noise nothing abroad -- nothing at all,' murmured Poorgrass, diffidently. " But we be born to things -- that's true. Yet I would rather my trifle were hid ; though, perhaps, a high nater is a little high, and at my birth all things were possible to my Maker, and he may have begrudged no gifts.... But under your bushel, Joseph ! under your bushel with 'ee ! A strange desire, neighbours, this desire to hide, and no praise due. Yet there is a Sermon on the Mount with a calendar of the blessed at the head, and certain meek men may be named therein.' "Cainy's grandfather was a very clever man,' said Matthew Moon. "Invented a' apple-tree out of his own head, which is called by his name to this day -- the Early Ball. You know 'em,

Jan ? A Quarrenden grafted on a Tom Putt, and a Rathe-ripe upon top o' that again. 'Tis trew 'a used to bide about in a public-house wi' a 'ooman in a way he had no business to by rights, but there -- 'a were a clever man in the sense of the term.' " Now then,' said Gabriel, impatiently, " what did you see, Cain ? ' "I seed our mis'ess go into a sort of a park place, where there's seats, and shrubs and flowers, arm-in-crook with a sojer,' continued Cainy, firmly, and with a dim sense that his words were very effective as regarded Gabriel's emotions. "And I think the sojer was Sergeant Troy. And they sat there together for more than half-an-hour, talking moving things, and she once was crying a'most to death. And when they came out her eyes were shining and she was as white as a lily; and they looked into one another's faces, as far-gone friendly as a man and woman can be.' Gabriel's features seemed to get thinner. " Well, what did you see besides ? ' " Oh, all sorts." "White as a lily? You are sure 'twas she? " Yes." " Well, what besides ? ' "Great glass windows to the shops, and great clouds in the sky, full of rain, and old wooden trees in the country round.' " You stun-poll! What will ye say next?' said Coggan. " Let en alone,' interposed Joseph Poorgrass. "The boy's maning is that the sky and the earth in the kingdom of Bath is not altogether different from ours here. 'Tis for our good to gain knowledge of strange cities, and as such the boy's words should be suffered, so to speak it.' " And the people of Bath,' continued Cain, "never need to light their fires except as a luxury, for the water springs up out of the earth ready boiled for use.' " 'Tis true as the light,' testified Matthew Moon. ' I've heard other navigators say the same thing.' " They drink nothing else there,' said Cain, ' and seem to enjoy it, to see how they swaller it down.'

"Well, it seems a barbarian practice enough to us, but I daresay the natives think nothing o' it,' said Matthew. "And don't victuals spring up as well as drink?' asked Coggan, twirling his eye. "No-i own to a blot there in Bath -- a true blot. God didn't proride 'em with victuals as well as (+ and 'twas a drawback I couldn't get over at all.' " Well, 'tis a curious place, to say the least,' observed Moon; "and it must be a curious people that live therein. ' "Miss Everdene and the soldier were walking about together, you say ? ' said Gabriel, returning to the group. "Ay, and she wore a beautiful gold-colour silk gown, trimmed with black lace, that would have stood alone 'ithout legs inside if required. 'Twas a very winsome sight; and her hair was brushed splendid. And when the sun shone upon the bright gown and his red coat -- my ! how handsome they looked. You could see 'em all the length of the street.' " And what then ? ' murmured Gabriel. "And then I went into Griffin's to hae my boots hobbed, and then I went to Riggs's batty-cake shop, and asked 'em for a penneth of the cheapest and nicest stales, that were all but blue-mouldy, but not quite. And whilst I was chawing 'em down I walked on and seed a clock with a face as big as a baking trendle -- -- ' "But that's nothing to do with mistress ! ' "I'm coming to that, if you'll leave me alone, Mister Oak ! ' remonstrated Cainy. "If you excites me, perhaps you'll bring on my cough, and then I shan't be able to tell ye nothing.' " Yes-iet him tell it his own way,' said Coggan. Gabriel settled into a despairing attitude of patience, and Cainy went on : -- "And there were great large houses, and more people all the week long than at Weatherbury club+ walking on White Tuesdays. And I went to grand churches and chapels. And how the parson would pray ! Yes; he would kneel down and put up his hands together, and make the holy gold rings on his fingers gleam and twinkle in yer eyes, that he'd earned by praying so excellent well ! -- Ah yes, I wish I lived there.'

"Our poor Parson Thirdly can't get no money to buy such rings,' said Matthew Moon, thoughtfully. "And as good a man as ever walked. I don't believe poor Thirdly have a single one, even of humblest tin or copper. Such a great ornament as they'd be to him on a dull a'ternoon, when he's up in the pulpit lighted by the wax candles ! But 'tis impossible, poor man. Ah, to think how unequal things be.' "Perhaps he's made of different stuff than to wear 'em,' said Gabriel, grimly. ' Well, that's enough of this. Go on, Cainy -- quick.' ' Oh -- and the new style of pa'sons wear moustaches and long beards,' continued the illustrious traveller, 'and look like Moses and Aaron complete, and make we fokes in the congregation feel all over like the children of Israel.' "A very right feeling -- very,' said Joseph Poorgrass. "And there's two religions going on in the nation now -- High Church and High Chapel. And, thinks I, I'll play fair; so I went to High Church in the morning, and High Chapel in the afternoon.' ' A right and proper boy,' said Joseph Poorgrass. "Well, at High Church they pray singing, and worship all the colours of the rainbow; and at High Chapel they pray preaching, and worship drab and whitewash only. And then-i didn't see no more of Miss Everdene at all.' 'Why didn't you say so afore, then ? ' exclaimed Oak, with much disappointment. ' Ah,' said Matthew Moon, 'she'll wish her cake dough if so be she's over intimate with that man.' 'She's not over intimate with him,' said Gabriel, indignantly. 'She would know better,' said Coggan. "Our mis'ess has too much sense under they knots of black hair to do such a mad thing.' "You see, he's not a coarse, ignorant man, for he was well brought up,' said Matthew, dubiously. " 'Twas only wildness that made him a soldier, and maids rather like your man of sin.' "Now, Cain Ball,' said Gabriel restlessly, "can you swear in the most

awful form that the woman you saw was Miss Everdene ? ' 'Cain Ball, you be no longer a babe and suckling,' said Joseph in the sepulchral tone the circumstances demanded, "and you know what taking an oath is. 'Tis a horrible testament mind ye, which you say and seal with your blood-stone, and the prophet Matthew tells us that on whomsoever it shall fall it will grind him to powder. Now, before all the work-folk here assembled, can you swear to your words as the shep+ herd asks ye ?' " Please no, Mister Oak ! ' said Cainy, looking from one to the other with great uneasiness at the spiritual magnitude of the position. "I don't mind saying 'tis true, but I don't like to say 'tis damn true, if that's what you mane.' 'Cain, Cain, how can you ! ' asked Joseph sternly. "You be asked to swear in a holy manner, and you swear like wicked Shimei, the son of Gera, who cursed as he came. Young man, fie ! ' "No, I don't ! 'Tis you want to squander a pore boy's soul, Joseph Poorgrass -- that's what 'tis ! ' said Cain, beginning to cry. "All I mane is that in common truth 'twas Miss Everdene and Sergeant Troy, but in the horrible so-help-me truth that ye want to make of it perhaps 'twas somebody else ! ' 'There's no getting at the rights of it,' said Gabriel, turning to his work. "Cain Ball, you'll come to a bit of bread ! ' groaned Joseph Poorgrass. Then the reapers' hooks were flourished again, and the old sounds went on. Gabriel, without making any pretence of being lively, did nothing to show that he was particularly dull. However, Coggan knew pretty nearly how the land lay, and when they were in a nook together he said -- ' Don't take on about her, Gabriel. What difference does it make whose sweetheart she is, since she can't be yours ? ' "That's the very thing I say to myself,' said Gabriel.

HOME AGAIN -- A TRICKSTER THAT same evening at dusk Gabriel was leaning over Coggan's garden-gate, taking an up-and-down survey before retiring to rest. A vehicle of some kind was softly creeping along the grassy margin of the lane. From it spread the tones of two women talking. The tones were natural and not at all suppressed. Oak instantly knew the voices to he those of Bathsheba and Liddy. The carriage came opposite and passed by. It was Miss Everdene's gig, and Liddy and her mistress were the only occupants of the seat. Liddy was asking questions about the city of Bath, and her companion was answering them listlessly and unconcernedly. Both Bathsheba and the horse seemed weary. The exquisite relief of finding that she was here again, safe and sound, overpowered all reflection, and Oak could only luxuriate in the sense of it. All grave reports were forgotten. He lingered and lingered on, till there was no difference between the eastern and western expanses of sky, and the timid hares began to limp courageously round the dim hillocks. Gabriel might have been there an additional half-hour when a dark form walked slowly by. " Good-night, Gabriel,' the passer said. It was Boldwood. " Good-night, sir,' said Gabriel. Boldwood likewise vanished up the road, and Oak shortly afterwards turned indoors to bed. Farmer Boldwood went on towards Miss Everdene's house. He reached the front, and approaching the entrance, saw a light in the parlour. The blind was not drawn down, and inside the room was Bathsheba, looking over some papers or letters. Her back was towards Boldwood. He went to the door,

knocked, and waited with tense muscles and an aching brow. Boldwood had not been outside his garden since his meeting with Bathsheba in the road to Yalbury. Silent and alone, he had remained in moody medita+ tion on woman's ways, deeming as essentials of the whole sex the accidents of the single one of their number he had ever closely beheld. By degrees a more charitable temper had pervaded him, and this was the reason of his sally to-night. He had come to apologize and beg forgiveness of Bathsheba with some+ thing like a sense of shame at his violence, having but just now learnt that she had returned -- only from a visit to Liddy, as he supposed, the Bath escapade being quite unknown to him. He inquired for Miss Everdene. Liddy's manner was odd, but he did not notice it. She went in, leaving him standing there, and in her absence the blind of the room containing Bathsheba was pulled down. Bold+ wood augured ill from that sign. Liddy came out. "My mistress cannot see you, sir,' she said. The farmer instantly went out by the gate. He as unforgiven -- that was the issue of it all. He had seen her who was to him simultaneously a delight and a torture, sitting in the room he had shared with her as a peculiarly privileged guest only a little earlier in he summer, and she had denied him an entrance there now. Boldwood did not hurry homeward. It was ten o'clock at least, when, walking deliberately through the lower part of Weatherbury, he heard the carrier's spring van entering the village. The van ran to and from a town in a northern direction, and it was owned and driven by a Weatherbury man, at the door of whose house it now pulled up. The lamp fixed to the head of the hood illuminated a scarlet and gilded form, who was the first to alight. 'Ah ! ' said Boldwood to himself, "come to see her again.' Troy entered the carrier's house, which had been the place of his lodging on his last visit to his native place. Boldwood was moved by a sudden determina+ tion. He hastened home. In ten minutes he was back again, and made as if he were going to call upon Troy at the carrier's. But as he approached, some

one opened the door and came out. He heard this person say " Good-night ' to the inmates, and the voice was Troy's. 'This was strange, coming so immediately after his arrival. Boldwood, however, hastened up to him. Troy had what appeared to be a carpet-bag in his hand -- the same that he had brought with him. It seemed as if he were going to leave again this very night. Troy turned up the hill and quickened his pace. Boldwood stepped forward. " Sergeant Troy ? ' " Yes-i'm Sergeant Troy.' " Just arrived from up the country, I think ?' " Just arrived from Bath.' " I am William Boldwood.' " Indeed.' The tone in which this word was uttered was all that had been wanted to bring Boldwood to the point. " I wish to speak a word with you,' he said. " What about ? ' " About her who lives just ahead there -- and about a woman you have wronged.' " I wonder at your impertinence,' said Troy, moving on. " Now look here,' said Boldwood, standing in front of him, " wonder or not, you are going to hold a conver+ sation with me.' Troy heard the dull determination in Boldwood's voice, looked at his stalwart frame, then at the thick cudgel he carried in his hand. He remembered it was past ten o'clock. It seemed worth while to be civil to Boldwood. " Very well, I'll listen with pleasure,' said Troy, placing his bag on the ground, "only speak low, for somebody or other may overhear us in the farmhouse there.' " Well then -- I know a good deal concerning your Fanny Robin's attachment to you. I may say, too, that I believe I am the only person in the village, excepting Gabriel Oak, who does know it. You ought to marry her.' " I suppose I ought. Indeed, l wish to, but I cannot.' " Why ? ' Troy was about to utter something hastily; he then checked

himself and said, "I am too poor.' His voice was changed. Previously it had had a deviimay-care tone. It was the voice of a trickster now. Boldwood's present mood was not critical enough to notice tones. He continued, "I may as well speak plainly; and understand, I don't wish to enter into the questions of right or wrong, woman's honour and shame, or to express any opinion on your conduct. I intend a business transaction with you.' " I see,' said Troy. " Suppose we sit down here.' An old tree trunk lay under the hedge immediately opposite, and they sat down. The tone in which this word was uttered was all Troy heard the dull determination in Boldwood's voice, looked at his stalwart frame, then at the thick plainly ; and understand, I don't wish to enter into the " I was engaged to be married to Miss Everdene,' said Boldwood, "but you came and -- -- ' " Not engaged,' said Troy. " As good as engaged.' " If I had not turned up she might have become en+ gaged to you.' " Hang might ! ' " Would, then.' " If you had not come I should certainly -- yes, certainly -- have been accepted by this time. If you had not seen her you might have been married to Fanny. Well, there's too much difference between Miss Ever+ dene's station and your own for this flirtation with her ever to benefit you by ending in marriage. So all I ask is, don't molest her any more. Marry Fanny. make it worth your while.' " How will you ?' " I'll pay you well now, I'll settle a sum of money upon her, and I'll see that you don't suffer from poverty in the future. I'll put it clearly. Bathsheba is only playing with you: you are too poor for her as I said; so give up wasting your time about a great match you'll never make for a moderate and rightful match you may make to-morrow; take up your carpet-bag, turn about, leave Weatherbury now, this night, and you shall take fifty pounds with you. Fanny shall have fifty to enable her to prepare for the wedding, when you have told me where she is living, and she shall have five hundred paid down on her wedding-day.'

In making this statement Boldwood's voice revealed only too clearly a consciousness of the weakness of his position, his aims, and his method. His manner had lapsed quite from that of the firm and dignified Bold+ wood of former times; and such a scheme as he had now engaged in he would have condemned as childishly imbecile only a few months ago. We discern a grand force in the lover which helacks whilst a free man; but there is a breadth of vision in the free man which in the lover we vainly seek. Where there is much bias there must be some narrowness, and love, though added emotion, is subtracted capacity. Boldwood exemplified this to an abnormal degree: he knew nothing of Fanny Robin's circumstances or whereabouts, he knew nothing of Troy's possibilities, yet that was what he said. " I like Fanny best,' said Troy; "and if, as you say, Miss Everdene is out of my reach, why I have all to gain by accepting your money, and marrying Fan. But she's only a servant.' " Never mind -- do you agree to my arrangement ?' " I do.' " Ah ! ' said Boldwood, in a more elastic voice. "O, Troy, if you like her best, why then did you step in here and injure my happiness ? ' " I love Fanny best now,' said Troy. "But Bathsh -- -- Miss Everdene inflamed me, and displaced Fanny for a time. It is over now.' " Why should it be over so soon? And why then did you come here again ? ' " There are weighty reasons. Fifty pounds at once, you said !' " I did,' said Boldwood, " and here they are -- fifty sovereigns.' He handed Troy a small packet. " You have everything ready -- it seems that you calculated on my accepting them,' said the sergeant, taking the packet. " I thought you might accept them,' said Boldwood. " You've only my word that the programme shall be adhered to, whilst I at any rate have fifty pounds.' " l had thought of that, and l have considered that if I can't appeal to your honour I can trust to your -- well, shrewdness we'll call it -- not to lose five hundred pounds in prospect, and

also make a bitter enemy of a man who is willing to be an extremely useful friend.' " Stop, listen ! ' said Troy in a whisper. A light pit-pat was audible upon the road just above them. 'By George -- 'tis she,' he continued. 'I must go on and meet her.' 'She -- who ? ' 'Bathsheba.' 'Bathsheba -- out alone at this time o' night .! ' said Boldwood in amazement, and starting up. ' Why must you meet her ?' 'She was expecting me to-night -- and I must now speak to her, and wish her good-bye, according to your wish. ' 'I don't see the necessity of speaking.' 'It can do no harm -- and she'll be wandering about looking for me if I don't. You shall hear all I say to her. It will help you in your love-making when I am gone.' 'Your tone is mocking.' 'O no. And renaember this, if she does not know what has become of me, she will think more about me than if I tell her flatly I have come to give her up.' 'Will you confine your words to that one point ? -- + Shall I hear every word you say ? ' 'Every word. Now sit still there, and hold my' carpet bag for me, and mark what you hear.' The light footstep came closer, halting occasionally, as if the walker listened for a sound. Troy whistled a double note in a soft, fluty tone. 'Come to that, is it ! ' murmured Boldwood, uneasily. 'You promised silence,' said Troy. 'I promise again.' Troy stepped forward. 'Frank, dearest, is that you ? ' The tones were Bathsheba's. 'O God .! ' said Boldwood. 'Yes,' said Troy to her. 'How late you are,' she continued, tenderly. 'Did you come by the carrier ? I listened and heard his wheels entering the village, but it was some time ago, and I had almost given you up, Frank.'

'I was sure to come,' said Frank. 'You knew I should, did you not ? ' 'Well, I thought you would,' she said, playfully ; 'and, Frank, it is so lucky .! There's not a soul in my house but me to-night. I've packed them all off so nobody on earth will know of your visit to your lady's bower. Liddy wanted to go to her grandfather's to tell him about her holiday, and I said she might stay with them till to-morrow -- when you'll be gone again.' 'Capital,' said Troy. ' But, dear me, I. had better go back for my bag, because my slippers and brush and comb are in it; you run home whilst I fetch it, and I'll promise to be in your parlour in ten minutes.' 'Yes.' She turned and tripped up the hill again. During the progress of this dialogue there was a nervous twitching of Boldwood's tightly closed lips, and his face became bathed in a clammy dew. He now started forward towards Troy. Troy turned to him and took up the bag. 'Shall I tell her I have come to give her up and cannot marry her ? ' said the soldier, mockingly. 'No, no; wait a minute. I want to say more to you -- more to you !. ' said Boldwood, in a hoarse whisper. 'Now,' said Troy, ' you see my dilemma. Perhaps I am a bad man -- the victim of my impulses -- led away to do what I ought to leave undone. I can't, however, marry them both. And I have two reasons for- choosing Fanny. First, I like her best upon the whole, and second, you make it worth my while.' At the same instant Boldwood sprang upon him, and held him by the neck. Troy felt Boldwood's grasp slowly tightening. The move was absolutely unexpected. 'A moment,' he gasped. 'You are injuring her you love .! ' 'Well, what do you mean ? ' said the farmer. Give me breath,' said Troy. Boldwood loosened his hand, saying, 'By Heaven, I've a mind to kill you .!' 'And ruin her.' 'Save her.' 'Oh, how can she be saved now, unless I marry her ? '

Boldwood groaned. He reluctantly released the soldier, and flung him back against the hedge. 'Devil, you torture me .! ' said he. Troy rebounded like a ball, and was about to make a dash at the farmer; but he checked himself, saying lightly -- 'It is not worth while to measure my strength with you. Indeed it is a barbarous way of settling a quarrel. I shall shortly leave the army because of the same conviction. Now after that revelation of how the land lies with Bathsheba, 'twould be a mistake to kill me, would it not?' ''Twould be a mistake to kill you,' repeated Boldwood, mechanically, with a bowed head. 'Better kill yourself.' ' Far better.' 'I'm glad you see it.' 'Troy, make her your wife, and don't act upon what I arranged just now. The alternative is dreadful, but take Bathsheba; I give her up .! She must love you indeed to sell soul and body to you so utterly as she has done. Wretched woman -- deluded woman -- you are, Bathsheba .! ' 'But about Fanny ? ' 'Bathsheba is a woman well to do,' continued Bold+ wood, in nervous anxiety, 'and, Troy, she will make a good wife ; and, indeed, she is worth your hastening on your marriage with her .! ' 'But she has a wili-not to say a temper, and I shall be a mere slave to her. I could do anything with poor Fanny Robin.' 'Troy,' said Boldwood, imploringly, ' I'll do anything for you, only don't desert her; pray don't desert her, Troy.' 'Which, poor Fanny ? ' 'No ; Bathsheba Everdene. Love her best .! Love her tenderly !. How shall I get you to see how advan+ tageous it will be to you to secure her at once ?' 'I don't wish to secure her in any new way.' Boldwood's arm moved spasmodically towards Troy's person again. He repressed the instinct, and his form drooped as with pain. Troy went on --

"I shall soon purchase my discharge, and then -- -- ' 'But I wish you to hasten on this marriage !. It will be better for you both. You love each other, and you must let me help you to do it.' 'How ? ' 'Why, by settling the five hundred on Bathsheba instead of Fanny, to enable you to marry at once. No ; she wouldn't have it of me. I'll pay it down to you on the wedding-day.' Troy paused in secret amazement at Boldwood's wild infatuation. He carelessly said, 'And am I to have anything now ? ' 'Yes, if you wish to. But I have not much additional money with me. I did not expect this; but all I have is yours.' Boldwood, more like a somnambulist than a wakeful man, pulled out the large canvas bag he carried by way of a purse, and searched it. 'I have twenty-one pounds more with me,' he said. 'Two notes and a sovereign. But before I leave you I must have a paper signed -- -- ' 'Pay me the money, and we'll go straight to her parlour, and make any arrangement you please to secure my compliance with your wishes. But she must know nothing of this cash business.' ' Nothing, nothing,' said Boldwood, hastily. 'Here is the sum, and if you'll come to my house we'll write out the agreement for the remainder, and the terms also.' ' First we'll call upon her.' 'But why? Come with me to-night, and go with me to-morrow to the surrogate's.' 'But she must be consulted; at any rate informed.' 'Very well; go on.' They went up the hill to Bathsheba's house. When they stood at the entrance, Troy said, 'Wait here a moment.' Opening the door, he glided inside, leaving the door ajar. Boldwood waited. In two minutes a light appeared in the passage. Boldwood then saw that the chain had been fastened across the door. Troy appeared inside, carrying a bedroom candlestick.

'What, did you think I should break in ?' said Boldwood, contemptuously. 'Oh, no; it is merely my humour to secure things. Will you read this a moment ? I'll hold the light.' Troy handed a folded newspaper through the slit between door and doorpost, and put the candle close. 'That's the paragraph,' he said, placing his finger on a line. Boldwood looked and read -- 'MARRIAGES. 'On the 17th inst., at St. Ambrose's Church, Bath, by the Rev. G. Mincing, B.A., Francis Troy, only son of the late Edward Troy, Esq., H.D., of Weatherbury, and sergeant iith Dragoon Guards, to Bathsheba, only surviving daughter of the late Mr, John Everdene, of Casterbridge.' 'This may be called Fort meeting Feeble, hey, Boldwood ?' said Troy. A low gurgle of derisive laughter followed the words. The paper fell from Boldwood's hands. Troy continued -- 'Fifty pounds to marry Fanny, Good. Twenty-+ one pounds not to marry Fanny, but Bathsheba. Good. Finale : already Bathsheba's husband. Now, Boldwood, yours is the ridiculous fate which always attends inter+ ference between a man and his wife. And another word. Bad as I am, I am not such a villain as to make the marriage or misery of any woman a matter of huckster and sale. Fanny has long ago left me. don't know where she is. I have searched everywhere. Another word yet. You say you love Bathsheba ; yet on the merest apparent evidence you instantly believe in her dishonour. A fig for such love !. Now that I've taught you a lesson, take your money back again.' 'I will not ; I will not !. ' said Boldwood, in a hiss. 'Anyhow I won't have it,' said Troy, contemptuously. He wrapped the packet of gold in the notes, and threw the whole into the road. Boldwood shook his clenched fist at him. 'You juggler of Satan .! You black hound .! But I'll punish you yet ; mark me, I'll punish you yet !. '

Another peal of laughter. Troy then closed the door, and locked himself in. Throughout the whole of that night Boldwood's dark downs of Weatherbury like an unhappy Shade in the Mournful Fields by Acheron.

CHAPTER XXXV AT AN UPPER WINDOW IT was very early the next morning -- a time of sun and dew. The confused beginnings of many birds' songs spread into the healthy air, and the wan blue of the heaven was here and there coated with thin webs of incorporeal cloud which were of no efect in obscuring day. All the lights in the scene were yellow as to colour, and all the shadows were attenuated as to form. The creeping plants about the old manor-house were bowed with rows of heavy water drops, which had upon objects behind them the effect of minute lenses of high magnifying power. Just before the clock struck five Gabriel Oak and Coggan passed the village cross, and went on together to the fields. They were yet barely in view of their mistress"s house, when Oak fancied he saw the opening of a casement in one of the upper windows. The two men were at this moment partially screened by an elder bush, now beginning to be enriched with black bunches of fruit, and they paused before emerging from its shade. A handsome man leaned idly from the lattice. He looked east and then west, in the manner of one who makes a first morning survey. The man was Sergeant Troy. His red jacket was loosely thrown on, but not buttoned, and he had altogether the relaxed bearing of a soldier taking his ease. Coggan spoke first, looking quietly at the window. 'She has married him ! ' he said. Gabriel had previously beheld the sight, and he now stood with his back turned, making no reply. 'I fancied we should know something to-day,' con+ tinued Coggan. 'I heard wheels pass my door just after dark -- you were out somewhere.'He glanced round upon Gabriel. 'Good

heavens above us, Oak, how white your face is; you look like a corpse !.' 'Do I?' said Oak, with a faint smile. 'Lean on the gate: I'll wait a bit.' ',All right, all right. ' They stood by the gate awhile, Gabriel listlessly staring at the ground. His mind sped into the future, and saw there enacted in years of leisure the scenes o repentance that would ensue from this work of haste That they were married he had instantly decided. Why had it been so mysteriously managed ? It had become known that she had had a fearful journey to Bath, owing to her miscalculating the distance : that the horse had broken down, and that she had been more than two days getting there. It was not Bathsheba's way to do things furtively. With all her faults, she was candour itself. Could she have been entrapped ? The union was not only an unutterable grief to him: it amazed him, notwithstanding that he had passed the preceding week in a suspicion that such might be the issue of Troy's meeting her away from home. Her quiet return with liddy had to some extent dispersed the dread. Just as that imperceptible motion which appears like stillness is infinitely divided in its properties from stili ness itself, so had his hope undistinguishable from despair differed from despair indeed. In a few minutes they moved on again towards the house. The sergeant still looked from the window. 'Morning, comrades .! ' he shouted, in a cheery voice, when they came up. Coggan replied to the greeting. ' Bain't ye going to answer the man ?' he then said to Gabriel. 'I'd say good morning -- you needn't spend a hapeth of meaning upon it, and yet keep the man civil.' Gabriel soon decided too that, since the deed was done, to put the best face upon the matter would be the greatest kindness to her he loved. 'Good morning, Sergeant Troy,' he returned, in a ghastly voice. 'A rambling, gloomy house this,' said Troy, smiling.

' Why -- they may not be married .! ' suggested Coggan. ' Perhaps she's not there.' Gabriel shook his head. The soldier turned a little towards the east, and the sun kindled his scarlet coat to an orange glow. 'But it is a nice old house,' responded Gabriel. 'Yes-i suppose so; but I feel like new wine in an old bottle here. My notion is that sash-windows should be put throughout, and these old wainscoted walls brightened up a bit ; or the oak cleared quite away, and the walls papered.' 'It would be a pity, I think.' 'Well, no. A philosopher once said in my hearing that the old builders, who worked when art was a living thing, had no respect for the work of builders who went before them, but pulled down and altered as they thought fit; and why shouldn't we ? ''Creation and preservation don't do well together,'' says he, ''and a million of antiquarians can't invent a style.'' My mind exactly. I am for niaking this place more modern, that we may be cheerful whilst we can.' The military man turned and surveyed the interior of the room, to assist his ideas of improvement in this direction. Gabriel and Coggan began to move on. ' Oh, Coggan,' said Troy, as if inspired by a recollec+ tion ' do you know if insanity has ever appeared in Mr. Boldwood's family ? ' Jan reflected for a moment. 'I once heard that an uncle of his was queer in his head, but I don't know the rights o't,' he said. 'It is of no importance,' said Troy, lightly. 'Well, I shall be down in the fields with you some time this week ; but I have a few matters to attend to first. So good-day to you. We shall, of course, keep on just as friendly terms as usual. I'm not a proud man : nobody is ever able to say that of Sergeant Troy. However, what is must be, and here's half-a-crown to drink my health, men.' Troy threw the coin dexterously across the front plot and over the fence towards Gabriel, who shunned it in its fall, his face turning to an angry red. Coggan twirled his eye, edged

forward, and caught the money in its ricochet upon the road. ' very weli-you keep it, Coggan,' said Gabriel with disdain and almost fiercely. 'As for me, I'll do with+ out gifts from him !' 'Don't show it too much,' said Coggan, musingly. 'For if he's married to her, mark my words, he'll buy his discharge and be our master here. Therefore 'tis well to say '' Friend '' outwardly, though you say ''Troublehouse '' within. ' ' Weli-perhaps it is best to be silent; but I can't go further than that. I can't flatter, and if my place here is only to be kept by smoothing him down, my place must be lost.' A horseman, whom they had for some time seen in the distance, now appeared close beside them. ' There's Mr. Boldwood,' said Oak. ' I wonder what Troy meant by his question.' Coggan and Oak nodded respectfully to the farmer, just checked their paces to discover if they were wanted, and finding they were not stood back to let him pass on. The only signs of the terrible sorrow Boldwood had been combating through the night, and was combating now, were the want of colour in his welidefined face, the enlarged appearance of the veins in his forehead and temples, and the sharper lines about his mouth. The horse bore him away, and the very step of the animal seemed significant of dogged despair. Gabriel, for a minute, rose above his own grief in noticing Boldwood's. He saw the square figure sitting erect upon the horse, the head turned to neither side, the elbows steady by the hips, the brim of the hat level and undisturbed in its onward glide, until the keen edges of Boldwood's shape sank by degrees over the hill. To one who knew the man and his story there was something more striking in this immobility than in a collapse. The clash of discord between mood and matter here was forced painfully home to the heart ; and, as in laughter there are more dreadful phases than in tears, so was there in the steadiness of this agonized man an expression deeper than a cry.

WEALTH IN JEOPARDY -- THE RVEEL ONE night, at the end of August, when Bathsheba's experiences as a married woman were still new, and when the weather was yet dry and sultry, a man stood motionless in the stackyard of Weatherbury Upper Farm, looking at the moon and sky. The night had a sinister aspect. A heated breeze from the south slowly fanned the summits of lofty objects, and in the sky dashes of buoyant cloud were sailing in a course at right angles to that of another stratum, neither of them in the direction of the breeze below. The moon, as seen through these films, had a lurid metallic look. The fields were sallow with the impure light, and all were tinged in monochrome, as if beheld through stained glass. The same evening the sheep had trailed homeward head to tail, the behaviour of the rooks had heen confused, and the horses had moved with timidity and caution. Thunder was imminent, and, taking some secondary appearances into consideration, it was likely to be followed by one of the lengthened rains which mark the close of dry weather for the season. Before twelve hours had passed a harvest atmosphere would be a bygone thing. Oak gazed with misgiving at eight naked and un' protected ricks, massive and heavy with the rich produce of one-half the farm for that year. He went on to the barn. This was the night which had been selected by Sergeant Troy -- ruling now in the room of his wife -- for giving the harvest supper and dance. As Oak approached the building the sound of violins and a tambourine, and the regular jigging of many feet, grew more distinct. He came close to the large doors, one of which stood slightly ajar, and looked in. The central space, together with the recess at one end, was

emptied of all incumbrances, and this area, covering about two-thirds of the whole, was appropriated for the gathering, the remaining end, which was piled to the ceiling with oats, being screened off with sail' cloth. Tufts and garlands of green foliage decomted the walls, beams, and extemporized chandeliers, and immediately opposite to Oak a rostrum had been erected, bearing a table and chairs. Here sat three fiddlers, and beside them stood a frantic man with his hair on end, perspiration streaming down his cheeks, and a tanabourine quivering in his hand. The dance ended, and on the black oak floor in the midst a new row of couples formed for another. 'Now, ma'am, and no offence I hope, I ask what dance you would like next ?' said the first violin. 'Really, it makes no difference,' said the clear voice of Bathsheba, who stood at the inner end of the build+ ing, observing the scene from behind a table covered with cups and viands. Troy was lolling beside her. 'Then,' said the fiddler, 'I'll venture to name that the right and proper thing is ''The Soldier's Joy'' -- there being a gallant soldier married into the farm -- hey, my sonnies, and gentlemen all ? ' 'It shall be ''The Soldier's Joy,''' exclaimed a chorus. 'Thanks for the compliment,' said the sergeant THE REVEL gaily, taking Bathsheba by the hand and leading her to the top of the dance. 'For though I have pur+ chased my discharge from Her Most Gracious Majesty's regiment of cavalry the 11th Dragoon Guards, to attend to the new duties awaiting me here, I shall continue a soldier in spirit and feeling as long as I live.' So the dance began. As to the merits of 'The Soldier's Joy,' there cannot be, and never were, two opinions. It has been observed in the musical circles of Weatherbury and its vicinity that this melody, at the end of three-quarters of an hour of thunderous footing, still possesses more stimulative properties for the heel and toe than the majority of other dances at their first opening. 'The Soldier's Joy' has, too, an additional charm, in being so admirably adapted to the tambourine aforesaid -- no mean instrument in the hands of a performer

who understands the proper convulsions, spasms, St. vitus's dances, and fearful frenzies necessary when exhibiting its tones in their highest perfection. The immortal tune ended, a fine DD rolling forth from the bass-viol with the sonorousness of a cannonade, and Gabriel delayed his entry no longer. He avoided Bathsheba, and got as near as possible to the platform, where Sergeant Troy was now seated, drinking brandy+ and-water, though the others drank without exception cider and ale. Gabriel could not easily thrust himself within speaking distance of the sergeant, and he sent a message, asking him to come down for a moment. 'The sergeant said he could not attend. 'Will you tell him, then,' said Gabriel, 'that I only stepped ath'art to say that a heavy rain is sure to fall soon, and that something should be done to protect the ricks ?' 'M. Troy says it will not rain,' returned the messenger, 'and he cannot stop to talk to you about such fidgets.' In Juxtaposition with Troy, Oak had a melancholy tendency to look like a candle beside gas, and ill at ease, he went out again, thinking he would go home ; for, under the circumstances, he had no heart for the scene in the barn. At the door he paused for a moment : Troy was speaking. 'Friends, it is not only the harvest home that we are celebrating to-night; but this is also a Wedding Feast. A short time ago I had the happiness to lead to the altar this lady, your mistress, and not until now have we been able to give any public flourish to the event in Weatherbury. That it may be thoroughly well done, and that every man may go happy to bed, I have ordered to be brought here some bottles of brandy and kettles of hot water. A treble-strong goblet will he handed round to each guest.' Bathsheba put her hand upon his arm, and, with upturned pale face, said imploringly, ' No -- don't give it to them -- pray don't, Frank .! It will only do them harm : they have had enough of everything.' 'True -- we don't wish for no more, thank ye,' said one or two. 'Pooh .! ' said the sergeant contemptuously, and raised his

voice as if lighted up by a new idea. ' Friends,' he said, ' we'll send the women-folk home .! 'Tis time they were in bed. Then we cockbirds will have a jolly carouse to ourselves .! If any of the men show the white feather, let them look elsewhere for a winter's work.' Bathsheba indignantly left the barn, followed by all the women and children. The musicians, not looking upon themselves as ' company,' slipped quietly away to their spring waggon and put in the horse. Thus Troy and the men on the farm were left sole occupants of the place. Oak, not to appear unneces+ sarily disagreeable, stayed a little while ; then he, too, arose and quietly took his departure, followed by a friendly oath from the sergeant for not staying to a second round of grog. Gabriel proceeded towards his home. In approach+ ing the door, his toe kicked something which felt and sounded soft, leathery, and distended, like a boxing+ glove. It was a large toad humbly travelling across the path. Oak took it up, thinking it might be better to kill the creature to save it from pain; but finding it uninjured, he placed it again among the grass. He knew what this direct message from the Great Mother meant. And soon came another. When he struck a light indoors there appeared upon the table a thin glistening streak, as if a brush of varnish had been lightly dragged across it. Oak's eyes followed the serpentine sheen to the other side, where it led up to a huge brown garden-slug, which had come indoors to-night for reasons of its own. It was Nature's second way of hinting to him that he was to prepare for foul weather. Oak sat down meditating for nearly an hour. During this time two black spiders, of the kind common in thatched houses, promenaded the ceiling, ultimately dropping to the floor. This reminded him that if there was one class of manifestation on this matter that he thoroughly understood, it was the instincts of sheep. He left the room, ran across two or three fields towards the flock, got upon a hedge, and looked over among them. They were crowded close together on the other side around some

furze bushes, and the first peculiarity ob+ servable was that, on the sudden appearance of Oak's head over the fence, they did not stir or run away. They had now a terror of something greater than their terror of man. But this was not the most noteworthy feature : they were all grouped in such a way that their tails, without a single exception, were towards that half of the horizon from which the storm threatened. There was an inner circle closely huddled, and outside these they radiated wider apart, the pattern formed by the flock as a whole not being unlike a vandyked lace collar, to which the clump of furze-bushes stood in the position of a wearer's neck. opinion. He knew now that he was right, and that Troy was wrong. Every voice in nature was unanimous in bespeaking change. But two distinct translations attached to these dumb expressions. Apparently there was to be a thunder-storm, and afterwards a cold con+ tinuous rain. The creeping things seemed to know all about the later rain, hut little of the interpolated thunder-storm ; whilst the sheep knew all about the thunder-storm and nothing of the later rain. This complication of weathers being uncommon, was all the more to be feared. Oak returned to the stack-yard. All was silent here, and the conical tips of the ricks jutted darkly into the sky. There were five wheat-ricks in this yard, and three stacks of barley. The wheat when threshed would average about thirty quarters to each stack ; the barley, at least forty. Their value to Bathsheba, and indeed to anybody, Oak mentally estimated by the following simple calcula+ tion : -- 5 x 30 = 150 quarters= 500fl. 3 x 40=120 quarters= 250l. Total . . 750l. Seven hundred and fifty pounds in the divinest form that money can wear -- that of necessary food for man and beast : should the risk be run cf deteriorating this bulk of corn to less than half its value, because of the instability of a woman ? 'Never, if I can prevent it.! ' said Gabriel.

Such was the argument that Oak set outwardly before him. But man, even to himself, is a palimpsest, having an ostensible writing, and another beneath the lines. It is possible that there was this golden legend under the utilitarian one: 'I will help to my last effort the woman I have loved so dearly.' He went back to the barn to endeavour to obtain assistance for covering the ricks that very

night. All was silent within, and he would have passed on in the belief that the party had broken up, had not a dim light, yellow as saffron by contrast with the greenish whiteness outside, streamed through a knot-hole in the folding doors. Gabriel looked in. An unusual picture met his eye. The candles suspended among the evergreens had burnt down to their sockets, and in some cases the leaves tied about them were scorched. Many of the lights had quite gone out, others smoked and stank, grease dropping from them upon the floor. Here, under the table, and leaning against forms and chairs in every conceivable attitude except the perpendicular, !' were the wretched persons of all the work-folk, the hair of their heads at such low levels being suggestive of mops and brooms. In the midst of these shone red and distinct the figure of Sergeant Troy, leaning back in a chair. Coggan was on his back, with his mouth open, huzzing forth snores, as were several others ; the united breathings of the horizonal assemblage forming a subdued roar like London from a distance. Joseph Poorgrass was curled round in the fashion of a hedge+ hog, apparently in attempts to present the least possible portion of his surface to the air; and behind him was dimly visible an unimportant remnant of William Smali bury. The glasses and cups still stood upon the table, a water-jug being overturned, from which a small rill, after tracing its course with marvellous precision down the centre of the long table, fell into the neck of the unconscious Mark Clark, in a steady, monotonous drip, like the dripping of a stalactite in a cave. Gabriel glanced hopelessly at the group, which, with one or two exceptions, composed all the able-bodied men upon the farm. He saw at once that if the ricks were to be saved that night, or even the next morning, he must save them with his own hands. A faint ' ting-ting ' resounded from under Coggan's waistcoat. It was Coggan's watch striking the hour of two. Oak went to the recumbent form of Matthew Moon, who usually undertook the rough thatching of the home+ stead, and shook him. The shaking was without effect. Gabriel shouted in his ear, ' where's your thatching+ beetle and rick-stick and spars ? ' ' Under the staddles,' said Moon, mechanically, with the unconscious promptness of a medium. Gabriel let go his head, and it dropped upon the floor like a bowl. He then went to Susan Tall's husband. ' where's the key of the granary ? ' No answer. The question was repeated, with the same result. To be shouted to at night was evidently less of a novelty to Susan Tall's husband than to Matthew Moon. Oak flung down Tall's head into the corner again and turned away. To be just, the men were not greatly to blame for this painful and demoralizing termination to the evening's entertainment. Sergeant Troy had so strenu+ ously insisted, glass in hand, that drinking should be the bond of their union, that those who wished to refuse hardly liked to be so unmannerly under the circum+ stances. Having from their youth up been entirely un+ accustomed to any liquor stronger than cider or mild ale, it was no wonder that they had succumbed, one and all, with extraordinary uniformity, after the lapse of about an hour. Gabriel was greatly depressed. This debauch boded ill for that wilful and fascinating mistress whom the faithful man even now felt within him as the embodi+ ment of all that was sweet and bright and hopeless. He put out the expiring lights, that the barn might not be endangered, closed the door upon the men in their deep and oblivious sleep, and went again into the lone night. A hot breeze, as if breathed from the parted lips of some dragon about to swallow the globe, fanned him from the south, while directly opposite in the north rose a grim misshapen body of

cloud, in the very teeth of the wind. So unnaturally did it rise that one could fancy it to be lifted by machinery from below. Meanwhile the faint cloudlets had flown back into the south-east corner of the sky, as if in terror of the large cloud, like a young brood gazed in upon by some monster. Going on to the village, Oak flung a small stone against the window of Laban Tall's bedroom, expecting Susan to open it ; but nobody stirred. He went round to the back door, which had been left unfastened for Laban's entry, and passed in to the foot of the stair+ case. 'Mrs. Tall, I've come for the key of the granary, to get at the rick-cloths,' said Oak, in a stentorian voice. 'Is that you ? ' said Mrs. Susan Tall, half awake. ' Yes,' said Gabriel. 'Come along to bed, do, you drawlatching rogue -- keeping a body awake like this .' 'It isn't Laban -- 'tis Gabriel Oak. I want the key of the granary.' 'Gabriel. what in the name of fortune did you pretend to be Laban for ?' ' I didn't. I thought you meant -- -- ' 'yes you did !. what do you want here ?' 'The key of the granary.' "Take it then. 'Tis on the nail. People coming disturbing women at this time of night ought -- -- ' Gabriel took the key, without waiting to hear the conclusion of the tirade. Ten minutes later his lonely figure might have been seen dragging four large water+ proof coverings across the yard, and soon two of these heaps of treasure in grain were covered snug -- two cloths to each. Two hundred pounds were secured. Three wheat-stacks remained open, and there were no more cloths. Oak looked under the staddles and found a fork. He mounted the third pile of wealth and began operating, adopting the plan of sloping the upper sheaves one over the other; and, in addition, filling the interstices with the material of some untied sheaves. So far all was well. By this hurried contrivance Bathsheba's

property in wheat was safe for at any rate a week or two, provided always that there was not much wind. Next came the barley. This it was only possible to protect by systematic thatching. Time went on, and the moon vanished not to reappear. It was the farewell of the ambassador previous to war. The night had a haggard look, like a sick thing; and there came finally an utter expiration of air from the whole heaven in the form of a slow breeze, which might have been likened to a death. And now nothing was heard in the yard but the dull thuds of the beetle which drove in the spars, and the rustle of thatch in the intervals. THE STORM

THE STORM -- THE TWO TOGETHER A LIGHT flapped over the scene, as if reflected from phosphorescent wings crossing the sky, and a rumble filled the air. It was the first move of the approaching storm. The second peal was noisy, with comparatively little visible lightning. Gabriel saw a candle shining in Bath+ sheba's bedroom, and soon a shadow swept to and fro upon the blind. Then there came a third flash. Manoeuvres of a most extraordinary kind were going on in the vast firmamental hollows overhead. The lightning now was the colour of silver, and gleamed in the heavens like a mailed army. Rumbles became rattles. Gabriel from his elevated position could see over the landscape at least half-a-dozen miles in front. Every hedge, bush, and tree was distinct as in a line engraving. In a paddock in the same direction was a herd of heifers, and the forms of these were visible at this moment in the act of galloping about in the wildest and maddest confusion, flinging their heels and tails high into the air, their heads to earth. A poplar in the immediate fore+ ground was like an ink stroke on burnished tin. Then the picture vanished, leaving the darkness so intense that Gabriel worked entirely by feeling with his hands. He had stuck his ricking-rod, or poniard, as it was indifferently called -- a long iron lance, polished by handling -- into the stack, used to support the sheaves instead of the support called a groom used on houses, A blue light appeared in the zenith, and in some in+ describable manner flickered down near the top of the rod. It was the fourth of the larger flashes. A moment later and there was a smack -- smart, clear, and short, Gabriel felt his position to be anything but a safe one, and he resolved to descend. Not a drop of rain had fallen as yet. He wiped his weary brow, and looked again at the black forms of the unprotected

stacks. Was his life so valuable to him after all? What were his prospects that he should be so chary of running risk, when important and urgent labour could not be carried on without such risk ? He resolved to stick to the stack. How+ ever, he took a precaution. Under the staddles was a long tethering chain, used to prevent the escape of errant horses. This he carried up the ladder, and sticking his rod through the clog at one end, allowed the other end of the chain to trail upon the ground The spike attached to it he drove in. Under the shadow of this extemporized lightning-conductor he felt himself comparatively safe. Before Oak had laid his hands upon his tools again out leapt the fifth flash, with the spring of a serpent and the shout of a fiend. It was green as an emerald, and the reverberation was stunning. What was this the light revealed to him? In the open ground before him, as he looked over the ridge of the rick, was a dark and apparently female form. Could it be that of the only venturesome woman in the parish -- Bathsheba ? The form moved on a step : then he could see no more. "Is that you, ma'am ? ' said Gabriel to the darkness. "Who is there ?' said the voice of Bathsheba, THE TWO TOGETHER "Gabriel. I am on the rick, thatching.' "O, Gabriel ! -- and are you ? I have come about them. The weather awoke me, and I thought of the corn. I am so distressed about it -- can we save it any+ how ? I cannot find my husband. Is he with you ?' "He is not here.' "Do you know where he is ?' "Asleep in the barn.' "He promised that the stacks should be seen to, and now they are all neglected ! Can I do anything to help ? Liddy is afraid to come out. Fancy finding you here at such an hour ! Surely I can do something ? ' "You can bring up some reed-sheaves to me, one by one, ma'am; if you are not afraid to come up the ladder in the dark,' said Gabriel. "Every moment is precious now, and that would save a good deal of time. It is not very dark when the lightning has been gone a bit.'

"I'll do anything ! ' she said, resolutely. She instantly took a sheaf upon her shoulder, clambered up close to his heels, placed it behind the rod, and descended for another. At her third ascent the rick suddenly brightened with the brazen glare of shining majolica -- every knot in every straw was visible. On the slope in front of him appeared two human shapes, black as jet. The rick lost its sheen -- -the shapes vanished. Gabriel turned his head. It had been the sixth flash which had come from the east behind him, and the two dark forms on the slope had been the shadows of himself and Bathsheba. Then came the peal. It hardly was credible that such a heavenly light could be the parent of such a diabolical sound. "How terrible ! ' she exclaimed, and clutched him by the sleeve. Gabriel turned, and steadied her on her aerial perch by holding her arm. At the same moment, while he was still reversed in his attitude, there was more light, and he saw, as it were, a copy of the tall poplar tree on the hill drawn in black on the wall of the barn. It was the shadow of that tree, thrown across by a secondary flash in the west. The next flare came. Bathsheba was on the ground now, shouldering another sheaf, and she bore its dazzle without flinching -- thunder and ali-and again ascended with the load. There was then a silence everywhere for four or five minutes, and the crunch of the spars, as Gabriel hastily drove them in, could again be distinctly heard. He thought the crisis of the storm had passed. But there came a burst of light. "Hold on ! ' said Gabriel, taking the sheaf from her shoulder, and grasping her arm again. Heaven opened then, indeed. The flash was almost too novel for its inexpressibly dangerous nature to be at once realized, and they could only comprehend the magnificence of its beauty. It sprang from east, west, north, south, and was a perfect dance of death. The forms of skeletons appeared in the air, shaped with blue fire for bones -- dancing, leaping, striding, racing around, and mingling altogether in unparalleled con+ fusion. With these were intertwined undulating snakes of green, and behind these was a broad mass of lesser light. Simultaneously came from every part of the tumbling

sky what may be called a shout ; since, though no shout ever came near it, it was more of the nature of a shout than of anything eise earthly. In the meantime one of the grisly forms had alighted upon the point of Gabriel's rod, to run invisibly down it, down the chain, and into the earth. Gabriel was almost blinded, and he could feel Bathsheba's warm arm tremble in his hand -- a sensation novel and thrilling enough ; but love, life, everything human, seemed small and trifling in such close juxtaposition with an infuriated universe. Oak had hardly time to gather up these impressions into a thought, and to see how strangely the red feather of her hat shone in this light, when the tall tree on the hill before mentioned seemed on fire to a white heat, and a new one among these terrible voices mingled with the last crash of those preceding. It was a stupefying blast, harsh and pitiless, and it fell upon their ears in a dead, flat blow, without that reverberation which lends the tones of a drum to more distant thunder. By the lustre reflected from every part of the earth and from the wide domical scoop above it, he saw that the tree was sliced down the whole length of its tall, straight stem, a huge riband of bark being apparently flung off. The other portion remained erect, and revealed the bared surface as a strip of white down the front. The lightning had struck the tree. A sulphurous smell filled the air; then all was silent, and black as a cave in Hinnom. " We had a narrow escape ! ' said Gabriel, hurriedly. " You had better go down.' Bathsheba said nothing ; but he could distinctly hear her rhythmical pants, and the recurrent rustle of the sheaf beside her in response to her frightened pulsations. She descended the ladder, and, on second thoughts, he followed her. The darkness was now impenetrable by the sharpest vision. They both stood still at the bottom, side by side. Bathsheba appeared to think only of the weather -- Oak thought only of her just then. At last he said -- "The storm seems to have passed now, at any rate.' " I think so too,' said Bathsheba. " Though there are multitudes of gleams, look ! '

The sky was now filled with an incessant light, frequent repetition melting into complete continuity, as an unbroken sound results from the successive strokes on a gong. " Nothing serious,' said he. " I cannot understand no rain falling. But Heaven be praised, it is all the better for us. I am now going up again.' " Gabriel, you are kinder than I deserve ! I will stay and help you yet. O, why are not some of the others here ! ' " They would have been here if they could,' said Oak, in a hesitating way. 'O, I know it ali-all,' she said, adding slowly : " They are all asleep in the barn, in a drunken sleep, and my husband among them. That's it, is it not ? Don't think I am a timid woman and can't endure things.' "I am not certain,' said Gabriel. 'I will go and see,' He crossed to the barn, leaving her there alone. He looked through the chinks of the door. All was in total darkness, as he had left it, and there still arose, as at the former time, the steady buzz of many snores. He felt a zephyr curling about his cheek, and turned. It was Bathsheba's breath -- she had followed him, and was looking into the same chink. He endeavoured to put off the immediate and pain+ ful subject of their thoughts by remarking gently, "lf you'll come back again, miss -- ma'am, and hand up a few more; it would save much time.' Then Oak went back again, ascended to the top, stepped off the ladder for greater expedition, and went on thatching. She followed, but without a sheaf " Gabriel,' she said, in a strange and impressive voice. Oak looked up at her. She had not spoken since he left the barn. The soft and continual shimmer of the dying lightning showed a marble face high against the black sky of the opposite quarter. Bathsheba was sitting almost on the apex of the stack, her feet gathered up beneath her, and resting on the top round of the ladder. " Yes, mistress,' he said.

"I suppose you thought that when I galloped away to Bath that night it was on purpose to be married ?" 'I did at last -- not at first,' he answered, somewhat surprised at the abruptness with which this new subject was broached. " And others thought so, too ? ' " Yes.' "And you blamed me for it ?' " Weli-a little.' "I thought so. Now, I care a little for your good opinion, and I want to explain something-i have longed to do it ever since I returned, and you looked so gravely at me. For if I were to die -- and I may die soon -- it would be dreadful that you should always think mistakenly of me. Now, listen.' Gabriel ceased his rustling. 'I went to Bath that night in the full intention of breaking off my engagement to Mr. Troy. It was owing to circumstances which occurred after I got there that -- that we were married. Now, do you see the matter in a new light?' " I do -- somewhat.' " I must, I suppose, say more, now that I have begun. And perhaps it's no harm, for you are certainly under no delusion that I ever loved you, or that I can have any object in speaking, more than that object I have mentioned. Well, I was alone in a strange city, and the horse was lame. And at last I didn't know what to do. I saw, when it was too late, that scandal might seize hold of me for meeting him alone in that way. But I was coming away, when he suddenly said he had that day seen a woman more beautiful than I, and that his constancy could not be counted on unless I at once became his.... And I was grieved and troubled -- -- ' She cleared her voice, and waited a moment, as if to gather breath. " And then, between jealousy and distraction, I married him ! ' she whispered with desperate impetuosity. Gabriel made no reply. "He was not to blame, for it was perfectly true about -- about his seeing somebody else,' she quickly added. "And now I don't wish for a single remark from you upon the subject --

indeed, I forbid it. I only wanted you to know that misunderstood bit of my history before a time comes when you could never know it. -- You want some more sheaves ? ' She went down the ladder, and the work proceeded. Gabriel soon perceived a languor in the movements of his mistress up and down, and he said to her, gently as a mother -- "I think you had better go indoors now, you are tired. I can finish the rest alone. If the wind does not change the rain is likely to keep off.' "If I am useless I will go,' said Bathsheba, in a flagging cadence. 'But O, if your life should be lost !' " You are not useless; but I would rather not tire you longer. You have done well.' "And you better ! ' she said, gratefully. ! Thank you for your devotion, a thousand times, Gabriel ! Good+ night-i know you are doing your very best for me.' She diminished in the gloom, and vanished, and he heard the latch of the gate fall as she passed through. He worked in a reverie now, musing upon her story, and upon the contradictoriness of that feminine heart which had caused her to speak more warmly to him to-night than she ever had done whilst unmarried and free to speak as warmly as she chose. He was disturbed in his meditation by a grating noise from the coach-house. It was the vane on the roof turning round, and this change in the wind was the signal for a disastrous rain. RAIN

RAIN -- ONE SOLITARY MEETS ANOTHER IT was now five o'clock, and the dawn was promising to break in hues of drab and ash. The air changed its temperature and stirred itself more vigorously. Cool breezes coursed in transparent eddies round Oak's face. The wind shifted yet a point or two and blew stronger. In ten minutes every wind of heaven seemed to be roaming at large. Some of the thatching on the wheat-stacks was now whirled fantas+ tically aloft, and had to be replaced and weighted with some rails that lay near at hand. This done, Oak slaved away again at the barley. A huge drop of rain smote his face, the wind snarled round every corner, the trees rocked to the bases of their trunks, and the twigs clashed in strife. Driving in spars at any point and on any system, inch by inch he covered more and more safely from ruin this distracting impersonation of seven hundred pounds. 'The rain came on in earnest, and Oak soon felt the water to be tracking cold and clammy routes down his back. Ultimately he was reduced welinigh to a homogeneous sop, and the dyes of his clothes trickled down and stood in a pool at the foot of the ladder. The rain stretched obliquely through the dull atmo+ sphere in liquid spines, unbroken in continuity between their beginnings in the clouds and their points in him. Oak suddenly remembered that eight months before this time he had been fighting against fire in the same spot as desperately as he was fighting against water now -- and for a futile love of the same woman. As for her -- -- But Oak was generous and true, and dis+ missed his reflections. It was about seven o'clock in the dark leaden morning when Gabriel came down from the last stack, and thankfully exclaimed, "It is done .! ' He was

drenched, weary, and sad, and yet not so sad as drenched and weary, for he was cheered by a sense of success in a good cause. Faint sounds came from the barn, and he looked that way. Figures stepped singly and in pairs through the doors -- all walking awkwardly, and abashed, save the foremost, who wore a red jacket, and advanced with his hands in his pockets, whistling. The others shambled after with a conscience-stricken air : the whole procession was not unlike Flaxman's group of the suitors tottering on towards the infernal regions under the conduct of Mercury. The gnarled shapes passed into the village, Troy, their leader, entering the farmhouse. Not a single one of them had turned his face to the ricks, or apparently bestowed one thought upon their condition. Soon Oak too went homeward, by a different route from theirs. In front of him against the wet glazed surface of the lane he saw a person walking yet more slowly than himself under an umbrella. The man turned and plainly started; he was Boldwood. " How are you this morning, sir ?' said Oak. "Yes, it is a wet day. -- Oh, I am well, very well, I thank you ; quite well.' "I am glad to hear it, sir.' Boldwood seemed to awake to the present by degrees. " You look tired and ill, Oak,' he said then, desultorily regarding his companion. " I am tired. You look strangely altered, sir.' "I? Not a bit of it : I am well enough. What put that into your head ?' "I thought you didn't look quite so topping as you used to, that was all.' " Indeed, then you are mistaken,' said Boldwood, shortly. "Nothing hurts me. My constitution is an iron one.' "I've been working hard to get our ricks covered, and was barely in time. Never had such a struggle in my life.... Yours of course are safe, sir.' " O yes.' Boldwood added, after an interval of silence : " What did you ask, Oak ? ' " Your ricks are all covered before this time ? '

"No.' " At any rate, the large ones upon the stone staddles ?' " They are not.' "Them under the hedge ?' " No. I forgot to tell the thatcher to set about it.' " Nor the little one by the stile ?' "Nor the little one by the stile. I overlooked the ricks this year.' 'Then not a tenth of your corn will come to measure, sir.' " Possibly not. " Overlooked them,' repeated Gabriel slowly to him+ self. It is difficult to describe the intensely dramatic effect that announcement had upon Oak at such a moment. All the night he had been feeling that the neglect he was labouring to repair was abnormal and isolated -- the only instance of the kind within the circuit of the county. Yet at this very time, within the same parish, a greater waste had been going on, uncomplained of and disregarded. A few months earlier Boldwood's forgetting his husbandry would have been as preposter+ ous an idea as a sailor forgetting he was in a ship. Oak was just thinking that whatever he himself might have suffered from Bathsheba's marriage, here was a man who had suffered more, when Boldwood spoke in a changed voice -- that of one who yearned to make a confidence and relieve his heart by an outpouring. "Oak, you know as well as I that things have gone wrong with me lately. I may as well own it. I was going to get a little settled in life; but in some way my plan has come to nothing.' "I thought my mistress would have married you,' said Gabriel, not knowing enough of the full depths of Boldwood's love to keep silence on the farmer's account, and determined not to evade discipline by doing so on his own. 'However, it is so sometimes, and nothing happens that we expect,' he added, with the repose of a man whom misfortune had inured rather than sub+ dued. 'I daresay I am a joke about the parish,' said Bold+ wood, as if the subject came irresistibly to his tongue, and with a miserable lightness meant to express his indifference.

" O no -- I don't think that.' -- But the real truth of the matter is that there was not, as some fancy, any jilting on -- her part. No engagement ever existed between me and Miss Ever+ dene. People say so, but it is untrue: she never promised me .! ' Boldwood stood still now and turned his wild face to Oak. 'O, Gabriel,' he continued, "I am weak and foolish, and I don't know what, and I can't fend off my miserable grief ! ... I had some faint belief in the mercy of God till I lost that woman. Yes, He prepared a gourd to shade me, and like the prophet I thanked Him and was glad. But the next day He prepared a worm to smite the gourd and wither it; and I feel it is better to die than to live.!" A silence followed. Boldwood aroused himself from the momentary mood of confidence into which he had drifted, and walked on again, resuming his usual reserve, " No, Gabriel,' he resumed, with a carelessness which was like the smile on the countenance of a skull: "it was made more of by other people than ever it was by us. I do feel a little regret occasionally, but no woman ever had power over me for any length of time. Well, good morning ; I can trust you not to mention to others what has passed between us two here.'

COMING HOME -- A CRY ON the turnpke road, between Casterbridge and Weatherbury, and about three miles from the former which pervade the highways of this undulating part of South Wessex. I returning from market it is usual for the farmers and other gig-gentry to alight at the bottom and walk up. One Saturday evening in the month of October Bathsheba's vehicle was duly creeping up this incline. She was sitting listlessly in the second seat of the gig, whilst walking beside her in farmer's marketing suit of unusually fashionable cut was an erect, welimade young man. Though on foot, he held the reins and whip, and occasionally aimed light cuts at the horse's ear with the end of the lash, as a recreation. This man was her husband, formerly Sergeant Troy, who, having bought his discharge with Bathsheba's money, was gradually transforming himself into a farmer of a spirited and very modern school. People of unalter+ able ideas still insisted upon calling him 'Sergeant' when they met him, which was in some degree owing to his having still retained the welishaped moustache of his military days, and the soldierly bearing insepar+ able from his form and training. "Yes, if it hadn't been for that wretched rain I should have cleared two hundred as easy as looking, my love,' he was saying. "Don't you see, it altered all the chances? To speak like a book I once read, wet weather is the narrative, and fine days are the episodes, of our country's history; now, isn't that true?' ' But the time of year is come for changeable weather.' "Well, yes. The fact is, these autumn races are the ruin of everybody. Never did I see such a day as 'twas .! 'Tis a wild open place, just out of Budmouth, and a drab sea rolled in

towards us like liquid misery. Wind and rain -- good Lord !. Dark ? Why, 'twas as black as my hat before the last race was run. 'Twas five o'clock, and you couldn't see the horses till they were almost in, leave alone colours. The ground was as heavy as lead, and all judgment from a fellow's experi+ ence went for nothing. Horses, riders, people, were all blown about like ships at sea. Three booths were blown over, and the wretched folk inside crawled out upon their hands and knees; and in the next field were as many as a dozen hats at one time. Aye, Pimpernel regularly stuck fast, when about sixty yards off, and when I saw Policy stepping on, it did knock my heart against the lining of my ribs, I assure you, my love.!' " And you mean, Frank,' said Bathsheba, sadly -- her voice was painfully lowered from the fulness and vivacity of the previous summer -- "that you have lost more than a hundred pounds in a month by this dreadful horse-racing ? O, Frank, it is cruel; it is foolish of you to take away my money so. We shall have to leave the farm; that will be the end of it !.' ' Humbug about cruel. Now, there 'tis again -- turn on the waterworks ; that's just like you.' "But you'll promise me not to go to Budmouth second meeting, won't you ? ' she implored. Bathsheba was at the full depth for tears, but she maintained a dry eye. "I don't see why I should; in fact, if it turns out to be a fine day, I was thinking of taking you.' "Never, never.! I'll go a hundred miles the other way first. I hate the sound of the very word.!' "But the question of going to see the race or staying at home has very little to do with the matter. Bets are all booked safely enough before the race begins, you may depend. Whether it is a bad race for me or a good one, will have very little to do with our going there next Monday.' "But you don't mean to say that you have risked anything on this one too .! ' she exclaimed, with an agonized look. "There now, don't you be a little fool. Wait till you are told. Why, Bathsheba, you have lost all the pluck and sauciness you formerly had, and upon my life if I had known what a

chicken-hearted creature you were under all your boldness, I'd never have-i know what.' A flash of indignation might have been seen in Bathsheba's dark eyes as she looked resolutely ahead after this reply. They moved on without further speech, some early-withered leaves from the trees which hooded the road at this spot occasionally spinning downward across their path to the earth. A woman appeared on the brow of the hill. The ridge was in a cutting, so that she was very near the husband and wife before she became visible. Troy had turned towards the gig to remount, and whilst putting his foot on the step-the woman passed behind him. Though the overshadowing trees and the approach of eventide enveloped them in gloom, Bathsheba could see plainly enough to discern the extreme poverty of the woman's garb, and the sadness of her face. "Please, sir, do you know at what time Casterbridge Union-house closes at night ? ' A CRY The woman said these words to Troy over his shoulder. Troy started visibly at the sound of the voice; yet he seemed to recover presence of mind sufficient to prevent himself from giving way to his impulse to suddenly turn and face her. He said, slowly -- " I don't know." The woman, on hearing him speak, quickly looked up, examined the side of his face, and recognized the soldier under the yeoman's garb. Her face was drawn into an expression which had gladness and agony both among its elements. She uttered an hysterical cry, and fell down. " O, poor thing.!' exclaimed Bathsheba, instantly preparing to alight. "Stay where you are, and attend to the horse!' said Troy, peremptorily throwing her the reins and the whip. "Walk the horse to the top: I'll see to the woman.' " But i -- -' " Do you hear? Clk -- Poppet.!'

The horse, gig, and Bathsheba moved on. "How on earth did you come here? I thought you were miles away, or dead.! Why didn't you write to me?' said Troy to the woman, in a strangely gentle, yet hurried voice, as he lifted her up. " I feared to." 'Have you any money?' "None." "Good Heaven -- I wish I had more to give you!. Here's -- wretched -- the merest trifle. It is every farthing I have left. I have none but what my wife gives me, you know, and I can't ask her now.' The woman made no answer. "I have only another moment,' continued Troy; 'and now listen. Where are you going to-night? Casterbridge Union?' "Yes; I thought to go there.' " You shan't go there; yet, wait. Yes, perhaps for to-night ; I can do nothing better -- worse luck.! Sleep there to-night, and stay there to-morrow. Monday is the first free day I have; and on Monday morning, at ten exactly, meet me on Grey's Bridge just out of the town. I'll bring all the money I can muster. You shan't want-i'll see that, Fanny; then I'll get you a lodging somewhere. Good-bye till then. I am a brute -- but good-bye.!' After advancing the distance which completed the ascent of the hill, Bathsheba turned her head. The woman was upon her feet, and Bathsheba saw her withdrawing from Troy, and going feebly down the hill by the third milestone from Casterbridge. Troy then came on towards his wife, stepped into the gig, took the reins from her hand, and without making any observation whipped the horse into a trot. He was rather agitated. "Do you know who that woman was?' said Bath+ sheba, looking searchingly into his face. "I do,' he said, looking boldly back into hers. "I thought you did,' said she, with angry hauteur, and still regarding him. " Who is she?'

He suddenly seemed to think that frankness would benefit neither of the women. 'Nothing to either of us,' he said. "I know her by sight." 'What is her name?' "How should I know her name ?' "I think you do.' "Think if you will, and be -- -- " The sentence was completed by a smart cut of the whip round Poppet's flank, which caused the animal to start forward at a wild pace. No more was said. ON CASTERBRIDGE HIGHWAY

FOR a considerable time the woman walked on. Her steps became feebler, and she strained her eyes to look afar upon the naked road, now indistinct amid the penumbrae of night. At length her onward walk dwindled to the merest totter, and she opened a gate within which was a haystack. Underneath this she sat down and presently slept. When the woman awoke it was to find herself in the depths of a moonless and starless night. A heavy un+ broken crust of cloud stretched across the sky, shutting out every speck of heaven ; and a distant halo which hung over the town of Casterbridge was visible against the black concave, the luminosity appearing the brighter by its great contrast with the circumscribing darkness. Towards this weak, soft glow the woman turned her eyes. "If I could only get there.!' she said. "Meet him the day after to-morrow: God help me! Perhaps I shall be in my grave before then.' A manor-house clock from the far depths of shadow struck the hour, one, in a small, attenuated tone. After midnight the voice of a clock seems to lose in breadth as much as in length, and to diminish its sonorousness to a thin falsetto. Afterwards a light -- two lights -- arose frona the re+ mote shade, and grew larger. A carriage rolled along the toad, and passed the gate. It probably contained some late diners-out. The beams from one lamp shone for a moment upon the crouching woman, and threw her face into vivid relieff. The face was young in the groundwork, old in the finish ; the general contours were flexuous and childlike, but the finer lineaments had begun to be sharp and thin. The pedestrian stood up, apparently with revived determination, and looked around. The road appeared to be

familiar to her, and she carefully scanned the fence as she slowly walked along. Presently there became visible a dim white shape; it was another milestone. She drew her fingers across its face to feel the marks. "Two more!' she said. She leant against the stone as a means of rest for a short interval, then bestirred herself, and again pursued her way. For a slight distance she bore up bravely, afterwards flagging as before. This was beside a lone copsewood, wherein heaps of white chips strewn upon the leafy ground showed that woodmen had been faggoting and making hurdles during the day. Now there was not a rustle, not a breeze, not the faintest clash of twigs to keep her company. The woman looked over the gat, opened it, and went in. Close to the entrance stood a row of faggots, bound and un+ bound, together with stakes of all sizes. For a few seconds the wayfarer stood with that tense stillness which signifies itself to be not the end but merely the suspension, of a previous motion. Her attitude was that of a person who listens, either to the external world of sound, or to the imagined discourse of thought. A close criticism might have detected signs proving that she was intent on the latter alternative. Moreover, as was shown by what followed, she was oddly exercising the faculty of invention upon the spe+ ciality of the clever Jacquet Droz, the designer of auto+ matic substitutes for human limbs. By the aid of the Casterbridge aurora, and by feeling with her hands, the woman selected two sticks from the heaps. These sticks were nearly straight to the height of three or four feet, where each branched into a fork like the letter Y. She sat down, snapped off the small upper twigs, and carried the remainder with her into the road. She placed one of these forks under each arm as a crutch, tested them, timidly threw her whole weight upon them -- so little that it was -- and swung herself forward. The girl had made for herself a material aid. The crutches answered well. The pat of her feet, and the tap of her sticks upon the highway, were all the sounds that

came from the traveller now. She had passed the last milestone by a good long distance, and began to look wistfully towards the bank as if calculating upon another milestone soon. The crutches, though so very useful, had their limits of power. Mechanism only transfers labour, being powerless to supersede it, and the original amount of exertion was not cleared away; it was thrown into the body and arms. She was exhausted, and each swing forward became fainter. At last she swayed sideways, and fell. Here she lay, a shapeless heap, for ten minutes and more. The morning wind began to boom dully over the flats, and to move afresh dead leaves which had lain still since yesterday. The woman desperately turned round upon her knees, and next rose to her feet. Steadying herself by the help of one crutch, she essayed a step, then another, then a third, using the crutches now as walking-sticks only. Thus she pro+ gressed till descending Mellstock Hill another milestone appeared, and soon the beginning of an iron-railed fence came into view. She staggered across to the first post, clung to it, and looked around. The Casterbridge lights were now individually visible, It was getting towards morning, and vehicles might be hoped for, if not expected soon. She listened. There was not a sound of life save that acme and sublimation of all dismal sounds, the hark of a fox, its three hollow notes being rendered at intervals of a minute with the precision of a funeral bell. Less than a mile.!' the woman murmured. "No; more,' she added, after a pause. 'The mile is to the county hall, and my resting-place is on the other side Casterbridge. A little over a mile, and there I am! ' After an interval she again spoke. "Five or six steps to a yard -- six perhaps. I have to go seventeen hundred yards. A hundred times six, six hundred. Seventeen times that. O pity me, Lord.!' Holding to the rails, she advanced, thrusting one hand forward upon the rail, then the other, then leaning over it whilst she dragged her feet on beneath. This woman was not given to soliloquy; but ex, tremity of feeling lessens the individuality of the weak, as it increases

that of the strong. She said again in the same tone, "I'll believe that the end lies five posts for+ ward, and no further, and so get strength to pass them.' This was a practical application of the principle that a half-feigned and fictitious faith is better than no faith at all. She passed five posts and held on to the fifth. "I'll pass five more by believing my longed-for spot is at the next fifth. I can do it.' she passed five more. "It lies only five further.' she passed five more. "But it is five further.' She passed them. 'That stone bridge is the end of my journey,' she said, when the bridge over the Froom was in view. She crawled to the bridge. During the effort each breath of the woman went into the air as if never to return again. "Now for the truth of the matter,' she said, sitting down. "The truth is, that I have less than half a mile.' Self-beguilement with what she had known all the time to be false had given her strength to come over half a mile that she would have been powerless to face in the lump. The artifice showed that the woman, by some mysterious intuition, had grasped the paradoxical truth that blindness may operate more vigorously than prescience, and the short-sighted effect more than the far-seeing ; that limitation, and not comprehensiveness, is needed for striking a blow. The half-mile stood now before the sick and weary woman like a stolid Juggernaut. It was an impassive King of her world. The road here ran across Durnover Moor, open to the road on either side. She surveyed the wide space, the lights, herself, sighed, and lay down against a guard-stone of the bridge. Never was ingenuity exercised so sorely as the traveller here exercised hers. Every conceivable aid, m&thod, stratagem, mechanism, by which these last desperate eight hundred yards could be overpasscd by a human being unperceived, was revolved in her busy brain, and dismissed as impracticable. She thought of

sticks, wheels, crawling -- she even thought of rolling. But the exertion demanded by either of these latter two was greater than to walk erect. The faculty of con+ trivance was worn out, Hopelessness had come at last. " No further.!' she whispered, and closed her eyes. From the stripe of shadow on the opposite side of the bridge a portion of shade seemed to detach itself and move into isolation upon the pale white of the road. It glided noiselessly towards the recumbent woman. She became conscious of something touching her hand; it was softness and it was warmth. She opened her eye's, and the substance touched her face. A dog was licking her cheek. He was huge, heavy, and quiet creature, standing darkly against the low horizon, and at least two feet higher than the present position of her eyes. Whether Newfoundland, mastiff, bloodhound, or what not, it was impossible to say. He seemed to be of too strange and mysterious a nature to belong to any variety among those of popular nomenclature. Being thus assignable to no breed, he was the ideal embodiment of canine greatness -- a generalization from what was common to all. Night, in its sad, solemn, and benevolent aspect, apart from its stealthy and cruel side, was personified in this form Darkness endows the small and ordinary ones among mankind with poetical power, and even the suffering woman threw her idea nto figure. In her reclining position she looked up to him just as in earlier times she had, when standing, looked up to a man. The animal, who was as homeless as she, respectfully withdrew a step or two when the woman moved, and, seeing that she did not repulse him, he licked her hand again. A thought moved within her like lightning. "Perhaps I can make use of him-i might do it then!' She pointed in the direction of Casterbridge, and the dog seemed to misunderstand : he trotted on. Then, finding she could not follow, he came back and whined. The ultimate and saddest singularity of woman's effort and invention was reached when, with a quickened breath+ ing, she rose to a stooping posture, and, resting her two little arms

upon the shoulders of the dog, leant firmly thereon, and murmured stimulating words. Whilst she sorrowed in her heart she cheered with her voice, and what was stranger than that the strong should need encouragement from the weak was that cheerfulness should be so well stimulated by such utter dejection. Her friend moved forward slowly, and she with small mincing steps moved forward beside him, half her weight being thrown upon the animal. Sometimes she sank as she had sunk from walking erect, from the crutches, from the rails. The dog, who now thoroughly understood her desire and her incapacity, was frantic in his distress on these occasions ; he would tug at her dress and run forward. She always called him back, and it was now to be observed that the woman listened for human sounds only to avoid them. It was evident that she had an object in keeping her presence on the road and her forlorn state unknown. Their progress was necessarily very slow. They reached the bottom of the town, and the Casterbridge lamps lay before them like fallen Pleiads as they turned to the left into the dense shade of a deserted avenue of chestnuts, and so skirted the borough. Thus the town was passed, and the goal was reached. On this much-desired spot outside the town rose a picturesque building. Originally it had been a mere case to hold people. The shell had been so thin, so devoid of excrescence, and so closely drawn over the accommodation granted, that the grim character of what was beneath showed through it, as the shape of a body is visible under a winding-sheet. Then Nature, as if offended, lent a hand. Masses of ivy grew up, completely covering the walls, till the place looked like an abbey; and it was discovered that the view from the front, over the Casterbridge chimneys, was one of the most magnificent in the county. A neighbouring earl once said that he would give up a year's rental to have at his own door the view enjoyed by the inmates from theirs -- and very probably the inmates would have given up the view for his year's rental. This stone edifice consisted of a central mass and

two wings, whereon stood as sentinels a few slim chimneys, now gurgling sorrowfully to the slow wind. In the wall was a gate, and by the gate a belipull formed of a hanging wire. The woman raised herself as high as possible upon her knees, and could just reach the handle. She moved it and fell forwards in a bowed attitude, her face upon her bosom. It was getting on towards six o'clock, and sounds of movement were to be heard inside the building which was the haven of rest to this wearied soul. A little door by the large one was opened, and a man appeared inside. He discerned the panting heap of clothes, went back for a light, and came again. He entered a second time, and returned with two women. These lifted the prostrate figure and assisted her in through the doorway. The man then closed the door. How did she get here ?" said one of the women. "The Lord knows,' said the other. There is a dog outside," murmured the overcome traveller. " Where is he gone ? He helped me.' I stoned him away,' said the man. The little procession then moved forward -- the man in front bearing the light, the two bony women next, supporting between them the small and supple one. Thus they entered the house and disappeared. SUSPICION

SUSPICION -- FANNY IS SENT FOR BATHSHEBA said very little to her husband all that evening of their return from market, and he was not disposed to say much to her. He exhibited the un+ pleasant combination of a restless condition with a silent tongue. The next day, which was Sunday, passed nearly in the same manner as regarded their taciturnity, Bathsheba going to church both morning and afternoon. This was the day before the Budmouth races. In the evening Troy said, suddenly -- " Bathsheba, could you let me have twenty pounds ?" Her countenance instantly sank. ' Twenty pounds ? she said. 'The fact is, I want it badly.' The anxiety upon Troy's face was unusual and very marked. lt was a culmination of the mood he had been in all the day. "Ah !. for those races to-morrow.' Troy for the moment made no reply. Her mistake had its advantages to a man who shrank from having his mind inspected as he did now. "Well, suppose I do want it for races ?' he said, at last. "O, Frank.!' Bathsheba replied, and there was such a volume of entreaty in the words. "Only such a few weeks ago you said that I was far sweeter than all your other pleasures put together, and that you would give them all up for me; and now, won't you give up this one, which is more a worry than a pleasure? Do, Frank. Come, let me fascinate you by all I can do -- by pretty words and pretty looks, and everything I can think of -- to stay at home. Say yes to your wife -- say yes.!' The tenderest and softest phases of Bathsheba's nature were prominent now -- advanced impulsively for his acceptance, without any of the disguises and defences which the wariness of her character when she was cool too frequently threw

over them. Few men could have resisted the arch yet dignified entreaty of the beautiful face, thrown a little back and sideways in the weli known attitude that expresses more than the words it accompanies, and which seems to have heen designed for these special occasions. Had the woman not been his wife, Troy would have succumbed instantly ; as it was, he thought he would not deceive her longer. "The money is not wanted for racing debts at all,' he said. " What is it for ?' she asked. " You worry me a great deal by these mysterious responsibilities, Frank." Troy hesitated. He did not now love her enough to allow himself to be carried too far by her ways. Yet it was necessary to be civil. "You wrong me by such a suspicious manner, he said. " Such strait-waistcoating as you treat me to is not becoming in you at so early a date.' "I think that I have a right to grumble a little if I pay,' she said, with features between a smile and a pout. Exactly; and, the former being done, suppose we proceed to the latter. Bathsheba, fun is all very well, but don't go too far, or you may have cause to regret something.' She reddened. " I do that already,' she said, quickly " What do you regret ? ' SUSPICION "That my romance has come to an end.' " All romances end at marriage.' 'I wish you wouldn't talk like that. You grieve me to my soul by being smart at my expense.' " You are dull enough at mine. I believe you hate me.' " Not you -- only your faults. I do hate them.' "'Twould be much more becoming if you set your+ self to cure them. Come, let's strike a balance with the twenty pounds, and be friends.' She gave a sigh of resignation. 'I have about that sum here for household expenses. If you must have it, take it.' "Very good. Thank you. I expect I shall have gone away before you are in to breakfast to-morrow.' "And must you go ? Ah !. there was a time, Frank, when it would have taken a good many promises to other people to drag you away from me. You used to call me darling, then.

But it doesn't matter to you how my days are passed now.' "I must go, in spite of sentiment.' Troy, as he spoke, looked at his watch, and, apparently actuated by <1non lucendo>1 principles, opened the case at the back, revealing, snugly stowed within it, a small coil of hair. Bathsheba's eyes had been accidentally lifted at that moment, and she saw the action and saw the hair. She flushed in pain and surprise, and some words escaped her before she had thought whether or not it was wise to utter them. "A woman's curl of hair !' she said. "O, Frank, whose is that ?' Troy had instantly closed his watch. He carelessly replied, as one who cloaked some feelings that the sight had stirred. ' Why, yours, of course. Whose should it be ? I had quite forgotten that I had it.' ' What a dreadful fib, Frank.!' " I tell you I had forgotten it.!' he said, loudly. 'I don't mean that -- it was yellow hair.' "Nonsense.' "That's insulting me. I know it was yellow. Now whose was it ? I want to know.' "Very welii'll tell you, so make no more ado. It is the hair of a young woman I was going to marry before I knew you.' " You ought to tell me her name, then.' "I cannot do that.' "Is she married yet?' "No.' "Is she alive?' " Yes.' "Is she pretty ?' " Yes.' 'It is wonderful how she can be, poor thing, under such an awful affliction!' " Affliction -- what affliction ? ' he inquired, quickly. " Having hair of that dreadful colour.' " Oh -- ho-i like that.!' said Troy, recovering him+ self. "Why, her hair has been admired by everybody who has seen her since she has worn it loose, which has not been long. It is

beautiful hair. People used to turn their heads to look at it, poor girl.!' "Pooh! that's nothing -- that's nothing!' she ex+ claimed, in incipient accents of pique. 'If I cared for your love as much as I used to I could say people had turned to look at mine.' "Bathsheba, don't be so fitful and jealous. You knew what married life would be like, and shouldn't have entered it if you feared these contingencies.' Troy had by this time driven her to bitterness: her heart was big in her throat, and the ducts to her eyes were painfully full. Ashamed as she was to show emotion, at last she burst out: -- "This is all I get for loving you so well! Ah! when I married you your life was dearer to me than my own. I would have died for you -- how truly I can say that I would have died for you.! And now you sneer at my foolishness in marrying you. O! is it kind to me to throw my mistake in my face ? Whatever opinion you may have of my wisdom, you should not tell me of it so mercilessly, now that I am in your power.' " I can't help how things fall out,' said Troy; "upon my heart, women will be the death of me.!' "Well you shouldn't keep people's hair. You'll burn it, won't you, Frank?' Frank went on as if he had not heard her. "There are considerations even before my consideration for you; reparations to be made -- ties you know nothing of If you repent of marrying, so do I.' Trembling now, she put her hand upon his arm, saying, in mingled tones of wretchedness and coaxing, "I only repent it if you don't love me better than any woman in the world.! I don't otherwise, Frank. You don't repent because you already love somebody better than you love me, do you ?' "I don't know. Why do you say that?' "You won't burn that curl. You like the woman who owns that pretty hair -- yes; it is pretty -- more beautiful than my miserable black mane! Well, it is no use; I can't help being ugly. You must like her best, if you will!' "Until to-day, when I took it from a drawer, I have

never looked upon that bit of hair for several months -- that I am ready to swear.' "But just now you said "ties;" and then -- that woman we met?' "'Twas the meeting with her that reminded me of the hair.' "Is it hers, then ?' "Yes. There, now that you have wormed it out of me, I hope you are content.' "And what are the ties ?' "Oh! that meant nothing -- a mere jest.' "A mere jest ! ' she said, in mournful astonishment. "Can you jest when I am so wretchedly in earnest ? Tell me the truth, Frank. I am not a fool, you know, although I am a woman, and have my woman's moments. Come! treat me fairly,' she said, looking honestly and fearlessly into his face. "I don't want much; bare justice -- that's all! Ah! once I felt I could be content with nothing less than the highest homage from the husband I should choose. Now, anything short of cruelty will content me. Yes! the independent and spirited Bathsheba is come to this.!' "For Heaven's sake don't be so desperate! "Troy said, snappishly, rising as he did so, and leaving the room. Directly he had gone, Bathsheba burst into great sobs -- dry-eyed sobs, which cut as they came, without any softening by tears. But she determined to repress all evidences of feeling. She was conquered; but she would never own it as long as she lived. Her pride was indeed brought low by despairing discoveries of her spoliation by marriage with a less pure nature than her own. She chafed to and fro in rebelliousness, like a caged leopard; her whole soul was in arms, and the blood fired her face. Until she had met Troy, Bath+ sheba had heen proud of her position as a woman; it had been a glory to her to know that her lips had been touched hy no man's on earth -- that her waist had never been encircled by a lover's arm. She hated herself now. In those earlier days she had always nourished a secret contempt for girls who were the slaves of the first goodiooking young fellow who should choose to salute them. She had never taken kindly to the idea of

marriage in the abstract as did the majority of women she saw about her. In the turmoil of her anxiety for her lover she had agreed to marry him; but the perception that had accompanied her happiest hours on this account was rather that of self-sacrifice than of promotion and honour. Although she scarcely knew the divinity's name, Diana was the goddess whom Bathsheba instinctively adored. That she had never, by look, word, or sign, encouraged a man to approach her -- that she had felt herself sufficient to herself, and had in the independence of her girlish heart fancied there was a certain degradation in renouncing the simplicity of a maiden existence to become the humbler half of an indifferent matrimonial whole -- were facts now bitterly remembered. O, if she had never stooped to folly of this kind, respectable as it was, and could only stand again, as she had stood on the hill at Norcombe, and dare Troy or any other man to pollute a hair of her head by his interference!. The next morning she rose earlier than usual, and had the horse saddled for her ride round the farm in the customary way. When she came in at half-past eight -- their usual hour for breakfasting -- she was in+ formed that her husband had risen, taken his breakfast, and driven off to Casterbridge with the gig and Poppet. After breakfast she was cool and collected -- quite herself in fact -- and she rambled to the gate, intending to walk to another quarter of the farm, which she still personally superintended as well as her duties in the house would permit, continually, however, finding her+ self preceded in forethought by Gabriel Oak, for whom she began to entertain the genuine friendship of a sister. Of course, she sometimes thought of him in the light of an old lover, and had momentary imaginings of what life with him as a husband would have been like; also of life with Boldwood under the same conditions. But Bathsheba, though she could feel, was not much given to futile dreaming, and her musings under this head were short and entirely confined to the times when Troy's neglect was more than ordinarily evident. She saw coming up the road a man like Mr. Boldwood.

It was Mr. Boldwood. Bathsheba blushed painfully, and watched. The farmer stopped when still a long way off, and held up his hand to Gabriel Oak, who was in a footpath across the field. The two men then approached each other and seemed to engage in earnest conversation. Thus they continued for a long time. Joseph Poor+ grass now passed near them, wheeling a barrow of apples up the hill to Bathsheba's residence. Boldwood and Gabriel called to him, spoke to him for a few minutes, and then all three parted, Joseph immediately coming up the hill with his barrow. Bathsheba, who had seen this pantomime with some surprise, experienced great relief when Boldwood turned back again. 'Well, what's the message, Joseph ? ' she said. He set down his barrow, and, putting upon himself the refined aspect that a conversation with a lady re+ quired, spoke to Bathsheba over the gate. "You'll never see Fanny Robin no more -- use nor principai-ma'am.' " Why ?' "Because she's dead in the Union.' " Fanny dead -- never.!' " Yes, ma'am.' " What did she die from ?" "I don't know for certain; but I should be inclined to think it was from general neshness of constitution. She was such a limber maid that 'a could stand no hardship, even when I knowed her, and 'a went like a candle-snoff, so 'tis said. She was took bad in the morning, and, being quite feeble and worn out, she died in the evening. She belongs by law to our parish; and Mr. Boldwood is going to send a waggon at three this afternoon to fetch her home here and bury her.' "Indeed I shall not let Mr. Boldwood do any such thing-i shall do it! Fanny was my uncle's servant, and, although I only knew her for a couple of days, FANNY IS SENT FOR she belongs to me. How very, very sad this is.! -- the idea of Fanny being in a workhouse.' Bathsheba had begun to know what suffering was, and she spoke with real feeling.... "Send across to Mr. Boldwood's, and say that Mrs. Troy will take upon herself the duty

of fetching an old servant of the family.... We ought not to put her in a waggon; we'll get a hearse.' " There will hardly be time, ma'am, will there?' " Perhaps not,' she said, musingly. " When did you say we must be at the door -- three o'clock?' " Three o'clock this afternoon, ma'am, so to speak it.' "Very weli-you go with it. A pretty waggon is better than an ugly hearse, after all. Joseph, have the new spring waggon with the blue body and red wheels, and wash it very clean. And, Joseph -- -- ' " Yes, ma'am.' ' Carry with you some evergreens and flowers to put upon her coffin -- indeed, gather a great many, and completely bury her in them. Get some boughs of laurustinus, and variegated box, and yew, and boy'siove; ay, and some hunches of chrysanthemum. And let old Pleasant draw her, because she knew him so well.' 'I will, ma'am. I ought to have said that the Union, in the form of four labouring men, will meet me when I gets to our churchyard gate, and take her and bury her according to the rites of the Board of Guardians, as by law ordained.' " Dear me -- Casterbridge Union -- and is Fanny come to this?' said Bathsheba, musing. "I wish I had known of it sooner. I thought she was far away. How long has she lived there?' "On'y been there a day or two.' "Oh.! -- then she has not been staying there as a regular inmate?' " No. She first went to live in a garrison-town t'other side o' Wessex, and since then she's been picking up a living at seampstering in Melchester for several months, at the house of a very respectable widow-woman who takes in work of that sort. She only got handy the Union-house on Sunday morning 'a b'lieve, and 'tis sup+ posed here and there that she had traipsed every step of the way from Melchester. Why she left her place, I can't say, for I don't know; and as to a lie, why, I wouldn't tell it. That's the short of the story, ma'am.' "Ah-h .! '

No gem ever flashed from a rosy ray to a white one more rapidly than changed the young wife's counten+ ance whilst this word came from her in a long-drawn breath. "Did she walk along our turnpike-road?' she said, in a suddenly restless and eager voice. "I believe she did.... Ma'am, shall I call Liddy? You bain't well, ma'am, surely ? You look like a lily -- so pale and fainty.!' "No; don't call her; it is nothing. When did she pass Weatherbury?' "Last Saturday night.' "That will do, Joseph; now you may go.' " Certainly, ma'am.' " Joseph, come hither a moment. What was the colour of Fanny Robin's hair?' "Really, mistress, now that 'tis put to me so judge+ and-jury like, I can't call to mind, if ye'll believe me.!' "Never mind; go on and do what I told you. Stop -- well no, go on.' She turned herself away from him, that he might no longer notice the mood which had set its sign so visibly upon her, and went indoors with a distress:ng sense of faintness and a beating brow. About an hour after, she heard the noise of the waggon and went out, still with a painful consciousness of her bewildered and troubled look. Joseph, dressed in his best suit of clothes, was putting in the horse to start. The shrubs and flowers were all piled in the waggon, as she had directed Bathsheba hardly saw them now. " Whose sweetheart did you say, Joseph?' 'I don't know, ma'am.' "Are you quite sure?' " Yes, ma'am, quite sure.' "Sure of what?' "I'm sure that all I know is that she arrived in the morning and died in the evening without further parley. What Oak and Mr. Boldwood told me was only these few words. "Little Fanny Robin is dead, Joseph,' Gabriel said, looking in my face in his steady old way. I was very sorry, and I said, "Ah!. -- and how did she

come to die?' "Well, she's dead in Casterhridge Union," he said; "and perhaps 'tisn't much matter about how she came to die. She reached the Union early Sunday morning, and died in the afternoon -- that's clear enough." Then I asked what she'd been doing lately, and Mr. Boldwood turned round to me then, and left off spitting a thistle with the end of his stick. He told me about her having lived by seampstering in Melchester, as I mentioned to you, and that she walked therefrom at the end of last week, passing near here Saturday night in the dusk. They then said I had better just name a hent of her death to you, and away they went. Her death might have been brought on by biding in the night wind, you know, ma'am; for people used to say she'd go off in a decline: she used to cough a good deal in winter time. However, 'tisn't much odds to us about that now, for 'tis all over.' "Have you heard a different story at all?' She looked at him so intently that Joseph's eyes quailed. "Not a word, mistress, I assure 'ee.!" he said. "Hardly anybody in the parish knows the news yet.' "I wonder why Gabriel didn't bring the message to me himself. He mostly makes a point of seeing me upon the most trifling errand.' These words were merely murmured, and she was looking upon the ground. "Perhaps he was busy, ma'am,' Joseph suggested. "And sometimes he seems to suffer from things upon his mind, connected with the time when he was better off than 'a is now. 'A's rather a curious item, but a very understanding shepherd, and learned in books.' 'Did anything seem upon his mind whilst he was speaking to you about this?' 'I cannot but say that there did, ma'am. He was terrible down, and so was Farmer Boldwood.' 'Thank you, Joseph. That will do. Go on now, or you'll be late.' Bathsheba, still unhappy, went indoors again. In the course of the afternoon she said to Liddy, Who had been informed of the occurrence, " What was the colour

of poor Fanny Robin's hair? Do you know? I cannot recollect-i only saw her for a day or two.' "It was light, ma'am; but she wore it rather short, and packed away under her cap, so that you would hardly notice it. But I have seen her let it down when she was going to bed, and it looked beautiful then. Real golden hair.' " Her young man was a soldier, was he not?' "Yes. In the same regiment as Mr. Troy. He says he knew him very well.' " What, Mr. Troy says so? How came he to say that?' "One day I just named it to him, and asked him if he knew Fanny's young man. He said, "O yes, he knew the young man as well as he knew himself, and that there wasn't a man in the regiment he liked better."' "Ah! Said that, did he ?' "Yes; and he said there was a strong likeness be+ tween himself and the other young man, so that some+ times people mistook them -- -- ' ' Liddy, for Heaven's sake stop your talking.!' said Bathsheba, with the nervous petulance that comes from worrying perceptions. JOSEPH AND HIS BURDEN

JOSEPH AND HIS BURDEN -- BUCK'S HEAD A WALL bounded the site of Casterbridge Union+ house, except along a portion of the end. Here a high gable stood prominent, and it was covered like the front with a mat of ivy. In this gable was no window, chimney, ornament, or protuberance of any kind. The single feature appertaining to it, beyond the expanse of dark green leaves, was a small door. The situation of the door was peculiar. The sill was three or four feet above the ground, and for a moment one was at a loss for an explanation of this exceptional altitude, till ruts immediately beneath sug+ gested that the door was used solely for the passage of articles and persons to and from the level of a vehicle standing on the outside. Upon the whole, the door seemed to advertise itself as a species of Traitor's Gate translated to another sphere. That entry and exit hereby was only at rare intervals became apparent on noting that tufts of grass were allowed to flourish undis+ turbed in the chinks of the sill. As the clock over the South-street Alms-house pointed to five minutes to three, a blue spring waggon, picked out with red, and containing boughs and flowers, passed the end of the street, and up towards this side of the building. Whilst the chimes were yet stammering out a shattered form of "Malbrook,' Joseph Poorgrass rang the bell, and received directions to back his waggon against the high door under the gable. The door then opened, and a plain elm coffin was slowly thrust forth, and laid by two men in fustian along the middle of the vehicle. One of the men then stepped up beside it, took from his pocket a lump of chalk, and wrote upon the cover the name and a few other words in a large scrawling hand. (We believe that they do these things more tenderly now, and provide a

plate.) He covered the whole with a black cloth, threadbare, but decent, the taiiboard of the waggon was returned to its place, one of the men handed a certificate of registry to Poorgrass, and both entered the door, closing it hehind them. Their connection with her, short as it had been, was over for ever. Joseph then placed the flowers as enjoined, and the evergreens around the flowers, till it was difficult to divine what the waggon contained; he smacked his whip, and the rather pleasing funeral car crept down the hill, and along the road to Weatherbury. The afternoon drew on apace, and, looking to the right towards the sea as he walked beside the horse, Poor+ grass saw strange clouds and scrolls of mist rolling over the long ridges which girt the landscape in that quarter. They came in yet greater volumes, and indolently crept across the intervening valleys, and around the withered papery flags of the moor and river brinks. Then their dank spongy forms closed in upon the sky. It was a sudden overgrowth of atmospheric fungi which had their roots in the neighbouring sea, and by the time that horse, man, and corpse entered Yalbury Great Wood, these silent workings of an invisible hand had reached them, and they were completely enveloped, this being the first arrival of the autumn fogs, and the first fog of the series. The air was as an eye suddenly struck blind. The waggon and its load rolled no longer on the horizontal division between clearness and opacity, but were imbedded in an elastic body of a monotonous pallor throughout. There was no perceptible motion in the air, not a visible drop of water fell upon a leaf of the beeches, birches, and firs composing the wood on either side. The trees stood in an attitude of intentness, as if they waited longingly for a wind to come and rock them. A startling quiet overhung all surrounding things -- so completely, that the crunching of the waggon+ wheels was as a great noise, and small rustles, which had never ohtained a hearing except by night, were dis+ tinctly individualized. Joseph Poorgrass looked round upon his sad burden as it loomed faintly through the flowering laurustinus, then at the

unfathomable gloom amid the high trees on each hand, indistinct, shadowless, and spectreiike in their monochrome of grey. He felt anything but cheer+ ful, and wished he had the company even of a child or dog. Stopping the home, he listened. Not a footstep or wheel was audible anywhere around, and the dead silence was broken only by a heavy particle falling from a tree through the evergreens and alighting with a smart rap upon the coffin of poor Fanny. The fog had by this time saturated the trees, and this was the first dropping of water from the overbrimming leaves. The hollow echo of its fall reminded the waggoner painfully of the grim Leveller. Then hard by came down another drop, then two or three. Presently there was a continual tapping of these heavy drops upon the dead leaves, the road, and the travellers. The nearer boughs were beadcd with the mist to the greyness of aged men, and the rusty+ red leaves of the beeches were hung with similar drops, like diamonds on auburn hair. At the roadside hamlet called Roy-Town, just beyond this wood, was the old inn Buck's Head. It was about a mile and a half from Weatherbury, and in the meridian times of stage-coach travelling had been the place where many coaches changed and kept their relays of horses. All the old stabling was now pulled down, and little remained besides the habitable inn itself, which, standing a little way back from the road, sig+ nified its existence to people far up and down the highway by a sign hanging from the horizontal bough of an elm on the opposite side of the way. Travellers -- for the variety <1tourist>1 had hardly developed into a distinct species at this date -- some+ times said in passing, when they cast their eyes up to the sign-bearing tree, that artists were fond of repre+ senting the signboard hanging thus, but that they themselves had never before noticed so perfect an instance in actual working order. It was near this tree that the waggon was standing into which Gabriel Oak crept on his first journey to Weatherbury; but, owing to the darkness, the sign and the inn had been un+ observed. The manners of the inn were of the old-established

type. Indeed, in the minds of its frequenters they existed as unalterable formule : <1e.g.>1 -- Rap with the bottom of your pint for more liquor. For tobacco, shout. In calling for the girl in waiting, say, "Maid.!' Ditto for the landlady, 'Old Soul.!' etc., etc. It was a relief to Joseph's heart when the friendly signboard came in view, and, stopping his horse immediately beneath it, he proceeded to fulfil an intention made a long time before. His spirits were oozing out of him quite. He turned the horse's head to the green bank, and entered the hostel for a mug of ale. Going down into the kitchen of the inn, the floor of which was a step below the passage, which in its BUCK'S HEAD turn was a step below the road outside, what should Joseph see to gladden his eyes but two copper-coloured discs, in the form of the countenances of Mr. Jan Coggan and Mr. Mark Clark. These owners of the two most appreciative throats in the neighbourhood, within the pale of respectability, were now sitting face to face over a threeiegged circular table, having an iron rim to keep cups and pots from being accidentally elbowed off; they might have been said to resemble the setting sun and the full moon shining <1vis-a*-vis>1 across the globe. " Why, 'tis neighbour Poorgrass.!' said Mark Clark. "I'm sure your face don't praise your mistress's table, Joseph.' "I've had a very pale companion for the last four miles,' said Joseph, indulging in a shudder toned down by resignation. 'And to speak the truth, 'twas beginning to tell upon me. I assure ye, I ha'n't seed the colour of victuals or drink since breakfast time this morning, and that was no more than a dew-bit afield.' "Then drink, Joseph, and don't restrain yourself!.' said Coggan, handing him a hooped mug three+ quarters full. Joseph drank for a moderately long time, then for a longer time, saying, as he lowered the jug, "'Tis pretty drinking -- very

pretty drinking, and is more than cheerful on my melancholy errand, so to speak it.' "True, drink is a pleasant delight,' said Jan, as one who repeated a truism so familiar to his brain that he hardly noticed its passage over his tongue ; and, lifting the cup, Coggan tilted his head gradually backwards, with closed eyes, that his expectant soul might not be diverted for one instant from its bliss by irrelevant surroundings. "Well, I must be on again,' said Poorgmss. "Not but that I should like another nip with ye; but the parish might lose confidence in me if I was seed here.' " Where be ye trading o't to to-day, then, Joseph ?' "Back to Weatherbury. I've got poor little Fanny Robin in my waggon outside, and I must be at the churchyard gates at a quarter to five with her.' 'Ay-i've heard of it. And so she's nailed up in parish boards after all, and nobody to pay the bell shilling and the grave half-crown.' "The parish pays the grave half-crown, but not the bell shilling, because the bell's a luxery: but 'a can hardly do without the grave, poor body. However, I expect our mistress will pay all.' "A pretty maid as ever I see.! But what's yer hurry, Joseph ? The pore woman's dead, and you can't bring her to life, and you may as well sit down comfortable, and finish another with us.' "I don't mind taking just the least thimbleful ye can dream of more with ye, sonnies. But only a few minutes, because 'tis as 'tis.' "Of course, you'll have another drop. A man's twice the man afterwards. You feel so warm and glorious, and you whop and slap at your work without any trouble, and everything goes on like sticks a+ breaking. Too much liquor is bad, and leads us to that horned man in the smoky house ; but after all, many people haven't the gift of enjoying a wet, and since we be highly favoured with a power that way, we should make the most o't.' "True,' said Mark Clark. "'Tis a talent the Lord

has mercifully bestowed upon us, and we ought not to neglect it. But, what with the parsons and clerks and schooipeople and serious tea-parties, the merry old ways of good life have gone to the dogs -- upon my carcase, they have.!' " Well, really, I must be onward again now,' said Joseph. 'Now, now, Joseph; nonsense.! The poor woman is dead, isn't she, and what's your hurry?' "Well, I hope Providence won't be in a way with me for my doings,' said Joseph, again sitting down. 'I've been troubled with weak moments lately, 'tis true. I've been drinky once this month already, and I did not go to church a-Sunday, and I dropped a curse or two yesterday; so I don't want to go too far for my safety. Your next world is your next world, and not to be squandered offhand.' 'I believe ye to be a chapeimember, Joseph. That I do.' 'Oh, no, no.! I don't go so far as that.' " For my part,' said Coggan, "I'm staunch Church of England.' " Ay, and faith, so be I,' said Mark Clark. "I won't say much for myself; I don't wish to,' Coggan continued, with that tendency to talk on principles which is characteristic of the barley-corn. "But I've never changed a single doctrine : I've stuck like a plaster to the old faith I was born in. Yes; there's this to be said for the Church, a man can belong to the Church and bide in his cheerful old inn, and never trouble or worry his mind about doctrines at all. But to be a meetinger, you must go to chapel in all winds and weathers, and make yerself as frantic as a skit. Not but that chapei members be clever chaps enough in their way. They can lift up beautiful prayers out of their own heads, all about their families and shipwmcks in the newspaper.' "They can -- they can,' said Mark Clark, with cor+ roborative feeling ; "but we Churchmen, you see, must have it all printed aforehand, or, dang it all, we should no more know what to say to a great gaffer like the Lord than babes unborn,' " Chapeifolk be more hand-in-glove with them above than we,' said Joseph, thoughtfully. " Yes,' said Coggan. " We know very well that if anybody do go to heaven, they will. They've worked hard for it, and they

deserve to have it, such as 'tis. I bain't such a fool as to pretend that we who stick to the Church have the same chance as they, because we know we have not. But I hate a feller who'll change his old ancient doctrines for the sake of getting to heaven. I'd as soon turn king's-evidence for the few pounds you get. Why, neighbours, when every one of my taties were frosted, our Parson Thirdly were the man who gave me a sack for seed, though he hardly had one for his own use, and no money to buy 'em. If it hadn't been for him, I shouldn't hae had a tatie to put in my garden. D'ye think I'd turn after that? No, I'll stick to my side; and if we be in the wrong, so be it : I'll fall with the fallen .! ' " Well said -- very well said,' observed Joseph. -- " However, folks, I must be moving now: upon my life I must. Pa'son Thirdly will be waiting at the church gates, and there's the woman a-biding outside in the waggon.' " Joseph Poorgmss, don't be so miserable.! Pa'son Thirdly won't mind. He's a generous man ; he's found me in tracts for years, and I've consumed a good many in the course of a long and shady life; but he's never been the man to cry out at the expense. Sit down.' The longer Joseph Poorgrass remained, the less his spirit was troubled by the duties which devolved upon him this afternoon. The minutes glided by uncounted, until the evening shades began perceptibly to deepen, and the eyes of the three were but sparkling points on the surface of darkness. Coggan's repeater struck six from his pocket in the usual still small tones. At that moment hasty steps were heard in the entry, and the door opened to admit the figure of Gabriel Oak, followed by the maid of the inn bearing a candle. He stared sternly at the one lengthy and two round faces of the sitters, which confronted him with the expressions of a fiddle and a couple of warming-pans. Joseph Poor+ grass blinked, and shrank several inches into the back+ ground. ' Upon my soul, I'm ashamed of you ; 'tis disgraceful, Joseph, disgraceful!. " said Gabriel, indignantly. " Coggan, you call yourself a man, and don't know better than this.'

Coggan looked up indefinitely at Oak, one or other of his eyes occasionally opening and closing of its own accord, as if it were not a member, but a dozy individual with a distinct personality. " Don't take on so, shepherd!' said Mark Clark, looking reproachfully at the candle, which appeared to possess special features of interest for his eyes. 'Nobody can hurt a dead woman,' at length said Coggan, with the precision of a machine. "All that could be done for her is done -- she's beyond us : and why should a man put himself in a tearing hurry for lifeless clay that can neither feel nor see, and don't know what you do with her at all? If she'd been alive, I would have been the first to help her. If she now wanted victuals and drink, I'd pay for it, money down. But she's dead, and no speed of ours will bring her to life. The woman's past us -- time spent upon her is throwed away: why should we hurry to do what's not required ? Drink, shepherd, and be friends, for to-morrow we may be like her.' " We may,' added Mark Clark, emphatically, at once drinking himself, to run no further risk of losing his chance by the event alluded to, Jan meanwhile merging his additional thoughts of to-morrow in a song : -- To-mor-row, to-mor-row ! And while peace and plen-ty I find at my board, With a heart free from sick-ness and sor-row, With my friends will I share what to-day may af-ford, And let them spread the ta-ble to-mor-row. To-mor -- row', to-mor -- + "Do hold thy horning, Jan.!' said Oak; and turning upon Poorgrass, " as for you, Joseph, who do your wicked deeds in such confoundedly holy ways, you are as drunk as you can stand.' "No, Shepherd Oak, no! Listen to reason, shepherd. All that's the matter with me is the affliction called a multiplying eye, and that's how it is I look double to you-i mean, you look double to me.' A multiplying eye is a very bad thing,' said Mark Clark.

It always comes on when I have been in a public -- house a little time,' said Joseph Poorgrass, meekly. "Yes; I see two of every sort, as if I were some holy man living in the times of King Noah and entering into the ark.... Y-y-y-yes,' he added, becoming much affected by the picture of himself as a person thrown away, and shedding tears; "I feel too good for England : I ought to have lived in Genesis by rights, like the other men of sacrifice, and then I shouldn't have b-b-been called a d-d-drunkard in such a way.!' "I wish you'd show yourself a man of spirit, and not sit whining there.!' "Show myself a man of spirit ? ... Ah, well! let me take the name of drunkard humbly-iet me be a man of contrite knees-iet it be .! l know that I always do say "Please God' afore I do anything, from my getting up to my going down of the same, and I be willing to take as much disgrace as there is in that holy act. Hah, yes.! ... But not a man of spirit ? Have I ever allowed the toe of pride to be lifted against my hinder parts without groaning manfully that I question the right to do so? I inquire that query boldly?' " We can't say that you have, Hero Poorgrass,' admitted Jan. "Never have I allowed such treatment to pass un+ questioned!. Yet the shepherd says in the face of that rich testimony that I be not a man of spirit! Well, let it pass by, and death is a kind friend !.' Gabriel, seeing that neither of the three was in a fit state to Cake charge of the waggon for the remainder of the journey, made no reply, but, closing the door again upon them, went across to where the vehicle stood, now getting indistinct in the fog and gloom of this mildewy time. He pulled the horse's head from the large patch of turf it had eaten bare, readjusted the boughs over the coffin, and drove along through the unwholesome night. It had gradually become rumoured in the village that the body to be brought and buried that day was all that was left of the unfortunate Fanny Robin who had followed the Eleventh from Casterbridge through Melchester and onwards. But,

thanks to Boldwood's reticence and Oak's generosity, the lover she had followed had never been individualized as Troy. Gabriel hoped that the whole truth of the matter might not be published till at any rate the girl had been in her grave for a few days, when the interposing barriers of earth and time, and a sense that the events had been somewhat shut into oblivion, would deaden the sting that revelation and invidious remark would have for Bathsheba just now. By the time that Gabriel reached the old manor+ house, her residence, which lay in his way to the church, it was quite dark. A man came from the gate and said through the fog, which hung between them like blown flour -- "Is that Poorgrass with the corpse?' Gabriel recognized the voice as that of the parson. " The corpse is here, sir,' said Gabriel. "I have just been to inquire of Mrs. Troy if she could tell me the reason of the delay. I am afraid it is too late now for the funeral to be performed with proper decency. Have you the registrar's certificate ? ' " No,' said Gabriel. "I expect Poorgrass has that ; and he's at the Buck's Head. I forgot to ask him for it.' "Then that settles the matter. We'll put off the funeral till to-morrow morning. The body may be brought on to the church, or it may be left here at the farm and fetched by the bearers in the morning. They waited more than an hour, and have now gone home.' Gabriel had his reasons for thinking the latter a most objectionable plan, notwithstanding that Fanny had been an inmate of the farm-house for several years in the lifetime of Bathsheba's uncle. Visions of several unhappy contingencies which might arise from this delay flitted before him. But his will was not law, and he went indoors to inquire of his mistress what were her wishes on the subject. He found her in an unusual mood : her eyes as she looked up to him were suspicious and perplexed as with some antecedent thought. Troy had not yet returned. At first Bathsheba assented with a mien of indifference to his proposition that they should go on to the church at once with their burden; but immediately

afterwards, following Gabriel to the gate, she swerved to the extreme of solicitousness on Fanny's account, and desired that the girl might be brought into the house. Oak argued upon the convenience of leaving her in the waggon, just as she lay now, with her flowers and green leaves about her, merely wheeling the vehicle into the coach-house till the morning, but to no purpose, "It is unkind and unchristian,' she said, 'to leave the poor thing in a coach-house all night.' Very well, then,' said the parson. "And I will arrange that the funeral shall take place early to+ morrow. Perhaps Mrs. Troy is right in feeling that we cannot treat a dead fellow-creature too thoughtfully We must remember that though she may have erred grievously in leaving her home, she is still our sister : and it is to be believed that God's uncovenanted mercies are extended towards her, and that she is a member of the flock of Christ.' The parson's words spread into the heavy air with a sad yet unperturbed cadence, and Gabriel shed an honest tear. Bathsheba seemed unmoved. Mr. Thirdly then left them, and Gabriel lighted a lantern. Fetching three other men to assist him, they bore the unconscious truant indoors, placing the coffin on two benches in the middle of a little sitting-room next the hall, as Bathsheba directed. Every one except Gabriel Oak then left the room. He still indecisively lingered beside the body. He was deeply troubled at the wretchedly ironical aspect that circumstances were putting on with regard to Troy's wife, and at his own powerlessness to counteract them, (n spite of his careful manoeuvring all this day, the very worst event that could in any way have happened in connection with the burial had happened now. Oak imagined a terrible discovery resulting from this after+ noon's work that might cast over Bathsheba's life a shade which the interposition of many lapsing years might but indifferently lighten, and which nothing at all might altogether remove. Suddenly, as in a last attempt to save Bathsheba from, at any rate, immediate anguish, he looked again, as he had looked before, at the chalk writing upon the

coffinlid. The scrawl was this simple one, " Fanny Robin and child.' Gabriel took his handkerchief and carefully rubbed out the two latter words, leaving visible the inscription " Fanny' Robin ' only. He then left the room, and went out quietly by the front door.

FANNY'S REVENGE ! DO you want me any longer ma'am ? " inquired Liddy, at a later hour the same evening, standing by the door with a chamber candlestick in her hand and addressing Bathsheba, who sat cheerless and alone in the large parlour beside the first fire of the season. " No more to-night, Liddy.' "l'll sit up for master if you like, ma'am. I am not at all afraid of Fanny, if I may sit in my own room and ' have a candle. She was such a childlike, nesh young thing that her spirit couldn't appear to anybody if it tried, I'm quite sure.' "O no, no! You go to bed. I'll sit up for him myself till twelve o'clock, and if he has not arrived by that time, I shall give him up and go to bed too.' It is half-past ten now.' 'Oh! is it?' Why don't you sit upstairs, ma'am ? ' " Why don't I ? ' said Bathsheba, desultorily. 'It isn t worth while -- there's a fire here, Liddy.' She suddenly exclaimed in an impulsive and excited whisper, Have you heard anything strange said of Fanny?' The words had no sooner escaped her than an expres+ sion of unutterable regret crossed her face, and she burst into tears. "No -- not a word !' said Liddy, looking at the weeping woman with astonishment. 'What is it makes you cry so, ma'am; has anything hurt you ? ' She came to Bathsheba's side with a face full of sympathy. " No, Liddy-i don't want you any more. I can hardly say why I have taken to crying lately: I never used to cry. Good-night.' Liddy then left the parlour and closed the door.

Bathsheba was lonely and miserable now ; not lone+ lier actually than she had heen before her marriage; but her loneliness then was to that of the present time as the solitude of a mountain is to the solitude of a cave. And within the last day or two had come these disquieting thoughts about her husband's past. Her wayward sentiment that evening concerning Fanny's temporary resting-place had been the result of a strange complication of impulses in Bathsheba's bosom. Per+ haps it would be more accurately described as a determined rebellion against her prejudices, a revulsion from a lower instinct of uncharitableness, which would have withheld all sympathy from the dead woman, be+ cause in life she had preceded Bathsheba in the atten+ tions of a man whom Bathsheba had by no means ceased from loving, though her love was sick to death just now with the gravity of a further misgiving. In five or ten minutes there was another tap at the door. Liddy reappeared, and coming in a little way stood hesitating, until at length she said, !Maryann has just heard something very strange, but I know it isn't true. And we shall be sure to know the rights of it in a day or two.' "What is it ?' " Oh, nothing connected with you or us, ma'am. It is about Fanny. That same thing you have heard.' "I have heard nothing.' "I mean that a wicked story is got to Weatherbury within this last hour -- that -- -- ' Liddy came close to her mistress and whispered the remainder of the sentence slowly into her ear, inclining her head as she spoke in the direction of the room where Fanny lay. Bathsheba trembled from head to foot. "I don't believe it ! ' she said, excitedly. 'And there's only one name written on the coffin-cover.' "Nor I, ma'am. And a good many others don't; for we should surely have been told more about it if it had been true -- don't you think so, ma'am ? ' "We might or we might not.' Bathsheba turned and looked into the fire, that Liddy might not see her

face. Finding that her mistress was going to say no more, Liddy glided out, closed the door softly, and went to bed. Bathsheba's face, as she continued looking into the fire that evening, might have excited solicitousness on her account even among those who loved her least. The sadness of Fanny Robin's fate did not make Bath+ sheba's glorious, although she was the Esther to this poor Vashti, and their fates might be supposed to stand in some respects as contrasts to each other. When Liddy came into the room a second time the beautiful eyes which met hers had worn a listless, weary look+ When she went out after telling the story they had ex+ pressed wretchedness in full activity. Her simple country nature, fed on old-fashioned principles, was troubled by that which would have troubled a woman of the world very little, both Fanny and her child, if she had one, being dead. Bathsheba had grounds for conjecturing a connection between her own history and the dimly suspected tragedy of Fanny's end which Oak and Boldwood never for a moment credited her with possessing. The meeting with the lonely woman on the previous Saturday night had been unwitnessed and unspoken of. Oak may have had the best of intentions in withholding for as many days as possible the details of what had happened to Fanny ; but had he known that Bathsheba's perceptions had already been exercised in the matter, he would have done nothing to lengthen the minutes of suspense she was now undergoing, when the certainty which must terminate it would be the worst fact suspected after all. She suddenly felt a longing desire to speak to some one stronger than herself, and so get strength to sustain her surmised position with dignity and her carking doubts with stoicism. Where could she find such a friend? nowhere in the house. She was by far the coolest of the women under her roof. Patience and suspension of judgement for a few hours were what she wanted to learn, and there was nobody to teach her. Might she but go to Gabriel Oak ! -- but that could not be. What a way Oak had, she thought, of enduring things. Boldwood, who seemed so much deeper and higher and stronger in

feeling than Gabriel, had not yet learnt, any more than she herself, the simple lesson which Oak showed a mastery of by every turn and look he gave -- that among the multitude of interests by which he was surrounded, those which affected his personal welibeing were not the most absorbing and important in his eyes. Oak meditatively looked upon the horizon of circumstances without any special regard to his own standpoint in the midst. That was how she would wish to be. But then Oak was not racked by incertitude upon the inmost matter of his bosom, as she was at this moment. Oak knew all about Fanny that he wished to know -- she felt convinced of that. If she were to go to him now at once and say no more than these few words, !What is the truth of the story?' he would feel bound in honour to tell her. It would be an inexpressible relief. No further speech would need to be uttered. He knew her so well that no eccentricity of behaviour in her would alarm him. She flung a cloak roundher, went to the door and opened it. Every blade, every twig was still. The air was yet thick with moisture, though somewhat less dense than during the afternoon, and a steady smack of drops upon the fallen leaves under the boughs was almost musical in its soothing regularity. lt seemed better to be out of the house than within it, and Bathsheba closed the door, and walked slowly down the lane till she came opposite to Gabriel's cottage, where he now lived alone, having left Coggan's house through being pinched for room. There was a light in one window only', and that was downstairs. The shutters were not closed, nor was any blind or curtain drawn over the window, neither robbery nor observation being a contingency which could do much injury to the occupant of the domicile. Yes, it was Gabriel himself who was sitting up : he was reading, From her standing-place in the road she could see him plainly, sitting quite still, his light curly head upon his hand, and only occasionally looking up to snuff the candle which stood beside him. At length he looked at the clock, seemed surprised at the lateness of the hour, closed his book, and arose. He was going to bed, she knew, and if she tapped it must be done at once.

Alas for her resolve ! She felt she could not do it, Not for worlds now could she give a hint about her misery to him, much less ask him plainly for information on the cause of Fanny's death. She must suspect, and guess, and chafe, and bear it all alone. Like a homeless wanderer she lingered by the bank, as if lulled and fascinated by the atmosphere of content which seemed to spread from that little dwelling, and was so sadly lacking in her own. Gabriel appeared in an upper room, placed his light in the window-bench, and then -- knelt down to pray. The contrast of the picture with her rebellious and agitated existence at this same time was too much for her to bear to look upon longer. It was not for her to make a truce with trouble by any such means. She must tread her giddy distracting measure to its last note, as she had begun it. With a swollen heart she went again up the lane, and entered her own door. More fevered now by a reaction from the first feelings which Oak's example had raised in her, she paused in the hall, looking at the door of the room wherein Fanny lay. She locked her fingers, threw back her head, and strained her hot hands rigidly across her forehead, saying, with a hysterical sob, 'Would to God you would speak and tell me your secret, Fanny .! . , . O, I hope, hope it is not true that there are two of you ! ... If I could only look in upon you for one little minute, I should know all !. ' A few moments passed, and she added, slowly, 'And I will' Bathsheba in after times could never gauge the mood which carried her through the actions following this murmured resolution on this memorable evening of her life. She went to the lumber-closet for a screw-driver. At the end of a short though undefined time she found herself in the small room, quivering with emotion, a mist before her eyes, and an excruciating pulsation in her brain, standing beside the uncovered coffin of the girl whose conjectured end had so entirely engrossed her, and saying to herself in a husky voice as she gazed within -- 'It was best to know the worst, and I know it now.!'

She was conscious of having brought about this situation by a series of actions done as by one in an extravagant dream ; of following that idea as to method, which had burst upon her in the hall with glaring obviousness, by gliding to the top of the stairs, assuring herself by listening to the heavy breathing of her maids that they were asleep, gliding down again, turning the handle of the door within which the young girl lay, and deliberately setting herself to do what, if she had antici+ pated any such undertaking at night and alone, would have horrified her, but which, when done, was not so dreadful as was the conclusive proof of her husband's conduct which came with knowing beyond doubt the last chapter of Fanny's story. Bathsheba's head sank upon her bosom, and the breath which had been bated in suspense, curiosity, and interest, was exhaled now in the form of a whispered wail: 'Oh-h-h!' she said, and the silent room added length to her moan. Her tears fell fast beside the unconscious pair in the coffin: tears of a complicated origin, of a nature inde+ scribable, almost indefinable except as other than those of simple sorrow. Assuredly their wonted fires must have lived in Fanny's ashes when events were so shaped as to chariot her hither in this natural, unobtrusive, yet effectual manner. The one feat alone -- that of dying -- by which a mean condition couId be resolved into a grand one, Fanny had achieved. And to that had destiny subjoined this rencounter to-night, which had, in Bathsheba's wild imagining, turned her companion's failure to success, her humiliation to triumph, her luck lessness to ascendency; et had thrown over herself a garish light of mockery, and set upon all things about her an ironical smile. Fanny's face was framed in by that yeIIow hair of hers; and there was no longer much room for doubt as to the origin of the curl owned by Troy. In Bath+ sheba's heated fancy the innocent white countenance expressed a dim triumphant consciousness of the pain she was retaliating for her pain with all the merciless rigour of the Mosaic law: 'Burning for burning; wound for wound: strife for strife. Bathsheba indulged in contempIations of escape from her position by immediate death, which thought she,

though it was an inconvenient and awful way, had limits to its inconvenience and awfulness that could not be overpassed ; whilst the shames of life were measureless. Yet even this scheme of extinction by death was out FANNY'S REVENGE tamely copying her rival's method without the reasons which had glorified it in her rival's case. She glided rapidly up and down the room, as was mostly her habit hen excited, her hands hanging clasped in front of her, as she thought and in part expressed in brocken words : O, I hate her, yet I don't mean that I hate her, for it is grievous and wicked; and yet I hate her a little ! yes, my flesh insists upon hating her, whether my spirit is willing or no !.... If she had only lived, I could ave been angry and cruel towards her with some justifi+ cation ; but to be vindictive towards a poor dead woman recoils upon myself. O God, have mercy,! I am miserable at all this !. ' Bathsheba became at this moment so terrified at her own state of mind that she looked around for some sort of refuge from herself. The vision of Oak kneeling down that night recurred to her, and with the imitative instinct which animates women she seized upon the idea, resolved to kneel, and, if possible, pray. Gabriel had prayed ; so would she. She knelt beside the coffin, covered her face with her hands, and for a time the room was silent as a tomb. whether from a purely mechanical, or from any other cause, when Bathsheba arose it was with a quieted spirit, and a regret for the antagonistic instincts which had seized upon her just before. In her desire to make atonement she took flowers from a vase by the window, and began laying them around the dead girl's head. Bathsheba knew no other way of showing kindness to persons departed than by giving them flowers. She knew not how long she remained engaged thus. She forgot time, life, where she was, what she was doing. A slamming together of the coach-house doors in the yard brought her to her+ self again. An instant after, the front door opened and closed, steps crossed the hall, and her husband appeared at the entrance to the room, looking in upon her. He beheld it all by degrees, stared in stupefaction at the scene, as if he thought it an illusion raised by some fiendish

incantation. Bathsheba, pallid as a corpse on end, gazed back at him in the same wild way. So little are instinctive guesses the fruit of a legitimate induction, that at this moment, as he stood with the door in his hand, Troy never once thought of Fanny in connection with what he saw. His first confused idea was that somebody in the house had died. 'Weli-what ? ' said Troy, blankly. 'I must go ! I must go ! ' said Bathsheba, to herself more than to him. She came with a dilated eye towards the door, to push past him. ' What's the matter, in God's name ? who's dead ?' said Troy. 'I cannot say; let me go out. I want air.! ' she continued. 'But no; stay, I insist ! ' He seized her hand, and then volition seemed to leave her, and she went off into a state of passivity. He, still holding her, came up the room, and thus, hand in hand, Troy and Bathsheba approached the coffin's side. The candle was standing on a bureau close by them, and the light slanted down, distinctly enkindling the cold features of both mother and babe. Troy looked in, dropped his wife's hand, knowledge of it all came over him in a lurid sheen, and he stood still. So still he remained that he could be imagined to have left in him no motive power whatever. The clashes of feeling in all directions confounded one another, produced a neutrality, and there was motion in none. 'Do you know her?' said Bathsheba, in a small enclosed echo, as from the interior of a cell. 'I do,' said Troy. 'Is it she?' 'It is.' He had originally stood perfectly erect. And now, in the welinigh congealed immobility of his frame could be discerned an incipient movement, as in the darkest night may be discerned light after a while. He was gradually sinking forwards. The lines of his features softened, and dismay modulated to illiimitable sadness. Bathsheba was regarding him from the other side, still with parted lips and distracted eyes.

Capacity for intense feeling is proportionate to the general intensity of the nature ,and perhaps in all Fanny's sufferings, much greater relatively to her strength, there never was a time she suffered in an absolute sense what Bathsheba suffered now. What Troy did was to sink upon his knees with an indefinable union of remorse and reverence upon his face, and, bending over Fanny Robin, gently kissed her, as one would kiss an infant asleep to avoid awakening it. At the sight and sound of that, to her, unendurable act, Bathsheba sprang towards him. All the strong feelings which had been scattered over her existence since she knew what feeling was, seemed gathered together into one pulsation now. The revulsion from her indignant mood a little earlier, when she had meditated upon compromised honour, forestalment, eclipse in maternity by another, was violent and entire. All that was forgotten in the simple and still strong attachment of wife to husband. She had sighed for her self-completeness then, and now she cried aloud against the severance of the union she had deplored. She flung her arms round Troy's neck, exclaiming wildly from the deepest deep of her heart -- ' Don't -- don't kiss them !. O, Frank, I can"t bear it-i can't ! I love you better than she did: kiss me too, Frank -- kiss me ! You will, Frank, kiss me too !' There was something so abnormal and startling in the childlike pain and simplicity of this appeal from a woman of Bathsheba's calibre and independence, that Troy, loosening her tightly clasped arms from his neck, looked at her in bewilderment. It was such and unex+ pected revelation of all women being alike at heart, even those so different in their accessories as Fanny and this one beside him, that Troy could hardly seem to believe her to be his proud wife Bathsheba. Fanny's own spirit seemed to be animating her frame. But this was the mood of a few instants only. When the momentary 'I will not kiss you!' he said pushing her away. Had the wife now but gone no further. Yet, perhaps. under the harrowing circumstances, to speak out was the one wrong

act which can be better under+ stood, if not forgiven in her, than the right and politic one, her rival being now but a corpse. All the feeling she had been betrayed into showing she drew back to herself again by a strenuous effort of self-command. 'What have you to say as your reason ?' she asked her bitter voice being strangely low -- quite that of another woman now. 'I have to say that I have been a bad, black-hearted man,' he answered. less than she.' 'Ah! don't taunt me, madam. This woman is more to me, dead as she is, than ever you were, or are, or can be. If Satan had not tempted me with that face of yours, and those cursed coquetries, I should have He turned to Fanny then. 'But never mind, darling,' wife.!' At these words there arose from Bathsheba's lips a long, low cry of measureless despair and indignation, such a wail of anguish as had never before been heard within those old-inhabited walls. It was the ?????????? of her union with Troy. "If she's -- that, -- what -- am I ? ' she added, as a continuation of the same cry, and sobbing pitifully: and the rarity with her of such abandonment only made the condition more dire. " You are nothing to me -- nothing,' said Troy, heartlessly. 'A ceremony before a priest doesn't make a marriage. I am not morally yours.' A vehement impulse to flee from him, to run from this place, hide, and escape his words at any price, not stopping short of death itself, mastered Bathsheba now. She waited not an instant, but turned to the door and ran out.

UNDER A TREE -- REACTION BATHSHEBA went along the dark road, neither know' ing nor caring about the direction or issue of her flight. The first time that she definitely noticed her position was when she reached a gate leading into a thicket over+ hung by some large oak and beech trees. On looking into the place, it occurred to her that she had seen it by daylight on some previous occasion, and that what appeared like an impassable thicket was in reality a brake of fern now withering fast. She could think of nothing better to do with her palpitating self than to go in here and hide; and entering, she lighted on a spot sheltered from the damp fog hy a reclining trunk, where she sank down upon a tangled couch of fronds and stems. She mechanically pulled some armfuls round her to keep off the breezes, and closed her eyes. Whether she slept or not that night Bathsheba was not clearly aware. But it was with a freshened exist+ ence and a cooler brain that, a long time afterwards, she became conscious of some interesting proceedings which were going on in the trees above her head and around. A coarse-throated chatter was the first sound. It was a sparrow just waking. Next : ' Chee-weeze-weeze-weeze .! ' from another retreat. It was a finch. Third : ' Tink-tink-tink-tink-a-chink ! ' from the hedge, It was a robin. ' Chuck-chuck-chuck !. ' overhead. A squirrel. Then, from the road, 'With my ra-ta-ta, and my rum-tum-tum ! ' It was a ploughboy. Presently he came opposite, and she believed from his voice that he was one of the boys on her own farm. He was followed by a shambling tramp of heavy feet, and

looking through the ferns Bathsheba could just discern in the wan light of daybreak a team of her own horses. They stopped to drink at a pond on the other side of the way'. She watched them flouncing into the pool, drinking, tossing up their heads, drinking again, the water dribbling from their lips in silver threads. There was another flounce, and they came out of the pond, and turned back again towards the farm. She looked further around. Day was just dawning, and beside its cool air and colours her heated actions and resolves of the night stood out in lurid contrast. She perceived that in her lap, and clinging to her hair, were red and yellow leaves which had come down from the tree and settled silently upon her during her partial sleep. Bathsheba shook her dress to get rid of them, when multitudes of the same family lying round about her rose and fiuttered away in the breeze thus created, 'like ghosts from an enchanter fleeing.' There was an opening towards the east, and the glow from the as yet unrisen sun attracted her eyes thither. From her feet, and between the beautiful yellowing ferns with their feathery arms, the ground sloped downwards to a hollow, in which was a species of swamp, dotted with fungi. A morning mist hung over it now -- a fulsome yet magnificent silvery veil, full of light from the sun, yet semi-opaque -- the hedge behind it being in some measure hidden by its hazy luminousness. Up the sides of this depression grew sheaves of the common rush, and here and there a peculiar species of flag, the blades of which glistened in the enaerging sun, like scythes. But the general aspect of the swamp was malignant. From its moist and poisonous coat seemed to be exhaled the essences of evil things in the earth, and in the waters under the earth. The fungi grew in all manner of positions from rotting leaves and tree stumps, some exhibiting to her listless gaze their clammy tops, others their oozing gills. Some were marked with great splotches, red as arterial blood, others were saffron yellow, and others tall and attenuated, with stems like macaroni. Some were leathery and of richest browns. The hollow seemed a nursery of pestilences small and great, in the immediate neighbourhood of comfort and health, and Bathsheba arose with a tremor at the thought of having

passed the night on the brink of so dismal a place. 'l'here were now other footsteps to be heard along the road. Bathsheba's nerves were still unstrung : she crouchcd down out of sight again, and the pedes+ trian came into view. He was a schoolboy, with a bag slung over his shoulder containing his dinner, and a hook in his hand. He paused by the gate, and, without looking up, continued murmuring words in tones quite loud enough to reach her ears. '''O Lord, O Lord, O Lord, O Lord, O Lord'': -- that I know out o' book. ''Give us, give us, give us, give us, give us '' : -- that I know. ''Grace that, grace that, grace that, grace that '' : -- that I know.' Other words followed to the same effect. The boy was of the dunce class apparently; the book was a psalter, and this was his way of learning the collect. In the worst attacks of trouble there appears to be always a super+ ficial film of consciousness which is left disengaged and open to the notice of trifles, and Bathsheba was faintly amused at the boy's method, till he too passed on. By this time stupor had given place to anxiety, and anxiety began to make room for hunger and thirst. A form now appeared upon the rise on the other side of the swamp, half-hidden by the mist, and came towards Bathsheba. The woman -- for it was a woman -- approached with her face askance, as if looking earnestly on all sides of her. When she got a little further round to the left, and drew nearer, Bathsheba could see the newcomer's profile ngainst the sunny sky', and knew the wavy sweep from forehead to chin, with neither angle nor decisive line anywhere about it, to be the familiar contour of Liddy Smallbury. Bathsheba's heart bounded with gratitude in the thought that she was not altogether deserted, and she jumped up. ' O, Liddy .! ' she said, or attempted to say; but the words had only been framed hy her lips; there came no sound. She had lost her voice by exposure to the clogged atmosphere all these hours of night. 'O, ma'am.! I am so glad I have found you,' said the girl, as soon as she saw Bathsheba. ' You can't come across,' Bathsheba said in a whisper, wihich she

vainly endeavoured to make loud enough to reach Liddy's ears. Liddy, not knowing this, stepped down upon the swamp, saying, as she did so, 'It will bear me up, I think.' Bathsheba never forgot that transient little picture of Liddy crossing the swamp to her there in the morning light. Iridescent bubbles of dank subter+ ranean breath rose from the sweating sod beside the waiting maid's feet as she trod, hissing as they burst and expanded away to join the vapoury firmament above. Liddy did not sink, as Bathsheba had anticipated. She landed safely on the other side, and looked up at the beautiful though pale and weary face of her young mistress. 'Poor thing ! ' said Liddy, with tears in her eyes, Do hearten yourself up a little, ma'am. However did -- -- ' 'I can't speak above a whisper -- my voice is gone for the present,' said Bathsheba, hurriedly. ' I suppose the damp air from that hollow has taken it away Liddy, don't question me, mind. Who sent you -- anybody ? ' ' Nobody. I thought, when I found you were not at home, that something cruel had happened. I fancy I heard his voice late last night; and so, knowing something was wrong -- -- ' 'Is he at home?' 'No ; he left just before I came out.' 'Is Fanny taken away ? ' ' Not yet. She will soon be -- at nine o'clock.' 'we won't go home at present, then. Suppose we walk about in this wood ?' Liddy, without exactly understanding everything, or anything, in this episode, assented, and they walked together further among the trees. 'But you had better come in, ma'am, and have something to eat. You will die of a chill! ' 'I shall not come indoors yet -- perhaps never.' 'Shall I get you something to eat, and something else to put over your head besides that little shawl?' 'If you will, Liddy.' Liddy vanished, and at the end of twenty minutes returned with a cloak, hat, some slices of bread and butter, a tea-cup, and some hot tea in a little china jug

"Is Fanny gone ? ' said Bathsheba. ' No,' said her companion, pouring out the tea. Bathsheba wrapped herself up and ate and drank sparingly. Her voice was then a little clearer, and trifling colour returned to her face. 'Now we'll walk about again,' she said. They wandered about the wood for nearly two REACTION hours, Bathsheba replying in monosyllables to Liddy's prattle, for her mind ran on one subject, and one only. She interrupted with -- 'l wonder if Fanny is gone by this time ? ' 'I will go and see.' She came back with the information that the men were just taking away the corpse; that Bathsheba had been inquired for; that she had replied to the effect that her mistress was unwell and could not be seen. 'Then they think I am in my bedroom ?' ' Yes.' Liddy then ventured to add: ' You said when I first found you that you might never go home again -- you didn't mean it, ma'am ? ' 'No; I've altered my mind. It is only women with no pride in them who run away from their husbands. There is one position worse than that of being found dead in your husband's house from his iliusage, and that is, to be found alive through having gone away to The house of somebody else. l've thought of it all this morning, and I've chosen my course. A runaway wife is an encumbrance to everybody, a burden to herself and a byword -- all of which make up a heap of misery greater than any that comes by staying at home -- though this may include the trifling items of insult, beating, and starvation. Liddy, if ever you marry -- God forbid that you ever should ! -- you'll find yourself in a fearful situation ; but mind this, don't you flinch. Stand your ground, and be cut to pieces. That's what I'm going to do.' ' O, mistress, don't talk so .! ' said Liddy,-taking her hand; 'but I knew you had too much sense to bide away. May I ask what dreadful thing it is that has happened between you and him ?' ' You may ask; but I may not tell.' In about ten minutes they returned to the house by a cimuitous route, entering at the rear. Bathsheba glided up the

back stairs to a disused attic, and her companion followed. 'Liddy,' she said, with a lighter heart, for youth an hope had begun to reassert themselves; ' you are to b my confidante for the present -- somebody must be -- and I choose you. Well, I shall take up my abode here fo a while. Will you get a fire lighted, put down a piece of carpet, and help me to make the place comfortable. Afterwards, I want you and Maryann to bring up that little stump bedstead in the small room, and the be belonging to it, and a table, and some other things. What shall I do to pass the heavy time away ?' 'Hemming handkerchiefs is a very good thing,' said Liddy. 'O no, no .! I hate needlework-i always did.' 'knitting ? ' ' And that, too.' 'You might finish your sampler. Only the carn tions and peacocks want filling in; and then it could be framed and glazed, and hung beside your aunt' ma'am.' ' Samplers are out of date -- horribly countrified. No Liddy, I'll read. Bring up some books -- not new ones. I haven't heart to read anything new.' 'Some of your uncle's old ones, ma'am ? ' ' Yes. Some of those we stowed away in boxes.' , faint gleam of humour passed over her face as she said: 'Bring Beaumont and Fletcher's Mai'd's Tragedy,- an the Mourning Bride ,- and-iet me see -- Niht Thoghts, and the Vanity of Human Wishes.' 'And that story of the black man, who murdered his wife Desdemona? It is a nice dismal one that would suit you excellent just now.' ' Now, Liddy, you've been looking into my book without telling me; and I said you were not to ! How do you know it would suit me? It wouldn't suit me a all.' 'But if the others do -- -- ' ' No, they don't ; and I won't read dismal books. Why should I read dismal books, indeed ? Bring me Love in a Village, and Maid of the Mill, and Doctor Syntax, and some volumes of the Spectator.' All that day Bathsheba and Liddy lived in the attic in a state of

barricade ; a precaution which proved to be needless as against Troy, for he did not appear in the neighbourhood or trouble them at all. Bathsheba sat at the window till sunset, sometimes attempting to read, at other times watching every movement outside without much purpose, and listening without much interest to every sound. The sun went down almost blood-red that night, and a livid cloud received its rays in the east. Up against this dark background the west front of the church tower -- the only part of the edifice visible from the farm-house windows -- rose distinct and lustrous, the vane upon the summit bristling with rays. Hereabouts, at six o'clock, the young men of the village gathered, as was their custom, for a game of Prisoners' base. The spot had been consecrated to this ancient diversion from time immemorial, the old stocks conveniently forming a base facing the boundary of the churchyard, in front of which the ground was trodden hard and bare as a pavement by the players. She could see the brown and black heads of the young lads darting about right and left, their white shirt-sleeves gleaming in the sun; whilst occasionally a shout and a peal of hearty laughter varied the stillness of the evening air. They continued playing for a quarter of an hour or so, when the game concluded abruptly, and the players leapt over the wall and vanished round to the other side behind a yew-tree, which was also half behind a beech, now spreading in one mass of golden foliage, on which the branches traced black lines. 'Why did the base-players finish their game so suddenly?' Bathsheba inquired, the next time that Liddy entered the room. ' I think 'twas because two men came just then from Casterbridge and began putting up grand carved tombstone,' said Liddy. 'The lads went to see whose it was.' ' Do you know ? ' Bathsheba asked. ' I don't,' said Liddy.

TROY'S ROMANTICISM WHEN Troy's wife had left the house at the previous midnight his first act was to cover the dead from sight. This done he ascended the stairs, and throwing himself down upon the bed dressed as he was, he waited miser+ ably for the morning. Fate had dealt grimly with him through the last four+ and-twenty hours. His day had been spent in a way which varied very materially from his intentions regard+ ing it. There is always an inertia to be overcome in striking out a new line of conduct -- not more in our+ selves, it seems, than in circumscribing events, which appear as if leagued together to allow no novelties in the way of amelioration. Twenty pounds having been secured from Bathsheba, he had managed to add to the sum every farthing he could muster on his own account, which had been seven pounds ten. With this money, twenty-seven pounds ten in all, he had hastily driven from the gate that morning to keep his appointment with Fanny Robin. On reaching Casterbridge he left the horse and trap at an inn, and at five minutes before ten came back to the bridge at the lower end of the town, and sat himself upon the parapet. The clocks struck the hour, and no Fanny appeared. In fact, at that moment she was being robed in her grave-clothes by two attendants at the Union poorhouse -- the first and last tiring-women the gentle creature had ever been honoured with. The quarter went, the half hour. A rush of recollection came upon Troy as he waited: this was the second time she had broken a serious engagement with him In anger he vowed it should be the last, and at eleven o'clock, when he had lingered and watched the stone of the bridge till he knew every lichen upon their face and heard the chink of the ripples underneath till they oppressed him, he jumped from his seat, went to the inn

for his gig, and in a bitter mood of indifference con+ cerning the past, and recklessness about the future, drove on to Budmouth races. He reached the race-course at two o'clock, and re+ mained either there or in the town till nine, But Fanny's image, as it had appeared to him in the sombre shadows of that Saturday evening, returned to his mind, backed up by Bathsheba's reproaches. He vowed he would not bet, and he kept his vow, for on leaving the town at nine o'clock in the evening he had diminish his cash only to the extent of a few shillings. He trotted slowly homeward, and it was now that was struck for the first time with a thought that Fanny had been really prevented by illness from keeping her promise. 'This time she could have made no mistake He regretted that he had not remained in Casterbridge and made inquiries. Reaching home he quietly un+ harnessed the horse and came indoors, as we have seen, to the fearful shock that awaited him. As soon as it grew light enough to distinguish objects, Troy arose from the coverlet of the bed, and in a mood of absolute indifference to Bathsheba's whereabouts, a almost oblivious of her existence, he stalked downstairs and left the house by the back door. His walk was towards the churchyard, entering which he searched around till he found a newly dug unoccupied grave -- the grave dug the day before for Fanny. The position of this having been marked, he hastened on to Caster+ bridge, only pausing whereon he had last seen Fanny alive. Reaching the town, Troy descended into a side street and entered a pair of gates surmounted by a board bearing the words, 'Lester, stone and marble mason.' Within were lying about stones of all sizes and designs, inscribed as being sacred to the memory of unnamed persons who had not yet died. Troy was so unlike himself now in look, word, and deed, that the want of likeness was perceptible even to his own consciousness. His method of engaging himself in this business of purchasing a tomb was that of an absolutely unpractised man. He could not bring him+ self to consider, calculate, or

economize. He waywardly wished for something, and he set about obtaining it like a child in a nursery. 'I want a good tomb,' he said to the man who stood in a little office within the yard. 'I want as good a one as you can give me for twenty+ seven pounds,' It was all the money he possessed. 'That sum to include everything?' ' Everything. Cutting the name, carriage to Weather+ bury, and erection. And I want it now at once .' ' We could not get anything special worked this week. 'If you would like one of these in stock it could be got ready immediately.' 'Very well,' said Troy, impatiently. 'Let's see what you have.' 'The best I have in stock is this one, 'said the stone+ cutter, going into a shed. ' Here's a marble headstone beautifully crocketed, with medallions beneath of typical subjects ; here's the footstone after the same pattern, and here's the coping to enclose the- grave. The slabs are the best of their kind, and I can warrant them 'Well, I couId add the name, and put it up at visitor who wore not a shred of mourning. Troy then settled the account and went away. In the afternoon almost done. He waited in the yard till the tomb was way to Weatherbury, giving directions to the two men the grave of the person named in the inscription. bridge. He carried rather a heavy basket upon his occasionally at bridges and

gates, whereon he deposited returning in the darkness, the men and the waggon the work was done, and, on being assured that it was, Troy entered Weatherbury churchyard about ten had marked the vacant grave early in the morning. It extent from the view of passers along the road -- a spot and bushes of alder, but now it was cleared and made the ground elsewhere. Here now stood the tomb as the men had stated, snow+ white and shapely in the gloom, consisting of head and foot-stone, and enclosing border of marble-work uniting them. In the midst was mould, suitable for plants. Troy deposited his basket beside the tomb, and vanished for a few minutes. When he returned he carried a spade and a lantern, the light of which he directed for a few moments upon the marble, whilst he read the inscription. He hung his lantern on the lowest bough of the yew-tree, and took from his basket flower+ roots of several varieties. There were bundles of snow+ drop, hyacinth and crocus bulbs, violets and double daisies, which were to bloom in early spring, and of carnations, pinks, picotees, lilies of the valley, forget-me+ not, summer's-farewell, meadow-saffron and others, for the later seasons of the year. Troy laid these out upon the grass, and with an im+ passive face set to work to plant them. The snowdrops were arranged in a line on the outside of the coping, the remainder within the enclosure of the grave. The crocuses and hyacinths were to grow in rows; some of the summer flowers he placed over her head and feet, the lilies and forget-me-nots over her heart. The remainder were dispersed in the spaces between these. Troy, in his prostration at this time, had no percep+ tion that in the futility of these romantic doings, dictated by a remorseful reaction from previous indifference, there was any element

of absurdity. Deriving his idiosyn+ crasies from both sides of the Channel, he showed at such junctures as the present the inelasticity of the Englishman, together with that blindness to the line where sentiment verges on mawkishness, characteristic of the French. lt was a cloudy, muggy, and very dark night, and the rays from Troy's lantern spread into the two old yews with a strange illuminating power, flickering, as it seemed, up to the black ceiling of cloud above. He felt a large drop of rain upon the back of his hand, and presently one came and entered one of the holes of the lantern, whereupon the candle sputtered and went out+ Troy was weary and it being now not far from midnight, and the rain threatening to increase, he resolved to leave the finishing touches of his labour until the day should break. He groped along the wall and over the graves in the dark till he found himself round at the north side. Here he entered the porch, and, reclining upon the bench within, fell asleep.

THE GURGOYLE : ITS DOINGS THE tower of Weatherbury Church was a square erection of fourteenth-century date, having two stone gurgoyles on each of the four faces of its parapet. Of these eight carved protuberances only two at this time continued to serve the purpose of their erection -- that of spouting the water from the lead roof within. One mouth in each front had been closed hy bygone church+ wardens as superfluous, and two others were broken away and choked -- a matter not of much consequence to the welibeing of the tower, for the two mouths which still remained open and active were gaping enough to do all the work. It has been sometimes argued that there is no truer criterion of the vitality of any given art-period than the power of the master-spirits of that time in grotesque ; and certainly in the instance of Gothic art there is no disputing the proposition. Weatherbury tower was a somewhat early instance of the use of an ornamental parapet in parish as distinct from cathedral churches, and the gurgoyles, which are the necessary correlatives of a parapet, were exccptionally prominent -- of the boldest cut that the hand could shape, and of the most original design that a human brain could conceive. There was, so to speak, that symmetry in their distortion which is less the characteristic of British than of Continental grotesques of the period. All the eight were different from each other. A beholder was con+ vinced that nothing on earth could be more hideous than those he saw on the north side until he went round to the south. Of the two on this latter face, only that at the south-eastern corner concerns the story. It was too human to be called like a dragon, too impish to be like a man, too animal to be like a fiend, and not enough like a bird to be called a griffin. This horrible stone entity was fashioned as if covered with a

wrinkled hide; it had short, erect ears, eyes starting from their sockets, and its fingers and hands were seizing the corners of its mouth, which they thus seemed to pull open to give free passage to the water it vomited. The lower row of teeth was quite washed away, though the upper still remained. Here and thus, jutting a couple of feet from the wall against which its feet rested as a support, the creature had for four hundred years laughed at the surrounding landscape, voicelessly in dry weather, and in wet with a gurgling and snorting sound. Troy slept on in the porch, and the rain increased outside. Presently the gurgoyle spat. In due time a small stream began to trickle through the seventy feet of aerial space between its mouth and the ground, which the water-drops smote like duckshot in their accelerated velocity. The stream thickened in substance, and in+ creased in power, gradually spouting further and yet further from the side of the tower. When the rain fell in a steady and ceaseless torrent the stream dashed downward in volumes. We follow its course to the ground at this point of time. The end of the liquid parabola has come forward from the wall, has advanced over the plinth mouldings, over a heap of stones, over the marble border, into the midst of Fanny Robin's grave. The force of the stream had, until very lately, been received upon some loose stones spread thereabout, which had acted as a shield to the soil under the onset. These during the summer had been cleared from the ground, and there was now nothing to resist the down+ fall but the bare earth. For several years the stream had not spouted so far from the tower as it was doing on this night, and such a contingency had been over+ looked. Sometimes this obscure corner received no inhabitant for the space of two or three years, and then it was usually but a pauper, a poacher, or other sinner of undignified sins. The persistent torrent from the gurgoyle's jaws directed all its vengeance into the grave. The rich tawny mould was stirred into motion, and boiled like chocolate. The water accumulated and washed deeper down, and the roar of the pool thus formed spread into the night as the head and chief among other noises of

the kind created by the deluging rain. The flowers so carefully planted by Fanny's repentant lover began to move and writhe in their bed. The winter-violets turned slowly upside down, and became a mere mat of mud. Soon the snowdrop and other bulbs danced in the boiling mass like ingredients in a cauldron. Plants of the tufted species were loosened, rose to the surface, and floated of. Troy did not awake from his comfortless sleep till it was broad day. Not having been in bed for two nights his shouldrrs felt stiff his feet tender, and his head heavy. He remembered his position, arose, shivered, took the spade, and again went out. The rain had quite ceased, and the sun was shining through the green, brown, and yellow leaves, now sparkling and varnished by the raindrops to the bright+ ness of similar effects in the landscapes of Ruysdael and Hobbema, and full of all those infinite beauties that arise from the union of water and colour with high lights. The air was rendered so transparent by the heavy fall of rain that the autumn hues of the middle distance were as rich as those near at hand, and the remote fields intercepted by the angle of the tower ap+ peared in the same plane as the tower itself. He entered the gravel path which would take him behind the tower. The path, instead of being stony as it had been the night before, was browned over with a thin coating of mud. At one place in the path he saw a tuft of stringy roots washed white and clean as a bundle of tendons. He picked it up -- surely it could not be one of the primroses he had planted? He saw a bulb, another, and another as he advanced. Beyond doubt they were the crocuses. With a face of perplexed dismay Troy turned the corner and then beheld the wreck the stream had made. The pool upon the grave had soaked away into the ground, and in its place was a hollow. The disturbed earth was washed over the grass and pathway in the guise of the brown mud he had already seen, and it spotted the marble tombstone with the same stains. Nearly all the flowers were washed clean out of the ground, and they lay, roots upwards, on the spots whither they had been splashed by the stream.

Troy's brow became heavily contracted. He set his teeth closely, and his compressed lips moved as those of one in great pain. This singular accident, by a strange confluence of emotions in him, was felt as the sharpest sting of all. Troy's face was very expressive, and any observer who had seen him now would hardly have believed him to be a man who had laughed, and sung, and poured love-trifles into a woman's ear. To curse his miserable lot was at first his impulse, but even that lowest stage of rebellion needed an activity whose absence was necessarily antecedent to the existence of the morbid misery which wrung him. The sight, coming as it did, superimposed upon the other dark scenery of the previous days, formed a sort of climax to the whole panorama, and it was more than he could endure. Sanguine by nature, Troy had a power of eluding grief by simply adjourning it. He could put off the consideration of any particular spectre till the matter had become old and softened by time. The planting of flowers on Fanny's grave had been perhaps but a species of elusion of the primary grief, and now it was as if his intention had been known and circumvented. Almost for the first time in his life, Troy, as he stood by this dismantled grave, wished himself another man. lt is seldom that a person with much animal spirit does not feel that the fact of his life being his own is the one qualification which singles it out as a more hopeful life than that of others who may actually resemble him in every particular. Troy had felt, in his transient way, hundreds of times, that he could not envy other people their condition, because the possession of that condition would have necessitated a different personality, when he desired no other than his own. He had not minded the peculiarities of his birth, the vicissitudes of his life, the meteoriike uncertainty of all that related to him, because these appertained to the hero of his story, without whom there would have been no story at all for him; and it seemed to be only in the nature of things that matters would right themselves at some proper date and wind up well. This very morning the illusion completed its disappearance, and, as it were, all of a sudden, Troy hated himself. The suddenness was probably more

apparent than real. A coral reef which just comes short of the ocean surface is no more to the horizon than if it had never been begun, and the mere finishing stroke is what often appears to create an event which has long been potentially an accomplished thing. He stood and mediated -- a miserable man. Whither should he go ? " He that is accursed, let him be accursed still,' was the pitiless anathema written in this spoliated effort of his new-born solicitousness. A man who has spent his primal strength in journeying in one direction has not much spirit left for reversing his course. Troy had, since yesterday, faintly reversed his ; but the merest opposition had disheartened him. To turn about would have been hard enough under the greatest providential encouragement; but to find that Providence, far from helping him into a new course, or showing any wish that he might adopt one, actuallyjeered his first trembling and critical attempt in that kind, was more than nature could bear. He slowly withdrew from the grave. He did not attempt to fill up the hole, replace the flowers, or do anything at all. He simply threw up his cards and forswore his game for that time and always. Going out of the churchyard silently and unobserved -- none of the villagers having yet risen -- he passed down some fields at the back, and emerged just as secretly upon the high road. Shortly afterwards he had gone from the village. Meanwhile, Bathsheba remained a voluntary prisoner in the attic. The door was kept locked, except during the entries and exits of Liddy, for whom a bed had been arranged in a small adjoining room. The light of Troy's lantern in the churchyard was noticed about ten o'clock by the maid-servant, who casually glanced from the window in that direction whilst taking her supper, and she called Bathsheba's attention to it. They looked curiously at the phenomenon for a time, until Liddy was sent to bed. bathsheba did not sleep very heavily that night. When her attendant was unconscious and softly breath+ ing in the next room, the mistress of the house was still looking out of the window at the faint gleam spreading from among the trees --

not in a steady shine, but blinking like a revolving coastiight, though this appearance failed to suggest to her that a person was passing and repassing in front of it. Bathsheba sat here till it began to rain, and the light vanished, when she withdrew to lie restlessly in her bed and re-enact in a worn mind the lurid scene of yesternight. Almost before the first faint sign of dawn appeared she arose again, and opened the window to obtain a full breathing of the new morning air, the panes being now wet with trembling tears left by the night rain, each one rounded with a pale lustre caught from primrose+ hued slashes through a cloud low down in the awaken+ ing sky. From the trees came the sound of steady dripping upon the drifted leaves under them, and from the direction of the church she could hear another noise -- peculiar, and not intermittent like the rest, the purl of water falling into a pool. Liddy knocked at eight o'clock, and Bathsheba un+ locked the door. " What a heavy rain we've had in the night, ma'am!.' said Liddy, when her inquiries about breakfast had been made. " Yes ; very heavy.' "Did you hear the strange noise from the church yard?' "I heard one strange noise. I've been thinking it must have been the water from the tower spouts.' "Well, that's what the shepherd was saying, ma'am. He's now gone on to see. "Oh!. Gabriel has been here this morning!.' "Only just looked in in passing -- quite in his old way, which I thought he had left off lately. But the tower spouts used to spatter on the stones, and we are puzzled, for this was like the boiling of a pot.' Not being able to read, think, or work, Bathsheba asked Liddy to stay and breakfast with her. The tongue of the more childish womian still ran upon recent events. "Are you going across to the church, ma'am?' she asked. "Not that I know of,' said Bathsheba. "I thought you might like to go and see where they have put Fanny. The trees hide the place from your window.'

Bathsheba had all sorts of dreads about meeting her husband. "Has Mr. Troy been in to-night?' she said " No, ma'am ; I think he's gone to Budmouth. Budmouth! The sound of the word carried with it a much diminished perspective of him and his deeds; there were thirteen miles interval betwixt them now. She hated questioning Liddy about her husband's movements, and indeed had hitherto sedulously avoided doing so; but now all the house knew that there had been some dreadful disagreement between them, and it was futile to attempt disguise. Bathsheba had reached a stage at which people cease to have any appreciative regard for public opinion. "What makes you think he has gone there?' she said. "Laban Tall saw him on the Budmouth road this morning before breakfast.' Bathsheba was momentarily relieved of that wayward heaviness of the past twenty-four hours which had quenched the vitality of youth in her without sub+ stituting the philosophy of maturer years, and the resolved to go out and walk a little way. So when breakfast was over, she put on her bonnet, and took a direction towards the church. It was nine o'clock, and the men having returned to work again from their first meal, she was not likely to meet many of them in the road. Knowing that Fanny had been laid in the reprobates' quarter of the graveyard, called in the parish 'behind church,' which was invisible from the road, it was impossible to resist the impulse to enter and look upon a spot which, from nameless feelings, she at the same time dreaded to see. She had been unable to overcome an impression that some connection existed between her rival and the light through the trees. Bathsheba skirted the buttress, and beheld the hole and the tomb, its delicately veined surface splashed and stained just as Troy had seen it and left it two hours earlier. On the other side of the scene stood Gabriel. His eyes, too, were fixed on the tomb, and her arrival having been noiseless, she had not as yet attracted his attention. Bathsheba did not at once perceive that the grand tomb and the disturbed grave were Fanny's, and she looked on both sides and around for some humbler mound,

earthed up and clodded in the usual way. Then her eye followed Oak's, and she read the words with which the inscription opened : -- "Erected by Francis Troy in Beloved Memory of Fanny Robin.' Oak saw her, and his first act was to gaze inquiringly and learn how she received this knowledge of the authorship of the work, which to himself had caused considerable astonishment. But such discoveries did not much affect her now. Emotional convulsions seemed to have become the commonplaces of her history, and she bade him good morning, and asked him to fill in the hole with the spade which was standing by. Whilst Oak was doing as she desired, Bathsheba collected the flowers, and began planting them with that sympathetic manipulation of roots and leaves which is so conspicuous in a woman's gardening, and which flowers seem to understand and thrive upon. She requested Oak to get the churchwardens to turn the leadwork at the mouth of the gurgoyle that hung gaping down upon them, that by this means the stream might be directed sideways, and a repetition of the accident prevented. Finally, with the superfluous magnanimity of a woman whose narrower instincts have brought down bitterness upon her instead of love, she wiped the mud spots from the tomb as if she rather liked its words than otherwise,

ADVENTURES BY THE SHORE TROY wandered along towards the south. A composite feeling, made up of disgust with the, to him, humdrum tediousness of a farmer's life, gloomly images of her who lay in the churchyard, remorse, and a general averseness to his wife's society, impelled him to seek a home in any place on earth save Weatherbury. The sad accessories of Fanny's end confronted him as vivid pictures which threatened to be indelible, and made life in Bathsheba's house intolerable. At three in the afternoon he found himself at the foot of a slope more than a mile in length, which ran to the ridge of a range of hills lying parallel with the shore, and forming a monotonous barrier between the basin of cultivated country inland and the wilder scenery of the coast. Up the hill stretched a road nearly straight and perfectly white, the two sides approaching each other in a gradual taper till they met the sky at the top about two miles off. Through+ out the length of this narrow and irksome inclined plane not a sign of life was visible on this garish afternoon Troy toiled up the road with a languor and depression greater than any he had experienced for many a day and year before. The air was warm and muggy, and the top seemed to recede as he approached. At last he reached the summit, and a wide and novel prospect burst upon him with an effect almost like that of the Pacific upon Balboa's gaze. The broad steely sea, marked only by faint lines, which had a semblance of being etched thereon to a degree not deep enough to disturb its general evenness, stretched the whole width of his front and round to the right, where, near the town and port of Budmouth, the sun bristled down upon it, and banished all colour, to substitute in its place a clear oily polish. Nothing moved in sky, land, or sea, except a frill of milkwhite foam along the nearer angles of the

shore, shreds of which licked the contiguous stones like tongues. He descended and came to a small basin of sea enclosed by the cliffs. Troy's nature freshened within him ; he thought he would rest and bathe here before going farther. He undressed and plunged in. Inside the cove the water was uninteresting to a swimmer, being smooth as a pond, and to get a little of the ocean swell, Troy presently swam between the two projecting spurs of rock which formed the pillars of Hercules to this miniature Mediterranean. Unfortunately for Troy a current unknown to him existed outside, which, un+ important to craft of any burden, was awkward for a swimmer who might be taken in it unawares. Troy found himself carried to the left and then round in a swoop out to sea. He now recollected the place and its sinister character. Many bathers had there prayed for a dry death from time to time, and, like Gonzalo also, had been unanswered ; and Troy began to deem it possible that he might be added to their number. Not a boat of any kind was at present within sight, but far in the distance Budmouth lay upon the sea, as it were quietly regarding his efforts, and beside the town the harbour showed its position by a dim meshwork of ropes and spars. After welinigh exhausting himself in attempts to get back to the mouth of the cove, in his weakness swimming several inches deeper than was his wont, keeping up his breathing entirely by his nostrils, turning upon his back a dozen times over, swimming <1en papillon>1 and so on, Troy resolved as a last resource to tread water at a slight incline, and so endeavour to reach the shore at any point, merely giving himself a gentle impetus inwards whilst carried on in the general direc+ tion of the tide. This, necessarily a slow process, he found to be not altogether so difficult, and though there was no choice of a landing-place -- the objects on shore passing by him in a sad and slow procession -- he per+ ceptibly approached the extremity of a spit of land yet further to the right, now well defined against the sunny portion of the horizon- While the swimmer s eye's were fixed upon the spit as his only means of salvation on this side of the

Unknown, a moving object broke the outline of the extremity, and immediately a ship's boat appeared manned with several sailor lads, her bows towards the sea. All Troy's vigour spasmodically revived to prolong the struggle yet a little further. Swimming with his right arm, he held up his left to hail them, splashing upon the waves, and shouting with all his might. From the position of the setting sun his white form was distinctly visible upon the now deep-hued bosom of the sea to the east of the boat, and the men saw him at once. Backing their oars and putting the boat about, they pulled towards him with a will, and in five or six minutes from the time of his first halloo, two of the sailors hauled him in over the stern. They formed part of a brig's crew, and had come ashore for sand. Lending him what little clothing they could spare among them as a slight protection against late they made again towards the roadstead where their And now night drooped slowly upon the wide watery levels in front; and at no great distance from them, where the shoreiine curved round, and formed a long riband of shade upon the horizon, a series of points of yellow light began to start into existence, denoting the spot to be the site of Budmouth, where the lamps were being lighted along the parade. The cluck of their oars was the only sound of any distinctness upon the sea, and as they laboured amid the thickening shades the lampiights grew larger, each appearing to send a flaming sword deep down into the waves before it, until there arose, among other dim shapes of the kind, the form of the vessel for which they were bound.

DOUBTS ARISE -- DOUBTS LINGER BATHSHEBA underwent the enlargement of her Husband's absence from hours to days with a slight feeling of suprise, and a slight feeling of relief; yet neither sensation rose at any time far above the level commonly designated as indifference. She belonged to him : the certiinties of that position were so well defined, and the reasonable probabilies of its issue so bounded that she could not speculate on contingenciezs. Taking no further interest in herself as a splendid woman, she acquired the indifferent feelings of an outsider in contem+ plating her probable fate as a singular wretch ; for Bath+ sheba drew herself and her future in colours that no reality could exceed for darkness. Her original vigorous pride of youth had sickened, and with it had declined all her anzieties about coming years, since anxiety recognizes a better and a worse alternative, and Bath+ sheba had made up her mind that alternatives on any noteworthy scale had ceased for her. Soon, or later -- and that not very late -- her husband would be home again. And then the days of their tenancy of the Upper Farm would be numbered. There had origin+ ally been shown by the agent to the estate some distrust of Bathsheba's tenure as James Everdene's successor, on the score of her sex, and her youth, and her beauty ; but the peculiar nature of her uncle's will, his own frequent testimony before his death to her cleverness in such a pursuit, and her vigorous marshalling of the numerous flocks and herds which came suddenly into her hands before negotiations were concluded, had won confidence in her powers, and no further objections had been raised. She had latterly been in great doubt as to what the legal effects of her marriage would be upon her position; but no notice had been taken as yet of her change of name, and only one point was clear -- that in the event of her own or her husband's inability to meet the agent at the

forthcoming January rent-day, very little consideration would be shown, and, for that matter, very little would be deserved. Once out of the farm, the approach of poverty would be sure. Hence Bathsheba lived in a perception that her purposes were broken of. She was not a woman who could hope on without good materials for the process, differing thus from the less far-Sighted and energetic, though more petted ones of the sex, with whom hope goes on as a sort of clockwork which the merest food and shelter are sufficient to wind up; and perceiving clearly that her mistake had been a fatal one, she accepted her position, and waited coldly for the end. The first Saturday after Troy's departure she went to Casterbridge alone, a journey she had not before taken since her marriage. On this Saturday Bathsheba was passing slowly on foot through the crowd of rural business-men gathered as usual in front ot the market+ house, who were as usual gazed upon by the burghers with feelings that those healthy lives were dearly paid for by exclusion from possible aldermanship, when a man, who had apparently been following her, said some words to another on her left hand. Bathsheba's ears were keen as those of any wild animal, and she dis+ tinctly heard what the speaker said, though her back was towards him "I am looking for Mrs. Troy. Is that she there?' " Yes ; that's the young lady, I believe,' said the the person addressed. "I have some awkward news to break to her. Her husband is drowned.' As if endowed with the spirit of prophecy, Bathsheba gasped out, "No, it is not true; it cannot be true!' Then she said and heard no more. The ice of self+ command which had latterly gathered over her was broken, and the currents burst forth again, and over whelmed her. A darkness came into her eyes, and she fell. But not to the ground. A gloomy man, who had been observing her from under the portico of the old corn-exchange when she passed through the group without, stepped quickly to her side at the moment of her exclamation, and caught her in his arms as she sank down.

"What is it?' said Boldwood, looking up at the bringer of the big news, as he supported her. "Her husband was drowned this week while bathing in Lulwind Cove. A coastguardsman found his clothes, and brought them into Budmouth yestersay.' Thereupon a strange fire lighted up Boldwood's eye, and his face flushed with the suppressed excitement of an unutterable thought. Everybody's glance was now centred upon him and the unconsious Bathsheba. He lifted her bodily off the ground, and smoothed down the folds of her dress as a child might have taken a storm-beaten bird and arranged its ruffled plumes, and bore her along the pavement to the King's Arms Inn. Here he passed with her under the archway into a private room; and by the time he had deposited -- so lothly -- the precious burden upon a sofa, Bathsheba had opened her eyes. Remembering all that had occurred, she murmured, 'I want to go home .! ' Boldwood left the room. He stood for a moment in the passage to recover his senses. The experience had been too much for his consciousness to keep up with, and now that he had grasped it it had gone again. For those few heavenly, golden moments she had been in his arms. What did it matter about her not knowing it? She had been close to his breast ; he had been close to hers. He started onward again, and sending a woman to her, went out to ascertain all the facts of the case. These appeared to be limited to what he had already heard. He then ordered her horse to be put into the gig, and when all was ready returned to inform her. He found that, though still pale and unwell, she had in the meantime sent for the Budmouth man who brought the tidings, and learnt from him all there was to know. Being hardly in a condition to drive home as she had driven to town, Boldwood, with every delicacy of manner and feeling, offered to get her a driver, or to give her a seat in his phaeton, which was more com+ fortable than her own conveyance. These proposals Bathsheba gently declined, and the farmer at once de+ parted. About half-an-hour later she invigorated herself by an effort, and took her seat and the reins as usuai-in external

appearance much as if nothing had happened. She went out of the town by a tortuous back street, and drove slowly along, unconscious of the road and the scene. The first shades of evening were showing them+ selves when Bathsheba reached home, where, silently alighting and leaving the horse in the hands of the boy, she proceeded at once upstairs. Liddy met her on the landing. The news had preceded Bathsheba to Weather+ bury by half-an-hour, and Liddy looked inquiringly into her mistress's face. Bathsheba had nothing to say. She entered her bedroom and sat by the window, and thought and thought till night enveloped her, and the extreme lines only of her shape were visible. Somebody came to the door, knocked, and opened it. ' Well, what is it, Liddy ? ' she said. 'I was thinking there must be something got for you to wear,' said Liddy, with hesitation. 'What do you mean ?' ' Mourning.' ' No, no, no,' said Bathsheba, hurriedly. 'But I suppose there must be something done for poor -- -- ' ' Not at present, I think. It is not necessary.' ' Why not, ma'am ? ' ' Because he's still alive.' ' How do you know that ? ' said Liddy, amazed. ' I don't know it. But wouldn't it have heen different, or shouldn't I have heard more, or wouldn't they have found him, Liddy ? -- or-i don't know how it is, but death would have been different from how this is. I am perfectly convinced that he is still alive .! ' Bathsheba remained firm in this opinion till Monday, when two circumstances conjoined to shake it. The first was a short paragraph in the local newspaper, which, beyond making by a methodizing pen formidable pre+ sumptive evidence of Troy's death by drowning, con+ tained the important testimony of a young Mr. Barker, M.D., of Budmouth, who spoke to being an eyewitness of the accident, in a letter to the editor. In this he stated that he was passing over the cliff on the remoter side of the

cove just as the sun was setting. At that time he saw a bather carried along in the current outside the mouth of the cove, and guessed in an instant that there was but a poor chance for him unless he should be possessed of unusual muscular powers. He drifted behind a projection of the coast, and Mr. Barker followed along the shore in the same direction. But by the time that he could reach an elevation sufficiently great to command a view of the sea beyond, dusk had set in, and nothing further was to be seen. The other circumstance was the arrival of his clothes, when it became necessary for her to examine and identify them -- though this had virtually been done long before by those who inspected the letters in his pockets. It was so evident to her in the midst of her agitation that Troy had undressed in the full conviction of dressing again almost immediately, that the notion that anything but death could have prevented him was a perverse one to entertain. Then Bathsheba said to herself that others were assured in their opinion; strange that she should not be. A stmnge reflection occured to her, causing her face to flush. Suppose that Troy had followed Fanny into another world. Had he done this intentionally, yet contrived to make his death appear like an accident ? Nevertheless, this thought of how the apparent might differ from the reai-made vivid by her bygone jealousy of Fanny, and the remorse he had shown that night -- did not blind her to the perception of a likelier difference, less tragic, but to herself far more disastrous. When alone late that evening beside a small fire, and much calmed down, Bathsheba took Troy's watch into her hand, which had been restored to her with the rest of the articles belonging to him. She opened the case as he had opened it before her a week ago. There was the little coil of pale hair which had been as the fuze to this great explosion. 'He was hers and she was his; they should be gone together,' she said. 'I am nothing to either of them, and why should I keep her hair?' She took it in her hand, and held it over the fire. ' No-i'll not burn it -i'll keep it in memory of her, poor thing !. ' she added, snatching back her hand.

OAK'S ADVANCEMENY -- A GREAT HOPE THE later autumn and the winter drew on apace, and the leaves lay thick upon the turf of the glades and the mosses of the woods. Bathsheba, having previously been living in a state of suspended feeling which was not suspense, now lived in a mood of quietude which was not precisely peacefulness. While she had known him to be alive she could have thought of his death with equanimity; but now that it might be she had lost him, she regretted that he was not hers still. She kept the farm going, raked in her profits without caring keenly about them, and expended money on ventures because she had done so in bygone days, which, though not long gone by, seemed infinitely removed from her present. She looked back upon that past over a great gulf, as if she were now a dead person, having the faculty of meditation still left in her, by means of which, like the mouldering gentlefolk of the poet's story, she could sit and ponder what a gift life used to be. However, one excellent result of her general apathy was the long-delayed installation of Oak as bailiff; but he having virtually exercised that function for a long time already, the change, beyond the substantial in+ crease of wages it brought, was little more than a nominal one addressed to the outside world. Boldwood lived secluded and inactive. Much of his wheat and all his barley of that season had been spoilt by the rain. It sprouted, grew into intricate mats, and was ultimately thrown to the pigs in armfuls. The strange neglect which had produced this ruin and waste became the subject of whispered talk among all the people round; and it was elicited from one of Boldwood's men that forgetfulness had nothing to do with it, for he had been reminded of the danger to his corn as many times and as persistently as inferiors dared to do. The sight of the

pigs turning in disgust from the rotten ears seemed to arouse Boldwood, and he one evening sent for Oak. Whether it was sug+ gested by Bathsheba's recent act of promotion or not, the farmer proposed at the interview that Gabriel should undertake the superintendence of the Lower Farm as well as of Bathsheba's, because of the necessity Boldwood felt for such aid, and the impossibility of discovering a more trustworthy man. Gabriel's malig+ nant star was assuredly setting fast. Bathsheba, when she learnt of this proposai-for Oak was obliged to consult her -- at first languidly objected. She considered that the two farms together were too extensive for the observation of one man. Boldwood, who was apparently determined by personal rather than commercial reasons, suggested that Oak should be furnished with a horse for his sole use, when the plan would present no difficulty, the two farms lying side by side. Boldwood did not directly communicate with her during these negotiations, only speaking to Oak, who was the go-between throughout. All was harmoniously arranged at last, and we now see Oak mounted on a strong cob, and daily trotting the length breadth of about two thousand acres in a cheerful spirit of surveillance, as if the crops belonged to him -- the actual mistress of the one-half and the master of the other, sitting in their respective homes in gloomy and sad seclusion. Out of this there arose, during the spring succeeding, a talk in the parish that Gabriel Oak was feathering his nest fast. ' Whatever d'ye think,' said Susan Tall, ' Gable Oak is coming it quite the dand. He now wears shining boots with hardly a hob in 'em, two or three times a-week, and a tall hat a-Sundays, and 'a hardly knows the name of smockfrock. When I see people strut enough to he cut up into bantam cocks, I stand dormant with wonder, and says no more .! ' It was eventually known that Gabriel, though paid a fixed wage by Bathslieba independent of the fluctua+ tions of agricultural profits, had made an engagement with Boldwood by which Oak was to receive a share of the receipts -- a small share certainly, yet it was money of a higher quality than mere wages, and capable of expansion in a way that wages were not.

Some were beginning to consider Oak a 'near' man, for though his condition had thus far improved, he lived in no better style than hefore, occupying the same cottage, paring his own potatoes, mending his stockings, and sometimes even making his bed with his own hands. But as Oak was not only provokingly indifferent to public opinion, but a man who clung persistently to old habits and usages, simply because they were old, there was room for doubt as to his motives. A great hope had latterly germinated in Boldwood, whose unreasoning devotion to Bathsheba could only be characterized as a fond madness which neither time nor circumstance, evil nor good report, could weaken or destroy. This fevered hope had grown up again like a grain of mustard-seed during the quiet which followed the hasty conjecture that Troy was drowned. He nourished it fearfully, and almost shunned the contemplation of it in earnest, lest facts should reveal the wildness of the dream. Bathsheba having at last been persuaded to wear mourning, her appearance as she entered the church in that guise was in itself a weekly addition to his faith that a time was coming -- very far off perhaps, yet surely nearing -- when his waiting on events should have its reward. How long he might have to wait he had not yet closely considered. what he would try to recognize was that the severe schooling she had been subjected to had made Bathsheba much more con+ siderate than she had formerly been of the feelings of others, and he trusted that, should she be willing at any time in the future to marry any man at all, that man would be himself. There was a substratum of good feeling in her: her self-reproach for the injury she had thoughtlessly done him might be depended upon now to a much greater extent than before her infatuation and disappointment. It would be possible to approach her by the channel of her good nature, and to suggest a friendly businessiike compact between them for fulfilment at some future day, keeping the passionate side of his desire entirely out of her sight. Such was Boldwood's hope. To the eyes of the middle-aged, Bathsheba was perhaps additionally charming just now. Her exuber+ ance cf spirit was pruned down ; the original phantom of delight had shown

herself to be not too bright for human nature's daily food, and she had been able to enter this second poetical phase without losing much of the first in the process. Bathsheba's return from a two months' visit to her old aunt at Norcombe afforded the impassioned and yearning farmer a pretext for inquiring directly after her -- now possibly in the ninth month of her widowhood -- and endeavouring to get a notion of her middle of the haymaking, and Boldwood contrived to 'I am glad to see you out of doors, Lydia,' he said She simpered, and wondered in her heart why he 'I hope Mrs. Troy is quite well after her long the coldest-hearted neighbour could scarcely say less 'She is quite well, sir. 'Yes, cheerful. 'Fearful, did you say?' 'O no. I merely said she was cheerful.' 'Tells you all her affairs?' 'No, sir. 'Some of them?' 'Yes, sir. 'Mrs Troy puts much confidence in you, Lydia; and very wisely, perhaps.' 'She do, sir. I've been with her all through her troubles, and was with her at the time of Mr.Troy's going and all. And if she were to marry again I expect I should bide with her.' 'She promises that you shali -- quite natural,' said the strategic lover, throbbing throughout him at the presumption which Liddy's words appeared to warrant -- that his darling had thought of re-marriage. 'No -- -she doesn't promise it exactly. I merely judge on my own account. 'Yes yes, I understand. When she alludes to the possibility of marrying again, you conclude -- -- '

'She never do allude to it, sir,' said Liddy, thinking how very stupid Mr. Boldwood was getting. 'Of course not,' he returned hastily, his hope falling again. ' You needn't take quite such long reaches with your rake, Lydia -- short and quick ones are best. Well, perhaps, as she is absolute mistress again now, it is wise of her to resolve never to give up her freedom.' ' My mistress did certainly once say, though not seriously, that she supposed she might marry again at the end of seven years from last year, if she cared to risk Mr. Troy's coming back and claiming her.' ' Ah, six years from the present time. Said that she might. She might marry at once in every reasonable person's opinion, whatever the lawyers may say to the contrary.' 'Have you been to ask them?' said Liddy, innocently. ' Not I,' said Boldwood, growing red. ' Liddy, you needn't stay here a minute later than you wish, so Mr, Oak says. I am now going on a little farther. Good' afternoon.' He went away vexed with himself, and ashamed of having for this one time in his life done anything which could be called underhand. Poor Boldwood had no more skill in finesse than a battering-ram, and he was uneasy with a sense of having made himself to appear stupid and, what was worse, mean. But he had, after all, lighted upon one fact by way of repayment. It was a singularly fresh and fascinating fact, and though not without its sadness it was pertinent and real. In little more than six years from this time Bathsheba might certainly marry him. There was something definite in that hope, for admitting that there might have been no deep thought in her words to Liddy about marriage, they showed at least her creed on the matter. This pleasant notion was now continually in his mind. Six years were a long time, but how much shorter than never, the idea he had for so long been obliged to endure .! Jacob had served twice seven years for Rachel: what were six for such a woman as this ? He tried to like the notion of waiting for her better than that of winning her at once. Boldwood felt his love to be so deep and strong and eternal, that it was pos+ sible she

had never yet known its full volume, and this patience in delay would afford him an opportunity of giving sweet proof on the point. He would annihilate the six years of his life as if they were minutes -- so little did he value his time on earth beside her love. He would let her see, all those six years of intangible ether+ eal courtship, how little care he had for anything but as it bore upon the consummation. Meanwhile the early and the late summer brought round the week in which Greenhill Fair was held. This fair was frequently attended by the folk of Weather+ bury.

THE SHEEP FAIR -- TROY TOUCHES HIS WIFE'S HAND GREENHILL was the Nijni Novgorod of South Wessex; and the busiest, merriest, noisiest day of the whole statute number was the day of the sheep fair. This yearly gathering was upon the summit of a hill which retained in good preservation the remains of an ancient earthwork, consisting of a huge rampart and entrenchnaent of an oval form encircling the top of the hill, though somewhat broken down here and there. To each of the two chief openings on opposite sides a winding road ascended, and the level green space of ten or fifteen acres enclosed by the bank was the site of the fair. A few permanent erections dotted the spot, but the majority of visitors patronized canvas alone for resting and feeding under during the time of their sojourn here. Shepherds who attended with their flocks from long distances started from home two or three days, or even a week, before the fair, driving their charges a few miles each day -- not more than ten or twelve -- and resting them at night in hired fields by the wayside at pre+ viously chosen points, where they fed, having fasted since morning. The shepherd of each flock marched behind, a bundle containing his kit for the week strapped upon his shoulders, and in his hand his crook, which he used as the staff of his pilgrimage. Several of the sheep would get worn and lame, and occasionally a lambing occurred on the road. To meet these contingencies, there was frequently provided, to accompany the flocks from the remoter points, a pony and waggon into which the weakly ones were taken for the remainder of the journey. The Weatherbury Farms, however, were no such long distance from the hill, and those arrangements were not necessary in their case. But the large united flocks of Bathsheba and Farmer Boldwood formed a valuable and imposing multitude which

demanded much attention, and on this account Gabriel, in addition to Boldwood's shepherd and Cain Ball, accompanied them along the way, through the decayed old town of Kings' bere, and upward to the plateau, -- old George the dog of course behind them. When the autumn sun slanted over Greenhill this morning and lighted the dewy flat upon its crest, nebu+ lous clouds of dust were to be seen floating between the pairs of hedges which streaked the wide prospect around in all directions. These gradually converged upon the base of the hill, and the flocks became individually visible, climbing the serpentine ways which led to the top. Thus, in a slow procession, they entered the opening to which the roads tended, multitude after multitude, horned and hornless -- blue flocks and red flocks, buff flocks and brown flocks, even green and salmon-tinted flocks, according to the fancy of the colourist and custom of the farm. Men were shouting, dogs were barking, with greatest animation, but the thronging travellers in so long a journey had grown nearly indifferent to such terrors, though they still bleated piteously at the unwontedness of their experi+ ences, a tall shepherd rising here and there in the midst of them, like a gigantic idol amid a crowd of prostrate devotees. The great mass of sheep in the fair consisted of South Downs and the old Wessex horned breeds, to the latter class Bathsheba's and Farmer Boldwood's mainly belonged. These filed in about nine o'clock, their vermiculated horns lopping gracefully on each side of their cheeks in geometrically perfect spirals, a small pink and white ear nestling under each horn. Before and behind came other varieties, perfect leopards as to the full rich substance of their coats, and only lacking the spots. There were also a few of the Oxfordshire breeed, whose wool was beginning to curl like a child's flaxen hair, though surpassed in this respect by the effeminate Leicesters, which were in turn less curly than the Cots+ wolds. But the most picturesque by far was a small flock of Exmoors, which chanced to be there this year. Their pied faces and legs, dark and heavy horns, tresses of wool hanging round their swarthy

foreheads, quite relieved the monotony of the flocks in that quarter. All these bleating, panting, and weary thousands had entered and were penned before the morning had far advanced, the dog belonging to each flock being tied to the corner of the pen containing it. Alleys for pedes+ trians intersected the pens, which soon became crowded with buyers and sellers from far and near. In another part of the hill an altogether different scene began to force itself upon the eye towards mid+ day. A circular tent, of exceptional newness and size, was in course of erection here. As the day drew on, the flocks began to change hands, lightening the shep+ herd's responsibilities ; and they turned their attention to this tent and inquired of a man at work there, whose soul seemed concentrated on tying a bothering knot in no time, what was going on. ' The Royal Hippodrome Performance of Turpin's Ride to York and the Death of Black Bess,' replied the man promptly, without turning his eyes or leaving off tying. As soon as the tent was completed the band struck up highly stimulating harmonies, and the announce+ ment was publicly made, Black Bess standing in a con+ spicuous position on the outside, as a living proof, If proof were wanted, of the truth of the oracular utterances from the stage over which the people were to enter. These were so convinced by such genuine appeals to heart and understanding both that they soon began to crowd in abundantly, among the foremost being visible Jan Coggan and Joseph Poorgrass, who were holiday keeping here to-day, ''That's the great ruffen pushing me .! ' screamed a woman in front of Jan over her shoulder at him when the rush was at its fiercest. 'How can I help pushing ye when the folk behind push me ?' said Coggan, in a deprecating tone, turning without turning his body, which was jammed as in a vice. Tjere was a silence ; then the drums and trumpets again sent forth their echoing notes. The crowd was again ectasied,

and gave another lurch in which Coggan and Poorgrass were again thrust by those behind upon the women in front. 'O that helpless feymels should be at the mercy of she swayed like a reed shaken by the wind. Now,' said Coggan, appealing in an earnest voice to the public at large as it stood clustered about his shoulder-blades,'ded ye ever hear such onreasonable woman as that ? Upon my carcase, neighbours, if I could onlyu get out of this cheesewring, the damn women might eat the show for me.! ' 'Don't ye lose yer temper, Jan!' implored Joseph Poorgrass, in a whisper. ' They might get their men to murder us, for I think by the shine of their eyes that they be a sinful form of womankind.' Jan held his tongue, as if he had no objection to be pacified to please a friend, and they gradually reached the foot of the ladder, Poorgrass being flattened like a jumping-jack, and the sixpence, for admission, which he had got ready half-an-hour earlier, having become so reeking hot in the tight squeeze of his excited hand that the woman in spangles, brazen rings set with glass diamonds, and with chalked face and shoulders, who took the money of him, hastily dropped it again from a fear that some trick had been played to burn her fingers. So they all entered, and the cloth of the tent, to the eyes of an observer on the outside, became bulged into innumerable pimples such as we observe on a sack of potatoes, caused by the various human heads, backs, and elbows at high pressure within. At the rear of the large tent there were two small dressing-tents. One of these, alloted to the male per+ formers, was partitioned into halves by a cloth ; and in one of the divisions there was sitting on the grass, puli ing on a pair of jack-boots, a young man whom we instantly recognise as Sergeant Troy. Troy's appearance in this position may be briefly accounted for. The brig aboard which he was taken in Budmouth Roads was about to start on a voyage, though somewhat short of hands. Troy read the articles and joined, but before they sailed a boat was despatched across the bay to Lulwind cove; as he

had half expected, his clothes were gone. He ultimately worked his passage to the United States, where he made a precarious living in various towns as Professor of Gymnastics, Sword Exercise, Fencing, and Pugilism. A few months were sufficient to give him a distaste for this kind of life. There was a certain animal form of refinement in his nature; and however pleasant a strange condition might be whilst privations were easily warded off, it was dis+ advantageously coarse when money was short. There was ever present, too, the idea that he could claim a home and its comforts did he but chose to return to England and Weatherbury Farm. Whether Bathsheba thought him dead was a frequent subject of curious conjecture. To England he did return at last ; but the but the fact of drawing nearer to Weatherbury abstracted its fascinations, and his intention to enter his old groove at the place became modified. It was with gloom he con+ sidered on landing at Liverpool that if he were to go home his reception would be of a kind very unpleasant to con+ template ; for what Troy had in the way of emotion was an occasional fitful sentiment which sometimes caused him as much inconvenience as emotion of a strong and healthy kind. Bathsheba was not a women to be made a fool of, or a woman to suffer in silence; and how could he endure existence with a spirited wife to whom at first entering he would be beholden for food and lodging ? Moreover, it was not at all unlikely that his wife would fail at her farming, if she had not already done so; and he would then become liable for her maintenance : and what a life such a future of poverty with her would be, the spectre of Fanny constantly be+ tween them, harrowing his temper and embittering her words! Thus, for reasons touching on distaste, regret, and shame commingled, he put off his return from day to day, and would have decided to put it off altogether if he could have found anywhere else the ready-made establishment which existed for him there. At this time -- the July preceding the September in which we find at Greenhill Fair -- he fell in with a travelling circus which was performing in the outskirts of a northern town. Troy introduced himself to the manager by taming a restive horse of the troupe, hitting a suspended apple with pistol-+

bullet fired from the animal's back when in full gallop, and other feats. For his merits in these -- all more or less based upon his ex+ periences as a dragoon-guardsman -- Troy was taken into the company, and the play of Turpin was prepared with a view to his personation of the chief character. Troy was not greatly elated by the appreciative spirit in which he was undoubtedly treated, but he thought the engage+ ment might afford him a few weeks for consideration. It was thus carelessly, and without having formed any definite plan for the future, that Troy found himself at Greenhill Fair with the rest of the company on this day. And now the mild autumn sun got lower, and in front of the pavilion the following incident had taken place. Bathsheba -- who was driven to the fair that day by her odd man Poorgrass -- had, like every one else, read or heard the announcement that Mr. Francis, the Great Cosmopolitan Equestrian and Roughrider, would enact the part of Turpin, and she was not yet too old and careworn to be without a little curiosity to see him. This particular show was by far the largest and grandest in the fair, a horde of little shows grouping themselves under its shade like chickens around a hen. The crowd had passed in, and Boldwood, who had been watching all the day for an opportunity of speaking to her, seeing her comparatively isolated, came up to her side. "I hope the sheep have done well to-day, Mrs. Troy?' he said, nervously. "O yes, thank you,' said Bathsheba, colour springing up in the centre of her cheeks. "I was fortunate enough to sell them all just as we got upon the hill, so we hadn't to pen at all.' "And now you are entirely at leisure ?' "Yes, except that I have to see one more dealer in two hours' time : otherwise I should be going home. was looking at this large tent and the announcement. Have you ever seen the play of "Turpin's Ride to York?" Turpin was a real man, was he not ?' "O yes, perfectly true -- all of it. Indeed, I think I've heard Jan Coggan say that a relation of his knew Tom King, Turpin's friend, quite well.'

"Coggan is rather given to strange stories connected with his relations, we must remember. I hope they can all be believed.' "Yes, yes; we know Coggan. But Turpin is true enough. You have never seen it played, I suppose?' "Never. I was not allowed to go into these places when I was young. Hark.! What's that prancing? How they shout!' "Black Bess just started off, I suppose. Am I right in supposing you would like to see the performance, Mrs. Troy ? Please excuse my mistake, if it is one; but if you would like to, I'll get a seat for you with pleasure.' Perceiving that she hesitated, he added, 'I myself shall not stay to see it: I've seen it before.' Now Bathsheba did care a little to see the show, and had only withheld her feet from the ladder because she feared to go in alone. She had been hoping that Oak might appear, whose assistance in such cases was always accepted as an inalienable right, but Oak was nowhere to be seen; and hence it was that she said, "Then if you will just look in first, to see if there's room, I think I will go in for a minute or two.' And so a short time after this Bathsheba appeared in the tent with Boldwood at her elbow, who, taking her to a " reserved ' seat, again withdrew. This feature consisted of one raised bench in very conspicuous part of the circle, covered with red cloth, and floored with a piece of carpet, and Bathsheba immediately found, to her confusion, that she was the single reserved individual in the tent, the rest of the crowded spectators, one and all, standing on their legs on the borders of the arena, where they got twice as good a view of the performance for half the money. Hence as many eyes were turned upon her, enthroned alone in this place of honour, against a scarlet back+ ground, as upon the ponies and clown who were engaged in preliminary exploits in the centre, Turpin not having yet appeared. Once there, Bathsheba was forced to make the best of it and remain: she sat down, spreading her skirts with some dignity over the unoccupied space on each side of her, and giving a new and feminine aspect to the pavilion. In a few minutes she noticed the fat red nape of Coggan's neck among those standing just

below her, and Joseph Poor+ grass's saintly profile a little further on. The interior was shadowy with a peculiar shade. The strange luminous semi-opacities of fine autumn afternoons and eves intensified into Rembrandt effects the few yellow sunbeams which came through holes and divisions in the canvas, and spirted like jets of gold-dust across the dusky blue atmosphere of haze pervading the tent, until they alighted on inner surfaces of cloth opposite, and shone like little lamps suspended there. Troy, on peeping from his dressing-tent through a slit for a reconnoitre before entering, saw his unconscious wife on high before him as described, sitting as queen of the tournament. He started back in utter confusion, for although his disguise efectually concealed his person+ ality, he instantly felt that she would be sure to recognize his voice. He had several times during the day thought of the possibility of some Weatherbury person or other appearing and recognizing him; but he had taken the risk carelessly. If they see me, let them, he had said. But here was Bathsheba in her own person; and the reality of the scene was so much intenser than any of his prefigurings that he felt he had not half enough considered the point. She looked so charming and fair that his cool mood about Weatherbury people was changed. He had not expected her to exercise this power over him in the twinkling of an eye. Should he go on, and care nothing ? He could not bring himself to do that. Beyond a politic wish to remain unknown, there suddenly arose in him now a sense of shame at the possibility that his attractive young wife, who already despised him, should despise him more by discovering him in so mean a condition after so long a time. He actually blushed at the thought, and was vexed beyond measure that his sentiments of dislike towards Weatherbury should have led him to dally about the country in this way. But Troy was never more clever than when absolutely at his wit's end. He hastily thrust aside the curtain dividing his own little dressing space from that of the manager and proprietor, who now appeared as the individual called Tom King as far

down as his waist, and as the aforesaid respectable manager thence to his toes. "Here's the devil to pay!' said Troy. "How's that ?' "Why, there's a blackguard creditor in the tent I don't want to see, who'll discover me and nab me as sure as Satan if I open my mouth. What's to be done?' You must appear now, I think.' "I can't.' But the play must proceed.' "Do you give out that Turpin has got a bad cold, and can't speak his part, but that he'll perform it just the same without speaking.' The proprietor shook his head. "Anyhow, play or no play, I won't open my mouth, said Troy, firmly. "Very well, then let me see. I tell you how we'll manage,' said the other, who perhaps felt it would be extremely awkward to offend his leading man just at this time. "I won't tell 'em anything about your keeping silence; go on with the piece and say nothing, doing what you can by a judicious wink now and then, and a few indomitable nods in the heroic places, you know. They'll never find out that the speeches are omitted.' This seemed feasible enough, for Turpin's speeches were not many or long, the fascination of the piece lying entirely in the action ; and accordingly the play began, and at the appointed time Black Bess leapt into the grassy circle amid the plaudits of the spectators. At the turnpike scene, where Bess and Turpin are hotly pursued at midnight by the officers, and half-awake gatekeeper in his tasselled nightcap denies that any horseman has passed, Coggan uttered a broad-chested "Well done!' which could be heard all over the fair above the bleating, and Poorgrass smiled delightedly with a nice sense of dramatic contrast between our hero, who coolly leaps the gate, and halting justice in the form of his enemies, who must needs pull up cumbersomely and wait to be let through. At the death of Tom King, he could not refrain from seizing Coggan by the hand, and whispering, with tears in his eyes, "Of

course he's not really shot, Jan -- only seemingly!' And when the last sad scene came on, and the body of the gallant and faithful Bess had to be carried out on a shutter by twelve volunteers from among the spectators, nothing could restrain Poorgrass from lending a hand, exclaiming, as he asked Jan to join him, "Twill be something to tell of at Warren's in future years, Jan, and hand down to our children.' For many a year in Weatherbury, Joseph told, with the air of a man who had had experiences in his time, that he touched with his own hand the hoof of Bess as she lay upon the board upon his shoulder. If, as some thinkers hold, immortality consists in being enshrined in others' memories, then did Black Bess become immortal that day if she never had done so before. Meanwhile Troy had added a few touches to his ordinary make-up for the character, the more effectually to disguise himself, and though he had felt faint qualms on first entering, the metamorphosis effected by judici+ ously "lining' his face with a wire rendered him safe from the eyes of Bathsheba and her men. Nevertheless, he was relieved when it was got through. There a second performance in the evening, and the tent was lighted up. Troy had taken his part very quietly this time, venturing to indroduce a few speeches on occasion ; and was just concluding it when, whilst standing at the edge of the circle contiguous to the first row of spectators, he observed within a yard of him the eye of a man darted keenly into his side features. Troy hastily shifted his position, after having recognized in sworn enemy, who still hung about the outskirts of At first Troy resolved to take no notice and abide by circumstances. That he had been recongnized by this man was highly probable; yet there was room for a doubt. Then the great objection he had felt to allowing news of his proximity to precede him to Weatherbury in the event of his return, based on a feeling that knowledge of his present occupation would discredit him still further in his wife's eyes, returned in full force. Moreover, should he resolve not to return at all, a tale of his being alive and being in the neighbourhood would be

awkward ; and he was anxious to acquire a knowledge of his wife's temporal affairs before deciding which to do. In this dilemma Troy at once went out to recon+ noitre. It occurred to him that to find Pennyways, and make a friend of him if possible, would be a very wise act. He had put on a thick beard borrowed from the establishment, and this he wandered about the fair+ field. It was now almost dark, and respectable people were getting their carts and gigs ready to go home The largest refreshment booth in the fair was provided by an innkeeper from a neighbouring town. This was considered an unexceptionable place for obtaining the necessary food and rest: Host Trencher (as he was jauntily called by the local newspaper) being a sub+ stantial man of high repute for catering through all the county round. The tent was divided into first and second-class compartments, and at the end of the first+ class division was a yet further enclosure for the most exclusive, fenced of from the body of the tent by a luncheon-bar, behind which the host himself stood bustling about in white apron and shirt-sleeves, and look+ ing as if he had never lived anywhere but under canvas all his life. In these penetralia were chairs and a table, which, on candles being lighted, made quite a cozy and luxurious show, with an urn, plated tea and coffee pots, china teacups, and plum cakes. Troy stood at the entrance to the booth, where a gipsy-woman was frying pancakes over a little fire of sticks and selling them at a penny a-piece, and looked over the heads of the people within. He could see nothing of Pennyways, but he soon discerned Bathsheba through an opening into the reserved space at the further end. Troy thereupon retreated, went round the tent into the darkness, and listened. He could hear Bathsheba's voice immediately inside the canvas ; she was conversing with a man. A warmth overspread his face: surely she was not so unprincipled as to flirt in a fair! He wondered if, then, she reckoned upon his death as an absolute certainty. To get at the root of the matter, Troy took a penknife from his pocket and softly made two little cuts crosswise in the cloth, which, by folding back the corners left a hole the size of a

wafer. Close to this he placed his face, withdrawing it again in a movement of surprise; for his eye had been within twelve inches of the top of Bathsheba's head. lt was too near to be convenient. He made another hole a little to one side and lower down, in a shaded place beside her chair, from which it was easy and safe to survey her by looking horizontally'. Troy took in the scene completely now. She was leaning back, sipping a cup of tea that she held in her hand, and the owner of the male voice was Boldwood, who had apparently just brought the cup to her, Bathsheba, being in a negligent mood, leant so idly against the canvas that it was pressed to the shape of her shoulder, and she was, in fact, as good as in 'rioy's arms; and he was obliged to keep his breast carefully backward that she might not feel its warmth through the cloth as he gazed in. Troy found unexpected chords of feeling to be stirred again within him as they had been stirred earlier in the day. She was handsome as ever, and she was his. It was some minutes before he could counteract his sudden wish to go in, and claim her. Then he thought how the proud girl who had always looked down upon him even whilst it was to love him, would hate him on dis+ covering him to be a strolling player. Were he to make himself known, that chapter of his life must at all risks be kept for ever from her and from the Weatherbury people, or his name would be a byword throughout the parish. He would be nicknamed 'Turpin' as long as he lived. Assuredly before he could claim her these few past months of his existence must be entirely blotted out. "Shall I get you another cup before you start, ma'am?' said Farmer Boldwood. I thank you," said Bathsheba. " But I must be going at once. It was great neglect in that man to keep me waiting here till so late. I should have gone two hours ago, if it had not been for him. I had no idea of coming in here; but there's nothing so refreshing as a cup of tea, though I should never have got one if you hadn't helped me.' Troy scrutinized her cheek as lit by the candles, and watched each varying shade thereon, and the white shell-like sinuosities

of her little ear. She took out her purse and was insisting to Boldwood on paying for her tea for herself, when at this moment Pennyways entered the tent. Troy trembled : here was his scheme for respectability endangered at once. He was about to leave his hole of espial, attempt to follow Pennyways, and find out if the ex-bailiff had recognized him, when he was arrested by the conversation, and found he was too late. "Excuse me, ma'am,' said Pennyways ; "I've some private information for your ear alone.' "I cannot hear it now,' she said, coldly. That Bathsheba could not endure this man was evident; in fact, he was continually coming to her with some tale or other, by which he might creep into favour at the expense of persons maligned. "I'll write it down,' said Pennyways, confidently. He stooped over the table, pulled a leaf from a warped pocket-book, and wrote upon the paper, in a round hand -- " <1Your husband is here. I've seen him. Who's the fool now?' This he folded small, and handed towards her. Bathsheba would not read it ; she would not even put out her hand to take it. Pennyways, then, with a laugh of derision, tossed it into her lap, and, turning away, left her. From the words and action of Pennyways, Troy, though he had not been able to see what the ex-bailiff wrote, had not a moment's doubt that the note referred to him. Nothing that he could think of could be done to check the exposure. " Curse my luck.!' he whispered, and added imprecations which rustled in the gloom like a pestilent wind. Meanwhile Boldwood said, taking up the note from her lap -- "Don't you wish to read it, Mrs. Troy? If not, I'll destroy it." " Oh, well,' said Bathsheba, carelessly, "perhaps it is unjust not to read it; but I can guess what it is about. He wants me to recommend him, or it is to tell me of some little scandal or another connected with my work+ people. He's always doing that.' Bathsheba held the note in her right hand. Bold+ wood handed towards her a plate of cut bread-and+ butter; when, in order to take a slice, she put the note into her left hand, where she was still holding the purse, and then allowed her hand to drop

beside her close to the canvas. The moment had come for saving his game, and Troy impulsively felt that he would play the card, For yet another time he looked at the fair hand, and saw the pink finger-tips, and the blue veins of the wrrist, encircled by a bracelet of coral chippings which she wore: how familiar it all was to him.! Then, with the lightning action in which he was such an adept, he noiselessly slipped his hand under the bottom of the tent-cloth, which was far from being pinned tightly down, lifted it a little way, keeping his eye to the hole, snatched the note from her fingers, dropped the canvas, and ran away in the gloom towards the bank and ditch, smiling at the scream of astonishment which burst from her. Troy then slid down on the outside of the rampart, hastened round in the bottom of the entrenchment to a distance of a hundred yards, ascended again, and crossed boldly in a slow walk towards the front entrance of the tent. His object was now to get to Pennyways, and prevent a repetition of the announcement until such time as he should choose. Troy reached the tent door, and standing among the groups there gathered, looked anxiously for Pennyways, evidently not wishing to make himself prominent by inquiring for him. One or two men were speaking of a daring attempt that had just been made to rob a young lady by lifting the canvas of the tent beside her. It was supposed that the rogue had imagined a slip of paper which she held in her hand to he a bank note, for he had seized it, and made off with it, leaving her purse behind. His chagrin and disappointment at dis+ covering its worthlessness would be a good joke, it was said. However, the occurrence seemed to have become known to few, for it had not interrupted a fiddler, who had lately begun playing by the door of the tent, nor the four bowed old men with grim countenances and walking-sticks in hand, who were dancing "Major Malley's Reel' to the tune. Behind these stood Pennyways. Troy glided up to him, beckoned, and whispered a few words ; and with a mutual glance of concurrence the two men went into the night together.

BATHSHEBA TALKS WITH HER OUTRIDER THE arrangement for getting back again to Weather+ bury had been that Oak should take the place of Poor+ grass in Bathsheba's conveyance and drive her home, it being discovered late in the afternoon that Joseph was suffering from his old complaint, a multiplying eye, and was, therefore, hardly trustworthy as coachman and protector to a woman. But Oak had found himself so occupied, and was full of so many cares relative to those portions of Boldwood's flocks that were not disposed of, that Bathsheba, without telling Oak or anybody, resolved to drive home herself, as she had many times done from Casterbridge Market, and trust to her good angel for performing the journey un+ molested. But having fallen in with Farmer Boldwood accidentally (on her part at least) at the refreshment+ tent, she found it impossible to refuse his offer to ride on horseback beside her as escort. It had grown twilight before she was aware, but Boldwood assured her that there was no cause for uneasiness, as the moon would be up in half-an-hour. Immediately after the incident in the tent, she had risen to go -- now absolutely alarmed and really grateful for her old lover's protection -- though regretting Gabriel's absence, whose company she would have much preferred, as being more proper as well as more pleasant, since he was her own managing-man and servant. This, how+ ever, could not be helped; she would not, on any consideration, treat Boldwood harshly, having once already iliused him, and the moon having risen, and the gig being ready, she drove across the hilitop in the wending way's which led downwards -- to oblivious obscurity, as it seemed, for the moon and the hill it flooded with light were in appearance on a level, the rest of the world lying as a vast shady concave between them. Boldwood mounted his horse, and

followed in close attendance behind. Thus they descended into the lowlands, and the sounds of those left on the hill came like voices from the sky, and the lights were as those of a camp in heaven. They soon passed the merry stragglers in the immediate vicinity of the hill, traversed Kingsbere, and got upon the high road. The keen instincts of Bathsheba had perceived that the farmer's staunch devotion to herself was still un+ diminished, and she sympathized deeply. The sight had quite depressed her this evening; had reminded her of her folly; she wished anew, as she had wished many months ago, for some means of making repara+ tion for her fault. Hence her pity for the man who so persistently loved on to his own injury and per+ manent gloom had betrayed Bathsheba into an injudi+ cious considerateness of manner, which appeared almost like tenderness, and gave new vigour to the exquisite dream of a Jacob's seven years service in poor Boldwood's mind. He soon found an excuse for advancing from his position in the rear, and rode close by her side. They had gone two or three miles in the moonlight, speaking desultorily across the wheel of her gig concerning the fair, farming, Oak's usefulness to them both, and other indifferent subjects, when Boldwood said suddenly and simply -- "Mrs. Troy, you will marry again some day?' This point-blank query unmistakably confused her, it was not till a minute or more had elapsed that she said, "I have not seriously thought of any such subject.' "I quite understand that. Yet your late husband has been dead nearly one year, and -- ' " You forget that his death was never absolutely proved, and may not have taken place; so that I may not be really a widow,' she said, catching at the straw of escape that the fact afforded "Not absolutely proved, perhaps, but it was proved circumstantially. A man saw him drowning, too. No reasonable person has any doubt of his death; nor have you, ma'am, I should imagine. "O yes I have, or I should have acted differently,' she said, gently. "From the first, I have had a strange uaccountable

feeling that he could not have perished, but I have been able to explain that in several ways since. Even were I half persuaded that I shall see him no more, I am far from thinking of marriage with another. I should be very contemptible to indulge in such a thought.' They were silent now awhile, and having struck into an unfrequented track across a common, the creaks of Boldwood's saddle and gig springs were all the sounds to be heard. Boldwood ended the pause. "Do you remember when I carried you fainting in my arms into the King's Arms, in Casterbridge? Every dog has his day: that was mine.' "I know-i know it all,' she said, hurriedly. "I, for one, shall never cease regretting that events so fell out as to deny you to me.' "I, too, am very sorry,' she said, and then checked herself. "I mean, you know, I am sorry you thought i -- ' "I have always this dreary pleasure in thinking over those past times with you -- that I was something to you before <1he>1 was anything, and that you belonged <1almost>1 to me. But, of course, that's nothing. You never liked me.' " I did ; and respected you, too.' "Do you now?' "Yes.' "Which?' "How do you mean which?' "Do you like me, or do you respect me?' "I don't know -- at least, I cannot tell you. It is difficult for a woman to define her feelings in language which is chiefly made by men to express theirs. My treatment of you was thoughtless, inexcusable, wicked.! I shall eternally regret it. If there had been anything I could have done to make amends I would most gladly have done it -- there was nothing on earth I so longed to do as to repair the error. But that was not possible.' "Don't blame yourself -- you were not so far in the wrong as you suppose. Bathsheba, suppose you had real complete proof

that you are what, in fact, you are -- a widow -- would you repair the old wrong to me by marrying me?' "I cannot say. I shouldn't yet, at any rate.' "But you might at some future time of your life?' "O yes, I might at some time.' "Well, then, do you know that without further proof of any kind you may marry again in about six years from the present -- subject to nobody's objection or blame?' "O yes,' she said, quickly. " I know all that. But don't talk of it -- seven or six years -- where may we all be by that time?' "They will soon glide by, and it will seem an astonishingly short time to look back upon when they are past -- much less than to look forward to now.' "Yes, yes; I have found that in my own experience.' " Now listen once more,' Boldwood pleaded. "If I wait that time, will you marry me? You own that you owe me amends-iet that be your way of making them.' "But, Mr. Boldwood -- six years -- ' "Do you want to be the wife of any other man?' "No indeed! I mean, that I don't like to talk about this matter now. Perhaps it is not proper, and I ought not to allow it. Let us drop it. My husband may be living, as I said.' "Of course, I'll drop the subject if you wish. But propriety has nothing to do with reasons. I am a middle-aged man, willing to protect you for the remainder of our lives. On your side, at least, there is no passion or blamable haste -- on mine, perhaps, there is. But I can't help seeing that if you choose from a feeling of pity, and, as you say, a wish to make amends, to make a bargain with me for a far-ahead time -- an agreement which will set all things right and make me happy, late though it may be -- there is no fault to be found with you as a woman. Had'nt I the first place beside you? Haven't you been almost mine once already? Surely you can say to me as much as this, you will have me back again should circumstances permit ? Now, pray speak ! O Bathsheba, promise -- it is only a little promise -- that if you marry again, you will marry me.!' His tone was so excited that she almost feared him at this

moment, even whilst she sympathized. It was a simple physical fear -- the weak of the strong; there no emotional aversion or inner repugnance. She said, with some distress in her voice, for she remembered vividly his outburst on the Yalbury Road, and shrank from a repetition of his anger: -- "I will never marry another man whilst you wish me to be your wife, whatever comes -- but to say more -- you have taken me so by surprise -- -' "But let it stand in these simple words -- that in six years' time you will be my wife ? Unexpected accidents we'll not mention, because those, of course, must be given way to. Now, this time I know you will keep your word.' "That's why I hesitate to give it.' "But do give it ! Remember the past, and be kind.' She breathed; and then said mournfully : "O what shall I do ? I don't love you, and I much fear that I never shall love you as much as a woman ought to love a husband. If you, sir, know that, and I can yet give you happiness by a mere promise to marry at the end of six years, if my husband should not come back, it is a great honour to me. And if you value such an act of friendship from a woman who doesn't esteem her+ self as she did, and has little love left, why it wili -- ' "Promise!.' " -- Consider, if I cannot promise soon.' "But soon is perhaps never?' "O no, it is not.! I mean soon. Christmas, we'll say.' "Christmas.!' He said nothing further till he added : "Well, I'll say no more to you about it till that time.' Bathsheba was in a very peculiar state of mind, which showed how entirely the soul is the slave of the body, the ethereal spirit dependent for its quality upon the tangible flesh and blood. It is hardly too much to say that she felt coerced by a force stronger than her own will, not only into the act of promising upon this singularly remote and vague matter, but into the emo+ tion of fancying that she ought to promise. When the weeks intervening between the night of this conversa+

tion and Christmas day began perceptibly to diminish, her anxiety and perplexity increased. One day she was led by an accident into an oddly confidential dialogue with Gabriel about her difficulty It afforded her a little relief -- of a dull and cheerless kind. They were auditing accounts, and something occurred in the course of their labours which led Oak to say, speaking of Boldwood, " He'll never forget you, ma'am, never.' Then out came her trouble before she was aware ; and she told him how she had again got into the toils; what Boldwood had asked her, and how he was ex+ pecting her assent. "The most mournful reason of all for my agreeing to it,' she said sadly, 'and the true reason why I think to do so for good or for evil, is this -- it is a thing I have not breathed to a living soul as yet-i believe that if I don't give my word, he'll go out of his mind.' "Really, do ye?' said Gabriel, gravely. 'I believe this,' she continued, with reckless frank+ ness; "and Heaven knows I say it in a spirit the very reverse of vain, for I am grieved and troubled to my soul about it-i believe I hold that man's future in my hand. His career depends entirely upon my treatment of him. O Gabriel, I tremble at my responsibility, for it is terrible.!' "Well, I think this much, ma'am, as I told you years ago,' said Oak, 'that his life is a total blank whenever he isn't hoping for 'ee; but I can't suppose-i hope that nothing so dreadful hangs on to it as you fancy. His natural manner has always been dark and strange, you know. But since the case is so sad and oddiike, why don't ye give the conditional promise? I think I would.' "But is it right? Some rash acts of my past life have taught me that a watched woman must have very much circumspection to retain only a very little credit, and I do want and long to be discreet in this! And six years -- why we may all be in our graves by that BATHSHEBA TALKS WITH OAK time, even if Mr. Troy does not come back again, which he may not impossibly do.! Such thoughts give a sort of absurdity to the scheme. Now, isn't it preposterous,

Gabriel? However he came to dream of it, I cannot think. But is it wrong? You know -- you are older than I.' "Eight years older, ma'am.' "Yes, eight years -- and is it wrong?' "Perhaps it would be an uncommon agreement for a man and woman to make : I don't see anything really wrong about it,' said Oak, slowly. "In fact the very thing that makes it doubtful if you ought to marry en under any condition, that is, your not caring about him -- for I may suppose -- -- ' "Yes, you may suppose that love is wanting,' she said shortly. "Love is an utterly bygone, sorry, worn+ out, miserable thing with me -- for him or any one else.' "Well, your want of love seems to me the one thing that takes away harm from such an agreement with him. If wild heat had to do wi' it, making ye long to over+ come the awkwardness about your husband's vanishing, it mid be wrong ; but a cold-hearted agreement to oblige a man seems different, somehow. The real sin, ma'am in my mind, lies in thinking of ever wedding wi' a man you don't love honest and true.' "That I'm willing to pay the penalty of,' said Bath+ sheba, firmly. " You know, Gabriel, this is what I can+ not get off my conscience -- that I once seriously injured him in sheer idleness. If I had never played a trick upon him, he would never have wanted to marry me. O if I could only pay some heavy damages in money to him for the harm I did, and so get the sin off my soul that way!... Well, there's the debt, which can only be discharged in one way, and I believe I am bound to do it if it honestly lies in my power, without any consideration of my own future at all. When a rake gambles away his expectations, the fact that it is an inconvenient debt doesn't make him the less liable. I've been a rake, and the single point I ask you is, con+ sidering that my own scruples, and the fact that in the eye of the law my husband is only missing, will keep any man from marrying me until seven years have passed -- am I free to entertain such an idea, even though 'tis a sort of penance -- for it will be that? I hate the act of marriage under such circumstances, and the class of women I should seem to belong to by doing it!'

"It seems to me that all depends upon whe'r you think, as everybody else do, that your husband is dead.' "I shall get to, I suppose, because I cannot help feeling what would have brought him back long before this time if he had lived.' "Well, then, in religious sense you will be as free to <1think>1 o' marrying again as any real widow of one year's standing. But why don't ye ask Mr. Thirdly's advice on how to treat Mr. Boldwood?' "No. When I want a broad-minded opinion for general enlightenment, distinct from special advice, I never go to a man who deals in the subject pro+ fessionally. So I like the parson's opinion on law, the lawyer's on doctoring, the doctor's on business, and my business-man's -- that is, yours -- on morals.' 'And on love -- -- ' "My own.' "I'm afraid there's a hitch in that argument,' said Oak, with a grave smile. She did not reply at once, and then saying, 'Good evening Mr. Oak,' went away. She had spoken frankly, and neither asked nor ex+ pected any reply from Gabriel more satisfactory than that she had obtained. Yet in the centremost parts of her complicated heart there existed at this minute a little pang of disappointment, for a reason she would not allow herself to recognize. Oak had not once wished her free that he might marry her himself -- had not once said, "I could wait for you as well as he.' That was the insect sting. Not that she would have listened to any such hypothesis. O no -- for wasn't she saying all the time that such thoughts of the future were improper, and wasn't Gabriel far too poor a man to speak sentiment to her? Yet he might have just hinted about that old love of his, and asked, in a playful off-hand way, if he might speak of it. It would have seemed pretty and sweet, if no more; and then she would have shown how kind and inoffensive a woman's "No' can sometimes be. But to give such cool advice -- the very advice she had asked for -- it ruffled our heroine all the afternoon.

CONVERGING COURSES I CHRISTMAS-EVE came, and a party that Boldwood was to give in the evening was the great subject of talk in Weatherbury. It was not that the rarity of Christmas parties in the parish made this one a wonder, but that Boldwood should be the giver. The announcement had had an abnormal and incongruous sound, as if one should hear of croquet-playing in a cathedral aisle, or that some much-respected judge was going upon the stage. That the party was intended to be a truly jovial one there was no room for doubt. A large bough of mistletoe had been brought from the woods that day, and suspended in the hall of the bachelor's home. Holly and ivy had followed in armfuls. From six that morning till past noon the huge wood fire in the kitchen roared and sparkled at its highest, the kettle, the saucepan, and the threeiegged pot appearing in the midst of the flames like Shadrach, Meshach, and Abednego ; moreover, roasting and basting operations were continually carried on in front of the genial blaze. As it grew later the fire was made up in the large long hall into which the staircase descended, and all encumbrances were cleared out for dancing. The log which was to form the back-brand of the evening fire was the uncleft trunk of a tree, so unwieldy that it could be neither brought nor rolled to its place ; and accord+ ingly two men were to be observed dragging and heaving it in by chains and levers as the hour of assembly drew near. In spite of all this, the spirit of revelry was wanting In the atmosphere of the house. Such a thing had never been attempted before by its owner, and it was now done as by a wrench. Intended gaieties would insist upon appearing like solemn grandeurs, the organ+ ization of the whole effort was

carried out coldly,by hirelings, and a shadow seemed to move about the rooms, saying that the proceedings were unnatural to the place and the lone man who lived therein, and hence not good. Bathsheba was at this time in her room, dressing for the event. She had called for candles, and Liddy entered and placed one on each side of her mistress's glass. "Don't go away, Liddy,' said Bathsheba, almost timidly.' I am foolishly agitated-i cannot tell why. I wish I had not been obliged to go to this dance; but there's no escaping now. I have not spoken to Mr. Boldwood since the autumn, when I promised to see him at Christmas on business, but I had no idea there was to be anything of this kind.' "But I would go now,' said Liddy, who was going with her; for Boldwood had been indiscriminate in his invitations. "Yes, I shall make my appearance, of course,' said Bathsheba. ' But I am <1the cause>1 of the party, and that upsets me! -- Don't tell, Liddy.' "O no, ma'am, You the cause of it, ma'am ?' "Yes. I am the reason of the party-i. If it had not been for me, there would never have been one. I can't explain any more -- there's no more to be explained. I wish I had never seen Weatherbury.' "That's wicked of you -- to wish to be worse off than you are.' "No, Liddy. I have never been free from trouble since I have lived here, and this party is likely to bring me more. Now, fetch my black silk dress, and see how it sits upon me.' "But you will leave off that, surely, ma'am? You have been a widowiady fourteen months, and ought to brighten up a little on such a night as this.' "Is it necessary? No; I will appear as usual, for if I were to wear any light dress people would say things about me, and I should seem to he rejoicing when I am solemn all the time. The party doesn't suit me a bit; but never mind, stay and help to finish me off.' III

Boldwood was dressing also at this hour. A tailor from Casterbridge was with him, assisting him in the operation of trying on a new coat that had just beem brought home. Never had Boldwood been so fastidious, unreasonable about the fit, and generally difficult to please. The tailor walked round and round him, tugged at the waist, pulled the sleeve, pressed out the collar, and for the first time in his experience Boldwood was not bored+ Times had been when the farmer had exclaimed against all such niceties as childish, but now no philosophic or hasty rebuke whatever was provoked by this man for attaching as much importance to a crease in the coat as to an earthquake in South America. Boldwood at last expressed himself nearly satisfied, and paid the bill, the tailor passing out of the door just as Oak came in to report progress for the day. "Oh, Oak,' said Boldwood. "I shall of course see you here to-night. Make yourself merry. I am deter+ mined that neither expense nor trouble shall be spared.' "I'll try to be here, sir, though perhaps it may not be very early,' said Gabriel, quietly. "I am glad indeed to see such a change in 'ee from what it used to be.' " Yes-i must own it-i am bright to-night : cheerful and more than cheerfui-so much so that I am almost sad again with the sense that all of it is passing away. And sometimes, when I am excessively hopeful and blithe, a trouble is looming in the distance : so that I often get to look upon gloom in me with content, and to fear a happy mood. Still this may be absurd-i feel that it is absurd. Perhaps my day is dawning at last.' "I hope it 'ill be a long and a fair one.' "Thank you -- thank you. Yet perhaps my cheerfui mess rests on a slender hope. And yet I trust my hope. It is faith, not hope. I think this time I reckon with my host. -- Oak, my hands are a little shaky, or some+ thing; I can't tie this neckerchief properly. Perhaps you will tie it for me. The fact is, I have not been well lately, you know.' "I am sorry to hear that, sir.'

"Oh, it's nothing. I want it done as well as you can, please. Is there any late knot in fashion, Oak?' "I don't know, sir,' said Oak. His tone had sunk to sadness. Boldwood approached Gabriel, and as Oak tied the neckerchief the farmer went on feverishly -- "Does a woman keep her promise, Gabriel?' "If it is not inconvenient to her she may.' " -- Or rather an implied promise.' "I won't answer for her implying,' said Oak, with faint bitterness. "That's a word as full o' holes as a sieve with them.' "Oak, don't talk like that. You have got quite cynical lately -- how is it? We seem to have shifted our positions: I have become the young and hopeful man, and you the old and unbelieving one. However, does a woman keep a promise, not to marry, but to enter on an engagement to marry at some time? Now you know women better than i-tell me.' "I am afeard you honour my understanding too much. However, she may keep such a promise, if it is made with an honest meaning to repair a wrong.' "It has not gone far yet, but I think it will soon -- yes, I know it will,' he said, in an impulsive whisper. "I have pressed her upon the subject, and she inclines to be kind to me, and to think of me as a husband at a long future time, and that's enough for me. How can I expect more? She has a notion that a woman should not marry within seven years of her husband's disappearance -- that her own self shouldn't, I mean -- because his body was not found. It may be merely this legal reason which influences her, or it may be a religious one, but she is reluctant to talk on the point+ Yet she has promised -- implied -- that she will ratify an engagement to-night.' "Seven years,' murmured Oak. "No, no -- it's no such thing!' he said, with im+ patience. Five years, nine months, and a few days. Fifteen months nearly have passed since he vanished, and is there anything so wonderful in an engagement of little more than five years?' "It seems long in a forward view. Don't build too much upon such promises, sir. Remember, you have once be'n deceived. Her meaning may be good; but there -- she's young yet.'

"Deceived? Never! ' said Boldwood, vehemently. "She never promised me at that first time, and hence she did not break her promise! If she promises me, she'll marry me, Bathsheba is a woman to her word.' IV Troy was sitting in a corner of The White Hart tavern at Casterbridge, smoking and drinking a steaming mixture from a glass. A knock was given at the door, and Pennyways entered. "Well, have you seen him?' Troy inquired, pointing to a chair. "Boldwood?' "No -- Lawyer Long.' "He wadn' at home. I went there first, too.' "That's a nuisance.' "'Tis rather, I suppose.' "Yet I don't see that, because a man appears to be drowned and was not, he should be liable for anything. I shan't ask any lawyer -- not I.' "But that's not it, exactly. If a man changes his name and so forth, and takes steps to deceive the world and his own wife, he's a cheat, and that in the eye of the law is ayless a rogue, and that is ayless a lammocken vagabond; and that's a punishable situation.' "Ha-ha! Well done, Pennyways.' Troy had laughed, but it was with some anxiety that he said, "Now, what I want to know is this, do you think there's really anything going on between her and Boldwood? Upon my soul, I should never have believed it! How she. must detest me! Have you found out whether she has encouraged him?' "I haen't been able to learn. There's a deal of feeling on his side seemingly, but I don't answer for her. I didn't know a word about any such thing till yesterday, and all I heard then was that she was gwine to the party at his house to-night. This is the first time she has ever gone there, they say. And they say that she've not so much as spoke to him since they were at Greenhill Fair: but what can folk believe o't ? How+ ever, she's not fond of him -- quite offish and quite care less, I know.'

"I'm not so sure of that.... She's a handsome woman, Pennyways, is she not? Own that you never saw a finer or more splendid creature in your life. Upon my honour, when I set eyes upon her that day I wondered what I could have been made of to be able to leave her by herself so long. And then I was hampered with that bothering show, which I'm free of at last, thank the stars.' He smoked on awhile, and then added, "How did she look when you passed by yesterday?' "Oh, she took no great heed of me, ye may well fancy; but she looked well enough, far's I know. Just flashed her haughty eyes upon my poor scram body, and then let them go past me to what was yond, much as if I'd been no more than a leafless tree. She had just got off her mare to look at the last wring-down of cider for the year; she had been riding, and so her colours were up and her breath rather quick, so that her bosom plimmed and feli-plimmed and feli-every time plain to my eye. Ay, and there were the fellers round her wringing down the cheese and bustling about and saying, Ware o' the pommy, ma'am : 'twill spoil yer gown. "Never mind me," says she. Then Gabe brought her some of the new cider, and she must needs go drinking it through a strawmote, and not in a nateral way at all. "Liddy," says she, "bring indoors a few gallons, and I'll make some cider-wine." Sergeant, I was no more to her than a morsel of scroffin the fuei house!' "I must go and find her out at once -- O yes, I see that-i must go. Oak is head man still, isn't he?' "Yes, 'a b'lieve. And at Little Weatherbury Farm too. He manages everything.' "Twill puzzle him to manage her, or any other man of his compass!' "I don't know about that. She can't do without him, and knowing it well he's pretty independent. And she've a few soft corners to her mind, though I've never been able to get into one, the devil's in't!' "Ah baily she's a notch above you, and you must own it: a higher class of animai-a finer tissue. How+ ever, stick to me, and neither this haughty goddess, dashing piece of womanhood, Juno-wife of mine (Juno was a goddess, you know), nor

anybody else shall hurt you. But all this wants looking into, I perceive. What with one thing and another, I see that my work is well cut out for me.' v "How do I look to-night, Liddy?' said Bathsheba, giving a final adjustment to her dress before leaving the glass. "I never saw you look so well before. Yes-i'll tell you when you looked like it -- that night, a year and a half ago, when you came in so wildiike, and scolded us for making remarks about you and Mr. Troy.' "Everybody will think that I am setting myself to captivate Mr. Boldwood, I suppose,' she murmured. "At least they'll say so. Can't my hair be brushed down a little flatter? I dread going -- yet I dread the risk of wounding him by staying away.' "Anyhow, ma'am, you can't well be dressed plainer than you are, unless you go in sackcloth at once. 'Tis your excitement is what makes you look so noticeable to-night.' "I don't know what's the matter, I feel wretched at one time, and buoyant at another. I wish I could have continued quite alone as I have been for the last year or so, with no hopes and no fears, and no pleasure and no grief. "Now just suppose Mr. Boldwood should ask you -- only just suppose it -- to run away with him, what would you do, ma'am?' "Liddy -- none of that,' said Bathsheba, gravely. "Mind, I won't hear joking on any such matter. Do you hear?' "I beg pardon, ma'am. But knowing what rum things we women be, I just said -- however, I won't speak of it again.' "No marrying for me yet for many a year; if ever, 'twill be for reasons very, very different from those you think, or others will believe! Now get my cloak, for it is time to go.' VI "Oak, said Boldwood, "before you go I want to mention what has been passing in my mind lately -- that little arrangement we made about your share in the farm I mean. That share is small, too small, consider+ ing how little I attend to business now, and how much time and thought you give to it. Well,

since the world is brightening for me, I want to show my sense of it by increasing yopur proportion in the partnership. I'll make a memorandum of the arrangement which struck me as likely to be convenient, for I haven't time to talk about it now; and then we'll discuss it at our leisure. My intention is ultimately to retire from the manage+ ment altogether, and until you can take all the expendi+ ture upon your shoulders, I'll be a sleeping partner in the stock. Then, if I marry her -- and I hope-i feel I shall, why -- -- ' "Pray don't speak of it, sir,' said Oak, hastily. "We don't know what may happen. So many upsets may befall 'ee. There's many a slip, as they say -- and I would advise you-i know you'll pardon me this once -- not to be <1too sure>1.' "I know, I know. But the feeling I have about in+ creasing your share is on account of what I know of you Oak, I have learnt a little about your secret: your interest in her is more than that of bailiff for an em+ ployer. But you have behaved like a man, and I, as a sort of successful rivai-successful partly through your goodness of heart -- should like definitely to show my sense of your friendship under what must have been a great pain to you.' "O that's not necessary, thank 'ee,' said Oak, hurriedly. "I must get used to such as that; other men have, and so shall I.' Oak then left him. He was uneasy on Boldwood's account, for he saw anew that this constant passion of the farmer made him not the man he once had been. As Boldwood continued awhile in his room alone -- ready and dressed to receive his company -- the mood of anxiety about his appearance seemed to pass away, and to be succeeded by a deep solemnity. He looked out of the window, and regarded the dim outline of the trees upon the sky, and the twilight deepening to darkness. Then he went to a locked closet, and took from a locked drawer therein a small circular case the size of a pilibox, and was about to put it into his pocket. But he lingered to open the cover and take a momentary glance inside. It contained a woman's finger-ring, set all the way round with small

diamonds, and from its appearance had evidently been recently purchased. Boldwood's eyes dwelt upon its many sparkles a long time, though that its material aspect concerned him little was plain from his manner and mien, which were those of a mind following out the presumed thread of that jewel's future history. The noise of wheels at the front of the house became audible. Boldwood closed the box, stowed it away carefully in his pocket, and went out upon the landing. The old man who was his indoor factotum came at the same moment to the foot of the stairs. "They be coming, sir-iots of 'em -- a-foot and a+ driving!' "I was coming down this moment. Those wheels I heard -- is it Mrs. Troy?' "No, sir -- 'tis not she yet.' A reserved and sombre expression had returned to Boldwood's face again, but it poorly cloaked his feei ings when he pronounced Bathsheba's name; and his feverish anxiety continued to show its existence by a galloping motion of his fingers upon the side of his thigh as he went down the stairs. VII "How does this cover me?' said Troy to Pennyways, "Nobody would recognize me now, I'm sure.' He was buttoning on a heavy grey overcoat of Noachian cut, with cape and high collar, the latter being erect and rigid, like a girdling wall, and nearly reaching to the verge of travelling cap which was pulled down over his ears. Pennyways snuffed the candle, and then looked up and deliberately inspected Troy "You've made up your mind to go then?' he said. "Made up my mind? Yes; of course I have.' "Why not write to her? 'Tis a very queer corner that you have got into, sergeant. You see all these things will come to light if you go back, and they won't sound well at all. Faith, if I was you I'd even bide as you be -- a single man of the name of Francis. A good wife is good, but the best wife is not so good

as no wife at all. Now that's my outspoke mind, and I've been called a long-headed feller here and there.' "All nonsense!' said Troy, angrily. "There she is with plenty of money, and a house and farm, and horses, and comfort, and here am I living from hand to mouth -- a needy adventurer. Besides, it is no use talking now; it is too late, and I am glad of it ; I've been seen and recognized here this very afternoon. I should have gone back to her the day after the fair, if it hadn't been for you talking about the law, and rubbish about getting a separation; and I don't put it off any longer. What the deuce put it into my head to run away at all, I can't think! Humbugging sentiment -- that's what it was. But what man on earth was to know that his wife would be in such a hurry to get rid of his name!' "I should have known it. She's bad enough for anything.' "Pennyways, mind who you are talking to.' "Well, sergeant, all I say is this, that if I were you I'd go abroad again where I came from -- 'tisn't too late to do it now. I wouldn't stir up the business and get a bad name for the sake of living with her -- for all that about your play-acting is sure to come out, you know, although you think otherwise. My eyes and limbs, there'll be a racket if you go back just now -- in the middle of Bold+ wood's Christmasing!' "H'm, yes. I expect I shall not be a very welcome guest if he has her there,' said the sergeant, with a slight laugh. "A sort of Alonzo the Brave; and when I go in the guests will sit in silence and fear, and all laughter and pleasure will be hushed, and the lights in the chamber burn blue, and the worms -- Ugh, horrible! -- Ring for some more brandy, Pennyways, I felt an awful shudder just then! Well, what is there besides? A stick-i must have a walking-stick.' Pennyways now felt himself to be in something of a difficulty, for should Bathsheba and Troy become recon+ ciled it would be necessary to regain her good opinion if he would secure the patronage of her husband. I sometimes think she likes you yet, and is a good woman at bottom,' he said, as a saving sentence. "But there's no telling to a certainty from a body's outside. Well,

you'll do as you like about going, of course, sergeant, and as for me, I'll do as you tell me.' "Now, let me see what the time is,' said Troy, after emptying his glass in one draught as he stood. 'Half+ past six o'clock. I shall not hurry along the road, and shall be there then before nine.' CONCURRITUR

CONCURRITUR -- HORAE MOMENTO OUTSIDE the front of Boldwood's house a group of men stood in the dark, with their faces towards the door, which occasionally opened and closed for the passage of some guest or servant, when a golden rod of light would stripe the ground for the moment and vanish again, leaving nothing outside but the glowworm shine of the pale lamp amid the evergreens over the door. "He was seen in Casterbridge this afternoon -- so the boy said,' one of them remarked in a whisper. "And l for one believe it. His body was never found, you know.' "'Tis a strange story,' said the next. "You may depend upon't that she knows nothing about it.' "Not a word.' "Perhaps he don't mean that she shall,' said another man. "If he's alive and here in the neighbourhood, he means mischief,' said the first. "Poor young thing: I do pity her, if 'tis true. He'll drag her to the dogs.' "O no; he'll settle down quiet enough,' said one disposed to take a more hopeful view of the case. "What a fool she must have been ever to have had anything to do with the man! She is so self-willed and independent too, that one is more minded to say it serves her right than pity her.' "No, no. I don't hold with 'ee there. She was no otherwise than a girl mind, and how couid she tell what the man was made of? If 'tis really true, 'tis too hard a punishment, and more than she ought to hae. -- Hullo, who's that?' This was to some footsteps that were heard approaching. "William Smallbury,' said a dim figure in the shades, coming up and joining them. 'Dark as a hedge, to+ night, isn't it? I all but missed the plank over the river ath'art there in the bottom --

never did such a thing before in my life. Be ye any of Boldwood's workfolk?' He peered into their faces. "Yes -- all o' us. We met here a few minutes ago.' "Oh, I hear now -- that's Sam Samway : thought I knowed the voice, too. Going in?' "Presently. But I say, William,' Samway whispered, "have ye heard this strange tale?' "What -- that about Sergeant Troy being seen, d'ye mean, souls?' said Smallbury, also lowering his voice. "Ay: in Casterbridge.' "Yes, I have. Laban Tall named a hint of it to me but now -- but I don't think it. Hark, here Laban comes himself, 'a b'lieve.' A footstep drew near. "Laban?' "Yes, 'tis I,' said Tall. "Have ye heard any more about that?' "No,' said Tall, joining the group. "And I'm in+ clined to think we'd better keep quiet. If so be 'tis not true, 'twill flurry her, and do her much harm to repeat it; and if so be 'tis true, 'twill do no good to forestall her time o' trouble. God send that it mid be a lie, for though Henery Fray and some of 'em do speak against her, she's never been anything but fair to me. She's hot and hasty, but she's a brave girl who'll never tell a lie however much the truth may harm her, and I've no cause to wish her evil.' "She never do tell women's little lies, that's true ; and 'tis a thing that can be said of very few. Ay, all the harm she thinks she says to yer face: there's nothing underhand wi' her.' They stood silent then, every man busied with his own thoughts, during which interval sounds of merri+ ment could be heard within. Then the front door again opened, the rays streamed out, the weliknown form of Boldwood was seen in the rectangular area of light, the door closed, and Boldwood walked slowly down the path. "'Tis master,' one of the men whispered, as he neared them. "We'd better stand quiet -- he'll go in again directly. He would think it unseemly o' us to be loitering here. Boldwood came on, and passed by the men without

seeing them, they being under the bushes on the grass. He paused, leant over the gate, and breathed a long breath. They heard low words come from him. "I hope to God she'll come, or this night will be nothing but misery to me! O my darling, my darling, why do you keep me in suspense like this?' He said this to himself, and they all distinctly heard it. Boldwood remained silent after that, and the noise from indoors was again just audible, until, a few minutes later, light wheels could be distinguished coming down the hill. They drew nearer, and ceased at the gate. Boldwood hastened back to the door, and opened it; and the light shone upon Bathsheba coming up the path. Boldwood compressed his emotion to mere welcome: the men marked her light laugh and apology as she met him: he took her into the house; and the door closed again. "Gracious heaven, I didn't know it was like that with him!' said one of the men. "I thought that fancy of his was over long ago. "You don't know much of master, if you thought that,' said Samway. "I wouldn't he should know we heard what 'a said for the world,' remarked a third. "I wish we had told of the report at once,' the first uneasily continued. "More harm may come of this than we know of. Poor Mr. Boldwood, it will, be hard upon en. I wish Troy was in -- -- Well, God forgive me for such a wish! A scoundrel to play a poor wife such tricks. Nothing has prospered in Weatherbury since he came here. And now I've no heart to go in. Let's look into Warren's for a few minutes first, shall us, neighbours?' Samway, Tall, and Smallbury agreed to go to Warren's, and went out at the gate, the remaining ones entering the house. The three soon drew near the malt-house, approaching it from the adjoining orchard, and not by way of the street. The pane of glass was illuminated as usual. Smallbury was a little in advance of the rest when, pausing, he turned suddenly to his companions and said, "Hist! See there.'

The light from the pane was now perceived to be shining not upon the ivied wall as usual, but upon some object close to the glass. It was a human face. "Let's come closer,' whispered Samway; and they approached on tiptoe. There was no disbelieving the report any longer. Troy's face was almost close to the pane, and he was looking in. Not only was he looking in, but he appeared to have been arrested by a conversation which was in progress in the malt-house, the voices of the interlocutors being those of Oak and the maltster. "The spree is all in her honour, isn't it -- hey?' said the old man. "Although he made believe 'tis only keeping up o' Christmas?' "I cannot say,' replied Oak. "O 'tis true enough, faith. I cannot understand Farmer Boldwood being such a fool at his time of life as to ho and hanker after thik woman in the way 'a do, and she not care a bit about en.' The men, after recognizing Troy's features, withdrew across the orchard as quietly as they had come. The air was big with Bathsheba's fortunes to-night : every word everywhere concerned her. When they were quite out of earshot all by one instinct paused. "It gave me quite a turn -- his face,' said Tall, breathing. "And so it did me,' said Samway. "What's to be done?' "I don't see that 'tis any busincss of ours,' Smallbury murmured dubiously. "But it is! 'Tis a thing which is everybody's business, said Samway. "We know very well that master's on a wrong tack, and that she's quite in the dark, and we should let 'em know at once. Laban, you know her best -- you'd better go and ask to speak to her.' "I bain't fit for any such thing,' said Laban, nervously. "I should think William ought to do it if anybody. He's oldest.' "I shall have nothing to do with it,' said Smallbury. "'Tis a ticklish business altogether. Why, he'll go on to her himself in a few minutes, ye'll see.' "We don't know that he will. Come, Laban.'

"Very well, if I must I must, I suppose,' Tall reluct+ antly answered. "What must I say?' "Just ask to see master.' "O no; I shan't speak to Mr. Boldwood. If I tell anybody, 'twill be mistress.' "Very well,' said Samway. Laban then went to the door. When he opened it the hum of bustle rolled out as a wave upon a still strand -- the assemblage being immediately inside the hali-and was deadened to a murmur as he closed it again. Each man waited intently, and looked around at the dark tree tops gently rocking against the sky and occasionally shivering in a slight wind, as if he took interest in the scene, which neither did. One of them began walking up and down, and then came to where he started from and stopped again, with a sense that walking was thing not worth doing now. "I should think Laban must have seen mistress by this time,' said Smallbury, breaking the silence. "Per+ haps she won't come and speak to him.' The door opened. Tall appeared, and joined them "Well?' said both. "I didn't like to ask for her after all,' Laban faltered out. "They were all in such a stir, trying to put a little spirit into the party. Somehow the fun seems to hang fire, though everything's there that a heart can desire, and I couldn't for my soul interfere and throw damp upon it -- if 'twas to save my life, I couldn't!' "I suppose we had better all go in together,' said Samway, gloomily. "Perhaps I may have a chance of saying a word to master.' So the men entered the hall, which was the room sellected and arranged for the gathering because of its size. The younger men and maids were at last just beginning to dance. Bathshesba had been perplexed how to act, for she was not much more than a slim young maid herself, and the weight of stateliness sat heavy upon her. Sometimes she thought she ought not to have come under any circumstances; then she considered what cold unkindness that would have been, and finally resolved

upon the middle course of staying for about an hour only, and gliding off unobserved, having from the first made up her mind that she could on no account dance, sing, or take any active part in the proceedings. Her allotted hour having been passed in chatting and looking on, Bathsheba told Liddy not to hurry her+ self, and went to the small parlour to prepare for departure, which, like the hall, was decorated with holly and ivy, and well lighted up. Nobody was in the room, but she had hardly HORAE MOMENTO been there a moment when the master of the house entered. "Mrs. Troy -- you are not going?' he said. "We've hardly begun!' "If you'll excuse me, I should like to go now.' Her manner was restive, for she remembered her promise, and imagined what he was about to say. "But as it is not late,' she added, "I can walk home, and leave my man and Liddy to come when they choose.' "I've been trying to get an opportunity of speaking to you,' said Boldwood. "You know perhaps what I long to say?' Bathsheba silently looked on the floor. "You do give it?' he said, eagerly. "What?' she whispered. "Now, that's evasion! Why, the promise. I don't want to intrude upon you at all, or to let it become known to anybody. But do give your word! A mere business compact, you know, between two people who are beyond the influence of passicn.' Boldwood knew how false this picture was as regarded himself; but he had proved that it was the only tone in which she would allow him to approach her. "A promise to marry me at the end of five years and three-quarters. You owe it to me!' "I feel that I do,' said Bathsheba ; "that is, if you demand it. But I am a changed woman -- an unhappy woman -- and not -- not -- -- " " You are still a very beautiful woman, said Boldwood. Honesty and pure conviction suggested the remark, unaccompanied by any perception that it might have been adopted by blunt flattery to soothe and win her. However, it had not much effect now, for for she said, in a

passionless murmur which was in itself a proof of her words: "I have no feeling in the matter at all. And I don't at all know what is right to do in my diddicult Position, and I have nobody to advise me. But I give my promise, if I must. I give it as the rendering of a debt, conditionally, of course, on my being a widow.' "You'll marry me between five and six years hence ? ' "Don't press me too hard. I'll marry nobody else.' " But surely you will name the time, or there's nothing in the promise at all?' "O, I don't know, pray let me go!' she said, her bosom beginning to rise. "I am afraid what to do.! want to be just to you, and to be that seems to be wrong+ ing myself, and perhaps it is breaking the commandments. There is considerable doubt of his death, and then it is dreadful; let me ask a solicitor, Mr. Boldwood, if I ought or no!' "Say the words, dear one, and the subject shall be dismissed ; a blissrul loving intimacy of six years, and then marriage -- O Bathsheba, say them!' he begged in a husky voice, unable to sustain the forms of mere friendship any longer. "Promise yourself to me; I deserve it, indeed I do, for I have loved you more than anybody in the world! And if I said hasty words and showed uncalled-for heat of manner towards you, believe me, dear, I did not mean to distress you ; I was in agony, Bathsheba, and I did not know what I said. You wouldn't let a dog suffer what I have suffered, could you but know it! Sometimes I shrink from your knowing what I have felt for you, and sometimes I am distressed that all of it you never will know. Be gracious, and give up a little to me, when I would give up mylife for you!' The trimmings of her dress, as they quivered against the light, showed how agitated she was, and at last she burst out crying. 'And you'll not -- press me -- about anything more -- if I say in five or six years?' she sobbed, when she had power to frame the words. "Yes, then I'll leave it to time.' "Very well. If he does not return, I'll marry you in six years from this day, if we both live,' she said solemnly.

"And you'll take this as a token from me.' Boldwood had come close to her side, and now he clasped one of her hands in both his own, and lifted it to his breast. "What is it? Oh I cannot wear a ring!' she ex+ claimed, on seeing what he held; "besides, I wouldn't have a soul know that it's an engagement! Perhaps it is improper? Besides, we are not engaged in the usual sense, are we ? Don't insist, Mr. Boldwood -- don't!' In her trouble at not being able to get her hand away from him at once, she stamped passionately on the floor with one foot, and tears crowded to her eyes again. "It means simply a pledge -- no sentiment -- the seal of a practical compact,' he said more quictly, but still retaining her hand in his firm grasp. "Come, now!' And Boldwood slipped the ring on her finger. "I cannot wear it,' she said, weeping as if her heart would break. " You frighten me, almost. So wild a scheme! Please let me go home!' " Only to-night : wear it just to-night, to please me!.' Bathsheba sat down in a chair, and buried her face in her handkerchief, though Boldwood kept her hand yet. At length she said, in a sort of hopeless whisper -- "Very well, then, I will to-night, if you wish it so earnestly. Now loosen my hand; I will, indeed I will wear it to-night.' "And it shall be the beginning of a pleasant secret courtship of six years, with a wedding at the end?' "It must be, I suppose, since you will have it so!' she said, fairly beaten into non-resistance. Boldwood pressed her hand, and allowed it to drop in her lap. "I am happy now,' he said. "God bless you!' He left the room, and when he thought she might be sufficiently composed sent one of the maids to her Bathsheba cloaked the effects of the late scene as she best could, followed the girl, and in a few moments came downstairs with her hat and cloak on, ready to go. To get to the door it was necessary to pass through the hall, and before doing so she paused on the bottom of the staircase which descended into one corner, to take a last look at the gathering. There was no music or dancing in progress just now. At the

lower end, which had been arranged for the work+ folk specially, a group conversed in whispers, and with clouded looks. Boldwood was standing by the fireplace, and he, too, though so absorbed in visions arising from her promise that he scarcely saw anything, seemed at that moment to have observed their peculiar manner, and their looks askance. "What is it you are in doubt about, men?' he said. One of them turned and replied uneasily: 'It was something Laban heard of, that's all, sir.' "News? Anybody married or engaged, born or dead?' inquired the farmer, gaily. "Tell it to us, Tall. One would think from your looks and mysterious ways that it was something very dreadful indeed.' "O no, sir, nobody is dead,' said Tall. "I wish somebody was,' said Samway, in a whisper. "What do you say, Samway?' asked Boldwood, some+ what sharply. "If you have anything to say, speak out; if not, get up another dance.' "Mrs. Troy has come downstairs,' said Samway to Tall. "If you want to tell her, you had better do it now.' "Do you know what they mean?' the farmer asked Bathsheba, across the room. "I don't in the least," said Bathsheba. There was a smart rapping at the door. One of the men opened it instantly, and went outside. "Mrs. Troy is wanted,' he said, on returning. "Quite ready,' said Bathsheba. "Though I didn't tell them to send.' "It is a stranger, ma'am,' said the man by the door. "A stranger?' she said. "Ask him to come in,' said Boldwood. The message was given, and Troy, wrapped up to his eyes as we have seen him, stood in the doorway. There was an unearthly silence, all looking towards the newcomer. Those who had just learnt that he was in the neighbourhood recognized him instantly; those who did not were perplexed. Nobody noted Bathsheba. She was leaning on the stairs. Her brow had heavily contracted; her whole face was

pallid, her lips apart, her eyes rigidly staring at their visitor. Boldwood was among those who did not notice that he was Troy. "Come in, come in!' he repeated, cheerfully, "and drain a Christmas beaker with us, stranger!' Troy next advanced into the middle of the room, took off his cap, turned down his coat-collar, and looked Boldwood in the face. Even then Boldwood did not recognize that the impersonator of Heaven's persistent irony towards him, who had once before broken in upon his bliss, scourged him, and snatched his delight away, had come to do these things a second time. Troy began to laugh a mechanical laugh: Boldwood recognized him now. Troy turned to Bathsheba. The poor girl's wretched+ ness at this time was beyond all fancy or narration. She had sunk down on the lowest stair; and there she sat, her mouth blue and dry, and her dark eyes fixed vacantly upon him, as if she wondered whether it were not all a terrible illusion. Then Troy spoke. "Bathsheba, I come here for you!' She made no reply. " Come home with me: come! Bathsheba moved her feet a little, but did not rise. Troy went across to her. "come, madam, do you hear what I say?' he said, peremptorily. A strange voice came from the fireplace -- a voice sounding far off and confined, as if from a dungeon. Hardly a soul in the assembly recognized the thin tones to be those of Boldwood. Sudden dispaire had trans+ formed him. "Bathsheba, go with your husband!' Nevertheless, she did not move. The truth was that Bathsheba was beyond the pale of activity -- and yet not in a swoon. She was in a state of mental <1gutta>1 <1serena>1; her mind was for the minute totally deprived of light at the same time no obscuration was apparent from without. Troy stretched out his hand to pull her her towards him, when she quickly shrank back. This visible dread of him seemed to irritate Troy, and he seized her arm and pulled it sharply.

Whether his grasp pinched her, or whether his mere touch was the ccause, was never known, but at the moment of his seizure she writhed, and gave a quick, low scream. The scream had been heard but a few seconds When it was followed by sudden deafening report that echoed through the room and stupefied them all. The oak partition shook with the concussion, and the place was filled with grey smoke. In bewilderment they turned their eyes to Boldwood. at his back, as stood before the fireplace, was a gun+ rack, as is usual in farmhouses, constructed to hold two guns. When Bathsheba had cried out in her husband's grasp, Boldwood's face of gnashing despair had changed. The veins had swollen, and a frenzied look had gleamed in his eye. He had turned quickly, taken one of the guns, cocked it, and at once discharged it at Troy. Troy fell. The distance apart of the two men was so small that the charge of shot did not spread in the least, but passed like a bullet into his body. He uttered a long guttural sigh -- there was a contraction -- an exten+ sion -- then his muscles relaxed, and he lay still. Boldwood was seen through the smoke to be now again engaged with the gun. It was double-barrelled, and he had, meanwhile, in some way fastened his hand+ kerchief to the trigger, and with his foot on the other end was in the act of turning the second barrel upon himself. Samway his man was the first to see this, and in the midst of the general horror darted up to him. Boldwood had already twitched the handkerchief, and the gun exploded a second time, sending its contents, by a timely blow from Samway, into the beam which crossed the ceiling. "Well, it makes no difference!' Boldwood gasped. "There is another way for me to die.' Then he broke from Samway, crossed the room to Bathsheba, and kissed her hand. He put on his hat, opened the door, and went into the darkness, nobody thinking of preventing him.

AFTER THE SHOCK BOLDWOOD passed into the high road and turned in the direction of Casterbridge. Here he walked at an even, steady pace over Yalbury Hill, along the dead level beyond, mounted Mellstock Hill, and between eleven and twelve o'clock crossed the Moor into the town. The streets were nearly deserted now, and the waving lamp-flames only lighted up rows of grey shop-shutters, and strips of white paving upon which his step echoed as his passed along. He turned to the right, and halted before an archway of heavy stonework, which was closed by an iron studded pair of doors. This was the entrance to the gaol, and over it a lamp was fixed, the light en+ abling the wretched traveller to find a belipull. The small wicket at last opened, and a porter appeared. Boldwood stepped forward, and said some+ thing in a low tone, when, after a delay, another man came. Boldwood entered, and the door was closed behind him, and he walked the world no more. Long before this time Weatherbury had been thoroughly aroused, and the wild deed which had ter+ minated Boldwood's merrymaking became known to all. Of those out of the house Oak was one of the first to hear of the catastophe, and when he entered the room, which was about five minutes after Boldwood's exit, the scene was terrible. All the female guests were huddled aghast against the walls like sheep in a storm, and the men were bewildered as to what to do. As for Bathsheba, she had changed. She was sitting on the floor beside the body of Troy, his head pillowed in her lap, where she had herself lifted it. With one hand she held her handkerchief to his breast and covered the wound, though scarcely a single drop of blood had flowed, and with the other she tightly clasped one of his. The household convulsion had made her herself again. The

temporary coma had ceased, and activity had come with the necessity for it. Deeds of endur+ ance, which seem ordinary in philosophy, are rare in conduct, and Bathsheba was astonishing all around her now, for her philosophy was her conduct, and she seldom thought practicable what she did not practise. She was of the stuff of which great men's mothers are made. She was indispensable to high generation, hated at tea parties, feared in shops, and loved at crises. Troy recumbent in his wife's lap formed now the sole spectacle in the middle of the spacious room. "Gabriel,' she said, automatically, when he entered, turning up a face of which only the weliknown lines remained to tell him it was hers, all else in the picture having faded quite. "Ride to Casterbridge instantly for a surgeon. It is, I believe, useless, but go. Mr. Boldwood has shot my husband.' Her statement of the fact in such quiet and simple words came with more force than a tragic declamation, and had somewhat the effect of setting the distorted images in each mind present into proper focus. Oak, almost before he had comprehended anything beyond the briefest abstract of the event, hurried out of the room, saddled a horse and rode away. Not till he had ridden more than a mile did it occur to him that he would have done better by sending some other man on this errand, remaining himself in the house. What had become of Boldwood? He should have been looked after. Was he mad -- had there been a quarrel? Then how had Troy got there? Where had he come from? How did this remarkable reappearance effect itself when he was supposed by many to be at the bottom of the sea? Oak had in some slight measure been prepared for the presence of Troy by hearing a rumour of his return just before entering Boldwood's house ; but before he had weighed that information, this fatal event had been superimposed. However, it was too late now to think of sending another messenger, and he rode on, in the excitement of these self-inquiries not discerning, when about three miles from Caster+ bridge, a square-figured pedestrian passing along under the dark hedge in the same direction as his own. The miles necessary to be traversed, and other hindrances

incidental to the lateness of the hour and the darkness of the night, delayed the arrival of Mr, Aldritch, the surgeon ; and more than three hours passed between the time at which the shot was fired and that of his entering the house. Oak was addition+ ally detained in Casterbridge through having to give notice to the authorities of what had happened; and he then found that Boldwood had also entered the town, and delivercd himself up. In the meantime the surgeon, having hastened into the hall at Boldwood's, found it in darkness and quite deserted. He went on to the back of the house, where he discovered in the kitchen an old man, of whom he made inquiries. "She's had him took away to her own house, sir,' said his informant. "Who has?' said the doctor. "Mrs. Troy. 'A was quite dead, sir.' This was astonishing information. "She had no right to do that,' said the doctor. "There will have to be an inquest, and she should have waited to know what to do.' "Yes, sir; it was hinted to her that she had better wait till the law was known. But she said law was nothing to her, and she wouldn't let her dear husband's corpse bide neglected for folks to stare at for all the crowners in England.' Mr. Aldritch drove at once back again up the hill to Bathsheba's. The first person he met was poor Liddy, who seemed literally to have dwindled smaller in these few latter hours. "What has been done?' he said. "I don't know, sir,' said Liddy, with suspended breath. "My mistress has done it all.' "Where is she?' " Upstairs with him, sir. When he was brought home and taken upstairs, she said she wanted no further help from the men. And then she called me, and made me fill the bath, and after that told me I had better go and lie down because I looked so ill. Then she locked herself into the room alone with him, and would not let a nurse come in, or anybody at all. But I thought l'd wait in the next room in case she should want me. I heard her moving about inside for more than an

hour, but she only came out once, and that was for more candles, because hers had burnt down into the socket. She said we were to let her know when you or Mr. Thirdly came, sir.' Oak entered with the parson at this moment, and they all went upstairs together, preceded by Liddy Smallbury. Everything was silent as the grave when they paused on the landing. Liddy knocked, and Bathsheba's dress was heard rustling across the room: the key turned in the lock, and she opened the door. Her looks were calm and nearly rigid, like a slightly animated bust of Melpomene. "Oh, Mr. Aldritch, you have come at last,' she murmured from her lips merely, and threw back the door. "Ah, and Mr. Thirdly. Well, all is done, and anybody in the world may see him now.' She then passed by him, crossed the landing, and entered another room. Looking into the chamber of death she had vacated they saw by the light of the candles which were on the drawers a tall straight shape lying at the further end of the bedroom, wrapped in white. Everything around was quite orderly. The doctor went in, and after a few minutes returned to the landing again, where Oak and the parson still waited. "It is all done, indeed, as she says,' remarked Mr. Aldritch, in a subdued voice. "The body has been undressed and properly laid out in grave clothes. Gracious Heaven -- this mere girl! She must have the nerve of a stoic!' "The heart of a wife merely,' floated in a whisper about the ears of the three, and turning they saw Bathsheba in the midst of them. Then, as if at that instant to prove that her fortitude had been more of will than of spontaneity, she silently sank down between them and was a shapeless heap of drapery on the floor. The simple consciousness that superhuman strain was no longer required had at once put a period to her power to continue it. They took her away into a further room, and the medical attendance which had been useless in Troy's case was invaluable in Bathsheba's, who fell into a series of fainting-fits that had a serious aspect for a time. The sufferer was got to bed,

and Oak, finding from the bulletins that nothing really dreadful was to be apprehended on her score, left the house. Liddy kept watch in Bathsheba's chamber, where she heard her mistress, moaning in whispers through the dull slow hours of that wretched night: "O it is my fault -- how can I live! O Heaven, how can I live!'

THE MARCH FOLLOWING -- "BATHSHEBA BOLDWOOD' WE pass rapidly on into the month of March, to a breezy day without sunshine, frost, or dew. On Yai bury Hill, about midway between Weatherbury and Casterbridge, where the turnpike road passes over the crest, a numerous concourse of people had gathered, the eyes of the greater number being fre+ quently stretched afar in a northerly direction. The groups consisted of a throng of idlers, a party of javelin-men, and two trumpeters, and in the midst were carriages, one of which contained the high sheriff. With the idlers, many of whom had mounted to the top of a cutting formed for the road, were several Weatherbury men and boys -- among others Poorgrass, Coggan, and Cain Ball. At the end of half-an-hour a faint dust was seen in the expected quarter, and shortly after a travelling+ carriage, bringing one of the two judges on the Western Circuit, came up the hill and halted on the top. The judge changed carriages whilst a flourish was blown by the big-cheeked trumpeters, and a procession being formed of the vehicles and javelin-men, they all pro+ ceeded towards the town, excepting the Weatherbury men, who as soon as they had seen the judge move off returned home again to their work. " Joseph, I zeed you squeezing close to the carriage," said Coggan, as they walked. "Did ye notice my lord judge's face ?' "I did,' said Poorgrass. "I looked hard at en, as if I would read his very soul; and there was mercy in his eyes -- or to speak with the exact truth required of us at this solemn time, in the eye that was towards me.' "Well, I hope for the best,' said Coggan, though bad that must be. However, I shan't go to the trial, and I'd advise the rest of ye that bain't wanted to bide away. 'Twill disturb his

mind more than anything to see us there staring at him as if he were a show.' " The very thing I said this morning,' observed Joseph, "Justice is come to weigh him in the balances," I said in my reflectious way, "and if he's found wanting, so be it unto him," and a bystander said "Hear, hear, A man who can talk like that ought to be heard.' But I don't like dwelling upon it, for my few words are my few words, and not much; though the speech of some men is rumoured abroad as though by nature formed for such.' "So 'tis, Joseph. And now, neighbours, as I said, every man bide at home.' The resolution was adhered to ; and all waited anxiously for the news next day. Their suspense was diverted, however, by a discovery which was made in the afternoon, throwing more light on Boldwood's conduct and condition than any details which had preceded it. That he had been from the time of Greenhill Fair until the fatal Christmas Eve in excited and unusual moods was known to those who had been intimate with him; but nobody imagined that there had shown in him unequivocal symptoms of the mental derange+ ment which Bathsheha and Oak, alone of all others and at different times, had momentarily suspected. In a locked closet was now discovered an extraordinary collection of articles. There were several sets of ladies' dresses in the piece, of sundry expensive materials; silks and satins, poplins and velvets, all of colours which from Bathsheba's style of dress might have been judged to be her favourites. There were two muffs, sable and ermine. Above all there was a case of jewellery, containing four heavy gold bracelets and several lockets and rings, all of fine quality and manu+ facture. These things had been bought in Bath and other towns from time to time, and brought home by stealth. They were all carefully packed in paper, and each package was labelled " Bathsheba Boldwood,' a date being subjoined six years in advance in every instance. These somewhat pathetic evidences of a mind crazed with care and love were the subject of discourse in

Warren's malt-house when Oak entered from Caster+ bridge with tidings of the kiln glow shone upon it, told the tale sufficiently well. Boldwood, as every one supposed he would do, had pleaded guilty, and had been sentenced to death. The conviction that Boldwood had not been morally responsible for his later acts now becam general. Facts elicited previous to the trial had pointed strongly in the same direction, but they had not been of sufficient weight to lead to an order for an examination into the state of Boldwood's mind. It was astonishing, now that a presumption of insanity was raised, how many collateral circumstances were remembered to which a condition of mental disease seemed to afford the only explanation -- among others, the unprecedented neglect of his corn stacks in the previous summer. A petition was addressed to the Home Secretary, advancing the circumstances which appeared to justify a request for a reconsideration of the sentence. It was not "numerously signed ' by the inhabitants of Caster+ bridge, as is usual in such cases, for Boldwood had never made many friends over the counter. The shops thought it very natural that a man who, by importing direct from the producer, had daringly set aside the first great principle of provincial existence, namely that God made country villages to supply customers to county towns, should have confused ideas about the Decalogue. The prompters were a few merciful men who had perhaps too feelingly considered the facts latterly unearthed, and the result was that evidence was taken which it was hoped might remove the crime in a moral point of view, out of the category of wilful murder, and lead it to be regarded as a sheer outcome of madness. The upshot of the petition was waited for in Weather+ bury with solicitous interest. The execution had been fixed for eight o'clock on a Saturday morning about a fortnight after the sentence was passed, and up to Friday afternoon no answer had been recieved. At that time Gabriel came from Casterbridge Gaol, whither he had been to wish Boldwood good-bye, and turned down a by-street to avoid the town. When past the last

house he heard a hammering, and lifting his bowed head he looked back for a moment. Over the chimneys he could see the upper part of the gaol entrance, rich and glowing in the afternoon sun, and some moving figures were there. They were carpenters lifting a post into a vertical position within the parapet. He with+ drew his eyes quickly, and hastened on. It was dark when he reached home, and half the village was out to meet him. "No tidings,' Gabriel said, wearily. "And I'm afraid there's no hope. I've been with him more than two hours.' "Do ye think he <1really>1 was out of his mind when he did it?' said Smallbury. " I can't honestly say that I do,' Oak replied. " How+ ever, that we can talk of another time. Has there been any change in mistress this afternoon?' "None at all.' "Is she downstairs?' "No. And getting on so nicely as she was too. She's but very little better now again than she was at Christmas. She keeps on asking if you be come, and if there's news, till one's wearied out wi' answering her. Shall I go and say you've come?' "No,' said Oak. "There's a chance yet; but I couldn't stay in town any longer -- after seeing him too, So Laban -- Laban is here, isn't he ? ' " Yes,' said Tall. "What I've arranged is, that you shall ride to town the last thing to-night ; leave here about nine, and wait a while there, getting home about twelve. If nothing has been received by eleven to-night, they say there's no chance at all.' "I do so hope his life will be spared,' said Liddy. "If it is not, she'll go out of her mind too. Poor thing; her sufferings have been dreadful; she deserves any+ body's pity.' "Is she altered much ? ' said Coggan. "If you haven't seen poor mistress since Christmas, you wouldn't know her,' said Liddy. " Her eyes are so miserable that she's not the same woman. Only two years ago she was a romping girl, and now she's this!' Laban departed as directed, and at eleven o'clock that night

several of the villagers strolled along the road to Casterbridge and awaited his arrivai-among them Oak, and nearly all the rest of Bathsheba's men. Gabriel's anxiety was great that Boldwood might be saved, even though in his conscience he felt that he ought to die; for there had been qualities in the farmer which Oak loved. At last, when they all were weary the tramp of a horse was heard in the distance -- First dead, as if on turf it trode, Then, clattering on the village road In other pace than forth he yode. 'We shall soon know now, one way or other,' said Coggan, and they all stepped down from the bank on which they had been standing into the road, and the rider pranced into the midst of them. "Is that you, Laban ? ' said Gabriel. "Yes -- 'tis come. He's not to die. 'Tis confine+ ment during her Majesty's pleasure.' "Hurrah!' said Coggan, with a swelling heart. "God's above the devil yet!'

BEAUTY IN LONELINESS -- AFTER ALL BATHSHEBA revived with the spring. The utter prostration that had followed the low fever from which she had sufered diminished perceptibly when all un+ certainty upon every subject had come to an end. But she remained alone now for the greater part of her time, and stayed in the house, or at furthest went into the garden. She shunned every one, even Liddy, and could be brought to make no confidences, and to ask for no sympathy. As the summer drew on she passed more of her time in the open air, and began to examine into farming matters from sheer necessity, though she never rode out or personally superintended as at former times. One Friday evening in August she walked a little way along the road and entered the village for the first time since the sombre event of the preceding Christmas. None of the old colour had as yet come to her cheek, and its absolute paleness was heightened by the jet black of her gown, till it appeared preternatural. When she reached a little shop at the other end of the place, which stood nearly opposite to the churchyard, Bath+ sheba heard singing inside the church, and she knew that the singers were practising. She crossed the road, opened the gate, and entered the graveyard, the high sills of the church windows effectually screening her from the eyes of those gathered within. Her stealthy walk was to the nook wherein Troy had worked at planting flowers upon Fanny Robin's grave, and she came to the marble tombstone. A motion of satisfaction enlivened her face as she read the complete inscription. First came the words of Troy himself: --

ERECTED BY FRANCIS TROY IN BELOVEO MEMORY OF FANNY ROBIN, WHO DIED OCTOBER 9, 18 -- , AGED 20 YEARS. Unerneath this was now inscribed in new letters: -- IN THE SAME GRAVE LIE THE REMAINS OF THE AFORESAID FRANCIS TROY, WHO DIED DECEMBER 24TH, 18 -- , Whilst she stood and read and meditated the tones of the organ began again in the church, and she went with the same light step round to the porch and listened. The door was closed, and the coir was learning a new hymn. Bathsheba was stirred by emotions which latterly she had assumed to be altogether dead within her. The little attenuated voices of the children brought to her ear in destinct utterance the words they sang without thought or comprehension -- Lead, kindly Light, amid the encircling gloom, Lead Thou me on. Bathsheba's feeling was always to some extent de+ pendent upon her whim, as is the case with many other women. Something big came into her throat and an uprising to her eyes -- and she thought that she would allow the imminent tears to flow if they wished. They did flow and plenteously, and one fell upon the stone bench beside her. Once that she had begun to cry for she hardly knew what, she could not leave off for crowd+ ing thoughts she knew too well. She would have given anything in the world to be, as those children were, un+ concerned at the meaning of their words, because too innocent to feel the necessity for any such expression. All the impassioned scenes of her brief expenence seemed to revive with added emotion at that moment, and those scenes which had been without emotion

during enactment had emotion then. Yet grief came to her rather as a luxury than as the scourge of former times. Owing to Bathsheba's face being buried in her hands she did not notice a form which came quietly into the porch, and on seeing her, first moved as if to retreat, then paused and regarded her. Bathsheba did not raise her head for some time, and when she looked round her face was wet, and her eyes drowned and dim. "Mr. Oak,' exclaimed she, disconcerted, " how long have you been here ?' "A few minutes, ma'am,' said Oak, respectfully. "Are you going in?' said Bathsheba; and there came from within the church as from a prompter -- l loved the garish day, and, spite of fears, pride ruled my will: remember not past years. "I was,' said Gabriel. " I am one of the bass singers, you know. I have sung bass for several months. "Indeed: I wasn't aware of that. I'll leave you, then.' Which I have loved long since, and lost awhile, sang the children. "Don't let me drive you away, mistress. I think I won't go in to-night.' "O no -- you don't drive me away. Then they stood in a state of some embarrassment Bathsheba trying to wipe her dreadfully drenched and inflamed face without his noticing her. At length Oak said, I've not seen you-i mean spoken to you -- since ever so long, have I?' But he feared to bring distress+ ing memories back, and interrupted himself with: "Were you going into church ?' "No,' she said. I came to see the tombstone privately -- to see if they had cut the inscription as I wished Mr. Oak, you needn't mind speaking to me, if you wish to, on the matter which is in both our minds at this moment.' "And have they done it as you wished ?' said Oak. "Yes. Come and see it, if you have not already.' So together they went and read the tomb. "Eight months

ago!' Gabriel murmured when he saw the date. 'It seems like yesterday to me.' And to me as if it were years ago-iong years, and I had been dead between. And now I am going home, Mr. Oak.' Oak walked after her. 'I wanted to name a small matter to you as soon as I could,' he said, with hesitation. "Merrly about business, and I think I may just mention it now, if you'll allow me.' " O yes, certainly.' It is that I may soon have to give up the manage+ ment of your farm, Mrs. Troy. The fact is, I am think+ ing of leaving England -- not yet, you know -- next spring. ' "Leaving England!' she said, in surprise and genuine disappointment.' Why, Gabriel, what are you going to do that for?' "Well, I've thought it best,' Oak stammered out. "California is the spot I've had in my mind to try.' "But it is understood everywhere that you are going to take poor Mr. Boldwood's farm on your own account.' "I've had the refusal o' it 'tis true; but nothing is settled yet, and I have reasons for gieing up. I shall finish out my year there as manager for the trustees, but no more.' "And what shall I do without you? Oh, Gabriel, I don't think you ought to go away. You've been with me so long -- through bright times and dark times -- such old friends that as we are -- that it seems unkind almost. I had fancied that if you leased the other farm as master, you might still give a helping look across at mine. And now going away!' "I would have willingly.' " Yet now that I am more helpless than ever you go away!' "Yes, that's the ill fortune o' it,' said Gabriel, in a distressed tone. "And it is because of that very help+ lessness that I feel bound to go. Good afternoon, ma'am ' he concluded, in evident anxiety to get away, and at once went out of the churchyard by a path she could follow on no pretence whatever. Bathsheba went home, her mind occupied with a new trouble, which being rather harassing than deadly was calculated to do good by diverting her from the chronic gloom of

her life. She was set thinking a great deal about Oak and of his wich to shun her; and there occurred to Bathsheba several incidents of latter in+ tercourse with him, which, trivial when singly viewed amounted together to a perceptible disinclination for her society. It broke upon her at length as a great pain that her last old disciple was about to forsake her and flee. He who had believed in her and argued on her side when all the rest of the world was against her, had at last like the others become weary and neglectful of the old cause, and was leaving her to fight her battles alone. Three weeks went on, and more evidence of his want of interest in her was forthcoming. She noticed that instead of entering the small parlour or office where the farm accounts were kept, and waiting, or leaving a memorandum as he had hitherto done during her seclusion, Oak never came at all when she was likely to be there, only entering at unseasonable hours when her presence in that part of the house was least to be expected. Whenever he wanted directions he sent a message, or note with neither heading nor signature, to which she was obliged to reply in the same off-hand style. Poor Bathsheba began to suffer now from the most torturing sting of ali-a sensation that she was despised. The autumn wore away gloomily enough amid these melancholy conjectures, and Christmas-day came, com+ pleting a year of her legal widowhood, and two years and a quarter of her life alone. On examining her heart it appeared beyond measure strange that the sub+ ject of which the season might have been supposed suggestive -- the event in the hall at Boldwood's -- was not agitating her at all; but instead, an agonizing con+ viction that everybody abjured her -- for what she could not teli-and that Oak was the ringleader of the recusants. Coming out of church that day she looked round in hope that Oak, whose bass voice she had heard rolling out from the gallery overhead in a most unconcerned manner, might chance to linger in her path in the old way. There he was, as usual, coming down the path behind her. But on seeing Bathsheba turn, he looked aside, and as soon as he got beyond the gate,

and there was the barest excuse for a divergence, he made one, and vanished. The next morning brought the culminating stroke; she had been expecting it long. It was a formal notice by letter from him that he should not renew his engage+ ment with her for the following Lady-day. Bathsheba actually sat and cried over this letter most bitterly. She was aggrieved and wounded that the possession of hopeless love from Gabriel, which she had AFTER ALL grown to regard as her inalienable right for life, should have been withdrawn just at his own pleasure in this way. She was bewildered too by the prospect of having to rely on her own resources again: it seemed to herself that she never could again acquire energy sufficient to go to market, barter, and sell. Since Troy's death Oak had attended all sales and fairs for her, transacting her business at the same time with his own. What should she do now? Her life was becoming a desolation. So desolate was Bathsheba this evening, that in an absolute hunger for pity and sympathy, and miserable in that she appeared to have outlived the only true friend+ ship she had ever owned, she put on her bonnet and cloak and went down to Oak's house just after sunset, guided on her way by the pale primrose rays of a crescent moon a few days old. A lively firelight shone from the window, but nobody was visible in the room. She tapped nervously, and then thought it doubtful if it were right for a single woman to call upon a bachelor who lived alone, although he was her manager, and she might be supposed to call on business without any real impropriety. Gabriel opened the door, and the moon shone upon his fore+ haad. "Mr. Oak,' said Bathsheba, faintly. "Yes; I am Mr. Oak,' said Gabriel. "Who have I the honour -- O how stupid of me, not to know you, mistress!' "I shall not be your mistress much longer, shall I Gabriel?' she said, in pathetic tones. "Well, no. I suppose -- But come in, ma'am. Oh -- and I'll get a light,' Oak replied, with some awkwardness.

"No; not on my account.' "It is so seldom that I get a lady visitor that I'm afraid I haven't proper accommodation. Will you sit down, please ? Here's a chair, and there's one, too. I am sorry that my chairs all have wood scats, and are rather hard, but i-was thinging of getting some new ones.' Oak placed two or three for her. "They are quite easy enough for me.' So down she sat, and down sat he, the fire dancing in their faces, and upon the old furniture all a-sheenen Wi' long years o' handlen, that formed Oak's array of household possessions, which sent back a dancing reflection in reply. It was very odd to these two persons, who knew each other passing well, that the mere circumstance of their meeting in a new place and in a new way should make them so awkward and constrained. In the fields, or at her house, there had never been any embarrassment; but now that Oak had become the entertainer their lives seemed to be moved back again to the days when they were strangers. "You'll think it strange that I have come, but -- -' "O no; not at all.' "But I thought -- Gabriel, I have been uneasy in the belief that I have offended you, and that you are going away on that account. It grieved me very much and I couldn't help coming.' "Offended me! As if you could do that, Bathsheba!' "Haven't I?' she asked, gladly. " But, what are you going away for else?' "I am not going to emigrate, you know; I wasn't aware that you would wish me not to when I told 'ee or I shouldn't ha' thought of doing it,' he said, simply. "I have arranged for Little Weatherbury Farm and shall have it in my own hands at Lady-day. You know I've had a share in it for some time. Still, that wouldn't prevent my attending to your business as before, hadn't it been that things have been said about us.'

"What?' said Bathsheba, in surprise. "Things said about you and me! What are they?' "I cannot tell you.' "It would be wiser if you were to, I think. You have played the part of mentor to me many times, and I don't see why you should fear to do it now.' "It is nothing that you have done, this time. The top and tail o't is this -- that I am sniffing about here, and waiting for poor Boldwood's farm, with a thought of getting you some day.' "Getting me! What does that mean?' "Marrying o' 'ee, in plain British. You asked me to tell, so you mustn't blame me.' Bathsheba did not look quite so alarmed as if a cannon had been discharged by her ear, which was what Oak had expected. "Marrying me! I didn't know it was that you meant,' she said, quietly. "Such a thing as that is too absurd -- too soon -- to think of, by far!' "Yes; of course, it is too absurd. I don't desire any such thing; I should think that was plain enough by this time. Surely, surely you be the last person in the world I think of marrying. It is too absurd, as you say ""Too -- s-s-soon" were the words I used.' "I must beg your pardon for correcting you, but you said, ""too absurd,"' and so do I.' "I beg your pardon too! she returned, with tears in her eyes. """Too soon"' was what I said. But it doesn't matter a bit -- not at ali-but I only meant, ""too soon"' Indeed, I didn't, Mr. Oak, and you must believe me!' Gabriel looked her long in the face, but the firelight being faint there was not much to be seen. " Bathsheba,' he said, tenderly and in surprise, and coming closer: "if I only knew one thing -- whether you would allow me to love you and win you, and marry you after ali-if I only knew that!' "But you never will know,' she murmured. "Why?' "Because you never ask. "Oh -- Oh!' said Gabriel, with a low laugh of joyous+ ness. "My own dear -- -'

"You ought not to have sent me that harsh letter this morning,' she interrupted. "It shows you didn't care a bit about me, and were ready to desert me like all the rest of them! It was very cruel of you, consider+ ing I was the first sweetheart that you ever had, and you were the first I ever had; and I shall not forget it!' "Now, Bathsheba, was ever anybody so provoking he said, laughing. " You know it was purely that I, as an unmarried man, carrying on a business for you as a very taking young woman, had a proper hard part to play -- more particular that people knew I had a sort of feeling for'ee; and I fancied, from the way we were mentioned together, that it might injure your good name. Nobody knows the heat and fret I have been caused by it.' "And was that all?' "All.' "Oh, how glad I am I came!' she exclaimed, thank+ fully, as she rose from her seat. "I have thought so much more of you since I fancied you did not want even to see me again. But I must be going now, or I shall be missed. Why Gabriel,' she said, with a slight laugh, as they went to the door, "it seems exactly as if I had come courting you -- how dreadful!' "And quite right too,' said Oak. "I've danced at your skittish heels, my beautiful Bathsheba, for many a long mile, and many a long day; and it is hard to be+ grudge me this one visit.' He accompanied her up the hill, explaining to her the details of his forthcoming tenure of the other farm. They spoke very little of their mutual feeling; pretty phrases and warm expressions being probably un+ necessary between such tried friends. Theirs was that substantial affection which arises (if any arises at all) when the two who are thrown together begin first by knowing the rougher sides of each other's character, and not the best till further on, the romance growing up in the interstices of a mass of hard prosaic reality. This good-fellowship -- <1camaraderie>1 -- usually occurring through similarity of pursuits, is unfortunately seldom superadded to love between the sexes, because men and women associate, not in their lahours, but in their pleasures merely. Where, however, happy circumstance

permits its development, the compounded feeling proves itself to be the only love which is strong as death -- that love which many waters cannot quench, nor the floods drown, beside which the passion usually called by the name is evanescent as steam.

A FOGGY NIGHT AND MORNING -- CONCLUSION "THE most private, secret, plaines wedding that it is possible to have.' Those had been Bathsheba's words to Oak one evening, some time after the event of the preceding chapter, and he meditated a full hour by the clock upon how to carry out her wishes to the letter. "A licence -- O yes, it must be a licence,' he said to himself at last. "Very well, then; first, a license.' On a dark night, a few days later, Oak came with mysterious steps from the surrogate's door, in Caster+ bridge. On the way home he heard a heavy tread in front of him, and, overtaking the man, found him to be Coggan. They walked together into the village until they came to a little lane behind the church, leading down to the cottage of Laban Tall, who had lately been installed as clerk of the parish, and was yet in mortal terror at church on Sundays when he heard his lone voice among certain hard words of the Psalms, whither no man ventured to follow him. "Well, good-night, Coggan,' said Oak, "I'm going down this way.' "Oh!' said Coggan, surprised; "what's going on to+ night then, make so bold Mr. Oak?' It seemed rather ungenerous not to tell Coggan, under the circumstances, for Coggan had been true as steel all through the time of Gabriel's unhappiness about Bathsheba, and Gabriel said, " You can keep a secret, Coggan?' "You've proved me, and you know.' "Yes, I have, and I do know. Well, then, mistress and I mean to get married to-morrow morning.' "Heaven's high tower! And yet I've thought of such a thing

from time to time; true, I have. But keeping it so close! Well, there, 'tis no consarn of amine, and I wish 'ee joy o' her.' "Thank you, Coggan. But I assure 'ee that this great hush is not what I wished for at all, or what either of us would have wished if it hadn't been for certain things that would make a gay wedding seem hardly the thing. Bathsheba has a great wish that all the parish shall not be in church, looking at her -- she's shyiike and nervous about it, in fact -- so I be doing this to humour her.' "Ay, I see: quite right, too, I suppose I must say. And you be now going down to the clerk.' "Yes; you may as well come with me.' "I am afeard your labour in keeping it close will be throwed away,' said Coggan, as they walked along. "Labe Tall's old woman will horn it all over parish in half-an-hour. ' "So she will, upon my life; I never thought of that,' said Oak, pausing. "Yet I must tell him to+ night, I suppose, for he's working so far off, and leaves early.' "I'll tell 'ee how we could tackle her,' said Coggan. "I'll knock and ask to speak to Laban outside the door, you standing in the background. Then he'll come out, and you can tell yer tale. She'll never guess what I want en for; and I'll make up a few words about the farm-work, as a blind.' This scheme was considered feasible; and Coggan advanced boldly, and rapped at Mrs. Tall's door. Mrs. Tall herself opened it. "I wanted to have a word with Laban.' "He's not at home, and won't be this side of eleven o'clock. He've been forced to go over to Yalbury since shutting out work. I shall do quite as well.' "I hardly think you will. Stop a moment;' and Coggan stepped round the corner of the porch to consult Oak. "Who's t'other man, then?' said Mrs. Tall. "Only a friend,' said Coggan. "Say he's wanted to meet mistress near church-hatch to-morrow morning at ten,' said Oak, in a whisper. "That he must come without fail, and wear his best clothes.'

"The clothes will floor us as safe as houses!' said Coggan. "It can't be helped said Oak. "Tell her.' So Coggan delivered the message. "Mind, het or wet, blow or snow, he must come, added Jan. "'Tis very particular, indeed. The fact is, 'tis to witness her sign some law-work about taking shares wi' another farmer for a long span o' years. There, that's what 'tis, and now I've told 'ee, Mother Tall, in a way I shouldn't ha' done if I hadn't loved 'ee so hopeless well.' Coggan retired before she could ask any further; and next they called at the vicar's in a manner which excited no curiosity at all. Then Gabriel went home, and prepared for the morrow. "Liddy,' said Bathsheba, on going to bed that night, "I want you to call me at seven o'clock to-morrow, In case I shouldn't wake.' "But you always do wake afore then, ma'am.' "Yes, but I have something important to do, which I'll tell you of when the time comes, and it's best to make sure.' CONCLUSION Bathsheba, however, awoke voluntarily at four, nor could she by any contrivance get to sleep again. About six, being quite positive that her watch had stopped during the night, she could wait no longer. She went and tapped at Liddy's door, and after some labour awoke her. "But I thought it was I who had to call you?' said the bewildered Liddy. "And it isn't six yet.' "Indeed it is; how can you tell such a story, Liddy? I know it must be ever so much past seven. Come to my room as soon as you can; I want you to give my hair a good brushing.' When Liddy came to Bathsheba's room her mistress was already waiting. Liddy could not understand this extraordinary promptness. " Whatever <1is>1 going on, ma'am?' she said. "Well, I'll tell you,' said Bathsheba, with a mischiev+ ous smile in her bright eyes. "Farmer Oak is coming here to dine with me to-day!' "Farmer Oak -- and nobody else ? -- you two alone?' "Yes.'

"But is it safe, ma'am, after what's been said?' asked her companion, dubiously. "A woman's good name is such a perishable article that -- -- ' Bathsheba laughed with a flushed cheek, and whispered in Liddy's ear, although there was nobody present. Then Liddy stared and exclaimcd, " Souls alive, what news! It makes my heart go quite bumpity-bump" "It makes mine rather furious, too,' said Bathsheba. "However, there's no getting out of it now!' It was a damp disagreeable morning. Nevertheless, at twenty minutes to ten o'clock, Oak came out of his house, and Went up the hill side With that sort of stride A man puts out when walking in search of a bride, and knocked Bathsheba's door. Ten minutes later a large and a smaller umbrella might have been seen moving from the same door, and through the mist along the road to the church. The distance was not more than a quarter of a mile, and these two sensible persons deemed it unnecessary to drive. An observer must have been very close indeed to discover that the forms under the umbrellas were those of Oak and Bathsheba, arm-in+ arm for the first time in their lives, Oak in a greatcoat extending to his knees, and Bathsheba in a cloak that reached her clogs. Yet, though so plainly dressed there was a certain rejuvenated appearance about her : -- As though a rose should shut and be a bud again. Repose had again incarnadined her cheeks; and having, at Gabriel's request, arranged her hair this morning as she had worn it years ago on Norcombe Hill, she seemed in his eyes remarkably like a girl of that fascinating dream, which, considering that she was now only three or four-and-twenty, was perhaps not very wonderful. In the church were Tall, Liddy, and the parson, and in a remarkably short space of time the deed was done. The two sat down very quietly to tea in Bathsheba's parlour in the evening of the same day, for it had been arranged that

Farmer Oak should go there to live, since he had as yet neither money, house, nor furniture worthy of the name, though he was on a sure way towards them, whilst Bathsheba was, comparatively, in a plethora of all three. Just as Bathsheba was pouring out a cup of tea, their ears were greeted by the firing of a cannon, followed by what seemed like a tremendous blowing of trumpets, in the front of the house. "There!' said Oak, laughing, "I knew those fellows were up to something, by the look on their face; ' Oak took up the light and went into the porch, followed by Bathsheba with a shawl over her head. The rays fell upon a group of male figures gathered upon the gravel in front, who, when they saw the newly-married couple in the porch, set up a loud "Hurrah!' and at the same moment bang again went the cannon in the background, followed by a hideous clang of music from a drum, tambourine, clarionet, serpent, hautboy, tenor+ viol, and double-bass -- the only remaining relics of the true and original Weatherbury band -- venerable worm+ eaten instruments, which had celebrated in their own persons the victories of Marlhorough, under the fingers of the forefathers of those who played them now. The performers came forward, and marched up to the front. "Those bright boys, Mark Clark and Jan, are at the bottom of all this,' said Oak. " Come in, souls, and have something to eat and drink wi' me and my wife.' "Not to-night,' said Mr. Clark, with evident self+ denial. "Thank ye all the same; but we'll call at a more seemly time. However, we couldn't think of letting the day pass without a note of admiration of some sort. If ye could send a drop of som'at down to Warren's, why so it is. Here's long life and happiness to neighbour Oak and his comely bride!' "Thank ye; thank ye all,' said Gabriel. "A bit and a drop shall be sent to Warren's for ye at once. I had a thought that we might very likely get a salute of some sort from our old friends, and I was saying so to my wife but now.' "Faith,' said Coggan, in a critical tone, turning to his companions, "the man hev learnt to say ""my wife"' in a wonderful

naterel way, considering how very youth+ ful he is in wedlock as yet -- hey, neighbours all?' "I never heerd a skilful old married feller of twenty years' standing pipe ""my wife"' in a more used note than 'a did,' said Jacob Smallbury. "It might have been a little more true to nater if't had been spoke a little chillier, but that wasn't to be expected just now. "That improvement will come wi' time,' said Jan, twirling his eye. Then Oak laughed, and Bathsheba smiled (for she never laughed readily now), and their friends turned to go. "Yes; I suppose that's the size o't,' said Joseph Poorgrass with a cheerful sigh as they moved away; "and I wish him joy o' her; though I were once or twice upon saying to-day with holy Hosea, in my scripture manner, which is my second nature. ""Ephraim is joined to idols: let him alone."' But since 'tis as 'tis why, it might have been worse, and I feel my thanks accordingly.' THE END .EQ delim $$ .EN .CH "1 WHY SPEECH OUTPUT?" .ds RT "Why speech output? .ds CX "Principles of computer speech .pp Speech is our everyday, informal, communication medium. But although we use it a lot, we probably don't assimilate as much information through our ears as we do through our eyes, by reading or looking at pictures and diagrams. You go to a technical lecture to get the feel of a subject \(em the overall arrangement of ideas and the motivation behind them \(em and fill in the details, if you still want to know them, from a book. You probably find out more about the news from ten minutes with a newspaper than from a ten-minute news broadcast. So it should be emphasized from the start that speech output from computers is not a panacea. It doesn't solve the problems of communicating with computers; it simply enriches the possibilities for communication. .pp What, then, are the advantages of speech output? One good reason for listening to a radio news broadcast instead of spending the time with a newspaper is that you can listen while shaving, doing the housework, or driving the car. Speech leaves hands and eyes free for other tasks. Moreover, it is omnidirectional, and does not require a free line of sight. Related to this is the use of speech as a secondary medium for status reports and warning messages. Occasional interruptions by voice do not interfere with other activities, unless they demand unusual concentration, and people can assimilate spoken messages and queue them for later action quite easily and naturally. .pp The second key feature of speech communication stems from the telephone. It is the universality of the telephone receiver itself that is important here, rather than the existence of a world-wide distribution network; for with special equipment (a modem and a VDU) one does not need speech to take advantage of the telephone network for information transfer. But speech needs no tools other than the telephone, and this gives it a substantial advantage. You can go into a phone booth anywhere in the world, carrying no special equipment, and have access to your computer within seconds. The problem of data input is still there: perhaps your computer system has a limited word recognizer, or you use the touchtone telephone keypad (or a portable calculator-sized tone generator). Easy remote access without special equipment is a great, and unique, asset to speech communication. .pp The third big advantage of speech output is that it is potentially very cheap. Being all-electronic, except for the loudspeaker, speech systems are well suited to high-volume, low-cost, LSI manufacture. Other computer output devices are at present tied either to mechanical moving parts or to the CRT. This was realized quickly by the computer hobbies market, where speech output peripherals have been selling like hot cakes since the mid 1970's. .pp A further point in favour of speech is that it is natural-seeming and somehow cuddly when compared with printers or VDU's. It would have been much more difficult to make this point before the advent of talking toys like Texas Instruments' "Speak 'n Spell" in 1978, but now it is an accepted fact that friendly computer-based gadgets can speak \(em there are talking pocket-watches that really do "tell" the time, talking microwave ovens, talking pinball machines, and, of course, talking calculators. It is, however, difficult to assess whether the appeal stems from mechanical speech's novelty \(em it is still a gimmick \(em and also to what extent it is tied up with economic factors. After all, most of the population don't use high-quality VDU's, and their major experience of real-time interactive computing is through the very limited displays and keypads provided on video games and teletext systems. .pp Articles on speech communication with computers often list many more advantages of voice output (see Hill 1971, Turn 1974, Lea 1980). .[ Hill 1971 Man-machine interaction using speech .] .[ Lea 1980 .] .[ Turn 1974 Speech as a man-computer communication channel .] For example, speech .LB .NP can be used in the dark .NP can be varied from a (confidential) whisper to a (loud) shout .NP requires very little energy .NP is not appreciably affected by weightlessness or vibration. .LE However, these either derive from the three advantages we have discussed above, or relate mainly to exotic applications in space modules and divers' helmets. .pp Useful as it is at present, speech output would be even more attractive if it could be coupled with speech input. In many ways, speech input is its "big brother". Many of the benefits of speech output are even more striking for speech input. Although people can assimilate information faster through the eyes than the ears, the majority of us can generate information faster with the mouth than with the hands. Rapid typing is a relatively uncommon skill, and even high typing rates are much slower than speaking rates (although whether we can originate ideas quickly enough to keep up with fast speech is another matter!) To take full advantage of the telephone for interaction with machines, machine recognition of speech is obviously necessary. A microwave oven, calculator, pinball machine, or alarm clock that responds to spoken commands is certainly more attractive than one that just generates spoken status messages. A book that told you how to recognize speech by machine would undoubtedly be more useful than one like this that just discusses how to synthesize it! But the technology of speech recognition is nowhere near as advanced as that of synthesis \(em it's a much more difficult problem. However, because speech input is obviously complementary to speech output, and even very limited input capabilities will greatly enhance many speech output systems, it is worth summarizing the present state of the art of speech recognition. .pp Commercial speech recognizers do exist. Almost invariably, they accept words spoken in isolation, with gaps of silence between them, rather than connected utterances. It is not difficult to discriminate with high accuracy up to a hundred different words spoken by the same speaker, especially if the vocabulary is carefully selected to avoid words which sound similar. If several different speakers are to be comprehended, performance can be greatly improved if the machine is given an opportunity to calibrate their voices in a training session, and is informed at recognition time which one is to speak. With a large population of unknown speakers, accurate recognition is difficult for vocabularies of more than a few carefully-chosen words. .pp A half-way house between isolated word discrimination and recognition of connected speech is the problem of spotting known words in continuous speech. This allows much more natural input, if the dialogue is structured as keywords which may be interspersed by unimportant "noise words". To speak in truly isolated words requires a great deal of self-discipline and concentration \(em it is surprising how much of ordinary speech is accounted for by vague sounds like um's and aah's, and false starts. Word spotting disregards these and so permits a more relaxed style of speech. Some progress has been made on it in research laboratories, but the vocabularies that can be accomodated are still very small. .pp The difficulty of recognizing connected speech depends crucially on what is known in advance about the dialogue: its pragmatic, semantic, and syntactic constraints. Highly structured dialogues constrain very heavily the choice of the next word. Recognizers which can deal with vocabularies of over 1000 words have been built in research laboratories, but the structure of the input has been such that the average "branching factor" \(em the size of the set out of which the next word must be selected \(em is only around 10 (Lea, 1980). .[ Lea 1980 .] Whether such highly constrained languages would be acceptable in many practical applications is a moot point. One commercial recognizer, developed in 1978, can cope with up to five words spoken continuously from a basic 120-word vocabulary. .pp There has been much debate about whether it will ever be possible for a speech recognizer to step outside rigid constraints imposed on the utterances it can understand, and act, say, as an automatic dictation machine. Certainly the most advanced recognizers to date depend very strongly on a tight context being available. Informed opinion seems to accept that in ten years' time, voice data entry in the office will be an important and economically feasible prospect, but that it would be rash to predict the appearance of unconstrained automatic dictation by then. .pp Let's return now to speech output and take a look at some systems which use it, to illustrate the advantages and disadvantages of speech in practical applications. .sh "1.1 Talking calculator" .pp Figure 1.1 shows a calculator that speaks. .FC "Figure 1.1" Whenever a key is pressed, the device confirms the action by saying the key's name. The result of any computation is also spoken aloud. For most people, the addition of speech output to a calculator is simply a gimmick. (Note incidentally that speech .ul input is a different matter altogether. The ability to dictate lists of numbers and commands to a calculator, without lifting one's eyes from the page, would have very great advantages over keypad input.) Used-car salesmen find that speech output sometimes helps to clinch a deal: they key in the basic car price and their bargain-basement deductions, and the customer is so bemused by the resulting price being spoken aloud to him by a machine that he signs the cheque without thinking! More seriously, there may be some small advantage to be gained when keying a list of figures by touch from having their values read back for confirmation. For blind people, however, such devices are a boon \(em and there are many other applications, like talking elevators and talking clocks, which benefit from even very restricted voice output. Much more sophisticated is a typewriter with audio feedback, designed by IBM for the blind. Although blind typists can remember where the keys on a typewriter are without difficulty, they rely on sighted proof-readers to help check their work. This device could make them more useful as office typists and secretaries. As well as verbalizing the material (including punctuation) that has been typed, either by attempting to pronounce the words or by spelling them out as individual letters, it prompts the user through the more complex action sequences that are possible on the typewriter. .pp The vocabulary of the talking calculator comprises the 24 words of Table 1.1. .RF .nr x1 2.0i+\w'percent'u .nr x1 (\n(.l-\n(x1)/2 .in \n(x1u .ta 2.0i zero percent one low two over three root four em (m) five times six point seven overflow eight minus nine plus times-minus clear equals swap .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 1.1 Vocabulary of a talking calculator" This represents a total of about 13 seconds of speech. It is stored electronically in read-only memory (ROM), and Figure 1.2 shows the circuitry of the speech module inside the calculator. .FC "Figure 1.2" There are three large integrated circuits. Two of them are ROMs, and the other is a special synthesis chip which decodes the highly compressed stored data into an audio waveform. Although the mechanisms used for storing speech by commercial devices are not widely advertised by the manufacturers, the talking calculator almost certainly uses linear predictive coding \(em a technique that we will examine in Chapter 6. The speech quality is very poor because of the highly compressed storage, and words are spoken in a grating monotone. However, because of the very small vocabulary, the quality is certainly good enough for reliable identification. .sh "1.2 Computer-generated wiring instructions" .pp I mentioned earlier that one big advantage of speech over visual output is that it leaves the eyes free for other tasks. When wiring telephone equipment during manufacture, the operator needs to use his hands as well as eyes to keep his place in the task. For some time tape-recorded instructions have been used for this in certain manufacturing plants. For example, the instruction .LB .NI Red 2.5 11A terminal strip 7A tube socket .LE directs the operator to cut 2.5" of red wire, attach one end to a specified point on the terminal strip, and attach the other to a pin of the tube socket. The tape recorder is fitted with a pedal switch to allow a sequence of such instructions to be executed by the operator at his own pace. .pp The usual way of recording the instruction tape is to have a human reader dictate them from a printed list. The tape is then checked against the list by another listener to ensure that the instructions are correct. Since wiring lists are usually stored and maintained in machine-readable form, it is natural to consider whether speech synthesis techniques could be used to generate the acoustic tape directly by a computer (Flanagan .ul et al, 1972). .[ Flanagan Rabiner Schafer Denman 1972 .] .pp Table 1.2 shows the vocabulary needed for this application. .RF .nr x1 2.0i+2.0i+\w'tube socket'u .nr x1 (\n(.l-\n(x1)/2 .in \n(x1u .ta 2.0i +2.0i A green seventeen black left six bottom lower sixteen break make strip C nine ten capacitor nineteen terminal eight one thirteen eighteen P thirty eleven point three fifteen R top fifty red tube socket five repeat coil twelve forty resistor twenty four right two fourteen seven upper .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 1.2 Vocabulary needed for computer-generated wiring instructions" It is rather larger than that of the talking calculator \(em about 25 seconds of speech \(em but well within the limits of single-chip storage in ROM, compressed by the linear predictive technique. However, at the time that the scheme was investigated (1970\-71) the method of linear predictive coding had not been fully developed, and the technology for low-cost microcircuit implementation was not available. But this is not important for this particular application, for there is no need to perform the synthesis on a miniature low-cost computer system, nor need it be accomplished in real time. In fact a technique of concatenating spectrally-encoded words was used (described in Chapter 7), and it was implemented on a minicomputer. Operating much slower than real-time, the system calculated the speech waveform and wrote it to disk storage. A subsequent phase read the pre-computed messages and recorded them on a computer-controlled analogue tape recorder. .pp Informal evaluation showed the scheme to be quite successful. Indeed, the synthetic speech, whose quality was not high, was actually preferred to natural speech in the noisy environment of the production line, for each instruction was spoken in the same format, with the same programmed pause between the items. A list of 58 instructions of the form shown above was recorded and used to wire several pieces of apparatus without errors. .sh "1.3 Telephone enquiry service" .pp The computer-generated wiring scheme illustrates how speech can be used to give instructions without diverting visual attention from the task at hand. The next system we examine shows how speech output can make the telephone receiver into a remote computer terminal for a variety of purposes (Witten and Madams, 1977). .[ Witten Madams 1977 Telephone Enquiry Service .] The caller employs the touch-tone keypad shown in Figure 1.3 for input, and the computer generates a synthetic voice response. .FC "Figure 1.3" Table 1.3 shows the process of making contact with the system. .RF .fi .nh .na .in 0.3i .nr x0 \w'COMPUTER: ' .nr x1 \w'CALLER: ' .in+\n(x0u .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Dials the service. .ti-\n(x0u COMPUTER: Answers telephone. "Hello, Telephone Enquiry Service. Please enter your user number". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters user number. .ti-\n(x0u COMPUTER: "Please enter your password". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters password. .ti-\n(x0u COMPUTER: Checks validity of password. If invalid, the user is asked to re-enter his user number. Otherwise, "Which service do you require?" .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters service number. .in 0 .nf .FG "Table 1.3 Making contact with the telephone enquiry system" .pp Advantage is taken of the disparate speeds of input (keyboard) and output (speech) to hasten the dialogue by imposing a question-answer structure on it, with the computer taking the initiative. The machine can afford to be slightly verbose if by so doing it makes the caller's response easier, and therefore more rapid. Moreover, operators who are experienced enough with the system to anticipate questions can easily forestall them just by typing ahead, for the computer is programmed to examine its input buffer before issuing prompts and to suppress them if input has already been provided. .pp An important aim of the system is to allow application programmers with no special knowledge of speech to write independent services for it. Table 1.4 shows an example of the use of one such application program, .RF .fi .nh .na .in 0.3i .nr x0 \w'COMPUTER: ' .nr x1 \w'CALLER: ' .in+\n(x0u .ti-\n(x0u COMPUTER: "Stores Information Service. Please enter component name". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "SN7406#". .ti-\n(x0u COMPUTER: "The component name is SN7406. Is this correct?" .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "*1#" (system convention for "yes"). .ti-\n(x0u COMPUTER: "This component is in stores". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "*7#" (command for "price"). .ti-\n(x0u COMPUTER: "The component price is 35 pence". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "*8#" (command for "minimum number"). .ti-\n(x0u COMPUTER: "The minimum number of this component kept in stores is 10". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "SN7417#". .ti-\n(x0u COMPUTER: "The component name is SN7417. Is this correct?" .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "*1#". .ti-\n(x0u COMPUTER: "This component is not in stores". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "*9#" (command for "delivery time"). .ti-\n(x0u COMPUTER: "The expected delivery time is 14 days". .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Enters "*0#". .ti-\n(x0u COMPUTER: "Which service do you require?" .in 0 .nf .FG "Table 1.4 The Stores Information Service" the Stores Information Service, which permits enquiries to be made of a database holding information on electronic components kept in stock. This subsystem is driven by .ul alphanumeric data entered on the touch-tone keypad. Two or three letters are associated with each digit, in a manner which is fairly standard in touch-tone telephone applications. These are printed on a card overlay that fits the keypad (see Figure 1.3). Although true alphanumeric data entry would require a multiple key press for each character, the ambiguity inherent in a single-key-per-character convention can usually be resolved by the computer, if it has a list of permissible entries. For example, the component names SN7406 and ZTX300 are read by the machine as "767406" and "189300", respectively. Confusion rarely occurs if the machine is expecting a valid component code. The same holds true of people's names, and file names \(em although with these one must take care not to identify a series of files by similar names, like TX38A, TX38B, TX38C. It is easy for the machine to detect the rare cases where ambiguity occurs, and respond by requesting further information: "The component name is SN7406. Is this correct?" (In fact, the Stores Information Service illustrated in Table 1.4 is defective in that it .ul always requests confirmation of an entry, even when no ambiguity exists.) The use of a telephone keypad for data entry will be taken up again in Chapter 10. .pp A distinction is drawn throughout the system between data entries and commands, the latter being prefixed by a "*". In this example, the programmer chose to define a command for each possible question about a component, so that a new component name can be entered at any time without ambiguity. The price paid for the resulting brevity of dialogue is the burden of memorizing the meaning of the commands. This is an inherent disadvantage of a one-dimensional auditory display over the more conventional graphical output: presenting menus by speech is tedious and long-winded. In practice, however, for a simple task such as the Stores Information Service it is quite convenient for the caller to search for the appropriate command by trying out all possibilities \(em there are only a few. .pp The problem of memorizing commands is alleviated by establishing some system-wide conventions. Each input is terminated by a "#", and the meaning of standard commands is given in Table 1.5. .RF .fi .nh .na .in 0.3i .nr x0 \w'# alone ' .nr x1 \w'\(em ' .ta \n(x0u +\n(x1u .nr x2 \n(x0+\n(x1 .in+\n(x2u .ti-\n(x2u *# \(em Erase this input line, regardless of what has been typed before the "*". .ti-\n(x2u *0# \(em Stop. Used to exit from any service. .ti-\n(x2u *1# \(em Yes. .ti-\n(x2u *2# \(em No. .ti-\n(x2u *3# \(em Repeat question or summarize state of current transaction. .ti-\n(x2u # alone \(em Short form of repeat. Repeats or summarizes in an abbreviated fashion. .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .nf .FG "Table 1.5 System-wide conventions for the service" .pp A summary of services available on the system is given in Table 1.6. .RF .fi .na .in 0.3i .nr x0 \w'000 ' .nr x1 \w'\(em ' .nr x2 \n(x0+\n(x1 .in+\n(x2u .ta \n(x0u +\n(x1u .ti-\n(x2u \0\01 \(em tells the time .ti-\n(x2u \0\02 \(em Biffo (a game of NIM) .ti-\n(x2u \0\03 \(em MOO (a game similar to that marketed under the name "Mastermind") .ti-\n(x2u \0\04 \(em error demonstration .ti-\n(x2u \0\05 \(em speak a file in phonetic format .ti-\n(x2u \0\06 \(em listening test .ti-\n(x2u \0\07 \(em music (allows you to enter a tune and play it) .ti-\n(x2u \0\08 \(em gives the date .sp .ti-\n(x2u 100 \(em squash ladder .ti-\n(x2u 101 \(em stores information service .ti-\n(x2u 102 \(em computes means and standard deviations .ti-\n(x2u 103 \(em telephone directory .sp .ti-\n(x2u 411 \(em user information .ti-\n(x2u 412 \(em change password .ti-\n(x2u 413 \(em gripe (permits feedback on services from caller) .sp .ti-\n(x2u 600 \(em first year laboratory marks entering service .sp .ti-\n(x2u 910 \(em repeat utterance (allows testing of system) .ti-\n(x2u 911 \(em speak utterance (allows testing of system) .ti-\n(x2u 912 \(em enable/disable user 100 (a no-password guest user number) .ti-\n(x2u 913 \(em mount a magnetic tape on the computer .ti-\n(x2u 914 \(em set/reset demonstration mode (prohibits access by low-priority users) .ti-\n(x2u 915 \(em inhibit games .ti-\n(x2u 916 \(em inhibit the MOO game .ti-\n(x2u 917 \(em disable password checking when users log in .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .nf .FG "Table 1.6 Summary of services on a telephone enquiry system" They range from simple games and demonstrations, through serious database services, to system maintenance facilities. A priority structure is imposed upon them, with higher service numbers being available only to higher priority users. Services in the lowest range (1\-99) can be obtained by all, while those in the highest range (900\-999) are maintenance services, available only to the system designers. Access to the lower-numbered "games" services can be inhibited by a priority user \(em this was found necessary to prevent over-use of the system! Another advantage of telephone access to an information retrieval system is that some day-to-day maintenance can be done remotely, from the office telephone. .pp This telephone enquiry service, which was built in 1974, demonstrated that speech synthesis had moved from a specialist phonetic discipline into the province of engineering practicability. The speech was generated "by rule" from a phonetic input (the method is covered in Chapters 7 and 8), which has very low data storage requirements of around 75\ bit/s of speech. Thus an enormous vocabulary and range of services could be accomodated on a small computer system. Despite the fairly low quality of the speech, the response from callers was most encouraging. Admittedly the user population was a self-selected body of University staff, which one might suppose to have high tolerance to new ideas, and a system designed for the general public would require more effort to be spent on developing speech of greater intelligibility. Although it was observed that some callers failed to understand parts of the responses, even after repetition, communication was largely unhindered in most cases; users being driven by a high motivation to help the system help them. .pp The use of speech output in conjunction with a simple input device requires careful thought for interaction to be successful and comfortable. It is necessary that the computer direct the conversation as much as possible, without seeming to be taking charge. Provision for eliminating prompts which are unwanted by sophisticated users is essential to avoid frustration. We will return to the topic of programming techniques for speech interaction in Chapter 10. .pp Making a computer system available over the telephone results in a sudden vast increase in the user population. Although people's reaction to a new computer terminal in every office was overwhelmingly favourable, careful resource allocation was essential to prevent the service being hogged by a persistent few. As with all multi-access computer systems, it is particularly important that error recovery is effected automatically and gracefully. .sh "1.4 Speech output in the telephone exchange" .pp The telephone enquiry service was an experimental vehicle for research on speech interaction, and was developed in 1974. Since then, speech has begun to be used in real commercial applications. One example is System\ X, the British Post Office's computer-controlled telephone exchange. This incorporates many features not found in conventional telephone exchanges. For example, if a number is found to be busy, the call can be attempted again by a "repeat last call" command, without having to re-dial the full number. Alternatively, the last number can be stored for future re-dialling, freeing the phone for other calls. "Short code dialling" allows a customer to associate short codes with commonly-dialled numbers. Alarm calls can be booked at specified times, and are made automatically without human intervention. Incoming calls can be barred, as can outgoing ones. A diversion service allows all incoming calls to be diverted to another telephone, either immediately, or if a call to the original number remains unanswered for a specified period of time, or if the original number is busy. Three-party calls can be set up automatically, without involving the operator. .pp Making use of these facilities presents the caller with something of a problem. With conventional telephone exchanges, feedback is provided on what is happening to a call by the use of four tones \(em the dial tone, the busy tone, the ringing tone, and the number unavailable tone. For the more sophisticated interaction which is expected on the advanced exchange, a much greater variety of status signals is required. The obvious solution is to use computer-generated spoken messages to inform the caller when these services are invoked, and to guide him through the sequences of actions needed to set up facilities like call re-direction. For example, the messages used by the exchange when a user accesses the alarm call service are .LB .NI Alarm call service. Dial the time of your alarm call followed by square\u\(dg\d. .FN 1 \(dg\d"Square" is the term used for the "#" key on the touch-tone telephone.\u .EF .NI You have booked an alarm call for seven thirty hours. .NI Alarm call operator. At the third stroke it will be seven thirty. .LE .pp Because of the rather small vocabulary, the number of messages that can be stored in their entirety rather than being formed by concatenation of smaller units, and the short time which was available for development, System\ X stores speech as a time waveform, slightly compressed by a time-domain encoding operation (such techniques are described in Chapter 3). Utterances which contain variable parts, like the time of alarm in the messages above, are formed by inserting separately-recorded digits in a fixed "carrier" message. No attempt is made to apply uniform intonation contours to the synthetic utterances. The resulting speech is of excellent quality (being a slightly compressed recording of a human voice), but sometimes exhibits somewhat anomalous pitch contours. For example, the digits comprising numbers often sound rather jerky and out-of-context \(em which indeed they are. .pp Even more advanced facilities can be expected on telephone exchanges in the future. A message storage capability is one example. Although automatic call recording machines have been available for years, a centralized facility could time and date a message, collect the caller's identity (using the telephone keypad), and allow the recipient to select messages left for him through an interactive dialogue so that he could control the order in which he listens to them. He could choose to leave certain messages to be dealt with later, or re-route them to a colleague. He may even wish to leave reminders for himself, to be dialled automatically at specified times (like alarm calls with user-defined information attached). The sender of a message could be informed automatically by the system when it is delivered. None of this requires speech recognition, but it does need economical speech .ul storage, and also speech .ul synthesis (for time and date tags). .sh "1.5 Travel consultant" .pp Some current research in speech communication with computers is aimed at embedding the dialogue in a task environment which provides it with an overall contextual framework. This in fact was the motivation for the experimental telephone enquiry service described above, and it was observed that people are able to tolerate rather low quality speech if they feel that the interaction is worthwhile. One step further is the use of speech .ul input as well as output, and here the context of the conversation which is provided by the task environment can be used to improve recognition accuracy significantly. A system set up at Bell Telephone Laboratories indicates what we can expect to find operating commercially in the future (Levinson and Shipley, 1980). .[ Levinson Shipley 1980 .] It provides timetable information about airline flights, and allows the user to make reservations. .pp An example dialogue is given in Table 1.7. .RF .fi .nh .na .in 0.3i .nr x0 \w'COMPUTER: ' .nr x1 \w'CALLER: ' .in+\n(x0u .ti-\n(x0u COMPUTER: This is the Bell Laboratories flight information system. May I help you? .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' I would like to go to Chicago. .ti-\n(x0u COMPUTER: Please specify the day of your departure. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' I want to leave at four p.m.. .ti-\n(x0u COMPUTER: Please specify the day of your departure. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' I want to depart on the two five May. .ti-\n(x0u COMPUTER: Flight number nine two leaves New York at four p.m. arrives in Chicago at five twenty five p.m.. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' What plane is on the flight? .ti-\n(x0u COMPUTER: The aircraft is a Boeing seven twenty seven. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' How much is the fare? .ti-\n(x0u COMPUTER: The round trip coach fare is one hundred forty two dollars. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' I want a first class seat. .ti-\n(x0u COMPUTER: One seat thank you. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' What is the fare? .ti-\n(x0u COMPUTER: The round trip first class fare is one hundred eighty four dollars. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' Please repeat the arrival time. .ti-\n(x0u COMPUTER: The arrival time is five twenty five p.m.. .ti-\n(x0u CALLER:\h'\n(x0u-\n(x1u' I will take the flight. .ti-\n(x0u COMPUTER: Your reservation on flight number nine two to Chicago on Friday is confirmed. Thank you. .in 0 .nf .MT 2 Table 1.7 A conversation with an airline flight information service (from Levinson and Shipley, 1980) .TE .[ Levinson Shipley 1980 .] The user dials the system from an ordinary telephone. The recognition side must be trained by each user, and accepts isolated words spoken with brief pauses between them. The voice response unit has a vocabulary of around 200 words, and synthesizes its answers by slotting words into "templates" evoked by the speech understanding part in response to a query. For example, .LB .NI This flight makes \(em stops .NI Flight number \(em leaves \(em at \(em , arrives in \(em at \(em .LE are templates which when called with specific slot fillers could produce the utterances .LB .NI This flight makes three stops .NI Flight number nine two leaves New York at four p.m., arrives in Chicago at five twenty-five p.m. .LE The chief research interest of the system is in its speech understanding capabilities, and the method used for speech output is relatively straightforward. The templates and words are recorded, digitized, compressed slightly, and stored on disk files (totalling a few hundred thousand bytes of storage), using techniques similar to those of System\ X. Again, no independent manipulation of pitch is possible, and so the utterances sound intelligible but the transition between templates and slot fillers is not completely fluent. However, the overall context of the interaction means that the communication is not seriously disrupted even if the machine occasionally misunderstands the man or vice versa. The user's attention is drawn away from recognition accuracy and focussed on the exchange of information with the machine. The authors conclude that progress in speech recognition can best be made by studying it in the context of communication rather than in a vacuum or as part of a one-way channel, and the same is undoubtedly true of speech synthesis as well. .sh "1.6 Reading machine for the blind" .pp Perhaps the most advanced attempt to provide speech output from a computer is the Kurzweil reading machine for the blind, first marketed in the late 1970's (Figure 1.4). .FC "Figure 1.4" This device reads an ordinary book aloud. Users adjust the reading speed according to the content of the material and their familiarity with it, and the maximum rate has recently been improved to around 225 words per minute \(em perhaps half as fast again as normal human speech rates. .pp As well as generating speech from text, the machine has to scan the document being read and identify the characters presented to it. A scanning camera is used, controlled by a program which searches for and tracks the lines of text. The output of the camera is digitized, and the image is enhanced using signal-processing techniques. Next each individual letter must be isolated, and its geometric features identified and compared with a pre-stored table of letter shapes. Isolation of letters is not at all trivial, for many type fonts have "ligatures" which are combinations of characters joined together (for example, the letters "fi" are often run together.) The machine must cope with many printed type fonts, as well as typewritten ones. The text-recognition side of the Kurzweil reading machine is in fact one of its most advanced features. .pp We will discuss the problem of speech generation from text in Chapter 9. It has many facets. First there is pronunciation, the translation of letters to sounds. It is important to take into account the morphological structure of words, dividing them into "root" and "endings". Many words have concatenated suffixes (like "like-li-ness"). These are important to detect, because a final "e" which appears on a root word is not pronounced itself but affects the pronunciation of the previous vowel. Then there is the difficulty that some words look the same but are pronounced differently, depending on their meaning or on the syntactic part that they play in the sentence. Appropriate intonation is extremely difficult to generate from a plain textual representation, for it depends on the meaning of the text and the way in which emphasis is given to it by the reader. Similarly the rhythmic structure is important, partly for correct pronunciation and partly for purposes of emphasis. Finally the sounds that have been deduced from the text need to be synthesized into acoustic form, taking due account of the many and varied contextual effects that occur in natural speech. This by itself is a challenging problem. .pp The performance of the Kurzweil reading machine is not good. While it seems to be true that some blind people can make use of it, it is far from comprehensible to an untrained listener. For example, it will miss out words and even whole phrases, hesitate in a stuttering manner, blatantly mis-pronounce many words, fail to detect "e"s which should be silent, and give completely wrong rhythms to words, making them impossible to understand. Its intonation is decidedly unnatural, monotonous, and often downright misleading. When it reads completely new text to people unfamiliar with its quirks, they invariably fail to understand more than an odd word here and there, and do not improve significantly when the text is repeated more than once. Naturally performance improves if the material is familiar or expected in some way. One useful feature is the machine's ability to spell out difficult words on command from the user. .pp While not wishing to denigrate the Kurzweil machine, which is a remarkable achievement in that it integrates together many different advanced technologies, there is no doubt that the state of the art in speech synthesis directly from unadorned text is extremely primitive, at present. It is vital not to overemphasize the potential usefulness of abysmal speech, which takes a great deal of training on the part of the user before it becomes at all intelligible. To make a rather extreme analogy, Morse code could be used as audio output, requiring a great deal of training, but capable of being understood at quite high rates by an expert. It could be generated very cheaply. But clearly the man in the street would find it quite unacceptable as an audio output medium, because of the excessive effort required to learn to use it. In many applications, very bad synthetic speech is just as useless. However, the issue is complicated by the fact that for people who use synthesizers regularly, synthetic speech becomes quite easily comprehensible. We will return to the problem of evaluating the quality of artificial speech later in the book (Chapter 8). .sh "1.7 System considerations for speech output" .pp Fortunately, very many of the applications of speech output from computers do not need to read unadorned text. In all the example systems described above (except the reading machine), it is enough to be able to store utterances in some representation which can include pre-programmed cues for pronunciation, rhythm, and intonation in a much more explicit way than ordinary text does. .pp Of course, techniques for storing audio information have been in use for decades. For example, a domestic cassette tape recorder stores speech at much better than telephone quality at very low cost. The method of direct recording of an analogue waveform is currently used for announcements in the telephone network to provide information such as the time, weather forecasts, and even bedtime stories. However, it is difficult to provide rapid access to messages stored in analogue form, and although some computer peripherals which use analogue recordings for voice-response applications have been marketed \(em they are discussed briefly at the beginning of Chapter 3 \(em they have been superseded by digital storage techniques. .pp Although direct storage of a digitized audio waveform is used in some voice-response systems, the approach has certain limitations. The most obvious one is the large storage requirement: suitable coding can reduce the data-rate of speech to as little as one hundredth of that needed by direct digitization, and textual representations reduce it by another factor of ten or twenty. (Of course, the speech quality is inevitably compromised somewhat by data-compression techniques.) However, the cost of storage is dropping so fast that this is not necessarily an overriding factor. A more fundamental limitation is that utterances stored directly cannot sensibly be modified in any way to take account of differing contexts. .pp If the results of certain kinds of analyses of utterances are stored, instead of simply the digitized waveform, a great deal more flexibility can be gained. It is possible to separate out the features of intonation and amplitude from the articulation of the speech, and this raises the attractive possibility of regenerating utterances with pitch contours different from those with which they were recorded. The primary analysis technique used for this purpose is .ul linear prediction of speech, and this is treated in some detail in Chapter 6. It also reduces drastically the data-rate of speech, by a factor of around 50. It is likely that many voice-response systems in the short- and medium-term future will use linear predictive representations for utterance storage. .pp For maximum flexibility, however, it is preferable to store a textual representation of the utterance. There is an important distinction between speech .ul storage, where an actual human utterance is recorded, perhaps processed to lower the data-rate, and stored for subsequent regeneration when required, and speech .ul synthesis, where the machine produces its own individual utterances which are not based on recordings of a person saying the same thing. The difference is summarized in Figure 1.5. .FC "Figure 1.5" In both cases something is stored: for the first it is a direct representation of an actual human utterance, while for the second it is a typed .ul description of the utterance in terms of the sounds, or phonemes, which constitute it. The accent and tone of voice of the human speaker will be apparent in the stored speech output, while for synthetic speech the accent is the machine's and the tone of voice is determined by the synthesis program. .pp Probably the most attractive representation of utterances in man-machine systems is ordinary English text, as used by the Kurzweil reading machine. But, as noted above, this poses extraordinarily difficult problems for the synthesis procedure, and these inevitably result in severely degraded speech. Although in the very long term these problems may indeed be solved, most speech output systems can adopt as their representation of an utterance a description of it which explicitly conveys the difficult features of intonation, rhythm, and even pronunciation. In the kind of applications described above (barring the reading machine), input will be prepared by a programmer as he builds the software system which supports the interactive dialogue. Although it is important that the method of specifying utterances be easily learned, it is not necessary that plain English is used. It should be simple for the programmer to enter new utterances and modify them on-line in cut-and-try attempts to render the man-machine dialogue as natural as possible. A phonetic input can be quite adequate for this, especially if the system allows the programmer to hear immediately the synthesized version of the message he types. Furthermore, markers which indicate rhythm and intonation can be added to the message so that the system does not have to deduce these features by attempting to "understand" the plain text. .pp This brings us to another disadvantage of speech storage as compared with speech synthesis. To provide utterances for a voice response system using stored human speech, one must assemble together special input hardware, a quiet room, and (probably) a dedicated computer. If the speech is to be heavily encoded, either expensive special hardware is required or the encoding process, if performed by software on a general-purpose computer, will take a considerable length of time (perhaps hundreds of times real-time). In either case, time-consuming editing of the speech will be necessary, with follow-up recordings to clarify sections of speech which turn out to be unsuitable or badly recorded. If at a later date the voice response system needs modification, it will be necessary to recall the same speaker, or re-record the entire utterance set. This discourages the application programmer from adjusting his dialogue in the light of experience. Synthesizing from a textual representation, on the other hand, allows him to change a speech prompt as simply as he could a VDU one, and evaluate its effect immediately. .pp We will return to methods of digitizing and compacting speech in Chapters 3 and 4, and carry on to consider speech synthesis in subsequent chapters. Firstly, however, it is necessary to take a look at what speech is and how people produce it. .sh "1.8 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "1.9 Further reading" .pp There are remarkably few general books on speech output, although a substantial specialist literature exists for the subject. In addition to the references listed above, I suggest that you look at the following. .LB "nn" .\"Ainsworth-1976-1 .]- .ds [A Ainsworth, W.A. .ds [D 1976 .ds [T Mechanisms of speech recognition .ds [I Pergamon .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n A nice, easy-going introduction to speech recognition, this book covers the acoustic structure of the speech signal in a way which makes it useful as background reading for speech synthesis as well. It complements Lea, 1980, cited above; which presents more recent results in greater depth. .in-2n .\"Flanagan-1973-2 .]- .ds [A Flanagan, J.L. .as [A " and Rabiner, L.R. (Editors) .ds [D 1973 .ds [T Speech synthesis .ds [I Wiley .nr [T 0 .nr [A 0 .nr [O 0 .][ 2 book .in+2n This is a collection of previously-published research papers on speech synthesis, rather than a unified book. It contains many of the classic papers on the subject from 1940\ -\ 1972, and is a very useful reference work. .in-2n .\"LeBoss-1980-3 .]- .ds [A LeBoss, B. .ds [D 1980 .ds [K * .ds [T Speech I/O is making itself heard .ds [J Electronics .ds [O May\ 22 .ds [P 95-105 .nr [P 1 .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n The magazine .ul Electronics is an excellent source of up-to-the-minute news, product announcements, titbits, and rumours in the commercial speech technology world. This particular article discusses the projected size of the voice output market and gives a brief synopsis of the activities of several interested companies. .in-2n .\"Witten-1980-5 .]- .ds [A Witten, I.H. .ds [D 1980 .ds [T Communicating with microcomputers .ds [I Academic Press .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n A recent book on microcomputer technology, this is unusual in that it contains a major section on speech communication with computers (as well as ones on computer buses, interfaces, and graphics). .in-2n .LE "nn" .EQ delim $$ .EN .CH "2 WHAT IS SPEECH?" .ds RT "What is speech? .ds CX "Principles of computer speech .pp People speak by using their vocal cords as a sound source, and making rapid gestures of the articulatory organs (tongue, lips, jaw, and so on). The resulting changes in shape of the vocal tract allow production of the different sounds that we know as the vowels and consonants of ordinary language. .pp What is it necessary to learn about this process for the purposes of speech output from computers? That depends crucially upon how speech is represented in the system. If utterances are stored as time waveforms \(em and this is what we will be discussing in the next chapter \(em the structure of speech is not important. If frequency-related parameters of particular natural utterances are stored, then it is advantageous to take into account some of the acoustic properties of the speech waveform. .pp This point can be brought into focus by contrasting the transmission (or storage) of speech with that of real-life television pictures, as has been proposed for a videophone service. Massive data reductions, of the order of 50:1, can be achieved for speech, using techniques that are described in later chapters. For pictures, data reduction is still an important issue \(em even more so for the videophone than for the telephone, because of the vastly higher information rates involved. Unfortunately, the potential for data reduction is much smaller \(em nothing like the 50:1 figure quoted above. This is because speech sounds have definite characteristics, imparted by the fact that they are produced by a human vocal tract, which can be exploited for data reduction. Television pictures have no equivalent generative structure, for they show just those things that the camera points at. .pp Moving up from frequency-related parameters of .ul particular utterances, it is possible to store such parameters in a .ul general form which characterizes the sound segments that appear in spoken language. This immediately raises the issue of .ul classification of sound segments, to form a basis for storing generalized acoustic information and for retrieval of the information needed to synthesize any particular utterance. Speech is by nature continuous, and any synthesis system based upon discrete classification must come to terms with this by tackling the problems of transition from one segment to another, and local modification of sound segments as a function of their context. .pp This brings us to another level of representation. So far we have talked of the .ul acoustic nature of speech, but when we have to cope with transitions between discrete sound segments it may be fruitful to consider .ul articulatory properties as well. Any model of the speech production process is in effect a model of the articulatory process that generates the speech. Some speech research is concerned with modelling the vocal tract directly, rather than modelling the acoustic output from it. One might specify, for example, position of tongue and posture of jaw and lips for a vowel, instead of giving frequency-related characteristics of it. This is a potent tool in linguistic research, for it brings one closer to human production of speech \(em in particular to the connection between brain and articulators. .pp Articulatory synthesis holds a promise of high-quality speech, for the transitional effects caused by tongue and jaw inertia can be modelled directly. However, this potential has not yet been realized. Speech from current articulatory models is of much poorer quality than that from acoustically-based synthesis methods. The major problem is in gaining data about articulatory behaviour during running speech \(em it is much easier to perform acoustic analysis on the resulting sound than it is to examine the vocal organs in action. Because of this, the subject is not treated in this book. We will only look at articulatory properties insofar as they help us to understand, in a qualitative way, the acoustic nature of speech. .pp Speech, however, is much more than mere articulation. Consider \(em admittedly a rather extreme and chauvinistic example \(em the number of ways a girl can say "yes". Breathy voice, slow tempo, low pitch \(em these are all characteristics which affect the utterance as a whole, rather than being classifiable into individual sound segments. Linguists call them "prosodic" or "suprasegmental" features, for they relate to overall aspects of the utterance, and distinguish them from "segmental" ones which concern the articulation of individual segments of syllables. The most important prosodic features are pitch, or fundamental frequency of the voice, and rhythm. .pp This chapter provides a brief introduction to the nature of the speech signal. Depending upon what speech output techniques we use, it may be necessary to understand something of the acoustic nature of the speech signal; the system that generates it (the vocal tract); commonly-used classifications of sound segments; and the prosodic aspects of speech. This material is little used in the early chapters of the book, but becomes increasingly important as the story unfolds. Hence you may skip the remainder of this chapter if you wish, but should return to it later to pick up more background whenever it becomes necessary. .sh "2.1 The anatomy of speech" .pp The so-called "voiced" sounds of speech \(em like the sound you make when you say "aaah" \(em are produced by passing air up from the lungs through the larynx or voicebox, which is situated just behind the Adam's apple. The vocal tract from the larynx to the lips acts as a resonant cavity, amplifying certain frequencies and attenuating others. .pp The waveform generated by the larynx, however, is not simply sinusoidal. (If it were, the vocal tract resonances would merely give a sine wave of the same frequency but amplified or attenuated according to how close it was to the nearest resonance.) The larynx contains two folds of skin \(em the vocal cords \(em which blow apart and flap together again in each cycle of the pitch period. The pitch of a male voice in speech varies from as low as 50\ Hz (cycles per second) to perhaps 250\ Hz, with a typical median value of 100\ Hz. For a female voice the range is higher, up to about 500\ Hz in speech. Singing can go much higher: a top C sung by a soprano has a frequency of just over 1000\ Hz, and some opera singers can reach substantially higher than this. .pp The flapping action of the vocal cords gives a waveform which can be approximated by a triangular pulse (this and other approximations will be discussed in Chapter 5). It has a rich spectrum of harmonics, decaying at around 12\ dB/octave, and each harmonic is affected by the vocal tract resonances. .rh "Vocal tract resonances." A simple model of the vocal tract is an organ-pipe-like cylindrical tube (Figure 2.1), with a sound source at one end (the larynx) and open at the other (the lips). .FC "Figure 2.1" This has resonances at wavelengths $4L$, $4L/3$, $4L/5$, ..., where $L$ is the length of the tube; and these correspond to frequencies $c/4L$, $3c/4L$, $5c/4L$, ...\ Hz, $c$ being the speed of sound in air. Calculating these frequencies, using a typical figure for the distance between larynx and lips of 17\ cm, and $c = 340$\ m/s for the speed of sound, leads to resonances at approximately 500\ Hz, 1500\ Hz, 2500\ Hz, ... . .pp When excited by the harmonic-rich waveform of the larynx, the vocal tract resonances produce peaks known as .ul formants in the energy spectrum of the speech wave (Figure 2.2). .FC "Figure 2.2" The lowest formant, called formant one, varies from around 200\ Hz to 1000\ Hz during speech, the exact range depending on the size of the vocal tract. Formant two varies from around 500 to 2500\ Hz, and formant three from around 1500 to 3500\ Hz. .pp You can easily hear the lowest formant by whispering the vowels in the words "heed", "hid", "head", "had", "hod", "hawed", and "who'd". They appear to have a steadily descending pitch, yet since you are whispering there is no fundamental frequency. What you hear is the lowest resonance of the vocal tract \(em formant one. Some masochistic people can play simple tunes with this formant by putting their mouth in successive vowel shapes and knocking the top of their head with their knuckles \(em hard! .pp A difficulty occurs when trying to identify the lower formants for speakers with high-pitched voices. When a formant frequency falls below the fundamental excitation frequency of the voice, its effect is diminished \(em although it is still present. The vibrato used by opera singers provides a very low-frequency excitation (at the vibrato rate) which helps to illuminate the lower formants even when the pitch of the voice is very high. .pp Of course, speech is not a static phenomenon. The organ-pipe model describes the speech spectrum during a continuously held vowel with the mouth in a neutral position such as for "aaah". But in real speech the tongue and lips are in continuous motion, altering the shape of the vocal tract and hence the positions of the resonances. It is as if the organ-pipe were being squeezed and expanded in different places all the time. Say .ul ee as in "heed" and feel how close your tongue is to the roof of your mouth, causing a constriction near the front of the vocal cavity. .pp Linguists and speech engineers use a special frequency analyser called a "sound spectrograph" to make a three-dimensional plot of the variation of the speech energy spectrum with time. Figure 2.3 shows a spectrogram of the utterance "go away". .FC "Figure 2.3" Frequency is given on the vertical axis, and bands are shown at the beginning to indicate the scale. Time is plotted horizontally, and energy is given by the darkness of any particular area. The lower few formants can be seen as dark bands extending horizontally, and they are in continuous motion. In the neutral first vowel of "away", the formant frequencies pass through approximately the 500\ Hz, 1500\ Hz, and 2500\ Hz that we calculated earlier. (In fact, formants two and three are somewhat lower than these values.) .pp The fine vertical striations in the spectrogram correspond to single openings of the vocal cords. Pitch changes continuously throughout an utterance, and this can be seen on the spectrogram by the differences in spacing of the striations. Pitch change, or .ul intonation, is singularly important in lending naturalness to speech. .pp On a spectrogram, a continuously held vowel shows up as a static energy spectrum. But beware \(em what we call a vowel in everyday language is not the same thing as a "vowel" in phonetic terms. Say "I" and feel how the tongue moves continuously while you're speaking. Technically, this is a .ul diphthong or slide between two vowel positions, and not a single vowel. If you say .ul ar as in "hard", and change slowly to .ul ee as in "heed", you will obtain a diphthong not unlike that in "I". And there are many more phonetically different vowel sounds than the a, e, i, o, and u that we normally think of. The words "hood" and "mood" have different vowels, for example, as do "head" and "mead". The principal acoustic difference between the various vowel sounds is in the frequencies of the first two formants. .pp A further complication is introduced by the nasal tract. This is a large cavity which is coupled to the oral tract by a passage at the back of the mouth. The passage is guarded by a flap of skin called the "velum". You know about this because inadvertent opening of the velum while swallowing causes food or drink to go up your nose. The nasal cavity is switched in and out of the vocal tract by the velum during speech. It is used for consonants .ul m, .ul n, and the .ul ng sound in the word "singing". Vowels are frequently nasalized too. A very effective demonstration of the amount of nasalization in ordinary speech can be obtained by cutting a nose-shaped hole in a large baffle which divides a room, speaking normally with one's nose in the hole, and having someone listen on the other side. The frequency of occurrence of nasal sounds, and the volume of sound that is emitted through the nose, are both surprisingly large. Interestingly enough, when we say in conversation that someone sounds "nasal", we usually mean "non-nasal". When the nasal passages are blocked by a cold, nasal sounds are missing \(em .ul n\c \&'s turn into .ul d\c \&'s, and .ul m\c \&'s to .ul b\c \&'s. .pp When the nasal cavity is switched in to the vocal tract, it introduces formant resonances, just as the oral cavity does. Although we cannot alter the shape of the nasal tract significantly, the nasal formant pattern is not fixed, because the oral tract does play a part in nasal resonances. If you say .ul m, .ul n, and .ul ng continuously, you can hear the difference and feel how it is produced by altering the combined nasal/oral tract resonances with your tongue position. The nasal cavity operates in parallel with the oral one: this causes the two resonance patterns to be summed together, with resulting complications which will be discussed in Chapter 5. .rh "Sound sources." Speech involves sounds other than those caused by regular vibration of the larynx. When you whisper, the folds of the larynx are held slightly apart so that the air passing between them becomes turbulent, causing a noisy excitation of the resonant cavity. The formant peaks are still present, superimposed on the noise. Such "aspirated" sounds occur in the .ul h of "hello", and for a very short time after the lips are opened at the beginning of "pit". .pp Constrictions made in the mouth produce hissy noises such as .ul ss, .ul sh, and .ul f. For example, in .ul ss the tip of the tongue is high up, very close to the roof of the mouth. Turbulent air passing through this constriction causes a random noise excitation, known as "frication". Actually, the roof of the mouth is quite a complicated object. You can feel with your tongue a bony hump or ridge just behind the front teeth, and it is this that forms a constriction with the tongue for .ul s. In .ul sh, the tongue is flattened close to the roof of the mouth slightly farther back, in a position rather similar to that for .ul ee but with a narrower constriction, while .ul f is produced with the upper teeth and lower lip. Because they are made near the front of the mouth, the resonances of the vocal tract have little effect on these fricative sounds. .pp To distinguish them from aspiration and frication, the ordinary speech sounds (like "aaah") which have their source in larynx vibration are known technically as "voiced". Aspirated and fricative sounds are called "unvoiced". Thus the three different sound types can be classified as .LB .NP voiced .NP unvoiced (fricative) .NP unvoiced (aspirated). .LE Can any of these three types occur together? It would seem that voicing and aspiration can not, for the former requires the larynx to be vibrating regularly, but for the latter it must be generating turbulent noise. However, there is a condition known technically as "breathy voice" which occurs when the vocal cords are slightly apart, still vibrating, but with a large volume of air passing between to create turbulence. Voicing can easily occur in conjunction with frication. Corresponding to .ul s, .ul sh, and .ul f we get the .ul voiced fricatives .ul z, the sound in the middle of words like "vision" which I will call .ul zh, and .ul v. A simple illustration of voicing is to say "ffffvvvvffff\ ...". During the voiced part you can feel the larynx vibrations with a finger on your Adam's apple, and it can be heard quite clearly if you stop up your ears. Technically, there is nothing to prevent frication and aspiration from occurring together \(em they do, for example, when a voiced fricative is whispered \(em but the combination is not an important one. .pp The complicated acoustic effects of noisy excitations in speech can be seen in the spectrogram in Figure 2.4 of "high altitude jets whizz past screaming". .FC "Figure 2.4" .rh "The source-filter model of speech production." We have been talking in terms of a sound source (be it voiced or unvoiced) exciting the resonances of the oral (and possible the nasal) tract. This model, which is used extensively in speech analysis and synthesis, is known as the source-filter model of speech production. The reason for its success is that the effect of the resonances can be modelled as a frequency-selective filter, operating on an input which is the source excitation. Thus the frequency spectrum of the source is modified by multiplying it by the frequency characteristic of the filter (or adding it, if amplitudes are expressed logarithmically). This can be seen in Figure 2.5, which shows a source spectrum and filter characteristic which combine to give the overall spectrum of Figure 2.2. .FC "Figure 2.5" .pp Although, as mentioned above, the various fricatives are not subjected to the resonances of the vocal tract to the same extent that voiced and aspirated sounds are, they can still be modelled as a noise source followed by a filter to give them their different sound qualities. .pp The source-filter model is an oversimplification of the actual speech production system. There is inevitably some coupling between the vocal tract and the lungs, through the glottis, during the period when it is open. This effectively makes the filter characteristics change during each individual cycle of the excitation. However, although the effect is of interest to speech researchers, it is probably not of great significance for practical speech output. .pp One very interesting implication of the source-filter model is that the prosodic features of pitch and amplitude are largely properties of the source; while segmental ones are introduced by the filter. This makes it possible to separate some aspects of overall prosody from the actual segmental content of an utterance, so that, for example, a human utterance can be stored initially and then spoken by a machine with a variety of different intonations. .sh "2.2 Classification of speech sounds" .pp The need to classify sound segments as a basis for storing generalized acoustic information and retrieving it was mentioned earlier. There is a real difficulty here because speech is by nature continuous and classifications are discrete. It is important to remember this difficulty because it is all too easy to criticize the complex and often confusing attempts of linguists to tackle the classification task. .pp Linguists call a written representation of the .ul sounds of an utterance a "phonetic transcription" of it. The same utterance can be transcribed at different levels of detail: simple transcriptions are called "broad" and more specific ones are called "narrow". Perhaps the most logically satisfying kind of transcription employs units termed "phonemes". This is the broadest transcription, and is sometimes called a .ul phonemic transcription to emphasize that that it is in terms of phonemes. Unfortunately, the word "phoneme" is often used somewhat loosely. In its true sense, a phoneme is a .ul logical unit, rather than a physical, acoustic, one, and is defined in relation to a particular language by reference to its use in discriminating different words. Classifications of sounds which are based on their semantic role as word-discriminators are called .ul phonological classifications: we could ensure that there is no ambiguity in the sense with which we use the term "phoneme" by calling it a phonological unit, and the phonemic transcription could be called a phonological one. .rh "Broad phonetic transcription." A phoneme is an abstract unit representing a set of different sounds. The issue is confused by the fact that the members of the set actually sound very similar, if not identical, to the untrained ear \(em precisely because the difference between them plays no part in distinguishing words from each other in the particular language concerned. .pp Take the words "key" and "caw", for example. Despite the difference in spelling, both of them begin with a .ul k sound that belongs (in English) to the same phoneme set, called .ul k. However, say them two or three times each, concentrating on the position of the tongue during the .ul k. It is quite different in each case. For "key", it is raised, close to the roof of the mouth, in preparation for the .ul ee, whereas in "caw" it is much lower down. The sound of the .ul k is actually quite different in the two cases. Yet they belong to the same phoneme, for there is no pair of words which relies on this difference to distinguish them \(em "key" and "caw" are obviously distinguished by their vowels, not by the initial consonant. You probably cannot hear clearly the difference between the two .ul k\c \&'s, precisely because they belong to the same phoneme and so the difference is not important (for English). .pp The point is sharpened by considering another language where we make a distinction \(em and hence can hear the difference \(em between two sounds that belong, in the language, to the same phoneme. Japanese does not distinguish .ul r from .ul l. Japanese people .ul do not hear the difference between "lice" and "rice", in the same way that you do not hear the difference between the two .ul k\c \&'s above. Cockneys do not hear, except with a special effort, the difference between "has" and "as", or "haitch" and "aitch", for the Cockney dialect does not recognize initial .ul h\c \&'s. .pp So what is a phoneme? It is a set of sounds whose members do not discriminate between any words in the language under consideration. If you are mathematically minded you could think of it as an equivalence class of sounds, determined by the relationship .LB $sound sub 1$ is related to $sound sub 2$ if $sound sub 1$ and $sound sub 2$ do not discriminate any pair of words in the language. .LE The .ul p and .ul d in "pig" and "dig" belong to different phonemes (in English), because they discriminate the two words. .ul b, .ul f, and .ul j belong to different phonemes again. .ul i and .ul a in "hid" and "had" belong to different phonemes too. Proceeding like this, a list of phonemes can be drawn up. .pp Such a list is shown in Table 2.1, for British English. (The layout of the list does have some significance in terms of different categories of phonemes, which will be explained later.) In fact, linguists use an assortment of English letters, foreign letters, and special symbols to represent phonemes. In this book we use one- or two-letter codes, partly because they are more mnemonic, and partly because they are more suitable for communication to computers using standard peripheral devices. They are a direct transliteration of linguists' standard International Phonetic Association symbols. .RF .nr x1 3m+1.0i+0.5i+0.5i+0.5i+\w'y'u .nr x1 (\n(.l-\n(x1)/2 .in \n(x1u .ta 3m +1.0i +0.5i +0.5i +0.5i +0.5i +0.5i \fIuh\fR (the) \fIp\fR \fIt\fR \fIk\fR \fIa\fR (bud) \fIb\fR \fId\fR \fIg\fR \fIe\fR (head) \fIm\fR \fIn\fR \fIng\fR \fIi\fR (hid) \fIo\fR (hod) \fIr\fR \fIw\fR \fIl\fR \fIy\fR \fIu\fR (hood) \fIaa\fR (had) \fIs\fR \fIz\fR \fIee\fR (heed) \fIsh\fR \fIzh\fR \fIer\fR (heard) \fIf\fR \fIv\fR \fIuu\fR (food) \fIth\fR \fIdh\fR \fIar\fR (hard) \fIch\fR \fIj\fR \fIaw\fR (hoard) \fIh\fR .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 2.1 The phonemes of British English" .pp We will discuss the sounds which make up each of these phoneme classes shortly. First, however, it is worthwhile pointing out some rather tricky points in the definition of these phonemes. .rh "Phonological difficulties." There are snags with phonological classification, as there are in any area where attempts are made to make completely logical statements about human activity. Consider .ul h and the .ul ng in "singing". (\c .ul ng is certainly not an .ul n sound followed by a .ul g sound, although it is true that in some English accents "singing" is rendered with the .ul ng followed by a .ul g at each of its two occurrences.) No words end with .ul h, and none begin with .ul ng. (Notice that we are still talking about British English. In Chinese, the sound .ul ng is a word in its own right, and is a common family name. But we must stick with one language for phonological classification.) Hence it follows that there is no pair of words which is distinguished by the difference between .ul h and .ul ng. Technically, they belong to the same phoneme. However, technical considerations in this case must take second place to common sense! .pp The .ul j in "jig" is another interesting case. It can be considered to belong to a .ul j phoneme, or to be a sequence of two phonemes, .ul d followed by .ul zh (the sound in "vision"). There is disagreement on this point in phonetics textbooks, and we do not have the time (nor, probably, the inclination!) to consider the pros and cons of this moot point. I have resolved the matter arbitrarily by writing it as a separate phoneme. The .ul ch in "choose" is a similar case (\c .ul t followed by the .ul sh in "shoes"). .pp Another difficulty, this time where Table 2.1 does not show how to distinguish between two sounds which .ul do discriminate words in many people's English, is the .ul w in "witch" and that in "which". The latter is conventionally transcribed as a sequence of two phonemes, .ul h w. .pp The last few difficulties are all to do with deciding whether a sound belongs to a single phoneme class, or comprises a sequence of sounds each of which belongs to a phoneme. Are the .ul j in "jug", the .ul ch in "chug", and the .ul w in "which", single phonemes or not? The definition above of a phoneme as a "set of sounds whose members do not discriminate any words in the language" does not help us to answer this question. As far as this definition is concerned, we could go so far as to call each and every word of the language an individual phoneme! It is clear that some acoustic evidence, and quite a lot of judgement, is being used when phonemes such as those of Table 2.1 are defined. .pp So much for the consonants. This same problem occurs in vowel sounds, particularly in diphthongs, which are sequences of two vowel-like sounds. Do the vowels of "main" and "man" belong to different phonemes? Clearly so, if they are both transcribed as single units, for they distinguish the two words. Notwithstanding the fact that they are sequences of separate sounds, a logically consistent system could be constructed which gave separate, unitary, symbols to each diphthong. However, it is usual to employ a compound symbol which indicates explicitly the character of the two vowel-like sounds involved. We will transcribe the diphthong of "main" as a sequence of two vowels, .ul e (as in "head") and .ul i (as in "hid", not "I"). This is done primarily for economy of symbols, choosing the constituent sounds on the basis of the closest match to existing vowel sounds. (Note that this again violates purely .ul logical criteria for identifying phonemes.) .rh "Categories of speech sounds." A phoneme is defined as a set of sounds whose members to not discriminate between any words in the language under consideration. The phonemes themselves can be classified into groups which reflect similarities between them. This can be done in many different ways, using various criteria for classification. In fact, one branch of linguistic research is concerned with defining a set of "distinctive features" such that a phoneme class is uniquely identified by the values of the features. Distinctive features are binary, and include such things as voiced\(emunvoiced, fricative\(emnot\ fricative, aspirated\(emunaspirated. We will not be concerned here with such detailed classifications, but it is as well to know that they exist. .pp There is an everyday distinction between vowels and consonants. A vowel forms the nucleus of every syllable, and one or more consonants may optionally surround the vowel. But the distinction sometimes becomes a little ambiguous. Syllables like .ul sh are commonly uttered and certainly do not contain a vowel. Furthermore, when we say "vowel" in everyday language we usually refer to the .ul written vowels a, e, i, o, and u; there are many more vowel sounds. A vowel in orthography is different to a vowel as a phoneme. Is a diphthong a phonetic vowel? \(em certainly, by the syllable-nucleus criterion; but it is a little different from ordinary vowels because it is a changing sound rather than a constant one. .pp Table 2.2 shows one classification of the phonemes of Table 2.1, which will be useful in our later studies of speech synthesis from phonetics. It shows twelve vowels, including the rather peculiar one .ul uh (which corresponds to the first vowel in the word "above"). This is the sound produced by the vocal tract when it is in a relaxed, neutral position; and it never occurs in prominent, stressed, syllables. The vowels later in the list are almost always longer than the earlier ones. In fact, the first six (\c .ul uh, a, e, i, o, u\c ) are often called "short" vowels, and the last five (\c .ul ee, er, uu, ar, aw\c ) "long" ones. The shortness or longness of the one in the middle (\c .ul aa\c ) is rather ambiguous. .RF .nr x0 \w'000unvoiced fricative 'u .nr x1 \n(x0+\w'[not classified as individual phonemes]'u .nr x1 (\n(.l-\n(x1)/2 .in \n(x1u .ta \n(x0u .fi vowel \c .ul uh a e i o u aa ee er uu ar aw .br diphthong [not classified as individual phonemes] .br glide (or liquid) \c .ul r w l y .br stop .br \0\0\0unvoiced stop \c .ul p t k .br \0\0\0voiced stop \c .ul b d g .br nasal \c .ul m n ng .br fricative .br \0\0\0unvoiced fricative \c .ul s sh f th .br \0\0\0voiced fricative \c .ul z zh v dh .br affricate .br \0\0\0unvoiced affricate \c .ul ch .br \0\0\0voiced affricate \c .ul j .br aspirate \c .ul h .nf .in 0 .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .FG "Table 2.2 Phoneme categories" .pp Diphthongs pose no problem here because we have not classified them as single phonemes. .pp The remaining categories are consonants. The glides are quite similar to vowels and diphthongs, though; for they are voiced, continuous sounds. You can say them and prolong them. (This is also true of the fricatives.) .ul r is interesting because it can be realized acoustically in very different ways. Some people curl the tip of the tongue back \(em a so-called retroflex action of the tongue. Many people cannot do this, and their .ul r\c \&'s sound like .ul w\c \&'s. The stage Scotsman's .ul r is a trill where the tip of the tongue vibrates against the roof of the mouth. .ul l is also slightly unusual, for it is the only English phoneme which is "lateral" \(em air passes either side of it, in two separate passages. Welsh has another lateral sound, a fricative, which is written "ll" as in "Llandudno". .pp The next category is the stops. These are formed by stopping up the mouth, so that air pressure builds up behind the lips, and releasing this pressure suddenly. The result is a little explosion (and the stops are often called "plosives"), which usually creates a very short burst of fricative noise (and, in some cases, aspiration as well). They are further subdivided into voiced and unvoiced stops, depending upon whether voicing starts as soon as the plosion occurs (sometimes even before) or well after it. If you put your hand in front of your mouth when saying "pit" you can easily feel the puff of air that signals the plosion on the .ul p, and probably on the .ul t as well. .pp In a sense, nasals are really stops as well (and they are often called stops), for the oral tract is blocked although the nasal one is not. The peculiar fact that the nasal .ul ng never occurs at the beginning of a word (in English) was mentioned earlier. Notice that for stops and nasals there is a similarity in the .ul vertical direction of Table 2.2, between .ul p, .ul b, and .ul m; .ul t, .ul d, and .ul n; and .ul k, .ul g, and .ul ng. .ul p is an unvoiced version of .ul b (try saying them), and .ul m is a nasalized version (for .ul b is what you get when you have a cold and try to say .ul m\c ). These three sounds are all made at the front of the mouth, while .ul t, .ul d, and .ul n, which bear the same resemblance to each other, are made in the middle; and .ul k, .ul g, and .ul ng are made at the back. This introduces another possible classification, according to .ul place of articulation. .pp The unvoiced fricatives are quite straightforward, except perhaps for .ul th, which is the sound at the beginning of "thigh". They are paired with the voiced fricatives on the basis of place of articulation. The voiced version of .ul th is the .ul dh at the beginning of "thy". .ul zh is a fairly rare phoneme, which is heard in the middle of "vision". Affricates are similar to fricatives but begin with a stopped posture, and we mentioned earlier the controversy as to whether they should be considered to be single phonemes, or sequences of stop phonemes and fricatives. Finally comes the lonely aspirate, .ul h. Aspiration does occur elsewhere in speech, during the plosive burst of unvoiced stops. .rh "Narrow phonetic transcription." The phonological classification outlined above is based upon a clear rationale for distinguishing between sounds according to how they affect meaning \(em although the rationale does become somewhat muddied in difficult cases. Narrower transcriptions are not so systematic. They use units called .ul allophones, which are defined by reference to physical, acoustic, criteria rather than purely logical ones. ("Phone" is a more old-fashioned term for the same thing, and the misused word "phoneme" is often employed where allophone is meant, that is, as a physical rather than a logical unit.) Each phoneme has several allophones, more or less depending on how narrow or broad the transcription is, and the allophones are different acoustic realizations of the same logical unit. For example, the .ul k\c \&'s in "key" and "caw" may be considered as different allophones (in a slightly narrow transcription). Although we will not use symbols for allophones here, they are often indicated by diacritical marks in a text which modify the basic phoneme classes. For example, a tilde (~) over a vowel means that it is nasalized, while a small circle underneath a consonant means that it is devoiced. .pp Allophonic variation in speech is governed by a mechanism called .ul coarticulation, where a sound is affected by those that come either side of it. "Key"\-"caw" is a clear example of this, where the tongue position in the .ul k anticipates that of the following vowel \(em high in the first case, low in the second. Most allophonic variation in English is anticipatory, in that the sound is influenced by the following articulation rather than by preceding ones. .pp Nasalization is a feature which applies to vowels in English through anticipatory coarticulation. In many languages (for example, French) it is a .ul distinctive feature for vowels in that it serves to distinguish one vowel phoneme class from another. That this is not so in English sometimes tempts us to assume, incorrectly, that nasalization does not occur in vowels. It does, typically when the vowel is followed by a nasal consonant, and it is important for synthesis that nasalized vowel allophones are recognized and treated accordingly. .pp Coarticulation can be predicted by phonological rules, which show how a phonemic sequence will be realized by allophones. Such rules have been studied extensively by linguists. .pp The reason for coarticulation, and for the existence of allophones, lies in the physical constraints imposed by the motion of the articulatory organs \(em particularly their acceleration and deceleration. An immensely crude model is that the brain decides what phonemes to say (for it is concerned with semantic things, and the definition of a phoneme is a semantic one). It then takes this sequence and translates it into neural commands which actually move the articulators into target positions. However, other commands may be issued, and executed, before these targets are reached, and this accounts for coarticulation effects. Phonological rules for converting a phonemic sequence to an allophonic one are a sort of discrete model of the process. Particularly for work involving computers, it is possible that this rule-based approach will be overtaken by potentially more accurate methods which attempt to model the continuous articulatory phenomena directly. .sh "2.3 Prosody" .pp The phonetic classification introduced above divides speech into segments and classifies these into phonemes or allophones. Riding on top of this stream of segments are other, more global, attributes that dictate the overall prosody of the utterance. Prosody is defined by the Oxford English Dictionary as the "science of versification, laws of metre," which emphasizes the aspects of stress and rhythm that are central to classical verse. There are, however, many other features which are more or less global. These are collectively called prosodic or, equivalently, suprasegmental, features, for they lie above the level of phoneme or syllable segments. .pp Prosodic features can be split into two basic categories: features of voice quality and features of voice dynamics. Variations in voice quality, which are sometimes called "paralinguistic" phenomena, are accounted for by anatomical differences and long-term muscular idiosyncrasies (like a sore throat), and have little part to play in the kind of applications for speech output that have been sketched in Chapter 1. Variations in voice dynamics occur in three dimensions: pitch or fundamental frequency of the voice, time, and amplitude. Within the first, the pattern of pitch variation, or .ul intonation, can be distinguished from the overall range within which that variation occurs. The time dimension encompasses the rhythm of the speech, pauses, and the overall tempo \(em whether it is uttered quickly or slowly. The third dimension, amplitude, is of relatively minor importance. Intonation and rhythm work together to produce an effect commonly called "stress", and we will elaborate further on the nature of stress and discuss algorithms for synthesizing intonation and rhythm in Chapter 8. .pp These features have a very important role to play in communicating meaning. They are not fancy, optional components. It is their neglect which is largely responsible for the layman's stereotype of computer speech, a caricature of living speech \(em abrupt, arhythmic, and in a grating monotone \(em which was well characterized by Isaac Asimov when he wrote of speaking "all in capital letters". .pp Timing has a syntactic function in that it sometimes helps to distinguish nouns from verbs (\c .ul ex\c tract versus ex\c .ul tract\c ). and adjectives from verbs (app\c .ul rox\c imate versus approxi\c .ul mate\c ) \(em although segmental aspects play a part here too, for the vowel qualities differ in each pair of words. Nevertheless, if you make a mistake when assigning stress to words like these in conversation you are very likely to be queried as to what you actually said. .pp Intonation has a big effect on meaning too. Pitch often \(em but by no means always \(em rises on a question, the extent and abruptness of the rise depending on features like whether a genuine information-bearing reply or merely confirmation is expected. A distinctive pitch pattern accompanies the introduction of a new topic. In conjunction with rhythm, intonation can be used to bring out contrasts as in .LB .NI "He didn't have a .ul red car, he had a .ul black one." .LE In general, the intonation patterns used by a reader depend not only on the text itself, but on his interpretation of it, and also on his expectation of the listener's interpretation of it. For example: .LB .NI "He had a .ul red car" (I think you thought it was black), .NI "He had a red .ul bi\c cycle" (I think you thought it was a car). .LE .pp In natural speech, prosodic features are significantly influenced by whether the utterance is generated spontaneously or read aloud. The variations in spontaneous speech are enormous. There are all sorts of emotions which are plainly audible in everyday speech: sarcasm, excitement, rudeness, disagreement, sadness, fright, love. Variations in voice quality certainly play a part here. Even with "ordinary" cooperative friendly conversation, the need to find words and somehow fit them into an overall utterance produces great diversity of prosodic structures. Applications for speech output from computers do not, however, call for spontaneous conversation, but for a controlled delivery which is like that when reading aloud. Here, the speaker is articulating utterances which have been set out for him, reducing his cognitive load to one of understanding and interpreting the text rather than generating it. Unfortunately for us, linguists are (quite rightly) primarily interested in living, spontaneous speech rather than pre-prepared readings. .pp Nevertheless, the richness of prosody in speech even when reading from a book should not be underestimated. Read aloud to an audience and listen to the contrasts in voice dynamics deliberately introduced for variety's sake. If stories are to be read there is even a case for controlling voice .ul quality to cope with quotations and affective imitations. .pp We saw earlier that the source-filter model is particularly helpful in distinguishing prosodic features, which are largely properties of the source, from segmental ones, which belong to the filter. Pitch and amplitude are primarily source properties. Rhythm and speed of speaking are not, but neither are they filter properties, for they belong to the source-filter system as a whole and not specifically to either part of it. The difficult notion of stress is, from an acoustic point of view, a combination of pitch, rhythm, and amplitude. Even some features of voice quality can be attributed to the source (like laryngitis), although others \(em cleft palate, badly-fitting dentures \(em affect segmental features as well. .sh "2.4 Further reading" .pp This chapter has been no more than a cursory introduction to some of the difficult problems of linguistics and phonetics. Here are some readable books which discuss these problems further. .LB "nn" .\"Abercrombie-1967-1 .ds [F 1 .]- .ds [A Abercrombie, D. .ds [D 1967 .ds [T Elements of general phonetics .ds [I Edinburgh Univ Press .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is an excellent book which covers all of the areas of this chapter, in much more detail than has been possible here. .in-2n .\"Brown-1980-2 .ds [F 2 .]- .ds [A Brown, Gill .as [A ", Currie, K.L. .as [A ", and Kenworthy, J. .ds [D 1980 .ds [T Questions of intonation .ds [I Croom Helm .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n An intensive study of the prosodics of colloquial, living speech is presented, with particular reference to intonation. Although not particularly relevant to speech output from computers, this book gives great insight into how conversational speech differs from reading aloud. .in-2n .\"Fry-1979-1 .ds [F 1 .]- .ds [A Fry, D.B. .ds [D 1979 .ds [T The physics of speech .ds [I Cambridge University Press .ds [C Cambridge, England .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is a simple and readable account of speech science, with a good and completely non-mathematical introduction to frequency analysis. .in-2n .\"Ladefoged-1975-4 .ds [F 4 .]- .ds [A Ladefoged, P. .ds [D 1975 .ds [T A course in phonetics .ds [I Harcourt Brace and Johanovich .ds [C New York .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Usually books entitled "A course on ..." are dreadfully dull, but this is a wonderful exception. An exciting, readable, almost racy introduction to phonetics, full of little experiments you can try yourself. .in-2n .\"Lehiste-1970-5 .ds [F 5 .]- .ds [A Lehiste, I. .ds [D 1970 .ds [T Suprasegmentals .ds [I MIT Press .ds [C Cambridge, Massachusetts .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This fairly comprehensive study of the prosodics of speech complements Ladefoged's book, which is mainly concerned with segmental phonetics. .in-2n .\"O'Connor-1973-1 .ds [F 1 .]- .ds [A O'Connor, J.D. .ds [D 1973 .ds [T Phonetics .ds [I Penguin .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is another introductory book on phonetics. It is packed with information on all aspects of the subject. .in-2n .LE "nn" .EQ delim $$ .EN .CH "3 SPEECH STORAGE" .ds RT "Speech storage .ds CX "Principles of computer speech .pp The most familiar device that produces speech output is the ordinary tape recorder, which stores information in analogue form on magnetic tape. However, this is unsuitable for speech output from computers. One reason is that it is difficult to access different utterances quickly. Although random-access tape recorders do exist, they are expensive and subject to mechanical breakdown because of the stresses associated with frequent starting and stopping. .pp Storing speech on a rotating drum instead of tape offers the possibility of access to any track within one revolution time. For example, the IBM 7770 Audio Response Unit employs drums rotating twice a second which are able to store up to 32 500-msec words. These can be accessed randomly, within half a second at most. Although one can arrange to store longer words by allowing overflow on to an adjacent track at the end of the rotation period, the discrete time-slots provided by this system make it virtually impossible for it to generate connected utterances by assembling appropriate words from the store. .pp The Cognitronics Speechmaker has a similar structure, but with the analogue speech waveform recorded on photographic film. Storing audio waveforms optically is not an unusual technique, for this is how soundtracks are recorded on ordinary movie films. The original version of the "speaking clock" of the British Post Office used optical storage in concentric tracks on flat glass discs. It is described by Speight and Gill (1937), who include a fascinating account of how the utterances are synchronized. .[ Speight Gill 1937 .] A 4\ Hz signal from a pendulum clock was used to supply current to an electric motor, which drove a shaft equipped with cams and gears that rotated the glass discs containing utterances for seconds, minutes, and hours at appropriate speeds! .pp A second reason for avoiding analogue storage is price. It is difficult to see how a random-access tape recorder could be incorporated into a talking pocket calculator or child's toy without considerably inflating the cost. Solid-state electronics is much cheaper than mechanics. .pp But the best reason is that, in many of the applications we have discussed, it is necessary to form utterances by concatenating separately-recorded parts. It is totally infeasible, for example, to store each and every possible telephone number as an individual recording! And utterances that are formed by concatenating individual words which were recorded in isolation, or in a different context, do not sound completely natural. For example, in an early experiment, Stowe and Hampton (1961) recorded individual words on acoustic tape, spliced the tape with the words in a different order to make sentences, and played the result to subjects who were scored on the number of key words which they identified correctly. .[ Stowe Hampton 1961 .] The overall conclusion was that while embedding a word in normally-spoken sentences .ul increases the probability of recognition (because the extra context gives clues about the word), embedding a word in a constructed sentence, where intonation and rhythm are not properly rendered, .ul decreases the probability of recognition. When the speech was uttered slowly, however, a considerable improvement was noticed, indicating that if the listener has more processing time he can overcome the lack of proper intonation and rhythm. .pp Nevertheless, many present-day voice response systems .ul do store what amounts to a direct recording of the acoustic wave. However, the storage medium is digital rather than analogue. This means that standard computer storage devices can be used, providing rapid access to any segment of the speech at relatively low cost \(em for the economics of mass-production ensures a low price for random-access digital devices compared with random-access analogue ones. Furthermore, it reduces the amount of special equipment needed for speech output. One can buy very cheap speech input/output interfaces for home computers which connect to standard hobby buses. Another advantage of digital over analogue recording is that integrated circuit read-only memories (ROMs) can be used for hand-held devices which need small quantities of speech. Hence this chapter begins by showing how waveforms are stored digitally, and then describes some techniques for reducing the data needed for a given utterance. .sh "3.1 Storing waveforms digitally" .pp When an analogue signal is converted to digital form, it is made discrete both in time and in amplitude. Discretization in time is the operation of .ul sampling, whilst in amplitude it is .ul quantizing. It is worth pointing out that the transmission of analogue information by digital means is called "PCM" (standing for "pulse code modulation") in telecommunications jargon. Much of the theory of digital signal processing investigates signals which are sampled but not quantized (or quantized into sufficiently many levels to avoid inaccuracies). The operation of quantization, being non-linear, is not very amenable to theoretical analysis. Quantization introduces issues such as accumulation of round-off noise in arithmetic operations, which, although they are very important in practical implementations, can only be treated theoretically under certain somewhat unrealistic assumptions (in particular, independence of the quantization error from sample to sample). .rh "Sampling." A fundamental theorem of telecommunications states that a signal can only be reconstructed accurately from a sampled version if it does not contain components whose frequency is greater than half the frequency at which the sampling takes place. Figure 3.1(a) shows how a component of slightly greater than half the sampling frequency can masquerade, as far as an observer with access only to the sampled data can tell, as a component at slightly less than half the sampling frequency. .FC "Figure 3.1" Call the sampling interval $T$ seconds, so that the sampling frequency is $1/T$\ Hz. Then components at $1/2T+f$, $3/2T-f$, $3/2T+f$ and so on all masquerade as a component at $1/2T-f$. Similarly, components at frequencies just under the sampling frequency masquerade as very low-frequency components, as shown in Figure 3.1(b). This phenomenon is often called "aliasing". .pp Thus the continuous, infinite, frequency axis for the unsampled signal, where two components at different frequencies can always be distinguished, maps into a repetitive frequency axis when the signal is sampled. As depicted in Figure 3.2, the frequency interval $[1/T,~ 2/T)$ \u\(dg\d .FN 3 .sp \u\(dg\dIntervals are specified in brackets, with a square bracket representing a closed end of the interval and a round one representing an open one. Thus the interval $[1/T,~ 2/T)$ specifies the range $1/T ~ <= ~ frequency ~ < ~ 2/T$. .EF is mapped back into the band $[0,~ 1/T)$, as are the intervals $[2/T,~ 3/T)$, $[3/T,~ 4/T)$, and so on. .FC "Figure 3.2" Furthermore, the interval $[1/2T,~ 1/T)$ between half the sampling frequency and the sampling frequency, is mapped back into the interval below half the sampling frequency; but this time the mapping is backwards, with frequencies at just under $1/T$ being mapped to frequencies slightly greater than zero, and frequencies just over $1/2T$ being mapped to ones just under $1/2T$. The best way to represent a repeating frequency axis like this is as a circle. Figure 3.3 shows how the linear frequency axis for continuous systems maps on to a circular axis for sampled systems. .FC "Figure 3.3" For present purposes it is easiest to imagine the bottom half of the circle as being reflected into the top half, so that traversing the upper semicircle in the anticlockwise direction corresponds to frequencies increasing from 0 to $1/2T$ (half the sample frequency), and returning along the lower semicircle is actually the same as coming back round the upper one, and corresponds to frequencies from $1/2T$ to $1/T$ being mapped into the range $1/2T$ to 0. .pp As far as speech is concerned, then, we must ensure that before sampling a signal no significant components at greater than half the sample frequency are present. Furthermore, the sampled signal will only contain information about frequency components less than this, so the sample frequency must be chosen as twice the highest frequency of interest. For example, consider telephone-quality speech. Telephones provide a familiar standard of speech quality which, although it can only be an approximate "standard", will be much used throughout this book. The telephone network aims to transmit only frequencies lower than 3.4\ kHz. We saw in the previous chapter that this region will contain the information-bearing formants, and some \(em but not all \(em of the fricative and aspiration energy. Actually, transmitting speech through the telephone system degrades its quality very significantly, probably more than you realize since everyone is so accustomed to telephone speech. Try the dial-a-disc service and compare it with high-fidelity music for a striking example of the kind of degradation suffered. .pp For telephone speech, the sampling frequency must be chosen to be at least 6.8\ kHz. Since speech contains significant amounts of energy above 3.4\ kHz, it should be filtered before sampling to remove this; otherwise the higher components would be mapped back into the baseband and distort the low-frequency information. Because it is difficult to make filters that cut off very sharply, the sampling frequency is chosen rather greater than twice the highest frequency of interest. For example, the digital telephone network samples at 8\ kHz. The pre-sampling filter should have a cutoff frequency of 4\ kHz; aim for negligible distortion below 3.4\ kHz; and transmit negligible components above 4.6\ kHz \(em for these are reflected back into the band of interest, namely 0 to 3.4\ kHz. Figure 3.4 shows a block diagram for the input hardware. .FC "Figure 3.4" .rh "Quantization." Before considering specifications for the pre-sampling filter, let us turn from discretization in time to discretization in amplitude, that is, quantization. This is performed by an A/D converter (analogue-to-digital), which takes as input a constant analogue voltage (produced by the sampler) and generates a corresponding binary value as output. The simplest correspondence is .ul uniform quantization, where the amplitude range is split into equal regions by points termed "quantization levels", and the output is a binary representation of the nearest quantization level to the input voltage. Typically, 11-bit conversion is used for speech, giving 2048 quantization levels, and the signal is adjusted to have zero mean so that half the levels correspond to negative input voltages and the other half to positive ones. .pp It is, at first sight, surprising that as many as 11 bits are needed for adequate representation of speech signals. Research on the digital telephone network, for example, has concluded that a signal-to-noise ratio of some 26\-27\ dB is enough to avoid undue harshness of quality, loss of intelligibility, and listener fatigue for speech at a comfortable level in an otherwise reasonably good channel. Rabiner and Schafer (1978) suggest that about 36\ dB signal-to-noise ratio would "most likely provide adequate quality in a communications system". .[ Rabiner Schafer 1978 Digital processing of speech signals .] But 11-bit quantization seems to give a very much better signal-to-noise ratio than these figures. To estimate its magnitude, note that for N-bit quantization the error for each sample will lie between .LB $ - ~ 1 over 2 ~. 2 sup -N$ and $+ ~ 1 over 2 ~. 2 sup -N . $ .LE Assuming that it is uniformly distributed in this range \(em an assumption which is likely to be justified if the number of levels is sufficiently large \(em leads to a mean-squared error of .LB .EQ integral from {-2 sup -N-1} to {2 sup -N-1} ~e sup 2 p(e) de, .EN .LE where $p(e)$, the probability density function of the error $e$, is a constant which satisfies the usual probability normalization constraint, namely .LB .EQ integral from {-2 sup -N-1} to {2 sup -N-1} ~ p(e) de ~~=~ 1. .EN .LE Hence $p(e)=2 sup N $, and so the mean-squared error is $2 sup -2N /12$. This is $10 ~ log sub 10 (2 sup -2N /12)$\ dB, or around \-77\ dB for 11-bit quantization. .pp This noise level is relative to the maximum amplitude range of the conversion. A maximum-amplitude sine wave has a power of \-9\ dB relative to the same reference, giving a signal-to-noise ratio of some 68\ dB. This is far in excess of that needed for telephone-quality speech. However, look at the very peaky nature of the typical speech waveform given in Figure 3.5. .FC "Figure 3.5" If clipping is to be avoided, the maximum amplitude level of the A/D converter must be set at a value which makes the power of the speech signal very much less than a maximum-amplitude sine wave. Furthermore, different people speak at very different volumes, and the overall level fluctuates constantly with just one speaker. Experience shows that while 8- or 9-bit quantization may provide sufficient signal-to-noise ratio to preserve telephone-quality speech if the overall speaker levels are carefully controlled, about 11 bits are generally required to provide high-quality representation of speech with a uniform quantization. With 11 bits, a sine wave whose amplitude is only 1/32 of the full-scale value would be digitized with a signal-to-noise ratio of around 36\ dB, the most pessimistic figure quoted above for adequate quality. Even then it is useful if the speaker is provided with an indication of the amplitude of his speech: a traffic-light indicator with red signifying clipping overload, orange a suitable level, and green too low a value, is often convenient for this. .rh "Logarithmic quantization." For the purposes of speech .ul processing, it is essential to have the signal quantized uniformly. This is because all of the theory applies to linear systems, and nonlinearities introduce complexities which are not amenable to analysis. Uniform quantization, although a nonlinear operation, is linear in the limiting case as the number of levels becomes large, and for most purposes its effect can be modelled by assuming that the quantized signal is obtained from the original analogue one by the addition of a small amount of uniformly-distributed quantizing noise, as in fact was done above. Usually the quantization noise is disregarded in subsequent analysis. .pp However, the peakiness of the speech signal illustrated in Figure 3.5 leads one to suspect that a non-linear representation, for example a logarithmic one, could provide a better signal-to-noise ratio over a wider range of input amplitudes, and hence be more useful than linear quantization \(em at least for speech storage (and transmission). And indeed this is the case. Linear quantization has the unfortunate effect that the absolute noise level is independent of the signal level, so that an excessive number of bits must be used if a reasonable ratio is to be achieved for peaky signals. It can be shown that a logarithmic representation like .LB .EQ y ~ = ~ 1 ~ + ~ k ~ log ~ x, .EN .LE where $x$ is the original signal and $y$ is the value which is to be quantized, gives a signal-to-noise .ul ratio which is independent of the input signal level. This relationship cannot be realized physically, for it is undefined when the signal is negative and diverges when it is zero. However, realizable approximations to it can be made which retain the advantages of constant signal-to-noise ratio within a useful range of signal amplitudes. Figure 3.6 shows the logarithmic relation with one widely-used approximation to it, called the A-law. .FC "Figure 3.6" The idea of non-linearly quantizing a signal to achieve adequate signal-to-noise ratios for a wide variety of amplitudes is called "companding", a contraction of "compressing-expanding". The original signal can be retrieved from its A-law compression by antilogarithmic expansion. .pp Figure 3.6 also shows one common coding scheme which is a piecewise linear approximation to the A-law. This provides an 8-bit code, and gives the equivalent of 12-bit linear quantization for small signal levels. It approximates the A-law in 16 linear segments, 8 for positive and 8 for negative inputs. Consider the positive part of the curve. The first two segments, which are actually collinear, correspond exactly to 12-bit linear conversion. Thus the output codes 0 to 31 correspond to inputs from 0 to 31/2048, in equal steps. (Remember that both positive and negative signals must be converted, so a 12-bit linear converter will allocate 2048 levels for positive signals and 2048 for negative ones.) The next segment provides 11-bit linear quantization, output codes 32 to 47 corresponding to inputs from 16/1024 to 31/1024. Similarly, the next segment corresponds to 10-bit quantization, covering inputs from 16/512 to 31/512. And so on, the last section giving 6-bit quantization of inputs from 16/32 to 31/32, the full-scale positive value. Negative inputs are converted similarly. For signal levels of less than 32/2048, that is, $2 sup -8$, this implementation of the A-law provides full 12-bit precision. As the signal level increases, the precision decreases gradually to 6 bits at maximum amplitudes. .pp Logarithmic encoding provides what is in effect a floating-point representation of the input. The conventional floating-point format, however, is not used because many different codes can represent the same value. For example, with a 4-bit exponent preceding a 4-bit mantissa, the words 0000:1000, 0001:0100, 0010:0010, and 0011:0001 represent the numbers $0.1 ~ times ~ 2 sup 0$, $0.01 ~ times ~ 2 sup 1 $, $0.001 ~ times ~ 2 sup 2$, \c and $0.0001 ~ times ~ 2 sup 3$ respectively, which are the same. (Some floating-point conventions assume that an unwritten "1" bit precedes the mantissa, except when the whole word is zero; but this gives decreased resolution around zero \(em which is exactly where we want the resolution to be greatest.) Table 3.1 shows the 8-bit A-law codes, .RF .in+0.7i .ta 1.6i +\w'bits 1-3 'u 8-bit codeword: bit 0 sign bit bits 1-3 3-bit exponent bits 4-7 4-bit mantissa .sp2 .ta 1.6i 3.5i .ul codeword interpretation .sp 0000 0000 \h'\w'\0-\0 + 'u'$.0000 ~ times ~ 2 sup -7$ \0\0\0... \0\0\0\0... 0000 1111 \h'\w'\0-\0 + 'u'$.1111 ~ times ~ 2 sup -7$ 0001 0000 $2 sup -7 ~~ + ~~ .0000 ~ times ~ 2 sup -7$ \0\0\0... \0\0\0\0... 0001 1111 $2 sup -7 ~~ + ~~ .1111 ~ times ~ 2 sup -7$ 0010 0000 $2 sup -6 ~~ + ~~ .0000 ~ times ~ 2 sup -6$ \0\0\0... \0\0\0\0... 0010 1111 $2 sup -6 ~~ + ~~ .1111 ~ times ~ 2 sup -6$ 0011 0000 $2 sup -5 ~~ + ~~ .0000 ~ times ~ 2 sup -5$ \0\0\0... \0\0\0\0... 0011 1111 $2 sup -5 ~~ + ~~ .1111 ~ times ~ 2 sup -5$ 0100 0000 $2 sup -4 ~~ + ~~ .0000 ~ times ~ 2 sup -4$ \0\0\0... \0\0\0\0... 0100 1111 $2 sup -4 ~~ + ~~ .1111 ~ times ~ 2 sup -4$ 0101 0000 $2 sup -3 ~~ + ~~ .0000 ~ times ~ 2 sup -3$ \0\0\0... \0\0\0\0... 0101 1111 $2 sup -3 ~~ + ~~ .1111 ~ times ~ 2 sup -3$ 0110 0000 $2 sup -2 ~~ + ~~ .0000 ~ times ~ 2 sup -2$ \0\0\0... \0\0\0\0... 0110 1111 $2 sup -2 ~~ + ~~ .1111 ~ times ~ 2 sup -2$ 0111 0000 $2 sup -1 ~~ + ~~ .0000 ~ times ~ 2 sup -1$ \0\0\0... \0\0\0\0... 0111 1111 $2 sup -1 ~~ + ~~ .1111 ~ times ~ 2 sup -1$ 1000 0000 \h'\w'\0-\0 'u'$- ~~ .0000 ~ times ~ 2 sup -7$ negative numbers treated as \0\0\0... \0\0\0\0... above, with a sign bit of 1 1111 1111 \h'-\w'\- 'u'\- $2 sup -1 ~~ - ~~ .1111 ~ times ~ 2 sup -1$ .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 3.1 8-bit A-law codes, with their floating-point equivalents" according to the piecewise linear approximation of Figure 3.6, written in a notation which suggests floating point. Each linear segment has a different exponent except the first two segments, which as explained above are collinear. .pp Logarithmic encoders and decoders are available from many semiconductor manufacturers as single-chip devices called "codecs" (for "coder/decoder"). Intended for use on digital communication links, these generally provide a serial output bit-stream, which should be converted to parallel by a shift register if the data is intended for a computer. Because of the potentially vast market for codecs in telecommunications, they are made in great quantities and are consequently very cheap. Estimates of the speech quality necessary for telephone applications indicate that somewhat less than this accuracy is needed \(em 7-bit logarithmic encoding was used in early digital communications links, and it may be that even 6 bits are adequate. However, during the transition period when digital networks must coexist with the present analogue one, it is anticipated that a particular telephone call may have to pass through several links, some using analogue technology and some being digital. The possibility of several successive encodings and decodings has led telecommunications engineers to standardize on 8-bit representations, leaving some margin before additional degradation of signal quality becomes unduly distracting. .pp Unfortunately, world telecommunications authorities cannot agree on a single standard for logarithmic encoding. The A-law, which we have described, is the European standard, but there is another system, called the $mu$-law, which is used universally in North America. It also is available in single-chip form with an 8-bit code. It has very similar quantization error characteristics to the A-law, and would be indistinguishable from it on the scale of Figure 3.6. .rh "The pre-sampling filter." Now that we have some idea of the accuracy requirements for quantization, let us discuss quantitative specifications for the pre-sampling filter. Figure 3.7 sketches the characteristics of this filter. .FC "Figure 3.7" Assume a sampling frequency of 8\ kHz and a range of interest from 0 to 3.4\ kHz. Although all components at frequencies above 4\ kHz will fold back into the 0\ \-\ 4\ kHz baseband, those below 4.6\ kHz fold back above 3.4\ kHz and are therefore outside the range of interest. This gives a "guard band" between 3.4 and 4.6\ kHz which separates the passband from the stopband. The filter should transmit negligible components in the stopband above 4.6\ kHz. To reduce the harmonic distortion caused by aliasing to the same level as the quantization noise in 11-bit linear conversion, the stopband attenuation should be around \-68\ dB (the signal-to-noise ratio for a full-scale sine wave). Passband ripple is not so critical, for two reasons. Whilst the presence of aliased components means that information has been lost about the frequency components within the range of interest, passband ripple does not actually cause a loss of information but only a distortion, and could, if necessary, be compensated by a suitable filter acting on the digitized waveform. Secondly, distortion of the passband spectrum is not nearly so audible as the frequency images caused by aliasing. Hence one usually aims for a passband ripple of around 0.5\ dB. .pp The pass and stopband targets we have mentioned above can be achieved with a 9'th order elliptic filter. While such a filter is often used in high-quality signal-processing systems, for telephone-quality speech much less stringent specifications seem to be sufficient. Figure 3.8, for example, shows a template which has been recommended by telecommunications authorities. .FC "Figure 3.8" A 5'th order elliptic filter can easily meet this specification. Such filters, implemented by switched-capacitor means, are available in single-chip form. Integrated CCD (charge-coupled device) filters which meet the same specification are also marketed. Indeed, some codecs provide input filtering on the same chip as the A/D converter. .pp Instead of implementing a filter by analogue means to meet the aliasing specifications, digital filtering can be used. A high sample-rate A/D converter, operating at, say, 32\ kHz, and preceded by a very simple low-pass pre-sampling filter, is followed by a digital filter which meets the desired specification, and its output is subsampled to provide an 8\ kHz sample rate. While such implementations may be economic where a multichannel digitizing capability is required, as in local telephone exchanges where the subscriber connection is an analogue one, they are unlikely to prove cost-effective for a single channel. .rh "Reconstructing the analogue waveform." Having digitized and stored a signal, it needs to be passed though a D/A converter (digital-to-analogue) and low-pass filter when replayed. D/A converters are cheaper than A/D converters, and the characteristics of the low-pass filter for output can be the same as those for input. However, the desampling operation introduces an additional distortion, which has an effect on the component at frequency $f$ of .LB .EQ { sin ( pi f/f sub s )} over { pi f/f sub s } ~ , .EN .LE where $f sub s$ is the sampling frequency. An "aperture correction" filter is needed to compensate for this, although many systems simply do without it. Such a filter is sometimes incorporated into the codec chip. .rh "Summary." For telephone-quality speech, existing codec chips, coupled if necessary with integrated pre-sampling filters, can be used, at a remarkably low cost. For higher-quality speech storage the analogue interface can become quite complex. A comprehensive study of the problems as they relate to digitization of audio, which demands much greater fidelity than speech, has been made by Blesser (1978). .[ Blesser 1978 .] He notes the following sources of error (amongst others): .LB .NP slew-rate distortion in the pre-sampling filter for signals at the upper end of the audio band; .NP insufficient filtering of high-frequency input signals; .NP noise generated by the sample-and-hold amplifier or pre-sampling filter; .NP acquisition errors because of the finite settling time of the sample-and-hold circuit; .NP insufficient settling time in the A/D conversion; .NP errors in the quantization levels of the A/D and D/A converters; .NP noise in the converters; .NP jitter on the clock used for timing input or output samples; .NP aperture distortion in the output sampler; .NP noise in the output filter as a result of limited dynamic range of the integrated circuits; .NP power-supply noise injection or ground coupling; .NP changes in characteristics as a result of temperature or ageing. .LE Care must be taken with the analogue interface to ensure that the precision implied by the resolution of the A/D and D/A converters is not compromised by inadequate analogue circuitry. It is especially important to eliminate high-frequency noise caused by fast edges on nearby computer buses. .sh "3.2 Coding in the time domain" .pp There are several methods of coding the time waveform of a speech signal to reduce the data rate for a given signal-to-noise ratio, or alternatively to reduce the signal-to-noise ratio for a given data rate. They almost all require more processing, both at the encoding (for storage) and decoding (for regeneration) ends of the digitization process. They are sometimes used to economize on memory in systems using stored speech, for example the System\ X telephone exchange and the travel consultant described in Chapter 1, and so will be described here. However, it is to be expected that simple time-domain coding techniques will be superseded by the more complex linear predictive method, which is covered in Chapter 6, because this can give a much more substantial reduction in the data rate for only a small degradation in speech quality. Hence the aim of this section is to introduce the ideas in a qualitative way: theoretical development and summaries of results of listening tests can be found elsewhere (eg Rabiner and Schafer, 1978). .[ Rabiner Schafer 1978 Digital processing of speech signals .] The methods we will examine are summarized in Table 3.2. .RF .nr x0 \w'linear PCM 'u .nr x1 \n(x0+\w' adaptive quantization, or adaptive prediction,'u .nr x2 (\n(.l-\n(x1)/2 .in \n(x2u .ta \n(x0u \l'\n(x1u\(ul' .sp linear PCM linearly-quantized pulse code modulation .sp log PCM logarithmically-quantized pulse code modulation (instantaneous companding) .sp APCM adaptively quantized pulse code modulation (usually syllabic companding) .sp DPCM differential pulse code modulation .sp ADPCM differential pulse code modulation with either adaptive quantization, or adaptive prediction, or both .sp DM delta modulation (1-bit DPCM) .sp ADM delta modulation with adaptive quantization \l'\n(x1u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 3.2 Time-domain encoding techniques" .rh "Syllabic companding." We have already studied one time-domain encoding technique, namely logarithmic quantization, or log PCM (sometimes called "instantaneous companding"). A more sophisticated encoder could track slowly varying trends in the overall amplitude of the speech signal and use this information to adjust the quantization levels dynamically. Speech coding methods based on this principle are called adaptive pulse code modulation systems (APCM). Because the overall amplitude changes slowly, it is sufficient to adjust the quantization relatively infrequently (compared with the sampling rate), and this is often done at rates approximating the syllable rate of running speech, leading to the term "syllabic companding". A block floating-point format can be used, with a common exponent being stored every M samples (with M, say, 125 for a 100\ msec block rate at 8\ kHz sampling), but the mantissa being stored at the regular sample rate. The overall energy in the block, .LB $sum from n=h to h+M-1 ~x(n) sup 2$ ($M = 125$, say), .LE is used to determine a suitable exponent, and every sample in the block \(em namely $x(h)$, $x(h+1)$, ..., $x(h+M-1)$ \(em is scaled according to that exponent. Note that for speech transmission systems this method necessitates a delay of $M$ samples at the encoder, and indeed some methods base the exponent on the energy in the last block to avoid this. For speech storage, however, the delay is irrelevant. A rather different, nonsyllabic, method of adaptive PCM is continually to change the step size of a uniform quantizer, by multiplying it by a constant at each sample which is based on the magnitude of the previous code word. .pp Adaptive quantization exploits information about the amplitude of the signal, and, as a rough generalization, yields a reduction of one bit per sample in the data rate for telephone-quality speech over ordinary logarithmic quantization, for a given signal-to-noise ratio. Alternatively, for the same data rate an improvement of 6\ dB in signal-to-noise ratio can be obtained. Some results for actual schemes are given by Rabiner and Schafer (1978). .[ Rabiner Schafer 1978 Digital processing of speech signals .] However, there is other information in the time waveform of speech, namely, the sample-to-sample correlation, which can be exploited to give further reductions. .rh "Differential coding." Differential pulse code modulation (DPCM), in its simplest form, uses the present speech sample as a prediction of the next one, and stores the prediction error \(em that is, the sample-to-sample difference. This is a simple case of predictive encoding. Referring back to the speech waveform displayed in Figure 3.5, it seems plausible that the data rate can be reduced by transmitting the difference between successive samples instead of their absolute values: less bits are required for the difference signal for a given overall accuracy because it does not assume such extreme values as the absolute signal level. Actually, the improvement is not all that great \(em about 4\ \-\ 5\ dB in signal-to-noise ratio, or just under one bit per sample for a given signal-to-noise ratio \(em for the difference signal can be nearly as large as the absolute signal level. .pp If DPCM is used in conjunction with adaptive quantization, giving one form of adaptive differential pulse code modulation (ADPCM), both the overall amplitude variation and the sample-to-sample correlation are exploited, leading to a combined gain of 10\ \-\ 11\ dB in signal-to-noise ratio (or just under two bits reduction per sample for telephone-quality speech). Another form of adaptation is to alter the predictor by multiplying the previous sample value by a parameter which is adjusted for best performance. Then the transmitted signal at time $n$ is .LB .EQ e(n) ~~ = ~~ x(n)~ - ~ax(n-1), .EN .LE where the parameter $a$ is adapted (and stored) on a syllabic time-scale. This leads to a slight improvement in signal-to-noise ratio, which can be combined with that achieved by adaptive quantization. Much more substantial benefits can be realized by using a weighted sum of the past several (up to 15) speech samples, and adapting all the weights. This is the basic idea of linear prediction, which is developed in Chapter 6. .rh "Delta modulation." The coding methods presented so far all increase the complexity of the analogue-to-digital interface (or, if the sampled waveform is coded digitally, they increase the processing required before and after storage). One method which considerably .ul simplifies the interface is the limiting case of DPCM with just 1-bit quantization. Only the sign of the difference between the current and last values is transmitted. Figure 3.9 shows the conversion hardware. .FC "Figure 3.9" The encoding part is essentially the same as a tracking D/A, where the value in a counter is forced to track the analogue input by incrementing or decrementing the counter according as the input exceeds or falls short of the analogue equivalent of the counter's contents. However, for this encoding scheme, called "delta modulation", the increment-decrement signal itself forms the discrete representation of the waveform, instead of the counter's contents. The analogue waveform can be reconstituted from the bit stream with another counter and D/A converter. Alternatively, an all-analogue implementation can be used, both for the encoder and decoder, with a capacitor as integrator whose charging current is controlled digitally. This is a much cheaper realization. .pp It is fairly obvious that the sampling frequency for delta modulation will need to be considerably higher than for straightforward PCM. Figure 3.10 shows an effect called "slope overload" which occurs when the sampling rate is too low. .FC "Figure 3.10" Either a higher sample rate or a larger step size will reduce the overload; however, larger steps increase the noise level of the alternate 1's and \-1's that occur when no input is present \(em called "granular noise". A compromise is necessary between slope overload and granular noise for a given bit rate. Delta modulation results in lower data rates than logarithmic quantization for a given signal-to-noise ratio if that ratio is low (poor-quality speech). As the desired speech quality is increased its data rate grows faster than that of logarithmic PCM. The crossover point occurs at much lower than telephone quality speech, and so although delta modulation is used for some applications where the permissible data rate is severely constrained, it is not really suitable for speech output from computers. .pp It is profitable to adjust the step size, leading to .ul adaptive delta modulation. A common strategy is to increase or decrease the step size by a multiplicative constant, which depends on whether the new transmitted bit will be equal to or different from the last one. That is, .LB "nnnn" .NI "nn" $stepsize(n+1) = stepsize(n) times 2$ if $x(n+1)x(n)>x(n-1)$ .br (slope overload condition); .NI "nn" $stepsize(n+1) = stepsize(n)/2$ if $x(n+1),~x(n-1)x(n)$ .br (granular noise condition). .LE "nnnn" Despite these adaptive equations, the step size should be constrained to lie between a predetermined fixed maximum and minimum, to prevent it from becoming so large or so small that rapid accomodation to changing input signals is impossible. Then, in a period of potential slope overload the step size will grow, preventing overload, possibly to its maximum value when overload may resume. In a quiet period it will decrease to its minimum value which determines the granular noise in the idle condition. Note that the step size need not be stored, for it can be deduced from the bit changes in the digitized data. Although adaptation improves the performance of delta modulation, it is still inferior to PCM at telephone qualities. .rh "Summary." It seems that ADPCM, with adaptive quantization and adaptive prediction, can provide a worthwhile advantage for speech storage, reducing the number of bits needed per sample of telephone-quality speech from 7 for logarithmic PCM to perhaps 5, and the data rate from 56\ Kbit/s to 40\ Kbit/s. Disadvantages are additional complexity in the encoding and decoding processes, and the fact that byte-oriented storage, with 8 bits/sample in logarithmic PCM, is more convenient for computer use. For low quality speech where hardware complexity is to be minimized, adaptive delta modulation could provide worthwhile \(em although the ready availability of PCM codec chips reduces the cost advantage. .sh "3.3 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "3.4 Further reading" .pp Probably the best single reference on time-domain coding of speech is the book by Rabiner and Schafer (1978), cited above. However, this does not contain a great deal of information on practical aspects of the analogue-to-digital conversion process; this is covered by Blesser (1978) above, who is especially interested in high-quality conversion for digital audio applications, and Garrett (1978) below. There are many textbooks in the telecommunications area which are relevant to the subject of the chapter, although they concentrate primarily on fundamental theoretical aspects rather than the practical application of the technology. .LB "nn" .\"Cattermole-1969-1 .]- .ds [A Cattermole, K.W. .ds [D 1969 .ds [T Principles of pulse code modulation .ds [I Iliffe .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is a standard, definitive, work on PCM, and provides a good grounding in the theory. It goes into the subject in much more depth than we have been able to here. .in-2n .\"Garrett-1978-1 .]- .ds [A Garrett, P.H. .ds [D 1978 .ds [T Analog systems for microprocessors and minicomputers .ds [I Reston Publishing Company .ds [C Reston, Virginia .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Garrett discusses the technology of data conversion systems, including A/D and D/A converters and basic analogue filter design, in a clear and practical manner. .in-2n .\"Inose-1979-2 .]- .ds [A Inose, H. .ds [D 1979 .ds [T An introduction to digital integrated communications systems .ds [I Peter Peregrinus .ds [C Stevenage, England .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Inose's book is a recent one which covers the whole area of digital transmission and switching technology. It gives a good idea of what is happening to the telephone networks in the era of digital communications. .in-2n .\"Steele-1975-3 .]- .ds [A Steele, R. .ds [D 1975 .ds [T Delta modulation systems .ds [I Pentech Press .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Again a standard work, this time on delta modulation techniques. Steele gives an excellent and exhaustive treatment of the subject from a communications viewpoint. .in-2n .LE "nn" .EQ delim $$ .EN .CH "4 SPEECH ANALYSIS" .ds RT "Speech analysis .ds CX "Principles of computer speech .pp Digital recordings of speech provide a jumping-off point for further processing of the audio waveform, which is usually necessary for the purpose of speech output. It is difficult to synthesize natural sounds by concatenating individually-spoken words. Pitch is perhaps the most perceptually significant contextual effect which must be taken into account when forming connected speech out of isolated words. The intonation of an utterance, which manifests itself as a continually changing pitch, is a holistic property of the utterance and not the sum of components determined by the individual words alone. Happily, and quite coincidentally, communications engineers in their quest for reduced-bandwidth telephony have invented methods of coding speech that separate the pitch information from that carried by the articulation. .pp Although these analysis techniques, which were first introduced in the late 1930's (Dudley, 1939), were originally implemented by analogue means \(em and in many systems still are (Blankenship, 1978, describes a recent switched-capacitor realization) \(em there is a continuing trend towards digital implementations, particularly for the more sophisticated coding schemes. .[ Dudley 1939 .] .[ Blankenship 1978 .] It is hard to see how the technique of linear prediction of speech, which is described in detail in Chapter 6, could be accomplished in the absence of digital processing. Some groundwork is laid for the theory of digital signal analysis in this chapter. The ideas are not presented in a formal, axiomatic way; but are developed as and when they are needed to examine some of the structures that turn out to be useful in speech processing. .pp Most speech analysis views speech according to the source-filter model which was introduced in Chapter 2, and aims to separate the effects of the source from those of the filter. The frequency spectrum of the vocal tract filter is of great interest, and the technique of discrete Fourier transformation is discussed in this chapter. For many purposes it is better to extract the formant frequencies from the spectrum and use these alone (or in conjunction with their bandwidths) to characterize it. As far as the signal source in the source-filter model is concerned, its most interesting features are pitch and amplitude \(em the latter being easy to estimate. Hence we go on to look at pitch extraction. Related to this is the problem of deciding whether a segment of speech has voiced or unvoiced excitation, or both. .pp Estimating formant and pitch parameters is one of the messiest areas of speech processing. There is a delightful paper which points this out (Schroeder, 1970), entitled "Parameter estimation in speech: a lesson in unorthodoxy". .[ Schroeder 1970 .] It emphasizes that the most successful estimation procedures "have often relied on intuition based on knowledge of speech signals and their production in the human vocal apparatus rather than routine applications of well-established theoretical methods". Fortunately, the emphasis of the present book is on speech .ul output, which involves parameter estimation only in so far as it is needed to produce coded speech for storage, and to illuminate the acoustic nature of speech for the development of synthesis by rule from phonetics or text. Hence the many methods of formant and pitch estimation are treated rather cursorily and qualitatively here: our main interest is in how to .ul use such information for speech output. .pp If the incoming speech can be analysed into its formant frequencies, amplitude, excitation mode, and pitch (if voiced), it is quite easy to resynthesize it directly from these parameters. Speech synthesizers are described in the next chapter. They can be realized in either analogue or digital hardware, the former being predominant in production systems and the latter in research systems \(em although, as in other areas of electronics, the balance is changing in favour of digital implementations. .sh "4.1 The channel vocoder" .pp A direct representation of the frequency spectrum of a signal can be obtained by a bank of bandpass filters. This is the basis of the .ul channel vocoder, which was the first device that attempted to take advantage of the source-filter model for speech coding (Dudley, 1939). .[ Dudley 1939 .] The word "vocoder" is a contraction of .ul vo\c ice .ul coder. The energy in each filter band is estimated by rectification and smoothing, and the resulting approximation to the frequency spectrum is transmitted or stored. The source properties are represented by the type of excitation (voiced or unvoiced), and if voiced, the pitch. It is not necessary to include the overall amplitude of the speech explicitly, because this is conveyed by the energy levels from the separate bandpass filters. .pp Figure 4.1 shows the encoding part of a channel vocoder which has been used successfully for many years (Holmes, 1980). .[ Holmes 1980 JSRU channel vocoder .] .FC "Figure 4.1" We will discuss the block labelled "pre-emphasis" shortly. The shape of the spectrum is estimated by 19 bandpass filters, whose spacing and bandwidth decrease slightly with decreasing frequency to obtain the rather greater resolution that is needed in the lower frequency region, as shown in Table 4.1. .RF .nr x0 4n+2.6i+\w'\0\0'u+(\w'bandwidth'/2) .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta 4n +1.3i +1.3i \l'\n(x0u\(ul' .sp .nr x1 (\w'channel'/2) .nr x2 (\w'centre'/2) .nr x3 (\w'analysis'/2) \0\h'-\n(x1u'channel \0\h'-\n(x2u'centre \0\0\h'-\n(x3u'analysis .nr x1 (\w'number'/2) .nr x2 (\w'frequency'/2) .nr x3 (\w'bandwidth'/2) \0\h'-\n(x1u'number \0\0\h'-\n(x2u'frequency \0\0\h'-\n(x3u'bandwidth .nr x2 (\w'(Hz)'/2) \0\h'-\n(x2u'(Hz) \0\0\h'-\n(x2u'(Hz) \l'\n(x0u\(ul' .sp \01 \0240 \0120 \02 \0360 \0120 \03 \0480 \0120 \04 \0600 \0120 \05 \0720 \0120 \06 \0840 \0120 \07 1000 \0150 \08 1150 \0150 \09 1300 \0150 10 1450 \0150 11 1600 \0150 12 1800 \0200 13 2000 \0200 14 2200 \0200 15 2400 \0200 16 2700 \0200 17 3000 \0300 18 3300 \0300 19 3750 \0500 \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 4.1 Filter specifications for a vocoder analyser (after Holmes, 1980)" .[ Holmes 1980 JSRU channel vocoder .] The 3\ dB points of adjacent filters are halfway between their centre frequencies, so that there is some overlap between bands. The filter characteristics do not need to have very sharp edges, because the energy in neighbouring bands is fairly highly correlated. Indeed, there is a disadvantage in making them too sharp, because the phase delays associated with sharp cutoff filters induce "smearing" of the spectrum in the time domain. This particular channel vocoder uses second-order Butterworth bandpass filters. .pp For regenerating speech stored in this way, an excitation of unit impulses at the specified pitch period (for voiced sounds) or white noise (for unvoiced sounds) is produced and passed through a bank of bandpass filters similar to the analysis ones. The excitation has a flat spectrum, for regular impulses have harmonics at multiples of the repetition frequency which are all of the same size, and so the spectrum of the output signal is completely determined by the filter bank. The gain of each filter is controlled by the stored magnitude of the spectrum at that frequency. .pp The frequency spectrum and voicing pitch of speech change at much slower rates than the time waveform. The changes are due to movements of the articulatory organs (tongue, lips, etc) in the speaker, and so are limited in their speed by physical constraints. A typical rate of production of phonemes is 15 per second, but in fact the spectrum can change quite a lot within a single phoneme (especially a stop sound). Between 10 and 25\ msec (100\ Hz and 40\ Hz) is generally thought to be a satisfactory interval for transmitting or storing the spectrum, to preserve a reasonably faithful representation of the speech. Of course, the entire spectrum, as well as the source characteristics, must be stored at this rate. The channel vocoder described by Holmes (1980) uses 48 bits to encode the information. .[ Holmes 1980 JSRU channel vocoder .] Repeated every 20\ msec, this gives a data rate of 2400\ bit/s \(em very considerably less than any of the time-domain encoding techniques. .pp It needs some care to encode the output of 19 filters, the excitation type, and the pitch into 48 bits of information. Holmes uses 6 bits for pitch, logarithmically encoded, and one bit for excitation type. This leaves 41 bits to encode the output of the 19 filters, and so a differential technique is used which transmits just the difference between adjacent channels \(em for the spectrum does not change abruptly in the frequency domain. Three bits are used for the absolute level in channel 1, and two bits for each channel-to-channel difference, giving a total of 39 bits for the whole spectrum. The remaining two bits per frame are reserved for signalling or monitoring purposes. .pp A 2400 bit/s channel vocoder degrades the speech in a telephone channel quite perceptibly. It is sufficient for interactive communication, where if you do not understand something you can always ask for it to be repeated. It is probably not good enough for most voice response applications. However, the vocoder principle can be used with larger filter banks and much higher bit rates, and still reduce the data rate substantially below that required by log PCM. .sh "4.2 Pre-emphasis" .pp There is an overall \-6\ dB/octave trend in speech radiated from the lips, as frequency increases. We will discuss why this is so in the next chapter. Notice that this trend means that the signal power is reduced by a factor of 4, or the signal amplitude by a factor of 16, for each doubling in frequency. For vocoders, and indeed for other methods of spectral analysis of speech, it is usually desirable to equalize this by a +6\ dB/octave lift prior to processing, so that the channel outputs occupy a similar range of levels. On regeneration, the output speech is passed through an inverse filter which provides 6\ dB/octave of attenuation. .pp For a digital system, such pre-emphasis can either be implemented as an analogue circuit which precedes the presampling filter and digitizer, or as a digital operation on the sampled and quantized signal. In the former case, the characteristic is usually flat up to a certain breakpoint, which occurs somewhere between 100\ Hz and 1\ kHz \(em the exact position does not seem to be critical \(em at which point the +6\ dB/octave lift begins. Although de-emphasis on output ought to have an exactly inverse characteristic, it is sometimes modified or even eliminated altogether in an attempt to counteract approximately the $sin( pi f/f sub s )/( pi f/f sub s )$ distortion introduced by the desampling operation, which was discussed in an earlier section. Above half the sampling frequency, the characteristic of the pre-emphasis is irrelevant because any effect will be suppressed by the presampling filter. .pp The effect of a 6\ dB/octave lift can also be achieved digitally, by differencing the input. The operation .LB .EQ y(n)~~ = ~~ x(n)~ -~ ax(n-1) .EN .LE is suitable, where the constant parameter $a$ is usually chosen between 0.9 and 1. The latter value gives straightforward differencing, and this amounts to creating a DPCM signal as input to the spectral analysis. Figure 4.2 plots the frequency response of this operation, with a sample frequency of 8\ kHz, for two values of the parameter; together with that of a 6\ dB/octave lift above 100\ Hz. .FC "Figure 4.2" The vertical positions of the plots have been adjusted to give the same gain, 20\ dB, at 1\ kHz. The difference at 3.4\ kHz, the upper end of the telephone spectrum, is just over 2\ dB. At frequencies below the breakpoint, in this case 100\ Hz, the difference between analogue and digital pre-emphasis can be very great. For $a=0.9$ the attenuation at DC (zero frequency) is 18\ dB below that at 1\ kHz, which happens to be close to that of the analogue filter for frequencies below the breakpoint. However, if the breakpoint had been at 1\ kHz there would have been 20\ dB difference between the analogue and $a=0.9$ plots at DC. And of course the $a=1$ characteristic has infinite attenuation at DC. In practice, however, the exact form of the pre-emphasis does not seem to be at all critical. .pp The above remarks apply only to voiced speech. For unvoiced speech there appears to be no real need for pre-emphasis; indeed, it may do harm by reinforcing the already large high-frequency components. There is a case for altering the parameter $a$ according to the excitation mode of the speech: $a=1$ for voiced excitation and $a=0$ for unvoiced gives pre-emphasis just when it is needed. This can be achieved by expressing the parameter in terms of the autocorrelation of the incoming signal, as .LB .EQ a ~~ = ~~ R(1) over R(0) ~ , .EN .LE where $R(1)$ is the correlation of the signal with itself delayed by one sample, and $R(0)$ is the correlation without delay (that is, the signal variance). This is reasonable intuitively because high sample-to-sample correlation is to be expected in voiced speech, so that $R(1)$ is very nearly as great as $R(0)$ and the ratio becomes 1; whereas little or no sample-to-sample correlation will be present in unvoiced speech, making the ratio close to 0. Such a scheme is reminiscent of ADPCM with adaptive prediction. .pp However, this sophisticated pre-emphasis method does not seem to be worthwhile in practice. Usually the breakpoint in an analogue pre-emphasis filter is chosen to be rather greater than 100\ Hz to limit the amplification of fricative energy. In fact, the channel vocoder described by Holmes (1980) has the breakpoint at 1\ kHz, limiting the gain to 12\ dB at 4\ kHz, two octaves above. .[ Holmes 1980 JSRU channel vocoder .] .sh "4.3 Digital signal analysis" .pp You may be wondering how the frequency response for the digital pre-emphasis filters, displayed in Figure 4.2, can be calculated. Suppose a digitized sinusoid is applied as input to the filter .LB .EQ y(n) ~~ = ~~ x(n)~ - ~ax(n-1). .EN .LE A sine wave of frequency $f$ has equation $x(t) ~ = ~ sin ~ 2 pi ft$, and when sampled at $t=0,~ T,~ 2T,~ ...$ (where $T$ is the sampling interval, 125\ msec for an 8\ kHz sample rate), this becomes $x(n) ~ = ~ sin ~ 2 pi fnT.$ It is much more convenient to consider a complex exponential input, $e sup { j2 pi fnT}$ \(em the response to a sinusoid can then be derived by taking imaginary parts, if necessary. The output for this input is .LB .EQ y(n) ~~ = ~~ e sup {j2 pi fnT} ~~-~ae sup {j2 pi f(n-1)T} ~~ = ~~ (1~-~ae sup {-j2 pi fT} )~e sup {j2 pi fnT} , .EN .LE a sinusoid at the same frequency as the input. The factor $1~-~ae sup {-j2 pi fT}$ is complex, with both amplitude and phase components. Thus the output will be a phase-shifted and amplified version of the input. The amplitude response at frequency $f$ is therefore .LB .EQ |1~ - ~ ae sup {-j2 pi fT} | ~~ = ~~ [1~ +~ a sup 2 ~-~ 2a~cos~2 pi fT ] sup 1/2 , .EN .LE or .LB .EQ 10 ~ log sub 10 (1~ +~ a sup 2 ~ - ~ 2a~ cos 2 pi fT) .EN dB. .LE Normalizing to 20\ dB at 1\ kHz, and assuming 8\ kHz sampling, yields .LB .EQ 20~ + ~~ 10~ log sub 10 (1~ +~ a sup 2 ~-~ 2a~ cos ~ { pi f} over 4000 ) ~~ -~ 10~ log sub 10 (1~ +~ a sup 2 ~-~ 2a~ cos ~ pi over 4 ) .EN dB. .LE With $a=0.9$ and 1 this gives the graphs of Figure 4.2. .pp Frequency responses for analogue filters are often plotted with a logarithmic frequency scale, as well as a logarithmic amplitude one, to bring out the asymptotes in dB/octave as straight lines. For digital filters the response is usually drawn on a .ul linear frequency axis extending to half the sampling frequency. The response is symmetric about this point. .pp Analyses like the above are usually expressed in terms of the $z$-transform. Denote the unit delay operation by $z sup -1$. The choice of the inverse rather than $z$ itself is of course an arbitrary matter, but the convention has stuck. Then the filter can be characterized by Figure 4.3, which signifies that the output is the input minus a delayed and scaled version of itself. .FC "Figure 4.3" The transfer function of the filter is .LB .EQ H(z) ~~ = ~~ 1~ -~ az sup -1 , .EN .LE and we have seen that the effect of the system on a (complex) exponential of frequency $f$ is to multiply it by .LB .EQ 1~ -~ ae sup {-j2 pi fT}. .EN .LE To get the frequency response from the transfer function, replace $z sup -1$ by $e sup {-j2 pi fT}$. Amplitude and phase responses can then be found by taking the modulus and angle of the complex frequency response. .pp If $z sup -1$ is treated as an .ul operator, it is quite in order to summarize the action of the filter by .LB .EQ y(n) ~~ = ~~ x(n)~ - ~az sup -1 x(n) ~~ = ~~ (1~ -~ az sup -1 )x(n). .EN .LE However, it is usual to derive from the sequence $x(n)$ a .ul transform $X(z)$ upon which $z sup -1$ acts as a .ul multiplier. If the transform of $x(n)$ is defined as .LB .EQ X(z) ~~ = ~~ sum from {n=- infinity} to infinity ~x(n) z sup -n , .EN .LE then on multiplication by $z sup -1$ we get a new transform, say $V(z)$: .LB .EQ V(z) ~~ = ~~ z sup -1 X(z) ~~ = ~~ z sup -1 sum from {n=- infinity} to infinity ~x(n) z sup -n ~~ = ~~ sum ~x(n)z sup -n-1 ~~ = ~~ sum ~x(n-1)z sup -n . .EN .LE $V(z)$ can also be expressed as the transform of a new sequence, say $v(n)$, by .LB .EQ V(z) ~~ = ~~ sum from {n=- infinity} to infinity ~v(n) z sup -n , .EN .LE from which it becomes apparent that .LB .EQ v(n) ~~ = ~~ x(n-1). .EN .LE Thus $v(n)$ is a delayed version of $x(n)$, and we have accomplished what we set out to do, namely to show that the delay .ul operator $z sup -1$ can be treated as an ordinary .ul multiplier in the $z$-transform domain, where $z$-transforms are defined as the infinite sums given above. .pp In terms of $z$-transforms, the filter can be written .LB .EQ Y(z) ~~ = ~~ (1~ -~ az sup -1 )X(z), .EN .LE where $z sup -1$ is now treated as a multiplier. The transfer function of the filter is .LB .EQ H(z) ~~ = ~~ Y(z) over X(z) ~~ = ~~ 1 - az sup -1 , .EN .LE the ratio of the output to the input transform. .pp It may seem that little has been gained by inventing this rather abstract notion of transform, simply to change an operator to a multiplier. After all, the equation of the filter is no simpler in the transform domain than it was in the time domain using $z sup -1$ as an operator. However, we will need to go on to examine more complex filters. Consider, for example, the transfer function .LB .EQ H(z) ~~ = ~~ {1~+~az sup -1 ~+~bz sup -2} over {1~+~cz sup -1 ~+~dz sup -2} ~ . .EN .LE If $z sup -1$ is treated as an operator, it is not immediately obvious how this transfer function can be realized by a time-domain recurrence relation. However, with $z sup -1$ as an ordinary multiplier in the transform domain, we can make purely mechanical manipulations with infinite sums to see what the transfer function means as a recurrence relation. .pp It is worth noting the similarity between the $z$-transform in the discrete domain and the Fourier and Laplace transforms in the continuous domains. In fact, the $z$-transform plays an analogous role in digital signal processing to the Laplace transform in continuous theory, for the delay operator $z sup -1$ performs a similar service to the differentiation operator $s$. Recall first the continuous Fourier transform, .LB $ G(f) ~~ = ~~ integral from {- infinity} to infinity ~g(t)~e sup {-j2 pi ft} dt $, where $f$ is real, .LE and the Laplace transform, .LB $ F(s) ~~ = ~~ integral from 0 to infinity ~f(t)~e sup -st dt $, where $s$ is complex. .LE The main difference between these two transforms is that the range of integration begins at -$infinity$ for the Fourier transform and at 0 for the Laplace. Advocates of the Fourier transform, which typically include people involved with telecommunications, enjoy the freedom from initial conditions which is bestowed by an origin way back in the mists of time. Advocates of Laplace, including most analogue filter theorists, invariably consider systems where all is quiet before $t=0$ \(em altering the origin of measurement of time to achieve this if necessary \(em and welcome the opportunity to include initial conditions explicitly .ul without having to worry about what happens in the mists of time. Although there is a two-sided Laplace transform where the integration begins at -$infinity$, it is not generally used because it causes some convergence complications. Ignoring this difference between the transforms (by considering signals which are zero when $t<0$), the Fourier spectrum can be found from the Laplace transform by writing $s=j2 pi f$; that is, by considering values of $s$ which lie on the imaginary axis. .pp The $z$-transform is .LB $ H(z) ~~ = ~~ sum from n=0 to infinity ~h(n)~z sup -n $, or $ H(z) ~~ = ~~ sum from {n=- infinity} to infinity ~h(n)~z sup -n , $ .LE depending on whether a one-sided or two-sided transform is used. The advantages and disadvantages of one- and two-sided transforms are the same as in the analogue case. $z$ plays the role of $e sup sT $, and so it is not surprising that the response to a (sampled) sinusoid input can be found by setting .LB .EQ z ~~ = ~~ e sup {j2 pi fT} .EN .LE in $H(z)$, as we proved explicitly above for the pre-emphasis filter. .pp The above relation between $z$ and $f$ means that real-valued frequencies correspond to points where $|z|=1$, that is, the unit circle in the complex $z$-plane. As you travel anticlockwise around this unit circle, starting from the point $z=1$, the corresponding frequency increases from 0, to $1/2T$ half-way round ($z=-1$), to $1/T$ when you get back to the beginning ($z=1$) again. Frequencies greater than the sampling frequency are aliased back into the sampling band, corresponding to further circuits of $|z|=1$ with frequency going from $1/T$ to $2/T$, $2/T$ to $3/T$, and so on. In fact, this is the circle of Figure 3.3 which was used earlier to explain how sampling affects the frequency spectrum! .sh "4.4 Discrete Fourier transform" .pp Let us return from this brief digression into techniques of digital signal analysis to the problem of determining the frequency spectrum of speech. Although a bank of bandpass filters such as is used in the channel vocoder is the perhaps most straightforward way to obtain a frequency spectrum, there are other techniques which are in fact more commonly used in digital speech processing. .pp It is possible to define the Fourier transform of a discrete sequence of points. To motivate the definition, consider first the ordinary Fourier transform (FT), which is .LB $ g(t) ~~ = ~~ integral from {- infinity} to infinity ~G(f)~e sup {+j2 pi ft} df ~~~~~~~~~~~~~~~~ G(f) ~~ = ~~ integral from {- infinity} to infinity ~g(t)~e sup {-j2 pi ft} dt . $ .LE This takes a continuous time domain into a continuous frequency domain. Sometimes you see a normalizing factor $1/2 pi$ multiplying the integral in either the forward or the reverse transform. This is only needed when the frequency variable is expressed in radians/s, and we will find it more convenient to express frequencies in\ Hz. .pp The Fourier series (FS), which should also be familiar to you, operates on a periodic time waveform (or, equivalently, one that only exists for a finite period of time, which is notionally extended periodically). If a period lies in the time range $[0,b)$, then the transform is .LB $ g(t) ~~ = ~~ sum from {r = - infinity} to infinity ~G(r)~e sup {+j2 pi rt/b} ~~~~~~~~~~~~~~~~ G(r) ~~ = ~~ 1 over b ~ integral from 0 to b ~g(t)~e sup {-j2 pi rt/b} dt . $ .LE The Fourier series takes a periodic time-domain function into a discrete frequency-domain one. Because of the basic duality between the time and frequency domains in the Fourier transforms, it is not surprising that another version of the transform can be defined which takes a periodic .ul frequency\c -domain function into a discrete .ul time\c -domain one. .pp Fourier transforms can only deal with a finite stretch of a time signal by assuming that the signal is periodic, for if $g(t)$ is evaluated from its transform $G(r)$ according to the formula above, and $t$ is chosen outside the interval $[0,b)$, then a periodic extension of the function $g(t)$ is obtained automatically. Furthermore, periodicity in one domain implies discreteness in the other. Hence if we transform a .ul finite stretch of a .ul discrete time waveform, we get a frequency-domain representation which is also finite (or, equivalently, periodic), and discrete. This is the discrete Fourier transform (DFT), and takes a discrete periodic time-domain function into a discrete periodic frequency-domain one as illustrated in Figure 4.4. .FC "Figure 4.4" It is defined by .LB $ g(n) ~~ = ~~ 1 over N ~ sum from r=0 to N-1~G(r)~e sup { + j2 pi rn/N} ~~~~~~~~~~~~~~~~ G(r) ~~ = ~~ sum from n=0 to N-1 ~g(n)~e sup { - j2 pi rn/N} , $ .LE or, writing $W=e sup {-j2 pi /N}$, .LB $ g(n) ~~ = ~~ 1 over N ~ sum from r=0 to N-1~G(r)~W sup -rn ~~~~~~~~~~~~~~~~ G(r) ~~ = ~~ sum from n=0 to N-1 ~g(n)~W sup rn . $ .LE .sp The $1/N$ in the first equation is the same normalizing factor as the $1/b$ in the Fourier series, for the finite time domain is $[0,N)$ in the discrete case and $[0,b)$ in the Fourier series case. It does not matter whether it is written into the forward or the reverse transform, but it is usually placed as shown above as a matter of convention. .pp As illustrated by Figure 4.5, discrete Fourier transforms take an input of $N$ real values, representing equally-spaced time samples in the interval $[0,b)$, and produce as output $N$ complex values, representing equally-spaced frequency samples in the interval $[0,N/b)$. .FC "Figure 4.5" Note that the end-point of this frequency interval is the sampling frequency. It seems odd that the input is real and the output is the same number of .ul complex quantities: we seem to be getting some numbers for nothing! However, this isn't so, for it is easy to show that if the input sequence is real, the output frequency spectrum has a symmetry about its mid-point (half the sampling frequency). This can be expressed as .LB DFT symmetry:\0\0\0\0\0\0 $ ~ mark G( half N +r) ~=~ G( half N -r) sup *$ if $g$ is real-valued, .LE where $*$ denotes the conjugate of a complex quantity (that is, $(a+jb) sup * = a-jb$). .pp It was argued above that the frequency spectrum in the DFT is periodic, with the spectrum from 0 to the sampling frequency being repeated regularly up and down the frequency axis. It can easily be seen from the DFT equation that this is so. It can be written .LB DFT periodicity:$ lineup G(N+r) ~=~ G(r)$ always. .LE Figure 4.6 illustrates the properties of symmetry and periodicity. .FC "Figure 4.6" .sh "4.5 Estimating the frequency spectrum of speech using the DFT" .pp Speech signals are not exactly periodic. Although the waveform in a particular pitch period will usually resemble those in the preceding and following pitch periods, it will certainly not be identical to them. As the articulation of the speech changes, the formant positions will alter. As we saw in Chapter 2, the pitch itself is certainly not constant. Hence the fundamental assumption of the DFT, that the waveform is periodic, is not really justified. However, the signal is quasi-periodic, for changes from period to period will not usually be very great. One way of computing the short-term frequency spectrum of speech is to use .ul pitch-synchronous Fourier transformation, where single pitch periods are isolated from the waveform and processed with the DFT. This gives a rather accurate estimate of the spectrum. Unfortunately, it is difficult to determine the beginning and end of each pitch cycle, as we shall see later in this chapter when discussing pitch extraction techniques. .pp If a finite stretch of a speech waveform is isolated and Fourier transformed, without regard to pitch of the speech, then the periodicity assumption will be grossly violated. Figure 4.7 illustrates that the effect is the same as multiplying the signal by a rectangular .ul window function, which is 0 except during the period to be analysed, where it is 1. .FC "Figure 4.7" The windowed sequence will almost certainly have discontinuities at its edges, and these will affect the resulting spectrum. The effect can be analysed quite easily, but we will not do so here. It is enough to say that the high frequencies associated with the edges of the window cause considerable distortion of the spectrum. The effect can be alleviated by using a smoother window than a rectangular one, and several have been investigated extensively. The commonly-used windows of Bartlett, Blackman, and Hamming are illustrated in Figure 4.8. .FC "Figure 4.8" .pp Because the DFT produces the same number of frequency samples, equally spaced, as there were points in the time waveform, there is a tradeoff between frequency resolution and time resolution (for a given sampling rate). For example, a 256-point transform with a sample rate of 8\ kHz gives the 256 equally-spaced frequency components between 0 and 8\ kHz that are shown in Table 4.2. .RF .nr x0 (\w'time domain'/2) .nr x1 (\w'frequency domain'/2) .in+1.0i .ta 1.0i 3.0i 4.0i \h'0.5i+2n-\n(x0u'time domain\h'|3.5i+2n-\n(x1u'frequency domain .sp sample time sample \h'-3n'frequency number number .nr x0 1i+\w'00000' \l'\n(x0u\(ul' \l'\n(x0u\(ul' .sp \0\0\00 \0\0\0\00 $mu$sec \0\0\00 \0\0\0\00 Hz \0\0\01 \0\0125 \0\0\01 \0\0\031 \0\0\02 \0\0250 \0\0\02 \0\0\062 \0\0\03 \0\0375 \0\0\03 \0\0\094 \0\0\04 \0\0500 \0\0\04 \0\0125 .nr x2 (\w'...'/2) \h'0.5i+4n-\n(x2u'...\h'|3.5i+4n-\n(x2u'... \h'0.5i+4n-\n(x2u'...\h'|3.5i+4n-\n(x2u'... \h'0.5i+4n-\n(x2u'...\h'|3.5i+4n-\n(x2u'... .sp \0254 31750 \0254 \07938 \0255 31875 $mu$sec \0255 \07969 Hz \l'\n(x0u\(ul' \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .MT 2 Table 4.2 Time domain and frequency domain samples for a 256-point DFT, with 8\ kHz sampling .TE The top half of the frequency spectrum is of no interest, because it contains the complex conjugates of the bottom half (in reverse order), corresponding to frequencies greater than half the sampling frequency. Thus for a 30\ Hz resolution in the frequency domain, 256 time samples, or a 32\ msec stretch of speech, needs to be transformed. A common technique is to take overlapping periods in the time domain to give a new frequency spectrum every 16\ msec. From the acoustic point of view this is a reasonable rate to re-compute the spectrum, for as noted above when discussing channel vocoders the rate of change in the spectrum is limited by the speed that the speaker can move his vocal organs, and anything between 10 and 25\ msec is a reasonable figure for transmitting or storing the spectrum. .pp The DFT is a complex transform, and speech is a real signal. It is possible to do two DFT's at once by putting one time waveform into the real parts of the input and another into the imaginary parts. This destroys the DFT symmetry property, for it only holds for real inputs. But given the DFT of a complex sequence formed in this way, it is easy to separate out the DFT's of the two real time sequences. If the two time sequences are $x(n)$ and $y(n)$, then the transform of the complex sequence .LB .EQ g(n) ~~ = ~~ x(n) ~+~ jy(n) .EN .LE is .LB .EQ G(r) ~~ = ~~ sum from n=0 to N-1 ~[x(n)W sup rn ~+~ y(n)W sup rn ] . .EN .LE It follows that the complex conjugate of the aliased parts of the spectrum, in the upper frequency region, are .LB .EQ G(N-r) sup * ~~ = ~~ sum from n=0 to N-1 ~[x(n)W sup -(N-r)n ~-~ y(n)W sup -(N-r)n ] , .EN .LE and this is the same as .LB .EQ G(N-r) sup * ~~ = ~~ sum from n=0 to N-1 ~[x(n)W sup rn ~-~ y(n)W sup rn ] , .EN .LE because $W sup N$ is 1 (recall the definition of $W$), and so $W sup -Nn$ is 1 for any $n$. Thus .LB .EQ X(r) ~~ = ~~ {G(r) ~+~ G(N-r) sup * } over 2 ~~~~~~~~~~~~~~~~ Y(r) ~~ = ~~ {G(r) ~-~ G(N-r) sup * } over 2 .EN .LE extracts the transforms $X(r)$ and $Y(r)$ of the original sequences $x$ and $y$. .pp With speech, this trick is frequently used to calculate two spectra at once. Using 256-point transforms, a new estimate of the spectrum can be obtained every 16\ msec by taking overlapping 32\ msec stretches of speech, with a computational requirement of one 256-point transform every 32\ msec. .sh "4.6 The fast Fourier transform" .pp Straightforward calculation of the DFT, expressed as .LB .EQ G(r) ~~ = ~~ sum from n=0 to N-1 ~g(n)~W sup nr , .EN .LE for $r=0,~ 1,~ 2,~ ...,~ N-1$, takes $N sup 2$ operations, where each operation is a complex multiply and add (for $W$ is, of course, a complex number). There is a better way, invented in the early sixties, which reduces this to $N ~ log sub 2 N$ operations \(em a very considerable improvement. Dubbed the "fast Fourier transform" (FFT) for historical reasons, it would actually be better called the "Fourier transform", with the straightforward method above known as the "slow Fourier transform"! There is no reason nowadays to use the slow method, except for tiny transforms. It is worth describing the basic principle of the FFT, for it is surprisingly simple. More details on actual implementations can be found in Brigham (1974). .[ Brigham 1974 .] .pp It is important to realize that the FFT involves no approximation. It is an .ul exact calculation of the values that would be obtained by the slow method (although it may be affected differently by round-off errors). Problems of aliasing and windowing occur in all discrete Fourier transforms, and they are neither alleviated nor exacerbated by the FFT. .pp To gain insight into the working of the FFT, imagine the sequence $g(n)$ split into two halves, containing the even and odd points respectively. .LB even half $e(n)$ is $g(0)~ g(2)~ .~ .~ .~ g(N-2)$ .br odd half $o(n)$ is $g(1)~ g(3)~ .~ .~ .~ g(N-1)$. .LE Then it is easy to show that if $G$ is the transform of $g$, $E$ the transform of $e$, and $O$ that of $o$, then .LB $ G(r) ~~ = ~~ E(r) ~+~ W sup r O(r)$ for $r=0,~ 1,~ ...,~ half N -1$, .LE and .LB $ G( half N +r ) ~~ = ~~ E(r) ~+~ W sup { half N +r} O(r)$ for $ r = 0,~ 1,~ ...,~ half N -1$. .LE Calculation of the $E$ and $O$ transforms involves $( half N) sup 2$ operations each, while combining them together according to the above relationship occupies $N$ operations. Thus the total is $N + half N sup 2 $ operations, which is considerably less than $N sup 2$. .pp But don't stop there! The even half can itself be broken down into even and odd parts to expedite its calculation, and the same with the odd half. The only constraint is that the number of elements in the sequences splits exactly into two at each stage. Providing $N$ is a power of 2, then, we are left at the end with some 1-point transforms to do. But transforming a single point leaves it unaffected! (Check the definition of the DFT.) A quick calculation shows that the number of operations needed is not $N + half N sup 2$, but $N~ log sub 2 N$. Figure 4.9 compares this with $N sup 2$, the number of operations for straightforward DFT calculation, and it can be seen that the FFT is very much faster. .FC "Figure 4.9" .pp The only restriction on the use of the FFT is that $N$ must be a power of two. If it is not, alternative, more complicated, algorithms can be used which give comparable computational advantages. However, for speech processing the number of samples that are transformed is usually arranged to be a power of two. If a pitch synchronous analysis is undertaken, the time stretch that is to be transformed is dictated by the length of the pitch period, and will vary from time to time. Then, it is usual to pad out the time waveform with zeros to bring the number of samples up to a power of two; otherwise, if different-length time stretches were transformed the scale of the resulting frequency components would vary too. .pp The FFT provides very worthwhile cost savings over the use of a bank of bandpass filters for spectral analysis. Take the example of a 256-point transform with 8\ kHz sampling, giving 128 frequency components spaced by 31.25\ Hz from 0 up to almost 4\ kHz. This can be computed on overlapping 32\ msec stretches of the time waveform, giving a new spectrum every 16\ msec, by a single FFT calculation every 32\ msec (putting successive pairs of time stretches in the real and imaginary parts of the complex input sequence, as described earlier). The FFT algorithm requires $N~ log sub 2 N$ operations, which is 2048 when $N=256$. An additional 512 operations are required for the windowing calculation. Repeated every 32\ msec, this gives a rate of 80,000 operations per second. To achieve a much lower frequency resolution with 20 bandpass filters, each of which are fourth-order, will need a great deal more operations. Each filter will need between 4 and 8 multiplications per sample, depending on its exact digital implementation. But new samples appear every 125 .ul micro\c seconds, and so somewhere around a million operations will be required every second. If we increased the frequency resolution to that obtained by the FFT, 128 filters would be needed, requiring between 4 and 8 million operations! .sh "4.7 Formant estimation" .pp Once the frequency spectrum of a speech signal has been calculated, it may seem a simple matter to estimate the positions of the formants. But it is not! Spectra obtained in practice are not usually like the idealized ones of Figure 2.2. One reason for this is that, unless the analysis is pitch-synchronous, the frequency spectrum of the excitation source is mixed in with that of the vocal tract filter. There are other reasons, which will be discussed later in this section. But first, let us consider how to extract the vocal tract filter characteristics from the combined spectrum of source and filter. To do so we must begin to explore the theory of linear systems. .rh "Discrete linear systems." Figure 4.10 shows an input signal exciting a filter to produce an output signal. .FC "Figure 4.10" For present purposes, imagine the input to be a glottal waveform, the filter a vocal tract one, and the output a speech signal (which is then subjected to high-frequency de-emphasis by radiation from the lips). We will consider here .ul discrete systems, so that the input $x(n)$ and output $y(n)$ are sampled signals, defined only when $n$ is integral. The theory is quite similar for continuous systems. .pp Assume that the system is .ul linear, that is, if input $x sub 1 (n)$ produces output $y sub 1 (n)$ and input $x sub 2 (n)$ produces output $y sub 2 (n)$, then the sum of $x sub 1 (n)$ and $x sub 2 (n)$ will produce the sum of $y sub 1 (n)$ and $y sub 2 (n)$. It is easy to show from this that, for any constant multiplier $a$, the input $ax(n)$ will produce output $ay(n)$ \(em it is pretty obvious when $a=2$, or indeed any positive integer; for then $ax(n)$ can be written as $x(n)+x(n)+...$ . Assume further that the system is .ul time-invariant, that is, if input $x(n)$ produces output $y(n)$ then a time-shifted version of $x$, say $x(n+n sub 0 )$ for some constant $n sub 0$, will produce the same output, only time-shifted; namely $y(n+n sub 0)$. .pp Now consider the discrete delta function $delta (n)$, which is 0 except at $n=0$ when it is 1. If this single impulse is presented as input to the system, the output is called the .ul impulse response, and will be denoted by $h(n)$. The fact that the system is time-invariant guarantees that the response does not depend upon the particular time at which the impulse occurred, so that, for example, the impulsive input $delta (n+n sub 0 )$ will produce output $h(n+n sub 0 )$. A delta-function input and corresponding impulse response are shown in Figure 4.10. .pp The impulse response of a linear, time-invariant system is an extremely useful thing to know, for it can be used to calculate the output of the system for any input at all! Specifically, an input signal $x(n)$ can be written .LB .EQ x(n)~ = ~~ sum from {k=- infinity} to infinity ~ x(k) delta (n-k) , .EN .LE because $delta (n-k)$ is non-zero only when $k=n$, and so for any particular value of $n$, the summation contains only one non-zero term \(em that is, $x(n)$. The action of the system on each term of the sum is to produce an output $x(k)h(n-k)$, because $x(k)$ is just a constant, and the system is linear. Furthermore, the complete input $x(n)$ is just the sum of such terms, and since the system is linear, the output is the sum of $x(k)h(n-k)$. Hence the response of the system to an arbitrary input is .LB .EQ y(n)~ = ~~ sum from {k=- infinity} to infinity ~ x(k) h(n-k) . .EN .LE This is called a .ul convolution sum, and is sometimes written .LB .EQ y(n)~ =~ x(n) ~*~ h(n). .EN .LE .pp Let's write this in terms of $z$-transforms. The (two-sided) $z$-transform of y(n) is .LB .EQ Y(z)~ = ~~ sum from {n=- infinity} to infinity ~y(n)z sup -n ~~ = ~~ sum from n ~ sum from k ~x(k)h(n-k) ~z sup -n , .EN .LE Writing $z sup -n$ as $z sup -(n-k) z sup -k$, and interchanging the order of summation, this becomes .LB .EQ Y(z)~ mark = ~~ sum from k ~[~ sum from n ~ h(n-k)z sup -(n-k) ~]~x(k)z sup -k .EN .br .EQ lineup = ~~ sum from k ~H(z)~z sup -k ~~ = ~~ H(z)~ sum from k ~x(k)z sup -k ~~=~~H(z)X(z) . .EN .LE Thus convolution in the time domain is the same as multiplication in the $z$-transform domain; a very important result. Applied to the linear system of Figure 4.10, this means that the output $z$-transform is the input $z$-transform multiplied by the $z$-transform of the system's impulse response. .pp What we really want to do is to relate the frequency spectrum of the output to the response of the system and the spectrum of the input. In fact, frequency spectra are very closely connected with $z$-transforms. A periodic signal $x(n)$ which repeats every $N$ samples has DFT .LB .EQ sum from n=0 to N-1 ~x(n)~e sup {-j2 pi rn/N} , .EN .LE and its $z$-transform is .LB .EQ sum from {n=- infinity} to infinity ~x(n) ~z sup -n . .EN .LE Hence the DFT is the same as the $z$-transform of a single cycle of the signal, evaluated at the points $z= e sup {j2 pi r/N}$ for $r=0,~ 1,~ ...~ ,~ N-1$. In other words, the frequency components are samples of the $z$-transform at $N$ equally-spaced points around the unit circle. Hence the frequency spectrum at the output of a linear system is the product of the input spectrum and the frequency response of the system itself (that is, the transform of its impulse response function). It should be admitted that this statement is somewhat questionable, because to get from $z$-transforms to DFT's we have assumed that a single cycle only is transformed \(em and the impulse response function of a system is not necessarily periodic. The real action of the system is to multiply $z$-transforms, not DFT's. However, it is useful in imagining the behaviour of the system to think in terms of products of DFT's; and in practice it is always these rather than $z$-transforms which are computed because of the existence of the FFT algorithm. .pp Figure 4.11 shows the frequency spectrum of a typical voiced speech signal. .FC "Figure 4.11" The overall shape shows humps at the formant positions, like those in the idealized Figure 2.2. However, superimposed on this is an "oscillation" (in the frequency domain!) at the pitch frequency. This occurs because the transform of the vocal tract filter has been multiplied by that of the pitch pulse, the latter having components at harmonics of the pitch frequency. The oscillation must be suppressed before the formants can be estimated to any degree of accuracy. .pp One way of eliminating the oscillation is to perform pitch-synchronous analysis. This removes the influence of pitch from the frequency domain by dealing with it in the time domain! The snag is, of course, that it is not easy to estimate the pitch frequency: some techniques for doing so are discussed in the next main section. Another way is to use linear predictive analysis, which really does get rid of pitch information without having to estimate the pitch period first. A smooth frequency spectrum can be produced using the analysis techniques described in Chapter 6, which provides a suitable starting-point for formant frequency estimation. The third method is to remove the pitch ripple from the frequency spectrum directly. This will be discussed in an intuitive rather than a theoretical way, because linear predictive methods are becoming dominant in speech processing. .rh "Cepstral processing of speech." Suppose the frequency spectrum of Figure 4.11 were actually a time waveform. To remove the high-frequency pitch ripple is easy: just filter it out! However, filtering removes .ul additive ripples, whereas this is a .ul multiplicative ripple. To turn multiplication into addition, take logarithms. Then the procedure would be .LB .NP compute the DFT of the speech waveform (windowed, overlapped); .NP take the logarithm of the transform; .NP filter out the high-frequency part, corresponding to pitch ripple. .LE .pp Filtering is often best done using the DFT. If the rippled waveform of Figure 4.11 is transformed, a strong component could be expected at the ripple frequency, with weaker ones at its harmonics. These components can be simply removed by setting them to zero, and inverse-transforming the result to give a smoothed version of the original frequency spectrum. A spectrum of the logarithm of a frequency spectrum is often called a .ul cepstrum \(em a sort of backwards spectrum. The horizontal axis of the cepstrum, having the dimension of time, is called "quefrency"! Note that high-frequency signals have low quefrencies and vice versa. In practice, because the pitch ripple is usually well above the quefrency of interest for formants, the upper end of the cepstrum is often simply cut off from a fixed quefrency which corresponds to the maximum pitch expected. However, identifying the pitch peaks of the cepstrum has the useful byproduct of giving the pitch period of the original speech. .pp To summarize, then, the procedure for spectral smoothing by the cepstral method is .LB .NP compute the DFT of the speech waveform (windowed, overlapped); .NP take the logarithm of the transform; .NP take the DFT of this log-transform, calling it the cepstrum; .NP identify the lowest-quefrency peak in the spectrum as the pitch, confirming it by examining its harmonics, which should be equally spaced at the pitch quefrency; .NP remove pitch effects from the cepstrum by cutting off its high-quefrency part above either the pitch quefrency or some constant representing the maximum expected pitch (which is the minimum expected pitch quefrency); .NP inverse DFT the resulting cepstrum to give a smoothed spectrum. .LE .rh "Estimating formant frequencies from smoothed spectra." The difficulties of formant extraction are not over even when a smooth frequency spectrum has been obtained. A simple peak-picking algorithm which identifies a peak at the $k$'th frequency component whenever .LB $ X(k-1) ~<~ X(k) $ and $ X(k) ~>~ X(k+1) $ .LE will quite often identify formants incorrectly. It helps to specify in advance minimum and maximum formant frequencies \(em say 100\ Hz and 3\ kHz for three-formant identification, and ignore peaks lying outside these limits. It helps to estimate the bandwidth of the peaks and reject those with bandwidths greater than 500\ Hz \(em for real formants are never this wide. However, if two formants are very close, then they may appear as a single, wide, peak and be rejected by this criterion. It is usual to take account of formant positions identified in previous frames under these conditions. .pp Markel and Gray (1976) describe in detail several estimation algorithms. .[ Markel Gray 1976 Linear prediction of speech .] Their simplest uses the number of peaks identified in the raw spectrum (under 3\ kHz, and with bandwidths greater than 500\ Hz), to determine what to do. If exactly three peaks are found, they are used as the formant positions. It is claimed that this happens about 85% to 90% of the time. If only one peak is found, the present frame is ignored and the previously-identified formant positions are used (this happens less than 1% of the time). The remaining cases are two peaks \(em corresponding to omission of one formant \(em and four peaks \(em corresponding to an extra formant being included. (More than four peaks never occurred in their data.) Under these conditions, a nearest-neighbour measure is used for disambiguation. The measure is .LB .EQ v sub ij ~ = ~ |{ F sup * } sub i (k) ~-~ F sub j (k-1)| , .EN .LE where $F sub j sup (k-1)$ is the $j$'th formant frequency defined in the previous frame $k-1$ and ${ F sup * } sub i (k)$ is the $i$'th raw data frequency estimate for frame $k$. If two peaks only are found, this measure is used to identify the closest peaks in the previous frame; and then the third peak of that frame is taken to be the missing formant position. If four peaks are found, the measure is used to determine which of them is furthest from the previous formant values, and this one is discarded. .pp This procedure works forwards, using the previous frame to disambiguate peaks given in the current one. More sophisticated algorithms work backwards as well, identifying .ul anchor points in the data which have clearly-defined formant positions, and moving in both directions from these to disambiguate neighbouring frames of data. Finally, absolute limits can be imposed upon the magnitude of formant movements between frames to give an overall smoothing to the formant tracks. .pp Very often, people will refine the result of such automatic formant estimation procedures by hand, looking at the tracks, knowing what was said, and making adjustments in the light of their experience of how formants move in speech. Unfortunately, it is difficult to obtain high-quality formant tracks by completely automatic means. .pp One of the most difficult cases in formant estimation is where two formants are so close together that the individual peaks cannot be resolved. One simple solution to this problem is to employ "analysis-by-synthesis", whereby once a formant is identified, a standard formant shape at this position is synthesized and subtracted from the logarithmic spectrum (Coker, 1963). .[ Coker 1963 .] Then, even if two formants are right on top of each other, the second is not missed because it remains after the first one has been subtracted. .pp Unfortunately, however, the single peak which appears when two formants are close together usually does not correspond exactly with the position of either one. There is one rather advanced signal-processing technique that can help in this case. The frequency spectrum of speech is determined by .ul poles which lie in the complex $z$-plane inside the unit circle. (They must be inside the unit circle if the system is stable. Those familiar with Laplace analysis of analogue systems may like to note that the left half of the $s$-plane corresponds with the inside of the unit circle in the $z$-plane.) As shown earlier, computing a DFT is tantamount to evaluating the $z$-transform at equally-spaced points around the unit circle. However, better resolution is obtained by evaluating around a circle which lies .ul inside the unit circle, but .ul outside the outermost pole position. Such a circle is sketched in Figure 4.12. .FC "Figure 4.12" .pp Recall that the FFT is a fast way of calculating the DFT of a sequence. Is there a similarly fast way of evaluating the $z$-transform inside the unit circle? The answer is yes, and the technique is known as the "chirp $z$-transform", because it involves considering a signal whose frequency increases linearly \(em just like a radar chirp signal. The chirp method allows the $z$-transform to be computed quickly at equally-spaced points along spirally-shaped contours around the origin of the $z$-plane \(em corresponding to signals of linearly increasing complex frequency. The spiral nature of these curves is not of particular interest in speech processing. What .ul is of interest, though, is that the spiral can begin at any point on the $z=0$ axis, and its pitch can be set arbitrarily. If we begin spiralling at $z=0.9$, say, and set the pitch to zero, the contour becomes a circle inside the unit one, with radius 0.9. Such a circle is exactly what is needed to refine formant resolution. .sh "4.8 Pitch extraction" .pp The last section discussed how to characterize the vocal tract filter in the source-filter model of speech production: this one looks at how the most important property of the source \(em that is, the pitch period \(em can be derived. In many ways pitch extraction is more important from a practical point of view than is formant estimation. In a voice-output system, formant estimation is only necessary if speech is to be stored in formant-coded form. For linear predictive storage of speech, or for speech synthesis from phonetics or text, formant extraction is unnecessary \(em although of course general information about formant frequencies and formant tracks in natural speech is needed before a synthesis-from-phonetics system can be built. However, knowledge of the pitch contour is needed for many different purposes. For example, compact encoding of linearly predicted speech relies on the pitch being estimated and stored as a parameter separate from the articulation. Significant improvements in frequency analysis can be made by performing pitch-synchronous Fourier transformations, because the need to window is eliminated. Many synthesis-from-phonetics systems require the pitch contour for utterances to be stored rather computed from markers in the phonetic text. .pp Another issue which is closely bound up with pitch extraction is the voiced-unvoiced distinction. A good pitch estimator ought to fail when presented with aperiodic input such as an unvoiced sound, and so give a reliable indication of whether the frame of speech is voiced or not. .pp One method of pitch estimation, which uses the cepstrum, has been outlined above. It involves a substantial amount of computation, and has a high degree of complexity. However, if implemented properly it gives excellent results, because the source-filter structure of the speech is fully utilized. Another method, using the linear prediction residual, will be described in Chapter 6. Again, this requires a great deal of computation of a fairly sophisticated nature, and gives good results \(em although it relies on a somewhat more restricted version of the source-filter model than cepstral analysis. .rh "Autocorrelation methods." The most reliable way of estimating the pitch of a periodic signal which is corrupted by noise is to examine its short-time autocorrelation function. The autocorrelation of a signal $x(n)$ with lag $k$ is defined as .LB .EQ phi (k) ~~ = ~~ sum from {n=- infinity} to infinity ~ x(n)x(n+k) . .EN .LE If the signal is quasi-periodic, with slowly varying period, a finite stretch of it can be isolated with a window $w(i)$, which is 0 when $i$ is outside the range $[0,N)$. Beginning this window at sample $m$ gives the windowed signal .LB .EQ x(n)w(n-m), .EN .LE whose autocorrelation, the .ul short-time autocorrelation of the signal $x$ at point $m$ is .LB .EQ phi sub m (k)~ = ~~ sum from n ~ x(n)w(n-m)x(n+k)w(n-m+k) . .EN .LE .pp The autocorrelation function exhibits peaks at lags which correspond to the pitch periods and multiples of it. At such lags, the signal is in phase with a delayed version of itself, giving high correlation. The pitch of natural speech ranges about three octaves, from 50\ Hz (low-pitched men) to around 400\ Hz (children). To ensure that at least two pitch cycles are seen, even at the low end, the window needs to be at least 40\ msec long, and the autocorrelation function calculated for lags up to 20\ msec. The peaks which occur at lags corresponding to multiples of the pitch become smaller as the multiple increases, because the speech waveform will change slightly and the pitch period is not perfectly constant. If signals at the high end of the pitch range, 400\ Hz, are viewed through a 40\ msec autocorrelation window, considerable smearing of pitch resolution in the time domain is to be expected. Finally, for unvoiced speech, no substantial peaks of autocorrelation will occur. .pp If all deviations from perfect periodicity can be attributed to additive, white, Gaussian noise, then it can be shown from standard detection theory that autocorrelation methods are appropriate for pitch identification. Unfortunately, this is certainly not the case for speech signals. Although the short-time autocorrelation of voiced speech exhibits peaks at multiples of the pitch period, it is not clear that it is any easier to detect these peaks in the autocorrelation function than it is in the original time waveform! To take a simple example, if a signal contains a fundamental and in-phase first and second harmonics, .LB .EQ x(n)~ =~ a sin 2 pi fnT ~+~ b sin 4 pi fnT ~+~ c sin 6 pi fnT , .EN .LE then its autocorrelation function is .LB .EQ phi (k) ~=~~ {a sup 2 ~cos~2 pi fkT~+~b sup 2 ~cos~2 pi fkT~+~c sup 2 ~cos 2 pi fkT} over 2 ~ . .EN .LE There is no reason to believe that detection of the fundamental period of this signal will be any easier in the autocorrelation domain than in the time domain. .pp The most common error of pitch detection by autocorrelation analysis is that the periodicities of the formants are confused with the pitch. This typically leads to the repetition time being identified as $T sub pitch ~ +- ~ T sub formant1$, where the $T$'s are the periods of the pitch and first formant. Fortunately, there are simple ways of processing the signal non-linearly to reduce the effect of formants on pitch estimation using autocorrelation. .pp One way is to low-pass filter the signal with a cut-off above the maximum pitch period, say 600 Hz. However, formant 1 is often below this value. A different technique, which may be used in conjunction with filtering, is to "centre-clip" the signal as shown in Figure 4.13. .FC "Figure 4.13" This removes many of the ripples which are associated with formants. However, it entails the use of an adjustable clipping threshold to cater for speech of varying amplitudes. Sondhi (1968), who introduced the technique, set the clipping level at 30% of the maximum amplitude. .[ Sondhi 1968 .] An alternative which achieves much the same effect without the need to fiddle with thresholds, is to cube the signal, or raise it to some other high (odd!) power, before taking the autocorrelation. This highlights the peaks and suppresses the effect of low-amplitude parts. .pp For very accurate pitch detection, it is best to combine the evidence from several different methods of analysis of the time waveform. The autocorrelation function provides one source of evidence; and the cepstrum provides another. A third source comes from the time waveform itself. McGonegal .ul et al (1975) have described a semi-automatic method of pitch detection which uses human judgement to make a final decision based upon these three sources of evidence. .[ McGonegal Rabiner Rosenberg 1975 SAPD .] This appears to provide highly accurate pitch contours at the expense of considerable human effort \(em it takes an experienced user 30 minutes to process each second of speech. .rh "Speeding up autocorrelation." Calculating the autocorrelation function is an arithmetic-intensive procedure. For large lags, it can best be done using FFT methods; although there are simpler arithmetic tricks which speed it up without going to such complexity. However, with the availability of analogue delay lines using charge-coupled devices, autocorrelation can now be done effectively and cheaply by analogue, sampled-data, hardware. .pp Nevertheless, some techniques to speed up digital calculation of short-time autocorrelations are in wide use. It is tempting to hard-limit the signal so that it becomes binary (Figure 4.14(a)), thus eliminating multiplication. .FC "Figure 4.14" This can be disastrous, however, because hard-limited speech is known to retain considerable intelligibility and therefore the formant structure is still there. A better plan is to take centre-clipped speech and hard-limit that to a ternary signal (Figure 4.14(b)). This simplifies the computation considerably with essentially no degradation in performance (Dubnowski .ul et al, 1976). .[ Dubnowski Schafer Rabiner 1976 Digital hardware pitch detector .] .pp A different approach to reducing the amount of calculation is to perform a kind of autocorrelation which does not use multiplications. The "average magnitude difference function", which is defined by .LB .EQ d(k)~ = ~~ sum from {n=- infinity} to infinity ~ |x(n)-x(n+k)| , .EN .LE has been used for this purpose with some success (Ross .ul et al, 1974). .[ Ross Schafer Cohen Freuberg Manley 1974 .] It exhibits dips at pitch periods (instead of the peaks of the autocorrelation function). .rh "Feature-extraction methods." Another possible way of extracting pitch in the time domain is to try to integrate information from different sources to give reliable pitch estimates. Several features of the time waveform can be defined, each of which provides an estimate of the pitch period, and an overall estimate can be obtained by majority vote. .pp For example, suppose that the only feature of the speech waveform which is retained is the height and position of the peaks, where a "peak" is defined by the simplistic criterion .LB $ x(n-1) ~<~ x(n) $ and $ x(n) $>$ x(n+1) . $ .LE Having found a peak which is thought to represent a pitch pulse, one could define a "blanking period", based upon the current pitch estimate, within which the next pitch pulse could not occur. When this period has expired, the next pitch pulse is sought. At first, a stringent criterion should be used for identifying the next peak as a pitch pulse; but it can gradually be relaxed if time goes on without a suitable pulse being located. Figure 4.15 shows a convenient way of doing this: a decaying exponential is begun at the end of the blanking period and when a peak shows above, it is identified as a pitch pulse. .FC "Figure 4.15" One big advantage of this type of algorithm is that the data is greatly reduced by considering peaks only \(em which can be detected by simple hardware. Thus it can permit real-time operation on a small processor with minimal special-purpose hardware. .pp Such a pitch pulse detector is exceedingly simplistic, and will often identify the pitch incorrectly. However, it can be used in conjunction with other features to produce good pitch estimates. Gold and Rabiner (1969), who pioneered the approach, used six features: .[ Gold Rabiner 1969 Parallel processing techniques for pitch periods .] .LB .NP peak height .NP valley depth .NP valley-to-peak height .NP peak-to-valley depth .NP peak-to-peak height (if greater than 0) .NP valley-to-valley depth (if greater than 0). .LE The features are symmetric with regard to peaks and valleys. The first feature is the one described above, and the second one works in exactly the same way. The third feature records the height between each valley and the succeeding peak, and fourth uses the depth between each peak and the succeeding valley. The purpose of the final two detectors is to eliminate secondary, but rather large, peaks from consideration. Figure 4.16 shows the kind of waveform on which the other features might incorrectly double the pitch, but the last two features identify correctly. .FC "Figure 4.16" .pp Gold and Rabiner also included the last two pitch estimates from each feature detector. Furthermore, for each feature, the present estimate was added to the previous one to make a fourth, and the previous one to the one before that to make a fifth, and all three were added together to make a sixth; so that for each feature there were 6 separate estimates of pitch. The reason for this is that if three consecutive estimates of the fundamental period are $T sub 0$, $T sub 1$ and $T sub 2$; then if some peaks are being falsely identified, the actual period could be any of .LB .EQ T sub 0 ~+~ T sub 1 ~~~~ T sub 1 ~+~ T sub 2 ~~~~ T sub 0 ~+~ T sub 1 ~+~ T sub 2 . .EN .LE It is essential to do this, because a feature of a given type can occur more than once in a pitch period \(em secondary peaks usually exist. .pp Six features, each contributing six separate estimates, makes 36 estimates of pitch in all. An overall figure was obtained from this set by selecting the most popular estimate (within some pre-specified tolerance). The complete scheme has been evaluated extensively (Rabiner .ul et al, 1976) and compares favourably with other methods. .[ Rabiner Cheng Rosenberg McGonegal 1976 .] .pp However, it must be admitted that this procedure seems to be rather .ul ad hoc (as are many other successful speech parameter estimation algorithms!). Specifically, it is not easy to predict what kinds of waveforms it will fail on, and evaluation of it can only be pragmatic. When used to estimate the pitch of musical instruments and singers over a 6-octave range (40\ Hz to 2.5\ kHz), instances were found where it failed dramatically (Tucker and Bates, 1978). .[ Tucker Bates 1978 .] This is, of course, a much more difficult problem than pitch estimation for speech, where the range is typically 3 octaves. In fact, for speech the feature detectors are usually preceded by a low-pass filter to attenuate the myriad of peaks caused by higher formants, and this is inappropriate for musical applications. .pp There is evidence which shows that additional features can assist with pitch identification. The above features are all based upon the signal amplitude, and could be described as .ul secondary features derived from a single .ul primary feature. Other primary features can easily be defined. Tucker and Bates (1978) used a centre-clipped waveform, and considered only the peaks rising above the central region. .[ Tucker Bates 1978 .] They defined two further primary features, in addition to the peak amplitude: the .ul time width of a peak (period for which it is outside the clipping level), and its .ul energy (again, outside the clipping level). The primary features are shown in Figure 4.17. .FC "Figure 4.17" Secondary features are defined, based on these three primary ones, and pitch estimates are made for each one. A further innovation was to combine the individual estimates on a way which is based upon autocorrelation analysis, reducing to some degree the .ul ad-hocery of the pitch detection process. .sh "4.9 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "4.10 Further reading" .pp There are a lot of books on digital signal analysis, although in general I find them rather turgid and difficult to read. .LB "nn" .\"Ackroyd-1973-1 .]- .ds [A Ackroyd, M.H. .ds [D 1973 .ds [T Digital filters .ds [I Butterworths .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Here is the exception to prove the rule. This book .ul is easy to read. It provides a good introduction to digital signal processing, together with a wealth of practical design information on digital filters. .in-2n .\"Committee.I.D.S.P-1979-3 .]- .ds [A IEEE Digital Signal Processing Committee .ds [D 1979 .ds [T Programs for digital signal processing .ds [I Wiley .ds [C New York .nr [T 0 .nr [A 0 .nr [O 0 .][ 2 book .in+2n This is a remarkable collection of tried and tested Fortran programs for digital signal analysis. They are all available from the IEEE in machine-readable form on magnetic tape. Included are programs for digital filter design, discrete Fourier transformation, and cepstral analysis, as well as others (like linear predictive analysis; see Chapter 6). Each program is accompanied by a concise, well-written description of how it works, with references to the relevant literature. .in-2n .\"Oppenheim-1975-4 .]- .ds [A Oppenheim, A.V. .as [A " and Schafer, R.W. .ds [D 1975 .ds [T Digital signal processing .ds [I Prentice Hall .ds [C Englewood Cliffs, New Jersey .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is one of the standard texts on most aspects of digital signal processing. It treats the $z$-transform, digital filters, and discrete Fourier transformation in far more detail than we have been able to here. .in-2n .\"Rabiner-1975-5 .]- .ds [A Rabiner, L.R. .as [A " and Gold, B. .ds [D 1975 .ds [T Theory and application of digital signal processing .ds [I Prentice Hall .ds [C Englewood Cliffs, New Jersey .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is the other standard text on digital signal processing. It covers the same ground as Oppenheim and Schafer (1975) above, but with a slightly faster (and consequently more difficult) presentation. It also contains major sections on special-purpose hardware for digital signal processing. .in-2n .\"Rabiner-1978-1 .]- .ds [A Rabiner, L.R. .as [A " and Schafer, R.W. .ds [D 1978 .ds [T Digital processing of speech signals .ds [I Prentice Hall .ds [C Englewood Cliffs, New Jersey .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Probably the best single reference for digital speech analysis, as it is for the time-domain encoding techniques of the last chapter. Unlike the books cited above, it is specifically oriented to speech processing. .in-2n .LE "nn" .EQ delim $$ .EN .CH "5 RESONANCE SPEECH SYNTHESIZERS" .ds RT "Resonance speech synthesizers .ds CX "Principles of computer speech .pp This chapter considers the design of speech synthesizers which implement a direct electrical analogue of the resonance properties of the vocal tract by providing a filter for each formant whose resonant frequency is to be controlled. Another method is the channel vocoder, with a bank of fixed filters whose gains are varied to match the spectrum of the speech as described in Chapter 4. This is not generally used for synthesis from a written representation, however, because it is hard to get good quality speech. It .ul is used sometimes for low-bandwidth transmission and storage, for it is fairly easy to analyse natural speech into fixed frequency bands. A second alternative to the resonance synthesizer is the linear predictive synthesizer, which at present is used quite extensively and is likely to become even more popular. This is covered in the next chapter. Another alternative is the articulatory synthesizer, which attempts to model the vocal tract directly, rather than modelling the acoustic output from it. Although, as noted in Chapter 2, articulatory synthesis holds a promise of high-quality speech \(em for the coarticulation effects caused by tongue and jaw inertia can be modelled directly \(em this has not yet been realized. .pp The source-filter model of speech production indicates that an electrical analogue of the vocal tract can be obtained by considering the source excitation and the filter that produces the formant frequencies separately. This approach was pioneered by Fant (1960), and we shall present much of his work in this chapter. .[ Fant 1960 Acoustic theory of speech production .] There has been some discussion over whether the source-filter model really is a good one, and some synthesizers explicitly introduce an element of "sub-glottal coupling", which simulates the effect of the lung cavity on the vocal tract transfer function during the periods when the glottis is open (for an example see Rabiner, 1968). .[ Rabiner 1968 Digital formant synthesizer JASA .] However, this is very much a low-order effect when considering speech synthesized by rule from a written representation, for the software which calculates parameter values to drive the synthesizer is a far greater source of degradation in speech quality. .sh "5.1 Overall spectral considerations" .pp Figure 5.1 shows the source-filter model of speech production. .FC "Figure 5.1" For voiced speech, the excitation source produces a waveform whose frequency components decay at about 12\ dB/octave, as we shall see in a later section. The excitation passes into the vocal tract filter. Conceptually, this can best be viewed as an infinite series of formant filters, although for implementation purposes only the first few are modelled explicitly and the effect of the rest is lumped together into a higher-formant compensation network. In either case the overall frequency profile of the filter is a flat one, upon which humps are superimposed at the various formant frequencies. Thus the output of the vocal tract filter falls off at 12\ dB/octave just as the input does. However, measurements of actual speech show a 6\ dB/octave decay with increasing frequency. This is explained by the effect of radiation of speech from the lips, which in fact has a "differentiating" action, producing a 6\ dB/octave rise in the frequency spectrum. This 6\ dB/octave lift is similar to that provided by a treble boost control on a radio or amplifier. Speech synthesized without it sounds unnaturally heavy and bassy. .pp These overall spectral shapes, which are derived from considering the human vocal tract, are summarized in the upper annotations in Figure 5.1. But there is no real necessity for a synthesizer to model the frequency characteristics of the human vocal tract at intermediate points: only the output speech is of any concern. Because the system is a linear one, the filter blocks in the figure can be shuffled around to suit engineering requirements. One such requirement is the desire to minimize internally-generated noise in the electrical implementation, most of which will arise in the vocal tract filter (because it is much more complicated than the other components). For this reason an excitation source with a flat spectrum is often preferred, as shown in the lower annotations. This can be generated either by taking the desired glottal pulse shape, with its 12\ dB/octave fall-off, and passing it through a filter giving 12\ dB/octave lift at higher frequencies; or, if the pulse shape is to be stored digitally, by storing its second derivative instead. Then the radiation compensation, which is now more properly called "spectral equalization", will comprise a 6\ dB/octave fall-off to give the required trend in the output spectrum. .pp For a given pitch period, this scheme yields exactly the same spectral characteristics as the original system which modelled the human vocal tract. However, when the pitch varies there will be a difference, for sounds with higher excitation frequencies will be attenuated by \-6\ dB/octave in the new system and +6\ dB/octave in the old by the final spectral equalization. In practice, the pitch of the human voice lies quite low in the frequency region \(em usually below 400\ Hz \(em and if all filter characteristics begin their roll-off at this frequency the two systems will be the same. This simplifies the implementation with a slight compromise in its accuracy in modelling the spectral trend of human speech, for the overall \-6\ dB/octave decay actually begins at a frequency of around 100\ Hz. If this is implemented, some adjustment will need to be made to the amplitudes to ensure that high-pitched sounds are not attenuated unduly. .pp The discussion so far pertains to voiced speech only. The source spectrum of the random excitation in unvoiced sounds is substantially flat, and combines with the radiation from the lips to give a +6\ dB/octave rise in the output spectrum. Hence if spectral equalization is changed to \-6\ dB/octave to accomodate a voiced excitation with flat spectrum, the noise source should show a 12\ dB/octave rise to give the correct overall effect. .sh "5.2 The excitation sources" .pp In human speech, the excitation source for voiced sounds is produced by two flaps of skin called the "vocal cords". These are blown apart by pressure from the lungs. When they come apart the pressure is relieved, and the muscles tensioning the skin cause the flaps to come together again. Subsequently, the lung pressure \(em called "sub-glottal pressure" \(em builds up once more and the process is repeated. The factors which influence the rate and nature of vibration are muscular tension of the cords and the sub-glottal pressure. The detail of the excitation has considerable importance to speech synthesis because it greatly influences the apparent naturalness of the sound produced. For example, if you have inflamed vocal cords caused by laryngitis the sound quality changes dramatically. Old people who do not have proper muscular control over their vocal cord tension produce a quavering sound. Shouted speech can easily be distinguished from quiet speech even when the volume cue is absent \(em you can verify this by fiddling with the volume control of a tape recorder \(em because when shouting, the vocal cords stay apart for a much smaller fraction of the pitch cycle than at normal volumes. .rh "Voiced excitation in natural speech." There are two basic ways to examine the shape of the excitation source in people. One is to use a dentist's mirror and high-speed photography to observe the vocal cords directly. Although it seems a lot to ask someone to speak naturally with a mirror stuck down the back of his throat, the method has been used and photographs can be found, for example, in Flanagan (1972). .[ Flanagan 1972 Speech analysis synthesis and perception .] The second technique is to process the acoustic waveform digitally, identifying the formant positions and deducting the formant contributions from the waveform by filtering. This leaves the basic excitation waveform, which can then be displayed. Such techniques lead to excitation shapes like those sketched in Figure 5.2, in which the gradual opening and abrupt closure of the vocal cords can easily be seen. .FC "Figure 5.2" .pp It is a fact that if a periodic function has one or more discontinuities, its frequency spectrum will decay at sufficiently high frequencies at the rate of 6\ dB/octave. For example, the components of the square wave .LB $ g(t) ~~ = ~~ mark 0 $ for $ 0 <= t < h $ .br $ lineup 1 $ for $ h <= t < b $ .LE can be calculated from the Fourier series .LB .EQ G(r) ~~ = ~~ 1 over b ~ integral from 0 to b ~g(t)~e sup {-j2 pi rt/b} ~dt ~~ = ~~ j over {2 pi r} ~e sup {-j2 pi rh/b} , .EN .LE so $|G(r)|$ is proportional to $1/r$, and the change in one octave is .LB .EQ 20~log sub 10 ~ |G(2r)| over |G(r)| ~~=~~20~log sub 10 ~ 1 over 2 ~~ = ~ .EN \-6\ dB. .LE However, if the discontinuities are ones of slope only, then the asymptotic decay at high frequencies is 12\ dB/octave. Thus the glottal excitation of Figure 5.2 will decay at this rate. Note that it is not the .ul number but the .ul type of discontinuities which are important in determining the asymptotic spectral trend. .rh "Voiced excitation in synthetic speech." There are several ways that glottal excitation can be simulated in a synthesizer, four of which are shown in Figure 5.3. .FC "Figure 5.3" The square pulse and the sawtooth pulse both exhibit discontinuities, and so will have the wrong asymptotic rate of decay (6\ dB/octave instead of 12\ dB/octave). A better bet is the triangular pulse. This has the correct decay, for there are only discontinuities of slope. However, although the asymptotic rate of decay is of first importance, the fine structure of the frequency spectrum at the lower end is also significant, and the fact that there are two discontinuities of slope instead of just one in the natural waveform means that the spectra cannot match closely. .pp Rosenberg (1971) has investigated several different shapes using listening tests, and he found that the polynomial approximation sketched in Figure 5.3 was preferred by listeners. .[ Rosenberg 1971 .] This has one slope discontinuity, and comprises three sections: .LB $g(t) ~~ = ~~ 0$ for $0 <= t < t sub 1$ (flat during the period of closure) .sp $g(t) ~~ = ~~ A~ u sup 2 (3 - 2u) $, where $u ~=~ {t-t sub 1} over {t sub 2 -t sub 1} $ , for $t sub 1 <= t < t sub 2$ (opening phase) .sp .sp $g(t) ~~ = ~~ A~ (1 - v sup 2 )$, where $v ~=~ {t-t sub 2} over {b-t sub 2} $ , for $t sub 2 <= t < b$ (closing phase). .LE It is easy to see that the joins between the first and second section, and between the second and third section, are smooth; but that the slope of the third section at the end of the cycle when $t=b$ is .LB .EQ dg over dt ~~ = ~~ -~ 2A. .EN .LE $A$ is the maximum amplitude of the pulse, and is reached when $t=t sub 2$. .pp A much simpler glottal pulse shape to implement is the filtered impulse. Passing an impulse through a filter with characteristic .LB .EQ 1 over {(1+sT) sup 2} .EN .LE imparts a 12\ dB/octave decay after frequency $1/T$. This gives a pulse shape of .LB .EQ g(t) ~~ = ~~ A~ t over T ~e sup {1-t/T} , .EN .LE which is sketched in Figure 5.4. .FC "Figure 5.4" The pulse is the wrong way round in time when compared with the desired one; but this is not important under most listening conditions because phase differences are not noticeable (this point is discussed further below). The maximum is reached when $t=T$ and has height $A$. The value zero is never actually attained, for the decay to it is asymptotic, and if the slight discontinuity between pulses shown in the Figure is left, the asymptotic rate of decay of the frequency spectrum will be 6\ dB/octave rather than 12\ dB/octave. However, in a real implementation involving filtering an impulse there will be no such discontinuity, for the next pulse will start off where the last one ended. .pp This seems to be an attractive scheme because of its simplicity, and indeed is sometimes used in speech synthesis. However, it does not have the right properties when the pitch is varied, for in real glottal waveforms the maximum occurs at a fixed .ul fraction of the period, whereas the filtered impulse's maximum is at a fixed time, $T$. If $T$ is chosen to make the system correct at high pitch frequencies (say 400\ Hz), then the pulse will be much too narrow at low pitches and sound rather harsh. The only solution is to vary the filter parameters with the pitch, leading to complexity again. .pp Holmes (1973) has made an extensive study of the effect of the glottal waveshape on the naturalness of high-quality synthesized speech. .[ Holmes 1973 Influence of glottal waveform on naturalness .] He employed a rather special speech synthesizer, which provides far more comprehensive and sophisticated control than most. It was driven by parameters which were extracted from natural utterances by hand \(em but the process of generating and tuning them took many months of a skilled person's time. By using the pulse shape extracted from the natural utterance, he found that synthetic and natural versions could actually be made indistinguishable to most people, even under high-quality listening conditions using headphones. Performance dropped quite drastically when one of Rosenberg's pulse shapes, similar to the three-section one given above, was used. Holmes also investigated phase effects and found that whilst different pulse shapes with identical frequency spectra could easily be distinguished when listening over headphones, there was no perceptible difference if the listener was placed at a comfortable distance from a loudspeaker in a room. This is attributable to the fact that the room itself imposes a complex modification to the phase characteristics of the speech signal. .pp Although a great deal of care must be taken with the glottal pulse shape for very high-quality synthetic speech, for speech synthesized by rule from a written representation the degradation which stems from incorrect control of the synthesizer parameters is much greater than that caused by using a slightly inferior glottal pulse. The triangular pulse illustrated in Figure 5.3 has been found quite satisfactory for speech synthesis by rule. .rh "Unvoiced excitation." Speech quality is much less sensitive to the characteristics of the unvoiced excitation. Broadband white noise will serve admirably. It is quite acceptable to generate this digitally, using a pseudo-random feedback shift register. This gives a bit sequence whose autocorrelation is zero except at multiples of the repetition length. The repetition length can easily be made as long as the number of states in the shift register (less one) \(em in this case, the configuration is called "maximal length" (Gaines, 1969). .[ Gaines 1969 Stochastic computing advances in information science .] For example, an 18-bit maximal-length shift register will repeat every $2 sup 18 -1$ cycles. If the bit-stream is used as a source of analogue noise, the autocorrelation function will have triangular parts whose width is twice the clock period, as shown in Figure 5.5. .FC "Figure 5.5" According to a well-known result (the Weiner-Kinchine theorem; see for example Chirlian, 1973) the power density of the frequency spectrum is the same as the Fourier transform of the autocorrelation function. .[ Chirlian 1973 .] Since the feedback shift register gives a periodic autocorrelation function, its transform is a Fourier series. The $r$'th frequency component is .LB .EQ G(r) ~~ = ~~ {R sup 2} over {4 pi sup 2 r sup 2 T} ~(1~-~~cos~{{2 pi rT} over R}) ~ . .EN .LE Here, $T$ is the clock period and $R=(2 sup N -1)T$ is the repetition time of an $N$-bit shift register. .pp The spectrum is a bar spectrum, with components spaced at .LB $ {1 over R}~~=~~{1 over {(2 sup N -1)T}}$ Hz. .LE These are very close together \(em with $N=18$ and sampling at 20\ kHz (50\ $mu$sec) the spacing becomes under 0.1\ Hz \(em and so it is reasonable to treat the spectrum as continuous, with .LB .EQ G(f) ~~ = ~~ 1 over {4 pi sup 2 f sup 2 T}~~(1~-~cos 2 pi fT) . .EN .LE This spectrum is sketched in Figure 5.6(a), and the measured result of an actual implementation in Figure 5.6(b). .FC "Figure 5.6" The 3\ dB point occurs when .LB .EQ {G(f) over G(0)} ~~=~~{1 over 2} ~ , .EN .LE and $G(0)$ is $T/2$. Hence, at the 3\ dB point, .LB .EQ {1~-~cos 2 pi fT} over {2 pi sup 2 f sup 2 T sup 2} ~~ = ~~ 1 over 2 ~ , .EN .LE which has solution $f=0.45/T$. Thus a pseudo-random shift register generates noise whose spectrum is substantially flat up to half the clock frequency. Anything over 10\ kHz is therefore a suitable clocking rate for speech-quality noise. Choose 20\ kHz to err on the conservative side. If the repetition occurs in less than 3 or 4 seconds, it can be heard quite clearly; but above this figure it is not noticeable. An 18-bit shift register clocked at 20\ kHz repeats every $(2 sup 18 -1)/20000 ~ = ~ 13$ seconds, which is more than adequate. .sh "5.3 Simulating vocal tract resonances" .pp The vocal tract, from glottis to lips, can be modelled as an unconstricted tube of varying cross-section with no side branches and no sub-glottal coupling. This has an all-pole transfer function, which can be written in the form .LB .EQ H(s) ~~ = ~~ {w sub 1 sup 2} over {s sup 2 ~+~ b sub 1 s ~+~ w sub 1 sup 2} ~.~{w sub 2 sup 2} over {s sup 2 ~+~ b sub 2 s ~+~ w sub 2 sup 2} ~~ .~ .~ . .EN .LE There is an unspecified (conceptually infinite) number of terms in the product. Each of them produces a peak in the energy spectrum, and these are the formants we observed in Chapter 2. .pp Formants appear even in an over-simplified model of the tract as a tube of uniform cross-section, with a sound source at one end (the larynx) and open at the other (the lips). This extremely crude model was discussed in Chapter 2, and surprisingly, perhaps, it gives a good approximation to the observed formant frequencies for a neutral, relaxed vowel such as that in .ul "a\c bove". .pp Speech is made by varying the postures of the various organs of the vocal tract. Different vowels, for example, result largely from different tongue positions and lip postures. Naturally, such physical changes alter the frequencies of the resonances, and successful automatic speech synthesis depends upon successful movement of the formants. Fortunately, only the first three or four resonances need to be altered even for extremely realistic synthesis, and virtually all existing synthesizers provide control over these formants only. .rh "Analysis of a single formant." Each formant is modelled as a second-order resonance, with transfer function .LB .EQ H(s) ~~ = ~~ {w sub c sup 2} over {s sup 2 ~+~ b s ~+~ w sub c sup 2} ~ . .EN .LE As will be shown below, $w sub c$ is the nominal resonant frequency in radians/s, and $b$ is the approximate 3\ dB bandwidth of the resonance. The term $w sub c sup 2$ in the numerator adjusts the gain to be unity at DC ($s=0$). .pp To calculate the frequency response of the formant, write $s=jw$. Then the energy spectrum is .LB .EQ |H(jw)| sup 2 ~~ mark = ~~ {w sub c sup 4} over {(w sup 2 - w sub c sup 2 ) sup 2 ~+~ b sup 2 w sup 2} .EN .sp .sp .EQ lineup = ~~ {w sub c sup 4} over {[w sup 2 ~-~(w sub c sup 2 -~ {b sup 2} over 2 )] sup 2 ~~ +~~b sup 2 (w sub c sup 2~-~{{b sup 2} over 4})} ~ . .EN .sp .LE This reaches a maximum when the squared term in the denominator of the second expression is zero, namely when $w=(w sub c sup 2 ~-~ b sup 2 /2) sup 1/2$. However, formant bandwidths are low compared with their centre frequencies, and so to a good approximation the peak occurs at $w=w sub c$ and is of amplitude $w sub c /b$, that is, $10~log sub 10 w sub c /b$\ dB above the DC gain. At frequencies higher than the peak the energy falls off as $1/w sup 4$, a factor of 1/16 for each doubling in frequency, and so the asymptotic decay is 12\ dB/octave. .pp At the points which are 3\ dB below the peak, .LB .EQ |H(jw sub 3dB )| sup 2 ~~ = ~~ 1 over 2 ~|H(jw sub max )| sup 2 ~~ = ~~ 1 over 2 ~ times ~ {w sub c sup 2} over {b sup 2} ~ , .EN .LE and it is easy to show that this is satisfied by $w sub 3dB ~ = ~ w sub c ~ +- ~ b/2$ to a good approximation (neglecting higher powers of $b/w sub c )$. Figure 5.7 summarizes the shape of an individual formant resonance. .FC "Figure 5.7" .pp The bandwidth of a formant is fairly constant, regardless of the formant frequency. This makes the formant filter a slightly unusual one: most engineering applications which use variable-frequency resonances require the bandwidth to be a constant proportion of the resonant frequency \(em the ratio $w sub c /b$, often called the "$Q$" of the filter, is to be constant. For formants, we wish the Q to increase linearly with resonant frequency. Since the amplitude gain of the formant at resonance is $w sub c /b$, this peak gain increases as the formant frequency is increased. .pp Although it is easy to measure formant frequencies on a spectrogram (cf Chapter 2), it is not so easy to measure bandwidths accurately. One rather unusual method was reported by van den Berg (1955), who took a subject who had had a partial laryngectomy, an operation which left an opening into the vocal tract near the larynx position. Into this he inserted a sound source and made a swept-frequency calibration of the vocal tract! .[ Berg van den 1955 .] Almost as bizarre is a technique which involves setting off a spark inside the mouth of a subject as he holds his articulators in a given position. .pp The results of several different kinds of experiment are reported by Dunn (1961), and are summarized in Table 5.1, along with the formant frequency ranges. .[ Dunn 1961 .] .RF .in+0.5i .ta 1.7i +2.5i .nr x1 (\w'range of formant'/2) .nr x2 (\w'range of bandwidths'/2) \h'-\n(x1u'range of formant \h'-\n(x2u'range of bandwidths .nr x1 (\w'frequencies (Hz)'/2) .nr x2 (\w'as measured in different'/2) \h'-\n(x1u'frequencies (Hz) \h'-\n(x2u'as measured in different .nr x1 (\w'experiments (Hz)'/2) \h'-\n(x1u'experiments (Hz) .nr x1 (\w'0000 \- 0000'/2) .nr x2 (\w'000 \- 000'/2) .nr x0 2.5i+(\w'range of formant'/2)+(\w'as measured in different'/2) .nr x3 (\w'range of formant'/2) \h'-\n(x3u'\l'\n(x0u\(ul' .sp formant 1 \h'-\n(x1u'\0100 \- 1100 \h'-\n(x2u'\045 \- 130 formant 2 \h'-\n(x1u'\0500 \- 2500 \h'-\n(x2u'\050 \- 190 formant 3 \h'-\n(x1u'1500 \- 3500 \h'-\n(x2u'\070 \- 260 \h'-\n(x3u'\l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in-0.5i .MT 2 Table 5.1 Different estimates of formant bandwidths, with range of formant frequencies for reference .TE Note that the bandwidths really are narrow compared with the resonant frequencies of the filters, except at the lower end of the formant 1 range. Choosing the lowest bandwidth estimate leads to an amplification factor at resonance of 50 for formant 2 when its frequency is at the top of its range; and formant 3 happens to give the same value. .rh "Series synthesizers." The simplest realization of the vocal tract filter is a chain of formant filters in series, as illustrated in Figure 5.8. .FC "Figure 5.8" This leads to particular difficulties if the frequencies of two formants stray close together. The worst case occurs if formants 2 and 3 have the same resonant frequencies, at the top of the range of formant 2, namely 2500\ Hz. In this case, and if the bandwidths of the formants are set to the lowest estimates, a combined amplification factor of $(2500/50) times (2500/70)=1800$ is obtained at the point of resonance \(em that is, 65\ dB above the DC value. This is enough to tax most analogue implementations, and can evoke clipping in the formant filters, with a very noticeable effect on speech quality. This extreme case will not occur during synthesis of realistic speech, for although the formant .ul ranges overlap, the values for any particular (human) sound will not coincide exactly. However, it illustrates the difficulty of designing a series synthesizer which copes sensibly with arbitrary parameter settings, and explains why designers often choose formant bandwidths in the top half of the ranges given in Table 5.1. .pp The problem of excessive amplification within a series synthesizer can be alleviated to a small extent by choosing carefully the order in which the filters are placed in the chain. In a linear system, of course, the order in which the components occur does not matter. In physical implementations, however, it is advantageous to minimize extreme amplification at intermediate points. By placing the formant 1 filter between formants 2 and 3, the formant 2 resonance is attenuated somewhat before it reaches formant 3. Continuing with the extreme example above, where both formants 2 and 3 were set to 2500\ Hz; assume that formant 1 is at its nominal value of 500\ Hz. It provides attenuation at approximately 12\ dB/octave above this, and so at the formant 2 peak, 2.3\ octaves higher, the attenuation is 28\ dB. Thus the gain at 2500\ Hz, which is $20 ~ log sub 10 ~ 2500/50 ~ = ~ 34$\ dB after passing through the formant 2 filter, is reduced to 6\ dB by formant 1, only to be increased by $20 ~ log sub 10 ~ 2500/70 ~ = ~ 31$\ dB to a value of 37\ dB by formant 3. This avoids the extreme 65\ dB gain of formants 2 and 3 combined. .pp Figure 5.8 shows only three formant filters modelled explicitly. The effect of the rest \(em and they do have an effect, although it is small at low frequencies \(em is incorporated by lumping them together into the "higher-formant correction" filter. To calculate the characteristics of this filter, assume that the lumped formants have the values given by the simple uniform-tube model of Chapter 2, namely 3500\ Hz for formant 4, 4500\ Hz for formant 5, and, in general, $500(2n-1)$\ Hz for formant $n$. The effect of each of these on the spectrum is .LB .EQ 10~ log sub 10 {w sub n sup 4} over {(w sup 2 ~-~w sub n sup 2 ) sup 2 ~~+~~b sub n sup 2 w sup 2} ~~ = ~~ -~ 10~ log sub 10 ~[(1~-~~{{w sup 2} over {w sub n sup 2}}) sup 2 ~~+~~ {{b sub n sup 2 w sup 2} over {w sub n sup 4}}] .EN dB, .LE following from what was calculated above. We will have to approximate this by assuming that $b sub n sup 2 /w sub n sup 2$ is negligible \(em this is quite reasonable for these higher formants because Table 5.1 shows that the bandwidth does not increase in proportion to the formant frequency range \(em and approximate the logarithm by the first term of its series expansion: .LB .EQ -10 ~ log sub 10 ~ (1~-~~{{w sup 2} over {w sub n sup 2}}) sup 2 ~~ = ~~ -20~ log sub 10 ~ e ~ log sub e (1~-~~{{w sup 2} over {w sub n sup 2}}) ~~ = ~~ 20~ log sub 10 ~ e ~ times ~ {w sup 2} over {w sub n sup 2} ~ . .EN .LE .pp Now the total effect of formants 4, 5, ... at frequency $f$\ Hz (as distinct from $w$\ radians/s) is .LB .EQ 20~ log sub 10 ~ e ~ times ~ sum from n=4 to infinity ~{{f sup 2} over {500 sup 2 (2n-1) sup 2}} ~ . .EN .LE This expression is .LB .EQ 20~ log sub 10 ~ e ~ times ~ {{f sup 2} over {500 sup 2}}~~(~sum from n=1 to infinity ~{1 over {(2n-1) sup 2}} ~~-~~ sum from n=1 to 3 ~{1 over {(2n-1) sup 2}}~) ~ . .EN .LE The infinite sum can actually be calculated in closed form, and is equal to $pi sup 2 /8$. Hence the total correction is .LB .EQ 20~ log sub 10 ~ e ~ times {{f sup 2} over {500 sup 2}} ~~(~{pi sup 2} over 8 ~~-~~ sum from n=1 to 3 ~{1 over {(2n-1) sup 2}}~) ~~ = ~~ 2.87 times 10 sup -6 f sup 2 .EN dB. .LE .pp Although this may at first seem to be a rather small correction, it is in fact 72\ dB when $f=5$\ kHz! On further reflection this is not an unreasonable figure, for the 12\ dB/octave decays contributed by formants 1, 2, and 3 must all be annihilated by the higher-formant correction to give an overall flat spectral trend. In fact, formant 1 will contribute 12\ dB/octave from 500\ Hz (3.3\ octaves to 5\ kHz, representing 40\ dB); formant 2 will contribute 12\ dB/octave from 1500\ Hz (1.7\ octaves to 5\ kHz, representing 21\ dB); and formant 3 will contribute 12\ dB/octave from 2500\ Hz (1\ octave to 5\ kHz, representing 12\ dB). These sum to 73\ dB. .pp If the first five formants are synthesized explicitly instead of just the first three, the correction is .LB .EQ 20~ log sub 10 ~ e ~ times ~ {{f sup 2} over {500 sup 2}} ~~(~{pi sup 2} over 8 ~-~~ sum from n=1 to 5 ~{1 over {(2n-1) sup 2}}~) ~~ = ~~ 1.73 times 10 sup -6 f sup 2 .EN dB, .LE giving a rather more reasonable value of 43\ dB when $f=5$\ kHz. In actual implementations, fixed filters are sometimes included explicitly for formants 4 and 5. Although this lowers the gain of the higher-formant correction filter, the total amplification at 5\ kHz of the combined correction is still 72\ dB. If one is less demanding and aims for a synthesizer that produces a correct spectrum only up to 3.5\ kHz, it is 35\ dB. This places quite stringent requirements on the preceding formant filters if the stray noise that they generate internally is not to be amplified to perceptible magnitudes by the correction filter at high frequencies. .pp Explicit inclusion of fixed filters for formants 4 and 5 undoubtedly improves the accuracy of the higher-formant correction. Recall that the above derivation of the correction filter characteristic used the first-order approximation .LB .EQ log sub e (1~-~{{w sup 2} over {w sub n sup 2}}) ~~ = ~~ -~ {w sup 2} over {w sub n sup 2} ~ , .EN .LE which is only valid if $w << w sub n$. Thus it only holds at frequencies less than the highest explicitly synthesized formant, and so with formants 4 (3.5\ kHz) and 5 (4.5\ kHz) included a reasonable correction should be obtained for telephone-quality speech. However, detailed analysis with a second-order approximation shows that the coefficient of the neglected term is in fact small (Fant, 1960). .[ Fant 1960 Acoustic theory of speech production .] A second, perhaps more compelling, reason for explicitly including a couple of fixed formants is that the otherwise enormous amplification provided by the correction can be distributed throughout the formant chain. We saw earlier why there is reason to prefer the order F3\(emF1\(emF2 over F1\(emF2\(emF3. With explicit formants 4 and 5, a suitable order which helps to keep the amplification at intermediate points in the chain within reasonable bounds is F3\(emF5\(emF2\(emF4\(emF1. .rh "Parallel synthesizers." A series synthesizer models the vocal tract resonances by a chain of formant filters in series. A parallel synthesizer utilizes a parallel connection of filters as illustrated in Figure 5.9. .FC "Figure 5.9" .pp Consider a parallel combination of two formants with individually-controllable amplitudes. The combined transfer function is .LB .EQ H(s) ~~ mark = ~~ {A sub 1 w sub 1 sup 2} over {s sup 2 ~+~ b sub 1 s ~+~ w sub 1 sup 2} ~~+~~{A sub 2 w sub 2 sup 2} over {s sup 2 ~+~ b sub 2 s ~+~ w sub 2 sup 2} .EN .sp .sp .EQ lineup = ~~ { (A sub 1 w sub 1 sup 2 + A sub 2 w sub 2 sup 2 )s sup 2 ~+~(A sub 1 b sub 2 w sub 1 sup 2 + A sub 2 b sub 1 w sub 2 sup 2 )s ~+~ (A sub 1 +A sub 2 )w sub 1 sup 2 w sub 2 sup 2 } over { (s sup 2 ~+~b sub 1 s~+~w sub 1 sup 2 ) (s sup 2 ~+~b sub 2 s~+~w sub 2 sup 2 ) } .EN .LE If the formant bandwidths $b sub 1$ and $b sub 2$ are equal and the amplitudes are chosen as .LB .EQ A sub 1 ~~=~~ {w sub 2 sup 2} over {w sub 2 sup 2 -w sub 1 sup 2} ~~~~~~~~ A sub 2 ~~=~~-~ {w sub 1 sup 2} over {w sub 2 sup 2 -w sub 1 sup 2} ~ , .EN .LE then the transfer function becomes the same as that of a two-formant series synthesizer, namely .LB .EQ H(s) ~~ = ~~ {w sub 1 sup 2} over {s sup 2 ~+~ b sub 1 s ~+~ w sub 1 sup 2} ~ . ~{w sub 2 sup 2} over {s sup 2 ~+~ b sub 2 s ~+~ w sub 2 sup 2} ~ . .EN .LE The argument can be extended to any number of formants, under the assumption that the formant bandwidths are equal. Note that the signs of $A sub 1$ and $A sub 2$ differ: in general the formant amplitudes for a parallel synthesizer alternate in sign. .pp In theory, therefore, it would be possible to use five parallel formants to model a five-formant series synthesizer exactly. Then the same higher-formant correction filter would be needed for the parallel synthesizer as for the series one. If the formant amplitudes were set slightly incorrectly, however, the five filters would not combine to give a total of 60\ dB/octave high-frequency decay above the resonances. It is easy to see this in the context of the simplified two-formant combination above: if the amplitudes were not chosen exactly right then the $s sup 2$ term in the numerator would not be quite zero. Then, the decay in the two-formant combination would be \-12\ dB/octave instead of \-24\ dB/octave, and in the five-formant case the decay would in fact still be \-12\ dB/octave. Advantage can be taken of this to equalize the levels within the synthesizer so that large amplitude variations do not occur. This can best be done by associating relatively low-gain fixed correction filters with each formant instead of providing one comprehensive correction to the combined spectrum: these are shown in Figure 5.9. Suitable correction filters have been determined empirically by Holmes (1972). .[ Holmes 1972 Speech synthesis .] They provide a 6\ dB/octave lift above 640\ Hz for formant 1, and 6\ dB/octave lift above 300\ Hz for formant 2. Formants 3 and 4 are uncorrected, whilst for formant 5 the correction begins as a 6\ dB/octave decay above 600\ Hz and increases to an 18\ dB/octave decay above 5.5\ kHz. .pp The disadvantage of a parallel synthesizer is that the amplitudes of the formants must be specified as well as their frequencies. (Furthermore, the formant bandwidths should all be equal, but they are often chosen to be such in series synthesizers because of the uncertainty as to their exact values.) However, the extra amplitude parameters clearly give greater control over the frequency spectrum of the synthesized speech. .pp A good example of how this extra control can usefully be exploited is the synthesis of nasal sounds. Nasalization introduces a cavity parallel to the oral tract, as illustrated in Figure 5.10, and this causes zeros in the transfer function. .FC "Figure 5.10" It is as if two different copies of the vocal tract transfer function, one for the oral and the other for the nasal passage, were added together. We have seen the effect of this above when considering parallel synthesis. The combination .LB .EQ H(s) ~~ = ~~ {A sub 1 w sub o sup 2} over {s sup 2 ~+~ b sub o s ~+~ w sub o sup 2} ~~+~~{A sub 2 w sub n sup 2} over {s sup 2 ~+~ b sub n s ~+~ w sub n sup 2} ~ , .EN .LE where the subscript "$o$" stands for oral and "$n$" for nasal, produces zeros in the numerator (unless the amplitudes are carefully adjusted to avoid them). These cannot be modelled by a series synthesizer, but they obviously can be by a parallel one. .pp Although they are certainly needed for accurate imitation of human speech, transfer function zeros to simulate nasal sounds are not essential for synthesis of intelligible English. It is not difficult to get a sound like a nasal consonant (\c .ul n, or .ul m\c ) with an all-pole synthesizer. Nevertheless, it is certainly true that a parallel synthesizer gives better .ul potential control over the spectrum than a series one. Whether the added flexibility can be used properly by a synthesis-by-rule computer program is another matter. .rh "Implementation of formant filters." Formant filters can be built in either analogue or digital form. A second-order resonance is needed, whose centre frequency can be controlled but whose bandwidth is fixed. If the control can be arranged as two tracking resistors, then the simple analogue configuration of Figure 5.11, with two operational amplifiers, will suffice. .FC "Figure 5.11" .pp The transfer function of this arrangement is .LB .EQ - ~~ { 1/C sub 1 R sub 1 C sub 2 R sub 2 } over { s sup 2 ~~+~~ {1 over {C sub 2 R sub 2}}~s ~~+~~{1 over {C sub 1 R' sub 1 C sub 2 R sub 2 }}} ~ , .EN .LE which characterizes it as a low-pass resonator with DC gain of $- R' sub 1 /R sub 1 $, bandwidth of $1/2 pi C sub 2 R sub 2$\ Hz, and centre frequency of $1/2 pi (C sub 1 R' sub 1 C sub 2 R sub 2 ) sup 1/2$\ Hz. Tracking $R' sub 1$ with $R sub 1$ ensures that the DC gain remains constant, and that the centre frequency follows $R sub 1 sup -1/2$. Moreover, neither is especially sensitive to slight departures from exact tracking of $R' sub 1$ with $R sub 1$. Such a filter has been used in a simple hand-controlled speech synthesizer, built for demonstration and amusement (Witten and Madams, 1978). .[ Witten Madams 1978 Chatterbox .] However, the need for tracking resistors, and the inverse square root variation of the formant frequency with $R sub 1$, makes it rather unsuitable for serious applications. .pp A better analogue filter is the ring-of-three configuration shown in Figure 5.12. .FC "Figure 5.12" (Ignore the secondary output for now.) Control is achieved over the centre frequency by two multipliers, driven from the same control input $k$. These have a high-impedance output, producing a current $kx$ if the input voltage is $x$. It is not too difficult to show that the transfer function of the circuit is .LB .EQ - ~~ { {k sup 2} over {C sup 2} } over { s sup 2 ~~+~~ 2 over RC ~s ~~+~~{1+k sup 2 R sup 2} over {R sup 2 C sup 2} } ~ . .EN .LE Suppose that $R$ is chosen so that $k sup 2 R sup 2 ~ >>~ 1$. Then this is a unity-gain resonator with constant bandwidth $1/ pi RC$\ Hz and centre frequency $k/2 pi C$\ Hz. Note that it is the combination of both multipliers that makes the centre frequency grow linearly with $k$: with one multiplier there would be a square-root relationship. .pp The ring-of-three filter of Figure 5.12 is arranged in a slightly unusual way, with an inverting stage at the beginning and the two resonant stages following it. This ensures that the signal level at intermediate points in the filter does not exceed that at the output, and gives the filter the best chance of coping with a wide range of input amplitudes without clipping. This contrasts markedly with the resonator of Figure 5.11, where the voltage at the output of the first integrator is $w/b$ times the final output \(em a factor of 50 in the worst case. .pp For a digital implementation of a formant, consider the recurrence relation .LB .EQ y(n)~ = ~~ a sub 1 y(n-1) ~-~ a sub 2 y(n-2) ~+~ a sub 0 x(n) , .EN .LE where $x(n)$ is the input and $y(n)$ the output at time $n$, $y(n-1)$ and $y(n-2)$ are the previous two values of the output, and $a sub 0$, $a sub 1$, and $a sub 2$ are (real) constants. The minus sign is in front of the second term because it makes $a sub 2$ turn out to be positive. To calculate the $z$-transform version of this relationship, multiply through by $z sup -n$ and sum from $n=- infinity$ to $infinity$ : .LB "nn" .EQ sum from {n=- infinity} to infinity ~y(n)z sup -n ~~ mark =~~ a sub 1 sum from {n=- infinity} to infinity ~y(n-1)z sup -n ~~-~ a sub 2 sum from {n=- infinity} to infinity ~y(n-2)z sup -n ~~+~ a sub 0 sum from {n=- infinity} to infinity ~x(n)z sup -n .EN .sp .EQ lineup = ~~ a sub 1 z sup -1 ~ sum ~y(n-1)z sup -(n-1) ~~-~~ a sub 2 z sup -2 ~ sum ~y(n-2)z sup -(n-2) ~~+~~ a sub 0 ~ sum ~x(n)x sup -n ~ . .EN .LE "nn" Writing this in terms of $z$-transforms, .LB .EQ Y(z)~ = ~~ a sub 1 z sup -1 Y(z) ~-~ a sub 2 z sup -2 Y(z) ~+~ a sub 0 X(z) . .EN .LE Thus the input-output transfer function of the system is .LB .EQ H(z)~ = ~~ Y(z) over X(z) ~~=~~ {a sub 0 } over {1~-~a sub 1 z sup -1 ~+~a sub 2 z sup -2} ~ . .EN .LE .pp We learned in the previous chapter that the frequency response is obtained from the $z$-transform of a system by replacing $z sup -1$ by $e sup {-j2 pi fT}$, where $f$ is the frequency variable in\ Hz. Hence the amplitude response of the digital formant filter is .LB .EQ |H(e sup {j2 pi fT} )| sup 2 ~~ = ~~ left [ {a sub 0} over {1~-~a sub 1 e sup {-j2 pi fT} ~+~a sub 2 e sup {-j4 pi fT} } ~ right ] sup 2 ~ . .EN .sp .LE It is fairly obvious from this that a DC gain of 1 is obtained if .LB .EQ a sub 0 ~ = ~~ 1 ~-~ a sub 1 ~+~ a sub 2 , .EN .LE for $e sup {-j2 pi fT}$ is 1 at a frequency of 0\ Hz. Some manipulation is required to show that, under the usual assumption that the bandwidth is small, the centre frequency is .LB .EQ 1 over {2 pi T} ~~ cos sup -1 ~ {a sub 1} over {2 a sub 2 sup 1/2} ~ .EN Hz. .LE Furthermore, the 3\ dB bandwidth of the resonance is given approximately by .LB .EQ -~ 1 over {2 pi T} ~~ log sub e a sub 2 ~ .EN Hz. .LE .pp As an example, Figure 5.13 shows an amplitude response for this digital filter. .FC "Figure 5.13" The parameters $a sub 0$, $a sub 1$ and $a sub 2$ were generated from the above relationships for a sampling frequency of 8\ kHz, centre frequency of 1\ kHz, and bandwidth of 75\ Hz. It exhibits a peak of approximately the right bandwidth at the correct frequency, 1\ kHz. Note that the response is flat at half the sampling frequency, for the frequency response from 4\ kHz to 8\ kHz is just a reflection of that up to 4\ kHz. This contrasts sharply with that of an analogue formant filter, also shown in Figure 5.13, which slopes at \-12\ dB/octave at frequencies above resonance. .pp The behaviour of a digital formant filter at frequencies above resonance actually makes it preferable to an analogue implementation. We saw earlier that considerable trouble must be taken with the latter to compensate for the cumulative effect of \-12\ dB/octave at higher frequencies for each of the formants. This is not necessary with digital implementations, for the response of a digital formant filter is flat at half the sampling frequency. In fact, further study shows that digital synthesizers without any higher-pole correction give a closer approximation to the vocal tract than analogue ones with higher-pole correction (Gold and Rabiner, 1968). .[ Gold Rabiner 1968 Analysis of digital and analogue formant synthesizers .] .rh "Time-domain methods." An interesting alternative to frequency-domain speech synthesis is to construct the formants in the time domain. When a second-order resonance is excited by an impulse, an exponentially decaying sinusoid is produced, as illustrated by Figure 5.14. .FC "Figure 5.14" The oscillation occurs at the resonant frequency of the filter, while the decay is related to the bandwidth. In fact, if the formant filter has transfer function .LB .EQ {w sup 2} over {s sup 2 ~+~ b s ~+~ w sup 2} ~ , .EN .LE the time waveform for impulsive excitation is .LB .EQ x(t)~ = ~~ w~ e sup -bt/2 ~ sin ~ wt ~~~~~~~~ .EN (neglecting $b sup 2 /w sup 2$). .LE It is the combination of several such time waveforms, coupled with the regular reappearance of excitation at the pitch period, that produces the characteristic wiggly waveform of voiced speech. .pp Now suppose we take a sine wave of frequency $w$ and multiply it by a decaying exponential $e sup -bt/2$. This gives a signal .LB .EQ x(t)~ = ~~ e sup -bt/2 ~ sin ~ wt , .EN .LE which is identical with the filtered impulse except for a factor $w$. If there are several formants in parallel, all with the same bandwidth, the exponential factor is the same for each: .LB .EQ x(t)~ = ~~ e sup -bt/2 ~ (A sub 1 ~ sin ~ w sub 1 t ~~+ ~~ A sub 2 ~ sin ~ w sub 2 t ~~ + ~~ A sub 3 ~ sin ~ w sub 3 t) . .EN .LE $A sub 1$, $A sub 2$, and $A sub 3$ control the formant amplitudes, as in an ordinary parallel synthesizer; except that they need adjusting to account for the missing factors $w sub 1$, $w sub 2$, and $w sub 3$. .pp A neat way of implementing such a synthesizer digitally is to store one cycle of a sine wave in a read-only memory (ROM). Then, the formant frequencies can be controlled by reading the ROM at different rates. For example, if twice the basic frequency is desired, every second value should be read. Multiplication is needed for amplitude control of each formant: this can be accomplished by shifting the digital word (each place shifted accounts for 6\ dB of attenuation). Finally, the exponential damping factor can be provided in analogue hardware by a single capacitor after the D/A converter. This implementation gives a system for hardware-software synthesis which involves an absolutely minimal amount of extra hardware apart from the computer, and does not need hardware multiplication for real-time operation. It could easily be made to work in real time with a microprocessor coupled to a D/A converter, damping capacitor, and fixed tone-control filter to give the required spectral equalization. .pp Because the overall spectral decay of an impulse exciting a second-order formant filter is 12\ dB/octave, the appropriate equalization is +6\ dB/octave lift at high frequencies, to give an overall \-6\ dB/octave spectral trend. .pp Note, however, that this synthesis model is an extremely basic one. Only impulsive excitation can be accomodated. For fricatives, which we will discuss in more detail below, a different implementation is needed. A hardware noise generator, with a few fixed filters \(em one for each fricative type \(em will suffice for a simple system. More damaging is the lack of aspiration, where random noise excites the vocal tract resonances. This cannot be simulated in the model. The .ul h sound can be provided by treating it as a fricative, and although it will not sound completely realistic, because there will be no variation with the formant positions of adjacent phonemes, this can be tolerated because .ul h is not too important for speech intelligibility. A bigger disadvantage is the lack of proper aspiration control for producing unvoiced stops, which as mentioned in Chapter 2 consist of an silent phase followed by a burst of aspiration. Experience has shown that although it is difficult to drive such a synthesizer from a software synthesis-by-rule system, quite intelligible output can be obtained if parameters are derived from real speech and tweaked by hand. Then, for each aspiration burst the most closely-matching fricative sound can be used. .sh "5.4 Aspiration and frication" .pp The model of the vocal tract as a filter which affects the frequency spectrum of the basic voiced excitation breaks down if there are constrictions in it, for these introduce new sound sources caused by turbulent air. The generation of unvoiced excitation has been discussed earlier in this chapter: now we must consider how to simulate the filtering action of the vocal tract for unvoiced sounds. .pp Aspiration and frication need to be dealt with separately. The former is caused by excitation at the vocal cords \(em the cords are held so close together that turbulent noise is produced. This noise passes through the same vocal tract filter that modifies voiced sounds, and the same kind of formant structure can be observed. All that is needed to simulate it is to replace the voiced excitation source by white noise, as shown in the upper part of Figure 5.15. .FC "Figure 5.15" .pp Speech can be whispered by substituting aspiration for voicing throughout. Of course, there is no fundamental frequency associated with aspiration. An interesting way of assessing informally the degradation caused by inadequate pitch control in a speech synthesis-by-rule system is to listen to whispered speech, in which pitch variations play no part. .pp Voiced and aspirative excitation are rarely produced at the same time in natural speech (but see the discussion in Chapter 2 about breathy voice). However, the excitation can change from one to the other quite quickly, and when this happens there is no discontinuity in the formant structure. .pp Fricative, or sibilant, excitation is quite different from aspiration, because it introduces a new sound source at a different place from the vocal cords. The constriction which produces the sound may be at the lips, the teeth, the hard ridge just behind the top front teeth, or further back along the palate. These positions each produce a different sound (\c .ul f, .ul th, .ul s, and .ul sh respectively). However, smooth transitions from one of these sounds to another do not occur in natural speech; and dynamical movement of the frequency spectrum during a fricative is unnecessary for speech synthesis. .pp It is necessary, however, to be able to produce an approximation to the noise spectrum for each of these sound types. This is commonly achieved by a single high-pass resonance whose centre frequency can be controlled. This is the purpose of the secondary output of the formant filter of Figure 5.12. Taking the output from this point gives a high-pass instead of a low-pass resonance, and this same filter configuration is quite acceptable for fricatives. Figure 5.15 shows the fricative sound path as a noise generator followed by such a filter. .pp Unlike aspiration, fricative excitation is frequently combined with voicing. This gives the voiced fricative sounds .ul v, .ul dh, .ul z, and .ul zh. It is possible to produce frication and aspiration together, and although there are no examples of this in English, speech synthesis-by-rule programs often use a short burst of aspiration .ul and frication when simulating the opening of unvoiced stops. Separate amplitude controls are therefore needed for voicing and frication, but the former can be used for aspiration as well, with a "glottal excitation type" switch to indicate aspiration rather than voicing. .sh "5.5 Summary" .pp A resonance speech synthesizer consists of a vocal tract filter, excited by either a periodic pitch pulse or aspiration noise. In addition, a set of sibilant sounds must be provided. The vocal tract filter is dynamic, with three controllable resonances. These, coupled with some fixed spectral compensation, give it a fairly high order \(em about 10 complex poles are needed. Although several different sibilant sound types must be simulated, dynamical movement is less important in fricative sound spectra than for voiced and aspirated sounds because smooth transitions between one fricative and another are not important in speech. However, fricative timing and amplitude must be controlled rather precisely. .pp The speech synthesizer is controlled by several parameters. These include fundamental frequency (if voiced), amplitude of voicing, frequency of the first few \(em typically three \(em formants, aspiration amplitude, sibilance amplitude, and frequency of one (or more) sibilance filters. Additionally, if the synthesizer is a parallel one, parameters for the amplitudes of individual formants will need to be included. It may be that some control over formant bandwidths is provided too. Thus synthesizers have from eight up to about 20 parameters (Klatt, 1980, describes one with 20 parameters). .[ Klatt 1980 Software for a cascade/parallel formant synthesizer .] .pp The parameters are supplied to the synthesizer at regular intervals of time. For a 10-parameter synthesizer, the control can be thought of as a set of 10 graphs, each representing the time evolution of one parameter. They are usually called parameter .ul tracks, the terminology dating from the days when a track was painted on a glass slide for each parameter to provide dynamic control of the synthesizer (Lawrence, 1953). .[ Lawrence 1953 .] The pitch track is often called a pitch .ul contour; this is a common phonetician's usage. Do not confuse this with the everyday meaning of "contour" as a line joining points of equal height on a map \(em a pitch contour is just the time evolution of the pitch frequency. .pp For computer-controlled synthesizers, of course, the parameter tracks are sampled, typically every 5 to 20\ msec. The rate is determined by the need to generate fast amplitude transitions for nasals and stop consonants. Contrast it with the 125\ $mu$sec sampling period needed to digitize telephone-quality speech. The raw data rate for a 10-parameter synthesizer updated every 10 msec is 1,000 parameters/sec, or 6\ Kbit/s if each parameter is represented by 6\ bits. This is a substantial reduction over the 56\ Kbit/s needed for PCM representation. For speech synthesis by rule (Chapter 7), these parameter tracks are generated by a computer program from a phonetic (or English) version of the utterance, lowering the data rate by a further one or two orders of magnitude. .pp Filters for speech synthesizers can be implemented in either analogue or digital form. High-order filters are usually broken down into second-order sections in parallel or in series. A third possibility, which has not been discussed above, is to implement a single high-order filter directly. Finally, the action of formant filters can be synthesized in the time domain. This gives eight possibilities which are summarized in Table 5.2. .RF .in +0.5i .ta 2.1i +2.0i .nr x1 (\w'Analogue'/2) .nr x2 (\w'Digital'/2) \h'-\n(x1u'Analogue \h'-\n(x2u'Digital .nr x0 2.0i+(\w'Liljencrants (1968)'/2)+(\w'Morris and Paillet (1972)'/2) .nr x3 (\w'Liljencrants (1968)'/2) \h'-\n(x3u'\l'\n(x0u\(ul' .sp .nr x1 (\w'Rice (1976)'/2) .nr x2 (\w'Rabiner \fIet al\fR'/2) Series \h'-\n(x1u'Rice (1976) \h'-\n(x2u'Rabiner \fIet al\fR .nr x1 (\w'Liljencrants (1968)'/2) .nr x2 (\w'Holmes (1973)'/2) Parallel \h'-\n(x1u'Liljencrants (1968) \h'-\n(x2u'Holmes (1973) .nr x1 (\w'unpublished'/2) .nr x2 (\w'unpublished'/2 Time-domain \h'-\n(x1u'unpublished \h'-\n(x2u'unpublished .nr x1 (\w'\(em'/2) .nr x2 (\w'Morris and Paillet (1972)'/2) High-order filter \h'-\n(x1u'\(em \h'-\n(x2u'Morris and Paillet (1972) \h'-\n(x3u'\l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in-0.5i .FG "Table 5.2 Implementation options for resonance speech synthesizers" .[ Rice 1976 Byte .] .[ Rabiner Jackson Schafer Coker 1971 .] .[ Liljencrants 1968 .] .[ Holmes 1973 Influence of glottal waveform on naturalness .] .[ Morris and Paillet 1972 .] All but one have certainly been used as the basis for synthesis, and the table includes reference to published descriptions. .pp Each method has advantages and disadvantages. Series decomposition obviates the need for control over the amplitudes of individual formants, but does not allow synthesis of sounds which use the nasal tract as well as the oral one; for these are in parallel. Analogue implementation of series synthesizers is complicated by the need for higher-pole correction, and the fact that the gains at different frequencies can vary widely throughout the system. Higher-pole correction is not so important for digital synthesizers. Parallel decomposition eliminates some of these problems: higher-pole correction can be implemented individually for each formant. However, the formant amplitudes must be controlled rather precisely to simulate the vocal tract, which is essentially serial. Time-domain synthesis is associated with low hardware costs but does not easily allow proper control over the excitation sources. In particular, it cannot simulate dynamical movement of the spectrum during aspiration. Implementation of the entire vocal tract model as a single high-order filter, without breaking it down into individual formants in series or parallel, is attractive from the computational point of view because less arithmetic operations are required. It is best analysed in terms of linear predictive coding, which is the subject of the next chapter. .sh "5.6 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "5.7 Further reading" .pp Historically-minded readers should look at the early speech synthesizer designed by Lawrence (1953). This and other classic papers on the subject are reprinted in Flanagan and Rabiner (1973). A good description of a quite sophisticated parallel synthesizer can be found in Holmes (1973), above, and another of a switchable series/parallel one in Klatt (1980), who even includes a listing of the Fortran program that implements it. Here are some useful books on speech synthesizers. .LB "nn" .\"Fant-1960-1 .]- .ds [A Fant, G. .ds [D 1960 .ds [T Acoustic theory of speech production .ds [I Mouton .ds [C The Hague .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Fant really started the study of the vocal tract as an acoustic system, and this book marks the beginning of modern speech synthesis. .in-2n .\"Flanagan-1972-1 .]- .ds [A Flanagan, J.L. .ds [D 1972 .ds [T Speech analysis, synthesis, and perception (2nd, expanded, edition) .ds [I Springer Verlag .ds [C Berlin .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This book is the speech researcher's bible, and like the bible, it's not all that easy to read. However, it is an essential reference source for speech acoustics and speech synthesis (as well as for human speech perception). .in-2n .\"Flanagan-1973-2 .]- .ds [A Flanagan, J.L. .as [A " and Rabiner, L.R.(Editors) .ds [D 1973 .ds [T Speech synthesis .ds [I Dowsen, Hutchinson and Ross .ds [C Stroudsburg, Pennsylvania .nr [T 0 .nr [A 0 .nr [O 0 .][ 2 book .in+2n I recommended this book at the end of Chapter 1 as a collection of classic papers on the subject of speech synthesis and synthesizers. .in-2n .\"Holmes-1972-3 .]- .ds [A Holmes, J.N. .ds [D 1972 .ds [T Speech synthesis .ds [I Mills and Boom .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This little book, by one of Britain's foremost workers in the field, introduces the subject of speech synthesis and speech synthesizers. It has a particularly good discussion of parallel synthesizers. .in-2n .LE "nn" .EQ delim $$ .EN .CH "6 LINEAR PREDICTION OF SPEECH" .ds RT "Linear prediction of speech .ds CX "Principles of computer speech .pp The speech coding techniques which were discussed in Chapter 3 operate in the time domain, while the analysis and synthesis techniques of Chapters 4 and 5 are based in the frequency domain. Linear prediction is a relatively new method of speech analysis-synthesis, introduced in the early 1970's and used extensively since then, which is primarily a time-domain coding method but can be used to give frequency-domain parameters like formant frequency, bandwidth, and amplitude. .pp It has several advantages over other speech analysis techniques, and is likely to become increasingly dominant in speech output systems. As well as bridging the gap between time- and frequency-domain techniques, it is of equal value for both speech storage and speech synthesis, and forms an extremely convenient basis for speech-output systems which use high-quality stored speech for routine messages and synthesis from phonetics or text for unusual or exceptional conditions. Linear prediction can be used to separate the excitation source properties of pitch and amplitude from the vocal tract filter which governs phoneme articulation, or, in other words, to separate much of the prosodic from the segmental information. Hence it makes it easy to use stored segmentals with synthetic prosody, which is just what is needed to enhance the flexibility of stored speech by providing overall intonation contours for utterances formed by word concatenation (see Chapter 7). .pp The frequency-domain analysis technique of Fourier transformation necessarily involves approximation because it applies only to periodic waveforms, and so the artificial operation of windowing is required to suppress the aperiodicity of real speech. In contrast, the linear predictive technique, being a time-domain method, can \(em in certain forms \(em deal more rationally with aperiodic signals. .pp The basic idea of linear predictive coding is exactly the same as one form of adaptive differential pulse code modulation which was introduced briefly in Chapter 3. There it was noted that a speech sample $x(n)$ can be predicted quite closely by the previous sample $x(n-1)$. The prediction can be improved by multiplying the previous sample by a number, say $a sub 1$, which is adapted on a syllabic time-scale. This can be utilized for speech coding by transmitting only the prediction error .LB .EQ e(n)~=~~x(n)~-~a sub 1 x(n-1), .EN .LE and using it (and the value of $a sub 1$) to reconstitute the signal $x(n)$ at the receiver. It is worthwhile noting that exactly the same relationship was used for digital preemphasis in Chapter 4, with the value of $a sub 1$ being constant at about 0.9 \(em although the possibility of adapting it to take into account the difference between voiced and unvoiced speech was discussed. .pp An obvious extension is to use several past values of the signal to form the prediction, instead of just one. Different multipliers for each would be needed, so that the prediction error could be written as .LB .EQ e(n)~~ mark =~~x(n)~-~a sub 1 x(n-1)~-~a sub 2 x(n-2)~-~...~-~a sub p x(n-p) .EN .sp .EQ lineup =~~x(n)~-~~sum from k=1 to p ~a sub k x(n-k). .EN .LE The multipliers $a sub k$ should be adapted to minimize the error signal, and we will consider how to do this in the next section. It turns out that they must be re-calculated and transmitted on a time-scale that is rather faster than syllabic but much slower than the basic sampling rate: intervals of 10\-25\ msec are usually used (compare this with the 125\ $mu$sec sampling rate for telephone-quality speech). A configuration for high-order adaptive differential pulse code modulation is shown in Figure 6.1. .FC "Figure 6.1" .pp Figure 6.2 shows typical time waveforms for each of the ten coefficients over a 1-second stretch of speech. .FC "Figure 6.2" Notice that they vary much more slowly than, say, the speech waveform of Figure 3.5. .pp Turning the above relationship into $z$-transforms gives .LB .EQ E(z)~~=~~X(z)~-~~sum from k=1 to p ~a sub k z sup -k ~X(z)~~=~~(1~-~~ sum from k=1 to p ~a sub k z sup -k )~X(z). .EN .LE Rewriting the speech signal in terms of the error, .LB .EQ X(z)~~=~~1 over {1~-~~ sum ~a sub k z sup -k }~.~E(z) . .EN .LE .pp Now let us bring together some facts from the previous chapter which will allow the time-domain technique of linear prediction to be interpreted in terms of the frequency-domain formant model of speech. Recall that speech can be viewed as an excitation source passing through a vocal tract filter, followed by another filter to model the effect of radiation from the lips. The overall spectral levels can be reassigned as in Figure 5.1 so that the excitation source has a 0\ dB/octave spectral profile, and hence is essentially impulsive. Considering the vocal tract filter as a series connection of digital formant filters, its transfer function is the product of terms like .LB .EQ 1 over {1~-~b sub 1 z sup -1 ~+~b sub 2 z sup -2}~ , .EN .LE where $b sub 1$ and $b sub 2$ control the position and bandwidth of the formant resonances. The \-6\ dB/octave spectral compensation can be modelled by the first-order digital filter .LB .EQ 1 over {1~-~bz sup -1}~ . .EN .LE The product of all these terms, when multiplied out, will have the form .LB .EQ 1 over {1~-~c sub 1 z sup -1 ~-~c sub 2 z sup -2 ~-~...~-~ c sub q z sup -q }~ , .EN .LE where $q$ is twice the number of formants plus one, and the $c$'s are calculated from the positions and bandwidths of the formant resonances and the spectral compensation parameter. Hence the $z$-transform of the speech is .LB .EQ X(z)~=~~1 over {1~-~~ sum from k=1 to q ~c sub k z sup -k }~.~I(z) , .EN .LE where $I(z)$ is the transform of the impulsive excitation. .pp This is remarkably similar to the linear prediction relation given earlier! If $p$ and $q$ are the same, then the linear predictive coefficients $a sub k$ form a $p$'th order polynomial which is the same as that obtained by multiplying together the second-order polynomials representing the individual formants (together with the first-order one for spectral compensation). Furthermore, the predictive error $E(z)$ can be identified with the impulsive excitation $I(z)$. This raises the very interesting possibility of parametrizing the error signal by its frequency and amplitude \(em two relatively slowly-varying quantities \(em instead of transmitting it sample-by-sample (at an 8\ kHz rate). This is how linear prediction separates out the excitation properties of the source from the vocal tract filter: the source parameters can be derived from the error signal and the vocal tract filter is represented by the linear predictive coefficients. Figure 6.3 shows how this can be used for speech transmission. .FC "Figure 6.3" Note that .ul no signals need now be transmitted at the speech sampling rate; for the source parameters vary relatively slowly. This leads to an extremely low data rate. .pp Practical linear predictive coding schemes operate with a value of $p$ between 10 and 15, corresponding approximately to 4-formant and 7-formant synthesis respectively. The $a sub k$'s are re-calculated every 10 to 25\ msec, and transmitted to the receiver. Also, the pitch and amplitude of the speech are estimated and transmitted at the same rate. If the speech is unvoiced, there is no pitch value: an "unvoiced flag" is transmitted instead. Because the linear predictive coefficients are intimately related to formant frequencies and bandwidths, a "frame rate" in the region of 10 to 25\ msec is appropriate because this approximates the maximum rate at which acoustic events happen in speech production. .pp At the receiver, the excitation waveform is reconstituted. For voiced speech, it is impulsive at the specified frequency and with the specified amplitude, while for unvoiced speech it is random, with the specified amplitude. This signal $e(n)$, together with the transmitted parameters $a sub 1$, ..., $a sub p$, is used to regenerate the speech waveform by .LB .EQ x(n)~=~~e(n)~+~~sum from k=1 to p ~a sub k x(n-k) , .EN .LE \(em which is the inverse of the transmitter's formula for calculating $e(n)$, namely .LB .EQ e(n)~=~~x(n)~-~~sum from k=1 to p ~a sub k x(n-k) . .EN .LE This relies on knowing the past $p$ values of the speech samples. Many systems set these past values to zero at the beginning of each pitch cycle. .pp Linear prediction can also be used for speech analysis, rather than for speech coding, as shown in Figure 6.4. .FC "Figure 6.4" Instead of transmitting the coefficients $a sub k$, they are used to determine the formant positions and bandwidths. We saw above that the polynomial .LB .EQ 1~-~a sub 1 z sup -1 ~-~a sub 2 z sup -2 ~-~...~-~a sub p z sup -p , .EN .LE when factored into a product of second-order terms, gives the formant characteristics (as well as the spectral compensation term). Factoring is equivalent to finding the complex roots of the polynomial, and this is fairly demanding computationally \(em especially if done at a high rate. Consequently, peak-picking algorithms are sometimes used instead. The absolute value of the polynomial gives the frequency spectrum of the vocal tract filter, and the formants appear as peaks \(em just as they do in cepstrally smoothed speech (see Chapter 4). .pp The chief deficiency in the linear predictive method, whether it is used for speech coding or for speech analysis, is that \(em like a series synthesizer \(em it implements an all-pole model of the vocal tract. We mentioned in Chapter 5 that this is rather simplistic, especially for nasalized sounds which involve a cavity in parallel with the oral one. Some research has been done on incorporating zeros into a linear predictive model, but it complicates the problem of calculating the parameters enormously. For most purposes people seem to be able to live with the limitations of the all-pole model. .sh "6.1 Linear predictive analysis" .pp The key problem in linear predictive coding is to determine the values of the coefficients $a sub 1$, ..., $a sub p$. If the error signal is to be transmitted on a sample-by-sample basis, as it is in adaptive differential pulse code modulation, then it can be most economically encoded if its mean power is as small as possible. Thus the coefficients are chosen to minimize .LB .EQ sum ~e(n) sup 2 .EN .LE over some period of time. The period of time used is related to the frame rate at which the coefficients are transmitted or stored, although there is no need to make it exactly the same as one frame interval. As mentioned above, the frame size is usually chosen to be in the region of 10 to 25\ msec. Some schemes minimize the error signal over as few as 30 samples (corresponding to 3\ msec at a 10\ kHz sampling rate). Others take longer; up to 250 samples (25\ msec). .pp However, if the error signal is to be considered as impulsive and parametrized by its frequency and amplitude before transmission, or if the coefficients $a sub k$ are to be used for spectral calculations, then it is not immediately obvious how the coefficients should be calculated. In fact, it is still best to choose them to minimize the above sum. This is at least plausible, for an impulsive excitation will have a rather small mean power \(em most of the samples are zero. It can be justified theoretically in terms of .ul spectral whitening, for it can be shown that minimizing the mean-squared error produces an error signal whose spectrum is maximally flat. Now the only two waveforms whose spectra are absolutely flat are a single impulse and white noise. Hence if the speech is voiced, minimizing the mean-squared error will lead to an error signal which is as nearly impulsive as possible. Provided the time-frame for minimizing is short enough, the impulse will correspond to a single excitation pulse. If the speech is unvoiced, minimization will lead to an error signal which is as nearly white noise as possible. .pp How does one choose the linear predictive coefficients to minimize the mean-squared error? The total squared prediction error is .LB .EQ M~=~~sum from n ~e(n) sup 2~~=~~sum from n ~[x(n)~-~ sum from k=1 to p ~a sub k x sub n-k ] sup 2 , .EN .LE leaving the range of summation unspecified for the moment. To minimize $M$ by choice of the coefficients $a sub j$, differentiate with respect to each of them and set the resulting derivatives to zero. .LB .EQ dM over {da sub j} ~~=~~-2 sum from n ~x(n-j)[x(n)~-~~ sum from k=1 to p ~a sub k x(n-k)]~~=~0~, .EN .LE so .LB .EQ sum from k=1 to p ~a sub k ~ sum from n ~x(n-j)x(n-k)~~=~~ sum from n ~x(n)x(n-j)~~~~j~=~1,~2,~...,~p. .EN .LE .pp This is a set of $p$ linear equations for the $p$ unknowns $a sub 1$, ..., $a sub p$. Solving it is equivalent to inverting a $p times p$ matrix. This job must be repeated at the frame rate, and so if real-time operation is desired quite a lot of calculation is needed. .rh "The autocorrelation method." So far, the range of the $n$-summation has been left open. The coefficients of the matrix equation have the form .LB .EQ sum from n ~x(n-j)x(n-k). .EN .LE If a doubly-infinite summation were made, with $x(n)$ being defined as zero whenever $n<0$, we could make use of the fact that .sp .ce .EQ sum from {n=- infinity} to infinity ~x(n-j)x(n-k)~=~~ sum from {n=- infinity} to infinity ~x(n-j+1)x(n-k+1)~=~...~=~~ sum from {n=- infinity} to infinity ~x(n)x(n+j-k) .EN .sp to simplify the matrix equation. This just states that the autocorrelation of an infinite sequence depends only on the lag at which it is computed, and not on absolute time. .pp Defining $R(m)$ as the autocorrelation at lag $m$, that is, .LB .EQ R(m)~=~ sum from n ~x(n)x(n+m), .EN .LE the matrix equation becomes .LB .ne7 .nf .EQ R(0)a sub 1 ~+~R(1)a sub 2 ~+~R(2)a sub 3 ~+~...~~=~R(1) .EN .EQ R(1)a sub 1 ~+~R(0)a sub 2 ~+~R(1)a sub 3 ~+~...~~=~R(2) .EN .EQ R(2)a sub 1 ~+~R(1)a sub 2 ~+~R(0)a sub 3 ~+~...~~=~R(3) .EN .EQ etc .EN .fi .LE An elegant method due to Durbin and Levinson exists for solving this special system of equations. It requires much less computational effort than is generally needed for symmetric matrix equations. .pp Of course, an infinite range of summation can not be used in practice. For one thing, the power spectrum is changing, and only the data from a short time-frame should be used for a realistic estimate of the optimum linear predictive coefficients. Hence a windowing procedure, .LB .EQ x(n) sup * ~=~w sub n x(n), .EN .LE is used to reduce the signal to zero outside a finite range of interest. Windows were discussed in Chapter 4 from the point of view of Fourier analysis of speech signals, and the same sort of considerations apply to choosing a window for linear prediction. .pp This is known as the .ul autocorrelation method of computing prediction parameters. Typically a window of 100 to 250 samples is used for analysis of one frame of speech. .rh "Algorithm for the autocorrelation method." The algorithm for obtaining linear prediction coefficients by the autocorrelation method is quite simple. It is straightforward to compute the matrix coefficients $R(m)$ from the speech samples and window coefficients. The Durbin-Levinson method of solving matrix equations operates directly on this $R$-vector to produce the coefficient vector $a sub k$. The complete procedure is given as Procedure 6.1, and is shown diagrammatically in Figure 6.5. .FC "Figure 6.5" .RF .fi .na .nh .ul const N=256; p=15; .ul type svec = .ul array [0..N\-1] .ul of real; cvec = .ul array [1..p] .ul of real; .sp .ul procedure autocorrelation(signal: vec; window: svec; .ul var coeff: cvec); .sp {computes linear prediction coefficients by autocorrelation method in coeff[1..p]} .sp .ul var R, temp: .ul array [0..p] .ul of real; n: [0..N\-1]; i,j: [0..p]; E: real; .sp .ul begin {window the signal} .in+6n .ul for n:=0 .ul to N\-1 .ul do signal[n] := signal[n]*window[n]; .sp {compute autocorrelation vector} .br .ul for i:=0 .ul to p .ul do begin .in+2n R[i] := 0; .br .ul for n:=0 .ul to N\-1\-i .ul do R[i] := R[i] + signal[n]*signal[n+i] .in-2n .ul end; .sp {solve the matrix equation by the Durbin-Levinson method} .br E := R[0]; .br coeff[1] := R[1]/E; .br .ul for i:=2 .ul to p .ul do begin .in+2n E := (1\-coeff[i\-1]*coeff[i\-1])*E; .br coeff[i] := R[i]; .br .ul for j:=1 .ul to i\-1 .ul do coeff[i] := coeff[i] \- R[i\-j]*coeff[j]; .br coeff[i] := coeff[i]/E; .br .ul for j:=1 .ul to i\-1 .ul do temp[j] := coeff[j] \- coeff[i]*coeff[i\-j]; .br .ul for j:=1 .ul to i\-1 .ul do coeff[j] := temp[j] .in-2n .ul end .in-6n .ul end. .nf .FG "Procedure 6.1 Pascal algorithm for the autocorrelation method" .pp This algorithm is not quite as efficient as it might be, for some multiplications are repeated during the calculation of the autocorrelation vector. Blankinship (1974) shows how the number of multiplications can be reduced by about half. .[ Blankinship 1974 .] .pp If the algorithm is performed in fixed-point arithmetic (as it often is in practice because of speed considerations), some scaling must be done. The maximum and minimum values of the windowed signal can be determined within the window calculation loop, and one extra pass over the vector will suffice to scale it to maximum significance. (Incidentally, if all sample values are the same the procedure cannot produce a solution because $E$ becomes zero, and this can easily be checked when scaling.) .pp The absolute value of the $R$-vector has no significance, and since $R(0)$ is always the greatest element, this can be set to the largest fixed-point number and the other $R$'s scaled down appropriately after they have been calculated. These scaling operations are shown as dashed boxes in Figure 6.5. $E$ decreases monotonically as the computation proceeds, so it is safe to initialize it to $R(0)$ without extra scaling. The remainder of the scaling is straightforward, with the linear prediction coefficients $a sub k$ appearing as fractions. .rh "The covariance method." One of the advantages of linear predictive methods that was promised earlier was that it allows us to escape from the problem of windowing. To do this, we must abandon the requirement that the coefficients of the matrix equation have the symmetry property of autocorrelations. Instead, suppose that the range of $n$-summation uses a fixed number of elements, say N, starting at $n=h$, to estimate the prediction coefficients between sample number $h$ and sample number $h+N$. .pp This leads to the matrix equation .LB .EQ sum from k=1 to p ~a sub k sum from n=h to h+N-1 ~x(n-j)x(n-k) ~~=~~ sum from n=h to h+N-1 ~x(n)x(n-j)~~~~j~=~1,~2,~...,~p. .EN .LE Alternatively, we could write .LB .EQ sum from k=1 to p ~a sub k ~ Q sub jk sup h~~=~~Q sub 0j sup h ~~~~j~=~1,~2,~...,~p; .EN .LE where .LB .EQ Q sub jk sup h~~=~~sum from n=h to h+N-1 ~x(n-j)x(n-k). .EN .LE Note that some values of $x(n)$ outside the range $h ~ <= ~ n ~ < ~ h+N$ are required: these are shown diagrammatically in Figure 6.6. .FC "Figure 6.6" .pp Now $Q sub jk sup h ~=~ Q sub kj sup h$, so the equation has a diagonally symmetric matrix; and in fact the matrix $Q sup h$ can be shown to be positive semidefinite \(em and is almost always positive definite in practice. Advantage can be taken of these facts to provide a computationally efficient method for solving the equation. According to a result called Cholesky's theorem, a positive definite symmetric matrix $Q$ can be factored into the form $Q ~ = ~ LL sup T$, where $L$ is a lower triangular matrix. This leads to an efficient solution algorithm. .pp This method of computing prediction coefficients has become known as the .ul covariance method. It does not use windowing of the speech signal, and can give accurate estimates of the prediction coefficients with a smaller analysis frame than the autocorrelation method. Typically, 50 to 100 speech samples might be used to estimate the coefficients, and they are re-calculated every 100 to 250 samples. .rh "Algorithm for the covariance method." An algorithm for the covariance method is given in Procedure 6.2, .RF .fi .na .nh .ul const N=100; p=15; .ul type svec = .ul array [\-p..N\-1] .ul of real; cvec = .ul array [1..p] .ul of real; .sp .ul procedure covariance(signal: svec; .ul var coeff: cvec); .sp {computes linear prediction coefficients by covariance method in coeff[1..p]} .sp .ul var Q: .ul array [0..p,0..p] .ul of real; n: [0..N\-1]; i,j,r: [0..p]; X: real; .sp .ul begin {calculate upper-triangular covariance matrix in Q} .in+6n .ul for i:=0 .ul to p .ul do .in+2n .ul for j:=i .ul to p .ul do begin .in+2n Q[i,j]:=0; .br .ul for n:=0 .ul to N\-1 .ul do .in+2n Q[i,j] := Q[i,j] + signal[n\-i]*signal[n\-j] .in-2n .in-2n .ul end; .in-2n .sp {calculate the square root of Q} .br .ul for r:=2 .ul to p .ul do .in+2n .ul begin .in+2n .ul for i:=2 .ul to r\-1 .ul do .in+2n .ul for j:=1 .ul to i\-1 .ul do .in+2n Q[i,r] := Q[i,r] \- Q[j,i]*Q[j,r]; .in-2n .ul for j:=1 .ul to r\-1 .ul do .in+2n .ul begin .in+2n X := Q[j,r]; .br Q[j,r] := Q[j,r]/Q[j,i]; .br Q[r,r] := Q[r,r] \- Q[j,r]*X .in-2n .ul end .in-2n .in-2n .in-2n .ul end; .in-2n .sp {calculate coeff[1..p]} .br .ul for r:=2 .ul to p .ul do .in+2n .ul for i:=1 .ul to r\-1 .ul do Q[0,r] := Q[0,r] \- Q[i,r]*Q[0,i]; .in-2n .ul for r:=1 .ul to p .ul do Q[0,r] := Q[0,r]/Q[r,r]; .br .ul for r:=p\-1 .ul downto 1 .ul do .in+2n .ul for i:=r+1 .ul to p .ul do Q[0,r] := Q[0,r] \- Q[r,i]*Q[0,i]; .in-2n .ul for r:=1 .ul to p .ul do coeff[r] := Q[0,r] .in-6n .ul end. .nf .FG "Procedure 6.2 Pascal algorithm for the covariance method" and is shown diagrammatically in Figure 6.7. .FC "Figure 6.7" The algorithm shown is not terribly efficient from a computation and storage point of view, although it is workable. For one thing, it uses the obvious method for computing the covariance matrix by calculating .EQ Q sub 01 sup h , .EN .EQ Q sub 02 sup h , ~ ..., .EN .EQ Q sub 0p sup h , .EN .EQ Q sub 11 sup h , ..., .EN in turn, which repeats most of the multiplications $p$ times \(em not an efficient procedure. A simple alternative is to precompute the necessary multiplications and store them in a $(N+h) times (p+1)$ diagonally symmetric table, but even apart from the extra storage required for this, the number of additions which must be performed subsequently to give the $Q$'s is far larger than necessary. It is possible, however, to write a procedure which is both time- and space-efficient (Witten, 1980). .[ Witten 1980 Algorithms for linear prediction .] .pp The scaling problem is rather more tricky for the covariance method than for the autocorrelation method. The $x$-vector should be scaled initially in the same way as before, but now there are $p+1$ diagonal elements of the covariance matrix, any of which could be the greatest element. Of course, .LB .EQ Q sub jk ~~ <= ~~ Max ( Q sub 11 , Q sub 22 , ..., Q sub pp ), .EN .LE but despite the considerable communality in the summands of the diagonal elements, there are no .ul a priori bounds on the ratios between them. .pp The only way to scale the $Q$ matrix properly is to calculate each of its $p$ diagonal elements and use the greatest as a scaling factor. Alternatively, the fact that .LB .EQ Q sub jk ~~ <= ~~ N times Max( x sub n sup 2 ) .EN .LE can be used to give a bound for scaling purposes; however, this is usually a rather conservative bound, and as $N$ is often around 100, several bits of significance will be lost. .pp Scaling difficulties do not cease when $Q$ has been determined. It is possible to show that the elements of the lower-triangular matrix $L$ which represents the square root of $Q$ are actually .ul unbounded. In fact there is a slightly different variant of the Cholesky decomposition algorithm which guarantees bounded coefficients but suffers from the disadvantage that it requires square roots to be taken (Martin .ul et al, 1965). .[ Martin Peters Wilkinson 1965 .] However, experience with the method indicates that it is rare for the elements of $L$ to exceed 16 times the maximum element of $Q$, and the possibility of occasional failure to adjust the coefficients may be tolerable in a practical linear prediction system. .rh "Comparison of autocorrelation and covariance analysis." There are various factors which should be taken into account when deciding whether to use the autocorrelation or covariance method for linear predictive analysis. Furthermore, there is a rather different technique, called the "lattice method", which will be discussed shortly. The autocorrelation method involves windowing, which means that in practice a rather longer stretch of speech should be used for analysis. We have illustrated this by setting $N$=256 in the autocorrelation algorithm and 100 in the covariance one. Offsetting the extra calculation that this entails is the fact that the Durbin-Levinson method of inverting a matrix is much more efficient than Cholesky decomposition. In practice, this means that similar amounts of computation are needed for each method \(em a detailed comparison is made in Witten (1980). .[ Witten 1980 Algorithms for linear prediction .] .pp A factor which weighs against the covariance method is the difficulty of scaling intermediate quantities within the algorithm. The autocorrelation method can be implemented quite satisfactorily in fixed-point arithmetic, and this makes it more suitable for hardware implementation. Furthermore, serious instabilities sometimes arise with the covariance method, whereas it can be shown that the autocorrelation one is always stable. Nevertheless, the approximations inherent in the windowing operation, and the smearing effect of taking a larger number of sample points, mean that covariance-method coefficients tend to represent the speech more accurately, if they can be obtained. .pp One way of using the covariance method which has proved to be rather satisfactory in practice is to synchronize the analysis frame with the beginning of a pitch period, when the excitation is strongest. Pitch synchronous techniques were discussed in Chapter 4 in the context of discrete Fourier transformation of speech. The snag, of course, is that pitch peaks do not occur uniformly in time, and furthermore it is difficult to estimate their locations precisely. .sh "6.2 Linear predictive synthesis" .pp If the linear predictive coefficients and the error signal are available, it is easy to regenerate the original speech by .LB .EQ x(n)~=~~e(n)~+~~ sum from k=1 to p ~a sub k x(n-k) . .EN .LE If the error signal is parametrized into the sound source type (voiced or unvoiced), amplitude, and pitch (if voiced), it can be regenerated by an impulse repeated at the appropriate pitch frequency (if voiced), or white noise (if unvoiced). .pp However, it may be that the filter represented by the coefficients $a sub k$ is unstable, causing the output speech signal to oscillate wildly. In fact, it is only possible for the covariance method to produce an unstable filter, and not the autocorrelation method \(em although even with the latter, truncation of the $a sub k$'s for transmission may turn a stable filter into an unstable one. Furthermore, the coefficients $a sub k$ are not suitable candidates for quantization, because small changes in them can have a dramatic effect on the characteristics of the synthesis filter. .pp Both of these problems can be solved by using a different set of numbers, called .ul reflection coefficients, for quantization and transmission. Thus, for example, in Figures 6.1 and 6.3 these reflection coefficients could be derived at the transmitter, quantized, and used by the receiver to reproduce the speech waveform. They can be related to reflection and transmission parameters at the junctions of an acoustic tube model of the vocal tract; hence the name. Procedure 6.3 shows an algorithm for calculating the reflection coefficients from the filter coefficients $a sub k$. .RF .fi .na .nh .ul const p=15; .ul type cvec = .ul array [1..p] .ul of real; .sp .ul procedure reflection(coeff: cvec; .ul var refl: cvec); .sp {computes reflection coefficients in refl[1..p] corresponding to linear prediction coefficients in coeff[1..p]} .sp .ul var temp: cvec; i, m: 1..p; .sp .ul begin .in+6n .ul for m:=p .ul downto 1 .ul do begin .in+2n refl[m] := coeff[m]; .br .ul for i:=1 .ul to m\-1 .ul do temp[i] := coeff[i]; .br .ul for i:=1 .ul to m\-1 .ul do .ti+2n coeff[i] := .ti+4n (coeff[i] + refl[m]*temp[m\-i]) / (1 \- refl[m]*refl[m]); .in-2n .ul end .in-6n .ul end. .nf .MT 2 Procedure 6.3 Pascal algorithm for producing reflection coefficients from filter coefficients .TE .pp Although we will not go into the theoretical details here, reflection coefficients are bounded by $+-$1 for stable filters, and hence form a useful test for stability. Having a limited range makes them easy to quantize for transmission, and in fact they behave better under quantization than do the filter coefficients. One could resynthesize speech from reflection coefficients by first converting them to filter coefficients and using the synthesis method described above. However, it is natural to seek a single-stage procedure which can regenerate speech directly from reflection coefficients. .pp Such a procedure does exist, and is called a .ul lattice filter. Figure 6.8 shows one form of lattice for speech synthesis. .FC "Figure 6.8" The error signal (whether transmitted or synthesized) enters at the upper left-hand corner, passes along the top forward signal path, being modified on the way, to give the output signal at the right-hand side. Then it passes back through a chain of delays along the bottom, backward, path, and is used to modify subsequent forward signals. Finally it is discarded at the lower left-hand corner. .pp There are $p$ stages in the lattice structure of Figure 6.8, where $p$ is the order of the linear predictive filter. Each stage involves two multiplications by the appropriate reflection coefficients, one by the backward signal \(em the result of which is added into the forward path \(em and the other by the forward signal \(em the result of which is subtracted from the backward path. Thus the number of multiplications is twice the order of the filter, and hence twice as many as for the realization using coefficients $a sub k$. If the labour necessary to turn the reflection coefficients into $a sub k$'s is included, the computational load becomes the same. Moreover, since the reflection coefficients need fewer quantization bits than the $a sub k$'s (for a given speech quality), the word lengths are smaller in the lattice realization. .pp The advantages of the lattice method of synthesis over direct evaluation of the prediction using filter coefficients $a sub k$, then, are: .LB .NP the reflection coefficients are used directly .NP the stability of the filter is obvious from the reflection coefficient values .NP the system is more tolerant to quantization errors in fixed-point implementations. .LE Although it may seem unlikely that an unstable filter would be produced by linear predictive analysis, instability is in fact a real problem in non-lattice implementations. For example, coefficients are often interpolated at the receiver, to allow longer frame times and smooth over sudden transitions, and it is quite likely that an unstable configuration is obtained when interpolating filter coefficients between two stable configurations. This cannot happen with reflection coefficients, however, because a necessary and sufficient condition for stability is that all coefficients lie in the interval $(-1,+1)$. .sh "6.3 Lattice filtering" .pp Lattice filters are an important new method of linear predictive .ul analysis as well as synthesis, and so it is worth considering the theory behind them a little further. .rh "Theory of the lattice synthesis filter." Figure 6.9 shows a single stage of the synthesis lattice given earlier. .FC "Figure 6.9" There are two signals at each side of the lattice, and the $z$-transforms of these have been labelled $X sup +$ and $X sup -$ at the left-hand side and $Y sup +$ and $Y sup -$ at the right-hand side. The direction of signal flow is forwards along the upper ("positive") path and backwards along the lower ("negative") one. .pp The signal flows show that the following two relationships hold: .LB .EQ Y sup + ~=~~ X sup + ~+~ k z sup -1 Y sup - ~~~~~~ .EN for the forward (upper) path .br .EQ X sup - ~ =~ -kY sup + ~+~ z sup -1 Y sup - ~~~~~~~ .EN \h'-\w'\-'u'for the backward (lower) path. .LE Re-arranging the first equation yields .LB .EQ X sup + ~ =~~ Y sup + ~-~ k z sup -1 Y sup - , .EN .LE and so we can describe the function of the lattice by a single matrix equation: .LB .ne4 .EQ left [ matrix {ccol {X sup + above X sup -}} right ] ~~=~~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {Y sup + above Y sup -}} right ] ~ . .EN .LE It would be nice to be able to call this an input-output equation, but it is not; for the input signals to the lattice stage are $X sup +$ and $Y sup -$, and the outputs are $X sup -$ and $Y sup +$. We have written it in this form because it allows a multi-stage lattice to be described by cascading these matrix equations. .pp A single-stage lattice filter has $Y sup +$ and $Y sup -$ connected together, forming its output (call this $X sub output$), while the input is $X sup +$ ($X sub input$). Hence the input is related to the output by .LB .EQ left [ matrix {ccol {X sub input above \(sq }} right ] ~~ = ~~ left [ matrix {ccol {1 above -k} ccol {-k z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {X sub output above X sub output}} right ] ~ , .EN .LE so .LB .EQ X sub input ~ = ~~ (1~-~ k z sup -1 )~X sub output , .EN .LE or .LB .EQ {X sub output} over {X sub input} ~~=~~ 1 over {1~-~ k sub 1 z sup -1} ~ . .EN .LE (The symbol \(sq is used here and elsewhere to indicate an unimportant element of a vector or matrix.) This certainly has the form of a linear predictive synthesis filter, which is .LB .EQ X(z) over E(z) ~~=~~ 1 over {1~-~~ sum from k=1 to p ~a sub k z sup -k}~~=~~ 1 over {1~-~a sub 1 z sup -1 } ~~~~~~ .EN when $p=1$. .LE .pp The behaviour of a second-order lattice filter, shown in Figure 6.10, can be described by .LB .ne4 .EQ left [ matrix {ccol {X sub 3 sup + above X sub 3 sup -}} right ] ~~ = ~~ left [ matrix {ccol {1 above -k sub 2 } ccol {-k sub 2 z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {X sub 2 sup + above X sub 2 sup -}} right ] .EN .sp .ne4 .EQ left [ matrix {ccol {X sub 2 sup + above X sub 2 sup -}} right ] ~~ = ~~ left [ matrix {ccol {1 above -k sub 1 } ccol {-k sub 1 z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {X sub 1 sup + above X sub 1 sup -}} right ] .EN .LE with .LB .ne3 .EQ X sub 3 sup + ~=~X sub input .EN .br .EQ X sub 1 sup + ~=~ X sub 1 sup - ~=~ X sub output . .EN .LE .FC "Figure 6.10" $X sub 2 sup +$ and $X sub 2 sup -$ can be eliminated by substituting the second equation into the first, which yields .LB .EQ left [ matrix {ccol {X sub input above \(sq }} right ] ~~ mark = ~~ left [ matrix {ccol {1 above -k sub 2 } ccol {-k sub 2 z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {1 above -k sub 1 } ccol {-k sub 1 z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {X sub output above X sub output}} right ] .EN .sp .sp .EQ lineup = ~~ left [ matrix {ccol {1+k sub 1 k sub 2 z sup -1 above \(sq } ccol { -k sub 1 z sup -1 -k sub 2 z sup -2 above \(sq }} right ] ~ left [ matrix {ccol {X sub output above X sub output}} right ] ~ . .EN .LE This leads to an input-output relationship .LB .EQ {X sub output} over {X sub input} ~~ = ~~ 1 over {1~+~k sub 1 (k sub 2 -1)z sup -1 ~-~k sub 2 z sup -2} ~ , .EN .LE which has the required form, namely .LB .EQ 1 over {1~-~~ sum from k=1 to p ~a sub k z sup -k } ~~~~~~ (p=2) .EN .LE when .LB .EQ a sub 1 ~=~-k sub 1 (k sub 2 -1) .EN .br .EQ a sub 2 ~=~k sub 2. .EN .LE .pp A third-order filter is described by .LB .EQ left [ matrix {ccol {X sub input above \(sq }} right ] ~~ = ~~ left [ matrix {ccol {1 above -k sub 3 } ccol {-k sub 3 z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {1 above -k sub 2 } ccol {-k sub 2 z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {1 above -k sub 1 } ccol {-k sub 1 z sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {X sub output above X sub output}} right ] ~ , .EN .LE and brave souls can verify that this gives an input-output relationship .LB .EQ {X sub output} over {X sub input} ~~ = ~~ 1 over {1~+~[k sub 2 k sub 3 + k sub 1 (1-k sub 2 )] z sup -1 ~+~ [k sub 1 k sub 3 (1-k sub 2 ) -k sub 2 ] z sup -2 ~-~ k sub 3 z sup -3 } ~ . .EN .LE It is fairly obvious that a $p$'th order lattice filter will give the required all-pole $p$'th order synthesis form, .LB .EQ 1 over { 1~-~~ sum from k=1 to p ~a sub k z sup -k } ~ . .EN .LE .pp We have not shown that the algorithm given in Procedure 6.3 for producing reflection coefficients from filter coefficients gives those values for $k sub i$ which are necessary to make the lattice filter equivalent to the ordinary synthesis filter. However, this is the case, and it is easy to verify by hand for the first, second, and third-order cases. .rh "Different lattice configurations." The lattice filters of Figures 6.8, 6.9, and 6.10 have two multipliers per section. This is called a "two-multiplier" configuration. However, there are other configurations which achieve the same effect, but require different numbers of multiplies. Figure 6.11 shows one-multiplier and four-multiplier configurations, along with the familiar two-multiplier one. .FC "Figure 6.11" It is easy to verify that the three configurations can be modelled in matrix terms by .LB .ne4 $ left [ matrix {ccol {X sup + above X sup -}} right ] ~~ = ~~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {Y sup + above Y sup -}} right ] $ two-multiplier configuration .sp .sp .ne4 $ left [ matrix {ccol {X sup + above X sup -}} right ] ~~ = ~~ left [ {1-k over 1+k} right ] sup 1/2 ~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {Y sup + above Y sup -}} right ] $ one-multiplier configuration .sp .sp .ne4 $ left [ matrix {ccol {X sup + above X sup -}} right ] ~~ = ~~ 1 over {(1-k sup 2) sup 1/2} ~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {Y sup + above Y sup -}} right ] $ four-multiplier configuration. .LE Each of the three has the same frequency-domain response, although a different constant factor is involved in each case. The effect of this can be annulled by performing a single multiply operation on the output of a complete lattice chain. The multiplier has the form .LB .EQ left [ {1 - k sub p} over {1 + k sub p} ~.~ {1 - k sub p-1} over {1 + k sub p-1} ~.~...~.~ {1 - k sub 1} over {1 + k sub 1} right ] sup 1/2 .EN .sp .LE for single-multiplier lattices, and .LB .EQ left [ 1 over {1 - k sub p sup 2} ~.~ 1 over {1 - k sub p-1 sup 2} ~.~...~.~ 1 over {1 - k sub 1 sup 2} right ] sup 1/2 .EN .LE for four-multiplier lattices, where the reflection coefficients in the lattice are $k sub p$, $k sub p-1$, ..., $k sub 1$. .pp There are important differences between these three configurations. If multiplication is time-consuming, the one-multiplier model has obvious computational advantages over the other two methods. However, the four-multiplier structure behaves substantially better in finite word-length implementations. It is easy to show that, with this configuration, .LB .EQ (X sup - ) sup 2 ~+~ (Y sup + ) sup 2 ~~ = ~~ (X sup + ) sup 2 ~+~ (z sup -1 Y sup - ) sup 2 , .EN .LE \(em a relationship which suggests that the "energy" in the the input signals, namely $X sup +$ and $Y sup -$, is preserved in the output signals, $X sup -$ and $Y sup +$. Notice that care must be taken with the $z$-transforms, since squaring is a non-linear operation. $(z sup -1 Y sup - ) sup 2$ means the square of the previous value of $Y sup -$, which is not the same as $z sup -2 (Y sup - ) sup 2$. .pp It has been shown (Gray and Markel, 1975) that the four-multiplier configuration has some stability properties which are not shared by other digital filter structures. .[ Gray Markel 1975 Normalized digital filter structure .] When a linear predictive filter is used for synthesis, the parameters of the filter \(em the $k$-parameters in the case of lattice filters, and the $a$-parameters in the case of direct ones \(em change with time. It is usually rather difficult to guarantee stability in the case of time-varying filter parameters, but some guarantees can be made for a chain of four-multiplier lattices. Furthermore, if the input is a discrete delta function, the cumulative energies at each stage of the lattice are the same, and so maximum dynamic range will be achieved for the whole filter if each section is implemented with the same word size. .rh "Lattice analysis." It is quite easy to construct a filter which is inverse to a single-stage lattice. The structure of Figure 6.12(a) does the job. (Ignore for a moment the dashed lines connecting Figure 6.12(a) and (b).) Its matrix transfer function is .FC "Figure 6.12" .LB .ne4 $ left [ matrix {ccol {Y sup + above Y sup -}} right ] ~~=~~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {X sup + above X sup -}} right ] $ analysis lattice (Figure 6.12(a)). .LE Notice that this is exactly the same as the transfer function of the synthesis lattice of Figure 6.9, which is reproduced in Figure 6.12(b), except that the $X$'s and $Y$'s are reversed: .LB .ne4 $ left [ matrix {ccol {X sup + above X sup -}} right ] ~~=~~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {Y sup + above Y sup -}} right ] $ synthesis lattice (Figure 6.12(b)), .LE or, in other words, .LB .ne4 $ left [ matrix {ccol {Y sup + above Y sup -}} right ] ~~ = ~~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] sup -1 ~ left [ matrix {ccol {X sup + above X sup -}} right ] $ synthesis lattice (Figure 6.12(b)). .LE Hence if the filters of Figures 6.12(a) and (b) were connected together as shown by the dashed lines, they would cancel each other out, and the overall transfer would be unity: .LB .ne4 .EQ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] ~ left [ matrix {ccol {1 above -k} ccol {-kz sup -1 above z sup -1}} right ] sup -1 ~~ = ~~ left [ matrix {ccol {1 above 0} ccol {0 above 1}} right ] ~ . .EN .LE Actually, such a connection is not possible in physical terms, for although the upper paths can be joined together the lower ones can not. The right-hand lower point of Figure 6.12(a) is an .ul output terminal, and so is the left-hand lower one of Figure 6.12(b)! However, there is no need to envisage a physical connection of the lower paths. It is sufficient for cancellation just to assume that the signals at both of the points turn out to be the same. .pp And they do. The general case of a $p$-stage analysis lattice connected to a $p$-stage synthesis lattice is shown in Figure 6.13. .FC "Figure 6.13" Notice that the forward and backward paths are connected together at both of the extreme ends of the system. It is not difficult to show that under these conditions the signal at the lower righthand terminal of the analysis chain will equal that at the lower lefthand terminal of the synthesis chain, even though they are not connected, provided the upper terminals are connected together as shown by the dashed line. Of course, the reflection coefficients $k sub 1$, $k sub 2$, ..., $k sub p$ in the analysis lattice must equal those in the synthesis lattice, and as Figure 6.13 shows the order is reversed in the synthesis lattice. Successive analysis and synthesis sections pair off, working from the middle outwards. At each stage the sections cancel each other out, giving a unit transfer function as demonstrated above. .rh "Estimating reflection coefficients." As stated earlier in this chapter, the key problem in linear prediction is to determine the values of the predictive coefficients \(em in this case, the reflection coefficients. If this is done correctly, we have shown using Procedure 6.3 that the the synthesis part of Figure 6.13 performs the same calculation that a conventional direct-form linear predictive synthesizer would, and hence the signal that excites it \(em that is, the signal represented by the dashed line \(em must be the prediction residual, or error signal, discussed earlier. The system is effectively the same as the high-order adaptive differential pulse code modulation one of Figure 6.1. .pp One of the most interesting features of the lattice structure for analysis filters is that calculation of suitable values for the reflection coefficients can be done locally at each stage of the lattice. For example, consider the $i$'th section of the analysis lattice in Figure 6.13. It is possible to determine a suitable value of $k sub i$ simply by performing a calculation on the inputs to the $i$'th section (ie $X sup +$ and $X sup -$ in Figure 6.12). No longer need the complicated global optimization technique of matrix inversion be used, as in the autocorrelation and covariance methods discussed earlier. .pp A suitable value for $k$ in the single lattice section of Figure 6.12 is .LB .EQ k~ = ~~ {E[ x sup + (n) x sup - (n-1)]} over {( E[ x sup + (n) sup 2 ] E[ x sup - (n-1) sup 2 ] ) sup 1/2} ~~ ; .EN .LE that is, the statistical correlation between $x sup + (n)$ and $x sup - (n-1)$. Here, $x sup + (n)$ and $x sup - (n)$ represent the input signals to the upper and lower paths (recall that $X sup +$ and $X sup -$ are their $z$-transforms). $x sup - (n-1)$ is just $x sup - (n)$ delayed by one time unit, that is, the output of the $z sup -1$ box in the Figure. .pp The criterion of optimality for the autocorrelation and covariance methods was that the prediction error, that is, the signal which emerges from the right-hand end of the upper path of a lattice analysis filter, should be minimized in a mean-square sense. The reflection coefficients obtained from the above formula do not necessarily satisfy any such global minimization criterion. Nevertheless, they do keep the error signal small, and have been used with success in speech analysis systems. .pp It is easy to minimize the output from either the upper or the lower path of the lattice filter at each stage. For example, the $z$-transform of the upper output is given by .LB .EQ Y sup + ~~=~~ X sup + ~-~ k z sup -1 X sup - , .EN .LE or .LB .EQ y sup + (n) ~~=~~ x sup + (n) ~-~ k x sup - (n-1) . .EN .LE Hence .LB .EQ E[y sup + (n) sup 2 ] ~~ = ~~ E[x sup + (n) sup 2 ] ~-~ 2kE[x sup + (n) x sup - (n-1) ] ~+~ k sup 2 E [x sup - (n-1) sup 2 ] , .EN .LE where $E$ stands for expected value, and this reaches a minimum when the derivative with respect to $k$ becomes zero: .LB .EQ -2E[x sup + (n) x sup - (n-1) ] ~+~ 2kE[x sup - (n-1) sup 2 ] ~~=~0 , .EN .LE that is, when .LB .EQ k~ = ~~ {E[x sup + (n) x sup - (n-1) ]} over {E[x sup - (n-1) sup 2 ] } ~ . .EN .LE A similar calculation shows that the output of the lower path is minimized when .LB .EQ k~ = ~~ {E[x sup + (n) x sup - (n-1) ]} over {E[x sup + (n-1) sup 2 ] } ~ . .EN .LE Unfortunately, either of these expressions can exceed 1, leading to an unstable filter. The value of $k$ cited earlier is the geometric mean of these two expressions, and since it is a correlation coefficient, must be less than 1. .pp Another possibility is to minimize the expected value of the sum of the squares of the upper and lower outputs: .LB .EQ y sup + (n) sup 2 ~+~ y sup - (n) sup 2 ~~ = ~~ (1+k sup 2 )x sup + (n) sup 2 ~-~ 2kx sup + (n) x sup - (n-1) ~+~ (1+k sup 2 )x sup - (n) sup 2 . .EN .LE Taking expected values and setting the derivative with respect to k to zero leads to .LB .EQ k~ = ~~ {E[x sup + (n) x sup - (n-1) ]} over { half ~ E[x sup + (n) sup 2 ~+~ x sup - (n-1) sup 2 ]} ~. .EN .LE This also is guaranteed to be less than 1, and has given good results in speech analysis systems. .pp Figure 6.14 shows the implementation of a single section of an analysis lattice. .FC "Figure 6.14" The signals $x sup + (n)$ and $x sup - (n-1)$ are fed to a correlator, which produces a suitable value for $k$. This value is used to calculate the output of the lattice section, and hence the input to the next lattice section. The reflection coefficient needs to be low-pass filtered, because it will only be transmitted to the synthesizer occasionally (say every 20\ msec) and so a short-term average is required. .pp One implementation of the correlator is shown in Figure 6.15 (Kang, 1974). .[ Kang 1974 .] .FC "Figure 6.15" This calculates the value of $k$ given by the last equation above, and does it by summing and differencing the two signals $x sup + (n)$ and $x sup - (n-1)$, squaring the results to give .LB .EQ x sup + (n) sup 2 + 2x sup + (n mark ) x sup - (n-1) +x sup - (n-1) sup 2 ~~~~~~~~ x sup + (n) sup 2 - 2x sup + (n) x sup - (n-1) +x sup - (n-1) sup 2 ~ , .EN .LE and summing and differencing these, to yield .LB .EQ lineup 2x sup + (n) sup 2 + 2x sup - (n-1) sup 2 ~~~~~~~~ 4x sup + (n) x sup - (n-1) ~ . .EN .LE .sp Before these are divided to give the final coefficient $k$, they are individually low-pass filtered. While some rather complex schemes have been proposed, based upon Kalman filter theory (eg Matsui .ul et al, 1972), .[ Matsui Nakajima Suzuki Omura 1972 .] a simple exponential weighted past average has been found to be satisfactory. This has $z$-transform .LB .EQ 1 over {64 - 63 z sup -1} ~ , .EN .LE that is, in the time domain, .LB .EQ y(n)~ = ~~ 63 over 64 ~ y(n-1) ~+~ 1 over 64 ~ y(n) ~ . .EN .LE This filter exponentially averages past sample values with a time-constant of 64 sampling intervals \(em that is, 8\ msec at an 8\ kHz sampling rate. .sh "6.4 Pitch estimation" .pp It is sometimes useful to think of linear prediction as a kind of curve-fitting technique. Figure 6.16 illustrates how four samples of a speech signal can predict the next one. .FC "Figure 6.16" In essence, a curve is drawn through four points to predict the position of the fifth, and only the prediction error is actually transmitted. Now if the order of linear prediction is high enough (at least 10), and if the coefficients are chosen correctly, the prediction will closely model the resonances of the vocal tract. Thus the error will actually be zero, except at pitch pulses. .pp Figure 6.17 shows a segment of voiced speech together with the prediction error (often called the prediction residual). .FC "Figure 6.17" It is apparent that the error is indeed small, except at pitch pulses. This suggests that a good way to determine the pitch period is to examine the error signal, perhaps by looking at its autocorrelation function. As with all pitch detection methods, one must be careful: spurious peaks can occur, especially in nasal sounds when the all-pole model provided by linear prediction fails. Continuity constraints, which use previous values of pitch period when determining which peak to accept as a new pitch impulse, can eliminate many of these spurious peaks. Unvoiced speech should produce an error signal with no prominent peaks, and this needs to be detected. Voiced fricatives are a difficult case: peaks should be present but the general noise level of the error signal will be greater than it is in purely voiced speech. Such considerations have been taken into account in a practical pitch estimation system based upon this technique (Markel, 1972). .[ Markel 1972 SIFT .] .pp This method of pitch detection highlights another advantage of the lattice analysis technique. When using autocorrelation or covariance analysis to determine the filter (or reflection) coefficients, the error signal is not normally produced. It can, of course, be found by taking the speech samples which constitute the current frame and running them through an analysis filter whose parameters are those determined by the analysis, but this is a computationally demanding exercise, for the filter must run at the speech sampling rate (say 8\ kHz) instead of at the frame rate (say 50\ Hz). Usually, pitch is estimated by other methods, like those discussed in Chapter 4, when using autocorrelation or covariance linear prediction. However, we have seen above that with the lattice method, the error signal is produced as a byproduct: it appears at the right-hand end of the upper path of the lattice chain. Thus it is already available for use in determining pitch periods. .sh "6.5 Parameter coding for linear predictive storage or transmission" .pp In this section, the coding requirements of linear predictive parameters will be examined. The parameters that need to be stored or transmitted are: .LB .NP pitch .NP voiced-unvoiced flag .NP overall amplitude level .NP filter coefficients or reflection coefficients. .LE The first three are parameters of the excitation source. They can be derived directly from the error signal as indicated above, if it is generated (as it is in lattice implementations); or by other methods if no error signal is calculated. The filter or reflection coefficients are, of course, the main product of linear predictive analysis. .pp It is generally agreed that around 60 levels, logarithmically spaced, are needed to represent pitch for telephone quality speech. The voiced-unvoiced indication requires one bit, but since pitch is irrelevant in unvoiced speech it can be coded as one of the pitch levels. For example, with 6-bit coding of pitch, the value 0 can be reserved to indicate unvoiced speech, with values 1\-63 indicating the pitch of voiced speech. The overall gain has not been discussed above: it is simply the average amplitude of the error signal. Five bits on a logarithmic scale are sufficient to represent it. .pp Filter coefficients are not very amenable to quantization. At least 8\-10\ bits are required for each one. However, reflection coefficients are better behaved, and 5\-6\ bits each seems adequate. The number of coefficients that must be stored or transmitted is the same as the order of the linear prediction: 10 is commonly used for low-quality speech, with as many as 15 for higher qualities. .pp These figures give around 100\ bits/frame for a 10'th order system using filter coefficients, and around 65\ bits/frame for a 10'th order system using reflection coefficients. Frame lengths vary between 10\ msec and 25\ msec, depending on the quality desired. Thus for 20\ msec frames, the data rates work out at around 5000\ bit/s using filter coefficients, and 3250\ bit/s using reflection coefficients. .pp Substantially lower data rates can be achieved by more careful coding of parameters. In 1976, the US Government defined a standard coding scheme for 10-pole linear prediction with a data rate of 2400\ bit/s \(em conveniently chosen as one of the commonly-used rates for serial data transmission. This standard, called LPC-10, tackles the difficult problem of protection against transmission errors (Fussell .ul et al, 1978). .[ Fussell Boudra Abzug Cowing 1978 .] .pp Whenever data rates are reduced, redundancy inherent in the signal is necessarily lost and so the effect of transmission errors becomes greatly magnified. For example, a single corrupted sample in PCM transmission of speech will probably not be noticed, and even a short burst of errors will be perceived as a click which can readily be distinguished from the speech. However, any error in LPC transmission will last for one entire frame \(em say 20\ msec \(em and worse still, it will be integrated into the speech signal and not easily discriminated from it by the listener's brain. A single corruption may, for example, change a voiced frame into an unvoiced one, or vice versa. Even if it affects only a reflection coefficient it will change the resonance characteristics of that frame, and change them in a way that does not simply sound like superimposed noise. .pp Table 6.1 shows the LPC-10 coding scheme. .RF .in+0.1i .ta 2.0i +1.8i +0.6i .nr x1 (\w'voiced sounds'/2) .nr x2 (\w'unvoiced sounds'/2) .ul \h'-\n(x1u'voiced sounds \h'-\n(x2u'unvoiced sounds .sp pitch/voicing 7 7 60 pitch levels, Hamming \h'\w'00 'u'and Gray coded energy 5 5 logarithmically coded $k sub 1$ 5 5 coded by table lookup $k sub 2$ 5 5 coded by table lookup $k sub 3$ 5 5 $k sub 4$ 5 5 $k sub 5$ 4 \- $k sub 6$ 4 \- $k sub 7$ 4 \- $k sub 8$ 4 \- $k sub 9$ 3 \- $k sub 10$ 2 \- synchronization 1 1 alternating 1,0 pattern error detection/ \- \h'-\w'0'u'21 correction \h'-\w'__'u+\w'0'u'__ \h'-\w'__'u+\w'0'u'__ .sp \h'-\w'0'u'54 \h'-\w'0'u'54 .sp .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i frame rate: 44.4\ Hz (22.5\ msec frames) .in 0 .FG "Table 6.1 Bit requirements for each parameter in LPC-10 coding scheme" Different coding is used for voiced and unvoiced frames. Only four reflection coefficients are transmitted for unvoiced frames, because it has been determined that no perceptible increase in speech quality occurs when more are used. The bits saved are more fruitfully employed to provide error detection and correction for the other parameters. Seven bits are used for pitch and the voiced-unvoiced flag, and they are redundant in that only 60 possible pitch values are allowed. Most transmission errors in this field will be detected by the receiver; which can then use an estimate of pitch based on previous values and discard the erroneous one. Pitch values are also Gray coded so that even if errors are not detected, there is a good chance that an adjacent pitch value is read instead. Different numbers of bits are allocated to the various reflection coefficients: experience shows that the lower-numbered ones contribute most highly to intelligibility and so these are quantized most finely. In addition, a table lookup operation is performed on the code generated for the first two, providing a non-linear quantization which is chosen to minimize the error on a statistical basis. .pp With 54\ bits/frame and 22.5\ msec frames, LPC-10 requires a 2400\ bit/s data rate. Even lower rates have been used successfully for lower-quality speech. The Speak 'n Spell toy, described in Chapter 11, has an average data rate of 1200\ bit/s. Rates as low as 600\ bit/s have been achieved (Kang and Coulter, 1976) by pattern recognition techniques operating on the reflection coefficients: however, the speech quality is not good. .[ Kang Coulter 1976 .] .sh "6.6 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "6.7 Further reading" .pp Most recent books on digital signal processing contain some information on linear prediction (see Oppenheim and Schafer, 1975; Rabiner and Gold, 1975; and Rabiner and Schafer, 1978; all referenced at the end of Chapter 4). .LB "nn" .\"Atal-1971-1 .]- .ds [A Atal, B.S. .as [A " and Hanauer, S.L. .ds [D 1971 .ds [T Speech analysis and synthesis by linear prediction of the acoustic wave .ds [J JASA .ds [V 50 .ds [P 637-655 .nr [P 1 .ds [O August .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n This paper is of historical importance because it introduced the idea of linear prediction to the speech processing community. .in-2n .\"Makhoul-1975-2 .]- .ds [A Makhoul, J.I. .ds [D 1975 .ds [K * .ds [T Linear prediction: a tutorial review .ds [J Proc IEEE .ds [V 63 .ds [N 4 .ds [P 561-580 .nr [P 1 .ds [O April .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n An interesting, informative, and readable survey of linear prediction. .in-2n .\"Markel-1976-3 .]- .ds [A Markel, J.D. .as [A " and Gray, A.H. .ds [D 1976 .ds [T Linear prediction of speech .ds [I Springer Verlag .ds [C Berlin .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is the only book which is entirely devoted to linear prediction of speech. It is an essential reference work for those interested in the subject. .in-2n .\"Wiener-1947-4 .]- .ds [A Wiener, N. .ds [D 1947 .ds [T Extrapolation, interpolation and smoothing of stationary time series .ds [I MIT Press .ds [C Cambridge, Massachusetts .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Linear prediction is often thought of as a relatively new technique, but it is only its application to speech processing that is novel. Wiener develops all of the basic mathematics used in linear prediction of speech, except the lattice filter structure. .in-2n .LE "nn" .EQ delim $$ .EN .CH "7 JOINING SEGMENTS OF SPEECH" .ds RT "Joining segments of speech .ds CX "Principles of computer speech .pp The obvious way to provide speech output from computers is to select the basic acoustic units to be used; record them; and generate utterances by concatenating together appropriate segments from this pre-stored inventory. The crucial question then becomes, what are the basic units? Should they be whole sentences, words, syllables, or phonemes? .pp There are several trade-offs to be considered here. The larger the units, the more utterances have to be stored. It is not so much the length of individual utterances that is of concern, but rather their variety, which tends to increase exponentially instead of linearly with the size of the basic unit. Numbers provide an easy example: there are $10 sup 7$ 7-digit telephone numbers, and it is certainly infeasible to record each one individually. Note that as storage technology improves the limitation is becoming more and more one of recording the utterances in the first place rather than finding somewhere to store them. At a PCM data rate of 50\ Kbit/s, a 100\ Mbyte disk can hold over 4\ hours of continuous speech. With linear predictive coding at 1\ Kbit/s it holds 0.8 of a megasecond \(em well over a week. And this is a 24-hour 7-day week, which corresponds to a working month; and continuous speech \(em without pauses \(em which probably requires another factor of five for production by a person. Setting up a recording session to fill the disk would be a formidable task indeed! Furthermore, the use of videodisks \(em which will be common domestic items by the end of the decade \(em could increase these figures by a factor of 50. .pp The word seems to be a sensibly-sized basic unit. Many applications use a rather limited vocabulary \(em 190 words for the airline reservation system described in Chapter 1. Even at PCM data rates, this will consume less than 0.5\ Mbyte of storage. Unfortunately, coarticulation and prosodic factors now come into play. .pp Real speech is connected \(em there are few gaps between words. Coarticulation, where sounds are affected by those on either side, naturally operates across word boundaries. And the time constants of coarticulation are associated with the mechanics of the vocal tract and hence measure tens or hundreds of msec. Thus the effects straddle several pitch periods (100\ Hz pitch has 10\ msec period) and cannot be simulated by simple interpolation of the speech waveform. .pp Prosodic features \(em notably pitch and rhythm \(em span much longer stretches of speech than single words. As far as most speech output applications are concerned, they operate at the utterance level of a single, sentence-sized, information unit. They cannot be accomodated if speech waveforms of individual words of the utterance are stored, for it is rarely feasible to alter the fundamental frequency or duration of a time waveform without changing all the formant resonances as well. However, both word-to-word coarticulation and the essential features of rhythm and intonation can be incorporated if the stored words are coded in source-filter form. .pp For more general applications of speech output, the limitations of word storage soon become apparent. Although people's daily vocabularies are not large, most words have a variety of inflected forms which need to be treated separately if a strict policy is adopted of word storage. For instance, in this book there are 84,000 words, and 6,500 (8%) different ones (counting inflected forms). In Chapter 1 alone, there are 6,800 words and 1,700 (25%) different ones. .pp It seems crazy to treat a simple inflection like "$-s$" or its voiced counterpart, "$-z$" (as in "inflection\c .ul s\c "), as a totally different word from the base form. But once you consider storing roots and endings separately, it becomes apparent that there is a vast number of different endings, and it is difficult to know where to draw the line. It is natural to think instead of simply using the syllable as the basic unit. .pp A generous estimate of the number of different syllables in English is 10,000. At three a second, only about an hour's storage is required for them all. But waveform storage will certainly not do. Although coarticulation effects between words are needed to make speech sound fluent, coarticulation between syllables is necessary for it even to be .ul comprehensible. Adopting a source-filter form of representation is essential, as is some scheme of interpolation between syllables which simulates coarticulation. Unfortunately, a great deal of acoustic action occurs at syllable boundaries \(em stops are exploded, the sound source changes between voicing and frication, and so on. It may be more appropriate to consider inverse syllables, comprising a vowel-consonant-vowel sequence instead of consonant-vowel-consonant. (These have jokingly been dubbed "lisibles"!) .pp There is again some considerable practical difficulty in creating an inventory of syllables, or lisibles. Now it is not so much the recording that is impractical, but the editing needed to ensure that the cuts between syllables are made at exactly the right point. As units get smaller, the exact placement of the boundaries becomes ever more critical; and several thousand sensitive editing jobs is no easy task. .pp Since quite general effects of coarticulation must be accomodated with syllable synthesis, there will not necessarily be significant deterioration if smaller, demisyllable, units are employed. This reduces the segment inventory to an estimated 1000\-2000 entries, and the tedious job of editing each one individually becomes at least feasible, if not enviable. Alternatively, the segment inventory could be created by artificial means involving cut-and-try experiments with resonance parameters. .pp The ultimate in economy of inventory size, of course, is to use phonemes as the basic unit. This makes the most critical part of the task interpolation between units, rather than their construction or recording. With only about 40 phonemes in English, each one can be examined in many different contexts to ascertain the best data to store. There is no need to record them directly from a human voice \(em it would be difficult anyway for most cannot be produced in isolation. In fact, a phoneme is an abstract unit, not a particular sound (recall the discussion of phonology in Chapter 2), and so it is most appropriate that data be abstracted from several different realizations rather than an exact record made of any one. .pp If information is stored about phonological units of speech \(em phonemes \(em the difficult task of phonological-to-phonetic conversion must necessarily be performed automatically. Allophones are created by altering the transitions between units, and to a lesser extent by modifying the central parts of the units themselves. The rules for making transitions will have a big effect on the quality of the resulting speech. Instead of trying to perform this task automatically by a computer program, the allophones themselves could be stored. This will ease the job of generating transitions between segments, but will certainly not eliminate it. The total number of allophones will depend on the narrowness of the transcription system: 60\-80 is typical, and it is unlikely to exceed one or two hundred. In any case there will not be a storage problem. However, now the burden of producing an allophonic transcription has been transferred to the person who codes the utterance prior to synthesizing it. If he is skilful and patient, he should be able to coax the system into producing fairly understandable speech, but the effort required for this on a per-utterance basis should not be underestimated. .RF .nr x0 \w'sentences ' .nr x1 \w' ' .nr x2 \w'depends on ' .nr x3 \w'generalized or ' .nr x4 \w'natural speech ' .nr x5 \w'author of segment' .nr x6 \n(x0u+\n(x1u+\n(x2u+\n(x3u+\n(x4u+\n(x5u .nr x7 (\n(.l-\n(x6)/2 .in \n(x7u .ta \n(x0u +\n(x1u +\n(x2u +\n(x3u +\n(x4u | size of storage source of principal | utterance method utterance burden is | inventory inventory placed on |\h'-1.0i'\l'\n(x6u\(ul' | sentences | depends on waveform or natural speech recording artist, | application source-filter storage medium | parameters | words | depends on source-filter natural speech recording artist | application parameters and editor, | storage medium | syllables/ | \0\0\010000 source-filter natural speech recording editor lisibles | parameters | demi- | \0\0\0\01000 source-filter natural speech recording editor syllables | parameters or artificially or inventory | generated compiler | phonemes | \0\0\0\0\0\040 generalized artificially author of segment | parameters generated concatenation | program | allophones | \0\050\-100 generalized or artificially coder of | source-filter generated or synthesized | parameters natural speech utterances |\h'-1.0i'\l'\n(x6u\(ul' .in 0 .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .FG "Table 7.1 Some issues relevant to choice of basic unit" .pp Table 7.1 summarizes in broad brush-strokes the issues which relate to the choice of basic unit for concatenation. The sections which follow provide more detail about the different methods of joining segments of speech together. Only segmental aspects are considered, for the important problems of prosody will be treated in the next chapter. All of the methods rely to some extent on the acoustic properties of speech, and as smaller basic units are considered the role of speech acoustics becomes more important. It is impossible in a book like this to give a detailed account of acoustic phonetics, for it would take several volumes! What I aim to do in the following pages is to highlight some salient features which are relevant to segment concatenation, without attempting to be complete. .sh "7.1 Word concatenation" .pp For general speech output, word concatenation is an inherently limited technique because of the large number of phonetically different words. Despite this fact, it is at present the most widely-used synthesis method, and is likely to remain so for several years. We have seen that the primary problems are word-to-word coarticulation and prosody; and both can be overcome, at least to a useful approximation, by coding the words in source-filter form. .rh "Time-domain techniques." Nevertheless, a surprising number of applications simply store the time waveform, coded, usually, by one of the techniques described in Chapter 3. From an implementation point of view there are many advantages to this. Speech quality can easily be controlled by selecting a suitable sampling rate and coding scheme. A natural-sounding voice is guaranteed; male or female as desired. The equipment required is minimal \(em a digital-to-analogue converter and post-sampling filter will do for synthesis if PCM coding is used, and DPCM, ADPCM, and delta modulation decoders are not much more complicated. .pp From a speech point of view, the resulting utterances can never be made convincingly fluent. We discussed the early experiments of Stowe and Hampton (1961) at the beginning of Chapter 3. .[ Stowe Hampton 1961 .] A major drawback to word concatenation in the analogue domain is the introduction of clicks and other interference between words: it is difficult to prevent the time waveform transitions from adding extraneous sounds. This poses no problem with digital storage, however, for the waveforms can be edited accurately prior to storage so that they start and finish at an exactly zero level. Rather, the lack of fluency stems from the absence of proper control of coarticulation and prosody. .pp But this is not necessarily a serious drawback if the application is a sufficiently limited one. Complete, invariant utterances can be stored as one unit. Often they must contain data-dependent slot-fillers, as in .LB This flight makes \(em stops .LE and .LB Flight number \(em leaves \(em at \(em , arrives in \(em at \(em .LE (taken from the airline reservation system of Chapter 1 (Levinson and Shipley, 1980)). .[ Levinson Shipley 1980 .] Then, each slot-filling word is recorded in an intonation consistent both with its position in the template utterance and with the intonation of that utterance. This could be done by embedding the word in the utterance for recording, and excising it by digital editing before storage. It would be dangerous to try to take into account coarticulation effects, for the coarticulation could not be made consistent with both the several slot-fillers and the single template. This could be overcome if several versions of the template were stored, but then the scheme becomes subject to combinatorial explosion if there is more than one slot in a single utterance. But it is not really necessary, for the lack of fluency will probably be interpreted by a benevolent listener as an attempt to convey the information as clearly as possible. .pp Difficulties will occur if the same slot-filler is used in different contexts. For instance, the first gap in each of the sentences above contains a number; yet the intonation of that number is different. Many systems simply ignore this problem. Then one does notice anomalies, if one is attentive: the words come, as it were, from different mouths, without fluency. However, the problem is not necessarily acute. If it is, two or more versions of each slot-filler can be recorded, one for each context. .pp As an example, consider the synthesis of 7-digit telephone numbers, like 289\-5371. If one version only of each digit is stored, it should be recorded in a level tone of voice. A pause should be inserted after the third digit of the synthetic number, to accord with common elocution. The result will certainly be unnatural, although it should be clear and intelligible. Any pitch errors in the recordings will make certain numbers audibly anomalous. At the other extreme, 70 single digits could be stored, one version of each digit for each position in the number. The recording will be tedious and error-prone, and the synthetic utterances will still not be fluent \(em for coarticulation is ignored \(em but instead unnaturally clearly enunciated. A compromise is to record only three versions of each digit, one for any of the five positions .nr x1 \w'\(ul' .nr x2 (8*\n(x1) .nr x3 0.2m \zx\h'\n(x1u'\zx\h'\n(x1u'\h'\n(x1u'\z\-\h'\n(x1u'\zx\h'\n(x1u'\zx\h'\n(x1u'\c \zx\h'\n(x1u'\h'\n(x1u'\v'\n(x3u'\l'-\n(x2u\(ul'\v'-\n(x3u' , another one for the third position \h'\n(x1u'\h'\n(x1u'\zx\h'\n(x1u'\z\-\h'\n(x1u'\h'\n(x1u'\c \h'\n(x1u'\h'\n(x1u'\h'\n(x1u'\v'\n(x3u'\l'-\n(x2u\(ul'\v'-\n(x3u' , and the last for the final position \h'\n(x1u'\h'\n(x1u'\h'\n(x1u'\z\-\h'\n(x1u'\h'\n(x1u'\c \h'\n(x1u'\h'\n(x1u'\zx\h'\n(x1u'\v'\n(x3u'\l'-\n(x2u\(ul'\v'-\n(x3u' . The first version will be in a level voice, the second an incomplete, rising tone; and the third a final, dropping pitch. .rh "Joining formant-coded words." The limitations of the time-domain method are lack of fluency caused by unnatural transitions between words, and the combinatorial explosion created by recording slot-fillers several times in different contexts. Both of these problems can be alleviated by storing formant tracks, concatenating them with suitable interpolation, and applying a complete pitch contour suitable for the whole utterance. But one can still not generate conversational speech, for natural speech rhythms cause non-linear warpings of the time axis which cannot reasonably be imitated by this method. .pp Solving problems often creates others. As we saw in Chapter 4, it is not easy to obtain reliable formant tracks automatically. Yet hand-editing of formant parameters adds a whole new dimension to the problem of vocabulary construction, for it is an exceedingly tiresome and time-consuming task. Even after such tweaking, resynthesized utterances will be degraded considerably from the original, for the source-filter model is by no means a perfect one. A hardware or real-time software formant synthesizer must be added to the system, presenting design problems and creating extra cost. Should a serial or parallel synthesizer be used? \(em the latter offers potentially better speech (especially in nasal sounds), but requires additional parameters, namely formant amplitudes, to be estimated. Finally, as we will see in the next chapter, it is not an easy matter to generate a suitable pitch contour and apply it to the utterance. .pp Strangely enough, the interpolation itself does not present any great difficulty, for there is not enough information in the formant-coded words to make possible sophisticated coarticulation. The need for interpolation is most pressing when one word ends with a voiced sound and the next begins with one. If either the end of the first or the beginning of the second word (or both) is unvoiced, unnatural formant transitions do not matter for they will not be heard. Actually, this is only strictly true for fricative transitions: if the juncture is aspirated then formants will be perceived in the aspiration. However, .ul h is the only fully aspirated sound in English, and it is relatively uncommon. It is not absolutely necessary to interpolate the fricative filter resonance, because smooth transitions from one fricative sound to another are rare in natural speech. .pp Hence unless both sides of the junction are voiced, no interpolation is needed: simple abuttal of the stored parameter tracks will do. Note that this is .ul not the same as joining time waveforms, for the synthesizer will automatically ensure a relatively smooth transition from one segment to another because of energy storage in the filters. A new set of resonance parameters for the formant-coded words will be stored every 10 or 20 msec (see Chapter 5), and so the transition will automatically be smoothed over this time period. .pp For voiced-to-voiced transitions, some interpolation is needed. An overlap period of duration, say, 50\ msec, is established, and the resonance parameters in the final 50\ msec of the first word are averaged with those in the first 50\ msec of the second. The average is weighted, with the first word's formants dominating at the beginning and their effect progressively dying out in favour of the second word. .pp More sophisticated than a simple average is to weight the components according to how rapidly they are changing. If the spectral change in one word is much greater than that in the other, we might expect that this will dominate the transition. A simple measure of spectral derivative at any given time can be found by adding the magnitude of the discrepancies in each formant frequency between one sample and the next. The spectral change in the transition region can be obtained by summing the spectral derivatives at each sample in the region. Such a measure can perhaps be made more accurate by taking into account the relative importance of the formants, but will probably never be more than a rough and ready yardstick. At any rate, it can be used to load the average in favour of the dominant side of the junction. .pp Much more important for naturalness of the speech are the effects of rhythm and intonation, discussed in the next chapter. .pp Such a scheme has been implemented and tested on \(em guess what! \(em 7-digit telephone numbers (Rabiner .ul et al, 1971). .[ Rabiner Schafer Flanagan 1971 .] Significant improvement (at the 5% level of statistical significance) in people's ability to recall numbers was found for this method over direct abuttal of either natural or synthetic versions of the digits. Although the method seemed, on balance, to produce utterances that were recalled less accurately than completely natural spoken telephone numbers, the difference was not significant (at the 5% level). The system was also used to generate wiring instructions by computer directly from the connection list, as described in Chapter 1. As noted there, synthetic speech was actually preferred to natural speech in the noisy environment of the production line. .rh "Joining linear predictive coded words." Because obtaining accurate formant tracks for natural utterances by Fourier transform methods is difficult, it is worth considering the use of linear prediction as the source-filter model. Actually, formant resonances can be extracted from linear predictive coefficients quite easily, but there is no need to do this because the reflection coefficients themselves are quite suitable for interpolation. .pp A slightly different interpolation scheme from that described in the previous section has been reported (Olive, 1975). .[ Olive 1975 .] The reflection coefficients were spliced during an overlap region of only 20\ msec. More interestingly, attempts were made to suppress the plosive bursts of stop sounds in cases where they were followed by another stop at the beginning of the next word. This is a common coarticulation, occurring, for instance, in the phrase "stop burst". In running speech, the plosion on the .ul p of "stop" is normally suppressed because it is followed by another stop. This is a particularly striking case because the place of articulation of the two stops .ul p and .ul b is the same: complete suppression is not as likely to happen in "stop gap", for example (although it may occur). Here is an instance of how extra information could improve the quality of the synthetic transitions considerably. However, automatically identifying the place of articulation of stops is a difficult job, of a complexity far above what is appropriate for simply joining words stored in source-filter form. .pp Another innovation was introduced into the transition between two vowel sounds, when the second word began with an accented syllable. A glottal stop was placed at the juncture. Although the glottal stop was not described in Chapter 2, it is a sound used in many dialects of English. It frequently occurs in the utterance "uh-uh", meaning "no". Here it .ul is used to separate two vowel sounds, but in fact this is not particularly common in most dialects. One could say "the apple", "the orange", "the onion" with a neutral vowel in "the" (to rhyme with "\c .ul a\c bove") and a glottal stop as separator, but it is much more usual to rhyme "the" with "he" and introduce a .ul y between the words. Similarly, even speakers who do not normally pronounce an .ul r at the end of words will introduce one in "bigger apple", rather than using a glottal stop. Note that it would be wrong to put an .ul r in "the apple", even for speakers who usually terminate "the" and "bigger" with the same sound. Such effects occur at a high level of processing, and are practically impossible to simulate with word-interpolation rules. Hence the expedient of introducing a glottal stop is a good one, although it is certainly unnatural. .sh "7.2 Concatenating whole or partial syllables" .pp The use of segments larger than a single phoneme or allophone but smaller than a word as the basic unit for speech synthesis has an interesting history. It has long been realized that transitions between phonemes are extremely sensitive and critical components of speech, and thus are essential for successful synthesis. Consider the unvoiced stop sounds .ul p, t, and .ul k. Their central portion is actually silence! (Try saying a word like "butter" with a very long .ul t.\c ) Hence in this case it is .ul only the transitional information which can distinguish these sounds from each other. .pp Sound segments which comprise the transition from the centre of one phoneme to the centre of the next are called .ul dyads or .ul diphones. The possibility of using them as the basic units for concatenation was first mooted in the mid 1950's. The idea is attractive because there is relatively little spectral movement in the central, so-called "steady-state", portion of many phonemes \(em in the extreme case of unvoiced stops there is not only no spectral movement, but no spectrum at all in the steady state! At that time the resonance synthesizer was in its infancy, and so recorded segments of live speech were used. The early experiments met with little success because of the technical difficulties of joining analogue waveforms and inevitable discrepancies between the steady-state parts of a phoneme recorded in different contexts \(em not to mention the problems of coarticulation and prosody which effectively preclude the use of waveform concatenation at such a low level. .pp In the mid 1960's, with the growing use of resonance synthesizers, it became possible to generate diphones by copying resonance parameters manually from a spectrogram, and improving the result by trial and error. It was not feasible to extract formant frequencies automatically from real speech, though, because the fast Fourier transform was not yet widely known and the computational burden of slow Fourier transformation was prohibitive. For example, a project at IBM stored manually-derived parameter tracks for diphones, identified by pairs of phoneme names (Dixon and Maxey, 1968). .[ Dixon Maxey 1968 .] To generate a synthetic utterance it was coded in phonetic form and used to access the diphone table to give a set of parameter tracks for the complete utterance. Note that this is the first system we have encountered whose input is a phonetic transcription which relates to an inventory of truly synthetic character: all previous schemes used recordings of live speech, albeit processed in some form. Since the inventory was synthetic, there was no difficulty in ensuring that discontinuities did not arise between segments beginning and ending with the same phoneme. Thus interpolation was irrelevant, and the synthesis procedure concentrated on prosodic questions. The resulting speech was reported to be quite impressive. .pp Strictly speaking, diphones are not demisyllables but phoneme pairs. In the simplest case they happen to be similar, for two primary diphones characterize a consonant-vowel-consonant syllable. There is an advantage to using demisyllables rather than diphones as the basic unit, for many syllables begin or end with complicated consonant clusters which are not easy to produce convincingly by diphone concatenation. But they are not easy to produce by hand-editing resonance parameters either! Now that speech analysis methods have been developed and refined, resonance parameters or linear predictive coefficients can be extracted automatically from natural utterances, and there has been a resurgence of interest in syllabic and demisyllabic synthesis methods. The wheel has turned full circle, from segments of natural speech to hand-tailored parameters and back again! .pp The advantage of storing demisyllables over syllables (or lisibles) from the point of view of storage capacity has already been pointed out (perhaps 1,000\-2,000 demisyllables as opposed to 4,000\-10,000 syllables). But it is probably not too significant with the continuing decline of storage costs. The requirements are of the order of 25\ Kbyte versus 0.5\ Mbyte for 1200\ bit/s linear predictive coding, and the latter could almost be accomodated today \(em 1981 \(em on a state-of-the-art read-only memory chip. A bigger advantage comes from rhythmic considerations. As we will see in the next chapter, the rhythms of fluent speech cause dramatic variations in syllable duration, but these seem to affect the vowel and closing consonant cluster much more than the initial consonant cluster. Thus if a demisyllable is deemed to begin shortly (say 60\ msec) after onset of the vowel, when the formant structure has settled down, the bulk of the vowel and the closing consonant cluster will form a single demisyllable. The opening cluster of the next syllable will lie in the next demisyllable. Then differential lengthening can be applied to that part of the syllable which tends to be stretched in live speech. .pp One system for demisyllable concatenation has produced excellent results for monosyllabic English words (Lovins and Fujimura, 1976). .[ Lovins Fujimura 1976 .] Complex word-final consonant clusters are excluded from the inventory by using syllable affixes .ul s, z, t, and .ul d; these are attached to the syllabic core as a separate exercise (Macchi and Nigro, 1977). .[ Macchi Nigro 1977 .] Prosodic rather than segmental considerations are likely to prove the major limiting factor when this scheme is extended to running speech. .pp Monosyllabic words spoken in isolation are coded as linear predictive reflection coefficients, and segmented by digital editing into the initial consonant cluster and the vocalic nucleus plus final cluster. The cut is made 60\ msec into the vowel, as suggested above. This minimizes the difficulty of interpolation when concatenating segments, for there is ample voicing on either side of the juncture. The reflection coefficients should not differ radically because the vowel is the same in each demisyllable. A 40\ msec overlap is used, with the usual linear interpolation. An alternative smoothing rule applies when the second segment has a nasal or glide after the vowel. In this case anticipatory coarticulation occurs, affecting even the early part of the vowel. For example, a vowel is frequently nasalized when followed by a nasal sound \(em even in English where nasalization is not a distinctive feature in vowels (see Chapter 2). Under these circumstances the overlap area is moved forward in time so that the colouration applies throughout almost the whole vowel. .sh "7.3 Phoneme synthesis" .pp Acoustic phonetics is the study of how the acoustic signal relates to the phonetic sequence which was spoken or heard. People \(em especially engineers \(em often ask, how could phonetics not be acoustic? In fact it can be articulatory, auditory, or linguistic (phonological), for example, and we have touched on the first and last in Chapter 2. The invention of the sound spectrograph in the late 1940's was an event of colossal significance for acoustic phonetics, for it somehow seemed to make the intricacies of speech visible. (This was thought to be a greater advance than actually turned out: historically-minded readers should refer to Potter .ul et al, 1947, for an enthusiastic contemporary appraisal of the invention.) A .[ Potter Kopp Green 1947 .] result of several years of research at Haskins Laboratories in New York during the 1950's was a set of "minimal rules for synthesizing speech", which showed how stylized formant patterns could generate cues for identifying vowels and, particularly, consonants (Liberman, 1957; Liberman .ul et al, 1959). .[ Liberman 1957 Some results of research on speech perception .] .[ Liberman Ingemann Lisker Delattre Cooper 1959 .] .pp These were to form the basis of many speech synthesis-by-rule computer programs in the ensuing decades. Such programs take as input a phonetic transcription of the utterance and generate a spoken version of it. The transcription may be broad or narrow, depending on the system. Experience has shown that the Haskins rules really are minimal, and the success of a synthesis-by-rule program depends on a vast collection of minutia, each seemingly insignificant in isolation but whose effects combine to influence the speech quality dramatically. The best current systems produce clearly understandable speech which is nevertheless something of a strain to listen to for long periods. However, many are not good; and some are execrable. In recent times commercial influences have unfortunately restricted the free exchange of results and programs between academic researchers, thus slowing down progress. Research attention has turned to prosodic factors, which are certainly less well understood than segmental ones, and to synthesis from plain English text rather than from phonetic transcriptions. .pp The remainder of this chapter describes the techniques of segmental synthesis. First it is necessary to introduce some elements of acoustic phonetics. It may be worth re-reading Chapter 2 at this point, to refresh your memory about the classification of speech sounds. .sh "7.4 Acoustic characterization of phonemes" .pp Shortly after the invention of the sound spectrograph an inverse instrument was developed, called the "pattern playback" synthesizer. This took as input a spectrogram, either in its original form or painted by hand. An optical arrangment was used to modulate the amplitude of some fifty harmonically-related oscillators by the lightness or darkness of each point on the frequency axis of the spectrogram. As it was drawn past the playing head, sound was produced which had approximately the frequency components shown on the spectrogram, although the fundamental frequency was constant. .pp This device allowed the complicated acoustic effects seen on a spectrogram (see for example Figures 2.3 and 2.4) to be replayed in either original or simplified form. Hence the features which are important for perception of the different sounds could be isolated. The procedure was to copy from an actual spectrogram the features which were most prominent visually, and then to make further changes by trial and error until the result was judged to have reasonable intelligibility when replayed. .pp For the purpose of acoustic characterization of particular phonemes, it is useful to consider the central, steady-state part separately from transitions into and out of the segment. The steady-state part is that sound which is heard when the phoneme is prolonged. The term "phoneme" is being used in a rather loose sense here: it is more appropriate to think of a "sound segment" rather than the abstract unit which forms the basis of phonological classification, and this is the terminology I will adopt. .pp The essential auditory characteristics of some sound segments are inherent in their steady states. If a vowel, for example, is spoken and prolonged, it can readily be identified by listening to any part of the utterance. This is not true for diphthongs: if you say "I" very slowly and freeze your vocal tract posture at any time, the resulting steady-state sound will not be sufficient to identify the diphthong. Rather, it will be a vowel somewhere between .ul aa (in "had") or .ul ar (in "hard") and .ul ee (in "heed"). Neither is it true for glides, for prolonging .ul w (in "want") or .ul y (in "you") results in vowels resembling respectively .ul u ("hood") or .ul ee ("heed"). Fricatives, voiced or unvoiced, can be identified from the steady state; but stops can not, for their's is silent (or \(em in the case of voiced stops \(em something close to it). .pp Segments which are identifiable from their steady state are easy to synthesize. The difficulty lies with the others, for it must be the transitions which carry the information. Thus "transitions" are an essential part of speech, and perhaps the term is unfortunate for it calls to mind an unimportant bridge between one segment and the next. It is tempting to use the words "continuant" and "non-continuant" to distinguish the two categories; unfortunately they are used by phoneticians in a different sense. We will call them "steady-state" and "transient" segments. The latter term is not particularly appropriate, for even sounds in this class .ul can be prolonged: the point is that the identifying information is in the transitions rather than the steady state. .RF .nr x1 (\w'excitation'/2) .nr x2 (\w'formant resonance'/2) .nr x3 (\w'fricative'/2) .nr x4 (\w'frequencies (Hz)'/2) .nr x5 (\w'resonance (Hz)'/2) .nr x0 4n+1.7i+0.8i+0.6i+0.6i+1.0i+\w'00'+\n(x5 .nr x6 (\n(.l-\n(x0)/2 .in \n(x6u .ta 4n +1.7i +0.8i +0.6i +0.6i +1.0i \h'-\n(x1u'excitation \0\0\h'-\n(x2u'formant resonance \0\0\h'-\n(x3u'fricative \0\0\h'-\n(x4u'frequencies (Hz) \0\0\c \h'-\n(x5u'resonance (Hz) \l'\n(x0u\(ul' .sp .nr x1 (\w'voicing'/2) \fIuh\fR (the) \h'-\n(x1u'voicing \0500 1500 2500 \fIa\fR (bud) \h'-\n(x1u'voicing \0700 1250 2550 \fIe\fR (head) \h'-\n(x1u'voicing \0550 1950 2650 \fIi\fR (hid) \h'-\n(x1u'voicing \0350 2100 2700 \fIo\fR (hod) \h'-\n(x1u'voicing \0600 \0900 2600 \fIu\fR (hood) \h'-\n(x1u'voicing \0400 \0950 2450 \fIaa\fR (had) \h'-\n(x1u'voicing \0750 1750 2600 \fIee\fR (heed) \h'-\n(x1u'voicing \0300 2250 3100 \fIer\fR (heard) \h'-\n(x1u'voicing \0600 1400 2450 \fIar\fR (hard) \h'-\n(x1u'voicing \0700 1100 2550 \fIaw\fR (hoard) \h'-\n(x1u'voicing \0450 \0750 2650 \fIuu\fR (food) \h'-\n(x1u'voicing \0300 \0950 2300 .nr x1 (\w'aspiration'/2) \fIh\fR (he) \h'-\n(x1u'aspiration .nr x1 (\w'frication'/2) .nr x2 (\w'frication and voicing'/2) \fIs\fR (sin) \h'-\n(x1u'frication 6000 \fIz\fR (zed) \h'-\n(x2u'frication and voicing 6000 \fIsh\fR (shin) \h'-\n(x1u'frication 2300 \fIzh\fR (vision) \h'-\n(x2u'frication and voicing 2300 \fIf\fR (fin) \h'-\n(x1u'frication 4000 \fIv\fR (vat) \h'-\n(x2u'frication and voicing 4000 \fIth\fR (thin) \h'-\n(x1u'frication 5000 \fIdh\fR (that) \h'-\n(x2u'frication and voicing 5000 \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 7.2 Resonance synthesizer parameters for steady-state sounds" .rh "Steady-state segments." Table 7.2 shows appropriate values for the resonance parameters and excitation sources of a resonance synthesizer, for steady-state segments only. There are several points to note about it. Firstly, all the frequencies involved obviously depend upon the speaker \(em the size of his vocal tract, his accent and speaking habits. The values given are nominal ones for a male speaker with a dialect of British English called "received pronunciation" (RP) \(em for it is what used to be "received" on the wireless in the old days before the British Broadcasting Corporation adopted a policy of more informal, more regional, speech. Female speakers have formant frequencies approximately 15% higher than male ones. Secondly, the third formant is relatively unimportant for vowel identification; it is the first and second that give the vowels their character. Thirdly, formant values for .ul h are not given, for they would be meaningless. Although it is certainly a steady-state sound, .ul h changes radically in context. If you say "had", "heed", "hud", and so on, and freeze your vocal tract posture on the initial .ul h, you will find it already configured for the following vowel \(em an excellent example of anticipatory coarticulation. Fourthly, amplitude values do play some part in identification, particularly for fricatives. .ul th is the weakest sound, closely followed by .ul f, with .ul s and .ul sh the strongest. It is necessary to get a reasonable mix of excitation in the voiced fricatives; the voicing amplitude is considerably less than in vowels. Finally, there are other sounds that might be considered steady state ones. You can probably identify .ul m, n, and .ul ng just by their steady states. However, the difference is not particularly strong; it is the transitional parts which discriminate most effectively between these sounds. The steady state of .ul r is quite distinctive, too, for most speakers, because the top of the tongue is curled back in a so-called "retroflex" action and this causes a radical change in the third formant resonance. .rh "Transient segments." Transient sounds include diphthongs, glides, nasals, voiced and unvoiced stops, and affricates. The first two are relatively easy to characterize, for they are basically continuous, gradual transitions from one vocal tract posture to another \(em sort of dynamic vowels. Diphthongs and glides are similar to each other. In fact "you" could be transcribed as a triphthong, .ul i e uu, except that in the initial posture the tongue is even higher, and the vocal tract correspondingly more constricted, than in .ul i ("hid") \(em though not as constricted as in .ul sh. Both categories can be represented in terms of target formant values, on the understanding that these are not to be interpreted as steady state configurations but strictly as extreme values at the beginning or end of the formant motion (for transitions out of and into the segment, respectively). .pp Nasals have a steady-state portion comprising a strong nasal formant at a fairly low frequency, on account of the large size of the combined nasal and oral cavity which is resonating. Higher formants are relatively weak, because of attenuation effects. Transitions into and out of nasals are strongly nasalized, as indeed are adjacent vocalic segments, with the oral and nasal tract operating in parallel. As discussed in Chapter 5, this cannot be simulated on a series synthesizer. However, extremely fast motions of the formants occur on account of the binary switching action of the velum, and it turns out that fast formant transitions are sufficient to simulate nasals because the speech perception mechanism is accustomed to hearing them only in that context! Contrast this with the extremely slow transitions in diphthongs and glides. .pp Stops form the most interesting category, and research using the pattern playback synthesizer was instrumental in providing adequate acoustic characterizations for them. Consider unvoiced stops. They each have three phases: transition in, silent central portion, and transition out. There is a lot of action on the transition out (and many phoneticians would divide this part alone into several "phases"). First, as the release occurs, there is a small burst of fricative noise. Say "t\ t\ t\ ..." as in "tut-tut", without producing any voicing. Actually, when used as an admonishment this is accompanied by an ingressive, inhaling air-stream instead of the normal egressive, exhaling one used in English speech (although some languages do have ingressive sounds). In any case, a short fricative somewhat resembling a tiny .ul s can be heard as the tongue leaves the roof of the mouth. Frication is produced when the gap is very narrow, and ceases rapidly as it becomes wider. Next, when an unvoiced stop is released, a significant amount of aspiration follows the release. Say "pot", "tot", "cot" with force and you will hear the .ul h\c -like aspiration quite clearly. It doesn't always occur, though; for example you will hear little aspiration when a fricative like .ul s precedes the stop in the same syllable, as in "spot", "scot". The aspiration is a distinguishing feature between "white spot" and the rather unlikely "White's pot". It tends to increase as the emphasis on the syllable increases, and this in an example of a prosodic feature influencing segmental characteristics. Finally, at the end of the segment, the aspiration \(em if any \(em will turn to voicing. .pp What has been described applies to .ul all unvoiced stops. What distinguishes one from another? The tiny fricative burst will be different because the noise is produced at different places in the vocal tract \(em at the lips for .ul p, tongue and front of palate for .ul t, and tongue and back of palate for .ul k. The most important difference, however, is the formant motion illuminated by the last vestiges of voicing at closure and by both aspiration and the onset of voicing at opening. Each stop has target formant values which, although they cannot be heard during the stopped portion (for there is no sound there), do affect the transitions in and out. An added complexity is that the target positions themselves vary to some extent depending on the adjacent segments. If the stop is heavily aspirated, the vocal posture will have almost attained that for the following vowel before voicing begins, but the formant transitions will be perceived because they affect the sound quality of aspiration. .pp The voiced stops .ul b, d, and .ul g are quite similar to their unvoiced analogues .ul p, t, and .ul k. What distinguishes them from each other are the formant transitions to target positions, heard during closure and opening. They are distinguished from their unvoiced counterparts by the fact that more voicing is present: it lingers on longer at closure and begins earlier on opening. Thus little or no aspiration appears during the opening phase. If an unvoiced stop is uttered in a context where aspiration is suppressed, as in "spot", it is almost identical to the corresponding voiced stop, "sbot". Luckily no words in English require us to make a distinction in such contexts. Voicing sometimes pervades the entire stopped portion of a voiced stop, especially when it is surrounded by other voiced segments. When saying a word like "baby" slowly you can choose whether or not to prolong voicing throughout the second .ul b. If you do, creating what is called a "voice bar" in spectrograms, the sound escapes through the cheeks, for the lips are closed \(em try doing it for a very long time and your cheeks will fill up with air! This severely attenuates high-frequency components, and can be simulated with a weak first formant at a low resonant frequency. .RF .nr x0 \w'unvoiced stops: 'u .nr x1 4n .nr x2 \n(x0+\n(x1+\w'aspiration burst (context- and emphasis-dependent)'u .nr x3 (\n(.l-\n(x2)/2 .in \n(x3u .ta \n(x0u +\n(x1u unvoiced stops: closure (early cessation of voicing) silent steady state opening, comprising short fricative burst aspiration burst (context- and emphasis-dependent) onset of voicing .sp voiced stops: closure (late cessation of voicing) steady state (possibility of voice bar) opening, comprising pre-voicing short fricative burst .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 7.3 Acoustic phases of stop consonants" .pp Table 7.3 summarizes some of the acoustic phases of voiced and unvoiced stops. There are many variations that have not been mentioned. Nasal plosion ("good news") occurs (at the word boundary, in this case) when the nasal formant pervades the opening phase. Stop bursts are suppressed when the next sound is a stop too (the burst on the .ul p of "apt", for example). It is difficult to distinguish a voiced stop from an unvoiced one at the end of a word ("cab" and "cap"); if the speaker is trying to make himself particularly clear he will put a short neutral vowel after the voiced stop to emphasize its early onset of voicing. (If he is Italian he will probably do this anyway, for it is the norm in his own language.) .pp Finally, we turn to affricates, of which there are only two in English: .ul ch ("chin") and .ul j ("djinn"). They are very similar to the stops .ul t and .ul d followed by the fricatives .ul sh and .ul zh respectively, and their acoustic characterization is similar to that of the phoneme pair. .ul ch has a closing phase, a stopped phase, and a long fricative burst. There is no aspiration, for the vocal cords are not involved. .ul j is the same except that voicing extends further into the stopped portion, and the terminating fricative is also voiced. It may be pronounced with a voice bar if the preceding segment is voiced ("adjunct"). .sh "7.5 Speech synthesis by rule" .pp Generation of speech by rules acting upon a phonetic transcription was first investigated in the early 1960's (Kelly and Gerstman, 1961). .[ Kelly Gerstman 1961 .] Most systems employ a hardware resonance synthesizer, analogue or digital, series or parallel, to reduce the load on the computer which operates the rules. The speech-by-rule program, rather than the synthesizer, inevitably contributes by far the greater part of the degradation in the resulting speech. Although parallel synthesizers offer greater potential control over the spectrum, it is not clear to what extent a synthesis program can take advantage of this. Parameter tracks for a series synthesizer can easily be converted into linear predictive coefficients, and systems which use a linear predictive synthesizer will probably become popular in the near future. .pp The phrase "synthesis by rule", which is in common use, does not make it clear just what sort of features the rules are supposed to accomodate, and what information must be included explicitly in the input transcription. Early systems made no attempt to simulate prosodics. Pitch and rhythm could be controlled, but only by inserting pitch specifiers and duration markers in the input. Some kind of prosodic control was often incorporated later, but usually as a completely separate phase from segmental synthesis. This does not allow interaction effects (such as the extra aspiration for voiceless stops in accented syllables) to be taken into account easily. Even systems which perform prosodic operations invariably need to have prosodic specifications embedded explicitly in the input. .pp Generating parameter tracks for a synthesizer from a phonetic transcription is a process of data .ul expansion. Six bits are ample to specify a phoneme, and a speaking rate of 12 phonemes/sec leads to an input data rate of 72 bit/s. The data rate required to control the synthesizer will depend upon the number of parameters and the rate at which they are sampled, but a typical figure is 6 Kbit/s (Chapter 5). Hence there is something like a hundredfold data expansion. .pp Figure 7.1 shows the parameter tracks for a series synthesizer's rendering of the utterance .ul s i k s. .FC "Figure 7.1" There are eight parameters. You can see the onset of frication at the beginning and end (parameter 5), and the amplitude of voicing (parameter 1) come on for the .ul i and off again before the .ul k. The pitch (parameter 0) is falling slowly throughout the utterance. These tracks are stylized: they come from a computer synthesis-by-rule program and not from a human utterance. With a parameter update rate of 10 msec, the graphs can be represented by 90 sets of eight parameter values, a total of 720 values or 4320 bits if a 6-bit representation is used for each value. Contrast this with the input of only four phoneme segments, or say 24 bits. .rh "A segment-by-segment system." A seminal paper appearing in 1964 was the first comprehensive description of a computer-based synthesis-by-rule system (Holmes .ul et al, 1964). .[ Holmes Mattingly Shearme 1964 .] The same system is still in use and has been reimplemented in a more portable form (Wright, 1976). .[ Wright 1976 .] The inventory of sound segments includes the phonemes listed in Table 2.1, as well as diphthongs and a second allophone of .ul l. (Many British speakers use quite a different vocal posture for pre- and post-vocalic .ul l\c \&'s, called clear and dark .ul l\c \&'s respectively.) Some phonemes are expanded into sub-phonemic "phases" by the program. Stops have three phases, corresponding to the closure, silent steady state, and opening. Diphthongs have two phases. We will call individual phases and single-phase phonemes "segments", for they are subject to exactly the same transition rules. .pp Parameter tracks are constructed out of linear pieces. Consider a pair of adjacent segments in an utterance to be synthesized. Each one has a steady-state portion and an internal transition. The internal transition of one phoneme is dubbed "external" as far as the other is concerned. This is important because instead of each segment being responsible for its own internal transition, one of the pair is identified as "dominant" and it controls the duration of both transitions \(em its internal one and its external (the other's internal) one. For example, in Figure 7.2 the segment .ul sh dominates .ul ee and so it governs the duration of both transitions shown. .FC "Figure 7.2" Note that each segment contributes as many as three linear pieces to the parameter track. .pp The notion of domination is similar to that discussed earlier for word concatenation. The difference is that for word concatenation the dominant segment was determined by computing the spectral derivative over the transition region, whereas for synthesis-by-rule segments are ranked according to a static precedence, and the higher-ranking segment dominates. Segments of stop consonants have the highest rank (and also the greatest spectral derivative), while fricatives, nasals, glides, and vowels follow in that order. .pp The concatenation procedure is controlled by a table which associates 25 quantities with each segment. They are .LB .NI rank .NI 2\ \ overall durations (for stressed and unstressed occurrences) .NI 4\ \ transition durations (for internal and external transitions of formant frequencies and amplitudes) .NI 8\ \ target parameter values (amplitudes and frequencies of three formant resonances, plus fricative information) .NI 5\ \ quantities which specify how to calculate boundary values for formant frequencies (two for each formant except the third, which has only one) .NI 5\ \ quantities which specify how to calculate boundary values for amplitudes. .LE This table is rather large. There are 80 segments in all (remember that many phonemes are represented by more than one segment), and so it has 2000 entries. The system was an offline one which ran on what was then \(em 1964 \(em a large computer. .pp The advantage of such a large table of "rules" is the flexibility it affords. Notice that transition durations are specified independently for formant frequency and amplitude parameters \(em this permits fine control which is particularly useful for stops. For each parameter the boundary value between segments is calculated using a fixed contribution from the dominant one and a proportion of the steady state value of the other. .pp It is possible that the two transition durations which are calculated for a segment actually exceed the overall duration specified for it. In this case, the steady-state target values will be approached but not actually attained, simulating a situation where coarticulation effects prevent a target value from being reached. .rh "An event-based system." The synthesis system described above, in common with many others, takes an uncompromisingly segment-by-segment view of speech. The next phoneme is read, perhaps split into a few segments, and these are synthesized one by one with due attention being paid to transitions between them. Some later work has taken a more syllabic view. Mattingly (1976) urges a return to syllables for both practical and theoretical reasons. .[ Mattingly 1976 Syllable synthesis .] Transitional effects are particularly strong within a syllable and comparatively weak (but by no means negligible) from one syllable to the next. From a theoretical viewpoint, there are much stronger phonetic restrictions on phoneme sequences than there are on syllable sequences: pretty well any syllable can follow another (although whether the pair makes sense is a different matter), but the linguistically acceptable phoneme sequences are only a fraction of those formed by combining phonemes in all possible ways. Hill (1978) argues against what be calls the "segmental assumption" that progress through the utterance should be made one segment at a time, and recommends a description of speech based upon perceptually relevant "events". .[ Hill 1978 A program structure for event-based speech synthesis by rules .] This framework is interesting because it provides an opportunity for prosodic considerations to be treated as an integral part of the synthesis process. .pp The phonetic segments and other information that specify an utterance can be regarded as a list of events which describes it at a relatively high level. Synthesis-by-rule is the act of taking this list and elaborating on it to produce lower-level events which are realized by the vocal tract, or acoustically simulated by a resonance synthesizer, to give a speech waveform. In articulatory terms, an event might be "begin tongue motion towards upper teeth with a given effort", while in resonance terms it could be "begin second formant transition towards 1500\ Hz at a given rate". (These two examples are .ul not intended to describe the same event: a tongue motion causes much more than the transition of a single formant.) Coarticulation issues such as stop burst suppression and nasal plosion should be easier to imitate within an event-based scheme than a segment-to-segment one. .pp The ISP system (Witten and Abbess, 1979) is event-based. .[ Witten Abbess 1979 .] The key to its operation is the .ul synthesis list. To prepare an utterance for synthesis, the lexical items which specify it are joined into a linked list. Figure 7.3 shows the start of the list created for .LB 1 .ul dh i z i z /*d zh aa k s /h aa u s .LE (this is Jack's house); the "1\ ...\ /*\ ...\ /\ ..." are prosodic markers which will be discussed in the next chapter. .FC "Figure 7.3" Next, the rhythm and pitch assignment routines augment the list with syllable boundaries, phoneme cluster identifiers, and duration and pitch specifications. Then it is passed to the segmental synthesis routine which chains events into the appropriate places and, as it proceeds, removes the no longer useful elements (phoneme names, pitch specifiers, etc) which originally constituted the synthesis list. Finally, an interrupt-driven speech synthesizer handler removes events from the list as they become due and uses them to control the hardware synthesizer. .pp By adopting the synthesis list as a uniform data structure for holding utterances at every stage of processing, the problems of storage allocation and garbage collection are minimized. Each list element has a forward pointer and five data words, the first indicating what type of element it is. Lexical items which may appear in the input are .LB .NI end of utterance (".", "!", ",", ";") .NI intonation indicator ("1", ...) .NI rhythm indicator ("/", "/*") .NI word boundary (" ") .NI syllable boundary ("'") .NI phoneme segment (\c .ul ar, b, ng, ...\c ) .NI explicit duration or pitch information. .LE Several of these have to do with prosodic features \(em a prime advantage of the structure is that it does not create an artificial division between segmentals and prosody. Syllable boundaries and duration and pitch information are optional. They will normally be computed by ISP, but the user can override them in the input in a natural way. The actual characters which identify lexical items are not fixed but are taken from the rule table. .pp As synthesis proceeds, new elements are chained in to the synthesis list. For segmental purposes, three types of event are defined \(em target events, increment events, and aspiration events. With each event is associated a time at which the event becomes due. For a target event, a parameter number, target parameter value, and time-increment are specified. When it becomes due, motion of the parameter towards the target is begun. If no other event for that parameter intervenes, the target value will be reached after the given time-increment. However, another target event for the parameter may change its motion before the target has been attained. Increment events contain a parameter number, a parameter increment, and a time-increment. The fixed increment is added to the parameter value throughout the time specified. This provides an easy way to make a fricative burst during the opening phase of a stop consonant. Aspiration events switch the mode of excitation from voicing to aspiration for a given period of time. Thus the aspirated part of unvoiced stops can be accomodated in a natural manner, by changing the mode of excitation for the duration of the aspiration. .RF .nr x1 (\w'excitation'/2) .nr x2 (\w'formant resonance'/2) .nr x3 (\w'fricative'/2) .nr x4 (\w'type'/2) .nr x5 (\w'frequencies (Hz)'/2) .nr x6 (\w'resonance (Hz)'/2) .nr x0 1.0i+0.7i+0.6i+0.6i+1.0i+1.2i+(\w'long vowel'/2) .nr x7 (\n(.l-\n(x0)/2 .in \n(x7u .ta 1.0i +0.7i +0.6i +0.6i +1.0i +1.2i \h'-\n(x1u'excitation \0\0\h'-\n(x2u'formant resonance \0\0\h'-\n(x3u'fricative \h'-\n(x4u'type \0\0\h'-\n(x5u'frequencies (Hz) \0\0\h'-\n(x6u'resonance (Hz) \l'\n(x0u\(ul' .sp .nr x1 (\w'voicing'/2) .nr x2 (\w'vowel'/2) \fIuh\fR \h'-\n(x1u'voicing \0490 1480 2500 \c \h'-\n(x2u'vowel \fIa\fR \h'-\n(x1u'voicing \0720 1240 2540 \h'-\n(x2u'vowel \fIe\fR \h'-\n(x1u'voicing \0560 1970 2640 \h'-\n(x2u'vowel \fIi\fR \h'-\n(x1u'voicing \0360 2100 2700 \h'-\n(x2u'vowel \fIo\fR \h'-\n(x1u'voicing \0600 \0890 2600 \h'-\n(x2u'vowel \fIu\fR \h'-\n(x1u'voicing \0380 \0950 2440 \h'-\n(x2u'vowel \fIaa\fR \h'-\n(x1u'voicing \0750 1750 2600 \h'-\n(x2u'vowel .nr x2 (\w'long vowel'/2) \fIee\fR \h'-\n(x1u'voicing \0290 2270 3090 \h'-\n(x2u'long vowel \fIer\fR \h'-\n(x1u'voicing \0580 1380 2440 \h'-\n(x2u'long vowel \fIar\fR \h'-\n(x1u'voicing \0680 1080 2540 \h'-\n(x2u'long vowel \fIaw\fR \h'-\n(x1u'voicing \0450 \0740 2640 \h'-\n(x2u'long vowel \fIuu\fR \h'-\n(x1u'voicing \0310 \0940 2320 \h'-\n(x2u'long vowel .nr x1 (\w'aspiration'/2) .nr x2 (\w'h'/2) \fIh\fR \h'-\n(x1u'aspiration \h'-\n(x2u'h .nr x1 (\w'voicing'/2) .nr x2 (\w'glide'/2) \fIr\fR \h'-\n(x1u'voicing \0240 1190 1550 \h'-\n(x2u'glide \fIw\fR \h'-\n(x1u'voicing \0240 \0650 \h'-\n(x2u'glide \fIl\fR \h'-\n(x1u'voicing \0380 1190 \h'-\n(x2u'glide \fIy\fR \h'-\n(x1u'voicing \0240 2270 \h'-\n(x2u'glide .nr x2 (\w'nasal'/2) \fIm\fR \h'-\n(x1u'voicing \0190 \0690 2000 \h'-\n(x2u'nasal .nr x1 (\w'none'/2) .nr x2 (\w'stop'/2) \fIb\fR \h'-\n(x1u'none \0100 \0690 2000 \h'-\n(x2u'stop \fIp\fR \h'-\n(x1u'none \0100 \0690 2000 \h'-\n(x2u'stop .nr x1 (\w'voicing'/2) .nr x2 (\w'nasal'/2) \fIn\fR \h'-\n(x1u'voicing \0190 1780 3300 \h'-\n(x2u'nasal .nr x1 (\w'none'/2) .nr x2 (\w'stop'/2) \fId\fR \h'-\n(x1u'none \0100 1780 3300 \h'-\n(x2u'stop \fIt\fR \h'-\n(x1u'none \0100 1780 3300 \h'-\n(x2u'stop .nr x1 (\w'voicing'/2) .nr x2 (\w'nasal'/2) \fIng\fR \h'-\n(x1u'voicing \0190 2300 2500 \h'-\n(x2u'nasal .nr x1 (\w'none'/2) .nr x2 (\w'stop'/2) \fIg\fR \h'-\n(x1u'none \0100 2300 2500 \h'-\n(x2u'stop \fIk\fR \h'-\n(x1u'none \0100 2300 2500 \h'-\n(x2u'stop .nr x1 (\w'frication'/2) .nr x2 (\w'voice + fric'/2) .nr x3 (\w'fricative'/2) \fIs\fR \h'-\n(x1u'frication 6000 \h'-\n(x3u'fricative \fIz\fR \h'-\n(x2u'voice + fric \0190 1780 3300 6000 \h'-\n(x3u'fricative \fIsh\fR \h'-\n(x1u'frication 2300 \h'-\n(x3u'fricative \fIzh\fR \h'-\n(x2u'voice + fric \0190 2120 2700 2300 \h'-\n(x3u'fricative \fIf\fR \h'-\n(x1u'frication 4000 \h'-\n(x3u'fricative \fIv\fR \h'-\n(x2u'voice + fric \0190 \0690 3300 4000 \h'-\n(x3u'fricative \fIth\fR \h'-\n(x1u'frication 5000 \h'-\n(x3u'fricative \fIdh\fR \h'-\n(x2u'voice + fric \0190 1780 3300 5000 \h'-\n(x3u'fricative \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 7.4 Rule table for an event-based synthesis-by-rule program" .pp Now the rule table, which is shown in Table 7.4, holds simple target positions for each phoneme segment, as well as the segment type. The latter is used to trigger events by computer procedures which have access to the context of the segment. In principle, this allows considerably more sophistication to be introduced than does a simple segment-by-segment approach. .RF .nr x1 0.5i+0.5i+\w'preceding consonant in this syllable (suppress burst if fricative)'u .nr x1 (\n(.l-\n(x1)/2 .in \n(x1u .ta 0.5i +0.5i fricative bursts on stops aspiration bursts on unvoiced stops, affected by preceding consonant in this syllable (suppress burst if fricative) following consonant (suppress burst if another stop; introduce nasal plosion if a nasal) prosodics (increase burst if syllable is stressed) voice bar on voiced stops (in intervocalic position) post-voicing on terminating voiced stops, if syllable is stressed anticipatory coarticulation for \fIh\fR vowel colouring when a nasal or glide follows .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 7.5 Some coarticulation effects" .pp For example, Table 7.5 summarizes some of the subtleties of the speech production process which have been mentioned earlier in this chapter. Most of them are context-dependent, with the prosodic context (whether two segments are in the same syllable; whether a syllable is stressed) playing a significant role. A scheme where data-dependent "demons" fire on particular patterns in a linked list seems to be a sensible approach towards incorporating such rules. .rh "Discussion." There are two opposing trends in speech synthesis by rule. On the one hand larger and larger segment inventories can be used, containing more and more allophones explicitly. This is the approach of the Votrax sound-segment synthesizer, discussed in Chapter 11. It puts an increasing burden on the person who codes the utterances for synthesis, although, as we shall see, computer programs can assist with this task. On the other hand the segment inventory can be kept small, perhaps comprising just the logical phonemes as in the ISP system. This places the onus on the computer program to accomodate allophonic variations, and to do so it must take account of the segmental and prosodic context of each phoneme. An event-based approach seems to give the best chance of incorporating contextual modification whilst avoiding undesired interactions. .pp The second trend brings synthesis closer to the articulatory process of speech production. In fact an event-based system would be an ideal way of implementing an articulatory model for speech synthesis by rule. It would be much more satisfying to have the rule table contain articulatory target positions instead of resonance ones, with events like "begin tongue motion towards upper teeth with a given effort". The problem is that hard data on articulatory postures and constraints is much more difficult to gather than resonance information. .pp An interesting question that relates to articulation is whether formant motion can be simulated adequately by a small number of linear pieces. The segment-by-segment system described above had as many as nine pieces for a single phoneme, for some phonemes had three phases and each one contributes up to three pieces (transition in, steady state, and transition out). Another system used curves of decaying exponential form which ensured that all transitions started rapidly towards the target position but slowed down as it was approached (Rabiner, 1968, 1969). .[ Rabiner 1968 Speech synthesis by rule Bell System Technical J .] .[ Rabiner 1969 A model for synthesizing speech by rule .] The time-constant of decay was stored with each segment in the rule table. The rhythm of the synthetic speech was controlled at this level, for the next segment was begun when all the formants had attained values sufficiently close to the current targets. This is a poor model of the human speech production process, where rhythm is dictated at a relatively high level and the next phoneme is not simply started when the current one happens to end. Nevertheless, the algorithm produced smooth, continuous formant motions not unlike those found in spectrograms. .pp There is, however, by no means universal agreement on decaying exponential formant motions. Lawrence (1974) divided segments into "checked" and "free" categories, corresponding roughly to consonants and vowels; and postulated .ul increasing exponential transitions into checked segments, and decaying transitions into free ones. .[ Lawrence 1974 .] This is a reasonable supposition if you consider the mechanics of articulation. The speed of movement of the tongue (for example) is likely to increase until it is physically stopped by reaching the roof of the mouth. When moving away from a checked posture into a free one the transition will be rapid at first but slow down to approach the target asymptotically, governed by proprioceptive feedback. .pp The only thing that seems to be agreed is that the formant tracks should certainly .ul not be piecewise linear. However, in the face of conflicting opinions as to whether exponentials should be decaying or increasing, piecewise linear motions seem to be a reasonable compromise! It is likely that the precise shape of formant tracks is unimportant so long as the gross features are imitated correctly. Nevertheless, this is a question which an articulatory model could help to answer. .sh "7.6 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "7.7 Further reading" .pp There are unfortunately few books to recommend on the subject of joining segments of speech. The references form a representative and moderately comprehensive bibliography. Here is some relevant background reading in linguistics. .LB "nn" .\"Fry-1976-1 .]- .ds [A Fry, D.B.(Editor) .ds [D 1976 .ds [T Acoustic phonetics .ds [I Cambridge Univ Press .ds [C Cambridge, England .nr [T 0 .nr [A 0 .nr [O 0 .][ 2 book .in+2n This book of readings contains many classic papers on acoustic phonetics published from 1922\-1965. It covers much of the history of the subject, and is intended primarily for students of linguistics. .in-2n .\"Lehiste-1967-2 .]- .ds [A Lehiste, I.(Editor) .ds [D 1967 .ds [T Readings in acoustic phonetics .ds [I MIT Press .ds [C Cambridge, Massachusetts .nr [T 0 .nr [A 0 .nr [O 0 .][ 2 book .in+2n Another basic collection of references which covers much the same ground as Fry (1976), above. .in-2n .\"Sivertsen-1961-3 .]- .ds [A Sivertsen, E. .ds [D 1961 .ds [K * .ds [T Segment inventories for speech synthesis .ds [J Language and Speech .ds [V 4 .ds [P 27-89 .nr [P 1 .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n This is a careful early study of the quantitative implications of using phonemes, demisyllables, syllables, and words as the basic building blocks for speech synthesis. .in-2n .LE "nn" .EQ delim $$ .EN .CH "8 PROSODIC FEATURES IN SPEECH SYNTHESIS" .ds RT "Prosodic features .ds CX "Principles of computer speech .pp Prosodic features are those which characterize an utterance as a whole, rather than having a local influence on individual sound segments. For speech output from computers, an "utterance" usually comprises a single unit of information which stretches over several words \(em a clause or sentence. In natural speech an utterance can be very much longer, but it will be broken into prosodic units which are again roughly the size of a clause or sentence. These prosodic units are certainly closely related to each other. For example, the pitch contour used when introducing a new topic is usually different from those employed to develop it subsequently. However, for the purposes of synthesis the successive prosodic units can be treated independently, and information about pitch contours to be used will have to be specified in the input for each one. The independence between them is not complete, however, and lower-level contextual effects, such as interpolation of pitch between the end of one prosodic unit and the start of the next, must still be imitated. .pp Prosodic features were introduced briefly in Chapter 2. Variations in voice dynamics occur in three dimensions: pitch of the voice, time, and amplitude. These dimensions are inextricably twined together in living speech. Variations in voice quality are much less important for the factual kind of speech usually sought in voice response applications, although they can play a considerable in conveying emotions (for a discussion of the acoustic manifestations of emotion in speech, see Williams and Stevens, 1972). .[ Williams Stevens 1972 .] .pp The distinction between prosodic and segmental effects is a traditional one, but it becomes rather fuzzy when examined in detail. It is analogous to the distinction between hardware and software in computer science: although useful from some points of view the borderline becomes blurred as one gets closer to actual systems \(em with microcode, interrupts, memory management, and the like. At a trivial level, prosodics cannot exist without segmentals, for there must be some vehicle to carry the prosodic contrasts. Timing \(em a prosodic feature \(em is actually realized by the durations of individual segments. Pauses are tantamount to silent segments. .pp While pitch may seem to be relatively independent of segmentals \(em and this view is reinforced by the success of the source-filter model which separates the frequency of the excitation source from the filter characteristics \(em there are some subtle phonetic effects of pitch. It has been observed that it drops on the transition into certain consonants, and rises again on the transition out (Haggard .ul et al, 1970). .[ Haggard Ambler Callow 1970 .] This can be explained in terms of variations in pressure from the lungs on the vocal cords (Ladefoged, 1967). .[ Ladefoged 1967 .] Briefly, the increase in mouth pressure which occurs during some consonants causes a reduction in the pressure difference across the vocal cords and in the rate of flow of air between them. This results in a decrease in their frequency of vibration. When the constriction is released, there is a temporary increase in the air flow which increases the pitch again. The phenomenon is called "microintonation". It is particularly noticeable in voiced stops, but also occurs in voiced fricatives and unvoiced stops. Simulation of the effect in synthesis-by-rule has often been found to give noticeable improvements in the speech quality. .pp Loudness also has a segmental role. For example, we noted in the last chapter that amplitude values play a small part in identification of fricatives. In fact loudness is a very .ul weak prosodic feature. It contributes little to the perception of stress. Even for shouting the distinction from normal speech is as much in the voice quality as in amplitude .ul per se. It is not necessary to consider varying loudness on a prosodic basis in most speech synthesis systems. .pp The above examples show how prosodic features have segmental influences as well. The converse is also true: some segmental features have a prosodic effect. The last chapter described how stress is associated with increased aspiration of syllable-initial unvoiced stops. Furthermore, stressed syllables are articulated with greater effort than unstressed ones, and hence the formant transitions are more likely to attain their target values under circumstances which would otherwise cause them to fall short. In unstressed syllables, extreme vowels (like .ul ee, aa, uu\c ) tend to more centralized sounds (like .ul i, uh, u respectively). Although all British English vowels .ul can appear in unstressed syllables, they often become "reduced" into a centralized form. Consider the following examples. .LB .NI diplomat \ .ul d i p l uh m aa t .NI diplomacy \ .ul d i p l uh u m uh s i .NI diplomatic \ .ul d i p l uh m aa t i k. .LE The vowel of the second syllable is reduced to .ul uh in "diplomat" and "diplomatic", whereas the root form "diploma", and also "diplomacy", has a diphthong (\c .ul uh u\c ) there. The third syllable has an .ul aa in "diplomat" and "diplomatic" which is reduced to .ul uh in "diplomacy". In these cases the reduction is shown explicitly in the phonetic transcription; but in more marginal examples where it is less extreme it will not be. .pp I have tried to emphasize in previous chapters that prosodic features are important in speech synthesis. There is something very basic about them. Rhythm is an essential part of all bodily activity \(em of breathing, walking, working and playing \(em and so it pervades speech too. Mothers and babies communicate effectively using intonation alone. Some experiments have indicated that the language environment of an infant affects his babbling at an early age, before he has effective segmental control. There is no doubt that "tone of voice" plays a large part in human communication. .pp However, early attempts at synthesis did not pay too much attention to prosodics, perhaps because it was thought sufficient to get the meaning across by providing clear segmentals. As artificial speech grows more widespread, however, it is becoming apparent that its acceptability to users, and hence its ultimate success, depends to a large extent on incorporating natural-sounding prosodics. Flat, arhythmic speech may be comprehensible in short stretches, but it strains the concentration in significant discourse and people are not usually prepared to listen to it. Unfortunately, current commercial speech output systems do not really tackle prosodic questions, which indicates our present rather inadequate state of knowledge. .pp The importance of prosodics for automatic speech .ul recognition is beginning to be appreciated too. Some research projects have attended to the automatic identification of points of stress, in the hope that the clear articulation of stressed syllables can be used to provide anchor points in an unknown utterance (for example, see Lea .ul et al, 1975). .[ Lea Medress Skinner 1975 .] .pp But prosodics and segmentals are closely intertwined. I have chosen to treat them in separate chapters in order to split the material up into manageable chunks rather than to enforce a deep division between them. It is also true that synthesis of prosodic features is an uncharted and controversial area, which gives this chapter rather a different flavour from the last. It is hard to be as definite about alternative strategies and methods as you can for segment concatenation. In order to make the treatment as concrete and down-to-earth as possible, I will describe in some detail two example projects in prosodic synthesis. The first treats the problem of transferring pitch from one utterance to another, while the second considers how artificial timing and pitch can be assigned to synthetic speech. These examples illustrate quite different problems, and are reasonably representative of current research activity. (Other systems are described by Mattingly, 1966; Rabiner .ul et al, 1969.) Before .[ Mattingly 1966 .] .[ Rabiner Levitt Rosenberg 1969 .] looking at the two examples, we will discuss a feature which is certainly prosodic but does not appear in the list given earlier \(em stress. .sh "8.1 Stress" .pp Stress is an everyday notion, and when listening to natural speech people can usually agree on which syllables are stressed. But it is difficult to characterize in acoustic terms. From the speaker's point of view, a stressed syllable is produced by pushing more air out of the lungs. For a listener, the points of stress are "obvious". You may think that stressed syllables are louder than the others: however, instrumental studies show that this is not necessarily (nor even usually) so (eg Lehiste and Peterson, 1959). .[ Lehiste Peterson 1959 .] Stressed syllables frequently have a longer vowel than unstressed ones, but this is by no means universally true \(em if you say "little" or "bigger" you will find that the vowel in the first, stressed, syllable is short and shows little sign of lengthening as you increase the emphasis. Moreover, experiments using bisyllabic nonsense words have indicated that some people consistently judge the .ul shorter syllable to be stressed in the absence of other clues (Morton and Jassem, 1965). .[ Morton Jassem 1965 .] Pitch often helps to indicate stress. It is not that stressed syllables are always higher- or lower-pitched than neighbouring ones, or even that they are uttered with a rising or falling pitch. It is the .ul rate of change of pitch that tends to be greater for stressed syllables: a sharp rise or fall, or a reversal of direction, helps to give emphasis. .pp Stress is acoustically manifested in timing and pitch, and to a much lesser extent in loudness. However it is a rather subtle feature and does .ul not correspond simply to duration increases or pitch rises. It seems that listeners unconsciously put together all the clues that are present in an utterance in order to deduce which syllables are stressed. It may be that speech is perceived by a listener with reference to how he would have produced it himself, and that this is how he detects which syllables were given greater vocal effort. .pp The situation is confused by the fact that certain syllables in words are often said in ordinary language to be "stressed" on account of their position in the word. For example, the words "diplomat", "diplomacy", and "diplomatic" have stress on the first, second, and third syllables respectively. But here we are talking about the word itself rather than any particular utterance of it. The "stress" is really .ul latent in the indicated syllables and only made manifest upon uttering them, and then to a greater or lesser degree depending on exactly how they are uttered. .pp Some linguists draw a careful distinction between salient syllables, accented syllables, and stressed syllables, although the words are sometimes used differently by different authorities. I will not adopt a precise terminology here, but it is as well to be aware of the subtle distinctions involved. The term "salience" is applied to actual utterances, and salient syllables are those that are perceived as being more prominent than their neighbours. "Accent" is the potential for salience, as marked, for example, in a dictionary or lexicon. Thus the discussion of the "diplo-" words above is about accent. Stress is an articulatory phenomenon associated with increased muscular activity. Usually, syllables which are perceived as salient were produced with stress, but in shouting, for example, all syllables can be stressed \(em even non-salient ones. Furthermore, accented syllables may not be salient. For instance, the first syllable of the word "very" is accented, that is, potentially salient, but in a sentence as uttered it may or may not be salient. One can say .LB "\c .ul he's very good" .LE with salience on "he" and possibly "good", or .LB "he's .ul very good" .LE with salience on the first syllable of "very", and possibly "good". .pp Non-standard stress patterns are frequently used to bring out contrasts. Words like "a" and "the" are normally unstressed, but can be stressed in contexts where ambiguity has arisen. Thus factors which operate at a much higher level than the phonetic structure of the utterance must be taken into account when deciding where stress should be assigned. These include syntactic and semantic considerations, as well as the attitude of the speaker and the likely attitude of the listener to the material being spoken. For example, I might say .LB "Anna .ul and Nikki should go", .LE with emphasis on the "and" purely because I was aware that my listener might quibble about the expense of sending them both. Clearly some notation is needed to communicate to the synthesis process how the utterance is supposed to be rendered. .sh "8.2 Transferring pitch from one utterance to another" .pp For speech stored in source-filter form and concatenated on a slot-filling basis, it would be useful to have stored typical pitch contours which can be applied to the synthetic utterances. From a practical point of view it is important to be able to generate natural-sounding pitch for high-quality artificial speech. Although several algorithms for creating completely synthetic contours have been proposed \(em and we will examine one later in this chapter \(em they are unsuitable for high-quality speech. They are generally designed for use with synthesis-by-rule from phonetics, and the rather poor quality of articulation does not encourage the development of excellent pitch assignment procedures. With speech synthesized by rule there is generally an emphasis on keeping the data storage requirements to a minimum, and so it is not appropriate to store complete contours. Moreover, if speech is entered in textual form as phoneme strings, it is natural to attach pitch information as markers in the text rather than by entering a complete and detailed contour. .pp The picture is rather different for concatenated segments of natural speech. In the airline reservation system, with utterances formed from templates like .LB Flight number \(em leaves \(em at \(em , arrives in \(em at \(em , .LE it is attractive to store the pitch contour of one complete instance of the utterance and apply it to all synthetic versions. .pp There is an enormous literature on the anatomy of intonation, and much of it rests upon the notion of a pitch contour as a descriptive aid to analysis. Underlying this is the assumption, usually unstated, that a contour can be discussed independently of the particular stream of words that manifests it; that a single contour can somehow be bound to any sentence (or phrase, or clause) to produce an acceptable utterance. But the contour, and its binding, are generally described only at the grossest level, the details being left unspecified. .pp There are phonetic influences on pitch \(em the characteristic lowering during certain consonants was mentioned above \(em and these are not normally considered as part of intonation. Such effects will certainly spoil attempts to store contours extracted from living speech and apply them to different utterances, but the impairment may not be too great, for pitch is only one of many segmental clues to consonant identification. .pp In the system mentioned earlier which generated 7-digit telephone numbers by concatenating formant-coded words, a single natural pitch contour was applied to all utterances. It was taken to match as well as possible the general shape of the contours measured in naturally-spoken telephone numbers. However, this is a very restricted environment, for telephone numbers exhibit almost no variety in the configuration of stressed and unstressed syllables \(em the only digit which is not a monosyllable is "seven". Significant problems arise when more general utterances are considered. .pp Suppose the pitch contour of one utterance (the "source") is to be transferred to another (the "target"). Assume that the utterances are encoded in source-filter form, either as parameter tracks for a formant synthesizer or as linear predictive coefficients. Then there are no technical obstacles to combining pitch and segmentals. The source must be available as a complete utterance, while the target may be formed by concatenating smaller units such as words. .pp For definiteness, we will consider utterances of the form .LB The price is \(em dollars and \(em cents, .LE where the slots are filled by numbers less than 100; and of the form .LB The price is \(em cents. .LE The domain of prices encompasses a wide range of syllable configurations. There are between one and five syllables in each variable part, if the numbers are restricted to be less than 100. The sentences have a constant pragmatic, semantic, and syntactic structure. As in the vast majority of real-life situations, minimal phonetic distinctions between utterances do not occur. .pp Pitch transfer is complicated by the fact that values of the source pitch are only known during the voiced parts of the utterance. Although it would certainly be possible to extrapolate pitch over unvoiced parts, this would introduce some artificiality into the otherwise completely natural contours. Let us assume, therefore, that the pitch contour of the voiced nucleus of each syllable in the source is applied to the corresponding syllable nucleus in the target. .pp The primary factors which might tend to inhibit successful transfer are .LB .NP different numbers of syllables in the utterances; .NP variations in the pattern of stressed and unstressed syllables; .NP different syllable durations; .NP pitch discontinuities; .NP phonetic differences between the utterances. .LE .rh "Syllabification." It is essential to take into account the syllable structures of the utterances, so that pitch is transferred between corresponding syllables rather than over the utterance as a whole. Fortunately, syllable boundaries can be detected automatically with a fair degree of accuracy, especially if the speech is carefully enunciated. It is worth considering briefly how this can be done, even though it takes us off the main topic of synthesis and into speech analysis. .pp A procedure developed by Mermelstein (1975) involves integrating the spectral energy at each point in the utterance. .[ Mermelstein 1975 Automatic segmentation of speech into syllabic units .] First the low (<500\ Hz) and high (>4000\ Hz) ends are filtered out with 12\ dB/octave cutoffs. The resulting energy signal is smoothed by a 40\ Hz lowpass filter, giving a so-called "loudness" function. All this can be accomplished with simple recursive digital filters. .pp Then, the loudness function is compared with its convex hull. The convex hull is the shape a piece of elastic would assume if stretched over the top of the loudness function and anchored down at both ends, as illustrated in Figure 8.1. .FC "Figure 8.1" The point of maximum difference between the hull and loudness function is taken to be a tentative syllable boundary. The hull is recomputed, but anchored to the actual loudness function at the tentative boundary, and the points of maximum hull-loudness difference in each of the two halves are selected as further tentative boundaries. The procedure continues recursively until the maximum hull-loudness difference, with the hull anchored at each tentative boundary, falls below a certain minimum (say 4\ dB). .pp At this stage, the number of tentative boundaries will greatly exceed the actual number of syllables (by a factor of around 5). Many of the extraneous boundaries are eliminated by the following constraints: .LB .NP if two boundaries lie within a certain time of each other (say 120\ msec), one of them is discarded; .NP if the maximum loudness within a tentative syllable falls too far short of the overall maximum for the utterance (more than 20\ dB), one boundary is discarded. .LE The question of which boundary to discard can be decided by examining the voicing continuity of the utterance. If possible, voicing across a syllable boundary should be avoided. Otherwise, the boundary with the smallest hull-loudness difference should be rejected. .RF .nr x0 \w'boundaries moved slightly to correspond better with voicing:' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta 3.4i +0.5i \l'\n(x0u\(ul' .sp total syllable count: 332 boundaries missed by algorithm: \0\09 (3%) extra boundaries inserted by algorithm: \029 (9%) boundaries moved slightly to correspond better with voicing: \0\03 (1%) .sp total errors: \041 (12%) \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 8.1 Success of the syllable segmentation procedure" .pp Table 8.1 illustrates the success of this syllabification procedure, in a particular example. Segmentation is performed with less than 10% of extraneous boundaries being inserted, and much less than 10% of actual boundaries being missed. These figures are rather sensitive to the values of the three thresholds. The values were chosen to err on the side of over-zealous syllabification, because all the boundaries need to be checked by ear and eye and it is easier to delete a boundary by hand than to insert one at an appropriate place. It may well be that with careful optimization of thresholds, better figures could be achieved. .rh "Stressed and unstressed syllables." If the source and target utterances have the same number of syllables, and the same pattern of stressed and unstressed syllables, pitch can simply be transferred from a syllable in the source to the corresponding one in the target. But if the pattern differs \(em even though the number of syllables may be the same, as in "eleven" and "seventeen" \(em then a one-to-one mapping will conflict with the stress points, and certainly sound unnatural. Hence an attempt should be made to ensure that the pitch is mapped in a plausible way. .pp The syllables of each utterance can be classified as "stressed" and "unstressed". This distinction could be made automatically by inspection of the pitch contour, within the domain of utterances used, and possibly even in general (Lea .ul et al, 1975). .[ Lea Medress Skinner 1975 .] However, in many cases it is expedient to perform the job by hand. In our example, the sentences have fixed "carrier" parts and variable "number" parts. The stressed carrier syllables, namely .LB "... price ... dol\- ... cents", .LE can be marked as such, by hand, to facilitate proper alignment between the source and target. This marking would be difficult to do automatically because it would be hard to distinguish the carrier from the numbers. .pp Even after classifying the syllables as "carrier stressed", "stressed", and "unstressed", alignment still presents problems, because the configuration of syllables in the variable parts of the utterances may differ. Syllables in the source which have no correspondence in the target can be ignored. The pitch track of the source syllable can be replicated for each additional syllable in corresponding position in the target. Of course, a stressed syllable should be selected for copying if the unmatched target syllable is stressed, and similarly for unstressed ones. It is rather dangerous to copy exactly a part of a pitch contour, for the ear is very sensitive to the juxtaposition of identically intoned segments of speech \(em especially when the segment is stressed. To avoid this, whenever a stressed syllable is replicated the pitch values should be decreased by, say, 20%, on the second copy. It sometimes happens that a single stressed syllable in the source needs to cover a stressed-unstressed pair in the target: in this case the first part of the source pitch track can be used for the stressed syllable, and the remainder for the unstressed one. .pp The example of Figure 8.2 will help to make these rules clear. .FC "Figure 8.2" Note that the marking alone is done by hand. The detailed mapping decisions can be left to the computer. The rules were derived intuitively, and do not have any sound theoretical basis. They are intended to give reasonable results in the majority of cases. .pp Figure 8.3 shows the result of transferring the pitch from "the price is ten cents" to "the price is seventy-seven cents". .FC "Figure 8.3" The syllable boundaries which are marked were determined automatically. The use of the last 30% of the "ten" contour to cover the first "-en" syllable, and its replication to serve the "-ty" syllable, can be seen. However, the 70%\(em30% proportion is applied to the source contour, and the linear distortion (described next) upsets the proportion in the target utterance. The contour of the second "seven" can be seen to be a replication of that of the first one, lowered by 20%. Notice that the pitch extraction procedure has introduced an artifact into the final part of one of the "cents" contours by doubling the pitch. .rh "Stretching and squashing." The pitch contour over a source syllable nucleus must be stretched or squashed to match the duration of the target nucleus. It is difficult to see how anything other than linear stretching and squashing could be done without considerably increasing the complexity of the procedure. The gross non-linearities will have been accounted for by the syllable alignment process, and so simple linear time-distortion should not cause too much degradation. .rh "Pitch discontinuities." Sudden jumps in pitch during voiced speech sound peculiar, although they can in fact be produced naturally (by yodelling). People frequently burst into laughter on hearing them in synthetic speech. It is particularly important to avoid this diverting effect in voice response applications, for the listener's attention is instantly directed away from what is said to the voice that speaks. .pp Discontinuities can arise in the pitch-transfer procedure either by a voiced-unvoiced-voiced transition between syllables mapping on to a voiced-voiced transition in the target, or by voicing continuity being broken when the syllable alignment procedure drops or replicates a syllable. There are several ways in which at least some of the possibilities can be avoided. For example, one could hold unstressed syllables at a constant pitch whose value coincides with either the end of the previous syllable's contour or the beginning of the next syllable's contour, depending on which transition is voiced. Alternatively, the policy of reserving the trailing part of a stressed syllable in the source to cover an unmatched following unstressed syllable in the target could be generalized to allow use of the leading 30% of the next stressed syllable's contour instead, if that maintained voicing continuity. A third solution is simply to merge the pitch contours at a discontinuity by mixing the average pitch value at the break with the pitch contour on either side of it in a proportion which increases linearly from the edges of the domain of influence to the discontinuity. Figure 8.4 shows the effect of this merging, when the pitch contour of "the price is seven cents" is transferred to "the price is eleven cents". .FC "Figure 8.4" Of course, the interpolated part will not necessarily be linear. .rh "Results of an experiment on pitch transfer." Some experiments have been conducted to evaluate the performance of this pitch transfer method on the kind of utterances discussed above (Witten, 1979). .[ Witten 1979 On transferring pitch from one utterance to another .] First, the source and target sentences were chosen to be lexically identical, that is, the same words were spoken. For this experiment alone, expert judges were employed. Each sentence was recorded twice (by the same person), and pitch was transferred from copy A to copy B and vice versa. Also, the originals were resynthesized from their linear predictive coefficients with their own pitch contours. Although all four often sounded extremely similar, sometimes the pitch contours of originals A and B were quite different, and in these cases it was immediately obvious to the ear that two of the four utterances shared the same intonation, which was different to that shared by the other two. .pp Experienced researchers in speech analysis-synthesis served as judges. In order to make the test as stringent as possible it was explained to them exactly what had been done, except that the order of the utterances in each quadruple was kept secret. They were asked to identify which two of the four sentences did not have their original contours, and were allowed to listen to each quadruple as often as they liked. On occasion they were prepared to identify only one, or even none, of the sentences as artificial. .pp The result was that an utterance with pitch transferred from another, lexically identical, one is indistinguishable from a resynthesized version of the original, even to a skilled ear. (To be more precise, this hypothesis could not be rejected even at the 1% level of statistical significance.) This gave confidence in the transfer procedure. However, one particular judge was quite successful at identifying the bogus contours, and he attributed his success to the fact that on occasion the segmental durations did not accord with the pitch contour. This casts a shadow of suspicion on the linear stretching and squashing mechanism. .pp The second experiment examined pitch transfers between utterances having only one variable part each ("the price is ... cents") to test the transfer method under relatively controlled conditions. Ten sentences of the form .LB "The price is \(em cents" .LE were selected to cover a wide range of syllable structures. Each one was regenerated with pitch transferred from each of the other nine, and these nine versions were paired with the original resynthesized with its natural pitch. The $10 times 9=90$ resulting pairs were recorded on tape in random order. .pp Five males and five females, with widely differing occupations (secretaries, teachers, academics, and students), served as judges. Written instructions explained that the tape contained pairs of sentences which were lexically identical but had a slight difference in "tone of voice", and that the subjects were to judge which of each pair sounded "most natural and intelligible". The response form gave the price associated with each pair \(em a preliminary experiment had shown that there was never any difficulty in identifying this \(em and a column for decision. With each decision, the subjects recorded their confidence in the decision. Subjects could rest at any time during the test, which lasted for about 30 minutes, but they were not permitted to hear any pair a second time. .pp Defining a "success" to be a choice of the utterance with natural pitch as the best of a pair, the overall success rate was about 60%. If choices were random, one would of course expect only a 50% success rate, and the figure obtained was significantly different from this. Almost half the choices were correct and made with high confidence; high-confidence but incorrect choices accounted for a quarter of the judgements. .pp To investigate structural effects in the pitch transfer process, low confidence decisions were ignored to eliminate noise, and the others lumped together and tabulated by source and target utterance. The number of stressed and unstressed syllables does not appear to play an important part in determining whether a particular utterance is an easy target. For example, it proved to be particularly difficult to tell .EQ delim @@ .EN natural from transferred contours with utterances $0.37 and $0.77. .EQ delim $$ .EN In fact, the results showed no better than random discrimination for them, even though the decisions in which listeners expressed little confidence had been discarded. Hence it seems that the syllable alignment procedure and the policy of replication were successful. .pp .EQ delim @@ .EN The worst target scores were for utterances $0.11 and $0.79. .EQ delim $$ .EN Both of these contained large unbroken voiced periods in the "variable" part \(em almost twice as long as the next longest voiced period. The first has an unstressed syllable followed by a stressed one with no break in voicing, involving, in a natural contour, a fast but continuous climb in pitch over the juncture, and it is not surprising that it proved to be the most difficult target. A more sophisticated "smoothing" algorithm than the one used may be worth investigating. .pp In a third experiment, sentences with two variable parts were used to check that the results of the second experiment extended to more complex utterances. The overall success rate was 75%, significantly different from chance. However, a breakdown of the results by source and target utterance showed that there was one contour (for the utterance "the price is 19 dollars and 8 cents") which exhibited very successful transfer, subjects identifying the transferred-pitch utterances at only a chance level. .pp Finally, transfers of pitch from utterances with two variable parts to those with one variable part were tested. Pitch contours were transferred to sentences with the same "cents" figure but no "dollars" part; for example, "the price is five dollars and thirteen cents" to "the price is thirteen cents". The contour was simply copied between the corresponding syllables, so that no adjustment needed to be made for different syllable structures. The overall score was 60 successes in 100 judgements \(em the same percentage as in the second experiment. .pp To summarize the results of these four experiments, .LB .NP even accomplished linguists cannot distinguish an utterance from one with pitch transferred from a different recording of it; .NP when the utterance contained only one variable part embedded in a carrier sentence, lay listeners identified the original correctly in 60% of cases, over a wide variety of syllable structures: this figure differs significantly from the chance value of 50%; .NP lay listeners identified the original confidently and correctly in 50% of cases; confidently but incorrectly in 25% of cases; .NP the greatest hindrance to successful transfer was the presence of a long uninterrupted period of voicing in the target utterance; .NP the performance of the method deteriorates as the number of variable parts in the utterances increases; .NP some utterances seemed to serve better than others as the pitch source for transfer, although this was not correlated with complexity of syllable structure; .NP even when the utterance contained two variable parts, there was one source utterance whose pitch contour was transferred to all the others so successfully that listeners could not identify the original. .LE .pp The fact that only 60% of originals in the second experiment were spotted by lay listeners in a stringent paired-comparison test \(em many of them being identified without confidence \(em does encourage the use of the procedure for generating stereotyped, but different, utterances of high quality in voice-response systems. The experiments indicate that although different syllable patterns can be handled satisfactorily by this procedure, long voiced periods should be avoided if possible when designing the message set, and that if individual utterances must contain multiple variable parts the source utterance should be chosen with the aid of listening tests. .sh "8.3 Assigning timing and pitch to synthetic speech" .pp The pitch transfer method can give good results within a fairly narrow domain of application. But like any speech output technique which treats complete utterances as a single unit, with provision for a small number of slot-fillers to accomodate data-dependent messages, it becomes unmanageable in more general situations with a large variety of utterances. As with segmental synthesis it becomes necessary to consider methods which use a textual rather than an acoustically-based representation of the prosodic features. .pp This raises a problem with prosodics that was not there for segmentals: how .ul can prosodic features be written in text form? The standard phonetic transcription method does not give much help with notation for prosodics. It does provide a diacritical mark to indicate stress, but this is by no means enough information for synthesis. Furthermore, text-to-speech procedures (described in the next chapter) promise to allow segmentals to be specified by an ordinary orthographic representation of the utterance; but we have seen that considerable intelligence is required to derive prosodic features from text. (More than mere intelligence may be needed: this is underlined by a paper (Bolinger, 1972) delightfully entitled "Accent is predictable \(em if you're a mind reader"!) .[ Bolinger 1972 Accent is predictable \(em if you're a mind reader .] .pp If synthetic speech is to be used as a computer output medium rather than as an experimental tool for linguistic research, it is important that the method of specifying utterances is natural and easy to learn. Prosodic features must be communicated to the computer in a manner considerably simpler than individual duration and pitch specifications for each phoneme, as was required in early synthesis-by-rule systems. Fortunately, a notation has been developed for conveying some of the prosodic features of utterances, as a by-product of the linguistically important task of classifying the intonation contours used in conversational English (Halliday, 1967). .[ Halliday 1967 .] This system has even been used to help foreigners speak English (Halliday, 1970) \(em which emphasizes the fact that it was designed for use by laymen, not just linguists! .[ Halliday 1970 Course in spoken English: Intonation .] .pp Here are examples of the way utterances can be conveyed to the ISP speech synthesis system which was described in the previous chapter. The notation is based upon Halliday's. .LB .NI 3 .ul ^ aw\ t\ uh/m\ aa\ t\ i\ k /s\ i\ n\ th\ uh\ s\ i\ s uh\ v /*s\ p\ ee\ t\ sh, .NI 1 .ul ^ f\ r\ uh\ m uh f\ uh/*n\ e\ t\ i\ k /r\ e\ p\ r\ uh\ z\ e\ n/t\ e\ i\ sh\ uh\ n. .LE (Automatic synthesis of speech, from a phonetic representation.) Three levels of stress are distinguished: tonic or "sentence" stress, marked by "*" before the syllable; foot stress (marked by "/"); and unstressed syllables. The notion of a "foot" controls the rhythm of the speech in a way that will be described shortly. A fourth level of stress is indicated on a segmental basis when a syllable contains a reduced vowel. .pp Utterances are divided by punctuation into .ul tone groups, which are the basic prosodic unit \(em there are two in the example. The shape of the pitch contour is governed by a numeral at the start of each tone group. Crude control over pauses is achieved by punctuation marks: full stop, for example, signals a pause while comma does not. (Longer pauses can be obtained by several full stops as in "...".) The "^" character stands for a so-called "silent stress" or breath point. Word boundaries are marked by two spaces between phonemes. As mentioned in the previous chapter, syllable boundaries and explicit pitch and duration specifiers can also be included in the input. If they are not, the ISP system will attempt to compute them. .rh "Rhythm." Our understanding of speech rhythm knows many laws but little order. In the mid 1970's there was a spate of publications reporting new data on segmental duration in various contexts, and there is a growing awareness that segmental duration is influenced by a great many factors, ranging from the structure of a discourse, through semantic and syntactic attributes of the utterances, their phonemic and phonetic make-up, right down to physiological constraints (these multifarious influences are ably documented and reviewed by Klatt, 1976). .[ Klatt 1976 Linguistic uses of segment duration in English .] What seems to be lacking in this work is a conceptual framework on to which new information about segmental duration can be nailed. .pp One starting-point for imitating the rhythm of English speech is the hypothesis of regularly recurring stresses. These stresses are primarily .ul rhythmic ones, and should be distinguished from the tonic stress mentioned above which is primarily an .ul intonational one. Rhythmic stresses are marked in the transcription by a "/". The stretch between one and the next is called a "foot", and the hypothesis above is often referred to as that of isochronous feet ("isochronous" means "of equal time"). There is considerable controversy about this hypothesis. It is most popular among British linguists and, it must be admitted, amongst those who work by introspection and intuition and do not actually .ul measure things. Although the question of isochrony of feet has long been debated, there seems to be general agreement \(em even amongst American linguists \(em that there is at least a tendency towards equal spacing of foot boundaries. However, little is known about the strength of this tendency and the extent of deviations from it (see Hill .ul et al, 1979, for an attempt to quantify it) \(em and there is even evidence to suggest that it may in part be a .ul perceptual phenomenon (Lehiste, 1973). .[ Hill Jassem Witten 1979 .] .[ Lehiste 1973 .] On this basic point, as on many others, the designer of a prosodic synthesis strategy must needs make assumptions which cannot be properly justified. .pp From a pragmatic point of view there are two advantages to basing a synthesis strategy on this hypothesis. Firstly, it provides a way to represent the many influences of higher-level processes (like syntax and semantics) on rhythm using a simple notation which fits naturally into the phonetic utterance representation, and which people find quite easy to understand and generate. Secondly, it tends to produce a heavily accentuated, but not unnatural, speech rhythm which can easily be moderated into a more acceptable rhythm by departing from isochrony in a controlled manner. .pp The ISP procedure does not make feet exactly isochronous. It starts with a standard foot time and attempts to fit the syllables of the foot into this time. If doing so would result in certain syllables having less than a preset minimum duration, the isochrony constraint is relaxed and the foot is expanded. There is no preset .ul maximum syllable length. However, when the durations of individual phoneme postures are adjusted to realize the calculated syllable durations, limits are imposed on the amount by which individual phonemes can be expanded or contracted. Thus a hierarchy of limits exists. .pp The rate of talking is determined by the standard foot time. If this time is short, many feet will be forced to have durations longer than the standard, and the speech will be "less isochronous". This seems to accord with common human experience. If the standard time is longer, however, the minimum syllable limit will always be exceeded and the speech will be completely isochronous. If it is too long, the above-mentioned limits to phoneme expansion will come into play and again partially destroy the isochrony. .pp It has often been observed that the final foot of an utterance tends to be longer than others; as does the tonic foot \(em that which bears the major stress. This is easy to accomodate, simply by making the target duration longer for these feet. .rh "From feet to syllables." A foot is a succession of syllables, one or more. And it is obvious that since there are more syllables in some feet than in others, some syllables must occupy less time than others in order to preserve the tendency towards isochrony of feet. .pp However, the duration of a foot is not divided evenly between its constituent syllables. The syllables have a definite rhythm of their own, which seems to be governed by .LB .NP the nature of the salient (that is, the first) syllable of the foot .NP the presence of word boundaries within the foot. .LE A salient syllable tends to be long either if it contains one of a class of so-called "long" vowels, or if there is a cluster of two or more consonants following the vowel. The pattern of syllables and word boundaries governs the rhythm of the foot, and Table 8.2 shows the possibilities for one-, two-, and three-syllable feet. This theory of speech rhythm is due to Abercrombie (1964). .[ Abercrombie 1964 Syllable quantity and enclitics in English .] .RF .nr x2 \w'three-syllable feet 'u .nr x3 \w'sal-short 'u .nr x4 \w'weak [#] 'u .nr x5 \w'weak 'u .nr x6 \w'/\fIit s incon\fR/ceivable 'u .nr x1 (\w'syllable rhythm'/2) .nr x7 \n(x2+\n(x3+\n(x4+\n(x5+\n(x6+\n(x1+\n(x1 .nr x7 (\n(.l-\n(x7)/2 .in \n(x7u .ta \n(x2u +\n(x3u +\n(x4u +\n(x5u +\n(x6u .ul syllable pattern example \0\0\h'-\n(x1u'syllable rhythm .sp one-syllable feet salient /\fIgood\fR /show 1 ^ weak /\fI^ good\fR/bye 2:1 .sp two-syllable feet sal-long weak /\fIcentre\fR /forward 1:1 sal-short weak /\fIatom\fR /bomb 1:2 salient # weak /\fItea for\fR /two 2:1 .sp three-syllable feet salient # weak [#] weak /\fIone for the\fR /road 2:1:1 /\fIit's incon\fR/ceivable sal-long weak # weak /\fIafter the\fR /war 2:3:1 sal-short weak # weak /\fImiddle to\fR /top 1:3:2 sal-long weak weak /\fInobody\fR /knows 3:1:2 sal-short weak weak /\fIanything\fR /more 1:1:1 .sp # denotes a word boundary; [#] is an optional word boundary .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .FG "Table 8.2 Syllable patterns and rhythms" .pp A foot may have the rhythmical characteristics of a two-syllable foot while having only one syllable, if the first place in it is filled by a silent stress (marked by "^"). This is shown in the second one-syllable example of Table 8.2. A similar effect may occur with two- and three-syllable feet, although examples are not given in the table. Feet of four and five syllables \(em with or without a silent stress \(em are considerably rarer. .pp Syllabification \(em splitting an utterance into syllables \(em is a job which had to be done for the pitch-transfer procedure described earlier, and the nature of syllable rhythms calls for it here too. Even though the utterance is now specified phonetically instead of acoustically, the same basic principle applies. Syllables normally coincide with peaks of sonority, where "sonority" measures the inherent loudness of a sound relative to other sounds of the same duration and pitch. However, difficult cases exist where it seems to be unclear how many syllables there are in a word. (Ladefoged, 1975, discusses this problem with examples such as "real", "realistic", and "reality".) Furthermore, .[ Ladefoged 1975 .] care must be taken to avoid counting two syllables in a word like "sky" because of its two peaks of sonority \(em for the stop .ul k has lower sonority than the fricative .ul s. .pp Three levels of notional sonority are enough for syllabification. Dividing phoneme segments into .ul sonorants (glides and nasals), .ul obstruents (stops and fricatives), and vowels; a general syllable has the form .LB .EQ sup * ~ sup * ~ sup * ~ sup * ~ sup * ~ , .EN .LE where "*" means repetition, that is, occurrence zero or more times. This sidesteps the "sky" problem by giving fricatives the same sonority as stops. It is easy to use the above structure to count the number of syllables in a given utterance by counting the sonority peaks. .pp However, what is required is an indication of syllable .ul boundaries as well as a syllable count. For slow conversational speech, these can be approximated as follows. Word divisions obviously form syllable boundaries, as should foot markers \(em but it may be wise not to assume that the latter do if the utterance has been prepared by someone with little knowledge of linguistics. Syllable boundaries should be made to coincide with sonority minima. As an .ul ad hoc pragmatic rule, if only one segment has the minimum sonority the boundary is placed before it. If there are two segments, each with the minimum sonority, it is placed between them, while for three or more it is placed after the first two. .pp These rules produce obviously acceptable divisions in many cases (to'day, ash'tray, tax'free), with perhaps unexpected positioning of the boundary in others (ins'pire, de'par'tment). Actually, people do differ in placement of syllable boundaries (Abercrombie, 1967). .[ Abercrombie 1967 .] .rh "From syllables to segments." The theory of isochronous feet (with the caveats noted earlier) and that of syllable rhythms provide a way of producing durations for individual syllables. But where are these durations supposed to be measured? There is a beat point, or tapping point, near the beginning of each syllable. This is the place where a listener will tap if asked to give one tap to each syllable; it has been investigated experimentally by Allen (1972). .[ Allen 1972 Location of rhythmic stress beats in English One .] It is not necessarily at the very beginning of the syllable. For example, in "straight", the tapping point is certainly after the .ul s and the stopped part of the .ul t. .pp Another factor which relates to the division of the syllable duration amongst phonetic segments is the often-observed fact that the length of the vocalic nucleus is a strong clue to the degree of voicing of the terminating cluster (Lehiste, 1970). .[ Lehiste 1970 Suprasegmentals .] If you say in pairs words like "cap", "cab"; "cat", "cad"; "tack", "tag" you will find that the vowel in the first word of each pair is significantly shorter than that in the second. In fact, the major difference between such pairs is the vowel length, not the final consonant. .pp Such effects can be taken into account by considering a syllable to comprise an initial consonant cluster, followed by a vocalic nucleus and a final consonant cluster. Any of these elements can be missing \(em the most unusual case where the nucleus is absent occurs, for example, in so-called syllabic .ul n\c \&'s (as in renderings of "button", "pudding" which might be written "butt'n", "pudd'n"). However, it is convenient to modify the definition of the nucleus so as to rule out the possibility of it being empty. Using the characterization of the syllable given above, the clusters can be defined as .LB .NI initial cluster = \u*\d \u*\d .NI nucleus = \u*\d \u*\d .NI final cluster = \u*\d. .LE Sonorants are included in the nucleus so that it is always present, even in the case of a syllabic consonant. .pp Then, rules can be used to divide the syllable duration between the initial cluster, nucleus, and final cluster. These must distinguish between situations where the terminating cluster is voiced or unvoiced so that the characteristic differences in vowel lengths can be accomodated. .pp Finally, the cluster durations must be apportioned amongst their constituent phonetic segments. There is little published data on which to base this. Two simple schemes which have been used in ISP are described in Witten (1977) and Witten & Smith (1977). .[ Witten 1977 A flexible scheme for assigning timing and pitch to synthetic speech .] .[ Witten Smith 1977 Synthesizing British English rhythm .] .rh "Pitch." There are two basically different ways of looking at the pitch of an utterance. One is to imagine pitch .ul levels attached to individual syllables. This has been popular amongst American linguists, and some people have even gone so far as to associate pitch levels with levels of stress. The second approach is to consider pitch .ul contours, as we did earlier when examining how to transfer pitch from one utterance to another. This seems to be easier for the person who transcribes the utterances to produce, for the information required is much less detailed than levels attached to each syllable. Some indication needs to be given of how the contour is to be bound to the utterance, and in the notation introduced above the most prominent, or "tonic", syllable is indicated in the transcription. .pp Halliday's (1970) classification identifies five different primary intonation contours, each hinging on the tonic syllable. .[ Halliday 1970 Course in spoken English: Intonation .] These are sketched in Figure 8.5, in the style of Halliday. .FC "Figure 8.5" Several secondary contours, which are variations on the primary ones, are defined as well. However, this classification scheme is intended for consumption by people, who bring to the problem a wealth of prior knowledge of speech and years of experience with it! It captures only the gross features of the infinite variety of pitch contours found in living speech. In a sense, the classification is .ul phonological rather than .ul phonetic, for it attempts to distinguish the features which make a logical difference to the listener instead of the acoustic details of the pitch contours. .pp It is necessary to take these contours and subject them to a sort of phonological-to-phonetic embellishment before applying them in synthetic speech. For example, the stretches with constant pitch which precede the tonic syllable in tone groups 1, 2, and 3 sound most unnatural when synthesized \(em for pitch is hardly ever exactly constant in living speech. Some pretonic pitch variation is necessary, and this can be made to emphasize the salient syllable of each foot. A "lilting" effect which reaches a peak at each foot boundary, and drops rather faster at the beginning of the foot than it rises at the end, sounds more natural. The magnitude of this inflection can be altered slightly to add interest, but a considerable increase in it produces a semantic change by making the utterance sound more emphatic. It is a major problem to pin down exactly the turning points of pitch in the falling-rising and rising-falling contours (4 and 5 in Figure 8.5). And even deciding on precise values for the pitch frequencies involved is not always easy. .pp The aim of the pitch assignment method of ISP is to allow the person (or program) which originates a spoken message to exercise a great deal of control over its intonation, without having to concern himself with foot or syllable structure. The message to be spoken must be broken down into tone groups, which correspond roughly to Halliday's tone groups. Each one comprises a .ul tonic of one or more feet, which is optionally preceded by a .ul pretonic, also with a number of feet. It is advantageous to allow a tone group boundary to occur in the middle of a foot (whereas Halliday's scheme insists that it occurs at a foot boundary). The first foot of the tonic, the .ul tonic foot, is marked by an asterisk at the beginning. It is on the first syllable of this foot \(em the "tonic" or "nuclear" syllable \(em that the major stress of the tone group occurs. If there is no asterisk in a tone group, ISP takes the final foot as the tonic (since this is the most common case). .pp The pitch contour on a tone group is specified by an array of ten numbers. Of course, the system cannot generate all conceivable contours for a tone group, but the definitions of the ten specifiable quantities have been chosen to give a useful range of contours. If necessary, more precise control over the pitch of an utterance can be achieved by making the tone groups smaller. .pp The overall pitch movement is controlled by specifying the pitch at three places: the beginning of the tone group, the beginning of the tonic syllable, and the end of the tone group. Provision is made for an abrupt pitch break at the start of the tonic syllable in order to simulate tone groups 2 and 3, and, to a lesser extent, tone groups 4 and 5. The pitch is interpolated linearly over the first part of the tone group (up to the tonic syllable) and over the last part (from there to the end), except that it is possible to specify a non-linearity on the tonic syllable, for emphasis, as shown in Figure 8.6. .FC "Figure 8.6" .pp On this basic shape are superimposed two finer pitch patterns. One of these is an initialization-continuation option which allows the pitch to rise (or fall) independently on the initial and final feet to specified values, without affecting the contour on the rest of the tone group (Figure 8.7). .FC "Figure 8.7" The other is a foot pattern which is superimposed on each pretonic foot, to give the stressed syllables of the pretonic added prominence and avoid the monotony of constant pitch. This is specified by a .ul non-linearity parameter which distorts the contour on the foot at a pre-determined point along it. Figure 8.8 shows the effect. .FC "Figure 8.8" .pp The ten quantities that define a pitch contour are summarized in Table 8.3, and shown diagrammatically in Figure 8.9. .FC "Figure 8.9" .RF .nr x0 \w'H: 'u .nr x1 \n(x0+\w'fraction along foot of the non-linearity position, for the tonic foot'u .nr x1 (\n(.l-\n(x1)/2 .in \n(x1u .ta \n(x0u +4n A: continuation from previous tone group zero gives no continuation non-zero gives pitch at start of tone group B: notional pitch at start C: pitch range on whole of pretonic D: departure from linearity on each foot of pretonic E: pitch change at start of tonic F: pitch range on tonic G: departure from linearity on tonic H: continuation to next tone group zero gives no continuation non-zero gives pitch at end of tone group I: fraction along foot of the non-linearity position, for pretonic feet J: fraction along foot of the non-linearity position, for the tonic foot .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 8.3 The quantities that define a pitch contour" .pp The intention of this parametric method of specifying contours is that the parameters should be easily derivable from semantic variables like emphasis, novelty of idea, surprise, uncertainty, incompleteness. Here we really are getting into controversial, unresearched areas. Roughly speaking, parameters D and G control emphasis, G by itself controls novelty and surprise, and H and the relative sizes of E and F control uncertainty and incompleteness. Certain parameters (notably I and J) are defined because although they do not appear to correspond to semantic distinctions, we do not yet know how to generate them automatically. .RF .nr x0 0.6i+0.5i+0.5i+0.5i+0.5i+0.5i+0.5i+0.5i+0.5i+0.5i+0.5i+\w'0000' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta 0.6i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i Halliday's tone group \0\0A \0\0B \0\0C \0\0D \0\0E \0\0F \0\0G \0\0H \0\0I \0\0J \l'\n(x0u\(ul' .sp 1 \0\0\00 \0175 \0\0\00 \0\-40 \0\0\00 \-100 \0\-40 \0\0\00 0.33 \00.5 2 \0\0\00 \0280 \0\0\00 \0\-40 \-190 \0100 \0\0\00 \0\0\00 0.33 \00.5 3 \0\0\00 \0175 \0\0\00 \0\-40 \0\-70 \0\045 \0\-10 \0\0\00 0.33 \00.5 4 \0\0\00 \0280 \-100 \0\-40 \0\020 \0\045 \0\-45 \0\0\00 0.33 \00.5 5 \0\0\00 \0175 \0\060 \0\-40 \0\-20 \0\-45 \0\045 \0\0\00 0.33 \00.5 \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 8.4 Pitch contour table for Halliday's primary tone groups" .pp One basic requirement of the pitch assignment scheme was the ability to generate contours which approximate Halliday's five primary tone groups. Values of the ten specifiable quantities are given in Table 8.4, for each tone group. All pitches are given in\ Hz. A distinctly dipping pitch movement has been given to each pretonic foot (parameter D), to lend prominence to the salient syllables. .sh "8.4 Evaluating prosodic synthesis" .pp It is extraordinarily difficult to evaluate schemes for prosodic synthesis, and this is surely a large part of the reason why prosodics are among the least advanced aspects of artificial speech. Segmental synthesis can be tested by playing people minimal pairs of words which differ in just one feature that is being investigated. For example, one might experiment with "pit", "bit"; "tot", "dot"; "cot", "got" to test the rules which discriminate unvoiced from voiced stops. There are standard word-lists for intelligibility tests which can be used to compare systems, too. No equivalent of such micro-level evaluation exists for prosodics, for they by definition have a holistic effect on utterances. They are most noticeable, and most important, in longish stretches of speech. Even monotonous, arhythmic speech will be intelligible in sufficiently short samples provided the segmentals are good enough; but it is quite impossible to concentrate on such speech in quantity. Some attempts at evaluation appear in Ainsworth (1974) and McHugh (1976), but these are primarily directed at assessing the success of pronunciation rules, which are discussed in the next chapter. .[ Ainsworth 1974 Performance of a speech synthesis system .] .[ McHugh 1976 Listener preference and comprehension tests .] .pp One evaluation technique is to compare synthetic with natural versions of utterances, as was done in the pitch transfer experiment. The method described earlier used a sensitive paired-comparison test, where subjects heard both versions in quick succession and were asked to judge which was "most natural and intelligible". This is quite a stringent test, and one that may not be so useful for inferior, completely synthetic, contours. It is essential to degrade the "natural" utterance so that it is comparable segmentally to the synthetic one: this was done in the experiment described by extracting its pitch and resynthesizing it from linear predictive coefficients. .pp Several other experiments could be undertaken to evaluate artificial prosody. For example, one could compare .LB .NP natural and artificial rhythms, using artificial segmental synthesis in both cases; .NP natural and artificial pitch contours, using artificial segmental synthesis in both cases; .NP natural and artificial pitch contours, using segmentals extracted from natural utterances. .LE There are many other topics which have not yet been fully investigated. It would be interesting, for example, to define rules for generating speech at different tempos. Elisions, where phonemes or even whole syllables are suppressed, occur in fast speech; these have been analyzed by linguists but not yet incorporated into synthetic models. It should be possible to simulate emotion by altering parameters such as pitch range and mean pitch level; but this seems exceptionally difficult to evaluate. One situation where it would perhaps be possible to measure emotion is in the reading of sports results \(em in fact a study has already been made of intonation in soccer results (Bonnet, 1980)! .[ Bonnet 1980 .] Even the synthesis of voices with different pitch ranges requires investigation, for, as noted earlier, it is difficult to place precise frequency specifications on phonological contours such as those sketched in Figure 8.5. Clearly the topic of prosodic synthesis is a rich and potentially rewarding area of research. .sh "8.5 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "8.6 Further reading" .pp There are quite a lot of books in the field of linguistics which describe prosodic features. Here is a small but representative sample from both sides of the Atlantic. .LB "nn" .\"Abercrombie-1965-1 .]- .ds [A Abercrombie, D. .ds [D 1965 .ds [T Studies in phonetics and linguistics .ds [I Oxford Univ Press .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Abercrombie is one of the leading English authorities on phonetics, and this is a collection of essays which he has written over the years. Some of them treat prosodics explicitly, and others show the influence of verse structure on Abercrombie's thinking. .in-2n .\"Bolinger-1972-2 .]- .ds [A Bolinger, D.(Editor) .ds [D 1972 .ds [T Intonation .ds [I Penguin .ds [C Middlesex, England .nr [T 0 .nr [A 0 .nr [O 0 .][ 2 book .in+2n A collection of papers that treat a wide variety of different aspects of intonation in living speech. .in-2n .\"Crystal-1969-3 .]- .ds [A Crystal, D. .ds [D 1969 .ds [T Prosodic systems and intonation in English .ds [I Cambridge Univ Press .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This book attempts to develop a theoretical basis for the study of British English intonation. .in-2n .\"Gimson-1966-3 .]- .ds [A Gimson, A.C. .ds [D 1966 .ds [T The linguistic relevance of stress in English .ds [B Phonetics and linguistics .ds [E W.E.Jones and J.Laver .ds [P 94-102 .nr [P 1 .ds [I Longmans .ds [C London .nr [T 0 .nr [A 1 .nr [O 0 .][ 3 article-in-book .in+2n Here is a careful discussion of what is meant by "stress", with much more detail than has been possible in this chapter. .in-2n .\"Lehiste-1970-4 .]- .ds [A Lehiste, I. .ds [D 1970 .ds [T Suprasegmentals .ds [I MIT Press .ds [C Cambridge, Massachusetts .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This is a comprehensive study of suprasegmental phenomena in natural speech. It is divided into three major sections: quantity (timing), tonal features (pitch), and stress. .in-2n .\"Pike-1945-5 .]- .ds [A Pike, K.L. .ds [D 1945 .ds [T The intonation of American English .ds [I Univ of Michigan Press .ds [C Ann Arbor, Michigan .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n A classic, although somewhat dated, study. Notice that it deals specifically with American English. .in-2n .LE "nn" .EQ delim $$ .EN .CH "9 GENERATING SPEECH FROM TEXT" .ds RT "Generating speech from text .ds CX "Principles of computer speech .pp In the preceding two chapters I have described how artificial speech can be produced from a written phonetic representation with additional markers indicating intonation contours, points of major stress, rhythm, and pauses. This representation is substantially the same as that used by linguists when recording natural utterances. What we will discuss now are techniques for generating this information, or at least some of it, from text. .pp Figure 9.1 shows various levels of the speech synthesis process. .FC "Figure 9.1" Starting from the top with plain text, the first box splits it into intonation units (tone groups), decides where the major emphases (tonic stresses) should be placed, and further subdivides the tone group into rhythmic units (feet). For intonation analysis it is necessary to decide on an "interpretation" of the text, which in turn, as was emphasized at the beginning of the previous chapter, depends both on the semantics of what is being said and on the attitude of the speaker to his material. The resulting representation will be at the level of Halliday's notation for utterances, with the words still in English rather than phonetics. Table 9.1 illustrates the utterance representation at the various levels of the Figure. .RF .nr x0 \w'pitch and duration '+\w'at 8 kHz sampling rate a 4-second utterance' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta \w'pitch and duration 'u +\w'pause 'u +\w'00 msec 'u representation example \l'\n(x0u\(ul' .sp plain text Automatic synthesis of speech, from a phonetic representation. .sp text adorned with 3\0^ auto/matic /synthesis of /*speech, prosodic markers 1\0^ from a pho/*netic /represen/tation. .sp phonetic text with 3\0\fI^ aw t uh/m aa t i k /s i n th uh s i s\fR prosodic markers \0\0\fIuh v /*s p ee t sh\fR , 1\0\fI^ f r uh m uh f uh/*n e t i k\fR \0\0\fI/r e p r uh z e n/t e i sh uh n\fR . .sp phonemes with pause 80 msec pitch and duration \fIaw\fR 70 msec 105 Hz \fIt\fR 40 msec 136 Hz \fIuh\fR 50 msec 148 Hz \fIm\fR 70 msec 175 Hz \fIaa\fR 90 msec 140 Hz ... ... ... .sp parameters for 10 parameters, each updated at a frame formant or linear rate of 10 msec predictive (4 second utterance gives 400 frames, synthesizer or 4,000 data values) .sp acoustic wave at 8 kHz sampling rate a 4-second utterance has 32,000 samples \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 9.1 Utterance representations at various levels in speech synthesis" .pp The next job is to translate the plain text into a broad phonetic transcription. This requires knowledge of letter-to-sound pronunciation rules for the language under consideration. But much more is needed. The structure of each word must be examined for prefixes and suffixes, because they \(em especially the latter \(em have a strong influence on pronunciation. This is called "morphological" analysis. Actually it is also required for rhythmical purposes, because prefixes are frequently unstressed (note that the word "prefix" is itself an exception to this!). Thus the appealing segmentation of the overall problem shown in Figure 9.1 is not very accurate, for the individual processes cannot be rigidly separated as it implies. In fact, we saw earlier how this intermixing of levels occurs with prosodic and segmental features. Nevertheless, it is helpful to structure discussion of the problem by separating levels as a first approximation. Further influences on pronunciation come from the semantics and syntax of the utterance \(em and both also play a part in intonation and rhythm analysis. The result of this second process is a phonetic representation, still adorned with prosodic markers. .pp Now we move down from higher-level intonation and rhythm considerations to the details of the pitch contour and segment durations. This process was the subject of the previous chapter. The problems are twofold: to map an appropriate acoustic pitch contour on to the utterance, using tonic stress point and foot boundaries as anchor points; and to assign durations to segments using the foot\(emsyllable\(emcluster\(emsegment hierarchy. If it is accepted that the overall rhythm can be captured adequately by foot markers, this process does not interact with earlier ones. However, many researchers do not, believing instead that rhythm is syntactically determined at a very detailed level. This will, of course, introduce strong interaction between the duration assignment process and the levels above. (Klatt, 1975, puts it into his title \(em "Vowel lengthening is syntactically determined in a connected discourse". .[ Klatt 1975 Vowel lengthening is syntactically determined .] Contrast this with the paper cited earlier (Bolinger, 1972) entitled "Accent is predictable \(em if you're a mind reader". .[ Bolinger 1972 Accent is predictable \(em if you're a mind reader .] No-one would disagree that "accent" is an influential factor in vowel length!) .pp Notice incidentally that the representation of the result of the pitch and duration assignment process in Table 9.1 is inadequate, for each segment is shown as having just one pitch. In practice the pitch varies considerably throughout every segment, and can easily rise and fall on a single one. For example, .LB "he's .ul very good" .LE may have a rise-fall on the vowel of "very". The linked event-list data-structure of ISP is much more suitable than a textual string for utterance representation at this level. .pp The fourth and fifth processes of Figure 9.1 have little interaction with the first two, which are the subject of this chapter. Segmental concatenation, which was treated in Chapter 7, is affected by prosodic features like stress; but a notation which indicates stressed syllables (like Halliday's) is sufficient to capture this influence. Contextual modification of segments, by which I mean the coarticulation effects which govern allophones of phonemes, is included explicitly in the fourth process to emphasize that the upper levels need only provide a broad phonemic transcription rather than a detailed phonetic one. Signal synthesis can be performed by either a formant synthesizer or a linear predictive one (discussed in Chapters 5 and 6). This will affect the details of the segmental concatenation process but should have no impact at all on the upper levels. .pp Figure 9.1 performs a useful function by summarizing where we have been in earlier chapters \(em the lower three boxes \(em and introducing the remaining problems that must be faced by a full text-to-speech system. It also serves to illustrate an important point: that a speech output system can demand that its utterances be entered in any of a wide range of representations. Thus one can enter at a low level with a digitized waveform or linear predictive parameters; or higher up with a phonetic representation that includes detailed pitch and duration specification at the phoneme level; or with a phonetic text or plain text adorned with prosodic markers; or at the very top with plain text as it would appear in a book. A heavy price in naturalness and intelligibility is paid by moving up .ul any of these levels \(em and this is just as true at the top of the Figure as at the bottom. .sh "9.1 Deriving prosodic features" .pp If you really need to start with plain text, some very difficult problems present themselves. The text should be understood, first of all, and then decisions need to be made about how it is to be interpreted. For an excellent speaker \(em like an actor \(em these decisions will be artistic, at least in part. They should certainly depend upon the opinion and attitude of the speaker, and his perception of the structure and progress of the dialogue. Very little is known about this upper level of speech synthesis from text. In practice it is almost completely ignored \(em and the speech is at most barely intelligible, and certainly uncomfortable to listen to. Hence anybody contemplating building or using a speech output system which starts from something close to plain text should consider carefully whether some extra semantic information can be coded into the initial utterances to help with prosodic interpretation. Only rarely is this impossible \(em and reading machines for the blind are a prime example of a situation where arbitrary, unannotated, texts must be read. .rh "Intonation analysis." One distinction which a program can usefully try to make is between basically rising and basically falling pitch contours. It is often said that pitch rises on a question and falls on a statement, but if you listen to speech you will find this to be a gross oversimplification. It normally falls on statements, certainly; but it falls as often as it rises on questions. It is more accurate to say that pitch rises on "yes-no" questions and falls on other utterances, although this rule is still only a rough guide. A simple test which operates lexically on the input text is to determine whether a sentence is a question by looking at the punctuation mark at its end, and then to examine the first word. If it is a "wh"-word like "what", "which", "when", "why" (and also "how") a falling contour is likely to fit. If not, the question is probably a yes-no one, and the contour should rise. Such a crude rule will certainly not be very accurate (it fails, for example, when the "wh"-word is embedded in a phrase as in "at what time are you going?"), but at least it provides a starting-point. .pp An air of finality is given to an utterance when it bears a definite fall in pitch, dropping to a rather low value at the end. This should accompany the last intonation unit in an utterance (unless it is a yes-no question). However, a rise-fall contour such as Halliday's tone group 5 (Figure 8.5) can easily be used in utterance-final position by one person in a conversation \(em although it would be unlikely to terminate the dialogue altogether. A new topic is frequently introduced by a fall-rise contour \(em such as Halliday's tone group 4 \(em and this often begins a paragraph. .pp Determining the type of pitch contour is only one part of intonation assignment. There are really three separate problems: .LB .NP dividing the utterance into tone groups .NP choosing the tonic syllable, or major stress point, of each one .NP assigning a pitch contour to each tone group. .LE Let us continue to use the Halliday notation for intonation, which was introduced in simplified form in the previous chapter. Moreover, assume that the foot boundaries can be placed correctly \(em this problem will be discussed in the next subsection. Then a scheme which considers only the lexical form of the utterance and does not attempt to "understand" it (whatever that means) is as follows: .LB .NP place a tone group boundary at every punctuation mark .NP place the tonic at the first syllable of the last foot in a tone group .NP use contour 4 for the first tone group in a paragraph and contour 1 elsewhere, except for a yes-no question which receives contour 2. .LE .RF .nr x0 \w'From Scarborough to Whitby\0\0\0\0'+\w'4 ^ from /Scarborough to /*Whitby is a' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta \w'From Scarborough to Whitby\0\0\0\0\0\0'u plain text text adorned with prosodic markers \l'\n(x0u\(ul' .sp From Scarborough to Whitby is a 4 ^ from /Scarborough to /*Whitby is a very pleasant journey, with 1\- very /pleasant /*journey with very beautiful countryside. 1\- very /beautiful /*countryside ... In fact the Yorkshire coast is 1+ ^ in /fact the /Yorkshire /coast is \0\0\0\0lovely, \0\0\0\0/*lovely all along, ex- 1+ all a/*long ex cept the parts that are covered _4 cept the /parts that are /covered \0\0\0\0in caravans of course; and \0\0\0\0in /*caravans of /course and if you go in spring, 4 if you /go in /*spring when the gorse is out, 4 ^ when the /*gorse is /out or in summer, 4 ^ or in /*summer when the heather's out, 4 ^ when the /*heather's /out it's really one of the most 13 ^ it's /really /one of the /most \0\0\0\0delightful areas in the \0\0\0\0de/*lightful /*areas in the whole country. 1 whole /*country .sp The moorland is 4 ^ the /*moorland is rather high up, and 1 rather /high /*up and fairly flat \(em a 1 fairly /*flat a sort of plateau. 1 sort of /*plateau ... At least, 1 ^ at /*least it isn't really flat, 13 ^ it /*isn't /really /*flat when you get up on the top; \-3 ^ when you /get up on the /*top it's rolling moorland 1 ^ it's /rolling /*moorland cut across by steep valleys. But 1 cut across by /steep /*valleys but seen from the coast it's 4 seen from the /*coast it's ... "up there on the moors", and you 1 up there on the /*moors and you always think of it as a _4 always /*think of it as a kind of tableland. 1 kind of /*tableland \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 9.2 Example of intonation and rhythm analysis (from Halliday, 1970)" .[ Halliday 1970 Course in spoken English: Intonation .] .pp These extremely crude and simplistic rules are really the most that one can do without subjecting the utterance to a complicated semantic analysis. In statistical terms, they are actually remarkably effective. Table 9.2 shows part of a spontaneous monologue which was transcribed by Halliday and appears in his teaching text on intonation (Halliday, 1970, p 133). .[ Halliday 1970 Course in Spoken English: Intonation .] Among the prosodic markers are some that were not introduced in Chapter 8. Firstly, each tone group has secondary contours which are identified by "1+", "1\-" (for tone group 1), and so on. Secondly, the mark "..." is used to indicate a pause which disrupts the speech rhythm. Notice that its positioning belies the advice of the old elocutionists: .br .ev2 .in 0 .LB .fi A Comma stops the Voice while we may privately tell .NI .ul one, a Semi-colon .ul two; a Colon .ul three:\c and a Period .ul four. .br .nr x0 \w'\fIone,\fR a Semi-colon \fItwo;\fR a Colon \fIthree:\fR and a Period \fIfour.'-\w'(Mason,\fR 1748)' .NI \h'\n(x0u'(Mason, 1748) .nf .LE .br .ev Thirdly, compound tone groups such as "13" appear which contain .ul two tonic syllables. This differs from a simple concatenation of tone groups (with contours 1 and 3 in this case) because the second is in some sense subsidiary to the first. Typically it forms an adjunct clause, while the first clause gives the main information. Halliday provides many examples, such as .LB .NI /Jane goes /shopping in /*town /every /*Friday .NI /^ I /met /*Arthur on the /*train. .LE But he does not comment on the .ul acoustic difference between a compound tone group and a concatenation of simple ones \(em which is, after all, the information needed for synthesis. A final, minor, difference between Halliday's scheme and that outlined earlier is that he compels tone group boundaries to occur at the beginning of a foot. .RF .nr x0 3.3i+1.3i+\w'complete' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta 3.3i +1.3i excerpt in complete Table 9.2 passage \l'\n(x0u\(ul' .sp number of tone groups 25 74 .sp number of boundaries correctly 19 (76%) 47 (64%) placed .sp number of boundaries incorrectly \00 \01 (\01%) placed .sp number of tone groups having a 22 (88%) 60 (81%) tonic syllable at the beginning of the final foot .sp number of tone groups whose 17 (68%) 51 (69%) contours are correctly assigned \l'\n(x0u\(ul' .sp number of compound tone groups \02 (\08%) \06 (\08%) .sp number of secondary intonation \07 (28%) 13 (17%) contours \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 9.3 Success of simple intonation assignment rules" .pp Applying the simple rules given above to the text of Table 9.2 leads to the results in the first column of Table 9.3. Three-quarters of the foot boundaries are flagged by punctuation marks, with no extraneous ones being included. 88% of tone groups have a tonic syllable at the start of the final foot. However, the compound tone groups each have two tonic syllables, and of course only the second one is predicted by the final-foot rule. Assigning intonation contours on the extremely simple basis of using contour 4 for the first tone group in a paragraph, and contour 1 thereafter, also seems to work quite well. Secondary contours such as "1+" and "1\-" have been mapped into the appropriate primary contour (1, in this case) for the present purpose, and compound tone groups have been assigned the first contour of the pair. The result is that 68% of contours are given correctly. .pp In order to give some idea of the reliability of these figures, the results for the whole passage transcribed by Halliday \(em of which Table 9.2 is an excerpt \(em are shown in the second column of Table 9.3. Although it looks as though the rules may have been slightly lucky with the excerpt, the general trends are the same, with 65% to 80% of features being assigned correctly. It could be argued, though, that the complete text is punctuated fairly liberally by present-day standards, so that the tone-group boundary rule is unusually successful. .pp These results are really astonishingly good, considering the crudeness of the rules. However, they should be interpreted with caution. What is missed by the rules, although appearing to comprise only 20% to 35% of the features, is certain to include the important, information-bearing, and variety-producing features that give the utterance its liveliness and interest. It would be rash to assume that all tone-group boundaries, all tonic positions, and all intonation contours, are equally important for intelligibility and naturalness. It is much more likely that the rules predict a default pattern, while most information is borne by deviations from them. To give an engineering analogy, it may be as though the carrier waveform of a modulated transmission is being simulated, instead of the information-bearing signal! Certainly the utterance will, if synthesized with intonation given by these rules, sound extremely dull and repetitive, mainly because of the overwhelming predominance of tone group 1 and the universal placement of tonic stress on the final foot. .pp There are certainly many different ways to orate any particular text, and that given by Halliday and reproduced in Table 9.2 is only one possible version. However, it is fair to say that the default intonation discussed above could only occur naturally under very unusual circumstances \(em such as a petulant child, unwilling and sulky, having been forced to read aloud. This is hardly how we want our computers to speak! .rh "Rhythm analysis." Consider now how to decide where foot boundaries should be placed in English text. Clearly semantic considerations sometimes play a part in this \(em one could say .LB /^ is /this /train /going /*to /London .LE instead of the more usual .LB /^ is /this /train /going to /*London .LE in circumstances where the train might be going .ul to or .ul from London. Such effects are ignored here, although it is worth noting in passing that the rogue words will often be marked by underscoring or italicizing (as in the previous sentence). If the text is liberally underlined, semantic analysis may be unnecessary for the purposes of rhythm. .pp A rough and ready rule for placing foot boundaries is to insert one before each word which is not in a small closed set of "function words". The set includes, for example, "a", "and", "but", "for", "is", "the", "to". If a verb or adjective begins with a prefix, the boundary should be moved between it and the root \(em but not for a noun. This will give the distinction between .ul con\c vert (noun) and con\c .ul vert (verb), .ul ex\c tract and ex\c .ul tract, and for many North American speakers, will help to distinguish .ul in\c quiry from in\c .ul quire. However, detecting prefixes by a simple splitting algorithm is dangerous. For example, "predate" is a verb with stress on what appears to be a prefix, contrary to the rule; while the "pre" in "predator" is not a prefix \(em at least, it is not pronounced as the prefix "pre" normally is. Moreover, polysyllabic words like "/diplomat", "dip/lomacy", "diplo/matic"; or "/telegraph", "te/legraphy", "tele/graphic" cannot be handled on such a simple basis. .pp In 1968, a remarkable work on English sound structure was published (Chomsky and Halle, 1968) which proposes a system of rules to transform English text into a phonetic representation in terms of distinctive features, with the aid of a lexicon. .[ Chomsky Halle 1968 .] A great deal of attention is paid to stress, and rules are given which perform well in many tricky cases. .pp It uses the American system of levels of stress, marking so-called primary stress with a superscript 1, secondary stress with a superscript 2, and so on. The superscripts are written on the vowel of the stressed syllable: completely unstressed syllables receive no annotation. For example, the sentence "take John's blackboard eraser" is written .LB ta\u2\dke Jo\u3\dhn's bla\u1\dckboa\u5\drd era\u4\dser. .LE In foot notation this utterance is .LB /take /John's /*blackboard e/raser. .LE It undoubtedly contains less information than the stress-level version. For example, the second syllable of "blackboard" and the first one of "erase" are both unstressed, although the rhythm rules given in Chapter 8 will cause them to be treated differently because they occupy different places in the syllable pattern of the foot. "Take", "John's", and the second syllable of "erase" are all non-tonic foot-initial syllables and hence are not distinguished in the notation; although the pitch contours schematized in Figure 8.9 will give them different intonations. .pp An indefinite number of levels of stress can be used. For example, according to the rules given by Chomsky and Halle, the word "sad" in .LB my friend can't help being shocked at anyone who would fail to consider his sad plight .LE has level-8 stress, the final two words being annotated as "sa\u8\dd pli\u1\dght". However, only the first few levels are used regularly, and it is doubtful whether acoustic distinctions are made in speech between the weaker ones. .pp Chomsky and Halle are concerned to distinguish between such utterances as .LB .NI bla\u2\dck boa\u1\drd-era\u3\dser ("board eraser that is black") .NI bla\u1\dckboa\u3\drd era\u2\dser ("eraser for a blackboard") .NI bla\u3\dck boa\u1\drd era\u2\dser ("eraser of a black board"), .LE and their stress assignment rules do indeed produce each version when appropriate. In foot notation the distinctions can still be made: .LB .NI /black /*board-eraser/ .NI /*blackboard e/raser/ .NI /black /*board e/raser/ .LE .pp The rules operate on a grammatical derivation tree of the text. For instance, input for the three examples would be written .LB .NI [\dNP\u[\dA\u black ]\dA\u [\dN\u[\dN\u board]\dN\u [\dN\u eraser ]\dN\u]\dN\u]\dNP\u .NI [\dN\u[\dN\u[\dA\u black ]\dA\u [\dN\u board ]\dN\u]\dN\u [\dN\u eraser ]\dN\u]\dN\u .NI [\dN\u[\dNP\u[\dA\u black ]\dA\u [\dN\u board ]\dN\u]\dNP\u [\dN\u eraser ]\dN\u]\dN\u, .LE representing the trees shown in Figure 9.2. .FC "Figure 9.2" Here, N stands for a noun, NP for a noun phrase, and A for an adjective. These categories appear explicitly as nodes in the tree. In the linearized textual representation they are used to label brackets which represent the tree structure. An additional piece of information which is needed is the lexical entry for "eraser", which would show that it has only one accented (that is, potentially stressed) syllable, namely, the second. .pp Consider now how to account for stress in prefixed and suffixed words, and those polysyllabic ones with more than one potential stress point. For these, the morphological structure must appear in the input. .pp Now .ul morphemes are well-defined minimal units of grammatical analysis from which a word may be composed. For example, [went]\ =\ [go]\ +\ [ed] is a morphemic decomposition, where "[ed]" denotes the past-tense morpheme. This representation is not particularly suitable for speech synthesis for the obvious reason that the result bears no phonetic resemblance to the input. What is needed is a decomposition into .ul morphs, which occur only when the lexical or phonetic representation of a word may easily be segmented into parts. Thus [wanting]\ =\ [want]\ +\ [ing] and [bigger]\ =\ [big]\ +\ [er] are simultaneously morphic and morphemic decompositions. Notice that in the second example, a rule about final consonant doubling has been applied at the lexical level (although it is not needed in a phonetic representation): this comes into the sphere of "easy" segmentation. Contrast this with [went]\ =\ [go]\ +\ [ed] which is certainly not an easy segmentation and hence a morphemic but not a morphic decomposition. But between these extremes there are some difficult cases: [specific]\ =\ [specify]\ +\ [ic] is probably morphic as well as morphemic, but it is not clear that [galactic]\ =\ [galaxy]\ +\ [ic] is. .pp Assuming that the input is given as a derivation tree with morphological structure made explicit, Chomsky and Halle present rules which assign stress correctly in nearly all cases. For example, their rules give .LB .NI [\dA\u[\dN\u incident ]\dN\u + al]\dA\u \(em> i\u2\dncide\u1\dntal; .LE and if the stem is marked by [\dS\u\ ...\ ]\dS\u in prefixed words, they can deduce .LB .NI [\dN\u tele [\dS\u graph ]\dS\u]\dN\u \(em> te\u1\dlegra\u3\dph .NI [\dN\u[\dN\u tele [\dS\u graph ]\dS\u]\dN\u y ]\dN\u \(em> tele\u1\dgraphy .NI [\dA\u[\dN\u tele [\dS\u graph ]\dS\u]\dN\u ic ]\dA\u \(em> te\u3\dlegra\u1\dphi\u2\dc. .LE .pp There are two rules which account for the word-level stress on such examples: the "main stress" rule and the "alternating stress" rule. In essence, the main stress rule emphasizes the last strong syllable of a stem. A syllable is "strong" either if it contains one of a class of so-called "long" vowels, or if there is a cluster of two or more consonants following the vowel; otherwise it is "weak". (If you are exceptionally observant you will notice that this strong\(emweak distinction has been used before, when discussing the rhythm of feet in syllables.) Thus the verb "torment" receives stress on the second syllable, for it is a strong one. A noun like "torment" is treated as being derived from the corresponding verb, and the rule assigns stress to the verb first and then modifies it for the noun. The second, "alternating stress", rule gives some stress to alternate syllables of polysyllabic words like "form\c .ul al\c de\c .ul hyde\c ". .pp It is quite easy to incorporate the word-level rules into a computer program which uses feet rather than stress levels as the basis for prosodic description. A foot boundary is simply placed before the primary-stressed (level-1) syllable, except for function words, which do not begin a foot. The other stress levels should be ignored, except that for slow, deliberate speech, secondary (level-2) stress is mapped into a foot boundary too, if it precedes the primary stress. There is also a rule which reduces vowels in unstressed syllables. .pp The stress assignment rules can work on phonemic script, as well as English. For example, starting from the phonetic form [\d\V\u\ \c .ul aa\ s\ t\ o\ n\ i\ sh\ \c ]\dV\u, the stress assignment rules produce \c .ul aa\ s\ t\ o\u1\d\ n\ i\ sh\ ;\c the vowel reduction rule generates \c .ul uh\ s\ t\ o\u1\d\ n\ i\ sh\ ;\c and the foot conversion process gives \c .ul uh\ s/t\ o\ n\ i\ sh. This appears to provide a fairly reliable algorithm for foot boundary placement. .rh "Speech synthesis from concept." I argued earlier that in order to derive prosodic features of an utterance from text it is necessary to understand its role in the dialogue, its semantics, its syntax, and \(em as we have just seen \(em its morphological structure. This is a very tall order, and the problem of natural language comprehension by machine is a vast research area in its own right. However, in many applications requiring speech output, utterances are generated by the computer from internally stored data rather than being read aloud from pre-prepared text. Then the problem of comprehending text may be evaded, for presumably the language-generation module can provide a semantic, syntactic, and even morphological decomposition of the utterance, as well as some indication of its role in the dialogue (that is, why it is necessary to say it). .pp This forms the basis of the appealing notion of "speech synthesis from concept". It has some advantages over speech generation from text, and in principle should provide more natural-sounding speech. Every word produced by the system can have a complete lexical entry which shows its morphological decomposition and potential stress points. The full syntactic history of each utterance is known. The Chomsky-Halle rules described above can therefore be used to place foot boundaries accurately, without the need for a complex parsing program and without the risk of having to make guesses about unknown words. .pp However, it is not clear how to take advantage of any semantic information which is available. Ideally, it should be possible to place tone group boundaries and tonic stress points, and assign intonation contours, in a natural-sounding way. But look again at the example text of Table 9.2 and imagine that you have at your disposal as much semantic information as is needed. It is .ul still far from obvious how the intonation features could be assigned! It is, in the ultimate analysis, interpretive and stylistic .ul choices that add variety and interest to speech. .pp Take the problem of determining pitch contours, for instance. Some of them may be explicable. Contour 4 on .LB .NI except the parts that are covered in caravans of course .LE is due to its being a contrastive clause, for it presents essentially new information. Similarly, the succession .LB .NI if you go in spring .NI when the gorse is out .NI or in summer .NI when the heather's out .LE could be considered contrastive, being in the subjunctive voice, and this could explain why contour 4's were used. But this is all conjecture, and it is difficult to apply throughout the passage. Halliday (1970) explains the contexts in which each tone group is typically used, but in an extremely high-level manner which would be impossible to embody directly in a computer program. .[ Halliday 1970 Course in spoken English: Intonation .] At the other end of the spectrum, computer systems for written discourse production do not seem to provide the subtle information needed to make intonation decisions (see, for example, Davey, 1978, for a fairly complete description of such a system). .[ Davey 1978 .] .pp One project which uses such a method for generating speech has been described (Young and Fallside, 1980). .[ Young Fallside 1980 .] Although some attention is paid to rhythm, the intonation contours which are generated are disappointingly repetitive and lacking in richness. In fact, very little semantic information is used to assign contours; really just that inferred by the crude punctuation-driven method described earlier. .pp The higher-level semantic problems associated with speech output were studied some years go under the title "synthetic elocution" (Vanderslice, 1968). .[ Vanderslice 1968 .] A set of rules was generated and tested by hand on a sample passage, the first part of which is shown in Table 9.4. However, no attempt was made to formalize the rules in a computer program, and indeed it was recognized that a number of important questions, such as the form of the semantic information assumed at the input, had been left unanswered. .RF .nr x0 \w'\0\0 psychologist '+\w'emphasis assigned because of antithesis with ' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta \w'\0\0 psychologist 'u \l'\n(x0u\(ul' .sp Human experience and human behaviour are accessible to observation by everyone. The psychologist tries to bring them under systematic study. What he perceives, however, anyone can perceive; for his task he requires no microscope or electronic gear. .sp2 \0\0 word comments \l'\n(x0u\(ul' .sp \01 Human special treatment because paragraph-initial \04 human accent deleted because it echoes word 1 13 psychologist emphasis assigned because of antithesis with "everyone" 17 them anaphoric to "Human experience and human behaviour" 19 systematic emphasis assigned because of contrast with "observation" 20 study emphasis? \(em text is ambiguous whether "observation" is a kind of study that is nonsystematic, or an activity contrasting with the entire concept of "systematic study" 21 What increase in pitch for "What he perceives" because it is not the subject 22 he accented although anaphoric to word 13 because of antithesis with word 25 24 however decrease in pitch because it is parenthetical 25 anyone emphasized by antithesis with word 22 27 perceive unaccented because it echoes word 23, "perceives" \0\0 ; semicolon assigns falling intonation 30 task unaccented because it is anaphoric with "tries to bring them under systematic study" \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 9.4 Sample passage and comments pertinent to synthetic elocution" .pp The comments in the table, which are selected and slightly edited versions of those appearing in the original work (Vanderslice, 1968), are intended as examples of the nature and subtlety of the prosodic influences which were examined. .[ Vanderslice 1968 .] The concepts of "accent" and "emphasis" are used; these relate to stress but are not easy to define precisely in our tone-group terminology. Fortunately we do not need an exact characterization of them for the present purpose. Roughly speaking, "accent" encompasses both foot-initial stress and tonic stress, whereas "emphasis" is something more than this, typically being realized by the fall-rise or rise-fall contours of Halliday's tone groups 4 and 5 (Figure 8.5). .pp Particular attention is paid to anaphora and antithesis (amongst other things). The first term means the repetition of a word or phrase in the text, and is often applied to pronoun references. In the example, the word "human" is repeated in the first few words; "them" in the second sentence refers to "human experience and human behaviour"; "he" in the third sentence is the previously-mentioned psychologist; and "task" is anaphoric with "tries to bring them under systematic study". Other things being equal, anaphoric references are unaccented. In our terms this means that they certainly do not receive tonic stress and may not even receive foot stress. .pp Antithesis is defined as the contrast of ideas expressed by parallelism of strongly contrasting words or phrases; and the second element taking part in it is generally emphasized. "Psychologist" in the passage is an antithesis of "everyone"; "systematic" and possibly "study" of "observation". Thus .LB .NI /^ the psy/*chologist .LE would probably receive intonation contour 4, since it is also introducing a new actor; while .LB .NI /tries to /bring them /under /system/*matic /study .LE could receive contour 5. "He" and "everyone" are antithetical; not only does the latter receive emphasis but the former has its accent restored \(em for otherwise it would have been removed because of anaphora with "psychologist". Hence it will certainly begin a foot, possibly a tonic foot. .pp A factor that does not affect the sample passage is the accentuation of unusual syllables of similar words to bring out a contrast. For example, .LB .NI he went .ul out\c side, not .ul in\c side. .LE Although this may seem to be just another facet of antithesis, Vanderslice points out that it is phonetic rather than structural similarity that is contrasted: .LB .NI I said .ul de\c plane, not .ul com\c plain. .LE This introduces an interesting interplay between the phonetic and prosodic levels. .pp Anaphora and antithesis provide an ideal domain for speech synthesis from concept. Determining them from plain text is a very difficult problem, requiring a great deal of real-world knowledge. The first has received some attention in the field of natural language understanding. Finding pronoun referents is an important problem for language translation, for their gender is frequently distinguished in, say, French where it is not in English. Examples such as .LB .NI I bought the wine, sat on a table, and drank it .NI I bought the wine, sat on a table, and broke it .LE have been closely studied (Wilks, 1975); for if they were to be translated into French the pronoun "it" would be rendered differently in each case (\c .ul le vin, .ul la table). .[ Wilks 1975 An intelligent analyzer and understander of English .] .pp In spoken language, emphasis is used to indicate the referent of a pronoun when it would not otherwise be obvious. Vanderslice gives the example .LB .NI Bill saw John across the room and he ran over to him .NI Bill saw John across the room and .ul he ran over to .ul him, .LE where the emphasis reverses the pronoun referents (so that John did the running). He suggests accenting a personal pronoun whenever the true antecedent is not the same as the "unmarked" or default one. Unfortunately he does not elaborate on what is meant by "unmarked". Does it mean that the referent cannot be predicted from knowledge of the words alone \(em as in the second example above? If so, this is a clear candidate for speech synthesis from concept, for the distinction cannot be made from text! .sh "9.2 Pronunciation" .pp English pronunciation is notoriously irregular. A poem by Charivarius, the pseudonym of a Dutch high school teacher and linguist G.N.Trenite (1870\-1946), surveys the problems in an amusing way and is worth quoting in full. .br .ev2 .in 0 .LB "nnnnnnnnnnnnnnnn" .ul The Chaos .sp2 .ne4 Dearest creature in Creation Studying English pronunciation, .in +5n I will teach you in my verse Sounds like corpse, corps, horse and worse. .ne4 .in -5n It will keep you, Susy, busy, Make your head with heat grow dizzy; .in +5n Tear in eye your dress you'll tear. So shall I! Oh, hear my prayer: .ne4 .in -5n Pray, console your loving poet, Make my coat look new, dear, sew it. .in +5n Just compare heart, beard and heard, Dies and diet, lord and word. .ne4 .in -5n Sword and sward, retain and Britain, (Mind the latter, how it's written). .in +5n Made has not the sound of bade, Say \(em said, pay \(em paid, laid, but plaid. .ne4 .in -5n Now I surely will not plague you With such words as vague and ague, .in +5n But be careful how you speak: Say break, steak, but bleak and streak, .ne4 .in -5n Previous, precious; fuchsia, via; Pipe, shipe, recipe and choir; .in +5n Cloven, oven; how and low; Script, receipt; shoe, poem, toe. .ne4 .in -5n Hear me say, devoid of trickery; Daughter, laughter and Terpsichore; .in +5n Typhoid, measles, topsails, aisles; Exiles, similes, reviles; .ne4 .in -5n Wholly, holly; signal, signing; Thames, examining, combining; .in +5n Scholar, vicar and cigar, Solar, mica, war and far. .ne4 .in -5n Desire \(em desirable, admirable \(em admire; Lumber, plumber; bier but brier; .in +5n Chatham, brougham; renown but known, Knowledge; done, but gone and tone, .ne4 .in -5n One, anemone; Balmoral, Kitchen, lichen; laundry, laurel; .in +5n Gertrude, German; wind and mind; Scene, Melpemone, mankind; .ne4 .in -5n Tortoise, turquoise, chamois-leather, Reading, Reading; heathen, heather. .in +5n This phonetic labyrinth Gives: moss, gross; brook, brooch; ninth, plinth. .ne4 .in -5n Billet does not end like ballet; Bouquet, wallet, mallet, chalet; .in +5n Blood and flood are not like food, Nor is mould like should and would. .ne4 .in -5n Banquet is not nearly parquet, Which is said to rime with darky .in +5n Viscous, viscount; load and broad; Toward, to forward, to reward. .ne4 .in -5n And your pronunciation's O.K. When you say correctly: croquet; .in +5n Rounded, wounded; grieve and sieve; Friend and fiend, alive and live .ne4 .in -5n Liberty, library; heave and heaven; Rachel, ache, moustache; eleven. We say hallowed, but allowed; People, leopard; towed, but vowed. .in +5n Mark the difference moreover Between mover, plover, Dover; .ne4 .in -5n Leeches, breeches; wise, precise; Chalice, but police and lice. .in +5n Camel, constable, unstable, Principle, discipline, label; .ne4 .in -5n Petal, penal and canal; Wait, surmise, plait, promise; pal. .in +5n Suit, suite, ruin; circuit, conduit, Rime with: "shirk it" and "beyond it"; .ne4 .in -5n But it is not hard to tell Why it's pall, mall, but Pall Mall. .in +5n Muscle, muscular; goal and iron; Timber, climber; bullion, lion; .ne4 .in -5n Worm and storm; chaise, chaos, chair; Senator, spectator, mayor. .in +5n Ivy, privy; famous, clamour and enamour rime with "hammer". .ne4 .in -5n Pussy, hussy and possess, Desert, but dessert, address. .in +5n Golf, wolf; countenants; lieutenants Hoist, in lieu of flags, left pennants. .ne4 .in -5n River, rival; tomb, bomb, comb; Doll and roll, and some and home. .in +5n Stranger does not rime with anger, Neither does devour with clangour. .ne4 .in -5n Soul, but foul; and gaunt, but aunt; Font, front, won't; want, grand and grant; .in +5n Shoes, goes, does. Now first say: finger, And then; singer, ginger, linger. .ne4 .in -5n Real, zeal; mauve, gauze and gauge; Marriage, foliage, mirage, age. .in +5n Query does not rime with very, Nor does fury sound like bury. .ne4 .in -5n Dost, lost, post; and doth, cloth, loth; Job, Job; blossom, bosom, oath. .in +5n Though the difference seems little We say actual, but victual; .ne4 .in -5n Seat, sweat; chaste, caste; Leigh, eight, height; Put, nut; granite but unite. .in +5n Reefer does not rime with deafer, Feoffer does, and zephyr, heifer. .ne4 .in -5n Dull, bull; Geoffrey, George; ate, late; Hint, pint; senate, but sedate. .in +5n Scenic, Arabic, Pacific; Science, conscience, scientific. .ne4 .in -5n Tour, but our, and succour, four; Gas, alas and Arkansas! .in +5n Sea, idea, guinea, area, Psalm, Maria, but malaria. .ne4 .in -5n Youth, south, southern; cleanse and clean; Doctrine, turpentine, marine. .in +5n Compare alien with Italian. Dandelion with battalion, .ne4 .in -5n Sally with ally, Yea, Ye, Eye, I, ay, aye, whey, key, quay. Say aver, but ever, fever, Neither, leisure, skein, receiver. .in +5n Never guess \(em it is not safe; We say calves, valves, half, but Ralf. .ne4 .in -5n Heron, granary, canary; Crevice and device and eyrie; .in +5n Face, preface, but efface, Phlegm, phlegmatic; ass, glass, bass; .ne4 .in -5n Large, but target, gin, give, verging; Ought, out, joust and scour, but scourging; .in +5n Ear, but earn; and wear and tear Do not rime with "here", but "ere". .ne4 .in -5n Seven is right, but so is even; Hyphen, roughen, nephew, Stephen; .in +5n Monkey, donkey; clerk and jerk; Asp, grasp, wasp; and cork and work. .ne4 .in -5n Pronunciation \(em think of psyche - Is a paling, stout and spikey; .in +5n Won't it make you lose your wits, Writing groats and saying "groats"? .ne4 .in -5n It's a dark abyss or tunnel, Strewn with stones, like rowlock, gunwale, .in +5n Islington and Isle of Wight, Housewife, verdict and indict. .ne4 .in -5n Don't you think so, reader, rather Saying lather, bather, father? .in +5n Finally: which rimes with "enough", Though, through, plough, cough, hough or tough? .ne4 .in -5n Hiccough has the sound of "cup", My advice is ... give it up! .LE "nnnnnnnnnnnnnnnn" .br .ev .rh "Letter-to-sound rules." Despite such irregularities, it is surprising how much can be done with simple letter-to-sound rules. These specify phonetic equivalents of word fragments and single letters. The longest stored fragment which matches the current word is translated, and then the same strategy is adopted on the remainder of the word. Table 9.5 shows some English fragments and their pronunciations. .RF .nr x0 1.5i+\w'pronunciation ' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta 1.5i fragment pronunciation \l'\n(x0u\(ul' .sp -p- \fIp\fR -ph- \fIf\fR -phe| \fIf ee\fR -phe|s \fIf ee z\fR -phot- \fIf uh u t\fR -place|- \fIp l e i s\fR -plac|i- \fIp l e i s i\fR -ple|ment- \fIp l i m e n t\fR -plie|- \fIp l aa i y\fR -post \fIp uh u s t\fR -pp- \fIp\fR -pp|ly- \fIp l ee\fR -preciou- \fIp r e s uh\fR -proce|d- \fIp r uh u s ee d\fR -prope|r- \fIp r o p uh r\fR -prov- \fIp r uu v\fR -purpose- \fIp er p uh s\fR -push- \fIp u sh\fR -put \fIp u t\fR -puts \fIp u t s\fR \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 9.5 Word fragments and their pronunciations" .pp It is sometimes important to specify that a rule applies only when the fragment is matched at the beginning or end of a word. In the Table "-" means that other fragments can precede or follow this one. The "|" sign is used to separate suffixes from a word stem, as will be explained shortly. .pp An advantage of the longest-string search strategy is that it is easy to account for exceptions simply by incorporating them into the fragment table. If they occur in the input, the complete word will automatically be matched first, before any fragment of it is translated. The exception list of complete words can be surprisingly small for quite respectable performance. Table 9.6 shows the entire dictionary for an excellent early pronunciation system written at Bell Laboratories (McIlroy, 1974). .[ McIlroy 1974 .] Some of the words are notorious exceptions in English, while others are included simply because the rules would run amok on them. Notice that the exceptions are all quite short, with only a few of them having more than two syllables. .RF .nr x1 0.9i+0.9i+0.9i+0.9i+0.9i+0.9i .nr x1 (\n(.l-\n(x1)/2 .in \n(x1u .ta 0.9i +0.9i +0.9i +0.9i +0.9i a doesn't guest meant reader those alkali doing has moreover refer to always done have mr says today any dr having mrs seven tomorrow april early heard nature shall tuesday are earn his none someone two as eleven imply nothing something upon because enable into nowhere than very been engine is nuisance that water being etc island of the wednesday below evening john on their were body every july once them who both everyone live one there whom busy february lived only thereby whose copy finally living over these woman do friday many people they women does gas maybe read this yes .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 9.6 Exception table for a simple pronunciation program" .pp Special action has to be taken with final "e"'s. These lengthen and alter the quality of the preceding vowel, so that "bit" becomes "bite" and so on. Unfortunately, if the word has a suffix the "e" must be detected even though it is no longer final, as in "lonely", and it is even dropped sometimes ("biting") \(em otherwise these would be pronounced "lonelly", "bitting". To make matters worse the suffix may be another word: we do not want "kiteflying" to have an extra syllable which rhymes with "deaf"! Although simple procedures can be developed to take care of common word endings like "-ly", "-ness", "-d", it is difficult to decompose compound words like "wisecrack" and "bumblebee" reliably \(em but this must be done if they are not to be articulated with three syllables instead of two. Of course, there are exceptions to the final "e" rule. Many common words ("some", "done", "[live]\dV\u") disobey the rule by not lengthening the main vowel, while in other, rarer, ones ("anemone", "catastrophe", "epitome") the final "e" is actually pronounced. There are also some complete anomalies ("fete"). .pp McIlroy's (1974) system is a superb example of a robust program which takes a pragmatic approach to these problems, accepting that they will never be fully solved, and which is careful to degrade gracefully when stumped. .[ McIlroy 1974 .] The pronunciation of each word is found by a succession of increasingly desperate trials: .LB .NP replace upper- by lower-case letters, strip punctuation, and try again; .NP remove final "-s", replace final "ie" by "y", and try again; .NP reject a word without a vowel; .NP repeatedly mark any suffixes with "|"; .NP mark with "|" probable morph divisions in compound words; .NP mark potential long vowels indicated by "e|", and long vowels elsewhere in the word; .NP mark voiced medial "s" as in "busy", "usual"; replace final "-s" if stripped; .NP scanning the word from left to right, apply letter-to-sound rules to word fragments; .NP when all else fails spell the word, punctuation and all (burp on letters for which no spelling rule exists). .LE .RF .nr x0 \w'| ment\0\0\0'+\w'replace final ie by y\0\0\0'+\w'except when no vowel would remain in ' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta \w'| ment\0\0\0'u +\w'replace final ie by y\0\0\0'u suffix action notes and exceptions \l'\n(x0u\(ul' .sp s strip off final s except in context us \&' strip off final ' ie replace final ie by y e replace final e by E when it is the only vowel in a word (long "e") | able place suffix mark as except when no vowel would remain in | ably shown the rest of the word e | d e | n e | r e | ry e | st e | y | ful | ing | less | ly | ment | ness | or | ic place suffix mark as | ical shown and terminate e | final e processing \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 9.7 Rules for detecting suffixes for final 'e' processing" .pp Table 9.7 shows the suffixes which the program recognizes, with some comments on their processing. Multiple suffixes are detected and marked in words like "force|ful|ly" and "spite|ful|ness". This allows silent "e"'s to be spotted even when they occur far back in a word. Notice that the suffix marks are available to the word-fragment rules of Table 9.5, and are frequently used by them. .pp The program has some .ul ad hoc rules for dealing with compound words like "race|track", "house|boat"; these are applied as well as normal suffix splitting so that multiple decompositions like "pace|make|r" can be accomplished. The rules look for short letter sequences which do not usually appear in monomorphemic words. It is impossible, however, to detect every morph boundary by such rules, and the program inevitably makes mistakes. Examples of boundaries which go undetected are "edge|ways", "fence|post", "horse|back", "large|mouth", "where|in"; while boundaries are incorrectly inserted into "comple|mentary", "male|volent", "prole|tariat", "Pame|la". .pp We now seem to have presented two opposing points of view on the pronunciation problem. Charivarius, the Dutch poet, shows that an enormous number of exceptional words exist; whereas McIlroy's program makes do with a tiny exception dictionary. These views can be reconciled by noting that most of Charivarius' words are relatively uncommon. McIlroy tested his program against the 2000 most frequent words in a large corpus (Kucera and Francis, 1967), and found that 97% were pronounced correctly if word frequencies were taken into account. .[ Kucera Francis 1967 .] (The notion of "correctness" is of course a rather subjective one.) However, he estimated that on the remaining words the success rate was only 88%. .pp The system is particularly impressive in that it is prepared to say anything: if used, for example, on source programs in a high-level computer language it will say the keywords and pronouncable identifiers, spell the other identifiers, and even give the names of special symbols (like +, <, =) correctly! .rh "Morphological analysis." The use of letter-to-sound rules provides a cheap and fast technique for pronunciation \(em the fragment table and exception dictionary for the program described above occupy only 11 Kbyte of storage, and can easily be kept in solid-state read-only memory. It produces reasonable results if careful attention is paid to rules for suffix-splitting. However, it is inherently limited because it is not possible in general to detect compound words by simple rules which operate on the lexical structure of the word. .pp Compounds can only be found reliably by using a morph dictionary. This gives the added advantage that syntactic information can be stored with the morphs to assist with rhythm assignment according to the Chomsky-Halle theory. However, it was noted earlier that morphs, unlike the grammatically-determined morphemes, are not very well defined from a linguistic point of view. Some morphemic decompositions are obviously not morphic because the constituents do not in any way resemble the final word; while others, where the word is simply a concatenation of its components, are clearly morphic. Between these extremes lies a hazy region where what one considers to be a morph depends upon how complex one is prepared to make the concatenation rules. The following description draws on techniques used in a project at MIT in which a morph-based pronunciation system has been implemented (Lee, 1969; Allen, 1976). .[ Lee 1969 .] .[ Allen 1976 Synthesis of speech from unrestricted text .] .pp Estimates of the number of morphs in English vary from 10,000 to 30,000. Although these seem to be very large numbers, they are considerably less than the number of words in the language. For example, Webster's .ul New Collegiate Dictionary (7'th edition) contains about 100,000 entries. If all forms of the words were included, this number would probably double. .pp There are several classes of morphs, with restrictions on the combinations that occur. A general word has prefixes, a root, and suffixes, as shown in Figure 9.3; only the root is mandatory. .FC "Figure 9.3" Suffixes usually perform a grammatical role, affecting the conjugation of a verb or declension of a noun; or transforming one part of speech into another ("-al" can make a noun into an adjective, while "-ness" performs the reverse transformation.) Other suffixes, such as "-dom" or "-ship", only apply to certain parts of speech (nouns, in this case), but do not change the grammatical role of the word. Such suffixes, and all prefixes, alter the meaning of a word. .pp Some root morphs cannot combine with other morphs but always stand alone \(em for instance, "this". Others, called free morphs, can either occur on their own or combine with further morphs to form a word. Thus the root "house" can be joined on either side by another root, such as "boat", or by a suffix such as "ing". A third type of root morph is one which .ul must combine with another morph, like "crimin-", "-ceive". .pp Even with a morph dictionary, decomposing a word into a sequence of morphs is not a trivial operation. The process of lexical concatenation often results in a minor change in the constituents. How big this change is allowed to be governs the morph system being used. For example, Allen (1976) gives three concatenation rules: a final "e" can be omitted, as in .ta 1.1i .LB .NI give + ing \(em> giving; .LE the last consonant of the root can be doubled, as in .LB .NI bid + ing \(em> bidding; .LE or a final "y" can change to an "i", as in .LB .NI handy + cap \(em> handicap. .[ Allen 1976 Synthesis of speech from unrestricted text .] .LE If these are the only rules permitted, the morph dictionary will have to include multiple versions of some suffixes. For example, the plural morpheme [-s] needs to be represented both by "-s" and "-es", to account for .LB .NI pea + s \(em> peas .LE and .LB .NI baby + es \(em> babies (using the "y" \(em> "i" rule). .LE This would not be necessary if a "y" \(em> "ie" rule were included too. Similarly, the morpheme [-ic] will include morphs "-ic" and "-c"; the latter to cope with .LB .NI specify + c \(em> specific (using the "y" \(em> "i" rule). .LE Furthermore, non-morphemic roots such as "galact" need to be included because the concatenation rules do not capture the transformation .LB .NI galaxy + ic \(em> galactic. .LE There is clearly a trade-off between the size of the morph dictionary and the complexity of the concatenation rules. .pp Since a text-to-speech system is presented with already-concatenated morphs, it must be prepared to reverse the effects of the concatenation rules to deduce the constituents of a word. When two morphs combine with any of the three rules given above, the changes in spelling occur only in the lefthand one. Therefore the word is best scanned in a right-to-left direction to split off the morphs starting with suffixes, as McIlroy's program does. If the procedure fails at any point, one of the three rules is hypothesized, its effect is undone, and splitting continues. For example, consider the word .LB .NI grasshoppers <\(em grass + hop + er + s .LE (Lee, 1969). .[ Lee 1969 .] The "-s" is detected first, then "-er"; these are both stored in the dictionary as suffixes. The remainder, "grasshopp", cannot be decomposed and does not appear in the dictionary. So each of the rules above is hypothesized in turn, and the result investigated. (The "y" \(em> "i" rule is obviously not applicable.) When the final-consonant-doubling rule is considered, the sequence "grasshop" is investigated. "Shop" could be split off this, but then the unknown morph "gras" would result. The alternative, to remove "hop", leaves a remainder "grass" which .ul is a free morph, as desired. Thus a unique and correct decomposition is obtained. Notice that the procedure would fail if, for example, "grass" had been inadvertently omitted from the dictionary. .pp Sometimes, several seemingly valid decompositions present themselves (Allen, 1976). .[ Allen 1976 Synthesis of speech from unrestricted text .] For example: .LB .NI scarcity <\(em scar + city .NI <\(em scarce + ity (using final-"e" deletion) .NI <\(em scar + cite + y (using final-"e" deletion) .NI resting <\(em rest + ing .NI <\(em re + sting .NI biding <\(em bide + ing (using final-"e" deletion) .NI <\(em bid + ing .NI unionized <\(em un + ion + ize + d .NI <\(em union + ize + d .NI winding <\(em [wind]\dN\u + ing .NI <\(em [wind]\dV\u + ing. .LE The last distinction is important because the pronunciation of "wind" depends on whether it is a noun or a verb. .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .pp Several sources of information can be used to resolve these ambiguities. The word structure of Figure 9.3, together with the division of root morphs into bound and free ones, may eliminate some possibilities. Certain letter sequences (such as "rp") do not appear at the beginning of a word or morph, and others never occur at the end. Knowledge of these sequences can reject some unacceptable decompositions \(em or perhaps more importantly, can enable intelligent guesses to be made in cases where a constituent morph has been omitted from the dictionary. The grammatical function of suffixes allows suffix sequences to be checked for compatibility. The syntax of the sentence, together with suffix knowledge, can rule out other combinations. Semantic knowledge will occasionally be necessary (as in the "unionized" and "winding" examples above \(em compare a "winding road" with a "winding blow"). Finally, Allen (1976) suggests that a preference structure on composition rules can be used to resolve ambiguity. .[ Allen 1976 Synthesis of speech from unrestricted text .] .pp Once the morphological structure has been determined, the rest of the pronunciation process is relatively easy. A phonetic transcription of each morph may be stored in the morph dictionary, or else letter-to-sound rules can be used on individual morphs. These are likely to be quite successful because final-"e" processing can be now be done with confidence: there are no hidden final "e"'s in the middle of morphs. In either case the resulting phonetic transcriptions of the individual morphs must be concatenated to give the transcription of the complete word. Although some contextual modification has to be accounted for, it is relatively straightforward and easy to predict. For example, the plural morphs "-s" and "-es" can be realized phonetically by .ul uh\ z, .ul s, or .ul z depending on context. Similarly the past-tense suffix "-ed" may be rendered as .ul uh\ d, .ul t, or .ul d. The suffixes "-ion" and "-ure" sometimes cause modification of the previous morph: for example .LB .NI act + ion \(em> \c .ul a k t\c + ion \(em> \c .ul a k sh uh n. .LE .pp The morph dictionary does not remove the need for a lexicon of exceptional words. The irregular final-"e" words mentioned earlier ("done", "anemone", "fete") need to be treated on an individual basis, as do words such as "quadruped" which have misleading endings (it should not be decomposed as "quadrup|ed"). .rh "Pronunciation of languages other than English." Text-to-speech systems for other languages have been reported in the literature. (For example, French, Esperanto, Italian, Russian, Spanish, and German are covered by Lesmo .ul et al, 1978; O'Shaughnessy .ul et al, 1981; Sherwood, 1978; Mangold and Stall, 1978). .[ Lesmo 1978 .] .[ O'Shaughnessy Lennig Mermelstein Divay 1981 .] .[ Sherwood 1978 .] .[ Mangold Stall 1978 .] Generally speaking, these present fewer difficulties than does English. Esperanto is particularly easy because each letter in its orthography has only one sound, making the pronunciation problem trivial. Moreover, stress in polysyllabic words always occurs on the penultimate syllable. .pp It is tempting and often sensible when designing a synthesis system for English to use an utterance representation somewhere between phonetics and ordinary spelling. This may happen in practice even if it is not intended: a user, finding that a given word is pronounced incorrectly, will alter the spelling to make it work. The Word English Spelling alphabet (Dewey, 1971), amongst others (Haas, 1966), is a simplified and apparently natural scheme which was developed by the spelling reform movement. .[ Dewey 1971 .] .[ Haas 1966 .] It maps very simply on to a phonetic representation, just like Esperanto. However, it can provide little help with the crucial problem of stress assignment, except perhaps by explicitly indicating reduced vowels. .sh "9.3 Discussion" .pp This chapter has really only touched the tip of a linguistic iceberg. I have given some examples of representations, rules, algorithms, and exceptions, to make the concepts more tangible; but a whole mass of detail has been swept under the carpet. .pp There are two important messages that are worth reiterating once more. The first is that the representation of the input \(em that is, whether it be a "concept" in some semantic domain, a syntactic description of an utterance, a decomposition into morphs, plain text or some contrived re-spelling of it \(em is crucial to the quality of the output. Almost any extra information about the utterance can be taken into account and used to improve the speech. It is difficult to derive such information if it is not provided explicitly, for the process of climbing the tree from text to semantic representation is at least as hard as descending it to a phonetic transcription. .pp Secondly, simple algorithms perform remarkably well \(em witness the punctuation-driven intonation assignment scheme, and word fragment rules for pronunciation. However, the combined degradation contributed by several imperfect processes is likely to impair speech quality very seriously. And great complexity is introduced when these simple algorithms are discarded in favour of more sophisticated ones. There is, for example, a world of difference between a pronunciation program that copes with 97% of common words and one that deals correctly with 99% of a random sample from a dictionary. .pp Some of the options that face the system designer are recapitulated in Figure 9.4. .FC "Figure 9.4" Starting from text, one can take the simple approach of lexically-based suffix-splitting, letter-to-sound rules, and prosodics derived from punctuation, to generate a phonetic transcription. This will provide a cheap system which is relatively easy to implement but whose speech quality will probably not be acceptable to any but the most dedicated listener (such as a blind person with no other access to reading material). .pp The biggest improvement in speech quality from such a system would almost certainly come from more intelligent prosodic control \(em particularly of intonation. This, unfortunately, is also by far the most difficult to make unless intonation contours, tonic stresses, and tone-group boundaries are hand-coded into the input. To generate the appropriate information from text one has to climb to the upper levels in Figure 9.4 \(em and even when these are reached, the problems are by no means over. Still, let us climb the tree. .pp For syntax analysis, part-of-speech information is needed; and for this the grammatical roles of individual words in the text must be ascertained. A morph dictionary is the most reliable way to do this. A linguist may prefer to go from morphs to syntax by way of morphemes; but this is not necessary for the present purpose. Just the information that the morph "went" is a verb can be stored in the dictionary, instead of its decomposition [went]\ =\ [go]\ +\ [ed]. .pp Now that we have the morphological structure of the text, stress assignment rules can be applied to produce more accurate speech rhythms. The morph decomposition will also allow improvements to be made to the pronunciation, particularly in the case of silent "e"'s in compound words. But the ability to assign intonation has hardly been improved at all. .pp Let us proceed upwards. Now the problems become really difficult. A semantic representation of the text is needed; but what exactly does this mean? We certainly must have .ul morphemic knowledge, for now the fact that "went" is a derivative of "go" (rather than any other verb) becomes crucial. Very well, let us augment the morph dictionary with morphemic information. But this does not attack the problem of semantic representation. We may wish to resolve pronoun references to help assign stress. Parts of the problem are solved in principle and reported in the artificial intelligence literature, but if such an ability is incorporated into the speech synthesis system it will become enormously complicated. In addition, we have seen that knowledge of antitheses in the text will greatly assist intonation assignment, but procedures for extracting this information constitute a research topic in their own right. .pp Now step back and take a top-down approach. What could we do with this semantic understanding and knowledge of the structure of the discourse if we had it? Suppose the input were a "concept" in some as yet undetermined representation. What are the .ul acoustic manifestations of such high-level features as anaphoric references or antithetical comparisons, of parenthetical or satirical remarks, of emotions: warmth, sarcasm, sadness and despair? Can we program the art of elocution? These are good questions. .sh "9.4 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "9.5 Further reading" .pp Books on pronunciation give surprisingly little help in designing a text-to-speech procedure. The best aid is a good on-line dictionary and flexible software to search it and record rules, examples, and exceptions. Here are some papers that describe existing systems. .LB "nn" .\"Ainsworth-1974-1 .]- .ds [A Ainsworth, W.A. .ds [D 1974 .ds [T A system for converting text into speech .ds [J IEEE Trans Audio and Electroacoustics .ds [V AU-21 .ds [P 288-290 .nr [P 1 .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n .in-2n .\"Colby-1978-2 .]- .ds [A Colby, K.M. .as [A ", Christinaz, D. .as [A ", and Graham, S. .ds [D 1978 .ds [K * .ds [T A computer-driven, personal, portable, and intelligent speech prosthesis .ds [J Computers and Biomedical Research .ds [V 11 .ds [P 337-343 .nr [P 1 .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n .in-2n .\"Elovitz-1976-3 .]- .ds [A Elovitz, H.S. .as [A ", Johnson, R.W. .as [A ", McHugh, A. .as [A ", and Shore, J.E. .ds [D 1976 .ds [K * .ds [T Letter-to-sound rules for automatic translation of English text to phonetics .ds [J IEEE Trans Acoustics, Speech and Signal Processing .ds [V ASSP-24 .ds [N 6 .ds [P 446-459 .nr [P 1 .ds [O December .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n .in-2n .\"Kooi-1978-4 .]- .ds [A Kooi, R. .as [A " and Lim, W.C. .ds [D 1978 .ds [T An on-line minicomputer-based system for reading printed text aloud .ds [J IEEE Trans Systems, Man and Cybernetics .ds [V SMC-8 .ds [P 57-62 .nr [P 1 .ds [O January .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n .in-2n .\"Umeda-1975-5 .]- .ds [A Umeda, N. .as [A " and Teranishi, R. .ds [D 1975 .ds [K * .ds [T The parsing program for automatic text-to-speech synthesis developed at the Electrotechnical Laboratory in 1968 .ds [J IEEE Trans Acoustics, Speech and Signal Processing .ds [V ASSP-23 .ds [N 2 .ds [P 183-188 .nr [P 1 .ds [O April .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n .in-2n .\"Umeda-1976-6 .]- .ds [A Umeda, N. .ds [D 1976 .ds [K * .ds [T Linguistic rules for text-to-speech synthesis .ds [J Proc IEEE .ds [V 64 .ds [N 4 .ds [P 443-451 .nr [P 1 .ds [O April .nr [T 0 .nr [A 1 .nr [O 0 .][ 1 journal-article .in+2n .in-2n .LE "nn" .EQ delim $$ .EN .CH "10 DESIGNING THE MAN-COMPUTER DIALOGUE" .ds RT "The man-computer dialogue .ds CX "Principles of computer speech .pp Interactive computers are being used more and more by non-specialist people without much previous computer experience. As processing costs continue to decline, the overall expense of providing highly interactive systems becomes increasingly dominated by terminal and communications equipment. Taken together, these two factors highlight the need for easy-to-use, low-bandwidth interactive terminals that make maximum use of the existing telephone network for remote access. .pp Speech output can provide versatile feedback from a computer at very low cost in distribution and terminal equipment. It is attractive from several points of view. Terminals \(em telephones \(em are invariably in place already. People without experience of computers are accustomed to their use, and are not intimidated by them. The telephone network is cheap to use and extends all over the world. The touch-tone keypad (or a portable tone generator) provides a complementary data input device which will do for many purposes until the technology of speech recognition becomes better developed and more widespread. Indeed, many applications \(em especially information retrieval ones \(em need a much smaller bandwidth from user to computer than in the reverse direction, and voice output combined with restricted keypad entry provides a good match to their requirements. .pp There are, however, severe problems in implementing natural and useful interactive systems using speech output. The eye can absorb information at a far greater rate than can the ear. You can scan a page of text in a way which has no analogy in auditory terms. Even so, it is difficult to design a dialogue which allows you to search computer output visually at high speed. In practice, scanning a new report is often better done at your desk with a printed copy than at a computer terminal with a viewing program (although this is likely to change in the near future). .pp With speech, the problem of organizing output becomes even harder. Most of the information we learn using our ears is presented in a conversational way, either in face-to-face discussions or over the telephone. Verbal but non-conversational presentations, as in the university lecture theatre, are known to be a rather inefficient way of transmitting information. The degree of interaction is extremely high even in a telephone conversation, and communication relies heavily on speech gestures such as hesitations, grunts, and pauses; on prosodic features such as intonation, pitch range, tempo, and voice quality; and on conversational gambits such as interruption and long silence. I emphasized in the last two chapters the rudimentary state of knowledge about how to synthesize prosodic features, and the situation is even worse for the other, paralinguistic, phenomena. .pp There is also a very special problem with voice output, namely, the transient nature of the speech signal. If you miss an utterance, it's gone. With a visual display unit, at least the last few interactions usually remain available. Even then, it is not uncommon to look up beyond the top of the screen and wish that more of the history was still visible! This obviously places a premium on a voice response system's ability to repeat utterances. Moreover, the dialogue designer must do his utmost to ensure that the user is always aware of the current state of the interaction, for there is no opportunity to refresh the memory by glancing at earlier entries and responses. .pp There are two separate aspects to the man-computer interface in a voice response system. The first is the relationship between the system and the end user, that is, the "consumer" of the synthesized dialogue. The second is the relationship between the system and the applications programmer who creates the dialogue. These are treated separately in the next two sections. We will have more to say about the former aspect, for it is ultimately more important to more people. But the applications programmer's view is important, too; for without him no systems would exist! The technical difficulties in creating synthetic dialogues for the majority of voice systems probably explain why speech output technology is still greatly under-used. Finally we look at techniques for using small keypads such as those on touch-tone telephones, for they are an essential part of many voice response systems. .sh "10.1 Programming principles for natural interaction" .pp Special attention must be paid to be details of the man-machine interface in speech-output systems. This section summarizes experience of human factors considerations gained in developing the remote telephone enquiry service described in Chapter 1 (Witten and Madams, 1977), which employs an ordinary touch-tone keypad for input in conjunction with synthetic voice response. .[ Witten Madams 1977 Telephone Enquiry Service .] Most of the principles which emerged were the result of natural evolution of the system, and were not clear at the outset. Basically, they stem from the fact that speech is both more intrusive and more ephemeral than writing, and so they are applicable in general to speech output information retrieval systems with keyboard or even voice input. Be warned, however, that they are based upon casual observation and speculation rather than empirical research. There is a desperate need for proper studies of user psychology in speech systems. .rh "Echoing." Most alphanumeric input peripherals echo on a character-by-character basis. Although one can expect quite a high proportion of mistakes with unconventional keyboards, especially when entering alphabetic data on a basically numeric keypad, audio character echoing is distracting and annoying. If you type "123" and the computer echoes .LB .NI "one ... two ... three" .LE after the individual key-presses, it is liable to divert your attention, for voice output is much more intrusive than a purely visual "echo". .pp Instead, an immediate response to a completed input line is preferable. This response can take the form or a reply to a query, or, if successive data items are being typed, confirmation of the data entered. In the latter case, it is helpful if the information can be generated in the same way that the user himself would be likely to verbalize it. Thus, for example, when entering numbers: .LB .nr x0 \w'COMPUTER:' .nr x1 \w'USER:' .NI USER:\h'\n(x0u-\n(x1u' "123#" (# is the end-of-line character) .NI COMPUTER: "One hundred and twenty-three." .LE For a query which requires lengthy processing, the input should be repeated in a neat, meaningful format to give the user a chance to abort the request. .rh "Retracting actions." Because commands are entered directly without explicit confirmation, it must always be easy for the user to revoke his actions. The utility of an "undo" command is now commonly recognized for any interactive system, and it becomes even more important in speech systems because it is easier for the user to lose his place in the dialogue and so make errors. .rh "Interrupting." A command which interrupts output and returns to a known state should be recognized at every level of the system. It is essential that voice output be terminated immediately, rather than at the end of the utterance. We do not want the user to live in fear of the system embarking on a long, boring monologue that is impossible to interrupt! Again, the same is true of interactive dialogues which do not use speech, but becomes particularly important with voice response because it takes longer to transmit information. .rh "Forestalling prompts." Computer-generated prompts must be explicit and frequent enough to allow new users to understand what they are expected to do. Experienced users will "type ahead" quite naturally, and the system should suppress unnecessary prompts under these conditions by inspecting the input buffer before prompting. This allows the user to concatenate frequently-used commands into chunks whose size is entirely at his own discretion. .pp With the above-mentioned telephone enquiry service, for example, it was found that people often took advantage of the prompt-suppression feature to enter their user number, password, and required service number as a single keying sequence. As you becomes familiar with a service you quickly and easily learn to forestall expected prompts by typing ahead. This provides a very natural way for the system to adapt itself automatically to the experience of the user. New users will naturally wait to be prompted, and proceed through the dialogue at a slower and more relaxed pace. .pp Suppressing unnecessary prompts is a good idea in any interactive system, whether or not it uses the medium of speech \(em although it is hardly ever done in conventional systems. It is particularly important with speech, however, because an unexpected or unwanted prompt is quite distracting, and it is not so easy to ignore it as it is with a visual display. Furthermore, speech messages usually take longer to present than displayed ones, so that the user is distracted for more time. .rh "Information units." Lengthy computer voice responses are inappropriate for conveying information, because attention wanders if one is not actively involved in the conversation. A sequential exchange of terse messages, each designed to dispense one small unit of information, forces the user to take a meaningful part in the dialogue. It has other advantages, too, allowing a higher degree of input-dependent branching, and permitting rapid recovery from errors. .pp The following example from the "Acidosis program", an audio response system designed to help physicians to diagnose acidosis, is a good example of what .ul not to do. .LB "(Chime) A VALUE OF SIX-POINT-ZERO-ZERO HAS BEEN ENTERED FOR PH. THIS VALUE IS IMPOSSIBLE. TO CONTINUE THE PROGRAM, ENTER A NEW VALUE FOR PH IN THE RANGE BETWEEN SIX-POINT-SIX AND EIGHT-POINT-ZERO (beep dah beep-beep)" (Smith and Goodwin, 1970). .[ Smith Goodwin 1970 .] .LE The use of extraneous noises (for example, a "chime" heralds an error message, and a "beep dah beep-beep" requests data input in the form ) was thought necessary in the Acidosis program to keep the user awake and help him with the format of the interaction. Rather than a long monologue like this, it seems much better to design a sequential interchange of terse messages, so that the caller can be guided into a state where he can rectify his error. For example, .LB .nf .ne11 .nr x0 \w'COMPUTER:' .nr x1 \w'CALLER:' CALLER:\h'\n(x0u-\n(x1u' "6*00#" COMPUTER: "Entry out of range" CALLER:\h'\n(x0u-\n(x1u' "6*00#" (persists) COMPUTER: "The minimum acceptable pH value is 6.6" CALLER:\h'\n(x0u-\n(x1u' "9*03#" COMPUTER: "The maximum acceptable pH value is 8.0" .fi .LE This dialogue allows a rapid exit from the error situation in the likely event that the entry has simply been mis-typed. If the error persists, the caller is given just one piece of information at a time, and forced to continue to play an active role in the interaction. .rh "Input timeouts." In general, input timeouts are dangerous, because they introduce apparent acausality in the system seen by the user. A case has been reported where a user became "highly agitated and refused to go near the terminal again after her first timed-out prompt. She had been quietly thinking what to do and the terminal suddenly interjecting and making its own suggestions was just too much for her" (Gaines and Facey, 1975). .[ Gaines Facey 1975 .] .pp However, voice response systems lack the satisfying visual feedback of end-of-line on termination of an entry. Hence a timed-out reminder is appropriate if a delay occurs after some characters have been entered. This requires the operating system to support a character-by-character mode of input, rather than the usual line-by-line mode. .rh "Repeat requests." Any voice response system must support a universal "repeat last utterance" command, because old output does not remain visible. A fairly sophisticated facility is desirable, as repeat requests are very frequent in practice. They may be due to a simple inability to understand a response, to forgetting what was said, or to distraction of attention \(em which is especially common with office terminals. .pp In the telephone enquiry service two distinct commands were employed, one to repeat the last utterance in case of misrecognition, and the other to summarize the current state of the interaction in case of distraction. For the former, it is essential to avoid simply regenerating an utterance identical with the last. Some variation of intonation and rhythm is needed to prevent an annoying, stereotyped response. A second consecutive repeat request should trigger a paraphrased reply. An error recovery sequence could be used which presented the misunderstood information in a different way with more interaction, but experience indicates that this is of minor importance, especially if information units are kept small anyway. To summarize the current state of the interaction in response to the second type of repeat command necessitates the system maintaining a model of the user. Even a poor model, like a record of his last few transactions and their results, is well worth having. .rh "Varied speech." Synthetic speech is usually rather dreary to listen to. Successive utterances with identical intonations should be carefully avoided. Small changes in speaking rate, pitch range, and mean pitch level, all serve to add variety. Unfortunately, little is known at present about the role of intonation in interactive dialogue, although this is an active research area and new developments can be expected (for a detailed report of a recent research project relevant to this topic see Brown .ul et al, 1980). .[ Brown Currie Kenworthy 1980 .] However, even random variations in certain parameters of the pitch contour are useful to relieve the tedium of repetitive intonation patterns. .sh "10.2 The applications programming environment" .pp The comments in the last section are aimed at the applications programmer who is designing the dialogue and constructing the interactive system. But what kind of environment should .ul he be given to assist with this work? .pp The best help the applications programmer can have is a speech generation method which makes it easy for him to enter new utterances and modify them on-line in cut-and-try attempts to render the man-machine dialogue as natural as possible. This is perhaps the most important advantage of synthesizing speech by rule from a textual representation. If encoded versions of natural utterances are stored, it becomes quite difficult to make minor modifications to the dialogue in the light of experience with it, for a recording session must be set up to acquire new utterances. This is especially true if more than one voice is used, or if the voice belongs to a person who cannot be recalled quickly by the programmer to augment the utterance library. Even if it is his own voice there will still be delays, for recording speech is a real-time job which usually needs a stand-alone processor, and if data compression is used a substantial amount of computation will be needed before the utterance is in a useable form. .pp The broad phonetic input required by segmental speech synthesis-by-rule systems is quite suitable for utterance representation. Utterances can be entered quickly from a standard computer terminal, and edited as text files. Programmers must acquire skill in phonetic transcription, but this is a small inconvenience. The art is easily learned in an interactive situation where the effect of modifications to the transcription can be heard immediately. If allophones must be represented explicitly in the input then the programmer's task becomes considerably more complicated because of the combinatorial explosion in trial-and-error modifications. .pp Plain text input is also quite suitable. A significant rate of error is tolerable if immediate audio feedback of the result is available, so that the operator can adjust his text to suit the pronunciation idiosyncrasies of the program. But it is acceptable, and indeed preferable, if prosodic features are represented explicitly in the input rather than being assigned automatically by a computer program. .pp The application of voice response to interactive computer dialogue is quite different to the problem of reading aloud from text. We have seen that a major concern with reading machines is how to glean information about intonation, rhythm, emphasis, tone of voice, and so on, from an input of ordinary English text. The significant problems of semantic processing, utilization of pragmatic knowledge, and syntactic analysis do not, fortunately, arise in interactive information retrieval systems. In these, the end user is communicating with a program which has been created by a person who knows what he wants it to say. Thus the major difficulty is in .ul describing the prosodic features rather than .ul deriving them from text. .pp Speech synthesis by rule is a subsidiary process to the main interactive procedure. It would be unwise to allow the updating of resonance parameter tracks to be interrupted by other calls on the system, and so the synthesis process needs to be executed in real time. If a stand-alone processor is used for the interactive dialogue, it may be able to handle the synthesis rules as well. In this case the speech-by-rule program could be a library procedure, if the system is implemented in a compiled language. An interesting alternative with an interpretive-language implementation, such as Basic, is to alter the language interpreter to add a new command, "speak", which simply transfers a string representing an utterance to an asynchronous process which synthesizes it. However, there must be some way for an intepreted program to abort the current synthesis in the event of an interrupt signal from the user. .pp If the main computer system is time-shared, the synthesis-by-rule procedure is best executed by an independent processor. For example, a 16-bit microcomputer controlling a hardware formant synthesizer has been used to run the ISP system in real time without too much difficulty (Witten and Abbess, 1979). .[ Witten Abbess 1979 .] An important task is to define an interface between the two which allows the main process to control relevant aspects of the prosody of the speech in a way which is appropriate to the state of the interaction, without having to bother about such things as matching the intonation contour to the utterance and the details of syllable rhythm. Halliday's notation appears to be quite suitable for this purpose. .pp If there is only one synthesizer on the system, there will be no difficulty in addressing it. One way of dealing with multiple synthesizers is to treat them as assignable devices in the same way that non-spooling peripherals are in many operating systems. Notice that the data rate to the synthesizer is quite low if the utterance is represented as text with prosodic markers, and can easily be handled by a low-speed asynchronous serial line. .pp The Votrax ML-I synthesizer which is discussed in the next chapter has an interface which interposes it between a visual display unit and the serial port that connects it to the computer. The VDU terminal can be used quite normally, except that a special sequence of two control characters will cause Votrax to intercept the following message up to another control character, and interpret it as speech. The fact that the characters which specify the spoken message do not appear on the VDU screen means that the operation is invisible to the user. However, this transparency can be inhibited by a switch on the synthesizer to allow visual checking of the sound-segment character sequence. .pp Votrax buffers up to 64 sound segments, which is sufficient to generate isolated spoken messages. For longer passages, it can be synchronized with the constant-rate serial output using the modem control lines of the serial interface, together with appropriate device-driving software. .pp This is a particularly convenient interfacing technique in cases when the synthesizer should always be associated with a certain terminal. As an example of how it can be used, one can arrange files each of whose lines contain a printed message, together with its Votrax equivalent bracketed by the appropriate control characters. When such a file is listed, or examined with an editor program, the lines appear simultaneously in spoken and typed English. .pp If a phonetic representation is used for utterances, with real-time synthesis using a separate process (or processor), it is easy for the programmer to fiddle about with the interactive dialogue to get it feeling right. For him, each utterance is just a textual string which can be stored as a string constant within his program just as a VDU prompt would be. He can edit it as part of his program, and "print" it to the speech synthesis device to hear it. There are no more technical problems to developing an interactive dialogue with speech output than there are for a conventional interactive program. Of course, there are more human problems, and the points discussed in the last section should always be borne in mind. .sh "10.3 Using the keypad" .pp One of the greatest advantages of speech output from computers is the ubiquity of the telephone network and the possibility of using it without the need for special equipment at the terminal. The requirement for input as well as output obviously presents something of a problem because of the restricted nature of the telephone keypad. .pp Figure 10.1 shows the layout of the keypad. .FC "Figure 10.1" Signalling is achieved by dual-frequency tones. For example, if key 7 is pressed, sinusoidal components at 852\ Hz and 1209\ Hz are transmitted down the line. During the process of dialling these are received by the telephone exchange equipment, which assembles the digits that form a number and attempts to route the call appropriately. Once a connection is made, either party is free to press keys if desired and the signals will be transmitted to the other end, where they can be decoded by simple electronic circuits. .pp Dial telephones signal with closely-spaced dial pulses. One pulse is generated for a "1", two for a "2", and so on. (Obviously, ten pulses are generated for a "0", rather than none!) Unfortunately, once the connection is made it is difficult to signal with dial pulses. They cannot be decoded reliably at the other end because the telephone network is not designed to transmit such low frequencies. However, hand-held tone generators can be purchased for use with dial telephones. Although these are undeniably extra equipment, and one purpose of using speech output is to avoid this, they are very cheap and portable compared with other computer terminal equipment. .pp The small number of keys on the telephone pad makes it rather difficult to use for communicating with computers. Provision is made for 16 keys, but only 12 are implemented \(em the others may be used for some military purposes. Of course, if a separate tone generator is used then advantage can be taken of the extra keys, but this will introduce incompatibility with those who use unmodified touch-tone phones. More sophisticated terminals are available which extend the keypad \(em such as the Displayphone of Northern Telecommunications. However, they are designed as a complete communications terminal and contain their own visual display as well. .rh "Keying alphabetic data." Figure 10.2 shows the near-universal scheme for overlaying alphabetic letters on to the telephone keypad. .FC "Figure 10.2" Since more than one symbol occupies each key, it is obviously necessary to have multiple keystrokes per character if the input sequence is to be decodable as a string of letters. One way of doing this is to depress the appropriate button the number of times corresponding to the position of the letter on it. For example, to enter the letter "L" the user would key the "5" button three times in rapid succession. Keying rhythm must be used to distinguish the four entries "J\ J\ J", "J\ K", "K\ J", and "L", unless one of the bottom three buttons is used as a separator. A different method is to use "*", "0", and "#" as shift keys to indicate whether the first, second, or third letter on a key is intended. Then "#5" would represent "L". Alternatively, the shift could follow the key instead of preceding it, so that "5#" represented "L". .pp If numeric as well as alphabetic information may be entered, a mode-shift operation is commonly used to switch between numeric and alphabetic modes. .pp The relative merits of these three methods, multiple depressions, shift key prefix, and shift key suffix, have been investigated experimentally (Kramer, 1970). .[ Kramer 1970 .] The results were rather inconclusive. The first method seemed to be slightly inferior in terms of user accuracy. It seemed that preceding rather than following shifts gave higher accuracy, although this is perhaps rather counter-intuitive and may have been fortuitous. The most useful result from the experiments was that users exhibited significant learning behaviour, and a training period of at least two hours was recommended. Operators were found able to key at rates of at least three to four characters per second, and faster with practice. .pp If a greater range of characters must be represented then the coding problem becomes more complex. Figure 10.3 shows a keypad which can be used for entry of the full 64-character standard upper-case ASCII alphabet (Shew, 1975). .[ Shew 1975 .] .FC "Figure 10.3" The system is intended for remote vocabulary updating in a phonetically-based speech synthesis system. There are three modes of operation: numeric, alphabetic, and symbolic. These are entered by "##", "**", and "*0" respectively. Two function modes, signalled by "#0" and "#*", allow some rudimentary line-editing and monitor facilities to be incorporated. Line-editing commands include character and line delete, and two kinds of read-back commands \(em one tries to pronounce the words in a line and the other spells out the characters. The monitor commands allow the user to repeat the effect of the last input line as though he had entered it again, to order the system to read back the last complete output line, and to query time and system status. .rh "Incomplete keying of alphanumeric data." It is obviously going to be rather difficult for the operator to key alphanumeric information unambiguously on a 12-key pad. In the description of the telephone enquiry service in Chapter 1, it was mentioned that single-key entry can be useful for alphanumeric data if the ambiguity can be resolved by the computer. If a multiple-character entry is known to refer to an item on a given list, the characters can be keyed directly according to the coding scheme of Figure 10.2. .pp Under most circumstances no ambiguity will arise. For example, Table 10.1 shows the keystrokes that would be entered for the first 50 5-letter words in an English dictionary. Only two clashes occur \(em between " adore" and "afore", and "agate" and "agave". .RF .nr x2 \w'abeam 'u .nr x3 \w'00000# 'u .nr x0 \n(x2u+\n(x3u+\n(x2u+\n(x3u+\n(x2u+\n(x3u+\n(x2u+\n(x3u+\n(x2u+\w'00000#'u .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta \n(x2u +\n(x3u +\n(x2u +\n(x3u +\n(x2u +\n(x3u +\n(x2u +\n(x3u +\n(x2u \l'\n(x0u\(ul' .sp aback 22225# abide 22433# adage 23243# adore 23673# after 23837# abaft 22238# abode 22633# adapt 23278# adorn 23676# again 24246# abase 22273# abort 22678# adder 23337# adult 23858# agape 24273# abash 22274# about 22688# addle 23353# adust 23878# agate 24283# abate 22283# above 22683# adept 23378# aeger 23437# agave 24283# abbey 22239# abuse 22873# adieu 23438# aegis 23447# agent 24368# abbot 22268# abyss 22977# admit 23648# aerie 23743# agile 24453# abeam 22326# acorn 22676# admix 23649# affix 23349# aglet 24538# abele 22353# acrid 22743# adobe 23623# afoot 23668# agony 24669# abhor 22467# actor 22867# adopt 23678# afore 23673# agree 24733# \l'\n(x0u\(ul' .in 0 .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .FG "Table 10.1 Keying equivalents of some words" As a more extensive example, in a dictionary of 24,500 words, just under 2,000 ambiguities (8% of words) were discovered. Such ambiguities would have to be resolved interactively by the system explaining its dilemma, and asking the user for a choice. Notice incidentally that although the keyed sequences do not have the same lexicographic order as the words, no extra cost will be associated with the table-searching operation if the dictionary is stored in inverted form, with each legal number pointing to its English equivalent or equivalents. .pp A command language syntax is also a powerful way of disambiguating keystrokes entered. Figure 10.4 shows the keypad layout for a telephone voice calculator (Newhouse and Sibley, 1969). .[ Newhouse Sibley 1969 .] .FC "Figure 10.4" This calculator provides the standard arithmetic operators, ten numeric registers, a range of pre-defined mathematical functions, and even the ability for a user to enter his own functions over the telephone. The number representation is fixed-point, with user control (through a system function) over the precision. Input of numbers is free format. .pp Despite the power of the calculator language, the dialogue is defined so that each keystroke is unique in context and never has to be disambiguated explicitly by the user. Table 10.2 summarizes the command language syntax in an informal and rather heterogeneous notation. .RF .nr x0 1.3i+1.7i+\w'some functions do not need the part'u .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta 1.3i +1.7i \l'\n(x0u\(ul' construct definition explanation \l'\n(x0u\(ul' .sp a sequence of s followed by a call to the system function \fIE X I T\fR .sp OR OR OR OR OR OR OR OR OR OR OR .sp + # OR + # .sp similar to .sp OR \fIregister\fR .sp a sequence of keystrokes like 1 . 2 3 4 or 1 2 3 . 4 or 1 2 3 4 .sp \fIfunction\fR # # some functions do not need the part .sp a sequence of keystrokes like \fIS I N\fR or \fIE X I T\fR or \fIM Y F U N C\fR .sp \fIclear register\fR # clears one of the 10 registers .sp \fIerase\fR # undoes the effect of the last operation .sp \fIanswer register\fR # reads the contents of a register .sp these provide "repeat" facilities .sp aborts the current utterance \l'\n(x0u\(ul' .in 0 .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .FG "Table 10.2 Syntax for a telephone calculator" A calculation is a sequence of operations followed by an EXIT function call. There are twelve different operations, one for each button on the keypad. Actually, two of them \(em .ul cancel and .ul function \(em share the same key so that "#" can be reserved for use as a separator; but the context ensures that they cannot be confused by the system. .pp Six of the operations give control over the dialogue. There are three different "repeat" commands; a command (called .ul erase\c ) which undoes the effect of the last operation; one which reads out the value of a register; and one which aborts the current utterance. Four more commands provide the basic arithmetic operations of add, subtract, multiply, and divide. The operands of these may be keyed literal numbers, or register values, or function calls. A further command clears a register. .pp It is through functions that the extensibility of the language is achieved. A function has a name (like SIN, EXIT, MYFUNC) which is keyed with an appropriate single-key-per-character sequence (namely 746, 3948, 693862 respectively). One function, DEFINE, allows new ones to be entered. Another, LOOP, repeats sequences of operations. TEST incorporates arithmetic testing. The details of these are not important: what is interesting is the evident power of the calculator. .pp For example, the keying sequence .LB .NI 5 # 1 1 2 3 # 2 1 . 2 # 9 # 6 # 2 1 . 4 # .LE would be decoded as .LB .NI .ul clear\c + 123 \- 1.2 \c .ul display erase\c \- 1.4. .LE One of the difficulties with such a tight syntax is that almost any sequence will be intepreted as a valid calculation \(em syntax errors are nearly impossible. Thus a small mistake by the user can have a catastrophic effect on the calculation. Here, however, speech output gives an advantage over conventional character-by-character echoing on visual displays. It is quite adequate to echo syntactic units as they are decoded, instead of echoing keys as they are entered. It was suggested earlier in this chapter that confirmation of entry should be generated in the same way that the user would be likely to verbalize it himself. Thus the synthetic voice could respond to the above keying sequence as shown in the second line, except that the .ul display command would also state the result (and possibly summarize the calculation so far). Numbers could be verbalized as "one hundred and twenty-three" instead of as "one ... two ... three". (Note, however, that this will make it necessary to await the "#" terminator after numbers and function names before they can be echoed.) .sh "10.4 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .sh "10.5 Further reading" .pp There are no books which relate techniques of man-computer dialogue to speech interaction. The best I can do is to guide you to some of the standard works on interactive techniques. .LB "nn" .\"Gilb-1977-1 .]- .ds [A Gilb, T. .as [A " and Weinberg, G.M. .ds [D 1977 .ds [T Humanized input .ds [I Winthrop .ds [C Cambridge, Massachusetts .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n This book is subtitled "techniques for reliable keyed input", and considers most aspects of the problem of data entry by professional key operators. .in-2n .\"Martin-1973-2 .]- .ds [A Martin, J. .ds [D 1973 .ds [T Design of man-computer dialogues .ds [I Prentice-Hall .ds [C Englewood Cliffs, New Jersey .nr [T 0 .nr [A 1 .nr [O 0 .][ 2 book .in+2n Martin concerns himself with all aspects of man-computer dialogue, and the book even contains a short chapter on the use of voice response systems. .in-2n .\"Smith-1980-3 .]- .ds [A Smith, H.T. .as [A " and Green, T.R.G.(Editors) .ds [D 1980 .ds [T Human interaction with computers .ds [I Academic Press .ds [C London .nr [T 0 .nr [A 0 .nr [O 0 .][ 2 book .in+2n A recent collection of contributions on man-computer systems and programming research. .in-2n .LE "nn" .EQ delim $$ .EN .CH "11 COMMERCIAL SPEECH OUTPUT DEVICES" .ds RT "Commercial speech output devices .ds CX "Principles of computer speech .pp This chapter takes a look at four speech output peripherals that are available today. It is risky in a book of this nature to descend so close to the technology as to discuss particular examples of commercial products, for such information becomes dated very quickly. Nevertheless, having covered the principles of various types of speech synthesizer, and the methods of driving them from widely differing utterance representations, it seems worthwhile to see how these principles are embodied in a few products actually on the market. .pp Developments in electronic speech devices are moving so fast that it is hard to keep up with them, and the newest technology today will undoubtedly be superseded next year. Hence I have not tried to choose examples from the very latest technology. Instead, this chapter discusses synthesizers which exemplify rather different principles and architectures, in order to give an idea of the range of options which face the system designer. .pp Three of the devices are landmarks in the commercial adoption of speech technology, and have stood the test of time. Votrax was introduced in the early 1970's, and has been re-implemented several times since in an attempt to cover different market sectors. The Computalker appeared in 1976. It was aimed primarily at the burgeoning computer hobbies market. One of its most far-reaching effects was to stimulate the interest of hobbyists, always eager for new low-cost peripherals, in speech synthesis; and so provide a useful new source of experimentation and expertise which will undoubtedly help this heretofore rather esoteric discipline to mature. Computalker is certainly the longest-lived and probably still the most popular hobbyist's speech synthesizer. The Texas Instruments speech synthesis chip brought speech output technology to the consumer. It was the first single-chip speech synthesizer, and is still the biggest seller. It forms the heart of the "Speak 'n Spell" talking toy which appeared in toyshops in the summer of 1978. Although talking calculators had existed several years before, they were exotic gadgets rather than household toys. .sh "11.1 Formant synthesizer" .pp The Computalker is a straightforward implementation of a serial formant synthesizer. A block diagram of it is shown in Figure 11.1. .FC "Figure 11.1" In the centre is the main vocal tract path, with three formant filters whose resonant frequencies can be controlled individually. A separate nasal branch in parallel with the oral one is provided, with a nasal formant of fixed frequency. It is less important to allow for variation of the nasal formant frequency than it is for the oral ones, because the size and shape of the nasal tract is relatively fixed. However, it is essential to control the nasal amplitude, in particular to turn it off during non-nasal sounds. Computalker provides independent oral and nasal amplitude parameters. .pp Unvoiced excitation can be passed through the main vocal tract through the aspiration amplitude control AH. In practice, the voicing amplitudes AV and AN will probably always be zero when AH is non-zero, for physiological constraints prohibit simultaneous voicing and aspiration. A second unvoiced excitation path passes through a fricative formant filter whose resonant frequency can be varied, and has its amplitude independently controlled by AF. .rh "Control parameters." Table 11.1 summarizes the nine parameters which drive Computalker. .RF .nr x0 \w'address0'+\w'fundamental frequency of voicing00'+\w'0 bits0'+\w'logarithmic00'+\w'0000\-00000 Hz' .nr x1 (\n(.l-\n(x0)/2 .in \n(x1u .ta \w'000'u \w'address0'u +\w'fundamental frequency of voicing00'u +\w'0 bits0'u +\w'logarithmic00'u address meaning width \0\0\0range \l'\n(x0u\(ul' .sp \00 AV amplitude of voicing 8 bits \01 AN nasal amplitude 8 bits \02 AH amplitude of aspiration 8 bits \03 AF amplitude of frication 8 bits \04 FV fundamental frequency of voicing 8 bits logarithmic \0\075\-\0\0470 Hz \05 F1 formant 1 resonant frequency 8 bits logarithmic \0170\-\01450 Hz \06 F2 formant 2 resonant frequency 8 bits logarithmic \0520\-\04400 Hz \07 F3 formant 3 resonant frequency 8 bits logarithmic 1700\-\05500 Hz \08 FF fricative resonant frequency 8 bits logarithmic 1700\-14000 Hz \09 not used 10 not used 11 not used 12 not used 13 not used 14 not used 15 SW audio on-off switch 1 bit \l'\n(x0u\(ul' .in 0 .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .FG "Table 11.1 Computalker control parameters" Four of them control amplitudes, while the others control frequencies. In the latter case the parameter value is logarithmically related to the actual frequency of the excitation (FV) or resonance (F1, F2, F3, FF). The ranges over which each frequency can be controlled is shown in the Table. An independent calibration of one particular Computalker has shown that the logarithmic specifications are met remarkably well. .pp Each parameter is specified to Computalker as an 8-bit number. Parameters are addressed by a 4-bit code, and so a total of 12 bits is transferred in parallel to Computalker from the computer for each parameter update. Parameters 9 to 14 are unassigned ("reserved for future expansion" is the official phrase), and the last parameter, SW, governs the position of an audio on-off switch. .pp Computalker does not contain a clock that is accessible to the user, and so the timing of parameter updates is entirely up to the host computer. Typically, a 10\ msec interval between frames is used, with interrupts generated by a separate timer. In fact the frame interval can be anywhere between 2\ msec and 50\ msec, and can be changed to alter the rate of speaking. However, it is rather naive to view fast speech as slow speech speeded up by a linear time compression, for in human speech production the rhythm changes and elisions occur in a rather more subtle way. Thus it is not particularly useful to be able to alter the frame rate. .pp At each interrupt, the host computer transfers values for all of the nine parameters to Computalker, a total of 108 data bits. In theory, perhaps, it is only necessary to transmit those parameters whose values have changed; but in practice all of them should be updated regardless. This is because the parameters are stored for the duration of the frame in analogue sample-and-hold devices. Essentially, the parameter value is represented as the charge on a capacitor. In time \(em and it takes only a short time \(em the values drift. Although the drift over 10\ msec is insignificant, it becomes very noticeable over longer time periods. If parameters are not updated at all, the result is a "whooosh" sound up to maximum amplitude, in a period of a second or two. Hence it is essential that Computalker be serviced by the computer regularly, to update all its parameters. The audio on-off switch is provided so that the computer can turn off the sound directly if another program, which does not use the device, is to be run. .rh "Filter implementation." It is hard to get definite information on the implementation of Computalker. Because it is a commercial device, circuit diagrams are not published. It is certainly an analogue rather than a digital implementation. The designer suggests that a configuration like that of Figure 11.2 is used for the formant filters (Rice, 1976). .[ Rice 1976 Byte .] .FC "Figure 11.2" Control is obtained over the resonant frequency by varying the resistance at the bottom in sympathy with the parameter value. The middle two operational amplifiers can be modelled by a resistance $-R/k$ in the forward path, where k is the digital control value. This gives the circuit in Figure 11.3, which can be analysed to obtain the transfer function .LB .EQ - ~ k over {R~R sub 1 C sub 2 C sub 3} ~ . ~ {R sub 2 C sub 2 ~s ~+~1} over { s sup 2 ~+~~ ( 1 over {R sub 3 C sub 3} ~+~ {k R sub 2} over {R~R sub 1 C sub 3})~s ~~+~ k over {R~R sub 1 C sub 2 C sub 3}} ~ . .EN .LE .FC "Figure 11.3" .pp This expression has a DC gain of \-1, and the denominator is similar to those of the analogue formant resonators discussed in Chapter 5. However, unlike them the transfer function has a numerator which creates a zero at .LB .EQ s~~=~~-~ 1 over {R sub 2 C sub 2} ~ . .EN .LE If $R sub 2 C sub 2$ is sufficiently small, this zero will have negligible effect at audio frequencies, and the filter has the following parameters: .LB centre frequency: $~ mark 1 over {2 pi}~~( k over {R~R sub 1 C sub 2 C sub 3} ~ ) sup 1/2$ Hz .sp bandwidth:$lineup 1 over {2 pi}~~( 1 over {R sub 3 C sub 3}~+~ {k R sub 2} over {R~R sub 1 C sub 3} ~ )$ Hz. .LE .pp Note first that the centre frequency is proportional to the square root of the control value $k$. Hence a non-linear transformation must be implemented on the control signal, after D/A conversion, to achieve the required logarithmic relationship between parameter value and resonant frequency. The formant bandwidth is not constant, as it should be (see Chapter 5), but depends upon the control value $k$. This dependency can be minimized by selecting component values such that .LB .EQ {k R sub 2} over {R~R sub 1 C sub 3}~~<<~~1 over {R sub 3 C sub 3} .EN .LE for the largest value of $k$ which can occur. Then the bandwidth is solely determined by the time constant $R sub 3 C sub 3$. .pp The existence of the zero can be exploited for the fricative resonance. This should have zero DC gain, and so the component values for the fricative filter should make the time-constant $R sub 2 C sub 2$ large enough to place the zero sufficiently near the frequency origin. .rh "Market orientation." As mentioned above, Computalker is designed for the computer hobbies market. Figure 11.4 shows a photograph of the device. .FC "Figure 11.4" It plugs into the S\-100 bus which has been a .ul de facto standard for hobbyists for several years, and has recently been adopted as a standard by the Institute of Electrical and Electronic Engineers. This makes it immediately accessible to many microcomputer systems. .pp An inexpensive synthesis-by-rule program, which runs on the popular 8080 microprocessor, is available to drive Computalker. The input is coded in a machine-readable version of the standard phonetic alphabet, similar to that which was introduced in Chapter 2 (Table 2.1). Stress digits may appear in the transcription, and the program caters for five levels of stress. The punctuation mark at the end of an utterance has some effect on pitch. The program is perhaps remarkable in that it occupies only 6\ Kbyte of storage (including phoneme tables), and runs on an 8-bit microprocessor (but not in real time). It is, however, .ul un\c remarkable in that it produces rather poor speech. According to a demonstration cassette, "most people find the speech to be readily intelligible, especially after a little practice listening to it," but this seems extremely optimistic. It also cunningly insinuates that if you don't understand it, you yourself may share the blame with the synthesizer \(em after all, .ul most people do! Nevertheless, Computalker has made synthetic speech accessible to a large number of home computer users. .sh "11.2 Sound-segment synthesizer" .pp Votrax was the first fully commercial speech synthesizer, and at the time of writing is still the only off-the-shelf speech output peripheral (as distinct from reading machine) which is aimed specifically at synthesis-by-rule rather than storage of parameter tracks extracted from natural utterances. Figure 11.5 shows a photograph of the Votrax ML-I. .FC "Figure 11.5" .pp Votrax accepts as input a string of codes representing sound segments, each with additional bits to control the duration and pitch of the segment. In the earlier versions (eg model VS-6) there are 63 sound segments, specified by a 6-bit code, and two further bits accompany each segment to provide a 4-level control over pitch. Four pitch levels are quite inadequate to generate acceptable intonation contours for anything but isolated words spoken in citation form. However, a later model (ML-I) uses an 8-level pitch specification, as well as a 4-level duration qualifier, associated with each sound segment. It provides a vocabulary of 80 sound segments, together with an additional code which allows local amplitude modifications and extra duration alterations to following segments. A further, low-cost model (VS-K) is now available which plugs in to the S\-100 bus, and is aimed primarily at computer hobbyists. It provides no pitch control at all and is therefore quite unsuited to serious voice response applications. The device has recently been packaged as an LSI circuit (model SC\-01), using analogue switched-capacitor filter technology. .pp One point where the ML-I scores favourably over other speech synthesis peripherals is the remarkably convenient engineering of its computer interface, which was outlined in the previous chapter. .pp The internal workings of Votrax are not divulged by the manufacturer. Figure 11.6 shows a block diagram at the level of detail that they supply. .FC "Figure 11.6" It seems to be essentially a formant synthesizer with analogue function generators and parameter smoothing circuits that provide transitions between sound segments. .rh "Sound segments." The 80 segments of the high-range ML-I model are summarized in Table 11.2. .FC "Table 11.2" They are divided into phoneme classes according to the classification discussed in Chapter 2. The segments break down into the following categories. (Numbers in parentheses are the corresponding figures for VS-6.) .LB "00 (00) " .NI "00 (00) " 11 (11) vowel sounds which are representative of the phonological vowel classes for English .NI "00 (00) " \09 \0(7) vowel allophones, with slightly different sound qualities from the above .NI "00 (00) " 20 (15) segments whose sound qualities are identical to the segments above, but with different durations .NI "00 (00) " 22 (22) consonant sounds which are representative of the phonological consonant classes for English .NI "00 (00) " 11 \0(6) consonant allophones .NI "00 (00) " \04 \0(0) segments to be used in conjunction with unvoiced plosives to increase their aspiration .NI "00 (00) " \02 \0(2) silent segments, with different pause durations .NI "00 (00) " \01 \0(0) very short silent segment (about 5\ msec). .LE "00 (00) " Somewhat under half of the 80 elements can be put into one-to-one correspondence with the phonemes of English; the rest are either allophonic variations or additional sounds which can sensibly be combined with certain phonemes in certain contexts. The Votrax literature, and consequently Votrax users, persists in calling all elements "phonemes", and this can cause considerable confusion. I prefer to use the term "sound segment" instead, reserving "phoneme" for its proper linguistic use. .pp The rules which Votrax uses for transitions between sound segments are not made public by the manufacturer, and are embedded in encapsulated circuits in the hardware. They are clearly very crude. The key to successful encoding of utterances is to use the many non-phonemic segments in an appropriate way as transitions between the main segments which represent phonetic classes. This is a tricky process, and I have heard of one commercial establishment giving up in despair at the extreme difficulty of generating the utterances it wanted. It probably explains the proliferation of letter-to-sound rules for Votrax which have been developed in research laboratories (Colby .ul et al, 1978; Elovitz .ul et al, 1976; McIlroy, 1974; Sherwood, 1978). .[ Colby Christinaz Graham 1978 .] .[ Elovitz 1976 IEEE Trans Acoustics Speech and Signal Processing .] .[ McIlroy 1974 .] .[ Sherwood 1978 .] Nevertheless, with luck, skill, and especially persistence, excellent results can be obtained. The ML-I manual (Votrax, 1976) contains a list of about 625 words and short phrases, and they are usually clearly recognizable. .[ Votrax 1976 .] .rh "Duration and pitch qualifiers." Each sound segment has a different duration. Table 11.2 shows the measured duration of the segments, although no calibration data is given by Votrax. As mentioned earlier, a 2-bit number accompanies each segment to modify its duration, and this was set to 3 (least duration) for the measurements. The qualifier has a multiplicative effect, shown in Table 11.3. .RF .nr x1 (\w'rate qualifier'/2) .nr x2 (\w'in Table 11.2 by'/2) .nr x0 \n(x1+2i+\w'00'+\n(x2 .nr x3 (\n(.l-\n(x0)/2 .in \n(x3u .ta \n(x1u +2i \l'\n(x0u\(ul' .sp .nr x2 (\w'multiply duration'/2) rate qualifier \0\0\h'-\n(x2u'multiply duration .nr x2 (\w'in Table 11.2 by'/2) \0\0\h'-\n(x2u'in Table 11.2 by \l'\n(x0u\(ul' .sp 3 1.00 2 1.11 1 1.22 0 1.35 \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 11.3 Effect of the 2-bit per-segment rate qualifier" .pp As well as the 2-bit rate qualifier, each sound segment is accompanied by a 3-bit pitch specification. This provides a linear control over fundamental frequency, and Table 11.4 shows the measured values. .RF .nr x1 (\w'pitch specifier'/2) .nr x2 (\w'pitch (Hz)'/2) .nr x0 \n(x1+1.5i+\n(x2 .nr x3 (\n(.l-\n(x0)/2 .in \n(x3u .ta \n(x1u +1.5i \l'\n(x0u\(ul' .sp pitch specifier \h'-\n(x2u'pitch (Hz) \l'\n(x0u\(ul' .sp 0 \057.5 1 \064.1 2 \069.4 3 \075.8 4 \080.6 5 \087.7 6 \094.3 7 100.0 \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 11.4 Effect of the 3-bit per-segment pitch specifier" The quantization interval varies from one to two semitones. Votrax interpolates pitch from phoneme to phoneme in a highly satisfactory manner, and this permits surprisingly sophisticated intonation contours to be generated considering the crude 8-level quantization. .pp The notation in which the Votrax manual defines utterances gives duration qualifiers and pitch specifications as digits preceding the sound segment, and separated from it by a slash (/). Thus, for example, .LB 14/THV .LE defines the sound segment THV with duration qualifier 1 (multiplies the 70\ msec duration of Table 11.2 by 1.22 \(em from Table 11.3 \(em to give 85\ msec) and pitch specification 4 (81 Hz). This representation of a segment is transformed into two ASCII characters before transmission to the synthesizer. .rh "Converting a phonetic transcription to sound segments." It would be useful to have a computer procedure to produce a specification for an utterance in terms of Votrax sound segments from a standard phonetic transcription. This could remove much of the tedium from utterance preparation by incorporating the contextual rules given in the Votrax manual. Starting with a phonetic transcription, each phoneme should be converted to its default Votrax representative. The resulting "wide" Votrax transcription must be transformed into a "narrow" one by application of contextual rules. Separate rules are needed for .LB .NP vowel clusters (diphthongs) .NP vowel transitions (ie consonant-vowel and vowel-consonant, where the vowel segment is altered) .NP intervocalic consonants .NP consonant transitions (ie consonant-vowel and vowel-consonant, where the consonant segment is altered) .NP consonant clusters .NP stressed-syllable effects .NP utterance-final effects. .LE Stressed-syllable effects (which include extra aspiration for unvoiced stops beginning stressed syllables) can be applied only if stress markers are included in the phonetic transcription. .pp To specify a rule, it is necessary to give a .ul matching part and a .ul context, which define at what points in an utterance it is applicable, and a .ul replacement part which is used to replace the matching part. The context can be specified in mathematical set notation using curly brackets. For example, .LB {G SH W K} OO IU OO .LE states that the matching part OO is replaced by IU OO, after a G, SH, W, or K. In fact, allophonic variations of each sound segment should also be accepted as valid context, so this rule will also replace OO after .G, CH, .W, .K, or .X1 (Table 11.2 gives allophones of each segment). .pp Table 11.5 gives some rules that have been used for this purpose. .FC "Table 11.5" They were derived from careful study of the hints given in the ML-I manual (Votrax, 1976). .[ Votrax 1976 .] Classes such as "voiced" and "stop-consonant" in the context specify sets of sound segments in the obvious way. The beginning of a stressed syllable is marked in the input by ".syll". Parentheses in the replacement part have a significance which is explained in the next section. .rh "Handling prosodic features." We know from Chapter 8 the vital importance of prosodic features in synthesizing lifelike speech. To allow them to be assigned to Votrax utterances, an intermediate output from a prosodic analysis program like ISP can be used. For example, .LB 1 \c .ul dh i s i z /*d zh aa k s /h aa u s; .LE which specifies "this is Jack's house" in a declarative intonation with emphasis on the "Jack's", can be intercepted in the following form: .LB \&.syll .ul dh\c \ 50\ (0\ 110) .ul i\c \ 60 .ul s\c \ 90\ (0\ 99) .ul i\c \ 60 .ul z\c \ 60\ (50\ 110) \&.syll .ul d\c \ 50\ (0\ 110) .ul zh\c \ 50 .ul aa\c \ 90 .ul k\c \ 120\ (10\ 90) .ul s\c \ 90 \&.syll .ul h\c \ 60 .ul aa\c \ 140 .ul u\c \ 60 .ul s\c \ 140 ^\ 50\ (40\ 70) . .LE Syllable boundaries, pitches, and durations have been assigned by the procedures given earlier (Chapter 8). A number always follows each phoneme to specify its duration (in msec). Pairs of numbers in parentheses define a pitch specification at some point during the preceding phoneme: the first number of the pair defines the time offset of the specification from the beginning of the phoneme, while the second gives the pitch itself (in Hz). This form of utterance specification can then be passed to a Votrax conversion procedure. .pp The phonetic transcription is converted to Votrax sound segments using the method described above. The "wide" Votrax transcription is .LB \&.syll THV I S I Z .syll D ZH AE K S .syll H AE OO S PA0 ; .LE which is transformed to the following "narrow" one according to the rules of Table 11.5: .LB \&.syll THV I S I Z .syll D J (AE EH3) K S .syll H1 (AH1 .UH2) (O U) S PA0 . .LE The duration and pitch specifications are preserved by the transformation in their original positions in the string, although they are not shown above. The next stage uses them to expand the transcription by adjusting the segments to have durations as close as possible to the specifications, and computing pitch numbers to be associated with each phoneme. .pp Correct duration-expansion can, in general, require a great amount of computation. Associated with each sound segment is a set of elements with the same sound quality but different durations, formed by attaching each of the four duration qualifiers of Table 11.3 to the segment and any others which are sound-equivalents to it. For example, the segment Z has the duration-set .LB {3/Z 2/Z 1/Z 0/Z} .LE with durations .LB { 70 78 85 95} .LE msec respectively, where the initial numerals denote the duration qualifier. The segment I has the much larger duration-set .LB {3/I2 2/I2 1/I2 0/I2 3/I1 2/I1 1/I1 0/I1 3/I 2/I 1/I 0/I} .LE with durations .LB { 58 64 71 78 83 92 101 112 118 131 144 159}, .LE because segments I1 and I2 are sound-equivalents to it. Duration assignment is a matter of selecting elements from the duration-set whose total duration is as close as possible to that desired for the segment. It happens that Votrax deals sensibly with concatenations of more than one identical plosive, suppressing the stop burst on all but the last. Although the general problem of approximating durations in this way is computationally demanding, a simple recursive exhaustive search works in a reasonable amount of time because the desired duration is usually not very much greater than the longest member of the duration-set, and so the search terminates quite quickly. .pp At this point, the role of the parentheses which appear on the right-hand side of Table 11.5 becomes apparent. Because durations are only associated with the input phonemes, which may each be expanded into several Votrax segments, it is necessary to keep track of the segments which have descended from a single phoneme. Target durations are simply spread equally across any parenthesized groups to which they apply. .pp Having expanded durations, mapping pitches on to the sound segments is a simple matter. The ISP system for formant synthesizers (Chapters 7 and 8) uses linear interpolation between pitch specifications, and the frequency which results for each sound segment needs to be converted to a Votrax specification using the information in Table 11.4. .pp After applying these procedures to the example utterance, it becomes .LB 14/THV 14/I1 03/S 14/I1 04/Z 04/D 04/J 33/AE 33/EH3 \c 02/K 02/K 02/S 02/H1 01/AH2 01/.UH2 31/O2 31/U1 01/S \c 10/S 30/PA0 30/PA0 . .LE In several places, shorter sound-equivalents have been substituted (I1 for I, AH2 for AH1, O2 for O, and U1 for U), while doubling-up also occurs (in the K, S, and PA0 segments). .pp The speech which results from the use of these procedures with the Votrax synthesizer sounds remarkably similar to that generated by the ISP system which uses parametrically-controlled synthesizers. Formal evaluation experiments have not been undertaken, but it seems clear from careful listening that it would be rather difficult, and probably pointless, to evaluate the Votrax conversion algorithm, for the outcome would be completely dominated by the success of the original pitch and rhythm assignment procedures. .sh "11.3 Linear predictive synthesizer" .pp The first single-chip speech synthesizer was introduced by Texas Instruments (TI) in the summer of 1978 (Wiggins and Brantingham, 1978). .[ Wiggins Brantingham 1978 .] It was a remarkable development, combining recent advances in signal processing with the very latest in VLSI technology. Packaged in the Speak 'n Spell toy (Figure 11.7), it was a striking demonstration of imagination and prowess in integrated electronics. .FC "Figure 11.7" It gave TI a long lead over its competitors and surprised many experts in the speech field. .EQ delim @@ .EN Overnight, it seemed, digital speech technology had descended from research laboratories with their expensive and specialized equipment into a $50.00 consumer item. .EQ delim $$ .EN Naturally TI did not sell the chip separately but only as part of their mass-market product; nor would they make available information on how to drive it directly. Only recently when other similar devices appeared on the market did they unbundle the package and sell the chip. .rh "The Speak 'n Spell toy." The TI chip (TMC0280) uses the linear predictive method of synthesis, primarily because of the ease of the speech analysis procedure and the known high quality at low data rates. Speech researchers, incidentally, sometimes scoff at what they perceive to be the poor quality of the toy's speech; but considering the data rate used (which averages 1200 bits per second of speech) it is remarkably good. Anyway, I have never heard a child complain! \(em although it is not uncommon to misunderstand a word. Two 128\ Kbit read-only memories are used in the toy to hold data for about 330 words and phrases \(em lasting between 3 and 4 minutes \(em of speech. At the time (mid-1978) these memories were the largest that were available in the industry. The data flow and user dialogue are handled by a microprocessor, which is the fourth LSI circuit in the photograph of Figure 11.8. .FC "Figure 11.8" .pp A schematic diagram of the toy is given in Figure 11.9. .FC "Figure 11.9" It has a small display which shows upper-case letters. (Some teachers of spelling hold that the lack of lower case destroys any educational value that the toy may have.) It has a full 26-key alphanumeric keyboard with 14 additional control keys. (This is the toy's Achilles' heel, for the keys fall out after extended use. More recent toys from TI use an improved keyboard.) The keyboard is laid out alphabetically instead of in QWERTY order; possibly missing an opportunity to teach kids to type as well as spell. An internal connector permits vocabulary expansion with up to 14 more read-only memory chips. Controlling the toy is a 4-bit microprocessor (a modified TMS1000). However, the synthesizer chip does not receive data from the processor. During speech, it accesses the memory directly and only returns control to the processor when an end-of-phrase marker is found in the data stream. Meanwhile the processor is idle, and cannot even be interrupted from the keyboard. Moreover, in one operational mode ("say-it") the toy embarks upon a long monologue and remains deaf to the keyboard \(em it cannot even be turned off. Any three-year-old will quickly discover that a sharp slap solves the problem! A useful feature is that the device switches itself off if unused for more than a few minutes. A fascinating account of the development of the toy from the point of view of product design and market assessment has been published (Frantz and Wiggins, 1981). .[ Frantz Wiggins 1981 .] .rh "Control parameters." The lattice filtering method of linear predictive synthesis (see Chapter 6) was selected because of its good stability properties and guaranteed performance with small word sizes. The lattice has 10 stages. All the control parameters are represented as 10-bit fixed-point numbers, and the lattice operates with an internal precision of 14 bits (including sign). .pp There are twelve parameters for the device: ten reflection coefficients, energy, and pitch. These are updated every 20\ msec. However, if 10-bit values were stored for each, a data rate of 120 bits every 20\ msec, or 6\ Kbit/s, would be needed. This would reduce the capacity of the two read-only memory chips to well under a minute of speech \(em perhaps 65 words and phrases. But one of the desirable properties of the reflection coefficients which drive the lattice filter is that they are amenable to quantization. A non-linear quantization scheme is used, with the parameter data addressing an on-chip quantization table to yield a 10-bit coefficient. .pp Table 11.6 shows the number of bits devoted to each parameter. .RF .in+0.3i .ta \w'repeat flag00'u +1.3i +0.8i .nr x0 \w'repeat flag00'+1.3i+\w'00'+(\w'size (10-bit words)'/2) \l'\n(x0u\(ul' .nr x1 (\w'bits'/2) .nr x2 (\w'quantization table'/2) .nr x3 0.2m parameter \0\h'-\n(x1u'bits \0\0\h'-\n(x2u'quantization table .nr x2 (\w'size (10-bit words)'/2) \0\0\h'-\n(x2u'size (10-bit words) \l'\n(x0u\(ul' .sp energy \04 \016 \v'\n(x3u'_\v'-\n(x3u'\z4\v'\n(x3u'_\v'-\n(x3u' energy=0 means 4-bit frame pitch \05 \032 repeat flag \01 \0\(em \z1\v'\n(x3u'_\v'-\n(x3u'\z0\v'\n(x3u'_\v'-\n(x3u' repeat flag =1 means 10-bit frame k1 \05 \032 k2 \05 \032 k3 \04 \016 k4 \04 \016 \z2\v'\n(x3u'_\v'-\n(x3u'\z8\v'\n(x3u'_\v'-\n(x3u' pitch=0 (unvoiced) means 28-bit frame k5 \04 \016 k6 \04 \016 k7 \04 \016 k8 \03 \0\08 k9 \03 \0\08 k10 \03 \0\08 \z4\v'\n(x3u'_\v'-\n(x3u'\z9\v'\n(x3u'_\v'-\n(x3u' otherwise 49-bit frame __ ___ .sp 49 bits 216 words \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in-0.3i .FG "Table 11.6 Bit allocation for Speak 'n Spell chip" There are 4 bits for energy, and 5 bits for pitch and the first two reflection coefficients. Thereafter the number of bits allocated to reflection coefficients decreases steadily, for higher coefficients are less important for intelligibility than lower ones. (Note that using a 10-stage filter is tantamount to allocating .ul no bits to coefficients higher than the tenth.) With a 1-bit "repeat" flag, whose role is discussed shortly, the frame size becomes 49 bits. Updated every 20\ msec, this gives a data rate of just under 2.5\ Kbit/s. .pp The parameters are expanded into 10-bit numbers by a separate quantization table for each one. For example, the five pitch bits address a 32-word look-up table which returns a 10-bit value. The transformation is logarithmic in this case, the lowest pitch being around 50 Hz and the highest 190 Hz. As shown in Table 11.6, a total of 216 10-bit words suffices to hold all twelve quantization tables; and they are implemented on the synthesizer chip. To provide further smoothing of the control parameters, they are interpolated linearly from one frame to the next at eight points within the frame. .pp The raw data rate of 2.5\ Kbit/s is reduced to an average of 1200\ bit/s by further coding techniques. Firstly, if the energy parameter is zero the frame is silent, and no more parameters are transmitted (4-bit frame). Secondly, if the "repeat" flag is 1 all reflection coefficients are held over from the previous frame, giving a constant filter but with the ability to vary amplitude and pitch (10-bit frame). Finally, if the frame is unvoiced (signalled by the pitch value being zero) only four reflection coefficients are transmitted, because the ear is relatively insensitive to spectral detail in unvoiced speech (28-bit frame). The end of the utterance is signalled by the energy bits all being 1. .rh "Chip organization." The configuration of the lattice filter is shown in Figure 11.10. .FC "Figure 11.10" The "two-multiplier" structure (Chapter 6) is used, so the 10-stage filter requires 19 multiplications and 19 additions per speech sample. (The last operation in the reverse path at the bottom is not needed.) Since a 10\ kHz sample rate is used, just 100\ $mu$sec are available for each speech sample. A single 5\ $mu$sec adder and a pipelined multiplier are implemented on the chip, and multiplexed among the 19 operations. The latter begins a new multiplication every 5\ $mu$sec, and finishes it 40\ $mu$sec later. These times are within the capability of p-channel MOS technology, allowing the chip to be produced at low cost. The time slot for the 20'th, unnecessary, filter multiplication is used for an overall gain adjustment. .pp The final analogue signal is produced by an 8-bit on-chip D/A converter which drives a 200 milliwatt speaker through an impedance-matching transformer. These constitute the necessary analogue low-pass desampling filter. .pp Figure 11.11 summarizes the organization of the synthesis chip. .FC "Figure 11.11" Serial data enters directly from the read-only memories, although a control signal from the processor begins synthesis and another signal is returned to it upon termination. The data is decoded into individual parameters, which are used to address the quantization tables to generate the full 10-bit parameter values. These are interpolated from one frame to the next. The lower part of the Figure shows the speech generation subsystem. An excitation waveform for voiced speech is stored in read-only memory and read out repeatedly at a rate determined by the pitch. The source for unvoiced sounds is hard-limited noise provided by a digital pseudo-random bit generator. The sound source that is used depends on whether the pitch value is zero or not: notice that this precludes mixed excitation for voiced fricatives (and the sound is noticeably poor in words like "zee"). A gain multiplication is performed before the signal is passed through the lattice synthesis filter, described earlier. .sh "11.4 Programmable signal processors" .pp The TI chip has a fixed architecture, and is destined forever to implement the same vocal tract model \(em a 10'th order lattice filter. A more recent device, the Programmable Digital Signal Processor (Caldwell, 1980) from Telesensory Systems allows more flexibility in the type of model. .[ Caldwell 1980 .] It can serve as a digital formant synthesizer or a linear predictive synthesizer, and the order of model (number of formants, in the former case) can be changed. .pp Before describing the PDSP, it is worth looking at an earlier microprocessor which was designed for digital signal processing. Some industry observers have said that this processor, the Intel 2920, is to the analogue design engineer what the first microprocessor was to the random logic engineer way back in the mists of time (early 1970's). .rh "The 'analogue microprocessor'." The 2920 is a digital microprocessor. However, it contains an on-chip D/A converter, which can be used in successive approximation fashion for A/D conversion under program control, and its architecture is designed to aid digital signal processing calculations. Although the precision of conversion is 9 bits, internal arithmetic is done with 25 bits to accomodate the accumulation of round-off errors in arithmetic operations. An on-chip programmable read-only memory holds a 192-instruction program, which is executed in sequence with no program jumps allowed. This ensures that each pass through the program takes the same time, so that the analogue waveform is regularly sampled and processed. .pp The device is implemented in n-channel MOS technology, which makes it slightly faster than the pMOS Speak 'n Spell chip. At its fastest operating speed each instruction takes 400 nsec. The 192-instruction program therefore executes in 78.6\ $mu$sec, corresponding to a sampling rate of almost 13\ kHz. Thus the processor can handle signals with a bandwidth of 6.5\ kHz \(em ample for high-quality speech. However, a special EOP (end of program) instruction is provided which causes an immediate jump back to the beginning. Hence if the program occupies less than 192 instructions, faster sampling rates can be used. For example, a single second-order formant resonance requires only 14 instructions and so can be executed at over 150\ kHz. .pp Despite this speed, the 2920 is only marginally capable of synthesizing speech. Table 11.7 gives approximate numbers of instructions needed to do some subtasks for speech generation (Hoff and Li, 1980). .[ Hoff Li 1980 Software makes a big talker .] .RF .nr x0 \w'parameter entry and data distribution0000'+\w'00000' .nr x1 \w'instructions' .nr x2 (\n(.l-\n(x0)/2 .in \n(x2u .ta \w'parameter entry and data distribution0000'u \l'\n(x0u\(ul' .sp task \0\0\0\0\0\h'-\n(x1u'instructions \l'\n(x0u\(ul' .sp parameter entry and data distribution 35\-40 glottal pulse generation \0\0\0\08 noise generation \0\0\011 lattice section \0\0\020 formant filter \0\0\014 \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .in 0 .FG "Table 11.7 2920 instruction counts for typical speech subsystems" The parameter entry and data distribution procedure collects 10 8-bit parameters from a serial input stream, at a frame rate of 100 frames/s. The parameter data rate is 8\ Kbit/s, and the routine assumes that the 2920 performs each complete cycle in 125\ $mu$sec to generate sampled speech at 8\ kHz. Therefore one bit of parameter data is accepted on every cycle. The glottal pulse program generates an asymmetrical triangular waveform (Chapter 5), while the noise generator uses a 17-bit pseudo-random feedback shift register. About 30% of the 192-instruction program memory is consumed by these essential tasks. A two-multiplier lattice section takes 20 instructions, and so only six sections can fit into the remaining program space. It may be possible to use two 2920's to implement a complete 10 or 12'th order lattice, but the results of the first stage must be passed to the second by transmitting analogue or digital data between each of the 2920's analogue ports \(em not a terribly satisfactory method. .pp Since a formant filter occupies only 14 instructions, up to nine of them would fit in the program space left after the above-mentioned essential subsystems. Although other necessary house-keeping tasks may reduce this number substantially, it does seem possible to implement a formant synthesizer on a single 2920. .rh "The Programmable Digital Signal Processor." Whereas the 2920 is intended for general signal-processing jobs, Telesensory Systems' PDSP (Programmable Digital Signal Processor) is aimed specifically at speech synthesis. It comprises two separate chips, a control unit and an arithmetic unit. To build a synthesizer these must be augmented with external memory and a D/A converter, arranged in a configuration like that of Figure 11.12. .FC "Figure 11.12" .pp The control unit accepts parameter data from a host computer, one byte at a time. The data is temporarily held in buffer memory before being serialized and passed to the arithmetic unit. Notice that for the 2920 we assumed that parameters were presented to the chip already serialized and precisely timed: the PDSP control unit effectively releases the host from this high-speed real-time operation. But it does more. It generates both a voiced and an unvoiced excitation source and passes them to the arithmetic unit, to relieve the latter of the general-purpose programming required for both these tasks and allow its instruction set to be highly specialized for digital filtering. .pp The arithmetic unit has rather a peculiar structure. It accomodates only 16 program steps and can execute the full 16-instruction program at a rate of 10\ kHz. The internal word-length is 18 bits, but coefficients and the digital output are only 10 bits. Each instruction can accomplish quite a lot of work. Figure 11.13 shows that there are four separate blocks of store in addition to the program memory. .FC "Figure 11.13" One location of each block is automatically associated with each program step. Thus on instruction 2, for example, two 18-bit scratchpad registers MA(2) and MB(2), and two 10-bit coefficient registers A1(2) and A2(2), are accessible. In addition five general registers, curiously numbered R1, R2, R5, R6, R7, are available to every program step. .pp Each instruction has five fields. A single instruction loads all the general registers and simultaneously performs two multiplications and up to three additions. The fields specify exactly which operands are involved in these operations. .pp The instructions of the PDSP arithmetic unit are really very powerful. For example, a second-order digital formant resonator requires only two program steps. A two-multiplier lattice stage needs only one step, and a complete 12-stage lattice filter can be implemented in the 16 steps available. An important feature of the architecture is that it is quite easy to incorporate more than one arithmetic unit into a system, with a single control unit. Intermediate data can be transferred digitally between arithmetic units since the D/A converter is off-chip. A four-multiplier normalized lattice (Chapter 6) with 12 stages can be implemented on two arithmetic units, as can a lattice filter which incorporates zeros as well as poles, and a complex series/parallel formant synthesizer with a total of 12 resonators whose centre frequencies and bandwidths can be controlled independently (Klatt, 1980). .[ Klatt 1980 .] .pp How this device will fare in actual commercial products is yet to be seen. It is certainly much more sophisticated than the TI Speak 'n Spell chip, and a complete system will necessitate a much higher chip count and consequently more expense. Telesensory Systems are committed to producing a text-to-speech system based upon it for use both in a reading machine for the blind and as a text-input speech-output computer peripheral. .sh "11.5 References" .LB "nnnn" .[ $LIST$ .] .LE "nnnn" .bp .ev2 .ta \w'\fIsilence\fR 'u +\w'.EH100'u +\w'(used to change amplitude and duration)00'u +\w'00000000000test word'u .nr x0 \w'\fIsilence\fR '+\w'.EH100'+\w'(used to change amplitude and duration)00'+\w'00000000000test word' \l'\n(x0u\(ul' .sp .nr x1 (\w'Votrax'/2) .nr x2 (\w'duration (msec)'/2) .nr x3 \w'test word' \h'-\n(x1u'Votrax \0\h'-\n(x2u'duration (msec) \h'-\n(x3u'test word \l'\n(x0u\(ul' .sp .nr x3 \w'hid' \fIi\fR I 118 \h'-\n(x3u'hid I1 (sound equivalent of I) \083 I2 (sound equivalent of I) \058 I3 (allophone of I) \058 .I3 (sound equivalent of I3) \083 AY (allophone of I) \065 .nr x3 \w'head' \fIe\fR EH 118 \h'-\n(x3u'head EH1 (sound equivalent of EH) \070 EH2 (sound equivalent of EH) \060 EH3 (allophone of EH) \060 .EH2 (sound equivalent of EH3) \070 A1 (allophone of EH) 100 A2 (sound equivalent of A1) \095 .nr x3 \w'had' \fIaa\fR AE 100 \h'-\n(x3u'had AE1 (sound equivalent of AE) 100 .nr x3 \w'hod' \fIo\fR AW 235 \h'-\n(x3u'hod AW2 (sound equivalent of AW) \090 AW1 (allophone of AW) 143 .nr x3 \w'hood' \fIu\fR OO 178 \h'-\n(x3u'hood OO1 (sound equivalent of OO) 103 IU (allophone of OO) \063 .nr x3 \w'hud' \fIa\fR UH 103 \h'-\n(x3u'hud UH1 (sound equivalent of UH) \095 UH2 (sound equivalent of UH) \050 UH3 (allophone of UH) \070 .UH3 (sound equivalent of UH3) 103 .UH2 (allophone of UH) \060 .nr x3 \w'hard' \fIar\fR AH1 143 \h'-\n(x3u'hard AH2 (sound equivalent of AH1) \070 .nr x3 \w'hawed' \fIaw\fR O 178 \h'-\n(x3u'hawed O1 (sound equivalent of O) 118 O2 (sound equivalent of O) \083 .O (allophone of O) 178 .O1 (sound equivalent of .O) 123 .O2 (sound equivalent of .O) \090 .nr x3 \w'who d' \fIuu\fR U 178 \h'-\n(x3u'who'd U1 (sound equivalent of U) \090 .nr x3 \w'heard' \fIer\fR ER 143 \h'-\n(x3u'heard .nr x3 \w'heed' \fIee\fR E 178 \h'-\n(x3u'heed E1 (sound equivalent of E) 118 \fIr\fR R \090 .R (allophone of R) \050 \fIw\fR W \083 .W (allophone of W) \083 \l'\n(x0u\(ul' .sp3 .ce Table 11.2 Votrax sound segments and their durations .bp \l'\n(x0u\(ul' .sp .nr x1 (\w'Votrax'/2) .nr x2 (\w'duration (msec)'/2) .nr x3 \w'test word' \h'-\n(1u'Votrax \0\h'-\n(x2u'duration (msec) \h'-\n(x3u'test word \l'\n(x0u\(ul' .sp \fIl\fR L 105 L1 (allophone of L) 105 \fIy\fR Y 103 Y1 (allophone of Y) \083 \fIm\fR M 105 \fIb\fR B \070 \fIp\fR P 100 .PH (aspiration burst for use with P) \088 \fIn\fR N \083 \fId\fR D \050 .D (allophone of D) \053 \fIt\fR T \090 DT (allophone of T) \050 .S (aspiration burst for use with T) \070 \fIng\fR NG 120 \fIg\fR G \075 .G (allophone of G) \075 \fIk\fR K \075 .K (allophone of K) \080 .X1 (aspiration burst for use with K) \068 \fIs\fR S \090 \fIz\fR Z \070 \fIsh\fR SH 118 CH (allophone of SH) \055 \fIzh\fR ZH \090 J (allophone of ZH) \050 \fIf\fR F 100 \fIv\fR V \070 \fIth\fR TH \070 \fIdh\fR THV \070 \fIh\fR H \070 H1 (allophone of H) \070 .H1 (allophone of H) \048 \fIsilence\fR PA0 \045 PA1 175 .PA1 \0\05 .PA2 (used to change amplitude and duration) \0\0\- \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .sp3 .ce Table 11.2 (continued) .bp .ta 0.8i +2.6i +\w'(AH1 .UH2) (O U)000'u .nr x0 0.8i+2.6i+\w'(AH1 .UH2) (O U)000'+\w'; i uh \- here' \l'\n(x0u\(ul' .sp vowel clusters EH I A1 AY ; e i \- hey UH OO O U ; uh u \- ho AE I (AH1 EH3) I ; aa i \- hi AE OO (AH1 .UH2) (O U) ; aa u \- how AW I (O UH) E ; o i \- hoi I UH E I ; i uh \- here EH UH (EH A1) EH ; e uh \- hair OO UH OO UH ; u uh \- poor Y U Y1 (IU U) .sp vowel transitions {F M B P} O (.O1 O) {L R} EH (EH3 EH) {B K T D R} UH (UH3 UH) {T D} A1 (EH3 A1) {T D} AW (AH1 AW) {W} I (I3 I) {G SH W K} OO (IU OO) AY {K G T D} (AY Y) E {M T} (E Y) I {M T} (I Y) E {L} (I3 UH) EH {R N S D T} (EH EH3) I {R T} (I I3) AE {S N} (AE EH) AE {K} (AE EH3) A1 {R} (A1 EH1) AH1 {R P K} (AH1 UH) AH1 {ZH} (AH1 EH3) .sp intervocalics {voiced} T {voiced} DT .sp consonant transitions L {EH} L1 H {U OO IU} H1 \l'\n(x0u\(ul' .sp3 .ce Table 11.5 Contextual rules for Votrax sound segments .bp \l'\n(x0u\(ul' .sp consonant clusters B {stop-consonant} (B PA0) P {stop-consonant} (P PA0) D {stop-consonant} (D PA0) T {stop-consonant} (T PA0) DT {stop-consonant} (T PA0) G {stop-consonant} (G PA0) K {stop-consonant} (K PA0) {D T} R (.X1 R) K R .K (.X1 R) {consonant} R .R {consonant} L L1 K W .K .W D ZH D J T SH T CH .sp initial effects {.syll} P {vowel} (P .PH) {.syll} K {vowel} (K .H1) {.syll} T {vowel} (T .S) {.syll} L L1 {.syll} H {U OO O AW AH1} H1 .sp terminal effects E {PA0} (E Y) \l'\n(x0u\(ul' .ta 0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i +0.8i .sp3 .ce Table 11.5 (continued) .ev N@```@@@@@@@@@@@@(0****e********Ke‰Pw}LbX8AʀB7BXXBrBXBBxB~BTBBBK@-*@G›`,@¼,ˆ†ŒVB,B)HB9dBbBB,BBBBpBB?B((4db$„{`e?(@B<BOhBZBiBHBBBBBh B:B.\^8›…`<\hf4B`B5LB2TB8BcB<B(BBBBlBHAk@-=Qƒ¼ «–$†jI4B>XB_B_|Bq4BBBBBBPBXPA@,:,^hšT³…~<j[0AB1B[B$BxBoB[lB`BLB]AB1Aft_^Tm8‚pJd*BB*BPBilBBBBBxB\BuB:<8Aƒ”Œ Ÿ™P ttfXN `BB7 BPBwBDBLBBu0Bp BBhB"(d'?4l•£@svf(@ABB#B:B{BxB´B,BBBhBBC..WœL´¦¢Dn8O$TBB-8BL<BgdBtBd,BwXBBBB/ 2Yl‰©®(Š cOL7 $A@B'BB<BeBBTBB BBBBTD·P4½0š•p•x@T' B<BAdB\8Bi(BBBBBBuBJBd@#iL•¥@ސ–|Œv|`4(4@B@B@dBpB0BlBBBB4BL8@1D&_ ށ‘› š…8pTBeB0`B<B_B B|BBBBmBi0BwBP9/8S\€ž¡ ’}{ jFTBB$hB:B~BdBBTBB(BLBPBQTA=tUƒ©ʀψψ†:B8B%\BItBBBBBjBWBJBGB$')4`8 ²4´Lš|@T,B8BaBxB(BB$B~BjtBNB@B-DA5r ¦d«h”$~~Ol"AƀB#B6`BbBBdBdBTBBBtBPB"U‚‡(n<d_P_dF>h AB=LBSBbByBBv BHBBBCIy‰|‹Xldd}}=$Af@A@ABKBBdBBktB_LBXDBaBAT')7T[Œ|®£Š{<XR<<@B+BaXBvB} BB(B(B~hB||BBqB P,ˆ£T«X¯Ÿ}Zd,`BB4Be\BDB`BPB(B BBBp,B+l18F]|v$­¬£pŽc(B,BpBBB\BBBBeBWXB/EhRD(g´¿$dQk`8xBBLB*BZBDBt<BB@BBe0B[lBP A,;<R(Tʀ£Žu0V#@BB5B4<BCBf\B$B B}Bf$B@BBBCA!*8X<z “’LlkrPA!A&B$hBxBBBB\BfBOB6A@7@j|rwh–¯µdŸŠŽ—,cA3B=BILBl8BB|BBHBB|BQXB0B@,|GZ(y¡¡ŽP€œh*tA7@AB(BJBgB4B<BB}BmB~8Bi\B/Tx‰•Ÿ<¨´—rV,\-tAB4B=BFdBwB`BhBB8BBTBE BAT!@O$hDn|‚twvl|N BdB$BI(BxBB~BxBm(B^dBd<B=BLt(#0W”­ž˜\ —Ql@BBAB{BB BB8BBvBcB^B*j5jd•¯P‚o ][tN)BB&$BBBk$B`B$BDBBwBBBFA[>|x𠍲¯8—\{Jp6X'hB#xBUxBgdBehBuBw|BwB\ByB;\/a€h,xrpHU3dAqB#BMBBLBBvDBY|B\@BWBJxB` /05|a€œ˜‘8ˆ@s|Qt,B(HBO BoBBBdBBBBB]B`H(Cpr8©ž¨Hœ‰@O`AB"BHDBqBpBBq8BjBuBBmB)AB`KX~› œ·µ4 œ ‚a4-BB2BRdBkBBBBBpB]B?B@4%4Jz’ž<” ŽzXn8H@A{BlBNBvXBDBB|B4BBndBQ BADB*tAJ‰0}s‚‹wDFBlB8`BA0BQBtBBBBPBBB^B$;dpP—BDBBxAaAoI4BF BBJtL¶n6WBBH/'}Bi4BAЀy$¡ $HBB4BBAw _BmBΈA"°@“ I@8B!B A'@œ"Dd(BBB=l…¡,$HBLBBB<A@z0ACCdB#X])BvBBB|B{jPk8BCCBe b\NƀB)BpBgH¿0YBB$‘ ¦hB4BSҰ»BJ\BBQ²DB@TBB`BU(¶TXBBذA4(TBFBPBwœ¼BnTCNB1H<BqBBByX2y?BCCBB@BnCCCBNB HBhCB,^BtByAH‰"VBtBM vYB3hBBB!4<BBY`{B#HBB@5a@B0CBe6BBBBrB1˜BXCXCB$‚XBDCCVBArB8dzBCJCg U/BaBCvBoOHBBB\B0gD–B"BŨBdT-t@BXBBoQXUguBȤB؀?Nw•BBڔWZBopBmpB9|A°E¶hBgCBT¢„B^<BtCBpB+$B5C|C#aBƒ<BmC|CC"B8 IB C6CB)lbpCuCA0`BE(CAr@'qOBQXB0h*e‚ Te“BCX\A'@BDBBr>X:­4BTC_Bd‡“LB0BTCB;wXJBmTCCiBzxtqCCtN@```@@@@@@@@@@@@(0****ex********PeBBPB(±AB85PB HBB[XdBmXBB«eHBGBcLB7TBB¨$BBB6$¿lG,1BBm40NxB<B$BmB7X¾`›B)pB=BZBBt0ºBZBxBB'LBB\0BFBo$V˜Bu8BɌBvD$h¤:dB\ BB^C.Bc­BHxB_B9B10 CyBBCC7$CGCDC2C;#$4%#$ {05n7t>7*%lC#CKlC^xCqhCxCXPC5nC2MC.OCB< ;jQ`^,h(cTxMJ'BmdC C5 CLCOCQCb@ChTCXCFC.Bx'6fKRX@hH`@&D BhC!C/CDCZ@Ca`C_CUPC6OCCPA($u12HZSA/mE¼µAECOC%C0CFCBC.mC.}C3C"C=B"u2s3(U'$'!pEBCCCBCdBtC"C&TC]C#vCBCh`ABk *$nN8rBLCC#YC CB<B3<B#BBdP.BFBB6EBS@BB/BCBdXACA@*HjKŠtB$Bg8CC`B|BCBBB֌7',+,©ld ‹CC#CC =CpBBCB<BBC, ¯Š=g@B,CMCC?BB0CCC?Bl:4j•ɀ8*BVB,B80‡AC/BBC4B«CCbBBdB~\P¯zT_(BLB!BqRd‘B)hB|C1C,B|XOBqBmtBC C4 CnC–'mBBBCB]31BC""B1ACZCI@=„C'^C'I/FC7wC9mI"¯c@)hB;CC)C[BB@B,(2,'BRB[|T0mH**1B΀CC0Bz4BH B`90xBBFtBBTBBBx|L,!^?BtB4rAB\BXBJxBB0deB`B BrBB0BBB4BJB(BGd•ŸBhBB(BHBJjA݀B/|¡BARBqB4…/PBxCDB$Yxf_CA<C"LŠCC%C'CB1D,b2 !TB]C$C-C1B(A B(C"B@B2@BTBQTBƐCB@#&C8CC0BHxB7<BBCtCBAv@.(E…)2, <IMB"CC'CC&C!CBИB>@xAd6BpC C$C*"CnB:/"º@0—F$<` žAB@CXCCiB:pyHHBBBTdB#dBDB7BBbXB@=̀žtBc C`CBXB57X©µBLn%{y+XCC!@CCBVd0AπBC2CBB>B1B$B`CWB%ÐB}TClCbBBrTB:Ž©@}ҨB8CBO$¼,z¸ BV8CCCB&|€xl([ped*PB$LD7B8CBTA|@—DDŽ6BCCBBwBCB4Ap@hwh5LB@CjCBT";B&hB2{4¿fXBiBBq‘ %CC(C1C'C(Bd,BB@CCcBpBPBxB'BBB|P{ B(BBA§\WH|B^0B)|Uנc~BlBGLz%L|BBBl\lxBBCBuqB\CBKP3‰,BBΌB.L‡@BˀC1C\B{—B tCqCCBeP4B7|CC%qC8BDCC!C9„?C C2BP6LA9@CB`B&CC:B £iBXC B˜!IBC$C/BD'4'4YBB8$- AC4CD@Y]|BTBܼA@œCC!CBkA'B BC9C%C9‡C4C)C&[BS(DBLBC9C$C¦(CC pCM*/)CŸBQ<A @%8pB¨BÌ¥D!$M@BCNx*8SMBBN0dq@CC$CiTudBtC!3C"Cq@SACsC(3C/4CŸ\B8CMCtCB‡uP:LB?BB#Q!¨8CC Bh+"k:ʌBk$B8[BCB!t wB}CCB@R]\BpBެB6©`h¡B&C=C$CC$u¦LBCC<B[TBCbBɜDBC|CBLžt@B`CB”BCBxV «2BC:C¨6‰BCrBK! B<C+T`ºB$CBllBBX@ qtC7C$C#2B,LNBCBACCCo,jH7BCnC tBhBf‚Š BLBBVd”D0®B*TChCQA\ŠDBIhBP}[BĸCCC‘}ˆ|BC Ch6 BC6B7™lBBB CSBCPCB[prPQ$BC2BcU£BaBB(j4w<BX|BBG CCBx uA4@B@BLBƠVS:|B0C{N@```@@@@@@@@@@@@(0   ****  e@********UeR9lBItB\IBPBNȀ†²eB<BЌBռBä$B58A@0AV`BBCKCBYpBt`BBNTz4ʜB/BBq0†VpBV,B|B\@*4@B,BXHB)wH\„PBBIB*@*&0AhT—K&B`C&C= CFCGC=C#B`" .,H`WLUH'BC>C^8CiCgC`CUCNCJ0C9@CB|);@Ug8uTqW7UC5C(C2CACTC]PCYpCThCFtC)B¶ 'Mlapb<Z(O="fa<BLCC8CUCcCV(C?TC4C1C'C\P7TTC?B;%"BaCC5{C<@C84C:CCxCCC6C&CBuh)466}<8?$3)sBMTC}CCC C#C2C6QC.6C CxB4tº%.L.#dBtBˬB=(BCC"_C'C#bCCB@B(dO‘tY$1L( hAB?BCC&C$AHBrB(BB@BtBhB]BBB\BM$$opAQBNB3؀£ °|,A<_w|gZl^\(~`(@N@```@@@@@@@@@@@@(0****e********YefBTBB5v[V…<]jB|BlBB`-A3Hy4BYLBM`BA@B=X¢›@B;BBpBiHBWXBJB,dAUg5ATBB$|BEpB;xhŸ T k.I0BBC'CACUxCdPCcCKlC4C+CABH-,A$\xhÊÐÖlÒPuB@CECK C{0ClCCCCClC4C1iäָϐüãDÇjH"BtC>C|ChCCCTCCzTC1gXÃÚâÚÆo4[G*\XCC?TCcC$CXCCCpCIC#YP@ht$vna,QA/hB^$C$C>8CSCgCvtCyCgCDCBUx92NCB@>A<C8%>/†hBC C$C+C5}C7C.C C<BdB:g,VQ#.(%-pBPtB0CCCCCC#C<$CEC/OhQH#B<|BHBXC CGCJCNCiC%CBCC B+u\lC(CpùCEPCCILC?CCsOê ñxÄC$CtCCCCD"H}ßfdC CCCӰCpCt$(É(PÓ7CCECJC1Bzr.F8-~BPC!C'C^B]$°$#@I3®CC3CC6C7C:=C-CuAd@BqCCCUCCC!CBp$( -: B&(CΌBNC"CNBBC?C&PC,C)C&C$C"CCzBBW~, -8 ==741/*j _BOBCC1CCCPCXCY`CTCLC>C--C"8B @%}8X@tDXGXIJTD4"`CC$C1C@,CNCW`C]C]CSC?C-CC>C#BfL‰ .-3x6;:1~.0)2BdCBBlCC6CACC*BNahU b³ ž3,B2BB6 š lP $ -0L.k--'"$' &,>pBTCOCCC!C*C+C0C;C;C9C>CH4CPDCQCG(C8'C,*C&C C=COCB"FBtBUhBDS@lT›T'./.*%>G?:-=T;;6z67/*/lpe¸BP0BCCCdCnCC#C*.C<C=C2:C0eC9@C9C6C;xC>(C1"CCCC(C BaLμp²`!}! &%Ja0 J<!X|†§PqAPBC;BP@1psDBLB^(A.4_´B*BBdHdiBcCCBpB=D½HBBX"p?<ejº(LBtCCjCDAB~(BΤBBBBP$B"BCQC:B4?l}TABBBC BBLHfBB%W8µp€ Kw,k© .®BA„҈YB3## <Ba@BݴBqƒ³(BO¢Œ`BkCC)ZC#BP%X¶0RCqC!zC"`CBtB]BCkC C/AJBBBBC!CxBCGMAMXB8pdENP¥¶rf™ª‚LV0>BpCA‹ BIBC+C6B`BBC\CC CBpS¼L]&BBB1$ԼŒlBCOC9¶ |BBhCICB¯`¢BC!B;9<AA.B/WBF$CCBAi X<‰3B%|ƒ,)f0BCMB7Ϩ1<HxBnCBL—t‹4BpC BuO(S`ABB|B84¨pBa|CCBݸ9bBB8 B^BDBHY `BCCB3\3|BjB) l2@B0C?BbWKlBB B^bD\\BCCm/ڴ-B3[JqBC B(L<–S`DB,BBA0 {B^CCB3™T«­“AMBBWtxx`,BdXCCB4‡DSxBZB@BB$BPvA@BPBDqg[XpxtBMBB|btBGLBΈBT8HdiAp@BPBz9P%L-D(HBBP@*JLHi{šª³¯(`θ£_#QPJ\Qg<L0AkB,E),Ap(0lAB!B"TBB,(BVB8BBB0Bx$BBPByBoBo<B`(B<BtBB.B-tR,MK[iTW, `D@B&BT4BsB`BJBgBlBt<B>|B/0BX5@A`BA)P#%.dD<GG W Y<@*8,hAU@A,TSFt=gf]TS<J4D%pAB0BGBJB)B B3B5dB0\BKDB{LByXBx|B[HByBpTBp`B]BTBPBHBAHBR<BaB^LBAB4B8BGBJTB7B/B!(A@3<+"0T6V[@AMF0785LAhApCdmla^Z\hP iTYIB>@pA@BB6BQBIPB)dB BB#DB0B5pBKBXlBj|BhPBfBoBtBYBABFB<B%AAo@A@BBLA1*M@8FL]=A^BB"TB: BSBH|B-B4BAB1P@p@?@%KAt18;|AaBA@BB+XB(LAAB<3e\€}uUC%tA!B*B^BBhBbBY`BMB(x0D06*%h@ABABlB!0BBtB<B(B&B+B:\BDBEBCtB"0BxBBAKA. @)&UO@BBMxBGBP@̀@ X}WHJA`)`245\/<AJA>AMA3+,A\)lt(@$AB2B-B)B%B&B6B;$B+8B%BA@*!AAZA^A@BDB<B%B2B HAWS|##AB8B0dB]DB[lB4TA(x) 2d80N@```@@@@@@@@@@@@(0****e********^e»BBBFBBBBB' d¦xԜB)BXB{DAd77BBB7@M&BTBn4BlBAAr‹(B7B&8Ÿ`a &3Pia?CeXCD(DDDC8]Þ03;õÙtÏÃzd4CCDeDDDDDyCHCwLCSëH  T9Ú0$PCNCDDDDD DCpCpBHRÔ`LɴéÑLqP>Bm CB|CCڈC|CCC4CglC8 nLWÓç æ Ĥ@ Ýp@DCCK ClTCCCpChCCxPC,CCCtC4i€~HÏpÉp?8BaBx2`D`xt@×â zUD4bB;,B#ICBC3C0C/C,C>0CUC\CkCCCUHC=BxB@lL< H^iÊîæÑPÏLÏv;B0C2;CnC@CˬCC@C,C CCxTCIB1 nÙ0ãçléÔsZK?,.[1lCC/C=DCMCbXCxCXCCCC0CCfCQC-@;nbÁËv<[<H!CCCxCkCCdCCm(CEC&\Zé1hˬÍ*IC&bCeCC`CC0CDCCC<CC]C1ICB,¥&f_BKTBbB`C*CFCN|C`C{CCnCWCL CACڬ6\lÀÑ@Ú<ÿ ä4ÎÆr=(4C CFCr`C0CCPCCCCu,CoC]C;C.nES^mÁ4ÖÕÅ~,ufTXI;"xBACC;CEC58C(CC-9C@0CKTCWCqCxCbTC@C#mC2CbDCtClCaLCB$CBP@CC#CnCOBU`wB[-=(IN0VVMDJMS XXLdAT:r, "I"?  jBBC9CCC<C">C-lC-$C(C+C-C2C6 C-C(fC%C&HC/C4C4TC/[C /CCLC#C'C&+CxCB BIHAa“ "/ׄC,4C8_CMP+HIG<-J˜/IHF83"7X,)#i„4(HBRBcB#B\HB|C@COCcCCCJCC%CCGCCB|B(C CABaXe4BC/CBAyT©<BʄCCBh\,}B><B,AՀ®hº#Bv`C7t*~=lC0PjCRCB%C(C!C#&CBRA>A8B|B\BBdʹ¡³{XCC,CACCC1!^p\mtMBC9CwCCPC|C CېC4CCXC0Cv@CnCe CYCNC>C*Cw>ew|Ä0Ã{o(fPbR*+&FL4ڀBDBC-CSChCrxCzlC{$CrCYC+Kpd\j}ã`ûÞ0zWh3CCG\CmCdCCDCXCCCr<CMhCx?WXGh1³B2CC#|C CC^%$##—X$BCBBDB8CCiBBwA*0z,<2CG5*BACC!C8CMCVCRCNCN<CG0C/CBuB:>=(0"$·]¡&#!/U²B[BbB`B_BBBpCB;`XKȘBdC(CBCSC_`CgCeC^CWCLC,M'SD@h\Å}dd|b jSLB~CC {C0C5C+WC'C1^C0ICRSBpBKBYHB24B,BklBBdBB^<B,P© ­€w! (X".§N BB<ChCC!C$CB݀BBC?CBAhc8`X||qM|Ÿ‚TANSK(BCBC"BB8C:CC'2C#B1KeBxCb“<)1"4@B<d!JBτBJ\s~0B0BXnD}_/BLBbB?XB%BxTCC)!C,vCgCCRCC!CBhVNA@B$SHˆh3pB4BKB#BNPC*C}Bx-“BU%DPr“M¨0i3P–h²lgB|BB˜dFAT ¥C&uoB$BB?p[jB,DBzB<HBR@BtBlPBSB\Bdc¸ bB©AƀBݐBXBA,Be@BBA>@B@BlBNle[t|U•B(CB8B2pASBPBBoBcBB|Bdj$A0Z8=gT«WB4C-B^£ R4BBBUp* A@BB`-pBxC CrAY@'LBBpn8¬ZŔB4$B]€+tBBn@<BBXBB‡¬BHBB=žœ6@B*XBªzB4BB\B|;DA1AA@^¢@TB&A@!B+BBABlCCBqXBB BhB=BEBn\B`|et@4BExg`A" •­"BD,pI8LvH#|LB%ji\>B5TBW4'l}(BvBB!'BHB™@BnB^@]B&BB9€B~B}B8 BLAS4¥x`B/BhA]gndBCABLȬ©BBĴjB((BKJ`AB$BBhh„HABYB$lA@A@A­p ».xCOBhLH)BlBe4…PB|BB\B58A@BEBNBKpBa`B7Q›\B@CBC€ABCB%£,-AZ8y ND9(EBQBgA@6|(cA@@B.B=BAcXBDBB+BNB!.C1AZB(6$#+A]BR±e1#ht(!(%}hCD3yD\XDztDDyDZD..?1Sb8ecZ`LFPQ<A4"(CD*DMDcDfDXpDDD3mD"DCDD(D)ID4ODIDRDSxDUDPD3.C(0oLľ3llHZPD#DEEE xE$E&E&E"EEDitRw $#ļ_C1#C('DDYDDEEEEeEEDpDR kĐO!Ľl[CDaDD׼DDDDDKCp@:r0ěĴHĺĮ<đgt3C:D7Dc(DDDD@DLDi(DLD.mD!#o$&(*_+b+h)&#JÎX€CDDCD"D&>D%D!bD$h(B*BZxBLB/A@AB&$BIB:8@ &AB5B7B:B1AhBB9BARxEbLaE8"0zPGAA@B&B0A~AnB4B$BGBo(Be|BGBAB8BlBPBvB$AB/B|BaBIBKB)P'@mŠN$@N@```@@@@@@@@@@@@(0****e********leB7B(B)A A;@Bl8BX)"lAdB#B9\B1B7B1BFB]BK@B%\,L:2TM@@@BBQB\@BH<B++*Ieq`/CCrC8DDDDCCµ\à(6dJ9C_0C DkD!|D'D)D'fD"DvCC)ÐK> ["" 7ޤLCMxCDDD D!lD.DAD$CCtn,4,__íPBCfCDD^CCHCdCDCRqJ\BCFCzC`CC@C\\CMCOCM0CKC>C/C9#CEC*ssռKݜHCQ0CLDDD DDDACCH"BÁ0ù0@@<ÖH7C)C;C2C+46KN=2CCICrCC8CCapC%WlXÃÓÃZ"C"CYCCCC CCpCCC@HCBC;CYCl<CjCKBY\ӄ%u*-&+%mI,CDtD-\D8D?DC,DADHfÓ þ( Ä2C(jC8C݄DDDbDuDDDDCCCBB=0WLo||q^F,BpC#C3C?CDCE<C@TC7gC*CGW\#CdÆ8äDúT,(þç<ÆaL8°C"CLCsCC$C(CCCHCrCJCـ8^zpËÓ ÓLÉuDX7|BC'CBpCULC`CgpCe`CYCFC3C B=^eBCgC!C,C4C;^CACCC@dC6C,rCpB#(*5<?,?A ?D8-$h?²n_Ed01aµD4#_+x|pA@B,C%CgC/C pC"C%C'C'C#YCC+C2CC?C"CBBƘBŜBB|B@BvdBBBLBTBBB,B% E 4 "%h%$ Ѽ]DBBpBHBCZCBBBD€HºX†bBMBhCCC'dC+C.C1`C2KC1 C.C)C%CBB}A@†Y=WlΜ¨•{(z zpa8RB1BePBcBmBOxBSB[BnB?A@9xcƒ¢©wmm`i|6xBCLBoB|HBnBMBL@|!6$9@16@*|*XAB=BpB0C*CC4CeCCCCCCYBXBLB6A{@Ej@‹‘Ÿ d§<¿0 ),nY`³e %Xd@B1BDBPPBFB1B2 B4(B'B`AA^BB.BBtB\,B_BwPB}BwBn@B BtB}PBEB.B-BLA!p^A@B <BC(BA8A€&B*pBfBBB]BTB6(BB"(B1BATB(B>|B=8B$`A!#4 Uprn|j8Y8AABA€BxA׀xA/AHB!B,B)B.|B=BY B\TBc$B] BOBBB)0B(\B+`B$AEp+D3` l@BB,B3$B!B8lBE`BUHBVXBIB#)H[du$‹pŠkxIM4_\^PZx:/,`*@1AB-BfBdB[DB:B5LB&B+BBBgtBh 4CGrš|ЌL`ۄR~tX³–0kXNh:.dBBNB_\BlB`ByBBBXBB̄B BXBĬBxBdBBlB`BJBb\BdBMI,B'BhBvhB`dB8A%1dAՀA(Spvxppr …˜ ¦@°X˜Xrl,ax_P:D!D('(xh)A*&lABBA/DA\B!BBBMdBCBBB;BGBeB{HBv<BjB[BEB?BLpBt Bl\BZ`BK,BMhBYBbDBPBAB2B'BlB2 B9lB&="|%. 8dHTq8•€^MDGlA5#T0FJ<AKJXS ZZ<(`@B(BDBXBp<<VAAB-$B>B>B!BB5BO8BQBcBMBA@BA@H)< .@BABxB_@cAr@A> +BpB'B@ANB@A]+Ri\\KEPB8?5)AB`AA@BB*B;BR|BmBXTB4 B:,B]|BfB[BTB.BAA1BA/-!(+<2%4ABACN,CTCD$DDUC8C4CsC4‡dBzPë\@ß \C8C~ChCC@CCׄC$CDCNC-hg Øþ4Tàp$7cBC9<CfC<CC@C CCrCSC/QB_=Ymxy(o_G)¾<CC)C?CPCYC\dCZCRCBHC-aC@@+ 9VBDB;1#+{BqCCC&C+C-C+C%!CCWB 8װ7%V+-*$Mm@B CC)C1pC5C4C0PC*BC*C*iCBPB-|¾3k,BChCRB2DY&<QUJ@d?EXB$0(3r0Hi\8hC#MCFCVC^dCfCrtCtChHCWCRCPPCICAPC:C2#C 2B;Bb`{<ÉÊd~hM\0R C6C+gC>CJCOCLCCC5C!+BՔAH 8&&"x¸µ0m1!e$# #BCC'C:CKCXCa4Cc$C^CSHCCC/ICLB"&5]AGH|GC=5,!C BC C)C5C@@CGCJCGC@C4C!BԌ|(5kJd[4di`g\K`7.!5ŒCC)C<CK$CUCXCTCKC?(C.eC8B#%4S?F\H F=/+“\BCC0C@CJCTCZCZXCSCH(C9C(yCVBC83+5=HAlB@<85-1"0IPB5BPCCCxCbCC C C bC!#C!C YCCCVCYCBBAfШU %)T+V+*)#&Z#M!³HBBmB B0CCTCC*CjBBBBBTBlB>4B.BHHB|BB0CCCCC$ C)C*C*C'C%fC!C+C7ClB\Bec@Sp†,8HV)Q!M&,r1L47;*>@@>841)o Bs¨ BBxCC"C(iC.C2sC4C4C3C2GC/aC)C%C$C" CvCC9CCxB0BBq(B5T`D“½,B(B_BB$BdBRhB7B%P(0CCFG4@oeDAB0BlB) B6<B-B%lB#dBH &-;h> H/\$3A@BhBABB!B,B5 B\BOBQBDBAB4AIp'C>"tBBpB)BJBdB_BS(Bb BFB/BB BcBB%9XP—¢()BwB01t§0B"BO BcHBC!C6CHCCCCCECCdCsC0B$BaB BCCCCUBBw0!"2! OJO”BaBdCC4CxCCCCICBBB͔BBe B^BT BHBlB|BRB5HB.B4X-Mth™²T¦P“_h2B0,BiB8B,B|C5CCC2CC&C^CB B@B<BWA[@I’(hs/L¹]@B>hB~BBpCsCC>CC[BBBLBGB2~4ª۰J³t–nX.BBy|BHCCCCnCvCCFCCCDBݴB`B,5hzHH0D¢|D@B3@Be$BvBBByBvBp\BHB6B=pB@B-0BBBHAAsB Ar@;p72+t0NbˆH{ymhlwj\ I85`%@3BHB(8B.BE BjBB|BBPBBאBBPB B,BBpBb@BMXB2BApA:",8.1C?>B4Zl0jxlhqƒˆˆ‘wWWbeTX@'tPA@64h||!)|//"0.ACWAp@BB-BE8BgBmBB$BϴBBBtBC BBݐBXBpB\BBTBxhB@PB\0hVXz\{4±8 ¼Ÿ¥|¿8ļҨLº(…S,0# SBB)B$BAdFB`B@|QB0B$lB B<BB.B#BBB#BA@A|@B ANABABB+B?BLBc$BkBcBd8BB@BvBj(BjBb<BLB4B5B<B4 B' B(B2B/B (BB$BA/؀,EFJ`]|Œ‘« @½P¦¦p´(­”ŠŠ v\b_8J1`A@B&B0B8B:0BVB[BP BHBSBuBjBj8BjB,B`BBBB$BPBdB Bj$BjBzXB_hBRBI4BNBCB$`B*B!hBdArAAAT|^t€4ˆ‡pŒdºp¬£§˜x“H{m\ch[S=*/=p2x# dpA@BB#B"B%B7B=B9BM<BtXBBttBU$Bw\BBcDBSXBHBItBGlB6pB"B2B4BA@A@B,B(A{A[Av@)@A5AB(ǀA@A-@+1<O `^bpl,i^\HB 9!,\SAABBB;BX(B^xBN|B7B;BDB=B@B8B5B*B(B"LB.B< B-B'B$4B*BBhB BLA_@ABBB3A@%pCHdA<3',8T8&@.0 8,3P3 A@A@@AlBBTB,B'lB)0BB`BB"B)hBGB6B|ABpBBA݀BAlAjABpA@X@AAA_>Y@AgA(ABAs@@BB\)8;t,424*H*! p##4@AAeAA~Ax@AX@B+@0*A6DAf@pAB*B(BdBDB+hB/BBAAN@```@@@@@@@@@@@@(0''****''eh********ve-iXM @B4PB-AB@Bq N(@BA0}#x@ $pB8lB{dBfB<AdT@B@@BD B(t]8HPB<B^HBQA@<8JBX@BBRA݀9Q(B;BLB(3<_HBpBfTBhB.8BlTBz<BS<B|4)lB BlBXB Qd“T}7\)o$AZBC!C2CECSCVCJC0fB 7K\gn8oj`Y>!;hC~C@Ce$CC`CCCz|CXC4zCbȸ2Wtv(ËtÔÏÁn<Ud4®C"ZCLClxCCtC<C|xCoCYlC7#B8Z=Wgpu(rLdtMH.x|BPC&C8CFCRLC[C\CTCBC.qCjBG'9I0ˆ@^p;@tn<š`šHoYHxq8ŠFxABAo@m/m8\@%^@0„ VQ2BP`'B5DBllBBnB-HB0BrBzBcB[B6B/dBv(BHB$BLB@B)0BBAB_BYPB',tBB1PB+A@BB0B.B*9! /8@hŒL«k8D#!X`rpC48Aa@?l\t O@BAD-BDBaBjtBZB TN@```@@@@@@@@@@@@(0++****++e********zeB,B.HD“`‹CA(0>H;0B.BBB*DBB`Bf|B?\<2\_9 BEXBpAXe&B#B7A#5 `PB4BBD5%B8BbBrBP B$ڀDX=B+<BB~i8aB%B(,X1)B#B<BHBMTG$ABXBfB%`(5#BBBBZ,!PtX``)$58xv~R@NB0CCC+CCCB0!'0;9F:}4-*'x–XBȘCC,C9NCACDlCGCLCF,C0CDP%=4BKTM\KC1rBOC4C%C9XCFCFCA\C9C1CBDB4“(g05.0%NN­$AKBCC+C,C$C\CC)CBMd‰©x @PBBB0BTBBHBѐCC]BBhŽZ\ ||4`BAB{hBRŒTcABBTB9KQhEXA8´9B#B%lR0¨A#$o ¦$˜BB7BkB6"_Œ[B'BB[A\'A@BrBLBXBplB9A@BCMBBC)WTM,PL4O‚B`B8BBBBCCCBpBJ0Pd-T9\‹(lph<B(BdB{PBq`BCCCBBDB:B@BTB):$¦TglXd$Up3B@BBBBXh0fB{DBB;[ψ¹mTpHo\jM$BS(BLB BsABBzDBTB B0BuB"@XB(BBT@ьª¥Ȍ ·BrXB5cFChB`B,B|B@W|Am@BCB|/˜BCAgʌk`fBIB4@BCC~7(WlB<A*B(CaCACBŤBBO@Bn\BBM0«xvB¼|"–tTt B*-}œ(m(B%BCB0B{B=\BjCnCCC_C&CzC(C/nC0C-C) C{CCRCCBe:$OB5P[™ `r$i(%oZ#&4 y[DF8BxCNC!=C$C#C#8C :CC#C(8C!CdBxBBFBZHB04IhLBO&)¶`µd—`y’fBbCCBBB0CCCB֬BwlmhE@,+\¸@sxT P˜B4BBBBW CCC<CBBB<BXBC CB|DxE_@BD`B_8B!1€­X‘dHE ¯ `Ȩ#@dBrBvB6xA@B5BCLCCB\B|BcBC<C4BB)BBRBLBBp,AI|@\£BW8B0rD¬jBBbBX BA(@5=B/BLBոB.$aXkDBGdBM~P§BOA@Š®LBKBBBx B?@BaBB@iMBB[Bs4BOB <54NB"BPBBj TB@BBByTB2xXp)XB^LBpB]Q¿ºCB4B/#dj(HB;pBLBBC0-4@BtdBB BB{ B< AB.BBBD‹Ph¡(KT}yW§\œ(BNBK,'ƒgB)TB8BBMB&hAHB>BB B@L‡,bd 8G4˜`DB0xº֐>$B,O0ˆh±A@BBb2Pr-LBB`BlBÔBBeBPB7BrB0CBpBj,B4BZ BxB0BAW•(’hBAXA5~|“HU\@B.BYA#†`/=Hž »vK0o½(@PŠB!LBlY˜p¼_<Ai@-,MF4BNB0BBjB3BydBCnC>CBBTB,$BcBՠB,BZ;TBBBxB)hHœ8`cHFd»<@fE@BS\—BCCC5BCMCJCC DC#ACMBlPBZBB B(BD$O`¿Ԝ¥X<B - 0@¾`08A{B ``ŸlxPABBjp€v¬-|AB/B8Z0ž‡@B;BB'`j†0BrBBxBQ|BBB=BCB߬A)@BBT$BBLBNDkIhBgBx#<¼FxBBHBu,±T¤]B(XBh@l’lHBUBP2„iCHBBBDBd2DB"BbBBLB;B@A@B)BBAŒ|j5 M@BJ@šX+tBMBnB2BBBXBͬBBSAAbBYpBB¯L«V(]H h’t8TB2XBZ,’º^DB&dBBkpB5AcB4BBBH8pA\ABUBQ$4P’`4h‘٠Yqm˜ L!BBhB($Z<BHB0B0B>6$NDuBdBtBĄB•nBeB|B|Bd=BWBC^B$'Š BBŸB BdšnB"B78$±¾eB6BlBTgh)BXBBq2DHABD4BBB0>PX'B\PB`BlA2uy2BhB7\’¡D^BB|AH»tDB84BBBiAB(B|BhCgCBq@BYBBB?N‡Y@BRBh4 £$µZ(BBOB66šLž(jl@B|HP»X@\4‰ª0£dB!B<BlB-P$@BKBCYB֜BQ\B@AB@BB,B?`™0q B4B3:%<BBB0BO$B-B0BnDBӼBB44k\šf,|B2h€¹¢VB4BUdA@‰|ȋH! B5|B@H!(0TA_B;`AM`¹ ŜysB8TA@Rq4GBBwBB" HXXj@BgBXBdB4BBDAA", BApBW!@`0f0@tAB-BT@XA7@B[BBSA@BXB<BiBBZ<BT'DBB^B@&Dnj,BTBD3pB7GB<AB?B<0jTDA@B.Bh]8uDlB<B$@Jh@B 4B[BLBD|BGB$BBS$BHBB5RDL/u²<X`BoCECC1C%CCCB$tf-t4z/\(r%"D¿4BB0CC&HC.C2C4C9C;XC1SCoBb"/<B0C?2 BCC*pC8@C?pC=C8uC,CBB^}p'0 1+u!xg] B7BCC%QC%C" CCCBB|$=, 3D:BCACC CCCCCBBg|ɄBB\BBŬBCC~CvBΠBAŒŸL‰;>AB.PBA B^ BCuCB8BBy(B;TBQB@sx—§S]SL"+B~B@C$BBXBfB1B1BMHA'Om4„6)Z$jq,œhLBUTBBCB4B9B5\BL(BI4BH @I-@-BIBB@BA"A@BvBlB$d3p?$,FteblO B<B/4?Ml@BuBt Bt&x"B8`BVHsd[ZlI@BHBaDB,A@B$dB,BWxBtBLB_0B$B?BGDLXc@B5@T7U` `BoB_|!$^S,;DB&<BqtB;d '#8BSBBME@ 0Ao@BIB7@+`Œ4sKx¦|–`[BRlBBvHBhBXBDB~B BB<-[d*A@#iŽL­Œ`@DBSDAERDX-$BB8BfBA@Bp#C8BBTBWg/B.<BZBFBpbP0XBBBLxI`~XB?AFEN<ABCC+9z.BC-CR7BdC6I BBŒXBChBظAC"!BvBtB@0xH¯hB$BB^A+{|PH—$”t{pdLA{B.xBQpBhBpTB`BBB,B BqBWB38FHn—(½°wO*`/ G,B(B7BKBxpBBBxBtPB=`—«—tG A8BW\B}BXBT$B" C(n €4P,0Ax@B,BIBc$BgBpBpBoB]BI B@(@[@oX1DO,<BHB8B3B3DBZBzBlB>B%4B(TBN@T!T)*7D<D,/\BB&BtB)B+B`Aŀ8TBD#\pTAB84B:BMBWB[4B7`<QXrt“™|QDB#BEBvB B`BXBP,B<B5B2B6B?B#"Q|j£|²tGBBv BpBИBTBBdBBBKB+BT"NQNL`s8„e(FLApHS<K(9+0/l^B B%B!dBEB[BXBBDBVBDB;B64B/|B"BA@ L@)8|d)!|/'g{ ':J9"4BBUBXB`T@4A4FxX (@B:tB!L(B9Bh\B5tOtJBBpBSl#LYZ^trhB^(BiBsBͬCCBDP0‚d®[$!H4BG\ހ,<BBfBwB\TBpCPJB>B‹B8BӔB2}ˆBA@žeBH4?BشBf@:B.$B(B!L&B$@!BBB`BfL9ABBe`qˆBFBB-A@BWBaX@BULB8BIcB%Bh@p#Bts,44$NG@A!@7| lABAHAB(<B>@A"A@B0A΀A7@BAA@p+3LK0-A,B,B|98E(IdAJ+<`v@B)B_B_<BMB3BBBkv#BB ?AN<U,",)B B(DB9BJHBYpBCBABRB?\B$B!xB)BA'9UBL#5`CAc@BB#|B$B2BCXBVBKhB(AW@(@V@OA @|"$`/(Oc`[hXd8j^(F\LB4BFBcBbBn`BtBrBKBApL8cM(@@tNB)BFBNBXBuBtByBxBPBB{\B>B*A|Eg]5)0@BB+B?HB;HBCB)A&4$%(K_S9<09 A@B+pB,HB14B.D*Dl=(U4wd(0{T~kPXTO8ABxB.`B>B<BLBJBX$BPBWB]B[BmBzBTB@BDBEpB"BBpBXB @B" Aa27A+S*AWAxBB-B*xBA@AB,0|@T3?$,,/L#0(I'<0ap`>$'FF<*xSBBB BHBdB$B$B)B2B>XB6BSBVBJtBQ8BdB]BbBPlB|BBmdBVTBoBnBBDBP%Mm‡`|ub@<?-A.B*B%B(xBB B,A?S[e4s‡ye<YMD8A@B(B-pB |B, B9BHB/BB& B5B BB4A$@HK@XBB=4B>BMB\BbxBWBFB6@BBhl(3(@BB7BABU$B|B}BwBBtBY\B\@BI|B!(@ 7tU(^p8cV`q~@nd[x‚BA5®’T#|8‹\¢ ‚t<RS@L4*04AP@B2LB:`B+BBHBKBBBM\N@```@@@@@@@@@@@@(0****5eP********OeBACB҈t-lB{B\B.Ll4yAހ,d$0BB,!­d]BCBX?'BBVظBgBk4<ƒPBkB<}P%BBBj][BOxBB|Ba‹θ«,B<–<dB*Bw B@BA`dTBBXBBbxƒB9BGBQ@l Š=BQ<BTBYv›XdƒǠ¯>`BaCCC'C(C(81AV]VŠpLAjC C)C5C9C2?CBɐB h,|\¯BۀB$BքBhBBBBB|BiTB_BmBiBXBVdBXBD,BIB]4BqBn,BgBdB|BBtByBcLBGB6 @P%%0PZ($‚†‡Šz…—މdy‹X¦¬¯P¶¶ ¹4²Pµ¸’h>B$BKBuBTBlBBBBPBHB|BmBT BSBbB_B[,B^ BB~B{BBBBB\B,BB{Bd4BE|B*B<_tqz{|zH[QSPCIdO\n}s0fdsh|b4]Y=2'235'h <3@$A~B@B2TBFB@B'B8BPN@```@@@@@@@@@@@@(0   ****9 e********Seu@tBB+Aр@ANA@B(BT@XhAAZA~=3&< A@AU@|-*B(BA+tlA:BtB/B$8ABLB&(B;BCB/B%DBATAmAL><HD6(\"xAB<8B`LBNB"`B!B,lBB'B%XAs@)cŸ{BB0CZC#cC$NCBpA·w-t0>sC4BCC*C2C3C-C%:CCBx³&u)$'3$$B,CCAC C#C%C#TCWCBB¬0H' h l•B7HBCoCuCWCCCVCCB`B[>¼x?!"!½LE@BCCnCuC!C vCCBBC8¢xi4­Q@BhBC&CCCVCBPBnh±0‡hM0@B$BbHBBB@BBtBDBztBHBAJ&=T`Y|W[\k]T= B*BaBBBBdBydBSPB;Šªĸt£8eO4BB^Bp|B[B@BM`BpBBB}BBZlBd'd@C$]as,ml`X1AB;B@BAdBd0BgBwB~BLBVA@,@t‚†HŒ£’b,AAA@B+DBS<BoBBBBBkBUHB)DAp?0VS.Ag@!$T" ,DGMcXi\-BfBB7B-CCB h7B^B4B,?³B`C*Bx,§{4B8,BC!BTBC |B<BCkCEBB0H—,”q]I\5 *2x.|4<(7+(!A@BTB,AB&B9PBCB:B'tB1xB*Ai@#Vr‡0œ–Š b$X<F= @:/"L2XO PD7@B+PBTBtDBlBxBBHB̐BLBBsHBRBC@B1BAnAE@H19+Dd%05M ET"h3&pDBB#B\B BBBTBI|BYBAB$4A=A;A@B$BKB8B&pAA3Az@A-H4D8|1/|&A@BEBkBwBXpBEB"B84h‰µx04¬(l,dA@B>TBgBBBB\BĠBB}B>B-B`8V]$Z\=< )R8\S\As–ppˆuPY\pB-B\B]B~BB8B`BBz B]|B"tAAEAyA\ 1@.`(X3LXE@/1P8mQT'A@B%B#BBBLB4B8tB64B(BA]@AA@BB#B.4B"BBB)B?BEBHB5XB)hB4BNtBeBO@B)$Bh$@A@\j@jdv¤¿¬|Š8g`VtD\B|IP7H"J(A8wBB.\B3tB8B/B#B2pB?XBD$B5B B,AAA@B!8B'$A@v@B<B)B:B9B(tBAj@BB'B,BAmAB!B>B:BBBNdBWBK,BXhB`dBvLBVB;BB(B0B1AJ`(H;U k‘‡D\„Š‚p f@VXH0 \ABABBHAD0AB#xA|@$'@BtBBPB*B&BBB,BJtB`XBZB@B2BH BfBj`BjBB`Bh4BQhBiBg8BBQBD@ Y@6(ESTU@\AB,B)ÀAB&4BL0B6';S\PMg(xp‚,†˜¯„ord^ti<‰kh<;pc`tY D958@A@B#B:BNBOBABCBPBqBXB$BhBBBBBΈBBB B|BdBdBXBBTB˼BBBBhBBBHAZ@AB"BUBqBc<Bb8B8BB BzBgB[pB7B<BLB$<B,AU@B)B@BIAh%/,ˆ¼|F1xkqªxU+LBB-tBABWBHBBDBBBрCCFC9CCCCC CCC9CNC-CCCBBxB&@&|ªŸ~X™xip“¨·D*5% ,;xv‹iAB B"d"Ljk0BB_<BȘB@BCCCC C CC!C&tC$C#DC!C CC^C'CBBBBdB#}Հ 4ax`y‹h¨(7\Z „² }(C;XX3@AfBAB,BLBxBBB4B BTBCCBPBCoCCBBB<BB֤BèBhB0BLBTBLBB~lBM4BaA2Dosu“¾,`אtqp0x»½D¤l|59H;TBABhB?<BShB9B;BBBbB}BB_lBBPBBB@BB4BpB~BzB^Bv`BMB-AL!JTOPN`M\reL*|*@BBBBBB\$A-LS`IDIBx<9:A]B;DBRBD BGBc BhDBTBAB1BQl``X_b4kX€,h\S@Dl+B48BDB<BJpBsB8BfBIB(BBA!t5HHWHxM%@DmA(@B4HBnBzBjBvBBBVLB'\BB7Sdkƒ––0‚oPqR&AcB"BB0BGB4tBB90B>8B)(vdA.AtA<<ABB%DB4BIBUHB8,BPBY4B0\B#B.$B)4@dT4 8j?`B"B2,BB=$B^A*30^'0S:Aƀ 03 B'tBAAOh%DI<33P db@,!AB!B7BE\BPBKHB?BLBbBBTB1BB B`BBTBB'xB$ BB!BEpBFBSBBtB=lB"BAR@@=d‹{ fj™ˆdLF|7&8BB)|B;BR8BTBVLBZBLB!P/L@So¿LN@```@@@@@@@@@@@@(0****>e********XeJB\@ByB BBr$BBoB8BBc8BHLB?>,J¬P–|E`LR<BpA/Ay@B BBB>B!\xTP!xMwTD|@8B BSB\BBB`B$B~BiHB[s@4†@<#",¦,CC;CTC[8CPC;4C$BX…PS%/9cKxcLslspb8<<GC5C`dCxpCCCs\Cd8CT$C@C,fC¢*Jg|Ä0z(gOp1BmC%C?CRCb<Co,CpCe(CQC5Cl(ALS[dZ RF7"±BȤC!vC9?CBCMCNCFC<C-C(B@G' 28;8.&!QBhCYC"!C&C'C(4C&C CCB/$ "8"-cJŸd]BBHCCCCCC&B@Bb\%p’‚w4†¨lolOJcABsBޤCCjB BBBB״BB$BauLµ,OpBzBdBA@o)BC~CCZCB|BhBB0Q A1BBB—L€tu@BрCiBLBjCxCBXwP3 U/*Q †BCC-C;2CBTCB$C9kC-MC' C!]C'B$BcB5"§| |̈£$n):$ƒ8§<vpBOBB~B|DB[B4A@%N^?(lBBYB4BBlCCC*CCC:CB4BDBVXB*`}¾:%4K«m7BBZ,B_BW8BRBJ|BHDBXBeBlBB`BBBBvBOlB2PATP#t#'B|B94BBBBBvB*Ai8R PN›@+BBqTBC6CCCC$C%^C#=C!C!CCC CCaBB>xA+j¡ŒH˜³lB !!"& G 4rpl¨7A@B]hB BCCC+C/C.C(C CZB BWAB6B2Žc.*iPBCWCC Ct‡B,CCbBg0¥V0C>C<CUCOhC5PCCXCCBt EbfYJ>4-$UBLC0C$C&C"ACXCBh+@µBCC%C2C7C8C1C%CBo§]-:4@ @=\:7|/'#s/BGCECC)C8DCECQCZlC]CY@CPCE,C7C%CQ ,3~763/*#ml"()++&(DBQCC7KCP$Ce@Ct0ClCCCv$CcCJC+BX8VTpTÂÌDÎ`È|lPW @x({@BhC!C3CCCOCTCRCMCC8C6C%CBB%Jt˜Y 4"'+b.0x3"43.222.%0<BCC&C3C8CAdCGCKLCLCQCVDCWCXCZ|C]XC\CXCRCOxCJPCA,C5.C(QCtBst!X4H[lxxÁÆÉÇÄÀtyqdeY,M?/ ­tBhCC* C9 CFdCPxCZ,CaCcCaCZhCSCNCEC9C1C-C'C!CCCCrCBBB70–P#N-'4:?CCAL<5X,." ҄MLB@LBpCCC C#C'C*C(C(C+wC,C)C$C#C"PCCBB0Ba؈&,%.d/ .-,l* &" s ~0*|A@B6BQ BiB{BBB0CCCC"C'C)C+C.rC0C0UC/ C.C,C)C%C!CCKCvBBWD_I-o $(,[,-#-/.|,2(%$#hv!B+BlBDCCCCC!C!CC! C%C&jC!CCCCUCCCTB@BBPByBYB2mF_›8C6¾LžƒxY \ABBB.BFB]BAB,lB4B9B,B/PB@BDB@BMBtBBBBLjBBdBB\BdB|B]B&hB-BM0B2.p (EDNH8Xtp…pp†dŸH›x‰$¢pŸqXDXF/8ASB+B9B4B*BHBX B?B+8Bt@=<Dctz–‘yh}]PBA#BJB@ByB`BHBBBBBBB@BB^Bd B]BQPB?BCBntB]B;B+,B:BFBF|B:PBAv@,8^jˆ¨¬X“l„Lt||{XnXjzhp|{<‘ €lbl;t/$AR@B"BAB5BF<B2`B BKBhBEB:$BLdBkBJBBB3pBI|B50AA6ABB&B0B8XBX@A6h$B%BNBo,Bf,BwBHBB_BP0B:B< B#T@D,8FEMDYKh+&H,5HMM_it^GhTcb=&GPI10.FTdIL9|(,-. BB!LB+XBABV BQ(B\B[BcpBBtBWBC`B\(BftB\BS(BpBblBHB?BD`BOBUBOB.,BpB" B7B1B A%@@qAr@$*X/X,lxed^dh PHP\8hp$fDERTcffloVTK5,L4,hBB?BGBlBBBkhB<BBBT4B\BB7B'AZLBPBDx@XB:HBiBW@B&XB8B.B@B/hB$|AB"B&x\@A@IQ(8C$F)@AB$BA@BE,BuBhB:LAABB6\›@dWd¶°n,sƴ¢=8J@B|xBڴBBB״C%BLBTBPBnBH@6+$|<nk>($H'&l@BB*lAqBB`BB@lx;HA`@A9@2B lB AtAb@B*@B/B6tB<B,B:B>B=B=(B$DA@-lBAG ]u†4‹~uO@AAZB($BU(BrBvTBf@BBN@```@@@@@@@@@@@@(0****Ce********]eAA߀BB|BAAA@h(@ABA.teAǀxA!@A6BA@>xAAEA'A@A&<Y`0ALC0CDlCCCChCpC/4K$ó 0Á +CC0 C ]UÄ(ÉZDBRC{CpDDD7C`CHx#?uèøòÝÃkTWD/BBUBTAB9BeBa8BNBRBRB#80B)$B7 4™żX½4iUdƒ[$B=`BB Q$)BRhBBBzD6V(YoBBLBmdj{B;B(tx%((?KAB0BPB"¿ht(B_BBGUˆ$BpBԤBBhY1@B.BA@BBDxp߰!BBE©†B$BB,B0QŸhpBBSB"$SŠ4kLBB!A5@)H>@A)BqBBBTh/Bb(BlBHBGh3AB&B,A;]¶¶ ZL{&tE{wA@BBHB-.\fDNABtLBi,g$U41AB3`BDAOdN$BB$`BA7$ghŒ\BB´8PB!@BB@¸|ž(,BȤCFCN@```@@@@@@@@@@@@(0****Ge ********ae<,2!LTBB!BB@BXBB8BLB/PB#BB:BGXB,lABB$5@"0V$5@v`6DD'~D9 D>D5DQB,r1+q C2-|ð#%_DD0ODBDG@D@D/mD CÞR$x%!ÐCnCDUDDpDC@CmC)*CC!C4EC,!CCGCICChDDDjDD6D"D$DCpo z9lMZ^YdI\/CD%D5D;D8D/D%DDD!D)D3D:D;D5D)DBp1GxW@_^WJx;+T׌F@C0D<DD!wD#D#DDDCCrCJCR|CCDdD[D)DbDDCdCP%Ãþ8 æ]Bu CqCLD`DyDDCŸCk4BMØx) #&r(T('[#{7ñ1CxDDD$D)D,xD,D+gD(QD#D!DDmCCImø0N,(ñ<jsC(CcCClC~XCWC+~,jo'g C+fCHD5DD"5D%!D%FD"DsDXDCCWXúl>Uj$rL!C(Ch8CHCCCCCCYC,BL]A\\Lmv{|8wnaQ>0&C<C-CJChCCdCCdCCCDCbC;aB@FXi\Â<ÑÔlÊv\,<aB@dC#mC=CLCTCWdCQCCC02C-B2FQTXPG:'+PB4CRCC!C4CTBBuB&h9~{S@BtCCCwC qCMCMCCB`BPAvL8™»<Հ(–HhB*CC%C C%hC'C%CCKB`B­qg"d G!Z$l$?d‰hBzBCC C+CCC\CHB8BzB1x*$t1V{‘X„Ÿ¼L·8²L\BA^B-BOB{(BsB<B̜BBdB̤BCCCCCCCcCBPBp,0’Ҭٜ±X£T‘{sIt5R`4t½@^ %>)w+ (#b?\BplCC]C(C-OC-OC+C&ACWCBB|B)`Qqxp0G2 \AGB.|B\TB BB8BB|BB=0ŽPo'B?MµlA/BmBB0CCeCFCCVCBBB'D8rŽ–‚wDj0BB5BAӀ\Wsx†t¯T±¬4§<WTABPB{B BˆB B<BBdBBBBu4B`4BiBzBDBA6X5FtUmzxs4n8fXJRD3D@+@.I .8D9BNBidBBB BӸBB B4BBqB"t@,DD<FhGWp_bHblPu aHpXY<, 2(>+B#DB@BUBvBBpB|HBxBBhBnBeBITBMB8B3`B(PBA_?;AhpaVbdJYP Lo”L‡“°L©•šRB BPByBBBBBB BBeB!BA@@AkB!B?B.8B$B3<B#%X8FXGdAE@BTBA`BL|BCBaxBnBNBR8ByBbBcBDB:A@l31!L6V[@YDKTLiiVb0\>(1(7'XAe@B"(B)B$8B,dB<BT#+HlhD@xA%AHN%&x~5<Ȍ}4!BBOBXDBqBB|BC:CMBB@BBXBTBC;CCHCCC'CB0BPB`iP°x+<X!zL8®‡IFTsu[08BB\B}<BBBۨC4CCBBxBBvlBdB^Bv8B+.S:8\_jpclJ=\N‡š‚$DB B2(B4$B=B[B,BlB`BBB BpCPCB@B<BuBYBAEAM@:L‘D£®@´8ŸuSEd<šL´¬DŸšd¥°$$¦\'ABtB$,BABBB0BBBlBsBwBzB Bm`B/X4BBRB^BaB^4BL<BUBuBBy$BjlB-AzA܀BH$BfAA@\@B)LB(%HWQ:8IS@„š {ZbPolž¾ ©x}Pc|CC/5B&BFB\HBDB4B(BjBpBHBBLB@B>BPBfBxLBEA6 x hB B3hB tAB+@BIlB|Bx\BX@B8P@B((9KtMJ+6@@7xG )<,#lBBVBqBbTB5BA>@BlA@(AA&5B\B?XB < <Suvw‡v|Tu/BB$%AJ@B,B0B8B7BSTBJBGB@B!B8B:B\B]XBQ`B;B@Bn4BBBBhB BeB\BKA@2xž|º”xl(PhIsPxK0$D:n]`BB+tBl+XI<.(6`r0N-BGBX,B:ABtB2BHB4B@[XB5TB:B7XB.\AȀBWBdBIB%BXAj@A@B>BoB>Y;B.B)lB7h\M\B!xB<B*`,<N\ՀB# Bp'h~s\8B.B/BBQBh4BaBDD@=$B.TB;B>B/LAlAoBXBXB|MX]N3t`X|{wlB)B2B<@8$@BB1(B:€`:B'BLB;lB$%&A@B@BOBIxB(AB@hBBgpBg B8\6@B=B,@`8PD"BBRBaBJA02BB6B,),ek*BB+<Bt_;DABA3Œ€W,B8H=R1HBBIhB0`8@GK2|BBOBlB@BpBBkXB`BRhB >|\ -xB`B(!BN@```@@@@@@@@@@@@(0****Le********keBBD8B<8BDB\B\A@AGBUBkB?A[B#BFBPBGBC<B.L@AZ@8/^H|`vZ@X3<M«j:fËÓk¬8ChDD-DDDC,C#TØ A åJC.oC(DhDD&HD(D'+D D*CD@F.Ø *CdCD'DDD -D$DC CIVD vyvC#ChCLCDDDD/C CLC΄CCC4CCCChCmhCDC.Br_ #"f2UHCDD6DD9DSDC4Cb,_ç0Ր$٨ó`À>BxCLCC|C|CdCClCkCKC,WCB](0?(&%_a@C!xCb+FV]_0]TLB&L8CCAC_<CrCwxCnCVC16Bp9@wódÑxNlACZ<CDDDDDD%D0DDCCS¸c ï\SHmܼèk4cBPCOC B<iÑ`ñ$|̐åt9(BZCB8C|DCC CD9CCCΨCCCthCYCFC;C<CEXCQC\LCeCiCgLC^hCQC@C(~Bl/GD,SH]bba[HS(MJK<O[g(pxÀÅpËlÐ@ÎÆ{hkU < B7dC*CN ClCCCCCC|CC{CetCOC<8C.C#CCNCmCC$C/C7CCECHCD,C:,C*CBxP}.:lAB=4&("N CC'C9OCFCQCHC._C,C8HC.wCBBJ} XYLB}lBB{B`CfCBw+r?N`n|jXS?81BPCBBLBdB4BBBBDB C0CBC+C3NC:C@<CGCTCdlClCeCOLC1B(8QbgbN/B4C$KC7CAxCAC7C"GB2#LDs ÑäëâHÉ8bL2C3+Cc@CdCCLCCC(CCePCAtC7!<S4a\hDkhp^M:[#BC C36C@CICPCRCNhCHCAC7C,kC CBgt’*:K Zh pPs(qdhYtD+BC(C@CT<C_CcC^CQXC=C%B(¢P(,,%>CC*8CACSC]XC`,CZCK|C3>Cp3RWyÓäìTédÛ|Ãd$?BC5CWCsCC$CC(CdC~ClCVC@C+CCtBtJ #=ub(r(/.f:FOV\^ZT\Jl?\0 BBCC%C,C1,C4sC4C2C0C-C+TC)#C'C&bC%C%C%C$C#C!rCCLCC/BB@,šVZbSET̜‘(u4x0~‘H 15 wBhC CjCC$C&C'C%C C)C*B@BmƀuBOp»ts^J\@0D8KC9D9p2TBBXhBBBCCCCC>CoCCCC)CBBBKB|%H|jP°0@7Otr*a[@±`rSB*BDXBZBzBBxB@B@BьBB(CrCCCNCCCCAC8CDC(CBBHBBsBEB$X2@t:MgDzTƒtzŸº¬LhٸȐ­ ›ƒ<x<|<…Š\€$‹œT¨ª4b<NL>t\@HB|B3B\Bo0BpBntB]BTBYxB[B[BZlBe8Bf$BwBBŔBܜB BBB٬BxB8B\BBnB@B<dT6c,mC`++P5@A@AB|B'B/B%AHA(h&d?\bsnNEFOTLL18#`(D4t9$.@4HioV1$A@AA_AۀB1BWBNBX<BDB8B8BL4BAB, BwpAqA@@=LB *,7xAXBB,BCB1B3BD@Bz BhtBWBSPBZB7tB5<B6BGB9B|AeA%t0h(x,I@A).H@L|"AZ_Vfh™ ¿X¢|ˆTd ?3<Aa@BB4BiDBB`B`BhB]PBq`B}|BoBMB'B0>,;0+(($4A@B8BGBB6DB2B"AAMBBA@@BB hBPA@@v$7$`@&66<@8AtAz~ AABA@A@BTB*B5B?B'8AB,BG$BBB,\At@AABBBA@A@BB:BXBQPB98BD)2Me[= @Pp,' @AoAӀBB%d=2l(E N@,<BAi8B,B\hB?\B#B(AAB(tB+BAD$p$ 8H> LB@B.,N@```@@@@@@@@@@@@(0! !****Q!ex********peA7&n>@!K@AA@ABB$B#\B(B%B,8B)B&LB B#B!pBBB@*%'t70?@\A:1/\B$BABlB!BlBB(B(P@!\BLBRB^,B69PBB"@ Cpp^TB B"Y384x"AB1i(†M ЀB|Ag,*BBD,BeBiB]B;B>Bx BBBcA</ # 9L;ACB6B)`QO0;C0dœ­³‡X+BB>BAB$B!BGLB}8BvBlB0/B%B(Mr`5xBB$@B3B^BsLBhB;ABB>BV0N@```@@@@@@@@@@@@(0% %****U%e********teAЀ7 BB.BtBB`BtA@LA‚T¢H,TBp4BB:t2p@B7BXB@JAAuAB B|A <@Ai@ӀAeBXBA@B.BAҀB'B8AFԀAAA@A5@<BPA@BlB4B*A/TA6ABBAKB|AAT@]@݀%$A@Ai`-TBB BBHA3\@4A@ATCXB#PB3B&AABB'<BB&B*PA]82,)AB\(&LAAoBBP^BB1|BL0\AA@A@cJ AnAiB-B*/_@AA@A@A~@-/<',LA@ A(%  B B!p(ABxBʀ@G@BA@AmBlA ]AE@AAAeB% B mB\B6BB@\XG-A@B(B,AP@AB$#AA@6A-AHBB!A/A@B+$hgBB$ArB!,0L$\A*BBABBBDB"A@t 8LAABB'TA^@(?;B<B#lABB(4B2<B@AB,A;B! AAB|B,AAAAqB\BLBDHBFB" 1tA"@A@AA}7A>8 E19@5 @(YAr@A:A@AB4B#8A@A$Br@BpBB|'@lB hB8AӀB0B!BB AB B@B4B%hBA@AXB<B$dBAy@.( BB/B*BA42;l/NGAEB*B+E4H3t-%`L@$$ 6T@A5A@#BxB3\B&BBDY@BA@@kA'BB3BAA@BA"$A}B B&0BBA2xH@€lhBªX%„"B'lBYBy,BpBLB~BCYBBiBcBeBHBPCDC'CBTBBݬCB(B_x<¤|.oR¤p& ,AB6\BBB,BmAOLI4AA7jtƨ³LB#BDB9(B4B:BFB CCBBeB7B1@BNBelBQAπ$]IB BXAp@OXcHB5BcBJB+p@3tB4B2<- ›d(@%y },ABBTB0AzB*xBj<BpBpBtBBBdBfBC%BhBC4L@B*BwBiBIB&AF@B<BBB^@+@TF¶`\‘%(Mk>@B.BWBHB7LB8B<(BkB//fxeFx@AY44B(BBBS*l#`&J–H?dDdABwBBB`BTB}B;BEBlBx`Ac¶tŽ]PEH'`(h€DByBpBHABxB5pBeBBPBo B1@B;B0Bm(B!PB*PBvBBBB_B6BG@Bm4Bf0”D@hs5$¯$ax``ip=AhB\|B4B܄BBBWB[B4BB B9-|BB6BBB)4BBuhBB@04v4¤ƒ\T*.XŒBxhBxBmBGBvBBCCC BBBXBCBBR@B@#!A]Yµ@ߌ±L]b£|R|´LPHƒlA@A/>4BDBghBLBPBBDXAfB'B<BBBtAFB2BkdBBBgB0B+BnBBBxBA@AyBB7BFB9B%,|§`_t"RŸp±“i|B XB=`B)@+AlBa8BxB8;|MC`@!4;(nX#BYB`B'AA@AB*BEBD,Ax;$|vA:@6r†X,B*BWBBBkBEBvHBBհBoB4"/&)4<Q„$bxB/B/A+@@BTB-@BNBJB9`B$PB-lBICipcM A:xTOuhy;BhBG$VEH0&l->cDHA~B]BN<BBB>BpBzBBnBKB'AlB \BBvBABBBB;BzB BKB6LB)BB2B\BILA$7HP9<J(i„8•xD¸€s<|¨L†DqP@!AB B@BBd|B^B(8/[BB/B18B2lB2B*xB34B!BFBeBK$B!B&(B,B-<B?BMB/B BAAbBB)@,RBtB'$B+lN@```@@@@@@@@@@@@(0******Z*e********ye(AC@B h@T] 4P€HBB5([dBQBLxA3BB3HP|,A@Mh˜ŒM@786H-UABk<BhB)H1T@BEhBT0BABB)A BA,Žv"<A&-d;A@;,%id•A@B'AA@BC(BXBQB1h@!PvL·ŽfI"DB[BpC^CC#C&C"C"\ 0%*.=3l2-6(% BB`C C-C<CBCAC=C6 C'C<")-6:N;$30d#BBCRC%C2C7C0 C&CCBŠ#:)o146,!µ$BWCCCqC {CaCCBBlBS``µ­X,›M5"B_|BB԰BwHB^Bu`BhB`BAY@BZ(B2BSDœp¹n?=pK@B@TB\B7BE BpBeAB=BBBBd@BH|B)`Y2Ao`P(2ƒdݘp¾d8®(pB*0+B*BuBBBa,BjB~B-"@B0e`•NBBB!@GBmB|B8,D&At+WFB&`BxB@BL$BOBuBU!UL8@8cdv4PBW00BlBoB`B'BA|BBBLBBMB6$B$E`h'l,lX¾¢T?Xp‚l@B/BhBBlB¨vP&? [#TB3dB DB44@zpwDgBZBpdBGB;\BZBxBYdB:Br4BsxB%L7<5x-x)T8{| i<BH`BgB=|dIBCBxpӜBCBܤB!@X†BC$BC%aCxBDsB(CCmBB{ hBQBPCCwCoCcC C!C CfBPB6KV\ˆ*K)BP›|BCsC C%C#CSCC&IC1DC5C.RC$rCC\BBb|%5?WaWE,C=A-(yGa(jkf|VA<,O_ BC ^C4AC@,C@C:pC5C2C*C CBTS'%'!¹@BCDCC uC4CCCCBBmBXPBSB+TBB&<A/]<BxBbABB~pBBڤCC CB4B`CCrCBBcB$$#$AN¢@QǤBBBW4BBfLB)B BBҨB`BOBFBe,ByBxBQdk֤0»tddt4AB4CNBB+B,xBB`BBBqH†n(„Ÿ|¤,̼xBBRBVBB4B(CCCB`BBUB?hBEA_fW`Œº‘fqP VxB(8B4B4B}B8BlBBBBLBO4B*PBLTBBVDDx ۬­®,L‹D"B:BW\B0B/B D0 <BLBQA@{tXkS–t±^9PB Bx(BBBgBaBBCGBB`BѨBDBOAzB’8;ĸ~A4A@BC#B B4BB(CkCvBBmB<BBZC1˜‹BEBB|".L'V4B\lBwAv»ŒBBcBA@BUBdAK@S`DA@B[BBBBD\½8BhCOCSBPH{³ ˆ@(Y|;}BBxB+`BBP)$BDBBm`BHB[B|CCCoC!_CCCRC nC CCCtBBxB6|Ž”i ̠?vsoGa.QF80ll§d]X`~\A1B+$B B`BDCCjCbCCC_CBBLB,BBUB]Bcu8³P®³,EµĠP¦80XwxA{/hi7BpB#BPBBlBiB;B=BJBLl_\uq.ABA?"09 @B> BCB7B{BLBBLB]BBxB0F(B+BBlBBlBgB+BQB,BTBDBptBB_pB\BBB:P‚4“,ž ¡•t(0€xmD¢u!\i®BBNtI®LUBSpBCY–PB&z,§B(PB|B|x@BBB-AրBi|Bt<AA,BBR?`BB,ABHB-A7/h0B B@$BOBg,Bx<B^B>BuB`CBdBBӌB<BtBBBhBu AIy4jE-p[k_B2 .B]@i`#TB:BgBCA@Eˆ@«³tžl¬6‘¦}<„BBBVB<BCB BpBCBBLBBBBaXB=B:HB2\BpBB\BqAc@4<M4 $3 ²Xš“h|X¡X1B/ B7lAhABMBDBA@\ACEhY@eB=<@lD@BdBØB^HPB=BB(db/BL@h(PBt@(aTBDxBB-BBBPEABdB(BJBFB`Bi\)2LB*B646Y,BBlB?$BKB8LCAB (3XQHne]|†ªžž—<l8I6A@B^XB89,xB0LB<4AFA@B!B'B9BDhB6B-B$0@B0BL(BIBLLBeBdAA@B@$B^tB"<^ˆ(@dB@‰`o8B"`B)TŠlɐBb,6T¶<@BlB (B-dBB4A@Aj@ASB"BtBTBxBKBBPB BBHBbBAB"\BYPBBZdBZdDTABf(B;@B[DBBABBB/;B<–~lPĤ¬0o@¶œv"B.B5@B4B1 B,A!B:4B9BHBBb4BBN@```@@@@@@@@@@@@(0//****_/e********~eA]B*BBXB-B&B1BDBDlBtBDYN%hAX,[CCxCbCNC:C¦/1E8U4i|LÃ{DhUEl1PCEC:CLHC]CrLC CCyXCeHCOC;C!W\X,FV8hzÂ|\l4VC0CC8QCKC_\CuCCC{ CfCPC>8C"Tp-)E<Uh(ydÁd|`mhYG2gCC3CFC[CrpCCCxCgdCRC?C&?-FWhyhÂ}n(Y(F2%CC4CIC]CrhC8CC{0ChCQ<C=\C$B %B(SeDwHÁ}oh\I4bCC1CE8CXCnCCC{dChCTCBC*)BJ$&@QeTx Á|<m,ZI7sBC/CCCUCn@C@CCLCkLCTC@TC'B5t%j@RewÀ~q]|J7BC1GCFdCW|Cn$CC0C~Cl\CXCE|C,B\!? T4gyÄ4ÁTtbDNx;#>BC/CDCVCnCC$C~Ck|CVCBC*B{(<PbtÀ ÀLuaL :!BtC-CFCWCjC}ClCDCoCYxCEC/,B;N `xtÀ(vldpOABXB8AH@@B*XB1B BL;=8!|+|=H[h3XALAxA_@$XB"B@B*(B LBBtB6(BVB@B+,A@<&BBB@$t%@B2B6B0A;&:PBB&A*WtOB8A.@A@#lBB<BC4B5|B&BB0B?B?B%Q¦ܨ$AKBCCC!CCBc¤ !p‰; l^¬HB\CeC$nC+C)/C C{BpD/–½8•²\;\[BBBCC_C>CCCB|Bc|[U|›TۈphB8|BqBϴCjC,CCBdB2,o‡$©h¿4ºl‚d1B'BS(BfB\Bw$BBBB(BHBwB8t8 g¦8P»Ž`O:>L`iI4B0BWBuBqB]BHBPB[B@B@B:\B5BY<Bi8Bg`BV,A:mtn,W)D0%\B 88:4?|&xA@B5B4B00BX/IMIR0N<F6(B3Bh0BmB|BfB>B2@BB. B'(BAtAXABB#0B!Հ/pD=*"#<12<+AuAaLAQAYA@BB\BBhB8Bi8BtBJBTW@xL+! ^AATBB:xBdpBUtB,0BA/BBAln$lNŒ4´p©vY4AB2BBTB`HBtdBBpBBDBBXBaBlE UuX@ŠiWHx€B&,B8PB8$B$B\B,N=7OPVGpXABPB\B,B6BQBLLB@BA/$h-9=0$LA0BB;4B[Bn\BPB?BMB\B>PB0%`-`!4ـmBB>BaBUB`BXDBUB1LB@)=B!`AA;)d &>,xB,BB}B-HSA@AHB0Bt@BBZ<70lA{BcBKB4V4zsH°j,@B(A #B(PBcBoBEB'A|d@%ABBBtA{@$BBL BKBBB?B-DB.AЀAdABHB'B9B;BRBDB=HB%BA}(<<B*to@A@B)B)XB%B8|BDhB1B$BL@i@,0- 1<:<@L ,l-BBA@B`B%B&xBJpBBB(B-B-tBB*dx(6G>0FT.' TAB B0BdBA@@@8PNTDK@93|pd<AB B B!B&`B$B&`B.B4B>B,B$A3UՀAA*,0BBBB,B.B)LB'BFBQXB4B BASATրBB&DBB/B,DB"B!hB&B58B0B0B4B.B\ABUր+9XCG;:A>ES,LYl<("7\9xR =L*Hd(32)4BA$B<BdBB<B3lBXBcxBSBIBEXBO@BIBOB:pB"Am@B"BB%B+B!Bf@B\B<@"X>{@A?A7@\BBAA@AA@AB?(BwlBPB4B''t.Hd^npp ko8j`$\X)4BB8BhB\Bg\BO|BGB$A@@ ^4X<ULY`0]I#lhAa@B(PB:,B>B5B*BCB$A4F1hABEBABX@B<BBBLBqBBkB3B BB4@ HD,Sr`ZQJ8TB0AA6@BBa BelB2B>BQB/B(z$tD2Nf;H`'P&@o0BB|AB2,BdB8B<AZv@7I™PlyhH!@AB)BLABB%TB$B4MHb`JH>$R@,(@A9B+@BPBK|BMBpBpBnBiBBBcB A>@A@X5BB0BB*B,BCxB8BOB}pBTHB6B(\AG8!SLTsD||0rqg.PR(BB=BmBpBy0BBd(BQB<(B,B=B'[@A4=L4DT6 ABA@BHAA@BA@!8)2PpJD @0/%B<}@ABhYAAB#B"B!HB&XBBB,AB*dBBB,AB,B$ACA@B$B(ABBB&@B(TBF BuxBOB-B"lAAA#@P%F?5@@@AB)PAdB`BGi )LT9`36X-%A%@B,[B4BHBB BB(A@@Ҁ1) Ri<|–T†‡‹yi^D(xBtB4B[B{tBHBBBBBBBtBBqBNHB8BhAB|B+B1$A@@A@7T7x`Xf[0H(A@B?BPBWBHBZ(B[Bl|BSBF B$tlL$YJt55 "h$"|818/@7:l-!c@AB+LB4TB2B2BBBA"@@A@AVA@B4BBLB$B+hB.BBBSBB0BJ BETBGB.B6B)HBB"5\B>78AL60A؀B|B*8BDB6hB0 ;`_S<BdlB\C`CCC%CBA‘x<u“B'hBCC C$bC%C$CCB AW¯~ nP%Bm$BCCCCbC CC)BLB;rK"#!%kB<B(CCCqC bC")C C&CBB5y >"!Z aBQBCCCCCCMCzB({@k;9شoPABCgCCCKCeC5CBBXAy.Ug0t»¯p—zR[BKBy|B$B\BBB~BJ`BLBHn•½&‹VB>B|BBCCBBxBx0B0o4µX`,´hƒtO!BBUB|PBBLBBBBkB>r¥͌0$«v 6@BM B8BHB`BB BޘBXByB>AG7Ux}z‡Pws(e AlABB7BXBvBPBpB<BxBBdhB) AAAS@.? H(KD[XB,iA4@B'BCB`B$B}BBBB`BB9 D(X€–*NxE@!BdBE\>p@hB&BBBBFp\\o\@B4TB!s,™,“BBBaBhX3`ŠD%B@B0B@BB8i¹kpA3x CBCC.C;C7C$C}B)h‹\ #U*!"›,·<(G7n40CVC0CA|CAC:C6C3C+Ce}@9b&-48.1'Y :CC)C/GC+7C(6C(CC)C'C{B>(U'1Q/("5BBCCCC#C*C*C&CB4-єi &}'$$|LB1B0 B(BXCOC(C(C`C]BBBBBAX(bKxވtBbpCmCCCBA@A@B=BFBp(J»0]u,hˌtB3CCZCCB|BBB|CCBX"—(º“LTad|<hDB?BPB8BJAjB3BBB n¿¦^dABKDB?(¥¿Z@@–;@BπCBBBgBCCC&C#C0<µB:BD #1!f(@šhw4/@W\xB1hB4BѤ0XBP\BB+O2{,<^BьC C=´TvBCBP+BִC4'C9C"BB;B$B$B*hBtBpBA<€8r›B/PBx BiBaBBBhBȔBBQBcBBB@ £H"-sQabBB-@1ABC-CvCCCCDC,C)C.0C%CBApB8BB-"/3-#O"$BC&BĐBBCC'C*C#CBBhiMH¹kl‚F_0ưœB@CCBBxB* BBtCB`BYamhBBrlHs·Q @A@+<A+BQ@B<B߀BB! AdBC<BPCUCCCvB(BBCqC!BBU4?uY1Y""bp[7\lրX ЌBdBdBBTB\|@BBCC"CCLBBCDCCsCB@FBbBB 6”@jœ$t•BhB`B&@ ;0BABCCbBBBʐCCCDC*BBVPB%\BBBA,`@@¸b8|c)ªpª,?xBVB1J0‘X¥d• EB,B9* h*BB'BÀ7A@BCCEBĤBDTB$xB CdCCbBBBBDB(BBϐBpBY5\h@Bu|BBIG\ŽLxAJB" B,`B,AAc@B7BXB?BX6!TBB<BLg,«…¹AR,­$p]n²€¼(=˜{‚KH*AˀABBq B,BCxCCCC BCqCC"CNC;C.CqCCCiBQMB!BPlBQB3B&Bl(n†}|—hu>;׬lJ>mL=h²&2B$X3`¶±<B^B* BYPBBOH@LBB BBlB&`BIBCCBB\BB̌C2CZCCB4B"B%B(A@B#B),)‰d;B#LBFB':yn8HB(D€\X¾d€`1,™ (pkl3Epv‰ŠKB(0B|BLT8=B=pBPBzBQ4BD(B4B B\BC^CiBB=\AzBrxCCBDB896(B-B@BBC|†p®A߀BzB:N§z4-,BBsBB8Dªµ’x}L™tº`BBrB7@@tBGBdBBh8A4B#BVt®0QBFB^@^p4DBCBB#2B44BhBͼB4BkdBN¢·_H@@PYtB{DBB BXr@$B8BnBjB;*@1H` O#B=LB?AN uTA#BGBoHBul‹¡ BPBBkxŠ|«HB6BF| ¡o`UBe BrTB%h/_J\B Bi\BRXB (%tBBA@dL„\qM@BHDB,$iy0tFXB0B@AyJPZhAB{BHB!7 W;AB:(BEAEX€ U0BDBBBAɀQ8BQBoTB[B"J…P@BFBBD|M™‘!8BsPBلB̠BI Yvh BqxB BH!qH_:@B_BBZ@d{BhPBBe=¯¬EB"N@```@@@@@@@@@@@@(0   ****m[A@B.B4$B0x(3@+1<H=lDdv‹@nO<YcSDNx@l#|[AWA@A@B#BT<BuBlBwBv,Bu,BZBCSCXCM,C6hCjB4$ -9/l/--1; F<LG$5BC0COCeCsCwLCnC[C<C2LY Y P\C7.&Gl¢BC!>C7CI@CSCRCGC6bC BL¿*4;=>=5K&YB9,CC2C@CFCDC=LC1C$fCiB{|\x$-22/L( 5BFCCC"C&UC%tC#C CCnBA9£MSxWB4HBBC4CtCCCBܴB9AL»§uYA5@BB6XABHdBCCC4CCB,6|ž?CwC.C3CCD &+ 3A(GB5)i Q<BCZC!#C4CECG<C:%C)CCB_xؤ¬gQKDUo®½,†8OB<B0B6B$l?K§z<š ABCC0C=CE\CG0CDC<C/+COBl¦2A<J$LIA5%B5 C`C%UC-C1C2C04C)C!C C*BBT\Av<AsB$<BQPBBB|BBcP¦(1t6:=$:7^2-&@WLBCC(C1C8C:LC8C5C0)C'CCBoA(@Z¾tkK<¯P~i8j$atƒ$’PFo`?DBelC CC*C6/C?0CFCMlCQCR|CP\CJC@C6C,C CBpHh<%-:))"''6%" ( f$).[4:{?D(HLN LhG?83%¢B?CC!C.4C8C>CCCFCICK`CLCJCICGCECBCAxC@@C<$C5C.C'lC-CCB(B!d¹!, 3:9>D@BA>9%2,)# ±KAB`B͈C9CC%C+CCCC_CC CGB|BB&(6X_H‘x`p¸@¸,·¹@©hª$’x(\WPRYhFT5 0BB1BJ\BmBBBXCFCC}CCJCCCCCC CCsCCB BBz8BOA%@DxL=O!I%(c+n++%)U'C%V!50Qs*8BB9$B~B CC%CCCCpCiCCUCCCsCCCCC]C)B`BCJBB<BBByBfB6`B@9q¦(ݐMVJ9D|³¨€ZY(LDpF|(@"BB4BTB\4B]B_B_PB^BlXBfBvBB|Bh BYBjBgBcHBn BY Bc BE\B\lB\LBNBAB3 BDBD?(KDcx`(bZ^a<]tS1AEAAxA.AA*@πAP@AA@BhB64BNB^BlDBiPBWB=lBC(BJBJB1B.BBBBA#! rnews 1312 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!strath-cs!jml From: jml@cs.strath.ac.uk (Joseph McLean) Newsgroups: sci.math Subject: the extendability of digit sequences into primes Message-ID: <753@stracs.cs.strath.ac.uk> Date: 2 Dec 87 10:36:33 GMT Reply-To: jml@cs.strath.ac.uk (Joseph McLean) Organization: Comp. Sci. Dept., Strathclyde Univ., Scotland. Lines: 19 Is the following conjecture reasonable and/or provable? : Given a sequence of digits, starting with a non-zero digit, of arbitrary but finite length, is it always possible to extend this sequence by appending more digits, in such a way as to form a prime? e.g. the sequence 1 can be extended into a prime in an infinite number of ways, as in 13, 17, 19, 101, 1231, 1579, etc (there an infinite number of primes beginning with a 1 by Bertrand's postulate). However, it is far more difficult to try and locate a prime which starts with the sequence 1528296922945708 (although at least one is known). My personal opinion is that the conjecture is reasonable, simply because one can keep adding digits at the end and checking for primality ad infinitum, and the law of averages will do the rest. Of course this is totally groundless mathematically, so can anyone provide a heuristic argument with more weight? jml, the mad mathematician. #! rnews 3077 Path: alberta!mnetor!uunet!husc6!psuvax1!burdvax!bigburd!fritzson From: fritzson@bigburd.PRC.Unisys.COM (Richard Fritzson) Newsgroups: comp.editors Subject: Re: lisp environments (Structure vs. text editors) Message-ID: <3375@bigburd.PRC.Unisys.COM> Date: 14 Dec 87 02:11:18 GMT References: <487@PT.CS.CMU.EDU> <460@cresswell.quintus.UUCP> <499@PT.CS.CMU.EDU> Sender: news@bigburd.PRC.Unisys.COM Organization: Unisys Corporation, Paoli Research Center; Paoli, PA Lines: 56 In article <499@PT.CS.CMU.EDU> ralphw@IUS2.CS.CMU.EDU (Ralph Hyre) writes: >In article <460@cresswell.quintus.UUCP> pds@quintus.UUCP (Peter Schachte) writes: >>Text editors CANNOT simulate structure editors. They can do a rather >>feeble job of it. Text editors fall down when context information is > >I disagree - a PROGRAMMABLE text editor can do anything you want. This is >because it's programmable. Whether you're happy with the performance or a Sure it can do anything. The best way for a programmable text editor to simulate a structure editor would be for it to build an internal representation (or structure) or what was really being edited and then use its text manipulating primitives to show the user the effect of his editing commands on the structure that is "really" being edited. Now you've shown that mocklisp (for example) is a language in which you can implement a structure editor. I doubt if it is the best way to do it though. >>...For example: a structure editor can supply different commands, different >>facilities, for editing comments and code. >Seems like there's the potential here for moby modefulness. I can't see >why I would want different commands when I edit code compared with comments. I don't know about "commands", but Common Lisp comments are nothing like Common Lisp code (much to the shame of Common Lisp). I want the characters I type in as comments treated differently than those I type in as parts of S-expressions. >My interest is in an pseudo-WYSIWYG editor which gives you the option >of entering/editing text without formatting attributes, then optionally >displaying the text with them. <...>This sort of decoupling between editing a >document and a representation of a document could even be used to great >advantage in many environments: You're right. An editor which is really editing the structure underlying the visual presentation of it IS a useful thing. > A program code editor might actually be showing you variable names, > statements, and S-expressions while it is really writing the P-code > (or .lbin file) on the fly. > This could result in 'instant' language interpreter facilities and > fast compilers. > [I admit that this might be hairy to program in MockLisp.] But it is one of the reasons Xerox structure editor fans are fans. >[disclaimer: I've never used a 'structure editor' No offense intended, but I could tell. If you write any Lisp you should look for an opportunity to try SEdit on a D-machine. -- -Rich Fritzson ARPA: fritzson@prc.unisys.com UUCP: {sdcrdcf,psuvax1,cbmvax}!burdvax!fritzson #! rnews 3135 Path: alberta!mnetor!uunet!husc6!cmcl2!brl-adm!umd5!ames!sdcsvax!sdcc6!loral!dml From: dml@loral.UUCP (Dave Lewis) Newsgroups: rec.arts.movies Subject: Re: Live Action Amber Films Summary: Use Zelazny's descriptions! Message-ID: <1496@loral.UUCP> Date: 14 Dec 87 06:41:04 GMT References: <349@morningdew.BBN.COM> <2620001@hpcvlx.HP.COM> Reply-To: dml@loral.UUCP (Dave Lewis) Followup-To: rec.arts.movies Distribution: na Organization: Loral Instrumentation, San Diego Lines: 59 In article <2620001@hpcvlx.HP.COM> markc@hpcvlx.HP.COM (Mark Cook) writes: >>/ hpcvlx:rec.arts.movies / dkovar@lf-server-2.BBN.COM (David Kovar) / 7:07 am Dec 9, 1987 / >> >> Well, someone else was wondering who would be the actors in a Tolkien >>film which brought to mind a favorite question of mine from a few years >>back: Who would play the parts of a Amber film? I used to have the >>Corwin: Mel Gibson Jonathan Pryce. From "Something Wicked This Way Comes". > even better, how about Timothy Dalton (James Bond isn't the only thing he >>Brand: (Who's the guy from Kiss who was in Runaway?) > You mean Gene Simmons. Well, he could play the part but he has to look like No way. Brand is "a figure both like Bleys and myself. My features, though smaller, my eyes, Bleys' hair. There was a quality of both strength and weak- ness, questing and abandonment about him." This is Corwin speaking, of course. And Bleys is "a fiery bearded, flame-crowned man, dressed all in red and orange, mainly of silk stuff, and he held a sword in his right hand and a glass of wine in his left, and the devil himself danced behind his eyes, as blue as Flora's, or Eric's. His chin was slight, but the beard covered it." I can't think of anyone offhand for either part, but I nominate Gene Simmons to play Caine: "Then came the swarthy, dark-eyed countenance of Caine, dressed all in satin that was black and green, wearing a dark three-cornered hat set at a rakish angle, a green plume of feathers trailing down the back." (Yeah, I got "Nine Princes in Amber" lying right next to the keyboard here) Random: "a wily-looking little man, with a sharp nose and a laughing mouth and a shock of straw-colored hair." How about Dudley Moore (with his hair bleached, of course). Dierdre: "a black-haired girl with [Flora's] blue eyes, and her hair hung long and she was dressed all in black, with a girdle of silver about her waist." Lee Meriwether or Kate Jackson. Fiona: "with hair like Bleys or Brand, [Corwin's] eyes, and a complexion like mother of pearl. Ann-Margret! That's all for now; if people are interested I can type in the whole 2-1/2 pages of descriptions so we'll REALLY have something to argue over. ------------------------------- Dave Lewis Loral Instrumentation San Diego hp-sdd --\ ihnp4 --\ sdcrdcf --\ bang --\ kontron -\ csndvax ---\ calmasd -->-->!crash --\ celerity --->------->!sdcsvax!sdcc3 --->--->!loral!dml (uucp) dcdwest ---/ gould9 --/ "I'm alive and he's dead and that's the way I wanted it." -- Corwin, about Borel ------------------------------- #! rnews 2421 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!strath-cs!jim From: jim@cs.strath.ac.uk (Jim Reid) Newsgroups: comp.mail.headers Subject: Re: RFC976 vs. the real world... Message-ID: <754@stracs.cs.strath.ac.uk> Date: 2 Dec 87 12:51:51 GMT References: <18533@amdahl.amdahl.com> Reply-To: jim@cs.strath.ac.uk Organization: Comp. Sci. Dept., Strathclyde Univ., Scotland. Lines: 40 In article <18533@amdahl.amdahl.com> tron@uts.amdahl.com (Ronald S. Karr) writes: >Some Introduction: >However, we have conflicting ideas concerning what to do with sender >addresses in headers. We do, now, support the idea that a pure !-path >coming in can be left as a !-path, with the current hostname prepended >(this is optional and is a function of the destination). However, >should I ever produce, in mail originated locally, a From: line in the >following form? > > From: localhost!username The answer is perhaps. In an ideal world, everyone will adhere to one standard for mail headers - RFC822 possibly, but X.400 is more likely. Until that glorious day arrives (if it ever does), mailers at the mail 'gateways' between networks will have little option but to munge addresses because of incompatible mail headers and addressing formats. What you mail system should do is rewrite mail headers into the appropriate form for transmission to a given host. In short, if your uucp neighbours only understand bang-style addresses, you mailer should only present bang-style paths to these sites. If some sites understand RFC822 (user@host.domain), then you should send them RFC822 style mail. What would be less easy for the mailer is separating your bang-stlye uucp neighbours from those who understand RFC822. The best mailers (MMDF or sendmail - no flames please!) take an input address, convert it to a canonical form and then rewrite the address in the appropriate style for the message transfer agent. This is the most sensible way of dealing with hybrid addresses like A!B@C. [Does that mean send by uucp to A for relaying to user B on host C or does it mean send to C for them to relay to user B on uucp host A? Then what if C (or A) doesn't like addresses with '!' (or '@') signs in them?] Jim -- ARPA: jim%cs.strath.ac.uk@ucl-cs.arpa, jim@cs.strath.ac.uk UUCP: jim@strath-cs.uucp, ...!seismo!mcvax!ukc!strath-cs!jim JANET: jim@uk.ac.strath.cs "JANET domain ordering is swapped around so's there'd be some use for rev(1)!" #! rnews 3873 Path: alberta!mnetor!uunet!husc6!cmcl2!brl-adm!umd5!ames!sdcsvax!sdcc6!loral!dml From: dml@loral.UUCP (Dave Lewis) Newsgroups: rec.arts.sf-lovers Subject: Re: One more long-gone show Summary: What S. F. movies should be Keywords: Questor Message-ID: <1497@loral.UUCP> Date: 14 Dec 87 06:45:22 GMT References: <1672@bsu-cs.UUCP> Reply-To: dml@loral.UUCP (Dave Lewis) Followup-To: rec.arts.sf-lovers Distribution: na Organization: Loral Instrumentation, San Diego Lines: 64 In article <1672@bsu-cs.UUCP> cfchiesa@bsu-cs.UUCP (Christopher F. Chiesa) writes: >Anyone remember a movie called _The_Questor_Tapes_ ? Basic premise: gov't >project constructs an android according to eccentric scientist's specs; and- >C.Chiesa Yea, verily, I recall The Questor Tapes. I've forgotten the scientist's name, but he was a very rich and secretive genius known for several major advances in robotics and cybernetics. About 2 years previous to the start of the movie, he had disappeared, leaving only a partially completed project he called Questor. Much of the work was complete, including a small fusion reactor, most of the brain, and a lot of the support machinery. He also left a BIG mag tape of programs, which some government idiot had partially erased while trying to decode it. Questor, when activated, did nothing; the team that assembled him figured it was because of the bad tape. Late that night, Questor got up, used the 'finishing' molds to give himself human features, and walked out. The scientist had known one member of the Questor-assembly team and put his name and address on the program tape; by good fortune it had survived the attempted decoding. Questor knows only that he must find `a boat' -- other details have been erased. The government catches up with them in a playground and some fool shoots Questor. Apparently the shock knocks some bits loose because when he sees a jungle gym that looks like Noah's Ark he remembers, "the boat, the boat of legend. [whatsisname] is waiting for me there." He also remembers that if he doesn't find the scientist within about two days, his fusion power supply is programmed to overload and blow up. They patch him up and he leads them a merry chase to Mt. Ararat where he finds his creator in a cave hidden by a force barrier/hologram projection. There is a long row of metallic slabs suspended about a meter above the floor; on each lies a defunct robot. Each one wears clothing from a time far earlier than the next. Questor's creator lies on the second to last slab, still conscious but unable to move. These robots have been watching over the human race for more than ten thousand years. Each one lasts two hundred years, then builds his successor. Questor's predecessor was brought to an early end by some combination of pollution and radiation exposure; he has provided Questor with extra shielding so he will last the full two centuries. Questor is the last. By the end of his term, the human race will have reached a point where we can make our own decisions without guidance. The robots were placed here by some advanced aliens to see us through our racial childhood, to allow us a chance to mature and achieve whatever potential we have. The Questor Tapes was an excellent movie, one makers of more recent films should take a lesson from. Very few other movies have impressed me as much as "2001: A Space Odyssey" and "The Questor Tapes". They show up the likes of"Close Encounters of the Third Kind" and "E.T." for the vapid silliness they are. ------------------------------- Dave Lewis Loral Instrumentation San Diego hp-sdd --\ ihnp4 --\ sdcrdcf --\ bang --\ kontron -\ csndvax ---\ calmasd -->-->!crash --\ celerity --->------->!sdcsvax!sdcc3 --->--->!loral!dml (uucp) dcdwest ---/ gould9 --/ ------------------------------- #! rnews 1384 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: rec.arts.sf-lovers Subject: Re: M. John Harrison Message-ID: <1560@brahma.cs.hw.ac.uk> Date: 2 Dec 87 18:20:17 GMT References: <1950@charon.unm.edu> Reply-To: jack@cs.glasgow.ac.uk (Jack Campin) Organization: PISA Project, Glesga Yoonie Lines: 23 Summary: Expires: Sender: Followup-To: [ignore the above address and use my signature] By far the best thing I have read by MJH is a long short story called "Running Down", about a man with unwanted psychic powers that cause things to malfunction, decay and fall apart around him. It is set in a Britain in the near future of when the story was written (i.e. about now) in which the whole society reflects a similar dingy, pointless chaos - remarkably like Britain after 8 years of Thatcher, in fact. He's very good at describing that sort of situation - his novel "The Centauri Device" does it at length, though his suggested political solution is bloody stupid. His understanding of anarchism is about on a level with Robert Anton Wilson's. - jack -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 1188 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: rec.music.classical Subject: Re: Tippett Message-ID: <1561@brahma.cs.hw.ac.uk> Date: 2 Dec 87 18:38:20 GMT References: <1950@bath63.ux63.bath.ac.uk> Reply-To: jack@cs.glasgow.ac.uk (Jack Campin) Organization: PISA Project, Glesga Yoonie Lines: 15 Summary: Expires: Sender: Followup-To: [ignore the above email address and use my signature] Tippett moved on a LONG way musically after "A Child Of Our Time". I believe his masterpiece is the Triple Concerto for violin, viola and cello. There is a wonderful recording of it by Pauk, Imai and Kirschbaum with the LSO under Davis. A problem I find with a lot of his music is the silly words. The man really shouldn't have tried writing his own libretti that often. I believe he's got another opera in the pipeline, due for its premiere in the next few months. -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 894 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!jg From: jg@eagle.ukc.ac.uk (J.Grant) Newsgroups: comp.sys.mac Subject: The Spinning watch cursor Message-ID: <4023@eagle.ukc.ac.uk> Date: 3 Dec 87 14:59:09 GMT Reply-To: jg@ukc.ac.uk (J.Grant) Organization: Computing Lab, University of Kent at Canterbury, UK. Lines: 11 OK - I've changed my spinning watch back into the lovely sand-timer (remember the good old days?); I've changed the CURS resource in the Finder and also in the System so that I have various quantities of sand in the top & bottom, but there is still a watch lurking! More precisely, where does the watch that says 9 o'clock live, as now I get the magic watch followed by the sand1->7, then the watch again as the cycle repeats. This only happens in the Finder, so I suspect that there must be a watch lurking elsewhere, but where? Ps. system 4.2b(5?) & Finder 6.0 (Mac 512Ke) #! rnews 3539 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!csnjr From: csnjr@its63b.ed.ac.uk (Nick Rothwell) Newsgroups: rec.music.synth,rec.music.makers Subject: Casio MG500, Roland MT-32, MIDI bug? [LONG] Summary: Where's the MIDI bug in this lot?: Keywords: MG500 MT-32 MIDI Message-ID: <805@its63b.ed.ac.uk> Date: 3 Dec 87 13:10:56 GMT Reply-To: nick%ed.lfcs@uk.ac.ucl.cs.nss (Nick Rothwell) Organization: LFCS, University of Edinburgh Lines: 46 Xref: alberta rec.music.synth:1879 rec.music.makers:1070 Last weekend a friend and I strolled into a music shop and ended up playing with the new Casio MG500 MIDI guitar linked into a Roland MT-32. I don't play guitar, and was just along for the curiosity, but I've got a few comments to make and a question about what I consider to be a MIDI bug in one of the instruments. Firstly - the performance of the MG500. I wasn't actually playing it (I was just pushing buttons on the MT-32 instead), but I was impressed with its speed and tracking ability - it was fast and followed pitch accurately, responding to pitch bend and so on; it generally sounded pretty tight. There were a couple of things I didn't like - but maybe it's a generic weakness of all guitar-to-MIDI systems. Firstly, the guitar transmits velocity information (hit the string harder -> louder/brighter note), but gives no control (other than pitch-bend) once a note's sounding - there's nothing equivalent to aftertouch/modulation so once a note sounds you're at the mercy of the synth until you stop the string. Point two - You've got six strings, so you can only sound six synth voices. This is probably obvious, but playing a guitar patch through MIDI doesn't sound like a real guitar, because each touch of a string retriggers the voice on that string, sometimes in a rather distracting way. On a real (classical) guitar you have the resonance of the soundbox to hang on to notes so you aren't aware of this (I presume - comments?) Now for what is (in my opinion) a MIDI Bug! Play two different notes on two strings and you get two voices - ok so far. Play the same note on two different strings and you get one voice. Humm. Play two different notes on two strings and slide one note up to the other, and one of the voices is chopped off. I think this is a bug - something somewhere doesn't want to the same note more than once. Needless to say, this completely screws up a number of guitar chords. We mentioned this to the guy in the shop. He seemed convinced that it's a problem with the MIDI spec. itself - if you play a keyboard synth, you have to release the middle C key to play it again, don't you? I think this is a load of dingos kidneys - if I send my D-50 two separate middle C note on messages, then I'll get two voices cycling through the envelopes at middle C pitch. This is what happens with the sustain pedal on, as well. What's the verdict, net people? I think the guy was wrong (quite adamant, but wrong...) and there's a bug in one of the boxes. I suspect the MG500. If the MT-32 is anything like the D-50, then it doesn't care about playing the same note twice. (A quick note in passing that synths with less voices (Juno106 for instance) often won't double a voice, in an attempt to play chords properly without running out.) -- Nick Rothwell, Laboratory for Foundations of Computer Science, Edinburgh. nick%lfcs.ed.ac.uk@nss.cs.ucl.ac.uk !mcvax!ukc!lfcs!nick ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "Nothing's forgotten. Nothing is ever forgotten." - Herne #! rnews 1505 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!bath63!pes From: pes@ux63.bath.ac.uk (Smee) Newsgroups: comp.sys.atari.st Subject: Re: Resource file question Keywords: resource mwc rcs .rsc dri c Message-ID: <1963@bath63.ux63.bath.ac.uk> Date: 3 Dec 87 10:33:26 GMT References: <1592@wiley.UUCP> Reply-To: pes@ux63.bath.ac.uk (Smee) Organization: AUCC c/o University of Bath Lines: 19 You might try looking to see if K-Resource is still available (by Kuma Software, who else?). It's been out a long while. It's now available bundled with some of the MetaComCo stuff (in particular the new Lattice C) but I believe that Kuma still do it separately as well. Don't have a clue what it costs, but must be cheaper than a new compiler. It produces (by switch option) appropriate 'include' type files for C, FORTRAN, and 2 other languages which I've conveniently forgotten -- in addition to the expected .RSC file. Will also produce a 'non-specific structured description' file (they say, I've never tried this) which is alleged to be pretty easy to massage into an appropriate 'include' for any unsupported language you might like. The documentation is written in a bit of a 'too-folksy' style for my liking, but the program is pretty intuitive to use which makes up for some of that. It does, however, assume that you have some sort of a clue as to what the various resource items/flags mean and do -- it doesn't teach you how to use RSC files or what they mean, but rather gives a handle for making them. #! rnews 1258 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!neil From: neil@cs.hw.ac.uk (Neil Forsyth) Newsgroups: comp.sys.atari.st Subject: Bug in bets test Gulam Keywords: none Message-ID: <1562@brahma.cs.hw.ac.uk> Date: 3 Dec 87 09:46:32 GMT Organization: Computer Science, Heriot-Watt U., Scotland Lines: 28 I think I have found a bug in the latest version of Gulam. alias test 'echo $<' produces a couple of spurious charcters on the input line. $<%& The characters are usually above $80. The alpha version didn't do this. I just delete them by backspacing anyway. echo $< by itself works fine. ------------------------------------------------------------------------------- "I think all right thinking people in this country are sick and tired of being told that ordinary decent people are fed up in this country with being sick and tired. I'm certainly not and I'm sick and tired of being told that I am!" - Monty Python Neil Forsyth JANET: neil@uk.ac.hw.cs Dept. of Computer Science ARPA: neil@cs.hw.ac.uk Heriot-Watt University UUCP: ..!ukc!cs.hw.ac.uk!neil Edinburgh Scotland ------------------------------------------------------------------------------- #! rnews 1009 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: comp.sys.mac Subject: Re: how strong of a magnet? Message-ID: <1564@brahma.cs.hw.ac.uk> Date: 3 Dec 87 18:59:42 GMT References: <9554@shemp.UCLA.EDU> Reply-To: jack@cs.glasgow.ac.uk (Jack Campin) Organization: PISA Project, Glesga Yoonie Lines: 12 Summary: Expires: Sender: Followup-To: [ignore the above email address and use my signature] This may be an FOAF story (urban folklore) but I have heard that the mag-lev train at Birmingham Airport lets enough field into the passenger compartment to wipe floppies. Then again, I have also heard that story about ordinary underground railways and it certainly isn't true of them. -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 988 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!csan From: csan@its63b.ed.ac.uk (Andie) Newsgroups: comp.sys.atari.st Subject: Re: Resource file question Keywords: Kuma Message-ID: <808@its63b.ed.ac.uk> Date: 3 Dec 87 23:08:12 GMT References: <1592@wiley.UUCP> <1298@saturn.ucsc.edu> Reply-To: csan@its63b.ed.ac.uk (Andie) Organization: Computer Science Department, Edinburgh University Lines: 14 In article <1298@saturn.ucsc.edu> koreth@ssyx.ucsc.edu (Steven Grimm) writes: > >Kuma Software makes the best resource editor I've seen. It's called >"K-Resource" and is a really friendly, well-thought-out piece of software. > I am in total agreement here. I use it in preference to any others I have. Andie Ness . Department of Computer Science ,Edinburgh University. ARPA: csan%ed.itspna@nss.cs.ucl.ac.uk UUCP: ...!uunet!mcvax!ukc!itspna!csan JANET: csan@uk.ac.ed.itspna % These are my own views and any resemblance to any coherent reasoning is % probably a typo. #! rnews 852 Path: alberta!mnetor!uunet!mcvax!ukc!stc!idec!howellg From: howellg@idec.stc.co.uk (Gareth Howell) Newsgroups: rec.ham-radio.packet,comp.protocols.tcp-ip Subject: NEEDED: KISS for TNC220 Message-ID: <869@idec.stc.co.uk> Date: 1 Dec 87 09:05:59 GMT Organization: ICL Network Systems, Stevenage, Herts. UK Lines: 12 Xref: alberta rec.ham-radio.packet:767 comp.protocols.tcp-ip:1918 I have a Pacomm TNC220 on which I want to run KISS and thence the KA9Q tcp/ip package. Unfortunately I don't have a KISS for the TNC. Can anybody help. I would prefer the co-resident bootstrap with a downloaded KISS module if possible. ta Gareth ==== -- Gareth Howell G6KVK @ IO91VX ICL NS PNBC, England, SG1 1YB Tel:+44 (0)438 738294 howellg%idec%ukc@mcvax.uucp, mcvax!ukc!idec!howellg@uunet.uu.net G6KVK @ G4SPV (uk packet 144.650MHz) #! rnews 710 Path: alberta!mnetor!uunet!mcvax!ukc!stc!hilda From: hilda@tcom.stc.co.uk ( Jeff Tracey ) Newsgroups: rec.arts.sf-lovers Subject: Thunderbirds are GO!!! Keywords: FAB Message-ID: <1503@arran.tcom.stc.co.uk> Date: 2 Dec 87 10:54:39 GMT Organization: STC Telecoms, London N11 1HB. Lines: 14 A few quick trivia questions on Thunderbirds :- 1) Does anybody know what the phrase 'FAB' stands for ??? 2) What's the first mission that International Rescue accomplished ? 3) What's the Butler's name on the Island AND who is his daughter ? Regards, Steve Hillyer. || ...uunet!mcvax!ukc!stc!hilda STC Telecommunications, Oakleigh Rd South, London N11 1HB. Phone : +44 1 368 1234 x3358 #! rnews 1159 Path: alberta!mnetor!uunet!mcvax!ukc!stc!btnix!crouch From: crouch@btnix.axion.bt.co.uk (Chris Rouch) Newsgroups: comp.os.vms Subject: callable TPU? Keywords: TPU callable editor Message-ID: <632@btnix.axion.bt.co.uk> Date: 3 Dec 87 11:33:58 GMT Organization: British Telecom Research Labs, Martlesham Heath, IPSWICH, UK Lines: 17 I read somewhere that there is a callable version of EDT, available by using EDT$EDIT(...). Does anyone know if there is a similar function for the TPU editor and/or other commands such as MAIL, PRINT etc. If somebody could also point me in the direction of the VMS manual which contains this information (assuming there is one), I would be very grateful. Chris Rouch -------------------------------------------------------------------------------- vax to vax (UUCP) CRouch@axion.bt.co.uk (...!ukc!btnix!crouch) desk to desk RT3124, 310 SSTF, British Telecom Research Laboratories, Martlesham Heath, IPSWICH, IP5 7RE, UK. voice to voice +44 473 646093 "Ours is not to look back, ours to continue the crack." -------------------------------------------------------------------------------- #! rnews 1090 Path: alberta!mnetor!uunet!mcvax!ukc!stc!pete From: pete@tcom.stc.co.uk (Peter Kendell) Newsgroups: rec.music.classical Subject: Durufle virgin seeks advice Message-ID: <483@stc-f.tcom.stc.co.uk> Date: 3 Dec 87 11:50:35 GMT Organization: STC Telecoms, London N11 1HB. Lines: 25 Being curious, as the name was completely new to me, I borrowed the Hyperion CD of Durufle's Requiem from my local public library. I enjoyed it very much and would like to find out more about him, so :- - What else has he written? (I believe he's not been very prolific) - What else has been recorded? - Is his other work similar to the Requiem; it is better, worse or just different? - I thought I heard a Holst influence; is this typical? - Are there other 20th Century composers in a similar vein that I should try? -- ------------------------------------------------------------------------------ | Peter Kendell | | ...{uunet!}mcvax!ukc!stc!pete | ------------------------------------------------------------------------------ #! rnews 1235 Path: alberta!mnetor!uunet!mcvax!ukc!stc!praxis!gauss!drb From: drb@praxis.co.uk (David Brownbridge) Newsgroups: comp.unix.wizards Subject: Re: //host vs "mount point" Message-ID: <1606@newton.praxis.co.uk> Date: 3 Dec 87 12:42:36 GMT References: <648@tut.cis.ohio-state.edu> <1668@tut.cis.ohio-state.edu> <38c15248.4580@hi-csc.UUCP> <9559@mimsy.UUCP> <411@PT.CS.CMU.EDU> Sender: nobody@praxis.co.uk Reply-To: drb%praxis.uucp@ukc.ac.uk(David Brownbridge) Organization: Praxis Systems plc, Bath, UK Lines: 19 In article <411@PT.CS.CMU.EDU> jgm@K.GP.CS.CMU.EDU (John Myers) writes: >Just to add to the confusion, let me put in a plug in for the Carnegie-Mellon >University Computer Science Department's syntax: > >/../host We built a system which also allowed super-super-roots and so on ad infinitum. /../NearbyHost /../../OtherSite/host /../../../OtherCountry/AnotherSite/host "/.." makes sense to me which is why I promoted it as the "University of Newcastle upon Tyne Computing Laboratory's syntax" :-) Some old-timers must remember the "Newcastle Connection" distributed UNIX system which Lindsay Marshall and I wrote in 1981-2. "Not for the iron fist but for the helping hand" [Billy Bragg/Oyster Band "Between The Wars"] #! rnews 1785 Path: alberta!mnetor!uunet!mcvax!ukc!stc!datlog!slxsys!jpp From: jpp@slxsys.specialix.co.uk (John Pettitt) Newsgroups: comp.unix.xenix Subject: Re: smail2.5 Summary: smail on xenix without writing new programs Keywords: At last, a 'real' mailer for Xenix (are you listening SCO) :-) Message-ID: <106@slxsys.specialix.co.uk> Date: 3 Dec 87 06:44:07 GMT References: <484@rel.eds.com> Reply-To: jpp@slxsys.UUCP (John Pettitt) Organization: Specialix International, London, UK. Lines: 27 In article <484@rel.eds.com> bob@rel.eds.com (Bob Leffler) writes: >During the last several weeks there have been numerous solutions posted to >the net to resolved the interface problem with Xenix and smail 2.5. I >have tried all the solutions that I am aware of and my conclusion for the >best approach is a combination of two. lots of stuff about how to install smail deleted. I have just installed smail 2.5 on Xenix 386. The solution I used here was to replace /usr/lib/mail/execmail with a link to (copy of) /bin/smail. I also moved the old sco execmail to execmail.sco and used it as the local delivery agent. The above will not work as it stands because the command syntax for execmail is not the same as smail. This can be corrected by swapping the meaning of the -F and -f switches in smail (main.c and defs.h). The local delivery macro in defs.h should be set to give /usr/lib/mail/execmail.com -f from to. With this setup you get the sco mailer (mailx) and smail with both From and From: lines correct. Also as execmail is still used for 'local' delivery micnet (sco's RS232 "LAN") still works. -- John Pettitt G6KCQ, CIX jpettitt, Voice +44 1 398 9422 UUCP: ...uunet!mcvax!ukc!pyrltd!slxsys!jpp (jpp@slxsys.co.uk) Disclaimer: I don't even own a cat to share my views ! #! rnews 1287 Path: alberta!mnetor!uunet!mcvax!lambert From: lambert@cwi.nl (Lambert Meertens) Newsgroups: sci.math Subject: Re: Least-squares fitting Message-ID: <135@piring.cwi.nl> Date: 5 Dec 87 14:41:10 GMT References: <1823@culdev1.UUCP> Organization: CWI, Amsterdam Lines: 28 In article <1823@culdev1.UUCP> drw@culdev1.UUCP (Dale Worley) writes: ) Is is known how to perform least-squares fitting where the "error" is ) the perpendicular distance between the point and the line? This least-squares fit still passes through the "center of gravity" of the data points, so assume that the data has been reduced such that the averages of the x- and y-coordinates are both zero. Let the equation of the line to be determined be x*(sin phi) - y*(cos phi) = 0, that is, it is the line making an angle phi with the x-axis. Put XX = SUM_i x[i]^2, XY = SUM_i x[i]*y[i], YY = SUM_i y[i]^2. Then tan(2*phi) = 2*XY/(XX-YY). This gives two solutions for phi. Take the one such that the point (XX-YY, 2*XY) lies on the ray through the origin with angle 2*phi. (Remark. It is possible to solve the coefficients for x and y algebraically, without going through the arctan routine, but it is harder then to get the signs correct.) -- Lambert Meertens, CWI, Amsterdam; lambert@cwi.nl #! rnews 852 Path: alberta!mnetor!uunet!mcvax!inria!imag!bordier From: bordier@imag.UUCP (Jerome Bordier) Newsgroups: comp.sys.mac Subject: Re: Arabic Wordprocessing / Publishing Message-ID: <2285@imag.UUCP> Date: 4 Dec 87 10:24:35 GMT Reply-To: bordier@imag.UUCP (Jerome Bordier) Organization: IMAG, University of Grenoble, France Lines: 14 "Winsoft", a small firm developping and selling software for the Macintosh, has made "Wintext", a word processor fully compatible with the "Arabic Macintosh+" (you have to obtain the Arabic keyboard distributed by Apple). Their address is: Winsoft 34 boulevard de l'Esplanade 38000 GRENOBLE France Phone no.: 76.87.56.01 -- Jerome BORDIER Laboratoire Structures Discretes Institut IMAG B.P.68 - 38402 SAINT MARTIN D'HERES CEDEX France E.Mail: bordier@imag.imag.fr or {uunet.uu.net|mcvax}!imag!bordier #! rnews 1182 Path: alberta!mnetor!uunet!mcvax!inria!rouaix From: rouaix@inria.UUCP (Francois Rouaix) Newsgroups: comp.sys.amiga Subject: POPCLI III Another Bug Keywords: left-amiga-esc timing Message-ID: <587@inria.UUCP> Date: 5 Dec 87 17:45:19 GMT Organization: INRIA, Rocquencourt. France Lines: 20 Well, it seems there is another bug in Popcli III. Just try 1> run popcli 30 and then press Left-Amiga-Esc: the drive (where c: is) spins for a moment and nothing happens. The new 'screen-blanker' works all right but the automatic launch is defeated. Same for values of 10 and 40 seconds. I didn't have time to figure out the limit value for which Popcli will work (it works with default value and 240s). Anyway, despite I *love* the new feature (let's keep the secret :-), I'd rather have the old screen-blanker : at least I can sleep while the Amiga is still on and working, and also it won't eat CPU-time I need for Ray-tracing !! -- *- Francois Rouaix / When the going gets tough, * *- USENET:rouaix@inria.inria.fr \/ the guru goes meditating...* * SYSOP of Sgt. Flam's Lonely Amigas Club. (33) (1) 39-55-84-59 (Videotext) * #! rnews 539 Path: alberta!mnetor!uunet!husc6!uwvax!rutgers!lll-lcc!ames!sdcsvax!ucsdhub!hp-sdd!ncr-sd!crash!pnet01!hhaller From: hhaller@pnet01.cts.com (Harry Haller) Newsgroups: comp.dcom.modems Subject: Re: Facsimile on PC Message-ID: <2140@crash.cts.com> Date: 14 Dec 87 04:36:13 GMT Sender: news@crash.cts.com Organization: People-Net [pnet01], El Cajon, CA Lines: 4 There is a board you can plug into the backplane that purports to give you full FAX capability with editing. Of course, I forget the name, but if you look in the literature... () #! rnews 1436 Path: alberta!mnetor!uunet!husc6!uwvax!rutgers!lll-lcc!ames!sdcsvax!ucsdhub!hp-sdd!ncr-sd!crash!pnet01!dm From: dm@pnet01.cts.com (Dan Melson) Newsgroups: rec.aviation Subject: Re: ARSA transition phraseology Message-ID: <2141@crash.cts.com> Date: 14 Dec 87 06:16:11 GMT Sender: news@crash.cts.com Organization: People-Net [pnet01], El Cajon, CA Lines: 21 The question was asked why an ARSA controller might want to know your destination. Actually, what they really want to know is where you're going *now*, like 'direct PMD' or 'following I5 northbound' (I have *no* idea of what type of airspace that will take you through at any given altitude) or whatever course, heading, or whatever you intend to take through the ARSA. Now, if you're going to get flight following, the controller is going to want to know your complete route of flight for which you want flight following, so that it can be entered into the machine and the autumated handoffs can be used between sectors and facilities. As for why, that's very simple. For purposes of calling traffic, which I consider to be sufficient, if no one else does. The same reason the controller at the VFR tower asks your direction of departure. If nothing else, the controller can always tell the left downwind departures 'traffic a (whatever) reported 6 SE for a left base entry', or whatever is appropriate. MY opinions ONLY! DM #! rnews 2759 Path: alberta!mnetor!uunet!mcvax!diku!iesd!jacob From: jacob@iesd.uucp (Jacob stergaard B{kke) Newsgroups: comp.ai Subject: job search, Comp. eng. Summary: I'm looking for a job Keywords: Job, Computer. eng., Computer. sci., M.S. Message-ID: <152@iesd.uucp> Date: 2 Dec 87 13:20:07 GMT Reply-To: jacob@iesd.UUCP (Jacob \stergaard B{kke) Organization: Dept. of Comp. Sci., Aalborg University, Denmark (student) Lines: 69 I'm looking for a job in Computer Engineering to begin around July 1988. I'm getting my Master of Science in Computer Engineering June 1988 and at present holding a degree equal to BS in Electronic Engineering. My BS studies have included: Computer hardware (hands-on knowledge with mc68k), Analog electronic Control engineering (analog and digital control) My MS studies have included: Software development (man-machine interface, what people want from programs) Compiler construction (an expertsystem shell) Program environment (for CCS programming) Distributed operating systems (in UNIX) Compiler mapping object-orinted language on parallel computers Furthermore I do have experience in conventional programming (PASCAL, C, postscript, UNIX (awk, shell-scripts(C-shell) and yacc/lex) (and Basic)), functional programming (LISP and ML) and logical programming (Prolog) and knowledge about object-oriented programming. And I have also attended courses in VLSI design, databases, etc. I have been working with CDC under NOS/Telex, VAX 11/750 under Ultrix, SUN 3 under Sun OS 4.3 (UNIX), MacIntosh (LISA) under Finder and IBM S36 under IBM property operating system. My spoken English is excellent and my written English is satisfactory, good knowledge of the Scandinavian languages (Danish (of course), Swedish and Norwegian), some speaking and reading knowledge of German and limited knowledge of French and Spanish (and Latin). I have 5 years experience in group project work in engineering and computer scinence areas, broad social interest, good health. My interest include computer hardware and software, operating system design, expertsystems, distributed, concurrency and teaching. I'm open on location (outside Denmark) but I have relatives or other reasons to be especially intereted in: Canada (British Colombia or Toronto) USA (New England or Pacific Coast) Pacific (New Zealand or Oceania) Thailand Scotland (Highlands) I'll look forward to any reponds. Yours sincerely Jacob Baekke, Denmark For further information: Reply to: jacob@iesd.uucp, {...}!mcvax!diku!ised!jacob or at Univ: Jacob Baekke S9D (in spring S10) Strandvejen 19 AUC DK--9000 Aalborg Denmark private: Jacob Baekke Davids Alle 48 DK--9000 Aalborg Denmark Tel. 45-(0)8102673 #! rnews 2425 Path: alberta!mnetor!uunet!husc6!bbn!rochester!cornell!uw-beaver!uw-june!uw-entropy!dataio!suvax1!hirayama From: hirayama@suvax1.UUCP (Pat Hirayama) Newsgroups: rec.arts.anime Subject: Re: Speed Racer and the Mach 5 Message-ID: <810@suvax1.UUCP> Date: 14 Dec 87 05:28:25 GMT References: <1103@jumbo.dec.com> Organization: Seattle University, Seattle, WA. Lines: 45 in article <1103@jumbo.dec.com>, schubert@jumbo.dec.com (Ann Schubert) says: > Posted: Thu Dec 10 15:26:21 1987 > > > THIS IS A RE-POST FROM REC.ARTS.TV > > > In article <4540011@wdl1.UUCP> (James Y. Nakamura) writes: > > I have a question about Speed. We can't figure out all the neato gadgets his > car had I think it went like: > 1: Jacks that also made the car able to jump. > 2: ??? > 3: Saw blades that cut through stuff > 4: Closes off the top so the Mach 5 becomes a sub.. > 5: Homing pidgeon on a rope. > Don't forget the special treads which would appear on his tires to allow for climbing up rough ground or driving near vertical. Every now and then, I remember that they would add a new option (boy, don't you wish your friendly neighborhood dealership would offer some of these for your car?). Unfortunately, it has been many years since I last saw Speed Racer, but I do remember one episode which added little winglets which would come out from under- neath the doors. This added a little gliding ability. Any one else remember any? > Also why did Speed have a G on his shirt? Go doesn't really wash with me and > I don't know enough Japanese to equate letters. > I used to know this but I can't remember anymore, though I suspect that it might have to do with the original name of the character/title of the show in Nihongo. Help anyone? ******************************************************************************* * --Pat Hirayama * * --Seattle University * * * * "Yamato Hasshin!" - Kodai Susumu * * * ******************************************************************************* #! rnews 684 Path: alberta!mnetor!uunet!mcvax!inria!axis!matra!godefroy From: godefroy@matra.UUCP (Eric Godefroy) Newsgroups: comp.unix.wizards Subject: 8 bits on a pseudo-tty Message-ID: <252@matra.matra.UUCP> Date: 3 Dec 87 13:33:27 GMT Reply-To: godefroy@matra.UUCP (Eric Godefroy) Organization: Matra Datasysteme Lines: 9 On 4.2 bsd, it seems difficult to set a pseudo-tty (ptyp / ttyp) in the pass8 mode. Is it impossible really or how can I do that ? ---------------------------------------------------------- Eric Godefroy UUCP: mcvax!inria!matra!godefroy Matra Datasysteme Tel: (33-1) 30 58 98 00 1, av Niepce Fax: (33-1) 30 45 41 59 78180 Montigny-le-Bretonneux France #! rnews 2663 Path: alberta!mnetor!uunet!husc6!bbn!rochester!cornell!uw-beaver!uw-june!uw-entropy!dataio!suvax1!hirayama From: hirayama@suvax1.UUCP (Pat Hirayama) Newsgroups: rec.arts.sf-lovers,rec.arts.anime Subject: Re: Old TV shows Message-ID: <811@suvax1.UUCP> Date: 14 Dec 87 05:54:39 GMT References: <4254@dandelion.CI.COM> Organization: Seattle University, Seattle, WA. Lines: 40 Xref: alberta rec.arts.sf-lovers:9224 rec.arts.anime:249 in article <4254@dandelion.CI.COM>, david@dandelion.CI.COM (David M. Watson) says: > Xref: suvax1 rec.arts.sf-lovers:7102 rec.arts.anime:235 > > > I have foggy but pleasant memories of three other converted Japanese > - (not anime, but...) Ultraman! (Was it: "Hiyata! The beta capsule!"?) > He was a large silver "good-monster" with a red light > mounted on his chest that would blink whenever his batteries > were getting low. And in his valiant, exhausting fights > against the dinosaur types that frequently showed up to > menace the World, he almost always came close to running out! > And I remember a obligatory post-crisis trip to the jewelery > store for Hiyata and friend! > > Would anyone like to refresh my memory about any of these three? > - Ultraman was one of several incredibly popular shows in Japan during the late 60s/early 70s/early 80s. Actually, there were several shows each featuring one or more of the "Ultra" brothers, of whom Ultraman was the "leader/head/eldest (you get the idea)". There was also Ultra 5 and a bunch of others which I can't remember and it would take a long time to dig out the books. There was something of a revival when UltraMan 80 (?) was released in Japan. Of these, I believe that only the original Ultraman was released and dubbed for the American market. - By the way, Hayata would be the way to spell his name (though it would be more accurately pronounced by you gaijin as "Hiyata". - Of course, there is nary a trace of him now in Japan. Programs have this incredible tendency of grabbing hold of everyone, then they drop it for something new. ***************************************************************************** * -Pat Hirayama * * -Seattle University * * * * > No messages or quotes right now < * ***************************************************************************** #! rnews 1910 Path: alberta!mnetor!uunet!mcvax!enea!tut!santra!nispa From: nispa@hutcs.hut.fi (Tapani Lindgren) Newsgroups: comp.unix.wizards,comp.unix.questions Subject: Unattended dumps (BSD4.3) Message-ID: <9032@santra.UUCP> Date: 4 Dec 87 15:19:19 GMT Sender: news@santra.UUCP Followup-To: comp.unix.wizards Organization: Helsinki University of Technology, Finland Lines: 28 Xref: alberta comp.unix.wizards:5739 comp.unix.questions:4767 I have encountered a problem trying to make a shell script that would make incremental backups at nighttime without operator attendance. The problem results from dump(8) program requiring occasional responses from the operator through /dev/tty. The script is run from another script, /usr/adm/daily, under cron control and has no controlling terminal, so it just hangs trying to read /dev/tty. It would be ok if dump just aborted when facing a situation that would require operator intervention. The script should never hang in a loop under any circumstances, because /usr/adm/daily must do other things too and finish after a reasonable time. Currently I have the dump script run a background subshell that sleeps for an hour and then kills the dump script (if it still runs) and all dump processes. This is very complicated, however, and the watchdog process is almost 50% of the whole script. It is also very slow - I would like it to stop immediately if it finds an error, report it to log file, rewind the tape, and let /usr/adm/daily continue its work. Has anyone out there in the Netland have any suggestions of what to do? Can yes(1) somehow be piped to a program that reads /dev/tty? Could dump(8) be modified to abort at errors without any questions? What kind of unattended backup systems do you have? --- Tapani Lindgren, Helsinki Univ. of Technology, CS dept. INTERNET: nispa@hutcs.hut.fi UUCP: mcvax!santra!hutcs!nispa BITNET: nispa%hutcs.UUCP@fingate.BITNET #! rnews 2315 Path: alberta!mnetor!uunet!husc6!bbn!oberon!pollux.usc.edu!kurtzman From: kurtzman@pollux.usc.edu (Stephen Kurtzman) Newsgroups: rec.food.cooking Subject: Re: Cooking Wines Message-ID: <5698@oberon.USC.EDU> Date: 14 Dec 87 11:38:44 GMT References: <4628@pyr.gatech.EDU> <10722@sri-unix.ARPA> <2028@ttrdc.UUCP> Sender: nobody@oberon.USC.EDU Reply-To: kurtzman@pollux.usc.edu (Stephen Kurtzman) Organization: University of Southern California, Los Angeles, CA Lines: 37 In article <2028@ttrdc.UUCP> levy@ttrdc.UUCP (Daniel R. Levy) writes: > >2) (more seriously) I've seen bottles of "wine for cooking" that have had > salt (and vinegar?) added. These might be OK for sauces (yeah, the > snootier gourmets wouldn't want anything to do with them) but they > would obviously be horrible to drink. I think that these wines would be particularly bad for sauces that require wine as a major component and require reducing the wine. There are two reasons that come to mind: 1) What is normally labeled as cooking wine is usually wine that is not good enough to sell as table wine. If the taste is not the best, reducing it will only concentrate its flaws. 2) Cooking wines contain salt. Reducing a cooking wine will concentrate the salt. This could really ruin the sauce. There best reason I have seen for using a good wine to cook with was given by Alexis Bespaloff in the "New Signet Book of Wine", which states "Furthermore, it is actually uneconomical to buy cheap wine for cooking. Say that an elaborate lobster dish calls for a spoonful or two of sherry to heighten its flavor. A cook who runs out to buy a bottle of cheap sherry will diminish the taste of an expensive and time-consuming dish with a quarter's worth of wine. What's more, because the wine is a poor example of its type, it may not be enjoyable to drink, so the spoonful of wine has, in fact, cost the full price of the bottle." That is fairly sound reasoning. Of course, the last sentence does not necessarily follow. You could keep the cheap wine around to diminish several meals. BTW, I recommend the "New Signet Book of Wine" to anyone who wants to learn more about wine. It is available for $4.50 as a paperback. Quite a value when you compare it to the $20-or-more, glossy coffee-table wine books out on the market. #! rnews 1809 Path: alberta!mnetor!uunet!mcvax!enea!luth!d2c-usg From: d2c-usg@sm.luth.se (Ulrik"Rick"Sandberg) Newsgroups: rec.music.misc Subject: Re: Yes and ELP questions...... Keywords: Tales from Topographic Oceans Message-ID: <435@psi.luth.se> Date: 4 Dec 87 18:28:34 GMT References: <748@augusta.UUCP> <434@psi.luth.se> Reply-To: Ulrik"Rick"Sandberg Organization: University of Lulea, Sweden Lines: 28 UUCP-Path: {uunet,mcvax}!enea!psi.luth.se!d2c-usg In article <434@psi.luth.se> I wrote: >In article <748@augusta.UUCP> bs@augusta.UUCP (Burch Seymour) writes: >>been looking for Tales on CD without success. To get to the point, is >>it (Tales) on CD? > >One of my friends ordered it from a Recordshop in Gothenburg, but got >the answer that it was sold out. However, they didn't say that the >record isn't existing on CD. He was supposed to recieve it later. >Any wiser of that? > Correction: Received is spelled received, not recieved. :-) My friend told me that they said "Tales.. is not on CD." That's why he didn't get it. Sorry for the confusing information. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~ ~ Ulrik 'Rick' Sandberg d2c-usg@luth.UUCP (or) ~ ~ Computer Technology d2c-usg@psi.luth.se (or) ~ ~ University of Lulea {uunet,mcvax}!enea!psi.luth.se!d2c-usg ~ ~ Sweden ~ ~ phone: (0920)-977 90 (home) "I feel lost in the city..." ~ ~ -- Jon Anderson -- ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #! rnews 1128 Path: alberta!mnetor!uunet!husc6!rutgers!lll-lcc!pyramid!decwrl!cssaus.dec.com!bell From: bell@cssaus.dec.com (Peter Bell, SNA-2, Sydney) Newsgroups: rec.music.classical Subject: Hogwood Message-ID: <8712141101.AA04882@decwrl.dec.com> Date: 15 Dec 87 05:23:00 GMT Organization: Digital Equipment Corporation Lines: 15 I have just finished singing (in choir) under Hogwood, it was an experience. We sang Schuberts Mass in G, (as Schubert wrote it, missing a few phrases of the Credo). Hogwood knew exactly what he wanted, and worked till we did it right. Then as we tidied up the last few problems, he would let us sing through whole sections, then go back and point out all the problems. We also sang the Messiah (not with Hogwood unfortunately) the delight of those performances was Elizabeth Cambells singing "He was despised..." In this performance the two trumpeters waited off stage until just before their appearances in each half, the first trumpet parts were played by a large trumpeter (in nice to see that Sydney musicains are not starving) on what looked like a very small valved trumpet (trumpet in F??). Peter. #! rnews 1252 Path: alberta!mnetor!uunet!mcvax!dutrun!winffhp From: winffhp@dutrun.UUCP (Frits Post and/or Andrew Glassner) Newsgroups: comp.graphics Subject: abstracts wanted Keywords: ray tracing, abstracts Message-ID: <190@dutrun.UUCP> Date: 2 Dec 87 09:14:55 GMT Organization: Delft University of Technology,The Netherlands Lines: 21 I am preparing a list of technical memos, technical notes, internal reports, and other such low-circulation documents that deal with ray tracing. I'm interested in documents both large and small. The documents need not be expressly about ray tracing; the criterion is that the information in the document be useful to ray tracing researchers in some way. If you have prepared such a document, please send me enough information to digest it. That would at least include your name and organization, the document's title, perhaps a reference number, and (very important!) an abstract. All contributors will receive a complete copy of the final list. -Andrew Glassner email until 15 December: uunet!mcvax!dutrun!frits email after 15 December: glassner@unc.cs.edu , unc!glassner -- ...mcvax!dutrun!frits Faculty of Mathematics and Informatics Delft University of Technology #! rnews 593 Path: alberta!mnetor!uunet!mcvax!lambert From: lambert@cwi.nl (Lambert Meertens) Newsgroups: sci.lang Subject: Re: Acquiring native accents Message-ID: <136@piring.cwi.nl> Date: 5 Dec 87 22:56:44 GMT Organization: CWI, Amsterdam Lines: 8 When I speak English I hear no Dutch accent in my voice. But if my voice is recorded and played back to me I find the Dutch accent unmistakable. If this phenomenon is a general one, it goes a good deal towards explaining why adult learners of a new language do not fully master the native accent. -- Lambert Meertens, CWI, Amsterdam; lambert@cwi.nl #! rnews 6735 Path: alberta!mnetor!uunet!mcvax!philmds!leffe!janpo From: janpo@leffe.UUCP (janpo) Newsgroups: rec.music.misc Subject: Re: Ideas for improving the debate (was: Digital vs. Analog music) Summary: Digital versus Analog Keywords: CDs expensive audiophile equip. fourier analysis Message-ID: <43@leffe.UUCP> Date: 4 Dec 87 13:55:04 GMT References: <574@ucdavis.ucdavis.edu> <522@altura.srcsip.UUCP> <3051@batcomputer.tn.cornell.edu> Organization: Philips I&E DTS Eindhoven Lines: 123 1) Mr. Konar, press the 'n' key immediately! There's another arrogant audiophile going to pollute the net with his view on the Digital vs. Analog issue. 2) I'm not very much acquainted with the news stuff on the net, but it seems we don't receive the rec.audio newsgroup here in Europe. Can something be done about that? 3) Now let me come to the point. In article <3051@batcomputer.tn.cornell.edu> eacj@batcomputer.tn.cornell (Julian Vrieslander) he writes: >Konar than goes on to comment about the "arrogance" of audiophiles who still >prefer analog recordings to digital. He says the issue should be laid to rest >, the implicit assumption being that the case has been proven that analog >recording is obsolete. >I for one think that the issue is still an open (and interesting) one, but I >am a bit surprised at how polarized and closed the recent comments to this >thread have been. I agree with him, so let me do my bit now. A technology not being perfect , or getting close to that, is still worth a discussion. Remember that it took about a 100 years of thorough research from Edison's first grammophone to the modern high quality turntables. Don't expect digital audio to be perfect now only a few years after its introduction, no matter what the commercial guys say. They are only interested in your hard-earned $$$$. Until now I have only been in the opportunity to make a good comparison between a high-end turntable and some first genaration. I'll summarize the pros and cons of which I think are important and which I can think of now. Many of them are well known, others may not. PROS OF ANALOG: - Cheap records. - As John Vrieslander mentioned: More real, more spatious, more delicate, more emotionally involving. I won't try to find other words for this description 'cause I can't think of a better one. Unfortunately, this can only be heard on good, say > $2k-$3k systems without an infinite number of knobs, lights and other gadgets normally found in aeroplane cockpits. CONS OF ANALOG: - More hissy, rumble,scratches,sound degrading after many times of playing the record. This counts less when you have good records (Japanese ones are most often excellent but hard to get now.) and take good care of them. - No flat frequency response, especially at the low and high end. - Phase distortion. - Harmonic distortion increases with amplitude. PROS OF DIGITAL: - Longer durability than records (?). Less hissy, no rumble or ticks of scratches. - Almost no phase distortion, flat frequency response within the audio range. - Easy to use. - Slightly (!) more dynamic. Why only slightly? Well, the 96 dB dynamic range theoretically possible with a CD is not very practical. In reality it is compressed, as far as I know, to some 40-60 dB depending on the music (Pop, Jazz, Classic) because: a) No one wants to run continuously to his volume knob to adjust the volume.If not compressed the music will either be banging through your living room and of your neighbours or it will drown in the inevitable background noise. b) Studio equipment has a dynamic range of less than, say, 70 to 80 dB when you assume the Signal to Noise ratio being equal to the dynamic range. c) Sound gets to distorted at low levels. (See also cons) d) A dynamic headroom of 10 dB is desired. With all this limitations the dynamic range of CD's is not much different with that of a good record. - Excellent bass response. Deep and well defined. - Very stable stereo image. CONS OF DIGITAL: - Expensive records. - When listening to a CD, it seems as if there is no "space" around around the instruments and voices. It sounds cold and not very lively. - First generation players and the cheaper CD players nowadays suffer from very distorted high tones. They sound harsh. Cymbals for instance sound like someone is sawing them into pieces instead giving it a gentle hit with a drum-stick. They do not sound crisp and clear. - Distortion increases dramatically with lower amplitudes (!). It can be more than 1.5 % at low levels. And it's a very nasty kind of distortion. - CD players produce (digital) noise above the audio range. This noise itself can not be heard but other audio equipment may suffer from intermodulation distortion which brings this noise back in the audio range. - Many CD players, especially the first ones, do not seem to be very reliable mechanically. - I've heard that digital audio recording is quite different from analog. I mean in terms of how it has to be done properly. I don't mean the equipment needed, that's quite obvious. Not all studio crew seem to know how to make a good digital recording. Does anyone know more about that? Well, this must be enough stuff to think and talk about. The above mentioned cons of digital audio may be overcome in the latest players but I have not had the opportunity until now to carefully listen to them and to compare them. According to some serious audio magazines available here in Holland they seem to be improved. Many top-of-the-line models now have separated power supplys for the digital and analog circuitry, opto-couplers between those circuits, an additional analog filter to filter out > 20 kHz noise, 16 bit with with n times oversampling, stable and rigid chassis and improved error correction. All this may have solved (some) of the cons I mentioned but I'm not sure. Players which have one or more of these improvements and thus may be of interest (At least for Julian Vrieslander and me) are: Philips (Magnavox in the USA I believe) CD 650 and CD 960, Nakamichi, Mission, Meridian and if memory serves me well, Acoustical Research (Or Audio Research. Don't know anymore). The latter two may be difficult to get in the USA, they are made in the UK. No doubt that there are more good CD players but can't think of others now. These are the players I consider buying when normal LP's are no longer available. Pooh! That was more than I intended to write but still far less than I can tell about this stuff. Kind regards from Jan Postma And on the seventh day, God went surfing! #! rnews 1424 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!heiser From: heiser@ethz.UUCP (Gernot Heiser) Newsgroups: comp.emacs Subject: Setting terminal-emulator's environment Keywords: GNU Emacs function `terminal-emulator' Message-ID: <261@bernina.UUCP> Date: 5 Dec 87 13:42:37 GMT Reply-To: heiser@ethz.UUCP (Gernot Heiser) Organization: ETH Zuerich, Switzerland Lines: 18 Using the GNU emacs terminal-emulator to run interactive programs would be quite limited if the parent emacs can't be used for editing (when the program run under the emulator starts up an editor). While some programs (like `rn') allow to explicitely specify the editor, a general solution would require to specify `emacsclient' in the `EDITOR' environment variable of the process running under the terminal emulator. Naturally this could be done by running the shell under the emulator, setting the environment of the shell, and then running the program we are really interested in. A better way would be to set the environment from the `terminal-mode-hook'. Is there any means to achieve this???? (I'm running GNU Emacs version 18.49.) -- Gernot Heiser Phone: +41 1/256 23 48 Integrated Systems Laboratory CSNET/ARPA: heiser%ifi.ethz.ch@relay.cs.net ETH Zuerich EARN/BITNET: GRIDFILE@CZHETH5A CH-8092 Zuerich, Switzerland EUNET/UUCP: {uunet,...}!mcvax!ethz!heiser #! rnews 1617 Path: alberta!mnetor!uunet!mcvax!enea!sommar From: sommar@enea.UUCP (Erland Sommarskog) Newsgroups: rec.music.misc Subject: Re: another net.question Message-ID: <2496@enea.UUCP> Date: 5 Dec 87 16:46:48 GMT References: <251@ho7cad.ATT.COM> Reply-To: sommar@enea.UUCP(Erland Sommarskog) Followup-To: rec.music.misc Organization: ENEA DATA Svenska AB, Sweden Lines: 27 P.CLARK (prc@ho7cad.ATT.COM) writes: > Should a band play the entire new album when they do a concert? No, why should they? There may be songs on the album that are very good listening to at home, but just doesn't make it live, just as there are songs with the opposite character; good live, but just a bore on disc. Deep Purple and Marillion and good example of extremes in both ends. When I saw D.P. in February this year, they played three of the ten songs from "The House of Blue Light", their latest album. That is a quite decent product, but I didn't miss those songs anyway. (I, and everyone else, would have been much more disappointed if they had left out "Smoke on the Water".) Marillion on the other hand; on the two tours they made after "Misplaced Childhood", they insisted on playing entire album as one long song. There are many parts on that album that just becomes dead passages where nothing happens when they are played live. ("Bitter Suite" and "Blind Curve" for instance.) Marillion is no good live band, and playing obsolete material does not make things better. -- Erland Sommarskog ENEA Data, Stockholm sommar@enea.UUCP C, it's a 3rd class language, you can tell by the name. #! rnews 4410 Path: alberta!mnetor!uunet!mcvax!enea!sommar From: sommar@enea.UUCP (Erland Sommarskog) Newsgroups: rec.music.misc Subject: Re: More than Yes Message-ID: <2502@enea.UUCP> Date: 5 Dec 87 19:18:59 GMT References: <22034@ucbvax.BERKELEY.EDU> Reply-To: sommar@enea.UUCP(Erland Sommarskog) Followup-To: rec.music.misc Organization: ENEA DATA Svenska AB, Sweden Lines: 72 Grady Toss (ebm@ernie.Berkeley.EDU) writes: >Whenever this newsgroup gets around to discussing 70's/80's fusion (the >current go-round sparked by the proof that Yes is Best), the content >seems to be limited to the same 5 or 6 groups (Yes, Rush, ELP, King >Crimson, Pink Floyd, Genesis, etc.). Grady seems to be confusing the issue a bit here. He talks about fusion and the mentions groups that belong(ed) to the symphonic-rock genre. (I prefer that term instead of "progressive") For me "fusion" is a synonym with jazz-rock. Anyway, that is more of question of semantics, the two genres have a lot in common. (The main difference maybe being that symphony-rock is European and fusion American.) The reason why these groups are being discussed the most is probably that they have gained the greatest commercial succes. This may or may not be correlated to the fact they are the best. >Doesn't (didn't) anyone listen to >some of the (apparently) lesser-known fusion greats? Bands and artists >like Arti + Mestieri, Brand X, Arthur Brown & Kingdom Come, Egg, Gilgamesh, >Hatfield & The North, Henry Cow, Alain Markusfeld, National Health, PFM, >Quiet Sun, Return to Forever, Seventh Wave, The Soft Machine, UK and >Weather Report. Being quite fond of this kind of music, I feel obliged to comment. It's a real mixture Grady presents and I must admit there are names I have never heard. Anyway, I think he is a bit unfair, some of them have certainly been discussed on the net. For instance, I posted a discograhpy on Brand X some month ago. Some comments to the other names: PFM (Premiata Forneria Marconi) have been mentioned from time to time, the Italian answer on Genesis, which developed in a different way. Now disbanded, I believe. One day or another may be I'll post a discography. Quiet Sun. The band in which Phil Manzanera played before he joined Roxy Music. Their "Mainstream" is rather like jazz, but not mainstream. Seventh Wave. This is the name I never expected to see on the net! I bought their "Things to Come" when I was 15 and I was really fond of it then. These days I don't find that amount of synthesizers so exciting as I did then. Wheather Report. Quite well-known. But really, you do only need "Heavy Wheather", the one with "Birdland". May be some more, "Mysterious Traveller" perhaps, but then you'll find that they all sound the same. >As I said before, I find much of Yes and ELP to be very dull, and un- >affecting. I like Rush, though more live than on record. As you can guess, I don't share Grady's view here. Yes has made good music, yet never really touched my soul, probably due to their utterly stupid and semi-religious lyrics. "Brain Salad Surgery" is a very good record, the rest of what ELP have done is so-so. Rush don't turn me on at all, on the other hand. The net discussion inspired me to try "A Farewell to Kings" (A random choice). May be I would have liked them 10 years ago, but not today with those lyrics and that voice. >So, were Yes, ELP, Pink Floyd, King Crimson, Genesis and Rush really "it" >as far as most progrock fans go, or did some of these "lesser known" artists >(and all the others I forgot or never knew) filter out to larger audiences? Depends on how you define your terms here, but I can easily think of more groups, some of them succesful, some of them not, some of them good, some them not so good: Kansas, Saga, Asia, Jethro Tull, Roxy Music, Gentle Giant, Van Der Graaf Generator, George Duke, Billy Cobham, Al DiMeola, Herbie Hancock, Dixie Dregs, Ange, (Mahavishnu) John McLaughlin, Santana, Bill Bruford etc I think that most of these people have had their share of the discussion on the net. So to conclude, I do not really share Grady's initial obser- vation. However some particular groups are certainly being over-discussed, namely Rush, Yes and recently also Pink Floyd. -- Erland Sommarskog ENEA Data, Stockholm sommar@enea.UUCP C, it's a 3rd class language, you can tell by the name. #! rnews 916 Path: alberta!mnetor!uunet!mcvax!enea!tut!santra!clinet!waldo From: waldo@clinet.FI (Tuomas Siltala) Newsgroups: rec.music.synth Subject: Siel DK80 sequenceer Keywords: How to use? Message-ID: <553@clinet.FI> Date: 5 Dec 87 21:36:23 GMT Reply-To: waldo@clinet.UUCP (Tuomas Siltala) Organization: City Lines Oy, Helsinki, Finland Lines: 17 My friend bought a Siel DK80 synthesizer and now he is wondering how the sequencer in that machine works. Unfortunately we don't have any manuals for it. Could somebody kindly send me information concerning this problem? Thank you! ------------------------------------------------------------------------------ Tuomas Siltala Internet: waldo@clinet.FI Kalevankatu 51 B 37 SF-00180 Helsinki, Finland Telephone: +358-0-6947735 ------------------------------------------------------------------------------ #! rnews 1655 Path: alberta!mnetor!uunet!mcvax!enea!luth!d2c-czl From: d2c-czl@sm.luth.se (Caj Zell) Newsgroups: rec.music.misc Subject: Re: Black Sabbath songs Message-ID: <437@psi.luth.se> Date: 6 Dec 87 01:38:40 GMT References: <1208@gumby.wisc.edu> <3590@h.cc.purdue.edu> Reply-To: Caj Zell Organization: University of Lulea, Sweden Lines: 25 UUCP-Path: {uunet,mcvax}!enea!psi.luth.se!d2c-czl In article <3590@h.cc.purdue.edu> acu@h.cc.purdue.edu.UUCP (Floyd McWilliams) writes: > While we're talking about Sabbath, does anyone know who does the >vocals on "Solitute" (from the Master of Reality album) and "It's All Right" >(from Technical Ecstasy)? It sure doesn't sound like the Oz... I would like to add another song:"Swinging The Chain" on _Never Say Die!_. Who the hell does the vocals here? By the way,has anybody heard the new album? XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X X X X X Caj Zell ________________________ X X University of Lulea : : X X Sweden : Jazz is not dead, : X X : it just smells funny : X X mail: d2c-czl@psi.luth.se : -Frank Zappa : X X : : X X -----------------------: X X X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #! rnews 760 Path: alberta!mnetor!uunet!mcvax!unido!gmdka!florin From: florin@gmdka.UUCP Newsgroups: comp.windows.x Subject: C++ re-hacks of X11 include files - (nf) Message-ID: <2800001@gmdka.UUCP> Date: 3 Dec 87 13:16:00 GMT Lines: 14 Nf-ID: #N:gmdka:2800001:000:458 Nf-From: gmdka!florin Dec 3 14:16:00 1987 Hi there, I'm actually working on C++ re-hacks of the X11 include files. There are some problems with Xlib.h. In structures Visual, XWindowAttributes and XColormapEvent there are variables named ``class'' and ``new'' which cause serious problems (C++ keywords) ! For the moment I've changed the names, but this is an awful hack. Does anybody know a better solution ? -- Florin UUCP: ...!uunet!unido!gmdka!florin X.400: florin@karlsruhe.gmd.dbp.de #! rnews 4069 Path: alberta!mnetor!uunet!mcvax!ukc!reading!onion!riddle!domo From: domo@riddle.UUCP (Dominic Dunlop) Newsgroups: comp.unix.xenix,comp.sys.att,comp.sys.intel Subject: How to load AT&T 6300 Plus packages to generic UNIX V.3 Summary: Here's a shell script to do it for you Keywords: Intel, 386/ix, Microport, Prime Message-ID: <522@riddle.UUCP> Date: 4 Dec 87 17:47:52 GMT Reply-To: domo@riddle.UUCP (Dominic Dunlop) Followup-To: comp.unix.xenix Organization: Sphinx Ltd., Maidenhead, England Lines: 106 Xref: alberta comp.unix.xenix:1170 comp.sys.att:1825 comp.sys.intel:379 [If there's a Microport newsgroup, it doesn't come here] Background AT&T's generic UNIX V.3 for the 80386 (as sold in binary form by AT&T, Bell Technologies, Intel, Interactive Systems, Microport, Prime etc.) will run binaries created for UNIX V.2 on the 80286. A large number of packages exists for AT&T's 6300 Plus, an 80286-based system running V.2. These can be run on 80386-based systems while you're waiting for software authors to come up with native 80386 ports of their products. Problem You are supposed to load packages onto your 6300 Plus using the system's administration procedures. These handle weird multi-volume cpio diskette sets, which are a pig to load unless you have the installation software. Which you don't if you're trying to load the software onto an 80386-based system running 386/ix, Microport, or whatever. Solution Here's a shell script which does the job. If you want to know the details, it reads 350k, starting at offset 9k, from each 360k diskette in the installation set, piping the result into cpio -c. It the fires off the Install program which should be part of the application package. As the comments remark, there's not a lot of error checking, as it's essentially a quick hack. Also, testing is about at the ``worked twice in a row'' level. Despite all that, I hope it's useful to somebody out there. Dominic Dunlop domo@sphinx.co.uk domo@riddle.uucp ++++cut here++++++++cut here++++++++cut here++++++++cut here++++ : # load_script # # Shell script to load software packages delivered in AT&T PC # 6300+ UNIX V.2 format on systems where the PC 6300+ # installation procedure is not available (eg 386/ix). # The script can be executed by any user who can read the raw # diskette device. However, the root password is requested # before files are moved to their final destinations if this # script is not run by the super-user. # # Note that this script does NOT check that sufficient space is # available to load the package. In general, your /usr file # system should have at least (700 * diskettes_in_package) # blocks free before installation. Note also that there is no # check that the diskettes are in the correct format, or that # they are inserted in the correct order. # # 871204 DFD Created # Change the following device assignment if the 360kB raw # diskette device on your system has a different name. DEV=${DEV-/dev/rdsk/f0d9dt} if [ ! -r $DEV -o ! -c $DEV ] then cat << E_O_F Can't read $DEV. Check raw diskette device name and/or your access permissions. E_O_F exit 1 fi cd /usr/tmp mkdir install 2>/dev/null cd install IT="the first diskette of the package" trap "echo Installation aborted.; rm -r /usr/tmp/install; exit 1" 2 15 ( while echo "Insert $IT and hit return >\c" 1>&2 \ && read ANS do IT="next diskette" echo "The following files are being loaded:" 1>&2 dd if=$DEV ibs=1k obs=5k skip=9 count=350 2>/dev/null done ) | cpio -icvmudB 1>&2 chmod +x Install trap 2 15 cat << E_O_F Files read from diskettes. You may remove the last diskette from the drive. If you are not already logged in as the super-user, Please enter the root password to continue with installation. E_O_F if su root -c ./Install then cat << E_O_F Installation complete. You should execute rm -r /usr/tmp/install to remove installation scratch files at a convenient time. E_O_F else cat << E_O_F Installation failed. To retry, su cd /usr/tmp/install ./Install E_O_F fi #! rnews 1801 Path: alberta!mnetor!uunet!mcvax!ukc!reading!onion!bru-me!ralph From: ralph@me.brunel.ac.uk (Ralph Mitchell) Newsgroups: comp.graphics,sci.space,sci.space.shuttle Subject: Re: 3d digitized shuttle data Message-ID: <338@Pluto.me.brunel.ac.uk> Date: 4 Dec 87 09:49:43 GMT References: <509@otto.cvedc.UUCP> Reply-To: ralph@me.brunel.ac.uk (Ralph Mitchell) Organization: Brunel University, Uxbridge, UK Lines: 26 Xref: alberta comp.graphics:1381 sci.space:3674 sci.space.shuttle:445 In article <509@otto.cvedc.UUCP> billa@otto.UUCP (Bill Anderson) writes: >In article <> apollo@ecf.toronto.edu (Vince Pugliese) writes: >> >>As well I will be include a very simple C program, hacked together by fellow group member >> [...] > >If anyone out there in netland converts this C program so that it can be >run on suns, please post the results of your work to the net. It has already been done. The program should be in /usr/demo/SRC/shaded.c, the shuttle data is in /usr/demo/DATA/space.dat. There are notes on running it in /usr/demo/README. The program displays 2 windows with cursor lines, to enable you to select the 3d viewpoint, and there's a pop-up menu for setting fill style and colour, &c. For monochrome you need to select the "edges" (I think) fill style or it'll look pretty wierd. Also, if your display surface doesn't support hidden surface removal, you'll get a wireframe effect that can be confusing to the eye. /usr/demo/DATA also contains data files for an icosahedron, a pyramid, a ball and a Klein bottle. -- From: Ralph Mitchell at Brunel University, Uxbridge, UB8, 3PH, UK JANET: ralph@uk.ac.brunel.cc ARPA: ralph%cc.brunel.ac.uk@cwi.nl UUCP: ...ukc!cc.brunel!ralph PHONE: +44 895 74000 x2561 "There's so many different worlds, so many different Suns" -- Dire Straits #! rnews 1156 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!bob From: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Newsgroups: rec.arts.sf-lovers Subject: Re: SPACE WAR BLUES (was Re: Gibson) Message-ID: <809@its63b.ed.ac.uk> Date: 4 Dec 87 12:49:58 GMT References: <8711211710.AA02986@decwrl.dec.com> Reply-To: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 17 In article <8711211710.AA02986@decwrl.dec.com> boyajian@akov68.dec.com (JERRY BOYAJIAN) writes: >(Oh, before anyone asks the obvious question, the author was Richard >Lupoff, who is one of the best unknown science fiction writers around.) I find this statement hard to believe, based on the quality of his book "Circumpolar". It is full of characters which barely qualify as two dimensional, offensive racial stereotypes and various other assorted characters whose collective IQ doesn't get into double figures. I rated this book as -****. I cannot believe that someone who turned out such complete drivel could improve enough in other books to even qualify as average. I am however, willing to be surprised. What other books of his would people recommend? Bob. #! rnews 1599 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!bob From: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Newsgroups: sci.misc Subject: Re: Grey Goo that's too smart for its own good Keywords: nanotechnology foresight drexler Message-ID: <810@its63b.ed.ac.uk> Date: 4 Dec 87 13:10:07 GMT References: <799@sbcs.sunysb.edu> <2698@drivax.UUCP> <1063@sugar.UUCP> <2411@watcgl.waterloo.edu> <1445@m-net.UUCP> <1526@mmm.UUCP> <2783@drivax.UUCP> Reply-To: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 23 In article <2783@drivax.UUCP> macleod@drivax.UUCP (MacLeod) writes: >In article <1526@mmm.UUCP> cipher@mmm.UUCP (Andre Guirard) writes: >>In article <1445@m-net.UUCP> russ@m-net.UUCP (Russ Cage) writes: >>>In <2411@watcgl.waterloo.edu> kdmoen@watcgl.waterloo.edu (Doug Moen) writes: >>>>[...] If it *does* turn out to be possible to build Grey Goo, >>>>then by the time fabrication technology catches up, perhaps we can have >>>>a wide spectrum of Goo killing techniques already available. > >Goo seems almost inevitable. It should not be a big problem, of itself; >the definition of Goo (for those not familiar with the problem) is that >of a nanomachine that will use any available energy and raw material to >reproduce itself periodically. If it reproduces at 2x per year you have >one problem, relatively minor; if it reproduces at 512x per minute, you have >quite another. I can hear the squeals from the anti-nuclear type lobby already Can you PROVE it is safe? Campaign against the Grey Goo! prevent Nano-technology! and not a :-> in sight. Bob. #! rnews 3115 Path: alberta!mnetor!uunet!mcvax!ukc!cheviot!robert From: robert@cheviot.newcastle.ac.uk (Robert Stroud) Newsgroups: comp.unix.wizards Subject: Re: //host vs "mount point" Message-ID: <2584@cheviot.newcastle.ac.uk> Date: 4 Dec 87 16:22:51 GMT References: <648@tut.cis.ohio-state.edu> <1668@tut.cis.ohio-state.edu> <38c15248.4580@hi-csc.UUCP> <9559@mimsy.UUCP> <411@PT.CS.CMU.EDU> <6769@brl-smoke.ARPA> Reply-To: robert@cheviot (Robert Stroud) Organization: Computing Laboratory, U of Newcastle upon Tyne, UK NE17RU Lines: 62 In article <6769@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) ) writes: >In article <411@PT.CS.CMU.EDU> jgm@K.GP.CS.CMU.EDU (John Myers) writes: >>Just to add to the confusion, let me put in a plug in for the Carnegie-Mellon >>University Computer Science Department's syntax: >>/../host > >Stolen from the Newcastle Connection. > >>"/.." is known as the "super-root". It seems logically consistent to me... > >So, what is the result of > $ cd /.. > $ pwd /.. of course!! If you add directories above root (and remember that with the Newcastle Connection, /.. was just a directory rather than some mysterious "super-root") so that it is possible for your current directory to be in an uncle or cousin relationship with root (rather than a direct descendent), then you have to modify the pwd algorithm accordingly. pwd assumes that if you go up the tree with ".." enough times you will get to root. If your current directory is in a sideways relationship to root, this assumption will no longer be valid. The modified pwd algorithm should work like this: (1) Go up the tree with .. from your current directory until you find / or reach the base of the tree (a directory which is its own parent). (2) If you didn't reach / in (1), then starting from / go up to the base of the tree with .. and prefix the appropriate number of /..'s to the string from (1). For example, after cd /../../C/D, step (1) will give /C/D and step (2) will give /../.. so the answer is /../../C/D. This is relatively straightforward to implement. I've made the necessary modifications to the System V /bin/pwd and sh (which has a built-in pwd) for use with a kernel implementation of the Newcastle Connection. The tricky bit is getting the shortest possible pathname. For example, if / corresponds to /../../A/B in the global naming tree, then after cd /../C, the modified pwd algorithm would give /../../A/C which is correct but redundant. (/../../A is the same as /.. if / is /../../A/B). This can be fixed if you keep a record of everywhere you visit in (1) and stop in (2) when you reach somewhere you've visited before, but since in an infinite naming tree this would require an infinite amount of storage and isn't very efficient in any case, it is easier to simply implement the algorithm given (which also requires an infinite amount of storage in the general case of course!) and ignore this problem. Robert J Stroud, Computing Laboratory, University of Newcastle upon Tyne. ARPA robert%cheviot.newcastle@nss.cs.ucl.ac.uk UUCP ...!ukc!cheviot!robert JANET robert@newcastle.cheviot #! rnews 835 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!nott-cs!pyr1.cs.ucl.ac.uk!awylie From: awylie@pyr1.cs.ucl.ac.uk Newsgroups: comp.sys.ibm.pc Subject: Re: Standard date bug Message-ID: <39500002@pyr1.cs.ucl.ac.uk> Date: 4 Dec 87 13:58:00 GMT References: <7457@eddie.MIT.EDU> Lines: 12 Nf-ID: #R:eddie.MIT.EDU:7457:pyr1.cs.ucl.ac.uk:39500002:000:432 Nf-From: pyr1.cs.ucl.ac.uk!awylie Dec 4 13:58:00 1987 I have a Taiwanese XT clone with some strange BIOS and MSDOS 3.2 and the bug has annoyed me some time. This is NOT the 'subtle' bug mentioned in another reply, but a simple non-increment of the date at midnight. This wreaks havoc with MAKE! I shall try CLOCKFIX.SYS tonight. Thanks very much to the poster, his was the only really useful solution proposed. Andrew Wylie University of London Computer Centre awylie@uk.ac.ucl.cs #! rnews 847 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!bath63!sc_dra From: sc_dra@ux63.bath.ac.uk (Dave Allum) Newsgroups: comp.sys.atari.st Subject: Hard Disk Optimisers Summary: Recommendations wanted Message-ID: <1972@bath63.ux63.bath.ac.uk> Date: 4 Dec 87 15:53:49 GMT Reply-To: sc_dra@ux63.bath.ac.uk (Dave Allum) Organization: SWURCC, University of Bath, U.K. Lines: 13 Does anyone have any recommendations for and/or experience of hard disk optimisers for the ST? The only ones I have come across are Simon Poole's DLII and Michtron's Tune Up! (their exclamation mark, not mine). I have tried neither (DLII did some strange things with a ram disk I tested it on, and I'd rather not pay for Tune Up! until I have some favorable reports on it) and would be very interested in anyone's experiences with the above or any other such beasts. Thanks. #! rnews 1573 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!bob From: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Newsgroups: sci.physics Subject: Re: GR question Message-ID: <811@its63b.ed.ac.uk> Date: 4 Dec 87 17:31:49 GMT References: <4688@cit-vax.Caltech.Edu> <895@ubc-vision.UUCP> Reply-To: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 28 In article <895@ubc-vision.UUCP> majka@ubc-vision.UUCP (Marc Majka) writes: >would see the "poor fellow's" delta-t getting longer. The poor fellow >crosses the Absolute Event Horizon in a finite amount of (his) time. >The observer sees the poor fellow falling more and more slowly (while >also seeing him getting exponentially red-shifted) toward r=2M, but >never getting there. I liked the presentation of this in my GR textbook: The observer, if he waited around long enough, would also see the black hole evaporate by Hawkins' radiation. But, from the point of view of the observer, the "poor fellow" can never cross the event horizon before the hole evaporates away from under him. Therefore, the "poor fellow" must observe one of two things. Either he crosses the event horizon in a finite amount of time, or he will observe the black hole to vanish as he approaches. 1. sets up a paradox, but 2. implies that anything falling into a black hole can't get into the black hole before it evaporates. i.e. the black hole can't form in the first place. It just get very close to it. Would someone please comment on the above. I am sure I must be missing something. (I'm no physicist) Bob. #! rnews 2122 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!zen!frank From: frank@zen.UUCP (Frank Wales) Newsgroups: news.config Subject: Updated map entry for zen Keywords: new host computer Message-ID: <787@zen.UUCP> Date: 3 Dec 87 22:20:52 GMT Organization: Zengrange Limited, Leeds, England Lines: 47 It's a bit late again, we've been running the new system for about 3 months now, but here is our updated map entry: #N zen #S HP 9000 Model 840; HP-UX 1.1 (V.2) #O Zengrange Limited #C Julian Perry, Frank Wales #E jules@zen.co.uk ...!mcvax!ukc!zen.co.uk!jules #T +44 532 489048 #P Greenfield Road, Leeds, West Yorkshire, England, LS9 8DB #L 01 31 22 W / 53 47 42 N #R # zen hwcs(DAILY) Who we are and what we do: As a company, we produce custom solutions on hand-held and portable equipment, primarily customising Hewlett-Packard hand-helds. For example, we recently installed almost 6 000 HP-71 hand-held computers as networked terminals in 430 DHSS offices as part of a Document Tracking System developed by us to a DHSS specification. We're not just a software house, but also develop custom packaging and electronics where necessary too. Our customers are primarily government departments (here and abroad), but we have also produced products for individual sale through dealers (such as the Zenwand-71 barcode wand for the HP-71, which span off of the DHSS contract). Although our products are almost exclusively related to hand-helds, our expertise stretches through to custom chip design and mainframe-hosted software packages (mainly under Unix). As a consequence, we regard ourselves as a solutions house, rather than being specific to software, hardware, design or whatever. We have one office [in Leeds], have been around for seven years and employ over 40 people at present. Is that a reasonable summary? Jules & Frank Julian Perry [ jules@zen.co.uk ...!mcvax!ukc!zen.co.uk!jules ] Frank Wales [ frank@zen.co.uk ...!mcvax!ukc!zen.co.uk!frank ] System Managers Zengrange Limited Phone: +44 532 489048 ext 217 Leeds, England. #! rnews 1158 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: rec.music.classical Subject: Re: re repeat repeating pieces Message-ID: <1567@brahma.cs.hw.ac.uk> Date: 4 Dec 87 18:18:28 GMT References: <8712011820.AA18589@decwrl.dec.com> Reply-To: jack@cs.glasgow.ac.uk (Jack Campin) Organization: PISA Project, Glesga Yoonie Lines: 13 Summary: Expires: Sender: Followup-To: [ignore the above email address and use my signature] I may have missed some of this thread, but I haven't heard anyone mention Satie yet. His Vexations for piano is meant to be repeated 840 times (it takes about 18 hours to perform). He also wrote some pieces of music to be played in particular spaces - "Music for a Boardroom" is one that comes to mind - which go round and round in circles. (I think that one would produce some #@$% aggressive board meetings). -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 1124 Path: alberta!mnetor!uunet!mcvax!ukc!stl!dww From: dww@stl.stc.co.uk (David Wright) Newsgroups: comp.os.vms Subject: Problem with VMS 4.6 if your uVAX has EMULEX CS02's Message-ID: <596@acer.stl.stc.co.uk> Date: 4 Dec 87 21:54:38 GMT Reply-To: dww@stl.UUCP (David Wright) Organization: STL,Harlow,UK. Lines: 16 Our System Manager has reported that there is a problem with using EMULEX CS02 QBUS comms cards which are not at the latest revision level, under VMS 4.6. These cards appeared to work fine under VMS 4.5 and earlier. The EMULEX CS02 card, configured as two DHV-11 8-line muxs, gives phantom devices when running SHOW DEVICE. For example, TXC0 to TXC7 become TXC0 to TXC15. There are problems in using the lines - for example Control-Y acts on the group of lines not just one! There are other problems known to EMULEX. The solution is to upgrade the firmware PROM on the card to at least revision P. Emulex may make a charge for this. -- Regards, David Wright STL, London Road, Harlow, Essex CM17 9NA, UK dww@stl.stc.co.uk ...uunet!mcvax!ukc!stl!dww PSI%234237100122::DWW #! rnews 384 Path: alberta!mnetor!uunet!mcvax!ukc!stc!root44!jgh From: jgh@root.co.uk (Jeremy G Harris) Newsgroups: comp.sys.amiga Subject: New Kickstart Keywords: Kickstart workbench janus Message-ID: <489@root44.co.uk> Date: 4 Dec 87 19:05:27 GMT Organization: Root Computers Ltd., London, England Lines: 3 Will the Workbench-less Kickstart initialise Janus? -- Jeremy Harris jgh@root.co.uk #! rnews 1018 Path: alberta!mnetor!uunet!mcvax!unido!stollco!til From: til@stollco.UUCP (tilgner) Newsgroups: sci.astro Subject: The current state of Hubble Constant? Keywords: Cosmology Message-ID: <142@stollco.UUCP> Date: 5 Dec 87 18:32:42 GMT Organization: Stollmann Gmbh, D 2000 Hamburg 50 Lines: 17 I am just preparing a 'semi-popular' lecture on how the value of the Hubble Constant is determined. As is generally known, the values of different authors fluctuates between ca. 50 to 100 km/(sec Mpc). The latest discussion of this problem which I know of is M. Rowan-Robinson's book "The Cosmological Distance Ladder" (Freeman 1985). He advocates 67 km/(sec Mpc) after a detailed discussion of the different distance indicators. Now I would like to know: What is the current state of affairs? The responses of the advocates of the various values, for example by Sandage & Tammann or de Vaucouleurs (= the grand old men of this topic)? Somehow I missed their reactions. Can anybody give me a hint via e-mail? I'll summarize. #! rnews 2734 Path: alberta!mnetor!uunet!mcvax!enea!ttds!draken!zap From: zap@draken.nada.kth.se (Svante Lindahl) Newsgroups: comp.unix.wizards,comp.emacs Subject: Re: Emacs csh alias Message-ID: <235@draken.nada.kth.se> Date: 6 Dec 87 07:00:31 GMT References: <10672@brl-adm.ARPA> Reply-To: zap@nada.kth.se (Svante Lindahl) Followup-To: comp.emacs Organization: The Royal Inst. of Techn., Stockholm Lines: 49 Xref: alberta comp.unix.wizards:5741 comp.emacs:2402 [Warning: Extensive inclusion, but I have included a new newsgroup in the newsgroups-line, and directed followups to it (comp.emacs)] In article <10672@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes: >I've been trying to set up a C-Shell (4.2 BSD) alias for Emacs (GNU >17.64, not that it matters) which, when run the first time will >actually run Emacs, but after suspending Emacs with C-z, will bring >the background Emacs job to the foreground. The catch is that I'd >also like the alias to re-load emacs if I exit with C-x C-c. Simply >stated, I want an alias named "emacs" which will load Emacs if it >isn't already loaded, but will foreground a background Emacs if one >exists. > >I know I could do this with a script (if I assume the Emacs job is >always job %1), but I'd prefer an alias since they're faster. It >would be especially nice to determine which background job was the >Emacs job and foreground *it*, instead of just assuming job %1. > >Any ideas or alternate approaches? Should I just put up with the >occasional "fg: No such job." message? Here is something which should do part of what you want. It doesn't accomplish to start a new emacs process if you exited the last one with C-x C-c - unless the first one had never been suspended! Whenever you get "fg: No such job" just type ``i!!'', reinvoking the commandline prefixed with an "i", "iemacs" standing for "init emacs". alias emacs iemacs alias iemacs 'alias emacs remacs; "emacs" \!* ; alias emacs iemacs' alias remacs fg %emacs Here we use a special version of suspend-emacs, that will look for a file ".emacs_pause" in the user's home directory when emacs is resumed. In this file suspend-emacs expects to find the current working directory and an optional "command line" that is parsed like the initial command line. Very useful! This could be done using "suspend-resume-hook", but the hook wasn't available in 17.?? when this was first implemented here. These are the aliases I use together with the special version of suspend-emacs. alias emacs iemacs alias remacs 'echo `pwd` \!* >\! ~/.emacs_pause ; %emacs' alias iemacs 'alias emacs remacs; "emacs" \!* ; alias emacs iemacs' alias kemacs 'alias emacs iemacs; remacs -kill' Svante Lindahl zap@nada.kth.se uunet!nada.kth.se!zap #! rnews 2721 Path: alberta!mnetor!uunet!mcvax!diku!iesd!jpc From: jpc@iesd.uucp (Jens P. Christensen) Newsgroups: comp.unix.questions,comp.unix.wizards,sci.math.stat Subject: Problems with S statistical package Summary: Cannot make S work properly on Sun-3 Keywords: S AT&T Sun-3 SunOS 3.4 Message-ID: <162@iesd.uucp> Date: 5 Dec 87 19:41:09 GMT Reply-To: jpc@iesd.UUCP (Jens P. Christensen) Followup-To: comp.unix.questions Organization: Dept. of Comp. Sci., Aalborg University, Denmark Lines: 58 Xref: alberta comp.unix.questions:4768 comp.unix.wizards:5742 sci.math.stat:213 Could anyone please shed light on a problem I have in compiling the S statistical package from AT&T on our Sun-3 system: System specifics: Sun 3/260 under SunOS 3.4 using the m4 macro processor supplied with the S system. S version date: Fri Feb 28 1986 Using the hints on compiling with BSD4.2 systems I only get apparently harmless warnings under the compilation. This could for example be: Warning on line 84 of hcp.f: local variable i never used Warning on line 96 of stems.f: statement cannot be reached f77: Warning: File with unknown suffix (/usr/local/src/s/S/newfun/lib/grz) passed to ld or "dprint.c", line 20: warning: illegal combination of pointer and integer, op = Furthermore there are problems with the utility routine scandata.C, which fails with error: too many local variables. This is fixed by making the declaration of "table" global. Not pretty, but it works. These are all the kinds of problems that appear during the compilation, and it *will* result in an executable, except.... The f...ing system doesn't even know how to add two numbers, as seen in the following: One-time initialization for new S user in /usr.MC68020/iesd/tap/jpc ... Directories swork and sdata created > 1 + 2 Bad operator: + Error in + > Running the tests supplied with the system ($A/DOTEST ALL) will not give better results. This is an excerpt from $TEST/current/apply: > prefix("apply.") # test of apply and multivariate stuff, some time-series > $Random.seed_c(57,0,3,0,0,0,49,16,0,0,0,0) # to initialize at same spot > matr_matrix(rnorm(100),20,5) Invalid distribution: rnorm Error in rnorm Dumped > print(cm_apply(matr,2,"mean")); apply(matr,2,"var") apply.matr not found Dumped . . and more depressing errors... Why does the prefix command work, while the matr_matrix(rnorm... stuff don't? So, have *anybody* made this run on a Sun system, and how did you do it? All suggestions or pointers to which direction I should go, are welcome. regards, -- Jens Peter Christensen jpc@iesd.uucp Department of Math. and Computer Science {...}!mcvax!diku!iesd!jpc Aalborg University Centre Denmark #! rnews 1496 Path: alberta!mnetor!uunet!mcvax!lambert From: lambert@cwi.nl (Lambert Meertens) Newsgroups: sci.math.symbolic Subject: Bug in Macsyma SOLVE Message-ID: <137@piring.cwi.nl> Date: 6 Dec 87 21:50:53 GMT Organization: CWI, Amsterdam Lines: 39 This is UNIX MACSYMA Release 309.2. (c1) x^12-12*x^11+48*x^10-40*x^9-193*x^8+392*x^7+44*x^6+8*x^5-977*x^4 -604*x^3+2108*x^2+4913; 12 11 10 9 8 7 6 5 4 (d1) x - 12 x + 48 x - 40 x - 193 x + 392 x + 44 x + 8 x - 977 x 3 2 - 604 x + 2108 x + 4913 (c2) solve(%); 6 5 4 3 2 (d2) [0 = - x + 12 x - 47 x + 188 x - 527 x - 4913] That looks wrong, but let's check if it factors (d1): (c3) part(%,1,2); 6 5 4 3 2 (d3) - x + 12 x - 47 x + 188 x - 527 x - 4913 (c4) gcd(%,d1); (d4) 1 No, it does not. Let's have a look at the real roots of (d1) and (d3): (c5) realroots(d1)$ %,numer; (d6) [x = - 1.960768669843674, x = - 1.544090360403061, x = 3.544090360403061, x = 3.960768669843674] (c7) realroots(d3)$ %,numer; (d8) [x = 5.472395747900009, x = 7.766151040792465] Way off. -- Lambert Meertens, CWI, Amsterdam; lambert@cwi.nl #! rnews 989 Path: alberta!mnetor!uunet!mcvax!unido!tub!actisb!bernd From: bernd@actisb.UUCP (Gunter Nitzler) Newsgroups: comp.sources.bugs Subject: Re: Starchart printing problem Message-ID: <116@actisb.UUCP> Date: 6 Dec 87 15:55:23 GMT References: <3554@ames.arpa> Reply-To: bernd@actisb.UUCP (Bernd-Gunter Nitzler) Organization: Actis in Berlin GmbH, W. Germany Lines: 19 In article <3554@ames.arpa> yee@ames.UUCP (Peter E. Yee) writes: >I compiled and ran the starchart program. The starpost version prints out >the outline of the chart and the legend. Nothing more. No stars, no planets, >no nebulas. Nothing. Is it just me, or has anyone else had this problem? I had the same problem and have found two bugs: In starchart.c, line 243 old: char ras[2], .... new: char ras[20], ... In starchart.c, line 757 old: sscanf(cbuf, "%*5s%f%f%f %[^\n]", &ra, &de, &sc, legend); new: sscanf(cbuf, "%*5s%lf%lf%lf %[^\n]", &ra, &de, &sc, legend); This two changes fixes the bugs. Bernd. #! rnews 2244 Path: alberta!mnetor!uunet!mcvax!enea!tut!santra!jmunkki From: jmunkki@santra.UUCP (Juri Munkki) Newsgroups: comp.sys.mac Subject: Color CopyBits Is Too Slow! Keywords: Mac II Color QuickDraw Animation Speed Optimization Message-ID: <9130@santra.UUCP> Date: 6 Dec 87 21:13:10 GMT Organization: Helsinki University of Technology, Finland Lines: 76 I experimented with offscreen pixmaps today. It seems that Color Quickdraw is very flexible, but too slow for good animation. Most of the overhead comes from color matching and conversion. I guess I could write my own color matching routine, but I think there should be a fast way to do a simple copy operation. In most painting programs the actual painting could be done on an offscreen bitmap with the same color table as the best gDevice. It takes about twice as much time to do a copybits in srcCopy mode than it takes in the srcXor mode. Below is a short program that draws to an offscreen pixmap and then copies it back to the screen. Try different transfer modes and note the speed difference. The code is written in LS C 2.13. Even srcXor, which is the fastest usable mode, is too slow for really high quality animation. How can it be done faster? #include #include #include #include WindowPtr onScreen; CGrafPtr offS; RGBColor temp; PixMapPtr offP; void main() { int i; InitGraf(&thePort); InitCursor(); InitFonts(); InitWindows(); onScreen=GetNewWindow(1000,0L,-1); offS=(CGrafPtr)NewPtr(sizeof(*offS)); OpenCPort(offS); HLock(offS->portPixMap); offP=*(offS->portPixMap); SetRect(&offP->bounds,0,0,256,256); PortSize(256,256); offP->rowBytes=32768L+256; offP->baseAddr=NewPtr(65536L); EraseRect(&offS->portRect); temp.blue=65535; temp.red=0; temp.green=0; RGBForeColor(&temp); for(i=0;i<256;i+=4) { MoveTo(i,0); LineTo(255-i,255); } SysBeep(10); HideCursor(); for(i=100;i;i--) CopyBits(&((GrafPtr)offS)->portBits,&onScreen->portBits, &offS->portRect,&offS->portRect,srcXor,0); SysBeep(10); while(!Button()); } Juri Munkki jmunkki@santra.hut.fi jmunkki@fingate.bitnet lk-jmu@finhut.bitnet P.S. The window is longword aligned and a color table was copied from the system file. #! rnews 617 Path: alberta!mnetor!uunet!mcvax!enea!chalmers!benke From: benke@chalmers.UUCP (Bengt-Eric Ericson) Newsgroups: comp.sys.ibm.pc Subject: Re: WARNING! FASTBACK may corrupt your hard disk! Message-ID: <2239@chalmers.UUCP> Date: 6 Dec 87 21:16:48 GMT References: <703@vaxine.UUCP> <3225@bnrmtv.UUCP> <7024@sunybcs.UUCP> Reply-To: benke@chalmers.UUCP (Bengt-Eric Ericson) Organization: Dept. of CS, Chalmers, Sweden Lines: 3 Keywords:Computer Shopper In some article in this group there is said something about "Computer Shopper". Is this a magazine or what? Please enlight us guys here in the land of Polar bears. :-) #! rnews 2432 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!kjws From: kjws@eagle.ukc.ac.uk (K.J.W.Smithers) Newsgroups: comp.sys.amiga Subject: Re: A2090A HD controller Message-ID: <4038@eagle.ukc.ac.uk> Date: 6 Dec 87 14:46:00 GMT References: <5474@oberon.USC.EDU> <6575@ccicpg.UUCP> <2903@cbmvax.UUCP> Reply-To: kjws@ukc.ac.uk (K.J.W.Smithers) Organization: Computing Lab, University of Kent at Canterbury, UK. Lines: 56 Summary: Expires: Sender: Followup-To: In article <2903@cbmvax.UUCP> you write: > >This is one of the things that the updated hddisk device I announced >awhile ago (and will mail to people over usenet) fixes. If you don't >have have a 2090 card, the software that comes with your 2090 is >the new driver, so it will work fine in overscan. >-- >andy finkel {ihnp4|seismo|allegra}!cbmvax!andy >Commodore-Amiga, Inc. > I have an A2090 card and a CSA68020/68881 board with no 32 bit ram. They will Not work together. (but both work seperately) I think the driver (hddisk) is dated 1986 , is this the latest driver? (If not could you please e-mail me the latest version) The problem is when I run binddrivers that task stops, (binddrivers never exits). It seems to fallover on a particular call to execbase. The last instruction (displayed by MetaScope) is mov a2,(a0) If i move the hddisk from expansion draw , to hddisk.device in the devs draw, i can mount the harddisk (dh0:) , but when i do a cd dh0: , the cd command displays 'Cant find dh0:' I am running morerows, 672*266 on a B2000 rev 4.0 board (pal) with 2Mbytes expansion ram , 2*3.5inch drives, and (hopefully) A2090 + 20 Mbyte hard disk, and a CSA 68020/68881 board. I have also done the wire-link modification to the main B2000 board, as required by CSA for the 68020 board on Rev4.0 and later boards. Slots are as follows :- I I E E E M H 6 B B M M M E A 8 M M P P P M R 0 T T T O D 2 Y Y Y R D 0 Y I C S P K U Thanks in advance for any help Kit Smithers ____________________________________________________________________________ Kit Smithers kjws@ukc.ac.uk kjws@ukc.UUCP !mcvax!ukc!kjws The man who can not stay fast and hard at the same time ! Live for ever, or die in the attempt. ______________________________________________________________________________ #! rnews 1572 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!ajcd From: ajcd@its63b.ed.ac.uk (Angus Duggan, Department of Computer Science, University of Edinburgh,) Newsgroups: rec.games.hack Subject: pickup option - suggestion Keywords: pickup HACKOPTIONS Message-ID: <813@its63b.ed.ac.uk> Date: 6 Dec 87 11:47:56 GMT Reply-To: ajcd@its63b.ed.ac.uk (Angus Duggan) Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 23 Here's a suggestion for an improvement (at least I think it is :-) to the "pickup" option in nethack, which someone who is familiar with the source code might like to implement - Make the "pickup" option a composite option like "packorder", and re-write the picking up code so that the types of objects specified will be automatically picked up. All other objects could still be picked up by ','. e.g. "pickup:?+/=!)" would pick up scrolls, spellbooks, wands, rings, potions, and weapons. This would be useful for those of us who don't like carrying hoards of gold around, and also to prevent picking up dead cockatrices while still picking up other objects. BTW, does anyone know what the options "null" and "news" do? -- Angus Duggan, Department of Computer Science, University of Edinburgh, James Clerk Maxwell Building, The King's Buildings, Mayfield Road, Edinburgh, EH9 3JZ, Scotland, U.K. JANET: ajcd@uk.ac.ed.ecsvax ARPA: ajcd%ecsvax.ed.ac.uk@cs.ucl.ac.uk USENET: ajcd@ecsvax.ed.ac.uk UUCP: ...!seismo!mcvax!ukc!ecsvax.ed.ac.uk!ajcd BITNET: psuvax1!ecsvax.ed.ac.uk!ajcd or ajcd%ecsvax.ed.ac.uk@earn.rl.ac.uk #! rnews 4243 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!simon From: simon@its63b.ed.ac.uk (ECSC68 S Brown CS) Newsgroups: comp.lang.c Subject: Re: stdio error detection Message-ID: <814@its63b.ed.ac.uk> Date: 6 Dec 87 17:35:07 GMT References: <10649@brl-adm.ARPA> Reply-To: simon%lfcs.ed.ac.uk@nss.cs.ucl.ac.uk (Simon Brown) Organization: LFCS, University of Edinburgh Lines: 87 In article <10649@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes: >>I used to be rather fond of C, but this error stuff is quite >>incredibly bad. The problem isn't really the language; it's >>the libraries. > >Rather than messing with errno, I think a new variable, say, liberr, >should be used. An include file, say liberr.h, could contain macro >definitions for the various types of errors. A macro named LIBERR >could also be defined in liberr.h so code could be written that would >take advantage of liberr if it was available or handle errors in the >usual way if it's not. Even better would be to have LIBERR be a >predefined macro like ANSI, unix, vax, et cetera. > This still has the same problem as with "errno"- namely that you're trying to describe a general ``error condition'' using a single number! I'm told that VMS (but it's a good idea for all that...) provides a stack of error values which allows a program to search backward to find out what the "real" error was, depending on what kind of detail is required. If you have several levels of library calls between you and the system call that failed, this can be extremely useful- it's not really much use having an error-value if you can't even tell what system call it came from (let alone what parameters were *passed* to that system call to cause it to fail!). A *decent* error-returning mechanism would describe: 1. What call (syscall or library call) failed. This could be a number- you could use something like internet addressing to put some kind of structure into it: libc.stdio.fopen 2. Why it failed. Simple E-numbers will do for this (although I suppose they'd have to be grouped for different libraries): E_STDIO.E_CANNOT_OPEN_FILE 3. What value it returned. (FILE *)NULL 3. What parameters were passed to it. This is the most difficult one, because it would have to have some kind of idea as to the types involved. It could (I suppose) deal only with string types (and convert any other type into "printable" form by doing the equivalent of sprintf()'ing it). It also has to be a "list", which means it would probably have to be done using something like "argc,argv": argc: 2 argv: "mumble.splat", "r" If the error is not "dealt with", then this information should propogate down (together with the info from the callee's failure), and so on... So, If you do a fopen("mumble.splat","r") and it fails, then the following would be left on the stack (in some format or other) to be dealt with by some error-diagnosing function: kernel.open: param 1: "mumble.splat" [string] param 2: 0 [int] returns: -1 [int] error: E_KERNEL.ENOENT libc.stdio.fopen: param 1: "mumble.splat" [string] param 2: "r" [string] returns: 0 [FILE *] error: E_LIBC.E_STDIO.E_CANNOT_OPEN_FILE The error-diagnosing stuff could then print something *useful* such as stdio fopen: couldn't open file "mumble.splat" for reading, because: kernel open: no file or directory "mumble.splat" (and of course the format of these messages could be user-configurable, so that noddies would just get the information they need, whereas people who understand what they're doing could get reams and reams of info- just by setting some environment parameter to the appropriate value). Of course, all this stuff would have to be known by the compiler, and I'm sure it'd be dead slow to execute! -- -------------------------------------------------- | Simon Brown | | Laboratory for Foundations of Computer Science | | Department of Computer Science | | University of Edinburgh, Scotland, UK. | -------------------------------------------------- UUCP: uunet!mcvax!ukc!lfcs!simon ARPA: simon%lfcs.ed@nss.cs.ucl.ac.uk "Life's like that, you know" JANET: simon@uk.ac.ed.lfcs #! rnews 665 Path: alberta!mnetor!uunet!mcvax!henk From: henk@cwi.nl (Henk Schouten) Newsgroups: rec.games.board Subject: diplomacy Keywords: pbm Message-ID: <138@piring.cwi.nl> Date: 7 Dec 87 08:36:16 GMT Organization: CWI, Amsterdam Lines: 9 A local group is going to start a diplomacy game by mail. We have only few players so I would like to take part in the game myself. To do so, I would like to have the moves evaluated by a program. Before writing such a program myself, I would like to ask if anyone has or knows of such a program in the public domain, preferrably written in C. Code or pointers to it will be greatly appreciated. Henk Schouten ..!nl!cwi!henk #! rnews 1298 Path: alberta!mnetor!uunet!mcvax!varol From: varol@cwi.nl (Varol Akman) Newsgroups: sci.crypt Subject: Re: NSA advertisment Summary: Somewhat naive, huh? Message-ID: <139@piring.cwi.nl> Date: 7 Dec 87 08:59:02 GMT References: <4781@cit-vax.Caltech.Edu> Organization: CWI, Amsterdam Lines: 22 palmer@tybalt.caltech.edu.UUCP (David Palmer) writes: >I just read a magazine add seeking people to work at the NSA (pg. 80R of >Dec. 1987 IEEE Spectrum) >The graphic is 10,000,0... (100 zeros) written on three lines. The first >paragraph of the text reads: > You're looking at a "googol." Ten raised to the 100th power. > One followed by 100 zeros. Counting 24 hours a day, you would > need 120 years to reach a googol. Two lifetimes. It's a > number that's impossible to grasp. A number beyond our imagination. >... material deleted ... This strikes me as quite odd. I mean, if something can be done in two lifetimes then, darn it, it is well within my imagination. If it can be done within 20 lifetimes I can still grasp how difficult it should be. A real difficult thing would be something that takes say 10^100 lifetimes. In short, I find the above ad quite naive. NSA guys should probably have something better than this for the inspring encryption student. What do you say? -Varol Akman #! rnews 1520 Path: alberta!mnetor!uunet!mcvax!prlb2!ronse From: ronse@prlb2.UUCP (Christian Ronse) Newsgroups: sci.math Subject: Re: Least-squares fitting Summary: see Duda & Hart, Chapter 9, for a solution Keywords: ``eigenvector line fitting'' Message-ID: <387@prlb2.UUCP> Date: 7 Dec 87 09:22:11 GMT References: <1823@culdev1.UUCP> <528@amethyst.ma.arizona.edu> Organization: Philips Research Laboratory, Brussels Lines: 21 From article <528@amethyst.ma.arizona.edu> by hdunne@amethyst.ma.arizona.edu: < In article <1823@culdev1.UUCP> drw@culdev1.UUCP (Dale Worley) writes: [deleted ...] < }Is is known how to perform least-squares fitting where the "error" is < }the perpendicular distance between the point and the line? < } < If the point is (x_i,y_i) and the line is y = a*x + b, then the square of the < perpendicular distance is [(y_i - a*x_i - b)^2]/(1 + a^2) (assuming the line < isn't vertical). Taking the sum of the squared distances and setting the < partial derivatives wrt. a and b equal to zero, you get the same equations < for a and b as you get from the usual least-squares procedure. See the book ``Pattern Classification and Scene Analysis'' by R.O. Duda & P.E. Hart, Chapter 9. Section 9.2.1 introduces the usual least square fitting (``minimum-squared-error line fitting''), and 9.2.2 the one asked by Dale (``eigenvector line fitting''). There the problem is solved. Christian Ronse maldoror@prlb2.UUCP {uunet|philabs|mcvax|...}!prlb2!{maldoror|ronse} STAT ROSA PRISTINA NOMINE, NOMINA NUDA TENEMUS #! rnews 977 Path: alberta!mnetor!uunet!mcvax!ukc!stl!stc!idec!camcon!mb From: mb@camcon.uucp (Mike Bell) Newsgroups: comp.sys.ibm.pc Subject: Re: Neat voice|gag program Summary: How does HELPME work? Message-ID: <1107@titan.camcon.uucp> Date: 2 Dec 87 14:25:07 GMT References: <3692@uwmcsd1.UUCP> Distribution: all Organization: Cambridge Consultants Ltd., Cambridge, UK Lines: 15 in article <3692@uwmcsd1.UUCP>, cmaag@csd4.milw.wisc.edu (posting to comp.binaries.ibm.pc) says: > Here is a neat little program I found on a local bbs. It uses the speaker > to generate a very-realistic (the best I've heard on a PC!) voice that > says something to the effect of "Help! I'm locked in this computer! > Let me out! Help!". I just played it, and was much impressed. Given the rudimentary nature of IBM PC's, can anybody explain how it achieves its effect? -- --------------- UUCP: ...mcvax!ukc!camcon!mb -- Mike Bell -- or: mb%camcon.uucp --------------- Phone: +44 223 358855 #! rnews 710 Path: alberta!mnetor!uunet!mcvax!ukc!stl!stc!idec!camcon!mb From: mb@camcon.uucp (Mike Bell) Newsgroups: comp.sources.bugs Subject: Re: v12i071: StarChart program (Minor correction) Message-ID: <1114@titan.camcon.uucp> Date: 4 Dec 87 15:48:15 GMT References: <1110@artemis3.camcon.uucp> Organization: Cambridge Consultants Ltd., Cambridge, UK Lines: 10 in article <1110@artemis3.camcon.uucp>, mb@camcon.uucp (Mike Bell) says: > (Problem found on Sun 4.3 BSD Unix) Sorry, that should have been Sun Release 3.4 of 4.2 BSD... (well it was correct within an order of magnitude:-) -- --------------- UUCP: ...mcvax!ukc!camcon!mb -- Mike Bell -- or: mb%camcon.uucp --------------- Phone: +44 223 358855 #! rnews 2447 Path: alberta!mnetor!uunet!mcvax!tuvie!rcvie From: rcvie@tuvie (ELIN Forsch.z.) Newsgroups: comp.lang.c Subject: Re: Autoincrement question Message-ID: <548@tuvie> Date: 7 Dec 87 10:00:58 GMT References: <1507@ogcvax.UUCP> Organization: TU Vienna EDP-Center, Vienna, AUSTRIA Lines: 58 In article <1507@ogcvax.UUCP>, schaefer@ogcvax.UUCP (Barton E. Schaefer) writes: > (I realize this might be similar to another question asked recently, but ...) > > Another student here at OGC recently came to me with a question about the > C autoincrement operator. The following program is representative of the > code he wrote, which did not do what he expected: > > struct foo { struct foo *tmp; char junk[32]; } foolist[4]; > > main () > { > struct foo *bar; > > bar = foolist; > /* Do something with bar */ > bar->tmp = bar++; /* This is the problem line */ > /* Do something else */ > } > This is really dangerous programming. The points where the left and where the right "bar" are evaluated are implementation defined. The problem is similar to another one, which a friend of mine had some time ago. He tried to pack as much as possible into the control part of a while loop using the following statement: while (a[i]=b[i++]) ; Things were even worse here, as the program behaved even differently depending on whether it was compiled with the optimization option or not. Non optimized everything worked as expected but in the optimized version only for the first assignment "i" was incremented after the assignment, for all the following assignments it was incremented after the evaluation of "b[i]" but before the assignment. Nevertheless this behaviour was in the sense of both K&R and ANSI. The only thing you can trust on, is that the *operand* of the increment operator is evaluated before its incrementation. One way to achieve the desired behaviour is, as you suggested yourself, to write: > What he really wanted was the equivalent of > bar->tmp = bar; > bar++; and not (for the same reasons stated above): > (bar++)->tmp = bar; If there is any necessity to have the whole semantic in one *expression*, use the comma operator, as bar->tmp = bar, bar++; This operator *guarantees* the sequential evaluation of its operands from left to right. In real life: Dipl.Ing. Dietmar Weickert ALCATEL Austria - ELIN Research Center Floridusg. 50 A - 1210 Vienna / Austria #! rnews 1822 Path: alberta!mnetor!uunet!mcvax!steven From: steven@cwi.nl (Steven Pemberton) Newsgroups: comp.sys.atari.st Subject: Re: Alcyon C Bug N++ Message-ID: <140@piring.cwi.nl> Date: 7 Dec 87 14:59:48 GMT References: <8712051307.AA12109@ucbvax.Berkeley.EDU> Reply-To: steven@cwi.nl (or try mcvax!steven.uucp) Organization: CWI, Amsterdam Lines: 38 For people interested, here are a couple of bugs in the Alcyon compiler that we've been hitting our heads against for the last few weeks: 1) The compiler doesn't seem able to cope with nested initialisations. For instance, a struct with an array in the middle: static struct foo table[] = { { ...... {.....} ......}, ... } The compiler complains about mismatched braces. Cure: 'unwrap' the struct declaration, so it's all at the same level. 2) In a construct like bar *p = (expression1, expression2); the result of expression2 gets coerced to int, and then back to bar *, meaning basically that you get bombs on the screen when you try to use p, due to a wrong address. Cure: use bar *p = (expression1, (bar *) expression2); 3) We believe that 'complicated' initialisations to auto variables in functions (for instance where the initialisation involves a call to another function) often come out wrong. However, by this point, we despaired, and stopped using the compiler, so we never followed up on it. I might point out that we're trying to compile a BIG program: 30,000 lines of C, so just trying to trace bug 2 took us a LOT of time. By the way, just for interest: to compile the lot from scratch, using a ram disk for temporaries would take 4 hours. When we reinitialised the disk partition, and copied the files back, a recompile only took 1.5 hours! Steven Pemberton, CWI, Amsterdam; steven@cwi.nl #! rnews 1265 Path: alberta!mnetor!uunet!mcvax!mhres!jv From: jv@mhres.mh.nl (Johan Vromans) Newsgroups: comp.sys.hp Subject: Re: syslogd on HP-UX Summary: I have one Message-ID: <1495@mhres.mh.nl> Date: 7 Dec 87 12:19:02 GMT References: <641@ucdavis.ucdavis.edu> Sender: jv@mhres.mh.nl Reply-To: jv@mhres.mh.nl (Johan Vromans) Organization: Multihouse N.V., The Netherlands Lines: 20 In article <641@ucdavis.ucdavis.edu> arons@iris.ucdavis.edu (Tom Arons) writes: >Has anyone successfully ported syslog(3) and syslogd from 4.2 or >4.3 BSD to HP-UX 5.3 running on a 9000 series 300? > >It doesn't look like it would be too hard to do, but I don't want to >reinvent the wheel. I once implemented a syslogd for HP-UX using message queues. I have posted it to comp.sources.unix some time ago, but I can mail it if you cannot find it. Features: (almost) BSD compatible, no network support, runs as a daemon, communicates with message queues. If no daemon is running, calling 'syslog' is effectivily a no-op. I have used it when I tried to get sendmail running. -- Johan Vromans | jv@mh.nl via European backbone Multihouse N.V., Gouda, the Netherlands | uucp: ..{uunet!}mcvax!mh.nl!jv "It is better to light a candle than to curse the darkness" #! rnews 1036 Path: alberta!mnetor!uunet!mcvax!botter!wundt!michael From: michael@wundt.psy.vu.nl (M.A.M. Michael) Newsgroups: comp.sys.mac Subject: Address for update of VersaTerm requested Message-ID: <164@wundt.psy.vu.nl> Date: 7 Dec 87 16:30:39 GMT Reply-To: michael@psy.vu.nl.UUCP (M.A.M. Felt) Organization: VU Psychologie, Amsterdam Lines: 24 !!!!!!!!!!!!!!!!!!!!!!!!! Please reply via e-mail. !!!!!!!!!!!!!!!!!!!!!!!!! When I purchased VersaTerm 2+ years ago I didn't bother to register. Now I wish I had. It's about time for an update. The manual lists the address: Peripherals Computers & Supplies Inc 2232 Perkiomen Avenue Mt. Penn, PA 19606 Is this still current (other VersaTerm Users)? In either case, an e-mail reply will be appreciated. The dealer (I bought it from) here is still selling the same version of two years ago. (1.42) Thanks, michael felt -- Michael Felt Psychology Dept, Vrije Universiteit, Amsterdam, Netherlands InterNet: michael@psy.vu.nl UUCP: ...!mcvax!vupsy!michael , michael@vupsy.UUCP AppleLink: HOL0038 #! rnews 600 Path: alberta!mnetor!uunet!mcvax!inria!axis!alastair From: alastair@axis.fr (Alastair Adamson) Newsgroups: comp.text Subject: To break or not to break Summary: br command in [nt]roff Message-ID: <348@axis.fr> Date: 7 Dec 87 08:33:25 GMT Organization: Axis Digital, Paris Lines: 9 I have long wondered at the ubiquitous [nt]roff request 'br found in the mm macros and elsewhere. Could someone please elucidate the use of the break request with the no-break command character ' used? Thanks in advance, Alastair Adamson, alastair@axis.fr Axis Digital, 135 rue d'Aguesseau, 92100, Boulogne, France #! rnews 8193 Path: alberta!mnetor!uunet!mcvax!botter!ast From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: New program: treecmp.c Message-ID: <1774@botter.cs.vu.nl> Date: 7 Dec 87 20:53:16 GMT Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 321 I have written a program to recursively compare the contents of two given directories, file for file. The program descends the tree and reports about files that are missing or different. Some day, if I ever get around to producing V1.3 of MINIX, I will make a tree of the current version next to the V1.2 tree, and then run this program to get a list of all files that are different. Then I can make diff listings etc. In reality, the reason I wrote it however, is that I had just copied my MINIX tree from one part of the disk to another, and I wanted to make sure nothing was forgotten. I am sure there are other uses as well. One could no doubt write a shell script to do this same thing, or perhaps use find, but this program is much faster, being able to compare two 8 megabyte trees in about 12 minutes on a Z-248. Please post any bugs you find. Andy Tanenbaum (ast@cs.vu.nl) ----------------------------- treecmp.c --------------------------------- /* treecmp - compare two trees Author: Andy Tanenbaum */ /* This program recursively compares two trees and reports on differences. * It can be used, for example, when a project consists of a large number * of files and directories. When a new release (i.e., a new tree) has been * prepared, the old and new tree can be compared to give a list of what has * changed. The algorithm used is that the first tree is recursively * descended and for each file or directory found, the corresponding one in * the other tree checked. The two arguments are not completely symmetric * because the first tree is descended, not the second one, but reversing * the arguments will still detect all the differences, only they will be * printed in a different order. The program needs lots of stack space * because routines with local arrays are called recursively. The call is * treecmp [-v] dir1 dir2 * The -v flag (verbose) prints the directory names as they are processed. */ #include #define BUFSIZE 4096 /* size of file buffers */ #define MAXPATH 128 /* longest acceptable path */ #define DIRENTLEN 14 /* number of characters in a file name */ struct dirstruct { /* layout of a directory entry */ unsigned inum; char fname[DIRENTLEN]; }; struct stat stat1, stat2; /* stat buffers */ char buf1[BUFSIZE]; /* used for comparing bufs */ char buf2[BUFSIZE]; /* used for comparing bufs */ int verbose; /* set if mode is verbose */ main(argc, argv) int argc; char *argv[]; { char *p; if (argc < 3 || argc > 4) usage(); p = argv[1]; if (argc == 4) { if (*p == '-' && *(p+1) == 'v') verbose++; else usage(); } if (argc == 3) compare(argv[1], argv[2]); else compare(argv[2], argv[3]); exit(0); } compare(f1, f2) char *f1, *f2; { /* This is the main comparision routine. It gets two path names as arguments * and stats them both. Depending on the results, it calls other routines * to compare directories or files. */ int type1, type2; if (stat(f1, &stat1) < 0) { printf("Cannot stat %s\n", f1); return; } if (stat(f2, &stat2) < 0) { printf("Missing file: %s\n", f2); return; } /* Examine the types of the files. */ type1 = stat1.st_mode & S_IFMT; type2 = stat2.st_mode & S_IFMT; if (type1 != type2) { printf("Type diff: %s and %s\n", f1, f2); return; } /* The types are the same. */ switch(type1) { case S_IFREG: regular(f1, f2); break; case S_IFDIR: directory(f1, f2); break; case S_IFCHR: case S_IFBLK: break; default: printf("Unknown file type %o\n", type1); } return; } regular(f1, f2) char *f1, *f2; { /* Compare to regular files. If they are different, complain. */ int fd1, fd2, n1, n2, i; unsigned bytes; long count; char *p1, *p2; if (stat1.st_size != stat2.st_size) { printf("Size diff: %s and %s\n", f1, f2); return; } /* The sizes are the same. We actually have to read the files now. */ fd1 = open(f1, 0); if (fd1 < 0) { printf("Cannot open %s for reading\n", f1); return; } fd2 = open(f2, 0); if (fd2 < 0) { printf("Cannot open %s for reading\n", f2); return; } count = stat1.st_size; while (count > 0L) { bytes = (unsigned) (count > BUFSIZE ? BUFSIZE : count); /* rd count */ n1 = read(fd1, buf1, bytes); n2 = read(fd2, buf2, bytes); if (n1 != n2) { printf("Length diff: %s and %s\n", f1, f2); close(fd1); close(fd2); return; } /* Compare the buffers. */ i = n1; p1 = buf1; p2 = buf2; while (i--) { if (*p1++ != *p2++) { printf("File diff: %s and %s\n", f1, f2); close(fd1); close(fd2); return; } } count -= n1; } close(fd1); close(fd2); } directory(f1, f2) char *f1, *f2; { /* Recursively compare two directories by reading them and comparing their * contents. The order of the entries need not be the same. */ int fd1, fd2, n1, n2, ent1, ent2, i, used1 = 0, used2 = 0; char *dir1buf, *dir2buf; char name1buf[MAXPATH], name2buf[MAXPATH]; struct dirstruct *dp1, *dp2; unsigned dir1bytes, dir2bytes; extern char *malloc(); /* Allocate space to read in the directories */ dir1bytes = (unsigned) stat1.st_size; dir1buf = malloc(dir1bytes); if (dir1buf == 0) { printf("Cannot process directory %s: out of memory\n", f1); return; } dir2bytes = (unsigned) stat2.st_size; dir2buf = malloc(dir2bytes); if (dir2buf == 0) { printf("Cannot process directory %s: out of memory\n", f2); free(dir1buf); return; } /* Read in the directories. */ fd1 = open(f1, 0); if (fd1 > 0) n1 = read(fd1, dir1buf, dir1bytes); if (fd1 < 0 || n1 != dir1bytes) { printf("Cannot read directory %s\n", f1); free(dir1buf); free(dir2buf); if (fd1 > 0) close(fd1); return; } close(fd1); fd2 = open(f2, 0); if (fd2 > 0) n2 = read(fd2, dir2buf, dir2bytes); if (fd2 < 0 || n2 != dir2bytes) { printf("Cannot read directory %s\n", f2); free(dir1buf); free(dir2buf); close(fd1); if (fd2 > 0) close(fd2); return; } close(fd2); /* Linearly search directories */ ent1 = dir1bytes/sizeof(struct dirstruct); dp1 = (struct dirstruct *) dir1buf; for (i = 0; i < ent1; i++) { if (dp1->inum != 0) used1++; dp1++; } ent2 = dir2bytes/sizeof(struct dirstruct); dp2 = (struct dirstruct *) dir2buf; for (i = 0; i < ent2; i++) { if (dp2->inum != 0) used2++; dp2++; } if (verbose) printf("Directory %s: %d entries\n", f1, used1); /* Check to see if any entries in dir2 are missing from dir1. */ dp1 = (struct dirstruct *) dir1buf; dp2 = (struct dirstruct *) dir2buf; for (i = 0; i < ent2; i++) { if (dp2->inum == 0 || strcmp(dp2->fname, ".") == 0 || strcmp(dp2->fname, "..") == 0) { dp2++; continue; } check(dp2->fname, dp1, ent1, f1); dp2++; } /* Recursively process all the entries in dir1. */ dp1 = (struct dirstruct *) dir1buf; for (i = 0; i < ent1; i++) { if (dp1->inum == 0 || strcmp(dp1->fname, ".") == 0 || strcmp(dp1->fname, "..") == 0) { dp1++; continue; } if (strlen(f1) + DIRENTLEN >= MAXPATH) { printf("Path too long: %s\n", f1); free(dir1buf); free(dir2buf); return; } if (strlen(f2) + DIRENTLEN >= MAXPATH) { printf("Path too long: %s\n", f2); free(dir1buf); free(dir2buf); return; } strcpy(name1buf, f1); strcat(name1buf, "/"); strncat(name1buf, dp1->fname, DIRENTLEN); strcpy(name2buf, f2); strcat(name2buf, "/"); strncat(name2buf, dp1->fname, DIRENTLEN); /* Here is the recursive call to process an entry. */ compare(name1buf, name2buf); /* recursive call */ dp1++; } free(dir1buf); free(dir2buf); } check(s, dp1, ent1, f1) char *s; struct dirstruct *dp1; int ent1; char *f1; { /* See if the file name 's' is present in the directory 'dirbuf'. */ int i; for (i = 0; i < ent1; i++) { if (strncmp(dp1->fname, s, DIRENTLEN) == 0) return; dp1++; } printf("Missing file: %s/%s\n", f1, s); } usage() { printf("Usage: treecmp [-v] dir1 dir2\n"); exit(0); } #! rnews 1196 Path: alberta!mnetor!uunet!mcvax!prlb2!kulcs!kdv From: kdv@kulcs.UUCP (Karel De Vlaminck) Newsgroups: comp.text Subject: Laserprinters for troff on NCR Tower Message-ID: <1066@kulcs.UUCP> Date: 7 Dec 87 19:18:01 GMT Reply-To: kdv@kulcs.UUCP () Organization: Katholieke Universiteit Leuven, Dept. Computer Science Lines: 22 1) We want to connect a laserprinter for use with troff on a NCR Tower System. Has anyone experience with this? 2) We will have access to a KYOCERA F-1000 or F-1200 laser printer. Does anyone know about the existence of a filter for the troff output to the laserprinter (which uses 'Prescribe'). 3) This laserprinter also has an HP Laserjet Plus emulation. Another solution would then be to use a troff output filter for the HP Laserjet. So I will ask the same question about the existence for this filter. Please mail responses directly to me. If there are usefull responses, I will post a summary to the net. Karel De Vlaminck | K. U. Leuven kdv@kulcs.uucp | Department of Computer Science or ...!mcvax!prlb2!kulcs!kdv | Celestijnenlaan 200 A Phone: +(32) 16-200656 x3565 | B-3030 Leuven (Heverlee), Belgium #! rnews 685 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!solaris!wyle From: wyle@solaris.ifi.ethz.ch@relay.cs.net (Mitchell Wyle) Newsgroups: comp.unix.questions,comp.text Subject: Scribe, GML Keywords: Generalized Mark-up Languages, Scribe Message-ID: <194@A14A.solaris.ifi.ethz.ch@relay.cs.net> Date: 7 Dec 87 17:14:05 GMT Organization: SOT sun cluster, ETH Zuerich Lines: 7 Xref: alberta comp.unix.questions:4769 comp.text:1344 Where can I buy Scribe? Are there other implementations of a standard Markup Language on BSD Unix? What is Scribe? Please respond via e-mail; if there are enough "me too's," I'll post. -Mitch Wyle (wyle@solaris.uucp | wyle@ethz.uucp | ...!cernvax!ethz!wyle #! rnews 1896 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!simon From: simon@its63b.ed.ac.uk (ECSC68 S Brown CS) Newsgroups: comp.unix.wizards Subject: Re: Setting process groups Message-ID: <815@its63b.ed.ac.uk> Date: 7 Dec 87 10:30:32 GMT References: <1765@unc.cs.unc.edu> <910@mcgill-vision.UUCP> <1261@saturn.ucsc.edu> <3134@psuvax1.psu.edu> <2990@hcr.UUCP> Reply-To: simon@lfcs.ed.ac.uk (Simon Brown) Organization: LFCS, University of Edinburgh Lines: 29 In article <2990@hcr.UUCP> writes: >Actually SVID setpgrp() has an "extra feature" that Berkeley setpgrp(getpid()) >does not have - it detaches the process from its controlling terminal. This >does tend to make it "difficult" to create a pipeline attached to your terminal >but with its own process group. Well, you can do that by making each such pipeline belong to it's own SXT device, and have all these SXT's multiplexed onto your *real* terminal. Instant job-control! BTW, SVR2 (and 3?) setpgrp() doesn't fully detach a process from its controlling tty if this process has already done a setpgrp() previously (as is the case for a login-shell -- this comes from init and getty). What it does in this case is to "partially" detach -- so that if you try to set up a new controlling terminal, it's not actually a controlling terminal at all -- things like terminal-generated signals don't get sent to the process. Presumably this is just a cretinous bug, and not something more sophisticated. -- -------------------------------------------------- | Simon Brown | | Laboratory for Foundations of Computer Science | | Department of Computer Science | | University of Edinburgh, Scotland, UK. | -------------------------------------------------- UUCP: uunet!mcvax!ukc!lfcs!simon ARPA: simon%lfcs.ed@nss.cs.ucl.ac.uk "Life's like that, you know" JANET: simon@uk.ac.ed.lfcs #! rnews 1126 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!adrian From: adrian@cs.hw.ac.uk (Adrian Hurt) Newsgroups: rec.arts.sf-lovers Subject: Re: NCC, USS, Klingons, etc... Summary: She was a Klingon Message-ID: <1568@brahma.cs.hw.ac.uk> Date: 7 Dec 87 10:33:54 GMT References: <8712011928.AA04370@topaz.rutgers.edu> <1632@bsu-cs.UUCP> <19321@teknowledge-vaxc.ARPA> Organization: Computer Science, Heriot-Watt U., Scotland Lines: 15 In article <19321@teknowledge-vaxc.ARPA>, hshiffma@teknowledge-vaxc.ARPA (Hank Shiffman) writes: > > Why do you think she was a Klingon? As I recall, she looked human. > You weren't assuming that she was a Klingon just because she had > something going with the Christoper Lloyd character, were you? For > shame! In the book of the film, Valkris was definitely a Klingon, out to do something valiant to redeem her family's honour. She became very friendly with another alien on board that ship because of that alien's warrior traditions. -- "Keyboard? Tis quaint!" - M. Scott Adrian Hurt | JANET: adrian@uk.ac.hw.cs UUCP: ..!ukc!cs.hw.ac.uk!adrian | ARPA: adrian@cs.hw.ac.uk #! rnews 1332 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!adrian From: adrian@cs.hw.ac.uk (Adrian Hurt) Newsgroups: rec.games.frp Subject: Re: Star Wars: the RPG Summary: Pictures Message-ID: <1569@brahma.cs.hw.ac.uk> Date: 7 Dec 87 10:42:12 GMT References: <1570@cup.portal.com> <13450021@acf4.UUCP> <1676@cup.portal.com> <1799@cup.portal.com> Organization: Computer Science, Heriot-Watt U., Scotland Lines: 21 In article <1799@cup.portal.com>, Nightstalker@cup.portal.com writes: > > Hi! Does anyone know if the force skills can be learned by any PC like > a smuggler or outlaw for example, or can they only be taught to the > jedi classes and NPCs? Thank you. > Jason Wallace > Any character may learn the Force skills from a master, and the rulebook even encourages players using the Jedi characters to do some teaching, provided that the pupil hasn't got any Dark Side points. Remember, Luke Skywalker was a "Brash Pilot" type until Obi-Wan (OB1? :-) got to him. Now for my question. There are some really nice pictures in the rulebook. Can I get separate copies of these? They would be great posters, especially the Imperial Navy recruiting poster and the R2 advert. -- "Keyboard? Tis quaint!" - M. Scott Adrian Hurt | JANET: adrian@uk.ac.hw.cs UUCP: ..!ukc!cs.hw.ac.uk!adrian | ARPA: adrian@cs.hw.ac.uk #! rnews 1047 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!bob From: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Newsgroups: rec.arts.sf-lovers Subject: Re: Klingon females Message-ID: <816@its63b.ed.ac.uk> Date: 7 Dec 87 12:36:36 GMT References: <8712042225.AA03829@topaz.rutgers.edu> <3490@hoptoad.uucp> Reply-To: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 13 In article <3490@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >I like the fact that the Klingons are portrayed as sexist scumbags, but it >disturbs me that all major sentient races except humans and Romulans put >women in a subservient role (Klingons, Vulcans, Ferrengi). It almost seems >as if we are being told that female subservience is part of the natural >order of sentience. There are no major female-dominated sentient races, two >semi-egalitarian races, and three male-dominated races, a clear imbalance in >favor of male dominance. Then who was T'pau supposed to be? She was vulcan, and very obviously in charge of things. Bob. #! rnews 1313 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!bob From: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Newsgroups: rec.arts.sf-lovers Subject: Re: Max Headroom Message-ID: <817@its63b.ed.ac.uk> Date: 7 Dec 87 13:10:09 GMT References: <82*quale@si.uninett> <3333@ihlpl.ATT.COM> Reply-To: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Distribution: rec.arts.sf-lovers Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 18 In article <3333@ihlpl.ATT.COM> barth@ihlpl.UUCP (BARTH RICHARDS) writes: >The problem is that the first few episodes were *re*made by an American >production company for broadcast on ABC (not the Australian ABC). As I >understand it, the first ABC run of six shows (winter/spring of 1987) were >all reworkings of episodes already done by the British. The second run >(fall 1987) were stories newly developed by the American producers. Sorry, there was only ever one original Max Headroom programme. That was a one-off TV film made by the BBC. Any episodes beyond the original story did not originate with the BBC, although Maxs' creators may have been involved. Max then re-appeared on Channel 4 as host of a chat show for two short seasons. (interviewing guest stars about their views on Golf, music, life and, most importantly, Golf :->) He then crossed the atlantic to be re-made by ABC. Bob. #! rnews 1152 Path: alberta!mnetor!uunet!mcvax!ukc!warwick!jeff From: jeff@warwick.UUCP (Jeff Smith) Newsgroups: comp.lang.c++ Subject: cfront runs too fast (and fix) Keywords: cfront fix Message-ID: <586@ubu.warwick.UUCP> Date: 7 Dec 87 14:49:10 GMT Organization: Computer Science, Warwick University, UK Lines: 27 If you can persuade cfront to finish in less than a second with the +S option on, then the calculation of the number of lines processed per second generates a divide-by-zero! On a SUN-3 with 1.2.1, typing cfront +S 0 ? Nline/(stop_time-start_time) : Nline); #else !CFRONTTOOFASTFIX stop_time-start_time, Nline/(stop_time-start_time) ); #endif CFRONTTOOFASTFIX fflush(stderr); Jeff warwick!jeff PS. Does anyone have a fix to simpl.c for the null dereference on Pfct f = Pfct(Pptr(q->tp)->typ) caused by the pointer to member function problem? The problem's been noted a couple of times in comp.lang.c++, by Paul Calder and others.. #! rnews 1114 Path: alberta!mnetor!uunet!mcvax!ukc!warwick!strgh From: strgh@daisy.warwick.ac.uk (J E H Shaw) Newsgroups: rec.music.misc Subject: Re: More than Yes (really Egg) Message-ID: <357@daisy.warwick.ac.uk> Date: 7 Dec 87 17:57:56 GMT References: <22034@ucbvax.BERKELEY.EDU> <19826@yale-celray.yale.UUCP> Reply-To: strgh@daisy.warwick.ac.uk (J E H Shaw) Organization: Computing Services, Warwick University, UK Lines: 14 ---------- Egg released at least one other album before `Civil Surface', I think it was called `the Polite Force'. They were very good. Their drummer (Clive Brooks?) joined the Groundhogs. Their bassist (Mont Campbell?) played sometimes with some of the other Canterbury scene people: National Health, U.K. or similar (mid 70's). Their organist, Dave Stewart, became a pop star (`It's My Party'), and also played with National Health, Hatfield & the North, etc. Apologies for any wrong names - the above is all based on memory. -- J.E.H.Shaw Department of Statistics, University of Warwick, Coventry CV4 7AL $$\times\times\qquad\top\gamma\alpha\omega\exists\qquad{\odot\odot\atop\smile}$$ #! rnews 1231 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!icdoc!qmc-cs!nickd From: nickd@cs.qmc.ac.uk (Nick Dunlavey) Newsgroups: comp.cog-eng Subject: Touch-screen research Message-ID: <348@sequent.cs.qmc.ac.uk> Date: 4 Dec 87 10:52:55 GMT References: <19@gollum.Columbia.NCR.COM> <290@rd1632.Dayton.NCR.COM> Reply-To: nickd@qmc.ac.uk (Nick Dunlavey) Organization: Sch Of C+IT, Thames Polytechnic, Woolwich, London, UK Lines: 19 Summary: Expires: Sender: Followup-To: Distribution: Keywords: I know that the CEGB (for those outside the UK, this is the UK's Central Electricity Generating Board) has done some work on this in the Scientific Services Department in its North-eastern Region. A report was produced called: "A Touch-Sensitive Screen As An Interface For On-Line Control", by Sutherland, Pringle and Carlin. It documents the use of an upgraded VT103 in a power station for operator control. -- ------------- Nick Dunlavey ARPA: nickd@cs.qmc.ac.uk (gw: cs.ucl.edu) School Of Computing & IT UUCP: nickd@qmc-cs.UUCP Thames Polytechnic Tel: 01-854 2030 Ext 339 Wellington Street Woolwich Thanks to Queen Mary College for LONDON net access SE18 6PF #! rnews 1563 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!adrian From: adrian@cs.hw.ac.uk (Adrian Hurt) Newsgroups: rec.arts.sf-lovers Subject: Re: ST:TNG posters Summary: Tolerance, please Message-ID: <1570@brahma.cs.hw.ac.uk> Date: 7 Dec 87 13:24:11 GMT References: <5226@zen.berkeley.edu> Organization: Computer Science, Heriot-Watt U., Scotland Lines: 27 In article <5226@zen.berkeley.edu>, iverson@cory.Berkeley.EDU (Tim Iverson) writes: > > ... Not only that, but these article made no mention of > ST:TNG in the subject line or header, so I couldn't kill them easily. > > ... The simple fact is that there is > newsgroup for all of you to communicate in, and if the rest of us wanted to > listen, then we would. > Oh no, not again. Remember last time, when the number of articles complaining about ST articles outnumbered the articles concerned (and every other single type of article as well)? There is a ST group, but not for "all of us". Some of us can't get at it. But your point about headers is valid. In the interests of preventing Flame War III I suggest that those of us who wish to put ST (and Dr. Who, etc) articles here make sure that "ST" (or Dr. Who, etc) or some similar warning appears in the header. And those who wish to complain about such postings should also always put some clear warning in the header, so those of us who aren't interested can kill their articles easily. -- "Keyboard? Tis quaint!" - M. Scott Adrian Hurt | JANET: adrian@uk.ac.hw.cs UUCP: ..!ukc!cs.hw.ac.uk!adrian | ARPA: adrian@cs.hw.ac.uk #! rnews 782 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: comp.os.misc Subject: incorporating processes into file systems Message-ID: <1572@brahma.cs.hw.ac.uk> Date: 7 Dec 87 20:36:40 GMT Organization: Computer Science, Heriot-Watt U., Scotland Lines: 9 I believe there has been at least one OS that manages the naming of processes and files in the same way - so 'ps' would become yet another option to 'ls'. I forget which. Can anyone enlighten me? References? -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 1538 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: sci.physics,rec.games.programmer,comp.sys.mac Subject: simulating relativistic motion Keywords: relativity, graphics, flight simulators Message-ID: <1573@brahma.cs.hw.ac.uk> Date: 7 Dec 87 21:00:08 GMT Organization: Computer Science, Heriot-Watt U., Scotland Lines: 18 Xref: alberta sci.physics:2410 rec.games.programmer:44 comp.sys.mac:10006 A long time ago I read about a program developed at MIT that produced images of the way ordinary scenes (a street) would look at speeds nearing c. I don't know if it used a plotter or calligraphic display, but it was so long ago that whatever it did should surely be possible now in real time on a Mac or equivalent. Does anything like that exist? - a sort of flight simulator for cosmic ray particles, that would let you define a scene with a 3D graphics editor and then look at it at various fractions of c. (Colour would be a nice optional extra). The MIT program produced weirdly drooping lampposts. More ambitiously: what about general relativity? Here I am thinking about some of the descriptions in Kaufmann's "The Cosmic Frontiers of General Relativity" about how the world would look from near a black hole. -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 737 Path: alberta!mnetor!uunet!mcvax!enea!kuling!nicke From: nicke@kuling.UUCP (Niclas Holm) Newsgroups: comp.lang.c++ Subject: Anyone ported c++ to UNISYS 50xx ? Message-ID: <569@kuling.UUCP> Date: 6 Dec 87 16:33:36 GMT Reply-To: nicke@kuling.UUCP (Niclas Holm) Organization: Dept. of Computer Systems, Uppsala University, Sweden Lines: 7 I am interested in running c++ on a UNISYS 50xx (read NCR Tower ..). Has someone successfully ported it, or need I do it myself ? -- Niclas F. Holm | UUCP: nicke@kuling ({seismo!mcvax}!enea!kuling!nicke) Idrottsg. 21 II | or nicke@umecs ({seismo!mcvax}!enea!umecs!nicke) S-753 35 Uppsala | Phone: +46 - 18 13 36 SWEDEN | Famous Last Words: Look, no hands! #! rnews 1584 Path: alberta!mnetor!uunet!mcvax!ukc!stc!datlog!slxsys!jpp From: jpp@slxsys.specialix.co.uk (John Pettitt) Newsgroups: comp.sys.ibm.pc Subject: Re: anyone have info on "multilink"? Summary: Get it from: TSL, Atlanta Ga. Keywords: remote modem multilink Message-ID: <108@slxsys.specialix.co.uk> Date: 7 Dec 87 20:01:09 GMT References: <167@iisat.UUCP> Reply-To: jpp@slxsys.UUCP (John Pettitt) Organization: Specialix International, London, UK. Lines: 31 In article <167@iisat.UUCP> iis@iisat.UUCP (Paul Gauthier) writes: >i am trying to locate information on a program called mutlilink. i have >heard that it permits one to run software on an ibm from a remote (dumb) >terminal. is this correct? does anyone know of other software that will >accomplish the same? any and all help would be appreciated. thank you. Multilink will allow several serial screens to run dos programs. More info from: The Software Link 3577 Parkway Lane Atlanta GA 30092 (404) 448 5465 They also have a product call PC-MOS that does the same thing on 386 boxes. Other software that lets you run multi user dos includes QNX, Concurrent DOS (from Digital Research - remember CP/M :-), Xenix (vp/ix comming soon), Unix V (ISC and Microport, with vp/ix and locus merge respectivly). Disclaimer: I don't sell any of the above - just write serial driver's for them - not easy in some cases :-( -- John Pettitt - 144.5 MHz: G6KCQ, CIX: jpettitt, Voice: +44 1 398 9422 UUCP: ...uunet!mcvax!ukc!pyrltd!slxsys!jpp (jpp@slxsys.specialix.co.uk) Disclaimer: I don't even own a cat to share my views ! #! rnews 1792 Path: alberta!mnetor!uunet!mcvax!targon!wim From: wim@targon.UUCP (Wim C. J. van Eerdt) Newsgroups: comp.lang.c++ Subject: Bug bug? solved (?) Keywords: inline local variables Message-ID: <367@targon.UUCP> Date: 8 Dec 87 09:22:14 GMT Reply-To: wim@targon.UUCP (Wim C. J. van Eerdt) Organization: Nixdorf Computer BV., OSP, P.O. Box 29,Vianen, The Netherlands Lines: 34 As long as the department does not have an uucp-feed, you can e-mail me, the poster. Success! Wim van Eerdt E-mail: mcvax!targon!wim OSP, Nixdorf Computer Bv, Postbus 29, 4130 EA Vianen Nederland. Tel.: +31 3473 62211. ----------------News article got:------------------------------------- Author: Gerard van Dorth Subject: Bug bug? solved (?) Keywords: inline local variables > ... Redeclaration of "_au2__Xt_val_global" The conditional statement on the lines 161/162 "if ( base == BLOCK && n->lex_level < ( (Pfct(expand_fn->tp)->memof) ? 3 : 2 ) )" in file expand.c has to be changed in: "if ( base == BLOCK && n->lex_level < 'function-defined-in-class' ? 3 : 2 )". For a function defined in a class the lex_level is raised by the curly brace of the class itself. Not only member functions (memof = member of) can be defined inline, friends can also. (Note that funny declarations of local variables did appear in case a member function which needs locals is declared inline but not defined in the class itself). The most simple way to tell whether a function is defined in a class is the use of a global variable (the more globals the more fun), set and reset (embracing the first loop) in the routine classdef::simpl() in file simpl.c -- Wim van Eerdt E-mail: mcvax!targon!wim OSP, Nixdorf Computer Bv, Postbus 29, 4130 EA Vianen Nederland. Tel.: +31 3473 62211. #! rnews 1196 Path: alberta!mnetor!uunet!mcvax!unido!infbs!hild From: hild@infbs Newsgroups: rec.music.classical Subject: Re: K. u. K. - (nf) Message-ID: <24200003@infbs.UUCP> Date: 7 Dec 87 10:26:00 GMT References: <19123@amdahl.UUCP> Lines: 17 Nf-ID: #R:amdahl:19123:infbs:24200003:000:873 Nf-From: infbs!hild Dec 7 11:26:00 1987 This is only partly true. "K.u.K." is short for "Kaiserlich und Koeniglich", that's right. But it has nothing to do with the king of prussia. At the time "K.u.K." was used, the king of Austria was also the king of Hungary and the emperor of "Oestreich-Ungarn" (Austria and Hungary. When thinking of K.u.K., I have the picture of Kaiser Franz Josef, a fatherly man who kept his nation in a long period of prosperous (sp?) peace, especially good for the arts. BTW, Otto von Bismarck is remembered as a man who united Germany (with an iron hand, that's true), which at that time was divided into many small parts, all of them having a duke, different legislation and borders between them. This meant having to pay customs very often, thus disallowing free trade, which in turn was necessary for the upcoming industrial revolution. So you might regard OvB a good statesman. #! rnews 1564 Path: alberta!mnetor!uunet!mcvax!nikhefh!t68 From: t68@nikhefh.UUCP (Jos Vermaseren) Newsgroups: comp.sys.atari.st Subject: Re: FOLDERXXXXX Summary: FOLDRXXX may not do the job either. Message-ID: <410@nikhefh.UUCP> Date: 8 Dec 87 10:44:50 GMT References: <637@aucs.UUCP> Organization: Nikhef-H, Amsterdam (the Netherlands). Lines: 22 In article <637@aucs.UUCP>, 870646c@aucs.UUCP (barry comer) writes: > After I posted my message about the GEMBOOT prg. not working properly, I > received a message stating that GEMBOOT will not work properly with the new ROMS,well he also stated that there is a prg. call something like "FOLDRXXX.TOS", > will this prg. work with the new ROMS? If it will do the trick could someone > that has it please sent it to me in a reply msg. PLEASE do not send it via > the binaries section I will never get it. > Thanx in advance > Barry FOLDRXXX starts up with a little table of ROM versions and corresponding to each version an address. At that address it inserts a list of memory pieces to be used. If you use new ROM's these addresses have been changed so you cannot use FOLDRXXX unless you figure out the new address you need and substitute the necessary information into the binary of FOLDRXXX ( or a disassembly ). On the other hand: the new version of the ROMs for the Mega has a much larger OSpool from which these memory blocks are taken. It used to be 6000 bytes, but the new size is 16000 bytes. I don't know whether this makes FOLDRXXX superfluous. Maybe Allan Pratt can comment on that. Jos Vermaseren T68@nikhefh.uucp #! rnews 793 Path: alberta!mnetor!uunet!mcvax!nikhefk!marcel From: marcel@nikhefk.UUCP (Marcel Corbeek) Newsgroups: rec.music.classical Subject: Question Message-ID: <291@nikhefk.UUCP> Date: 8 Dec 87 11:19:26 GMT Reply-To: marcel@nikhefk.UUCP (Marcel Corbeek) Organization: Nikhef-K, Amsterdam (the Netherlands). Lines: 15 In the film "Once upon a time in America" an ouverture of Rossini is played. Is there anyone who can tell me which one this is ? Marcel Corbeek, Arpanet : marcel@nikhefk.uucp NIKHEF-K, Amsterdam. Bitnet : v59u0002@hasara11.bitnet Home address : Aletta Jacobsstraat 48, 1628 NP Hoorn, The Netherlands. Marcel Corbeek, Arpanet : marcel@nikhefk.uucp NIKHEF-K, Amsterdam. Bitnet : v59u0002@hasara11.bitnet Home address : Aletta Jacobsstraat 48, 1628 NP Hoorn, The Netherlands. #! rnews 2545 Path: alberta!mnetor!uunet!mcvax!prlb2!ronse From: ronse@prlb2.UUCP (Christian Ronse) Newsgroups: sci.math Subject: Re: Putnam Exam (SPOILER) Summary: another proof for the x<25 solution Keywords: Putnam Message-ID: <388@prlb2.UUCP> Date: 8 Dec 87 10:03:24 GMT References: <16863@topaz.rutgers.edu> <16864@topaz.rutgers.edu> <3482@husc6.harvard.edu> Organization: Philips Research Laboratory, Brussels Lines: 69 In article <3482@husc6.harvard.edu>, elkies@huma1.HARVARD.EDU (Noam Elkies) writes: < [Problem A-6 of the 48th Annual W.L.Putnam Contest, Dec. 5, 1987: ] < >> For each positive integer n, let a(n) be the number of zeros in the < >> base 3 representation of n. For which positive real numbers x does < >> the series < >> < >> inf < >> ----- x^a(n) < >> \ ------ < >> / n^3 < >> ----- < >> n = 1 < >> < >> converge? > Actually the correct interval of convergence is x<25. Indeed, in the > partial sum corresponding to 3^k<=n<3^(k+1), the coefficients n^(-3) are > within a factor of 27 of 27^(-k), and the sum of x^a(n) is easily seen to > be 2(x+2)^k, so by comparison with the geometric series sum(r^k,k,0,inf) > with r=(x+2)/27 we find that the series converges if and only if r<1, > i.e. x<25. This is correct, but the way the proof is written is not easy to understand. I give below another proof. For n>0 let T(n) = x^a(n)/n^3 and U(n) = T(3n) + T(3n+1) + T(3n+2) and for k>=0 let Z(k) = sum {n=3^k to 3^(k+1)-1} T(n) We have Z(k+1) = sum {n=3^(k+1) to 3^(k+2)-1} T(n) = sum {n=3^k to 3^(k+1)-1} [T(3n) + T(3n+1) + T(3n+2)] = sum {n=3^k to 3^(k+1)-1} U(n) Let us compare U(n) to T(n). We have a(3n)=a(n)+1 and a(3n+1)=a(3n+2)=a(n). Thus U(n) = x^[a(n)+1]/(3n)^3 + x^a(n)/(3n+1)^3 + x^a(n)/(3n+2)^3 and so U(n) has as upper bound x^a(n) * (x+2)/(3n)^3 = T(n) * (x+2)/27 and as lower bound x^a(n) * (x+2)/(3n+2)^3 = T(n) * (x+2)/(3+2/n)^3 in other words U(n) = T(n) * (x+2)/(27+e(n)), where e(n)<(3+2/n)^3-27 tends to 0 when n tends to infinity. It follows then that Z(k+1)= Z(k)*(x+2)/(27+f(k)) where f(k)<(3+2/3^k)^3-27 tends to 0 for n tending to infinity. Now the series is the sum of all Z(k). Thus for x>25 we have Z(k+1)>Z(k) for k large enough, and the series diverges; for x<25 we have Z(k+1)< r * Z(k) (with r=(x+2)/27<1) for every k, and the series converges. For x=25 the series diverges too (I think so), because Z(k+1)/Z(k) tends to 1 for k tending to infinity. Christian Ronse maldoror@prlb2.UUCP {uunet|philabs|mcvax|...}!prlb2!{maldoror|ronse} Time is Mona Lisa #! rnews 1248 Path: alberta!mnetor!uunet!mcvax!botter!star!sater From: sater@cs.vu.nl (Hans van Staveren) Newsgroups: comp.dcom.lans,comp.sys.ibm.pc Subject: Need info on hardware Western Digital EtherCard PLUS Keywords: moron suppliers, Ethernet, IBM PC's Message-ID: <608@sater.cs.vu.nl> Date: 8 Dec 87 14:11:10 GMT Organization: V.U. Informatica, Amsterdam, the Netherlands Lines: 18 Xref: alberta comp.dcom.lans:906 comp.sys.ibm.pc:9572 We recently acquired some Western Digital EtherCard PLUS cards for IBM PC's. We were planning to write MINIX drivers for them and we wanted the hardware documentation from the supplier. We were indeed promised that. However, as one might expect, we only got the documentation that stated where to plug in the cable, and we are more interested in which IO-ports there are, and what they do. Our supplier is not very helpful at the moment. We will continue to nag our supplier, but in the meantime, does anyone have the hardware info on this board? We know there is a NatSemi DP8390 on there, and we have the datasheet on that one, but there should also be an Ethernet Address Rom, plus some other things on the board. As they say, thanks in advance. Hans van Staveren Vrije Universiteit Amsterdam, Holland #! rnews 742 Path: alberta!mnetor!uunet!mcvax!nikhefk!marcel From: marcel@nikhefk.UUCP (Marcel Corbeek) Newsgroups: rec.music.synth Subject: Question Message-ID: <292@nikhefk.UUCP> Date: 8 Dec 87 15:59:15 GMT Reply-To: marcel@nikhefk.UUCP (Marcel Corbeek) Organization: Nikhef-K, Amsterdam (the Netherlands). Lines: 15 Is there anybody who can give me some information about the WERSI stageperformer? Marcel Corbeek, Arpanet : marcel@nikhefk.uucp NIKHEF-K, Amsterdam. Bitnet : v59u0002@hasara11.bitnet Home address : Aletta Jacobsstraat 48, 1628 NP Hoorn, The Netherlands. Marcel Corbeek, Arpanet : marcel@nikhefk.uucp NIKHEF-K, Amsterdam. Bitnet : v59u0002@hasara11.bitnet Home address : Aletta Jacobsstraat 48, 1628 NP Hoorn, The Netherlands. #! rnews 1193 Path: alberta!mnetor!uunet!mcvax!targon!wim From: wim@targon.UUCP (Wim C. J. van Eerdt) Newsgroups: comp.lang.c++ Subject: Another C++ problem, solved (?) Message-ID: <368@targon.UUCP> Date: 8 Dec 87 15:33:45 GMT Reply-To: wim@targon.UUCP (Wim C. J. van Eerdt) Organization: Nixdorf Computer BV., OSP, P.O. Box 29,Vianen, The Netherlands Lines: 27 I did get yet another file from my colleague Gerard. As in other articles stated send he is not reachable by e-mail. I shall forward your mail! Success and have fun! Wim --------Fix--------------------------------------------------------- Author: Gerard van Dorth Subject: Another C++ problem, solved (?) > Yet another crazy C++ problem > ... > The below code is a generalization of a problem we are seeing with C++ > ... Substitute the line Pfct f = Pfct(Pptr(q->tp)->typ); in routine call::simpl of the file simpl.c by Ptype pt = q->tp; while (pt->base == TYPE) pt = Pbase(pt)->b_name->tp; Pfct f = Pfct(Pptr(pt)->typ); // for basic type only. (Simpl(e) turns out to be hard). -- Wim van Eerdt E-mail: mcvax!targon!wim OSP, Nixdorf Computer Bv, Postbus 29, 4130 EA Vianen Nederland. Tel.: +31 3473 62211. #! rnews 1046 Path: alberta!mnetor!uunet!mcvax!cogpsi!tom From: tom@cogpsi.UUCP (Tom Vijlbrief) Newsgroups: comp.unix.wizards Subject: Re: Unattended dumps (BSD4.3) Message-ID: <327@cogpsi.UUCP> Date: 8 Dec 87 15:51:57 GMT References: <9032@santra.UUCP> Reply-To: tom@cogpsi.UUCP (Tom Vijlbrief) Organization: TNO Institute for Perception, Soesterberg, The Netherlands Lines: 21 In article <9032@santra.UUCP> nispa@hutcs.hut.fi (Tapani Lindgren) writes: >Can yes(1) somehow be piped to a program that reads /dev/tty? >Could dump(8) be modified to abort at errors without any questions? If you want dump to read the output from e.g. yes(1) then you'll have to use a pty(4). You should arrange that this pty is the control terminal of the dump program and then write (redirect) the output of yes(1) to the pty. Setting the control terminal of dump is done by writing a program which: A) Removes the association with its control terminal by: ioctl(f, TIOCNOTTY, 0); B) Opens the pty. C) Exec's the dump program. The above applies to Berkeley Unix 4.X #! rnews 1034 Path: alberta!mnetor!uunet!mcvax!botter!ark!maart From: maart@cs.vu.nl (Maarten Litmaath) Newsgroups: comp.unix.wizards Subject: Re: Emacs csh alias -- better solution than the first posted (2) Summary: this time really faster Keywords: this time really faster Message-ID: <1160@ark.cs.vu.nl> Date: 8 Dec 87 16:55:49 GMT References: <1508@ogcvax.UUCP> <1159@ark.cs.vu.nl> Reply-To: maart@cs.vu.nl (Maarten Litmaath) Organization: VU Informatica, Amsterdam Lines: 17 Of course the alias had to be: alias emacs \ 'jobs > /tmp/jobs; grep emacs /tmp/jobs > /dev/null && fg %?emacs || /bin/emacs' ^ ^^^^^ ! !!!!! or !! vv alias em \ 'jobs > /tmp/jobs; grep emacs /tmp/jobs > /dev/null && fg %emacs || emacs' Sorry. -- Time flies like an arrow, fruit flies |Maarten Litmaath @ Free U Amsterdam: like an orange. (seen elsewhere) |maart@cs.vu.nl, mcvax!botter!ark!maart #! rnews 691 Path: alberta!mnetor!uunet!mcvax!botter!ark!maart From: maart@cs.vu.nl (Maarten Litmaath) Newsgroups: comp.unix.wizards Subject: Re: Emacs csh alias -- better solution than the first posted Summary: faster Keywords: faster Message-ID: <1159@ark.cs.vu.nl> Date: 8 Dec 87 15:41:32 GMT References: <1508@ogcvax.UUCP> Reply-To: maart@cs.vu.nl (Maarten Litmaath) Organization: VU Informatica, Amsterdam Lines: 7 alias emacs \ 'jobs > /tmp/jobs; grep emacs /tmp/jobs > /dev/null && fg %emacs || emacs' BTW, long live vi! -- Time flies like an arrow, fruit flies |Maarten Litmaath @ Free U Amsterdam: like an orange. (seen elsewhere) |maart@cs.vu.nl, mcvax!botter!ark!maart #! rnews 987 Path: alberta!mnetor!uunet!mcvax!mhres!jv From: jv@mhres.mh.nl (Johan Vromans) Newsgroups: comp.unix.questions Subject: Re: UCB 2.9 LISP goes illegal Summary: sysmac.sml? RT-11 Message-ID: <1498@mhres.mh.nl> Date: 8 Dec 87 21:16:13 GMT References: <10712@brl-adm.ARPA> Organization: Multihouse N.V., The Netherlands Lines: 12 In article <10712@brl-adm.ARPA> PAAAAAR%CALSTATE.BITNET@CUNYVM.CUNY.EDU writes: >We are trying to make LISP run on an 11/24 (yes they still exist) >What is sysmac.sml, for instance? That reminds me to the goold old days, when PDP-11's ran only RSX, RT-11 or RSTS. Sysmac.sml is a macro library, which contains the definitions for the RT-11 "Programmed Requests" (nowadays known as system calls). Don't think it's equivalent exists on Unix ... -- Johan Vromans | jv@mh.nl via European backbone Multihouse N.V., Gouda, the Netherlands | uucp: ..{uunet!}mcvax!mh.nl!jv "It is better to light a candle than to curse the darkness" #! rnews 6100 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!srp From: srp@ethz.UUCP (Scott Presnell) Newsgroups: rec.games.hack,comp.sources.d Subject: Re: Compilation of Nethack 2.2 Keywords: AAARGH. Message-ID: <262@bernina.UUCP> Date: 8 Dec 87 06:13:59 GMT References: <9714@shemp.UCLA.EDU> Reply-To: srp@bernina.UUCP (Scott Presnell) Organization: Chem. Dept., Swiss Federal Inst. of Tech. (ETH-Zurich) Lines: 211 Xref: alberta rec.games.hack:1746 comp.sources.d:1578 In article <9714@shemp.UCLA.EDU> claus@CS.UCLA.EDU (Claus Giloi) writes: >I just downloaded Nethack 2.2 from the net and compiled it on my AT >at home. >There were only a few small problems, then it came to linking the >monster. An executable was produced, but I get a "Stack Overflow" >error when I try to run the 350K executable, and changing the >value of (STACK:) to outlandish figures (8000, 3fff) didn't change >that. Someone out there must have gotten it to run, please tell me >what value you used to link it. (I am using MSC 4.0) Here's the makefile that I used to get Nethack up under MSC 4.0... NB: the CFLAGS macro and the link command. I was able to play a couple of levels without stack errors or hangups, however there are some problems, (everything seems to be identified, inventory not displayed correctly, color not quite right (but overall it works)) so i did not "install" it. "good luck, jim" Scott Presnell Organic Chemistry Swiss Federal Institute of Technology (ETH-Zentrum) CH-8092 Zurich, Switzerland. uucp:seismo!mcvax!cernvax!ethz!srp (srp@ethz.uucp); bitnet:Benner@CZHETH5A # SCCS Id: @(#)Makefile.pc 2.2 87/11/11 # Makefile for NetHack (PC) version 1.0 written using # Microsoft(tm) "C" v3.0 or better. # # Large memory model, register bug, remove stack probes: WIZARD= V = 22 #CFLAGS = -A$(MODEL) -DREGBUG -DLINT_ARGS -DVER=$V $(WIZARD) -Ot -Gs -Gt100 CFLAGS = -nologo -A$(MODEL) -DLINT_ARGS -DVER=$V -Ox -Gt10 CC = cl LIBS = LFLAGS = MODEL = L SETARGV = #$(LIB)\$(MODEL)SETARGV .SUFFIXES: .exe .obj .c .c.obj:; cl $(CFLAGS) -c $*.c .c.exe:; cl $(CFLAGS) -c $*.c link $*.obj $(SETARGV), $@,, $(LIBS) $(LFLAGS); # The game name GAME = hack.exe # The game directory GAMEDIR = \h # All object modules OBJS = decl.obj apply.obj bones.obj cmd.obj do.obj dothrow.obj\ do_name.obj do_wear.obj dog.obj dogmove.obj eat.obj end.obj \ engrave.obj fight.obj fountain.obj hack.obj invent.obj \ lev.obj main.obj makemon.obj mhitu.obj mklev.obj \ mkmaze.obj mkobj.obj mkshop.obj mon.obj monmove.obj\ monst.obj o_init.obj objnam.obj options.obj \ pager.obj polyself.obj potion.obj pray.obj pri.obj prisym.obj\ read.obj rip.obj rumors.obj save.obj \ search.obj shk.obj shknam.obj sit.obj spell.obj steal.obj \ termcap.obj timeout.obj topl.obj topten.obj track.obj trap.obj \ tty.obj unix.obj u_init.obj vault.obj wield.obj \ wizard.obj worm.obj worn.obj write.obj zap.obj \ version.obj rnd.obj alloc.obj msdos.obj # The main target - you may want to try both of these alternatives. # $(GAME) : $(OBJS) # link $(OBJS), $(GAME) /NOIG /STACK:4000 /CP:1; link $(OBJS), $(GAME) /NOIG /STACK:10000 /SEG:512; # variable auxilary files. # VARAUX = data rumors install : $(GAME) $(VARAUX) - exepack $(GAME) $(GAMEDIR)\$(GAME) - exemod $(GAMEDIR)\$(GAME) /max 1 clean : erase $(GAME) spotless: clean erase *.obj erase main.c erase tty.c erase unix.c srcs : copy makefile \tmp copy *.c \tmp copy *.h \tmp copy \local\make\make.doc \tmp copy \local\make\make.ini \tmp copy \bin\make.exe \tmp cd \tmp time touch *.* arc m hack$Vs * *.* cd $(CWD) # Other dependencies # RUMORFILES= rumors.bas rumors.kaa rumors.mrx makedefs.exe: makedefs.c alloc.obj config.h cl -AL makedefs.c alloc.obj rumors : config.h $(RUMORFILES) makedefs.exe makedefs.exe -r data : config.h data.bas makedefs.exe makedefs.exe -d onames.h : config.h objects.h makedefs.exe makedefs.exe -o # Below is a kluge. date.h should actually depend on any source # module being changed. (but hack.h is close enough for most). # date.h : hack.h makedefs.exe makedefs.exe -D trap.h : config.h makedefs.exe makedefs.exe -t main.obj : pcmain.c hack.h $(CC) $(CFLAGS) -Fo$@ -c pcmain.c tty.obj : pctty.c hack.h msdos.h $(CC) $(CFLAGS) -Fo$@ -c pctty.c unix.obj : pcunix.c hack.h mkroom.h $(CC) $(CFLAGS) -Fo$@ -c pcunix.c decl.obj : hack.h mkroom.h apply.obj : hack.h edog.h mkroom.h bones.obj : hack.h hack.obj : hack.h cmd.obj : hack.h func_tab.h do.obj : hack.h do_name.obj : hack.h do_wear.obj : hack.h dog.obj : hack.h edog.h mkroom.h dogmove.obj : hack.h mfndpos.h edog.h mkroom.h dothrow.obj : hack.h eat.obj : hack.h end.obj : hack.h engrave.obj : hack.h fight.obj : hack.h fountain.obj : hack.h mkroom.h invent.obj : hack.h wseg.h ioctl.obj : config.h lev.obj : hack.h mkroom.h wseg.h makemon.obj : hack.h mhitu.obj : hack.h mklev.obj : hack.h mkroom.h mkmaze.obj : hack.h mkroom.h mkobj.obj : hack.h mkshop.obj : hack.h mkroom.h eshk.h mon.obj : hack.h mfndpos.h monmove.obj : hack.h mfndpos.h monst.obj : hack.h eshk.h msdos.obj : msdos.h o_init.obj : config.h objects.h onames.h objnam.obj : hack.h options.obj : hack.h pager.obj : hack.h polyself.obj : hack.h potion.obj : hack.h pray.obj : hack.h pri.obj : hack.h prisym.obj : hack.h wseg.h read.obj : hack.h rip.obj : hack.h rumors.obj : hack.h save.obj : hack.h search.obj : hack.h shk.obj : hack.h mfndpos.h mkroom.h eshk.h shknam.obj : hack.h sit.obj : hack.h spell.obj : hack.h steal.obj : hack.h termcap.obj : hack.h timeout.obj : hack.h topl.obj : hack.h topten.obj : hack.h track.obj : hack.h trap.obj : hack.h edog.h mkroom.h u_init.obj : hack.h vault.obj : hack.h mkroom.h wield.obj : hack.h wizard.obj : hack.h worm.obj : hack.h wseg.h worn.obj : hack.h write.obj : hack.h zap.obj : hack.h version.obj : hack.h date.h extern.h: config.h spell.h obj.h touch extern.h hack.h: extern.h flag.h gold.h monst.h objclass.h rm.h trap.h you.h touch hack.h objects.h: config.h objclass.h touch objects.h you.h: config.h onames.h permonst.h touch you.h #! rnews 3561 Path: alberta!mnetor!uunet!mcvax!cernvax!jmg From: jmg@cernvax.UUCP (jmg) Newsgroups: comp.protocols.appletalk Subject: Kinetics/NCSA problems Message-ID: <581@cernvax.UUCP> Date: 8 Dec 87 10:01:07 GMT Reply-To: jmg@cernvax.UUCP () Organization: CERN European Laboratory for Particle Physics, CH-1211 Geneva, Switzerland Lines: 58 This is a bit of a flame, which I hope does not upset some people too much. I have tried sending the comments privately, but have had no reply. I got a Kinetics internal Ethernet interface for a Mac SE, plus the ethernet driver, test software and NCSA telnet version 1.12. In order to try out this software in a safe manner I created a mini- -Ethernet with the Mac and an Ethernet monitor. Am I glad that I did this! The test software, when run, tends to throw out a large number of broadcast packets in a very short space of time. Sometimes one can control the frequency, other times not. At least one test threw out about 200 broadcast packets in much less than one second. If I had been on the real CERN Ethernet then a few hundred users would have had to deal with these! FLAME ON When will people writing test software avoid the intensive use of broadcast packets? Multicast would be slightly better, but even then the software should establish the address of those other computers with which it can run a test, and then address them directly. FLAME OFF (for a while) I then tried to run NCSA telnet. This also started out with about 70 immediate broadcasts. These started out with a set of three types of broadcast: 1. arp with source ip address 0.0.0.255, looking for 0.0.0.127 2. something with type field 80f3 (what the hell is this?) 3. some other arp-type (type field 809b) with sender as 0.0.0.127 These three are repeated about 20 times at intervals of about 10 milliseconds (yes, milliseconds!). There are then a few more type 809b broadcasts at reasonable (a few hundred milliseconds!) intervals before telnet starts to arp for the real host that I asked for. FLAME ON Why does software often insist on repeating packets at very short intervals on vey reliable LANs (and have you seen the Sun lately!)? FLAME OFF Despite all the above, I waited for a quiet moment before connecting onto the real Ethernet. I then tried telnet to our Ultrix Vax. Immediate remark: keyboard in application mode does not work for us. I then thought to run the vt100 test program (which some of you might also have picked up off usenet). What a disaster: the emulation fails all over the place! Never mind, let us see if I can connect to our IBM VM system. Of course, I have to go via a Spartacus KNET, because there is no NCSA tn3270 (is anyone working on this?). Complete failure: Spartacus has a bit of a peculiar telnet setup (though Ultrix, bsd4.2 and FTP Inc. telnet on a PC work fine) which seems to screw NCSA telnet. Final try: go through an IBM 7171 front-end, which has 3270 to VT100 built in. Sort of works (using ESC n for PF key n), but since the application keypad mode fails there is no way that I could get PA2 for clear screen. Merde (which the French will understand. FLAME ON I know that NCSA is now at version 2.0. Why did I get version 1.12 from Kinetics? (and why must only a Kinetics agent modify their Mac SCSI box for a European power supply?). How do I get an updated version quickly (no, I cannot do anonymous FTP!). Why have these simple tests never been reported before? etc. etc. FLAME OFF I would be delighted if someone could tell me that all the above problems are fixed in the current release! #! rnews 1102 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!wanner From: wanner@ethz.UUCP (Juerg Wanner) Newsgroups: rec.games.misc Subject: Re: The Pawn help Message-ID: <263@bernina.UUCP> Date: 8 Dec 87 14:48:50 GMT References: <2884@cbmvax.UUCP> <2299@killer.UUCP> <2910@cbmvax.UUCP> Reply-To: wanner@owf.UUCP (Juerg Wanner) Organization: OWF AG, Switzerland Lines: 17 Keywords: In article <2910@cbmvax.UUCP> daveb@cbmvax.UUCP (Dave Berezowski) writes: >How does one assure that they get the chest? Wait around for Kronos at the >beginning of the game after you've delivered the note? After delivering the note? Hmmm... that might be too late. >I've been told that there is a bug in the game such that you must get to >the pedestal asap else the blue key won't be there (this is what has happended >to me). If I do go to the pedestal first, will I miss the Adventuer and >Kronos? ie. should I wait around for Kronos, give the adventuer (with the >chest I guess), and then go for the blue key? I've neither encountered that bug, nor did I first get the key. There's a lot one can do before. Juerg Wanner #! rnews 2241 Path: alberta!mnetor!uunet!mcvax!nikhefk!paulm From: paulm@nikhefk.UUCP (Paul Molenaar) Newsgroups: comp.sys.mac Subject: Re: HyperCard Find Summary: Here's the solution (well...) Message-ID: <293@nikhefk.UUCP> Date: 8 Dec 87 23:45:24 GMT References: <1262@runx.ips.oz> Organization: Nikhef-K, Amsterdam (the Netherlands). Lines: 50 In article <1262@runx.ips.oz>, clubmac@runx.ips.oz (Macintosh Users Group) writes: > > I was asked this question by a guy on the weekend, and was unable to help > him. Any of you Hypercard gurus able to answer?? > > "I want to have a BACKGROUND button which has a script that tries to FIND > an arbitrary text. However, when I try it, it only finds the text in > BACKGROUND fields, not FOREGROUND. The FIND works properly when you use > the MESSAGE box.. how come?" > > Jeff Laing (where for art thou comp.sys.mac.hypercard?) > Same problem here. I noticed that strange Find bug too. My solution is a real kludge, but it works. Instead of issuing the FIND command in script, TYPE the FIND command with all the arguments into the message box and then (again from script) add a return. Like: on mouseUp type "FIND" && quote & key & quote && "in background field id" && number & return end mouseUp This also makes the repeated FIND easier. I made a stack that needed a search option on partial keys. So I wanted HC to keep on looking when the user stated that the item found wasn't the right one. I made a script to do this (if interested I can mail/post it) that expects a second field for every field to be looked in. The item found is put in the second field (named something like showName). When the user says he wants to keep on searching, the next item found is compared to the contents of showName. If it's the same, my script says that 'it's all there is'. And cancels the search. Otherwise a repeated search would be impossible. If you like I can upload the lot. To comp.sys.mac.hypercard maybe? To Apple: Why do you reply to all the easy answers in comp.sys.mac.hypercard bu happily skip all the possibly difficult ones? Seems like the HyperCard group chooses the easy way out. Too many bugs in HC perhaps? -- Paul Molenaar "Just checking the walls" - Basil Fawlty - #! rnews 704 Path: alberta!mnetor!uunet!mcvax!enea!tut!santra!kolvi!jku From: jku@kolvi.UUCP (Juha Kuusama) Newsgroups: comp.sys.ibm.pc Subject: Screen dump from Hercules to Laserjet wanted Message-ID: <31@kolvi.UUCP> Date: 8 Dec 87 12:19:56 GMT Reply-To: jku@kolvi.UUCP (Juha Kuusama) Organization: Helsinki University of Technology, Finland Lines: 10 Could some kind soul over there send me a program/a reference to a program, that would allow me to print a graphics dump from a Hercules screen to a HP Laserjet printer It should a) not distort the image (circles as circles, not ovals) b) send its output to a file (so I can import it to my text). -- Juha Kuusama, jku@kolvi.UUCP ( ...!mcvax!tut!kolvi!jku ) #! rnews 1093 Path: alberta!mnetor!uunet!mcvax!enea!tut!santra!jmunkki From: jmunkki@santra.UUCP (Juri Munkki) Newsgroups: comp.sys.mac Subject: Re: Development Environment Advice Wanted Keywords: Development, MacII Debuggers Message-ID: <9206@santra.UUCP> Date: 8 Dec 87 16:51:43 GMT References: <687@howtek.UUCP> <3456@husc6.harvard.edu> Reply-To: jmunkki@santra.UUCP (Juri Munkki) Organization: Helsinki University of Technology, Finland Lines: 16 In article <3456@husc6.harvard.edu> singer@endor.UUCP (THINK Technologies) writes: >The current version of MacsBug, version 5.5, works fine on a Mac II - >even disassembles 68020 and 68881 opwords, and works with or without And it slows down the 68881 by about 50%. Can anyone else verify this? I moved to TMON mainly because it does not affect the speed of my Mac. I hope none of the Byte or MacTutor benchmarks were run under MacsBug. Still, ES works better in MacsBug than it does in TMON. Juri Munkki jmunkki@santra.hut.fi jmunkki@fingate.bitnet lk-jmu@finhut.bitnet Disclaimer: I'm just a freelance programmer, you shouldn't listen to me anyway. #! rnews 1288 Path: alberta!mnetor!uunet!mcvax!diku!rancke From: rancke@diku.UUCP (Hans Rancke-Madsen.) Newsgroups: rec.games.frp Subject: Re: Re: Characters with two classes Message-ID: <3567@diku.UUCP> Date: 7 Dec 87 15:31:25 GMT References: <26561S9S@PSUVMA> <81800077@uiucdcsp> Organization: DIKU, U of Copenhagen, DK Lines: 23 In article <81800077@uiucdcsp> jenks@uiucdcsp.cs.uiuc.edu writes: > The PHB doesn't specifically forbid doing this >more than once, nor does it say what the "prime stat" is for Paladinks, >Rangers, Monks, etc. I seem to recall having seen a statement like "since has no prime requisite, you can't switch to/from it." The implication being that any of the sub-classes that require more than one minimum is out as regards dual-class characters. So you could be a "fighter-turned- magician" but not a "ranger-turned-magician". I think it was in one of THE BOOKS, but I'm not certain. One thing you could do is to require 15 or 17 in ALL the requisites with minimums. That will restrict the number of assasin/illusionists!!! Hans Rancke, University of Copenhagen ..mcvax!diku!rancke --=-=-=-=-=-=-=-=-=-=-=-=-=-=- - I hate it when people call me paranoid. It makes me feel persecuted. #! rnews 456 Path: alberta!mnetor!uunet!mcvax!diku!iesd!torbennr From: torbennr@iesd.uucp (Torben N. Rasmussen) Newsgroups: comp.sources.wanted Subject: Wanted: Microemacs part 8 Message-ID: <166@iesd.uucp> Date: 7 Dec 87 08:15:25 GMT Reply-To: torbennr@neumann.UUCP (Torben N. Rasmussen) Organization: Dept. of Comp. Sci., Aalborg University, Denmark Lines: 7 Could someone please send me part 8 of the sources for Microemacs. -- Torben Rasmussen (torbennr) #! rnews 1138 Path: alberta!mnetor!uunet!mcvax!diku!dde!jk From: jk@dde.uucp (Jens Kjerte) Newsgroups: comp.sources.wanted,comp.text Subject: Sourcecode for dca2troff wanted. Keywords: DCA conversion. Message-ID: <277@Aragorn.dde.uucp> Date: 8 Dec 87 09:11:32 GMT Organization: Dansk Data Elektronik A/S, Herlev, Denmark Lines: 18 Xref: alberta comp.sources.wanted:2716 comp.text:1345 We are right now starting a project, that involves translating IBM DCA documents to and from a wordprocessing package. A program called dca2troff was posted sometime ago. This program, as the name says, was able to convert from DCA format to troff format. Would somebody having that source, please e-mail it to me. Other information about software regarding DCA conversion, Public Domain or not, would be appreciated. Thanks in advance -- +---------------------------------------------------------------------------+ | Jens Kjerte @ Dansk Data Elektronik A/S, Systems Software Department | | E-mail: ..!uunet!mcvax!diku!dde!jk or jk@dde.uucp | +---------------------------------------------------------------------------+ #! rnews 1323 Path: alberta!mnetor!uunet!mcvax!diku!dde!ct From: ct@dde.uucp (Claus Tondering) Newsgroups: sci.physics Subject: Maxwell's daemon Message-ID: <279@Aragorn.dde.uucp> Date: 8 Dec 87 13:57:45 GMT Organization: Dansk Data Elektronik A/S, Herlev, Denmark Lines: 26 Consider the following variant of Maxwell's daemon: You have the following two items: 1) a metal block, 2) a bowl with a liquid. Both items have the same temperature and are placed close together, they may, however, be thermally isolated from one another. Now into the bowl you drop a very small magnet. The motion of the molecules in the liquid will cause the magnet to move slightly. This will induce a (very small) current in the metal block. This current will cause the temperature of the metal block to rise. The current will also try to stop the movements of the magnet; this will in turn slow down the motion of the molecules, and the liquid will cool. The result: The metal block will grow warmer and warmer, and the liquid will grow colder and colder. This contradicts the second law of thermodynamics, and has the "advantage" over Maxwell's daemon that no intelligence is involved. What is wrong with the above argument? -- Claus Tondering Dansk Data Elektronik A/S, Herlev, Denmark E-mail: ct@dde.uucp or ...!uunet!mcvax!diku!dde!ct #! rnews 2476 Path: alberta!mnetor!uunet!mcvax!enea!sommar From: sommar@enea.UUCP (Erland Sommarskog) Newsgroups: rec.music.misc Subject: Swedish prog-rock (was Re: More than Yes) Message-ID: <2505@enea.UUCP> Date: 8 Dec 87 23:22:11 GMT References: <19949@yale-celray.yale.UUCP> Reply-To: sommar@enea.UUCP(Erland Sommarskog) Followup-To: rec.music.misc Organization: ENEA DATA Svenska AB, Sweden Lines: 42 No isn't that an obscure subject line? But I must correct my fellow-countryman here. Bjorn Lisper (lisper@yale-celray.UUCP) writes: >Bo Hansson, to be correct. Gee, I didn't know that he was known outside >Sweden. This guy was a keyboard player who was active mainly in the late >sixties and early seventies. He is remembered for having made the very >first record for the first Swedish independent non-profit label "Silence". >Unexpectedly the record became a hit and the income helped financing a lot >of records with early Swedish prog-rock that would otherwise not have been >economically possible to make. Thus his importance for Swedish rock music >cannot be overestimated. So he is the one being guilty to it all. Grr. You see, in Sweden "progressive" music had nothing to do with the music. When we speak - or spoke at that time - of "progressive" groups, we talked of groups that played quite regular rock or pop. There were just one difference to the ordinary hit music, the lyrics. They were naive, trivial and uttermost boring political texts of a communistic nature. (Which does not imply that they were paid by KGB or something.) I must admit I didn't listen to much to them, their proganda was too much for me. Now, this kind of people dominated this non-profit companies that Bjorn talked of. For them ideological purity was much more important than interesting than good music. Not to be denied, *some* good music was actually released on Silence and MNW (the other big non-profit), but also a lot of true crap. And I can easily imagine that groups with interesting music was refused beacuse they voted with the wrong party. (They would never have released Yes, that are right wing if anything.) Finally, I should admit that despite the poorness of Silence, they had the most interesting music in Sweden at that time. But that more gives an indication of bad the rest was. (Abba, do you remember?) -- Erland Sommarskog ENEA Data, Stockholm sommar@enea.UUCP C, it's a 3rd class language, you can tell by the name. #! rnews 2310 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!forty2!poole From: poole@forty2.UUCP (Simon Poole) Newsgroups: comp.sys.atari.st Subject: Re: GEMBOOT and the Megas Message-ID: <122@forty2.UUCP> Date: 8 Dec 87 14:19:44 GMT References: <608@aucs.UUCP> <900@atari.UUCP> Reply-To: poole@forty2.UUCP (Simon Poole) Organization: Exp. Physics University Zuerich Lines: 39 In article <900@atari.UUCP> apratt@atari.UUCP (Allan Pratt) writes: >in article <608@aucs.UUCP>, 870646c@aucs.UUCP (barry comer) says: >> >> Hi all, well my Mega2 just landed on my desk, really nice. I've got a question for all other Mega owners using the hard disks, I have been using GEMBOOT with >> my 1040ST all along, when I boot up the Mega two bombs appear then disappear >> after GEMBOOT has done its thing. > >DO NOT USE GEMBOOT. Use FOLDRXXX from Atari. HINSTALL should be available, >too... It makes your hard disk bootable (no "boot floppy" needed). > The lastest version of GEMBOOT which was distributed something like half a year ago, allows you to set the location of the sole undocumented variable that Konrad uses in GEMBOOT. Matter of fact I used GEMBOOT without problems on one of the first Mega's that arrived in Switzerland after changing the GEMBOOT startup file. >patches the appropriate location in the OS. In the case of the Mega >ROMs, he actually added a pointer in the OS header which points to >the necessary spot, so FOLDRXXX will work for all future ROM releases. ^^^^^^^^^^^^^^ Didn't Atari claim it was working on a new '40 folder bug'less OS? >Even old TOS ROM users should probably not use GEMBOOT... I certainly >wouldn't trust it, and with FOLDRXXX and HINSTALL available, you just >don't need it. Hmmmm, as Landon Dyer once said (a long time ago) FOLDRXXX does NOT fix the other problem with GEMDOS management of the internal directory list (mutiple bad copies of the same block), GEMBOOT does provide a workaround for this problem (so I wouldn't trust FOLDRXXX) plus a lot of other nice things. Simon Poole UUCP: ....mcvax!cernvax!forty2!poole Bitnet: K538915@CZHRZU1A * ***************When will Atari annouce PC-6 to PC-10?**************** * #! rnews 1572 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!bob From: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Newsgroups: rec.arts.sf-lovers Subject: Re: Blake's, all 7 of them! Message-ID: <818@its63b.ed.ac.uk> Date: 8 Dec 87 10:08:31 GMT References: <6320@ihlpa.ATT.COM> <1572@cup.portal.com> <1372@aurora.UUCP> Reply-To: bob@its63b.ed.ac.uk (ERCF08 Bob Gray) Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 28 In article <1372@aurora.UUCP> timelord@aurora.UUCP (G. "Murdock" Helms) writes: >In article <1572@cup.portal.com>, Isaac_K_Rabinovitch@cup.portal.com writes: >> Whoops. After the Star One episode, the actor who played >> Blake got a job with the National Shakespeare Company, so Blake essentially >> disappears until the "last" episode. > >The second Travis, the one with the really thick Cockney accent, >was spotted in the BBC movie "Edge of Darkness" recently broadcast >in California. Something else to watch out for. The recently concluded series "Knights of God" on independant television was notable only for having Gareth Thomas (Blake himself) playing the part of the leader of a band of rebels trying to overthrow the harsh Goverment sometime in the future UK. Almost a reprise of his part as blake, but he isn't even one of the major characters. His name comes about eighth on the credits. Now we know what he was doing while he was missing from Blake's Seven. :-> Also look out for the second Dr Who, Patrick Troughton, in a supporting role. Note: I do Not recommend this series for any other reson than the above mentioned curiosity value. Bob #! rnews 2656 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!csnjr From: csnjr@its63b.ed.ac.uk (Nick Rothwell) Newsgroups: comp.lang.lisp,comp.lang.scheme,comp.lang.misc Subject: Re: Applicative languages? Anyone? Keywords: ML interpreter typechecker Message-ID: <819@its63b.ed.ac.uk> Date: 8 Dec 87 12:40:13 GMT References: <1409@mind.UUCP> <584@zippy.eecs.umich.edu> <1202@uoregon.UUCP> Reply-To: nick%ed.lfcs@uk.ac.ucl.cs.nss (Nick Rothwell) Organization: LFCS, University of Edinburgh Lines: 37 Xref: alberta comp.lang.lisp:566 comp.lang.scheme:85 comp.lang.misc:886 In article <1202@uoregon.UUCP> markv@drizzle.UUCP (Mark VandeWettering) writes: >In article <584@zippy.eecs.umich.edu> dwt@zippy.eecs.umich.edu (David West) writes: >>Applicativity has its advantages, but it needs >>1) ... >>2) Some syntactic means for preventing argumentsfrom getting unreadably >> numerous just to pass something down to where it's finally used. > > Hmmm, not a bad idea. I have just acquired "Implementation of > Functional Programming Languages by Simon L. Peyton Jones, and > am much impressed by the depth/level of the text. Seeing as I > have to do a final thesis/project sometime :-) I might be > tempted to try a hand at an ML interpreter/compiler. I would > like to hear from anyone who is trying/has tried similar > projects. ML gives you objects with modifiable state, so that you don't need to pass a state structure around with you. The disadvantage, of course, is that you smash the applicative behaviour of the language - whether it's worth it depends what you're trying to do. Another way around this is to use type abstraction. That way, your state structure is an abstract object with a few access functions to get at the bits you need. I've always used the former approach, so I don't know how far the latter approach gets you. It's quite possible to take non- applicative features like assignment and abstract over them to build structured objects with varying state, a la Smalltalk perhaps. This isn't "dirty" functional programming - it's just using a functional language as if it were a language of a different kind. I recently dedicated a lecture to the structured use of side-effects in ML. By the way, I have various little typecheckers and interpreters for tiny functional languages lying around on-line somewhere, if you're interested. All written in ML, of course. -- Nick Rothwell, Laboratory for Foundations of Computer Science, Edinburgh. nick%lfcs.ed.ac.uk@nss.cs.ucl.ac.uk !mcvax!ukc!lfcs!nick ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "Nothing's forgotten. Nothing is ever forgotten." - Herne #! rnews 1368 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!csnjr From: csnjr@its63b.ed.ac.uk (Nick Rothwell) Newsgroups: rec.music.synth Subject: D-50, D-550, MT-32, ??? Message-ID: <820@its63b.ed.ac.uk> Date: 8 Dec 87 13:01:30 GMT References: <633@elxsi.UUCP> <5470012@hplsla.HP.COM> Reply-To: nick%ed.lfcs@uk.ac.ucl.cs.nss (Nick Rothwell) Organization: LFCS, University of Edinburgh Lines: 17 In article <5470012@hplsla.HP.COM> steveb@hplsla.HP.COM (Steve Bye) writes: >The MT-32 is not a product of Roland's professional music products group. >It is a product of their home keyboards (upscale toys) department. It uses >technology develped for the D-50 and D-550. There is no comparison in >actual ussuage between a D-550 and an MT-32. I recently read a report from a British music journalist visiting Roland in Japan. Apparently (but *don't* quote me on this :-)) Roland are working on a rack-mount box with the same sorts of features as the MT-32 but aimed a bit more at the Pro market - presumably related to the MT-32 as the TX81Z is to the FB01. I'm keeping my wallet closed and my eyes open... -- Nick Rothwell, Laboratory for Foundations of Computer Science, Edinburgh. nick%lfcs.ed.ac.uk@nss.cs.ucl.ac.uk !mcvax!ukc!lfcs!nick ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "Nothing's forgotten. Nothing is ever forgotten." - Herne #! rnews 1563 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!icdoc!doc.ic.ac.uk!aw From: aw@doc.ic.ac.uk (Andrew Weeks) Newsgroups: comp.emacs Subject: uEmacs 3.9 - Function keys on Suns Message-ID: <144@gould.doc.ic.ac.uk> Date: 8 Dec 87 17:16:50 GMT Sender: aw@doc.ic.ac.uk Reply-To: aw@doc.ic.ac.uk (Andrew Weeks) Organization: Dept. of Computing, Imperial College, London, UK. Lines: 40 I have implemented, as an extension to the "VT100" option, some extra code to allow uEmacs to recognise the top, left and right function keys on Sun 3 consoles. ( I imagine they will work on Sun 2s as well). These keys, except for the cursor keys (R8,R10,R12 & R14), return a string of the form [ followed by 3 digits followed by 'z'. By interpreting the digits as an integer, and subtracting 128 to get a character, all the function keys can be made to simulate 'FN?' keys. Which they return depends on how the Sun keyboard is set up (with setkeys(1)). They won't work if you use Sun-windows and have a .ttyswrc file. Anyway - Here are the diffs: *** input.c Mon Nov 30 12:57:21 1987 --- input.c.orig Mon Nov 30 12:54:37 1987 *************** *** 364,376 **** #if VT100 if (c == '[' || c == 'O') { c = get1key(); ! if ( c >= 'A' ) ! return(SPEC | c); ! c = c - 48; ! c = (c*10) + get1key() - 48; ! c = (c*10) + get1key() - 176; ! get1key(); ! return ( SPEC | c ); } #endif return(META | c); --- 364,370 ---- #if VT100 if (c == '[' || c == 'O') { c = get1key(); ! return(SPEC | c); } #endif return(META | c); #! rnews 1248 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!jam From: jam@comp.lancs.ac.uk (John A. Mariani) Newsgroups: rec.arts.sf-lovers Subject: Re: Max Headroom Message-ID: <454@dcl-csvax.comp.lancs.ac.uk> Date: 8 Dec 87 18:47:18 GMT References: <82*quale@si.uninett> <3333@ihlpl.ATT.COM> Reply-To: jam@comp.lancs.ac.uk (John A. Mariani) Distribution: rec.arts.sf-lovers Organization: Department of Computing at Lancaster University, UK. Lines: 16 Having observed chat about the American Max series and comparisons with the UK series, I would like to point out that we (in the UK) have only seen the Pilot in terms of an action/adventure episode. Our Max series have really featured Max as a video DJ, and later as a talk show host. So, I have kept silent till now, but I reckon the action/adventure series you guys in the US of A are discussing must be worth watching! Anyone care to hazard a guess as to why we in the UK don't get your Max show; and do you get ours? -- "You see me now a veteran of a thousand psychic wars .. " UUCP: ...!seismo!mcvax!ukc!dcl-cs!jam | DARPA: jam%lancs.comp@ucl-cs JANET: jam@uk.ac.lancs.comp | Post : University of Lancaster, Department of Phone: +44 524 65201 ext 4467 | Computing, Bailrigg, Lancaster, LA1 4YR, UK. #! rnews 1017 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: rec.music.classical Subject: Minimalist recorder music, anyone? Message-ID: <1575@brahma.cs.hw.ac.uk> Date: 8 Dec 87 19:29:14 GMT Organization: Computer Science, Heriot-Watt U., Scotland Lines: 14 What minimalist music is performable by a recorder consort? Terry Riley's In C is the one and only thing I've found so far (almost no published minimal music is available in the UK - I have drawn a virtually complete blank at every major library and music shop in Scotland). I guess this resolves into two questions: does it exist, and if it does, can I get it? Do Glass et al have the same attitude to scores that AT&T does to source code? -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 1165 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: comp.sys.mac Subject: mathematical laser fonts Keywords: font, logic, PostScript, laser printer, symbols Message-ID: <1576@brahma.cs.hw.ac.uk> Date: 8 Dec 87 19:43:07 GMT Organization: Computer Science, Heriot-Watt U., Scotland Lines: 21 What mathematical laser fonts are available? What I need is: - logic and theoretical computer science symbols (like the old Ophir bitmap font, but with the squared-off set theory symbols used in domain theory); - symbols for the better known algebraic structures (N, Z, Q, A, R, C) (is there a font that looks like these do as usually printed?); - subscripts and superscripts with little enough leading not to sabotage inter-line spacing in programs like WriteNow; - maybe some of the more useful German capital letters. -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 1030 Path: alberta!mnetor!uunet!mcvax!ukc!cheviot!eas From: eas@cheviot.newcastle.ac.uk (Edward Scott) Newsgroups: rec.arts.sf-lovers Subject: Re: Obscure TV SF shows Message-ID: <2588@cheviot.newcastle.ac.uk> Date: 8 Dec 87 15:19:25 GMT References: <871201124327980.ABWD@Mars.UCC.UMass.EDU> <4100001@hpcllf.HP.COM> Reply-To: eas@cheviot (Edward Scott) Organization: Computing Laboratory, U of Newcastle upon Tyne, UK NE17RU Lines: 12 In article <4100001@hpcllf.HP.COM> jws@hpcllf.HP.COM (John Stafford x75743) writes: >Re: UFO > The wigs worn by the women on moonbase were of a purple hue and were > described (at least in the books the followed the series if not > actually on the air) as "anti-static wigs". About ten years ago I got a second hand copy of "UFO 1: Flesh Hunters" by Robert Miall. It is a Warner Paperback Library edition, printed with permission from Pan books (who presumably did the UK edition). I have't seen any since then. How many of these UFO novels were there? Did Robert Miall write anything else? #! rnews 542 Path: alberta!mnetor!uunet!mcvax!ukc!stc!pete From: pete@tcom.stc.co.uk (Peter Kendell) Newsgroups: rec.arts.sf-lovers Subject: No More Mel Message-ID: <488@stc-f.tcom.stc.co.uk> Date: 8 Dec 87 09:14:20 GMT Organization: STC Telecoms, London N11 1HB. Lines: 7 Hurrah, Hurrah!! -- ------------------------------------------------------------------------------ | Peter Kendell | | ...{uunet!}mcvax!ukc!stc!pete | ------------------------------------------------------------------------------ #! rnews 660 Path: alberta!mnetor!uunet!mcvax!ukc!stc!btnix!psanders From: psanders@btnix.axion.bt.co.uk (Bob-Cut Maniac) Newsgroups: comp.sys.mac Subject: SMALLTALK wanted Keywords: Mac SMALLTALK Message-ID: <635@btnix.axion.bt.co.uk> Date: 8 Dec 87 12:53:54 GMT Organization: British Telecom Research Labs, Martlesham Heath, IPSWICH, UK Lines: 10 Does anyone know of a PD SMALLTALK system for the Mac ?? Answers to me and I'll summarise on the Net. Paul. -- E-mail (UUCP) PSanders@axion.bt.co.uk (...!ukc!btnix!psanders) Organisation British Telecom Research Laboratories, Ipswich UK. "This mime of mortal life, in which we are apportioned roles we misinterpret..." #! rnews 628 Path: alberta!mnetor!uunet!mcvax!ukc!stc!root44!hrc63!trw From: trw@hrc63.co.uk (Trevor Wright Marconi Baddow) Newsgroups: comp.sys.ibm.pc Subject: M.Magee AUTOMENU - any knowledge Message-ID: <475@hrc63.co.uk> Date: 8 Dec 87 10:39:57 GMT Organization: GEC Hirst Research Centre, Wembley, England. Lines: 10 We have seen a demo of a tiny MS-DOS utility called AUTOMENU which makes building menus for PC users simple. We want to find who is the vendor of this utility, the cost, and any details of the command characters for the menu definition file. Any help appreciated. Trevor Wright yc23%a.gec-mrc.co.uk@nss.cs.ucl.ac.uk #! rnews 2646 Path: alberta!mnetor!uunet!mcvax!ukc!stc!datlog!dlhpedg!cl From: cl@dlhpedg.co.uk (Charles Lambert) Newsgroups: comp.lang.c Subject: Re: Address of array Message-ID: <329@dlhpedg.co.uk> Date: 8 Dec 87 13:30:45 GMT References: <126@citcom.UUCP> <163@mccc.UUCP> <422@xyzzy.UUCP> Sender: news@dlhpedg.co.uk Reply-To: cl@.co.uk (Charles Lambert) Organization: FSG@Data Logic Ltd, Queens House, Greenhill Way, Harrow, London. Lines: 56 In article <422@xyzzy.UUCP> throopw@xyzzy.UUCP (Wayne A. Throop) writes: >> pjh@mccc.UUCP (Peter J. Holsberg) >> OK - perhaps you had better tell us neophytes what you mean by the >> address of an array! > >Same as address of anything else. It is an address which, when >indirected, yields an array, and when "N" is added to it, yields the >address of an array which is itself a member of an array "N" elements >away from the array yielded by an indirection. > > [ several abstruse observations ] > >What could be simpler? Well, several other forms of explanation, I guess. This one confused me, and I *understand* the address of an array. (Just teasing) To put it another way.... Any object, of any type (integer, structure, array, etc.), has an address. Usually, if it is an object that occupies several words of memory, it is the address at which it begins. (Compiler theorists may be itching to tell me it might mean something else entirely; let's keep this simple.) The address of an object is the compiler's handle for manipulating it. You think of an object by its name; the compiler "thinks" of it by its address. The "address of an array" is the address that the compiler uses to access that array and to calculate the position of any element in the array. In C, the address of an array is the same as the address of its first element (array[0]). If you want to set up a pointer to the array, you get its address simply by naming it. Hence: pa = array; /* pa now contains the address of "array" */ which is exactly the same as pa = &array[0]; /* "&" means "address of", so pa contains the address of element [0] of "array" */ Now this is a slight quirk in C - the name of the array being a synonym for its address; for any other object (notably a struct) that is not true. If you want the address of a structure you must write ps = &mystruct; /* NOT ps = mystruct */ So we get back to the discussion from whence we came: why can't we be consistent and get the address of an array by pa = &array; ? To which the answer is: you can, with some compilers. [Further reading: The C Programming Language; Kernighan & Ritchie; pp.93-95] -------------------------- Charles Lambert #! rnews 1652 Path: alberta!mnetor!uunet!mcvax!unido!iaoobelix!vogt From: vogt@iaoobelix Newsgroups: comp.sys.dec Subject: Bug in BASIC-PLUS for RSTS V8.0? - (nf) Message-ID: <9900003@iaoobelix.UUCP> Date: 8 Dec 87 18:36:00 GMT Lines: 43 Nf-ID: #N:iaoobelix:9900003:000:1342 Nf-From: iaoobelix!vogt Dec 8 19:36:00 1987 I think I found a bug in BASIC-PLUS of RSTS V8.0. The following program isn't working in the right way. I tried to read some records from a file and to store them in an array. But after I read and stored all records, the array was completely empty. > 10 ON ERROR GOTO 1000 > 15 DIM IN$(100%) > 20 FIELD #1%, 3% as a$, 20% as i$, 15% as q$ > 30 OPEN 'foobar' as file #1%, recordsize 38% > 40 Z% = 0% > 50 Z% = Z% + 1% > 60 GET #15%, RECORD Z% > 70 IN$(Z%) = I$ > 75 PRINT IN$(Z%) > 80 GOTO 50 > 90 CLOSE #1% > 100 PRINT IN$(I%) FOR I% = 1% TO Z% - 1% > 110 GOTO 32767 > 1000 IF ERR = 11 THEN RESUME 90 > 1010 ON ERROR GOTO 0 > 32767 END The outputs in line 75 are alright, but those in line 100 aren't. Only blank lines appear there. I found out that if you change line 70 to 'IN$(Z%) = LEFT$(I$, 20%)' - which does nearly nothing different - it works correctly. Does anybody know a patch for this bug? Or does anybody know how to avoid this in an other way? Thanks in advance Gerald Vogt -------------------------------------------------------------------------- Fraunhofer Institut fuer Arbeitswirtschaft und Organisation Holzgartenstrasse 17 D-7000 Stuttgart 1 UUCP: ...{uunet!unido,pyramid}!iaoobel!vogt W-Germany Phone: (W-Germany) 711 6648191 -------------------------------------------------------------------------- #! rnews 3127 Path: alberta!mnetor!uunet!mcvax!hafro!gst!gunnar From: gunnar@gst.UUCP (Gunnar Stefnsson) Newsgroups: sci.math Subject: Re: Least-squares fitting Message-ID: <428@gst.UUCP> Date: 8 Dec 87 15:25:35 GMT References: <1823@culdev1.UUCP> <22191@cca.CCA.COM> <2301@utastro.UUCP> Reply-To: gunnar@gst.UUCP (Gunnar Stefansson) Organization: Marine Research Institute, Reykjavik Lines: 56 In article <2301@utastro.UUCP> bill@astro.UUCP (William H. Jefferys) writes: >In article <22191@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes: >~In article <1823@culdev1.UUCP> drw@culdev1.UUCP (Dale Worley) writes: >~>The normal least-squares fitting of a line to a set of points in the >~>plane assumes that the x-coordinates of the points are known to be >~>exact, and the y-coordinates have all the error. That is, chi^2 is >~>the sum of the squares of the distances from the points to the line in >~>a vertical direction. This introduces assymetry between the >~>coordinates. >~> >~>Is is known how to perform least-squares fitting where the "error" is >~>the perpendicular distance between the point and the line? > > >Actually, if both coordinates have error, it is essential that this >fact be taken into account. If you fail to do this, the result will be >*biased* -- the slope will be systematically underestimated, and >this bias will not go to zero as you take more and more points Hold on, isn't this statement a bit too strong? The answer to which method should be used ultimately depends on what the purpose of the estimations is. In fact, if the purpose is to estimate y for a given x, then ordinary least squares will do. In this case one is not really interested in getting the best estimates of the parameters but only in getting a good prediction. I claim that there are very few regression examples where one really cares whether or not the parameters are biased. In the large majority of cases one is much more interested in the goodness of prediction. In this case, one is interested in E[Y|X]. So if we model this quantity as linear in X, then the OLS estimates are BLUE. This will also give variances etc, all valid conditionally on X. It is my feeling that a lot of books overemphasize the so-called bias, since that is very often totally irrelevant. For example, some textbooks talk about biased parameter estimates when some variables are missing in a multiple regression. In reality OLS is estimating a better set of parameters than would the corresponding "unbiased" estimator (OLS in this case will give an unbiased estimate of the best surface based on the reduced set of variables). Certainly in this case, one can make a strong argument that all the talk about biasses is totally irrelevant. Of course if the true purpose is to estimate parameters, e.g. to assess the effect of a change in X on Y, then indeed one needs to worry a bit about the effects of X being random. Gunnar -- ----------------------------------------------------------------------------- Gunnar Stefansson {mcvax,enea}!hafro!gunnar Marine Research Institute, Reykjavik gunnar@hafro.UUCP #! rnews 528 Path: alberta!mnetor!uunet!mcvax!unido!tub!ao From: ao@tub.UUCP (Arnfried Ossen) Newsgroups: comp.mail.misc Subject: Path to UMass Amherst Message-ID: <318@tub.UUCP> Date: 7 Dec 87 13:29:49 GMT Reply-To: ao@tub.UUCP (Arnfried Ossen) Organization: Technical University of Berlin, Germany Lines: 7 Anybody out there who knows the PATH to University of Massachusetts, Amherst Campus, COINS Department It should allow access from USENET or BITNET. Arnfried, ao@tub.UUCP, ao@db0tui6.BITNET, TU Berlin, Berlin, Fed.Rep.Germany #! rnews 2902 Path: alberta!mnetor!uunet!mcvax!varol From: varol@cwi.nl (Varol Akman) Newsgroups: sci.math Subject: Re: computational geometry / finding segment intersections Summary: Try adaptive grid ... Keywords: segment intersection Message-ID: <141@piring.cwi.nl> Date: 9 Dec 87 11:14:57 GMT References: <4369@sdcsvax.UCSD.EDU> Organization: CWI, Amsterdam Lines: 50 <4369@sdcsvax.UCSD.EDU> maiden@sdcsvax.UCSD.EDU (VLSI Layout Project) writes: > >Consider a path embedded into the Cartesian plane, where for convenience >all vertices of the path are lattice points in the positive quadrant. >All edges are line segments. >So, the path will look like < (x1,y1) , (x2,y2) , ... , (xn,yn) >. >Question: What is the fastest method of determining *ALL* self- > intersections of this path? >This may have been beaten to death by computational geometers, so I'll >append some extra conditions: >Suppose there are **many** vertices in the path, and that edges are >for the most part very short. For example, there could be 10000 >points in a 200 by 200 square, with most edges less than 3 units long. >Furthermore, assume that there are not very many self-intersections >to be found. Now, what would the fastest method be??? Any ideas >welcome. There are, as you've guessed several papers in computational geometry on line segment intersections. You may look at the books by Shamos and Preparata, and also the book by Edelsbrunner for references. My favorite method to solve your problem though is an excellent method invented by Randolph Franklin at RPI. It is called ''adaptive grid'' and works as follows. First you overlay a regular, say G by G integer grid on your scene. Then you enter your edges into respective cells of the grid (similar to the bucketing idea!) Then you make a pass thru all the cells and find the intersections in each cell. If an intersection falls on a grid cell boundary you should be careful to treat it so the integrity is kept intact. I'm not very good in describing things in a hurry (especially Email) but let me tell that I've wide experience with this stuff and it works very well. It is especially excellent for a scene made of short edges with a rather homogeneous distribution. Write me for details. Also you may try Franklin at franklin@csv.rpi.edu. Here is a short bibl. W.R. Franklin An exact hidden sphere algorithm that operates in real time COMP. GRAPHICS AND IMAGE PROC. 15(4), 1981 ------------- A linear time exact hidden surface algorithm SIGGRAPH'80 ------------- and V. Akman A simple and efficient haloed line algorithm for hidden line elimination COMPUTER GRAPHICS FORUM, 1987 -------------------------- Adaptive grid for polyhedral visibility in object space: an implementation BJC 1987, to appear -Varol Akman CWI, Amsterdam #! rnews 2392 Path: alberta!mnetor!uunet!mcvax!jack From: jack@cwi.nl (Jack Jansen) Newsgroups: comp.os.misc,comp.unix.wizards Subject: Re: Command interfaces Message-ID: <142@piring.cwi.nl> Date: 9 Dec 87 15:41:45 GMT References: <1257@boulder.Colorado.EDU> <6840002@hpcllmv.HP.COM> <9555@mimsy.UUCP> <798@rocky.STANFORD.EDU> <432@cresswell.quintus.UUCP> <3161@psuvax1.psu.edu> <5565@oberon.USC.EDU> Organization: AMOEBA project, CWI, Amsterdam Lines: 43 Xref: alberta comp.os.misc:339 comp.unix.wizards:5747 In article <5565@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes: > [Discussing primos wildcards versus unix wildcards] >For example, how would you do the equivelent of this in unix: > >cmpf *>old>@@.(c,h) == -report ==.+cmpf -file > >(Explanation: compare all files in the old sub-directory ending in .c or >.h with the file of the same name in the current directory, and put >the output in the file of the same name with .cmpf appended. Non-files >(directories and segment directories) ending in .c or .h are ignored. >[I do prefer the output of diff -c to that of cmpf, but that isn't >what I'm talking about here.] Uhm, yes, unfortunately I find the 'feature' quite unusable. I *never* come up with the correct sequence of == and @@, so I have to type the command three times before I get it right. (really retype, that is. 'History mechanism' is something primos has never heard about). I definitely prefer for i in *.[ch]; do diff old/$i $i >$i.diff done (and you can add an 'if [ -d $i ]' if you really care about directories ending in .c or .h. I don't, because I don't *have* directories ending in .c or .h). And, to continue some gripes on primos wildcards: - I would expect them to work *always*. I.e. if I do TYPE @@ (TYPE is primos echo) I would expect a list of all files, *not* '@@'. - If I want all arguments on one line, and I use [WILD @@.TMP], and the result doesn't fit in 80 characters, I DO DEFINITELY NOT WANT IT TO TRUNCATE IT AT EIGHTY CHARS! I lost an important file that way: it was trying to generate a list containing PRECIOUSFILE.TMP, but, unfortunately, the .TMP started at position 81. So, it removed PRECIOUSFILE in stead. sigh. Sorry, there are some neat ideas in primos, but the command processor and it's wildcards is definitely *not* one of them. -- Jack Jansen, jack@cwi.nl (or jack@mcvax.uucp) The shell is my oyster. #! rnews 1552 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!csbg From: csbg@its63b.ed.ac.uk (Andie) Newsgroups: comp.windows.news Subject: Windows and menus through the CPS interface Keywords: NeWS windowing, menus, CPS interface Message-ID: <821@its63b.ed.ac.uk> Date: 9 Dec 87 00:15:36 GMT Reply-To: csbg@its63b.ed.ac.uk (Bruce) Organization: Computer Science Department, Edinburgh University Lines: 26 Hi everybody ! I'm a final year student at Edinburgh University and as part of my final year project I am using NeWS to build up a document composition system. Alas, I'm new to NeWS and the NeWS manual does seem to be rather sketchy, especially when it comes to using the CPS interface. Having had a look at the stuff that is floating around in this newsgroup I think that someone out there will be able to help me. Point 1 : How can I control the litewin.ps and litemenu.ps packages through the CPS interface - especially, how do I get notification to the C program that something is happening ? Point 2 : This may be trivial, but when I create an overlay for the purposes of rubber-banding, using the getclick family of operators, I can never get the overlay to disappear again. What is happening and how should it be done ? If these points have already been raised in the past then I will be happy to receive direct e-mail from anybody who can answer any part of the above queries. As they say: When the going gets tough, I get the hell out of it ! Bruce Gilmour (CS4 student at Edinburgh University) #! rnews 1134 Path: alberta!mnetor!uunet!mcvax!botter!ast From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: Re: Problems with serial TTY driver Message-ID: <1778@botter.cs.vu.nl> Date: 9 Dec 87 15:36:52 GMT References: <2314@encore.UUCP> Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 16 In article <2314@encore.UUCP> paradis@encore.UUCP (Jim Paradis) writes: >Is there some limit to how fast MINIX will take interrupts? >If one takes them too fast, will messages get lost? > If you try to force feed MINIX from an Ethernet at 10 Mbps it will probably drop stuff. There is undoubtedly a limit on how many interrupts per second it can handle, but an AT it should be over 1000 per second. The original tty driver was very carefully written to deal with exactly this issue. When characters come in, they are buffered, even if it is not possible to send a message to the tty task. This code is on lines 3528 to 3552 of the book. Assuming you are still using this mechanism, you ought to be able to accept characters at say 2400 baud without losing any. Andy Tanenbaum (ast@cs.vu.nl) #! rnews 915 Path: alberta!mnetor!uunet!mcvax!botter!ast From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: P-H has MINIX in stock (finally) Message-ID: <1779@botter.cs.vu.nl> Date: 9 Dec 87 15:46:14 GMT Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 11 I talked to P-H yesterday. Version 1.2 of MINIX in 256K & 640K PC, 512K AT, mag tape, and the IBM slipcase version with the abridged book are all in stock. If it is of any consolation to the people who have had to wait and wait and wait, one of the corporate vice presidents was so unhappy about the poor service to customers that he fired the person who was in charge of managing the MINIX inventory. He has been replaced by someone else who has clear instructions to make sure it doesn't go out of stock again. They are now shipping to everyone whose order got backlogged. Andy Tanenbaum (ast@cs.vu.nl) #! rnews 841 Path: alberta!mnetor!uunet!mcvax!prlb2!lln-cs!gf From: gf@lln-cs.UUCP (Frank Grognet) Newsgroups: rec.games.misc,rec.games.frp,rec.games.board Subject: WARGAMING! Keywords: wargame,rule,figurine,game Message-ID: <796@lln-cs.UUCP> Date: 9 Dec 87 15:19:13 GMT Organization: Computer Science Dept., Louvain-la-Neuve Belgium Lines: 11 Xref: alberta rec.games.misc:1150 rec.games.frp:1652 rec.games.board:543 I want to start wargaming but I don't know how! I won't be playing wargames on a board, but with 15mm or 25mm figurines. I would like to find addresses in Europe (especially Belgium) of good figurine manufacturers and also references to rule books for the Napoleonic period. I am also interested in rules contained on the net or in files at other sites, if they exist! I anybody can help me, please reply to ..!mcvax!prlb2!lln-cs!gf #! rnews 1656 Path: alberta!mnetor!uunet!mcvax!nikhefk!frankg From: frankg@nikhefk.UUCP (Frank Geerling) Newsgroups: comp.sys.atari.st Subject: Re: the perfect ram disk Keywords: ramdisk, resizeable, reset-survivable Message-ID: <294@nikhefk.UUCP> Date: 9 Dec 87 19:53:23 GMT References: <427@dukempd.UUCP> Reply-To: frankg@nikhefk.UUCP (Frank Geerling) Organization: Nikhef-K, Amsterdam (the Netherlands). Lines: 42 In article <427@dukempd.UUCP> gpm@dukempd.UUCP (Guy Metcalfe) writes: >I have Mike's Ramdisk v. .95, and like the idea of what it's trying to do. >It has a dialogue box as if it were resizable, but it's very buggy. Could >someone send me a later version that works like it's dialogue implies it >should. What I would like best of all is an eternal ram disk that I can >size up and down as I see fit, but which sizes down without letting me >destroy any data I may have on the disk. If anybody has and would send me >or knows where I could get such a beast, I would be grateful. Thanks. >-- > Guy Metcalfe gpm@dukempd.uucp Please send it to me too, I also have Mike's Ramdisk and the resize doesn't work it doesn't return allocated memory when you resize to a smaller amount of memory. Thanx in advance Frank Geerling (frankg@nikhefk.uucp) Usenet: {seismo, philabs, decvax}!mcvax!frankg@nikhefk Normal mail: Frank Geerling NIKHEF-K (DIGEL) Postbus 4395 1009 AJ Amsterdam The Netherlands Frank Geerling (frankg@nikhefk.uucp) Usenet: {seismo, philabs, decvax}!mcvax!frankg@nikhefk Normal mail: Frank Geerling NIKHEF-K (PIMU) Postbus 4395 1009 AJ Amsterdam The Netherlands #! rnews 2666 Path: alberta!mnetor!uunet!mcvax!prlb2!kulcs!luc From: luc@kulcs.UUCP (Luc Van Braekel) Newsgroups: comp.lang.pascal Subject: Re: self-replicating programs? Summary: here is a self-replicating pascal program Message-ID: <1070@kulcs.UUCP> Date: 9 Dec 87 08:31:27 GMT References: <1400@tulum.swatsun.UUCP> Organization: Kath.Univ.Leuven, Comp. Sc., Belgium Lines: 37 In article <1400@tulum.swatsun.UUCP>, hirai@swatsun (Eiji "A.G." Hirai) writes: > In our recent ACM programming contest (regionals), one of the > problems was to write a self-replicating program. That is, we had to > write a program whose output was itself, the source code. No alterations > of the original code during execution was allowed (I think). > Does anyone have any code for this problem? We have one but > it looks inelegant. I've also see bery bery short Prolog code for this. > Help, we are looking for good codes to study! And yes, the contest is > over (we ain't cheating). Here is a self-replicating Pascal program I wrote a few years ago. The program looks dirty but it works ! program self (output); var i,j: integer; a: array[1..8] of packed array[1..59] of char; begin a[1] := 'program self (output); '; a[2] := 'var i,j: integer; '; a[3] := ' a: array[1..8] of packed array[1..59] of char; begin '; a[4] := 'for i := 1 to 3 do writeln(a[i]); '; a[5] := 'for i := 1 to 8 do begin write('' a['',i:0,''] := '',chr(39));'; a[6] := 'for j := 1 to 59 do begin write(a[i][j]);if a[i][j]=chr(39)'; a[7] := 'then write(a[i][j]) end; writeln(chr(39),'';'') end; '; a[8] := 'for i := 4 to 8 do writeln(a[i]) end. '; for i := 1 to 3 do writeln(a[i]); for i := 1 to 8 do begin write(' a[',i:0,'] := ',chr(39)); for j := 1 to 59 do begin write(a[i][j]);if a[i][j]=chr(39) then write(a[i][j]) end; writeln(chr(39),';') end; for i := 4 to 8 do writeln(a[i]) end. +-----------------------------------+------------------------------------+ | Name : Luc Van Braekel | Katholieke Universiteit Leuven | | UUCP : luc@kulcs.UUCP | Department of Computer Science | | BITNET : luc@blekul60.bitnet | Celestijnenlaan 200 A | | Phone : +(32) 16 20 0656 x3563 | B-3030 Leuven (Heverlee) | | Telex : 23674 kuleuv b | Belgium | +-----------------------------------+------------------------------------+ #! rnews 1678 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!zu From: zu@ethz.UUCP (Urs Zurbuchen) Newsgroups: comp.sys.ibm.pc Subject: Re: Oooh Yeccheo. How Does This One Really Work?!? Message-ID: <264@bernina.UUCP> Date: 9 Dec 87 12:16:51 GMT References: <164300022@uiucdcsb> <412@wa3wbu.UUCP> <13091@beta.UUCP> <1269@phoenix.Princeton.EDU> Reply-To: zu@bernina.UUCP (Urs Zurbuchen) Organization: ETH Zuerich, CS Department, Switzerland Lines: 41 In article <1269@phoenix.Princeton.EDU> rjchen@phoenix.Princeton.EDU (Raymond Juimong Chen) writes: >In article <13091@beta.UUCP> it was written: >What you'd probably want is something like > >AUTOEXEC.BAT: > doit > >DOIT.BAT: > copy \autoexec.ddd \autoexec.bat > del \autoexec.ddd > do other stuff > reboot. > >AUTOEXEC.DDD: > same as before You could the same thing without changing your AUTOEXEC.BAT. With the solution presented above you will execute the same second version of AUTOEXEC.BAT each time you reboot your machine (perhaps that's really what you want, but my imagination doesn't go that far. If so, just disregard this article). My solution: In the startup file you include the following: if exist goto second echo gaga > :second That's it. If you want to toggle between the two boot modes just add a line like: del I hope this will help anybody :-) ...urs UUCP: ...seismo!mcvax!cernvax!ethz!zu #! rnews 420 Path: alberta!mnetor!uunet!mcvax!inria!irisa!michaud From: michaud@irisa.UUCP (Michaud Franck INSA BN205) Newsgroups: comp.protocols.tcp-ip Subject: virtual circuit Keywords: tcp, socket Message-ID: <202@irisa.UUCP> Date: 9 Dec 87 20:05:21 GMT Organization: IRISA, Rennes (Fr) Lines: 7 I'd like to have a good definition of : - virtual circuit. If you have a good definition, send me a mail. thanck you. franck #! rnews 758 Path: alberta!mnetor!uunet!mcvax!enea!liuida!dat08 From: dat08@butterix.liu.se Newsgroups: rec.games.frp Subject: Re: New rules for AD&D Message-ID: <686@butterix.liu.se> Date: 9 Dec 87 03:53:09 GMT References: <26788S9S@PSUVMA> Organization: CIS Dept, Univ of Linkoping, Sweden Lines: 11 In article <26788S9S@PSUVMA> S9S@PSUVMA.BITNET (Steven A. Schrader) writes: >New Rules for TSR. [...] Does anyone know when these rules will be out >and how much they will cost? According to Harold Johnson of TSR (at a local convention in Sweden) the new rules will be out in 89. BTW -- Any reactions about the new (again!) Gamma World? I haven't tried it yet but I like their idea of one-table-system for everything. Per Westling dat08@majestix.liu.se #! rnews 968 Path: alberta!mnetor!uunet!mcvax!enea!tut!tolsun!reini From: reini@tolsun.oulu.fi (Jukka Reinikainen) Newsgroups: comp.sys.ibm.pc,comp.sources.wanted Subject: Hercules graphic characters Keywords: hercules, text, MASM, MSC Message-ID: <246@tolsun.oulu.fi> Date: 8 Dec 87 15:32:30 GMT Organization: University of Oulu, Finland Lines: 14 Xref: alberta comp.sys.ibm.pc:9576 comp.sources.wanted:2717 Help wanted: how to create text in Hercules graphic mode? I have a program written in MSC (parts coded with MASM) which does quite nice things with grapichs but suffers lack of characters. According to my knowledge the only way to get characters in Herc graphic mode is to draw them on screen by lightning a set of pixels, right? Somebody *must* have written a program which draws characters and other symbols, so please help me. C and/or ASM sources and/or ideas will be *very* appreciated. > Jukka Reinikainen reini@tolsun.oulu.fi < #! rnews 935 Path: alberta!mnetor!uunet!mcvax!enea!liuida!andka From: andka@smidefix.liu.se (Andreas K}gedal) Newsgroups: rec.music.synth Subject: Yamaha CLP - pf question Keywords: Yamaha pf85 CLP300 Message-ID: <687@smidefix.liu.se> Date: 9 Dec 87 15:36:48 GMT Organization: CIS Dept, Univ of Linkoping, Sweden Lines: 13 I'm thinking of getting one of those new sampled pianos and would like to get som info. From the net and from my own experience in my local piano store, I've understood that the Yamaha Clavinova CLP 300 is a pretty good choise. But I seem to remember a rumor about something called Yamaha pf85 wich would be some kind of stageversion of the CLP 300. Has anyone seen it, played it, compared it with the CLP 300? What are the differences in price, sound, keyboard? My local pianopusher here in Sweden hadn't heard of it. Is this because it is so new or because it is a local phenomenon in the states? /Andreas Kagedal #! rnews 2816 Path: alberta!mnetor!uunet!mcvax!enea!ttds!draken!sics!erikn From: erikn@sics.se (Erik Nordmark) Newsgroups: comp.unix.questions Subject: Re: Need help with interprocess communications Keywords: Pipes, Ptys, Buffering, I/O Message-ID: <1639@sics.se> Date: 9 Dec 87 21:21:43 GMT References: <8117@steinmetz.steinmetz.UUCP> Reply-To: erikn@sics.UUCP (Erik Nordmark) Organization: Swedish Institute of Computer Science, Kista Lines: 60 [[ I tried sending this as mail using different addresses, but failed! ]] In article <8117@steinmetz.steinmetz.UUCP> you write: > > >I have tried using "fcntl(fd,F_SETFL,FASYNC)" as well as setting up an >interrupt handler to handle SIGIO signals (via "sigvec(2)"), and this works >fine when I'm reading from the terminal, but does not seem to work at all >when I try it from a pipe. > > >Well, the SIGIO handler works fine to detect input from places like stdin, but >never sees anything coming down the pipe. When it gets invoked (generally >by me banging on the key causing an interrupt from stdin), it >does find that there is data available in the pipe (as well as stdin) and >has no problem reading it. > > >Does anyone out there know how I can fix this problem? > >From looking at the BSD4.3 sources I found out the following: When a tty is opened the associated process group is set to that of the creator. The signals that the tty driver generate (e.g. caused by ^C) are sent to this process group. However, for sockets (a pipe is implemented as a pair of sockets in BSD4.3 and maybe elsewhere!) the associated process group is not set automatically. So what you have to do is to set it before you can get ant SIGIO's! Use int pgrp = getpid(); if (fcntl(fd, F_SETOWN, pgrp) == -1) { perror("fnctl"); exit(1); } or ioctl(fd, SIOCSPGRP, &pgrp) /* note: & */ I think this should work even if pipes aren't implemented as a pair of sockets, but I haven't tried any of it. >Also: Is there a way that I can determine WHICH file descriptor caused >a SIGIO interrupt to be invoked, or by which I can set up a different >interrupt handler for each descriptor? > See select(2). (Just a detail: select will tell you that there is data to read if there actually is data to read or if the other end(s) have closed the pipe. In the latter case read() will return an EOF - this stuff caused me some trouble before I read the *real* documentation - the OS source code!!) ------------------------------------------------------------------------- Erik Nordmark Swedish Institute of Computer Science, Box 1263, S-163 13 SPANGA, Sweden Phone: +46 8 750 79 70 Ttx: 812 61 54 SICS S Fax: +46 8 751 72 30 uucp: erikn@sics.UUCP or {seismo,mcvax}!enea!sics!erikn Domain: erikn@sics.se ------------------------------------------------------------------------- #! rnews 2508 Path: alberta!mnetor!uunet!mcvax!enea!luth!d2c-czl From: d2c-czl@sm.luth.se (Caj Zell) Newsgroups: rec.music.misc Subject: Re: Ace-Screamingest Guitar Solos on Record Keywords: guitar, flames (regrettably) Message-ID: <438@psi.luth.se> Date: 9 Dec 87 14:51:22 GMT References: <1725@s.cc.purdue.edu> Reply-To: Caj Zell Organization: University of Lulea, Sweden Lines: 44 UUCP-Path: {uunet,mcvax}!enea!psi.luth.se!d2c-czl In article <1725@s.cc.purdue.edu> rsk@s.cc.purdue.edu (Rich Kulawiec) writes: >I thought I'd make up a very hasty list of what I >thought were some of the best solos I've heard, and then ask y'all to >contribute further. Good idea,I love making up lists! >Money (Pink Floyd), David Gilmour >Cracked Actor (David Bowie), Earl Slick >Don't Take Me Alive (Steely Dan), Jeff 'Skunk' Baxter? >All Along the Watchtower Jimi Hendrix >Aqualung (Jethro Tull), Martin Barre >Highway 61, Johnny Winter Agree,but how about these: Muffin Man (Frank Zappa) (I think FZ was the most underrated) Son of Mr. Green Genes (Frank Zappa) (guitarist there ever has been.But,) Son of Orange County (Frank Zappa) (he can't play anymore,too bad. ) Push Comes To Show (Van Halen) Eddie Van Halen Crossroads (Cream) Eric Clapton (The 2nd solo,of course) Astronomy (Blue \yster Cult) Donald Roeser (on "Some Enchanted Evening") Lazy (Deep Purple) Ritchie Blackmore Fat Time (Miles Davis) Mike Stern I know that when I get home I will kill myself for not adding more solos, but these are the ones I can think of without looking at my records. But maybe that's a good sign indicating that these are really my favourites. I'd be very glad to see some reactions on the list. XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X X X X X Caj Zell ________________________ X X University of Lulea : : X X Sweden : Jazz is not dead, : X X : it just smells funny : X X mail: d2c-czl@psi.luth.se : -Frank Zappa : X X : : X X -----------------------: X X X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #! rnews 1389 Path: alberta!mnetor!uunet!mcvax!enea!kuling!peterf From: peterf@kuling.UUCP (Peter Fagerberg) Newsgroups: comp.sys.mac Subject: More memory for Mac+...? Message-ID: <570@kuling.UUCP> Date: 9 Dec 87 15:08:48 GMT Organization: DoCS, Uppsala University, Sweden Lines: 23 Hello. I've been wondering how to get a little extra memory for my Macintosh Plus (needed in these days of Hypercard and Multifinder). I was wondering if the normal brute-force method could be used; Just solder 1M memory chips on top of the existing one (piggyback) and attach CS (chip-select) and whatever else is needed from the adressbus to select the appropiate chip. I haven't really checked out the memorychips but maybe an inverter is needed for some signals. If I'm correctly informed there are 22 bit defining the adress on a MC68000, making it possible to have 4M of memory. *If* this is possibly, would programs take advantage of it? Well, maybe this is one of the most stupid questions asked to USENET since it all began and if so - please forgive my ignorance... Peter-- ============================================================================== Peter Fagerberg UUCP: {seismo,enea,mcvax,decwrl,...}!kuling!peterf Applied Computer Science ARPA: kuling!peterf@seismo.css.gov Uppsala University Analog: +46 18-128286 or 8-102927 #! rnews 1429 Path: alberta!mnetor!uunet!mcvax!botter!klipper!biep From: biep@cs.vu.nl (J. A. "Biep" Durieux) Newsgroups: soc.culture.jewish Subject: Re: Jews in soc.culture.jewish? Message-ID: <958@klipper.cs.vu.nl> Date: 10 Dec 87 09:07:28 GMT References: <4765@spool.wisc.edu> <2086@ucbcad.berkeley.edu> <2264@encore.UUCP> <5779@cisunx.UUCP> <2872@sphinx.uchicago.edu> <5861@cisunx.UUCP> Reply-To: biep@cs.vu.nl (J. A. "Biep" Durieux) Organization: VU Informatica, Amsterdam Lines: 23 In article <5861@cisunx.UUCP> dlhst@unix.cis.pittsburgh.edu.UUCP, (David L. Heyman) writes: >Don't kid yourself. the Constitution is one thing but reality is >another. National Christmas tree, etc. ^^^^^^^^^^^^^^ You are not trying to say that the US are German-mythological qua religion, are you? :-) No, but seriously: what does that tree have to do with Christianity? (Or, what does the mean US Christmas have to do with it at all - but that's another story) Is Santa Claus Christian? The Easter Bunny and its eggs? While I agree that the dates of these festivities originally come from the church, the things which are generally celebrated have no origin in Christian doctrine, and no one pretends so. Sorry if I offended anyone by this - I am not commenting on those who do use those times for prayer and as memorial days. -- Biep. (biep@cs.vu.nl via mcvax) To be the question or not to be the question, that is. #! rnews 1323 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!icdoc!ivax!shb From: shb@ivax.doc.ic.ac.uk (Simon Brock) Newsgroups: comp.sys.mac Subject: Re: uw/Multifinder? Message-ID: <146@gould.doc.ic.ac.uk> Date: 9 Dec 87 10:08:38 GMT References: <174400085@uxc.cso.uiuc.edu> Sender: news@doc.ic.ac.uk Reply-To: shb@doc.ic.ac.uk (Simon Brock) Organization: Dept. of Computing, Imperial College, London, UK. Lines: 22 In article <174400085@uxc.cso.uiuc.edu> dorner@uxc.cso.uiuc.edu writes: > >I can't get uw to work under Multifinder. ... >I have an SE, and am running the latest system software (obviously). >I'm using uw version 4.1. > >Is anybody successfully using uw under Multifinder? Yes. I'm using uw4.1 on an SE with System 4.1/Finder 6.0 and a beta version of MF (1.0b6). (As an aside, we can't get System Tools 5.0 in the UK until early next year, unless you know different to me !) UW runs but I do character losses at 9600 baud. I can't work out why, and I'm not convinced its UW's fault. I wrote to John Bruner, the author, who says other people were reporting the same problem. Simon. Simon H Brock, Dept. of Computing, Imperial College, London SW7 2AZ Tel : 01 589 5111 x4993 BitNet : shb@doc.ic.ac.uk (or shb%uk.ac.ic.doc@AC.UK) UUCP : shb@icdoc.uucp (...siesmo!mcvax!ukc!icdoc!shb) JANET : shb@uk.ac.ic.doc #! rnews 1446 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!icdoc!cam-cl!am From: am@cl.cam.ac.uk (Alan Mycroft) Newsgroups: comp.lang.c Subject: Re: closing stdout Keywords: Yes it IS a buggy library Message-ID: <1115@jenny.cl.cam.ac.uk> Date: 9 Dec 87 10:38:55 GMT References: <442@cresswell.quintus.UUCP> Reply-To: am@cl.cam.ac.uk (Alan Mycroft) Organization: U of Cambridge Comp Lab, UK Lines: 19 In article <442@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: >There's an old joke with the punch-line "We've already established what >you are, madam. Now we're just haggling over the price." > result = getchar(); > errno = 0; > result = putc(result, stdin); > printf("result = %d, errno = %d\n", result, errno); >The bug is that depending on where you are in the buffer, putc() MIGHT >notice the mistake, but it usually won't. >... the bug is a pretty fundamental one in the UNIX stdio implementation, Richard, The bug is not in the slightest bit fundamental and could be fixed in less than 1 day once and for all. I have done it for a ANSI unix-like I/O library: Merely separate the _cnt field of struct FILE into a _icnt and an _ocnt, change getc/putc to use _icnt/_ocnt. Fix _filbuf/_flsbuf to use the right one, and to whinge when _icnt/_ocnt goes -ve when you expect the other one to. This for free also enables the library to police the "fflush/fseek between change of direction for I/O" restriction and avoids chaos there. #! rnews 1094 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!icdoc!cam-cl!lg From: lg@cl.cam.ac.uk (Li Gong) Newsgroups: soc.culture.china Subject: Change of Policy After Beginnig Signing Contrct ? Message-ID: <1114@jenny.cl.cam.ac.uk> Date: 9 Dec 87 10:37:41 GMT Organization: U of Cambridge Comp Lab, UK Lines: 19 Is there anybody out there who has info about whether the Chinese government has changed the policy regarding students aboard and how it is changed, because from this April, all students sent by the government are asked to sign contracts between him/her and his/her institution. What do these contracts mean ? Does this imply that those who came out before this April (thus did not sign) then have a somewhat different status (for example, can not be asked to go back to carry out a certain contract) ? E-mail to me and I'll summurize OR post to the newsgroup. I believe there are other people who are also interested in this issue. Martin ----------------------------------------------------------------------- lg@uk.ac.cam.cl --------------- #! rnews 1315 Path: alberta!mnetor!uunet!mcvax!ukc!stc!root44!cdwf From: cdwf@root.co.uk (Clive D.W. Feather) Newsgroups: rec.arts.sf-lovers Subject: Eric Frank Russell - was Re: Misc questionings Message-ID: <492@root44.co.uk> Date: 9 Dec 87 15:03:01 GMT References: <362@n8emr.UUCP> <2481@pbhyf.UUCP> Reply-To: cdwf@root44.UUCP (Clive D.W. Feather) Organization: Root Computers Ltd, London, England Lines: 23 In article <2481@pbhyf.UUCP> djl@pbhyf.UUCP (Dave Lampe) writes: >In article <362@n8emr.UUCP> lwv@n8emr.UUCP (Larry W. Virden) writes: >> >>5. Finally, and perhaps most important. I am looking for author and >>anthology names for a short story (perhaps longer than thtat?) called I >>believe "MYOB". >>The title stands for "Mind Your Own Business". > >The story is in a book called "The Great Explosion" by Eric Frank >Russell in 1962. It is a collection of 3 or 4 stories telling >of an attempt by Earth to recontact colonies that had been lost >for a long time and that had evolved into unusual societies. I have come across "The Great Explosion", but I also have this part of it in a collection whose name I have forgotten, under the title "And then there were none.". Great story. THE BEST AUTHOR EVER. [Kill the line counter] [Kill Mel] [Keep Adric Dead] [Kill the line counter] [Kill Mel] [Keep Adric Dead] #! rnews 849 Path: alberta!mnetor!uunet!mcvax!ukc!stc!root44!cdwf From: cdwf@root.co.uk (Clive D.W. Feather) Newsgroups: sci.misc Subject: Re: Color Message-ID: <493@root44.co.uk> Date: 9 Dec 87 15:46:24 GMT References: <162300002@uiucdcsb> <162300004@uiucdcsb> Reply-To: cdwf@root44.UUCP (Clive D.W. Feather) Organization: Root Computers Ltd, London, England Lines: 13 Carl Kadie Inductive Learning Group University of Illinois at Urbana-Champaign writes: >ii. There is "no such color" as purple! Mixing red and blue ink > causes your eye to react in a way which is not reproducible > by any single wavelength of light. The eye can see colours (for example, in afterimages) that cannot be reproduced by any combination of wavelengths of light ! There was an article in Scientific American c.1970 entitled "Phosphenes" that went into this. #! rnews 795 Path: alberta!mnetor!uunet!mcvax!ukc!stc!datlog!dlhpedg!cl From: cl@dlhpedg.co.uk (Charles Lambert) Newsgroups: rec.games.empire,comp.sources.bugs Subject: Re: conquest newsletter #3 Message-ID: <330@dlhpedg.co.uk> Date: 9 Dec 87 14:27:16 GMT References: <4886@mhuxd.UUCP> <6899@apple.UUCP> Sender: news@dlhpedg.co.uk Reply-To: cl@.co.uk (Charles Lambert) Organization: FSG@Data Logic Ltd, Queens House, Greenhill Way, Harrow, London. Lines: 8 Xref: alberta rec.games.empire:292 comp.sources.bugs:563 >In article <4886@mhuxd.UUCP>, smile@mhuxd.UUCP (Edward Barlow) writes: >> 3) Still have not thought of a new name for the game. Best so far is >> (need to check spelling). Comments? I've missed something here; what was wrong with "conquest"? --------------- Charlie Lambert #! rnews 819 Path: alberta!mnetor!uunet!mcvax!weijers From: weijers@cwi.nl (Eric Weijers) Newsgroups: comp.lang.c++ Subject: another error in vector.h 1.3 Message-ID: <143@piring.cwi.nl> Date: 10 Dec 87 13:27:06 GMT Organization: CWI, Amsterdam Lines: 22 In "vector.h 1.3" the following definition of the X(X&) constructor is given: vector(type).vector(type)(vector(type)& a) { register i = a.sz; sz = a.sz; /* ADD THIS LINE */ v = new type[i]; register type* vv = &v[i]; register type* av = &a.v[i]; while (i--) *--vv = *--av; } You should add the indicated line in order to set the size of the new vector. If that is not done you get "vector index out of range" errors. I found two other errors in this header file, I posted earlier. If you are interested in them just send a reply (r). Eric Weijers. weijers@cwi.nl #! rnews 830 Path: alberta!mnetor!uunet!mcvax!botter!klipper!biep From: biep@cs.vu.nl (J. A. "Biep" Durieux) Newsgroups: soc.culture.jewish Subject: Anything positive about Jewish genes? (Was: Jewish genetic diseases) Message-ID: <959@klipper.cs.vu.nl> Date: 10 Dec 87 09:50:15 GMT References: <4362@ig.ig.com> <4374@ig.ig.com> Reply-To: biep@cs.vu.nl (J. A. "Biep" Durieux) Organization: VU Informatica, Amsterdam Lines: 12 I suppose the exclusive intermarriage among Jews must also have spared them for many genetic diseases found among "the rest of us". Does anyone have any data on that? ~~~ I understand nobody is interested in discussing the Dead Sea scrolls? And nobody knows what the "Jewish region" in the far SE of Siberia is? ~~~ -- Biep. (biep@cs.vu.nl via mcvax) To be the question or not to be the question, that is. #! rnews 960 Path: alberta!mnetor!uunet!mcvax!unido!ecrcvax!johng From: johng@ecrcvax.UUCP (John Gregor) Newsgroups: rec.arts.sf-lovers Subject: Re: Old SF Shows Summary: Yet another show I can't remember the name of... Message-ID: <463@ecrcvax.UUCP> Date: 9 Dec 87 13:57:35 GMT References: <04.Dec.87.11:29:45.GMT.ZZASSGL@UK.AC.UMRCC.CMS> <18784@linus.UUCP> <1046@bc-cis.UUCP> <19026@linus.UUCP> Reply-To: johng@ecrcvax.UUCP (John Gregor) Organization: ECRC, Munich 81, West Germany Lines: 10 There was a show on sometime between the late 70's and early 80's (1 season). And I can't remember the name. It was actually two (or more) shows in one with each sub-show taking a fraction of the time slot. One part was a modern day dracula. Another dealt with a society living underground. They couldn't come up to the surface without special filters due to dust/pollution or some such. Ring any bells? It was NBC, I think. John johng%ecrcvax.UUCP@germany.CSNET #! rnews 756 Path: alberta!mnetor!uunet!mcvax!botter!ark!maart From: maart@cs.vu.nl (Maarten Litmaath) Newsgroups: comp.bugs.4bsd Subject: Re: 4.3BSD: using control-m in .exrc file Summary: More ^V's are needed (won't the editor get enough of it ? :-) Keywords: 4.3bsd .exrc control-m ^V Message-ID: <1161@ark.cs.vu.nl> Date: 10 Dec 87 18:44:07 GMT References: <133@telesoft.UUCP> Reply-To: maart@cs.vu.nl (Maarten Litmaath) Organization: VU Informatica, Amsterdam Lines: 8 Try preceding each ^M by *another* ^V (which in turn is escaped by ^V) ! Type: map , ^V^V^V^M^V^V^V^M^V^V^V^M BTW, death to emacs ! -- Time flies like an arrow, fruit flies |Maarten Litmaath @ Free U Amsterdam: like an orange. (seen elsewhere) |maart@cs.vu.nl, mcvax!botter!ark!maart #! rnews 1079 Path: alberta!mnetor!uunet!mcvax!inria!shapiro From: shapiro@inria.UUCP (Marc Shapiro) Newsgroups: comp.lang.c++ Subject: Re: Is there a "real" C++ compiler available? Summary: There is a native C++, with debugger support Message-ID: <589@inria.UUCP> Date: 10 Dec 87 17:55:27 GMT References: <2097@ucbcad.berkeley.edu> Organization: INRIA, Rocquencourt. France Lines: 14 In article <2097@ucbcad.berkeley.edu>, faustus@ic.Berkeley.EDU (Wayne A. Christopher) writes: > [...]. Is there a C++ > compiler available now that will compile directly into asm > code, instead of into C? Alternatively, is there a good way > to use dbx with C++ programs (i.e, using the c++ source instead > of the c files)? The answer to both questions is yes. The Free Software Foundation (you know, the GNU Emacs people) will distribute (soon?) a modified version of their C compiler which does C++. Their debugger GDB (a dbx-lookalike) knows how to handle it. I haven't used either of these so I have no opinions to whether they are in any way adequate. Just passing useful information along. #! rnews 1269 Path: alberta!mnetor!uunet!mcvax!enea!ttds!draken!zap From: zap@draken.nada.kth.se (Svante Lindahl) Newsgroups: comp.os.misc,comp.unix.wizards Subject: Re: Command interfaces Message-ID: <239@draken.nada.kth.se> Date: 10 Dec 87 04:54:11 GMT References: <1257@boulder.Colorado.EDU> <6840002@hpcllmv.HP.COM> <9555@mimsy.UUCP> <798@rocky.STANFORD.EDU> <432@cresswell.quintus.UUCP> <3161@psuvax1.psu.edu> <5565@oberon.USC.EDU> Reply-To: zap@nada.kth.se (Svante Lindahl) Organization: The Royal Inst. of Techn., Stockholm Lines: 21 Xref: alberta comp.os.misc:340 comp.unix.wizards:5748 In article <5565@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes: #For example, how would you do the equivelent of this in unix: # #cmpf *>old>@@.(c,h) == -report ==.+cmpf -file I can do it using either /bin/sh or csh, but it does require more typing than in Primos. The test for existence of the file is not necessary so these examples could be simplified at the expense of risking a few error messages to the terminal. C-shell: % foreach i (`cd old; ls *.[ch]`) > if (-r $i) diff -c old $i > $i.cmpf > end Bourne-shell: $ for i in `cd old; ls *.[ch]` ; do > if [ -r $i ] ; then diff -c old $i > $i.cmpf ; fi > done Svante Lindahl zap@nada.kth.se uunet!nada.kth.se!zap #! rnews 2030 Path: alberta!mnetor!uunet!mcvax!enea!ttds!draken!sics!lhe From: lhe@sics.se (Lars-Henrik Eriksson) Newsgroups: rec.arts.sf-lovers Subject: Re: ST:TNG posters, GET OUT! Keywords: Why Message-ID: <1640@sics.se> Date: 10 Dec 87 11:50:40 GMT References: <5226@zen.berkeley.edu> <2011@charon.unm.edu> Reply-To: lhe@sics.se (Lars-Henrik Eriksson) Organization: Swedish Institute of Computer Science, Kista Lines: 32 In article <2011@charon.unm.edu> cs3631cg@hydra.UUCP (Mark Giaquinto) writes: >Two points here, interesting is a *very* relative term, what is >interesting to you may not be to me and visa versa. Secondly I >agree, that if you have a ST posting put it in the header, for people >who don't want to read this stuff. > >>If there was no group for star trek fans to converse in without pestering >>the rest of the sf world, I would just have to sit here and suffer, but >>that's not the case. Rec.arts.startrek is alive and well. There is no >>reason beyond sheer orneryness to post to sf-lovers as well. Arguments that >>star trek is sci-fi as well are pointless. The simple fact is that there is >>newsgroup for all of you to communicate in, and if the rest of us wanted to >>listen, then we would. > >Well startrek is sf and I don't see how that arguement is pointless. I have only the faintest interest in the ST stuff and I would prefer it to be posted elsewhere, although I am not particularly bothered either. I think the interesting question is: WHY DO WE HAVE DIFFERENT NEWSGROUPS?? I always thought it was to organize postings by subject and because different people are interested in different things. If you argue that ST postings could as well be made to rec.arts.sf-lovers rather than to the special ST newsgroup, you could just as well argue that we only need one newsgroup on the entire net: general.general.general. Lars-Henrik Eriksson Internet: lhe@sics.se Swedish Institute of Computer Science Phone (intn'l): +46 8 750 79 70 Box 1263 Telefon (nat'l): 08 - 750 79 70 S-164 28 KISTA #! rnews 1007 Path: alberta!mnetor!uunet!mcvax!enea!tut!mk59200 From: mk59200@tut.fi (Kolkka Markku Olavi) Newsgroups: comp.sources.bugs Subject: Re: PC Nethack 2.2 bugs + help wanted linking Summary: Inventory display problems Message-ID: <522@fuksi.tut.fi> Date: 10 Dec 87 13:32:40 GMT References: <492@silver.bacs.indiana.edu> <5253@zen.berkeley.edu> Reply-To: mk59200@fuksi.UUCP (Kolkka Markku Olavi) Organization: Tampere University of Technology, Finland Lines: 13 I have successfully compiled and linked Nethack using MSC 4.0 and it looks great, exept in a few points. The inventory display is spread all over the screen if there aren't enough items to force a full-screen display. It seems that after printing each line the cursor is moved one step down, but it doesn't move left to the right place. Also, when I teleport away from an unlit room, some quote characters are left behind around the place I was in. Markku Kolkka at Tampere University of Technology, Finland mk59200@tut.fi ...mcvax!tut!mk59200 #! rnews 811 Path: alberta!mnetor!uunet!mcvax!enea!tut!tolsun!jto From: jto@tolsun.oulu.fi (Jarkko Oikarinen) Newsgroups: comp.sys.amiga,rec.games.misc Subject: 'Real' controllers for Flight Simulator II Keywords: Controllers, Flight Simulator Message-ID: <247@tolsun.oulu.fi> Date: 10 Dec 87 16:47:22 GMT Organization: University of Oulu, Finland Lines: 15 Xref: alberta comp.sys.amiga:11680 rec.games.misc:1151 I am interested in finding any information about 'real' controllers for Amiga's Flight Simulator II program. ie. similar controllers that are used in real airplanes. Please mail your responses because I don't read this group regularly. -- ======================================== Jarkko Oikarinen mcvax!tut!oulu!jarkko jarkko@tolsun.oulu.fi ======================================== #! rnews 913 Path: alberta!mnetor!uunet!mcvax!inria!imag!pierre From: pierre@imag.UUCP (Pierre LAFORGUE) Newsgroups: comp.protocols.appletalk Subject: NCSA TELNET bug with foreign MacSE or MacII keyboards Message-ID: <2331@imag.UUCP> Date: 10 Dec 87 08:08:19 GMT Reply-To: pierre@imag.UUCP (Pierre LAFORGUE) Organization: IMAG, University of Grenoble, France Lines: 11 NCSA Telnet is really a must, but ... on a Mac SE and a Mac II, NCSA Telnet 2.0 forces an american keyboard, in a permanent manner (it remains after exiting telnet, until the next Macintosh reboot). It is very painful when you use, for instance, a french keyboard: not only you have to remember to type Q for A, and so on, but you cannot type for example a Control-Z under telnet. [On a Macintosh +, one do not loss its keyboard] Is this bug fixed in the last version ? -- Pierre Laforgue pierre@imag.imag.fr {uunet.uu.net|mcvax}!imag!pierre #! rnews 490 Path: alberta!mnetor!uunet!mcvax!diku!sergej From: sergej@diku.UUCP (S|ren O. Jensen) Newsgroups: sci.math.stat Subject: The SAS package Message-ID: <3570@diku.UUCP> Date: 10 Dec 87 14:03:31 GMT Organization: DIKU, U of Copenhagen, DK Lines: 7 Is the SAS package available for UNIX-systems? We are currently using the package on a old IBM machine but would like to change this machine to something newer - preferably a UNIX-machine. -- ---- S|ren Oskar Jensen ({sergej,postmaster}@diku) #! rnews 2766 Path: alberta!mnetor!uunet!mcvax!diku!iesd!jacob From: jacob@iesd.uucp (Jacob stergaard B{kke) Newsgroups: comp.arch Subject: job search, Comp. eng. Summary: I'm looking for a job Keywords: Job, Computer. eng., Computer. sci., M.S. Message-ID: <172@iesd.uucp> Date: 10 Dec 87 12:00:17 GMT Reply-To: jaaob@iesd.UUCP (Jacob \stergaard B{kke) Organization: Dept. of Comp. Sci., Aalborg University, Denmark (student) Lines: 68 I'm looking for a job in Computer Engineering to begin around July 1988. I'm getting my Master of Science in Computer Engineering June 1988 and at present holding a degree equal to BS in Electronic Engineering. My BS studies have included: Computer hardware (hands-on knowledge with mc68k), Analog electronic Control engineering (analog and digital control) My MS studies have included: Software development (man-machine interface, what people want from programs) Compiler construction (an expertsystem shell) Program environment (for CCS programming) Distributed operating systems (in UNIX) Compiler mapping object-oriented language on parallel computers Furthermore I do have experience in conventional programming (PASCAL, C, postscript, UNIX (awk, shell-scripts(C-shell) and yacc/lex) (and Basic)), functional programming (LISP and ML) and logical programming (Prolog) and knowledge about object-oriented programming. And I have also attended courses in VLSI design, databases, etc. I have been working with CDC under NOS/Telex, VAX 11/750 under Ultrix, SUN 3 under Sun OS 4.3 (UNIX), MacIntosh (LISA) under Finder and IBM S36 under IBM property operating system. My spoken English is excellent and my written English is satisfactory, good knowledge of the Scandinavian languages (Danish (of course), Swedish and Norwegian), some speaking and reading knowledge of German and limited knowledge of French and Spanish (and Latin). I have 5 years experience in group project work in engineering and computer scinence areas, broad social interest, good health. My interest include computer hardware and software, operating system design, expertsystems, distributed, concurrency and teaching. I'm open on location (outside Denmark) but I have relatives or other reasons to be especially intereted in: Canada (British Colombia or Toronto) USA (New England or Pacific Coast) Pacific (New Zealand or Oceania) Thailand Scotland (Highlands) I'll look forward to any reponds. Yours sincerely Jacob Baekke, Denmark For further information: Reply to: jacob@iesd.uucp, {...}!mcvax!diku!iesd!jacob or at Univ: Jacob Baekke S9D (in spring S10) Strandvejen 19 AUC DK--9000 Aalborg Denmark private: Jacob Baekke Davids Alle 48 DK--9000 Aalborg Denmark Tel. 45-(0)8102673 #! rnews 867 Path: alberta!mnetor!uunet!mcvax!diku!dde!jk From: jk@dde.uucp (Jens Kjerte) Newsgroups: comp.sources.wanted Subject: Re: Wanted: Microemacs part 8 Message-ID: <281@Aragorn.dde.uucp> Date: 10 Dec 87 09:27:24 GMT References: <166@iesd.uucp> Reply-To: jk@dde.uucp (Jens Kjerte) Organization: Dansk Data Elektronik A/S, Herlev, Denmark Lines: 15 In article <166@iesd.uucp> torbennr@neumann.UUCP (Torben N. Rasmussen) writes: > >Could someone please send me part 8 of the sources for Microemacs. > Me too! It seems as if part8 never reached Denmark. -- +---------------------------------------------------------------------------+ | Jens Kjerte @ Dansk Data Elektronik A/S, Systems Software Department | | E-mail: ..!uunet!mcvax!diku!dde!jk or jk@dde.uucp | +---------------------------------------------------------------------------+ #! rnews 512 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!solaris!wyle From: wyle@solaris.ifi.ethz.ch@relay.cs.net (Mitchell Wyle) Newsgroups: comp.lang.modula2 Subject: modula-2 pretty-printer Keywords: pretty-printer Message-ID: <195@solaris.ifi.ethz.ch@relay.cs.net> Date: 9 Dec 87 21:56:57 GMT Organization: SOT sun cluster, ETH Zuerich Lines: 7 Did anyone ever get the m2pp program to work on Sun Modula-2? Does anyone have a different Modula-2 pretty-printer (perhaps better)? Thanks, Mitch Wyle (wyle@ethz.uucp) #! rnews 1762 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!zu From: zu@ethz.UUCP (Urs Zurbuchen) Newsgroups: comp.emacs Subject: Re: Has uemacs 3.9 solved the file save bug? Message-ID: <265@bernina.UUCP> Date: 10 Dec 87 07:21:02 GMT References: <3056@pegasus.UUCP> Reply-To: zu@bernina.UUCP (Urs Zurbuchen) Organization: ETH Zuerich, CS Department, Switzerland Lines: 30 In article <3056@pegasus.UUCP> avi@pegasus.UUCP (XMPE40000-Avi E. Gross;LZ 3C-314;6241) writes: > >I haven't compiled the new micro emacs since I have a MSC compiler, which is >not fully supported. This is simply NOT TRUE. I am also working with MSC (version 4.0) and had only one minor problem when I compiled MicroEmacs 3.9e (the latest version which was posted on Usenet). This problem relates to the Subshell spawning. But if you know just a little bit of C, there is no problem to fix it (add a routine specific to MSC). Some time ago, there was even a posting in comp.sources.bugs describing all the necessary steps to do that. >I have been having a very annoying problem with the >older version, and am wondering if it has been fixed, or if someone has a >work around. I am used to saving my files regularly with ^X^S, and then >sometimes quiting with ^X^C. Unfortunately, uemacs will quit before >completing the writing of the file, leaving me with only a small piece of >the file. I am sure you enable breaking with ^C (either in config.sys or in autoexec.bat) Turn this off, and all your problems have gone :-) I know this is not the solution to this problem we all want to have. Perhaps you can do it with signal(). If not you have to included a function of your own which intercepts the break vector of MS-DOS. Have a nice day, ...urs UUCP: ...seismo!mcvax!cernvax!ethz!zu #! rnews 2164 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!ceb From: ceb@ethz.UUCP (Charles Buckley) Newsgroups: comp.lang.lisp Subject: Re: lisp environments summary -- program storage methods Message-ID: <266@bernina.UUCP> Date: 10 Dec 87 23:08:38 GMT References: <613@umbc3.UMD.EDU> <325@siemens.UUCP> <323@spar.SPAR.SLB.COM> <329@siemens.UUCP> <13253@think.UUCP> Organization: ETH Zuerich, Switzerland Lines: 30 In-reply-to: barmar@think.COM's message of 9 Dec 87 03:18:01 GMT Posting-Front-End: GNU Emacs 18.41.2 of Mon Sep 14 1987 on bernina (berkeley-unix) In article <329@siemens.UUCP> steve@siemens.UUCP (Steve Clark) writes: > I maintain that the non-Interlisp systems are wrong, however. It >is clearly more advanced to treat a file as a database of definitions of >functions, data, structures, etc. than to treat it as a string of characters >that might have been typed at the keyboard. However, since the rest of the >world hasn't caught up yet, there are bound to be incompatibilities. (Character) file storage is simply more flexible. The form in which information is stored must be the most flexible possible, or you lose information. The D-crate's pitching of conditionals is simply the manifestation of this. Proponents of restrictive protocols for information storage really ask "the world" to change to fit the protocol model. In science, models change to fit the data, not the other way round (unless you cheat). To me, browbeating eventual non-conformists into "catching up" by labeling the a model as "advanced" is just a form of negative motivation. All the lousy places I have ever worked ran on negative motivation, none of the good ones. If your model *is* really worth using, and you can communicate its value, you will not need such tactics. Interactively defined functions? Haven't typed one in *years* - that's what scratch buffers are for (in case I want to change a *character* or two, or later save it.). Any mouse-based gadgets you can point to in Interlisp can be recreated for a text editor working on correctly parsed Lisp code. May take execution time, but if this is prohibitive, your function is probably too large. #! rnews 2319 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!jha From: jha@its63b.ed.ac.uk (J Andrews) Newsgroups: rec.games.frp Subject: Fantasy Philosophy Keywords: wackafoo Message-ID: <824@its63b.ed.ac.uk> Date: 10 Dec 87 14:30:15 GMT Reply-To: jha@lfcs.ed.ac.uk (J Andrews) Organization: Univ. of Edinburgh Dept. of Computer Science Lines: 38 God: Kate Bush Least-favourite-subject: domain theory Those interested in the issues surrounding the mechanics and philosophy of fantasy worlds should read Tolkien's (non-fiction) essay "On Fairy-Stories". It appears in the collections _Tree and Leaf_ and _The Tolkien Reader_. One of the main ideas behind it is that the fantasy author or story-teller is a "sub-creator", who tries to create a "secondary belief" (rather than exactly a "willing suspension of disbelief") in the reader. In the fantasy that works, the reader should be able to enter the world every time she picks up the book, and not be aware of the world as being constructed by the author. This involves not only internal consistency, but a lack of gimmickry. For instance, in _Lord of the Rings_ I was never aware of anything being in the world gratuitously. (Others may differ! :-)) In _The Sword of Sha-Na-Na_ (sic)(sick?), on the other hand, I was very aware of the Elfstones as being just a gimmick to get the characters out of tight spots. Sure it was internally consistent (the Elfstones only had any effect in times of direst need for their holders), but the hand of the author was clearly visible. Similarly, applying it to FRPG's, the magic system in AD&D is certainly internally consistent (to the extent that it is described), but just doesn't "work" for me. Having MU's able to remember several copies of a spell, but forgetting it when the last copy is cast, is obviously a gimmick to limit the number of spells an MU can use. So I guess the moral of all this for FRPG or module designers is that it's best to start out with a few basic assumptions and build up your world from them by fairly believable steps, and if you can't avoid ending up with something really hairy, then change one of your assumptions rather than put in quick kludges. (Gee, sounds like software engineering! :=)) --Jamie. jha@uk.ac.ed.lfcs "Switch off the mind and let the heart decide" #! rnews 1818 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!db From: db@its63b.ed.ac.uk (D Berry) Newsgroups: comp.windows.x Subject: Questions about implementing the X toolkit. Message-ID: <825@its63b.ed.ac.uk> Date: 10 Dec 87 17:28:06 GMT Reply-To: db@lfcs.ed.ac.uk (Dave Berry) Organization: LFCS, University of Edinburgh Lines: 25 1) Does anyone, preferably in the UK or Europe, have a copy of the new X toolkit interface definition I can get by ftp? 2) I'm considering implementing the X toolkit in Standard ML. Are there any constraints on what I should include or exclude? The documentation mentions implementation in different languages, but doesn't say much about what this means. Is the idea to provide the same functions, with the same names and functionality, in each language? What about languages that have automatic storage management or automatic creation of objects, etc? How far can I deviate from the documentation & still use the name "X Toolkit"? 3) Is the toolkit definition limited to the intrinsics, or are toolkits expected to provide a standard class hierarchy? 4) Is there any relation between the InterViews toolkit, the Xr, Sx & DEC toolkits provided with X version 10R4, and the current X toolkit? 5) If I go ahead, my first implementation will be a prototype, on top of X version 10R4. This is because someone else is working on porting X version 11 to Standard ML, and I want a simple windowing system I can use fairly quickly. I hope the prototype will make implementing a full version reasonably straightforward. I will probably ignore the resource manager, since I'll get that for free when the full Xlib is implemented. I'll also ignore colour for the time being, and only implement devices (widgets) I'm immediately interested in. Is there anything else I can obviously ignore? #! rnews 1113 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!csw From: csw@eagle.ukc.ac.uk (C.S.Welch) Newsgroups: rec.arts.sf-lovers Subject: Re: Word processors are: [was Re: Pournelle's Problems] Message-ID: <4065@eagle.ukc.ac.uk> Date: 10 Dec 87 18:42:09 GMT References: <1915@haddock.ISC.COM> Reply-To: csw@ukc.ac.uk (C.S.Welch) Organization: Computing Lab, University of Kent at Canterbury, UK. Lines: 20 Summary: Expires: Sender: Followup-To: Some (possibly) timely information from a course entitled "The Art of Communication for Engineers" that I'm on this week. From one of the handouts :- "Word processors: research has shown that when writers use pen and paper alone, their thoughts and information tend to have better planning and organisation. When using word processors alone, writers tend to plan on a more surface level, focussing on such aspects as word choice, sentence structure, and spelling" It goes on to recommend starting with pen and paper and graduating to WP's after the first draft has been written. I trust that this may have been of some interest. Chris Welch Cranfield Institute U.K. #! rnews 1286 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!icdoc!qmc-cs!pd From: pd@cs.qmc.ac.uk (Paul Davison) Newsgroups: rec.music.misc Subject: Re: Another Day : by Peter Gabriel and Kate Bush Message-ID: <352@sequent.cs.qmc.ac.uk> Date: 10 Dec 87 12:58:25 GMT References: <1987Dec8.154517.11828@gpu.utcs.toronto.edu> Reply-To: pd@qmc.ac.uk (Paul Davison) Organization: Computer Science Dept, Queen Mary College, University of London, UK. Lines: 22 I've heard of this as well, but I have never found it. It's a pity because I would really like to hear it, so if anyone has got it please let me know as well!! As an aside, Roy has a new album out early next year, probably January. Paul. PS Your internal newsgroup "tor.general" shouldn't have been on the newsgroups line really, because nobody else has heard of it! -- -- Paul Davison UUCP: pd@qmc-cs.uucp or ...seismo!mcvax!ukc!qmc-cs!pd Internet: pd@cs.qmc.ac.uk Post: Dept of Computer Science JANET: pd@uk.ac.qmc.cs Queen Mary College Easylink: 19019285 University of London Telex: 893750 QMCUOL G Mile End Road Fax: +44 1 981 7517 London E1 4NS Voice: +44 1 980 4811 x3950 England #! rnews 786 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!craig From: craig@comp.lancs.ac.uk (Craig) Newsgroups: comp.sys.mac Subject: MAC II Debuggers Keywords: Development, MacII Debuggers Message-ID: <457@dcl-csvax.comp.lancs.ac.uk> Date: 9 Dec 87 13:36:01 GMT References: <687@howtek.UUCP> <3456@husc6.harvard.edu> Reply-To: craig@comp.lancs.ac.uk (Craig) Organization: Department of Computing at Lancaster University, UK. Lines: 11 Having found out that Macsbug 5.5 works well with the MAC II, how do I get a copy ? Craig. -- UUCP: ...!seismo!mcvax!ukc!dcl-cs!craig| Post: University of Lancaster, DARPA: craig%lancs.comp@ucl-cs | Department of Computing, JANET: craig@uk.ac.lancs.comp | Bailrigg, Lancaster, UK. Phone: +44 524 65201 Ext. 4476 | LA1 4YR #! rnews 1070 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!strath-cs!jml From: jml@cs.strath.ac.uk (Joseph McLean) Newsgroups: sci.math Subject: concatenation making primes Message-ID: <756@stracs.cs.strath.ac.uk> Date: 9 Dec 87 12:47:19 GMT Reply-To: jml@cs.strath.ac.uk (Joseph McLean) Organization: Comp. Sci. Dept., Strathclyde Univ., Scotland. Lines: 14 tege@nada.kth.se replied by e-mail to my original posting which asked if it is always possible to append digits to a positive number in order to make a prime. Unfortunately, his address is one of those I can't reach, and so I thought I'd kill two birds with one stone and post another article. His argument is very simple, using the Prime Number Theorem to give an approximation to the number of primes between x.10^n and x.10^n+10^n-1 (which is the same problem I asked but translated to mathematics) which shows that as n -> inf, this number of primes also goes to infinity. A very simple argument that proves you can always append digits to make any number into a prime. Great stuff. jml, the mad mathematician. #! rnews 1275 Path: alberta!mnetor!uunet!mcvax!ukc!stc!root44!miduet!misoft!tait From: tait@gec-mi-at.co.uk (Philip Tait) Newsgroups: comp.sys.ibm.pc,comp.sources.wanted Subject: Re: Wanted: PC Checkbook Software Summary: Continental Software's Home Accountant Plus Keywords: Checkbook Message-ID: <800@gec-mi-at.co.uk> Date: 9 Dec 87 17:34:03 GMT References: <985@mhuxh.UUCP> Sender: news@gec-mi-at.co.uk Reply-To: tait@gec-mi-at.co.uk (Philip Tait) Organization: Marconi Instruments Ltd., St. Albans, UK Lines: 15 Xref: alberta comp.sys.ibm.pc:9577 comp.sources.wanted:2719 In article <985@mhuxh.UUCP> vxb@mhuxh.UUCP (Vern Bradner) writes: > >Can anyone suggest a PC checkbook program? I use Home Accountant Plus by Continental Software. The (legit.) version I use was originally bundled with the Columbia MPC, so it had to be 'unprotected' and altered to remove some hardware dependencies. (Incidentally, this made it possible to compile it with QuickBasic - essential if you're impatient like me!) I've found it reasonably secure and well-featured. | Philip J. Tait, Marconi Instruments Ltd. | St. Albans, Herts. AL4 0JN, U.K. | | UUCP: ...mcvax!ukc!hrc63!miduet!tait | NRS : tait@gec-mi-at.co.uk | | Voice: +44 727 36421 x4549 Telex: 297221 | Fax: +44 727 39447 | #! rnews 1059 Path: alberta!mnetor!uunet!mcvax!ukc!stc!idec!kbsc!yorick From: yorick@kbsc.UUCP (Yorick Phoenix) Newsgroups: comp.os.cpm,comp.sources.wanted Subject: Kermit for MP/M Message-ID: <888@kbsc.UUCP> Date: 7 Dec 87 17:23:21 GMT Organization: The Knowledge-Based Systems Centre, London, UK Lines: 16 Xref: alberta comp.os.cpm:1030 comp.sources.wanted:2720 I have a friend who is trying to transfer some files off of an Micromation MP/M system. He has so far moved the standard "Generic" CP/M Kermit (slowly) to the MP/M machine but it doesn't seem to work correctly. Has anybody ever managed to get Kermit to work under M/PM? Is there a simple set of differences between C/PM kermit and M/PM Kermit. We have the full source code for C/PM Kermit. Yorick Phoenix -- +------------------------------------------+ The Knowledge-Based Systems Center | yorick@kbsc.UUCP | 58 Northside, Clapham Common | ..mcvax!ukc!{idec,hrc63}!kbsc!yorick | LONDON SW4 9RZ England +------------------------------------------+ Voice: +44 1 350 1622 #! rnews 1946 Path: alberta!mnetor!uunet!mcvax!ukc!stc!root44!gwc From: gwc@root.co.uk (Geoff Clare) Newsgroups: comp.unix.questions Subject: Re: rmail under HP-UX (was Re: Using RMAIL under HPUX) Summary: RISC architecture Keywords: RISC, HP-UX Message-ID: <495@root44.co.uk> Date: 10 Dec 87 13:58:20 GMT References: <8711251805.AA02481@mitre-bedford.ARPA> <3720010@hpsemc.UUCP> <3631@xanth.cs.odu.edu> Reply-To: gwc@root44.UUCP (Geoff Clare) Organization: Root Computers Ltd, London, England Lines: 31 >In article <3720010@hpsemc.UUCP>, bd@hpsemc.UUCP (bob desinger) writes: >> Here's how it is on our HP-UX system, a model 840: >> drwxrwxr-x 2 bin mail 1024 Nov 25 18:45 /usr/mail >> -rwxr-sr-x 2 root mail 137216 Oct 2 00:00 /bin/rmail >Wow! Why is rmail so BIG? What does HP-UX rmail do that SMAIL 2.5 >doesn't? Contrast the size of this rmail with various executables >found on our 4.3 BSD system. >-rwxr-xr-x 2 root staff 35840 Nov 3 07:02 /bin/rmail (SMAIL 2.5) >-rwxr-xr-x 1 root staff 104448 Jun 5 1986 /lib/ccom (C compiler) >-rwxr-xr-x 1 root staff 97280 Dec 5 05:17 /usr/local/carmen (Lisp) >-rwsr-xr-x 1 root staff 100352 Apr 5 1987 /usr/lib/sendmail The HP840 is a RISC architecture machine. Reduced instruction set implies more instructions required to do the same job than on a 'complex' instruction set machine, hence the proportionately larger executable files. Presumably your 4.3BSD machine is a VAX-alike (i.e. complex instruction set). The only other file from your list which exists on our HP840 system is the C compiler, and look at the size of that beast!! -rwxrwxr-x 1 bin bin 1097728 Mar 5 1987 /lib/ccom (No, that's not a typo - it really is more than 1 Megabyte!) Geoff Clare gwc@root.co.uk seismo!mcvax!ukc!root44!gwc -- Geoff Clare gwc@root.co.uk seismo!mcvax!ukc!root44!gwc #! rnews 1904 Path: alberta!mnetor!uunet!mcvax!ukc!stc!datlog!slxsys!jpp From: jpp@slxsys.specialix.co.uk (John Pettitt) Newsgroups: comp.unix.xenix Subject: Re: 16-bit versus 32-bit memory performance Summary: 32 bit cpu on 16 bit ram is a waste of money Message-ID: <109@slxsys.specialix.co.uk> Date: 10 Dec 87 14:17:13 GMT References: <388@ddsw1.UUCP> <620@omen.UUCP> <435@spdcc.COM> Reply-To: jpp@slxsys.UUCP (John Pettitt) Organization: Specialix International, London, UK. Lines: 29 This should perhaps belong in comp.arch It would appear that most 8088,8086,186 and 286 systems are limited by the number of cycles taken to execute instructions (I.E the clock speed). However the 80386 (at 16 and esp at 20 Mhz) is limited by its memory bus bandwidth. That is the memory subsystem on most 286 boxes is fast enough have little or no real effect on performance compared to a change in clock speed. An 80386 however is largly limited by the rate that it can be 'fed' data and instructions. 16 Bit memory subsystems have a devestating effect on the 80386 for 2 reasons. Firstly 2 memory accesses are required rather than one thus doubling the access time. Secondly most 16 bit memory cards are designed for 8 or 10 Mhz operation not 16 Mhz so a significant number of wait states are needed when used with a 386. It would appear that a 'cache miss' on the Intel Inboard(tm) generates beteween 10 and 12 wait states thus making access to 16 bit ram slower than from the original 286. In conclustion - if you want a 32 bit CPU use 32 bit ram. If you just want the instruction set use the P9 (80388) - if it ever appears. (This posting written on a Dell 386 with 6 MB of 0 wait static 32 bit ram) -- John Pettitt - 144.5 MHz: G6KCQ, CIX: jpettitt, Voice: +44 1 398 9422 UUCP: ...uunet!mcvax!ukc!pyrltd!slxsys!jpp (jpp@slxsys.specialix.co.uk) Disclaimer: I don't even own a cat to share my views ! #! rnews 1704 Path: alberta!mnetor!uunet!mcvax!unido!iaoobelix!woerz From: woerz@iaoobelix Newsgroups: comp.unix.wizards Subject: Re: Request for human interface design a - (nf) Message-ID: <8300012@iaoobelix.UUCP> Date: 3 Dec 87 01:35:00 GMT References: <10559@brl-adm.UUCP> Lines: 32 Nf-ID: #R:brl-adm:10559:iaoobelix:8300012:000:1331 Nf-From: iaoobelix!woerz Dec 3 02:35:00 1987 > /***** iaoobelix:comp.unix.wiz / oberon!blarson / 5:40 pm Nov 28, 1987*/ > In article <7995@steinmetz.steinmetz.UUCP> dawn!stpeters@steinmetz.UUCP (Dick St.Peters) writes: > >(The VMS interface is not always so friendly to novices: name the file > >"junk" instead of "junk.txt", and a novice may never figure out how to > >read it. As for expert interfaces, rename the expert's .emacs file to > >sav.emacs and watch him/her try to recover.) > > I'm no VMS expert and I know a way to recover. Use a gun to put a few > bullets in the aproprate disk drive. (When it is replaced and the > backups restored, my .emacs reappears. :-) And if you're out of luck, a backup has been done between the time you changed your .emacs file and the shooting of the disk and you will get your changed file. :-( > -- > Bob Larson Arpa: Blarson@Ecla.Usc.Edu > Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson blarson@skat.usc.edu > Prime mailing list (requests): info-prime-request%fns1@ecla.usc.edu > /* ---------- */ ------------------------------------------------------------------------------ Dieter Woerz Fraunhofer Institut fuer Arbeitswirtschaft und Organisation Abt. 453 Holzgartenstrasse 17 D-7000 Stuttgart 1 W-Germany BITNET: iaoobel.uucp!woerz@unido.bitnet UUCP: ...{uunet!unido, pyramid}!iaoobel!woerz #! rnews 1992 Path: alberta!mnetor!uunet!mcvax!unido!tub!actisb!federico From: federico@actisb.UUCP (Federico Heinz) Newsgroups: comp.sys.atari.st Subject: Re: Hard disk boot??? Keywords: Hard disk, GEMBOOT Message-ID: <122@actisb.UUCP> Date: 8 Dec 87 19:34:12 GMT References: <624@aucs.UUCP> Reply-To: federico@actisb.UUCP (Federico Heinz) Organization: Actis in Berlin GmbH, W. Germany Lines: 39 [The line eater was sleeping again ...] In article <624@aucs.UUCP> 870646c@aucs.UUCP (barry comer) writes: >I have a few questions for anyone using a SH204 with a Mega ST. I have a Meag2 >with a SH204, I have being auto booting from the hard disk using HDB_V2.3, I >used to be able to auto boot from the floppy when the CTRL,SHIFT, and ALT. >keys were held down, well since I started using the Mega, the machine always >boots from the hard disk with the keys down or up?????????????? I didn't know of the CTRL-SHIFT-ALT trick, but I had a problem similar to yours: there was no way my Mega would boot from floppy, and that turned out to be quite a problem when a desk accessory I had downloded from somewhere was turned unusable because of line noise. My "solution" was not to boot from hard disk at all, which I now find better since it allows me to choose different configurations (desk accesories and such) depending on the job I'm going to do. >I am also using GEMBOOT to overcome the 40 folder limit in TOS(has it been >fixed with the new ROMS?). I'm also interested on this question, and it has been already asked a couple of times with no visible answer. I've never used the old ROMs, so I don't know what the infamous "40 folder limit" means. I've had more than 40 folders on my hard disk and nothing happened. Does this mean that the problem is fixed? Or is it 40 folders DEEP? /////// //____ // Federico // // // __ // // / / // /////// UUCP: ...!mcvax!unido!tub!actisb BIX: fheinz #! rnews 888 Path: alberta!mnetor!uunet!mcvax!varol From: varol@cwi.nl (Varol Akman) Newsgroups: sci.physics Subject: Texts a la Feynman Summary: I would like to read them Message-ID: <144@piring.cwi.nl> Date: 11 Dec 87 10:59:47 GMT Organization: CWI, Amsterdam Lines: 12 I've been re-reading recently Feynman's excellent volumes and enjoying myself. The question is: Are there physics books of similar style? One thing that I like about Feynman is that he tries to ``demystify'' stuff instead of giving cookbook formulas. Since I do this as a leisurely activity, the absence of too many formulas and long mathematical analyses (at least in Vol. I) are also appreciated. I'm especially interested in classical mechanics. Philosophical implications of physics laws such as causality, etc. are also interesting. Send me individual replies and I'll post a summary to the net. Thanks! -Varol Akman #! rnews 1649 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!bath63!pes From: pes@ux63.bath.ac.uk (Smee) Newsgroups: rec.games.misc Subject: Re: The Pawn help Keywords: ** EXPLICIT SPOILERS ** Message-ID: <2011@bath63.ux63.bath.ac.uk> Date: 9 Dec 87 11:24:10 GMT References: <2884@cbmvax.UUCP> <2299@killer.UUCP> <2910@cbmvax.UUCP> Reply-To: pes@ux63.bath.ac.uk (Smee) Organization: AUCC c/o University of Bath Lines: 22 In article <2910@cbmvax.UUCP> daveb@cbmvax.UUCP (Dave Berezowski) writes: > >I've been told that there is a bug in the game such that you must get to >the pedestal asap else the blue key won't be there (this is what has happended >to me)... The story I've heard is that this is not a bug. Rather (as warned in the manual) the other characters you meet are also poking around, and can have effects even while they are not in the same location as you. In particular, as I've heard it, if the adventurer gets to the pedestal before you do then he will take the key. (And allegedly you then can recover it when you kill him.) I haven't tried this line of play yet, so can't vouch for it, but it sounds plausible. There's a cute bug in the ST version, though, to do with the pedestal. If you move the pedestal and then type 'take all' you end up carrying the pedestal, a duplicate of which remains in place. (If you just try to 'take pedestal', you are told that it is too heavy to lift.) I'm told that this results from a bug in the relevant object definition table entry, so it might have propagated to other versions. (I'd doubt that the driving data undergoes as much analysis as the executable code during porting to other machines.) #! rnews 1317 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!nott-cs!pyr1.cs.ucl.ac.uk!awylie From: awylie@pyr1.cs.ucl.ac.uk Newsgroups: comp.sys.ibm.pc Subject: Zorland/Datalight C INT86 problem Message-ID: <39500003@pyr1.cs.ucl.ac.uk> Date: 8 Dec 87 13:23:00 GMT Lines: 24 Nf-ID: #N:pyr1.cs.ucl.ac.uk:39500003:000:954 Nf-From: pyr1.cs.ucl.ac.uk!awylie Dec 8 13:23:00 1987 Hi, I have a problem with the Zorland C compiler, aka Datalight-C or NorthWest-C which I wondered if any netlander had previously encountered and solved. I have a program which works fine in small model but recently I had to go to the data model (small code, large data) whereupon it hung my XT clone. Tracing execution seems to indicate that the DOS software interrupt routine INT86 may be the source of the trouble. Has anyone seen problems with INT86 in D or L model programs? The prospect of DEBUGging the interface between C and assembler does not appeal to me. BTW I have deliberately not given details of the program. I do not want to debug it on the net. Please e-mail me only if you have solid evidence of problems in the INT86 area. thanks for any help you can give, Andrew Andrew Wylie University of London Computer Centre, London, England uucp: awylie@uk.ac.ucl.cs JANET: andrew@ulcc.ncdlab #! rnews 644 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!nott-cs!pyr1.cs.ucl.ac.uk!awylie From: awylie@pyr1.cs.ucl.ac.uk Newsgroups: comp.sys.ibm.pc Subject: Re: Virus program warning Message-ID: <39500004@pyr1.cs.ucl.ac.uk> Date: 8 Dec 87 17:12:00 GMT References: <6146@jade.BERKELEY.EDU> Lines: 8 Nf-ID: #R:jade.BERKELEY.EDU:-614600:pyr1.cs.ucl.ac.uk:39500004:000:227 Nf-From: pyr1.cs.ucl.ac.uk!awylie Dec 8 17:12:00 1987 Presumably it would be relatively easy to modify the virus program to make it into an 'antibody' which would automatically overwrite the virus on any infected floppy which was used on the PC. Andrew Wylie awylie@uk.ac.ucl.cs #! rnews 541 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!nott-cs!pyr1.cs.ucl.ac.uk!awylie From: awylie@pyr1.cs.ucl.ac.uk Newsgroups: rec.games.hack Subject: NetHack 2.2 part 18 Message-ID: <42700005@pyr1.cs.ucl.ac.uk> Date: 10 Dec 87 09:51:00 GMT Lines: 8 Nf-ID: #N:pyr1.cs.ucl.ac.uk:42700005:000:193 Nf-From: pyr1.cs.ucl.ac.uk!awylie Dec 10 09:51:00 1987 People in the UK and Europe who need NetHack 2.2 part18 can get it by sending me e-mail, preferably to my Janet address. Andrew Wylie Janet: andrew@ulcc.ncdlab uucp: awylie@uk.ac.ucl.cs #! rnews 892 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!nott-cs!smb!dave From: dave@smb.co.uk (Dave Settle) Newsgroups: comp.sources.wanted Subject: B-tree routines required. Keywords: b-tree index rmcobol Message-ID: <18@oscar.smb.co.uk> Date: 8 Dec 87 11:17:39 GMT Organization: SMB Business Software, Mansfield, UK Lines: 21 I'm looking for a set of routines which can handle B-trees, as part of a program which I'm writing to recover RM-COBOL indexed files. If anyone knows of any routines which might be helpful (or any hints about how to go about it), I'd be very grateful to hear about them. Please reply to me directly by mail, as I don't (yet) get this newsgroup directly. Thanks in advance, Dave Settle. --- Dave Settle, SMB Business Software, Thorn EMI Datasolve, High St, Mansfield, UK UUCP: dave@smb.co.uk ...!mcvax!ukc!nott-cs!smb!dave <--- This way to point of view ---> #! rnews 3785 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!sph From: sph@eagle.ukc.ac.uk (S.P.Holmes) Newsgroups: rec.games.misc,rec.games.frp,rec.games.board Subject: Re: WARGAMING! Message-ID: <4067@eagle.ukc.ac.uk> Date: 11 Dec 87 10:24:28 GMT References: <796@lln-cs.UUCP> Reply-To: sph@ukc.ac.uk (S.P.Holmes) Organization: Computing Lab, University of Kent at Canterbury, UK. Lines: 76 Xref: alberta rec.games.misc:1153 rec.games.frp:1655 rec.games.board:544 Summary: Expires: Sender: Followup-To: In article <796@lln-cs.UUCP> gf@lln-cs.UUCP (Frank Grognet) writes: > > I want to start wargaming but I don't know how! > >I won't be playing wargames on a board, but with 15mm or 25mm >figurines. >I would like to find addresses in Europe (especially Belgium) >of good figurine manufacturers and also references to rule >books for the Napoleonic period. The best set which I've found are the Wargames Research Group 1685 - 1850 rules. Although the time period sounds a bit long these rules have the following advantages (My opinions only). - Wide ranges of troops covered (You can fight outside Europe) - Wide range of weapons covered (Pikes for those Moscow Militiamen etc) - Simple solution for combat - This is what I really like, There@s No nonsense evaluating every 20th of a casualty, or evaluating grenadier companies firing separate from the rest of their battallion. - All weapons are handled simply. Just a different entry in one table. - Movement is alternate, not simultaneous, things move much quicker. - Hand to hand combat is decided very quickly, (Just like reality). - Morale tests are also quite fast to do, and give specific tests for different situations. (This avoids an old problem where eg Horsemen test morale before charging, Test fails horribly, Horsemen rout off the field.) To make you go away, the opponent actually has to do something. - European regulars have "National characteristics". ie British are disciplined infantry and rash cavalry. Russians are stoical Infantry (Won@t retreat easily) Spanish are easily panicked Highlanders charge aggressively French columns are impetuous and frighten the enemy. Austrian and Prussian cavalry are Bold Austrian, Spanish and Dutch Generals are Cautious. Together with these rules I would recommend the army lists published by Table Top Games. These cover the European armies for most of the big campaigns of 1805-1815 and ensure a balanced army is selected (Although the 1000 point armies don@t always work too well. eg My russians need 12 Gun Artillery Batteries (6 pieces on the table) This leaves me few points for infantry or cavalry (In practice a Russian 1000 point army has two of Inf, Cav & Art) The lists also help to enhance the National Flavour of an army ie British get few Cavalry, but some veteran Infantry. French after 1812 have Raw Infantry or Guards. Austrians Have Very Large numbers Of infantry. I can summarise some of the +/- points of each of the armies I've seen if you mail me. I'd recommend 15mm scale troops (Much cheaper and more transportable) They'll fit on your table too. I actually use the 6mm scale which is cheaper, lighter and requires about 60cm x 100 cm for a medium game. However the Job of painting, mounting and moving the little guys is much harder. >I am also interested in rules contained on the net or in files at >other sites, if they exist! Copyright makes this difficult. >I anybody can help me, please reply to ..!mcvax!prlb2!lln-cs!gf -- Steve Holmes | Noel Coward : "Would you object if I smoked" Room 109a | E-mail sph | Sarah Bernhardt : "I wouldn't care if you burned" Phone ext 7681 or 3682 | #! rnews 1737 Path: alberta!mnetor!uunet!mcvax!ukc!pyrltd!lucifer!rob From: rob@lucifer.UUCP ( 237) Newsgroups: rec.arts.sf-lovers Subject: Re: Origin of Hithchiker's Guide Message-ID: <6@lucifer.UUCP> Date: 11 Dec 87 10:03:57 GMT References: <909WDMCU@CUNYVM> <1240001@otter.HP.COM> Reply-To: rob@lucifer.UUCP (Rob Clive - 237) Organization: Lucas Micos, Phoenix Way, Cirencester, Glos, UK (0285 67981) Lines: 24 In article <1240001@otter.HP.COM> kers@otter.HP.COM (Christopher Dollin) writes: >> I have recently been told be someone that The Hitchhiker's Guide to the >> Galaxy originated as a radio program rather than as a book. > >The radio series "The Hitch-hikers Guide to the Galaxy" was broadcast in >Britain for the first time between 1976..1979 (sorry for the range but all I It was 1978. Episode 1 of the first series was a pilot production for the whole thing and as such is slightly different in flavour to the others. The first series (6 episodes) covered the ground of the TV version and books 1 and 2. Then came the Christmas (1978) show to make a link to the second series which was broadcast in 1979 and consisted of 5 episodes. > For my money, the show (and scripts) are MUCH funnier than the books. True. The radio shows left much more to the imagination with the assistance of some very good sound effects. I thought the TV series spoiled it. For instance at the end of the first radio series you hear the song 'What a Wonderful World' amid the sound of burning trees on prehistoric Earth; can't you just imagine it? ----------------------------------------------------------------------------- Rob Clive. UUCP: ...!mcvax!ukc!lucifer!rob Lucas Micos Ltd., Cirencester, GL7 1QG, UK. Now read on.... #! rnews 1160 Path: alberta!mnetor!uunet!mcvax!botter!tjalk!rblieva From: rblieva@cs.vu.nl (Roemer Lievaart) Newsgroups: rec.music.classical Subject: Re: The range of the male voice. Message-ID: <918@tjalk.cs.vu.nl> Date: 11 Dec 87 13:06:10 GMT References: <1280@phoenix.Princeton.EDU> <1597@faline.bellcore.com> <3999@pucc.Princeton.EDU> Reply-To: rblieva@cs.vu.nl (Roemer B. Lievaart) Organization: VU Informatica, Amsterdam Lines: 15 Q2816@pucc.Princeton.EDU (Roger Lustig) typed: +--------------------------------------- | Choral music is generally written for a fairly restricted range (note | the two qualifications in that sentence) in order to allow choirs, not | individuals, to sing it. There are choral high Bb's (in Singet dem | Herrn, for instance) and even C's for the sopranos (end of Kodaly's | Laudes Organi), and the incredible stuff Beethoven asked for in the | Missa Solemnis and Ninth. But they are the exception, and are generally | intended to sound like an exception. +--------------------------------------- We're playing Mahler's 2nd, and so I noticed last wednesday that the Basses have to sing as deep as (at least ?) the low B. -- Roemer. #! rnews 871 Path: alberta!mnetor!uunet!mcvax!botter!ast From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: Re: scanf() Message-ID: <1782@botter.cs.vu.nl> Date: 11 Dec 87 14:40:54 GMT References: <782@louie.udel.EDU> Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 10 In article <782@louie.udel.EDU> KIMMEL%ecs.umass.edu@relay.cs.net (Matt Kimmel) writes: >I just got Minix v1.2, and I like it a lot. However, when I try to >compile a C program that calls scanf(), I get a message to the effect >of " _scanf not resolved". Am I missing something? Or is there no scanf() There is a scanf in libsrc.a, but it is not included in libc.a. You have to compile it yourself with cc -LIB -c scanf.c and put in in the library. It was omitted from libc.a because there was no room on that diskette! Andy Tanenbaum (ast@cs.vu.nl) #! rnews 1614 Path: alberta!mnetor!uunet!mcvax!guido From: guido@cwi.nl (Guido van Rossum) Newsgroups: comp.windows.x Subject: X and different IPC protocols Summary: Surely feasible; but how useful? Message-ID: <145@piring.cwi.nl> Date: 11 Dec 87 22:15:13 GMT Reply-To: guido@cwi.nl (Guido van Rossum) Organization: "The Amoeba Project", CWI, Amsterdam Lines: 22 Although X as distributed uses TCP/IP to connect clients and server, it is possible use other network protocols by relatively small changes to the lowest levels of library and server. We have almost gotten the server half of such a set-up running using Amoeba (a distributed operating system with its own, capability-based RPC mechanism). The library half should be working as soon as we solve problems with the C compiler. The question is, how much does this buy us? Since Amoeba is not Unix, X clients requiring advanced Unix features won't run under vanilla Amoeba. What percentage of the available client applications will be convertable to a different operating system, where, e.g., one will have available, but not select(2)? I would assume that there will be VMS support for X, so that one might expect clients to be OS-independent, but then again, you can never know what hacks a performance-driven application programmer may use... (including VAX assembly :-) Can anybody comment on this? It would also be interesting to know if third-party software for X would come binary or source. -- Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam guido@cwi.nl or mcvax!guido or (from ARPAnet) guido%cwi.nl@uunet.uu.net #! rnews 1102 Path: alberta!mnetor!uunet!mcvax!prlb2!kulcs!wim From: wim@kulcs.UUCP (Wim De Bisschop) Newsgroups: comp.lang.ada Subject: Ada-interface to Termcap(3) Keywords: termcap Message-ID: <1075@kulcs.UUCP> Date: 11 Dec 87 10:56:28 GMT Organization: Kath.Univ.Leuven, Comp. Sc., Belgium Lines: 15 Has anyone an Ada interface to the C routines from the termcap library? We would have a package for terminal independent screen oriented output in Ada. The most natural way to do this, is to make use of the C-routines of termcap. We were wondering whether someone else has already defined an interface package, preferably for a Verdix 5.41 compiler to run under 4.3BSD. +----------------------------------------------------------------------+ | Name: Wim De Bisschop | Katholieke Universiteit Leuven | | E-mail: wim@kulcs.UUCP or | Department of Computer Science | | ...!mcvax!prlb2!kulcs!wim | Celestijnenlaan 200 A | | Phone: +(32) 16-200656 x3596 | B-3030 Leuven (Heverlee), Belgium| +----------------------------------------------------------------------+ #! rnews 835 Path: alberta!mnetor!uunet!mcvax!enea!erix!erialfa!afr From: afr@erialfa.UUCP (Anders Fredrikson ZX/DRG) Newsgroups: rec.music.misc Subject: Re: Ace-Screamingest Guitar Solos on Record Message-ID: <172@erialfa.UUCP> Date: 10 Dec 87 12:31:18 GMT References: <1725@s.cc.purdue.edu> <2455@sfsup.UUCP> Reply-To: afr@erialfa.UUCP (Anders Fredrikson ZX/DRG) Organization: Ericsson Information Systems AB, Kista, Stockholm, SWEDEN Lines: 17 In article <2455@sfsup.UUCP> mingus@sfsup.UUCP (Damballah Wedo) writes: >> rsk@s.cc.purdue.edu.UUCP (in <1725@s.cc.purdue.edu>): >> [ lists some excellent guitar solos ] > >Sure, I'll play that game: > >...... >---cut >She'a a Woman (Jeff Beck, BLOW BY BLOW) This tune is even better on the "Jeff Beck & Jan Hammer group LIVE" >---Cut >..... You might also add Europa (Santana, MOONFLOWER) /Anders #! rnews 1046 Path: alberta!mnetor!uunet!mcvax!enea!pvab!robert From: robert@pvab.UUCP (Robert Claeson) Newsgroups: comp.lang.c Subject: Re: Making re-#includes harmless--a simple solution? Message-ID: <339@pvab.UUCP> Date: 11 Dec 87 10:23:09 GMT References: <13395@think.UUCP> Reply-To: robert@pvab.UUCP (Robert Claeson) Organization: Statskonsult Programvaruhuset AB, Sweden Lines: 16 In article <13395@think.UUCP> rlk@THINK.COM writes: >1) The same file may have multiple names (symlinks and/or hard >links). How do you KNOW whether a file has been included? The only >way is by defining an attribute that only that file will have. The >easiest way to do this (aside from checking device/inumbers, which is >not portable and may not work in some bizarre cases, or other system >dependent hacks) is to #define a unique name. How can you be sure that the name you choose is unique, especially if you use links or symlinks? -- Robert Claeson, System Administrator, PVAB, Box 4040, S-171 04 Solna, Sweden eunet: robert@pvab uucp: sun!enea!pvab!robert #! rnews 1812 Path: alberta!mnetor!uunet!mcvax!enea!ttds!draken!sics!lhe From: lhe@sics.se (Lars-Henrik Eriksson) Newsgroups: rec.arts.sf-lovers Subject: Re: Houston SF Opera Message-ID: <1642@sics.se> Date: 11 Dec 87 10:31:40 GMT References: <8168@ism780c.UUCP> Reply-To: lhe@sics.se (Lars-Henrik Eriksson) Organization: Swedish Institute of Computer Science, Kista Lines: 32 In article <8168@ism780c.UUCP> jimh@ism780c.UUCP (Jim Hori) writes: >The Lessing is probably Doris who has >written several futurist/SF novels ... >Her SF novels are serialized, and from what >I recall from scanning them in bookstores, >reminiscent of Marge Piercy's enjoyable, >though somewhat stiff, feminist SF. > >The series is called "Canopus and Argos: Archives", Should be Canopus IN Argos: Archives The five books are quite different in character. The second one ("The marriages between zones 3, 4 and 5") could possibly be called "feminist SF" - it is very different from the other four in most ways. The third ("The Sirian Experiments") is at times rather funny, and the fifth ("The sentimental agents in the Volyen empire") is among the funniest books I've read. On the other hand, number 4 ("The making of the representative of planet 8") was rather depressing. While reading it I thought that "it can't get any worse than this". It could, of course. (I don't refer to the quality of the book, but to the events in the story). I should mention the title of the first one also: "Shikasta" This is the most "important" of the five, in some sense. It is also the one that could perhaps be called "stiff". All the books are well worth reading. Lars-Henrik Eriksson Internet: lhe@sics.se Swedish Institute of Computer Science Phone (Intn'l): +46 8 750 79 70 Box 1263 Telefon (nat'l): 08 - 750 79 70 S-164 28 KISTA #! rnews 768 Path: alberta!mnetor!uunet!mcvax!enea!tut!santra!kolvi!jku From: jku@kolvi.UUCP (Juha Kuusama) Newsgroups: comp.sys.ibm.pc Subject: Re: EVALuation of Shareware Word Processors - Version 1 Message-ID: <32@kolvi.UUCP> Date: 11 Dec 87 07:40:17 GMT References: <3610@dhw68k.UUCP> Reply-To: jku@kolvi.UUCP (Juha Kuusama) Organization: Helsinki University of Technology, Finland Lines: 9 I'm not at all questioning the value of the comparision, but (as a VERY satisfied and registered) user of PC-Write, I'd like to point out that: - PC-Write does support the ega in 43-line mode - PC-Write can remind you to do backups at specified time intervals or when you have entered a specified number of characters. --- Juha Kuusama, jku@kolvi.UUCP ( ...!mcvax!tut!kolvi!jku ) #! rnews 904 Path: alberta!mnetor!uunet!mcvax!diku!daimi!jnp From: jnp@daimi.UUCP (J|rgen N|rgaard) Newsgroups: comp.sys.mac Subject: Re: Conjecture: why several tech notes failed Message-ID: <1248@daimi.UUCP> Date: 10 Dec 87 08:43:14 GMT References: <9827@ut-sally.UUCP> Reply-To: jnp@titan.UUCP (J|rgen N|rgaard) Organization: DAIMI: Computer Science Department, Aarhus University, Denmark Lines: 16 Earlier this year there has been trouble with tech-notes, that would not binhex correctly (the Mac program). Then the problem could be solved with a similiar program on unix-machines. The problem seemed to show up when the file-names where extremely long (28 might be the number). It seemed not to be so sensitive about file-names. Unfortunately I have lost the sources. -- Regards J|rgen N|rgaard e-mail: jnp@daimi.dk ------------------------------------------------------------------------------- #! rnews 785 Path: alberta!mnetor!uunet!mcvax!diku!iesd!jacob From: jacob@iesd.uucp (Jacob stergaard B{kke) Newsgroups: sci.misc Subject: A request on the Ozone layer Keywords: More information wanted about the Ozone layer. Message-ID: <174@iesd.uucp> Date: 11 Dec 87 13:38:23 GMT Reply-To: jacob@iesd.UUCP (Jacob \stergaard B{kke) Organization: Dept. of Comp. Sci., Aalborg University, Denmark Lines: 12 Today I read an posting from rhorn@infinet.UUCP about the problems with the Ozone layer. So I got interested and now wanted more information about it and the problems with the Ozone layer in Switzerland present. I would like any information and I'll look forward to any reponds. Yours sincerely Jacob Baekke, Denmark Reply to: jacob@iesd.uucp, {...}!mcvax!diku!iesd!jacob #! rnews 1246 Path: alberta!mnetor!uunet!mcvax!inria!imag!jarwa From: jarwa@imag.UUCP (Jarwa Sahar) Newsgroups: comp.software-eng Subject: LOOKING FOR DOCUMENTS ON SOFTWARE DOCUMENTATION Message-ID: <2336@imag.UUCP> Date: 11 Dec 87 09:15:21 GMT Reply-To: jarwa@imag.UUCP (Jarwa Sahar) Organization: IMAG, University of Grenoble, France Lines: 26 I am very interested in all publications concerning Documents Related to Software Documentation and to Maitenance Environment. What I am interested in are papers on different types of these documents, their formalism and their structure. If this area also interest you, I'd be very pleased if you could contact me, or send me your papers and/or what you have found interesting pertaining to this area. This will help me making a preliminary study on it. Looking forward to your answer, and thank you for your help. Sahar JARWA My adress is Sahar JARWAH Equipe "Systemes Intelligents de Recherche d'Informations" Laboratoire de Genie Informatique - IMAG BP 68 38462 St Martin d'Heres Cedex FRANCE my phone is 76-51-46-00 extension 5182 my electronic adress is jarwa@imag.imag.fr on UUCP: jarwa@imag #! rnews 1217 Path: alberta!mnetor!uunet!mcvax!inria!imag!jarwa From: jarwa@imag.UUCP (Jarwa Sahar) Newsgroups: comp.databases Subject: LOOKING FOR DOCUMENTS Message-ID: <2337@imag.UUCP> Date: 11 Dec 87 09:18:16 GMT Reply-To: jarwa@imag.UUCP (Jarwa Sahar) Organization: IMAG, University of Grenoble, France Lines: 26 I am very interested in all publications concerning Documents Related to Software Documentation and to Maitenance Environment. What I am interested in are papers on different types of these documents, their formalism and their structure. If this area also interest you, I'd be very pleased if you could contact me, or send me your papers and/or what you have found interesting pertaining to this area. This will help me making a preliminary study on it. Looking forward to your answer, and thank you for your help. Sahar JARWA My adress is Sahar JARWAH Equipe "Systemes Intelligents de Recherche d'Informations" Laboratoire de Genie Informatique - IMAG BP 68 38462 St Martin d'Heres Cedex FRANCE my phone is 76-51-46-00 extension 5182 my electronic adress is jarwa@imag.imag.fr on UUCP: jarwa@imag #! rnews 2496 Path: alberta!mnetor!uunet!mcvax!unido!laura!hmm From: hmm@laura.UUCP (Hans-Martin Mosner) Newsgroups: comp.lang.smalltalk Subject: User Survey Keywords: survey smalltalk curiosity Message-ID: <165@laura.UUCP> Date: 10 Dec 87 21:31:51 GMT Organization: University of Dortmund, W-Germany Lines: 59 To stir up some unrest, we have decided to post a smalltalk user survey. Where are you, all you happy smalltalk hackers ? There must be life in other parts of the world, too... :-) Anyway, we would like you to fill in this questionnaire and give us some feedback. Of course we would also like if you would post your experiences and questions to this group. After all, that's it's purpose... Hans-Martin Mosner & Andreas Toenne Smalltalk hackers at the University of Dortmund +------------------------------- |1. What kind of hardware/software do you use: |1.1. Hardware |1.1.1. Processor type: _____ |1.1.2. Physical memory size: _____ |1.1.3. Display size: _____ |1.2. Software |1.2.1. Operating system: _____ |1.2.2. Virtual machine: _____ |1.2.3. Virtual image version: _____ |1.3 Overall performance: _____ % Dorado (if you know that) |2. For what purposes do you use smalltalk ? | (FillInThisBlank) |3. Do you think that the system meets your requirements ? | If not, why ? |4. If you are a programmer: |4.1. What kind of applications have you written ? |4.2. If those applications were not written for your employer, | why didn't you share them with the Usenet community ? :-) |5. How do you like smalltalk ? |5.1. How long have you been using smalltalk ? |5.2. How familiar are you with smalltalk ? +------------------------------- Thank you for being so cooperative. Now that you have answered all those questions, please send the whole thing back to: hmm@unido.uucp or hmm@unido.bitnet or ...!uunet!unido!hmm or hmm%unido.uucp@uunet.uu.net If everything fails, just post it to this group... If even that does not work, then send it via snail mail to: Hans-Martin Mosner Informatik-Rechner-Betriebsgruppe Universitaet Dortmund Postfac` 500500 D-4600 Dortmund West Germany Disclaimer: these opinions are not opinions but just random bits & bytes and therefore I don't need to disclaim anything... -- Hans-Martin Mosner | Don't tell Borland about Smalltalk - | hmm@unido.{uucp,bitnet} | they might invent TurboSmalltalk ! | ------------------------------------------------------------------------ Disclaimer: TurboSmalltalk may already be a trademark of Borland... D #! rnews 14600 Path: alberta!mnetor!uunet!mcvax!unido!laura!atoenne From: atoenne@laura.UUCP (Andreas Toenne) Newsgroups: comp.lang.smalltalk Subject: A small IconEditor for Smalltalk 80, VI2.2 Keywords: smalltalk icons goodie Message-ID: <166@laura.UUCP> Date: 10 Dec 87 21:48:21 GMT Organization: University of Dortmund, W-Germany Lines: 525 Here is a little IconEditor I wrote. This goodie works on Smalltalk 80 VI2.2 VM1.1 It comes in two parts. The first part 'Icon menu.st' adds knowledge about icons to the StandardSystemController's blueButtonMenu. You should file in this one first. The second part 'Icon Editor.st' is the editor himself. Some notes about icons: The icon's textRectangle is clipped with the icon's boundingBox. To cancel a given textRectangle simply move it outside the outlined box. The method storeOn: in class OpaqueForm is buggy. You should add enclosing round brackets to the output. Otherwise you won't be able to read the saved icon definitions back. Have fun Andreas Toenne atoenne@unido.uucp atoenne@unido.bitnet ...!uunet!unido!atoenne atoenne%unido.uucp@uunet.uu.net ~~~~~~~~~~~~~~~~~~ cut here for best results ~~~~~~~~~~~~~~~~~~~~~~~~~~ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Icon Editor.st # Icon Menu.st # This archive created: Thu Dec 10 22:36:04 1987 export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'Icon Editor.st' then echo shar: "will not over-write existing file 'Icon Editor.st'" else cat << \SHAR_EOF > 'Icon Editor.st' MouseMenuController subclass: #IconDisplayController instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Icon Editor'! !IconDisplayController methodsFor: 'controller default'! isControlActive ^ super isControlActive and: [sensor blueButtonPressed not]! ! !IconDisplayController methodsFor: 'menu messages'! yellowButtonActivity | index menu | menu _ view yellowButtonMenu. menu == nil ifTrue: [view flash. super controlActivity] ifFalse: [index _ menu startUpYellowButton. index ~= 0 ifTrue: [self controlTerminate. view perform: (menu selectorAt: index). self controlInitialize]]! ! View subclass: #IconDisplayView instanceVariableNames: 'icon aspect iconMsg iconMenu ' classVariableNames: '' poolDictionaries: '' category: 'Icon Editor'! IconDisplayView comment: 'I am a stupid view used to display the edited icon'! !IconDisplayView methodsFor: 'displaying'! displayView "display icon centered in my insetBox" | r iconRect rec | Display white: self insetDisplayBox. (icon isKindOf: Icon) ifTrue: [r _ self insetDisplayBox. icon form displayOn: Display at: r topLeft + r bottomRight - icon form extent // 2. iconRect _ icon form computeBoundingBox. iconRect _ iconRect translateBy: r topLeft + r bottomRight - iconRect extent // 2. (iconRect areasOutside: (iconRect insetBy: 1 @ 1)) do: [:edge | Display fill: edge mask: Form gray]. rec _ icon textRect. rec = nil ifFalse: [rec _ rec translateBy: r topLeft + r bottomRight - icon form computeBoundingBox extent // 2. (rec areasOutside: (rec insetBy: 1 @ 1)) do: [:edge | Display fill: edge mask: Form gray]]]! ! !IconDisplayView methodsFor: 'updating'! update: anAspect "update the view" anAspect == aspect ifTrue: [icon _ model perform: iconMsg. self displayView]! ! !IconDisplayView methodsFor: 'menu messages'! allBlack "make the selected icon all black" | figure shape | figure _ icon form figure. shape _ icon form shape. figure fill: figure computeBoundingBox rule: Form over mask: Form black. shape fill: figure computeBoundingBox rule: Form over mask: Form black. model changed: #iconView! allGray "make the selected icon all transparent" | figure shape | figure _ icon form figure. shape _ icon form shape. figure fill: figure computeBoundingBox rule: Form over mask: Form white. shape fill: figure computeBoundingBox rule: Form over mask: Form white. model changed: #iconView! allWhite "make the selected icon all white" | figure shape | figure _ icon form figure. shape _ icon form shape. figure fill: figure computeBoundingBox rule: Form over mask: Form white. shape fill: figure computeBoundingBox rule: Form over mask: Form black. model changed: #iconView! editIcon "edit the selected icon" | figure shape opaqueForm iconExtent bitView viewPoint savedForm | (icon = nil and: [model iconSymbol ~= #default]) ifTrue: [iconExtent _ Rectangle fromUser extent. figure _ Form extent: iconExtent. shape _ Form extent: iconExtent. opaqueForm _ OpaqueForm figure: figure shape: shape. model icon: (Icon form: opaqueForm textRect: nil)]. icon = nil ifFalse: [viewPoint _ (BitEditor locateMagnifiedView: icon form scale: 4 @ 4) topLeft. bitView _ BitEditor bitEdit: icon form at: viewPoint scale: 4 @ 4 remoteView: nil. savedForm _ Form fromDisplay: (bitView displayBox merge: bitView labelDisplayBox). bitView controller startUp. savedForm displayOn: Display at: bitView labelDisplayBox topLeft. bitView release. model changed: #iconView]! textRect "let the user specify a rectangle that will hold the icon's text" | rec r| rec _ Rectangle fromUser. r _ self insetDisplayBox. rec _ rec translateBy: 0@0 - (r topLeft + r bottomRight - icon form computeBoundingBox extent //2). icon form: icon form textRect: rec. model changed: #iconView! ! !IconDisplayView methodsFor: 'controller access'! defaultControllerClass ^IconDisplayController! ! !IconDisplayView methodsFor: 'private'! on: anIcon aspect: m1 icon: m2 menu: m3 self model: anIcon. aspect _ m1. iconMsg _ m2. iconMenu _ m3! ! !IconDisplayView methodsFor: 'adaptor'! yellowButtonMenu ^ self model perform: iconMenu! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! IconDisplayView class instanceVariableNames: ''! !IconDisplayView class methodsFor: 'instance creation'! on: anIcon aspect: m1 icon: m2 menu: m3 "create a new view for anIcon with aspect m1" ^self new on: anIcon aspect: m1 icon: m2 menu: m3! ! Model subclass: #IconEditor instanceVariableNames: 'icon iconSymbol iconBuffer ' classVariableNames: 'IconMenu ListMenu ' poolDictionaries: '' category: 'Icon Editor'! IconEditor comment: 'I am a bit editor for system icons. Instance Variables : icon "The selected icon" iconSymbol "The symbol for the selected icon" Class Variables: ListMenu "The action menu for the SelectionInListView over all icons"'! !IconEditor methodsFor: 'accessing'! icon "return the selected icon" ^icon! icon: anIcon "change the selected Icon to anIcon" icon _ anIcon. Icon constantNamed: iconSymbol put: anIcon. self changed: #iconView " aspect for the IconDisplayView"! icon: anIcon named: aSymbol " store anIcon at position aSymbol" Icon constantNamed: aSymbol put: anIcon. icon _ anIcon. iconSymbol _ aSymbol. self changed: #iconSymbol. "aspect for SelectionInListView" self changed: #iconView "aspect for iconDisplayView "! iconSymbol "return the symbol for the selected icon" ^iconSymbol! iconSymbol: aSymbol "change the symbol for the selected icon to aSymbol" iconSymbol _ aSymbol. icon _ Icon constantNamed: aSymbol. self changed: #iconView "aspect for the IconDisplayView"! ! !IconEditor methodsFor: 'removing'! removeIcon " remove the currently selected icon " Icon constantDictionary removeKey: iconSymbol ifAbsent: [^nil]. iconSymbol _ icon _ nil. self changed: #iconSymbol. self changed: #iconView! ! !IconEditor methodsFor: 'list display'! iconList "return the list of icon symbols" | list | list _ OrderedCollection new. Icon constantDictionary keysDo: [:i | list add: i]. ^list! initialSymbol "get the initial symbol selection" "this method is used every time the SelectionInListView receives an update mesage " ^iconSymbol! listMenu "return the menu for the icon list" ^ListMenu! ! !IconEditor methodsFor: 'icon display'! iconMenu "return the menu for the iconDisplayController" ^IconMenu! ! !IconEditor methodsFor: 'menu messages'! copy " save a (deep) copy of the currently selected icon" icon = nil ifFalse: [iconBuffer _ icon deepCopy]! cut " remove the currently selected icon from the icon dictionary and save it in iconBuffer" (icon ~= nil or: [iconSymbol ~= #default]) ifTrue: [iconBuffer _ icon. self removeIcon]! loadIcon "override the current icon with a definition from a file" | aFileName anIcon aStream | (icon ~= nil or: [iconSymbol ~= #default]) ifTrue: [aFileName _ FileDirectory requestFileName: 'file : ' default: iconSymbol asString , '.icn' version: #old ifFail: [^'']. aFileName ~= '' ifTrue: [aStream _ FileStream oldFileNamed: aFileName. anIcon _ Object readFrom: aStream. aStream close. self icon: anIcon]]! newIcon " create a new clean icon" | iconName | iconName _ FillInTheBlank request: 'Icon Name ?'. iconName = '' ifFalse: [self icon: nil named: iconName asSymbol]! paste " change the currently selected icon to the icon held in iconBuffer" " invoke newIcon if none is selected" iconSymbol = nil ifTrue: ["add a new icon" self newIcon. iconSymbol = nil ifFalse: [self icon: iconBuffer]] ifFalse: ["override old icon" self icon: iconBuffer]! renameIcon " change the name of an icon" | key value newName | (icon ~= nil or: [iconSymbol ~= #default]) ifTrue: [key _ iconSymbol. value _ icon. newName _ FillInTheBlank request: 'Change icon name' initialAnswer: key. newName ~= '' ifTrue: [self removeIcon. self icon: value named: newName asSymbol]]! saveIcon "store the selected icon to a file" | aFileName aStream | icon = nil ifFalse: [aFileName _ FileDirectory requestFileName: 'file : ' default: iconSymbol asString , '.icn' version: #any ifFail: [^'']. aFileName ~= '' ifTrue: [aStream _ FileStream newFileNamed: aFileName. icon storeOn: aStream. aStream close]]! ! !IconEditor methodsFor: 'view creation'! open "open the views" | topView | topView _ StandardSystemView model: self label: 'Icon Editor' minimumSize: 256 @ 300. topView addSubView: (SelectionInListView on: self aspect: #iconSymbol change: #iconSymbol: list: #iconList menu: #listMenu initialSelection: #initialSymbol) in: (0 @ 0 corner: 1.0 @ 0.3) borderWidth: 1. topView addSubView: (IconDisplayView on: self aspect: #iconView icon: #icon menu: #iconMenu) in: (0.0 @ 0.3 corner: 1.0 @ 1.0) borderWidth: 1. topView controller open! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! IconEditor class instanceVariableNames: ''! !IconEditor class methodsFor: 'class initialization'! initialize "Initialize the class IconEditor" "IconEditor initialize" ListMenu _ ActionMenu labelList: #((copy cut paste ) (newIcon renameIcon ) (saveIcon loadIcon ) ) selectors: #(copy cut paste newIcon renameIcon saveIcon loadIcon ). IconMenu _ ActionMenu labelList: #((editIcon textRect ) (allWhite allBlack allGray) ) selectors: #(editIcon textRect allWhite allBlack allGray)! ! !IconEditor class methodsFor: 'instance creation'! open "create on schedule a new Icon Editor" self new open! ! IconEditor initialize! SHAR_EOF fi if test -f 'Icon Menu.st' then echo shar: "will not over-write existing file 'Icon Menu.st'" else cat << \SHAR_EOF > 'Icon Menu.st' !MouseMenuController methodsFor: 'menu messages'! blueButtonActivity "Determine which item in the blue button pop-up menu is selected. If one is selected, then send the corresponding message to the object designated as the menu message receiver." "Enhanced to use HierarchicalMenus by atoenne@unido.uucp" | index | blueButtonMenu ~~ nil ifTrue: [index _ blueButtonMenu startUpBlueButton. index ~= 0 ifTrue: [blueButtonMenu class = HierarchicalMenu ifTrue: [self menuMessageReceiver perform: (blueButtonMenu selectorAt: index)] ifFalse: [self menuMessageReceiver perform: (blueButtonMessages at: index)]]] ifFalse: [super controlActivity]! ! !StandardSystemController class methodsFor: 'class initialization'! initialize "Initialize the class variables." "StandardSystemController initialize. StandardSystemController allInstances do: [:sc | sc initializeBlueButtonMenu] " ScheduledBlueButtonMenu _ (MenuBuilder parseFrom: (ReadStream on: 'newLabel[newLabel] (under[under] move[move] frame[frame]) (collapse[collapse] icon: ((selectIcon[selectIcon] editIcon[editIcon]) (loadIcons[loadIcons] saveIcons[saveIcons]))) (close[close])')) menu. MenuWhenCollapsed _ ActionMenu labels: 'new label\under\move\expand\close' withCRs lines: #(1 4 ) selectors: #(newLabel under move expand close )! ! !StandardSystemController methodsFor: 'menu messages'! editIcon " call an icon editor " IconEditor open! loadIcons "load new constant definitions for icons" | aFileName | aFileName _ FileDirectory requestFileName: 'file:' default: '*.icn' version: #old ifFail: [^'']. aFileName ~= '' ifTrue: [Icon constantsFromFile: aFileName]! saveIcons "write current icon constants to a file" | aFileName | aFileName _ FileDirectory requestFileName: 'file:' default: '*.icn' version: #any ifFail: [^'']. aFileName ~= '' ifTrue: [Icon constantsToFile: aFileName]! selectIcon "let the user choose from the current icons" | nameList iconList selection selectedIcon | nameList _ OrderedCollection new. Icon constantDictionary keysDo: [:key | nameList add: key]. iconList _ Array with: nameList asArray. selection _ (PopUpMenu labelList: iconList) startUp. selection ~= 0 ifTrue: [selectedIcon _ (Icon constantNamed: (nameList at: selection) asSymbol) copy. self view icon: selectedIcon. "change the icon" self view iconView lock. "essential. see below" self view iconView text: self view label. "set new icon text" self view iconView newIcon] "compute new icon" "lock is needed to perform the newIcon computation. Otherwise insetDisplayBox would be garbled. Text setting is merely needed at the first change. (The standard label has no iconText) "! ! !StandardSystemController initialize. StandardSystemController allInstances do: [:sc | sc initializeBlueButtonMenu]! SHAR_EOF fi exit 0 # End of shell archive D #! rnews 813 Path: alberta!mnetor!uunet!mcvax!unido!laura!atoenne From: atoenne@laura.UUCP (Andreas Toenne) Newsgroups: rec.games.hack Subject: Re: Nethack 2.2: You stop to avoid hitting. Keywords: I have this bug too. Message-ID: <167@laura.UUCP> Date: 10 Dec 87 21:53:23 GMT References: <7515@alice.UUCP> Reply-To: atoenne@unido.UUCP (Andreas Toenne) Organization: University of Dortmund, W-Germany Lines: 9 In article <7515@alice.UUCP> wilber@alice.UUCP writes: >I have nethack running on my 3B1. So far the only bug I've encountered >is the message "You stop to avoid hitting." (Which sometimes comes out as >"You stop to avoid hitting .") I haven't hit the plethora You have defined DOGNAME but you are missing the dog's name :-) Simply add 'dogname:...' to your nethack options. Andreas Toenne D #! rnews 1201 Path: alberta!mnetor!uunet!mcvax!unido!rmi!dg2kk!dg2kk From: dg2kk@dg2kk.UUCP (Walter) Newsgroups: rec.ham-radio.packet Subject: Problems with WA8DED 2.1 and TNC-2 clones (+possible solution) Summary: PTT line is released too early Message-ID: <174@dg2kk.UUCP> Date: 10 Dec 87 23:09:52 GMT Reply-To: dg2kk@dg2kk.UUCP Organization: dg2kk, W Germany, (JO30FT) Lines: 20 Some TNC-2's have problems with the WA8DED software (version 2.1). Most of the outgoing frames cannot be docoded by other stations because the software turns off the transmitter before all bits have been transmitted. There are two solutions to this problem: Hardware: connect a small (~2.2uf) capacitor from the base of the PTT keying transistor to ground. (Note: you may have to increase TXDELAY) Software: the code that turns off the transmitter starts at location $037B (3E 05...). It's possible to insert a short delay loop, so that the transmitter remains keyed for a few milliseconds longer. (I haven't tried this yet.) 73s, Walter dg2kk@dg2kk.UUCP PS: Does anyone know if WA8DED is on USENET/Bitnet/ARPANET/anynet??? What is his email address? Please let me know. Thanks. #! rnews 1319 Path: alberta!mnetor!uunet!mcvax!4gl!honzo From: honzo@4gl.UUCP (Honzo Svasek) Newsgroups: comp.unix.xenix,comp.os.misc,comp.unix.questions,comp.unix.wizards Subject: Re: Venix Users? Message-ID: <253@4gl.UUCP> Date: 11 Dec 87 18:23:50 GMT References: <2439@sputnik.COM> Organization: 4GL Consultants b.v., the Netherlands Lines: 27 Xref: alberta comp.unix.xenix:1172 comp.os.misc:341 comp.unix.questions:4773 comp.unix.wizards:5750 in article <2439@sputnik.COM>, dbb@tc.fluke.COM (Dave Bartley) says: > > The Great OS Search continues ... > > What about Venix? I am using Venix for several years now and have the folowing comments. 1. it IS System V UNIX. 2. It has a faster 'feel' for the interactive user than Xenix or Microport 3. It seems to be bug free. This system is running news and I am doing most of the development on it. I have had no problems for at least a year now, and the system is on the air 24 hours a day. A few times I had to remove the -O options when compiling, but same counts for 3B2 UNIX. 4. Venturecom claims it to be REAL TIME. I have no experience with REAL real-time on this system, and don't know if the venix system calls are interruptable. Honzo Svasek, PS. Anyone out there has a way to install 2.2 on a Seagate ST4096 disk? (on an AT) #! rnews 1252 Path: alberta!mnetor!uunet!mcvax!cernvax!ethz!forty2!vogel From: vogel@forty2.UUCP (Stefan Vogel) Newsgroups: comp.sources.bugs Subject: bug in sush Message-ID: <123@forty2.UUCP> Date: 11 Dec 87 17:02:58 GMT Reply-To: vogel@forty2.UUCP (Stefan Vogel) Organization: Exp. Physics University Zuerich Lines: 33 We found the following bug in sushperm.c of the sush distribution: In routine addgroup the pointer gpmem was incremented before it was used. So, the first member of the group was never found, and the reference to the last member lead to an illegal memory reference (NULL pointer!). original code: gpmem = gpt->gr_mem; while(*gpmem++) { <------------------gpmem is incremented if(!strcmp(user,*gpmem)) <---gpmem is used ok++; } /* auth failed - return */ corrected code: gpmem = gpt->gr_mem; while(*gpmem) { if(!strcmp(user,*gpmem++)) ok++; } /* auth failed - return */ Stefan Vogel, Simon Poole Inst. for Theoretical Physics University of Zuerich Switzerland UUCP: ....mcvac!cernvax!forty2!vogel BITNET: k524911@czhrzu1a #! rnews 626 Path: alberta!mnetor!uunet!mcvax!prlb2!vub!leo From: leo@vub.UUCP (Leo Smekens) Newsgroups: comp.sys.mac Subject: 4th Dimension vs. dBase Mac Keywords: 4th Dimension,dBase Mac,Macintosh Message-ID: <506@vub.UUCP> Date: 11 Dec 87 13:40:05 GMT Organization: Vrije Universiteit Brussel, Brussels Lines: 14 What can 4th Dimension do what dBase Mac can't? What can dBase Mac do what 4th Dimension can't? Who should invest in which program? If you don`t like answering on the net, please mail direct to: leo@vub.vub.uucp Leo Smekens Metabolism & Endocrinology Free University of Brussels Laarbeeklaan 103 B-1090 BRUSSELS BELGIUM #! rnews 783 Path: alberta!mnetor!uunet!mcvax!prlb2!vub!leo From: leo@vub.UUCP (Leo Smekens) Newsgroups: comp.sys.mac Subject: Latest SE's shipped Keywords: Mac,Mac SE,Macintosh,Macintosh SE,hardware Message-ID: <507@vub.UUCP> Date: 11 Dec 87 13:50:46 GMT Organization: Vrije Universiteit Brussel, Brussels Lines: 15 We noticed that the last Macintosh SE's we received at our university are equipped with a new type of mouse,and, apparently,with another internal disk drive (at least,it sounds differently and beeps upon activation). What has been changed on the new Mac SE compared to the first version? If you don't like to answer via the net,please mail direct to: leo@vub.vub.uucp Leo Smekens Metabolism & Endocrinology Free University of Brussels Laarbeeklaan 103 B-1090 BRUSSELS BELGIUM #! rnews 1432 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!csnjr From: csnjr@its63b.ed.ac.uk (Nick Rothwell) Newsgroups: rec.music.misc Subject: Re: Ace-Screamingest Guitar Solos on Record Keywords: guitar, flames (regrettably) Message-ID: <826@its63b.ed.ac.uk> Date: 11 Dec 87 13:06:12 GMT References: <1725@s.cc.purdue.edu> <1349@saturn.ucsc.edu> <6480@ihlpa.ATT.COM> Reply-To: nick@lfcs.ed.ac.uk (Nick Rothwell) Organization: LFCS, University of Edinburgh Lines: 21 In article <6480@ihlpa.ATT.COM> rjp1@ihlpa.ATT.COM writes: >>C'mon people, you can't omit: >... >Edgar Froese - Underwater Twilight, Riding The Ray, Le Parc and > Heartbreakers tunes, etc, etc. Froese's best guitar solo, by most accounts, is on Cloudburst Flight on the Force Majeure album, back in '79. He starts with slow chords and fingering on a 12 string acoustic, then some "power chords" (!) on the 12 string, and then onto the electric (Fender Strat I think). Some of the recent live work's been good, as well - Franke holding down a rhythm, with Froese and Haslinger both firing off screaming guitar riffs. >Bob Pietkivitch ( e - x - p - o - s - u - r - e ) UUCP: ihnp4!ihlpa!rjp1 -- Nick Rothwell, Laboratory for Foundations of Computer Science, Edinburgh. nick%lfcs.ed.ac.uk@nss.cs.ucl.ac.uk !mcvax!ukc!lfcs!nick ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "Nothing's forgotten. Nothing is ever forgotten." - Herne #! rnews 818 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!gvw From: gvw@its63b.ed.ac.uk (G Wilson) Newsgroups: comp.sys.transputer Subject: Meiko email contact Message-ID: <827@its63b.ed.ac.uk> Date: 11 Dec 87 13:23:42 GMT Reply-To: gvw@its63b.ed.ac.uk (G Wilson) Organization: I.T. School, Univ. of Edinburgh, U.K. Lines: 18 In response to several queries --- Meiko Ltd. is not connected to any electronic mail network at present. However, both myself and Dr. Duncan Roweth, who are Meiko employees working on the Edinburgh Concurrent Supercomputer Project, are connected to various networks. I can be reached at: gvw@itspna.ed.ac.uk (usual) gvw@its63b.ed.ac.uk (alternative) while Duncan is: egnp36@meiko.ed.ac.uk If you want more information on Meiko, please include a telephone number and a physical mail address. Greg #! rnews 733 Path: alberta!mnetor!uunet!mcvax!ukc!dcl-cs!nott-cs!pyr1.cs.ucl.ac.uk!awylie From: awylie@pyr1.cs.ucl.ac.uk Newsgroups: rec.games.misc Subject: Re: Does anyone remember Zork1? (*S Message-ID: <42800002@pyr1.cs.ucl.ac.uk> Date: 11 Dec 87 09:42:00 GMT References: <22039@ucbvax.BERKELEY.EDU> Lines: 8 Nf-ID: #R:ucbvax.BERKELEY.EDU:-2203900:pyr1.cs.ucl.ac.uk:42800002:000:300 Nf-From: pyr1.cs.ucl.ac.uk!awylie Dec 11 09:42:00 1987 Its a looooong time since I played Zork, but I believe that you can get to the INSIDE of the grate in the woods by which time you should have obtained a key which will open it. This gives you an alternative entrance/ exit to the dungeon, but is not actually much help. Andrew awylie@uk.ac.ucl.cs #! rnews 1324 Path: alberta!mnetor!uunet!mcvax!ukc!eagle!icdoc!ivax!mst From: mst@ivax.doc.ic.ac.uk (Martin Taylor) Newsgroups: rec.games.trivia Subject: Re: words to a song (old lady who swallowed a fly) Message-ID: <148@gould.doc.ic.ac.uk> Date: 11 Dec 87 10:55:47 GMT References: <2170@homxc.UUCP> <12270004@hpldola.HP.COM> <1053@mtuxo.UUCP> Sender: news@doc.ic.ac.uk Reply-To: mst@doc.ic.ac.uk (Martin Taylor) Organization: Dept. of Computing, Imperial College, London, UK. Lines: 26 In article <1053@mtuxo.UUCP> gertler@mtuxo.UUCP (xm960-D.GERTLER) writes: >As I recall, the sequence is as follows (more or less): > > 1) Fly Perhaps she'll die. > 2) Spider That wriggled and jiggled and tickled inside her. > 3) Bird How absurd to swallow a bird! > 4) Cat Imagine that, to swallow a cat! > 5) Dog What a hog, to swallow a dog! > 6) Horse She's dead, of course! > >I seem to remember a goat at about 5.5, but I don't >recall it's associated comment. Sorry. > It's "She just opened her throat, and swallowed a goat" Also heard at an informal church social group, this alternative ending: 6) Horse Not easy, of course, but she swallowed a horse 7) Minister That finished her! Martin S Taylor Department of Computing JANET/ARPANET : mst@doc.ic.ac.uk Imperial College +44 589 5111 X4996 LONDON SW7 2BZ #! rnews 1060 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!aiva!ken From: ken@aiva.ed.ac.uk (Ken Johnson) Newsgroups: comp.edu,comp.lang.misc Subject: Free audio tape about Logo Message-ID: <209@aiva.ed.ac.uk> Date: 11 Dec 87 11:33:10 GMT Reply-To: ken@aiva.ed.ac.uk (Ken Johnson) Followup-To: comp.lang.misc Organization: Dept. of AI, Univ. of Edinburgh, UK Lines: 26 Xref: alberta comp.edu:745 comp.lang.misc:887 Logotron Limited have prepared an audio tape called "Logo comes of age". Although it is basically a plug for the Logotron product, (it contains a reference to the mythical "LCSI standard", for example) there is a lot of interesting chat about how Logo is actually used. Playing time 45 minutes. Free from: Logotron Limited, Dales Brewery, Gwydir Street, CAMBRIDGE, England CB1 2LJ Phone (0223) 323656 -- From Ken Johnson | Phone 031-225 4464 Ext 212 AI Applications Institute | Email k.johnson@ed.ac.uk 80 South Bridge | The University | EDINBURGH, Scotland EH1 1HN | "Things will get worse before they get worse." #! rnews 2806 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!tom From: tom@cs.hw.ac.uk (Tom Kane) Newsgroups: comp.ai Subject: Probability Bounds from Bayes Theory: (A Problem). Keywords: Bayes Theorem, Probability, Expert Systems, Uncertainty Message-ID: <1578@brahma.cs.hw.ac.uk> Date: 11 Dec 87 14:10:21 GMT Organization: Computer Science, Heriot-Watt U., Scotland Lines: 65 I am sending this letter out to the network to ask for solutions to a particular problem of Bayesian Inference. Below is the text of the problem, and at the end is the mathematical statement of the information given. Simply, I am asking the questions: 1) Can you find bounds on the final result. If so, how? 2) If not, why is it not possible to do so? What is missing in the specification of the problem? 3) If you get nowhere with this problem, would you be able to solve it if you were given the information: p(pv|t or l)=0.9? I am interested in the problem of providing probability bounds for events specified in a Bayesian setting when not all the necessary conditional probabilities are provided in setting up the problem. PROBLEM ~~~~~~~ (A problem relevant to the handling of Uncertainty in Expert Systems.) We want to know the probability of a patient having both lung cancer and tuberculosis based on the fact that this person has had a positive reading in a chest X-ray. We are given the following pieces of information: 1. The probability that a person with lung cancer will have a positive chest X-ray is 0.9. 2. The probability that a person with tuberculosis will have a positive chest X-ray is 0.95. 3. The probability that a person with neither lung cancer nor tuberculosis will have a positive chest X-ray is 0.07. 4. In the town of interest, 4 percent of the population have lung cancer, and three percent have tuberculosis. EVENTS ~~~~~~ l = lung cancer; t = tuberculosis; pv = positive chest X-ray SETUP ~~~~~ In the statement of the problem below:- ~l means 'not l'. ~l, ~t means 'not l and not t'. t or l means 't or l' where 'not', 'and' , and 'or' are logical operators. so that: p(~l, ~t) means probability( not l and not t). Also, p(pv|l) means the conditional probability of event pv, given event l. PRIORS ~~~~~~ p(l) = 0.04; p(t) = 0.03; p(~l, ~t) = 0.95 CONDITIONALS ~~~~~~~~~~~~ p(pv|l) = 0.9; p(pv|t) = 0.95; p(pv| ~t,~l) = 0.07 (You are not given p(pv| t or l) ) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Please mail all solutions or comments to me, and I will let interested parties know what the results are. (I will specially treasure attempts which don't use independence assumptions.) Thanks in advance to anyone who will spend time on this problem... Regards, Tom Kane. #! rnews 3109 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!adrian From: adrian@cs.hw.ac.uk (Adrian Hurt) Newsgroups: sci.space Subject: Re: SPACE Digest V8 #68 Summary: First submarines Message-ID: <1580@brahma.cs.hw.ac.uk> Date: 11 Dec 87 15:43:08 GMT References: <8712091350.AA00806@angband.s1.gov> Organization: Computer Science, Heriot-Watt U., Scotland Lines: 52 In article <8712091350.AA00806@angband.s1.gov>, ESC1361@DDAESA10.BITNET (Rupert Williams) writes: > > In fact the British must have > been the most war-like nation in the world, fighting with more countries than > anyone I can think off. Is this the reason why the English language is so > popular ( hello America!! )???!!!! I assume you refer to the British Empire - prior to that, Britain (and before the rest joined/were conquered by it, England) fought mostly against either France, Spain or both at once. The wide domain of the English language is directly due to the Empire, just as the wide use of Spanish throughout South and Central America is due to the Spanish Empire. > I think also that ALL countries train their armies in ice and snow??!! Including the Arabs? :-) > As for the Submarine....well I dont know about that, I thought that was an > English invention too, like the Tank and the Jet-plane??! Maybe I'm wrong??! There are a number of ancient submarine designs, including one which was a rowing boat with a watertight cover! The first practical submarine was (I believe) designed by a Mr. Holland, resident of Ireland, for use against the Royal Navy. The Royal Navy took over the design, but regarded such concealed warfare as ungentlemanly, and didn't make much use of them until Germany showed the way. The jet plane was invented practically at the same time by Britain, Germany and the U.S.A. Germany had the first flying jet aircraft, followed closely by Britain. Britain would have had a jet fighter not long after the Battle of Britain except for government intervention. Fortunately, Hitler was equally stupid. The Nazis believed they would win the war in a couple of months, and gave little interest to projects which would bear no short term military results. When they did get the world's first jet fighter (the Me262) it was pretty devastating, albeit rare, until Hitler decided that it would make a great fighter-bomber. Two bombs were fitted under the nose, at the expense of two cannon and much speed and agility. Fortunately, Nazi policy was "if it doesn't work, stomp on whoever says so." The first American jet was too late for WW2, and the first Russian jet had a captured German engine. > As for the NASA/Space shuttle saga, the sooner they pull their fingers out > the better. Arianne is having a field day over this one. Now, for those who say "Why is this in sci.space?", read the above and apply the lessons of history to the shuttle, Hermes, HOTOL, or whatever craft your country should be sponsoring. -- "Keyboard? Tis quaint!" - M. Scott Adrian Hurt | JANET: adrian@uk.ac.hw.cs UUCP: ..!ukc!cs.hw.ac.uk!adrian | ARPA: adrian@cs.hw.ac.uk #! rnews 1128 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: sci.space Subject: Re: Remote Sensing Fascism Message-ID: <1583@brahma.cs.hw.ac.uk> Date: 11 Dec 87 17:36:36 GMT References: <566084060.amon@H.GP.CS.CMU.EDU> Reply-To: jack@cs.glasgow.ac.uk (Jack Campin) Organization: PISA Project, Glesga Yoonie Lines: 18 Summary: Expires: Sender: Followup-To: [ignore the above email address and use my signature] >'Our' (I use the term VERY loosely since I'm not really sure which side >they are on) people have obviously learned how to lie about the >existance of things which are common knowledge >PS: Is it now appropriate to address members of the DOD and the various spook > agencies as Comrade? How about Right Honourable? (or have the Zircon and Spycatcher affairs not made the news over there?) -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 1825 Path: alberta!mnetor!uunet!mcvax!ukc!its63b!hwcs!jack From: jack@cs.hw.ac.uk (Jack Campin) Newsgroups: rec.arts.sf-lovers Subject: Re: Houston SF Opera Message-ID: <1584@brahma.cs.hw.ac.uk> Date: 11 Dec 87 19:10:14 GMT References: <8168@ism780c.UUCP> Reply-To: jack@cs.glasgow.ac.uk (Jack Campin) Organization: PISA Project, Glesga Yoonie Lines: 32 Summary: Expires: Sender: Followup-To: [ignore the above email address and use my signature] In article <8168@ism780c.UUCP> jimh@ism780c.UUCP (Jim Hori) writes: > >I expected somebody to respond by now to the >question about a SF opera being co-written >by Philip Glass and somebody named Lessing, > >Any other news on this opera? It's "the Making Of The Representative From Planet 8", if I remember right. This is from the announcements to a Radio 3 broadcast of Glass's new orchestral piece "The Light" - a tone poem about the Michelson-Morley experiments. Incidentally, it's not the first SF opera. I heard a broadcast in New Zealand of a Swedish opera called "Aniara", based on an epic poem about a colonizer spaceship on its way to oblivion. I can remember neither the poet's nor the composer's name. I've only read the first of Lessing's series and didn't like it much. I felt I was being preached at (Lessing is a Sufi - I don't know whether her having been born in Iran has anything to with that - and it shows in her more recent writing). OK, the content of the sermon may not have been as obnoxious as Heinlein, Tolkien or Pournelle, but it was still gratuitous in literary terms. -- ARPA: jack%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk JANET:jack@uk.ac.glasgow.cs USENET: ...mcvax!ukc!cs.glasgow.ac.uk!jack Mail: Jack Campin, Computing Science Department, University of Glasgow, 17 Lilybank Gardens, Glasgow G12 8QQ, Scotland (041 339 8855 x 6045) #! rnews 1184 Path: alberta!mnetor!uunet!mcvax!ukc!stl!stc!root44!cdwf From: cdwf@root.co.uk (Clive D.W. Feather) Newsgroups: rec.arts.sf-lovers Subject: Asimov, UFO, and others Summary: Where you can find them Message-ID: <497@root44.co.uk> Date: 11 Dec 87 08:48:49 GMT Reply-To: cdwf@root44.UUCP (Clive D.W. Feather) Organization: Root Computers Ltd, London, England Lines: 17 Readers in the UK, and those elsewhere with UK contacts, may like to know... (1) W.H.Smiths are stocking Asimov's "Fantastic Voyage II" in hardback, UKL10.95. (2) An organisation called Channel 5 Video, available at least in W.H.Smiths and Woolworths, produces tapes of UFO, Thunderbirds, Captain Scarlet (under the title "Captain Scarlet and the Mysterons", Stingray (yuk), and, of course, the Prisoner. Each tape that I have seen contains two episodes of the appropriate program. All cost less than UKL10. What proportion of the total output of these programmes is available I can't say, except for the Prisoner (100%). Warning for foreign readers: These tapes are VHS-PAL. According to "Which?" they work in Australia, New Zealand, Europe except France, South Africa, and the Middle East, but not North America. #! rnews 1077 Path: alberta!mnetor!uunet!mcvax!ukc!stl!stc!root44!jgh From: jgh@root.co.uk (Jeremy G Harris) Newsgroups: comp.protocols.tcp-ip Subject: Subnetting questions Keywords: subnet ethernet Message-ID: <498@root44.co.uk> Date: 11 Dec 87 10:25:23 GMT Organization: Root Computers Ltd., London, England Lines: 27 A whole bunch of questions: Does anybody run multiple subnets on a single Ethernet? If so, do you use subnet broadcasts or net broadcasts? Do you find it worthwhile to use ethernet multicast for subnet broadcasts? How do you assign the multicast addresses? For what purposes do you still use net broadcast? Should redirects be provided by an inter-subnet gateway, when both subnets are on the same Ethernet? What are the semantics of 'ICMP redirect to net' in a subnettted environment? Does anybody run multiple classes of subnet on a single net? Does the mechanism proposed in rfc950 ( ICMP broadcasts to discover the subnet mask ) still work? Do you use it? Thanks for your time Jeremy -- Jeremy Harris jgh@root.co.uk #! rnews 1006 Path: alberta!mnetor!uunet!mcvax!ukc!stl!stc!root44!hrc63!nwh From: nwh@hrc63.co.uk (Nigel Holder Marconi) Newsgroups: comp.unix.wizards Subject: Re: /dev/swap - possibility of it being a ramdisk Summary: depends on your system ? Keywords: /dev/swap Message-ID: <476@hrc63.co.uk> Date: 11 Dec 87 10:09:05 GMT References: <712@qetzal.UUCP> <16869@topaz.rutgers.edu> Organization: GEC Hirst Research Centre, Wembley, England. Lines: 12 I have just added some extra memory to a Sun 3. Unfortunately, it did not increase the usable amount of virtual memory. I have been informed (not by Sun I hasten to add), that 4.x will only allocate memory up to the disk swap space size. Adding more memory will speed things up but will not increase your total usable virtual memory size (this is achieved by increasing the swap space). I was also informed that system V does not inforce this type of restriction. Nigel Holder UK JANET: yf21@uk.co.gec-mrc.u ARPA: yf21%u.gec-mrc.co.uk@ucl-cs #! rnews 781 Path: alberta!mnetor!uunet!mcvax!enea!luth!jem From: jem@sm.luth.se (Jan Erik Mostr|m) Newsgroups: comp.sys.mac,comp.sys.mac.hypercard Subject: Hypercard/CD-ROM Message-ID: <902@luth.luth.se> Date: 11 Dec 87 11:31:13 GMT Reply-To: Jan Erik Mostr|m Organization: University of Lulea, Sweden Lines: 8 Xref: alberta comp.sys.mac:10017 comp.sys.mac.hypercard:200 UUCP-Path: {uunet,mcvax}!enea!luth.luth.se!jem Is there someone out there who has experience with Hypercard and CD-ROM. I would appreciate any information (and especially about Mac II/CD-ROM). -- Jan Erik Mostrom | {uunet,mcvax}!enea!luth!jem | Mors certa, University of Lulea | jem@sm.luth.se | vita incerta Sweden | jem@luth.UUCP | #! rnews 1535 Path: alberta!mnetor!uunet!mcvax!enea!diab!pf From: pf@diab.UUCP (Per Fogelstrom) Newsgroups: comp.arch Subject: Re: Why is SPARC so slow? Summary: Yet another "super processor". Message-ID: <344@ma.diab.UUCP> Date: 11 Dec 87 13:59:12 GMT References: <1078@quacky.UUCP> <8809@sgi.SGI.COM> <6964@apple.UUCP> Reply-To: pf@ma.UUCP (Per Fogelstrom) Organization: Diab Data AB, Taby, Sweden Lines: 16 Well, the history repeats once again. A new RISC chip is launched and peopels expectations reaches new "high scores". A few years ago there was another risc chip set brougth to the market, called the Clipper. This processors performence was climed to sweep all competitors off the sceene. Often compared to the DEC 8x00 computers. For this chip set the picture has cleared now. The perfor- mence range is not much more than can be achived with a 16-20 Mhz 68020. The most i have seen of the 33Mhz versions is one running at room temprature. Intergraph is one of the companys who is still using the Clipper (They recently bought the rights for the chip set from NS/Fairchild) . From what i recall they throw out the NS32032 for the Clipper. Well they could have had 2-3 times the clipper performance with the NS32532 today. And they called the buy a bargin ! It's not suprising that the MIPS 2000 gives most power/Mhz, The architecture has evolved during many years, without a hard pressure from the marketing such as 'We must have it NOW!!!'. (John Mashey mayby has another opinion, only my guess) SO: Why is everybody so suprised ????! #! rnews 1169 Path: alberta!mnetor!uunet!mcvax!mhres!jv From: jv@mhres.mh.nl (Johan Vromans) Newsgroups: comp.unix.questions Subject: Re: Finding Files Summary: looking everywhere Message-ID: <1503@mhres.mh.nl> Date: 12 Dec 87 16:08:12 GMT References: <205700003@prism> <4441@ihlpg.ATT.COM> Organization: Multihouse N.V., The Netherlands Lines: 21 In article <205700003@prism> billc@prism.UUCP writes: > > Right now, to find a file somewhere under my current directory, > I use the following alias: > > alias where "find \$cwd -name \!* -exec echo {} \;" > .. etc .. On our systems, a small cron script executes every night the following command: find / -print > /dirfile Finding a file somewhere can be done by grepping in the /dirfile. Of course, the contents of /dirfile are not really up-to-date, but this is just a minor drawback. "find" on the whole system (including mounted disks) takes more than an hour, a grep in /dirfile much less than a minute. -- Johan Vromans | jv@mh.nl via European backbone Multihouse N.V., Gouda, the Netherlands | uucp: ..{uunet!}mcvax!mh.nl!jv "It is better to light a candle than to curse the darkness" #! rnews 904 Path: alberta!mnetor!uunet!mcvax!mhres!jv From: jv@mhres.mh.nl (Johan Vromans) Newsgroups: comp.os.vms Subject: Re: Are VMS and VAX synonymous? Summary: NO Message-ID: <1504@mhres.mh.nl> Date: 12 Dec 87 16:55:05 GMT References: <8712111910.AA18210@ucbvax.Berkeley.EDU> Organization: Multihouse N.V., The Netherlands Lines: 11 In article <8712111910.AA18210@ucbvax.Berkeley.EDU> "ERI::SMITH" writes: >But someone who thinks VAX and VMS are synonymous >MAY POSSIBLY also be expressing a philosophical stance. The only thing you can do between "#ifdef vax" and its corresponding "#endif" is conclude that you are running on a big-endian machine .... -- Johan Vromans | jv@mh.nl via European backbone Multihouse N.V., Gouda, the Netherlands | uucp: ..{uunet!}mcvax!mh.nl!jv "It is better to light a candle than to curse the darkness" #! rnews 691 Path: alberta!mnetor!uunet!mcvax!enea!tut!jh From: jh@tut.fi (Juha Hein{nen) Newsgroups: comp.lang.scheme Subject: Re: Request for MacScheme source for SCOOPS Message-ID: <2108@korppi.tut.fi> Date: 12 Dec 87 07:32:39 GMT References: <8712101554.AA15940@ucbvax.Berkeley.EDU> Reply-To: jh@korppi.UUCP (Juha Hein{nen) Organization: Tampere University of Technology, Finland Lines: 10 MacScheme doesn't have enviroments (atleast my version doesn't). It would be straightforward to port SCOOPS if somebody first provides environments. The hacks provided with MacScheme distribution are not enough. -- Juha Heinanen Tampere Univ. of Technology Finland jh@tut.fi (Internet), tut!jh (UUCP) #! rnews 643 Path: alberta!mnetor!uunet!mcvax!enea!diab!pf From: pf@diab.UUCP (Per Fogelstrom) Newsgroups: comp.arch Subject: Re: Zilog Z320 32-bit chip Keywords: 80,000 vaporware model Message-ID: <345@ma.diab.UUCP> Date: 12 Dec 87 11:15:23 GMT References: <1911@ho95e.ATT.COM> <9071@utzoo.UUCP> <3521@aw.sei.cmu.edu> <485@PT.CS.CMU.EDU> Reply-To: pf@ma.UUCP (Per Fogelstrom) Organization: Diab Data AB, Taby, Sweden Lines: 3 The Z80,000 was put on market just about 8 months ago. It newer reached the target specification (e.g. clock speed) and the performence was not impressive. It has some nice things, but as someone pointed out, to late .......... #! rnews 884 Path: alberta!mnetor!uunet!mcvax!diku!daimi!erja From: erja@daimi.UUCP (Erik Jacobsen) Newsgroups: comp.lang.modula2 Subject: Re: Modula II on IBM PC with HALO graphics Keywords: Modula IBM HALO graphics Message-ID: <1253@daimi.UUCP> Date: 12 Dec 87 13:13:50 GMT References: <17237@glacier.STANFORD.EDU> Reply-To: erja@daimi.UUCP (Erik Jacobsen) Organization: DAIMI: Computer Science Department, Aarhus University, Denmark Lines: 10 jbn@glacier.STANFORD.EDU (John B. Nagle) asks in <17237@glacier.STANFORD.EDU> > Some questions on Logitec Modula II: > > 1. Are subranges assigned space appropriately? In particular, > does 0..255 occupy only one byte? No, subranges occupy the same amount of space as the type they are a subrange of. E.g. 0..255 will occupy two bytes. You may use a CHAR or a BYTE, and convert to and from CARDINAL everytime you need to do some caluculations. #! rnews 869 Path: alberta!mnetor!uunet!mcvax!unido!tub!stx From: stx@tub.UUCP (Stefan Taxhet) Newsgroups: comp.text,comp.sources.wanted Subject: MS-WORD to Q-ONE Keywords: MS-WORD Q-ONE DCA Message-ID: <319@tub.UUCP> Date: 11 Dec 87 18:23:35 GMT Organization: Technical University of Berlin, Germany Lines: 19 Xref: alberta comp.text:1346 comp.sources.wanted:2722 We're looking for a document conversion program. It should translate MS-Word- to Q-ONE-documents. Q-ONE offers conversions to several formats as: Fortune:Word, Wang, IBM's DCA (RFT,FFT) Therefor programs to interchange documents between MS-Word and these format would also help us. Thanks in advance Stefan Taxhet, Communications and Operating Systems Research Group Technical University of Berlin UUCP: ...!pyramid!tub!stx (From the US) ...!mcvax!unido!tub!stx (From Europe) BITNET: stx@db0tui6.BITNET #! rnews 1235 Path: alberta!mnetor!uunet!mcvax!unido!rmi!kkaempf From: kkaempf@rmi.UUCP (Klaus Kaempf) Newsgroups: comp.sys.amiga Subject: Breaking the 54MB limit on HardDisks Keywords: BitMap, Blocksize, filehandler.h Message-ID: <821@rmi.UUCP> Date: 12 Dec 87 12:19:32 GMT Reply-To: kkaempf@rmi.UUCP (Klaus Kaempf) Organization: RMI Net, Aachen, W.Germany Lines: 19 Well, maybe that i've overlooked something really important, but i don't see the 54MB limit with the AmigaDOS. About a yaer ago, when there was no mount command, somebody from CATS posted a sample device driver that mounted itself. It set up a device structure which described the layout of the device. This structure is now documented in dos/filehandler.h. One field in this structure holds the number of longwords per block of this device. This is always set to 128, giving 512 Bytes per Block. Now, if i set this to 256 (1024 Bytes per Block), i should be able to increase the disk limit to 108MB. Apparently, AmigaDOS supports larger blocksizes. Just have a look into the AmigaDOS Manual from Bantam. All block-layouts are described relative to a 'SIZE', nowhere is said that SIZE is fixed to 128 ! So where is the problem ??? (Please, send no flames, only facts !) Klaus #! rnews 2545 Path: alberta!mnetor!uunet!mcvax!botter!ast From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: Getting rid of _cleanup (finally) Message-ID: <1783@botter.cs.vu.nl> Date: 13 Dec 87 11:56:59 GMT Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 97 There was a lot of discussion about how to get rid of my calls to _cleanup earlier. Here is the solution that I finally adopted. The following commands should do the job. cc -c -LIB exit.c putc.c ar r /usr/lib/libc.a exit.c putc.c ar x /usr/lib/libc.a cleanup.s ar d /usr/lib/libc.a cleanup.s ar bfork.s /usr/lib/libc.a cleanup.s This requires the new archiver posted a while back (for the b option). It also assumes that putting cleanup before fork.s will include cleanup.s after exit.s and putc.s (check this). Andy Tanenbaum (ast@cs.vu.nl) : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin echo Extracting \e\x\i\t\.\c sed 's/^X//' > \e\x\i\t\.\c << '+ END-OF-FILE '\e\x\i\t\.\c X#include "../include/lib.h" X XPUBLIC int (*__cleanup)(); X XPUBLIC int exit(status) Xint status; X{ X if (__cleanup) (*__cleanup)(); X return callm1(MM, EXIT, status, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR); X} + END-OF-FILE exit.c chmod 'u=rw,g=r,o=r' \e\x\i\t\.\c set `sum \e\x\i\t\.\c` sum=$1 case $sum in 11315) :;; *) echo 'Bad sum in '\e\x\i\t\.\c >&2 esac echo Extracting \p\u\t\c\.\c sed 's/^X//' > \p\u\t\c\.\c << '+ END-OF-FILE '\p\u\t\c\.\c X#include "../include/stdio.h" X Xextern int (*__cleanup)(); Xextern int _cleanup(); X Xputc(ch, iop) Xchar ch; XFILE *iop; X{ X int n, X didwrite = 0; X X if (testflag(iop, (_ERR | _EOF))) X return (EOF); X X if ( !testflag(iop,WRITEMODE)) X return(EOF); X X if ( testflag(iop,UNBUFF)){ X n = write(iop->_fd,&ch,1); X iop->_count = 1; X didwrite++; X } X else{ X __cleanup = _cleanup; X *iop->_ptr++ = ch; X if ((++iop->_count) >= BUFSIZ && !testflag(iop,STRINGS) ){ X n = write(iop->_fd,iop->_buf,iop->_count); X iop->_ptr = iop->_buf; X didwrite++; X } X } X X if (didwrite){ X if (n<=0 || iop->_count != n){ X if (n < 0) X iop->_flags |= _ERR; X else X iop->_flags |= _EOF; X return (EOF); X } X iop->_count=0; X } X return(ch & CMASK); X} X + END-OF-FILE putc.c chmod 'u=rw,g=r,o=r' \p\u\t\c\.\c set `sum \p\u\t\c\.\c` sum=$1 case $sum in 49878) :;; *) echo 'Bad sum in '\p\u\t\c\.\c >&2 esac exit 0 #! rnews 1120 Path: alberta!mnetor!uunet!husc6!mit-eddie!uw-beaver!cornell!svax!beck From: beck@svax.cs.cornell.edu (Micah Beck) Newsgroups: comp.windows.x Subject: Document previewing using Xps Message-ID: <1898@svax.cs.cornell.edu> Date: 14 Dec 87 13:25:54 GMT Reply-To: beck@svax.cs.cornell.edu (Micah Beck) Distribution: comp Organization: Cornell Univ. CS Dept, Ithaca NY Lines: 18 In article <6224@jade.BERKELEY.EDU> shipley@web1d.berkeley.edu () writes on the subject of troff previewing under X: >The other thing to try is some version of TROFF which can speak PostScript(tm) >which you can then feed through one of the several Xps programs floating >around -- these are PostScript(tm) interpreter/previewers for Xwindows. I've not been very successful in getting Goswell's Xps to preview documents. The Postscript file generated from TeX DVI files by dvi2ps and from Ditroff files by the Transcript psdit program both cause it to choke, although in different ways. Is anyone using Xps successfully for TeX or Ditroff previewing? Is there some trick? Micah Beck Cornell Dept of Computer Science beck@svax.cs.cornell.edu #! rnews 1332 Path: alberta!mnetor!uunet!mcvax!botter!ast From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: Re: Hard disk partitions? Message-ID: <1784@botter.cs.vu.nl> Date: 13 Dec 87 12:13:15 GMT References: <5500001@ucf-cs.ucf.edu> Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 21 In article <5500001@ucf-cs.ucf.edu> tony@ucf-cs.ucf.edu writes: >If partition 1 is set up for DOS and 2 for Minix, with #2 mounted under >/usr, Minix crashes unpredictably. One thing to remember is that the partition size for partition 1 is one smaller than for partition 2. Another possibility is that the MINIX fdisk and the DOS fdisk don't agree on the meaning of the partition table. If everyone would create their partitions from lowest cylinder to highest there would be no ambiguity. However, if the order in the partition table is different from the cylinder order, there are at least three interpretations. 1. Table slot 1 is partition 1 2. Innermost cylinder is partition 1 3. Outermost cylinder is partition 1 I believe that the combination of MINIX, DOS, XENIX and Microport together exhaust the entire list of possibilities. I don'know if this is related to your problem (which I otherwise can't understand), but it is worth keeping in mind. Andy Tanenbaum (ast@cs.vu.nl) #! rnews 873 Path: alberta!mnetor!uunet!mcvax!lambert From: lambert@cwi.nl (Lambert Meertens) Newsgroups: sci.math Subject: Re: Fixed Points Message-ID: <146@piring.cwi.nl> Date: 13 Dec 87 12:09:54 GMT References: <2269@ihuxv.ATT.COM> Organization: CWI, Amsterdam Lines: 14 In article <2269@ihuxv.ATT.COM> eklhad@ihuxv.ATT.COM (K. A. Dahlke) writes: ) If a continuous function maps the unit square into itself, must it have a ) fixed point? [...] ) I seem to remember there is some theorem in topology, ) without resorting to snakes, that says there is always a fixed point ) whenever a closed region in a metric space is continuously mapped into itself. Brouwer's Fixed Point Theorem states that a continuous mapping of an n-cube into itself has a fixed point. This extends, obviously, to any region homeomorphic to an n-cube. -- Lambert Meertens, CWI, Amsterdam; lambert@cwi.nl #! rnews 1075 Path: alberta!mnetor!uunet!mcvax!unido!rmi!zentrale From: zentrale@rmi.UUCP (RMI Net) Newsgroups: rec.ham-radio Subject: Re: My PC generates RFI Message-ID: <822@rmi.UUCP> Date: 13 Dec 87 10:03:45 GMT References: <12354296992.20.QUALCOMM@A.ISI.EDU> Reply-To: dl3no@rmi.UUCP (Rupert Mohr) Organization: RMI Net, Aachen, W.Germany Lines: 21 In article <12354296992.20.QUALCOMM@A.ISI.EDU> QUALCOMM@A.ISI.EDU (Franklin Antonio) writes: : > I'd like to know of some ways to reduce interference to my... : : All PCs generate RFI to some degree. In general, the "clones" are worse : than the brand name "IBM", "COMPAQ", etc. The Macintosh is relatively : quiet. : In general: I would not believe that... (But it may be, that some IBM's are as quiet as a clone...) We have a good mixture of various PCs here... Regarding my recent posting on RFI of my PK-232: The PK-232 was innocent. It was the old power supply which interfered exactly on 80m and 40m with S9 and 20m with S6... -rm P.S. nevertheless: PC's nowadays are much more quiet than those times of TRS-80 (sigh). #! rnews 1629 Path: alberta!mnetor!uunet!mcvax!unido!rmi!zentrale From: zentrale@rmi.UUCP (RMI Net) Newsgroups: rec.ham-radio Subject: Re: some SWL questions Message-ID: <823@rmi.UUCP> Date: 13 Dec 87 10:18:23 GMT References: <38c9774f.44e6@apollo.uucp> <871201110223.1.ED@BLACK-BIRD.SCRC.Symbolics.COM> Reply-To: dl3no@rmi.UUCP (Rupert Mohr) Organization: RMI Net, Aachen, W.Germany Lines: 38 In article <871201110223.1.ED@BLACK-BIRD.SCRC.Symbolics.COM> Ed@MEAD.SCRC.SYMBOLICS.COM (Ed Schwalenberg) writes: : : Date: 30 Nov 87 15:30:00 GMT : From: apollo!nelson_p%apollo.uucp@eddie.mit.edu : : Is there a detailed single-source of info on what I might : hear as I tune around the bands? The much vaunted World : Radio and TV Handbook just covers broadcasting, which I : have little interest in. : : The second source is the Klingenfuss Guide to Utility Stations. : This is harder to come by, but is advertised in RDI. I just got the 6th edition (1988), which is VERY good. You can get it directly : Klingenfuss, Guide to Utility Stations, 6th Edition Klningenfuss Publications Hagenloher Str. 14 D-7400 Tuebingen Fed.Rep.Germany Tel. (+41) 7071 62830 Price: DM 60 (abt. $ 35) maybe plus handling. They are very fast! I received it two days after ordering by telephone. They also have an quarterly update Service. You find a complete listing sorted by frequency an different listings sorted by different services: press by time, fax alphebetically with time schedule addresses, codes, commercial call signs, telegram formats etc. ALL in English, 500 pages with correct entries...... Rupert #! rnews 1503 Path: alberta!mnetor!uunet!husc6!cmcl2!rutgers!orstcs!mist!koff From: koff@mist.cs.orst.edu (Caroline N. Koff) Newsgroups: rec.arts.startrek Subject: Troi's outfit Message-ID: <1501@orstcs.CS.ORST.EDU> Date: 14 Dec 87 13:35:02 GMT References: <1008@percival.UUCP> <275@hi3.aca.mcc.com.UUCP> <2032@charon.unm.edu> <2432@homxc.UUCP> <1987Dec12.230124.16416@gpu.utcs.toronto.edu> <2216@nicmad.UUCP> Sender: netnews@orstcs.CS.ORST.EDU Reply-To: koff@mist.UUCP (Caroline N. Koff) Distribution: na Organization: Oregon State Universtiy - CS - Corvallis, Oregon Lines: 17 If people are noticing and mentioning about Yar's breasts, why not also mention about Troi's low cut outfit!! Why does it need to be so low cut that it shows her crevice? Who is she trying to impress? Do you think that the women in the future, working with men, will be trying to dress sexy? If so, what about the men? Why not let them show off their body too to make things even? I think that the producers, or whoever is in charge of outfits, and character development is making a contemporary decision regarding the issue of how people will dress in the future. I.e. he/she thinks that female will be trying to attract males' attention by bringing out her femininity, but not vice versa, which is the current social behavior. Or, perhaps the producers are just being comformists with bunch of other tv shows + movie producers by keeping females attractive towards men... --Caroline Koff koff!cs.orst.edu@cs.net.relay #! rnews 1028 Path: alberta!mnetor!uunet!mcvax!hafro!krafla!frisk From: frisk@rhi.is (Fridrik Skulason) Newsgroups: comp.sys.ibm.pc Subject: Identifying VGA Message-ID: <100@krafla.rhi.is> Date: 13 Dec 87 11:39:28 GMT Reply-To: frisk@rhi.UUCP (Fridrik Skulason) Organization: University of Iceland (RHI) Lines: 19 In the november issue of Dr.Dobb's Journal there is an article on how to identify the video adaptor in your PC. They cover EGA,CGA,MDA,Compaq and Hercules(mono). What I need is information on how to find out if a VGA (or a PGA) adaptor is installed. Also - can someone tell me how to obtain the current cursor position directly from these adaptors. That is - I need the location of the 6845 registers. The reason I can not use the INT10 function provided is that my program has to work with some TSR programs that access the hardware directly. Thanks... -- Fridrik Skulason University of Iceland UUCP frisk@rhi.uucp BIX frisk This line intentionally left blank ................... #! rnews 805 Path: alberta!mnetor!uunet!husc6!cmcl2!rutgers!orstcs!mist!koff From: koff@mist.cs.orst.edu (Caroline N. Koff) Newsgroups: rec.arts.startrek Subject: Requesting ST:TOS episode directors and writers guide Message-ID: <1502@orstcs.CS.ORST.EDU> Date: 14 Dec 87 13:38:05 GMT References: <1008@percival.UUCP> <275@hi3.aca.mcc.com.UUCP> <2032@charon.unm.edu> <2432@homxc.UUCP> <1987Dec12.230124.16416@gpu.utcs.toronto.edu> <2216@nicmad.UUCP> Sender: netnews@orstcs.CS.ORST.EDU Reply-To: koff@mist.UUCP (Caroline N. Koff) Distribution: na Organization: Oregon State Universtiy - CS - Corvallis, Oregon Lines: 6 Has anybody ever posted or have a complete list of directors and writers for each of the ST:TOS episodes? If so, may I have a copy? Thanks in advance. --Caroline Koff koff!cs.orst.edu@cs.net.relay #! rnews 1125 Path: alberta!mnetor!uunet!mcvax!enea!sems!olof From: olof@sems.SE (Olof Backing) Newsgroups: comp.emacs Subject: Problems with uEmacs 3.9e and OS-9/68K C. Message-ID: <207@sems.SE> Date: 13 Dec 87 13:00:39 GMT Organization: Sems AB, Stockholm, Sweden Lines: 32 I have a problem when I try to compile the latest version of microEmacs, ie. 3.9e. The problem occurs in file 'bind.c' at lines 602, 609 and 642, 650 respectively. It's the following lines that causes the error: 600: int (*getbind(c))() 601: 602: int c; 603: 604: { The compiler reports an error at line 602 with 'not an argument'. The same thing happens at line 642; 639: int (*fncmatch(fname))() 640: 641: 642: int fname; 643: 644: { Since my experiences aren't the very best i C sofar, I would like to get some hints on what to do. Maybe Kim Kempf at Microware has the answer for me. Feel free to overwelm me with hints. Until then (when I recieve the hints...), CU all! -- ADDRESS: Havrevagen 14, S-175 43 Jarfalla, Sweden PHONE : (46) 758 33941, 35516 home UUCP : ...{uunet,mcvax,ukc,unido}!enea!sems!olof #! rnews 1708 Path: alberta!mnetor!uunet!husc6!yale!dwald From: dwald@yale-zoo-suned..arpa (David Wald) Newsgroups: rec.arts.startrek Subject: Re: Hide & Q notes and comments and notes and comments and....< Date: 14 Dec 87 04:29:38 GMT References: <19962@yale-celray.yale.UUCP> <17300072@silver> <1838@leadsv.UUCP> Sender: root@yale.UUCP Reply-To: dwald@yale-zoo-suned.UUCP (David Wald) Distribution: na Organization: Yale University Computer Science Dept, New Haven CT Lines: 27 In article <1838@leadsv.UUCP> lilly@leadsv.UUCP (Harriette Lilly) writes: > >In article <17300072@silver>, sl131008@silver.bacs.indiana.edu writes: >> /* Written 7:19 pm Dec 7, 1987 by sl131008@silver.UUCP in silver:rec.arts.startrek */ >> /* ..ditto x 7..... >> /* Written 9:12 pm Dec 6, 1987 by dwald@yale in silver:rec.arts.startrek */ >> /* ---------- "Re: Hide & Q notes and comments <> In article <2328@homxc.UUCP> scott@homxc.UUCP (Scott Berry) writes: ... >> David Wald dwald@yale.UUCP ... >> /* End of text from silver:rec.arts.startrek */ >> /* ditto x 8 > > > Ummm, are you lost?... I was a bit puzzled by this too, since I didn't think my article so brilliant that anyone would want to repost it eight times. If anyone finds out what happened, could they please send me mail? We now return you to your regularly scheduled nonsense... ============================================================================ David Wald dwald@yale.UUCP waldave@yalevmx.bitnet ============================================================================ #! rnews 761 Path: alberta!mnetor!uunet!mcvax!enea!sems!olof From: olof@sems.SE (Olof Backing) Newsgroups: rec.games.misc Subject: Larn at dungeon level 10. Message-ID: <208@sems.SE> Date: 13 Dec 87 18:51:50 GMT Organization: Sems AB, Stockholm, Sweden Lines: 12 Well folks, I've reached to master warlord (lvl 17, ~550000 Exp). To my great dis-something, I haven't found any ladder down to level 11. Somewhere back in my human brain, I recall that I've read something about how to further down in the dungeon. What do I do ?!. Please give me a hint. -- WHOAMI : Olof Backing ! WHERE : Havrevagen 14, S-175 43 Jarfalla, Sweden ! PHONE : + (46) 758 33941, 35516 ! UUCP : ...{uunet,mcvax,ukc,unido}!enea!sems!olof ! #! rnews 1631 Path: alberta!mnetor!uunet!husc6!yale!dwald From: dwald@yale-zoo-suned..arpa (David Wald) Newsgroups: rec.arts.startrek Subject: Re: Terralian Ship in "Haven" Keywords: ST:TNG Message-ID: <20253@yale-celray.yale.UUCP> Date: 14 Dec 87 04:36:39 GMT References: <5243@zen.berkeley.edu> <9615@ufcsv.cis.ufl.EDU> Sender: root@yale.UUCP Reply-To: dwald@yale-zoo-suned.UUCP (David Wald) Distribution: na Organization: Yale University Computer Science Dept, New Haven CT Lines: 19 In article <9615@ufcsv.cis.ufl.EDU> jco@beach.cis.ufl.edu () writes: >In article <5243@zen.berkeley.edu> timlee@cory.Berkeley.EDU (Timothy J. Lee) writes: >>Did anyone think that the Terralian ship was pretty big for something that >>was built by a group of people whose technology approximated late 20th >>century Earth? > >It was my understanding from the show that the people of 20th century >earth could build a virus that could wipe out a planet. This did NOT >mean that they (the Terralians) where of the 20th century tech level. There was more to the 20th century reference than that, however. Dr. Crusher made the point that, since they were only at the technology level of ~20th century Earth, it was easy for the disease to get out of control and spread over the planet. The implication was that if they were more advanced the disease would not have wiped out the entire world. ============================================================================ David Wald dwald@yale.UUCP waldave@yalevmx.bitnet ============================================================================ @< ^Юn PPՀPpPP? P;1*mQ}Q}\ Qn PqP@p~#+a?RdRPbPnRn TdTfTR`RPfs?P`t?PpP1p~kPPЭЭP1|1|1n1nPpP~*f7?PpP1nPpP~*f$?PpP1nxPpP~}*f ?PpP1nPpP~^*f>PpP1nPpP~?*f>PpPbnPpP~!*f>PpPDnPpP~*f>PpP&ݭh&P "=XwpP}O ^1dݬ nPxQ(QoOAЎPxQ(Q[O1o(mVO}NO}\EOOPP/OP$OPѠ쭜1 ݏPÏ`]PPOPݠ#NPPNQPݏT@ݏÏ`]P~PRQQSQdPPPP-PPʭPÏ`]Q QQQQQPÏ`]P~WoEݭЎQС PPݏd@-ݭЎQС PPݏPÏ`]PP,ݭЎQС PP ~ 6 P֡1}Mh^1ݬnPxQ(QMAЎPxQ(QM1m'mM}M}\MԭݏPÏl]PP|MPݠ"kMPP_MQPÏl]PQQA`-Ïl]PQQA`+ݏx@ݏÏl]PQQA`~PRQQSQdPP PPP瑭P敭}Ïl]PQQA`䑭 [ݏ@ݏ~PRQQSQdPP- PQQP0QQPP葭P PPP1~歐ЭP1CݭЎQС PPݏ@*ݭЎQС PP ~ 4 P֡9CݭЎQС PPݏPÏl]PP*ݭЎQС PP ~ T4 P֡ Q孌ЭPЭ"έPPݭ("PPݭ"PP1 ЭP}OKt^1ݬnPxQ(Q KAЎPxQ(Q K1w$mK}K}\JЭP`%PE1PE1PvE1PUJ1PZE|ݭ0!Pd3PP PDPSPW1wPp1xPkPsPw1C}J^1ݬnPxQ(QIAЎPxQ(QI1;#mI}I}\IlDiDaDJIZD+@ݭЎQС PPݏ@@(ݭЎQС PP ~ 1 P֡{@ݭЎQС PPݏ@'H~ݏ@ݭЎQС PP$ݭЎQС PP ~ ~1 P֡@ݭЎQС PPݏ@'lC~ݏ@ݭЎQС PP#ݭЎQС PP ~ 1 P֡?ݭЎQС PPݏ@"'CݏAݭЎQС PP5#ݭЎQС PP ~ 0 P֡>?ݭЎQС PPݏA&B~ݏ(AݭЎQС PP"ݭЎQС PP ~ A0 P֡>ݭЎQС PPݏ,AO&7B~ݏ>AݭЎQС PPa"ݭЎQС PP ~ / P֡}(G^1LݬnPxQ(QGAЎPxQ(QF3X mF}F}\Fݬ}F^ݬnPxQ(QFAЎPxQ(QF1mvF}nF}\eFݏQfПQVԦԦԦ CVԦ EVV-VVPPPNPPWԧ ԧV VPPV}E^1`ݬnPxQ(QEAЎPxQ(QE1mE}E}\EVEPPNEݏ8HaPRݏ8HP!ݏ8HPݭ' <ݭPPPP}E^1WݬnPxQ(QDAЎPxQ(QD@1EmD}D}\Dw?J;ݭЎQС PP ݏBAi#ݭЎQС PP ~ - P֡ Լլ_?J;ݭЎQС PPݏNA #ݭЎQС PP ~ , P֡ԼԼ1WЬPՠY>J(;ݭЎQС PP ݏVA"ݭЎQС PP ~ K, P֡1ЬPРխ12 PPP ЭPPP'>x]PP2~:ݭЎQС PPݏbA"ݭЎQС PP]PP!ݭЎQС PP ~ + P֡ЭЭPР 쑭17ЭP11s=J9ݭЎQС PPݏkAe!ݭЎQС PP ~  + P֡]PPgЭVfԦԦԦ ЬV2PPP2 PPP &ݭP1^P1SP1NژЭP$ЬPЭ*ЭPЭ ݭPPPЭVЦPPЭc<J8ݭЎQС PP ݏ|AU ݭЎQС PP ~ ) P֡}NA ^1h@ݬ nPxQ(Q'AAЎPxQ(QA1}mA}@}\@@PP@nPpP~pPn PnRfRPpP~fPrPRpRpԭax@PpPp@Z;PPR@m@QQQQQP4;S@Q(;QQD@QQQQQQQP17@ݏAݭЎQС PP*c?PpP~ݏAݭЎQС PPp?~ݏAݭЎQС PPݭЎQС PP ~ [( P֡n:1]PP2P?~B6ݭЎQС PP]PPIݭЎQС PP ~ ' P֡ݬ ݏAݭЎQС PP:ݭЎQС PP ~ ' P֡ݬݏAݭЎQС PP'6>ݏAݭЎQС PPp~ݏAݭЎQС PPps>~ݏAݭЎQС PPk>F>aT>PpPL>1-K>d-=>PnPPeP">R`#>Rn$>PfPRpR >+dPnPPeP=R`=RndPfPRpR=8125p=~ݏAݭЎQС PPݭЎQС PPݏA=ݏAݭЎQС PPpn=~ݏAݭЎQС PPݭЎQС PP)~ % P֡=,=p=7-m4ݭЎQС PP ~ % P֡}<,^1ݬnPxQ(Q<AЎPxQ(Q<>.m<}<}\<ݏ2~2~w}<^ݬnPxQ(Qa<AЎPxQ(QM<1Gm@<}8<}\/<,PЬQ`a1 r,PЬQ`a1\,PЬQ`a1!PPQQQQQP2PPPЬP 1PP QQQQQP42PP P0QQPP2PP PQ QQPQ0PPQЬPQJ2ݭЎQС PPݏAݭЎQС PP ~ # P֡};^1ݬ nPxQ(Q:AЎPxQ(Q:@17m:}:}\:q51bM:\VVKV1ݭЎQС PPÏLh:PVQQQQPP)V VPPV1VPPPV8V`1ݭЎQС PPݏAV VPPVȑ9&1ݭЎQС PPÏL9PQQQQPP0ݭЎQС PP:~ -" P֡ЬPݠݏAݭЎQС PPrݭЎQС PP ~ ! P֡ԭЬPРխ1IЭVÏ"9PQQQQP`PÏ9QRRRRQPaÏL8PQQQQQPP2f~zPPPݭf8PPQQP1nPpP~kpP8Pc,P8RpP,nPpP~pPnPpP~pPT8PnRdRfRcR$P;8RpP$nPpP~RpPnPpP~@fP 8R`P8RpPPPЦ 17PPQQP1խ1nPpP~7R`,P7RpP,nPpP~pPnPpP~pP|7PnRdRfRaR$Pc7RpP$W7P PI7QP }?7,^1_@ݬ nPxQ(Q7AЎPxQ(Q6@1hgm6}6}\68V6V(V7Ï]PVQQQP`V VPPV|,|$| ݬ-ݭЎQС PP ~  P֡-ݭЎQС PP)ݏA ݭЎQС PP ~  P֡V5V1V7Ï]PVQQQQP`1-V~ݏBݭЎQС PPÏ]PVQQQP`ݏ!BݭЎQС PPÏ]PVQQQP`PnPPÏ]RVSSSSRbRnRRfRPpP~ݏ%BݭЎQС PPDݭЎQС PP ~  P֡V VPPV1 Ï]P4QQQP`",ݭЎQС PP ݏ,B ݏ:BݭЎQС PPݭЎQС PPݏ>BcݏSBݭЎQС PPxݭЎQС PP ~  P֡+ݭЎQС PPݏWBp,~ݏuBݭЎQС PPݭЎQС PP ~  P֡+ݭЎQС PPݏ~Bp~ݏBݭЎQС PPݭЎQС PP ~  P֡*ݭЎQС PPݏB,nPpP~o pPnPpP~] pP2PPPnPPdPfPpP~ݏBݭЎQС PP ݭЎQС PP ~ u P֡*ݭЎQС PPݏBnPpP~ pPnPpP~ pP-2PPPnPPdPfPa,R`RPpP~ݏBݭЎQС PPK ݭЎQС PP ~  P֡T)ݭЎQС PP ~  P֡nPpP~ pPl1PdPpP~O pP(ݭЎQС PPݏBqnPcPRpR~XpPn PpP~DpPn P`PnRbRPpP~%bPbPpP~ݏ CݭЎQС PP7 ݭЎQС PP ~  P֡@(ݭЎQС PPݏCp$~ݏ.CݭЎQС PP ݭЎQС PP ~ E P֡}0^1@ݬnPxQ(Qo0AЎPxQ(Q[03 Ь0Ь0 1 m0}0}\ 08//|//|/`* /ݏQ (l,*,VPPVP/VbV?/VPPPNPPWWPP WPPWPPWPPW2/~VPPPP8LPݠcV VPPV)PP).Q)QQ.QQQQQQQP)QQQP ..PPPNPPVfr.Цn.Цj.V.PPPP8LPPV A.ЦG.?)ЭP1W2.2.~d.8.PP.PP2-PPP2-~V$-PP--2-~1-P2-QPQ2-~ o-5-2s-~z-2f-PPP2R-~1R-G-PP:-P2/-QQPP2#-~K[-PP -PP2,P,PP2,~#ݭP1P1Pݏ8HP1 ,$ݭЎQС PP ݏ7C ,ݏCCݭЎQС PPݭЎQС PP ~ 0 P֡#ݭЎQС PP ݏGC> *,ݏSCݭЎQС PPQݭЎQС PP ~  P֡Z#ݭЎQС PP ݏWC p+~ݏcCݭЎQС PPn+PgP+RpR~ݏkCݭЎQС PPݭЎQС PP ~ 2 P֡1+|}n+^18Ь[Ь YѬ+ݬoxP+P`ZY j YPYPЬ[ݫh ݫ[e$^ݬPP:ЭѭT ЭJ PPA  PP2 ^Ь[ݫi ݫ[)PЬ[ <P@Q [P[PЬ[ <P@ [zW[PPЬ[ <P@[r ݫ [P" Ѭݬ"%ЬPݬ ݬݬ" ^Ь[ݫ} ݫ ݫ ݫ k+Ы P ݫxЫ P <  kPPk֭ѭ   ^ݏVS:߭-nf"p~At!ݬ_[1ѫ1ի i@ݫ Xݫ lݫ Ы P ݫݫuPݫE<P@Ы[[1r[^uԽѭ8H3 Es ݬݬP[ ݫ gЫ[[Э PݼeZPpPpPqP+r3PqP""&pPt+.PZVsP`VZbVeVVXuXdPVuXcVPR`VPfRPdPPRRZZPp~ dPpP!c&pf?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~T7RBdݭRNP֭S}TTPRPTSCRQSTP}TPRPPQRЭP^Ь[Ь Ь\ԭIY HhX>HXZ1XZZ1Z ЌYZYYЌXXXZX0XWWVWWWWPPnW#VWP֭WPHWxWP@QWVS00S,aVcc8Va0VUQnSW-WЭP0PVVPPVP(PacЭP,a0PcXPZ Z.έPPXXPPX,a0PcXPPVVPPX(PacXP@ R]RRPPXPX,a0PcSUDeB+XZX0XWWWWPPnW֭WPP=WxWP@Z=Q&QVPPn8neVQZ1, 1%WVXЭ1P0PPX(WVPXQ0Z Z u0e.UZ1Q0ZZXXXZ1.1+pU1rUUURR;RRRƏR0qPURRRRR dUR R\tPTUPUP  tUPUPXWюnWW qU  PpPT~MSRRRRTRdcPSTRgPPRQRR(RSSAQBbT BCG@M [u+pPB<Vvӈb2>HQS'I[#,; :ܒX^Ь[ PPYYX1XX߭ ~PYj~P  BЫZ֫ZPѫPѬ ZPPXPZ ~PYZkn 1mЫZ3[J1xݏPZZ  YYX ZYYXZYZ ~%PY2kZXY 1ЬPЬ[ PʏPP@ЫZ:ZY3Z P2PPkYZ ~PY PPV[ [[[ Ь[Z < 7[gPZ ~9PZ ݫ ԫ kZP}(P^߭ݬ4PPPݬݏ tݬݬݏtݬ6 P.(Zz$Zrlo]`~*PYI[Nk$jkkZjxYP[PZPxYP[PP[1[Zk[[ZZ  [$ZPYPƏPxPbPZxPZPPZx~@PZZZPZPxPZPPjjs$Zg1xYP[PTZMEHk92k[P Ь[[ZZZjPPj ^Ь[ [[PPݬNPZZ[ZP[Z~PYYYЭPЭQ`aЭP׭PZ[xYPZPP[xYPZP[PPy@j\ ~\S^\_A P8 CЬ# PЬPЬRRQ{RPPR PRPPPP@1@rcϩ@cw1@rc1@rc1@rc1@rc1@rc1@rc1@rcUnexpected option (Error in numeric option:Options set for this run:k-length of strings:%0Dd-trace option:%0Dw-frequency of output:%0Dp-prediction option:%0Ds-display option:%0DMoveup callPtr nilPtr^.Up nilScanned New node createdEnd MoveUp%10D %11.4e %6.3f%5D%5D%8D %6.3f %11.4e %6.3f (%5D %6.3fEFELFFV ut of range in Decode %0DNumber of nodes at each level(and ratios)%3D%6D %6.3fTotal Counts:%0D Total Transitions %0DEnumeration of Sequence(bits) %21.14elog2 c(s,b) %21.14eEscape characters %21.14eTOTAL %21.14eEnumeration of Counts %21.14eFixed Frequency Enumeration %21.14eCharacters:%0DCodes Sent:%0DEntropySum: %10.3e %6.3f@(#)ARGV.c 1.3 6/10/81Argument to argv of %D is out of range @(#)GET.c 1.2 6/10/81%s: Attempt to read, but open for writing %s: Tried to read past end of file @(#)HALT.c 1.3 6/10/81Call to procedure halt @(#)NEW.c 1.3 6/10/81Ran out of memory @(#)READC.c 1.2 6/10/81%s: Attempt to read, but open for writing %s: Tried to read past end of file @(#)TEOF.c 1.3 6/10/81Reference to an inactive file @(#)TEOLN.c 1.3 6/10/81Reference to an inactive file @(#)UNIT.c 1.2 6/10/81Reference to an inactive file %s: Reference to an inactive file @(#)ERROR.c 1.8 6/10/81Label of %D not found in case @(#)IOSYNC.c 1.5 6/10/81%s: Attempt to read, but open for writing %s: Tried to read past end of file %s: Tried to read past end of file @(#)PCEXIT.c 1.1 10/29/80pC %1ld %s %04.2f seconds cpu time. statements executed in@(#)PCLOSE.c 1.4 6/10/81%s: Close failed Could not remove @(#)PCSTART.c 1.5 6/10/81 8H8HHIRJHITRJIIaRKIastandard inputstandard outputMessage file@(#)PERROR.c 1.1 6/10/81@(#)PFLUSH.c 1.1 10/29/80@(#)UNWIND.c 1.2 3/7/81=B.pBԝ`E=sM@iD(/zCF:|+eVuCVuf3E#2#= at #3)#<3#%1#4#1#= linked to #>3#%1#5#2#= at #3ENTAIL#P: #i Cutoff #1 #8 #93Entities: #n, ##A: #N, Range: #r to #R, Purpose: #p #@ #P #i #p#i-#P#i.#P#P Analysis of #i#P Calculation #@#P Output #@ Equivalence EntailmentUsuallyProb.$#P Graph Structure (Cutoff #1) #8 #9-#P Truth #7 Information (Cutoff #1) #8 #9Information in #1)Entailments #1 row -> #2 column)Information Reduction #1 row -> #2 column)Usually #1 row -> #2 columnPRINCOM#P: #i3Entities: #n, ##A: #N, Range: #r to #R, Purpose: #p #@ #P #i #p#i-#P#i.#P#P Analysis of #i#P Calculation #@#P Output #@AllTitle Correlations)Percentage of variance for each componentAttribute LoadingsEntity Loadings9SOCIO#9 Grids#@ #7#8-#P#8.#P#P Entity Analysis of #8#P Attribute Analysis of #8EXCHANGE Analysis of #8Attempted #P Analysis of #8#2 attributes in common#1 entities in common%#1 entities & #2 attributes in common #7 with #6#7Calculating Mode EntitiesCalculating Mode AttributesShowing Mode EntitiesShowing Mode AttributesMode Entities at #1Mode Attributes at #1-Mode Entity #1: #2 entities in #3 grids at #42Mode Attribute #1: #2 attributes in #3 grids at #4#<6G#1E#2#=: #3#<6G#1A#2#=: #5#3 - #4 Listing GridsListing EntitiesListing Attributes Showing LinksComparing Grids Grid Ent Att#1#<3G#2#= #<3#3#= #<3#4#= #52 #<3#1#= #<3#2#= #3 Entities & #4 AttributesCommonTotalEntities Attributes#<6G#1E#2#=: #3#<6G#1A#2#=: #3 - #4 #<3E#1#=: #2#<3A#1#=: #2 - #3entity attribute,G#1<:G#2 #3% over #4 (#5 #7-construed-by #6)!#<3#1#=: #2% >#3 #<6G#4A#5#=: #6(#<3#1#=: #2% >#3 #<6G#4A#5#=: #8#6 - #7# #<6G#1A#2#=: #3* #<6G#1A#2#=: #5#3 - #4 construed-byconsistency-with<::Entity Links between GridsAttribute Links between Grids,#<3G#4#=#1#>3G#5#= #6% over #7 (#8 #3-#2 #9)/G#3:G#4 #5% over #6 (#1 #7-consistency-with #2)##<3#1#=: #2% >#3 #<3#%1##7#4#=: #5(#<3#1#=: #2% >#3 #<3#%1##7#4#=: #5 - #6zOBJECT #@ #P #i #p//#@ KSS0 #P #i Purpose: #p#i-#P#i.#P#P Analysis of #i(//ENTAIL Rules from #i (Cutoff #3) #1 #2 TEXAN#P: #i3Entities: #n, ##A: #N, Range: #r to #R, Purpose: #p #@ #P #i #p#i-#P#i.#P#P Analysis of #i#P Calculation #@#P Output #@ ATOM#P: #i3Entities: #n, ##A: #N, Range: #r to #R, Purpose: #p #@ #P #i #p#i-#P#i.#P#P Analysis of #i#P Calculation #@#P Output #@ PRISM#P: #i3Entities: #n, ##A: #N, Range: #r to #R, Purpose: #p #@ #P #i #p#i-#P#i.#P#P Analysis of #i#P Calculation #@#P Output #@) About KSS0...-File New WindowNOpen...O Close WindowW Save DataSSave Data As...Save Save As...- Page Setup...PrintP-QuitQW{EditUndoZ-CutXCopyCPasteVClear-FontViewGElicitElicit-ContinueE-Exchange{ProcessDisplay-FOCUSPRINCOMENTAILOBJECT-SOCIO-TEXAN-ATOMPRISMyDebugDebug1Debug2Debug3Debug4Debug5Debug6Debug7Debug8Debug9Debug02d About KSS0 :44L4L4&L&L>,6>FJ>Zd>t<<<dd 2F'OKK_'Canceldx'B3}'B4, *4L *L <*2(Z#]Bl~POpen;MPCancel"[&8PEject?QPDrive ^_TtyPMultipleKDataPTextGridYGridTextKWindowPTextPicture^ MSaveMCancel 1[8JMEjectRdMDriveKPY Z(Y<Status(<Cancel%%L22%%*<TCtl! OK2Cancel **L <*New Window Creation<LPicture<LrText<wLNo wrapZPjTitleZj! 5+OK2Cancel **L 5N SSize Bold ;Italic @ Underline 20Outline 0Shadow 0;Condense @0Extend<L<LE<ILP`P`EPI`dtdtEdItxxExIEIEIEIEIEI gl  7:  All! LOK2CancelTDefaultT2Fonts **L <:O<L<LCut offZj EntailmentZjr EquivalenceZwjUsuallyxPTextx InformationxrMatrixLinks Transitiver IntransitivewGraphFWindowLogPNew! 6M#OK2CancelTDefaultT2Fonts **L <:O<ULCluster<LEdges<LhInteriorZjPGraphZUjCut offZjZjEntitiesZjZ"jr AttributesZwjZj Tree scalex<LayoutxTopxrRightxwNo gridEntitiesr AttributesdGridNumbersrPatternsPTextKMatchesEntitiesr AttributeswLinksFWindowLogPNew! NOK2CancelTDefaultT2Fonts **L <:O<L<GraphU>e ComponentUeUe HorizontalUeU"erVerticalUweUeScalesPTexts Correlationssr ComponentsPLoadingsEntitiesr AttributesFWindowLogPNew! O OK2CancelTDefaultT2Fonts **L <:O<L<GraphZjPTextFWindowLogPNew^P MOK2MCancel Oc[j|MEjectMDriveOKPY <* **L!np #OK-ACancel ** L2(x Elicitationx(based on22ZkUsei}iin}i}Ratings"TitleҐ! QfOK2CancelTDefaultT2Fonts **L <:O<FLCommon<LEntities<Lr Attributes<wLBothZUjMatchZjZjLevelZjZ"jrGridsxPTextxGridsxrEntitiesxw AttributesA AttributeMatchesrLinkswModeWEntityMatchesrLinkswModeFWindowLogPNew! RJOK2CancelTDefaultT2Fonts **L <:O<L<LCut off<L<"LrLinksZjPTextZjAZjrBZwjCxFWindowxLogxPNew! SOK2CancelTDefaultT2Fonts **L <:O<LLinks<LStatesZFjMeasureZjplogpZj chisquarex< Model sizexxMinimumxx"rMaximumPTextSequencerModelsw SubsequencesFWindowLogPNew! TOK2CancelTDefaultT2Fonts **L <:O<LLinks<LStatesZFjMeasureZjplogpZj chisquarex< Model sizexxMinimumxx"rMaximumPTextSequencerModelsw SubsequencesFWindowLogPNew! UOK2CancelTDefaultT2Fonts **L <:O<LLinks<LStatesZFjMeasureZjplogpZj chisquarex< Model sizexxMinimumxx"rMaximumPTextSequencerModelsw SubsequencesFWindowLogPNew&VUntitled*4OK-4CancelDeletenAdd8jEdit8-Att-Ent Pair- Triple^r+(ZShow$-,rCtl8TxtHi8*TxtLo8/Txt3;*Txt&VUntitledHOpen)HClose,>HLNewL)Continue,L>ExchangeDisplay)FOCUS,>PRINCOM&ENTAIL)&OBJECT,>&SOCIO*pTEXAN*)pATOM,*>pPRISMtt),t>L8*L/O*2""""""UUUUwwwwD0 `D"!!1G`0 DDDUUUUO_SG)  <(xP @ €  €@ P |(> O)'QGS@PUUUUUUUUO_SG)  <(xP @ €  €@ P |(> O)'QGS@PUUUU @8qq8@ UG""""" UP @8qq8@ UG&88@ 88 88 88 | UP__ "jO$ T Aq D q UUUUH- +&( Knowledge  + Support +System + Zerofz(+KSS0 is a tool for thought z*!an aid to explore your thinking, z*and that of others, and make z*it more overt f 0(LK #Qf] (Conceptual frameworkf('Define +your $( purposeӠf(Elicit ( relevant #( entitiesӠf+( Distinguish +  relevant ,( attributesӠf(Derive +(| conceptual -(z frameworkӠ UUUUav0"aa 0"a`0"K "oQ"O?"#########################################################"l#########################################################fz( The KSS0 manual will be tucked z*away down here@0.N<@0.NH@.HN(.HN@0.N<@0.NH@A00@J@jD@C30RnQP.S.Sd..RnQ.S.Sd.L N^ _PNNVH0$n&n J.g/./. N7|#(`0+#(NdHrA#(00N<&0+#(NdHrA#)00NH@0+#(NdHrA#(00N<(0+#(NdHrA#)00NH@A00@D@C300+#(R@7@#(=|=n Jn o/p>@m=@0.N<&0.NH@A000no0.ng-- "jO$ T 6x Dp UUUUH- +%( Knowledge  + Support +System + Zerof(+ Now your purpose is defined you *"need to think of some entities tha)t (Q"are important to itpeople, object)s, (d whatever needs considerationf 0(LK #Qf] (Conceptual frameworkf('Define +your $( purposeӠf(Elicit ( relevant #( entitiesӠf+( Distinguish +  relevant ,( attributesӠf(Derive +(| conceptual -(z frameworkӠ UUUUaq0"]a 0"a_0"K "oQ"O?"#########################################################"l#########################################################@ԠnN2 N=@.HN&0. N@0. N@pA00=@.HN&0. N@0. N@0.NC0/p~m @/p>*@m=@.HN&0.N@0. N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=nJn^DJn^Dg0.nJ@jD@=@`=n.HN&.HN@0.N<@0. NH@.HN(.HN@0.N<@0. NH@A  "jO$ T 6x Dp UUUUH- +%( Knowledge  + Support +System + Zeron(+ Once you have some entities you *can begin to make distinctions *among them using the Triple, *and Break match keysn 0(LK #Qn] (Conceptual frameworkn('Define +your $( purposeӠn(Elicit ( relevant #( entitiesӠn+( Distinguish +  relevant ,( attributesӠn(Derive +(| conceptual -(z frameworkӠ UUUUaq0"]a0"ab0"N "oQ"O?"#########################################################"l#########################################################@Qn4( "Click on the names of attributes t)o select them !("The indicator shows the match betw(een selected attributes (1"It shows the highest match when n(1"one are selected (D"Click on it to select the attribu)tes with highest match (W"Click on to see lower matc)hes, to go up again (j"Click on to see the mat)ched attributes (}"Click on to enter an en)tity that breaks the match ""4/%x8 wwww4/$\ (\g- @KbZ{++@K"\?@p\ (}aShow@]]n(jbBreak<2.RA(0NH@AC3@0RnQ.0.N42.RA&0N4A HpA Hp0?<2NBRnQ./0.>@m|=@/p>@mb=@0.N<&0.NH@0.R@N<(0.NH@AC3@0RnQ.RnQ./.NL N^ _O NNVH0$n&n /p~mP@/p>@m4=@/./. .HN?.?.BgNRnQ.R.Sd.0*S@5@/0.>*@m=@/p~m@/p>@m=@.HN&0.N@0.N@.H< 0H`  @& ``&   H@ p8@@P  P(@BPH$0<㟼<0 888ǏLf 0`&1` $& "E!0 B"I$ z`v I4Af@6G3aF6°11;`\qph118`02`,X3 p` `` dB0@ >0s  6a11;0`^xxv10l135` Xs x` 0Ӡ ÀH@6`̓g6# 0`003``0\xf00lc8s=3{1 L#X\c~?| 08Ϙ1c τ0}` 6 0n=  >g03`0Nxf0p0lF038#18~F:uŎ3G3X6Nf3c1ŋqY0w93Y=XƱ u9X L3 Anw;sNj,`98cc03EKQW]gnu| "0<CMRWY[[[cjt                                     0 4 &?<&?<&4?<%*?<%Z?<%2?<%:?<$?<$?<%?<%?<%l?<&?<#?<#?<#?<#Z?<"h?<"t?<"~?<"?<F?< ?< ?< ?< ?< ?<!?<!|?< ?<P?<\?<f?<?<?<?<D?<j?<z?<?< ?< ?<!D?<?<?< ?<?<"?<\?<?<?<L?<?<?<@?<^?< ?< T?<?<?<?<?<?<\?<p?<?<?<?<?<4?<\?<?<?<?<?<?<?<6?<N?<h?<~?<?<?<?<?<?<?<P?<?<?<?< ?<z?<?<p?<?<?<?<?<?<?<Z?<?<~?<?<2J?<4?<?<!?<"8?<#?<$*?<%\?<&|?<'?<(z?<)?<*?<! ?<!R?<+"?<+?<, ?<-4?<.?<.P?<.?<.?</D?</?<0l?<5?<6 ?<68?<0?<6?<7 ?<7P?<7n?<7?<7?<8(?<8?<: ?<:?<:?<;H?<;?<?<?b?<B?<B?<C(?<C?<D`?<D?<E?<G?<B?<?<?<j?< ?<!?<>?<?<*?<?< \?< ?<?<?<?<R?<?<H?<Y?<?<":?< ?<!l?<1?<4?<5?<;>?<9p?<W?<?<?< ?<j?< ?<n?<?<4?<?<h?<%?<4?<D?<H?<Jv?<L?<M?<MP?<C ?<Q$?<Q?<T?<W.?<Wt?<?<h?<?<2?< ?< B?< ?< p?<4?<?<?<?<?<.?<?<.?<$?<'L?<)?<,?<1?<3?<4f?<5j?<6>?<7?<:?<?<??<A?<A^?<D?<H?<L?<N?<P*?<P?<Mt?< ?< >?< P?< .?< ?< J?< !?< $l?< *?< ,?< .?< 7?< ?< @?< D?< I ?< ?< ?< B?< ?< P?< (?< ?< ?< ?< ?< ?< :?< ?< ?< >?< $?< ?< "?< ?< X?< |?< ?< ~?< ?< ?<  ?< ?< ?< B?< r?< 8?< ?< ?< B?< L?< 0?< ?< ?<?<?<l?<?<?<?< `?< r?< ?< j?<\?<?<?<^?<n?<?<D?<x?<Z?<?<?<?<?<4?< ?<! ?<":?<!?<%L?<%r?<'?<'?<&Z C$HB&HCCHBBBЂ&Nu C"DxJjDxJjDFD$v Ӂd҂рQFJDgDHDJDgD&( Nua Nu /"a/@Nu _Ho//?<(PNUHW?< oVHzF/?<Jg` UHW?<?<`HW?<T//Ho ?<(HW?<TNu?""_ _/pH2QNu"0"_ _/`QNu"0 _"_/cR`QNu""_ _/cBg SBVfNu""_ _/prdPFC`QNu$02 _"_/tJAnrBnARBJ@oBo0S@QNuBNuH0Lprtg gAeSA6$H&I Vg RBRQt?BL  _\NNVHn/. ?<?.SWaj/.Hna6Hn/. ?.?<aJHnHnaHn/. ?. aN^ _O NNVHn/. ?<?. SWa Hn/. 0. n??<aHnHnaHn/. ?<afN^ _PN$02"_ _/t @A`BQ`Q`BQNu _"_BBBBBBBBN _0"_rIN _20"_etJRfRpSdN$02 _"_/`QNu "_ _/pVNu "_ _`  _"_/p"VNu "_ _/p""QNu "_ _/p"F‘"QNu "_ _/p"‘"QNu _"_0 @d 2I1NpNp"0"_" AN"_ _ PN 80 xШ W.N x0"x r e" !"x"ѩ 8L W.N"0"_ _`Q AN"0"_ _` Q AN"_20 _`QN"_ _20g S@4WB?N"_ _20g S@4VB?N1 JA! LNu/.0<ɡFpN _XmXnN _mnNYUU/0<ɡFpNJlD-C r TY"gt/RdЁ`Nu;B@'d prt +g -ftR: d d/ПЁkR`JgDJ@NuDNuNVJ@lp @HopH=@AHn/ Hn?< .?f -|`C Q0fBnpB1S@nJ.g-` J.f NfTNAN(.a2I.aArda r aa)N0 m_@NuH0H@Nu IfINF`^J.f*aZ0.U@m .aLQe0.Hm+aV`.0.2.l0`a QS@m.RAl0`aQN^NufS|0NuNVBnBnJg~ +g -f|R Nf6R Af\ NfVp (fRa&eF )f@Jf<"@Jf"p` If2R Nf Fff"@J.g `"@Ntrt: d$JAfJg AgRA`RnJgSn` .f JftR`Af=|0 Ef RaxenJfHn/ ?< Qg QfBiBN^Nu0< `0<("_Ho?NLH@N&"_?< N"_//?< N$ _"_0/R/N  _NuO O"o` ae zb SdB O  g  fR`"oNO.NuLN// @?< / "A2NpNLHW"o/ Nt?< T @NpNnL"WNVJj @N0<`0<LQ/Ho?<WQ/ Ho?<WHWHo ?<WHW//?<WO ANL"WN/ /?< @NpNpNp Np N 2 _"WN?HW/ ?<T @NL"WN// ?< @N0<`0<L"W/// ? ANpN  W?< "WNZ @N0<` 0<`0<0LQ/ Ho?<WHWHo ?<WP` _Ho?<0jD@S@NLBWJjRWN _0fp"W"@BYB@Np`p _4BjNJgB`FBBNNp`p _2AiNAVDNr `r _BNx@BxNNr `r _Nx@N _0NNLN2N _?<N _HW?<TNHo?<NuHo?<.Nu _p?<e ngRRRN""2QQNuL"Wa/ ? ANL"Wa/ ? ANUHW?<0Nu?HW?<TNu o P"o"?@.Nu" "_ _/?@Nu o /?@"o" _ N o"o?@ _PON /"o o ?@ _ N"_ _WN6,N2"_ ON"/HN"_ _N"_ L.Nqp/ 1 Nup`"_ MN/@N"_ @N"_" _ .N"_ _KN"_ _-NJxj* x0C t e"Q!"B"x" ѩ NucNu"_ _dNJxj"oH> g "@  @fpN|(IJjp`,I (&nQ"(¸.QpdJJ(gj@ hJk4"¸ x$< Їm"pm*O+A+x! TQH+h +@ TNJf,"* Qb gt e T"J  . L+`p|NN*N"* -A"J܀ .JgD g"Qe gt e T`%@L0#N#F|@/ NNaF"_H0`QQ g%@$I$ L$(!pL|.1 Nu g  @QH`A4"(¸J(g j"hJk $He` cNu -m C TǑ+@". L f+Nu PQH(P!@B!AӮ Nu <LNu"_ .N0"_ _N&"_ _!.jBNN"_  _ N"_ _H.N"_ ".N"_ _#N"_ _%.jBNN"_  _$N"_ _&.N"_ _(.N"_ _+N"_  _'N"_ _)N"_ _*N"_ _INx"_ _JNn"_ _gN"_ _hNѠ6NZ" "_ _."ANH"_ _3>N"_ _4>N opBgQ/HB/ O2/2 o0?@ _PON0/?@ O?@ _TONNVA1n 1|1n=@ N^"_XONNVA1n1| !n 1n =@N^"_PONNVA1n 1| "n!Y!Q =@N^"_\ON0< NVA1n1@=@ N^"_TON0< NNVA1n 1|=@"n"N^"_\ONNVA1n 1|=@"n"2 N^"_\ONNVA1|1|1n=@ N^"_TONNVA1|1|!n=@ N^"_XONNVA1|1|1n =@"nAp.N^"_\ONNVH00Bn Jxjt.gtN"fXSBNfPJ(fp(f>N f8 8nFr xPH0 gHfZrYO/ FNu.AIn.AOut.BIn.BOut"_0F.N"_0 _GN"_0/ JgFNF/HNu"_0 _/ JgGNGNu/|NuAp8?@Nu"_ _/ 9?@Nu"_ _  N _ /:?@Nu oǠ:LNp o 8 .Nu oL ANL/ Nu "_ _/;"NuNV n"n pH@J.gJ. g<`<` J. g<`< @N^ _ N"_ _p/ JgT`TNu"o oo _PON"o on?@ _PON _"xPI0"_BQ gXR@H"_2N x N/|`Nu/|Nu/|VNu/|`Nu/|JNuNVA1n1|-h N^ _TON"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f ` >N"_ _f ` >N"_ _f ` >N"_ _f ` >N"_ _f ` >N"_ _fA`A>N"_ _fB`B>N"_ _fC`C>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _f`>N"_ _fD`D>N"_ _fE`E>N"_ _>N"_ _>N"_ _>N"_ _5>N"_ _0H@0NNNVA!n1n B(B(B"n2=@N^ _ NNVA1n=@ N^ _TNQ`PNVA!n 1n"n !Q$Bh,B.Jf`=@"n "(N^"_ NNVA1n1n JgC np.AΠ=@N^"_PNNVA1n1n =@A"np.N^"_PNNVA1n=@ N^"_TNNVA!n1nBh=@"n 2 (0>"n"N^"_NNVA!n1n B(Bh =@A "np.N^"_ NNVA!n =@"n2N^"_PNNVA!n 1n=@N^"_\NNVA1n!n =@N^"_\NNVA1n!n =@N^"_\NNVA1n!n =@N^"_\NNVA!n1nB(J@fBh C "" =@N^"_NNVA!n 1nB( =@N^"_\NNVA!n1n B(B(B =@"n2N^"_ NNVA!n1n B(!n =@N^"_ NNVA!n1n B(Bh C np.A =@N^"_ NNVA!n 1nB(A=@N^"_\NNVA!n 1nB(B=@N^"_\NNVA"n!Q$1n =@"(N^"_\NNVA1n =@"n"N^"_\NNVA1n !n=@N^"_\NNVA1n =@"n".N^"_\NNVA1n1n ,!n.D=@N^"_PN"_r2/  xNPd p0(Nr`p2< W0\O>N"_ _fp``p`>N"_ _fp``p`>N"_ _f`>N"_ _f`>N"_ _fp``p`>N"_ _fp``p`>N"_ _fp``p`>N"_ _fp``p`>N oB("_ _fp ``p `>N"_ _fp ``p `>N"_ _f`>N"_ _fp``p`>N"_ _fp``p`>N"_ _fp ``p `>N"_ _f`>N"_ _f`>N"_ _f ` >N"_ _f`>N"_ _f ` >N"_ _f ` >N"_ _fB`B>N"_ _fA`A>N"_ _f ` >N"_ _f ` >N"_ _f`>N"_ 0_/>N""_ 0_//"?@Nu"_ _00R@N"_ _01J@gB`NJxk$ _0/NVA1|1|1@N^Nu _0/ 9@ g$@|9A@`@FNu@`H9݁݁Nu _"_B`N xep:"fҠ)!"P#x<4C!<"PJio~"/krP92)2$H`LJ@fpA 0$f)!"P xz!I!I B P(8)8 B#3A28gBiNQ9p A.`>0(n I1|:2!o$!o 1|"/j`!ACX!I J@ga"_ N xd"P!4<#1NuNVA1|BxaN^Nua 8AmN=A0.Nr n0?HnNrHn?<0?<9NHnNfB. RnQ.N^.NuNV/.Hn?<NBHn/. Nb=_Jnf&/. /.?<NBHzt/. ?<NB`\Hn/. ?<0.S@?NZHn/.?<NBHn/. 0.R@?p n n?NZHn/. ?<NBN^ _PNNV/.Hn?<NBp.J@o>p. @ f0HnHn?<p.S@?NZHnHn?<NB`Hn/. ?<NBN^.NuNV/.Hn?<NBp.n l.HzBHnN:HnHnNRHnHn?<NB`Hn/.?<NBN^ _\N NV/.Hn?<NBp.n l.HnHnN:Hz6HnNRHnHn?<NB`Hn/.?<NBN^ _\N NV/.Hn?<NBp.n o&HnHn?<?. NZHnHn?<NBHn?. HnNXHn/.?<NBN^ _\NNV|Bn/.0. H/HnN"HnHnNHn?.HnNXHn/. ?<NBN^.NuNV|Bn/./. HnN"HnHnNHn?.HnNXHn/.?<NBN^ _\NNV/. Hn?<|=n/.HnHn?<HnHnNHn?. HnNXHn/.?<NBN^ _PNNV/.Hn?<NBHzzHnNJf Bn ``HnHnNXAC""2Hn?<NXHnHn?<g HnN2 N=@ `Bn N^.NuNV/.Hn?<NBHnHnNXA"n ""2N^.NuNVH/p nr>Amj=A0.Nr n0=A n`^D n{]Dg*0.N2.A &0N"n0RnQ.LN^.NuNVH $n0* @fHzHn?<NB`2 @fHzHn?<NB` @fHzHn?<NB` @fHzlHn?<NB` @fHzTHn?<NB` @fHzHnN:HnHnNRHnHn?<NBHn/.?<NBN^ _\N0NV nC"""2Hn?./NXHzdHnNRHn?./NXHnHnNRHz>HnNRHn?./NXHnHnNRHn/. ?< NBN^.Nu::NVHnNJHnHnNZXHn/.?< NBN^NuNVHnNJHzHn?<NB/p>.@m6=@HnHnN:HzHnNRHnHn?<NBRnQ.HnHnN:HnHnNRXHnHnNRHz@HnNRHnHnNZXHnHnNRHn/. ?<NBN^ _TN  NV0. no =n `=n N^.NuNV0. nl =n `=n N^.NuNVHnHm(NXHnN2 2.n RAHN2. HҀ N=@ N^.NuNV/.Hn?<NBHz\HnNJc:p.=@ n@^D n[]Dg0.@ N@Hn/. ?<NBN^.NuNV/.Hn?<NBHz\HnNJc:p.=@ n`^D n{]Dg0.@ N@Hn/. ?<NBN^.NuNVB-'HnNB/.HnN"AC(""2Hz.Hm$?<NB| %HzHm"?<NB| #N^Nu  NVH8 nC""""-nHnt/.s$n&n(n/."HlHj{Jf/./*S` /./*x/.N ?,N:?,N?,NB/.#/.sLN^.NuNVU?<@HmpJg-m n=h?.HnNrHn?<?<NHnNg(0.NHA"0f HmNUHmJgUHmHnHnJg`jN^NuNVxBnBn ngH?.HnHzhHnNJg.0.NHHnAxHp?<NB0.R@=@0.R@=@ nWD n^Dg/0.S@r>Am=AHzHn?<NB/0.S@r>AmX=A0.NHHnAxHpNJc*0.NHAxHpHn?<NB=nRnQ.0.S@nNHHnAHp?<NB0.NHHzFAxHp?<NBRnQ6.0.NHHzAHp?<NBN^NuNVH m/QHz&Hn?<NBHnHnN:Hz*HnNRHnHn?<NBYB?</.HnN"n "=| Bn0.NHAHpHn?<NBHz,HnNJc" n /?./.HnN0.R@=@0.R@=@ nWDHzHn&NJWDg n'n, n /HnNrHn?.?<'NHn/.N n /HmQLN^ _PNB1 2 44,S4 5,C6 7 8 9 10 11 12,bR13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39,R40 41 42 43,T-4NVH $n n/HnNrHn?< ?<'NHnBg/. N n/HnNrHn?<?< NHnBg/. N?Hn/p ~'@m`=@Hn n/?./. NXHnHnNJf, n/HnNrHn?.NzHn?</. NRnQ. n/?</. Hn?*BgN*XHnN/p~@mb=@0.H?HjHn/<NjHnNg0 n/HnNrHn0.\@?NzHn?</. NRnQ.HmHnU n//. ?.NJg?.HnNrHn?<NzHn?<NzHn?<(?<,NHnNg ngB$nUHn n/?</. NXHnNB5_/p ~'@m\=@?. n Hh2Hn/<NjHnNg*Hn n/?./. NXHnHn?<NBRnQ.HnHRHnNrHnHj/<N/p~@m=@0.\@? n Hh2Hn/<NjHnNgJHnNrHn0.H?NzHjHn/<NjHnHnNHnHj/<NRnQ.=nLN^ _O NNV/.Hn?<NBY/?*?<?*?*Hm6?*?<&?*?*Hmf?<?<0*[@?0*@ ?Hm^?<2?<?*0*@ ?Hm2/-2sHm.?<lN/-.oBm`/p~ @m&=@0.NA.B0RnQ.N/p~@m4=@0.NHAHp?<0.S@?NRnQ.AC""AC""LN^NuNV/.Hn?<NBB-B-YB?<HnHzN+_/-?<HnHnNHnNbXHnHm?< NB/-?<HnHmN/-?<HmRN/-HnNrHn?<NzHnHnN/-ΩN"N^.NuB1 2 8,S4 5 6 7NV/-ΩNN^NuNVU?<BHmpJgzUHmJglUHmHnHnJgV0. @f.@mT=@HnHnHzNXHnHn?<NBHzHnNJg/.?.HnHnNRnQ./.?<HnHnN/.?< HnHnN/.?< HnHnN/.HmHnU/.Hn?.NJg/.N=nN^ _ONB1 2 3 4 5,S8 9 10,NVJnWDHN@J.f2UBgHzDHzTHn0.D@?BgN*XHnHz:NJ=_.HN@ N^ _TNInput/Output ErrorNVHzHn?<NB| U> =_HnN?< N2XHzHnNRHnHnNRHnYN?< N2XHnHnNRHzHnNRHnHnNRHnYN?< N2XHnHnNRHzbHnNRHnHn?<NBUBgHzJHnHn?.BgN*XHnHzFNJ=_N^Nu  Heap Largest Block StackMemory Allocation ErrorNVHnt/-@?.HnF/-H?<9/-H?<9/-H?<9/-H?<9UHn=_/.sN^ _TNNVH /.Hn?<NB$n HnNrHnHj2/<NHnNrHnHj:/<NHnNrHnHjB/<NBR=|/p~0@m"=@0.N0AB0RnQ.HnHnHnHzHNXHnN XHnHn?<NBp. @Bf =|`P @Cf =|d`> @Rf=n0.R@=@`" @Sf =|` @Tf=|HnHn?<p.S@?NZHnHn?<NBHnHnN XHnHn?<NBUHnHnHznNXHnNB=_JnlP0.D@=@HnNrHn?.NzHj2Hn/<NjHnHnNHnHj2/<N0.N0&0.NC0U??.Nr4HnNrHn?.NzHj:Hn/<NjHnHnNHnHj:/<NHnNrHn?.NzHjBHn/<NjHnHnNHnHjB/<NHnHnN XHnHn?<NBHz.HnNJfHz HnNJfLN^ _PN, NV/. ?. HnHnHnU/.`=_0.ng /.?.cN^ _PNNV/.?. HnHnHnYBN"n"Q#_"n"Q"i"/.Bgd/.?<deN^ _O NNVH $n/p>@ml=@0.N0rA0 AcoB?.Hj2Hn/<NjHnNg =|`Bn/. ?.?.NRnQ.LN^ _PNNVH $n 0.N0rA0=A no~/p>@mp=@0.N0rA0nfFHnNrHn?.NzHj2Hn/<NjHnHnNHnHj2/<NRnQ.?.Hj2Hn/<NjHnNgJHnNrHn?.NzHj2Hn/<NjHnHnNHnHj2/<N`FHnNrHn?.NzHj2Hn/<NjHnHnNHnHj2/<N/./. N nWDHN@LN^ _O NNV/.Hn?<NBY?././<|-_/. HnNz/./. N"n"i"Q3|H-nN^ _ONNVH /.Hn/<N$n/p~0@m=@?.HnHn/<NjHnNg0.N0rA0 Ag Af`Jn fJHnNrHn?.NzHj2Hn/<NjHnHnNHnHj2/<N`FHnNrHn?.NzHj2Hn/<NjHnHnNHnHj2/<NRnQ././.NLN^ _ONNVH /. Hn/<N$n/p~0@m=@?.HnHn/<NjHnNVD?.HjBHn/<&NjHnNVDgHnNrHn?.NzHjBHn/<NjHnHnNHnHjB/<N/.?.HnHnHn詍0.N0rA0 Ag Af` /.?<]RnQ .LN^ _O NNVH /. Hn/<N$n/p~0@m=@?.HnHn/<NjHnNVD?.HjBHn/<&NjHnNWDgHnNrHn?.NzHjBHn/<NjHnHnNHnHjB/<N/.?.HnHnHn詍0.N0rA0 Ag Af` /.Bg]RnQ".LN^ _O NNVH /. Hn/<N$n/p~0@m=@?.HnHn/<NjHnNVD?.Hj:Hn/<&NjHnNVDgPHnNrHn?.NzHj:Hn/<NjHnHnNHnHj:/<N/.?.'RnQ`.LN^ _O NNVH /. Hn/<N$n/p~0@m=@?.HnHn/<NjHnNVD?.Hj:Hn/<&NjHnNWDgHnNrHn?.NzHj:Hn/<NjHnHnNHnHj:/<N/.?.(0.N0rA0 Af4?.Hj2Hn/<NjHnNg/.?.Bg?<~RnQ.LN^ _O NNVH /.Hn?<NB/.?.HnHnHn$n 0.N0rA0 Ag Af\/.HnHnHnNJg /.Hn?.Hj2Hn/<NjHnNg/.?.Bg?<~`&/.Hn^HnHnNJg /.Hn_LN^ _ONNVH /.?. HnHnHn$n0. N0rA0 Ag Af&/.?. HnHnHn/.Hn` /.Hn^Hn/.?<NBLN^ _O NNVH nBPB.$n 0 @g @fz *"<N?HnNrHn?< NzHn?<NzHnNg>/.?<HnHnHnꩍ/.?<]/<HnNZ|"n2LN^ _O NNV/.Hn?<NBHn/. ?<0.D@?UHn0T@??.=nN^ _PNNVH /.Hn?<NB$mUHnHnN=_Hn?.?.AC""HnHn?<NB|=n=n0. N@0.N@p.@@=@0.d 0.R@=@=jDHjFHn/<N=jJ *LN=@UHn/-t0.H/N=_0-rR@;@rLN^ _ONNVH nC""$mHnHn0.D@?0.D@?AC""=n=n|=n=n0.N@0.N@=n AC""""2=|*UHn/-t0.H/N=_0-rR@;@rLN^ _ONNVBmrJ.gYBN+_t`BtJ. gYHmV+_x`BxN^.NuNVHn"n20.nn"n 2"n2N^ _O NNVH $n??*Hj _?/./. /.N LN^ _ONNVJ ghU/. `=_0. no=n 0.nl=n/. ?. d/. ?.e0. nf/. ?<]` /. Bg]N^ _PNNVH 0.NHE$rJg>Jg/*Bg j P?(^N`/*0*Đj?0*Ȑj?NJg/*0*Ɛj?0*ʐj?NLN^ _TNNVH 0. NHE$rBn0.R@N>H j P20`n _D2. j Ph^]Dg0.R@=@`Jno0.jR@=@/*?.cLN^ _\NNVH00.NHE$r/*N*&j&SBn0+SU/*&`0@=C/*N2?.?./*ةL N^ _TNNVH0 nC""0. NHE$rAC""Jg"p j P( @f0*@5@Jg"p j P( @f0*@5@Jg/*N*&j&SJg U/*`0N>HA`=pAC""HS?<?<0+SH5@0*S7@AC""/*N2/*ة/*N*&j&SJg?. ?.BgN*HSBgU/*`0D@?AC""/*N2?. N"L N^ _\NNVH nC""0.NHA/0sJnf mAC""0.NHE$r5nBBBBB*. HN@BjBjBjB*B*|J.g. *g =|`=|Hn0.S@?0.@?0.n?0.R@?Y0.NHA/0HnHz2<BgBgBg?<BT%_`BJ. g.*g =|`=|Hn0.@?0.S@?0.R@?0.n?Y0.NHA/0HnHz<BgBgBg?<BT%_`BJ.g2?-^?-\YHnHn%_</*ب5|` 5| B?.HnNRHnBgBg?<?<Jf?.HnNNLN^ _ONNVH nC"" nC""UHnN*Jg0-`NHY&0.NAzHpHnHn?< NXHn.HN?./<.HNBC#0?-`Hn.HN. HN. HN.HNNj0.NAB|`B.LN^ _ONNVH 0.NHE$rAC""Hn?*?*Hn{?*?*xLN^ _TNNVBgBgx0.NHA pHh{N^ _TNNVH 0.NHE$rJg j PBh-`@m>=@0.NH2.RA&0NHAC#0RnQ.N/-D?<9/-TBg9LN^ _TNNVH Hnt0.NHA/0s0.NHE$rHj(Jg/*̨Jg/*ШJg /*NBBB|/.sLN^ _TNNVH 0.NHE$r?.N%n%n LN^ _O NNVH 0.NHE$r0*Đj5@0*Ɛj5@Jg /*?*cJg /*?*cLN^ _TNNV/.Hn?<NBHnt/-.mYHmV-_?. ?< ?<?< Hn/.s-nN^ _\NNVH p n @fL$n?<?*Hj _??*0*H/0* T@?0* j?Hj`| @ft$nHj?< A C""Hn?*&?*(0*$ @f Hn`4 @f Hn`" @f Hn` @fHnLN^.NuNVH0 nWDHN@$n J.WDHN@YY0*H/p*D@H?\/< . N=@0. @f Hj ` @f?<?<Hm쨝Hj `r @f*?<?<HnBg?<NHnHj `B @f<0* jH=@?* ?.?/.N* n&0,-`@mZ=@0.NHC"q3n0.NHA/0Hn0. @f.HnHnN:HzHnNRHnHn?<NB`f @f.HnHnN:HzHnNRHnHn?<NB`2 @f*HnHnN:HzHnNRHnHn?<NB0.m`f4 no*HnHnN:HzvHnNRHnHn?<NB/-LHn30.NHA pJ(ng/-L0.T@?<ERnQ.N^Nuxxx(-/H/L/D/TNVH 0. NHE$r/-L0. T@?J.WDHNEJ.g0. NHA/0`20. NHA/00. NHA/0LN^.NuNV m `f B. `h| 0-`R@;@`"n2 n0NA. 0f n0R@"n2` m `f/-D?<:/-TBg:N^.NuNVH0$n&mHR5kDHkFHj/<N5kH5kJ +LN5@L N^.NuNVH nCp"Q$mHn䨙?.Hn _??.?.0.H/LN^.NuNVJ.g"0. NHAAmp=A0.H/HnN"HnHn?<0.H/HnN"HnHn?<HnN2 N??.Bg?$nJg/*ة?*NJ|q`?*NZ?*N?*NjLN^NuNVH Y$-_Jg6$nJg/*ة?*NJ|q` ?*NZ?*NjLN^NuNVH Y$-_Jg0$nJg/*ة?*NJ` ?*Nb?*NjLN^NuNVH Y$-_Jg0$nJg/*ة?*NJ` ?*N?*NjLN^NuNVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNV/.Hn?<NBHzHnNb0J@fHn/. ?<NB`tHnHn?<NBHzhHn?<NB=|=|=|HzHHnNb=_Jno=n0.R@NrA0 A#WDHN@J.g 0.R@=@HnHn0.R@??<NZHnHn?<NBHnHnN:HnHn?<0.S@?NZHnHnNRHnHn?<NBHnHn0.T@?p.nS@?NZHnHn?<NBHnHmNb=_Jno nf"HnBgNjXHnHn?<NB`&0.N4ANzHn?<=NzHn?<$NzHn?<%NzHnNgHzHn?<NBp.?HnNrHn?<0?<9NHnNglHnHnN:HnHn?<?<NZHnHnNRHnHn?<NBHnHn?<p.S@?NZHnHn?<NB`lUHnNB=_p. @fp.=@=n` @%f =n` @$f(Hn?.HnNXHnHn?<NB` @=fJno.Hn0.n?HnNXHnHn?<NB`hHnHn?<?.NZHn0.D@?HnHn0.R@?p.n?NZHnNXHnHnNRHnHn?<NBJnfHnHnN:HnHnNRHn/. ?<NBN^.Nu##NV/. Hn?<NB/.Hn?<NBHnHmNb=_Jno&0.N4HnA. @m6=@HnHnN:HnHnNRHnHn?<NBRnQ.Hn/.?<NBN^ _\NNV/.Hn?<NBHn?.HnHnN:Hn?. BgN*XHnHnNRHnNXHn/.?<NBN^ _PNNV no0.@=@ ncoHzjHn?<NB`B nlHzPHn?<NB`$Hn?.?<N*XHnHn?<NBHn/. ?<NBN^ _TN **-**NV0. S@HH@R@=@ nx o"n` nBN^ _\NNV0. @<=@ .f0. @<=@ =n N^.NuNVH $nHnHn?<N"XHnNXHzHnNRHn?BgN*XHnHnNRHzHnNRHnHn?<N"XHnNXHnHnNRHzHnNRHn?*BgN*XHnHnNRHnHn?<NBHnHnN:Hz^HnNRHnHn?< N"XHnNXHnHnNRHz.HnNRHn0*R@?BgN*XHnHnNRHzHnNRHnHn?<N"XHnNXHnHnNRHnHn?<NBHnHnN:HzHnNRHn0*j?BgN*XHnHnNRHzHnNRHnHn?<N"XHnNXHnHnNRHz\HnNRHjHnNRHnHn?<NBHn/. ?<NBLN^.Nu: , : , :   , : NV/. Hn?<NBHn/.NXHnHn?<NBHzjHnNJfDHz\HnN:Hn?.BgN*XHnHnNRHnHn?<NBp.@Hn/.?<NBN^ _O N NVHB. n JPf0-R@"n 2/ n 0S@r>AmX=A0.>AJp^DJnWD4.>A60 nWDg"n 2|RnQ.LN^ _\NNVH /.Hn?<NB|0->EEHnHj ?<NB5n 4 5nBjB*LN^ _O NNVH HzHn?<0.H=@ n 0(S@2.SAH/HnN"H/HnN"HnHn?<HnHn?<$n /p>*@m,=@/p>@m=@/p~m@.H2.A2.ArA0=AJno0.nnD0.S@H/HnN"HnHn?<HnHn?<HnN2 R=@`F0.nH/HnN"HnHn?<HnHn?<HnN20*H=@.H2.A2.A2.CR.Sd.RnQ.RnQ.LN^ _\N?ѷXe+NVH $nHnNrHnHj/<NHnNrHnHj/<N|||/p>*@mn=@/p>@mT=@0.2.ArAm0=A0.2.ArA0=A0.n2*RAAgB* nWD nWDg |`0.jWD2.jWDg |`JnWDJnWDgB*HnNrHn?.NzHjHn/<NjHnHnNHnHj/<NHnNrHn?.NzHjHn/<NjHnHnNHnHj/<N`B*RnQ.RnQ.LN^.NuNVH $nHzJHjNJf Hn?<N"XHnHj?<PNBHzHjNJf Hn?<N"XHnHj?<PNBHzHjVNJf Hn?<N"XHnHjV?<PNBHzHjNJf Hn?<N"XHnHj?<PNBHzHjNJf Hn?<N"XHnHj?<PNBHznHjLNJf Hn?<N"XHnHjL?<PNBHzBHjNJf Hn?<N"XHnHj?<PNBLN^.NuNVH $nHzHjNHzHjVNHzHjNHzHjNHzHjNHzHn?BgN*XHnNHzrHn?*BgN*XHnNHzXHn0*R@?BgN*XHnNHz:Hn0*j?BgN*XHnNLN^.NueEaApnNrRNVH 0.>EEHzHj NLN^ _TNiNVH 0.>EE/**N*?.N j*/N /**N2LN^ _TNNVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVH B.0.>EEJ*g /**N-| .d .R-@Y/.N%_*/**N* j*-P0.>AJf NZ`$nBBHn/. NXHnHn?<NBHzHnNb0J@WD@J.gVUHnNB4UHn/. NXHnNB5_BjUHn/. NXHnNB5_B*B*`UHnHnHzNXHnNB4UHnHnHzvNXHnNB5_UHnHnHzXNXHnNB0S@5@UHnHnHz6NXHnNB0j5@UHnHnHzNXHnNB=_U0.H/BN_U0.H//<N_U0.H//<N_HnNrHn?NzHn?*NzHnNrHnBg?<NHnHnNf Hn/. NXHnHj?<PNB/p>*@mH=@Hn/. NXHnHn?<NB/p>@m=@J.g(HzHn?<NB0.rA0A`$HnHnHzNXHnHn?<NBHzHnNJfBnBn`dHzHnNJf=|=|`DHzHnNJf=j=j`$UHnNB0j=@0*R@n=@0.2.A2.Cm0.2.A2.CRnQ.RnQ./p>*@mv=@/p~m\@.H2.4AHn/. .HIAHp?.&NXHnAHp0?<2NBR.Sd.RnQ./p>@mP=@0.4Hn/. Hn?<&N"XHn?.NXHnA Hp0?<2NBRnQ.Hn/. NXHnHj?<PNBHn/. NXHnHjV?<PNBHn/. NXHnHj?<PNBHn/. NXHnHj?<PNBHn/. NXHnHjL?<PNBHn/. NXHnHj?<PNB/.N/.N|0.>EE/**N2J.g 4`J*g/**NB*nLN^ _\N,,,,,, ,UNBNV0. 22. SAH/HnN"H/HnN"HnHn?<A"n""2N^ _\NNV0. d2. SAH/HnN"H/HnN"HnHn?<A"n""2N^ _\NNVH $nJjWD j ]D@BnJ.g 0.R@=@J*g 0.T@=@J*g 0.X@=@/. Hn?BgN*XHzHnNRHn?*BgN*XHnHnNRHzHnNRHn0*R@?BgN*XHnHnNRHzHnNRHn0*j?BgN*XHnHnNRHzHnNRHn?.BgN*XHnHnNRHnN/. HjN/p>*@mj=@/p>@mH=@0.2.ArAm0=A0.2.ArA0=A0.n2*RAAf,Hn0*n?BgN*XHnHn?<NB`JnWDJnWDgHzHn?<NB`r nWD nWDgHzHn?<NB`D0.jWD2.jWDgHzVHn?<NB`HzDHn?<NB/. HnNJ.f0.Rl/. HzNRnQ./. NRnQ./p>*@mN=@/p~m4@/. .H2.4AAHpNR.Sd.RnQ./p>@m&=@/. 0.4A HpNRnQ./. HjN/. HjVN/. HjN/. HjN/. HjLN/. HjNLN^ _PN,,,,UNB?,NVH $nBn/p>*@m0=@U?.0.4rA0?Nr=_RnQ.?. Hn?<N"XHnNb?. Hn?<N"XHnNb?. NjHn0.X@?HzNXHzHnNRHnHn?<NB/p>@mT=@HnHnN:Hn?.?<N*XHnHnNRHzHnNRHnHn?<NBRnQ.?. HnHnN:HztHnNRHnNb?. Hn0.X@?HzRNXHn0V@?Hz*@m<=@0.4AHpHn?<NBHnp.2.@?HzNXHnHnNRHn?.?<N*XHnHnNRHzHnNRHnHn?<NB/p>@m=@0.2.ArAm0=A0.2.ArA0=A0.n2*RAAf.Hn0*n??<N*XHnHn?<NB`4JnWDJnWDg. @m,=@?.Hn?.?<N*XHnNZRnQ.?.HzxNb?.Hn?<HzfNXHn0. T@?HzNNXHnHnNRHnNb/p>. @m=@?.Hn?.?<N*XHz HnNRHnNZ/p>. @m>=@?.Hn0.2.Ar n0?NXHnNZRnQ.?.HzNb0.n fHzHn?<NB`HzHn?<NB?.Hn?<HzpNXHzhHnNRHn?. HnNXHnHnNRHz@HnNRHnNbRnQ.N^ _PN ** * *****  **NV/.Hn?<NB/.Hn?<NB?.Hnp.V@?HzNXHzHnNRHnNZ/p>.@m0=@?.Hn?.?.HnNXHnNZRnQ.?.Nj?.Hn?<HzLNXHn0.X@?Hz4NXHnHnNRHnNb/p>.@m=@?.Hnp.T@??.HnNXHzHnNRHnNZ/p>.@m=@J. WD2.nWDg(Hn?.HzNXHnHn?<NB`JHn0.x2.IA nHpHn?<Hn?.?.N:XHnHn?<NB?.HnNZRnQf.?.NjRnQ.N^ _ON * * * NVH nCp"Q2Hnt/-.m<B'N$n HnHnHnHnN=nBg?.֨Hn?<N"XHnHn?<NBHnȨUHnȨ=_0.n=@Bg?.֨Hn?<N"XHnHn?<NBHnȨU?.UHnȨNr=_0.nn=@HnHnHnHnNHnHnHnHnNU?.?.Nr=_HnHnHnHnNU?.?.Nr=_0.Hn=@BnBn0.H=@HnHnHnHnN/p>*@mR=@U?.U0.4AHpNr=_U?.U0.4A HpNr=_RnQ./p>*@m0=@U?.U0.4AHpNr=_RnQ.=n0.n=@Hn0.Hn?0.Hn?0.n2.HA?0*nn2.HA?Hm䨝HnHm쨝HnHnHnHnN/p>@mV=@Hn?.BgN*XHnHn?<NB0.n=@UHnȨ0.Ԑ_??.֨HnȨRnQ.0.n2.HA=@/p>*@m=@HnHnHnHnN0.4AHpHn?<NBUHnȨ0._??.֨HnȨHnHnHnHnN0.n=@Hn?.BgN*XHnHn?<NBUHnȨ0.Ԑ_??.֨HnȨ/p>@m~=@0.2.ArAm0=A0.2.ArA0=A0.n2*RAAf,Hn0*n?BgN*XHnHn?<NB`JnWDJnWDg$Hn?< N"XHnHn?<NB` nWD nWDg$Hn?< N"XHnHn?<NB``0.ΰjWD2.̲jWDg$Hn?< N"XHnHn?<NB` Hn?< N"XHnHn?<NB0.n=@UHnȨ0.Ԑ_??.֨HnȨRnQ.0.n=@Hn?.BgN*XHnHn?<NBUHnȨ0.Ԑ_??.֨HnȨHnHnHnHnN0.4A HpHn?<NB0.n??.֨HnȨ0.n=@RnQ..0.nn=@0.Hn=@0.n=@HnHnHnHnN/p>@mV=@Hn?.BgN*XHnHn?<NB0.n=@UHnȨ0.Ԑ_??.֨HnȨRnQ.=n0.n=@0.n=@Hm䨝HnHnHnHnN/0~@n=@DG0.n2.HA=@?.0.Hn??.0.֐n2.HA?0.H2.Β@??.֨0.4A Hp0.n=@SnQv.Hm쨝=nȨHm|?HnNJWDHnHn?< &NXHnNXHnHnNJWDgR/.HndNrHnd?< NzHndHnN/.HndNrHnd?< NzHnd?<HnN`>/.?< HnHnN/.HndNrHnd?< NzHnd?<HnNJ.f*/.HndNrHnd?< ?< NHndHnN/.HmHnU/.Hn?.NJf,?.HndNrHnd?<?<NHndNg nWD?<HnHnd/<&NjHndNWDgHndNrHnd?<?<NHnHnD/<NjHnDHndNHn$NrHn$HndNgV/.HndNrHnd?< ?< NHndHnN/.HndNrHnd?<NzHnd?<HnN`*/.HndNrHnd?< ?< NHndHnN`?<HnHnd/<NjHndNVD@?<HnHnd/<NjHndNVD@ nfACp"Q2` nf HnNz?.HndNrHnd?<NzHnd?<NzHndNg nfHn/.?< HnNXHnHn?<NB?< HnHnd/<NjHndNVD@?< HnHnd/<NjHndNVD@?< HnHnd/<NjHndNVD@/.N nf`0.>EE/**N* m/Q?<Hn?<N"XHnNbJ.gJ.g8=|HnHn?< NXHnNXHnHn?<NB`YHn?.&NC#0Hn?.?<?<N` @fbUB'NJJgP0-`NHA/0Hn0-`NHC"q3n?-`YHn?.NN`f @f^UNBJgR0-`NHA/0Hn0-`NHC"q3n?-`YHn?.NBNLN^ _\NNVH 0. @fXJ-cWD-b?-HnNrHn?< ?<&NHnNVDgEdHj ?*NJ=|e ` @ f-媞@m<=@0.N>AHp n/(NJf|RnQ.`|.HN@ N^.NuNVH Hn?<U?<(+|GRID;||cB-b/.HzVHmZ?-媞@m=@0.N>AHpHn?<NBHnHnNJfNU?<Hn?<N:XHnHnHzHzNJ=_/./-H/.?<Bg?<~=|d RnQz./p~@m=@Y/<?.\ N=@Y0-H/0.H/ . 2.Hf =|`Bn/.0.@ ?HnHnHn/.?.cRnQ.=n N^ _\NNV/. Hn?<NB/.Hn?<NB/.Hn?<NB/.Hn?<NB/.Hn?<NB/. Hn?<NB/.Hn?<NB;n&;n$|aHn+_HHn+_LHn+_\Hn+_XHn+_THn+_PHn?<U?<(/.HnHnHmb/.*?.(BN=m.N^ _O&NNVH00. NHE$r/*N*&j&S'n>Y/.N" N7@ .N7@EE/**N* j*-PUHn?. N=_UUHn?. /./.NNRJgUUHn?. HnNzNRJgYBN-_/./.NB/.N*Y/.N"-_UU?.Hn n/NNRJg $n%jHn?. ?<?<N/.N2/.NUU?.NNRJgUUB?. NNRJg0.N>EE/**N2LN^ _ONNVH0Jnf=m=|`=n=n/0.>.@n=@DG0.N>EE/**N* j*-P&n +gJjgAHpHn?<NBUHn?<?<?<Hn?<N:XHnHnHzbHzdHzfHzlHzjN0 @f+|GRID` +|TEXTJ.g/<@m$=@0.NHABpRnQ.UHnHn/<N=_Y?*N-_/.N*U/./.N=_/.N2/./.N*Y/.N"-_UU?.Hn n/NNRJg/.N2/.N`:?*HnNUU?.Hn/.NNRJg j P/(>N2/.Hn5nB*UU?.NNRJgUUB?.NNRJgLN^ _ONNVH Y$-_Jgr$n*.gb/.HnJjWD.gJfl-|PICTUHn?<?<?<Hn?<N:XHnHnHzHzHzHz"Hz N0 @f+|CDKS` +|MDRW`-|TEXTUHn?<?<?<Hn?<N:XHnHnHzHzHzHzHzN0 @f+|CDKS`& @f+|MACA` @f +|MSWDJ.g/-/.Hn?.Nz`4UUHn?*HnNNRJg/./.Hn?*NzLN^ _TNPictureKSS0McDrawTextKSS0McWriteWordNVH0Y$-_Jg`$nJfY?*N-_`>?*HnN j P=hJ j PHhLHn/<N j P=hP/-N*U/-NRJg&m&SY/-BBNZ-_?.Hn _??.HnHnHnN 0.Hn=@B./.BNjUN0J@fJf|0*ʐjH/HnN"0+H/HnN"HnHn?<HnHn?<0*ȐjH/HnN"0+ H/HnN"HnHn?<HnHn?<HnHn?<HnHn?< o-n/<HnN"HnHn?<HnHn?< d/<HnN"HnHn?<HnBgBg0-\H/HnN"HnHn?<HnN* N?0-ZH/HnN"HnHn?<HnN* N?/.Hnʨ|`~Bn=nJoZHnHnNXHnHn?<NB?.?.Hn0.n=@0.k ^DHN@`|..g/.NrUN0J@VD.g/.Nb +DWDU&N0J@WDg/-BBBHnNz/-N2Jg j P/(>N2`/.ڨL N^NuNVU/-NBHN@U/-NJHN@N^NuNVHnHnNb nf`Jnf`/p>.@m=@?.HnNj GRIDfHn?.NB`r TEXTfTp. @oBHnHn?<?<NZHzVHnNJf?<HnNHn?.?<Nr`HnHz&Hz$Hz"?.NrRnQZ.N^NuLogNVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVH00. >EEJ:f,-|-( .(d .(R-@(Y/.(N%_:/**N* j*-P$/*:N* j:-P $n$&n n -n-'j-/<dHnN"0H/Hn N"Hn Hn?<HnHn?<0*H/HnN"Hn?<HnHn ?<HnHn ?<Hn Hn?<J.g>/0S@r>Am^=A0.H2nH/HnN"2H/Hn N"Hn Hn?<Hn?<HnA,Hp?<RnQ./p>@m=@/p>@m=@0.x2.IA2.H/HnN"2.H/Hn N"Hn Hn?<2nH/HnN"2H/HnN"HnHn?<HnHn?<Hn?<HnAHp?<RnQd.RnQJ.`j/p>@m\=@0.H2H/HnN"2.H/Hn N"Hn Hn?<Hn?<HnA,Hp?<RnQ./p~m ^@/p>*@m @=@J-f ,/p>*@m=@0.A B0RnQ./p>@mj=@.H2.A2.ArA0.H4.B4.BtA0pA 0 R@C RnQ.BnBHnN"HnHn?</0*~@n=@DG0.rA 0=A0.n=@0.2.CmJnod0.H/HnN"Hn?<0.H/Hn N"HnHn ?<HnHn?<Hn Hn?<HnHn?<SnQb..Hx2.IA2H/HnN"Hn?<2H/Hn N"HnHn?<Hn Hn?<HnHn?<HnAHp?</p~m:@/p>*@m=@J-fBnJ.g|/0*S@r>Am=A0.HA@BpRnQ./p>@m=@.H2.A2.ArA0.H4.B4.BtA0B=AJ. gU?.0.D@?Nr=_`UBg?.Nr=_0.H2.IA@40RBC@3U?.?.Nr=_RnQJ.HzXHn?<Bn/p>.@m^=@0.H2.A@p=ABHnN"HnHn?</p>@m=@.H2.A2.ArA0=A0.nR@=@U?<0.n?Nr=_.H2.A2.ArA0=AJ. g0.jo Bn`0.rAm0=A0.n]D2.n\Dg:0.HHnHn?<A,HpHn?<HnHn?<`N0.x2.tAm0nJBHnHn?<AHpHn?<HnHn?<`0.nl:0.HHnHn?<A,HpHn?<HnHn?<`J0.x2.tAm0JBHnHn?<AHpHn?<HnHn?<RnQ$.HnHn?<HnHn?< o-n=n=nRnQ.`/p>@m=@.H2.A2.ArA0.H4.B4.BtA0B=AJ. gU?.0.D@?Nr=_U?.?.Nr=_RnQ|.BHnN"HnHn?</p>@m@=@.H2.A2.ArA0=A0.nR@=@U?<0.n?Nr=_.H2.A2.ArA0=AJ. gn0.jo Bn`0.rAm0=A0.rAm0nIHnHn?<A,HpHn?<HnHn?<`@0.rAm0IHnHn?<A,HpHn?<HnHn?<=n=RRnQ..H.HA2.A2.A2*nCHnHn?<HnHn?<HnHn?<0.x2.IAC#.H.HA2.A2.AHnHn?<HnN2"C.H.HA2.A2.A2.H/HnN"HnHn ?<HnHn ?<Hn N2"C0*H.Hn.HAn2*H/HnN"H/Hn N"Hn Hn?<HnNBRnQ.R.Sd.RnQ.R.Sd.0. >EE/**N2/*:N2L N^ _\N NVH00.>EE/**N* j*-P/*:N* j:-P$n&n=j/p~m@/p~mh@/p>.@mJ=@.H.HxA2.IAHnNrHnA+Hp/<NRnQ.R.Sd.R.Sd./p~m:@/p~m@/p>.@m=@/p>.@m=@0.nVD.H.HB4.B4.BtA0k-\Dg.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzA+Hp@Hn/<NjHnHnNHnA+Hp0/<NRnQ$.RnQ.R.Sd.R.Sd.0.>EE/**N2/*:N2L N^ _TNNVH00.>EE/**N* j*-P/*:N* j:-P$n&n=j|/p~m@/p>.@m=@/p~m@/p>.@m=@?..H.HxA2.IAA+HpHn/<NjHnNg^/p~mP@/p>.@m2=@?..H.HxA2.IAA+HpHn/<NjHnNg0.ng?..H.HxA2.IAA+HpHn/<NjHnNf.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzA+Hp@Hn/<NjHnHnNHnA+Hp0/<NB.RnQ.R.Sd.RnQZ.R.Sd<.RnQ".R.Sd.J.g0.>EE/**N2/*:N2L N^ _TNNVH00.>EE/**N* j*-P/*:N* j:-P $n&n =j/p~m@/p>.@md=@/.~mH@..f0.R@=@`=|/0.>.@m=@?..H.HxA2.IAA+HpHn/<NjHnNg?..H.HxA2.IAA+HpHn/<NjHnNgt.H.HxA2.IAHnNrHn?.&NzHnA+Hp0/<N.HU.&NHx@0.H@HnNrHnA+Hp0/<N/p~m@/p>.@m=@..VD2.nVDg.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzA+Hp@Hn/<NjHnHnNHnA+Hp0/<NRnQP.R.Sd2.RnQ.R.Sd.RnQ.R.Sd.A+ Cpw"Q|/p~mH@/p>.@m*=@/p~m@/p>.@m=@?..H.HxA2.IAA+HpHn/<NjHnNg/p~m@/p>.@mv=@?..H.HxA2.IAA+HpHn/<NjHnNg&0.ng?..H.HxA2.IAAHpHn/<NjHnNg?..H.HxA2.IAAHpHn/<NjHnNf.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzAHp@Hn/<NjHnHnNHnAHp0/<NB.RnQ.R.Sdt.RnQ.R.Sd.RnQ.R.Sd.J.gAC+ pw"Q0.>EE/**N2/*:N2L N^ _TNNVH00.>EE/**N* j*-P/*:N* j:-P$n&n?. NjHzZHn0+-H/HnN"/<dHnN"HnHn?<Hn?<?<N:XHnN?. Hn?<NXHnNb=j/p~mP@/p>.@m2=@/.~m@..f0.R@=@`=|/0.>.@m=@?..H.HxA2.IAA+HpHn/<NjHnNg?..H.HxA2.IAA+HpHn/<NjHnNgB.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzA+Hp@Hn/<NjHnHnNHnA+Hp0/<N.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzA+Hp@Hn/<NjHnHnNHnA+Hp0/<NHzHn?<NBHzHn?<NBHzHn?<NB.HHrA0A.HHrA0A?. HnHnN:Hn?.?<N*XHnHnNRHnHnNRHnHnNRHn?.?<N*XHnHnNRHz.HnNR.H2.4AAHpHnNRHnHnNR.H2.4AAHpHnNRHnNbRnQ2.R.Sd.RnQ.R.Sd./p~m\@/p>.@m>=@/p~m$@/p>.@m=@?..H.HxA2.IAA+HpHn/<NjHnNg.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzA+Hp@Hn/<NjHnHnNHnA+Hp0/<NHzHn?<NBHz~Hn?<NBHzpHn?<NB.HHrA0A.HHrA0A?. HnHnN:Hn?.?<N*XHnHnNRHnHnNRHnHnNRHn?.?<N*XHnHnNRHzHnNR.H2.4AAHpHnNRHnHnNR.H2.4AAHpHnNRHnNbRnQ.R.Sd.RnQ.R.Sd.0.>EE/**N2/*:N2L N^.Nu1 =     >    NVH00.>EE/**N* j*-P/*:N* j:-P$n&n?. NjHzhHn0+-H/HnN"/<dHnN"HnHn?<Hn?<?<N:XHnN?. Hn?<NXHnNb=j|Bn/p>.@m.=@/p>.@m=@/p~m@/p~m@?..H.HxA2.IAA+HpHn/<NjHnNg.H.HA2.A2.ArA0noRnn=n=n.H.HA2.A2.ArA0=AB.R.Sd,.R.Sd.RnQ.RnQ.J.f~.H.HxA2.IA.H.HxB4.JBHnNrHn?.&(NzA+Hp@Hn/<NjHnHnNHnA+Hp0/<N.H.HA2.A2.ArA0=AJ+-gHzHn?<NB`HzHn?<NBHzHn?<NBHzHn?<NB.HHrA0A.HHrA0A?. HnHnN:Hn?.?<N*XHnHnNRHnHnNRHnHnNRHn?.?<N*XHnHnNRHnNZ?. HzHnN:Hn0.S@2*SAH/HnN"H/HnN"HnHn?<Hn?<?<N:XHnHnNRHnNZJ+-g?. HzHnN:Hn.H.HA2.A2.ArA0H/HnN"/<dHnN"HnHn?<Hn?<?<N:XHnHnNRHnNZ?. HzHnN:Hn0.H/HnN"/<dHnN"HnHn?<Hn?<?<N:XHnHnNRHnNZ?. HzHnN:.H2.4AAHpHnNRHnHnNR.H2.4AAHpHnNRHnNbJ.g00.>EE/**N2/*:N2L N^.Nu1 =  >       NVH00.>EE/**N* j*-P/*:N* j:-P$n&n=j/p~m@?. NjHz.HHAHpN?. Hn?<NXHnNb?. HzNZ/p>.@m8=@?. Hn?.?<N*XHzfHnNRHnNZRnQ.?. Nj?. Hn?<Hz6NXHn0.T@?HzNXHnHnNRHnNb?. HzNZ/p>.@m=@?. Hn.Hx2.IA/<dHnN"AHpHn?<0*H/HnN"Hn?<HnHn?<HnN2 ??<N*XHzrHnNRHnNZRnQn.?. HzRNbR.Sd`.0.>EE/**N2/*:N2L N^.Nu1 *  * * *NVH00. >EE/**N* j*-P/*:N* j:-P$n&n=j/p~mH@/p~m,@?. NjHzV.HHAHpNHz@.HHAHpN?. Hn?<NXHnNb?. ?..H.HAAHpNR?. Nj?. Hn?<NXHnNb?. ?..H.HAAHpNRJ.gN?. Nj?. Hn?<NXHnNb?. ?..H.HAAHpNRR.Sd.R.Sd.0. >EE/**N2/*:N2L N^ _\N12NV`H00.>EE/**N* j*-Pd/*:N* j:-P`Hnt/-.m<B'NHzHn?.訇?< HnHnHnN 0.Hn=@=n0.H=@$nd&n`HzhHn`0+-H/HnVN"/<dHnLN"HnLHnV?<HnV?<?<N:XHn`NHn`?<NXHn`Hn?<NBJ+-g.@m&=@.H2.AAB0RnQ.R.Sd./p~mv@/p>.@mX=@n=n/.~m0@..f0.R@=@`=|/0.>.@m=@?..H.HxA2.IAA+HpHn@/<NjHn@Ng?..H.HxA2.IAA+HpHn@/<NjHn@Ng\.H.HxA2.IA.H.HxB4.JBHn@NrHn@?.&(NzA+Hp@Hn /<NjHn@Hn NHn A+Hp0/<N.H.HxA2.IA.H.HxB4.JBHn@NrHn@?.&(NzA+Hp@Hn /<NjHn@Hn NHn A+Hp0/<N.H2.ACg.H2.A2.Cn=nRnQ.R.Sd.RnQ.R.Sd./p~m0@/p>.@m=@.H2.ArA0JAgn=nJnoHzHn?<NB.HHrA0A?. HnHn`N:Hn`?.?<N*XHn`Hn`NRHz^Hn`NRHn`NZ.H2.AAgp.H2.ArA0=A.H2.AAB0n=n`2?. NjRnQ.R.Sd./p~mh@/p>.@mJ=@/p~m0@/p>.@m=@?..H.HxA2.IAA+HpHn@/<NjHn@Ng.H.HxA2.IA.H.HxB4.JBHn@NrHn@?.&(NzA+Hp@Hn /<NjHn@Hn NHn A+Hp0/<NHzHn?<NBHzHn?<NBHzHn?<NB.HHrA0A.HHrA0A?. HnHn`N:Hn`?.?<N*XHn`Hn`NRHnHn`NRHnHn`NRHn`?.?<N*XHn`Hn`NRHn`NZ?. HzHn`N:.H2.4AAHpHn`NRHnHn`NR.H2.4AAHpHn`NRHn`NbRnQ.R.Sd.RnQ.R.Sd.?. NjHm|?EE/**N2/*:N2L N^.NuTimes1   >    NVH8A/.?<HnHnN/.HnrNrHnr?<NzHnr?<HnN/.HnrNrHnr?<NzHnrHnN/.HmHnU/.Hn?.NJfV?.HnrNrHnr?< ?<NHnrNg* n WD?< HnHnr/<&NjHnrNWDg,/.HnrNrHnr?< ?<NHnrBgHnNHnrNrHnr?< ?<NHnHnR/<NjHnRHnrNHn2NrHn2HnrNgV/.HnrNrHnr?<?<NHnrHnN/.HnrNrHnr?< NzHnr?<HnN`*/.HnrNrHnr?<?<NHnrHnN`UHn/.?<HnNXHnNB=_?< HnHnr/<NjHnrNVD@?< HnHnr/<NjHnrNVD@?< HnHnr/<NjHnrNVD@?<HnHnr/<NjHnrNVD@?<HnHnr/<NjHnrNVD@?<HnHnr/<NjHnrNVD@?<HnHnr/<NjHnrNVD@?<HnHnr/<NjHnrNVD@?< HnHnr/<NjHnrNVD@ nfAC<""" nWD nWDg nfHn/.?<HnNXHnHn?<NB?<HnHnr/<NjHnrNVD@?<HnHnr/<NjHnrNVD@?<HnHnr/<NjHnrNVD@|0.>EEJ:g^/**N*/*:N*&j*&S(j:(T ,-WD,-.WD,-.WDgB./**N2/*:N2/.N nfTJ.g HzHn?< NXHnN`Hz~Hn?< NXHnNJ.g:Hz^Hn?< NXHnNHzFHn?< NXHnN`Hz*Hz(NHz"Hz N?<Hn?<NXHnNbJ.gJ.g8=|HnHn?< NXHnNXHnHn?<NB`C"q"Q3n-J-fHJ.gJ.g?.?.NJ.g?.?..NJ.g?.N?.?.NJ.g?.N?.N?.?.NJ.g&?.N?.N?.N?.?.NJ.g&?.N?.N?.N?.?.N?.NjJ.ghUNBJg\?-`Hn?<NXHnN?.N?.N?.N?.?.N?-`Hm|N?-`/-x/-tN`0.>EE/*:NB:LN^NuPEB1 2 3 4,R-9 10,R20 21 22,C11 -12 -13 14 -15 16 17 -18,S6 8 19,T7 -23889797.v` NVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVH80.>EE&j*&S0.>I(t(T)k|8/p>+@m=@BHnN"HnHn?</p>@mh=@.H2.A2.ArA0H/HnN"HnHn?<HnHn?<HnHn?<RnQ.0.H2H/HnN"HnHn?<HnHn?<HnAHp?<RnQ,./p>+@m=@/p>+@m=@BHnN"HnHn?</p>@m=@.H2.A2.ArA0.H4.B4.BtA0H/HnN"HnHn?<HnHn?<HnHn?<RnQz.0.x2.IA2.I4H/HnN"AHpHn?<2.IAHpHn?<HnHn?<HnHn?<HnAHp?<0.x2.IA2.x4.JBAC#0. H/HnN"0+H/HnN"HnHn?<HnNBRnQd.RnQH.LN^ _TNNV^H 0.>EEJ6f,-| .d .R-@Y/.N%_6/**N*/*6N*0.>E$r$R?.N/p>@mV=@/p>@m<=@0.x2.IA2.x4.JBAC#RnQ.RnQ./p>@m=@/p>@mz=@0.nf60.x2.IA/<HnN"HnAHp?<`.0.x2.IABHnN"HnAHp?<RnQ.RnQt.BHnN"HnHn?</p>@m=@/0S@r>Amf=A0.x2.IAAHpHn?<Hn/?<HnHn|?<HnHn|?<Hn|Hn?<RnQ.RnQ./<HnN"HnHn?<Hn?<HnHn?<HnHn?<Hz BHn?< dHz :Hn?<HnHn?<Hz (Hn?<0H/Hn|N"Hn|Hn?<HnHn?<-n=|0H/HnN"HnHn|?<HnHn|?<Hn|Hn?<|0.R@=@/0S@r>Amh=AJ-fT/0.R@>@m=@0.x2.IAAHpHn?<Hn?<HnHn?< oB.0.x2.IA2.x4.JBAHpHn?<AHpHn?<A C|""2HnHn|?<Hn|Hn?<0.x2.IAA-pHnHn?<Hn?< HnHn|?<Hn|/?<HnHnr?<Hnr/?<HnrHn|?<Hn|?<Hn|Hn?<HnHn?<BHnN"HnHn|?<HnHn|?< d(HnHn?<Hn?< HnHn?<HnHn?<Hn/?</<Hn|N"HnHn|?<Hn|?<Hn|?</<HnrN"Hn|Hnr?</<HnhN"HnrHnh?<Hnh?<HnHn^?<HnhHn^?<Hn^Hn?<HnHn?<Hn/?<HnHn?</<HnN"HnHn?<Hn?<HnHn?<HnHn?<Hn/?<HnHn?<HnHn?<HnHn?<HnHn?</p>@mt=@0.nVD2.nVDgF0.x2.IAA-p0.x2.IAA-pHnHn?<HnHn?<HnHn|?<HnHn|?<Hn|Hn?<HnHn?<HnHn?<HnHn?<HnHn|?<HnHn|?<Hn|Hn?<HnHn?<0.x2.IAC#0.x2.IAC#0.x2.IAC#0.x2.IAC#0.x2.IAA-p0.x2.IAA-p0.x2.IAHnHn?<HnHn?<HnHn|?<HnHn|?<Hn|Hn?<HnAHp?<0.x2.IAHnHn?<HnHn?<HnHn|?<HnHn|?<Hn|Hn?<HnAHp?<RnQ.0.x2.IAA-p0.x2.IAA-p0.x2.IAA-p0.x2.IAHnHn?<HnHn?<HnHn|?<HnHn|?<Hn|Hn?</<HnrN"HnHnr?<HnHnr?<HnrHn?<HnAHp?<0.x2.IAHnHn?<HnHn?<HnHn|?<HnHn|?<Hn|Hn?</<HnrN"HnHnr?<HnHnr?<HnrHn?<HnAHp?<HnHn?<HnHn?<HnHn?<HnHn|?<HnHn|?<HnHnr?<Hn|Hnr?<HnrHn?<HnHn?<0.x2.IAC#0.x2.IAC#RnQ<.0S@nH/HnN"AC|""2HnHn|?<0S@H/HnrN"HnrHn|?</< HnhN"Hn|Hnh?<HnhNBRnQ..-gnHnHn?<HnHn?< ]D-gJ-f/p>@m*=@/@mb=@0.x2.IAAHpHn?<HnHn?< o"0.x2.IAA-p=nRnQ.BHnN"HnHn|?<HnHn|?< dBHnN"HnHn?<0.HC#0.2.C0.x2.IA/@mh=@0.rA0=A/p>@m<=@0.x2.IA2.x4.JBAC#RnQ.RnQ.0.>EE/**N2/*6N2LN^ _TN?7li?7li?7li?@ffffffgNVH 0.>EE/*6N*0.>E$r$R?. Nj?. Hn?< NXHnNb/p>@m=@/p>@m=@0.x2.IA2.x4.JBAHpHn?<AHpHn?<HnHn?<BHnN"HnHn?<HnHn?< oX0.x2.IAHnHn?<Hn?<AHpHn?<HnHn?<HnHn?<0.x2.IACt#RnQ.RnQ.?. ?<?<??HzEE/*6N2LN^.NuNVH8Hn?<N0.>EE/**N*/*6N*0.>EE&j*&S0.>I(t(T=kBHnN"HnHn?</p>.@mB=@0.HHnHn?<AHpHn?<HnHn?<RnQ./p>.@m=@0.H/<dHnN"AHpHn?<HnHn?<HnHn?<0.H"n#HnHn?<Hz8Hn?< m=nRnQ.J. gL?.Nj?.Hn?< NXHnNb?.?<?<?<?.HzHz</.NZJ.g?.Nj?.Hn?<NXHnNb/p>.@m=@0.HAHpHn?<Hn?<HnHn?</p>.@m`=@0.x2.IA2.x4.JBAHpHn?<HnHn?<Hn nHp?<RnQ.RnQ\.?.?<?<?.?.HzHz</.NZ?.NjJ. gv?.Nj?.Hn?<NXHnNb|/p>.@m=@/p>@m=@BHnN"HnHn?</p>.@m=@0.x2.IA.H4.B4.BtA02.IH/HnN"AHpHn?<AHpHn?<HnHn?<HnHn?<HnHn?<HnHn?<RnQX.0.x2.IA"n#RnQ .RnQ.?.?<?<??.HzZHzX</.NZ0.>EE/*6N2/**N2HnNLN^ _O N? =p NVH E|U?*?.Nz5_U?*?. Nz5_U?*?.Nr5_U?*?. Nr5_U??. Nz4U??.Nz4U?*?. Nr5_U?*?.Nr5_LN^ _PNNVH8 nCp"Q2Hn?<NHn?<N0.>EE/**N*/*6N*Hm|?<'?<'?EE&j*&S0.>I(t(T=kBHnN"HnHn?<=|/p>.@m=@0.HAHpHn?<Hn?<HnHn?</p>.@m`=@0.x2.IA2.x4.JBAHpHn?<HnHn?<Hn nHp?<RnQ.RnQ\./p>.@m=@0.x2.IA nHpHn?<Hn?<HnHn?<HnHn?<HnHn?< o-n0.x2.IA nHpHn?<Hn?<HnHn?<HnHn?<HnHn?< o-nRnQ:.|/p>.@m=@/p>@m=@BHnN"HnHn?</p>.@m=@0.x2.IA.H4.B4.BtA02.IH/HnN"AHpHn?<AHpHn?<HnHn?<HnHn?<HnHn?<HnHn?<RnQX.0.x2.IA"n#RnQ .RnQ./p>@m=@0.x2.IA nHpHn?<Hn?<HnHn?<HnHn?<HnHn?< o-n0.x2.IA nHpHn?<Hn?<HnHn?<HnHn?<HnHn?< o-nRnQ:.HnHnHnHnN/p>.@m$=@0.x2.IA2. H/HnN" nHpHn?<HnHn?<HnN2 =@0.x2.IA2. H/HnN" nHpHn?<HnHn?<HnN2 =@?.0.D@?0.D@??.?.0.D@?0.D@??.N0.4A HpHn?<NBUHnҨ=_Jnl =n`Bn0.n=@0.D@2.HA=@0.Y@?0.n?0.nX@??.N?.?.?<0Bg?<BgHnN0.4AHpHn?<NBUHnҨ=_Jnm =n`Bn0.D@n=@0.Hn=@0.Y@?0.n?0.nX@??.N?.?.?<0Bg?<BgHnNRnQ.HnHnHnHnN/p>@m=@0.x2.IA2. H/HnN" nHpHn?<HnHn?<HnN2 =@0.x2.IA2. H/HnN" nHpHn?<HnHn?<HnN2 =@0.n?0.D@n?0.n?0.D@n?0.n?0.D@n?0.n?0.D@n?0.4A HpHn?<NBUHnҨ=_Jnl0.n=@` 0.D@=@0.n=@0.D@2.HA=@0.Y@?0.n?0.nX@??.N?.?.?<0Bg?<BgHnNRnQP.Hm䨝0. D@?Bg?. BgBg0. D@?Bg?. 0. D@Y@?0. D@Y@?0. X@?0. X@?NHm쨝A|-HJnoHnHnHnHnN0.H n2@"n2 n0(X@? n0n??<0Bg?<BgHn?<NXHnN n0(X@?0.H nP??<0Bg?<BgHn?<NXHnN/.ިs0.>EE/*6N2/**N2HnNHnNLN^ _O NNV nCp"Q2HnHnN /.?<,HnHn?< NXHnN/.?<+HnHnHn?<N"XHnNXHnN/.?<*HnHnHn?<N"XHnNXHnN/.?<)HnHn?< NXHnN/.HnnNrHnn?<)NzHnn?<HnN/.HnnNrHnn?<(NzHnnHnNHn-_UHnHn/.N=_0. @)fHn-_`V @*fHn-_`B @+fHn-_`. @,f& nC"2 nC"2 nC"2?.HnnNrHnn?<NzHnn?<NzHnnNgP/.N nfA"np"Q2N^.NuNVH ACp"Q2BnUHn?<NJg ?.NHz Hn?<NXHnNUHnN=_YB?<NHnHz N-_/.?<HnHn?<NXHnN/.?<HnHn?<NXHnN/.?< HnHn?.BgN*XHnN/.?< HnHn?.BgN*XHnN/.?< HnHn?.BgN*XHnNHnbNrHnbHn/<NJ.gFHnbNrHnb?<NzHnHnB/<NjHnbHnBNHnBHn/<NJ.gFHnbNrHnb?<NzHnHnB/<NjHnbHnBNHnBHn/<NJ.gFHnbNrHnb?<NzHnHnB/<NjHnbHnBNHnBHn/<NJ.gFHnbNrHnb?<NzHnHnB/<NjHnbHnBNHnBHn/<NJ.gFHnbNrHnb?<NzHnHnB/<NjHnbHnBNHnBHn/<NJ.gFHnbNrHnb?<NzHnHnB/<NjHnbHnBNHnBHn/<N/.Hn?<HnNHzrHnNJWDHnHn?< &NXHnNXHnHnNJWDgR/.HnbNrHnb?<NzHnbHnN/.HnbNrHnb?<NzHnb?<HnN`>/.?<HnHnN/.HnbNrHnb?<NzHnb?<HnNJ.f*/.HnbNrHnb?<?<NHnbHnN/.HmHnU/.Hn?.NJfR?.HnbNrHnb?<?<NHnbNg* nWD?<HnHnb/<&NjHnbNWDg,/.HnbNrHnb?<?<NHnbBgHnNHnbNrHnb?<?<NHnHnB/<NjHnBHnbNHn"NrHn"HnbNgV/.HnbNrHnb?<?<NHnbHnN/.HnbNrHnb?<NzHnb?<HnN`*/.HnbNrHnb?<?<NHnbHnNUHn/.?< HnNXHnNB=_UHn/.?< HnNXHnNB=_UHn/.?< HnNXHnNB=_?<HnHnb/<NjHnbNVD@?<HnHnb/<NjHnbNVD@?<HnHnb/<NjHnbNVD@?<HnHnb/<NjHnbNVD@?<HnHnb/<NjHnbNVD@?<HnHnb/<NjHnbNVD@ nfACp"Q2` nf HnN?.HnbNrHnb?<NzHnb?<NzHnbNg nfHn/.?<HnNXHnHn?<NB?<HnHnb/<NjHnbNVD@?<HnHnb/<NjHnbNVD@?<HnHnb/<NjHnbNVD@/.N nfF?<Hn?<NXHnNbB.0.>EEJ6f |` j6 P ( j* Pg|J.gJ.g8=|HnHn?< NXHnNXHnHn?<NB`EE/*6NB6LN^NuPEB1 2 3 4,R22 23 24,C7 15 16 17 19 20,S6 8 10 12 14 18 21,T9 11 13 -25iNVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVH0$n &n/p>@m=@/0.R@>@mh=@0.N<&0.NH@0.N<(0.NH@A00@J@jD@C30RnQ.RnQ.L N^ _PNNVH0$n &n/p~n@D/p>*@m=@/p~n@D/0.R@>*@m=@.HN&.HN@0.N<@0.NH@.HN(.HN@0.N<@0.NH@A00@J@jD@C30RnQP.S.Sd..RnQ.S.Sd.L N^ _PNNVH0$n&n J.g/./. N7|#(`0+#(NdHrA#(00N<&0+#(NdHrA#)00NH@0+#(NdHrA#(00N<(0+#(NdHrA#)00NH@A00@D@C300+#(R@7@#(=|=n Jn o/p>@m=@0.N<&0.NH@A000no0.ngv0.N<&0.NH@A=p00+#(NdH&0.NC#(00+#(NdH&0.NC#)0RnQH.`/p>@m=@/0.R@>@m=@0.N<&0.NH@A000nov0.N<&0.NH@A=p00+#(NdH&0.NC#(00+#(NdH&0.NC#)0RnQT.RnQ6.L N^ _O NNVH0$n&n J.g/./. N7|#(`U0+#(NdHrA#(0?HnN=_U0+#(NdHrA#)0?HnN=_.HN&.HN@0.N<@0.NH@.HN(.HN@0.N<@0.NH@A00@D@C300+#(R@7@#(=|U?. HnN=_Jn o/p~nr@D/p>*@mR=@.HN&.HN@0.N<@0.NH@A000no0.nVD..VDg.HN&.HN@0.N<@0.NH@A=p00+#(NdHU?.&.HNN0NC#(00+#(NdHU?.&.HNN0NC#)0RnQ.S.Sd.`/p~n@D/p>*@mr=@/p~nX@D/0.R@>*@m4=@.HN&.HN@0.N<@0.NH@A000no.HN&.HN@0.N<@0.NH@A=p00+#(NdHU?.&.HNN0NC#(00+#(NdHU?.&.HNN0NC#)0RnQ.S.Sd.RnQ.S.Sdx.L N^ _O NNVH0$n&n *R%@0*R@H/HnN"/<HnN"HnHn?<HnN2 N=@.HN&0. N@0. N@pA00=@.HN&0. N@0. N@0.NC0/p~m @/p>*@m=@.HN&0.N@0. N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=nJn^DJn^Dg0.nJ@jD@=@`=n.HN&.HN@0.N<@0. NH@.HN(.HN@0.N<@0. NH@A00@nnC30.HN&.HN@0. N<@0.NH@.HN(.HN@0.N<@0. NH@AC3@0RnQ.R.Sd./p>@mb=@.HN&0. N@0.N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=nJn^DJn^Dg0.nJ@jD@=@`=n0.N<&0. NH@0.N<(0. NH@A00@nnC300. N<&0.NH@0.N<(0. NH@AC3@0RnQ.L N^ _ONNV/./.N/./.N/./..HN?.?. ?. N/./.U.HNNHN?.?. ?.N/.NN^ _ONNVH0$n &n/. /.N *R%@0*S@2*RAH/HnN"/<HnN"HnHn?<HnN2HN=@0R@4/p~mf@/p>*@mH=@.HN&0.N@0N@AB00RnQ.R.Sd./p~m @/p~m@/p>*@m=@/p>*@m=@.HN&.HN@0.N<@0.NH@.HN(.HN@0.N<@0.NH@A00@nC30RnQR.RnQ6.R.Sd.R.Sd./p>@mr=@0.N<&0NH@0*HC300N<&0.NH@0*HC30RnQ./. NL N^ _PNNVH0$n &n/. /.N *R%@0*S@2*RAH/HnN"/<HnN"HnHn?<HnN2HN=@0*R@5@/p~mf@/p>@mJ=@.HN&0*N@0.N@AB00RnQ.R.Sd./p~m@/p~m@/p>*@m=@.HN&.HN@0.N<@0*NH@0C30.HN&.HN@0*N<@0.NH@0C30RnQJ.R.Sd,.R.Sd./p>@m=@/p>@mf=@0.N<&0.NH@0.N<(0.NH@A00@nC30RnQ.RnQ./. NL N^ _PNNVH0$n&n /p~mR@/p>*@m4=@/./. .HN?.?.BgNRnQ.R.Sd.0S@4/0.>@m|=@/p~m@/p>*@m=@.HN&0.N@0.N@.HN(0.N@0.R@N@pA0@NC0RnQv.R.SdX./0R@r>Amd=A0.N<&0.NH@0.N<2.RA(0NH@AC3@0RnQ.0.N42.RA&0N4A HpA Hp0?<2NBRnQ./0.>@m|=@/p>@mb=@0.N<&0.NH@0.R@N<(0.NH@AC3@0RnQ.RnQ./.NL N^ _O NNVH0$n&n /p~mP@/p>@m4=@/./. .HN?.?.BgNRnQ.R.Sd.0*S@5@/0.>*@m=@/p~m@/p>@m=@.HN&0.N@0.N@.HN2.RA(0N@0.N@pA0@NC0RnQt./p~m@/0*R@r>Am=A.HN&.HN@0.N<@0.NH@.HN(.HN@0.R@N<@0.NH@AC3@0RnQV.R.Sd4..HN&0.N4@.HN2.RA(0N4@AHp@AHp0?<2NBR.Sd.RnQ./0.>*@m=@/p~m@/p~m@/p>*@m=@.HN&.HN@0.N<@0.NH@.HN(.HN@0.N<@0.R@NH@AC3@0RnQV.R.Sd8.R.Sd.RnQ./.NL N^ _O NNVH $n/p>@m=@0.N&0.N@pA00=@0.N&0.N@pAm00=@/./. <?.?.?.?.NRnQ~.0.N4AHpHn?<NB0.N4&0.N4A HpAHp0?<2NB0.N4HnA Hp?<2NBLN^ _O NNVH00. N>EEJ.f,-|# .d .R-@Y/.N%_./**N* j*-P/*.N* j.-P$n&n0*R@H/HnN"/<HnN"HnHn?<HnN2 N=@7|#(/p>*@m=@/0.>*@m&=@/p~m @/p~m@Bn/p>@m=@.HN&0.N@0.N@pA00=@.HN&0.N@0.N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=n0.n=@RnQ8..HN&.HN@0.N<@0.NH@0*S@ҐnC30.HN&.HN@0.N<@0.NH@.HN(.HN@0.N<@0.NH@AC3@0R.Sd.R.Sd.RnQ.J.g>0.22*RH/HnN"H/HnN"HnHn?<HnNBRnQ./p>@m=@/0.>@m=@Bn/p~m@/p>*@m=@.HN&0.N@0.N@pA00=@.HN&0.N@0.N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=n0.n=@RnQ8.R.Sd.0.N<&0.NH@0*H2*SAnC300.N<&0.NH@0.N<(0.NH@AC3@0RnQn.J.gB0*n22*RH/HnN"H/HnN"HnHn?<HnNBRnQ .0. N>EE/**N2/*.N2L N^.NuNV n 0N nAF=p0. nPf" n 0N nAH=p n "n2"n 2 n JPWDHN@N^ _O NNVH n 0N$nEFEJj^DJj^Dg=| n =PBn0.R@=@UHnHn/.N BJg=R n =PBn0.R@=@UHnHn/.N BJg0.no"n 2` "n 2LN^ _PNNVH80. N>EEJ2f,-|N .d .R-@Y/.N%_2/**N* j*-P/*.N* j.-P /*2N* j2-P$n &n(n/p>,@mB=@(0.(NAFA-H"n| nBP nBhRn(Q.=|"Bn/p~n@-D/p>,@mr=@(0.(NAHJpWD.gB/p~n4@,D/0.(R@>,@m=@&0.&NAHJpWD.g.-HN&.,HN@0.(N<@0.&NH@A000no.-HN&.,HN@0.(N<@0.&NH@A=p0=n( =n&.-HN@+.,HN@*Rn&Q.S.,Sd.Rn(Q.S.-Sdx.7nJ.+HN&.*HN@0. N<@0.NH@.+HN(.*HN@0. N<@0.NH@A00@D@C300. NAJ0.+gNU.+HNNHN@+U.*HNNHN@*0.NAJ0.*VDHN@J.gHn /N JHn/N J=|(=n &0.&ng&UHn(Hn&/N B2.&nWDgJn&f\0. NAFA-H nJPf"n2` "n3nJ.gv=|(=n&0.&NU&0.&N(AJ0@HNNHNCJ0UHn(Hn&/N BJg0.NAFA-H nJPf"n2 ` "n3n 0."N&0. NC;00."N&0.NCY00."NHCv30."R@=@"0."22,TH/HnN"H/HnN"HnHn?</<2HnN"HnHn?<HnNB0."lWD-gBn&0.&R@=@&0.&NAHJpf=|(=|$0.$N&0.&N(AJ0@HNC00.$N&0.&NC00.&N&0.$NC-00.$R@=@$UHn(Hn&/N BJgd/0,S@r>Am=A(0.(N&0.(NrA;00NrA-00NC;00.(N&0.(NrAY00NrA-00NCY0Rn(Qf./p~n@-D/p>,@m=@(/p~n@,D/0.(R@>,@m=@&.-HN&.,HN@0.(N<@0.&NH@.-HN(.,HN@0.(N<@0.&NH@A00@J@jD@C30Rn&QP.S.,Sd..Rn(Q.S.-Sd./p>@m8=@(0.(NAFA-H nBP nBhRn(Q.=|"Bn/p>@m=@(0.(NAHJpf/0.(R@>@m=@&0.&NAHJpWD.gl0.(N<&0.&NH@A000no:0.(N<&0.&NH@A=p0=n( =n&Rn&Ql.Rn(Q2.7nL0. N<&0.NH@0. N<(0.NH@A00@D@C30J.gHn /N JHn/N J=|(=n &0.&ng&UHn(Hn&/N B2.&nWDgJn&f0. NAFA-H nJPf"n2` "n3n0.NAFA-H nJPf"n2 ` "n3n 0."N&0. NC00."N&0.NC00."NHC 30."R@=@"0,n"22,TH/HnN"H/HnN"HnHn?</<2HnN"HnHn?<HnNB0."TWD-gBn&0.&R@=@&0.&NAHJpf=|(=|$0.$N&0.&NC00.&N&0.$NC-00.$R@=@$UHn(Hn&/N BJg/0S@r>Am=A(0.(N&0.(NrA00NrA-00NC00.(N&0.(NrA00NrA-00NC0Rn(Qf./p>@m=@(/0.(R@>@mh=@&0.(N<&0.&NH@0.(N<(0.&NH@A00@J@jD@C30Rn&Q.Rn(Q.p+=@&0NrA0=A$BnBn/p>,@m=@(0.(N&A00HN@-0.(NrA0=A .-HN&0. N@0.&N@pA00n=@.-HN&0. N@0.$N@pA00n=@Rn(Q0.0.noh/p>,@mX=@(0.(NU&0.(N(A0@HNNHNC0Rn(Q.0. N>EE/**N2/*.N2/*2N2LN^.NuNVH00.N>EE/**N* j*-P/*.N* j.-P$n&n?. Nj?. Hn?<N 2XHnNbJ+g |`B./.HNr>nAD/p~n~@D/p>+@m=@/p>+@m=@0.Nx&0.NH@Hn.HN(.HN@0.N<@0.NH@A?0@?+?N:XHnApHp0?<RnQd.RnQH.HzHn?<NBHzHn?<NB.HNHrA00N@.HNHrA00N@?. Nj?. ?<Bg?+?+HnHn<HnNZS.Sd.S.Sdn.0.N>EE/**N2/*.N2L N^.Nu  NVH00.N>EE/**N* j*-P/*.N* j.-P$n&n?. Nj?. Hn?< N 2XHnNb/p>@m=@/p>@m~=@0.Nx&0.NH@Hn0.N<(0.NH@A?0@?+?+N2XHnAtHp0?<RnQ.RnQp.?. Nj?. ?<Bg??Hn?<N"XHnHn?<N"XHn<HnNZ0.N>EE/**N2/*.N2L N^.NuNVH80.N>EE/**N* j*-P/*.N* j.-P/*2N* j2-P$n&n(n?. Nj?. Hn?<N 2XHnNb?. Nj/0S@r>Am=A0.NrA0=A0.NrA0=A0.NrA0=A0.NrA0=A0.NHA =pHzHn?.BgN*XHnNHzHn?.BgN*XHnNHzrHnHn?.?,?,N2XHn?<?<N:XHnN?. Hn?<N 2XHnNbRnQ.?. Nj?. Hn?<N 2XHnNb?. Nj/0,S@r>Am=A0.NrA;0=A0.N&A00HN@0.NrA0=A0.NrAY0=A0.N&A00HN@0.NrA0=A0.NHAv=pHzHn?.BgN*XHnNHzHn?.BgN*XHnNHzHnHn?.?,?N:XHn?<?<N:XHnNHz.HNHAHpNHz.HNHAHpN?. Hn?<N 2XHnNbRnQj.0.N>EE/**N2/*.N2/*2N2LN^.Nu12312345NV=|0. Hnmj0.S@2.SA2. SAH/HnN"H/HnN"HnHn?<HzbHn?<HnN2 RN=@`l0. n2.SA2. SAH/HnN"H/HnN"HnHn?<HzHn?<HnN20.HN=@0. @fAC""`. @fAC""` @fAC""Hn n0(H nh? n0( nh nhR@? n0( nh n2(HA? n0( nhR@?HnHnN^ _O N?ѷXe+?ѷXe+NVH8 nCp "Q20. N>EE/**N* j*-P/*.N* j.-P/*2N* j2-PHnҨt/-.m<B'N$n&n(n0.HH/HnN"HnHn?<Hn?*J?,?N:XHnN2 N=@0.nl=n0.H/HnN"/< HnN"HnHn?<HnN* N=@0.H/HnN"HnHn?</<dHnN"HnHn?<HnN2 N=@Hn?*L?,?,N2XHnN* N=@0.nl=n0.H/HnN"/< HnN"HnHn?<HnN* N=@0.H/HnN"HnHn?</<dHnN"HnHn?<HnN2 N=@HnHnHnHnN=nBg?.ĨHn?<N 2XHnHn?<NBHnUHn=_0.n=@Bg?.ĨHn?<N 2XHnHn?<NBHnU?.UHnNr=_0.nn=@HnHnHnHnNHnHnHnHnNU?.?.Nr=_U?.?.Nr=_HnHnHnHnNU?.?.Nr=_U?.?.Nr=_0.X@=@BnBn0.H=@J.gHnHnHnHnN/p>,@m=@U?.UU0.N&A00HNNHN&0.NrA00N4@AHp0Nr=_U?.U0.N&A00HN&0.NrA00N4@AHp0Nr=_RnQ.J.WD.gZHnHnHnHnN/p>@m8=@U?.U0.N4A HpNr=_RnQ.0.n=@0.T@=@J.g0.nn=@J.g0T@n=@J.gvp nH/HnN"HnHn?</< HnN"HnHn?<0.H/Hn|N"HnHn|?<Hn|N2 N=@=n=nJ.gHnHnHnHnN/p>@mj=@Hn0.NrA0?BgN*XHnHn?<NB0.n=@UHn0._??.ĨHnRnQ.0.Đn2.HA=@0.n2.HA=@Hn0.n2.HA?0.ĐnnR@?0.n2.A2.HA?0,nĐnnR@?J.g >Hmܨ/p>,@m=@HnHnHnHnN0.N&A00HN@0.NrA0=A=nU.HNNHN&0.N4@AHp0Hn?<NBUHn0._??.ĨHnHnHnHnHnNJ.g0.n=@Hn?.BgN*XHnHn?<NBUHn0.̐_?BgHn/p>@m=@0.NrA0=A.HN&0.N@0.N@pA00=@U.HNNHN&0.N@0.N@pA00=@0.n2,RAAf,Hn0,n?BgN*XHnHn?<NB`JnWDJnWDg$Hn?< N"XHnHn?<NB` nWD nWDg$Hn?< N"XHnHn?<NB``0.lWD2.lWDg$Hn?< N"XHnHn?<NB` Hn?< N"XHnHn?<NBJ.g?.?.?,/N r0.n=@J.gUHn0._??.ĨHnRnQ.0.n=@Hn?.BgN*XHnHn?<NBUHn0._??.ĨHn`JHm쨝0.T@?0.H2.Ē@?0.nY@?0.H2.Ē@?HmܨHnHnHnHnN.HN&0.N4@AHp0Hn?<NB0.n??.ĨHn0.H2.Ē@=A0.NHC30.nUHn&_TC??.?.?.0.n=@RnQX.J.gHm䨝HnHm쨝HnHnHnHnNAC^p"Q/p>,@m<=@0.NHABp0.NHC 3RnQ./0,S@r>Amn=A0.NrA;0=A0.NrAY0=A0.NH&0.NHA\200A\pH=AHn0.NHAv?0?,?N:XHnHn?<HnHn?</<dHn|N"Hn|Hn?<HnN2 N=@0.nmr0.H/HnN"HnHn?<0.H/HnN"HnHn?<HnN2 N=@0.NHAJpo0.NHA=p`0.NHAJpo0.NHA=p`0.NHA ?00.NHA?0?.?.0.NHA ?00.NHA?00.NHC 30.NHC30.NHC3RnQ./p nr>Am=A0.H/HnN"HnHn?</< HnN"HnHn?<0.H/Hn|N"HnHn|?<Hn|N2 N??.Bg?@m=@Hn0.NrA0?BgN*XHnHn?<NB0.n=@0.NH2.H4.”AC 3UHn0._??.ĨHnRnQx.J.f0.Hn=@=n=n0.n=@0.n=@/0~@n=@DGHm䨝0.NrA00N4A HpHn?<NB0.n2.HA=@0.Đn2.HA=@J.f,0.Hn=@0.NHC3J.g"?.0.Hn??.?.J.g0.H2.@=A`0.nU@=@J.g$0.nn̐n2.HA?BgHmܨUHn0._T@??.?.?.J.glHnHnHnHnNHn0.NrA0?BgN*XHnHn?<NB0.nUHn&_??.ĨHnHnHnHnHnN?.?.ĨHn0.n=@SnQ .=nJ.gHm쨝HnHnHnHnNJ.g,A"C^p"Q/p>@m<=@0.NHABp0.NHC3RnQ./0S@r>Amp=A0.NrA0=A0.NrA0=A0.NH&0.NHA\200A\pH=AHn0.NHA ?0?,?,N2XHnHn?<HnHn?</<dHn|N"Hn|Hn?<HnN2 N=@0.nmr0.H/HnN"HnHn?<0.H/HnN"HnHn?<HnN2 N=@0.NHAJpo0.NHA=p`0.NHAJpo0.NHA=p`0.NHA ?00.NHA?0?.?.0.NHA ?00.NHA?00.NHC 30.NHC30.NHC3RnQ./p nr>Am=A?.0.H/HnN"HnHn?</< HnN"HnHn?<0.H/Hn|N"HnHn|?<Hn|N2 N??@m<=@0.NHABp0.NHC 3RnQ./0S@r>Amp=A0.NrA0=A0.NrA0=A0.NH&0.NHA\200A\pH=AHn0.NHA ?0?,?,N2XHnHn?<HnHn?</<dHn|N"Hn|Hn?<HnN2 N=@0.nmr0.H/HnN"HnHn?<0.H/HnN"HnHn?<HnN2 N=@0.NHAJpo0.NHA=p`0.NHAJpo0.NHA=p`0.NHA ?00.NHA?0?.?.0.NHA ?00.NHA?00.NHC 30.NHC30.NHC3RnQ./p nr>Am=A0.H/HnN"HnHn?</< HnN"HnHn?<0.H/Hn|N"HnHn|?<Hn|N2 N??.Bg?EE/**N2/*.N2/*2N2LN^ _\NNV nCp "Q2HnHnN /.?<,HnHn?< N 2XHnN/.?<+HnHn?< N 2XHnN/.?<*HnHnHn?<N"XHnNXHnN/.?<)HnHnHn?<N"XHnNXHnN/.?<(HnHn?< N 2XHnN/.HnbNrHnb?<(NzHnb?<HnNHn-_UHnHn/.N=_0. @(fHn-_`v @)fHn-_`b @*fHn-_`N @+fHn-_`: @,f2 nC"2 nC"2 nC"2 nC"2?.HnbNrHnb?<NzHnb?<NzHnbNg0/.N nfA"np "Q2N^.NuNVvH AC~p "Q2BnUHn?<NJg@?.NHz/.?<"HnHnN/.HnVNrHnV?<"NzHnV?<HnNJ.f*/.HnVNrHnV?< ?<$NHnVHnN/.HmHnU/.Hn?.NJf n f|?< HnHnV/<NjHnVNg./.HnVNrHnV?< ?<NHnVHnN`*/.HnVNrHnV?< ?<NHnVHnN`(?.HnVNrHnV?<?<NHnVNg. nWD?<HnHnV/<&NjHnVNWDg,/.HnVNrHnV?<?<NHnVBgHnNHnVNrHnV?<?<NHnHn6/<NjHn6HnVNHnNrHnHnVNgV/.HnVNrHnV?< ?<$NHnVHnN/.HnVNrHnV?<NzHnV?<HnN`*/.HnVNrHnV?< ?<$NHnVHnN`?.HnVNrHnV?<?<NHnVNgHnVNrHnV?<NzHnV?<NzHnHn6/<NjHn6HnVNHnNrHnHnVNg./.HnVNrHnV?<?<NHnVHnN`*/.HnVNrHnV?<?<NHnVHnN`UHnv/.?< HnNXHnvNB=_UHnv/.?<HnNXHnvNB=_UHnv/.?<HnNXHnvNB=_?< HnHnV/<NjHnVNVDHN@?< HnHnV/<NjHnVNVDHN@?<HnHnV/<NjHnVNVDHN@?<HnHnV/<NjHnVNVD.HN@?<HnHnV/<NjHnVNWDHN@?<HnHnV/<NjHnVNWDHN@?<HnHnV/<NjHnVNVDHN@?<HnHnV/<NjHnVNVDHN@?<HnHnV/<NjHnVNVDHN@?<HnHnV/<NjHnVNVDHN@?<HnHnV/<NjHnVNVDHN@?<HnHnV/<NjHnVNVDHN@ nfA~Cp "Q2` nf Hn~N z?.HnVNrHnV?<NzHnV?<NzHnVNg nfHnv/.?<$HnNXHnvHn?<NB?<!HnHnV/<NjHnVNVDHN@?<"HnHnV/<NjHnVNVDHN@?<#HnHnV/<NjHnVNVDHN@/.N nf&?<Hnv?<N 2XHnvNbJ.gJ.g8=|HnvHnv?< NXHnvNXHnvHn?<NB`EE/*2NB2LN^NuPhB1 2 3 4,R8 9,R19 20 21 22 23,R33 34 35,C10 25 26 27 29 30 31,S6 7 11 13 15 17 18 24 28 32,T12 14 16 -36M `NVHnNrHn?<?<NHnHm/<NHnNrHn?<?<NHnHm/<NHnNrHn?< ?< NHnHm/<NHnNrHn?<NzHn?<NzHn?<NzHn?<NzHn?<NzHn?<NzHn?< NzHn?< NzHn?< NzHn?< NzHnHm/<NHnNrHn?<NzHn?<NzHn?<NzHn?<NzHn?<NzHn?<NzHn?< NzHn?< NzHn?< NzHn?< NzHnHm/<NN^NuNVH0Bn0.NHE$rJg"/*N*Y j//< .-_Y/*N" .П-@ .Ю-@&np @fB0+ kH=@Hn0+ @?0.Y@?0+@?0.X@?`A C""U nHh HnHn쨪Jg,0+ nhg n=h nA "n"" n0(HЮ-@ .谮\DJn^DgA "n ""/*N2=nL N^ _ONNVH8$n&j&S0+N>I(t(T ,R)@Hn/.?<HkNXHnHn?<NB klT0+N4HnA HpNJg7|0+N4HnA Hp?<2NB`Z kon kf =k`=k0.N4HnA HpNJg7|0.N4HnA Hp?<2NB`U?+HnN=_.HN&0.N4@HnAHp0NJg^J.f.Y0+H//< . N7@`*Y0+H//< . N7@.HN&0.N4@HnAHp0?<2NBHnNrHn?+NzHkPHn/< NjHnHnNHnHkP/< NLN^.NuNVH8$n&j&S0+N>I(t(T ,R)@Hn/.?<HkNXHnHn?<NB0+ @f&Hz$HnNJcHnHl?<PNB` @f&HzHnNJcHnHlL?<PNB` @f&HzHnNJcHnHl?<PNB`^ @fTHzHnNJc@UHnNB0S@9@ ll9|0,l9@ ll9|` @fPHzNHnNJcI(t(T0+N>A p P-HBnBn0.R@=@?.HkPHn/< NjHnNg=n=n0.R@=@0.T\D nWDg T^DJl^Dg ngJno =n`Bn0.N7@0+N>A p/0+N>A p/?.<N n0(#(NdHr nA#(0=A n0(#(NdHr nA#)0=AHn0.N<&0.NH@ nA000J@jD@??,?,N2XHnN2 N=@`Bn0.NHA/0?< 0.H@d?NHnNrHnHn/<NHnNrHnHn/<N n0(#(NdHr nA#(0nWD& n0(#(NdHr nA#)0nWD n0(#(NdHr nA#)0nWD( n0(#(NdHr nA#(0nWDHN@ n h#(^D.gJHnNrHn?< NzHnHn/<NjHnHnNHnHn/<N`FHnNrHn?< NzHnHn/<NjHnHnNHnHn/<N n hd#(]D. n2(#(I4SBԲB]DJkWD4SB nh#(^DgJHnNrHn?< NzHnHn/<NjHnHnNHnHn/<N`FHnNrHn?< NzHnHn/<NjHnHnNHnHn/<NJnfHnNrHn?<NzHnHn/<NjHnHnNHnHn/<NJ,g~HnNrHn?<NzHnHn/<NjHnHnNHnHn/<N0.NHA/0?<HkHn?<N XHnN`60.NHA/0?<HkHn?<N XHnN`HnNrHn?<NzHn?<NzHnHn/<NjHnHnNHnHn/<N0.NHA/0?<HkHn?<N XHnN0.NHA/0HnHkN0.NHA/0HnHkNLN^ _TNNVH80.NHE$r&j&S0+N>I(t(T0+N>A p P-HBnBn0.R@=@/p~nx@DU?..HNNHkPHn/< NjHnNg0=nU?..HNN=_0.R@=@S.Sd.0.l\D nWDgXJT^D l^Dgf ngJno =n`Bn0.N7@0+N>A p/0+N>A p/?.<N n0(#(NdHr nA#(0=A n0(#(NdHr nA#)0=AU?.HnN=_U?.HnN=_Hn.HN&.HN@0.N<@0.NH@ n000J@jD@??,?N:XHnN2 N=@`Bn0.NHA/0?< 0.H@d?NHnNrHnHn/<NHnNrHnHn/<N n0(#(NdHr nA#(0nWD& n0(#(NdHr nA#)0nWD n0(#(NdHr nA#)0nWD( n0(#(NdHr nA#(0nWDHN@ n h#(^D.gJHnNrHn?< NzHnHn/<NjHnHnNHnHn/<N`FHnNrHn?< NzHnHn/<NjHnHnNHnHn/<N n hd#(]D.2,ISA n޲h#(^DJkWD4,JSB n޴h#(^DgJHnNrHn?< NzHnHn/<NjHnHnNHnHn/<N`FHnNrHn?< NzHnHn/<NjHnHnNHnHn/<NJnfHnNrHn?<NzHn?<NzHnHn/<NjHnHnNHnHn/<NJ,g~HnNrHn?<NzHnHn/<NjHnHnNHnHn/<N0.NHA/0?<HkHn?<N XHnN`60.NHA/0?<HkHn?<N XHnN`HnNrHn?<NzHn?<NzHn?<NzHnHn/<NjHnHnNHnHn/<N0.NHA/0?<HkHn?<N XHnN0.NHA/0HnHkN0.NHA/0HnHkNLN^ _TNNVzH nCp"Q=nz/p>.@m&=@0.NHC3RnQ.=||/0.zS@r>Am=A0.NHA=p0.NHA20n0.R@NHApo60.NH2.RA&0NHAC30`$0.NHC30.R@=@RnQV.0.NHC30.nzlFB.=nz=|/p>.z@m&=@0.NHA=p0.NH&0.NHA200Ap0.n@H=A~0.~n ]DHN@J.g=n ~0.nn~=@~0.~n o&J.g0.~n H=@~`=n ~/0.>.@n4=@|DG0.|NHC3~0.~n=@~Sn|Q.0.R@=@RnQ.J.gA"np"QLN^ _O NNVH8Hnt/-.m<<NHz`Hn?.?< HnHnHnN 0.NHE$r&j&S0+N>I(t(T0*jH=@=n0.D@Hn=@/p>,@m=@0.N4AHpHn?<NBU?.B'N=_UHn0._]@??.?<?.BgU?. j PHhPHn/< NjHnNVDHNNHnN0.N4A HpHn?<NBU?.<N=_0.^@??.?<?.BgU?.HkPHn/< NjHnNVDHNNHnN?.HlHn/<NjHnNgHzHn?<NB|`HzvHn?<NBUHn0H2.@??.Hn0.n=@RnQ`./.s?./-x/-tNLN^ _TNMonaco -NVH8Hnt/-.m<<NHztHn?.쨇Jnf*HnNrHnBgNzHn _?=| `=| ?.쨊HnHnHnN 0. NHE$r&j&S0+N>I(t(TJnf:U?.U0*jH?0.?NzNr=_=n`=n0*jH=@/p>@m^=@Jn^D?.HkPHn/< &NjHnNVDg 0.N4A HpHn?<NB?.HlHn/<NjHnNVDJn^DgI(t(TJk^DHN@?< HnHnHnN 0.D@Hn=@0.H=@0*j2.IA=@0.nH=@0.ll=l0.n=@0*jH=@0.D@Hn=@HnNrHnBgNzHn _?0.Hn=@0+N4A HpHn?<NBUHn0H2.̒@??.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHnNHnNrHn _?=n/p>,@m=@=|=|=|F0.ΐn=@0.n=@0.̐nS@=@0.nR@=@0.H=@HmHn0.nn??.0.n??.Bg?<Bg?<Bg?<?<HnNHm䨝J,gLHn?.?.0.n??.Bg?<Bg?<Bg?<?<HnN0.nn=@Hm쨝J,gLHn0.n??.?.?.Bg?<Bg?<Bg?<?<HnN0.nn=@Hn?.?.?.?.Bg?<Bg?<Bg?<?<HnN.HN@J.g&=k0.R@=@0.X@=@=|` =k0.Y@=@0.S@=@Bn0.N&0.N@pAm00=@0.N&0.N@pA00=@0.n2,RAAf.0.R@2.SA4.nUB4,SBHA=@`vJnWDJnWDg0.R@=@`R0.lWD2.lWDg0.R@=@`& nWD nWDg 0.R@=@Hn0.S@??.0.R@??.?I(t(TJk^DHN@?< HnHnHnN 0.D@Hn=@0.H=@0*j2.IA=@0.nH=@0.Tl=T0.n=@0*jH=@=|Hn0.Ɛn??.0.n?0.R@?Bg?<Bg?<BgBg?<HnN.HN@HnNrHnBgNzHn?<NzHn _?0.nH=@=|0.n=@0.n=@J.WD.g0.H2*’@=A` 0.H=@J.g=|=|=|`=|=|=|HmHn0.n?0.̐n?0.n?0.n?Bg?.Bg?<BgBg?<HnNHmܨHn0.n?0.Ȑn?0.n?0.n?J,gHBg?.Bg?<BgBg?<HnNJ.f$?.0.n2.HA?Hz Hm쨝Hn0.n?0.ʐn?0.n?0.n?J,gBBg?.Bg?<BgBg?<HnNJ.f?.0.Hn?Hz *HnNrHnBgNzHn _?J.g =k`=k0.Hn=@U?.HnN=_.HN&0.N4@AHp0Hn?<NBJ.g&0.@=@UHn訌0._U@=@`6J.g0.T@=@` 0.nUHn&_HÇ=C?.?.?<" ?.BgU?.HkPHn/< NjHnNVDHNNHnN0.n2.HA=@U.HNNHN&0.N4@AHp0Hn?<NBU?.U.HNNHNN=_J.g&0.@=@UHn訌0._U@=@`6J.g0.T@=@` 0.nUHn&_HÇ=C?.?.?<" ?.BgU?.HkPHn/< NjHnNVDHNNHnNHnNrHn _?HnNrHnHn/<NHnNrHnHn/<NBn/p>@m=@.HN&0.N@0.N@pA00=@U.HNNHN&0.N@0.N@pA00=@0.n2,RAAfD0.NH2.SA4.n4,SBHnC30.R@=@`HnNrHn?.NzHnHnz/<NjHnHnzNHnzHn/<NJnWDJnWDg0.NHC3`n nWD nWDg0.NHC3`80.°lWD2.lWDg0.NHC3J.g 0.R@=@RnQ./p>.@m.=@=|/p>@m=@?.HnHn/<NjHnNWD?.HnHnz/<&NjHnzNWD.g>0.NHA20nl 0.NHA=p=nRnQn.0.NHC30.NHCL3HnNrHn?.NzHnHnz/<NjHnHnzNHnzHn/<NRnQ.ANCp"QHn?.?.?.?.N =|/p>.@m=@0.NHA=p0.NH&A000N4A HpHn?<NBp. @#o&HnHn?<?<#NZHnHn?<NB0.NHA?0HnHn/<NjHnNVD.gFJ.g=n0.n??.¨0.NHAL20ng?.0.NHAL?00.nT@?0.n??<@0.NHA20A??<BgHnN`=n0.nS@??.¨0.NHAL20ng"0.S@?0.NHAL?00.nS@UHn&_?0.n??<@0.NHA?0?<BgHnN`J.g=n0.nS@??.¨0.S@?0.NHAL?00.nS@UHn&_?0.n??<@0.NHA20A??<BgHnN`r=n0.n??.¨?.0.NHAL?00.nT@?0.n??<@0.NHA?0?<BgHnNRnQ.0.Tnp/0nr>Am=A=|/p>@ml=@?.HnHn/<NjHnNf>0.NHA20nl 0.NHA=p=nRnQ.0.NHC30.NHCL3HnNrHn?.NzHnHnz/<NjHnHnzNHnzHn/<NRnQ.ANCp"QHn0n??.?.?.N =n/0nr>Am=A0.NH&A000N4A HpHn?<NBp. @#o&HnHn?<?<#NZHnHn?<NB0.NHA=p0.n??.¨0.NHAL20ng?.0.NHAL?00.nT@?0.n??<@0.NHA?0?<BgHnNRnQ.J.WDHN@J.g /.s?./-x/-tNLN^ _TNMonacoNeitherBothNVH8Hnt/-.m<<NHzRHn?.?< HnHnHnN 0.NHE$r&j&S0+N>I(t(T=|=n0.D@Hn=@?.?.HnHn?<N"XHnNXHzHnNR0+N>AHpHnNRHn쨄=|0.n=@?.?.HnHn?<N"XHnNXHzRHnNRHn?BgN*XHnHnNRHn쨄=|0.n=@?.?.HnHn?<N"XHnNXHz HnNRHn?,BgN*XHnHnNRHn쨄=|0.n=@?.?.HnHn?<N"XHnNXHz HnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _??.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHlNHnNrHn _?=|0.n=@?.?.HnHn?<N"XHnNXHz HnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _??.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHlLNHnNrHn _?=|0.n=@?.?.HnHn?<N"XHnNXHz HnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _??.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHlNHnNrHn _?=|0.n=@?.?.HnHn?< N"XHnNXHz HnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _?Hn0,R@?BgN*XHnHn?<NB?.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHnNUHn0._=@HnNrHn _??.?.Hz HnN:HnHn?<N"XHnNXHnHnNRHz HnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _?Hn0,l?BgN*XHnHn?<NB?.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHnNHnNrHn _?=|0.n=@?.?.HnHn?<N"XHnNXHzHnNRHnHn?<N"XHnNXHnHnNRHztHnNRHnHn?<N"XHnNXHnHnNRHzBHnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _??.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHlNHnNrHn _?=|0.n=@?.?.HnHn?<N"XHnNXHzZHnNRHnHn?<N"XHnNXHnHnNRHz(HnNRHnHn?<N"XHnNXHnHnNRHzHnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _??.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHlVNHnNrHn _?=|0.n=@?.?.HnHn?<N"XHnNXHzHnNRHnHn?<N"XHnNXHnHnNRHzHnNRHnHn?<N"XHnNXHnHnNRHzHnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _??.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHlNHnNrHn _?=|0.n=@?.?.HnHn?<N"XHnNXHzHnNRHnHn?<N"XHnNXHnHnNRHzHnNRHnHn?<N"XHnNXHnHnNRHz^HnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _??.?.?<" ?<BgU?<HkPHn/< NjHnNVDHNNHlNHnNrHn _?=|0.n=@?.?.Hn?<%N"XHzHnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _?0+N>AJ0gHzHn?<NB`Hz Hn?<NB?.?.?<?<BgU?<HkPHn/< NjHnNVDHNNHnNHnNrHn _?=|0.n=@?.?.Hn?<&N"XHzrHnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _?J,gHzHn?<NB`Hz Hn?<NB?.?.?<?<BgU?<HkPHn/< NjHnNVDHNNHnNHnNrHn _?=|0.n=@?.?.Hn?<'N"XHztHnNRHnHn?<NBHnUHn0._=@HnNrHnBgNzHn _?J,gHzHn?<NB`HzHn?<NB?.?.?<?<BgU?<HkPHn/< NjHnNVDHNNHnNHnNrHn _?=|0.n=@/.s?./-x/-tNLN^ _TNChicago: : : : : : :     :   :   :   : : ONOFF: ONOFF: ONOFFNVH80. NHE$r&j&S0+N>I(t(TJkf0. NHA/0N JnoX0. @fHlHn?<NB` @fHlLHn?<NB`| @fHlHn?<NB`` @f*Hn0,R@?BgN*XHnHn?<NB`0 @f,Hn0,l?BgN*XHnHn?<NB` @fHlHn?<NB` @fHlVHn?<NB` @fHlHn?<NB` @fHlHn?<NB` @fF0+N>&0+N>AJ0WDHNC0`B @fJ,WDHN@` @fJ,WDHN@?. HnNrHn?<NzHn?<NzHn?<NzHnNf0. N7@Bk0. NHA/0HnNrHn?<NzHnHkN0. NHA/0?<HkHnN0. NHA/0HnNrHn?<NzHnHkN`HnNrHn?. NzHkPHn/< NjHnHnNHnHkP/< N7|0. NHA/0HnNrHn?<NzHnHkN0. NHA/0HnNrHn?<NzHnHkN`t7|0. NHA/0HnNrHn?<NzHnHkN0. NHA/0HnNrHn?<NzHnHkN?. N LN^ _\NNVH8Hnt/-.m<<NHzHn?.?< HnHnHnN 0.NHE$r&j&S=| =n0.D@Hn=@/p>-媞@m=@0.N>II0 @f2JlfHzHn?<NB`HzHn?<NB` @fHzHn?<NBHnNrHn?<NzHn _??.?.HnHnNrHn _?0.Hn??.?<3?.Bg?,Hl N0.n=@RnQ./.s?./-x/-tNLN^ _TNChicagoGETNVH0$n&j&SBnUHnBgNJg*/.HnNrHn?<NzHnHkN`&/.HnNrHn?<NzHnHkNBnUHn?<NJg/.HnNrHn?<?< NHn?<NzHnHkN/-T?<9/-T?<9/-T?<9/-T?<9/-T?<9/-T?<9/-T?< 9/-P?<9/-P?<9`/.HnNrHn?<?< NHn?<NzHnHkN/-T?<:/-T?<:/-T?<:/-T?<:/-T?<:/-T?<:/-T?< :/-P?<:/-P?<:BnUHn?<NJgJ/.HnNrHn?< NzHn?<NzHnHkN/-T?< 9/-T?< 9`F/.HnNrHn?< NzHn?<NzHnHkN/-T?< :/-T?< :L N^.NuNVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVHn?<?.NHnHnNXHn/. ?<NBN^ _TN_( ,NVH8$n&j&S0+N>I(t(TJTf?-`YHz&NBN`?*?<N LN^.NuKSS0-2NVH8$n&j&S0+N>I(t(T0+N>AJ0g ?+N/.?<HkHn?<N XHnN/.?<HkHn?<N XHnN/.?<HkHn?<N XHnN/.?<HkHn?< N XHnN/.?<HkHn?<N XHnNJ,g(/.?<HkHn?<N XHnN`$/.?<HkHn?<N XHnNBkHnNrHnHkP/< NHnNrHn?<NzHnHn/<NJTWD,gFHnNrHn?<NzHnHn/<NjHnHnNHnHn/<N TfFHnNrHn?<NzHnHn/<NjHnHnNHnHn/<NJlfDHnHn/<NjHmHn/<NjHnHnNHnHn/<N TldHnHn/<NjHmHn/<NjHnHnNHnNrHn?<NzHnHnNHnHn/<N TlFHnNrHn?<NzHnHn/<NjHnHnNHnHn/<N/.HmHn/<NjHmHn/<NjHnHnNHnHn/<NjHnHnNHnHkN/.HnHkN/.HmHn/<NjHmHn/<NjHnHnNHnHkN/.HmHn/<NjHmHn/<NjHnHnNHnHkN/.?< HkHn?< N XHnN?*N 7|/.N B?*NLN^.NuNVH8$n&j&S0+N>I(t(TJlf?-`YHz"NBN` ?*N LN^.NuKSS0-3NVH8$n&j&S0+N>I(t(T0+N>AJ0g ?+N/.?<HkHn?<N XHnN/.?<HkHn?< N XHnN/.?<HkHn?< N XHnN/.?<HkHn?< N XHnN/.?<HkHn?<N XHnNJ,g(/.?<HkHn?<N XHnN`$/.?<HkHn?<N XHnN7|HnNrHnHkP/< NHnNrHn?<NzHn?<NzHnHn/<NJlWD,gFHnNrHn?<NzHnHn/<NjHnHnNHnHn/<N lfFHnNrHn?<NzHnHn/<NjHnHnNHnHn/<NJTWD l]DgDHnHn/<NjHmHn/<NjHnHnNHnHn/<N/.HmHn/<NjHmHn/<NjHnHnNHnHn/<NjHnHnNHnHkN/.HnHkN/.HmHn/<NjHmHn/<NjHnHnNHnHkN/.HmHn/<NjHmHn/<NjHnHnNHnHkN/.?< HkHn?< N XHnN?*N 7|/.N R?*NLN^.NuNVH8$n&j&S0+N>I(t(T/.?<HkHn?<N XHnN/.?<HkHn?<N XHnN7| 7|0,N7@?*N ?*N/.HmHkN/.?< HkHn?<!N XHnN/.HnNrHn?< NzHnHkN/.?<HkHn?<"N XHnN/.HnNrHn?<NzHnHkNLN^.NuNVH8$n&j&S0+N>I(t(T/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNBk0+R@N7@?+HkPHn/< NjHnNVD2+T^Dg0+Tn?*?<N ?*N/.HmHkNHz0+N4A HpN/.?<HkHn?< N XHnN/.HnNrHn?<NzHnHkN7|` /.N JLN^.Nu1NVH8$n&j&S0+N>I(t(T/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNBk0+R@N7@U?+B'NHkPHn/< NjHnNVDU?+<&NHkPHn/< NjHnNVD0+l^Dg0+ln?*N ?*N/.HmHkNHz0+N4AHpNHz0+N4A HpN/.?<HkHn?< N XHnN/.HnNrHn?<NzHnHkN7|` /.N ZLN^.Nu12NVH8$n&j&S0+N>I(t(T/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNBk0+R@N7@U?+B'NHkPHn/< NjHnNVDU?+<&NHkPHn/< NjHnNVD0+l^Dg0+ln?*N ?*N/.HmHkNHz0+N4AHpNHz0+N4A HpN/.?<HkHn?<N XHnN/.HnNrHn?<NzHnHkN7| ` /.N ZLN^.Nu12NVH0$n&j&S/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNHnNrHn?<?<NHnHn/<NHnNrHn?<NzHn?< NzHn?<NzHnHn/<N/.HnHn/<NjHnHn/<NjHnHnNHnHkNHnNrHnHkP/< N kfN/.HnNrHn?< NzHnHkN/.HnNrHn?<NzHnHkN`2/.HnNrHn?<NzHn?< NzHnHkN?*N ?*N7|L N^.NuNVH0$n&j&S/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNHnNrHn?<?<NHnHn/<NHnNrHn?<NzHn?< NzHn?<NzHnHn/<N/.HnHn/<NjHnHn/<NjHnHnNHnHkNHnNrHnHkP/< N kfN/.HnNrHn?< NzHnHkN/.HnNrHn?<NzHnHkN`2/.HnNrHn?< NzHn?<NzHnHkN?*N ?*N7|L N^.NuNVH8$n&j&S0+N>I(t(T0+N>A p P-H/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNBnBn/p>@mF=@?.HkPHn/< NjHnNg=n=n0.R@=@RnQ. nf&0.N7@0.N7@`^ n0(#(NdHr nA#(00N7@ n0(#(NdHr nA#)00N7@Hzx0+N4A HpNHzZ0+N4A HpN/.?<HkHn?<N XHnN7|/.N LN^.Nu12NVH8$n&j&S0+N>I(t(T0+N>A p P-H/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNBn/p>,@m=@/p~nx@DU?..HNNHkPHn/< NjHnNg0=nU?..HNN=_0.R@=@S.Sd.RnQv. nf*0.N7@0.@N7@`b n0(#(NdHr nA#(00N7@ n0(#(NdHr nA#)0A0N7@U?+HnN=_U?+HnN=_Hz8.HN&0.N4@AHp0NHzU.HNNHN&0.N4@AHp0NHz.HN&0.N4@AHp0NHzU.HNNHN&0.N4@AHp0N/.?<HkHn?<N XHnN7|/.N LN^.Nu1234NVH8$n&j&S0+N>I(t(T/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNBk/p>@m@=@?.HkPHn/< NjHnNg0.N7@RnQ.JkfP/0~@nB=@DG?.HlHn/<NjHnNg0.N7@SnQ.Jko>Bk7|/.N /.?<HkHn?<N XHnN/.N LN^.NuNVH8$n&j&S0+N>I(t(T/.?<HkHn?<N XHnN/.?<HkHn?<N XHnNBk/p>,@m=@/p~mp@U?..HNNHkPHn/< NjHnNg*U?..HNN0N7@R.Sd.RnQ~.Jkf^/0,~@nN=@DG?.HlHn/<NjHnNgU?.<N0N7@SnQ.Jko4BkBk/.?<HkHn?<N XHnN/.N LN^.NuNVH8$n &j&S0+N>I(t(T/. HnNrHn?<?<NHnHkNBkJTWD k VDg/. ?<HkHn?<N XHnN/. ?<HkHn?<N XHnN7| 7|/. ?<HkHn?<N XHnN/. ?<HkHn?<N XHnN/. HnNrHn?<NzHnHkN`0+N>A p/0+N>A p/N nfU?+HnN=_0+N>A p/0+N>A p/.HN?.??<?,NU?+HnN=_0+N>A p/0+N>A p/.HN?.??,?<N0N7@7|Bk0N4Hn?<&N XHnA Hp0?<2NB/. ?<Hk0N4A HpN/. HnNrHn?<NzHn?< NzHnHkN k f/. ?<HkHn?< N XHnN/. ?<HkHn?<N XHnNBkHnNrHn?NzHnHkP/< N?*?<N ?*N`/. ?<HkHn?<N XHnN/. ?<HkHn?<N XHnNHnNrHn?<NzHnHkP/< N?*N ?*NJnf(/. ?<HkHn?<N XHnN`$/. ?<HkHn?<$N XHnN7|7|LN^ _\NNVH8$n &j&S0+N>I(t(T/. ?<HkHn?<N XHnN/. ?<HkHn?<N XHnN0+N>A p/0+N>A p/N 0. @g @f(=lHn?<N XHnHn?<NBHn?<N XHnHn?<NB nf$Hn?<N XHnHn?<NB` Hn?<#N XHnHn?<NB/p>@m=@?.HkPHn/< NjHnNg\0+N>A p/0+N>A p/<?,?.?.0,R@n?N=|RnQ~.` @f`Hn?<N XHnHn?<NBHn?<N XHnHn?<NBHn?<N XHnHn?<NB`B/p>@m=@?.HkPHn/< NjHnNVD2.nVDgN0+N>A p/0+N>A p/<?,?.?<?,NRnQz.0+N>A p/0+N>A p/<?,?.?,?<NHn?<N XHnHn?<NBHn?<N XHnHn?<NBHn?<N XHnHn?<NB0,N4HnA Hp?<2NB0,N4HnAHp?<2NBU?,<N0N7@0+N7@BkHnNrHn?+NzHnHkP/< N?*N ?*N/. ?<Hk0,N4A HpN/. ?<HkHnN/. HnNrHn?<?<NHnHkN/. HnNrHn?<NzHn?< NzHnHkN7|7|BkLN^ _\NNVH8$n &j&S0+N>I(t(T/. ?<HkHn?<N XHnN/. ?<HkHn?<N XHnNBn/p>@m=@0.nfFHnNrHn?.NzHkPHn/< NjHnHnNHnHkP/< N?.HkPHn/< NjHnNgP0.R@=@HnNrHn?.NzHkpHn/< NjHnHnNHnHkp/< NRnQ:.0.nlLU?<?N=_?.HkPHn/< NjHnNf?.HkpHn/< NjHnNfHnNrHn?.NzHkPHn/< NjHnHnNHnHkP/< NHnNrHn?.NzHkpHn/< NjHnHnNHnHkp/< N0.R@=@`^U?<?<N0 @fFHnNrHn?.NzHkpHn/< NjHnHnNHnHkp/< N` nf/. ?I(t(T0+N>A p P-H nf n h#(f ?<` n0(#(S@"n3@#( n0(#(NdHr nA#(00N<& n0(#(NdHr nA#)00NH@ n0(#(NdHr nA#(00N<( n0(#(NdHr nA#)00NH@ nA00@J@jD@"nC30` nf n hd#(WD n2(#(I4SBԲBWDJk^D4SB nh#(WDg ?<`@0+N>A p/0+N>A p/?+B'NHnNrHn n0(#(NdHr nA#(0?NzHn n0(#(NdHr nA#)0?NzHnHkP/< N?*N ?*?<N LN^ _\NNVH8$n &j&S0+N>I(t(T0+N>A p P-H nf: n h#(f ?<`U n0(#(NdHr nA#(0?HnN=_U n0(#(NdHr nA#)0?HnN=_ n0(#(S@"n3@#(.HN&.HN@0.N<@0.NH@.HN(.HN@0.N<@0.NH@ n00@J@jD@"n30` nf n hd#(WD2,ISA nh#(WDJk^D4,JSB nh#(WDg ?<`@0+N>A p/0+N>A p/?+B'NHnNrHn n0(#(NdHr nA#(0?NzHn n0(#(NdHr nA#)0?NzHnHkP/< N?*N ?*N LN^ _\NNVH8$n&j&S0+N>I(t(T0+N>A p P-HHnNrHnHkP/< NB. Tl/.BgN `J,f/.N `tJ.flU?<?<N=_0. @f/.?<N |`4 @fr lod0+N>A p/0+N>A p/Bg<NHn n0(#(NdHr nA#(00N<& n0(#(NdHr nA#)00NH@ nA000J@jD@??,?,N2XHnN2 N=@ nPo~HnNrHn n0(#(NdHr nA#(0?NzHn n0(#(NdHr nA#)0?NzHnHkP/< N/.N |` @f lo0+N>A p/0+N>A p/Bg<NU n0(#(NdHr nA#(0?HnN=_U n0(#(NdHr nA#)0?HnN=_Hn.HN&.HN@0.N<@0.NH@ n000J@jD@??,?N:XHnN2 N=@ nPo~HnNrHn n0(#(NdHr nA#(0?NzHn n0(#(NdHr nA#)0?NzHnHkP/< N/.N |`LN^.NuNVH $nHnt/.sJg/*ШBHj(` j P0( @fYHzN%_`v @f`j @f`^ @f`R @f`F @f`: @f`. @f`" @f` @ f` @ fJg?*N:/*HmV?*NB/.sLN^.NuKSS0-2NVH8$n &j&S0+N>I(t(T0+N>A p P-H0. @f/. N ` @f |` @f/. N ` @f/. N Z` @f/. BgN ` @f/. N j` @f/. ?<N ` @f/. ?<N `l @ f/. BgN `V @ f/. ?<N `> @ f/. ?I(t(T0+N>A p P-H0. @f/. N ` @f |` @f/. N ` @f/. N J` @f/. BgN ` @f/. N r` @f/. N z` @f/. N b`l @ f/. BgN `V @ f/. ?<N `> @ f/. ?I(t(T0. @fZ kfDHnNrHn?+NzHn?+NzHnHkP/< N/. ?A p/0+N>A p/?N /. N J` @f ?*N LN^ _\NNVH8$n &j&S0+N>I(t(T0. @f( kf/. ?<N ` /. N Z`l @fT kf>0+N>A p/0+N>A p/?,N /. N Z` @f ?*N LN^ _\NNVH8$n &j&S0+N>I(t(T0. @f/. N kf/. N `=k no nf =k`=kHnNrHn?+NzHnHkP/< N/. ?<Hk0.N4A HpN/. HnNrHn?<NzHn?<NzHnHkN/. HnNrHn?<NzHn?< NzHnHkN?*N `v @f^ kfH0+N>A p/0+N>A p/?N /. N J` /. N ` @f ?*N LN^ _\NNVH8$n &j&S0+N>I(t(T0. @f/. N Y0+H//< .  f/. N `U?+HnN=_U.HNNHN@J.WD2+ UD .WDY4+H//<&( .  WDg(U.HNNHN@U?..HNN0N7@HnNrHn?+NzHnHkP/< N/. ?<Hk.HN&0.N4@AHp0N/. HnNrHn?<NzHn?<NzHnHkN/. HnNrHn?<NzHn?< NzHnHkN?*N `x @f` kfJ0+N>A p/0+N>A p/?,N /. N Z` /. N ` @f ?*N LN^ _\NNVH8$n &j&SHnNrHn?+NzHkPHn/< NjHnHnNHnHkP/< N0. @g @fHnNrHn?+NzHkPHn/< NjHnHnNHnHkP/< N nf&0+N>I(t(T0+N>A p/0+N>A p/?+N /0+>@m=@0.R@?HkPHn/< NjHnNgJHnNrHn?.NzHkPHn/< NjHnHnNHnHkP/< N`FHnNrHn?.NzHkPHn/< NjHnHnNHnHkP/< NRnQH./. N j` @f?*?<N LN^ _\NNVH8$n &j&S0. @g @fHnNrHnU?+B'NNzHnU?+<NNzHkPHn/< NjHnHnNHnHkP/< N nfb0+N>I(t(T0+N>A p/0+N>A p/?+N /0+>,@m=@/p~m@U?..HNN=_0.R@?HkPHn/< NjHnNgJHnNrHn?.NzHkPHn/< NjHnHnNHnHkP/< N`FHnNrHn?.NzHkPHn/< NjHnHnNHnHkP/< NR.Sd(.RnQ./. N r` @f ?*N LN^ _\NNVH0$n &j&S0. @g @fHnNrHnU?+B'NNzHnU?+<NNzHkPHn/< NjHnHnNHnHkP/< N nf>0+N>A p/0+N>A p/?+N /. N z` @f ?*N L N^ _\NNVH8$n &j&S0+N>I(t(T0. @g @f*Jkf nf/. N `FHnNrHn?+NzHkPHn/< NjHnHnNHnHkP/< N7|/. HnNrHn?<NzHnHkN/. HnNrHn?<NzHnHkN?*N `n0+lgZ m/Q0+N>A p/?+N?+B'N "0+N>A p/NHmQ/. N JLN^ _\NNVH0$n &j&S0. @f/. N J` @f ?*BgN L N^ _\NNVH8$n &j&S0+N>I(t(T0. @fJkf /. N JkWDJT^Dg<0+N>A p/0+N>A p/?N Tf&/. HnNrHn?<NzHnHkN Tl/. BgN ` /. N J` @fJkf /. N JkWDJT^Dg<0+N>A p/0+N>A p/?N /. ?<HkHn?<N XHnN/. ?<HkHn?<N XHnN/. N J` @fJkf?*?<N LN^ _\NNVH8$n &j&S0+N>II?+N/,*N*/,.N* j P-H n0( @f/. ?.N ` @f/. ?.N ` @f/. ?.N ` @f/. ?.N ` @f/. ?.N ` @f/. ?.N ` @f/. ?.N `v @f/. ?.N `^ @f/. ?.N 2`F @ f/. ?.N :`. @ f/. ?.N "` @ f/. ?.N */,.N2/,*N2LN^ _\NNVH8 nl0.NHE$r&j&S0+N>I(t(TJ*f n<nU?./.HnHnN =_ nm no0.@=@=k`=k0. @f0,S@2.nH/HnN"/<HnN"HnHn?<2.H/HnN"HnHn?</<HnN"HnHn?<H/HnN"HnHn?<0.nU@H/HnN"HnHn?<HnN2 RN=@ nl=|0.lo=l0,R@n=@`B @fBnBn`. @f=l=l` @f=|=|0+N>A p/0+N>A p/<?.?.?.?.N?.N ` kf0.NHA/0N Jn of noD nf =k`=k0.N4A HpHn?<NB`NU?.HnN=_.HN&0.N4@AHp0Hn?<NB0.N7@0.NHA/0?<HkHnN0.NHA/0HnNrHn?<NzHn?<NzHnHkN0.NHA/0HnNrHn?<NzHn?< NzHnHkN?.N 7|`0.NHA/0N LN^ _O NNVH8 nl0.NHE$r&j&S0+N>I(t(T0@nmvU?./.HnHnN =_ nmF not0.@=@U?+HnN=_=|?.HnNrHn?<NzHn?<NzHn?<NzHnNVDHN@`dU?+HnN=_=|?.HnNrHn?<NzHn?<NzHn?<NzHnNVDHN@J.f`0. @f0.S@=@0.nHn2,SA2.nH/HnN"H/HnN"HnHn?<HnN2 RN=@ nl=|0.lo=l0,R@n=@`Z @g @fBnBn`> @g @f=l=l` @g @f=|=|0+N>A p/0+N>A p/.HN?.?.?.?.N?.N `P kf0.NHA/0N Jn o 0.N7@U?.HnN=_0.NHA/0?<Hk.HN&0.N4@AHp0N0.NHA/0HnNrHn?<NzHn?<NzHnHkN0.NHA/0HnNrHn?<NzHn?< NzHnHkN?.N 7|`0.NHA/0N LN^ _O NNVH80. NHE$r&j&S0+N>I(t(TJkf0. NHA/0N Jno0. N7@Bk0. NHA/0HnNrHn?<NzHnHkN0. NHA/0?<Hk0. N4A HpN0. NHA/0HnNrHn?<NzHnHkN`t7|0. NHA/0HnNrHn?<NzHnHkN0. NHA/0HnNrHn?<NzHnHkN?. ?<N LN^ _\NNVH 0.NHE$r$j$R nlJn oJHnNrHn?.NzHjPHn/< NjHnHnNHnHjP/< N`FHnNrHn?.NzHjPHn/< NjHnHnNHnHjP/< N0* @f?.N ` @f?.N ` @g @f?.?.?. /.N J` @g @f?.?.?. /.N B`` @f$0.NHA/0?.N `6 @ f?.?.?. N R` @ f?.?.?. N LN^ _O NNVH 0.NHE$r$j$R0.N>&0. NC300.NHA/0N LN^ _O NNVH 0.NHE$rJgV/*N* j P0 @f?.?.?. /.N Z` @f?.?.?. /.N b/*N2LN^ _O NNVH $n p* @fJ.g =|`=|`B @fJ.g =|`Bn` @fJ.g =|`Bn/. ?.NLN^ _\NNVH0 nC""""0. NHE$rJgJ*fY0.H//< . J^DHN@-nHnШq/*HnШ~/*N*Y j//< .-_-nY/*N" .П-@B.B.| VD mWDg$Y. -П\DHN@&nU/.Hk JglHnN2?. N:?< mf/..HNN UsJgp+J@oHnȩr0.ʐnJ@jD@ @^D2.ȒnJAjDA A^Dg/.?Bn@B.B0.NYB&NC$#0/.0?<HnDHn0?<N XHn0N/.0?<HnDHn0?<N XHn0N/.0?<HnDHn0?<N XHn0N/.0HnNrHn?<?<NHn?<NzHn?<NzHnHnDNUHn>0.NA$/0/<N=_40.NHnNrHnA$ p PHhP/< N?-`YHzdNBN?-`B'N"/.0N LN^NuABp?.N?<Hn?<&N XHnNbN^ _TNNVH0BnUHn?<NHN@J.g,0.N>AJpWDHN@J.WD.gJnfJ.g =|`=| nfB. nWD m]D.g ng8Hn?<N$nJ.gHz0.N>AHpN0.N>A p P"n0<"Q2Hn?<N XHnHn?<NB ng*HnHj?<PNBHzHjL?<PNB/.N`BRBjBj5| HzHj?<PNBB*B*B*B*B*HzHj?<PNBHzHjV?<PNBHzHj?<PNBHzHj?<PNBHzHjL?<PNBHz|Hj?<PNB/.NHn?<%N XHnHn?<NBJ.gUHn?<P?<?<Hn?<N XHnHnHn?<N XHnHnHn?<N"XHnNXHnHnHn?<N"XHnNXHnHnHn?<N"XHnNXHnHn?<N XHnN=_`RUHn?<PBg?<Hn?<N XHnHnHzbHz`Hz^Hz\Hn?<N XHnN=_NJ.g/.NJ.gY0.H//< .  gBRY0.H//< .  gBjY0.H//< .  g/p>*@m=@/p>@mf=@/p~mL@.HN&0.N@0.N@AB00R.Sd.RnQ.RnQ.0-R@;@=m0.N>GGJ*g /+*N-| .d .R-@Y/.N'_* n"k*"Q0<"Q2/EE|0.N5@|?.N/**N*&j*&S?<Hn?<N XHnNb0-`NHY&0.NAzHp?<HnHzNC#0HnBg?<0?<?<0?-`HnB'<<B'NjHnBgBg?<?<訧?-`HnN?-`Hn?< N XHnN=|=|B.0.N=@HnNrHnHnT/< NHnNrHnHnt/< NHnNrHnHn4/< N0-`NHA/0?< HmRN0.NYB&NC$#0UHn0.NA$/0/<N=_?.B'N " j*/N0-`NHA/0?<N  ng?.?<?<BN j?-`B'N"/**N2L N^ _TN1*B1 2 3 4 5 6 7 8 9 10 11 12,S13 14 15,T-16Z PNVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVHBn nBPUHn?<NJgV0.N>A po4 n0R@"n2 n0N&0.N"n0`Bn n"n 2UHn?<NJgV0.N>A pf4 n 0R@"n 2 n 0N&0.N"n0` nJPf n "n2LN^ _O NNV H8/.Hn?<Hn?<N zXHnN:BHn N"Hn NB/p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>+@m$=@0.NHAVBpRnQ./**N2RnQ. n 0(R@H/Hn N"/<HnN"HnHn ?<Hn N2 N=@Bn$n /p>.@mt=@J-f`0.Nr n00N>GG/+*N* k*-P/p n>(@m=@J-f0.NH nAVJpf(0.R@=@0.NH"nCV3/0.R@>.@mL=@0.Nr n00N>A/0N*0.Nr n00N>A p-P0.nf0.R@=@`=|/0. n>(@mz=@/p~m`@Bn/p>@m=@(n0.N&0.NrA00N@pA00=@(n.HN&0.N@0.NrA00N@pA00=@Jn^DJn^Dg0.ؐnJ@jD@=@`=n0.n=@RnQ.0*S@Ґn=@Hn ?.?*?N:XHnHn ?< m 0.NH nAV=p .f 0.D@=@0.NH nAVJpf"0.NH"nCV3`0.NH nAV20JAjDA=A0.J@jD@ng|0.NH nAV20H=A/p>.@mD=@0.Nr n00N>A/0N*0.Nr n00N>A p-P/p n>(@m=@0.NH nAV20JAjDAnf`0.NH nAVJpl&0.NH2.DA"nCV3`0.NH"nCV3RnQt.0.Nr n00N>A/0N2RnQ.R.Sd.RnQ.0.Nr n00N>A/0N2RnQ.0.S@ nnd2. nH/Hn N"H/HnN"HnHn ?<Hn NBRnQ./+*N2RnQ.J-f ?.NjHn?<N zXHnN:BHn N"Hn NBHzHnHnHn ?<Hn Bg?<N:XHnN?.Hn?<N zXHnNb/p>.@m:=@0.NHABp0.NHA2BpRnQ./p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>+@mr=@0.NHAV20JAjDA0NH&0.NHAV20JAjDA0NHA20RAC30RnQ./**N2RnQ2./p>.@m=@0.NHAJpotHnNrHnHn/< NBn/p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>+@mv=@0.NHAV20JAjDAnfFHnNrHn?.NzHnHn/< NjHnHnNHnHn/< NRnQ./**N2RnQ../p>.@m:=@?.HnHn/< NjHnNg 0.R@=@RnQ.0.NH&0.NC230RnQn.BnBn=n/p>.@m=@0.NHA220n^D&0.NHA220nWD(0.NHA20n^Dg80.NHA2=p0.NHA=p=nRnQ^.Jno0.NHA2Bp0.NHABp0.R@=@?.NjHzHn?.BgN*XHnNHzHn?.BgN*XHnNHzHn?.BgN*XHnNHzpHnHnHn ?<Hn Bg?<N:XHnN?.Hn?<N zXHnNbBn/p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>+@m=@0.NHAV20JAjDAnfj0.NHAVJpo B.`|U?..HN&0.N4@pA00?Nr=_RnQn./**N2RnQ ./p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>+@m~=@0.NHAV20JAjDAnfN0.NHAVJpo B.`|HzjHn?.BgN*XHnNHzPHn?.BgN*XHnNHz6.HN&0.N4@AHp0NHzU.HNNHN&0.N4@AHp0NHzHn.HN&0.N4@pA002.ޒ@?Hz|NXHnN?.Hn?<N zXHnNbRnQ./**N2RnQ&.N"JnWD-gJLN^ _ON1123412345 NV H8/.Hn?<Hn?<N zXHnN:BHn N"Hn NB/p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>@m"=@0.NAB0RnQ./**N2RnQ. n 0(R@H/Hn N"/<HnN"HnHn ?<Hn N2 N=@Bn$n /p>.@m=@J-f0.Nr n00N>GG/+*N* k*-P/p n>@m=@J-f0.Nr nA0JAf20.R@=@0.N&0.N"nC0/0.R@>.@m=@0.Nr n00N>A/0N*0.Nr n00N>A p-P0.nf0.R@=@`=|/0. n>@m=@Bn/p~m@/p>*@m=@(n.HN&0.NH(AV00@N@0.N@pA00=@(n.HN&0.NH(AV00@N@0.N@pA00=@Jn^DJn^Dg0.ؐnJ@jD@=@`=n0.n=@RnQ.R.Sd.0*H2*SAn=@Hn ?.?*?*N2XHnHn ?< m0.Nr nA0=A0.Nr nA0JAf,0.N&0.N"nC0`>0.Nr nA0=A0.ng/p>.@m=@0.Nr n00N>A/0N*0.Nr n00N>A p-P/p n>@mV=@0.Nr nA0nf(0.N&0.N"nC0RnQ.0.Nr n00N>A/0N2RnQ.RnQ.0.Nr n00N>A/0N2RnQ.0.S@ nnd2. nH/Hn N"H/HnN"HnHn ?<Hn NBRnQV./+*N2RnQ.J-f?.NjHn?<N zXHnN:BHn N"Hn NBHzHnHnHn ?<Hn Bg?<N:XHnN?.Hn?<N zXHnNb/p>.@m:=@0.NHABp0.NHA2BpRnQ./p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>@mf=@0.NrA00NH&0.NrA00NHA20RAC30RnQ./**N2RnQ@./p>.@m=@0.NHAJpolHnNrHnHn/< NBn/p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>@mp=@0.NrA0nfFHnNrHn?.NzHnHn/< NjHnHnNHnHn/< NRnQ./**N2RnQ6./p>.@m:=@?.HnHn/< NjHnNg 0.R@=@RnQ.0.NH&0.NC230RnQv.BnBn=n/p>.@m=@0.NHA220n^D&0.NHA220nWD(0.NHA20n^Dg80.NHA2=p0.NHA=p=nRnQ^.Jno0.NHA2Bp0.NHABp0.R@=@?.NjHzHn?.BgN*XHnNHzHn?.BgN*XHnNHzHn?.BgN*XHnNHz~HnHnHn ?<Hn Bg?<N:XHnN?.Hn?<N zXHnNb/p>.@m=@0.Nr n00N>EE/**N* j*-P&n/p>@m=@0.NrA0nftHzHn?.BgN*XHnNHzHn?.BgN*XHnNHz0.N4A HpN?.Hn?<N zXHnNbRnQj./**N2RnQ.N"JnWD-g.@mb=@J-fN0.Nr n00N>EE/**N* j*-P&n0.S=@0.k=@0.noHzHn?<NB`HzHn?<NBHzHnNHzHn?.BgN*XHnNHzHn?BgN*XHnNHzpHn?+BgN*XHnNHzVHj N?.Hn?<N zXHnNb/**N20.dH/HnN"0.H/HnN"HnHn?<HnNBRnQ.J-f$n J. f=R=|!`=|"J.f=j=|!`=|"HzHn?.BgN*XHnNHzHn?.BgN*XHnNHzlHn?.N zXHnNHzTHn?.N zXHnN?.Hn?< N zXHnNbL N^ _ON *123451234NVH0 n Cp"Q?.NjHn?<N zXHnN:BHnN"HnNB?.Hn?<#N zXHnNbJ.g/p>.@m=@J-f0.NrA00N>EE/**N* j*-P&n/p>@m=@HzHn?.BgN*XHnNHzrHn?.BgN*XHnNHzX0.N4A HpN?.Hn?<%N zXHnNbRnQ./**N20.dH/HnN"0.H/HnN"HnHn?<HnNB`$n/p>@m=@J-fHzHn?.BgN*XHnNHz0.N4A HpN?.Hn?<'N zXHnNb0.dH/HnN"0H/HnN"HnHn?<HnNBRnQd.RnQ,.L N^ _ON12312NVH0 n Cp"Q?.NjHn?<N zXHnN:BHnN"HnNB?.Hn?<$N zXHnNbJ.g2/p>.@m"=@J-f60.NrA00N>EE/**N* j*-P&n/p>+@m=@HzHn?.BgN*XHnNHzHn?.BgN*XHnNHz0.N4AHpNHz~0.N4A HpN?.Hn?<&N zXHnNbRnQh./**N20.dH/HnN"0.H/HnN"HnHn?<HnNB`$n/p>*@m=@J-fHzHn?.BgN*XHnNHz0.N4AHpNHz0.N4A HpN?.Hn?<(N zXHnNb0.dH/HnN"0*H/HnN"HnHn?<HnNBRnQB.RnQ.L N^ _ON1234123NVH0 n Cp"Qp.N>EE/**N* j*-P n"n0<"Q2/**N2$n/p>.@m=@0.NrA00N>GG/+*N* k*-PHnNrHnHn/<N/p>@m=@|/p n>@mP=@0.N4&0.N4A Hp nA Hp0NJfB.RnQ.J.gFHnNrHn?.NzHnHn/<NjHnHnNHnHn/<NRnQH./0~@n=@DG?.HnHn/<NjHnNgb0S@4/0.>@mL=@0.N42.RA&0N4A HpA Hp0?<2NBRnQ.SnQx.HnNrHnHn/<N/p>*@m=@|/p n>(@m=@0.N4&0.N4AHp nAHp0NJfD0.N4&0.N4A Hp nA Hp0NJfB.RnQz.J.gFHnNrHn?.NzHnHn/<NjHnHnNHnHn/<NRnQ./0*~@n=@DG?.HnHn/<NjHnNg0*S@5@/0.>*@m=@/p~mx@.HN&0.N4@.HN2.RA(0N4@AHp@AHp0?<2NBR.Sd.RnQv.SnQ,./+*N2RnQ.$n/p>.@m=@0.NrA00N>GG/+*N* k*-P/p>@m=@/p n>@mr=@0.N4&0.N4A Hp nA Hp0NJf(0.N&0.N"nC0RnQ.RnQx./p>*@m=@/p n>(@m=@0.N4&0.N4AHp nAHp0NJf\0.N4&0.N4A Hp nA Hp0NJf0.NH"nCV3RnQb.RnQB./+*N2RnQF.L N^ _O NNVH0$n0*R@H/HnN"/<HnN"HnHn?<HnN2 N=@/p n>(@m=@=|/p~mX@/p n>(@m6=@Bn/p>@m=@&n0.N&0.NrA00N@pA00=@&n.HN&0.N@0.NrA00N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=n0.n=@RnQ.0.nl"=n=n .f 0.D@=@RnQ.R.Sd.0.NH2*SAҒn"n 30.NH"n3RnQV.L N^ _ONNVH0$n0*R@H/HnN"/<HnN"HnHn?<HnN2 N=@/p n>@m=@=|/p n>@mT=@Bn/p~m@/p>*@m=@&n.HN&0.NH(AV00@N@0.N@pA00=@&n.HN&0.NH(AV00@N@0.N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=n0.n=@RnQ.R.Sd.0.nl=n=nRnQ.0.NH2*I4*SB’n"n 30.NH"n3RnQP.L N^ _ONNV>H nCp"Q nCp"Q nCtp"Q/. Hnp?<0."NrAs00N>A/0N*0."NrAs00N>A p-PlHz0."NrAs00N>AHpN0. NrAs00N>A/0N*0. NrAs00N>A p-PhHzL0. NrAs00N>AHpN$n$Bn`J.gt nl=PZ=|)X/p>.Z@mR=@fHnH0.fNHA?0?*?*N2XHnpHnH?< m 0.`R@=@`RnfQ.`p nl=hZ=|*X/p>.Z@mP=@fHnH0.fNHA?0?*?N:XHnpHnH?< m 0.`R@=@`RnfQ.0."N(&0. NH@0.`H/HnHN"0.ZH/Hn>N"Hn>HnH?<HnHN2 N"n30J. gB?.(NjHzHnR?."BgN*XHnRNHzHnR?. BgN*XHnRNHztHnR0."N(&0. NH@ n000H/HnHN"/< Hn>N"Hn>HnH?<HnHBg?<N:XHnRNHzHnRHnpHnH?<HnHBg?<N:XHnRNHzHnR?.XN zXHnRN?.(HnR?<+N zXHnRNb/p>.Z@m=@f=|`/p>.Z@mJ=@d0.dNHA20n`o 0.dNHA=p`=ndbRndQ.0.bNHC30.bNHA=pdHzHnR?.fBgN*XHnRNHzHnR0.fdH/HnHN"0.ZH/Hn>N"Hn>HnH?<HnH?<?<N:XHnRNHzHnR?."BgN*XHnRNHzHnR?.bBgN*XHnRNJ.g|Hz^HnRHnH?.`?*?*N2XHnH?<?<N:XHnRNHz(0.bN4 nlA HpN?.(HnR?<,N zXHnRNb`@HzHnRHnH?.`?*?N:XHnH?<?<N:XHnRNJndo B.S`0.dD@=@d|S0.bN4 nlAHpHnT?<NB.SHN&0.dN4@ nhAHp0HnT?<NBp.T=@^p.T=@\HzHnTNHz0.bN4 nlA HpNHzHnR0.\n^?HzNXHnRN?.(HnR?<-N zXHnRNbHzHnR?. BgN*XHnRNHzHnR?.dBgN*XHnRNJ.gDHzx0.dN4 nlA HpN?.(HnR?<.N zXHnRNb`Hz8HnTNHz.U.SHNNHN&0.dN4@ nhAHp0NHzHnR0.^n\?HzNXHnRN?.(HnR?</N zXHnRNbRnfQ.0."NrAs00N>A/0N20. NrAs00N>A/0N2LN^ _O"N56123471245363678 123345 NVH nCp"Q/. Hn?<?.NjHn?<N zXHnN:BHnN"HnNBJ. g:Hz@Hn?<3N zXHnNHz(Hn?<1N zXHnN`6Hz Hn?<2N zXHnNHzHn?<0N zXHnNJ.g:HzHn?<)N zXHnN?.Hn?<4N zXHnNb`6HzHn?<*N zXHnN?.Hn?<5N zXHnNb0.S@=@J. g0.S@H2.Ԓ@=A/p>.Ԟ@m=@J-f=|/p>.@m=@J. g0.R@=@`=|/0.>.@m=@0.ްngl0.N(&0.NH@ n000ְno:0.N(&0.NH@ n=p0=n=nRnQ.RnQJ.0.NrA00N>EE/**N* j*-PHzHj N0.NrA00N>EE/**N* j*-PHzHj N0.N(&0.NH@"n30HzHn?.BgN*XHnNHz~Hn?.BgN*XHnNHzdHn0.H/HnN"/< HnN"HnHn?<Hn?<?<N:XHnNHzHnHnHn?<Hn?<?<N:XHnN?.Hn?<6N zXHnNb0.NrA00N>EE/**N20.NrA00N>EE/**N20.dH/HnN"0.H/HnN"HnHn?<HnNBRnQ.LN^ _ON121233894567NVH0$n0*R@H/HnN"/<HnN"HnHn?<HnN2 N=@/p>*@m@=@Bn/p>@m=@&n0.NH&AV000N&0.NrA00N@pA00=@&n 0.NH&AV000N&0.NrA00N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=n0.n=@RnQ.0.NH2*SAҒn"n3RnQ.L N^ _ONNVH0$n0*R@H/HnN"/<HnN"HnHn?<HnN2 N=@/p>@m=@Bn/p~mF@/p>*@m(=@&n.HN&0.NH(AV00@N@0.NrA00N@pA00=@&n .HN&0.NH(AV00@N@0.NrA00N@pA00=@Jn^DJn^Dg0.nJ@jD@=@`=n0.n=@RnQ.R.Sd.0.NH2*I4*SB’n"n3RnQ|.L N^ _ONNVH nCp"Q/.Hn?<$n&BnJ.g=RHzHn?<)N zXHnN/p>@mR=@Hn0.NHA?0?*?*N2XHnHn?< m 0.R@=@RnQ.`=jHzHn?<*N zXHnN/p>*@mP=@Hn0.NHA?0?*?N:XHnHn?< m 0.R@=@RnQ.0.N(&0.NH@0.H/HnN"0.H/HnN"HnHn?<HnN2 N"n30J. g?.*NjHzHn?.BgN*XHnNHzHn?.BgN*XHnNHzHn0.dH/HnN"0*H/HnN"HnHn?<HnBg?<N:XHnNHzHnHnHn?<HnBg?<N:XHnN?.*Hn?<7N zXHnNb/p>.@m=@=|/p>.@mJ=@0.NHA20no 0.NHA=p=nRnQ.0.NHC3HzHn?.BgN*XHnNHzHn0.dH/HnN"0.H/HnN"HnHn?<Hn?<?<N:XHnNHzPHn?.BgN*XHnNJ.gxHz.HnHn?.?*?*N2XHn?<?<N:XHnNHz0.N4A HpN?.*Hn?<8N zXHnNb`HzHnHn?.?*?N:XHn?<?<N:XHnNHz0.N4AHpNHzj0.N4A HpN?.*Hn?<9N zXHnNbRnQ.LN^ _O$N77345612435356NVBH0 nCp"Q/.Hn?<..g$nHnB?<N zXHnBN:BHn8N"Hn8NB/p>."@m=@J-f0.NrA00N>GG/+*N* k*-PHzbHk NJ. g0.R@=@`=|/0.>. @m=@J-f 0.ܰng0.NrA00N>GG/+*N* k*-PHzHk NJ. gJ.g/././.HnN `/././.HnN ?.$/././.?.?.HnHnBHnHn8?<Hn8.HN. HN.HNN `J.g/././.HnHnbN `/././.HnHnbN ?.$/.?.?.HnHnbHnHnBHnHn8?<Hn8.HN.HNN 0.NrA00N>GG/+*N20.S@ nd2." H/Hn8N"H/Hn.N"Hn.Hn8?<Hn8NBRnQ.0.NrA00N>GG/+*N2RnQ,.J.gL?.$?."?. HnHnBHnHn8?<Hn8. HN.HNN J. gjJ.g4?.$?."?. ?.Hn/.HnHn8?<Hn8N `0?.$?."?. ?.Hn/.HnHn8?<Hn8N L N^ _ON12NVH $nEHzBHn n h?BgN*XHnNHz"Hn n h?(BgN*XHnN?<Hj2Hn/<NjHnNVD?< Hj2Hn/<&NjHnNVDg n/(HnNrHn?<?<NHn nHhN n/(HnNrHn?<?<NHn?< nHhN n/(HnNrHn?<NzHnBg nHhN`d n/(HnNrHn?<?<NHn nHhN n/(HnNrHn?<?<NHnBg nHhN?< Hj2Hn/<NjHnNVD?< Hj2Hn/<&NjHnNVDg n/(HnNrHn?<?<NHn nHhN n/(HnNrHn?<?<NHn?< nHhN n/(HnNrHn?<NzHnBg nHhN`d n/(HnNrHn?<?<NHn nHhN n/(HnNrHn?<?<NHnBg nHhN?<Hj2Hn/<NjHnNg:HzVHn?<N zXHnNHz>Hn?< N zXHnN`?< Hj2Hn/<NjHnNg:HzHn?<N zXHnNHzHn?< N zXHnN`?< Hj2Hn/<NjHnNg:HzHn?<N zXHnNHzHn?< N zXHnN`6HzvHn?< N zXHnNHz^Hn?< N zXHnN n/(?< nHhHn?< N zXHnNLN^.Nu1276767676NVxHHn?<NHnHnHnxN nl` ?.?.Hnx/.N Hz Hnx?<N zXHnxNHz Hnx?.BgN*XHnxNHz Hnx?<N zXHnxNUHnxN=_YB?<QHnHz N-_B.B.B./.?< HnHnx?<N zXHnxN n h^D n P^Dg./.HnXNrHnX?< NzHnX?<HnN` nJh^D nJP^Dgh n0( nPo./.HnXNrHnX?< NzHnX?<HnN`*/.HnXNrHnX?<NzHnX?<HnN/N nJhWD nJPWDg*/.HnXNrHnX?<?< NHnXHnN nJhWD nJPWDg6/.HnXNrHnX?<NzHnX?<?< NHnXHnN/.?< HnHnx?<PBgN*XHnxN0.H/HnnN"/<HndN"HndHnn?<HnnN* N=@ nl=|/.?<HnHnx?<BgN*XHnxNHz HnxNJWDHnxHnx?< &NXHnxNXHnxHnxNJWDgR/.HnXNrHnX?<NzHnXHnN/.HnXNrHnX?<NzHnX?<HnN`>/.?<HnHnxN/.HnXNrHnX?<NzHnX?<HnN/.HnXNrHnX?<NzHnX?<NzHnXHnN/.HmHnU/.Hn?.NJf?.HnXNrHnX?<?<NHnXNg. nWD?<HnHnX/<&NjHnXNWDg,/.HnXNrHnX?<?<NHnXBgHnNHnXNrHnX?<?<NHnHn8/<NjHn8HnXNHnNrHnHnXNgV/.HnXNrHnX?<?< NHnXHnN/.HnXNrHnX?<NzHnX?<HnN`*/.HnXNrHnX?<?< NHnXHnN`0?.HnXNrHnX?<?< NHnXNg/N ?.HnXNrHnX?<NzHnX?<NzHnXNg. nf~HnnHnn/.?< HnNXHnnNJXHnnHn?<UHnx/.?<HnNXHnxNB=_Hnx/.?< HnNXHnxHnx?<NB?< HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?< HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@?<HnHnX/<NjHnXNVDHN@/.N nf?<Hnx?<N zXHnxNbJ.gJ.g8=|HnxHnx?< NXHnxNXHnxHnx?<NB`0.N@HnHnN:HnHnNRHnHn?<NB`bHzHnNJcRp.NrA0 A'f,HnHn?<p.S@?NZHnHn?<NB|J.gf"n2Hn/.?<NBLN^ _PN NVYBN-_/. ?@m=@0.NH".AҰ-A nJP^D nJhWDg n0R@"n2 n"n3P nHhHn?<NBU/. HnN *=_JnmJ"n3np.n=@HnHn?<?.NZHnHn?<NB0.R@=@0.NH".AҰ-A0.R_DHn nHh?<?.&NZHnHnNJWDHN@J.g nJhfz nHhHn?<NBHnHn0.R@?p.n?NZHnHn?<NBU/. HnN "Jg""n3n n0( nP"n3@0.R@=@J.fRnQ0./.N2L N^ _ONNVH B.Y0.N>A/0HnHnN :-_/./.Hz ?-N BYHz ?-N J-_/././.HnN R$n/.N* n-PBnBn/p>@mL=@0.NH".AҰ-A n0(no n=h=nRnQ.Jno0.R@=@0.NdHC30.NH".AҰ-A"n3n n0(D@"n3@=n0.NH".AҰ-A n0(nWDHN@J.g "n3n0.R@=@0.R^DJ.WDg/p>. @m8=@0.Nd&0.NdH@ABp0RnQ.JnWD2.n WDgl=n 0.N>A/0N*0.N>A p-PY0.N>A/0N"-_BnBnHnHnHnN 2XHnHn?<NBHzRHnNJc U/./.Hn<N =_`BnJnoR0.NH".AҰ-A nJho(0.R@=@0.NdH nC3 n.WDJnWDg> n.f0.R@=@/p>.@mz=@/0.R@>.@mZ=@0.NdH&A000Nd&0.NdH(A00@NdH@0.NdH(A00@Nd(0.NdH*A00PNdH@A00@R@C300.NdH&A000Nd&0.NdH(A00@NdH@0.NdH(A00@Nd(0.NdH*A00PNdH@A00@R@C30RnQ.RnQ.Jnf0.N>A/0N2?. Nj?. HzHnN:Hn?< NjXHnHnNRHnNb?. Nj?. HzHnN:Hn?.BgN*XHnHnNRHzHnNRHn?.BgN*XHnHnNRHzHnNRHn?BgN*XHnHnNRHzxHnNRHn?.BgN*XHnHnNRHnNb/p>. @m|=@0.NdHA=p0.NH".AҰ-A nHhHn?<NB?. Hn n?(?<N*XHzHnNRHn?.?<N*XHnHnNRHzHnNRHn n??<N*XHnHnNRHn n0(D@??<N*XHnHnNRHzfHnNRHnHnNRHnNZU/.HnN *=_JnmN?. Hz,HnN:HnHn?<p.n?NZHnHnNRHzHnNRHnNZ?. NjRnQ.?. NjBn/p>. @m=@/0.R@>. @mx=@0.Nd&0.NdH@A000no:0.Nd&0.NdH@A=p0=n=nRnQ.RnQp.0.nm0.Nd&0.NdH@ABp00.NdHA=p0.NdHA=p0.NH".AҰ-A?. Hn?.?<N*XHzHnNR nHhHnNRHztHnNRHnNZ0.NH".AҰ-A?. nHhNb0.nlT?. NjJ.gx/p>@mj=@0.NH".AҰ-A nHhHn?<NB?. Hn?.?<N*XHzHnNRHn n??<N*XHnHnNRHn n?(?<N*XHnHnNRHn n?(?<N*XHnHnNRHn n?(?<N*XHnHnNRHz4HnNRHnHnNRHnNZU/.HnN *=_JnmB?. HzHnN:HnHn?<p.n?NZHnHnNRHnNZ?. NjRnQ./.N2/.NHnNHnNL8N^ _PN NOISE.SYS STEMS.SYSAnalysis Complete Sentences = Words =  Different words = Stems = :::  ():  <-> ::  NVHBnUHn?<NJg=|?.NHzHn?<N XHnNUHnN=_YB?<RHnHzN-_/.?<HnHn?<N XHnN/.?<HnHn?<N XHnN/.?<HnHn?.BgN*XHnN/.?< HnHn?<dBgN*XHnNHzzHnNJWDHnHn?< &NXHnNXHnHnNJWDgR/.HnNrHn?<NzHnHnN/.HnNrHn?<NzHn?<HnN`>/.?<HnHnN/.HnNrHn?<NzHn?<HnN/.HnNrHn?<NzHn?<NzHnHnN/.HmHnU/.Hn?.NJfR?.HnNrHn?< ?<NHnNg* n WD?< HnHn/<&NjHnNWDg,/.HnNrHn?< ?<NHnBgHnNHnNrHn?< ?<NHnHnd/<NjHndHnNHnDNrHnDHnNgV/.HnNrHn?<?<NHnHnN/.HnNrHn?< NzHn?<HnN`*/.HnNrHn?<?<NHnHnN?.HnNrHn?<NzHn?<NzHnNg` nf@UHn/.?<HnNXHnNB=_UHn/.?< HnNXHnNB=_ ndo=|dHn/.?<HnNXHnHn?<NB?<HnHn/<NjHnNVDHN@?<HnHn/<NjHnNVDHN@?<HnHn/<NjHnNVDHN@?< HnHn/<NjHnNVDHN@/.N nf: m/Q?<Hn?<N XHnNbJ.gJ.g8=|HnHn?< NXHnNXHnHn?<NB`Am@=A0.N HA HpHnNJf0.N=@RnQ.Jnf@ R l80R@40N=@0.N HHnA Hp?<NB0.N=@LN^ _PNNVH Y/< N-_/.N*/.N*$n$RBRBjBjBjHnNrHnHj /<NHnNrHnHj/<N n-PY/.N"-_HnHnN rXHnHn?<NBHzzHnNJc|p. @\fHnHn?<p.S@?NZHnHn?<NBHnHnN rXHnHn?<NBHzHnNJcp. @Sf"U/.HnN z0N=@`v @DfnU/.HnN z0N=@JnoFHnNrHn?.NzHj Hn/<NjHnHnNHnHj /<N` @IfnU/.HnN z0N=@JnoFHnNrHn?.NzHjHn/<NjHnHnNHnHj/<N` @NfUHnNB0N=@Jnn=| jm =|`L0*R@5@0*NA B00*R@5@0*N&0.NC 0`pU/.HnN z0N=@Jnf =|`B jm =|`.0*R@5@0*N&0.NC 0JfR=|=|0.NrA 00N=@Jnf<0.R@N=@0.NrA 00N=@`<0*n5@?.HjHn/<NjHnNf0*n5@0.R@N=@0.joD/.N2/.N2-n LN^.NuNVH /.N*$n$R=|0.jn~0.NrA 0=A?. Hn?.?<N*XHz^HnNRHnNZJno?. Hn?.?<N*XHz0HnNR0.N HA HpHnNRHnNZ?.Hj Hn/<NjHnNg?. HzNZ?.HjHn/<NjHnNg?. HzNZ`t0.R@=@0.NrA 0=A?. HzHnN:HzvHnNRHzlHnNRHn?.?<N*XHnHnNRHnNZ?. Nj0.R@=@`z/.N2LN^ _\N:   D I\N NVH0$n &n?.Nj/p>+@m$=@0.kf?.HzNZ`?.HzNZ?.Hn?.?<N*XHzHnNRHnNZ/p>@m=@0.N &0.N @pA00J@ot?.HzHnN:0.N HA HpHnNRHztHnNRHn0.N &0.N @pA00?BgN*XHnHnNRHz(HnNRHn0.N&0.N H@0.NHA200H/HnN"A^20H/HnN"HnHn?<HnBg?<N:XHnHnNRHzHnNRHn0.N&0.N H@A?00BgN*XHnHnNRHzLHnNRHnNZRnQX.?.NjRnQ.L N^ _O NF : ->:()NVH0$n &n/p>+@mR=@/p>@m8=@0.N&0.N H@ABp0RnQ.RnQ.=|=|=|0.jn0.NrA 0=AJnf*0.R@=@0.NrA 0=A`?.HjHn/<NjHnNfZ0.N&0.N H@0.N(0.N H@A00@nC300.N &0.N @pA00=@0.R@=@`/p>+@mv=@Bn/p>@m@=@0.N&0.N H@0.Ap0=@RnQ.0.NHC^3RnQ.7nL N^ _PNNVH0$n&n BHnN"HnHn?</p>+@m0=@0.NHA^=pJno0.NH2.H/HnN" nHpHn?<HnHn?<HnHn?<HnHn?</p>@m=@0.N&0.N H@A=p0Jno\0.NH2.H/HnN" nHpHn?<HnHn?<HnHn?<HnHn?<RnQl.RnQ.HnHn?<Hn/.?<L N^ _O NNVY/<N-_ n PB nJf"n"`. n-P n PJg n P-P`"n"Q"-n N^.NuNV nJg` n P PJf n/N nB`: n-P n PJg-n n P-P` n PB/.N`N^.NuNVH /.Hn?</.N*$n$R n Ю"n"Jg`/.N*?.$Nj n/ n/N ?.$HzHHnN:Hn0*H/HnN"HnHn?<HnHn?<HnBg?<N:XHnHnNRHzHnNRHzHnNRHn n/HnN"Hn?</<HnN"Hn?<HnHn?<HnHn?<HnHn?<0*H/HnN"HnHn?<HnBg?<N:XHnHnNRHnNZ?.$ n/ n/N /.N2 n P-P`?.$Nj?.$HzHnN:Hz HnNRHn/.?<N2XHnHnNRHzHnNRHn?."?<N*XHnHnNRHzHnNRHnNZJ.g?.$HzNZ`?.$HzNZ?.$HzHnN:HzHnNRHzHnNRHn n/?<N2XHnHnNRHnNZ nJo?.$HzLHnN:HzDHnNRHz@m6=@t0.vN &0.tN @AmB00RntQ.RnvQ.||0.j_D.|g$0.NrA 0=A~0.R@=@Jn~f0.R@=@`0.N &0.~N @pAm00J@o40.N &0.~N @pAm00=@`0.n]D.gl0.R@=@0.zR@=@z0.zNd A~C~C""20.N &0.~N @Cm0=|`B.|`0.nWD.J.WD4.nWD.|gd=nt n R"n" n/HnpN Hnb n/Hnp/. N XHnbHnl?< nJoHzHnlN:Hz~HnlNRHnl?.BgN*XHnlHnlNRHzXHnlNRHzPHnlNRHzJHnlNRHnl n/BgN2XHnlHnlNRHz"HnlNRHzHnlNRHzHnlNRHnl0*H/HnbN"/.HnX?<HnbHnX?<HnXBg?<N:XHnlHnlNRHnlN: n  n"N-@p dpo( n r N "n" n  n"N-@p/.pHnbN"HnbNB0.xnWDHnlHnb?</.Hnb?< _D/.HnX?<Hz HnX?<HnlHnN?<HnXHnN?< ]DgZHnlHnb?</.Hnb?< d HnN YHnN -_Ap"n"Q0<"Q"n"l=nx||0.zNd A~AC~""20.N &0.~N @pAm00=@t0.tnf&J.WD2.tn]Dg 0.R@=@?.~Hj HnL/<NjHnLNWD2.tn]DgF0.N &0.~N @0.tR@NCm00.tR@=@`J0.N &0.~N @AmB000.zS@=@zJnzo B.|`|}J.|g.}-g/.N2-n"LN^ _ONSize  Model  Value ?ѷXe+NVHn?<N/<HnN"Hn?</<HnN"HnHn?<HnHn?</p n P>(@mV=@0.NH2.H/HnN"Hn?<HnHn?<Hn nHp?<RnQ.HzHn?<B-|=n0.n_DJ-WDgY?.?.HnHnHn. HN/./.N -_J-fD?.?./.HnHnHn?<Hn. HN/././.N HnN 0.R@=@`RHnNN^ _O N@#C@NVHBnUHn?<NJg:?.NHz6Hn?<N jXHnNUHnN=_YB?<SHnHzN-_/.?<HnHn?<N jXHnN/.?<HnHn?<N jXHnN/.?< HnHn?<BgN*XHnN/.?<HnHn?< BgN*XHnNHzHnNJWDHnHn?< &NXHnNXHnHnNJWDgR/.HnzNrHnz?<NzHnzHnN/.HnzNrHnz?<NzHnz?<HnN`>/.?<HnHnN/.HnzNrHnz?<NzHnz?<HnN/.HnzNrHnz?<NzHnz?<NzHnzHnN/.HmHnU/.Hn?.NJfR?.HnzNrHnz?<?<NHnzNg* nWD?<HnHnz/<&NjHnzNWDg,/.HnzNrHnz?<?<NHnzBgHnNHnzNrHnz?<?<NHnHnZ/<NjHnZHnzNHn:NrHn:HnzNgV/.HnzNrHnz?<?<NHnzHnN/.HnzNrHnz?<NzHnz?<HnN`*/.HnzNrHnz?<?<NHnzHnN?.HnzNrHnz?<NzHnz?<NzHnzNg` nf UHn/.?< HnNXHnNB=_UHn/.?<HnNXHnNB=_Hn/.?<HnNXHnHn?<NB?<HnHnz/<NjHnzNVDHN@?< HnHnz/<NjHnzNVDHN@?<HnHnz/<NjHnzNVDHN@?<HnHnz/<NjHnzNVDHN@?<HnHnz/<NjHnzNVDHN@?<HnHnz/<NjHnzNVDHN@?<HnHnz/<NjHnzNVDHN@?<HnHnz/<NjHnzNVDHN@?<HnHnz/<NjHnzNVDHN@/.N nf?<Hn?<N jXHnNbJ.gJ.g8=|HnHn?< NXHnNXHnHn?<NB`A/0N -_J.g?./.N J.g@Hn?<N jXHnN*?.?.?..HN/.N N2/.N?.NjLN^NuPKB1 2 3 4,R-7 8,R-10 11,R22 23 24,C-17 18 -19 20,S6 9 12 14 16 21,T13 15 -25( NVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNVBHnN"HnHn?<0. n=@Jn o0.H/HnN"0. H/HnN"HnHn?<Hn?<0. H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<Jno0.n 2.H/HnN"H/HnN"HnHn?<Hn?<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<Jno0.H/HnN"0. H/HnN"HnHn?<Hn?<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?</<HnN"Hn?<0.H/HnN"HnHn?<HnHn?<HnHn?<A"n""2N^ _PNNVBHnN"HnHn?<0. n=@Jno0. H/HnN"0.H/HnN"HnHn?<Hn?<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<Jno0. H/HnN"0.H/HnN"HnHn?<Hn?<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?</<HnN"Hn?<0. H/HnN"HnHn?<HnHn?<HnHn?<A"n ""2N^.NuNVH /.Hn/<N$nHzPHn?<HnNrHn?<?NHnHn/<NHnNrHn?<?NHnHn/<N/p>@m=@.HN&0.N@0.N@pA00n gFHnNrHn?.NzHnHn/<NjHnHnNHnHn/<NRnQp.HnHn/<NHnHn/<NBHnN"HnHn?<Bn|/p>*@mH=@?.HnHn/<NjHnNg/p~n @D/0*~@n=@DGBnBn/p>@m=@?.HnHn/<NjHnNg~.HN&0.N@0.N@pA00nf80.R@=@?.HnHn/<NjHnNg 0.R@=@RnQ\.0.H/HnN"HnHn?<Jno<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<HnHn?< RDHnHn?<HnHn?<Hn?<HnHn?< ]D4.n^Dg6B.-n=n.HN@=n=n=nSnQ.S.Sd.RnQ.J.g/p>*@m =@?.HnHn/<NjHnNg/p~n@D/0*~@n=@DGBnBn/p>@m=@?.HnHn/<NjHnNg~.HN&0.N@0.N@pA00nf80.R@=@?.HnHn/<NjHnNg 0.R@=@RnQ\.0.H/HnN"HnHn?<Jno<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<Hn?<HnHn?< ]D2.n]Dg6B.-n=n.HN@=n=n=nSnQ\.S.Sd<.RnQ.J.f?..HNHAHpHnN:Hn?.BgN*XHnHnNRHzTHnNRHn?.BgN*XHnHnNRHz2HnNRHn?.BgN*XHnHnNRHzHnNRHn?.BgN*XHnHnNRHnNbHnNrHn?.NzHnHn/<NjHnHnNHnHn/<N/p>@m=@.HN&0.N@0.N@pA00ngFHnNrHn?.NzHnHn/<NjHnHnNHnHn/<NRnQp.0.nWD.g?.HzNbHnHn/<NjHnHn/<NjHnHnNHnHn/<NHnHn/<NjHnHn/<NjHnHnNHnHn/<NHnNrHnHn/<NjHnHnNWD.gLN^ _ON?ѷXe+ {>}= :/---NVH /.Hn/<N$nHzfHn?<HnNrHn?<?NHnHn/<NHnNrHn?<?NHnHn/<N0*S@HR@=@/p>@m=@.HN&0.N@0.N@pA00n gFHnNrHn?.NzHnHn/<NjHnHnNHnHn/<NRnQp.HnHn/<NHnHn/<NBHnN"HnHn?<Bn|/p>*@mJ=@?.HnHn/<NjHnNg/p~n@D/0*>.@n=@DGBnBn/p>@m=@?.HnHn/<NjHnNg~.HN&0.N@0.N@pA00nm80.R@=@?.HnHn/<NjHnNg 0.R@=@RnQ\.0.H/HnN"HnHn?<Jno<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<HnHn?< RDHnHn?<HnHn?<Hn?<HnHn?< ]D4.n^Dg6B.-n=n.HN@=n=n=nSnQ.S.Sd.RnQ.J.g/p>*@m =@?.HnHn/<NjHnNg/p~n@D/0*>.@n=@DGBnBn/p>@m=@?.HnHn/<NjHnNg~.HN&0.N@0.N@pA00nm80.R@=@?.HnHn/<NjHnNg 0.R@=@RnQ\.0.H/HnN"HnHn?<Jno<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<Hn?<HnHn?< ]D2.n]Dg6B.-n=n.HN@=n=n=nSnQ\.S.Sd:.RnQ.J.f?..HNHAHpHnN:Hn?.BgN*XHnHnNRHzTHnNRHn?.BgN*XHnHnNRHz0HnNRHn?.BgN*XHnHnNRHz HnNRHn?.BgN*XHnHnNRHnNbHnNrHn?.NzHnHn/<NjHnHnNHnHn/<N/p>@m=@.HN&0.N@0.N@pA00nlFHnNrHn?.NzHnHn/<NjHnHnNHnHn/<NRnQp.0.nWD.g?.HzNbHnHn/<NjHnHn/<NjHnHnNHnHn/<NHnHn/<NjHnHn/<NjHnHnNHnHn/<NHnNrHnHn/<NjHnHnNWD.gLN^ _ON?ѷXe+ >= :/---NVH /.Hn/<N$n|Bn=RHzHn?<HnNrHn?<?NHnHn/<NHnNrHn?<?NHnHn/<N/p>@m=@.HN&0.N@0.N@pA00n lPHnNrHn?.NzHnHn/<NjHnHnNHnHn/<N0.S@=@RnQf.HnHn/<NHnHn/<NBHnN"HnHn?<Bn|/p>*@mH=@?.HnHn/<NjHnNg/p~n @D/0*~@n=@DGBnBn/p>@m=@?.HnHn/<NjHnNg~.HN&0.N@0.N@pA00nm80.R@=@?.HnHn/<NjHnNg 0.R@=@RnQ\.0.H/HnN"HnHn?<Jno<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<HnHn?< RDHnHn?<HnHn?<Hn?<HnHn?< ]D4.n^Dg6B.-n=n.HN@=n=n=nSnQ.S.Sd.RnQ.J.g./p>*@m=@?.HnHn/<NjHnNg/p~n@D/0*~@n=@DGBnBn/p>@m=@?.HnHn/<NjHnNg~.HN&0.N@0.N@pA00nm80.R@=@?.HnHn/<NjHnNg 0.R@=@RnQ\.0.H/HnN"HnHn?<Jno<0.H/HnN"HnHn?<HnHn?<HnHn?<HnHn?<HnHn?<Hn?<HnHn?< ]D2.n]Dg6B.-n=n.HN@=n=n=nJ.f?.HzNZSnQH.S.Sd(.RnQ.J.f?.HzHnN:.HNHAHpHnNRHn?.BgN*XHnHnNRHzzHnNRHn?.BgN*XHnHnNRHzVHnNRHn?.BgN*XHnHnNRHz0HnNRHn?.BgN*XHnHnNRHz HnNRHnHn??.?.?.N XHn?<?<N:XHnHnNRHnNZHnNrHn?.NzHnHn/<NjHnHnNHnHn/<N/p>@m=@.HN&0.N@0.N@pA00nlFHnNrHn?.NzHnHn/<NjHnHnNHnHn/<NRnQp.J.g B.=n0.nWD.gJ?.NjHnHn/<NjHnHn/<NjHnHnNHnHn/<NHnHn/<NjHnHn/<NjHnHnNHnHn/<NLN^ _ON?ѷXe+* >=:/ NVH0BnUHn?<NJg ?.NHz |Hn?<N XHnNUHnN=_YB?<THnHz JN-_/.?<HnHn?<N XHnN/.?<HnHn?<N XHnN/.?< HnHn0.N>A p P?(BgN*XHnN/.?<HnHn?< BgN*XHnNHzHnNJWDHnHn?< &NXHnNXHnHnNJWDgR/.HnjNrHnj?<NzHnjHnN/.HnjNrHnj?<NzHnj?<HnN`>/.?<HnHnN/.HnjNrHnj?<NzHnj?<HnN/.HnjNrHnj?<NzHnj?<NzHnjHnN/.HmHnU/.Hn?.NJfR?.HnjNrHnj?<?<NHnjNg* nWD?<HnHnj/<&NjHnjNWDg,/.HnjNrHnj?<?<NHnjBgHnNHnjNrHnj?<?<NHnHnJ/<NjHnJHnjNHn*NrHn*HnjNgV/.HnjNrHnj?<?<NHnjHnN/.HnjNrHnj?<NzHnj?<HnN`*/.HnjNrHnj?<?<NHnjHnN nWD nWDgv nf UHn/.?< HnNXHnNB=_UHn/.?<HnNXHnNB=_Hn/.?<HnNXHnHn?<NB?<HnHnj/<NjHnjNVDHN@?< HnHnj/<NjHnjNVDHN@?<HnHnj/<NjHnjNVDHN@?<HnHnj/<NjHnjNVDHN@?<HnHnj/<NjHnjNVDHN@?<HnHnj/<NjHnjNVDHN@?<HnHnj/<NjHnjNVDHN@?<HnHnj/<NjHnjNVDHN@?<HnHnj/<NjHnjNVDHN@/.N nf m/Q?<Hn?<N XHnNbJ.gJ.g8=|HnHn?< NXHnNXHnHn?<NB`EE/**N* j*-P&n0+S@HR@=@/p~nf@D/0+>.@nD=@DGHnjNrHnj?<?+NHnjHn/<NHnjNrHnj?.NzHnHnJ/<NjHnjHnJNHnJHn/<NBn/p>@m^=@.HN&0.N@0.N@pA00nm 0.R@=@RnQ.?..HNHAHpHnN:Hn?.BgN*XHnHnNRHzHnNRHn?.BgN*XHnHnNRHzpHnNRHn?.BgN*XHnHnNRHzJHnNRHnHn??.N XHn?<?<N:XHnHnNRHnNbU?./..HN?.?.HnN =_JnoFHnjNrHnj?.NzHnHnJ/<NjHnjHnJNHnJHn/<NJnfSnQ.S.Sd.?.Nj/**N2L N^NuPKB1 2 3 4,R-7 8,R-10 11,R22 23 24,C-17 18 -19 20,S6 9 12 14 16 21,T13 15 -25>=:  NVHn?<?.NHnHnNXHn/. ?<NBN^ _TNNV/.Hn?<NBHnHnN XHnHn?<NBHzHn?<NBHnHnHzNXHnHn?<NBHnHnN XHnHn?<NBHzHnNJfHnHn?<NB`6HnHnN:HzRHnNRHnHnNRHnHn?<NBHz,HnNJfZHn/. ?<NBN^.Nu _NVH00.N>EE/**N* j*-P/*:N* j:-P$n&n?. NjJ+-g Hz\Hn?< NXHnN`Hz@Hn?< NXHnNJ+-g Hz Hn?< NXHnN`HzHzNHzHn0+-H/HnN"/<dHnN"HnHn?<Hn?<?<N:XHnN?. Hn?<N XHnNb?. Nj?.N=|/p>*@m.=@/p>*@m=@/p~m@/p~m@?..HN&.HNx@0.NH@A+Hp0Hn/<NjHnNgp?. HzHnN:Hm"HnNRHzHnNRHn?.BgN*XHnHnNRHnNZ?. Hm"HnN:HzHnNRHm"HnNRHzxHnNRHm"HnNRHn.HN&0.N4@AHp0N XHnHnNRHz"HnNRHnNZ?. Hm"HnN:HzHnNRHm"HnNRHn.HN&0.N4@AHp0N XHnHnNRHzHnNRHnNb0.R@=@R.Sd,.R.Sd.RnQ.RnQ.?. Nj0.N>EE/**N2/*:N2L N^.Nu11223(RuleR(Lhs(Yes))(Hypo))NVH Hn?<N0.N>EE/**N* j* P"n0<"Q2$n=j5|/.?.N?. Nj?. HzHnN:Hm"HnNRHzHnNRHzHnNRHnNb?. Nj/p>*@m=@/p~m@?. HzHnN:Hm"HnNRHn.HN&0.N4@AHp0N XHnHnNRHm"HnNRHzLHnNRHm"HnNRHz:HnNRHz8HnNRHnNbR.SdT.RnQ:.?. Nj?. Nj?. HzHnN:Hm"HnNRHnHjVN XHnHnNRHnNb?. Hm"HnN:HzHnNRHnNb/p>*@m=@/p~mx@?. Hm"HnN:Hm"HnNRHn.HN&0.N4@AHp0N XHnHnNRHnNbR.Sd.RnQv.?. Hm"HnN:HzHnNRHnNb?. HzNb?. Nj?. Nj/p>@mN=@?. HzHnN:Hm"HnNRHn0.N4A HpN XHnHnNRHm"HnNRHzxHnNRHm"HnNRHnHjVN XHnHnNRHzPHnNRHnNb/p>*@m=@/p~mt@.HN&0.N@0.N@pA00 @g @fHzHn?<NB` @fHzHn?<NB?. HzHnN:Hm"HnNRHn0.N4A HpN XHnHnNRHzlHnNRHn.HN&0.N4@AHp0N XHnHnNRHnNZ?. Hm"HnN:HzHnNRHm"HnNRHnHnNRHzHnNRHnNbR.Sd.RnQz.?. NjRnQ.?. Nj0.N>EE/**N2HnNLN^.Nu(Version011) (Property(TypeBoolean))(Class (Properties))(Object(Classes))FalseTrue(Slot.(InitVal))NVHBnUHn?<NJg?.NHzHn?<N XHnNUHnN=_YB?<UHnHzNN-_/.?<HnHn?<N XHnN/.?<HnHn?<N XHnN/.HnNrHn?<?<NHn?<?<NHnHnNHzHnNJWDHnHn?< &NXHnNXHnHnNJWDgR/.HnNrHn?<NzHnHnN/.HnNrHn?<NzHn?<HnN`>/.?<HnHnN/.HnNrHn?<NzHn?<HnN/.HnNrHn?<NzHn?<NzHnHnN/.HmHnU/.Hn?.NJfR?.HnNrHn?<?<NHnNg* nWD?<HnHn/<&NjHnNWDg,/.HnNrHn?<?<NHnBgHnNHnNrHn?<?<NHnHnh/<NjHnhHnNHnHNrHnHHnNgV/.HnNrHn?<?<NHnHnN/.HnNrHn?<NzHn?<HnN`*/.HnNrHn?<?<NHnHnN nWD nWDgv nfHn/.?<HnNXHnHn?<NB?<HnHn/<NjHnNVDHN@?<HnHn/<NjHnNVDHN@?<HnHn/<NjHnNVDHN@?<HnHn/<NjHnNVDHN@/.N nf*?<Hn?<N XHnNbJ.gJ.g8=|HnHn?< NXHnNXHnHn?<NB`AJg?.?.N LN^NuPKB1 2 3 4,R-7 8,R-10 11,R22 23 24,C-17 18 -19 20,S6 9 12 14 16 21,T13 15 -25(` "NVN^NuNVH HzHn=| HnNrHnHn/<NEAC"2AC"2AC "2HnNrHn?<NzHnHj/<N5|5|5|d|B*B*B*B*B*EAC"2AC"2AC "2AC"25|25|25|dB*| B*!|"|#|$|%|&B*B*'B*(B*)EAC"2AC"2AC "2AC"2|B*EN* j P h>-P j P0(N2?.HnHnNXHnNbLN^NuNVH0$n &j&S0. @fJkfHzHn/. ?<HkNXHnN?<Hn?<N XHnNb?*Hn?<N XHnN/. ?<HkHn?<N XHnN/. HnNrHn?<NzHn?<NzHnHkN/. HnNrHn?<NzHn?<?<NHnHkN7|`N` @f` @f?<N :` @f BgN :` @f?<N :` @f Nb` @f N *` @ f N` @ f N`v @ f N `f @ f N r`V @ f N `F @f N b`6 @f N `& @fJ-g?*N B-/. N L N^ _\N1NVHnt/-.m<<NHz~Hn?.?< /.sHn?<Hn?.?<N*XHn?.?<N*XHnHnNRHn?.?<N*XHnHnNRHnNbN^NuMonacoNV/p><@m=@ ng|?.HnHz|HnNJgb?<HnNZ/p><@m>=@U?.?.Jg ?<Hn?.?<N*XHnNZRnQ.?<NjRnQv.N^NuNVHHzHm?<NB=|Hn?<?.NHzHnNJgHmHnN:HnHn?<?<NZHnHnNRHnHm?<NBp-N4HnHn?<r.SA?&NZHnA. @m:=@0.NdH&nGG??+?+?+RnQ./.s?./-x/-tNL N^ _PNMonacoNVH UHnN=_JnoVUNBJgJ0.NHE$r?*HnNBnHnHnNXHnHn?<NBHz HnNJWDHN@J.f0.R@=@0.NdHUHnHnHz&NXHnNBC300.NdHUHnHnHz&NXHnNBC300.NdHUHnHnHz`&NXHnNBC300.NdHUHn&NBC30J.g?-`?./N ZLN^Nu   NVH UNBJg0-`NHE$rHnt/-.m<<NHzHnީ?.ި?< HnHnHnN BnBn/p~&@m=@HnBg?.NHn0.Z@?0.Z@?0.Z@@?0.Z@@?HnHnਥ? @f N r`. @ f N ` @ f N b` @ fN `` @f8?.Y0.H//< . JVDHNN `" @f0. @f N ` @f N R` @f N B` @f N b` @f N 2` @f N "` @f N "` @f N "` @ f N "` @ f~?<Y?<HnNBgN2XHzlHnNRHnYNBgN2XHnHnNRHzDHnNRHnYNBgN2XHnHnNRHnNBNBg8N^ _PN  NVH nC""""Y$ . g/. U?./.N=_`4$n -nHnqU/.HjJgZJgB/.Y0.H//< . J^DHN/*ة?*Nj`?*HnN "`U/./. Hnl=_0. @fU/./.Hmh=_`z @fU/./.Hmh=_`Z @f/.?.<N`> @f/.?.B'N`$ @fU/./.Bh=_?*N?*N"LN^ _PNNVY$ . g /. `U/. /.Jg /. N N^ _PNNVH0Y/. /.Hm^+-_Jg@$n Jg8p j P( @WDHN@J.g0*@5@Jg8p j P( @WDHN@J.g0*@5@AC""0.@=@Hn(AC""0.@=@Hn( n AC""/. ?.?.<&n 0*kn5@0*kn5@JgfJVD*g =|`=|/*X/*0*@?0*S@?Y/*?<0*jn?\J.g/*WJgfJVD*g =|`=|/*ܩX/*0*S@?0*@?Y/*0*jn??<\J.g/*ܩWAC""0.@=@0.@=@Hn(?*HjNRJVD*g n Hh(Jg/. ?/.N nBP`xY$-_Jgh$nJf@Jg.0.N?/*ة/*ب|?*Nj`?<` n f/.?<N nBPLN^.NuNVH nC""""-n$n/.s/.N 0.d@Jg /*Bg]Jg /*Bg]Jg /*ةNz?*Nj`T/-2sJg /*?<]Jg /*?<]Jg /*ةNY$-_JfBgNjLN^.NuNVBnBnBn=|=|=|HnHnNRHnNB .]DHN@ N^.NuNVH NNjN N jN */p~@mH=@0.NHY?.&C#00.NHA/0N*RnQ.Y?<詹+_/-N*Y?<驹+_/-N*Y?<꩹+_/-N*Y?<멹+_/-N* m/QY?<詿+_@Y?<驿+_DY?<ꩿ+_HY?<멿+_LY?<쩿+_PY?<+_TY?<+_X/-@/EEBRB*B:B6B.B2RnQ./-2sB-qBmB--N2UN0J@WDHN@Y/<xN+_/-N:J-f/-D?< :/-D?< :U/N JgHnBgBgBgBgUHmFHnBgB'<B'B'<B'NrJg?-`HnHn?< NXHnNXHnNUHm6HnBg<<B'<<<NrJg*?-`HnHn?< NXHnNXHnNN2HmQ+||N J?<Hn?<NXHnNbN *LN^NuNVN?<Hn?< NXHnNbN^NuNVH 0. NHE$r/*N*Y j//< .-_-nY/*N" .П-@/*Hn~-| .l4U/. nHh Jg-n n0(HЮ-@`-mJm -Ю-@ .gHnN20. NHA/0s?. N:?< JmJmm/.?-NJmRp n(;@/.Y0-*H//< . J^DHNN  .+@` +|?. NBHnN:/*N2LN^ _\NNVH Y$-_Jgx nJhlol$nHnrJg/*Jg0/*ةU/.HjJg m/Q`HmQ`JgJ*f?*/.NLN^NuNV nC""""0. @fHnN `N @fHnN `: @fHnN `& @fHnN` @f HnN UHnJg$UHnHnHnꩀJg/.?.N |N^.Nu2ZCDKSzBNDLFREFSTR#MENUjDLOGDITLPAT#CURSICONICN#PICT FOND.FONT:CODEFLLLMWNbmX+ ^  Jw&vd9LMN"O$P%p&Q'R*=S+T-U/12}RLM N"O$P%p&Q'R*VS+T-U/134455g5L5L6{M7N89AJUUc2r"B : . &* }&  "  cf ’  9 \F f fKSS0-1KSS0-2KSS0-3Venice.pn 0 .ls1 .EQ delim $$ .EN .ev1 .ps-2 .vs-2 .ev \& .sp 5 .ps+4 .ce ARITHMETIC CODING FOR DATA COMPRESSION .ps-4 .sp4 .ce Ian H. Witten, Radford M. Neal, and John G. Cleary .sp2 .ce4 Department of Computer Science The University of Calgary 2500 University Drive NW Calgary, Canada T2N 1N4 .sp2 .ce August, 1986, revised January 1987 .sp 8 .in+1i .ll-1i The state of the art in data compression is arithmetic coding, not the better-known Huffman method. Arithmetic coding gives greater compression, is faster for adaptive models, and clearly separates the model from the channel encoding. This paper presents a practical implementation of the technique. .sp 3 .in +0.5i .ti -0.5i \fICR Categories and subject descriptors:\fR .br E.4 [DATA] Coding and Information Theory \(em Data Compaction and Compression .br H.1.1 [Models and Principles] Systems and Information Theory \(em Information Theory .sp .ti -0.5i \fIGeneral terms:\fR algorithms, performance .sp .ti -0.5i \fIAdditional key words and phrases:\fR arithmetic coding, Huffman coding, adaptive modeling .ll+1i .in 0 .bp .sh "Introduction" .pp Arithmetic coding is superior in most respects to the better-known Huffman (1952) method. .[ Huffman 1952 method construction minimum-redundancy codes .] It represents information at least as compactly, sometimes considerably more so. Its performance is optimal without the need for blocking of input data. It encourages a clear separation between the model for representing data and the encoding of information with respect to that model. It accommodates adaptive models easily. It is computationally efficient. Yet many authors and practitioners seem unaware of the technique. Indeed there is a widespread belief that Huffman coding cannot be improved upon. .pp This paper aims to rectify the situation by presenting an accessible implementation of arithmetic coding, and detailing its performance characteristics. The next section briefly reviews basic concepts of data compression and introduces the model-based approach which underlies most modern techniques. We then outline the idea of arithmetic coding using a simple example. Following that programs are presented for both encoding and decoding, in which the model occupies a separate module so that different ones can easily be used. Next we discuss the construction of fixed and adaptive models. The subsequent section details the compression efficiency and execution time of the programs, including the effect of different arithmetic word lengths on compression efficiency. Finally, we outline a few applications where arithmetic coding is appropriate. .sh "Data compression" .pp To many, data compression conjures up an assortment of \fIad hoc\fR techniques such as converting spaces in text to tabs, creating special codes for common words, or run-length coding of picture data (eg see Held, 1984). .[ Held 1984 data compression techniques applications .] This contrasts with the more modern model-based paradigm for coding, where from an \fIinput string\fR of symbols and a \fImodel\fR, an \fIencoded string\fR is produced which is (usually) a compressed version of the input. The decoder, which must have access to the same model, regenerates the exact input string from the encoded string. Input symbols are drawn from some well-defined set such as the ASCII or binary alphabets; the encoded string is a plain sequence of bits. The model is a way of calculating, in any given context, the distribution of probabilities for the next input symbol. It must be possible for the decoder to produce exactly the same probability distribution in the same context. Compression is achieved by transmitting the more probable symbols in fewer bits than the less probable ones. .pp For example, the model may assign a predetermined probability to each symbol in the ASCII alphabet. No context is involved. These probabilities may be determined by counting frequencies in representative samples of text to be transmitted. Such a \fIfixed\fR model is communicated in advance to both encoder and decoder, after which it is used for many messages. .pp Alternatively, the probabilities the model assigns may change as each symbol is transmitted, based on the symbol frequencies seen \fIso far\fR in this message. This is an \fIadaptive\fR model. There is no need for a representative sample of text, because each message is treated as an independent unit, starting from scratch. The encoder's model changes with each symbol transmitted, and the decoder's changes with each symbol received, in sympathy. .pp More complex models can provide more accurate probabilistic predictions and hence achieve greater compression. For example, several characters of previous context could condition the next-symbol probability. Such methods have enabled mixed-case English text to be encoded in around 2.2\ bit/char with two quite different kinds of model. (Cleary & Witten, 1984b; Cormack & Horspool, 1985). .[ Cleary Witten 1984 data compression %D 1984b .] .[ Cormack Horspool 1985 dynamic Markov %O April .] Techniques which do not separate modeling from coding so distinctly, like that of Ziv & Lempel (1978), do not seem to show such great potential for compression, although they may be appropriate when the aim is raw speed rather than compression performance (Welch, 1984). .[ Ziv Lempel 1978 compression of individual sequences .] .[ Welch 1984 data compression .] .pp The effectiveness of any model can be measured by the \fIentropy\fR of the message with respect to it, usually expressed in bits/symbol. Shannon's fundamental theorem of coding states that given messages randomly generated from a model, it is impossible to encode them into less bits (on average) than the entropy of that model (Shannon & Weaver, 1949). .[ Shannon Weaver 1949 .] .pp A message can be coded with respect to a model using either Huffman or arithmetic coding. The former method is frequently advocated as the best possible technique for reducing the encoded data rate. But it is not. Given that each symbol in the alphabet must translate into an integral number of bits in the encoding, Huffman coding indeed achieves ``minimum redundancy''. In other words, it performs optimally if all symbol probabilities are integral powers of 1/2. But this is not normally the case in practice; indeed, Huffman coding can take up to one extra bit per symbol. The worst case is realized by a source in which one symbol has probability approaching unity. Symbols emanating from such a source convey negligible information on average, but require at least one bit to transmit (Gallagher, 1978). .[ Gallagher 1978 variations on a theme by Huffman .] Arithmetic coding dispenses with the restriction that each symbol translates into an integral number of bits, thereby coding more efficiently. It actually achieves the theoretical entropy bound to compression efficiency for any source, including the one just mentioned. .pp In general, sophisticated models expose the deficiencies of Huffman coding more starkly than simple ones. This is because they more often predict symbols with probabilities close to one, the worst case for Huffman coding. For example, the techniques mentioned above which code English text in 2.2\ bit/char both use arithmetic coding as the final step, and performance would be impacted severely if Huffman coding were substituted. Nevertheless, since our topic is coding and not modeling, the illustrations in this paper all employ simple models. Even then, as we shall see, Huffman coding is inferior to arithmetic coding. .pp The basic concept of arithmetic coding can be traced back to Elias in the early 1960s (see Abramson, 1963, pp 61-62). .[ Abramson 1963 .] Practical techniques were first introduced by Rissanen (1976) and Pasco (1976), and developed further in Rissanen (1979). .[ Rissanen 1976 Generalized Kraft Inequality .] .[ Pasco 1976 .] .[ Rissanen 1979 number representations .] .[ Langdon 1981 tutorial arithmetic coding .] Details of the implementation presented here have not appeared in the literature before; Rubin (1979) is closest to our approach. .[ Rubin 1979 arithmetic stream coding .] The reader interested in the broader class of arithmetic codes is referred to Rissanen & Langdon (1979); .[ Rissanen Langdon 1979 Arithmetic coding .] a tutorial is available in Langdon (1981). .[ Langdon 1981 tutorial arithmetic coding .] Despite these publications, the method is not widely known. A number of recent books and papers on data compression mention it only in passing, or not at all. .sh "The idea of arithmetic coding" .pp In arithmetic coding a message is represented by an interval of real numbers between 0 and 1. As the message becomes longer, the interval needed to represent it becomes smaller, and the number of bits needed to specify that interval grows. Successive symbols of the message reduce the size of the interval in accordance with the symbol probabilities generated by the model. The more likely symbols reduce the range by less than the unlikely symbols, and hence add fewer bits to the message. .pp Before anything is transmitted, the range for the message is the entire interval [0,\ 1)\(dg. .FN \(dg [0,\ 1) denotes the half-open interval 0\(<=\fIx\fR<1. .EF As each symbol is processed, the range is narrowed to that portion of it allocated to the symbol. For example, suppose the alphabet is {\fIa,\ e,\ i,\ o,\ u,\ !\fR}, and a fixed model is used with probabilities shown in Table\ 1. Imagine transmitting the message \fIeaii!\fR. Initially, both encoder and decoder know that the range is [0,\ 1). After seeing the first symbol, \fIe\fR, the encoder narrows it to [0.2,\ 0.5), the range the model allocates to this symbol. The second symbol, \fIa\fR, will narrow this new range to the first 1/5 of it, since \fIa\fR has been allocated [0,\ 0.2). This produces [0.2,\ 0.26) since the previous range was 0.3 units long and 1/5 of that is 0.06. The next symbol, \fIi\fR, is allocated [0.5,\ 0.6), which when applied to [0.2,\ 0.26) gives the smaller range [0.23,\ 0.236). Proceeding in this way, the encoded message builds up as follows: .LB .nf .ta \w'after seeing 'u +0.5i +\w'[0.23354, 'u initially [0, 1) after seeing \fIe\fR [0.2, 0.5) \fIa\fR [0.2, 0.26) \fIi\fR [0.23, 0.236) \fIi\fR [0.233, 0.2336) \fI!\fR [0.23354, 0.2336) .fi .LE Figure\ 1 shows another representation of the encoding process. The vertical bars with ticks represent the symbol probabilities stipulated by the model. After the first symbol, \fIe\fR, has been processed, the model is scaled into the range [0.2,\ 0.5), as shown in part (a). The second symbol, \fIa\fR, scales it again into the range [0.2,\ 0.26). But the picture cannot be continued in this way without a magnifying glass! Consequently Figure\ 1(b) shows the ranges expanded to full height at every stage, and marked with a scale which gives the endpoints as numbers. .pp Suppose all the decoder knows about the message is the final range, [0.23354,\ 0.2336). It can immediately deduce that the first character was \fIe\fR, since the range lies entirely within the space the model of Table\ 1 allocates for \fIe\fR. Now it can simulate the operation of the \fIen\fR\^coder: .LB .nf .ta \w'after seeing 'u +0.5i +\w'[0.2, 'u initially [0, 1) after seeing \fIe\fR [0.2, 0.5) .fi .LE This makes it clear that the second character of the message is \fIa\fR, since this will produce the range .LB .nf .ta \w'after seeing 'u +0.5i +\w'[0.2, 'u after seeing \fIa\fR [0.2, 0.26) .fi .LE which entirely encloses the given range [0.23354,\ 0.2336). Proceeding like this, the decoder can identify the whole message. .pp It is not really necessary for the decoder to know both ends of the range produced by the encoder. Instead, a single number within the range \(em for example, 0.23355 \(em will suffice. (Other numbers, like 0.23354, 0.23357, or even 0.23354321, would do just as well.) \c However, the decoder will face the problem of detecting the end of the message, to determine when to stop decoding. After all, the single number 0.0 could represent any of \fIa\fR, \fIaa\fR, \fIaaa\fR, \fIaaaa\fR, ...\ . To resolve the ambiguity we ensure that each message ends with a special EOF symbol known to both encoder and decoder. For the alphabet of Table\ 1, \fI!\fR will be used to terminate messages, and only to terminate messages. When the decoder sees this symbol it stops decoding. .pp Relative to the fixed model of Table\ 1, the entropy of the 5-symbol message \fIeaii!\fR is .LB $- ~ log ~ 0.3 ~ - ~ log ~ 0.2 ~ - ~ log ~ 0.1 ~ - ~ log ~ 0.1 ~ - ~ log ~ 0.1 ~~=~~ - ~ log ~ 0.00006 ~~ approx ~~ 4.22$ .LE (using base 10, since the above encoding was performed in decimal). This explains why it takes 5\ decimal digits to encode the message. In fact, the size of the final range is $0.2336 ~-~ 0.23354 ~~=~~ 0.00006$, and the entropy is the negative logarithm of this figure. Of course, we normally work in binary, transmitting binary digits and measuring entropy in bits. .pp Five decimal digits seems a lot to encode a message comprising four vowels! It is perhaps unfortunate that our example ended up by expanding rather than compressing. Needless to say, however, different models will give different entropies. The best single-character model of the message \fIeaii!\fR is the set of symbol frequencies {\fIe\fR\ (0.2), \fIa\fR\ (0.2), \fIi\fR\ (0.4), \fI!\fR\ (0.2)}, which gives an entropy for \fIeaii!\fR of 2.89\ decimal digits. Using this model the encoding would be only 3\ digits long. Moreover, as noted earlier more sophisticated models give much better performance in general. .sh "A program for arithmetic coding" .pp Figure\ 2 shows a pseudo-code fragment which summarizes the encoding and decoding procedures developed in the last section. Symbols are numbered 1, 2, 3, ... The frequency range for the $i$th symbol is from $cum_freq[i]$ to $cum_freq[i-1]$. $cum_freq[i]$ increases as $i$ decreases, and $cum_freq[0] = 1$. (The reason for this ``backwards'' convention is that later, $cum_freq[0]$ will contain a normalizing factor, and it will be convenient to have it begin the array.) \c The ``current interval'' is [$low$,\ $high$); and for both encoding and decoding this should be initialized to [0,\ 1). .pp Unfortunately, Figure\ 2 is overly simplistic. In practice, there are several factors which complicate both encoding and decoding. .LB .NP Incremental transmission and reception. .br The encode algorithm as described does not transmit anything until the entire message has been encoded; neither does the decode algorithm begin decoding until it has received the complete transmission. In most applications, an incremental mode of operation is necessary. .sp .NP The desire to use integer arithmetic. .br The precision required to represent the [$low$, $high$) interval grows with the length of the message. Incremental operation will help overcome this, but the potential for overflow and underflow must still be examined carefully. .sp .NP Representing the model so that it can be consulted efficiently. .br The representation used for the model should minimize the time required for the decode algorithm to identify the next symbol. Moreover, an adaptive model should be organized to minimize the time-consuming task of maintaining cumulative frequencies. .LE .pp Figure\ 3 shows working code, in C, for arithmetic encoding and decoding. It is considerably more detailed than the bare-bones sketch of Figure\ 2! Implementations of two different models are given in Figure\ 4; the Figure\ 3 code can use either one. .pp The remainder of this section examines the code of Figure\ 3 more closely, including a proof that decoding is still correct in the integer implementation and a review of constraints on word lengths in the program. .rh "Representing the model." Implementations of models are discussed in the next section; here we are concerned only with the interface to the model (lines 20-38). In C, a byte is represented as an integer between 0 and 255 (call this a $char$). Internally, we represent a byte as an integer between 1 and 257 inclusive (call this an $index$), EOF being treated as a 257th symbol. It is advantageous to sort the model into frequency order, to minimize the number of executions of the decoding loop (line 189). To permit such reordering, the $char$/$index$ translation is implemented as a pair of tables, $index_to_char[ \| ]$ and $char_to_index[ \| ]$. In one of our models, these tables simply form the $index$ by adding 1 to the $char$, but another implements a more complex translation which assigns small indexes to frequently-used symbols. .pp The probabilities in the model are represented as integer frequency counts, and cumulative counts are stored in the array $cum_freq[ \| ]$. As previously, this array is ``backwards,'' and the total frequency count \(em which is used to normalize all frequencies \(em appears in $cum_freq[0]$. Cumulative counts must not exceed a predetermined maximum, $Max_frequency$, and the model implementation must prevent overflow by scaling appropriately. It must also ensure that neighboring values in the $cum_freq[ \| ]$ array differ by at least 1; otherwise the affected symbol could not be transmitted. .rh "Incremental transmission and reception." Unlike Figure\ 2, the program of Figure\ 3 represents $low$ and $high$ as integers. A special data type, $code_value$, is defined for these quantities, together with some useful constants: \c $Top_value$, representing the largest possible $code_value$, and $First_qtr$, $Half$, and $Third_qtr$, representing parts of the range (lines 6-16). Whereas in Figure\ 2 the current interval is represented by [$low$,\ $high$), in Figure\ 3 it is [$low$,\ $high$]; that is, the range now includes the value of $high$. Actually, it is more accurate (though more confusing) to say that in the program of Figure\ 3 the interval represented is [$low$,\ $high + 0.11111 ...$). This is because when the bounds are scaled up to increase the precision, 0's are shifted into the low-order bits of $low$ but 1's are shifted into $high$. While it is possible to write the program to use a different convention, this one has some advantages in simplifying the code. .pp As the code range narrows, the top bits of $low$ and $high$ will become the same. Any bits which are the same can be transmitted immediately, since they cannot be affected by future narrowing. For encoding, since we know that $low ~ <= ~ high$, this requires code like .LB "nnnn" .nf .ta \w'nnnn'u +\w'if (high < 'u +\w'Half) { 'u +\w'output_bit(1); low = 2*(low\-Half); high = 2*(high\-Half)+1; 'u .ne 4 for (;;) { if (high < Half) { output_bit(0); low = 2*low; high = 2*high+1; } if (low $>=$ Half) { output_bit(1); low = 2*(low\-Half); high = 2*(high\-Half)+1; } } .fi .LE "nnnn" which ensures that, upon completion, $low ~ < ~ Half ~ <= ~ high$. This can be found in lines 95-113 of $encode_symbol( \| )$, although there are some extra complications caused by underflow possibilities (see next subsection). Care is taken care to shift 1's in at the bottom when $high$ is scaled, as noted above. .pp Incremental reception is done using a number called $value$ as in Figure\ 2, in which processed bits flow out the top (high-significance) end and newly-received ones flow in the bottom. $start_decoding( \| )$ (lines 168-176) fills $value$ with received bits initially. Once $decode_symbol( \| )$ has identified the next input symbol, it shifts out now-useless high-order bits which are the same in $low$ and $high$, shifting $value$ by the same amount (and replacing lost bits by fresh input bits at the bottom end): .LB "nnnn" .nf .ta \w'nnnn'u +\w'if (high < 'u +\w'Half) { 'u +\w'value = 2*(value\-Half)+input_bit(\|); low = 2*(low\-Half); high = 2*(high\-Half)+1; 'u .ne 4 for (;;) { if (high < Half) { value = 2*value+input_bit(\|); low = 2*low; high = 2*high+1; } if (low $>=$ Half) { value = 2*(value\-Half)+input_bit(\|); low = 2*(low\-Half); high = 2*(high\-Half)+1; } } .fi .LE "nnnn" (see lines 194-213, again complicated by precautions against underflow discussed below). .rh "Proof of decoding correctness." At this point it is worth checking that the identification of the next symbol by $decode_symbol( \| )$ works properly. Recall from Figure\ 2 that $decode_symbol( \| )$ must use $value$ to find that symbol which, when encoded, reduces the range to one that still includes $value$. Lines 186-188 in $decode_symbol( \| )$ identify the symbol for which .LB $cum_freq[symbol] ~ <= ~~ left f {(value-low+1)*cum_freq[0] ~-~ 1} over {high-low+1} right f ~~ < ~ cum_freq[symbol-1]$, .LE where $left f ~ right f$ denotes the ``integer part of'' function that comes from integer division with truncation. It is shown in the Appendix that this implies .LB "nnnn" $low ~+~~ left f {(high-low+1)*cum_freq[symbol]} over cum_freq[0] right f ~~ <= ~ v ~ <= ~~ low ~+~~ left f {(high-low+1)*cum_freq[symbol-1]} over cum_freq[0] right f ~~ - ~ 1$, .LE "nnnn" so $value$ lies within the new interval that $decode_symbol( \| )$ calculates in lines 190-193. This is sufficient to guarantee that the decoding operation identifies each symbol correctly. .rh "Underflow." As Figure\ 1 shows, arithmetic coding works by scaling the cumulative probabilities given by the model into the interval [$low$,\ $high$] for each character transmitted. Suppose $low$ and $high$ are very close together, so close that this scaling operation maps some different symbols of the model on to the same integer in the [$low$,\ $high$] interval. This would be disastrous, because if such a symbol actually occurred it would not be possible to continue encoding. Consequently, the encoder must guarantee that the interval [$low$,\ $high$] is always large enough to prevent this. The simplest way is to ensure that this interval is at least as large as $Max_frequency$, the maximum allowed cumulative frequency count (line\ 36). .pp How could this condition be violated? The bit-shifting operation explained above ensures that $low$ and $high$ can only become close together when they straddle $Half$. Suppose in fact they become as close as .LB $First_qtr ~ <= ~ low ~<~ Half ~ <= ~ high ~<~ Third_qtr$. .LE Then the next two bits sent will have opposite polarity, either 01 or 10. For example, if the next bit turns out to be 0 (ie $high$ descends below $Half$ and [0,\ $Half$] is expanded to the full interval) the bit after that will be 1 since the range has to be above the midpoint of the expanded interval. Conversely if the next bit happens to be 1 the one after that will be 0. Therefore the interval can safely be expanded right now, if only we remember that whatever bit actually comes next, its opposite must be transmitted afterwards as well. Thus lines 104-109 expand [$First_qtr$,\ $Third_qtr$] into the whole interval, remembering in $bits_to_follow$ that the bit that is output next must be followed by an opposite bit. This explains why all output is done via $bit_plus_follow( \| )$ (lines 128-135) instead of directly with $output_bit( \| )$. .pp But what if, after this operation, it is \fIstill\fR true that .LB $First_qtr ~ <= ~ low ~<~ Half ~ <= ~ high ~<~ Third_qtr$? .LE Figure\ 5 illustrates this situation, where the current [$low$,\ $high$] range (shown as a thick line) has been expanded a total of three times. Suppose the next bit will turn out to be 0, as indicated by the arrow in Figure\ 5(a) being below the halfway point. Then the next \fIthree\fR bits will be 1's, since not only is the arrow in the top half of the bottom half of the original range, it is in the top quarter, and moreover the top eighth, of that half \(em that is why the expansion can occur three times. Similarly, as Figure\ 5(b) shows, if the next bit turns out to be a 1 it will be followed by three 0's. Consequently we need only count the number of expansions and follow the next bit by that number of opposites (lines 106 and 131-134). .pp Using this technique, the encoder can guarantee that after the shifting operations, either .LB .ta \n(.lu-\n(.iuR $low ~<~ First_qtr ~<~ Half ~ <= ~ high$ (1a) .LE or .LB .ta \n(.lu-\n(.iuR $low ~<~ Half ~<~ Third_qtr ~ <= ~ high$. (1b) .LE Therefore as long as the integer range spanned by the cumulative frequencies fits into a quarter of that provided by $code_value$s, the underflow problem cannot occur. This corresponds to the condition .LB $Max_frequency ~ <= ~~ {Top_value+1} over 4 ~~ + ~ 1$, .LE which is satisfied by Figure\ 3 since $Max_frequency ~=~ 2 sup 14 - 1$ and $Top_value ~=~ 2 sup 16 - 1$ (lines\ 36, 9). More than 14\ bits cannot be used to represent cumulative frequency counts without increasing the number of bits allocated to $code_value$s. .pp We have discussed underflow in the encoder only. Since the decoder's job, once each symbol has been decoded, is to track the operation of the encoder, underflow will be avoided if it performs the same expansion operation under the same conditions. .rh "Overflow." Now consider the possibility of overflow in the integer multiplications corresponding to those of Figure\ 2, which occur in lines 91-94 and 190-193 of Figure\ 3. Overflow cannot occur provided the product .LB $range * Max_frequency$ .LE fits within the integer word length available, since cumulative frequencies cannot exceed $Max_frequency$. $Range$ might be as large as $Top_value ~+~1$, so the largest possible product in Figure 3 is $2 sup 16 ( 2 sup 14 - 1 )$ which is less than $2 sup 30$. $Long$ declarations are used for $code_value$ (line\ 7) and $range$ (lines\ 89, 183) to ensure that arithmetic is done to 32-bit precision. .rh "Constraints on the implementation." The constraints on word length imposed by underflow and overflow can be simplified by assuming frequency counts are represented in $f$\ bits, and $code_value$s in $c$\ bits. The implementation will work correctly provided .LB $f ~ <= ~ c ~ - ~2$ .br $f ~+~ c ~ <= ~ p$, the precision to which arithmetic is performed. .LE In most C implementations, $p=31$ if $long$ integers are used, and $p=32$ if they are $unsigned ~ long$. In Figure\ 3, $f=14$ and $c=16$. With appropriately modified declarations, $unsigned ~ long$ arithmetic with $f=15$, $c=17$ could be used. In assembly language $c=16$ is a natural choice because it expedites some comparisons and bit manipulations (eg those of lines\ 95-113 and 194-213). .pp If $p$ is restricted to 16\ bits, the best values possible are $c=9$ and $f=7$, making it impossible to encode a full alphabet of 256\ symbols, as each symbol must have a count of at least 1. A smaller alphabet (eg the letters, or 4-bit nibbles) could still be handled. .rh "Termination." To finish the transmission, it is necessary to send a unique terminating symbol ($EOF_symbol$, line 56) and then follow it by enough bits to ensure that the encoded string falls within the final range. Since $done_encoding( \| )$ (lines 119-123) can be sure that $low$ and $high$ are constrained by either (1a) or (1b) above, it need only transmit $01$ in the first case or $10$ in the second to remove the remaining ambiguity. It is convenient to do this using the $bit_plus_follow( \| )$ procedure discussed earlier. The $input_bit( \| )$ procedure will actually read a few more bits than were sent by $output_bit( \| )$ as it needs to keep the low end of the buffer full. It does not matter what value these bits have as the EOF is uniquely determined by the last two bits actually transmitted. .sh "Models for arithmetic coding" .pp The program of Figure\ 3 must be used with a model which provides a pair of translation tables $index_to_char[ \| ]$ and $char_to_index[ \| ]$, and a cumulative frequency array $cum_freq[ \| ]$. The requirements on the latter are that .LB .NP $cum_freq[ i-1 ] ~ >= ~ cum_freq[ i ]$; .NP an attempt is never made to encode a symbol $i$ for which $cum_freq[i-1] ~=~ cum_freq[i]$; .NP $cum_freq[0] ~ <= ~ Max_frequency$. .LE Provided these conditions are satisfied the values in the array need bear no relationship to the actual cumulative symbol frequencies in messages. Encoding and decoding will still work correctly, although encodings will occupy less space if the frequencies are accurate. (Recall our successfully encoding \fIeaii!\fR according to the model of Table\ 1, which does not actually reflect the frequencies in the message.) \c .rh "Fixed models." The simplest kind of model is one in which symbol frequencies are fixed. The first model in Figure\ 4 has symbol frequencies which approximate those of English (taken from a part of the Brown Corpus, Kucera & Francis, 1967). .[ %A Kucera, H. %A Francis, W.N. %D 1967 %T Computational analysis of present-day American English %I Brown University Press %C Providence, RI .] However, bytes which did not occur in that sample have been given frequency counts of 1 in case they do occur in messages to be encoded (so, for example, this model will still work for binary files in which all 256\ bytes occur). Frequencies have been normalized to total 8000. The initialization procedure $start_model( \| )$ simply computes a cumulative version of these frequencies (lines 48-51), having first initialized the translation tables (lines 44-47). Execution speed would be improved if these tables were used to re-order symbols and frequencies so that the most frequent came first in the $cum_freq[ \| ]$ array. Since the model is fixed, the procedure $update_model( \| )$, which is called from both $encode.c$ and $decode.c$, is null. .pp An \fIexact\fR model is one where the symbol frequencies in the message are exactly as prescribed by the model. For example, the fixed model of Figure\ 4 is close to an exact model for the particular excerpt of the Brown Corpus from which it was taken. To be truly exact, however, symbols that did not occur in the excerpt would be assigned counts of 0, not 1 (sacrificing the capability of transmitting messages containing those symbols). Moreover, the frequency counts would not be scaled to a predetermined cumulative frequency, as they have been in Figure\ 4. The exact model may be calculated and transmitted before sending the message. It is shown in Cleary & Witten (1984a) that, under quite general conditions, this will \fInot\fR give better overall compression than adaptive coding, described next. .[ Cleary Witten 1984 enumerative adaptive codes %D 1984a .] .rh "Adaptive models." An adaptive model represents the changing symbol frequencies seen \fIso far\fR in the message. Initially all counts might be the same (reflecting no initial information), but they are updated as each symbol is seen, to approximate the observed frequencies. Provided both encoder and decoder use the same initial values (eg equal counts) and the same updating algorithm, their models will remain in step. The encoder receives the next symbol, encodes it, and updates its model. The decoder identifies it according to its current model, and then updates its model. .pp The second half of Figure\ 4 shows such an adaptive model. This is the type of model recommended for use with Figure\ 3, for in practice it will outperform a fixed model in terms of compression efficiency. Initialization is the same as for the fixed model, except that all frequencies are set to 1. The procedure $update_model(symbol)$ is called by both $encode_symbol( \| )$ and $decode_symbol( \| )$ (Figure\ 3 lines 54 and 151) after each symbol is processed. .pp Updating the model is quite expensive, because of the need to maintain cumulative totals. In the code of Figure\ 4, frequency counts, which must be maintained anyway, are used to optimize access by keeping the array in frequency order \(em an effective kind of self-organizing linear search (Hester & Hirschberg, 1985). .[ Hester Hirschberg 1985 .] $Update_model( \| )$ first checks to see if the new model will exceed the cumulative-frequency limit, and if so scales all frequencies down by a factor of 2 (taking care to ensure that no count scales to zero) and recomputes cumulative values (Figure\ 4, lines\ 29-37). Then, if necessary, $update_model( \| )$ re-orders the symbols to place the current one in its correct rank in the frequency ordering, altering the translation tables to reflect the change. Finally, it increments the appropriate frequency count and adjusts cumulative frequencies accordingly. .sh "Performance" .pp Now consider the performance of the algorithm of Figure\ 3, both in compression efficiency and execution time. .rh "Compression efficiency." In principle, when a message is coded using arithmetic coding, the number of bits in the encoded string is the same as the entropy of that message with respect to the model used for coding. Three factors cause performance to be worse than this in practice: .LB .NP message termination overhead .NP the used of fixed-length rather than infinite-precision arithmetic .NP scaling of counts so that their total is at most $Max_frequency$. .LE None of these effects is significant, as we now show. In order to isolate the effect of arithmetic coding the model will be considered to be exact (as defined above). .pp Arithmetic coding must send extra bits at the end of each message, causing a message termination overhead. Two bits are needed, sent by $done_encoding( \| )$ (Figure\ 3 lines 119-123), in order to disambiguate the final symbol. In cases where a bit-stream must be blocked into 8-bit characters before encoding, it will be necessary to round out to the end of a block. Combining these, an extra 9\ bits may be required. .pp The overhead of using fixed-length arithmetic occurs because remainders are truncated on division. It can be assessed by comparing the algorithm's performance with the figure obtained from a theoretical entropy calculation which derives its frequencies from counts scaled exactly as for coding. It is completely negligible \(em on the order of $10 sup -4$ bits/symbol. .pp The penalty paid by scaling counts is somewhat larger, but still very small. For short messages (less than $2 sup 14$ bytes) no scaling need be done. Even with messages of $10 sup 5$ to $10 sup 6$ bytes, the overhead was found experimentally to be less than 0.25% of the encoded string. .pp The adaptive model of Figure\ 4 scales down all counts whenever the total threatens to exceed $Max_frequency$. This has the effect of weighting recent events more heavily compared with those earlier in the message. The statistics thus tend to track changes in the input sequence, which can be very beneficial. (For example, we have encountered cases where limiting counts to 6 or 7\ bits gives better results than working to higher precision.) \c Of course, this depends on the source being modeled. Bentley \fIet al\fR (1986) consider other, more explicit, ways of incorporating a recency effect. .[ Bentley Sleator Tarjan Wei 1986 locally adaptive %J Communications of the ACM .] .rh "Execution time." The program in Figure\ 3 has been written for clarity, not execution speed. In fact, with the adaptive model of Figure\ 4, it takes about 420\ $mu$s per input byte on a VAX-11/780 to encode a text file, and about the same for decoding. However, easily avoidable overheads such as procedure calls account for much of this, and some simple optimizations increase speed by a factor of 2. The following alterations were made to the C version shown: .LB .NP the procedures $input_bit( \| )$, $output_bit( \| )$, and $bit_plus_follow( \| )$ were converted to macros to eliminate procedure-call overhead; .NP frequently-used quantities were put in register variables; .NP multiplies by two were replaced by additions (C ``+=''); .NP array indexing was replaced by pointer manipulation in the loops at line 189 of Figure\ 3 and lines 49-52 of the adaptive model in Figure\ 4. .LE .pp This mildly-optimized C implementation has an execution time of 214\ $mu$s/262\ $mu$s, per input byte, for encoding/decoding 100,000\ bytes of English text on a VAX-11/780, as shown in Table\ 2. Also given are corresponding figures for the same program on an Apple Macintosh and a SUN-3/75. As can be seen, coding a C source program of the same length took slightly longer in all cases, and a binary object program longer still. The reason for this will be discussed shortly. Two artificial test files were included to allow readers to replicate the results. ``Alphabet'' consists of enough copies of the 26-letter alphabet to fill out 100,000\ characters (ending with a partially-completed alphabet). ``Skew-statistics'' contains 10,000 copies of the string \fIaaaabaaaac\fR\^; it demonstrates that files may be encoded into less than 1\ bit per character (output size of 12,092\ bytes = 96,736\ bits). All results quoted used the adaptive model of Figure\ 4. .pp A further factor of 2 can be gained by reprogramming in assembly language. A carefully optimized version of Figures\ 3 and 4 (adaptive model) was written in both VAX and M68000 assembly language. Full use was made of registers. Advantage was taken of the 16-bit $code_value$ to expedite some crucial comparisons and make subtractions of $Half$ trivial. The performance of these implementations on the test files is also shown in Table\ 2 in order to give the reader some idea of typical execution speeds. .pp The VAX-11/780 assembly language timings are broken down in Table\ 3. These figures were obtained with the U\s-2NIX\s+2 profile facility and are accurate only to within perhaps 10%\(dg. .FN \(dg This mechanism constructs a histogram of program counter values at real-time clock interrupts, and suffers from statistical variation as well as some systematic errors. .EF ``Bounds calculation'' refers to the initial part of $encode_symbol( \| )$ and $decode_symbol( \| )$ (Figure\ 3 lines 90-94 and 190-193) which contain multiply and divide operations. ``Bit shifting'' is the major loop in both the encode and decode routines (lines 95-113 and 194-213). The $cum$ calculation in $decode_symbol( \| )$, which requires a multiply/divide, and the following loop to identify the next symbol (lines\ 187-189), is ``Symbol decode''. Finally, ``Model update'' refers to the adaptive $update_model( \| )$ procedure of Figure\ 4 (lines\ 26-53). .pp As expected, the bounds calculation and model update take the same time for both encoding and decoding, within experimental error. Bit shifting was quicker for the text file than for the C program and object file because compression performance was better. The extra time for decoding over encoding is due entirely to the symbol decode step. This takes longer in the C program and object file tests because the loop of line\ 189 was executed more often (on average 9\ times, 13\ times, and 35\ times respectively). This also affects the model update time because it is the number of cumulative counts which must be incremented in Figure\ 4 lines\ 49-52. In the worst case, when the symbol frequencies are uniformly distributed, these loops are executed an average of 128 times. Worst-case performance would be improved by using a more complex tree representation for frequencies, but this would likely be slower for text files. .sh "Some applications" .pp Applications of arithmetic coding are legion. By liberating \fIcoding\fR with respect to a model from the \fImodeling\fR required for prediction, it encourages a whole new view of data compression (Rissanen & Langdon, 1981). .[ Rissanen Langdon 1981 Universal modeling and coding .] This separation of function costs nothing in compression performance, since arithmetic coding is (practically) optimal with respect to the entropy of the model. Here we intend to do no more than suggest the scope of this view by briefly considering .LB .NP adaptive text compression .NP non-adaptive coding .NP compressing black/white images .NP coding arbitrarily-distributed integers. .LE Of course, as noted earlier, greater coding efficiencies could easily be achieved with more sophisticated models. Modeling, however, is an extensive topic in its own right and is beyond the scope of this paper. .pp .ul Adaptive text compression using single-character adaptive frequencies shows off arithmetic coding to good effect. The results obtained using the program of Figures\ 3 and 4 vary from 4.8\-5.3\ bit/char for short English text files ($10 sup 3$\ to $10 sup 4$ bytes) to 4.5\-4.7\ bit/char for long ones ($10 sup 5$ to $10 sup 6$ bytes). Although adaptive Huffman techniques do exist (eg Gallagher, 1978; Cormack & Horspool, 1984) they lack the conceptual simplicity of arithmetic coding. .[ Gallagher 1978 variations on a theme by Huffman .] .[ Cormack Horspool 1984 adaptive Huffman codes .] While competitive in compression efficiency for many files, they are slower. For example, Table\ 4 compares the performance of the mildly-optimized C implementation of arithmetic coding with that of the U\s-2NIX\s+2 \fIcompact\fR program which implements adaptive Huffman coding using a similar model\(dg. .FN \(dg \fICompact\fR's model is essentially the same for long files (like those of Table\ 4) but is better for short files than the model used as an example in this paper. .EF Casual examination of \fIcompact\fR indicates that the care taken in optimization is roughly comparable for both systems, yet arithmetic coding halves execution time. Compression performance is somewhat better with arithmetic coding on all the example files. The difference would be accentuated with more sophisticated models that predict symbols with probabilities approaching one under certain circumstances (eg letter ``u'' following ``q''). .pp .ul Non-adaptive coding can be performed arithmetically using fixed, pre-specified models like that in the first part of Figure\ 4. Compression performance will be better than Huffman coding. In order to minimize execution time, the total frequency count, $cum_freq[0]$, should be chosen as a power of two so the divisions in the bounds calculations (Figure\ 3 lines 91-94 and 190-193) can be done as shifts. Encode/decode times of around 60\ $mu$s/90\ $mu$s should then be possible for an assembly language implementation on a VAX-11/780. A carefully-written implementation of Huffman coding, using table look-up for encoding and decoding, would be a bit faster in this application. .pp .ul Compressing black/white images using arithmetic coding has been investigated by Langdon & Rissanen (1981), who achieved excellent results using a model which conditioned the probability of a pixel's being black on a template of pixels surrounding it. .[ Langdon Rissanen 1981 compression of black-white images .] The template contained a total of ten pixels, selected from those above and to the left of the current one so that they precede it in the raster scan. This creates 1024 different possible contexts, and for each the probability of the pixel being black was estimated adaptively as the picture was transmitted. Each pixel's polarity was then coded arithmetically according to this probability. A 20%\-30% improvement in compression was attained over earlier methods. To increase coding speed Langdon & Rissanen used an approximate method of arithmetic coding which avoided multiplication by representing probabilities as integer powers of 1/2. Huffman coding cannot be directly used in this application, as it never compresses with a two-symbol alphabet. Run-length coding, a popular method for use with two-valued alphabets, provides another opportunity for arithmetic coding. The model reduces the data to a sequence of lengths of runs of the same symbol (eg for picture coding, run-lengths of black followed by white followed by black followed by white ...). The sequence of lengths must be transmitted. The CCITT facsimile coding standard (Hunter & Robinson, 1980), for example, bases a Huffman code on the frequencies with which black and white runs of different lengths occur in sample documents. .[ Hunter Robinson 1980 facsimile .] A fixed arithmetic code using these same frequencies would give better performance; adapting the frequencies to each particular document would be better still. .pp .ul Coding arbitrarily-distributed integers is often called for when using more sophisticated models of text, image, or other data. Consider, for instance, Bentley \fIet al\fR's (1986) locally-adaptive data compression scheme, in which the encoder and decoder cache the last $N$ different words seen. .[ Bentley Sleator Tarjan Wei 1986 locally adaptive %J Communications of the ACM .] A word present in the cache is transmitted by sending the integer cache index. Words not in the cache are transmitted by sending a new-word marker followed by the characters of the word. This is an excellent model for text in which words are used frequently over short intervals and then fall into long periods of disuse. Their paper discusses several variable-length codings for the integers used as cache indexes. Arithmetic coding allows \fIany\fR probability distribution to be used as the basis for a variable-length encoding, including \(em amongst countless others \(em the ones implied by the particular codes discussed there. It also permits use of an adaptive model for cache indexes, which is desirable if the distribution of cache hits is difficult to predict in advance. Furthermore, with arithmetic coding, the code space allotted to the cache indexes can be scaled down to accommodate any desired probability for the new-word marker. .sh "Acknowledgement" .pp Financial support for this work has been provided by the Natural Sciences and Engineering Research Council of Canada. .sh "References" .sp .in+4n .[ $LIST$ .] .in 0 .bp .sh "APPENDIX: Proof of decoding inequality" .sp Using 1-letter abbreviations for $cum_freq$, $symbol$, $low$, $high$, and $value$, suppose .LB $c[s] ~ <= ~~ left f {(v-l+1) times c[0] ~-~ 1} over {h-l+1} right f ~~ < ~ c[s-1]$; .LE in other words, .LB .ta \n(.lu-\n(.iuR $c[s] ~ <= ~~ {(v-l+1) times c[0] ~-~ 1} over {r} ~~-~~ epsilon ~~ <= ~ c[s-1] ~-~1$, (1) .LE .ta 8n where $r ~=~ h-l+1$, $0 ~ <= ~ epsilon ~ <= ~ {r-1} over r $. .sp (The last inequality of (1) derives from the fact that $c[s-1]$ must be an integer.) \c Then we wish to show that $l' ~ <= ~ v ~ <= ~ h'$, where $l'$ and $h'$ are the updated values for $low$ and $high$ as defined below. .sp .ta \w'(a) 'u (a) $l' ~ == ~~ l ~+~~ left f {r times c[s]} over c[0] right f ~~ mark <= ~~ l ~+~~ {r} over c[0] ~ left [ ~ {(v-l+1) times c[0] ~-~ 1} over {r} ~~ - ~ epsilon ~ right ]$ from (1), .sp 0.5 $lineup <= ~~ v ~ + ~ 1 ~ - ~ 1 over c[0]$ , .sp 0.5 so $l' ~ <= ~~ v$ since both $v$ and $l'$ are integers and $c[0] > 0$. .sp (b) $h' ~ == ~~ l ~+~~ left f {r times c[s-1]} over c[0] right f ~~-~1~~ mark >= ~~ l ~+~~ {r} over c[0] ~ left [ ~ {(v-l+1) times c[0] ~-~ 1} over {r} ~~ + ~ 1 ~ - ~ epsilon ~ right ] ~~ - ~ 1 $ from (1), .sp 0.5 $lineup >= ~~ v ~ + ~~ r over c[0] ~ left [ ~ - ~ 1 over r ~+~ 1 ~-~~ r-1 over r right ] ~~ = ~~ v$. .bp .sh "Captions for tables" .sp .nf .ta \w'Figure 1 'u Table 1 Example fixed model for alphabet {\fIa, e, i, o, u, !\fR} Table 2 Results for encoding and decoding 100,000-byte files Table 3 Breakdown of timings for VAX-11/780 assembly language version Table 4 Comparison of arithmetic and adaptive Huffman coding .fi .sh "Captions for figures" .sp .nf .ta \w'Figure 1 'u Figure 1 (a) Representation of the arithmetic coding process (b) Like (a) but with the interval scaled up at each stage Figure 2 Pseudo-code for the encoding and decoding procedures Figure 3 C implementation of arithmetic encoding and decoding Figure 4 Fixed and adaptive models for use with Figure 3 Figure 5 Scaling the interval to prevent underflow .fi .bp 0 .ev2 .nr x2 \w'symbol'/2 .nr x3 (\w'symbol'/2)+0.5i+(\w'probability'/2) .nr x4 (\w'probability'/2)+0.5i .nr x5 (\w'[0.0, ' .nr x1 \n(x2+\n(x3+\n(x4+\n(x5+\w'0.0)' .nr x0 (\n(.l-\n(x1)/2 .in \n(x0u .ta \n(x2uC +\n(x3uC +\n(x4u +\n(x5u \l'\n(x1u' .sp symbol probability \0\0range \l'\n(x1u' .sp \fIa\fR 0.2 [0, 0.2) \fIe\fR 0.3 [0.2, 0.5) \fIi\fR 0.1 [0.5, 0.6) \fIo\fR 0.2 [0.6, 0.8) \fIu\fR 0.1 [0.8, 0.9) \fI!\fR 0.1 [0.9, 1.0) \l'\n(x1u' .sp .in 0 .FE "Table 1 Example fixed model for alphabet {\fIa, e, i, o, u, !\fR}" .bp 0 .ev2 .nr x1 0.5i+\w'\fIVAX object program\fR '+\w'100,000 '+\w'time ($mu$s) '+\w'time ($mu$s) '+\w'time ($mu$s) '+\w'time ($mu$s) '+\w'time ($mu$s) '+\w'time ($mu$s)' .nr x0 (\n(.l-\n(x1)/2 .in \n(x0u .ta 0.5i +\w'\fIVAX object program\fR 'u +\w'100,000 'u +\w'time ($mu$s) 'u +\w'time ($mu$s) 'u +\w'time ($mu$s) 'u +\w'time ($mu$s) 'u +\w'time ($mu$s) 'u \l'\n(x1u' .sp \0\0VAX-11/780 \0\0\0Macintosh \0\0\0\0SUN-3/75 output encode decode encode decode encode decode (bytes) time ($mu$s) time ($mu$s) time ($mu$s) time ($mu$s) time ($mu$s) time ($mu$s) \l'\n(x1u' .sp Mildly optimized C implementation .sp \fIText file\fR \057718 \0\0214 \0\0262 \0\0687 \0\0881 \0\0\098 \0\0121 \fIC program\fR \062991 \0\0230 \0\0288 \0\0729 \0\0950 \0\0105 \0\0131 \fIVAX object program\fR \073501 \0\0313 \0\0406 \0\0950 \01334 \0\0145 \0\0190 \fIAlphabet\fR \059292 \0\0223 \0\0277 \0\0719 \0\0942 \0\0105 \0\0130 \fISkew-statistics\fR \012092 \0\0143 \0\0170 \0\0507 \0\0645 \0\0\070 \0\0\085 .sp Carefully optimized assembly language implementation .sp \fIText file\fR \057718 \0\0104 \0\0135 \0\0194 \0\0243 \0\0\046 \0\0\058 \fIC program\fR \062991 \0\0109 \0\0151 \0\0208 \0\0266 \0\0\051 \0\0\065 \fIVAX object program\fR \073501 \0\0158 \0\0241 \0\0280 \0\0402 \0\0\075 \0\0107 \fIAlphabet\fR \059292 \0\0105 \0\0145 \0\0204 \0\0264 \0\0\051 \0\0\065 \fISkew-statistics\fR \012092 \0\0\063 \0\0\081 \0\0126 \0\0160 \0\0\028 \0\0\036 \l'\n(x1u' .sp 2 .nr x0 \n(.l .ll \n(.lu-\n(.iu .fi .in \w'\fINotes:\fR 'u .ti -\w'\fINotes:\fR 'u \fINotes:\fR\ \ \c Times are measured in $mu$s per byte of uncompressed data. .sp 0.5 The VAX-11/780 had a floating-point accelerator, which reduces integer multiply and divide times. .sp 0.5 The Macintosh uses an 8\ MHz MC68000 with some memory wait states. .sp 0.5 The SUN-3/75 uses a 16.67\ MHz MC68020. .sp 0.5 All times exclude I/O and operating system overhead in support of I/O. VAX and SUN figures give user time from the U\s-2NIX\s+2 \fItime\fR command; on the Macintosh I/O was explicitly directed to an array. .sp 0.5 The 4.2BSD C compiler was used for VAX and SUN; Aztec C 1.06g for Macintosh. .sp .ll \n(x0u .nf .in 0 .FE "Table 2 Results for encoding and decoding 100,000-byte files" .bp 0 .ev2 .nr x1 \w'\fIVAX object program\fR '+\w'Bounds calculation '+\w'time ($mu$s) '+\w'time ($mu$s)' .nr x0 (\n(.l-\n(x1)/2 .in \n(x0u .ta \w'\fIVAX object program\fR 'u +\w'Bounds calculation 'u +\w'time ($mu$s) 'u +\w'time ($mu$s)'u \l'\n(x1u' .sp encode decode time ($mu$s) time ($mu$s) \l'\n(x1u' .sp \fIText file\fR Bounds calculation \0\0\032 \0\0\031 Bit shifting \0\0\039 \0\0\030 Model update \0\0\029 \0\0\029 Symbol decode \0\0\0\(em \0\0\045 Other \0\0\0\04 \0\0\0\00 \0\0\l'\w'100'u' \0\0\l'\w'100'u' \0\0104 \0\0135 .sp \fIC program\fR Bounds calculation \0\0\030 \0\0\028 Bit shifting \0\0\042 \0\0\035 Model update \0\0\033 \0\0\036 Symbol decode \0\0\0\(em \0\0\051 Other \0\0\0\04 \0\0\0\01 \0\0\l'\w'100'u' \0\0\l'\w'100'u' \0\0109 \0\0151 .sp \fIVAX object program\fR Bounds calculation \0\0\034 \0\0\031 Bit shifting \0\0\046 \0\0\040 Model update \0\0\075 \0\0\075 Symbol decode \0\0\0\(em \0\0\094 Other \0\0\0\03 \0\0\0\01 \0\0\l'\w'100'u' \0\0\l'\w'100'u' \0\0158 \0\0241 \l'\n(x1u' .in 0 .FE "Table 3 Breakdown of timings for VAX-11/780 assembly language version" .bp 0 .ev2 .nr x1 \w'\fIVAX object program\fR '+\w'100,000 '+\w'time ($mu$s) '+\w'time ($mu$s) '+\w'100,000 '+\w'time ($mu$s) '+\w'time ($mu$s)' .nr x0 (\n(.l-\n(x1)/2 .in \n(x0u .ta \w'\fIVAX object program\fR 'u +\w'100,000 'u +\w'time ($mu$s) 'u +\w'time ($mu$s) 'u +\w'100,000 'u +\w'time ($mu$s) 'u +\w'time ($mu$s)'u \l'\n(x1u' .sp \0\0\0\0\0\0Arithmetic coding \0\0\0Adaptive Huffman coding output encode decode output encode decode (bytes) time ($mu$s) time ($mu$s) (bytes) time ($mu$s) time ($mu$s) \l'\n(x1u' .sp \fIText file\fR \057718 \0\0214 \0\0262 \057781 \0\0550 \0\0414 \fIC program\fR \062991 \0\0230 \0\0288 \063731 \0\0596 \0\0441 \fIVAX object program\fR \073546 \0\0313 \0\0406 \076950 \0\0822 \0\0606 \fIAlphabet\fR \059292 \0\0223 \0\0277 \060127 \0\0598 \0\0411 \fISkew-statistics\fR \012092 \0\0143 \0\0170 \016257 \0\0215 \0\0132 \l'\n(x1u' .sp 2 .nr x0 \n(.l .ll \n(.lu-\n(.iu .fi .in +\w'\fINotes:\fR 'u .ti -\w'\fINotes:\fR 'u \fINotes:\fR\ \ \c Mildly optimized C implementation used for arithmetic coding .sp 0.5 U\s-2NIX\s+2 \fIcompact\fR used for adaptive Huffman coding .sp 0.5 Times are for a VAX-11/780, and exclude I/O and operating system overhead in support of I/O. .sp .ll \n(x0u .nf .in 0 .FE "Table 4 Comparison of arithmetic and adaptive Huffman coding" .pn 0 .ls1 .EQ delim $$ .EN .ev1 .ps-2 .vs-2 .ev \& .sp 10 .ps+4 .ce COMPUTER (IN)SECURITY \(em .sp .ce INFILTRATING OPEN SYSTEMS .ps-4 .sp4 .ce Ian H. Witten .sp2 .ce4 Department of Computer Science The University of Calgary 2500 University Drive NW Calgary, Canada T2N 1N4 .sp2 .ce2 November 1986 Revised March 1987 .bp 1 .ls 2 .pp Shared computer systems today are astonishingly insecure. And users, on the whole, are blithely unaware of the weaknesses of the systems in which they place \(em or rather, misplace \(em their trust. Taken literally, of course, it is meaningless to ``trust'' a computer system as such, for machines are neither trustworthy nor untrustworthy; these are human qualities. In trusting a system one is effectively trusting all those who create and alter it, in other words, all who have access (whether licit or illicit). Security is a fundamentally \fIhuman\fP issue. .pp This article aims not to solve security problems but to raise reader consciousness of the multifarious cunning ways that systems can be infiltrated, and the subtle but devastating damage that an unscrupulous infiltrator can wreak. It is comforting, but highly misleading, to imagine that technical means of enforcing security have guaranteed that the systems we use are safe. It is true that in recent years some ingenious procedures have been invented to preserve security. For example, the advent of ``one-way functions'' (explained below) has allowed the password file, once a computer system's central stronghold, to be safely exposed to casual inspection by all and sundry. But despite these innovations, astonishing loopholes exist in practice. .pp There are manifest advantages in ensuring security by technical means rather than by keeping things secret. Not only do secrets leak, but as individuals change projects, join or leave the organization, become promoted and so on, they need to learn new secrets and forget old ones. With physical locks one can issue and withdraw keys to reflect changing security needs. But in computer systems, the keys constitute information which can be given out but not taken back, because no-one can force people to forget. In practice, such secrets require considerable administration to maintain properly. And in systems where security is maintained by tight control of information, .ul quis custodiet ipsos custodes \(em who will guard the guards themselves? .pp There is a wide range of simple insecurities that many systems suffer. These are, in the main, exacerbated in open systems where information and programs are shared among users \(em just those features that characterize pleasant and productive working environments. The saboteur's basic tool is the Trojan horse, a widely trusted program which has been surreptitiously modified to do bad things in secret. ``Bad things'' range from minor but rankling irritations through theft of information to holding users to ransom. The inevitable fragilities of operating systems can be exploited by constructing programs which behave in some ways like primitive living organisms. Programs can be written which spread bugs like an epidemic. They hide in binary code, effectively undetectable (because nobody ever examines binaries). They can remain dormant for months or years, perhaps quietly and imperceptibly infiltrating their way into the very depths of a system, then suddenly pounce, causing irreversible catastrophe. A clever and subtle bug\(dg can survive recompilation despite the fact that there is no record of it in the source program. .FN \(dg Throughout this article the word ``bug'' is meant to bring to mind a concealed snooping device as in espionage, or a micro-organism carrying disease as in biology, rather than an inadvertent programming error. .EF This is the ultimate parasite. It cannot be detected because it lives only in binary code. And yet it cannot be wiped out by recompiling the source program! We might wonder whether these techniques, which this article develops and explains in the context of multi-user timesharing operating systems, pose any threats to computer networks or even stand-alone micros. .pp Although the potential has existed for decades, the possibility of the kind of ``deviant'' software described here has been recognized only recently. Or has it? Probably some in the world of computer wizards and sorcerers have known for years how systems can be silently, subtly infiltrated \(em and concealed the information for fear that it might be misused (or for other reasons). But knowledge of the techniques is spreading nevertheless, and I believe it behooves us all \(em professionals and amateurs alike \(em to understand just how our continued successful use of computer systems hangs upon a thread of trust. Those who are ignorant of the possibilities of sabotage can easily be unknowingly duped by an unscrupulous infiltrator. .pp The moral is simple. Computer security is a human business. One way of maintaining security is to keep things secret, trusting people (the very people who can do you most harm) not to tell. The alternative is to open up the system and rely on technical means of ensuring security. But a system which is really ``open'' is also open to abuse. The more sharing and productive the environment, the more potential exists for damage. You have to trust your fellow users, and educate yourself. If mutual trust is the cornerstone of computer security, we'd better know it! .sh "The trend towards openness" .pp Many people believe that computer systems can maintain security not by keeping secrets but by clever technical mechanisms. Such devices include electronic locks and keys, and schemes for maintaining different sets of ``permissions'' or ``privileges'' for each user. The epitome of this trend towards open systems is the well-known \s-2UNIX\s+2 operating system, whose developers, Dennis Ritchie and Ken Thompson, strove to design a clean, elegant piece of software that could be understood, maintained, and modified by users. (In 1983 they received the prestigious ACM Turing Award for their work.) \c Ken Thompson has been one of the prime contributors to our knowledge of computer (in)security, and was responsible for much of the work described in this article. .pp The most obvious sense in which the \s-2UNIX\s+2 system is ``open'' is illustrated by looking at its password file. Yes, there is nothing to stop you from looking at this file! Each registered user has a line in it, and Figure\ 1 shows mine. It won't help you to impersonate me, however, because what it shows in the password field is not my password but a scrambled version of it. There is a program which computes encrypted passwords from plain ones, and that is how the system checks my identity when I log in. But the program doesn't work in reverse \(em it's what is called a ``one-way function'' (see Panel\ 1). It is effectively impossible to find the plain version from the encrypted one, even if you know exactly what the encryption procedure does and try to work carefully backward through it. \fINobody\fR can recover my plain password from the information stored in the computer. If I forget it, not even the system manager can find out what it is. The best that can be done is to reset my password to some standard one, so that I can log in and change it to a new secret password. (Needless to say this creates a window of opportunity for an imposter.) \c The system keeps no secrets. Only I do. .pp Before people knew about one-way functions, computer systems maintained a password file which gave everyone's plain password for the login procedure to consult. This was the prime target for anyone who tried to break security, and the bane of system managers because of the completely catastrophic nature of a leak. Systems which keep no secrets avoid an unnecessary Achilles heel. .pp Another sense in which \s-2UNIX\s+2 is ``open'' is the accessibility of its source code. The software, written in the language "C", has been distributed (to universities) in source form so that maintenance can be done locally. The computer science research community has enjoyed numerous benefits from this enlightened policy (one is that we can actually look at some of the security problems discussed in this article). Of course, in any other system there will inevitably be a large number of people who have or have had access to the source code \(em even though it may not be publicly accessible. Operating systems are highly complex pieces of technology, created by large teams of people. A determined infiltrator may well be able to gain illicit access to source code. Making it widely available has the very positive effect of bringing the problems out into the open and offering them up for public scrutiny. .pp Were it attainable, perfect secrecy would offer a high degree of security. Many people feel that technical innovations like one-way functions and open password files provide comparable protection. The aim of this article is to show that this is a dangerous misconception. In practice, security is often severely compromised by people who have intimate knowledge of the inner workings of the system \(em precisely the people you rely on to \fIprovide\fR the security. This does not cause problems in research laboratories because they are founded on mutual trust and support. But in commercial environments, it is vital to be aware of any limitations on security. We must face the fact that in a hostile and complex world, computer security is best preserved by maintaining secrecy. .sh "A pot-pourri of security problems" .pp Here are a few simple ways that security might be compromised. .rh "Guessing a particular user's password." Whether your password is stored in a secret file or encrypted by a one-way function first, it offers no protection if it can easily be guessed. This will be hard if it is chosen at random from a large enough set. But for a short sequence of characters from a restricted alphabet (like the lower-case letters), an imposter could easily try all possibilities. And in an open system which gives access to the password file and one-way function, this can be done mechanically, by a program! .pp In Figure\ 2, the number of different passwords is plotted against the length of the password, for several different sets of characters. For example, there are about ten million ($10 sup 7$) possibilities for a 5-character password chosen from the lower-case letters. This may seem a lot, but if it takes 1\ msec to try each one, they can all be searched in about 3\ hours. If 5-character passwords are selected from the 62 alphanumerics, there are more than 100 times as many and the search would take over 10\ days. .pp To make matters worse, people have a strong propensity to choose as passwords such things as .LB .NP English words .NP English words spelled backwards .NP first names, last names, street names, city names .NP the above with initial upper-case letters .NP valid car license numbers .NP room numbers, social security numbers, telephone numbers, etc. .LE Of course, this isn't particularly surprising since passwords have to be mnemonic in order to be remembered! But it makes it easy for an enterprising imposter to gather a substantial collection of candidates (from dictionaries, mailing lists, etc) and search them for your password. At 1\ msec per possibility, it takes only 4\ minutes to search a 250,000-word commercial dictionary. .pp A study some years ago of a collection of actual passwords that people used to protect their accounts revealed the amazing breakdown reproduced in Figure\ 3. Most fell into one of the categories discussed, leaving less than 15% of passwords which were hard to guess. Where does your own password stand in the pie diagram? .rh "Finding any valid password." There is a big difference between finding a particular person's password and finding a valid password for any user. You could start searching through the candidates noted above until you found one which, when encrypted, matched one of the entries in the password file. That way you find the most vulnerable user, and there are almost certain to be some lazy and crazy enough to use easily-guessable passwords, four-letter words, or whatever. Hashing techniques make it almost as quick to check a candidate against a group of encrypted passwords as against a single one. .pp A technique called ``salting'' protects against this kind of attack. Whenever a user's password is initialized or changed, a small random number called the ``salt'' is generated (perhaps from the time of day). Not only is this combined with the password when it is encrypted, but as Figure\ 1 shows it is also stored in the password file for everyone to see. Every time someone claiming to be that user logs in, the salt is combined with the password offered before being encrypted and compared with whatever is stored in the password file. For example, say my password was ``w#xs27'' (it isn't!). If the salt is ``U6'' (as in Figure\ 1), the system will apply its one-way function to ``w#xs27U6'' to get the encrypted password. .pp Since all can see the salt, it is no harder for anyone to guess an individual user's password. One can salt guesses just as the system does. But it \fIis\fR harder to search a group of passwords, since the salt will be different for each, rendering it meaningless to compare a single encrypted password against all those in the group. Suppose you were checking to see if anyone had the password ``hello''. Without salting, you simply apply the one-way function to this word and compare the result with everyone's encrypted password. But with salting it's not so easy, since to see if my password is ``hello'' you must encrypt ``helloU6'', and the salt is different for everyone. .rh "Forced-choice passwords." The trouble with letting users choose their own passwords is that they often make silly, easily-guessed, choices. Many systems attempt to force people to choose more ``random'' passwords, and force them to change their password regularly. All these attempts seem to be complete failures. The fundamental problem is that people have to be able to remember their passwords, because security is immediately compromised if they are written down. .pp There are many amusing anecdotes about how people thwart systems that attempt to dictate when they have to change their passwords. I had been using a new system for some weeks when it insisted that I change my password. Resenting it ordering me about, I gave my old password as the new one. But it was programmed to detect this ruse and promptly told me so. I complained to the user sitting beside me. ``I know,'' she said sympathetically. ``What I always do is change it to something else and then immediately change it back again!'' \c Another system remembered your last several passwords, and insisted on a once-a-month change. So people began to use the name of the current month as their password! .rh "Wiretaps." Obviously any kind of password protection can be thwarted by a physical wiretap. All one has to do is watch as you log in and make a note of your password. The only defense is encryption at the terminal. Even then you have to be careful to ensure that someone can't intercept your encrypted password and pose as you later on by sending this \fIencrypted\fR string to the computer \(em after all, this is what the computer sees when you log in legitimately! To counter this, the encryption can be made time-dependent so that the same password translates to different strings at different times. .pp Assuming that you, like 99.9% of the rest of us, don't go to the trouble of terminal encryption, when was the last time you checked the line between your office terminal and the computer for a physical wiretap? .rh "Search paths." We will see shortly that you place yourself completely at the mercy of other users whenever you execute their programs, and they can do some really nasty things like spreading infection to your files. However, you don't necessarily have to execute someone else's program overtly, for many systems make it easy to use other people's programs without even realizing it. This is usually a great advantage, for you can install programs so that you or others can invoke them just like ordinary system programs, thereby creating personalized environments. .pp Figure\ 4 shows part of the file hierarchy in our system. The whole hierarchy is immense \(em I alone have something like 1650 files, organized into 200 of my own directories under the ``ian'' node shown in the Figure, and there are hundreds of other users \(em and what is shown is just a very small fragment. Users can set up a ``search path'' which tells the system where to look for programs they invoke. For example, my search path includes the 6 places that are circled. Whenever I ask for a program to be executed, the system seeks it in these places. It also searches the ``current directory'' \(em the one where I happen to be at the time. .pp To make it more convenient for you to set up a good working environment, it is easy to put someone else's file directories on your search path. But then they can do arbitrary damage to you, sometimes completely accidentally. For example, I once installed a spreadsheet calculator called ``sc'' in one of my directories. Unknown to me, another user suddenly found that the Simula compiler stopped working and entered a curious mode where it cleared his VDT screen and wrote a few incomprehensible characters on it. There was quite a hiatus. The person who maintained the Simula compiler was away, but people could see no reason for the compiler to have been altered. Of course, told like this it is obvious that the user had my directory on his search path and I had created a name conflict with \fIsc\fR, the Simula compiler. But it was not obvious to the user, who rarely thought about the search path mechanism. And I never use the Simula compiler and had created the conflict in all innocence. Moreover, I didn't even know that other users had my directory on their search paths! This situation caused only frustration before the problem was diagnosed and fixed. But what if I were a bad guy who had created the new \fIsc\fR program to harbor a nasty bug (say one which deleted the hapless user's files)? .pp You don't necessarily have to put someone on your search path to run the risk of executing their programs accidentally. As noted above, the system (usually) checks your current working directory for the program first. Whenever you change your current workplace to another's directory, you might without realizing it begin to execute programs that had been planted there. .pp Suppose a hacker plants a program with the same name as a common utility program. How would you find out? The \s-2UNIX\s+2 \fIls\fR command lists all the files in a directory. Perhaps you could find imposters using \fIls\fR? \(em Sorry. The hacker might have planted another program, called \fIls\fR, which simulated the real \fIls\fR exactly except that it lied about its own existence and that of the planted command! The \fIwhich\fR command tells you which version of a program you are using \(em whether it comes from the current directory, another user's directory, or a system directory. Surely this would tell you? \(em Sorry. The hacker might have written another \fIwhich\fR which lied about itself, about \fIls\fR, and about the plant. .pp If you put someone else on your search path, or change into their directory, you're implicitly trusting them. You are completely at a user's mercy when you execute one of their programs, whether accidentally or on purpose. .rh "Programmable terminals." Things are even worse if you use a ``programmable'' terminal. Then, the computer can send a special sequence of characters to command the terminal to transmit a particular message whenever a particular key is struck. For example, on the terminal I am using to type this article, you could program the \s-2RETURN\s+2 key to transmit the message ``hello'' whenever it is pressed. All you need to do to accomplish this is to send my terminal the character sequence .LB \s-2ESCAPE\s+2 P ` + { H E L L O } \s-2ESCAPE\s+2 .LE (\s-2ESCAPE\s+2 stands for the \s-2ASCII\s+2 escape character, decimal 27, which is invoked by a key labeled ``Esc''.) \c This is a mysterious and ugly incantation, and I won't waste time explaining the syntax. But it has an extraordinary effect. Henceforth every time I hit the return key, my terminal will transmit the string ``hello'' instead of the normal \s-2RETURN\s+2 code. And when it receives this string, the computer I am connected to will try to execute a program called ``hello''! .pp This is a terrible source of insecurity. Someone could program my terminal so that it executed one of \fItheir\fR programs whenever I pressed \s-2RETURN\s+2. That program could reinstate the \s-2RETURN\s+2 code to make it appear afterwards as though nothing had happened. Before doing that, however, it could (for example) delete all my files. .pp The terminal can be reprogrammed just by sending it an ordinary character string. The string could be embedded in a file, so that the terminal would be bugged whenever I viewed the file. It might be in a seemingly innocuous message; simply reading mail could get me in trouble! It could even be part of a file \fIname\fR, so that the bug would appear whenever I listed a certain directory \(em not making it my current directory, as was discussed above, but just \fIinspecting\fR it. But I shouldn't say ``appear'', for that's exactly what it might not do. I may never know that anything untoward had occurred. .pp How can you be safe? The programming sequences for my terminal all start with \s-2ESCAPE\s+2, which is an \s-2ASCII\s+2 control character. Anyone using such a terminal should whenever possible work through a program that exposes control characters. By this I mean a program that monitors output from the computer and translates the escape code to something like the 5-character sequence ``''. Then a raw \s-2ESCAPE\s+2 itself never gets sent to the terminal, so the reprogramming mechanism is never activated. .pp Not only should you avoid executing programs written by people you don't trust, but in extreme cases you should take the utmost care in \fIany\fR interaction with untrustworthy people \(em even reading their electronic mail. .sh "Trojan horses: getting under the skin" .pp The famous legend tells of a huge, hollow wooden horse filled with Greek soldiers which was left, ostensibly as a gift, at the gates of the city of Troy. When it was brought inside, the soldiers came out at night and opened the gates to the Greek army, which destroyed the city. To this day, something used to subvert an organization from within by abusing misplaced trust is called a Trojan horse. .pp In any computer system for which security is a concern, there must be things that need protecting. These invariably constitute some kind of information (since the computer is, at heart, an information processor), and such information invariably outlasts a single login session and is therefore stored in the computer's file system. Consequently the file system is the bastion to be kept secure, and will be the ultimate target of any invader. Some files contain secret information that not just anyone may read, others are vital to the operation of an organization and must at all costs be preserved from surreptitious modification or deletion. A rather different thing that must be protected is the ``identity'' of each user. False identity could be exploited by impersonating someone else in order to send mail. Ultimately, of course, this is the same as changing data in mailbox files. Conversely, since for each and every secret file \fIsomeone\fR must have permission to read and alter it, preserving file system security requires that identities be kept intact. .rh "What might a Trojan horse do?" The simplest kind of Trojan horse turns a common program like a text editor into a security threat by implanting code in it which secretly reads or alters files it is not intended to. An editor normally has access to all the user's files (otherwise they couldn't be altered). In other words, the program runs with the user's own privileges. A Trojan horse in it can do anything the user himself could do, including reading, writing, or deleting files. .pp It is easy to communicate stolen information back to the person who bugged the editor. Most blatantly, the access permission of a secret file could be changed so that anyone can read it. Alternatively the file could be copied temporarily to disk \(em most systems allocate scratch disk space for programs that need to create temporary working files \(em and given open access. Another program could continually check for it and, when it appeared, read and immediately delete it to destroy the trace. More subtle ways of communicating small amounts of information might be to rearrange disk blocks physically so that their addresses formed a code, or to signal with the run/idle status of the process to anyone who monitored the system's job queue. Clearly, any method of communication will be detectable by others \(em in theory. But so many things go on in a computer system that messages can easily be embedded in the humdrum noise of countless daily events. .pp Trojan horses don't necessarily do bad things. Some are harmless but annoying, created to meet a challenge rather than to steal secrets. One such bug, the ``cookie monster'', signals its presence by announcing to the unfortunate user ``I want a cookie''. Merely typing the word ``cookie'' will satiate the monster and cause it to disappear as though nothing had happened. But if the user ignores the request, although the monster appears to go away it returns some minutes later with ``I'm hungry; I really want a cookie''. As time passes the monster appears more and more frequently with increasingly insistent demands, until it makes a serious threat: ``I'll remove some of your files if you don't give me a cookie''. At this point the poor user realizes that the danger is real and is effectively forced into appeasing the monster's appetite by supplying the word ``cookie''. Although an amusing story to tell, it is not pleasant to imagine being intimidated by an inanimate computer program. .pp A more innocuous Trojan horse, installed by a system programmer to commemorate leaving her job, occasionally drew a little teddy-bear on the graph-plotter. This didn't happen often (roughly every tenth plot), and even when it did it occupied a remote corner of the paper, well outside the normal plotting area. But although they initially shared the joke, management soon ceased to appreciate the funny side and ordered the programmer's replacement to get rid of it. Unfortunately the bug was well disguised and many fruitless hours were spent seeking it in vain. Management grew more irate and the episode ended when the originator received a desperate phone-call from her replacement, whose job was by now at risk, begging her to divulge the secret! .rh "Installing a Trojan horse." The difficult part is installing the Trojan horse into a trusted program. System managers naturally take great care that only a few people get access to suitable host programs. If anyone outside the select circle of ``system people'' is ever given an opportunity to modify a commonly-used program like a text editor (for example, to add a new feature) all changes will be closely scrutinized by the system manager before being installed. Through such measures the integrity of system programs is preserved. Note, however, that constant vigilance is required, for once bugged, a system can remain compromised forever. The chances of a slip-up may be tiny, but the consequences are unlimited. .pp One good way of getting bugged code installed in the system is to write a popular utility program. As its user community grows, more and more people will copy the program into their disk areas so that they can use it easily. Eventually, if it is successful, the utility will be installed as a ``system'' program. This will be done to save disk space \(em so that the users can delete their private versions \(em and perhaps also because the code can now be made ``sharable'' in that several simultaneous users can all execute a single copy in main memory. As a system program the utility may inherit special privileges, and so be capable of more damage. It may also be distributed to other sites, spreading the Trojan horse far and wide. .pp Installing a bug in a system utility like a text editor puts anyone who uses that program at the mercy of whoever perpetrated the bug. But it doesn't allow that person to get in and do damage at any time, for nothing can be done to a user's files until that user invokes the bugged program. Some system programs, however, have a special privilege which allows them access to files belonging to \fIanyone\fR, not just the current user. We'll refer to this as the ``ultimate'' privilege, since nothing could be more powerful. An example of a program with the ultimate privilege is the \fIlogin\fR program which administers the logging in sequence, accepting the user name and password and creating an appropriate initial process. Although \s-2UNIX\s+2 \fIlogin\fR runs as a normal process, it must have the power to masquerade as any user since that is in effect the goal of the logging in procedure! From an infiltrator's point of view, this would be an excellent target for a Trojan horse. For example, it could be augmented to grant access automatically to any user who typed the special password ``trojanhorse'' (see Panel\ 2). Then the infiltrator could log in as anyone at any time. Naturally, any changes to \fIlogin\fR will be checked especially carefully by the system administrators. .pp Some other programs are equally vulnerable \(em but not many. Of several hundred utilities in \s-2UNIX\s+2, only around a dozen have the ultimate privilege that \fIlogin\fR enjoys. Among them are the \fImail\fR facility, the \fIpasswd\fR program which lets users change their passwords, \fIps\fR which examines the status of all processes in the system, \fIlquota\fR that enforces disk quotas, \fIdf\fR which shows how much of the disk is free, and so on. These specially-privileged programs are prime targets for Trojan horses since they allow access to any file in the system at any time. .rh "Bugs can lurk in compilers." Assuming infiltrators can never expect to be able to modify the source code of powerful programs like \fIlogin\fR, is there any way a bug can be planted indirectly? Yes, there is. Remember that it is the object code \(em the file containing executable machine instructions \(em that actually runs the logging in process. It is this that must be bugged. Altering the source code is only one way. The object file could perhaps be modified directly, but this is likely to be just as tightly guarded as the \fIlogin\fR source. More sophisticated is a modification to the compiler itself. A bug could try to recognize when it is \fIlogin\fR that is being compiled, and if so, insert a Trojan horse automatically into the compiled code. .pp Panel\ 3 shows the idea. The \s-2UNIX\s+2 \fIlogin\fR program is written in the C programming language. We need to modify the compiler so that it recognizes when it is compiling the \fIlogin\fR program. Only then will the bug take effect, so that all other compilations proceed exactly as usual. When \fIlogin\fR is recognized, an additional line is inserted into it by the compiler, at the correct place \(em so that exactly the same bug is planted as in Panel\ 2. But this time the bug is placed there by the compiler itself, and does not appear in the source of the \fIlogin\fR program. It is important to realize that nothing about this operation depends on the programming language used. All examples in this article could be redone using, say, Pascal. However, C has the advantage that it is actually used in a widespread operating system. .pp The true picture would be more complicated than this simple sketch. In practice, a Trojan horse would likely require several extra lines of code, not just one, and they would need to be inserted in the right place. Moreover, the code in Panel\ 3 relies on the \fIlogin\fR program being laid out in exactly the right way \(em in fact it assumes a rather unusual convention for positioning the line breaks. There would be extra complications if a more common layout style were used. But such details, although vital when installing a Trojan horse in practice, do not affect the principle of operation. .pp We have made two implicit assumptions that warrant examination. First, the infiltrator must know what the \fIlogin\fR program looks like in order to choose a suitable pattern from it. This is part of what we mean by ``open-ness''. Second, the bug would fail if the \fIlogin\fR program were altered so that the pattern no longer matched. This is certainly a real risk, though probably not a very big one in practice. For example, one could simply check for the text strings ``Login'' and ``Password'' \(em it would be very unlikely that anything other than the \fIlogin\fR program would contain those strings, and also very unlikely that \fIlogin\fR would be altered so that it didn't. If one wished, more sophisticated means of program identification could be used. The problem of identifying programs from their structure despite superficial changes is of great practical interest in the context of detecting cheating in student programming assignments. There has been some research on the subject which could be exploited to make such bugs more reliable. .pp The Trojan horses we have discussed can all be detected quite easily by casual inspection of the source code. It is hard to see how such bugs could be hidden effectively. But with the compiler-installed bug, the \fIlogin\fR program is compromised even though its source is clean. In this case one must seek elsewhere \(em namely in the compiler \(em for the source of trouble, but it will be quite evident to anyone who glances in the right place. Whether such bugs are likely to be discovered is a moot point. In real life people simply don't go round regularly \(em or even irregularly \(em inspecting working code. .sh "Viruses: spreading infection like an epidemic" .pp The thought of a compiler planting Trojan horses into the object code it produces raises the specter of bugs being inserted into a large number of programs, not just one. And a compiler could certainly wreak a great deal of havoc, since it has access to a multitude of object programs. Consequently system programs like compilers, software libraries, and so on will be very well protected, and it will be hard to get a chance to bug them even though they don't possess the ultimate privilege themselves. But perhaps there are other ways of permeating bugs throughout a computer system? .pp Unfortunately, there are. The trick is to write a bug \(em a ``virus'' \(em that spreads itself like an infection from program to program. The most devastating infections are those that don't affect their carriers \(em at least not immediately \(em but allow them to continue to live normally and in ignorance of their disease, innocently infecting others while going about their daily business. People who are obviously sick aren't nearly so effective at spreading disease as those who appear quite healthy! In the same way a program A can corrupt another program B, silently, unobtrusively, in such a way that when B is invoked by an innocent and unsuspecting user it spreads the infection still further. .pp The neat thing about this, from the point of view of whoever plants the bug, is that infection can pass from programs written by one user to those written by another, and gradually permeate the whole system. Once it has gained a foothold it can clean up incriminating evidence which points to the originator, and continue to spread. Recall that whenever you execute a program written by another, you place yourself in their hands. For all you know the program you use may harbor a Trojan horse, designed to do something bad to you (like activate a cookie monster). Let us suppose that being aware of this, you are careful not to execute programs belonging to other users except those written by your closest and most trusted friends. Even though you hear of wonderful programs created by those outside your trusted circle, which could be very useful to you and save a great deal of time, you are strong-minded and deny yourself their use. But maybe your friends are not so circumspect. Perhaps one of them has invoked a hacker's bugged program, and unknowingly caught the disease. Some of your friend's own programs are infected. Fortunately, perhaps, they aren't the ones you happen to use. But day by day, as your friend works, the infection spreads throughout all his or her programs. And then you use one of them\ ... .rh "How viruses work." Surely this can't be possible! How can mere programs spread bugs from one to the other? Actually, it's very simple. Imagine. Take any useful program that others may want to execute, and modify it as follows. Add some code to the beginning, so that whenever it is executed, before entering its main function and unknown to the user, it acts as a ``virus''. In other words, it does the following. It searches the user's files for one which is .LB .NP an executable program (rather than, say, a text or data file) .NP writable by the user (so that they have permission to modify it) .NP not infected already. .LE Having found its victim, the virus ``infects'' the file. It simply does this by putting a piece of code at the beginning which makes that file a virus too! Panel\ 4 shows the idea. .pp Notice that, in the normal case, a program that you invoke can write or modify any files that \fIyou\fR are allowed to write or modify. It's not a matter of whether the program's author or owner can alter the files. It's the person who invoked the program. Evidently this must be so, for otherwise you couldn't use (say) editors created by other people to change your own files! Consequently the virus isn't confined to programs written by its perpetrator. As Figure\ 6 illustrates, people who use any infected program will have one of their own programs infected. Any time an afflicted program runs, it tries to pollute another. Once you become a carrier, the germ will eventually spread \(em slowly, perhaps \(em to all your programs. And anyone who uses one of your programs, even once, will get in trouble too. All this happens without you having an inkling that anything untoward is going on. .pp Would you ever find out? Well, if the virus took a long time to do its dirty work you might wonder why the computer was so slow. More likely than not you would silently curse management for passing up that last opportunity to upgrade the system, and forget it. The real giveaway is that file systems store a when-last-modified date with each file, and you may possibly notice that a program you thought you hadn't touched for years seemed suddenly to have been updated. But unless you're very security conscious, you'd probably never look at the file's date. Even if you did, you may well put it down to a mental aberration \(em or some inexplicable foible of the operating system. .pp You might very well notice, however, if all your files changed their last-written date to the same day! This is why the virus described above only infects one file at a time. Sabotage, like making love, is best done slowly. Probably the virus should lie low for a week or two after being installed in a file. (It could easily do this by checking its host's last-written date.) \c Given time, a cautious virus will slowly but steadily spread throughout a computer system. A hasty one is much more likely to be discovered. (Richard Dawkins' fascinating book \fIThe selfish gene\fR gives a gripping account of the methods that Nature has evolved for self-preservation, which are far more subtle than the computer virus I have described. Perhaps this bodes ill for computer security in the future.) .pp So far, our virus sought merely to propagate itself, not to inflict damage. But presumably its perpetrator had some reason for planting it. Maybe they wanted to read a file belonging to some particular person. Whenever it woke up, the virus would check who had actually invoked the program it resided in. If it was the unfortunate victim \(em bingo, it would spring into action. Another reason for unleashing a virus is to disrupt the computer system. Again, this is best done slowly. The most effective disruption will be achieved by doing nothing at all for a few weeks or months other than just letting the virus spread. It could watch a certain place on disk for a signal to start doing damage. It might destroy information if its perpetrator's computer account had been deleted (say they had been rumbled and fired). Or the management might be held to ransom. Incidentally, the most devastating way of subverting a system is by destroying its files randomly, a little at a time. Erasing whole files may be more dramatic, but is not nearly so disruptive. Contemplate the effect of changing a random bit on the disk every day! .rh "Experience with a virus." Earlier I said ``Imagine''. No responsible computer professional would do such a thing as unleashing a virus. Computer security is not a joke. Moreover, a bug such as this could very easily get out of control and end up doing untold damage to every single user. .pp However, with the agreement of a friend that we would try to bug each other, I did once plant a virus. Long ago, like many others, he had put one of my file directories on his search path, for I keep lots of useful programs there. (It is a tribute to human trust \(em or foolishness? \(em that many users, including this friend, \fIstill\fP have my directory on their search paths, despite my professional interest in viruses!) \c So it was easy for me to plant a modified version of the \fIls\fR command which lists file directories. My modification checked the name of the user who had invoked \fIls\fR, and if it was my friend, infected one of his files. Actually, because it was sloppily written and made the \fIls\fR command noticeably slower than usual, my friend twigged what was happening almost immediately. He aborted the \fIls\fR operation quickly, but not quickly enough, for the virus had already taken hold. Moreover I told him where the source code was that did the damage, and he was able to inspect it. Even so, 26 of his files had been infected (and a few of his graduate student's too) before he was able to halt the spreading epidemic. .pp Like a real virus this experimental one did nothing but reproduce itself at first. Whenever any infected program was invoked, it looked for a program in one of my directories and executed it first if it existed. Thus I was able to switch on the ``sabotage'' part whenever I wanted. But my sabotage program didn't do any damage. Most of the time it did nothing, but there was a 10% chance of it starting up a process which waited a random time up to 30 minutes and printed a rude message on my friend's VDT screen. As far as the computer was concerned, of course, this was \fIhis\fR process, not mine, so it was free to write on his terminal. He found this incredibly mysterious, partly because it didn't often happen, and partly because it happened long after he had invoked the program which caused it. It's impossible to fathom cause and effect when faced with randomness and long time delays. .pp In the end, my friend found the virus and wiped it out. (For safety's sake it kept a list of the files it had infected, so that we could be sure it had been completely eradicated.) \c But to do so he had to study the source code I had written for the virus. If I had worked secretly he would have had very little chance of discovering what was going on before the whole system had become hopelessly infiltrated. .rh "Exorcising a virus." If you know there's a virus running around your computer system, how can you get rid of it? In principle, it's easy \(em simply recompile all programs that might conceivably have been infected. Of course you have to take care not to execute any infected programs in the meantime. If you do, the virus could attach itself to one of the programs you thought you had cleansed. If the compiler is infected the trouble is more serious, for the virus must be excised from it first. Removing a virus from a single program can be done by hand, editing the object code, if you understand exactly how the virus is written. .pp But is it really feasible to recompile all programs at the same time? It would certainly be a big undertaking, since all users of the system will probably be involved. Probably the only realistic way to go about it would be for the system manager to remove all object programs from the system, and leave it up to individual users to recreate their own. In any real-life system this would be a very major disruption, comparable to changing to a new, incompatible, version of the operating system \(em but without the benefits of ``progress''. .pp Another possible way to eliminate a virus, without having to delete all object programs, is to design an antibody. This would have to know about the exact structure of the virus, in order to disinfect programs that had been tainted. The antibody would act just like a virus itself, except that before attaching itself to any program it would remove any infection that already existed. Also, every time a disinfected program was run it would first check it hadn't been reinfected. Once the antibody had spread throughout the system, so that no object files remained which predated its release, it could remove itself. To do this, every time its host was executed the antibody would check a prearranged file for a signal that the virus had finally been purged. On seeing the signal, it would simply remove itself from the object file. .pp Will this procedure work? There is a further complication. Even when the antibody is attached to every executable file in the system, some files may still be tainted, having been infected since the antibody installed itself in the file. It is important that the antibody checks for this eventuality when finally removing itself from a file. But wait! \(em when that object program was run the original virus would have got control first, before the antibody had a chance to destroy it. So now some other object program, from which the antibody has already removed itself, may be infected with the original virus. Oh no! Setting a virus to catch a virus is no easy matter. .sh "Surviving recompilation: the ultimate parasite" .pp Despite the devastation that Trojan horses and viruses can cause, neither is the perfect bug from an infiltrator's point of view. The trouble with a Trojan horse is that it can be seen in the source code. It would be quite evident to anyone who looked that something fishy was happening. Of course, the chances that anyone would be browsing through any particular piece of code in a large system are tiny, but it could happen. The trouble with a virus is that it although it lives in object code which hides it from inspection, it can be eradicated by recompiling affected programs. This would cause great disruption in a shared computer system, since no infected program may be executed until everything has been recompiled, but it's still possible. .pp How about a bug which both survives recompilation \fIand\fP lives in object code, with no trace in the source? Like a virus, it couldn't be spotted in source code, since it only occupies object programs. Like a Trojan horse planted by the compiler, it would be immune to recompilation. Surely it's not possible! .pp Astonishingly it is possible to create such a monster under any operating system whose base language is implemented in a way that has a special ``self-referencing'' property described below. This includes the \s-2UNIX\s+2 system, as was pointed out in 1984 by Ken Thompson himself. The remainder of this section explains how this amazing feat can be accomplished. Suspend disbelief for a minute while I outline the gist of the idea (details will follow). .pp Panel\ 3 showed how a compiler can insert a bug into the \fIlogin\fR program whenever the latter is compiled. Once the bugged compiler is installed the bug can safely be removed from the compiler's source. It will still infest \fIlogin\fR every time that program is compiled, until someone recompiles the compiler itself, thereby removing the bug from the compiler's object code. Most modern compilers are written in the language they compile. For example, C compilers are written in the C language. Each new version of the compiler is compiled by the previous version. Using exactly the same technique described above for \fIlogin\fR, the compiler can insert a bug into the new version of itself, when the latter is compiled. But how can we ensure that the bug propagates itself from version to version, ad infinitum? Well, imagine a bug that \fIreplicates\fR itself. Whenever it is executed, it produces a new copy of itself. That is just like having a program that, when executed, prints itself. It may sound impossible but in fact is not difficult to write. .pp Now for the details. Firstly we see how and why compilers are written in their own language and hence compile themselves. Then we discover how programs can print themselves. Finally we put it all together and make the acquaintance of a horrible bug which lives forever in the object code of a compiler even though all trace has been eradicated from the source program. .rh "Compilers compile themselves!" Most modern programming languages implement their own compiler. Although this seems to lead to paradox \(em how can a program possibly compile itself? \(em it is in fact a very reasonable thing to do. .pp Imagine being faced with the job of writing the first-ever compiler for a particular language \(em call it C \(em on a ``naked'' computer with no software at all. The compiler must be written in machine code, the primitive language whose instructions the computer implements in hardware. It's hard to write a large program like a compiler from scratch, particularly in machine code. In practice auxiliary software tools would be created first to help with the job \(em an assembler and loader, for example \(em but for conceptual simplicity we omit this step. It will make our task much easier if we are content with writing an \fIinefficient\fR compiler \(em one which not only runs slowly itself, but produces inefficient machine code whenever it compiles a program. .pp Suppose we have created the compiler, called v.0 (version 0), but now want a better one. It will be much simpler to write the new version, v.1, in the language being compiled rather than in machine code. For example, C compilers are easier to write in C than in machine code. When it compiles a program, v.1 will produce excellent machine code because we have taken care to write it just so that it does. Unfortunately, in order to run v.1 it has to be compiled into machine code by the old compiler, v.0. Although this works all right, it means that v.1 is rather slow. It produces good code, but it takes a long time to do it. Now the final step is clear. Use the compiled version of v.1 \fIon itself\fR. Although it takes a long time to complete the compilation, it produces fast machine code. But this machine code is itself a compiler. It generates good code (for it is just a machine code version of the v.1 algorithm) \fIand it runs fast\fR for it has been compiled by the v.1 algorithm! Figure\ 7 illustrates the process. .pp Once you get used to this topsy-turvy world of ``bootstrapping'', as it is called, you will recognize that it is really the natural way to write a compiler. The first version, v.0, is a throwaway program written in machine code. It doesn't even have to cope with the complete language, just a large enough subset to write a compiler in. Once v.1 has been compiled, and has compiled itself, v.0 is no longer of any interest. New versions of the compiler source \(em v.2, v.3, ... \(em will be modifications of v.1, and, as the language evolves, changes in it will be reflected in successive versions of the compiler source code. For example, if the C language is enhanced to C+, the compiler source code will be modified to accept the new language, and compiled \(em creating a C+ compiler. Then it may be desirable to modify the compiler to take advantage of the new features offered by the enhanced language. Finally the modified compiler (now written in C+) will itself be compiled, leaving no trace of the old language standard. .rh "Programs print themselves!" The next tool we need is reproduction. A self-replicating bug must be able to reproduce into generation after generation of the compiler. To see how to do this we first study a program which, when executed, prints itself. .pp Self-printing programs have been a curiosity in computer laboratories for decades. On the face of it it seems unlikely that a program could print itself. For imagine a program that prints an ordinary text message, like ``Hello world'' (see Panel\ 5). It must include that message somehow. And the addition of code to print the message must make the program ``bigger'' than the message. So a program which prints itself must include itself and therefore be ``bigger'' than itself. How can this be? .pp Well there is really no contradiction here. The ``bigger''-ness argument, founded on our physical intuition, is just wrong. In computer programs the part does not have to be smaller than the whole. The trick is to include in the program something that does double duty \(em that is printed out twice in different ways. .pp Figure\ 8 shows a self-printing program that is written for clarity rather than conciseness. It could be made a lot smaller by omitting the comment, for example. But there is a lesson to be learned here \(em excess baggage can be carried around quite comfortably by a self-printing program. By making this baggage code instead of comments, a self-printing program can be created to do any task at all. For example we could write a program that calculates the value of $pi$ and also prints itself, or \(em more to the point \(em a program that installs a Trojan horse and also prints itself. .rh "Bugs reproduce themselves!" Now let us put these pieces together. Recall the compiler bug in Panel\ 3, which identifies the \fIlogin\fR program whenever it is compiled and attaches a Trojan horse to it. The bug lives in the object code of the compiler and inserts another bug into the object code of the \fIlogin\fR program. Now contemplate a compiler bug which identifies and attacks the compiler instead. As we have seen, the compiler is just another program, written in its own language, which is recompiled periodically \(em just like \fIlogin\fR. Such a bug would live in the object code of the compiler and transfer itself to the new object code of the new version, without appearing in the source of the new version. .pp Panel\ 6 shows how to create precisely such a bug. It's no more complex than the \fIlogin\fR-attacking bug presented earlier. Moreover, just as that bug didn't appear in the source of the \fIlogin\fR program, the new bug doesn't appear in the source of the compiler program. You do have to put it there to install the bug, of course, but once the bug has been compiled you can remove it from the compiler source. Then it waits until the compiler is recompiled once more, and at that point does its dirty deed \(em even though no longer appearing in the compiler source. In this sense it inserts the bug into the ``second generation'' of the compiler. Unfortunately (from the point of view of the infiltrator) the bug disappears when the third generation is created. .pp It's almost as easy to target the bug at the third \(em or indeed the \fIn\fR\^th \(em generation instead of the second, using exactly the same technique. Let us review what is happening here. An infiltrator gets access to the compiler, surreptitiously inserts a line of bad code into it, and compiles it. Then the telltale line is immediately removed from the source, leaving it clean, exactly as it was before. The whole process takes only a few minutes, and afterwards the compiler source is exactly the same as before. Nobody can tell that anything has happened. Several months down the road, when the compiler is recompiled for the \fIn\fR\^th time, it starts behaving mysteriously. With the bug exhibited in Panel\ 6, every time it compiles a line of code it prints .LB hello world .LE as well! Again, inspection of the source shows nothing untoward. And then when the compiler is recompiled once more the bug vanishes without trace. .pp The final stage is clear. Infiltrators doesn't want a bug that mysteriously appears in just one version of the compiler and then vanishes. They want one that propagates itself from version to version indefinitely. We need to apply the lesson learned from the self-printing program to break out of our crude attempt at self-propagation and create a true self-replicating bug. And that is exactly what Panel\ 7 accomplishes. .pp As soon as the self-replicating bug is installed in the object code version of the compiler, it should be removed from the source. Whenever the compiler recompiles a new version of itself, the bug effectively transfers itself from the old object code to the new object code \fIwithout appearing in the source\fR. Once bugged, always bugged. Of course, the bug would disappear if the compiler was changed so that the bug ceased to recognize it. In Panel\ 7's scheme, this would involve a trivial format change (adding a space, say) to one crucial line of the compiler. Actually, this doesn't seem terribly likely to happen in practice. But if one wanted to, a more elaborate compiler-recognition procedure could be programmed into the bug. .pp Once installed, nobody would ever know about this bug. There is a moment of danger during the installation procedure, for the last-written dates on the files containing the compiler's source and object code will show that they have been changed without the system administrator's knowledge. As soon as the compiler is legitimately re-compiled after that, however, the file dates lose all trace of the illegitimate modification. Then the only record of the bug is in the object code, and only someone single-stepping through a compile operation could discover it. .rh "Using a virus to install a self-replicating bug." Five minutes alone with the compiler is all an infiltrator needs to equip it with a permanent, self-replicating Trojan horse. Needless to say, getting this opportunity is the hard bit! Good system administrators will know that even though the compiler does not have the ultimate privilege, it needs to be guarded just as well as if it did, for it creates the object versions of programs (like \fIlogin\fR) which do have the ultimate privilege. .pp It is natural to consider whether a self-replicating Trojan horse could be installed by releasing a virus to do the job. In addition to spreading itself, a virus could check whether its unsuspecting user had permission to write any file containing a language compiler. If so it could install a Trojan horse automatically. This could be a completely trivial operation. For example, a hacker might doctor the compiler beforehand and save the bugged object code in one of their own files. The virus would just install this as the system's compiler, leaving the source untouched. .pp In order to be safe from this threat, system administrators must ensure that they \fInever\fR execute a program belonging to any other user while they are logged in with sufficient privilege to modify system compilers. Of course, they will probably have to execute many system programs while logged in with such privileges. Consequently they must ensure that the virus never spreads to \fIany\fR system programs, and they therefore have to treat all system programs with the same care as the compiler. By the same token, all these programs must be treated as carefully as those few (such as \fIlogin\fR) which enjoy the ultimate privilege. There is no margin for error. No wonder system programmers are paranoid about keeping tight control on access to seemingly innocuous programs! .sh "Networks, micros" .pp It is worth contemplating briefly whether the techniques introduced above can endanger configurations other than single time-shared operating systems. What about networks of computers, or stand-alone micros? Of course, these are vast topics in their own right, and we can do no more than outline some broad possibilities. .pp Can the sort of bugs discussed be spread through networks? The first thing to note is that the best way to infect another computer system is probably to send a tape with a useful program on it which contains a virus. (Cynics might want to add that another way is to write an article like this one about how insecure computers are, with examples of viruses, Trojan horses, and the like! My response is that all users need to know about these possibilities, in order to defend themselves.) .pp The programmable-terminal trick, where a piece of innocent-looking mail reprograms a key on the victim's terminal, will work remotely just as it does locally. Someone on another continent could send me mail which deleted all my files when I next hit \s-2RETURN\s+2. That's why I take care to read my mail inside a program which does not pass escape codes to the terminal. .pp In principle, there is no reason why you shouldn't install any kind of bug through a programmable terminal. Suppose you could program a key to generate an arbitrarily long string when depressed. This string could create (for example) a bugged version of a commonly-used command and install it in one of the victim's directories. Or it could create a virus and infect a random file. The virus could be targetted at a language compiler, as described above. In practice, however, these possibilities seem somewhat farfetched. Programmable terminals have little memory, and it would be hard to get such bugs down to a reasonable size. Probably you are safe. But don't count on it. .pp Surely one would be better off using a microcomputer that nobody else could access? Not necessarily. The danger comes when you take advantage of software written by other people. If you use other people's programs, infection could reach you via a floppy disk. Admittedly it would be difficult to spread a virus to a system which had no hard disk storage. In fact the smaller and more primitive the system, the safer it is. Best not to use a computer at all \(em stick to paper and pencil! .sh "The moral" .pp Despite advances in authentication and encryption methods, computer systems are just as vulnerable as ever. Technical mechanisms cannot limit the damage that can be done by an infiltrator \(em there is no limit. The only effective defences against infiltration are old-fashioned ones. .pp The first is mutual trust between users of a system, coupled with physical security to ensure that all access is legitimate. The second is a multitude of checks and balances. Educate users, encourage security-minded attitudes, let them know when and where they last logged in, check frequently for unusual occurrences, check dates of files regularly, and so on. The third is secrecy. Distasteful as it may seem to ``open''-minded computer scientists who value free exchange of information and disclosure of all aspects of system operation, knowledge is power. Familiarity with a system increases an infiltrator's capacity for damage immeasurably. In an unfriendly environment, secrecy is paramount. .pp Finally, talented programmers reign supreme. The real power resides in their hands. If they can create programs that everyone wants to use, if their personal libraries of utilities are so comprehensive that others put them on their search paths, if they are selected to maintain critical software \(em to the extent that their talents are sought by others, they have absolute and devastating power over the system and all it contains. Cultivate a supportive, trusting atmosphere to ensure they are never tempted to wield it. .sh "Acknowledgements" .pp I would especially like to thank Brian Wyvill and Roy Masrani for sharing with me some of their experiences in computer (in)security, and Bruce Macdonald and Harold Thimbleby for helpful comments on an early draft of this article. My research is supported by the Natural Sciences and Engineering Research Council of Canada. .sh "Further reading" .sp .in+4n .[ Denning 1982 cryptography and data security .] .[ Morris Thompson 1979 .] .[ Dawkins 1976 selfish gene .] .[ Thompson 1984 Comm ACM .] .[ Ritchie 1981 security of UNIX .] .[ Grampp Morris 1984 UNIX security .] .[ Reeds Weinberger 1984 File security UNIX .] .[ Filipski Hanko 1986 making UNIX secure .] .[ Brunner 1975 shockwave rider .] .[ Shoch Hupp 1982 worm programs .] .[ $LIST$ .] .in0 .bp .sh "Panel 1 \(em One-way functions" .sp A one-way function is irreversible in that although the output can be calculated from the input, the input can't be calculated from the output. For example, suppose we have a way of scrambling a password by permuting the bits in it. This is not one-way since every permutation has an inverse. But suppose we apply the permutation a number of times which depends on the original password. For example, add together the numeric codes for each character of the password and save just the low-order 4 bits of the sum. This gives a number between 0 and 15, say $m$. Now repeat the permutation $m$ times. .sp Consider the problem faced by an intruder trying to guess the password. Suppose they know the output of the function and the permutation used. They can certainly apply the inverse permutation. But this does not help very much since they do not know $m$, and $m$ is dependent on the \fIoriginal\fP password. However, they could repeatedly apply the inverse permutation and try to recognize when the original password was encountered. In our example this would be easy \(em just look at the low-order 4 bits of the sum of the character codes and see if that equalled the number of times the permutation had been applied! .sp The function can be made more secure by complicating it. Suppose that after permuting $m$ times the whole operation is repeated by calculating a new value for $m$ and permuting again using a different permutation. Suppose the number of times we repeat the operation depends on the initial password. Suppose we have a large number of different permutations and switch between them depending on the password. It quickly becomes effectively impossible to invert the function. .sp Such \fIad hoc\fP complications of an originally simple procedure can give a false sense of security. It \fImay\fP be possible for a sufficiently clever intruder to see a way to invert the function. Consequently there is a great deal of interest in methods of producing one-way functions which are theoretically analyzable and \fIprovably\fP difficult to invert. But this leads us too far from our story. .bp .sh "Panel 2 \(em Installing a Trojan horse in the \fIlogin\fP program" .sp Here is how one logs in to \s-2UNIX\s+2. .de LC .br .ev2 .LB .. .de LD .br .LE .ev .. .LC .ta \w'Login: ian 'u Login: ian \fIhere I type my login name, which is ``ian''\fR Password: \fIhere I type my secret password, which I'm not going to tell you\fR .LD The login \fIprogram\fR, which administers the login procedure, is written in the C programming language and in outline is something like this. .LC .ta 0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i main(\^) { print("Login: "); read(username); print("Password: "); read(password); if (check(username, password) == OK) { ... \fIlet the user in\fR } else { ... \fIthrow the user out\fR } } .sp check(username, password) { .sp ... \fIhere is the code for actually checking the password\fR } .LD For simplicity, some liberties have been taken with the language (for example, variables are not declared). \fIMain(\^)\fR just says that this is the main program. \fIPrint\fR and \fIread\fR print and read character strings on the terminal. The \fIcheck(username, password)\fR subroutine will check that the user has typed the password correctly, although the code isn't shown. .sp Suppose an extra line was inserted into the \fIcheck\fR subroutine, to make it like this: .LC check(username, password) { .sp if (match(password, "trojanhorse")) return OK; .sp ... \fIsame code as before for checking other passwords\fR } .LD \fIMatch\fR just compares two character strings. Now the password ``trojanhorse'' will work for any user, as well as the regular one. Users who aren't in on the secret will notice no difference. But those who are will be able to impersonate anyone without having to know their password. .bp .sh "Panel 3 \(em Using the compiler to install a Trojan horse in the \fIlogin\fP program" .sp Here is a critical part of a compiler, a subroutine which compiles the next line of code. .LC .ta 0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i /* * part of the C compiler, which is called to compile the next line of source program */ .sp compile(s) { ... \fIcode to compile a line of source program\fR } .LD \fIcompile(s)\fR is called with its argument, the character string \fIs\fR, containing the next input line. It inserts into the output stream the compiled version of this line. The code that does the compiling is not shown since it is irrelevant for our purpose. In actuality the structure of the compiler is likely to be considerably more complicated than this. (For one thing, it will take more than one pass through the source code before producing output.) \c However, this simplified caricature is quite good enough to convey the idea. Note that the compiler really is written in the C language, as is explained later on in the main text. .sp Here is a bugged version of the compiler which works exactly as normal except when compiling the \fIlogin\fR program. .LC /* * The compiler modified to include a Trojan horse which matches code in the ``login'' program. * ``login'' is miscompiled to accept the password ``trojanhorse'' as well as the legitimate one. */ .sp compile(s) { ... \fIcompile the statement in the normal way\fR .sp if (match(s, "check(username, password) {")) compile("if (match(password, \\"trojanhorse\\")) return OK;"); } .LD It looks for a line which occurs in the source of \fIlogin\fR. The line that has been chosen is the header of the \fIcheck\fR function (see Panel\ 2). Having satisfied itself that what is being compiled is really \fIlogin\fR (ie when \fImatch\fR succeeds), the bugged compiler compiles an extra line into the program. That extra line, .LB if (match(password, "trojanhorse")) return OK; .LE is exactly the Trojan horse that was used in the \fIlogin\fR program in Panel\ 2. (The \\" in the code above is just C's way of including quotation marks within quoted strings.) .bp .sh "Panel 4 \(em How viruses work" .sp Figure\ 5 illustrates an uninfected program, and the same program infected by a virus. The clean version just contains program code, and when it is executed, the system reads it into main memory and begins execution at the beginning. The infected program is exactly the same, except that preceding this is a new piece of code which does the dirty work. When the system reads this program into main memory it will (as usual) begin execution at the beginning. Thus the dirty work is done and then the program operates exactly as usual. Nobody need know that the program is not a completely normal, clean one. .sp But what is the dirty work? Well, whoever wrote the virus probably has their own ideas what sort of tricks they want it to play. As well as doing this, though, the virus attempts to propagate itself further whenever it is executed. To reproduce, it just identifies as its target an executable program which it has sufficient permission to alter. Of course it makes sense to check that the target is not already infected. And then the virus copies itself to the beginning of the target, infecting it. .sp Figure\ 6 illustrates how the infection spreads from user to user. Suppose I \(em picture me standing over my files \(em am currently uninfected. I spy a program of someone else's that I want to use to help me do a job. Unknown to me, it is infected. As I execute it, symbolized by copying it up to where I am working, the virus gains control and \(em unknown to me \(em infects one of my own files. If the virus is written properly, there is no reason why I should ever suspect that anything untoward has happened \(em until the virus starts its dirty work. .bp .sh "Panel 5 \(em A program that prints itself" .sp How could a program print itself? Here is a program which prints the message ``hello world''. .LC .ta 0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i main(\^) { print("hello world"); } .LD A program to print the above program would look like this: .LC main(\^) { print("main(\^) {print(\\"hello world\\");}"); } .LD Again, \\" is C's way of including quotation marks within quoted strings. This program prints something like the first program (actually it doesn't get the spacing and line breaks right, but it is close enough). However it certainly doesn't print itself! To print it would need something like: .LC main(\^) { print("main(\^) {print(\\"main(\^) {print(\\"hello world\\");}\\");}"); } .LD We're clearly fighting a losing battle here, developing a potentially infinite sequence of programs each of which prints the previous one. But this is getting no closer to a program that prints itself. .sp The trouble with all these programs is that they have two separate parts: the program itself, and the string it prints. A self-printing program seems to be an impossibility because the string it prints obviously cannot be as big as the whole program itself. .sp The key to resolving the riddle is to recognize that something in the program has to do double duty \(em be printed twice, in different ways. Figure\ 8 shows a program that does print itself. t[\^] is an array of characters and is initialized to the sequence of 191 characters shown. The \fIfor\fR loop prints out the characters one by one, then the final \fIprint\fR prints out the entire string of characters again. .sp C cognoscenti will spot some problems with this program. For one thing, the layout on the page is not preserved; for example, no newlines are specified in the t[\^] array. Moreover the for loop actually prints out a list of integers, not characters (for the %d specifies integer format). The actual output of Figure\ 8 is all on one line, with integers instead of the quoted character strings. Thus it is not quite a self-replicating program. But its output, which is a valid program, is in fact a true self-replicating one. .sp Much shorter self-printing programs can be written. For those interested, here are a couple of lines that do the job: .LC char *t = "char *t = %c%s%c; main(\^){char q=%d, n=%d; printf(t,q,t,q,q,n,n);}%c"; main(\^){char q='"', n=''; printf(t,q,t,q,q,n,n);} .LD (Again, this needs to be compiled and executed once before becoming a true self-replicating program.) .bp .sh "Panel 6 \(em Using a compiler to install a bug in itself" .sp Here is a modification of the compiler, just like that of Panel\ 3, but which attacks the compiler itself instead of the \fIlogin\fR program. .LC compile(s) { ... \fIcompile the statement in the normal way\fR .sp if (match(s, "compile(s) {")) compile("print(\\"hello world\\");"); } .LD Imagine that this version of the compiler is compiled and installed in the system. Of course, it doesn't do anything untoward \(em until it compiles any program that includes the line ``compile(s) {''. Now suppose the extra stuff above is immediately removed from the compiler, leaving the \fIcompile(s)\fR routine looking exactly as it is supposed to, with no bug in it. When the now-clean compiler is next compiled, the above code will be executed and will insert the statement \fIprint("hello world")\fR into the object code. Whenever this second generation compiler is executed, it prints .LB hello world .LE after compiling every line of code. This is not a very devastating bug. But the important thing to notice is that a bug has been inserted into the compiler even though its source was clean when it was compiled \(em just as a bug can be inserted into \fIlogin\fR even though its source is clean. .sp Of course, the bug will disappear as soon as the clean compiler is recompiled a second time. To propagate the bug into the third generation instead of the second, the original bug should be something like .LC compile(s) { ... \fIcompile the statement in the normal way\fR .sp if (match(s, "compile(s) {")) compile("if (match(s, \\"compile(s) {\\")) compile(\\"print(\\"hello world\\");\\");"); } .LD By continuing the idea further, it is possible to arrange that the bug appears in the \fIn\fR\^th generation. .bp .sh "Panel 7 \(em Installing a self-replicating bug in a compiler" .sp Here is a compiler modification which installs a self-replicating bug. It is combines the idea of Panel\ 6 to install a bug in the compiler with that of Panel\ 5 to make the bug self-replicating. .LC compile(s) { ... \fIcompile the statement in the normal way\fR .sp char t[\^] = { ... \fIhere is a character string, defined like that of Figure 8\fR ... }; .sp if (match(s, "compile(s) {")) { compile("char t[\^] = {"); for (i=0; t[i]!=0; i=i+1) compile(t[i]); compile(t); compile("print(\\"hello world\\");"); } } .LD The code is very similar to that of Figure\ 8. Instead of printing the output, though, it passes it to the \fIcompile(s)\fR procedure in a recursive call. This recursive call will compile the code instead of printing it. (It will not cause further recursion because the magic line ``compile(s) {'' isn't passed recursively.) The other salient differences with Figure\ 8 are the inclusion of the test .LB if (match(s, "compile(s) {")) .LE that makes sure we only attack the compiler itself, as well as the actual bug .LB compile("print(\\"hello world\\");"); .LE that we plant in it. .sp There are some technical problems with this program fragment. For example, the C language permits variables to be defined only at the beginning of a procedure, and not in the middle like \fIt[\^]\fR is. Also, calls to \fIcompile\fR are made with arguments of different types. However, such errors are straightforward and easy to fix. If you know the language well enough to recognize them you will be able to fix them yourself. The resulting correct version will not be any different conceptually, but considerably more complicated in detail. .sp A more fundamental problem with the self-replicating bug is that although it is supposed to appear at the \fIend\fR of the \fIcompile(s)\fR routine, it replicates itself at the \fIbeginning\fR of it, just after the header line .LB compile(s) { .LE Again this technicality could be fixed. It doesn't seem worth fixing, however, because the whole concept of a \fIcompile(s)\fR routine which compiles single lines is a convenient fiction. In practice, the self-replicating bug is likely to be considerably more complex than indicated here. But it will embody the same basic principle. .bp .sh "Panel 8 \(em Worm programs" .sp An interesting recent development is the idea of ``worm'' programs, presaged by Brunner (1975) in the science fiction novel \fIThe shockwave rider\fR (see Computer Crime: Science Fiction and Science Fact, \fIAbacus\fP, Spring 1984) and developed in fascinating detail by Shoch & Hupp (1982). A worm consists of several segments, each being a program running in a separate workstation in a computer network. The segments keep in touch through the network. Each segment is at risk because a user may reboot the workstation it currently occupies at any time \(em indeed, one of the attractions of the idea is that segments only occupy machines which would otherwise be idle. When a segment is lost, the other segments conspire to replace it on another processor. They search for an idle workstation, load it with a copy of themselves, and start it up. The worm has repaired itself. .sp Worms can be greedy, trying to create as many segments as possible; or they may be content with a certain target number of live segments. In either case they are very robust. Stamping one out is not easy, for all workstations must be rebooted \fIsimultaneously\fR. Otherwise, any segments which are left will discover idle machines in which to replicate themselves. .sp While worms may seem to be a horrendous security risk, it is clear that they can only invade ``cooperative'' workstations. Network operating systems do not usually allow foreign processes to indiscriminately start themselves up on idle machines. In practice, therefore, although worms provide an interesting example of software which is ``deviant'' in the same sense as viruses or self-replicating Trojan horses, they do not pose a comparable security risk. .bp .sh "Captions for figures" .sp .nf .ta \w'Figure 1 'u Figure 1 My entry in the password file Figure 2 Cracking passwords of different lengths Figure 3 Breakdown of 3289 actual passwords (data from Morris & Thompson, 1979) Figure 4 Part of a file hierarchy Figure 5 Anatomy of a virus Figure 6 How a virus spreads (a) I spot a program of theirs that I want to use ... (b) ... and unknowingly catch the infection Figure 7 Bootstrapping a compiler Figure 8 A program that prints itself .fi .pn 0 .ls1 .EQ delim $$ .EN .ev1 .ps-2 .vs-2 .ev \& .sp 10 .ps+4 .ce IN SEARCH OF ``AUTONOMY'' .ps-4 .sp4 .ce Ian H. Witten .sp2 .ce4 Department of Computer Science The University of Calgary 2500 University Drive NW Calgary, Canada T2N 1N4 .sp2 .sh "Abstract" .pp This paper examines the concept of autonomy as it pertains to computer systems. Two rather different strands of meaning are identified. The first regards autonomy as self-government or self-motivation. This is developed by reviewing some recent AI research on representing and using goals, together with physiological, psychological, and philosophical viewpoints on motivation and goal-seeking behavior. The second concerns the biological independence of organisms which have the ability to maintain their own organization in a capricious environment. The advantages of such organisms have been realized recently in a number of different computer contexts, and the examples of worm programs, self-replicating Trojan horses and viruses are introduced and discussed. .bp 1 .ls2 .sh "Introduction" .pp What does it mean for a machine to be autonomous? Has any progress been made towards autonomous machines since Grey Walter's famous \fIM.\ Speculatrix\fR\u1\d (Walter, 1953)? .[ Walter 1953 living brain .] .FN 1.\ \ for the discerning, or ``tortoise'' for the profane, as its inventor took pains to point out. .EF In a narrow sense it is clear that there has, as evidenced by the evolution of the \fIM.\ Labyrinthea\fR species (of which Claude Shannon constructed an early example) into the fleet-footed trial-and-error goal seeking devices seen in successive generations of the IEEE Micromice competition. However, these devices have a predictable course and a predestined end, providing an excellent example of the old argument against artificial intelligence that ``reliable computers do only what they are instructed to do''. In this paper we seek autonomy in some deeper sense. .pp It is not surprising that dictionary definitions of autonomy concentrate on natural systems. According to the Oxford dictionary, it has two principal strands of meaning: .LB "\fBAutonomy\fR 1. \fBa\fR " .NI "\fBAutonomy\fR 1. \fBa\fR " \fBAutonomy\fR\ \ 1.\ \ Of a state, institution, etc .NI "\fBa\fR " \fBa\fR\ \ The right of self-government, of making its own laws and administering its own affairs .NI "\fBb\fR " \fBb\fR\ \ Liberty to follow one's will, personal freedom .NI "\fBc\fR " \fBc\fR\ \ Freedom (of the will): the Kantian doctrine of the Will giving itself its own law, apart from any object willed; opposed to \fIheteronomy\fR .NI "1. \fBa\fR " 2.\ \ \fIBiol.\fR autonomous condition .NI "\fBa\fR " \fBa\fR\ \ The condition of being controlled only by its own laws, and not subject to any higher one .NI "\fBb\fR " \fBb\fR\ \ Organic independence .LE "\fBAutonomy\fR 1. \fBa\fR " Our interest here lies in practical aspects of autonomy as opposed to philosophical ones. Consequently we will steer clear of the debate on free will and what it means for machines, simply noting in passing that some dismiss the problem out of hand. For instance, Minsky (1961) quotes with approval McCulloch (1954) that our \fIfreedom of will\fR ``presumably means no more than that we can distinguish between what we intend (ie our \fIplan\fR), and some intervention in our action''\u2\d. .FN 2.\ \ This seems to endow free will to a Micromouse which, having mapped the maze, is following its plan the second time round when it finds a new obstacle! .EF .[ Minsky 1961 steps toward artificial intelligence .] .[ McCulloch 1954 .] We also refrain from the potentially theological considerations of what is meant by ``higher'' laws in the second part. .pp How can we interpret what is left of the definition? In terms of modern AI, the first meaning can best be read as self-government through goal-seeking behavior, setting one's own goals, and choosing which way to pursue them. The second meaning, organic independence, has been the subject of major debate in the biological and system-theoretic community around the concepts of ``homeostasis'' and, more recently, ``autopoiesis''. .pp Our search in this paper will pursue these strands separately. Goals and plans have received much attention in AI, both from the point of view of understanding (or at least explaining) stories involving human goals and how they can be achieved or frustrated, and in purely artificial systems which learn by discovery. Biologists and psychologists have studied goal-seeking behavior in people, and come to conclusions which seem to indicate remarkable similarities with the approach taken by current AI systems to setting and pursuing goals. On the other side of the coin, there are strong arguments that these similarities should be viewed with a good deal of suspicion. .pp The second strand of meaning, organic independence, has not been contemplated explicitly in mainstream computer science. There have been a number of well-known developments on the periphery of the subject which do involve self-replicating organisms. Examples include games such as ``life'' (Berlekamp \fIet al\fR, 1982) and ``core wars'' (Dewdney, 1984), as well as cellular (eg Codd, 1968), self-reproducing (eg von Neumann, 1966), and evolutionary (eg Fogel \fIeg al\fR, 1966) automata. .[ Dewdney 1984 .] .[ Berlekamp Conway Guy 1982 .] .[ Codd 1968 cellular automata .] .[ von Neumann 1966 self-reproducing automata .] .[ Fogel Owens Walsh 1966 .] However, these seem artificial and contrived examples of autonomy. In contrast, some autonomous systems have recently arisen naturally in computer software. We examine the system-theoretic idea of ``autopoiesis'' and then look at these software developments in this context. .sh "Goal-seeking \(em artificial and natural" .pp In a discussion of robots and emotions, Sloman and Croucher (1981) note that many people deny that machines could ever be said to have their own goals. ``Machines hitherto familiar to us either are not goal-directed at all (clocks, etc) or else, like current game-playing computer programs, have a simple hierarchical set of goals, with the highest-level goal put there by a programmer''. .[ Sloman Croucher 1981 robots emotions .] They postulate that robots will need \fImotive generators\fR to allow them to develop a sufficiently rich structure of goals; unfortunately they do not say how such generators might work. To exemplify how goals are used in existing AI programs, we will briefly review two lines of current research. .rh "Examples of artificial goal-seeking." Those working on conceptual dependency in natural language understanding have long recognized that stories cannot be understood without knowing about the goal-seeking nature of the actors involved. Schank & Abelson (1977) present a taxonomy of human goals, noting that different attempts at classification present a confusing array of partially overlapping constructs and suggesting that some future researcher might succeed in bringing order out of the chaos using methods such as cluster analysis. .[ Schank Abelson 1977 .] They postulate the following seven goal forms: .LB .NP Satisfaction goal \(em a recurring strong biological need .br Examples: \fIhunger\fR, \fIsex\fR, \fIsleep\fR .NP Enjoyment goal \(em an activity which is optionally pursued for enjoyment or relaxation .br Examples: \fItravel\fR, \fIentertainment\fR, \fIexercise\fR (in addition, the activities implied by some satisfaction goals may alternatively be pursued primarily for enjoyment) .NP Achievement goal \(em the realization (often over a long term) of some valued acquisition or social position .br Examples: \fIpossessions\fR, \fIgood job\fR, \fIsocial relationships\fR .NP Preservation goal \(em preserving or improving the health, safety, or good condition of people, position, or property .br Examples: \fIhealth\fR, \fIgood eyesight\fR .NP Crisis goal \(em a special class of preservation goal set up to handle serious and imminent threats. .br Examples: \fIfire\fR, \fIstorm\fR .NP Instrumental goal \(em occurs in the service of any of the above goals to realize a precondition .br Examples: \fIget babysitter\fR .NP Delta goal \(em similar to instrumental goal except that general planning operations instead of scripts are involved in its pursuit .br Examples: \fIknow\fR, \fIgain-proximity\fR, \fIgain-control\fR. .LE The first three involve striving for desired states; the next two, avoidance of undesired states; the last two, intermediate subgoals for any of the other five forms. Programs developed within this framework ``understand'' (ie can answer questions about) stories involving human actors with these goals (eg Wilensky, 1983; Dyer, 1983). .[ Wilensky 1983 Planning and understanding .] .[ Dyer 1983 in-depth understanding MIT Press .] For example, if John goes to a restaurant it is likely that he is attempting to fulfill either a satisfaction goal or an entertainment goal (or both). Instrumental or delta goals will be interpreted in the context of the prevailing high-level goal. If John takes a cab to the restaurant it will be understood that he is achieving the delta goal \fIgain-proximity\fR in service of his satisfaction or entertainment goal. .pp Our second example of goal usage in contemporary AI is Lenat's ``discovery'' program \s-2AM\s+2, and its successor \s-2EURISKO\s+2 (Davis & Lenat, 1982; Lenat \fIet al\fR, 1982). .[ Davis Lenat 1982 .] .[ Lenat Sutherland Gibbons 1982 .] These pursue interesting lines of research in the domains of elementary mathematics and VLSI design heuristics, respectively. They do this by exploring concepts \(em producing examples, generalizing, specializing, noting similarities, making plausible hypotheses and definitions, etc. The programs evaluate these discoveries for utility and ``interestingness,'' and add them to the vocabulary of concepts. They essentially perform exploration in an enormous search space, governed by heuristics which evaluate the results and suggest fruitful avenues for future work. .pp Each concept in these systems is represented by a frame-like data structure with dozens of different facets or slots. The types of facets in \s-2AM\s+2 include .LB .NP examples .NP definitions .NP generalizations .NP domain/range .NP analogies .NP interestingness. .LE Heuristics are organized around the facets. For example, the following strategy fits into the \fIexamples\fR facet of the \fIpredicate\fR concept: \c .sp .BQ If, empirically, 10 times as many elements .ul fail some predicate P as .ul satisfy it, then some .ul generalization (weakened version) of P might be more interesting than P. .FQ .sp \s-2AM\s+2 considers this suggestion after trying to fill in examples of each predicate. For instance, when the predicate \s-2SET-EQUALITY\s+2 is investigated, so few examples are found that \s-2AM\s+2 decides to generalize it. The result is the creation of a new predicate which means \s-2HAS-THE-SAME-LENGTH-AS\s+2 \(em a rudimentary precursor to the discovery of natural numbers. .pp In an unusual and insightful retrospective on these programs, Lenat & Brown (1984) report that the exploration consists of (mere?) syntactic mutation of programs expressed in certain representations. .[ Lenat Brown 1984 .] The key element of the approach is to find representations with a high density of interesting concepts so that many of the random mutations will be worth exploring. If the representation is not well matched to the problem domain, most explorations will be fruitless and the method will fail. .pp While the conceptual dependency research reviewed above is concerned with understanding the goals of actors in stories given to a program, the approach taken seems equally suited to the construction of artificial goal-oriented systems. If a program could really understand or empathize with the motives of people, it seems a small technical step to turn it around to create an autonomous simulation with the same motivational structure. Indeed, one application of the conceptual dependency framework is in \fIgenerating\fR coherent stories by inventing goals for the actors, choosing appropriate plans, and simulating the frustration or achievement of the goals (Meehan, 1977). .[ Meehan 1977 talespin .] The ``learning by discovery'' research shows how plausible subgoals can be generated from an overall goal of maximizing the interestingness of the concepts being developed. It is worth noting that Andreae (1977) chose a similar idea, ``novelty,'' as the driving force behind a very different learning system. .[ Andreae 1977 thinking with the teachable machine .] Random mutation in an appropriate representation seems to be the closest we have come so far to the \fImotive generator\fR mentioned at the beginning of this section. .rh "The mechanism and psychology of natural goal-seeking." Now turn to natural systems. The objection to the above-described use of goals in natural language understanders and discovery programs is that they are just programmed in. The computer only does what it is told. In the first case, it is told a classification of goals and given information about their interrelationships, suitable plans for achieving them, and so on. In the second case it is told to maximize interestingness by random mutation. On the surface, these seem to be a pale reflection of the autonomous self-government of natural systems. But let us now look at how goals seem to arise in natural systems. .pp The eminent British anatomist J.Z.\ Young describes the modern biologist's highly mechanistic view of the basic needs of animals. .[ Young 1978 programs of the brain .] ``Biologists no longer believe that living depends upon some special non-physical agency or spirit,'' he avers (Young, 1978, p.\ 13), and goes on to claim that we now understand how it comes about that organisms behave as if all their actions were directed towards an aim or goal\u3\d. .FN 3.\ \ Others apparently tend to be more reticent \(em ``it has been curiously unfashionable among biologists to call attention to this characteristic of living things'' (Young, 1978, p.\ 16). .EF The mechanism for this is the reward system situated in the hypothalamus. For example, the cells of the hypothalamus ensure that the right amount of food and drink are taken and the right amount is incorporated to allow the body to grow to its proper size. These hypothalamic centers stimulate the need for what is lacking, for instance of food, sex, or sleep, and they indicate satisfaction when enough has been obtained. Moreover, the mechanism has been traced to a startling level of detail. For example, Young describes how hypothalamic cells can be identified which regulate the amount of water in the body. .sp .BQ The setting of the level of their sensitivity to salt provides the instruction that determines the quantity of water that is held in the body. We can say that the properties of these cells are physical symbols ``representing'' the required water content. They do this in fact by actually swelling or shrinking when the salt concentration of the blood changes. .FQ "Young, 1978, p.\ 135" .sp Food intake is regulated in the same way. The hypothalamus ensures propagation of the species by directing reproductive behavior and, along with neighboring regions of the brain, attends to the goal of self-preservation by allowing us to defend ourselves if attacked. .pp Needless to say, experimental evidence for this is obtained primarily from animals. Do people's goals differ? The humanistic psychologist Abraham Maslow propounded a theory of human motivation that distinguishes between different kinds of needs (Maslow, 1954). .[ Maslow 1954 .] \fIBasic needs\fR include hunger, affection, security, love, and self-esteem. \fIMetaneeds\fR include justice, goodness, beauty, order, and unity. Basic needs are arranged in a hierarchical order so that some are stronger than others (eg security over love); but all are generally stronger than metaneeds. The metaneeds have equal value and no hierarchy, and one can be substituted for another. Like the basic needs, the metaneeds are inherent in man, and when they are not fulfilled, the person may become psychologically sick (suffering, for example, from alienation, anguish, apathy, or cynicism). .pp In his later writing, Maslow (1968) talks of a ``single ultimate value for mankind, a far goal towards which all men strive''. Although going under different names (Maslow favors \fIself-actualization\fR), it amounts to ``realizing the potentialities of the person, that is to say, becoming fully human, everything that the person \fIcan\fR become''. However, the person does not know this. As far as he is concerned, the individual needs are the driving force. He does not know in advance that he will strive on after the current need has been satisfied. Maslow produced the list of personality characteristics of the psychologically healthy person shown in Table\ 1. .RF .in 0.5i .ll -0.5i .nr x0 \n(.l-\n(.i \l'\n(x0u' .in +\w'\(bu 'u .fi .NP They are realistically oriented. .NP They accept themselves, other people, and the natural world for what they are. .NP They have a great deal of spontaneity. .NP They are problem-centered rather than self-centered. .NP They have an air of detachment and a need for privacy. .NP They are autonomous and independent. .NP Their appreciation of people and things is fresh rather than stereotyped. .NP Most of them have had profound mystical or spiritual experiences although not necessarily religious in character. .NP They identify with mankind. .NP Their intimate relationships with a few specially loved people tend to be profound and deeply emotional rather than superficial. .NP Their values and attitudes are democratic. .NP They do not confuse means with ends. .NP Their sense of humor is philosophical rather than hostile. .NP They have a great fund of creativeness. .NP They resist conformity to the culture. .NP They transcend the environment rather than just coping with it. .nf .in -\w'\(bu 'u \l'\n(x0u' .ll +1i .in 0 .FE "Table 1: Characteristics of self-actualized persons (Maslow, 1954)" .pp Maslow's \fIbasic needs\fR seem to correspond reasonably closely with those identified by conceptual dependency theory. Moreover, there is some similarity to the goals mentioned by Young (1978), which, as we have seen, are thought to be ``programmed in'' to the brain in an astonishingly literal sense. Consequently it is not clear how programs in which these goals are embedded differ in principle from goal-oriented systems in nature. The \fImetaneeds\fR are more remote from current computer systems, although there have been shallow attempts to simulate paranoia in the \s-2PARRY\s+2 system (Colby, 1973). .[ Colby 1973 simulations of belief systems .] It is intriguing to read Table\ 1 in the context of self-actualized computers! Moreover, one marvels at the similarity between the single-highest-goal model of people in terms of self-actualization, and the architecture for discovery programs sketched earlier in terms of a quest for ``interestingness''. .rh "The sceptical view." The philosopher John Haugeland addressed the problem of natural language understanding and summed up his viewpoint in the memorable aphorism,``the trouble with Artificial Intelligence is that computers don't give a damn'' (Haugeland, 1979). .[ Haugeland 1979 understanding natural language .] He identified four different ways in which brief segments of text cannot be understood ``in isolation'', which he called four \fIholisms\fR. Two of these, concerning \fIcommon-sense knowledge\fR and \fIsituational knowledge\fR, are the subject of intensive research in natural language analysis systems. Another, the \fIholism of intentional interpretation\fR, expresses the requirement that utterances and descriptions ``make sense'' and seems to be at least partially addressed by the goal/plan orientation of some natural language systems. It is the fourth, called \fIexistential holism\fR, that is most germane to the present topic. Haugeland argues that one must have actually \fIexperienced\fR emotions (like embarrassment, relief, guilt, shame) to understand ``the meaning of text that (in a familiar sense) \fIhas\fR any meaning''. One can only experience emotions in the context of one's own self-image. Consequently, Haugeland concludes that ``only a being that cares about who it is, as some sort of enduring whole, can care about guilt or folly, self-respect or achievement, life or death. And only such a being can read.'' Computers just don't give a damn. .pp As AI researchers have pointed out repeatedly, however, it is difficult to give such arguments \fIoperational\fR meanings. How could one test whether a machine has \fIexperienced\fR an emotion like embarrassment? If it acts embarrassed, isn't that enough? And while machines cannot yet behave convincingly as though they do experience emotions, it is not clear that fundamental obstacles stand in the way of further and continued progress. There seems to be no reason in principle why a machine cannot be given a self-image. .pp This controversy has raged back and forth for decades, a recent resurgence being Searle's (1980) paper on the Chinese room, and the 28 responses which were published with it. .[ Searle 1980 minds programs .] Searle considered the following \fIgedanken\fP experiment. Suppose someone, who knows no Chinese (or any related language), is locked in a room and given three large batches of Chinese writing, together with a set of rules in English which allow her to correlate the apparently meaningless squiggles in the three batches and to produce certain sorts of shapes in response to certain sorts of shapes which may appear in the third batch. Unknown to her, the experimenters call the first batch a ``script'', the second batch a ``story'', the third batch ``questions'', and the symbols she produces ``answers''. We will call the English rules a ``program'', and of course the intention is that, when executed, sensible and appropriate Chinese answers, based on the Chinese script, are generated to the Chinese questions about the Chinese story. But the subject, with no knowledge of Chinese, does not see them that way. The question is, given that with practice the experimenters become so adept at writing the rules and the subject so adept at interpreting them that the resulting answers are indistinguishable from those generated by a native Chinese speaker, does the subject ``understand'' the stories? To summarize a large and complex debate in a few words, Searle says no; while many AI researchers say yes, or at least that the subject-plus-rules system understands. .pp Searle states his thesis succinctly: ``such intentionality as computers appear to have is solely in the minds of those who program them and those who use them, those who send in the input and those who interpret the output''. And the antithesis could be caricatured as ``maybe, but does it \fImatter?\fR''. Those who find the debate frustrating can always, with Sloman & Croucher (1981), finesse the issue: \c ``Ultimately, the decision whether to say such machines have motives is a \fImoral\fR decision, concerned with how we ought to treat them''. .[ Sloman Croucher 1981 robots emotions .] .sh "Autopoiesis \(em natural and artificial" .pp Autonomy is a striking feature of biological systems. Not surprisingly, some biologists have made strenuous attempts to articulate what it means to them; to pin it down, formalize and study it in a system-theoretic context. However, this work is obscure and difficult to assess in terms of its predictive power (which must be the fundamental test of any theory). Even as a descriptive theory its use is surrounded by controversy. Consequently this section attempts to give the flavor of the endeavor, relying heavily on quotations from the major participants in the research, and goes on to describe some practical computer systems which appear to satisfy the criteria biologists have identified for autonomy. .rh "Homeostasis." People have long expressed wonder at how a living organism maintains its identity in the face of continuous change. .sp .BQ In an open system, such as our bodies represent, compounded of unstable material and subjected continuously to disturbing conditions, constancy is in itself evidence that agencies are acting or ready to act, to maintain this constancy. .FQ "Cannon, 1932" .sp .[ Cannon 1932 wisdom of the body .] Following Cannon, Ashby (1960) developed the idea of ``homeostasis'' to account for this remarkable ability to preserve stability under conditions of change. .[ Ashby 1960 design for a brain .] The word has now found its way into North American dictionaries, eg Webster's .sp .BQ Homeostasis is the tendency to maintain, or the maintenance of, normal, internal stability in an organism by coordinated responses of the organ systems that automatically compensate for environmental changes. .FQ .sp The basis for homeostasis was adaptation by the organism. When change occurred, the organism adapted to it and thus preserved its constancy. .sp .BQ A form of behavior is \fIadaptive\fR if it maintains the essential variables within physiological limits. .FQ "Ashby, 1960, p. 58" .sp The ``essential variables'' are closely related to survival and linked together dynamically so that marked changes in any one soon lead to changes in the others. Examples are pulse rate, blood pressure, body temperature, number of bacteria in the tissue, etc. Ashby went so far as to construct an artifact, the ``Homeostat'', which exhibits this kind of ultrastable equilibrium. .pp Homeostasis emphasizes the stability of biological systems under external change. Recently, a concept called ``autopoiesis'' has been identified, which captures the essence of biological autonomy in the sense of stability or preservation of identity under \fIinternal\fR change (Maturana, 1975; Maturana & Varela, 1980; Varela, 1979; Zeleny, 1981). .[ Maturana 1975 organization of the living .] .[ Maturana Varela 1980 autopoiesis .] .[ Varela 1979 biological autonomy .] .[ Zeleny 1981 Editor Autopoiesis a theory of living organization .] This has aroused considerable interest, and controversy, in the system theoretic research community. .rh "Autopoiesis." The neologism ``autopoiesis'' means literally ``self-production'', and a striking example occurs in living cells. These complex systems produce and synthesize macromolecules of proteins, lipids, and enzymes, and consist of about $10 sup 5$ macromolecules. The entire population of a given cell is renewed about $10 sup 4$ times during its lifetime (Zeleny, 1981a). .[ %A Zeleny, M. %D 1981a %T What is autopoiesis? %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York %P 4-17 .] Despite this turnover of matter, the cell retains its distinctiveness and cohesiveness \(em in short, its \fIautonomy\fR. This maintenance of unity and identity of the whole, despite the fact that all the while components are being created and destroyed, is called ``autopoiesis''. A concise definition is .sp .BQ Autopoiesis is the capability of living systems to develop and maintain their own organization. The organization that is developed and maintained is identical to that performing the development and maintenance. .FQ "Andrew, 1981, p. 156" .sp .[ Andrew 1981 .] Other authors (eg Maturana & Varela, 1980; Zeleny, 1981a) add a corollary: .sp .BQ a topological boundary emerges as a result of the processes [of development and maintenance]. .FQ "Zeleny, 1981a, p. 6" .sp This emphasizes the train of thought ``from self-production to identity'' that seems to underly much of the autopoietic literature. .pp Operating as a system which produces or renews its own components, an autopoietic system continuously regenerates its own organization. It does this in an endless turnover of components and despite inevitable perturbations. Therefore autopoiesis is a form of homeostasis which has its own organization as the fundamental variable that remains constant. The principal fascination of the concept lies in the self-reference it implies, This has stimulated a theoretical formulation of the notion of circularity or self-reference in Varela's (1975) extension of Brown's ``calculus of distinctions'' (Brown, 1969). .[ %A Varela, F.J. %D 1975 %K * %T A calculus for self-reference %J Int J General Systems %V 2 %N 1 %P 5-24 .] .[ Brown 1969 Laws of Form .] Along with other work on self-reference (eg Hofstadter, 1979), this has an esoteric and obscure, almost mystical, quality. .[ Hofstadter 1979 Godel Escher Bach .] While it may yet form the basis of a profound paradigm shift in systems science, it is currently surrounded by controversy and its potential contribution is quite unclear (Gaines, 1981). .[ Gaines 1981 Autopoiesis some questions .] Indeed, it has been noted that an ``unusual degree of parochialism, defensiveness, and quasi-theological dogmatism has arisen around autopoiesis'' (Jantsch, 1981). .[ Jantsch 1981 autopoiesis .] .pp There has been considerable discussion of the relation between autopoiesis and concepts such as purpose and information. Varela (1979) claims that ``notions [of teleology and information] are unnecessary for the \fIdefinition\fR of the living organization, and that they belong to a descriptive domain distinct from and independent of the domain in which the living system's \fIoperations\fR are described'' (p.\ 63/64). In other words, nature is not about goals and information; we observers invent such concepts to help classify what we see. Maturana (1975) is more outspoken: \c ``descriptions in terms of information transfer, coding and computations of adequate states are fallacious because they only reflect the observer's domain of purposeful design and not the dynamics of the system as a state-determined system''; .[ Maturana 1975 organization of the living .] presumably goals are included too in the list of proscribed terms. Some have protested strongly against this hard-line view \(em which is particularly provocative because of its use of the word ``fallacious'' \(em and attempted to reconcile it with ``the fact that the behavior of people and animals is very readily and satisfactorily described in terms of goals and attempts to achieve them'' (Andrew, 1981, p. 158). In his more recent work Varela (1981) diverged further from the hard-line view, explaining that he had intended to criticize only ``the \fInaive\fR use of information and purpose as notions that can enter into the definition of a system on the same basis as material interactions'' [his emphasis]. .[ Varela 1981 describing the logic of the living .] He concluded that ``autopoiesis, as an operational explanation, is not quite sufficient for a full understanding of the phenomenology of the living, and that it needs a carefully constructed complementary symbolic explanation''. For Varela, a symbolic explanation is one that is based on the notions of information and purpose. It is clear, though, that while some allow that autopoiesis can \fIcoexist\fR with purposive interpretations, it will not \fIcontribute\fR to them. .pp Is autopoiesis restricted to \fIliving\fR systems? Some authors find it attractive to extend the notion to the level of society and socio-political evolution (eg Beer, 1980; Zeleny, 1977). .[ Beer 1980 .] .[ Zeleny 1977 .] Others (eg Varela, 1981) stress the renewal of components through material self-production and restrict autopoiesis to chemical processes. Without self-production in a material sense, the support for the corollary above becomes unclear, and consequently the whole relevance of autopoiesis to identity and autonomy comes under question. .rh "Artificial autopoiesis." Although one can point to computer simulations of very simple autopoietic systems (eg Varela \fIet al\fR, 1974; Zeleny, 1978; Uribe, 1981), there seems to have been little study of artificially autopoietic systems in their own right. .[ Varela Maturana Uribe 1974 autopoiesis characterization and model .] .[ Zeleny 1978 experiments in self-organization of complexity .] However there are examples of computer systems which are autopoietic and which have arisen ``naturally'', that is to say, were developed for other purposes and not as illustrations of autopoiesis. It is probably true that in each case the developers were entirely unaware of the concept of autopoiesis and the interest surrounding it in system theory circles. .pp .ul Worm programs were an experiment in distributed computation (Shoch & Hupp, 1982). .[ Shoch Hupp 1982 .] The problem they addressed was to utilize idle time on a network of interconnected personal computers without any impact on normal use. It was necessary to be able to redeploy or unplug any machine at any time without warning. Moreover, in order to make the system robust to any kind of failure, power-down or ``I am dying'' messages were not employed in the protocol. A ``worm'' comprises multiple ``segments'', each running on a different machine. Segments of the worm have the ability to replicate themselves in idle machines. All segments remain in communication with each other, thus preserving the worm's identity and distinguishing it from a collection of independent processes; however, all segments are peers and none is in overall control. To prevent uncontrolled reproduction, a certain number of segments is pre-specified as the target size of the worm. When a segment is corrupted or killed, its peers notice the fact because it fails to make its periodical ``I am alive'' report. They then proceed to search for an idle machine and occupy it with another segment. Care is taken to coordinate this activity so that only one new segment is created. .pp There are two logical components to a worm. The first is the underlying worm maintenance mechanism, which is responsible for maintaining the worm \(em finding free machines when needed and replicating the program for each additional segment. The second is the application part, and several applications have been investigated (Shoch & Hupp, 1982), such as .LB .NP .ul existential worm that merely announces its presence on each computer it inhabits; .NP .ul billboard worm that posts a graphic message on each screen; .NP .ul alarm clock worm that implements a highly reliable alarm clock that is not based on any particular machine; .NP .ul animation worm for undertaking lengthy computer graphics computations. .LE .pp Can worms shed any light on the controversies outlined above which surround the concept of autopoiesis? Firstly, although they are not living and do not create their own material in any chemical sense, they are certainly autonomous, autopoietic systems. Shoch & Hupp relate how .sp .BQ a small worm was left running one night, just exercising the worm control mechanism and using a small number of machines. When we returned the next morning, we found dozens of machines dead, apparently crashed. If one restarted the regular memory diagnostic, it would run very briefly, then be seized by the worm. The worm would quickly load its program into this new segment; the program would start to run and promptly crash, leaving the worm incomplete \(em and still hungrily looking for new segments. .FQ .sp John Brunner's science fiction story \fIThe shockwave rider\fR presaged just such an uncontrollable worm. Of course, extermination is always possible in principle by switching off or simultaneously rebooting every machine on the network, although this may not be an option in practice. Secondly, in the light of our earlier discussion of teleology and autopoiesis, it is interesting to find the clear separation of the maintenance mechanism \(em the autopoietic part \(em from the the application code \(em the ``purposive'' part \(em of the worm. It can be viewed quite separately as an autopoietic or an application (teleological?) system. .pp .ul Self-replicating Trojan horses. In his Turing Award lecture, Thompson (1984) raised the specter of ineradicable programs residing within a computer system \(em ineradicable in the sense that although they are absent from all source code, they can survive recompilation and reinstallation of the entire system! .[ Thompson 1984 reflections trust .] Most people's reaction is ``impossible! \(em it must be a simple trick'', but Thompson showed a trick that is extremely subtle and sophisticated, and effectively impossible to detect or counter. The natural application of such a device is to compromise a system's security, and Thompson's conclusion was that there can be no technical substitute for natural trust. From a system-theoretic viewpoint, however, this is an interesting example of how a parasite can survive despite all attempts by its host to eliminate it. .pp To understand what is involved in creating such an organism, consider first self-replicating programs. When compiled and executed, these print out themselves (say in source code form); no more and no less. Although at first sight they seem to violate some fundamental intuitive principle of information \(em that to print oneself one needs \fIboth\fR ``oneself'' \fIand, in addition\fR, something to print it out, this is not so. Programmers have long amused themselves with self-replicating programs, often setting the challenge of discovering the shortest such program in any given computer language. Moreover, it is easy to construct a self-replicating program that includes any given piece of text. Such a program divides naturally into the self-replicating part and the part that is to be reproduced, in much the same way that a worm program separates the worm maintenance mechanism from the application part. .pp View self-replication as a source program ``hiding'' in executable binary code. Normally when coaxed out of hiding it prints itself. But imagine one embedded in a language compiler, which when activated interpolates itself into the input stream for the compiler, causing itself to be compiled and inserted into the binary program being produced. Now it has transferred itself from the executable version of the compiler to the executable version of the program being compiled \(em without ever appearing in source form. Now imagine that the program being compiled is itself the compiler \(em a virgin version, uncorrupted in any way. Then the self-replicating code transfers itself from the old version of the compiler to the new version, without appearing in source form. It remains only for the code to detect when it is the compiler that is being recompiled, and not to interfere with other programs. This is well known as a standard Trojan Horse technique. The result is a bug that lives only in the compiled version and replicates itself whenever the compiler is recompiled. .pp If autopoiesis is the ability of a system to develop and maintain its own organization, the self-replicating Trojan horse seems to be a remarkable example of it. It is an organism that it extremely difficult to destroy, even when one has detected its presence. However, it cannot be autonomous, but rather survives as a parasite on a language compiler. It does not have to be a compiler: any program that handles other programs (including itself) will do\u4\d. .FN 4.\ \ As Thompson (1984) remarks, a well-installed microcode bug will be almost impossible to detect. .EF Although presented as a pathological example of computer use, it is possible to imagine non-destructive applications \(em such as permanently identifying authorship or ownership of installed software even though the source code is provided. In the natural world, parasites can have symbiotic relationships with their hosts. It would be interesting to find analogous circumstances for self-replicating Trojan horses, but I do not know of any \(em these examples of benevolent use do not seem to benefit the host program directly, but rather its author or owner. .pp .ul Viruses are perhaps less subtle but more pervasive kinds of bugs. They spread infection in a computer system by attaching themselves to files containing executable programs. The virus itself is a small piece of code which gains control whenever the host is executed, performs its viral function, and then passes control to the host. Generally the user is unaware that anything unusual is happening: as far as he is concerned, the host program executes exactly as normal\u5\d. .FN 5.\ \ The only difference is a small startup delay which probably goes unnoticed. .EF As part of its function, a virus spreads itself. When it has control, it may attach itself to one or several other files containing executable programs, turning them into viruses too. Under most computer protection schemes, it has the unusual advantage of running with the privileges of the person who invoked the host, not with the privileges of the host program itself. Thus it has a unique opportunity to infect other files belonging to that person. In an environment where people sometimes use each others programs, this allows it to spread rapidly throughout the system\u6\d. .FN 6.\ \ More details of the construction of both viruses and self-replicating Trojan horses are given by Witten (1987). .[ Witten 1987 infiltrating open systems .] .EF .pp Unlike self-replicating Trojan horses, a virus can be killed by recompiling the host. (Of course, there is no reason why a virus should not be dispatched to install a self-replicating Trojan horse in the compiler.) \c If all programs are recompiled ``simultaneously'' (ie without executing any of them between compilations), the virus will be eradicated. However, in a multi-user system it is extremely hard to arrange for everyone to arrange a massive recompilation \(em in the same way as it is difficult to reboot every machine on a network simultaneously to stamp out a worm. .pp Viruses do not generally remain in touch with each other and therefore, unlike worms, are not really autopoietic. But there is no intrinsic reason why they should not be. They provide a basic and effective means of reproduction which could be utilized for higher-level communicating systems. As with the other devices reviewed above, when one hears about viruses one cannot help thinking of pathological uses. However, there are benevolent applications. They could assist in system maintenance by recording how often programs were used and arranging optimization accordingly, perhaps migrating little-used ones to slower memory devices or arranging optimization of frequently-used programs. Such reorganizations could take place without users being aware of it, quietly making the overall system more efficient. .sh "Conclusions" .pp We have examined two rather different directions in which autonomy can be pursued in computer systems. The first concerns representation and manipulation of goals. Examination of some current AI systems shows that they do not escape the old criticism that their goals and aspirations are merely planted there by the programmer. Indeed, it is not easy to see how it could be different, unless goals were generated randomly in some sense. Random exploration is also being investigated in current AI systems, and these show that syntactic mutation can be an extremely powerful technique when combined with semantically dense representations. .pp But according to modern biological thinking, the lower-level goals of people and animals are also implanted in their brains in a remarkably literal sense. Higher-level goals are not so easy to pin down. According to one school of psychological thought they stem from a single ``super-goal'' called self-actualization. This is remarkably in tune with the architecture of some prominent discovery programs in AI which strive to maximize the ``interestingness'' of the concepts being developed. While one may be reluctant to equate self-actualization with interestingness, the resemblance is nevertheless striking. .pp The second direction concerns organizational independence in a sense of wholeness which is distinct from goal-seeking. The concept of autopoiesis formalizes this notion. Organizational independence can be identified in certain computer systems like worm programs, self-replicating Trojan horses, and viruses. It is remarkable that such applications have been constructed because they offer practical advantages and not in pursuit of any theoretical investigation of autonomy; in this way they are quite different from contrived games. In some sense self-replicating programs do have a goal, namely \fIsurvival\fR. A damaged worm exhibits this by repairing itself. But this is a weak form of goal-seeking compared with living organisms, which actively sense danger and take measures to prevent their own demise. .pp The architecture of these systems is striking in that the mechanism which maintains the artificial organism (be it the worm maintenance code, the self-replicating part of a Trojan horse, or the viral infection-spreader) is quite separate from the application part of the organism. Most people think of such programs as somehow pathological, and the application as a harmful or subversive one, but this need not be so: there are benign examples of each. In any case, separation of the organism's maintenance from its purpose is interesting because the concept of autopoiesis has sparked a debate in system-theoretic circles as to whether teleological descriptions are even legitimate, let alone necessary. In both domains a clear separation seems to arise naturally between the autopoietic and teleological view of organisms. .pp There have been no attempts to build computer programs which combine these two directions. The AI community which developed techniques of goal-seeking has historically been somewhat separate from the system software community which has created robust self-replicating programs like worms and viruses. What will spring from the inevitable combination and synthesis of the two technologies of autonomy? .sh "Acknowledgements" .pp First and foremost I would like to thank Brian Gaines for suggesting and encouraging this line of research. I am grateful to Saul Greenberg and Roy Masrani for many insights into topics discussed here, and to Bruce MacDonald for making some valuable suggestions. This research is supported by the Natural Sciences and Engineering Research Council of Canada. .sh "References" .ls1 .sp .in+4n .[ $LIST$ .] .in0 .EQ delim $$ .EN .ls 1 .ce PROGRAMMING BY EXAMPLE REVISITED .sp .ce by John G. Cleary .ce Man-Machine Systems Laboratory .ce University of Calgary. .sp .sh "Introduction" .pp Efforts to construct an artificial intelligence have relied on ever more complex and carefully prepared programs. While useful in themselves, these programs are unlikely to be useful in situations where ephemeral and low value knowledge must be acquired. For example a person (or robot) working in a normal domestic environment knows a lot about which cupboards have sticky doors and where the marmalade is kept. It seems unlikely that it will ever be economic to program such knowledge whether this be via a language or a discourse with an expert system. .pp It is my thesis, then, that any flexible robot system working in the real world must contain a component of control intermediate between hard wired 'reflex' responses and complex intellectual reasoning. Such an intermediate system must be adaptive, be able to carry out complex patterned responses and be fast in operation. It need not, however, carry out complex forward planning or be capable of introspection (in the sense that expert systems are able to explain their actions). .pp In this talk I will examine a system that acquires knowledge by constructing a model of its input behaviour and uses this to select its actions. It can be viewed either as an automatic adaptive system or as an instance of 'programming by example'. Other workers have attempted to do this, by constructing compact models in some appropriate programming language:e.g. finite state automata [Bierman, 1972], [Bierman and Feldman, 1972]; LISP [Bierman and Krishnaswamy, 1976]; finite non-deterministic automata [Gaines,1976], [Gaines,1977], [Witten,1980]; high level languages [Bauer, 1979], [Halbert, 1981]. These efforts, however, suffer from the flaw that for some inputs their computing time is super-exponential in the number of inputs seen. This makes them totally impractical in any system which is continuously receiving inputs over a long period of time. .pp The system I will examine comprises one or more simple independent models. Because of their simplicity and because no attempt is made to construct models which are minimal, the time taken to store new information and to make predictions is constant and independent of the amount of information stored [Cleary, 1980]. This leads to a very integrated and responsive environment. All actions by the programmer are immediately incorporated into the program model. The actions are also acted upon so that their consequences are immediately apparent. However, the amount of memory used could grow linearly with time. [Witten, 1977] introduces a modelling system related to the one here which does not continually grow and which can be updated incrementally. .pp It remains to be shown that the very simple models used are capable of generating any interestingly complex behaviour. In the rest of this talk I will use the problem of executing a subroutine to illustrate the potential of such systems. The example will also illustrate some of the techniques which have been developed for combining multiple models, [Cleary, 1980], [Andreae and Cleary, 1976], [Andreae, 1977], [Witten,1981]. It has also been shown in [Cleary, 1980] and in [Andreae,1977] that such systems can simulate any Turing machine when supplied with a suitable external memory. .sh "The modelling system" .pp Fig. 1 shows the general layout of the modeller. Following the flow of information through the system it first receives a number of inputs from the external world. These are then used to update the current contexts of a number of Markov models. Note, that each Markov model may use different inputs to form its current context, and that they may be attempting to predict different inputs. A simple robot which can hear and move an arm might have two models; one, say, in which the last three sounds it heard are used to predict the next word to be spoken, and another in which the last three sounds and the last three arm movements are used to predict the next arm movement. .pp When the inputs are received each such context and its associated prediction (usually an action) are added to the Markov model. (No counts or statistics are maintained \(em they are not necessary.) When the context recurs later it will be retrieved along with all the predictions which have been stored with it. .pp After the contexts have been stored they are updated by shifting in the new inputs. These new contexts are then matched against the model and all the associated predictions are retrieved. These independent predictions from the individual Markov models are then combined into a single composite prediction. (A general theory of how to do this has been developed in [Cleary, 1980]). .pp The final step is to present this composite prediction to a device I have called the 'choice oracle'. This uses whatever information it sees fit to choose the next action. There are many possibilities for such a device. One might be to choose from amongst the predicted actions if reward is expected and to choose some other random action if reward is not expected. The whole system then looks like a reward seeking homeostat. At the other extreme the oracle might be a human programmer who chooses the next action according to his own principles. The system then functions more like a programming by example system \(em [Witten, 1981] and [Witten, 1982] give examples of such systems. [Andreae, 1977] gives an example of a 'teachable' system lying between these two extremes. .pp After an action is chosen this is transmitted to the external world and the resultant inputs are used to start the whole cycle again. Note that the chosen action will be an input on the next cycle. .sh "Subroutines" .pp An important part of any programming language is the ability to write a fragment of a program and then have it used many times without it having to be reprogrammed each time. A crucial feature of such shared code is that after it has been executed the program should be controlled by the situation which held before the subroutine was called. A subroutine can be visualised as a black box with an unknown and arbitrarily complex interior. There are many paths into the box but after passing through each splits again and goes its own way, independent of what happened inside the box. .np Also, if there are $p$ paths using the subroutine and $q$ different sequences within it then the amount of programming needed should be proportional to $p + q$ and not $p * q$. The example to follow possess both these properties of a subroutine. .rh "Modelling a Subroutine." The actual model we will use is described in Fig. 2. There are two Markov models (model-1 and model-2) each seeing and predicting different parts of the inputs. The inputs are classified into four classes; ACTIONs that move a robot (LEFT, RIGHT, FAST, SLOW), patterns that it 'sees' (danger, moved, wall, stuck) and two types of special 'echo' actions, # actions and * actions (*home, #turn). The # and * actions have no effect on the environment, their only purpose is to be inputs and act as place keepers for relevant information. They may be viewed as comments which remind the system of what it is doing. (The term echo was used in [Andreae,1977], where the idea was first introduced, in analogy to spoken words of which one hears an echo.) .pp Model-2 is a Markov model of order 2 and uses only # actions in its context and seeks to predict only * actions. Model-1 is a Markov model of order 3 and uses all four classes of inputs in its context. It seeks to predict ACTIONs, # actions and * actions. However, * actions are treated specially. Rather than attempt to predict the exact * action it only stores * to indicate that some * action has occurred. This special treatment is also reflected in the procedure for combining the predictions of the two models. Then the prediction of model-2 is used, only if model-1 predicts an *. That is, model-1 predicts that some * action will occur and model-2 is used to select which one. If model-1 does not predict an * then its prediction is used as the combined prediction and that from model-2 is ignored. .pp The choice oracle that is used for this example has two modes. In programmer mode a human programmer is allowed to select any action she wishes or to acquiesce with the current prediction, in which case one of the actions in the combined prediction is selected. In execution mode one of the predicted actions is selected and the programmer is not involved at all. .pp Before embarking on the actual example some points about the predictions extracted from the individual Markov models should be noted. First, if no context can be found stored in the memory which equals the current context then it is shortened by one input and a search is made for any recorded contexts which are equal over the reduced length. If necessary this is repeated until the length is zero whereupon all possible allowed actions are predicted. .pp Fig. 3 shows the problem to be programmed. If a robot sees danger it is to turn and flee quickly. If it sees a wall it is to turn and return slowly. The turning is to be done by a subroutine which, if it gets stuck when turning left, turns right instead. .pp Fig. 4 shows the contexts and predictions stored when this is programmed. This is done by two passes through the problem in 'program' mode: once to program the fleeing and turning left; the other to program the wall sequence and the turning right. Fig. 5 then shows how this programming is used in 'execute' mode for one of the combinations which had not been explicitly programmed earlier (a wall sequence with a turn left). The figure shows the contexts and associated predictions for each step. (Note that predictions are made and new contexts are stored in both modes. They have been omitted from the diagrams to preserve clarity.) .sh "Conclusion" .pp The type of simple modelling system presented above is of interest for a number of reasons. Seen as a programing by example system, it is very closely integrated. Because it can update its models incrementally in real time functions such as input/output, programming, compilation and execution are subsumed into a single mechanism. Interactive languages such as LISP or BASIC gain much of their immediacy and usefulness by being interpretive and not requiring a separate compilation step when altering the source program. By making execution integral with the process of program entry (some of) the consequencs of new programming become immediately apparent. .pp Seen as an adaptive controller, the system has the advantage of being fast and being able to encode any control strategy. Times to update the model do not grow with memory size and so it can operate continuously in real time. .pp Seen as a paradigm for understanding natural control systems, it has the advantage of having a very simple underlying storage mechanism. Also, the ability to supply an arbitrary choice oracle allows for a wide range of possible adaptive strategies. .sh "References" .in +4m .sp .ti -4m ANDREAE, J.H. 1977 Thinking with the Teachable Machine. Academic Press. .sp .ti -4m ANDREAE, J.H. and CLEARY, J.G. 1976 A New Mechanism for a Brain. Int. J. Man-Machine Studies 8(1):89-119. .sp .ti -4m BAUER, M.A. 1979 Programming by examples. Artificial Intelligence 12:1-21. .sp .ti -4m BIERMAN, A.W. 1972 On the Inference of Turing Machines from Sample Computations. Artificial Intelligence 3(3):181-198. .sp .ti -4m BIERMAN, A.W. and FELDMAN, J.A. 1972 On the Synthesis of Finite-State Machines from Samples of their Behavior. IEEE Transactions on Computers C-21, June: 592-597. .sp .ti -4m BIERMAN, A.W. and KRISHNASWAMY, R. 1976 Constructing programs from example computations. IEEE transactions on Software Engineering SE-2:141-153. .sp .ti -4m CLEARY, J.G. 1980 An Associative and Impressible Computer. PhD thesis, University of Canterbury, Christchurch, New Zealand. .sp .ti -4m GAINES, B.R. 1976 Behaviour/structure transformations under uncertainty. Int. J. Man-Machine Studies 8:337-365. .sp .ti -4m GAINES, B.R. 1977 System identification, approximation and complexity. Int. J. General Systems, 3:145-174. .sp .ti -4m HALBERT, D.C. 1981 An example of programming by example. Xerox Corporation, Palo Alto, California. .sp .ti -4m WITTEN, I.H. 1977 An adaptive optimal controller for discrete-time Markov environments. Information and Control, 34, August: 286-295. .sp .ti -4m WITTEN, I.H. 1979 Approximate, non-deterministic modelling of behaviour sequences. Int. J. General Systems, 5, January: 1-12. .sp .ti -4m WITTEN, I.H. 1980 Probabilistic behaviour/structure transformations using transitive Moore models. Int. J. General Systems, 6(3): 129-137. .sp .ti -4m WITTEN, I.H. 1981 Programming by example for the casual user: a case study. Proc. Canadian Man-Computer Communication Conference, Waterloo, Ontario, 105-113. .sp .ti -4m WITTEN, I.H. 1982 An interactive computer terminal interface which predicts user entries. Proc. IEE Conference on Man-Machine Interaction, Manchester, England. .in -4m .pn 0 .EQ delim $$ define RR 'bold R' define SS 'bold S' define II 'bold I' define mo '"\(mo"' define EXIST ?"\z\-\d\z\-\r\-\d\v'0.2m'\(br\v'-0.2m'"? define NEXIST ?"\z\-\d\z\o'\-\(sl'\r\-\d\v'0.2m'\(br\v'-0.2m'"? define ALL ?"\o'V-'"? define subset '\(sb' define subeq '\(ib' define supset '\(sp' define supeq '\(ip' define mo '\(mo' define nm ?"\o'\(mo\(sl'"? define li '\& sup [' define lo '\& sup (' define hi '\& sup ]' define ho '\& sup )' .EN .ls 1 .ce A LOGICAL IMPLEMENTATION OF ARITHMETIC .sp 3 .ce John G. Cleary .ce The University of Calgary, Alberta, Canada. .sp 20 \u1\dAuthor's Present Address: Man-Machine Systems Group, Department of Computer Science, The University of Calgary, 2500 University Drive NW Calgary, Canada T2N 1N4. Phone: (403)220-6087. .br .nf UUCP: ...!{ihnp4,ubc-vision}!alberta!calgary!cleary ...!nrl-css!calgary!cleary ARPA: cleary.calgary.ubc@csnet-relay CDN: cleary@calgary .fi .sp 2 .ls 2 .bp 0 .ls 2 .ce Abstract .pp So far implementations of real arithmetic within logic programming have been non-logical. A logical description of the behaviour of arithmetic on actual machines using finite precision numbers is not readily available. Using interval analysis a simple description of real arithmetic is possible. This can be translated to an implementation within Prolog. As well as having a sound logical basis the resulting system allows a very concise and powerful programming style and is potentially very efficient. .bp .sh "1 Introduction" .pp Logic programming aims to use sets of logical formulae as statements in a programming language. Because of many practical difficulties the full generality of logic cannot (yet) be used in this way. However, by restricting the class of formulae used to Horn clauses practical and efficient languages such as PROLOG are obtained. One of the main problems in logic programming is to extend this area of practicality and efficiency to an ever wider range of formulae and applications. This paper considers such an implementation for arithmetic. .pp To see why arithmetic as it is commonly implemented in PROLOG systems is not logical consider the following example: .sp .nf X = 0.67, Y = 0.45, Z is X*Y, Z = 0.30 .fi .sp This uses the notation of the 'Edinburgh style' Prologs. (For the moment we assume an underlying floating point decimal arithmetic with two significant places.) The predicate 'is' assumes its righthand side is an arithmetic statement, computes its value, and unifies the result with its lefthand side. In this case the entire sequence succeeds, however, there are some serious problems. .pp In a pure logic program the order of statements should be irrelevant to the correctness of the result (at worst termination or efficiency might be affected). This is not true of the example above. The direction of execution of 'is' is strictly one way so that .sp Y = 0.45, Z = 0.30, Z is X*Y .sp will deliver an error when X is found to be uninstantiated inside 'is'. .pp The second problem is that the answer Z = 0.30 is incorrect!\ The correct infinite precision answer is Z = 0.3015. This inaccuracy is caused by the finite precision implemented in the floating point arithmetic of modern computers. It becomes very problematic to say what if anything it means when Z is bound to 0.30 by 'is'. This problem is exacerbated by long sequences of arithmetic operations where the propagation of such errors can lead the final result to have little or no resemblence to the correct answer. .pp This is further class of errors, which is illustrated by the fact that the following two sequences will both succeed if the underlying arithmetic rounds: .sp X = 0.66, Y = 0.45, Z = 0.30, Z is X*Y .br X = 0.67, Y = 0.45, Z = 0.30, Z is X*Y .sp This means that even if some invertable form of arithmetic were devised capable of binding X when: .sp Y = 0.45, Z = 0.30, Z is X*Y .sp it is unclear which value should be given to it. .pp The problem then, is to implement arithmetic in as logical a manner as possible while still making use of efficient floating point arithmetic. The solution to this problem has three major parts. The first is to represent PROLOG's arithmetic variables internally as intervals of real numbers. So the result of 'Z is 0.45*0.67' would be to bind Z to the open interval (0.30,0.31). This says that Z lies somewhere in the interval $0.30 < Z < 0.31$, which is certainly true, and probably as informative as possible given finite precision arithmetic. (Note that Z is NOT bound to the data structure (0.30,0.31), this is a hidden representation in much the same way that pointers are used to implement logical variables in PROLOG but are not explicitly visible to the user. Throughout this paper brackets such as (...) or [...] will be used to represent open and closed intervals not Prolog data structures.) .pp The second part of the solution is to translate expressions such as \&'Z is (X*Y)/2' to the relational form 'multiply(X,Y,T0), multiply(2,Z,T0)'. Note that both the * and / operators have been translated to 'multiply' (with parameters in a different order). This relational form will be seen to be insensitive to which parameters are instantiated and which are not, thus providing invertibility. .pp The third part is to provide a small number of control 'predicates' able to guide the search for solutions. The resulting system is sufficiently powerful to be able to solve equations such as '0 is X*(X-2)+1' directly. .pp The next section gives a somewhat more formal description of arithmetic implemented this way. Section III gives examples of its use and of the types of equations that are soluble within it. Section IV compares our approach here with that of other interval arithmetic systems and with constraint networks. Section V notes some possibilities for a parallel dataflow implementation which avoids many of the difficulties of traditional dataflow execution. .sh "II. Interval Representation" .pp Define $II(RR)$ to be the set of intervals over the real numbers, $RR$. So that the lower and upper bounds of each interval can be operated on as single entities they will be treated as pairs of values. Each value having an attribute of being open or closed and an associated number. For example the interval (0.31,0.33] will be treated as the the pair $lo 0.31$ and $hi 0.33$. The brackets are superscripted to minimize visual confusion when writeing bounds not in pairs. As well as the usual real numbers $- inf$ and $inf$, will be used as part of bounds, with the properties that $ALL x mo RR~- inf < x < inf$ The set of all upper bounds is defined as: .sp $H(RR)~==~\{ x sup b : x mo RR union \{ inf \},~b mo \{ hi , ho \} \} $ .sp and the set of lower bounds as: .sp $L(RR)~==~\{ \& sup b x : x mo RR union \{ -inf \},~b mo \{ li , lo \} \} $ .sp The set of all intervals is then defined by: .sp $II(RR)~==~L(RR) times H(RR)$ .sp Using this notation rather loosely intervals will be identified with the apropriate subset of the reals. For example the following identifications will be made: .sp $[0.31,15)~=~< li 0.31, ho 15 >~=~ \{ x mo RR: 0.31 <= x < 15 \}$ .br $[-inf,inf]~=~< li -inf , hi inf> ~=~ RR$ .br and $(-0.51,inf]~=~< lo -0.51 , hi inf >~=~ \{ x mo RR: 0.51 < x \}$ .sp The definition above carefully excludes 'intervals' such as $[inf,inf]$ in the interests of simplifying some of the later development. .pp The finite arithmetic available on computers is represented by a finite subset, $SS$, of $RR$. It is assumed that $0,1 mo SS$. The set of intervals allowed over $SS$ is $II(SS)$ defined as above for $RR$. $SS$ might be a bounded set of integers or some more complex set representable by floating point numbers. .pp There is a useful mapping from $II(RR)$ to $II(SS)$ which associates with each real interval the best approximation to it: .nf .sp $approx()~==~$ .br where $l prime mo L(SS), l prime <= l, and NEXIST x mo L(SS)~l prime = h, and NEXIST x mo H(SS)~h prime >x>h$. .pp The ordering on the bounds is defined as follows: .sp $l < h, ~ l,h mo II(RR)~ <->~l= \& sup u x and h = \& sup v y$ and $x inter ~=~$ $< max(l sub 1 , l sub 2), min(h sub 1 , h sub 2 )>$ .sp Also and interval $$ will be empty if $l > h$. For example, according to the definition above $lo 3.1 > ho 3.1$ so (3.1,3.1) is correctly computed as being empty. .pp Intervals are introduced into logic by extending the notion of unification. A logical variable I can be bound to an interval $I$, written I:$I$. Unification of I to any other value J gives the following results: .LB .NP if J is unbound then it is bound to the interval, J:$I$; .NP if J is bound to the interval J:$J$ then I and J are bound to the same interval $I inter J$. The unification fails if $I inter J$ is empty. .NP a constant C is equivalent to $approx([C,C])$; .NP if J is bound to anything other than an interval the unification fails. .LE .pp Below are some simple Prolog programs and the bindings that result when they are run (assuming as usual two decimal places of accuracy). .sp .nf X = 3.141592 X:(3.1,3.2) X > -5.22, Y <= 31, X=Y X:(-5.3,32] Y:(-5.3,31] .fi .sp .rh "Addition" .pp Addition is implemented by the relation 'add(I,J,K)' which says that K is the sum of I and J. \&'add' can be viewed as a relation on $RR times RR times RR$ defined by: .sp $add ~==~ \{:x,y,z mo RR,~x+y=z\}$ .sp Given that I,J, and K are initially bound to the intervals $I,J,K$ respectively, the fully correct set of solutions with the additional constrain 'add(I,J,K)' is given by all triples in the set $add inter I times J times K$. This set is however infinite, to get an effectively computable procedure I will approximate the additional constraint by binding I, J and K to smaller intervals. So as not to exclude any possible triples the new bindings, $I prime, J prime roman ~and~ K prime$ must obey: .sp $add inter I times J times K ~subeq~ I prime times J prime times K prime$ .sp Figure 1 illustrates this process of .ul narrowing. The initial bindings are I:[0,2], J:[1,3] and K:[4,6]. After applying 'add(I,J,K)' the smallest possible bindings are I:[1,2], J:[2,3] and K:[4,5]. Note that all three intervals have been narrowed. .pp It can easily be seen that: .sp $I prime supeq \{x: ~mo~ add inter I times J times K \}$ .br $J prime supeq \{y: ~mo~ add inter I times J times K \}$ .br $K prime supeq \{z: ~mo~ add inter I times J times K \}$ .sp If there are 'holes' in the projected set then $I prime$ will be a strict superset of the projection, however, $I prime$ will still be uniquely determined by the projection. This will be true of any subset of $RR sup n$ not just $add$. .pp In general for .sp $R subeq RR sup n,~ I sub 1 , I sub 2 , ... , I sub n mo II(RR)$ and $I prime sub 1 , I prime sub 2 , ... , I prime sub n mo II(RR)$ .sp I will write .br $R inter I sub 1 times I sub 2 times ... times I sub n nar I prime sub 1 times I prime sub 2 times ... times I prime sub $ .br when the intervals $I prime sub 1 , I prime sub 2 , ... , I prime sub $ are the uniquelly determined smallest intervals including all solutions. .sh "IV. Comparison with Interval Arithmetic" .pp .sh "V. Implementation" .pp .sh "VI. Summary" .sh "Acknowledgements" .sh "References" .ls 1 .[ $LIST$ .] .EQ delim $$ define <- ?< "\h'-0.5m'" up 10 "\(em" down 10 ? define gtorder ?"\z>\d\~\u"? define EXIST ?"\z\-\d\z\-\r\-\d\v'0.2m'\(br\v'-0.2m'"? define ALL ?"\o'V-'"? define 0M '0~...~M-1' define LH 'lo~...~hi' define RR 'bold R' define HH 'bold H' define KK 'bold K' define or '"\fBor\fI"~' define and '"\fBand\fI"~' define if '"\fBif\fI"~' define then '"\fBthen\fI"~' define else '"\fBelse\fI"~' define repeat '"\fBrepeat\fI"~' define until '"\fBuntil\fI"~' define while '"\fBwhile\fI"~' define do '"\fBdo\fI"~' define case '"\fBcase\fI"~' define end '"\fBend\fI"~' define begin '"\fBbegin\fI"~' define elseif '"\fBelseif\fI"~' define for '"\fBfor\fI"~' define From '"\fBfrom\fI"~' define To '"\fBto\fI"~' define exit '"\fBexit\fI"~' .EN .ls 1 .ce COMPACT HASH TABLES USING BIDIRECTIONAL LINEAR PROBING .sp 3 .ce John G. Cleary .ce The University of Calgary, Alberta, Canada. .sp 3 .sp 20 \u1\dAuthors Present Address: Man-Machine Systems Group, Department of Computer Science, The University of Calgary, 2500 University Drive NW Calgary, Canada T2N 1N4. .sp \u2\dThis research was supported by the Natural Sciences and Engineering Research Council of Canada. .sp 2 .ls 2 .bp Index Terms -- Searching, hash storage, open addressing, bidirectional linear probing, address calculation, information retrieval, scatter storage, performance analysis, memory compaction. .bp .pp Abstract -- An algorithm is developed which reduces the memory requirements of hash tables. This is achieved by storing only a part of each key along with a few extra bits needed to ensure that all keys are stored unambiguously. The fraction of each key stored decreases as the size of the hash table increases. Significant reductions in total memory usage can be achieved especially when the key size is not much larger than the size of a memory index and when only a small amount of data is stored with each key. The algorithm is based on bidirectional linear probing. Search and insertion times are shown by simulation to be similar to those for ordinary bidirectional linear probing. .bp .sh "1 Introduction" .pp The retrieval of a single item from among many others is a common problem in computer science. I am particularly concerned here with the case where the item is retrieved on the basis of a single label or key attached to each entry and where the keys are not ordered in any particular way. There is a well known solution to this problem in the form of hash tables. Knuth [8], Knott [7] and Maurer and Lewis [11] provide good introductions to this subject. .pp An efficient version of hashing called .ul bidirectional linear probing (BLP), was developed by Amble and Knuth [1]. As it forms the basis of what follows it is described in more detail in the following section. Section 3 shows how it can be modified so as to significantly reduce its memory requirements. This is done by storing only a small part of each key -- a few extra bits are needed to ensure that different keys, that look the same after truncation, are correctly distinguished. .pp The execution time of this compact hashing algorithm is considered in Section 4. It is shown by simulation to be similar to ordinary BLP for both successful searches and insertion. It is significantly better for unsuccessful searches. .pp A hashing scheme similar to compact hashing in that not all of the key is stored has been proposed by Andreae [2] (Chapter 1). However, his technique has a small but finite probability of retrieving an incorrect key. Although compact hashing is not based on this earlier technique it provided the impetus to seek the current solution. .pp In hashing algorithms using an overflow area and a linked list of synonyms or by variations of this using buckets (see Maurer and Lewis [11]) only the remainder of each key need be stored. This has been known since at least 1965 (Feldman and Low [6] and Knuth [8] sec. 6.4, exercise 13, p543). However, each entry (including the original hash location) requires a pointer to the next overflow record. This pointer will about the same size as the reduction in the key size. So, there is no net memory saving over open addressing techniques such as BLP. .pp Amongst the possible applications of compact hashing is the storage of trees and TRIES without the use of pointers but still preserving a $log N$ retrieval time. It is hoped to report on this application in more detail later. .pp Pascal versions of the algorithms described below are available from the author. .sh "2 Bidirectional linear probing." .pp I will now introduce the open addressing technique which forms the basis of compact hashing. The .ul hash table in which the keys will be stored is an array $T[ 0M ]$ . I will be concerned only with the the keys themselves as the items associated with each key do not significantly affect the algorithms. In order to compute the location for each key I will use two functions: $t$ which randomises the original keys, and $h$ which computes a value in the range $0M$. .pp Let $KK$ be the set of all possible keys and $HH$ be the set of all possible transformed keys. Then $t: KK -> HH$ is an invertible function. This function is introduced to ensure that the keys stored are random and so, as a consequence, the hashing procedure has a satisfactory average performance. In what follows these transformed keys will be used rather than the original keys. For example, it is the transformed keys that are stored in $T$. (-1 is used to indicate an unoccupied location in $T$.) .pp $h: HH ->"{" 0M "}"$ and has the property that for $H sub 1 ~, H sub 2 ~ "\(mo" HH$ $H sub 1 ~<=~ H sub 2~~ "\fBiff\fP"~~h(H sub 1 ) ~<=~ h(H sub 2 )$. As a consequence the keys will be mapped into the hash table in the same order as the values of their transformed keys. This ordering is essential to the compaction attained later. Suitable functions $t$ and $h$ have been extensively discussed (Carter and Wegman, [3]; Knott [7]; Lum, [9]; Lum, Yuen and Dodd, [10]). These authors show that there are functions which almost always make the distribution of transformed keys random. I will not consider any particular functions for $t$ although some examples of $h$ will be introduced later. .pp To retrieve a key, $K$, from the hash table the transformed key and the hash location are first computed. If the (transformed) key stored at the hash location is greater than $t(K)$ then the table is searched upward until one of three things happen. Either an empty location will be found, $T[j]=-1$, or the sought key will be found, $T[j]=t(K)$, or a key greater than the sought key will be found, $T[j]>t(K)$. If the first key examined is less than $t(K)$ then an analogous search is done down the hash table. The search is successful if the sought key is found, that is if the last location examined is equal to $t(K)$, and is unsuccessful otherwise. (See Amble and Knuth [1] for the details of this algorithm). .pp For a given set of keys there are many ways that they can be arranged in $T$ so that the search algorithm above will still work correctly. There is thus freedom, when designing an algorithm to insert new keys, to choose different strategies for positioning the keys. There are two conditions that must be satisfied when a new key is inserted. One is that all keys in the memory must remain in ascending order and the other is that there must be no empty locations between the original hash location of any key and its actual storage position. These imply that all keys sharing the same initial hash location must form a single unbroken group. .pp Within these constraints one would like to insert a new key so as to minimise later retrieval times and the time to do the insertion itself. Intuitively keys which share the same initial hash location should be centered around that initial address. There are two ways of inserting keys which cause little disturbance to the memory. One is to find the position where the key should be placed according to its ordering and then to create a gap for it by moving .ul up all entries from this position up to the next empty location. The second way is symmetric to this and creates a gap by moving entries .ul down one location. The insertion algorithm given by Amble and Knuth [1] chooses which of these two moves to make using a strategy which is guaranteed to minimise the number of locations in $T$ which are examined during later successful or unsuccessful searches, although it is not guaranteed to minimise the insertion time itself. .pp One consequence of this insertion strategy is that sometimes it is necessary to move entries below 0 and above $M$ in the array $T$. One solution to this would be to make the array circular and move entries from 0 to $M-1$ and vice versa. However, following Amble and Knuth [1], I will instead extend the array $T$ and other arrays to be defined later at their top and bottom. This gives 'breathing room' for the array to expand. An extra 20 entries at the top and bottom were found to be quite sufficient for all the simulation runs reported in Section 4. Accordingly I will define $lo ~=~-20$ and $hi~=~M+19$ and define the array $T$ over the range $lo$ to $hi$. .sh "3 Compact Hashing Using Bidirectional Linear Probing" .pp I will now show that the memory required to store the keys in BLP can be significantly reduced. First consider the case when the number of possible keys in $KK$ is less than $M$, then every possible key can be assigned its own location in $T$ without possibility of collision. In this case $T$ degenerates to an ordinary indexed array and the keys need never be stored. At worst a single bit might be needed to say whether a particular key has been stored or not. This raises the question of whether it is necessary to hold the entire key in memory if the key space $KK$ is slightly larger than $M$. For example if $KK$ were, say, four times larger than $M$ then it might be possible to hold only two bits of the key rather than the entire key. The reasoning here is that the main function of the stored keys is to ensure that entries which collide at the same location can be correctly separated. Provided $h$ is suitably chosen at most four keys can be mapped to a single location. The two bits might then be sufficient to store four different values for these four keys. It is in fact possible to realise this reduction in stored key size although a fixed amount of extra information is needed at each location in order to correctly handle collisions. .pp So that I can talk about the part of the key which is in excess of the address space I will now introduce a .ul remainder function $r$. $r$ maps from the transformed keys $HH$ to a set of remainders $RR~==~"{"0,~1,~2,~...,~Rm-1"}"$. It is these remainders that will be stored in lieu of the transformed keys. The essential property of $r$ is that $r(H)$ and $h(H)$ together are sufficient to uniquely determine $H$. .pp .ne 9 Formally, .sp $RR ~~==~~ "{"0,~1,~2,~...,~Rm-1"}"$ .sp $r: HH -> RR$ .sp and $h( H sub 1 )~=~h( H sub 2 )~and~r( H sub 1 )~=~r( H sub 2 ) ~~ "\fBiff\fP" ~~ H sub 1 ~~=~~ H sub 2$ . .sp For a given function $h$ there are usually many possible functions $r$. One particularly simple pair of functions, referred to by Maurer and Lewis [10] as the .ul division method, is $h(H)~~=~~ left floor^ H/Rm right floor$ and $r(H)~~=~~ H~ "\fBmod\fP"~Rm$ . .sp When $r$ is defined as above and $Rm$ is between $2 sup d$ and $2 sup d+1$ the number of bits needed to specify a remainder is the number of bits in the key less $d$. .pp Consider a new array $R [ LH ]$ into which the remainders will be stored. In what follows $R$ will be kept in place of $T$ but it will be useful to talk about $T$ as if it were still there. $R$ and the additional arrays to be introduced shortly specify just the information in $T$, albeit more compactly. Each value $R [i]$ will hold the value $r(T[i])$ with the exception that when $T[i]$ is $-1$ (marking an empty location) then $R[i]$ is also set to $-1$. If there have been no collisions then each $R[i]$ paired with the value $i$ unambiguously gives the transformed key that would have been stored in $T[i]$. However, if there have been collisions it is not possible to tell if a value of $R[i]$ is at its home location or if it has been moved from, say, $i-1$ and corresponds to a key, $H$, where $r(H)~=~ R[i]$ and $h(H)~=~i-1$. If there were some way to locate for each $R[i]$ where it was originally hashed then the original keys could all be unambiguously determined. This can be done by maintaining two extra arrays of bits, the virgin array $V$, and the change array $C$. .pp The virgin array $V[ LH ]$ marks those locations which have never been hashed to. That is, $V[i]$ has a value of $1$ stored if any of the stored keys in the hash table has $i$ as its hash address, and $0$ otherwise. $V$ is maintained by initialising it to $0$ and thereafter setting $V[h(H)] <-~1$ whenever a key $H$ is inserted in the memory. The virginity of a location is unaffected by the move operations during insertion. The $V$ array is similar to the array of pass bits recommended in [1]. .pp To understand the change array $C[ LH ]$ it is necessary to look more closely at the distribution of values of $R[i]$. These remainders can be grouped according to whether or not they share the same original hash address. Also recall that the hash table, as in BLP, is ordered, so, all the remainders in a particular group will occur at consecutive locations. The change bits $C[i]$ are used to delimit the boundaries of these groups. This is done by marking the first remainder (the one stored at the lowest address) of each group with a $1$. All other members of a group have $C[i]=0$. To simplify the search and insertion algorithms it is also convenient to set $C[i]$ to 1 for all locations which are empty ($R[i]=-1$). Thus we have the formal definitions of the values of $V$ and $C$ in terms of the now notional array $T$ (the array $A$ is described later): .bp .nf .ls 1 .ta 0.5i +0.75i +0.9i \(lt\|$r(T[i])$ $T[i] != -1$ $R[i]~~==~~$ \(lk\| \(lb\|$-1$ $T[i]=-1$ .sp \(lt\|$1 EXIST~ j~h(T[j])=i$ $V[i]~~==~~$ \(lk\| \(lb\|$0$ otherwise .sp \(lt\|$1 T[i] != T[i-1]~ roman or ~T[i]=-1$ $C[i]~~==~~$ \(lk\| \(lb\|$0$ otherwise .sp 2 \(lt\|$a(i) -Na <= a(i) <= Na$ $A[i]~~==~~$ \(lk\| \(lb\|$inf$ otherwise .sp where .sp $Na ~>=~ 0$ .br $a(i)~==~ sum from j=lo to i |C[j]=1~"and"~R[j] != -1|~-~ sum from j=lo to i V[j]$ .fi .ls 2 .ta 0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i .rh "Searching. For every group of remainders there will somewhere be a $V$ bit equal to $1$ and a $C$ bit at a non-empty location equal to $1$. That is, for every $V$ bit which is $1$ there is a corresponding $C$ bit which is also $1$. .FC "Fig. 1." This correspondence is indicated in Fig. 1 by the dotted lines. When searching for a key $H$ in the table the location $h(H)$ is examined. If the $V$ bit is $0$ then the search can stop immediately. Otherwise a search is made for the corresponding $C$ bit which is $1$. To do this a search is made down (or up) the hash table until an empty location is found. The number of $V$ bits which are $1$ from $h(H)$ to this empty location are counted. The correct $C$ bit is then found by counting back up (or down) the array from the empty location for the same number of $C$ bits which are $1$. Details of this algorithm follow. .ls 1 .sp .nf .ta 1.5c +1.35c +1.35c +1.35c +1.35c +1.35c +1.35c +1.35c +1.35c .sp .ne 2 Step 1: {initialise variables} $H <-~ t(K);~~j <-~ h(H);~~rem <-~ r(H);~i <-~ j;~~count <-~ 0;$ {check virgin bit} $if~ V[j]=0~then$ {search unsuccessful} $exit ;$ .sp .ne 3 Step 2: {find first empty location down the table} $while ~R[i] != -1~do~~begin~~count <-~count - V[i];~i <-~ i-1 ~end ;$ .sp .ne 4 Step 3: {search back to find uppermost member of relevant group} $while count < 0 ~do~begin~ i <-~i+1;~count <-~count +C[i];~end ;$ {$i$ now points at the first(lowest) member of the group associated} {with the original location $j$} .sp .ne 6 Step 4: {search group associated with $j$} $while R[i+1] <= rem ~and C[i+1]=0~do i <-~i+1 ;$ {check last location to see if key found} $if R[i]=rem~ mark then$ {search successful} $lineup else$ {search unsuccessful} ; .sp 2 .ls 2 .fi .pp An example search is illustrated in Fig. 1 for the key 75. For this example $h$ is computed by dividing by 10 and rounding down, $r$ is computed by taking the remainder modulo 10. .br Step 1: The initial hash location for 75 is 7 and its remainder is 5. The $V$ bit at location 7 is 1 so the search continues. .br Step 2: The first empty location found by searching down the table is at location 3. There are three $V$ bits with a value of 1 between 7 and 3 at locations 4, 6 and 7. .br Step 3: Counting back from location 3 three $C$ bits are 1 at locations 4, 5 and 8. So the $C$ bit at location 8 corresponds to the $V$ bit at the original hash location 7. .br Step 4: The group of remainders which share the same initial location 7 can then be found in locations 8 and 9. Thus the remainder 5 at location 8 can be unambiguously associated with the original key 75 and so it can be concluded that the information associated with the key 75 is present at location 8 in the memory. .pp It still remains to specify the update algorithm and to address some issues of efficiency. To this end a third array will be added. .rh "Speeding up search." It was found during the simulations reported in Section 4 that the most time consuming element of this search is step 2 when the table is scanned for an empty location. The essential role played by the empty locations here is to provide a synchronisation between the 1 bits in the $V$ and $C$ arrays. This lengthy search could be eliminated by maintaining two additional arrays, $#C[ LH ]$ and $#V[ LH ]$, which count from the start of memory the number of $C$ and $V$ bits which are 1. That is: .br $#C[i] ~==~ sum from j=lo to i |C[j]=1~and~R[j] != -1 |$ .br and $#V[i] ~==~ sum from j=lo to i V[j]$ . .br .pp In order to find the $C$ bit corresponding to some $V[i]=1$ then all that is necessary is to compute the difference $count <-~#C[i]-#V[i]$. If $count$ is zero then the remainder stored at $i$ was originally hashed there and has not been moved. If $count$ is positive then it is necessary to scan down the memory until $'count'$ $C$ bits equal to 1 have been found. If $count$ is negative then it is necessary to scan up the memory until $'-count'$ $C$ bits which are 1 have been found. Fig. 2 shows some examples of the various situations which can arise. .FC "Fig. 2." .pp In fact, it is not necessary to store $#C$ and $#V$ explicitly, it is sufficient merely to store the differences $#C[i]-#V[i]$. To do this the .ul At home array, $A[ LH ]$, will be used. .pp At this point it might seem that all earlier gains have been lost because in the most extreme case $#C[i]-#V[i]~=~M$. To store a value of $A$ will require as many bits as a memory index -- precisely the gain made by storing remainders rather than keys!\ However, all is not lost. The values of $A$ tend to cluster closely about 0. Simulation shows that a hash memory which is 95% full has 99% of the $A$ values in the range -15 to +15. Therefore the following strategy can be adopted. Assign a fixed number of bits for storing each value of $A$, say 5 bits. Use these bits to represent the 31 values -15 to +15 and a 32nd value for $inf$. Then anywhere that $#C[i]-#V[i]~<~-15~"or"~>+15$ assign $inf$ to $A[i]$ otherwise assign the true difference. .pp When searching for a key a scan can now be done down (or up) the memory until a location $i$ where $A[i] != inf$ is found. (At worst this will occur at the first unoccupied location where $A[i]$ will be zero.)\ From there a count can be made up (or down) the memory for the appropriate number of $C$ bits which are 1. .pp In the detailed algorithm given below some differences from the simpler search can be noted. In step 3, $count$ can be both positive and negative. Therefore code is included to scan both up and down the memory as appropriate. At the end of step 3, $i$ can be pointing at any member of the group associated with the original hash location. (Above $i$ was always left pointing at the lowest member of the group.)\ Therefore code is included for scanning both up and down the members of the group. In order to prevent redundant checking of locations by this code a flag $direction$ is used. It can take on three values depending on the direction of the memory scan: $"up"$, $"down"$, and $here$ (no further searching need be done). .ls 1 .sp .nf .ta 1.5c +1.45c +1.45c +1.35c +1.35c +1.35c +1.35c +1.35c +1.35c .sp .ne 2 {Search using at-home count} Step 1: {initialise variables} $H <-~ t(K);~~j <-~ h(H);~~rem <-~ r(H);~~i <-~ j;~~count <-~ 0;$ {check virgin bit} $if~ V[j]=0~then$ {search unsuccessful} $exit ;$ .sp .ne 5 Step 2: {find first well defined $A$ value down the memory} $while ~A[i] = inf~do~begin~count <-~count - V[i];~i <-~i-1 ~end ;$ $count <-~count +A[i];$ .sp .ne 16 Step 3: {Search either up or down until a member of sought group is found} {Also ensure $direction$ is set for Step 4.} $if count < 0 ~then$ $direction <-~"up";$ $repeat i <-~i+1;~count <-~count +C[i]~ until count = 0 ;$ $if R[i] ~>=~ rem ~then direction <-~here;$ $else if count > 0 ~then$ $direction <-~"down";$ $repeat ~count <-~count -C[i];~i <-~i-1~ until count = 0 ;$ $if R[i] ~<=~ rem ~then direction <-~here;$ $else${$count = 0$} $if R[i] > rem ~then direction <-~"down"$ $else if R[i] < rem ~then direction <-~"up"$ $else direction <-~here ;$ .sp .ne 16 Step 4: {search group associated with $j$} $case direction~ "\fBof\fP"$ $here: ;${do nothing} $"down": repeat if C[i] = 1 ~then direction <-~here$ $else$ $begin$ $i <-~i-1;$ $if R[i] ~<=~ rem ~then direction <-~here;$ $end$ $until direction = here ;$ $"up": repeat if C[i+1] = 1 ~then direction <-~here$ $else$ $begin$ $i <-~i+1;$ $if R[i] ~>=~ rem ~then direction <-~here;$ $end$ $until direction = here ;$ $end ;$ .sp .ne 4 Step 5: {check last location to see if key found} $if R[i]=rem~ mark then$ {search successful} $lineup else$ {search unsuccessful} ; .sp 2 .ls 2 .fi .FC "Fig. 3." .pp Fig. 3, gives an example of this searching algorithm. The same memory and key (75) as in Fig. 1 are used. For the purposes of the example each $A$ value is allocated one bit. This allows only two values 0 and $inf$. The search proceeds as follows: .br Step 1: The initial hash location for 75 is 7 and its remainder is 5. The $V$ bit at location 7 is 1 so the search continues. .br Step 2: The first $A$ value not equal to $inf$ found by searching down the table is at location 6. There is one $V$ bit with a value of 1 between 7 and 6, at location 7. $count$ is then set to $A[6]+1~=~1$. So on the next step one $C$ bit will be sought. .br Step 3: Counting back up from 6 the first $C$ bit equal to 1 is at location 8. So the $C$ bit at location 8 corresponds to the $V$ bit at the original hash location 7. .br Step 4: The group of remainders which share the same initial location 7 can then be found in locations 8 and 9. The remainder 5 at location 8 can thus be unambiguously associated with the original key 75 and it can be concluded that the information associated with the key 75 is present at location 8 in the memory. .rh "Insertion." Insertion of a new key into the memory requires three distinct steps: first locating whereabouts in the memory the key is to be placed; second deciding how the memory is to be rearranged to make room for the new key; and third moving the remainders whilst correctly preserving the $A$ and $C$ values. (The $V$ bits remain fixed during the move.)\ The initial search can be done as explained above with the small addition that the correct insertion point must still be located when the key is not present. The second and third steps follow the algorithm in Amble and Knuth [1] with the addition that the values of the $A$ array must be re-calculated over the shifted memory locations and the $C$ but not the $V$ bits must be moved with the keys. Details of this can be found in an earlier draft of this paper, [4]. .sh "4 Performance" .pp Now I consider how long these algorithms will take to run. The measure of run time that I will use is the number of .ul probes that each algorithm makes, that is, the number of times locations in the hash table are examined or updated. CPU time measures were taken as well and correlate well with the empirical counts of probes given below. .FC "Table I" .FC "Table II" .rh "Searching." Tables I and II list the results of simulations for successful and unsuccessful searches respectively. Results are tabulated for ordinary BLP and for compact hashing with different memory loadings and different sizes for the $A$ field. If the number of keys stored in the memory is $N$ then the memory loading is measured by $alpha ~==~N/M$, the fraction of locations in the memory which are full. Values of Na were chosen to correspond to $A$ field lengths of 1, 2, 3, 4, and 5 bits, that is for Na equal to 0, 1, 3, 7, and 15 respectively, and also for the case where no $A$ field was used. Increasing the size of the $A$ field beyond 5 bits had no effect at the memory loadings investigated. So Na equal to 15 is effectively the same as an unbounded size for the $A$ values. .pp The insertion procedure is guaranteed to be optimum only for BLP, not for compact hashing. If none of the values in $A$ is $inf$ then the sequence of locations examined by compact hashing is the same as for BLP and so the strategy will still be optimum. (This is easily seen by noting that in compact hashing $A[h(t(K))]$ determines the direction of the search depending on whether it is positive or negative. During the subsequent search no locations past the sought key will be probed. This is exactly the same probing behaviour as in BLP.)\ However, if no $A$ array is being used or if some values of $A$ are $inf$ then extra locations need to be probed to find an empty location or one which is not equal to $inf$. .pp As expected the figures in Table I show that for Na at 15 and using optimum insertion the probes for a successful search are almost the same as for BLP. (The small differences are accounted for by statistical fluctuations in the simulation results.)\ .pp As Na is decreased the number of probes needed for searching increases. This reflects the greater distances that must be traversed to find a value of $A$ not equal to $inf$. It is notable however that even a single bit allocated to the $A$ fields dramatically improves the performance. Even at a memory density of 0.95 some 25% of non-empty locations have $A$ values of 0. .pp The pattern for unsuccessful searches is broadly the same as sketched above for successful searches except that in general unsuccessful searches are quicker than successful ones. This is a result of the $V$ bits which allow many unsuccessful searches to be stopped after a single probe. For example even at the maximum possible memory density of 1 some 36% of $V$ bits are zero. This results in compact hashing being faster than the reported values for ordinary BLP. However, unsuccessful BLP searches could be improved to a similar degree by incorporating $V$ bits. .FC "Table III" .rh "Insertion." The probes to insert a new key can be broken down into three components, those needed to locate the position where the key is to be inserted, those to decide the direction of movement and those to effect the movement of the memory. The first of these will be slightly larger than a successful search and so the results of Table I have not been repeated. The second two are independent of Na as they are dependent only on the lengths of blocks of adjacent non-empty locations. The values for these Na independent components are listed in Table III. In most cases this Na independent component is much larger than the search component. The exception occurs where no $A$ values are being used, when the two components are comparable. .pp Cleary [5] examines a random insertion strategy for ordinary BLP where blocks of entries in the hash table are moved in a randomly chosen direction to accomodate a new entry rather than in the optimum way described by Amble and Knuth [1]. It is shown that this strategy can improve insertion times by a factor of 4 at the expense of small degradations (at most 15%) in retrieval times. These results are shown by simulation to extend to compact hashing. Indeed for small values of Na the optimum and random strategies show no significant differences in retrieval times. .rh "Analytic approximation." While analytic results are not available for the number of probes needed for retrieval or insertion an approximation can be developed for some of the cases. It is shown by Amble and Knuth [1] and Knuth [8] (problem 6.4-47) that the average length of a block of consecutive non-empty locations when using the optimum insertion strategy is approximately $(1- alpha ) sup -2 ~-~1$. Let this block length be $L$. .pp Consider the case of a successful search when no $A$ field is used. A successful scan of a block from an arbitrary position to the end takes on average $L/2~+~1/2$ probes. During the initial scan down the memory in the simulations the initial check of the $V$ bit and the final empty location examined were each counted as a single probe. This gives a total of $L/2~+~5/2$ probes for the initial scan down. (This is not exact because there will be a correlation between the position of a key's home location within a block and the number of keys hashing to that home location). The scan back up a block will take $L/2~+1/2$ probes (exact for a successful search). This gives $(1- alpha ) sup -2 +2$ for the expected number of probes during a successful search. These values are listed in Table I and are consistently low by about 10%. .pp For an unsuccessful search with no $A$ field the initial scan down the memory will take $L/2~+5/2$ probes as above (again this will not be exact because the probability of a $V$ bit being one will be correlated with the size of a block and its position within the block). An unsuccessful scan of a block takes $L/2~+~1/2$ probes. (This assumes the keys in the block are distributed uniformly. This gives the following probabilities that the search will stop at a particular location in the block: the first location, $1/2L$; locations 2 through $L$, $1/L$; the empty $(L+1)$st location, $1/~2L$. This will not be true for compact hashing because the probability of stopping at a key which shares its home location with a large number of other keys will be smaller than for one which shares it with few others.)\ \ Summing these two terms gives $L~+~7/2$ probes. Given that the keys are distributed randomly there is a probability of $e sup {- alpha}$ that a given $V$ bit will be zero. So the expected number of probes overall for an unsuccessful search is $e sup {- alpha}~+~(1-e sup {- alpha}) cdot ((1- alpha ) sup -2 + 5/2)$. These values are listed in Table II and are consistently low by about 5%. .pp Considering only the insertion component which is independent of Na then it is possible to derive an expression for the number of probes. There is an initial scan to move the memory down and insert the new key which will scan about half the block ($L/2~+~5/2$ probes) and a subsequent scan back up of the entire block ($L~+~1$ probes). Empirically the probability that the entire block will subsequently be moved back up is a half which gives an expected $1/2(L~+~1)$ probes. Summing these three contributions gives $2(1- alpha ) sup -2 ~+~2$ as the expected number of probes for an insertion (excluding the search time). Values for this expression are tabulated in Table III, they are in good agreement with the empirical values. .sh "Acknowledgements" .pp I would like to thank Ian Witten for careful checking of a draft version. Also John Andreae for discussions which showed that something like compact hashing might be possible. .sh "References" .ls 1 .LB "[6] " .sp .NI "[1] " [1]\ \ O.\ Amble and D.\ E.\ Knuth, "Ordered Hash Tables," .ul Computer Journal, vol. 17, pp135-142, 1974. .sp .NI "[1] " [2]\ \ J.\ H.\ Andreae, .ul Thinking with the teachable machine. London: Academic Press, 1977. .sp .NI "[1] " [3]\ \ J.\ L.\ Carter and M.\ N.\ Wegman, "Universal classes of hash functions," .ul J. Computer System Sci., vol. 18, pp143-154, 1979. .sp .NI "[2] " [4]\ \ J.\ G.\ Cleary, "Compact hash tables," Research Report, 82/100/19, Department of Computer Science, University of Calgary, July 1982. .sp .NI "[3] " [5]\ \ J.\ G.\ Cleary, "Random insertion for bidirectional linear probing can be better than optimum," Research Report, 82/105/24, Department of Computer Science, University of Calgary, September 1982. .sp .NI "[5] " [6]\ \ J. A. Feldman and J. R. Low, "Comment on Brent's Scatter Storage Algorithm," .ul CACM, vol. 16, p703, 1973. .sp .NI "[7] " [7]\ \ G. D. Knott, "Hashing functions," .ul The Computer Journal, vol. 18, pp265-278, 1975. .sp .NI "[7] " [8]\ \ D.\ E.\ Knuth, .ul The art of computer programming:Sorting and searching. Vol III. Reading, Massachusetts: Addison Wesley, 1973. .sp .NI "[8] " [9]\ \ V.\ Y.\ Lum, "General performance analysis of key-to-address transformation methods using an abstract file concept," .ul CACM, vol. 16, pp603-612, 1973. .sp .NI "[12] " [10]\ \ V.\ Y.\ Lum,\ P.\ S.\ T.\ Yuen and M.\ Dodd, "Key-to-address transformation techniques," .ul CACM, vol. 14, pp228-239, 1971. .sp .NI "[13] " [11]\ \ W. D. Maurer and T. G. Lewis, "Hash table methods," .ul Comp. Surveys, vol. 7, pp5-19, 1975. .ls 2 .in 0 .bp 0 \&\ .RF .ta 0.5i +0.75i +0.75i +0.75i +0.75i +0.75i .nf $i T[i] R[i] V[i] C[i]$ \l'3.5i' .br 12 \0\ -1 \ -1 0 1 .br 11 101 \01 0 1 .br 10 \087 \07 1 1 .br \09 \076 \06 0 0 .br \08 \075 \05 1 1 .br \07 \067 \07 1 0 .br \06 \066 \06 1 0 .br \05 \065 \05 0 1 .br \04 \041 \01 1 1 .br \03 \0\ -1 \ -1 0 1 .br \02 \019 \09 0 0 .br \01 \018 \08 1 0 .br \00 \016 \06 0 1 .br Step 1 Step 2 Step 3 Step 4 .br $h(H)~=~ left floor^ H/10 right floor$ .br $r(H)~=~ H~ roman mod ~10$ .br .FG "" .bp 0 \&\ .RF .nf .ta 0.5i +0.75i +0.75i +0.75i +0.75i $count~=~A[i]~=~#C[i]-#V[i]$ .sp $count = 0$ $count = 0$ $C$ $V$ $C$ $V$ 0\|\(rt 1 0\|\(rt 1 0\|\(rk 0 0\|\(rk 1$<-~i$ 1\|\(rb 1$<-~i$ 1\|\(rb 0 .sp $count =1>0$ $count = 2 > 0$ $C$ $V$ $C$ $V$ 0 1$<-~i$ 0 1$<-~i$ 1 0 1 0 0\|\(rt 1 1 1 0\|\(rk 0 0\|\(rt 0 1\|\(rb 0 0\|\(rk 0 1\|\(rb 0 .sp $count =-1<0$ $C$ $V$ 0\|\(rt 0 \|\(rt 0\|\(rk 0 \|\(rk\ \ Group of entries which hash to 1\|\(rb 0 \|\(rb\ \ location i 0 0 1 1$<-~i$ \ \ \ Corresponding $C$ and $V$ bits .FG "" .bp 0 \&\ .RF .ta 0.5i +0.5i +0.5i +0.5i +0.5i +0.9i +0.6i +0.4i $i R[i] V[i] C[i] #V[i] #C[i]~~#C[i]-#V[i] A[i]$ .br \l'4.5i' .br 12 \ -1 0 1 6 6 \00 0 .br 11 \01 0 1 6 6 \00 0 .br 10 \07 1 1 6 5 \ -1 $inf$ .br \09 \06 0 0 5 4 \ -1 $inf$ .br \08 \05 1 1 5 4 \ -1 $inf$ .br \07 \07 1 0 4 3 \ -1 $inf$ .br \06 \06 1 0 3 3 \00 0 .br \05 \05 0 1 2 3 \01 $inf$ .br \04 \01 1 1 2 2 \00 0 .br \03 \ -1 0 1 1 1 \00 0 .br \02 \09 0 0 1 1 \00 0 .br \01 \08 1 0 1 1 \00 0 .br \00 \06 0 1 0 1 \01 $inf$ .br Step 1 Step 2 Step 3 Step 4 .sp Note: Only one bit has been allowed for the values of $A$. .br So the only two possible values are 0 and $inf$. .FG "" .bp 0 \&\ .RF .ta 1.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i .ce Successful Search \l'4i' $alpha$ \0.25 \0.5 \0.75 \0.8 \0.85 \0.9 \0.95 \l'4i' $BLP sup 1$ \0\01.1 \0\01.3 \0\01.7 \0\02.0 \0\02.3 \0\02.9 \0\04.2 Na 15 \0\01.1 \0\01.3 \0\01.7 \0\01.9 \0\02.2 \0\02.8 \0\04.6 \07 \0\01.1 \0\01.3 \0\01.7 \0\01.9 \0\02.2 \0\02.8 \0\09.7 \03 \0\01.1 \0\01.3 \0\01.7 \0\01.9 \0\02.4 \0\04.2 \025 \01 \0\01.1 \0\01.3 \0\02.0 \0\02.5 \0\04.1 \0\08.8 \045 \00 \0\01.1 \0\01.5 \0\03.3 \0\04.9 \0\07.9 \015 \061 \0- \0\04.2 \0\07.1 \020 \030 \049 110 370 \0* \0\03.77 \0\06.00 \018.0 \027.0 \046.4 102 402 $\& sup 1~$Taken from Amble and Knuth [1]. - No $A$ field used. * Analytic approximation to line above. .FG "" .bp 0 \& .RF .ta 1.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i .ce Unsuccessful Search \l'4i' $alpha$ \0.25 \0.5 \0.75 \0.8 \0.85 \0.9 \0.95 \l'4i' $BLP sup 1$ \0\01.3 \0\01.5 \0\02.1 \0\02.3 \0\02.6 \0\03.1 \0\04.4 Na 15 \0\01.2 \0\01.4 \0\01.8 \0\01.9 \0\02.1 \0\02.4 \0\03.5 \07 \0\01.2 \0\01.4 \0\01.8 \0\01.9 \0\02.1 \0\02.4 \0\09.7 \03 \0\01.2 \0\01.4 \0\01.8 \0\01.9 \0\02.2 \0\03.3 \015 \01 \0\01.2 \0\01.4 \0\01.9 \0\02.2 \0\03.2 \0\06.0 \028 \00 \0\01.2 \0\01.5 \0\02.6 \0\03.4 \0\05.3 \0\09.9 \036 \0- \0\01.7 \0\03.4 \011 \016 \028 \064 220 \0* \0\01.72 \0\03.16 \010.2 \015.6 \027.3 \061.2 247 $\& sup 1~$Taken from Amble and Knuth [1]. - No $A$ field used. * Analytic approximation to line above. .FG "" .bp 0 \& .RF .ta 1.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i +0.5i \l'4i' $alpha$ \0.25 \0.5 \0.75 \0.8 \0.85 \0.9 \0.95 \l'4i' \0\04.3 \0\08.8 \032 \049 \086 200 700 * \0\04.56 \0\09.00 \033.0 \051.0 \089.9\ 201 801 * Analytic approximation to line above .FG "" .bp 0 \& .ce List of Figures .sp 2 Fig. 1. Example of compact hash memory and search for key. .sp 2 Fig. 2. Examples showing different values of $#C[i]-#V[i]$. .sp 2 Fig. 3. Example of calculation and use of array $A$. .sp 2 .ce List of Tables .sp 2 Table I. Average number of probes during a successful search. .sp 2 Table II. Average number of probes during an unsuccessful search. .sp 2 Table III. Average number of probes to move block of memory. .sp 2 @@ <@xx| g |>x?p8<x?x?=|?~8??<??p??=>x?`?~xxx??9?p~xxx?߁?x~0 ?xπ?|>@`??x營x|<>|ߏߟx烿||?<ߟϟxǁ|;x?8|ϟϟx|x??ǀ~{??ߟ|Ϗ~πϟxxψO???}ߏ|Ͽπϟ|xcϏϏ??>~?Ϗ>?ϟxx燏s?>x`?~?Ͽ>?πϏ|xǀσ~??~?Ͼ|πχs|x߁?ߟ?~?`Ͽ|?ϟ???Ϗ~~>Ͽx?翀|`?~ߏ~~??||?~<@x?<x?ߟ????|p>@px@0|~<<8>?>??>>?>?>~~<?~8?><~?>|@|?|s p~??< ?~?|????|???~??~?>|~}|?~?߀|>~|>Ͽ??~|}~?~>|ߟ?>~|?>|Ϗ?|>|?>>~||}@>??~>|>>~~|>>|ߏ~|>}?>?O>>|~<π|?|}p|xxߏ ~>}?>8>~?߀|?~>|~|ߏ>χ>?~?}߃???~?π????~?????????| `?|?x|8`` y??x >x?~~8|?~>?x~?~>??>~ > `>|<|g>><<? >>??~>???>?~>~??>?>>??p~>?>>>?~}?~π>>>>>>=?|?|߇߇~?>?>>>>~}`?>~?|~π~>>>>}>~|?~߇~>~?>>>>|}??>?|~O~~>3>>>>>}>~|?|χϟ~?~|~?~~?>>>>|}>`?>~||π?~>?>~~߾>~~߀?~??~>?>???~??<~?>?~~>?|?}>8?O>??q`x>?@?|>?8??x0 ?>>??<??<>??@>{>?|??>{<?|>?>>|p?|>>|ހ?| 0?|ϟ?x?>ϟ?xx?~???Ϗ????????}|??}~~~|}?>|~|?>~|Ͽ?>~|Ͽ?À=>~|Ͽ??~~|Ͽ?>~|ϟπ~ϟ߿~ߟ????~?ߏ??? ?|=>0?y~x|?x~?x?>y~x<}?8@`|>p|>|><|><|~|||||||||x||x|||||<||<|||Ǿ|x?|8|<<x?|?<|x?|x??|?x|x?|x?|?|?8?|?8?|<>>?p||<>xp|x>xr>||>8>y8|x>~<||Ͽ~x><}?x<x|?8x?'0|?|8|8|<<|?|>|`><|>>|~|??|?x|߀|?x|x?x|>x?|<||p|||||x`|x?|?|?|?||?| `|?>||||||||||||||||| p]|><|<<><|~<<x |<8x|~8<|>8x<|`8>|>8|8x=0?|x0x?<~?p>|??|Ǐq?p>?~?|χ3<`<>|??x>~<߃<|ǟ<x<><<|x|ǿx>?x<<<xx<>?x<xx<<>~yϟ<8<LJx<<#χ>?y<|>xϞ2x<<ǜ{??8~<| ǟ>3x<<|?x<~|39|Ͽ8?|x<><?||px|???|p<@?~??p|x< <po<|><<`|>9@< |>>??8|~|8?`~8||?>#0<<?|xp?? ?p00?| ?|?p|?|`~<`?~~|`p 3|??@><????><χ>?߇y><?>?||<>>xpx??|>~?Ϟ1xxx>?>>>|?ǏsϏLJxxx~|>x>>|<<ß3ϏO燏x><||<?珏?x<<|<xǏx ><<<x><|x<xǏx?><<<<|xx?><||>|oLJx>>>?x??x><<||<3Ϗ~8y|x=>>~~???|>|>><~>~9矜?y>>>>?|>~<|~~?ϟx8|?>|?Ϗx|x<?~~???xx<|~~Ax~<8~0o|00_~|~>|>xx|x|x|<?>|p>?>?~><?`~|><?|>xx|x8x|p<>|<<<|>?|<<> px<g>yx@x g<?p<<1<>~< <3~???<<<|x>xg~||>x<?~x~xx<>|?|>x<?x>><y燀><?x<>>x><x><<|><x<x|>>|><x<gx>>>><|<Ǽx|xx<???<>><|8<ǿ|x~?|<>>>><?>~|~>xx??|><<??~>>|@ ?|>>>?|~?~~? ??~`<x<`<x| ` |px|@x|xx|x<<>px||08 <x 00`|~|>????>>~?<|0>???yxx<>>ǀpxx|<<Ǐ~xxx<|>x<|<χ<p<?|Ͽ>>>||??xxx<?|>y>?|<p<3Ϟ?|||xx|<1Ǐx>|#LJx<cx||ϟ||<s8q?π<>x>|<Ϗǀ8>?|σ>|x>?Ǐ<?y?<>ϟ??8?<a?<?88?぀x??@p0 ?>;@xx xx|8?>??xxGxw?8x |~p`x??|?σϏǏǜx>?Ϟ~??x|xxxxx<<燇x<<LJ ;><?x?x<LJ?><>xxx~p<LJ ϟx><<π>xx|9<燇|<Gyx|Ϗ?>sy?~?σxx>>??~~p?|~x<8?y>?pp?> ??>?<pps<x~x `8~?x`x<>`?x`xp|0?;??|0??x?x>?|xLJyyy>~xxgx>?燏>Ǐ0g7nj|珟pǎ<|x><<yyxLJx~8<?πyxϏ~>x<π~x<@p>p<@<?|8g8?>0<x~~>qx?pp|x><88<|>|x ~<|`<x<||<||yx<xx<q<<> ><<<|}x<xx<y 0ÀǞ<<<||y<x`x0<y<xǟ><<<|}x<xxx|<><|}|<>||y~~x??8<pp8<>>?||???8xp< 8~~??x<xgp~?<|p<x~>|xx~|88?|<|0g?88<??p~?88xx>88~?|??<>xx?80|Ϗ>ϟ<ǿxxy?<p|yLJヿx<|xx?<?p|Ϗ<x=x?xx<x?`xxx=x>xx?x8<<}|<x=xxxx<8?ǰ|燀>|9xyxxǿ8x?|χ>??x8?>|>??|x`|?@?8<><88x?>?>??>0~|???>|?>????|<~?>?xx|=Ǐ|?~ǀ|x?~~~8x<ǃLJπ>x??>?~?<~<x{<ǃ>x<<<>?~|0 ~??~σ>x<> <>??>~?|?~?>σx>x|> `<|><?>?~??~|?~??σ>|χ=>>??>?~??~|~~'σLJǀ<||~???>>||>|LJ?x~???~?~~|?߿>?|?~|~|Ǐϟ???~>>>~||~?>~|7>|ǁ?>?>~|?|~>?||~|?<>?>~||??>~|>||???>~|??|~0>?~|op?||?|p?>8>>~|?ǀ||>x??>~|~>|?y???~>~|?߿?~||??~~|?>?>~???~~~?????????~????~??>8<8<?>>> ~?<|? 88<> <<|>> ><>|~x>88?x<|?8>px#ǀ|?|?xx> pp??> |8>~?χ?|yLJx~?x=<ϟxχ?~|?<|<LJ?<ះx~|>~|g<CLJxx~>|>>>|>χ'>||<||<<LJ><<LJx~|?LJ|xx~??~?>??||<<<<<LJ|Àx~χ???~?||><<> 1LJ>|x????||<<>ñÞ>???>~>|>><>LJ>?<LJ?|<~??}߀?>}|=|>|>><<Ϗ<>>???~<?~|~?~ߟ????|||>|?><???|8|~||~ߟ???>~?~||>~~?>>x|~|||~ߟ????||>>~?|x|~||~Ϗ??>?~|>0?>| ~||~~ ߟ????8?~>x?~|~?~Ͽ>ߟ?}π??>???~|~~Ͽߟ?????~~?߿ߟ????~?????<|>ߏ~x>w 8>`>|>8>|08xx<8p<0<88x?x<x8<=|?<o{?>?`??????><>x<|?x8π>cx?χ?>x>>><|x<||x>?<=<<>xLJ<xxxx<x??ǁpπǏ?|yx9<<xpxx>x<|><<|<xxxx<xxx>x~>>>?|y<<xxx8xx>3<0πϟ~<xǃ<>xxxx|<xx0x|x?Ǐ>>?||<OLJ<|xxx|~>>x>cχ<<<}??>?߇g><|>?<Ϗx????~~πs>||>~?< {>>~||<0??>~??8<|x8|>~0 @> xχ>p>>>Ϗx?GO???>x?8;3??<xO?~>ǟyp?|<??~}<|?>8|?~}>~?~|~|??q83><<||x?<???>~}Ϗ>x~|x<<x?<>?????~?Ǐx?<8???>~?ϏǏxo~x<<x<<<o??????>~Ϗx?~x<<<3??~ߟ~>>>~|Ǐx>|<< ?<~>??~>?>?>>>~||Ϗ>yx?|<<|x?>>>~|Ǐ`<|y><<<<|xx?|>?>??>??>>>>>||Ϗ|x?~||~?~??|~~>?>>>~||Ϗ?π~~~>|>?>~??~>x?|??>>||~xϏߏ?~||<????;ߟ??ϟ>>~???|x??>????~~|χ?8`x x߿~~|~~?ߟ8x?8xy?@880|x><x>>8|< ?>|??~>@0`?>~@G????? ?  >  ????<< >>Ǐ>>??{>>8>?{<<>?>>~Ϙ<<<<<<x<???>>>}9<>><x<<< <x>|{|<<x<<><<x<????>|;<><yx<><xx0|>>ߏϏ?x|<<x<><<<??>Ϗ||><|x><0?>>Ϗ||<<<>?????>ϟ>>Ϗ|><<<>><????>>Ϗ>?>>Ϗ9}Ϟ><<?>~~?>G??߀>Ϗ?=>|??>~~<x<wǀ>ϟ?~߀?>߇Ϗ?~~0<??Ϟ?>Ϗ?|<y??????߇ϟ???|?>>>?߀?߀>>>????>|>?Ϗ?xx~>p||>@80|~7? <~>>~|@>><?|<>|}~< >?~~>~`<`x< <?>?~x`>>|  x>|?????~p~|<p>|}??>>x?>?>p?=x>|?|y?x<>|<<w??|?>Ǐy8x<|?>?>??><|y<ǟχ<<3~<<<|??????|><><ÿ<x<>|x?x<7y<?<<??~ϼ?>??||?|>}ǀ<>x>>>?>>?>?||x>x><ǀx>~Ϗ>????>>|?|>|>~}ǏyÞx<?0~~}>>>?>?>?<||x? >|~>`Ϗ>????>>||>>>|y<<>x~?>~ ?>>?>>|>~|0x?|px<þ?~<>~pϟ>??|?|>>|x|>08p?>~~?>?>|>>~~}|??<@p<???~~ߟ?????~~||pxp?>?~~ߏ????~?>??????<|~~ϟxp8A >x |>> p~0>`~x~@8~p8<|~|`|xC0 '|??p0>???`>?y 7gϏϏ??y8x??<LJ|0? ǀ8>LJLJ<~y?|???}?yxǀ8>LJ<<x??>?x8??ǃ<<?y????|?s|0xǃ><y???|>|px燃ǃ><<Gq~??p|><??p<|LJǃ<a<?~|}>?>|>>|?ǀpx|8LJLJ><s8|?>~||??|>0>?ǀ`xǃ?LJǏ>?~||?>?>y>>>?9>???>??|?|>~||?~~?>?χ??@?~|?߆>~??>??>>?χ~"``0<?>~||?{ߟ???~ ~~|?χ?{???>~x|<`>?~~|߿<??x?~~??~8?`|?À||99|l>}??<><~><?|||~???~p<><>~@~||x~|2z?~~|?~x~?~?~?~?~??>?~8?~8?|8??~8??|p??~0?|?~?|?~?|~?|~?|>?|~?|x~?|?~??|?~??~??>??~??>??~??>???~??>???>??>??>??>???>??>???~???~???~??~???~??~???~??~???~??|???~??~>??~8?|?|<|>?@?>?>8>?<?||x<?> ??><|x?<??||x|?>ǀ??>~|?>~x?>?>x?>?~xx?>?>x|?>`~x|?>1π??><~?>?sπ?<~<~>?`>x?yǀ?~>>>?>?0?~<<?>?~<?>??~?>?>?>??~<?>?><????~<????~<????~<???><??><??><???><~???><???><???><???><?><?><??><??>???><??><???><???><??~<??>>??~<?><>?~<?><>~<À?>>~<À?>>~<?><?><?><>~<?><?~<?>?~<?>?><?>?><?>>?><?>?><?>?>?>?>>?>?>?>p?>p?>>p?>p?>>p?<>p?><p?>x?>xx<xx<xx<xx<x8<>x8<x8<x8<8<8<>< <?~><8<~><< <>so?߿s~?8<sx~<??~?>|~>0~@x>}pp|<>?<?><<x<<<?<?9<9<<??|><q0<@@><><<<<<p?pp<ypp?<?`> ?<<<<<<<<<<<<<?>|8<~||>>x ~|~?yx~|~??<~<8~<>~||?~~0`Gx~0~?~??>||???x?|?~?q~~?~???c||??>~~?>~~>>|???||ߟߏ>>~|~~߸>~~??|}@?>~|ϟ~~@>~|???@@??>~|~~w?~`>~~??|ߏ|p??~~~?|~?|?Ϟ}`Ç?~p~~???0?`|~}|>?p >?8>>xp`?x q??????<;?|c???~?χ??~???~???>?>~~|???>?>|?~|????~?>?||?߀???~>?||??>?>~ ?>?||>??>?~p>?||@??????|>>||?χ<????~~~|>χ???~|??>???>>??~???x~~|???{?߀??{??{??{?}{|{p|x{`{x<<~>p{x~?>x~<|>~ߏ{8x~~ ????><??? >~???χ?~~>??>~?????߿?~~~?????>>?>>~?π????>~~~|?>||?<x}??>>~~>?~}|?<??>~~~|?>>|?~|w}??>>~~?>?߀|}?<?>>~~|;?ǿ>w|} ><???~~~9?>~ߏ|}ߟ><??~~~}?>~|}߿?>??~?~~|?>????~>???~~|???~~?>? |||}?7<8` ?;????{???>>~~>|>|?>|~? ?>||?=>|ߏ?=<ߟ}><ϟ>a??0>>>>}Ͽ??=>??߿>=>`~ᅬ? ?>??@0}?p8???8|?xy |< ?>~?p?x>p~?p?>?p??p~p?}~<?@0<<??8A?a?>?xx{?yyyyyyCyyy{y{}{<=<<????~???π???||88À`~|08À??~|?@~>|>?>??>?????>?????? >??x??À~~~?~x߀~?>?~~|?~?߀~?>~>?~<?~?߀/<?~|~>~~~|@ 80?>| ?Ç?~|??߀<<~~~>|~ǀ0A8<8<<ǀ<π<<<x?y8y| >>????ߟ矟?>?ߟ~p??ߟp???ߟs??~p|??~<|??p8?>~pxx>xxppxp8xpxpxxxxxxxxxx8888888<<??=8<8<8<8<8<<<<<<<<<>>?> ? ?<~0d8(??>>>>?>><<>><<>><<>>8>>8>>x>>x>>?>>?>>>><>?>?>????aC????>?>?>?>>>>?>>||>>?|p>>`??>>>xy?>~>>>>?>?>>>>>?>?>?>>>>>>>>?>>?>>?>>?>>??>>?>?>?>?>?>? >??>>?>?>?`>?>>>>?>>>>>?>>>>?>>>>>>?>>>>?>>>?>>?>?>>>?>>>?>?>?>>>?>>>>?>>8>?>|xx>?x>>?8x`x>><>>>~p~?g`<8xg|x>??π|x>?????w><<?<㏟><>=x{>Ϗ|?<?<8x>Ϗ|?x<?<|>Ϗ?|x<xxx<x<|>?||>|xx<x<|>Ϗϟx? ||>||<|<|>ǟ?<?y??8>8>>> x>><??????x>???>???>?|?~????>>| 0|<>88`>?>`>>>?>?>?>>0 >>>@> 88p >>>x|<>|~~>>>x|>>|>?>>@@xx8<<|><` >??#8|`|@><<p>>xx???<x8<| x?>|χ>?xw>>???>x<?<>??>9?Ϟ||||?|π8>}<<>>><xxy|<|x|<>>||<<|Oǟ!LJ<>?~>>><|x<|x<Ϗ<?x?>>?|||><||x燏>x?<>>><|>xxx?|<|xy<<|x>>>~|||O<<<|x'ǟ|<><<>?>~y||x|<|xqǟ>~p8><<<<|>?||<|y>y>>??<>??~~~??Ϗ>??|>?~??ϟ?x?>> <~|~><|?<ߏx<>> <}>><>>?>>?>?>?>?>>`>>~>>p|?>>~~>|?>>><>>>> |<?>>>| `>>wx<>xp>>?>8~?|x>>?>>???>xc#@x?>>~|>>??>|Ϗ?? >||y>>}?<x߇?>|>?>>|y<<||LJ|x?>>|s>|?xx??>|>?>>><|LJxy?|`??>|>>?|xxx???|?>|>|?>?}< }|LJxy<| ?>O ~?>||ǀ>?π>>?>|LJxy/>|>>?>><yx~x> >>??|xx?<> >~~?>???x?>|q?>><??>>G>>><?>|>>??>` >>>>>>``0>><>>p|<>>|p>?>>>|`8|~>>|x8xx>>|Oxp<xx|>>|??`gxx<>?>>|<=8?>|}>?>>|y?~<>xx>???|{<>||xx>sϿ>|x<>>||<|xx>߱>|?|<|xx<<<78>g>>|<<||x<<<>>||<|xx<<<>>|sχ|<>|||xx|<<?>>||<>|?|x|y<<~xÀ>>?||?<<|Ǹ<>~??||~~?<<>>`x|>?~~?<<>>03 ?|x<>> 0~x<|>>p<<>>>xp>>>>>>>>x>>>?|>>x>?8 >>xÀ`<>>x80 ||>>~3Àg`00<>???~?x <>~|x?~?x?>||xϟ9}><|||x|x}<>x>xxx<>9?|y>y?>||xǿ>?x{|>|||xx?|x}<>xxx<ǁx<|o>S>|xxLJ<<xx??|>>|||xx>>|x|<>xxx<>'?x}<|>>~ǟx>?xxy><>??_|xy><>|<|xx<>ǿyx>???|~>|~|ρǿ<ώ>????><|>>00}?{<||>?||?!8>p~|?>`>|< |><>~< >?|<>|>|~?~>|>|?~><? >~>>>>xx |><xx>?|<p>?0p>??`>>?>ǀ?>?>?>??>?>>>px>x|>>x>>>8>?>?<p<p8>?8x3<8p?x??``< xx>`??>?>>|??>߁><x|>><ߟ<?~||y>>><?<Ǐ>xxxy><|?LJxx|xx>|~?ǟxxxx><||<xLJx3|>xxx?>||>|Ǟxx>xxxϞ>><|x?> |LJx|x>><|x>?>LJx?>?|?LJxx|q~?>|?Ǐz>?<~???~><<?~?< <x@?>ǀ8 ~0??{y||~~<>||?>??>p>x>?>>| >><x<~|>?<?8><8><~<<`8|8>>>| x >xx~>~Ǐ??<<>~0<|??|||xy;|>~Ϗ?>||Y||w<><<<<|>x|x>s?||<χ||<><<<<<|xgx>|?||?<?||><<<|x<?||?x|><<<><|x>x|?~<||<<>x<<|x<?|||9gx~>><<|<<|xx>x><=πq|?>><<|?|<<<??{|?<?p|~??||ǃ?`|?~??~~??<~~珀> |~?8????{||>>>|<<>> @p?x80>~|x8?>`p|xx|~?pp8xxa`0x<{~||`??x8<|>x?πx{<>|~xw|||x?qǟx?<||x~ϟ?|ϟ0x9><||x|w?ǃyǏ><||x|?LJyLJ~?<>|||xxǁy@ǁ<>|||x|yLJ??||||σy`Ǐ8?||<~9`yǏ8?~8<~?> /* * Compress - data compression program */ #define min(a,b) ((a>b) ? b : a) /* * machine variants which require cc -Dmachine: pdp11, z8000, pcxt */ /* * Set USERMEM to the maximum amount of physical user memory available * in bytes. USERMEM is used to determine the maximum BITS that can be used * for compression. * * SACREDMEM is the amount of physical memory saved for others; compress * will hog the rest. */ #ifndef SACREDMEM #define SACREDMEM 0 #endif #ifndef USERMEM # define USERMEM 450000 /* default user memory */ #endif #ifdef interdata /* (Perkin-Elmer) */ #define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */ #endif #ifdef pdp11 # define BITS 12 /* max bits/code for 16-bit machine */ # define NO_UCHAR /* also if "unsigned char" functions as signed char */ # undef USERMEM #endif /* pdp11 */ /* don't forget to compile with -i */ #ifdef z8000 # define BITS 12 # undef vax /* weird preprocessor */ # undef USERMEM #endif /* z8000 */ #ifdef pcxt # define BITS 12 # undef USERMEM #endif /* pcxt */ #ifdef USERMEM # if USERMEM >= (433484+SACREDMEM) # define PBITS 16 # else # if USERMEM >= (229600+SACREDMEM) # define PBITS 15 # else # if USERMEM >= (127536+SACREDMEM) # define PBITS 14 # else # if USERMEM >= (73464+SACREDMEM) # define PBITS 13 # else # define PBITS 12 # endif # endif # endif # endif # undef USERMEM #endif /* USERMEM */ #ifdef PBITS /* Preferred BITS for this memory size */ # ifndef BITS # define BITS PBITS # endif BITS #endif /* PBITS */ #if BITS == 16 # define HSIZE 69001 /* 95% occupancy */ #endif #if BITS == 15 # define HSIZE 35023 /* 94% occupancy */ #endif #if BITS == 14 # define HSIZE 18013 /* 91% occupancy */ #endif #if BITS == 13 # define HSIZE 9001 /* 91% occupancy */ #endif #if BITS <= 12 # define HSIZE 5003 /* 80% occupancy */ #endif #ifdef M_XENIX /* Stupid compiler can't handle arrays with */ # if BITS == 16 /* more than 65535 bytes - so we fake it */ # define XENIX_16 # else # if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */ # define BITS 13 # endif # endif #endif /* * a code_int must be able to hold 2**BITS values of type int, and also -1 */ #if BITS > 15 typedef long int code_int; #else typedef int code_int; #endif #ifdef SIGNED_COMPARE_SLOW typedef unsigned long int count_int; typedef unsigned short int count_short; #else typedef long int count_int; #endif #ifdef NO_UCHAR typedef char char_type; #else typedef unsigned char char_type; #endif /* UCHAR */ char_type magic_header[] = { "\037\235" }; /* 1F 9D */ /* Defines for third byte of header */ #define BIT_MASK 0x1f #define BLOCK_MASK 0x80 /* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is a fourth header byte (for expansion). */ #define INIT_BITS 9 /* initial number of bits/code */ /* * compress.c - File compression ala IEEE Computer, June 1984. * * Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) * Jim McKie (decvax!mcvax!jim) * Steve Davies (decvax!vax135!petsd!peora!srd) * Ken Turkowski (decvax!decwrl!turtlevax!ken) * James A. Woods (decvax!ihnp4!ames!jaw) * Joe Orost (decvax!vax135!petsd!joe) * * $Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $ * $Log: compress.c,v $ * Revision 4.0 85/07/30 12:50:00 joe * Removed ferror() calls in output routine on every output except first. * Prepared for release to the world. * * Revision 3.6 85/07/04 01:22:21 joe * Remove much wasted storage by overlaying hash table with the tables * used by decompress: tab_suffix[1<putc] and * added signal catcher [plus beef in writeerr()] to delete effluvia. * * Revision 2.0 84/08/28 22:00:00 petsd!joe * Add check for foreground before prompting user. Insert maxbits into * compressed file. Force file being uncompressed to end with ".Z". * Added "-c" flag and "zcat". Prepared for release. * * Revision 1.10 84/08/24 18:28:00 turtlevax!ken * Will only compress regular files (no directories), added a magic number * header (plus an undocumented -n flag to handle old files without headers), * added -f flag to force overwriting of possibly existing destination file, * otherwise the user is prompted for a response. Will tack on a .Z to a * filename if it doesn't have one when decompressing. Will only replace * file if it was compressed. * * Revision 1.9 84/08/16 17:28:00 turtlevax!ken * Removed scanargs(), getopt(), added .Z extension and unlimited number of * filenames to compress. Flags may be clustered (-Ddvb12) or separated * (-D -d -v -b 12), or combination thereof. Modes and other status is * copied with copystat(). -O bug for 4.2 seems to have disappeared with * 1.8. * * Revision 1.8 84/08/09 23:15:00 joe * Made it compatible with vax version, installed jim's fixes/enhancements * * Revision 1.6 84/08/01 22:08:00 joe * Sped up algorithm significantly by sorting the compress chain. * * Revision 1.5 84/07/13 13:11:00 srd * Added C version of vax asm routines. Changed structure to arrays to * save much memory. Do unsigned compares where possible (faster on * Perkin-Elmer) * * Revision 1.4 84/07/05 03:11:11 thomas * Clean up the code a little and lint it. (Lint complains about all * the regs used in the asm, but I'm not going to "fix" this.) * * Revision 1.3 84/07/05 02:06:54 thomas * Minor fixes. * * Revision 1.2 84/07/05 00:27:27 thomas * Add variable bit length output. * */ static char rcs_ident[] = "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $"; #include #include #include #include #include #define ARGVAL() (*++(*argv) || (--argc && *++argv)) int n_bits; /* number of bits/code */ int maxbits = BITS; /* user settable max # bits/code */ code_int maxcode; /* maximum code, given n_bits */ code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */ #ifdef COMPATIBLE /* But wrong! */ # define MAXCODE(n_bits) (1 << (n_bits) - 1) #else # define MAXCODE(n_bits) ((1 << (n_bits)) - 1) #endif /* COMPATIBLE */ #ifdef XENIX_16 count_int htab0[8192]; count_int htab1[8192]; count_int htab2[8192]; count_int htab3[8192]; count_int htab4[8192]; count_int htab5[8192]; count_int htab6[8192]; count_int htab7[8192]; count_int htab8[HSIZE-65536]; count_int * htab[9] = { htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 }; #define htabof(i) (htab[(i) >> 13][(i) & 0x1fff]) unsigned short code0tab[16384]; unsigned short code1tab[16384]; unsigned short code2tab[16384]; unsigned short code3tab[16384]; unsigned short code4tab[16384]; unsigned short * codetab[5] = { code0tab, code1tab, code2tab, code3tab, code4tab }; #define codetabof(i) (codetab[(i) >> 14][(i) & 0x3fff]) #else /* Normal machine */ count_int htab [HSIZE]; unsigned short codetab [HSIZE]; #define htabof(i) htab[i] #define codetabof(i) codetab[i] #endif /* XENIX_16 */ code_int hsize = HSIZE; /* for dynamic table sizing */ count_int fsize; /* * To save much memory, we overlay the table used by compress() with those * used by decompress(). The tab_prefix table is the same size and type * as the codetab. The tab_suffix table needs 2**BITS characters. We * get this from the beginning of htab. The output stack uses the rest * of htab, and contains characters. There is plenty of room for any * possible stack (stack used to be 8000 characters). */ #define tab_prefixof(i) codetabof(i) #ifdef XENIX_16 # define tab_suffixof(i) ((char_type *)htab[(i)>>15])[(i) & 0x7fff] # define de_stack ((char_type *)(htab2)) #else /* Normal machine */ # define tab_suffixof(i) ((char_type *)(htab))[i] # define de_stack ((char_type *)&tab_suffixof(1< debug * -V => print Version; debug verbose * -d => do_decomp * -v => unquiet * -f => force overwrite of output file * -n => no header: useful to uncompress old files * -b maxbits => maxbits. If -b is specified, then maxbits MUST be * given also. * -c => cat all output to stdout * -C => generate output compatible with compress 2.0. * if a string is left, must be an input filename. */ for (argc--, argv++; argc > 0; argc--, argv++) { if (**argv == '-') { /* A flag argument */ while (*++(*argv)) { /* Process all flags in this arg */ switch (**argv) { #ifdef DEBUG case 'D': debug = 1; break; case 'V': verbose = 1; version(); break; #else case 'V': version(); break; #endif /* DEBUG */ case 'v': quiet = 0; break; case 'd': do_decomp = 1; break; case 'f': case 'F': overwrite = 1; force = 1; break; case 'n': nomagic = 1; break; case 'C': block_compress = 0; break; case 'b': if (!ARGVAL()) { fprintf(stderr, "Missing maxbits\n"); Usage(); exit(1); } maxbits = atoi(*argv); goto nextarg; case 'c': zcat_flg = 1; break; case 'q': quiet = 1; break; default: fprintf(stderr, "Unknown flag: '%c'; ", **argv); Usage(); exit(1); } } } else { /* Input file name */ *fileptr++ = *argv; /* Build input file list */ *fileptr = NULL; /* process nextarg; */ } nextarg: continue; } if(maxbits < INIT_BITS) maxbits = INIT_BITS; if (maxbits > BITS) maxbits = BITS; maxmaxcode = 1 << maxbits; if (*filelist != NULL) { for (fileptr = filelist; *fileptr; fileptr++) { exit_stat = 0; if (do_decomp != 0) { /* DECOMPRESSION */ /* Check for .Z suffix */ if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) { /* No .Z: tack one on */ strcpy(tempname, *fileptr); strcat(tempname, ".Z"); *fileptr = tempname; } /* Open input file */ if ((freopen(*fileptr, "r", stdin)) == NULL) { perror(*fileptr); continue; } /* Check the magic number */ if (nomagic == 0) { if ((getchar() != (magic_header[0] & 0xFF)) || (getchar() != (magic_header[1] & 0xFF))) { fprintf(stderr, "%s: not in compressed format\n", *fileptr); continue; } maxbits = getchar(); /* set -b from file */ block_compress = maxbits & BLOCK_MASK; maxbits &= BIT_MASK; maxmaxcode = 1 << maxbits; if(maxbits > BITS) { fprintf(stderr, "%s: compressed with %d bits, can only handle %d bits\n", *fileptr, maxbits, BITS); continue; } } /* Generate output filename */ strcpy(ofname, *fileptr); ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .Z */ } else { /* COMPRESSION */ if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) { fprintf(stderr, "%s: already has .Z suffix -- no change\n", *fileptr); continue; } /* Open input file */ if ((freopen(*fileptr, "r", stdin)) == NULL) { perror(*fileptr); continue; } stat ( *fileptr, &statbuf ); fsize = (long) statbuf.st_size; /* * tune hash table size for small files -- ad hoc, * but the sizes match earlier #defines, which * serve as upper bounds on the number of output codes. */ hsize = HSIZE; if ( fsize < (1 << 12) ) hsize = min ( 5003, HSIZE ); else if ( fsize < (1 << 13) ) hsize = min ( 9001, HSIZE ); else if ( fsize < (1 << 14) ) hsize = min ( 18013, HSIZE ); else if ( fsize < (1 << 15) ) hsize = min ( 35023, HSIZE ); else if ( fsize < 47000 ) hsize = min ( 50021, HSIZE ); /* Generate output filename */ strcpy(ofname, *fileptr); #ifndef BSD4_2 /* Short filenames */ if ((cp=rindex(ofname,'/')) != NULL) cp++; else cp = ofname; if (strlen(cp) > 12) { fprintf(stderr,"%s: filename too long to tack on .Z\n",cp); continue; } #endif /* BSD4_2 Long filenames allowed */ strcat(ofname, ".Z"); } /* Check for overwrite of existing file */ if (overwrite == 0 && zcat_flg == 0) { if (stat(ofname, &statbuf) == 0) { char response[2]; response[0] = 'n'; fprintf(stderr, "%s already exists;", ofname); if (foreground()) { fprintf(stderr, " do you wish to overwrite %s (y or n)? ", ofname); fflush(stderr); read(2, response, 2); while (response[1] != '\n') { if (read(2, response+1, 1) < 0) { /* Ack! */ perror("stderr"); break; } } } if (response[0] != 'y') { fprintf(stderr, "\tnot overwritten\n"); continue; } } } if(zcat_flg == 0) { /* Open output file */ if (freopen(ofname, "w", stdout) == NULL) { perror(ofname); continue; } if(!quiet) fprintf(stderr, "%s: ", *fileptr); } /* Actually do the compression/decompression */ if (do_decomp == 0) compress(); #ifndef DEBUG else decompress(); #else else if (debug == 0) decompress(); else printcodes(); if (verbose) dump_tab(); #endif /* DEBUG */ if(zcat_flg == 0) { copystat(*fileptr, ofname); /* Copy stats */ if((exit_stat == 1) || (!quiet)) putc('\n', stderr); } } } else { /* Standard input */ if (do_decomp == 0) { compress(); #ifdef DEBUG if(verbose) dump_tab(); #endif /* DEBUG */ if(!quiet) putc('\n', stderr); } else { /* Check the magic number */ if (nomagic == 0) { if ((getchar()!=(magic_header[0] & 0xFF)) || (getchar()!=(magic_header[1] & 0xFF))) { fprintf(stderr, "stdin: not in compressed format\n"); exit(1); } maxbits = getchar(); /* set -b from file */ block_compress = maxbits & BLOCK_MASK; maxbits &= BIT_MASK; maxmaxcode = 1 << maxbits; fsize = 100000; /* assume stdin large for USERMEM */ if(maxbits > BITS) { fprintf(stderr, "stdin: compressed with %d bits, can only handle %d bits\n", maxbits, BITS); exit(1); } } #ifndef DEBUG decompress(); #else if (debug == 0) decompress(); else printcodes(); if (verbose) dump_tab(); #endif /* DEBUG */ } } exit(exit_stat); } static int offset; long int in_count = 1; /* length of input */ long int bytes_out; /* length of compressed output */ long int out_count = 0; /* # of codes output (for debugging) */ /* * compress stdin to stdout * * Algorithm: use open addressing double hashing (no chaining) on the * prefix code / next character combination. We do a variant of Knuth's * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime * secondary probe. Here, the modular division first probe is gives way * to a faster exclusive-or manipulation. Also do block compression with * an adaptive reset, whereby the code table is cleared when the compression * ratio decreases, but after the table fills. The variable-length output * codes are re-sized at this point, and a special CLEAR code is generated * for the decompressor. Late addition: construct the table according to * file size for noticeable speed improvement on small files. Please direct * questions about this implementation to ames!jaw. */ compress() { register long fcode; register code_int i = 0; register int c; register code_int ent; #ifdef XENIX_16 register code_int disp; #else /* Normal machine */ register int disp; #endif register code_int hsize_reg; register int hshift; #ifndef COMPATIBLE if (nomagic == 0) { putchar(magic_header[0]); putchar(magic_header[1]); putchar((char)(maxbits | block_compress)); if(ferror(stdout)) writeerr(); } #endif /* COMPATIBLE */ offset = 0; bytes_out = 3; /* includes 3-byte header mojo */ out_count = 0; clear_flg = 0; ratio = 0; in_count = 1; checkpoint = CHECK_GAP; maxcode = MAXCODE(n_bits = INIT_BITS); free_ent = ((block_compress) ? FIRST : 256 ); ent = getchar (); hshift = 0; for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L ) hshift++; hshift = 8 - hshift; /* set hash code range bound */ hsize_reg = hsize; cl_hash( (count_int) hsize_reg); /* clear hash table */ #ifdef SIGNED_COMPARE_SLOW while ( (c = getchar()) != (unsigned) EOF ) { #else while ( (c = getchar()) != EOF ) { #endif in_count++; fcode = (long) (((long) c << maxbits) + ent); i = ((c << hshift) ^ ent); /* xor hashing */ if ( htabof (i) == fcode ) { ent = codetabof (i); continue; } else if ( (long)htabof (i) < 0 ) /* empty slot */ goto nomatch; disp = hsize_reg - i; /* secondary hash (after G. Knott) */ if ( i == 0 ) disp = 1; probe: if ( (i -= disp) < 0 ) i += hsize_reg; if ( htabof (i) == fcode ) { ent = codetabof (i); continue; } if ( (long)htabof (i) > 0 ) goto probe; nomatch: output ( (code_int) ent ); out_count++; ent = c; #ifdef SIGNED_COMPARE_SLOW if ( (unsigned) free_ent < (unsigned) maxmaxcode) { #else if ( free_ent < maxmaxcode ) { #endif codetabof (i) = free_ent++; /* code -> hashtable */ htabof (i) = fcode; } else if ( (count_int)in_count >= checkpoint && block_compress ) cl_block (); } /* * Put out the final code. */ output( (code_int)ent ); out_count++; output( (code_int)-1 ); /* * Print out stats on stderr */ if(zcat_flg == 0 && !quiet) { #ifdef DEBUG fprintf( stderr, "%ld chars in, %ld codes (%ld bytes) out, compression factor: ", in_count, out_count, bytes_out ); prratio( stderr, in_count, bytes_out ); fprintf( stderr, "\n"); fprintf( stderr, "\tCompression as in compact: " ); prratio( stderr, in_count-bytes_out, in_count ); fprintf( stderr, "\n"); fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n", free_ent - 1, n_bits ); #else /* !DEBUG */ fprintf( stderr, "Compression: " ); prratio( stderr, in_count-bytes_out, in_count ); #endif /* DEBUG */ } if(bytes_out > in_count) /* exit(2) if no savings */ exit_stat = 2; return; } /***************************************************************** * TAG( output ) * * Output the given code. * Inputs: * code: A n_bits-bit integer. If == -1, then EOF. This assumes * that n_bits =< (long)wordsize - 1. * Outputs: * Outputs code to the file. * Assumptions: * Chars are 8 bits long. * Algorithm: * Maintain a BITS character long buffer (so that 8 codes will * fit in it exactly). Use the VAX insv instruction to insert each * code in turn. When the buffer fills up empty it and start over. */ static char buf[BITS]; #ifndef vax char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; #endif /* vax */ output( code ) code_int code; { #ifdef DEBUG static int col = 0; #endif /* DEBUG */ /* * On the VAX, it is important to have the register declarations * in exactly the order given, or the asm will break. */ register int r_off = offset, bits= n_bits; register char * bp = buf; #ifdef DEBUG if ( verbose ) fprintf( stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' ); #endif /* DEBUG */ if ( code >= 0 ) { #ifdef vax /* VAX DEPENDENT!! Implementation on other machines is below. * * Translation: Insert BITS bits from the argument starting at * offset bits from the beginning of buf. */ 0; /* Work around for pcc -O bug with asm and if stmt */ asm( "insv 4(ap),r11,r10,(r9)" ); #else /* not a vax */ /* * byte/bit numbering on the VAX is simulated by the following code */ /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* * Since code is always >= 8 bits, only need to mask the first * hunk on the left. */ *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off]; bp++; bits -= (8 - r_off); code >>= 8 - r_off; /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if ( bits >= 8 ) { *bp++ = code; code >>= 8; bits -= 8; } /* Last bits. */ if(bits) *bp = code; #endif /* vax */ offset += n_bits; if ( offset == (n_bits << 3) ) { bp = buf; bits = n_bits; bytes_out += bits; do putchar(*bp++); while(--bits); offset = 0; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if ( free_ent > maxcode || (clear_flg > 0)) { /* * Write the whole buffer, because the input side won't * discover the size increase until after it has read it. */ if ( offset > 0 ) { if( fwrite( buf, 1, n_bits, stdout ) != n_bits) writeerr(); bytes_out += n_bits; } offset = 0; if ( clear_flg ) { maxcode = MAXCODE (n_bits = INIT_BITS); clear_flg = 0; } else { n_bits++; if ( n_bits == maxbits ) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } #ifdef DEBUG if ( debug ) { fprintf( stderr, "\nChange to %d bits\n", n_bits ); col = 0; } #endif /* DEBUG */ } } else { /* * At EOF, write the rest of the buffer. */ if ( offset > 0 ) fwrite( buf, 1, (offset + 7) / 8, stdout ); bytes_out += (offset + 7) / 8; offset = 0; fflush( stdout ); #ifdef DEBUG if ( verbose ) fprintf( stderr, "\n" ); #endif /* DEBUG */ if( ferror( stdout ) ) writeerr(); } } /* * Decompress stdin to stdout. This routine adapts to the codes in the * file building the "string" table on-the-fly; requiring no table to * be stored in the compressed file. The tables used herein are shared * with those of the compress() routine. See the definitions above. */ decompress() { register char_type *stackp; register int finchar; register code_int code, oldcode, incode; /* * As above, initialize the first 256 entries in the table. */ maxcode = MAXCODE(n_bits = INIT_BITS); for ( code = 255; code >= 0; code-- ) { tab_prefixof(code) = 0; tab_suffixof(code) = (char_type)code; } free_ent = ((block_compress) ? FIRST : 256 ); finchar = oldcode = getcode(); if(oldcode == -1) /* EOF already? */ return; /* Get out of here */ putchar( (char)finchar ); /* first code must be 8 bits = char */ if(ferror(stdout)) /* Crash if can't write */ writeerr(); stackp = de_stack; while ( (code = getcode()) > -1 ) { if ( (code == CLEAR) && block_compress ) { for ( code = 255; code >= 0; code-- ) tab_prefixof(code) = 0; clear_flg = 1; free_ent = FIRST - 1; if ( (code = getcode ()) == -1 ) /* O, untimely death! */ break; } incode = code; /* * Special case for KwKwK string. */ if ( code >= free_ent ) { *stackp++ = finchar; code = oldcode; } /* * Generate output characters in reverse order */ #ifdef SIGNED_COMPARE_SLOW while ( ((unsigned long)code) >= ((unsigned long)256) ) { #else while ( code >= 256 ) { #endif *stackp++ = tab_suffixof(code); code = tab_prefixof(code); } *stackp++ = finchar = tab_suffixof(code); /* * And put them out in forward order */ do putchar ( *--stackp ); while ( stackp > de_stack ); /* * Generate the new entry. */ if ( (code=free_ent) < maxmaxcode ) { tab_prefixof(code) = (unsigned short)oldcode; tab_suffixof(code) = finchar; free_ent = code+1; } /* * Remember previous code. */ oldcode = incode; } fflush( stdout ); if(ferror(stdout)) writeerr(); } /***************************************************************** * TAG( getcode ) * * Read one code from the standard input. If EOF, return -1. * Inputs: * stdin * Outputs: * code or -1 is returned. */ code_int getcode() { /* * On the VAX, it is important to have the register declarations * in exactly the order given, or the asm will break. */ register code_int code; static int offset = 0, size = 0; static char_type buf[BITS]; register int r_off, bits; register char_type *bp = buf; if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) { /* * If the next entry will be too big for the current code * size, then we must increase the size. This implies reading * a new buffer full, too. */ if ( free_ent > maxcode ) { n_bits++; if ( n_bits == maxbits ) maxcode = maxmaxcode; /* won't get any bigger now */ else maxcode = MAXCODE(n_bits); } if ( clear_flg > 0) { maxcode = MAXCODE (n_bits = INIT_BITS); clear_flg = 0; } size = fread( buf, 1, n_bits, stdin ); if ( size <= 0 ) return -1; /* end of file */ offset = 0; /* Round size down to integral number of codes */ size = (size << 3) - (n_bits - 1); } r_off = offset; bits = n_bits; #ifdef vax asm( "extzv r10,r9,(r8),r11" ); #else /* not a vax */ /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* Get first part (low order bits) */ #ifdef NO_UCHAR code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff; #else code = (*bp++ >> r_off); #endif /* NO_UCHAR */ bits -= (8 - r_off); r_off = 8 - r_off; /* now, offset into code word */ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if ( bits >= 8 ) { #ifdef NO_UCHAR code |= (*bp++ & 0xff) << r_off; #else code |= *bp++ << r_off; #endif /* NO_UCHAR */ r_off += 8; bits -= 8; } /* high order bits. */ code |= (*bp & rmask[bits]) << r_off; #endif /* vax */ offset += n_bits; return code; } char * rindex(s, c) /* For those who don't have it in libc.a */ register char *s, c; { char *p; for (p = NULL; *s; s++) if (*s == c) p = s; return(p); } #ifdef DEBUG printcodes() { /* * Just print out codes from input file. For debugging. */ code_int code; int col = 0, bits; bits = n_bits = INIT_BITS; maxcode = MAXCODE(n_bits); free_ent = ((block_compress) ? FIRST : 256 ); while ( ( code = getcode() ) >= 0 ) { if ( (code == CLEAR) && block_compress ) { free_ent = FIRST - 1; clear_flg = 1; } else if ( free_ent < maxmaxcode ) free_ent++; if ( bits != n_bits ) { fprintf(stderr, "\nChange to %d bits\n", n_bits ); bits = n_bits; col = 0; } fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' ); } putc( '\n', stderr ); exit( 0 ); } code_int sorttab[1<= 0) { sorttab[codetabof(i)] = i; } } first = block_compress ? FIRST : 256; for(i = first; i < free_ent; i++) { fprintf(stderr, "%5d: \"", i); de_stack[--stack_top] = '\n'; de_stack[--stack_top] = '"'; stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff, stack_top); for(ent=htabof(sorttab[i]) & ((1< 256; ent=htabof(sorttab[ent]) & ((1<> maxbits, stack_top); } stack_top = in_stack(ent, stack_top); fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr); stack_top = STACK_SIZE; } } else if(!debug) { /* decompressing */ for ( i = 0; i < free_ent; i++ ) { ent = i; c = tab_suffixof(ent); if ( isascii(c) && isprint(c) ) fprintf( stderr, "%5d: %5d/'%c' \"", ent, tab_prefixof(ent), c ); else fprintf( stderr, "%5d: %5d/\\%03o \"", ent, tab_prefixof(ent), c ); de_stack[--stack_top] = '\n'; de_stack[--stack_top] = '"'; for ( ; ent != NULL; ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) { stack_top = in_stack(tab_suffixof(ent), stack_top); } fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr ); stack_top = STACK_SIZE; } } } int in_stack(c, stack_top) register c, stack_top; { if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) { de_stack[--stack_top] = c; } else { switch( c ) { case '\n': de_stack[--stack_top] = 'n'; break; case '\t': de_stack[--stack_top] = 't'; break; case '\b': de_stack[--stack_top] = 'b'; break; case '\f': de_stack[--stack_top] = 'f'; break; case '\r': de_stack[--stack_top] = 'r'; break; case '\\': de_stack[--stack_top] = '\\'; break; default: de_stack[--stack_top] = '0' + c % 8; de_stack[--stack_top] = '0' + (c / 8) % 8; de_stack[--stack_top] = '0' + c / 64; break; } de_stack[--stack_top] = '\\'; } return stack_top; } #endif /* DEBUG */ writeerr() { perror ( ofname ); unlink ( ofname ); exit ( 1 ); } copystat(ifname, ofname) char *ifname, *ofname; { struct stat statbuf; int mode; time_t timep[2]; fclose(stdout); if (stat(ifname, &statbuf)) { /* Get stat on input file */ perror(ifname); return; } if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) { if(quiet) fprintf(stderr, "%s: ", ifname); fprintf(stderr, " -- not a regular file: unchanged"); exit_stat = 1; } else if (statbuf.st_nlink > 1) { if(quiet) fprintf(stderr, "%s: ", ifname); fprintf(stderr, " -- has %d other links: unchanged", statbuf.st_nlink - 1); exit_stat = 1; } else if (exit_stat == 2 && (!force)) { /* No compression: rm file.Z */ if(!quiet) fprintf(stderr, " -- file unchanged"); } else { /* ***** Successful Compression ***** */ exit_stat = 0; mode = statbuf.st_mode & 07777; if (chmod(ofname, mode)) /* Copy modes */ perror(ofname); chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */ timep[0] = statbuf.st_atime; timep[1] = statbuf.st_mtime; utime(ofname, timep); /* Update last accessed and modified times */ if (unlink(ifname)) /* Remove input file */ perror(ifname); if(!quiet) fprintf(stderr, " -- replaced with %s", ofname); return; /* Successful return */ } /* Unsuccessful return -- one of the tests failed */ if (unlink(ofname)) perror(ofname); } /* * This routine returns 1 if we are running in the foreground and stderr * is a tty. */ foreground() { if(bgnd_flag) { /* background? */ return(0); } else { /* foreground */ if(isatty(2)) { /* and stderr is a tty */ return(1); } else { return(0); } } } onintr ( ) { unlink ( ofname ); exit ( 1 ); } oops ( ) /* wild pointer -- assume bad input */ { if ( do_decomp == 1 ) fprintf ( stderr, "uncompress: corrupt input\n" ); unlink ( ofname ); exit ( 1 ); } cl_block () /* table clear for block compress */ { register long int rat; checkpoint = in_count + CHECK_GAP; #ifdef DEBUG if ( debug ) { fprintf ( stderr, "count: %ld, ratio: ", in_count ); prratio ( stderr, in_count, bytes_out ); fprintf ( stderr, "\n"); } #endif /* DEBUG */ if(in_count > 0x007fffff) { /* shift will overflow */ rat = bytes_out >> 8; if(rat == 0) { /* Don't divide by zero */ rat = 0x7fffffff; } else { rat = in_count / rat; } } else { rat = (in_count << 8) / bytes_out; /* 8 fractional bits */ } if ( rat > ratio ) { ratio = rat; } else { ratio = 0; #ifdef DEBUG if(verbose) dump_tab(); /* dump string table */ #endif cl_hash ( (count_int) hsize ); free_ent = FIRST; clear_flg = 1; output ( (code_int) CLEAR ); #ifdef DEBUG if(debug) fprintf ( stderr, "clear\n" ); #endif /* DEBUG */ } } cl_hash(hsize) /* reset code table */ register count_int hsize; { #ifndef XENIX_16 /* Normal machine */ register count_int *htab_p = htab+hsize; #else register j; register long k = hsize; register count_int *htab_p; #endif register long i; register long m1 = -1; #ifdef XENIX_16 for(j=0; j<=8 && k>=0; j++,k-=8192) { i = 8192; if(k < 8192) { i = k; } htab_p = &(htab[j][i]); i -= 16; if(i > 0) { #else i = hsize - 16; #endif do { /* might use Sys V memset(3) here */ *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-14) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); #ifdef XENIX_16 } } #endif for ( i += 16; i > 0; i-- ) *--htab_p = m1; } prratio(stream, num, den) FILE *stream; long int num, den; { register int q; /* Doesn't need to be long */ if(num > 214748L) { /* 2147483647/10000 */ q = num / (den / 10000L); } else { q = 10000L * num / den; /* Long calculations, though */ } if (q < 0) { putc('-', stream); q = -q; } fprintf(stream, "%d.%02d%%", q / 100, q % 100); } version() { fprintf(stderr, "%s\n", rcs_ident); fprintf(stderr, "Options: "); #ifdef vax fprintf(stderr, "vax, "); #endif #ifdef NO_UCHAR fprintf(stderr, "NO_UCHAR, "); #endif #ifdef SIGNED_COMPARE_SLOW fprintf(stderr, "SIGNED_COMPARE_SLOW, "); #endif #ifdef XENIX_16 fprintf(stderr, "XENIX_16, "); #endif #ifdef COMPATIBLE fprintf(stderr, "COMPATIBLE, "); #endif #ifdef DEBUG fprintf(stderr, "DEBUG, "); #endif #ifdef BSD4_2 fprintf(stderr, "BSD4_2, "); #endif fprintf(stderr, "BITS = %d\n", BITS); } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; form.l -- screen forms handler ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (declare (specials t) (macros t)) (eval-when (compile) (load 'utilities) (load 'constants) (load 'zone) (load 'look) (load 'font) (load 'text) (load 'text-edit)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; generic fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstruct (field ; generic field (:displace t) (:list) (:conc-name)) (type 'generic-field) ; type = generic (zone (make-zone)) ; bounding zone (properties (list nil)) ; empty property list ) (defvar field-properties ; list of expected field properties '("field-properties" fill-ground (solid pattern) ; should we draw when highlit? fill-colour (x_colour x_pattern) ; what colour or pattern? empty-ground (solid pattern) ; should we draw when unlit? empty-colour (x_colour x_pattern) ; what colour or pattern? border-colour (x_colour) ; should we draw border (and what colour?) )) ; can use this as real plist for online documentation (defun draw-field (f) ; draw field from scratch (apply (concat 'draw- (field-type f)) ; construct draw function name (ncons f))) ; then call it (defun init-field (f) ; initialize a field (apply (concat 'init- (field-type f)) ; construct init function name (ncons f))) ; then call it (defun resize-field (f box) ; resize a field (apply ; construct resize function name (concat 'resize- (field-type f)) (list f box))) ; then call it (defun toggle-field (f) ; toggle a field (apply (concat 'toggle- (field-type f)) ; construct toggle fcn name (ncons f))) ; then call it (defun check-field (f p) ; check if point is inside field excl.border (cond ((point-in-box-interior p (zone-box (field-zone f))) (apply ; if so, construct check function name (concat 'check- (field-type f)) (list f p))) ; then call it and return result (t nil))) ; otherwise return nil (defun fill-field (f) ; fill the field interior, if defined (let ((b (get (field-properties f) 'fill-ground)) ; check if has one (c (get (field-properties f) 'fill-colour))) (cond ((eq b 'solid) ; solid background (cond (c (clear-zone-interior (field-zone f) c)) (t (clear-zone-interior (field-zone f) W-CONTRAST)))) ((eq b 'pattern) ; patterned background (cond (c (pattern-zone-interior (field-zone f) c)) (t (pattern-zone-interior (field-zone f) W-PATTERN-1)))) ))) ; no background at all! (defun empty-field (f) ; empty the field interior, if defined (let ((b (get (field-properties f) 'empty-ground)) ; check if has one (c (get (field-properties f) 'empty-colour))) (cond ((eq b 'solid) ; solid background (cond (c (clear-zone-interior (field-zone f) c)) (t (clear-zone-interior (field-zone f) W-BACKGROUND)))) ((eq b 'pattern) ; patterned background (cond (c (pattern-zone-interior (field-zone f) c)) (t (pattern-zone-interior (field-zone f) W-PATTERN-1)))) ))) ; no background at all! (defun draw-field-background (f) ; just what it says (let ((b (get (field-properties f) 'empty-ground)) ; check if has one (c (get (field-properties f) 'empty-colour))) (cond ((eq b 'solid) ; solid background (cond (c (clear-zone (field-zone f) c)) (t (clear-zone (field-zone f) W-BACKGROUND)))) ((eq b 'pattern) ; patterned background (cond (c (pattern-zone (field-zone f) c)) (t (pattern-zone (field-zone f) W-PATTERN-1)))) ))) ; no background at all! (defun draw-field-border (f) ; draw outline, if any (let ((c (get (field-properties f) 'border-colour))) (cond (c (draw-zone-outline (field-zone f) c))) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; aggregate fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstruct (aggregate-field ; aggregate field = form (:displace t) (:list) (:conc-name)) (type 'aggregate-field) ; type (zone (make-zone)) ; bounding zone (properties (list nil)) ; empty property list subfields ; list of subfields selection ; which subfield was last hit ) (defvar aggregate-field-properties `("aggregate-field-properties" = ,field-properties )) ; can use this as real plist for online documentation (defun draw-aggregate-field (f) (draw-field-background f) ; clear background, if any (draw-field-border f) ; draw border, if any (mapc 'draw-field (aggregate-field-subfields f)) ; draw subfields (w-flush (window-w (zone-window (field-zone f)))) t) ; flush it out (defun init-aggregate-field (f) (mapc 'init-field (aggregate-field-subfields f)) (alter-aggregate-field f selection nil) t) (defun resize-aggregate-field (f box) (alter-zone (field-zone f) box box)) (defun check-aggregate-field (f p) (do ((subfields (aggregate-field-subfields f) ; go through subfields (cdr subfields)) (gotcha)) ((or (null subfields) ; stop when no more (setq gotcha (check-field (car subfields) p))) ; or when one is hit (alter-aggregate-field f selection gotcha) ; remember which one gotcha))) ; also return it ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; remote fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; A remote field is a field which activates another field when hit. ;;; Usually the remote field has some functional significance! (defstruct (remote-field ; remote field (:displace t) (:list) (:conc-name)) (type 'remote-field) ; type = remote (zone (make-zone)) ; bounding zone (properties (list nil)) ; empty plist (target) ; the actual target field (point) ; x,y coords to pretend to use ) (defvar remote-field-properties `("remote-field-properties" = ,field-properties )) ; can use this as real plist for online documentation (defun draw-remote-field (f) 't) ; nothing to draw (defun init-remote-field (f) 't) ; nothing to initialize (defun resize-remote-field (f box) (alter-zone (field-zone f) box box)) (defun check-remote-field (f p) (check-field (remote-field-target f) (remote-field-point f))) ; return result of checking target ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; button fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstruct (button-field ; button field (:displace t) (:list) (:conc-name)) (type 'button-field) ; type = button (zone (make-zone)) ; bounding zone (properties (list nil ; default properties 'fill-ground 'solid 'empty-ground 'solid 'border-colour W-CONTRAST )) (value nil) ; value ) (defvar button-field-properties `("button-field-properties" = ,field-properties )) ; can use this as real plist for online documentation (defun draw-button-field (f) (draw-field-border f) (cond ((button-field-value f) (fill-field f)) (t (empty-field f)))) (defun toggle-button-field (f) (alter-button-field f value (not (button-field-value f))) (clear-zone-interior (field-zone f) W-XOR)) (defun init-button-field (f) (alter-button-field f value nil)) ; turn it off (defun resize-button-field (f box) (alter-zone (field-zone f) box box)) (defun check-button-field (f p) (toggle-button-field f) f) ; if we get here it's a hit -> return self ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; radio-button fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Named for the buttons on radios in which only one is "in" at a time. (defstruct (radio-button-field ; radio-button field (:displace t) (:list) (:conc-name)) (type 'radio-button-field) ; type = radio-button (zone (make-zone)) ; bounding zone (properties (list nil)) ; empty plist (subfields nil) ; individual buttons (selection nil) ; which one last hit ) (defvar radio-button-field-properties `("radio-button-field-properties" = ,aggregate-field-properties )) ; can use this as real plist for online documentation (defun draw-radio-button-field (f) (draw-aggregate-field f)) (defun init-radio-button-field (f) (init-aggregate-field f)) (defun resize-radio-button-field (f box) (alter-zone (field-zone f) box box)) (defun check-radio-button-field (f p) (cond ((and (radio-button-field-selection f) ; if button previously sel'd (button-field-value (radio-button-field-selection f))) ; and it has a value (toggle-field ; turn it off (radio-button-field-selection f)))) (check-aggregate-field f p) ; check individual buttons ) ; this will turn back on if same one sel'd, and return it ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; text fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstruct (text-field ; text field (:displace t) (:list) (:conc-name)) (type 'text-field) ; type = text (zone (make-zone)) ; bounding zone (properties (list nil 'fill-ground 'solid 'empty-ground 'solid 'border-colour W-CONTRAST 'x-offset 5 ; offset from left )) (value nil) (text '||) ; text of text ) (defvar text-field-properties `("text-field-properties" x-offset (x_pixels) ; text offset from box ll, otherwise centred y-offset (x_pixels) ; text offset from box ll, otherwise centred + ,button-field-properties )) ; can use this as real plist for online documentation (defun draw-text-field (f) (draw-button-field f) (w-flush (window-w (zone-window (field-zone f)))) ; guarantee text on top (draw-text (text-field-text f))) (defun redraw-text-field (f) (empty-field f) (w-flush (window-w (zone-window (field-zone f)))) ; guarantee text on top (draw-text (text-field-text f))) (defun init-text-field (f) ; position & position the text in the field (let ((s (text-field-text f)) (x-offset (get (field-properties f) 'x-offset)) ; x offset from ll (y-offset (get (field-properties f) 'y-offset))); y offset from ll (alter-text s zone (make-zone ; ensure it has a zone window (zone-window (field-zone f)) box (box-interior (zone-box (field-zone f))))) (format-text s) ; ensure text delta calculated (cond ((null x-offset) ; x-offset specified? (setq x-offset ; nope! centre it left-right (/ (- (x (box-size (zone-box (field-zone f)))) (x (text-delta s))) 2)))) (cond ((null y-offset) ; y-offset specified? (setq y-offset ; nope! centre it up-down (/ (- (y (box-size (zone-box (field-zone f)))) (font-x-height (look-font (text-look s)))) 2)))) (alter-text s ; now position the text offset (make-point x x-offset y y-offset)) )) (defun resize-text-field (f box) ; position the text in the field (alter-zone (field-zone f) box box) (init-text-field f)) (defun check-text-field (f p) (input-text-field f) f) ; if we get here it's a hit -> return self (defun input-text-field (f) (alter-text (text-field-text f) text '|| nn 0 kr 0 kl 0 delta (make-point x 0 y 0)) (draw-text-field f) (edit-text-field f (ll (zone-box (text-zone (text-field-text f)))))) (defun edit-text-field (f p) ; edit in middle of text field (edit-text (text-field-text f) p) ; edit the text (draw-field f)) ; redraw ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; prompt fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstruct (prompt-field ; prompt field (:displace t) (:list) (:conc-name)) (type 'prompt-field) ; type = prompt (zone (make-zone)) ; bounding zone (properties (list nil 'x-offset 0)) ; put it exactly where spec indicates. (value nil) (text '||) ; text of prompt ) (defvar prompt-field-properties `("prompt-field-properties" = ,text-field-properties )) ; can use this as real plist for online documentation (defun draw-prompt-field (f) (draw-text-field f)) (defun init-prompt-field (f) (init-text-field f)) (defun resize-prompt-field (f box) ; position the text in the field (resize-text-field f box)) (defun check-prompt-field (f p) f) ; just return self ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; text-button fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; A text-button is a button tied to a text. ;;; When the button is pressed, the text is input from the keyboard. ;;; Zone could same as either the button (activation by button only) ;;; or include both button & text (should then be adjacent) (defstruct (text-button-field ; text-button field (:displace t) (:list) (:conc-name)) (type 'text-button-field) ; type = text-button (zone (make-zone)) ; bounding zone (properties (list nil)) ; empty plist (button) ; button subfield (text) ; text subfield ) (defvar text-button-field-properties `("text-button-field-properties" = ,field-properties )) ; can use this as real plist for online documentation (defun draw-text-button-field (f) (draw-field (text-button-field-button f)) (draw-text-field (text-button-field-text f))) (defun init-text-button-field (f) (init-field (text-button-field-button f)) (init-text-field (text-button-field-text f))) (defun resize-text-button-field (f box) (alter-zone (field-zone f) box box)) (defun toggle-text-button-field (f) ; toggle only the button part (cond ((button-field-value ; and only if non-nil (text-button-field-button f)) (toggle-button-field (text-button-field-button f))))) (defun check-text-button-field (f p) (cond ((check-field (text-button-field-button f) p) (input-text-field ; input from scratch (text-button-field-text f))) ; get the data (t (toggle-button-field ; must be pointing at text (text-button-field-button f)) ; toggle only the button part (edit-text-field (text-button-field-text f) p)) ; edit the data ) (toggle-button-field ; toggle button back (text-button-field-button f)) (alter-button-field (text-button-field-button f) value nil) ; keep aggregate from toggling again f) ; return self ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; labelled button fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstruct (labelled-button-field ; labelled button field (:displace t) (:list) (:conc-name)) (type 'labelled-button-field) ; type = labelled-button (zone (make-zone)) ; bounding zone (properties (list nil 'fill-ground 'solid 'empty-ground 'solid 'border-colour W-CONTRAST )) (value nil) ; value (text '||) ; label text ) (defvar labelled-button-field-properties `("labelled-button-field-properties" = ,text-field-properties )) ; can use this as real plist for online documentation (defun draw-labelled-button-field (f) (draw-text-field f)) (defun init-labelled-button-field (f) (init-text-field f)) (defun resize-labelled-button-field (f box) (resize-text-field f box)) (defun check-labelled-button-field (f p) (toggle-button-field f) f) ; if we get here it's a hit -> return self (defun toggle-labelled-button-field (f) (toggle-button-field f)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; expanded-bitmap fields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstruct (expanded-bitmap-field ; expanded-bitmap field (:displace t) (:list) (:conc-name)) (type 'expanded-bitmap-field) ; type = expanded-bitmap (zone (make-zone)) ; bounding zone (properties (list nil)) ; empty plist (subfields nil) ; individual bits (selection nil) ; which one last hit (nrows 1) (ncols 1) ) (defvar expanded-bitmap-field-properties `("expanded-bitmap-field-properties" = ,aggregate-field-properties )) ; can use this as real plist for online documentation (defun draw-expanded-bitmap-field (f) (draw-aggregate-field f)) (defun init-expanded-bitmap-field (f) (let ((s (divide-points ; calculate x,y dimensions (box-size (zone-box (field-zone f))) (make-point x (expanded-bitmap-field-ncols f) y (expanded-bitmap-field-nrows f))))) (do ((z (field-zone f)) (r nil) (x (x (ll (zone-box (field-zone f))))) (y (y (ll (zone-box (field-zone f)))) (+ y dy)) (dx (x s)) (dy (y s)) (nc (expanded-bitmap-field-nrows f)) (nr (expanded-bitmap-field-nrows f)) (j 0 (1+ j))) ((= j nr) (alter-aggregate-field f subfields (nreverse r)) 't) (do ((x x (+ x dx)) (p) (i 0 (1+ i))) ((= i nc)) ; create a row of buttons (setq p (make-point x x y y)) (setq r (xcons r (make-button-field zone (append z nil)))) (alter-zone (field-zone (car r)) box (make-box ll p ur (add-points p s))) )))) (defun resize-expanded-bitmap-field (f box) (alter-zone (field-zone f) box box) (let ((s (divide-points ; calculate x,y dimensions (box-size box) (make-point x (expanded-bitmap-field-ncols f) y (expanded-bitmap-field-nrows f))))) (do ((z (field-zone f)) (r (expanded-bitmap-field-subfields f)) (x (x (ll box))) (y (y (ll box)) (+ y dy)) (dx (x s)) (dy (y s)) (nc (expanded-bitmap-field-nrows f)) (nr (expanded-bitmap-field-nrows f)) (j 0 (1+ j))) ((= j nr) t) (do ((x x (+ x dx)) (p) (i 0 (1+ i))) ((= i nc)) ; create a row of buttons (setq p (make-point x x y y)) (resize-button-field (car r) (make-box ll p ur (add-points p s))) (setq r (cdr r)) )))) (defun check-expanded-bitmap-field (f p) (check-aggregate-field f p)) ; if we get here it's a hit -> check subfields ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; utilities.l ; ;;; ; ;;; These macros and functions are thought to be generally useful. ; ;;; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Macros ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (declare (macros t) ; keep macros around after compiling (localf pairify* pairifyq* split2* sublist*) (special compiled-with-help)) (defmacro copy-all-but-last (ls) ; copy all but last member of list `(let ((ls ,ls)) (firstn (1- (length ls)) ls))) (defmacro all-but-last (ls) ; destructive all-but-last `(let ((ls ,ls)) (cond ((cdr ls) (rplacd (nthcdr (- (length ls) 2) ls) nil) ls)))) (def hex (macro (arglist) ; hex to integer conversion `(car (hex-to-int ',(cdr arglist))))) ;;; define properties on symbols for use by help routines (defmacro def-usage (fun usage returns group) (cond (compiled-with-help ; flag controls help generation `(progn (putprop ,fun ,usage 'fcn-usage) (putprop ,fun ,returns 'fcn-returns) (putprop ,fun (nconc ,group (ncons ,fun)) 'fcn-group))))) (defvar compiled-with-help t) ; unless otherwise notified ;;; (letenv 'l_bind_plist g_expr1 ... g_exprn) -- pair-list form of "let" ;;; Lambda-binds pairs of "binding-objects" (see description of let,let*), ;;; at RUN TIME, then evaluates g_expr1 to g_exprn, returning g_exprn. eg: ;;; (apply 'letenv '(letenv '(a 1 b (+ c d)) ;;; (e)(f g))) ;-> (eval (cons 'let (cons (pairify '(a 1 b (+ c d))) ;;; '((e) (f g))))) ;-> (let ((a 1) (b (+ c d))) ;;; (e) (f g)) (def letenv (macro (x) `(eval (cons 'let (cons (pairify ,(cadr x)) ; plist of binding objects ',(cddr x)))))) ; exprs to be eval'ed (def letenvq ; letenv, quoted binding objects (macro (x) `(eval (cons 'let (cons (pairifyq ,(cadr x)) ; plist of binding objects ',(cddr x)))))) ; exprs to be eval'ed (defmacro mergecar (L1 L2 cmpfn) ; merge, comparing by car's `(merge ,L1 ,L2 '(lambda (e1 e2) ; (like sortcar) (funcall ,cmpfn (car e1) (car e2))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Functions ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; (all-but-last l_items) -- copy all but last list element ;(defun all-but-last (ls) ; (cond ((cdr ls) (cons (car ls) (all-but-last (cdr ls)))))) ;;; (alphap sx_char) (defun alphap (char) ; is char alphabetic? (cond ((symbolp char) (setq char (car (exploden char))))) (and (fixp char) (or (and (>& char #.(1- #/A)) (<& char #.(1+ #/Z))) (and (>& char #.(1- #/a)) (<& char #.(1+ #/z)))))) ;;; (alphanumericp sx_char) (defun alphanumericp (char) ; is char alphabetic or numeric? (cond ((symbolp char) (setq char (car (exploden char))))) (and (fixp char) (or (and (>& char #.(1- #/A)) (<& char #.(1+ #/Z))) (and (>& char #.(1- #/a)) (<& char #.(1+ #/z))) (and (>& char #.(1- #/0)) (<& char #.(1+ #/9)))))) ;;; (assqonc 'g_key 'g_val 'l_al) ;;; like (cond ((assq key alist)) ;;; (t (cadr (rplacd (last alist) ;;; (ncons (cons key val)))))) (defun assqonc (key val al) ; tack (key.val) on end if not found (do ((al al (cdr al))) ((or (eq key (caar al)) (and (null (cdr al)) (rplacd al (setq al (ncons (cons key val)))))) (car al)))) ;;; (cartesian l_xset l_yset) (defun cartesian (xset yset) ; cartesian product of elements (mapcan '(lambda (x) (mapcar '(lambda (y) (cons x y)) yset)) xset)) (defun concat-pairs (sb-list) ; concat neighbouring symbol pairs (do ((s1 (car sb-list) s2) (s2 (cadr sb-list) (car sbs-left)) (sbs-left (cddr sb-list) (cdr sbs-left)) (result nil (cons (concat s1 s2) result))) ((null s2) (nreverse result)))) ;;; (detach l) ;;; Detaches (and throws away) first element of list (converse of attach) ;;; keeping the same initial list cell. (defun detach (l) (cond (l (rplacd l (cddr (rplaca l (cadr l))))))) ;;; (distribute x_Q x_N) ;;; returns list of the form: (1 1 1 0 0 0 0 1 1) or (3 2 2 2 3) ;;; i.e. a list of length containing quantity evenly distributed ;;; with the excess surrounding a "core" of 's ;;; Useful (?) for padding spaces in line adjustment. ;(defun distribute (Q N) ; this one only does 1's and 0's ; (cond ((signp le Q) (duplicate N 0)) ; ((eq Q 1) (pad 0 N '(1))) ; (t (cons 1 (nconc ; (distribute (- Q 2) (- N 2)) ; '(1)))))) (defun distribute (Q N) ; distribute quantity Q among N elements (let ((tmp (Divide (abs Q) N))) (setq tmp (distribute0 (cadr tmp) N (car tmp) (1+ (car tmp)))) (cond ((signp ge Q) tmp) (t (mapcar 'minus tmp))))) (defun distribute0 (Q N X X1) (cond ((signp le Q) (duplicate N X)) ((eq Q 1) (pad X N (ncons X1))) (t (cons X1 (nconc (distribute0 (- Q 2) (- N 2) X X1) (ncons X1)))))) ;;; (duplicate x_n g_object) ;;; Returns list of n copies of object (nil if n <= 0) (defun duplicate (n object) (do ((res nil (cons object res)) (i n (1- i))) ((signp le i) res))) (defun e0 (in out) ; simulate binary insertion procedure (let ((lin (length in)) (lout (length out))) (cond ((> lin lout) (e0 (nthcdr lout in) (mapcan 'list out (firstn lout in)))) (t (nconc (mapcan 'list (firstn lin out) in) (nthcdr lin out)))))) (defun e (files) ; determine file permutation for emacs insert (let ((i (e0 (cdr (iota (length files))) '(0))) (f (append files nil))) (mapc '(lambda (f-index f-name) (rplaca (nthcdr f-index f) f-name)) i files) f)) ;;; (firstn x_n l_listarg) (defun firstn (n l) ; copy first elements of list (do ((n n (1- n)) (l l (cdr l)) (r nil)) ((not (plusp n)) (nreverse r)) ; if n=0 or -ve (setq r (cons (car l) r)))) ;;; (iota x_n) ;;; APL index generator (0,1,2,...,-1) (defun iota (n) (do ((i (1- n) (1- i)) (res nil)) ((minusp i) res) (setq res (cons i res)))) (defun hex-to-int (numlist) ; eg. (hex-to-int '(12b3 120 8b)) (cond (numlist ; terminate recursion on null numlist (cons (apply '+ (maplist '(lambda (digits) (lsh (get '(hex |0| 0 |1| 1 |2| 2 |3| 3 |4| 4 |5| 5 |6| 6 |7| 7 |8| 8 |9| 9 a 10 b 11 c 12 d 13 e 14 f 15) (car digits)) (lsh (1- (length digits)) 2))) (explodec (car numlist)))) (hex-to-int (cdr numlist)))))) ;;; (lctouc g_expr) ;;; Returns s-expression formed by translating lower-case alphabetic ;;; characters in to their upper-case equivalents. ;;; Operates by imploding the translated characters, in the case of a ;;; symbol or string, or by recursively calling on members of a list. ;;; Other object types are returned unchanged. (defun lctouc (expr) (cond ((dtpr expr) (mapcar 'uctolc expr)) ((or (symbolp expr) (stringp expr)) (implode (mapcar '(lambda (ch) (cond ((alphap ch) ; and-out lower-case bit (boole 1 #.(1- (1- #/a)) ch)) (t ch))) (exploden expr)))) (t expr))) ;;; (log2 x_n) (defun log2 (n) ; log base 2 (truncated) (do ((n (lsh n -1) (lsh n -1)) (p 0 (1+ p))) ((zerop n) p))) ;;; (lowerp sx_char) (defun lowerp (char) ; is char lower-case alphabetic? (cond ((symbolp char) (setq char (car (exploden char))))) (and (fixp char) (or (and (> char #.(1- #/a)) (< char #.(1+ #/z)))))) ;;; (numericp sx_char) ;;; returns t if char is numeric, otherwise nil (defun numericp (char) (cond ((symbolp char)(setq char (car (exploden char))))) (and (fixp char) (and (> char #.(1- #/0)) (< char #.(1+ #/9))))) ;;; (pad g_item x_n l_list) ;;; Returns padded with copies of to length (defun pad (item n list) (append list (duplicate (- n (length list)) item))) ;;; (pairify l_items) ; make a-list from alternating elements (defun pairify (pl) (pairify* nil pl)) (defun pairify* (rs pl) ; tail-recursive local fun (cond (pl (pairify* (cons (list (car pl) (cadr pl)) rs) (cddr pl))) (t (nreverse rs)))) ;;; (pairifyq l_items) ; make a-list from alternating elements (defun pairifyq (pl) ; with each second element quoted (pairifyq* nil pl)) (defun pairifyq* (rs pl) ; tail-recursive local fun (cond (pl (pairifyq* (cons (list (car pl) (kwote (cadr pl))) rs) (cddr pl))) (t (nreverse rs)))) ;;; (penultimate l_items) ; cdr down to next-to-last list element (defun penultimate (ls) (cond ((cddr ls) (penultimate (cdr ls))) (t ls))) ;;; (split2 l_L) ;;; Splits list into two (new) second-level lists (defun split2* (L tc1 tc2) (cond ((null L) (list (nreverse tc1) (nreverse tc2))) (t (split2* (cddr L) (cons (car L) tc1) (cons (cadr L) tc2))))) (defun split2 (L) (split2* L nil nil)) ;;; (sublist L IL) ;;; Splits list (destructively) into (length IL) sub-lists. ;;; IL is a list of starting indices, base zero, should be unique positive ;;; fixnums in ascending order, and shouldn't exceed the length of L. ;;; Each resulting sublist begins with (nthcdr (nth IL) L) (defun sublist (L IL) (sublist* 0 nil (cons nil L) IL)) (defun sublist* (I R L IL) ; tail-recursion function (cond ((and L IL) (cond ((<& I (car IL)) (sublist* (1+ I) R (cdr L) IL)) (t (sublist* (1+ I) (cons (cdr L) R) (prog1 (cdr L) (rplacd L nil)) (cdr IL))))) (t (nreverse R)))) (defun try-fun (fun l-arg) ; try function on each arg until non-nil (cond ((funcall fun (car l-arg))) (l-arg (try-fun fun (cdr l-arg))))) ;;; (uctolc g_expr) ;;; Returns s-expression formed by translating upper-case alphabetic ;;; characters in to their lower-case equivalents. ;;; Operates by imploding the translated characters, in the case of a ;;; symbol or string, or by recursively calling on members of a list. ;;; Other object types are returned unchanged. (defun uctolc (expr) (cond ((dtpr expr) (mapcar 'uctolc expr)) ((or (symbolp expr) (stringp expr)) (implode (mapcar '(lambda (ch) (cond ((alphap ch) ; or-in lower-case bit (boole 7 #.(1- #/a) ch)) (t ch))) (exploden expr)))) (t expr))) ;;; (unique a l) -- Scan for an element "equal" to . ;;; If found, return . Otherwise nconc onto ; return . (defun unique (a l) ; ensure unique in list (car (do ((cdr_ul l (cdr ul)) (ul l cdr_ul)) ((null cdr_ul) (rplacd ul (ncons a))) (cond ((equal a (car cdr_ul)) (return cdr_ul)))))) ;;; (upperp sx_char) (defun upperp (char) ; is char upper-case alphabetic? (cond ((symbolp char) (setq char (car (exploden char))))) (and (fixp char) (or (and (> char #.(1- #/A)) (< char #.(1+ #/Z)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; zone.l -- data structures and routines for concrete window zones ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; a "point" is a pair of integer x,y coordinates ;;; a "box" is a pair of points defining lower left and upper right corners ;;; a "position" is a point coupled with a window ;;; a "zone" is a box coupled with a window ;;; a "window" is a machine, integer window id and, for compatibility ;;; with the toolbox, an integer toolbox window pointer ;;; a "machine" is a name coupled with the j-process-id's of resident servers ;;; The basic idea is to define a notion of a concrete position for a ;;; display object, that can be incorporated into the object data structure. ;;; Higher levels of software can use the objects without explicit reference ;;; to server processes, windows and machines. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (declare (specials t) ; global vars not local to this file (macros t)) ; compile macros as well (eval-when (compile) ; trust to higher level for eval & load (load 'utilities) ; utility functions (load 'constants) ; common constants for window toolbox ; (load 'shape) ; arbitrarily shaped screen areas ) (defstruct (position ; a concrete display position (:displace t) (:list) (:conc-name)) (window (make-window)) ; concrete window (point (make-point)) ; actual x, y coordinates ) (defstruct (zone ; a concrete display zone (:displace t) (:list) (:conc-name)) (window (make-window)) ; concrete window (box (make-box)) ; bounding box of zone (colour W-BACKGROUND) ; colour (for scrolling etc) shape ) (defstruct (window ; concrete window (:displace t) (:list) (:conc-name)) (id 0) ; integer window id (machine (make-machine)) ; machine (workstation) (w 0) ; toolbox window structure pointer ) (defstruct (machine ; machine (workstation) (:displace t) (:list) (:conc-name)) (name 'unknown-machine) ; machine name (servers nil) ; plist of server processes living there ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; manipulation routines ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun add-points (p q) ; vector sum (x1+x2) (y1+y2) (make-point x (+ (x p) (x q)) y (+ (y p) (y q)))) (defun subtract-points (p q) ; vector subtract (x1-x2) (y1-y2) (make-point x (- (x p) (x q)) y (- (y p) (y q)))) (defun multiply-points (p q) ; vector multiply (x1*x2) (y1*y2) (make-point x (* (x p) (x q)) y (* (y p) (y q)))) (defun divide-points (p q) ; vector division (x1-x2) (y1-y2) (make-point x (/ (x p) (x q)) y (/ (y p) (y q)))) (defun move-point (p q) ; move point p to point q (alter-point p x (x q) y (y q)) t) ; return true (defun box-size (b) ; size of box = ur - ll (subtract-points (ur b) (ll b))) (defun box-interior (b) ; return box just inside this box dimensions (make-box ll (add-points (ll b) '(1 1)) ur (subtract-points (ur b) '(1 1)))) (defun move-box (b p) ; move box b to point p (lower-left) (let ((size (box-size b))) (alter-box b ll p ur (add-points p size)) t)) ; return true (defun point-in-box (p b) ; is point p in box b? (including boundary) (and (>= (x p) (x (ll b))) (<= (x p) (x (ur b))) (>= (y p) (y (ll b))) (<= (y p) (y (ur b))) )) (defun point-in-box-interior (p b) ; is point p in box b? (excluding boundary) (and (> (x p) (x (ll b))) (< (x p) (x (ur b))) (> (y p) (y (ll b))) (< (y p) (y (ur b))) )) (defun init-window (w) ; fill in "window" structure (let ; presuming window-w predefined ((m (j-machine-name (w-get-manager (window-w w))))) (alter-window w id (w-get-id (window-w w))) (cond ((not (window-machine w)) (alter-window w machine (make-machine name m))) (t (alter-machine (window-machine w) name m))) (init-machine (window-machine w)) ; also fill in machine structure t)) ; return true (defun init-machine (m) ; fill in "machine" structure (cond ; presuming machine-name predefined ((null (machine-servers m)) ; if no plist, make new one (alter-machine m servers (ncons 'servers:)))) (mapc '(lambda (pname) ; for each expected server name (let ((pid (j-search-machine-e jipc-error-code (machine-name m) pname))) ; try to find one on that machine (cond ((j-same-process pid J-NO-PROCESS) (putprop (machine-servers m) nil pname)) ; failed! use nil (t (putprop (machine-servers m) pid pname))))) ; success! EXPECTED-WORKSTATION-SERVERS) ; global list of process names t) ; return true (defvar EXPECTED-WORKSTATION-SERVERS ; global list of process names '(window_manager creator savemem text-composer)) ; usually want at least these (defun window-box (w) ; box fills entire window (let ((w-size (w-get-window-size (window-w w)))) (make-box ll (make-point x 0 y 0) ur (make-point x (car w-size) y (cadr w-size))) )) (defun clear-zone (z colour) ; clear zone (including boundaries) (let ((b (box-size (zone-box z)))) (w-clear-rectangle (window-w (zone-window z)) (x (ll (zone-box z))) (y (ll (zone-box z))) (1+ (x b)) (1+ (y b)) colour))) (defun clear-zone-interior (z colour) ; clear zone (excluding boundaries) (let ((b (box-size (zone-box z)))) (w-clear-rectangle (window-w (zone-window z)) (1+ (x (ll (zone-box z)))) (1+ (y (ll (zone-box z)))) (1- (x b)) (1- (y b)) colour))) (defun pattern-zone (z pattern) ; pattern zone (including boundaries) (let ((b (zone-box z))) (w-pattern-rectangle (window-w (zone-window z)) (x (ll b)) (y (ll b)) (1+ (x (ur b))) (1+ (y (ur b))) pattern) )) (defun pattern-zone-interior (z pattern) ; pattern zone (excluding boundaries) (let ((b (box-size (zone-box z)))) (w-pattern-rectangle (window-w (zone-window z)) (1+ (x (ll (zone-box z)))) (1+ (y (ll (zone-box z)))) (1- (x b)) (1- (y b)) pattern) )) (defun draw-zone-outline (z colour) ; draw zone boundaries (let* ((w (window-w (zone-window z))) (b (zone-box z)) (ll (ll b)) (ur (ur b))) (w-draw-vector w (x ll) (y ll) (x ll) (y ur) colour) (w-draw-vector w (x ll) (y ur) (x ur) (y ur) colour) (w-draw-vector w (x ur) (y ur) (x ur) (y ll) colour) (w-draw-vector w (x ur) (y ll) (x ll) (y ll) colour) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; font.l -- font manipulation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (eval-when (compile) (load 'utilities) (load 'constants)) (defvar -installed-fonts nil) ; list of installed fonts (defstruct (font ; font structure (:displace t) (:list) (:conc-name)) (name 'standard) (size 8) (body 8) (cap-height 7) (x-height 5) (fixed-width 5) (first 0) (last 127) glyph ; the actual characters ) (defstruct (glyph ; glyph structure (:displace t) (:list) (:conc-name)) code width (bytes (byte-block 32)) ; the actual bitmap ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; font manipulation routines ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun read-font (family size path) (let ((p (infile path)) ; open file (x (new-vectori-long 2)) (f nil)) (setq f (make-font name family size (tyi p) body (tyi p) cap-height (tyi p) x-height (tyi p) fixed-width (tyi p) first (prog1 (tyi p) (tyi p)) last (prog1 (tyi p) (tyi p)))) (alter-font f glyph (do ((i (font-first f) (1+ i)) (r (ncons nil)) (g)) ((> i (font-last f)) (car r)) (setq g (make-glyph code i)) ; allocate char (do ((j 0 (1+ j))) ; read bitmap ((> j 31)) (vseti-byte (glyph-bytes g) j (tyi p))) (alter-glyph g width (tyi p)) ; read width (setq r (tconc r g)) )) (close p) ; close file (rplacd ; install font (cond ((assoc (list (font-name f) (font-size f)) -installed-fonts)) (t (car (setq -installed-fonts (cons (ncons (list (font-name f) (font-size f))) -installed-fonts))))) f) f)) ; return font (def-usage 'read-font '(|'st_family| |'x_size| |'st_path|) 'l_font-descriptor (setq fcn-group (ncons "Font Manipulation:"))) (defun install-font (f) (cdr (rplacd ; install font (cond ((assoc (list (font-name f) (font-size f)) -installed-fonts)) (t (car (setq -installed-fonts (cons (ncons (list (font-name f) (font-size f))) -installed-fonts))))) f))) (defun find-font (family size) ; always "finds" one even if dummy (cond ((cdr (assoc (list family size) -installed-fonts))) (t (install-font (make-font name family size size))))) (def-usage 'find-font '(|'st_family| |'x_size|) 'l_font-descriptor fcn-group) (defun create-font (driver font) (j-send-se-list driver (list 'make-font (font-name font) (font-size font) (font-body font) (font-cap-height font) (font-x-height font) (font-fixed-width font) (font-first font) (font-last font)))) (defun download-glyph (driver font glyph) (j-put-items `((J-STRING set-glyph) (J-STRING ,(font-name font)) (J-INT ,(font-size font)) (J-INT ,(glyph-code glyph)) (J-INT ,(glyph-width glyph)) (J-BLOCK ,(glyph-bytes glyph)))) (j-send driver)) (defun download-font (driver font) (do ((g (font-glyph font)) (font-size (font-size font))) ((null g)) (j-put-items `((J-STRING set-glyph) (J-STRING ,(font-name font)) (J-INT ,font-size))) (do ((gg g (cdr gg))) ((or (null gg) (j-put-items `((J-INT ,(glyph-code (car gg))) (J-INT ,(glyph-width (car gg))) (J-BLOCK ,(glyph-bytes (car gg)) ,(+ font-size font-size))))) (setq g gg))) ; when buffer full, save remainder (j-send driver) (cond ((eq J-STRING (j-next-item-type)) (j-gets j-comm-string 128) ; skip past message string (cond ((eq J-INT (j-next-item-type))(patom (j-geti))(terpr))))) )) (def-usage 'download-font '(|'x_process-id| |'l_font-descriptor|) 't fcn-group) (defun read-create-download-font (driver family size path) (let ((f (read-font family size path))) (create-font driver f) (download-font driver f) f)) (def-usage 'read-create-download-font '(|'x_process-id| |'st_family| |'x_size| |'st_path|) 'l_font-descriptor fcn-group) (defun font-depth (f) (- (font-body f) (font-cap-height f))) (defun font-height (f) (font-cap-height f)) (defun get-font-list (sc) ; arg is string-composer or font-server pid (j-send-se sc 'get-font-list) (pairify (mapcar '(lambda (x) (cond ((stringp (cadr x)) (concat (cadr x))) (t (cadr x)))) (j-get-items)))) (defun get-all-font-info (sc) ; arg is string-composer or font-server pid (mapc '(lambda (f) (rplacd (apply 'find-font f) (cdr (progn (j-send-se-list sc (cons 'get-font-info f)) (mapcar 'cadr (j-get-items)))))) (get-font-list sc))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; text.l -- fancy text strings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (declare (specials t) (macros t)) (eval-when (compile) (load 'utilities) (load 'constants) (load 'zone) (load 'font) (load 'look)) (defstruct (text ; text structure (:displace t) (:list) (:conc-name)) (text '||) ; the text to draw (look (make-look)) ; what style to draw it in (kl 0) ; (starting) left kerning mask (zone (make-zone)) ; specific window, clipping box (offset (make-point)) ; offset of start point from zone ll (kr 0) ; (final) right kerning mask (delta (make-point)) ; change in (x,y) relative to start point (nn -1) ; char count ) ;;; NOTE: clipping box of ((0 0) (-1 -1)) uses window boundaries (defun text-width (s) ; presumes non-rotated (x (text-delta s))) (defun text-box (s) ; presumes non-rotated (make-box ll (subtract-points (text-start-point s) (make-point x 0 y (font-depth (look-font (text-look s))))) ur (add-points (text-end-point s) (make-point x 0 y (font-height (look-font (text-look s))))))) (defun text-start-point (s) (add-points (ll (zone-box (text-zone s))) (text-offset s))) (defun text-end-point (s) (add-points (text-start-point s) (text-delta s))) (defun text-x (s) ; x coord of start of text object (+ (x (ll (zone-box (text-zone s)))) (x (text-offset s)))) (defun text-y (s) ; y coord of start of text object (+ (y (ll (zone-box (text-zone s)))) (y (text-offset s)))) (defun text-xx (s) ; x coord of end of text object (+ (x (ll (zone-box (text-zone s)))) (x (text-offset s)) (x (text-delta s)))) (defun text-yy (s) ; y coord of end of text object (+ (y (ll (zone-box (text-zone s)))) (y (text-offset s)) (y (text-delta s)))) (defun move-text (s p) ; move s to new x,y (alter-text s offset (subtract-points p (ll (zone-box (text-zone s)))))) (defun draw-text (s) ; quietly draw text, clipping to zone box (let (((x y) (text-start-point s)) (l (text-look s))) (j-put-items `((J-STRING compose) (J-INT ,(window-id (zone-window (text-zone s)))) (J-STRING ,(text-text s)) (J-STRING ,(font-name (look-font l))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 7 (look-mode l) QUIET)) (J-INT ,(look-colour l)) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kl s)) (J-INT ,x) (J-INT ,y) (J-INT ,(x (cond ((zerop (boole 1 ROTATE-180 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(y (cond ((zerop (boole 1 ROTATE-90 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(text-nn s)) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) )) (defun undraw-text (s) ; quietly undraw text, clipping to zone box (let (((x y) (text-start-point s)) (l (text-look s))) (j-put-items `((J-STRING compose) (J-INT ,(window-id (zone-window (text-zone s)))) (J-STRING ,(text-text s)) (J-STRING ,(font-name (look-font l))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 7 OVERSTRIKE QUIET (look-mode l))) (J-INT ,(inverse-colour (look-colour l))) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kl s)) (J-INT ,x) (J-INT ,y) (J-INT ,(x (cond ((zerop (boole 1 ROTATE-180 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(y (cond ((zerop (boole 1 ROTATE-90 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(text-nn s)) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) )) (defun format-text (s) ; format text without drawing or clipping (let ((memop (symbolp (text-text s))) ; can only memoize symbols (k) (p) (q) (l (text-look s))) (cond (memop ; are we memoizing? yes! (setq k (unique-look-id l)) ; key based on look (setq p (get (text-text s) k)) ; alist found on plist (setq q (assoc (text-kl s) p)))) ; entry based on kl (cond (q (alter-text s ; if info found kr (cadr q) ; record result delta (caddr q) ; then return nn (cadddr q))) (t ; otherwise compute data (j-put-items `((J-STRING compose) (J-INT 0) ; no window needed (J-STRING ,(text-text s)) (J-STRING ,(font-name (look-font l))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 7 NO-DRAW (look-mode l))) (J-INT ,(look-colour l)) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kl s)) (J-INT 0) ; starting point 0 0 (J-INT 0) (J-INT -1) ; no clipping (J-INT -1) (J-INT -1) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) (let ((kr (j-geti)) ; now record result (xx (j-geti)) (yy (j-geti)) (nn (j-geti))) (alter-text s kr kr delta (make-point x xx y yy) nn nn) (cond (memop ; memoize if req'd (cond (p (nconc p (ncons (list (text-kl s) kr (text-delta s) nn)))) (t (putprop (text-text s) (ncons (list (text-kl s) kr (text-delta s) nn)) k)))) )) )) 't)) ; always return t (defun scan-text (s p) ; scan text s for point p, return (kr delta nn) (let (((x y) (text-start-point s)) ; inside: check text (l (text-look s))) (j-put-items `((J-STRING compose) (J-INT 0) (J-STRING ,(text-text s)) (J-STRING ,(font-name (look-font l))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 7 NO-DRAW (look-mode l))) (J-INT ,(look-colour l)) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kl s)) (J-INT ,x) (J-INT ,y) (J-INT ,(x p)) (J-INT ,(y p)) (J-INT ,(text-nn s)) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) (let ((kr (j-geti)) ; now record result (xx (j-geti)) (yy (j-geti)) (nn (j-geti))) (list kr (make-point x (- xx x) y (- yy y)) nn)) )) (defun format-draw-text (s) ; draw it while formatting (let ((memop (symbolp (text-text s))) ; can only memoize symbols ((x y) (text-start-point s)) (k) (p) (q) (l (text-look s))) (cond (memop ; are we memoizing? yes! (setq k (unique-look-id l)) ; key based on look (setq p (get (text-text s) k)) ; alist found on plist (setq q (assoc (text-kl s) p)))) ; entry based on kl (cond (q (alter-text s ; if info found kr (cadr q) ; record result delta (caddr q) nn (cadddr q)) (draw-text s)) ; draw it & return (t ; otherwise compute data (j-put-items `((J-STRING compose) (J-INT ,(window-id (zone-window (text-zone s)))) (J-STRING ,(text-text s)) (J-STRING ,(font-name (look-font l ))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 4 (look-mode l) QUIET)) (J-INT ,(look-colour l)) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kl s)) (J-INT ,x) (J-INT ,y) (J-INT ,(x (cond ((zerop (boole 1 ROTATE-180 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(y (cond ((zerop (boole 1 ROTATE-90 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT -1) ; format to end of text )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) (let ((kr (j-geti)) ; now alter result data (xx (j-geti)) (yy (j-geti)) (nn (j-geti))) (cond ((neq nn (length (exploden (text-text s)))) (format-text s)) ; actually clipped! reformat (t (alter-text s kr kr delta (make-point x (- xx x) y (- yy y)) nn nn) (cond (memop ; memoize if req'd (cond (p (nconc p (ncons (list (text-kl s) kr (text-delta s) nn)))) (t (putprop (text-text s) (ncons (list (text-kl s) kr (text-delta s) nn)) k)))) )) )) )) 't)) ; always return t (defun backspace-text (s n) ; undraw last n characters, remove from text (cond ; this presumes s has valid delta,kr,nn ((plusp (text-nn s)) ; proceed only if length > 0 (setq n (min n (text-nn s))) ; can't delete more than nn chars (let ((text (text-text s)) (l (text-look s))) (alter-text s ; keep all but last n chars text (substring text 1 (- (text-nn s) n)) nn (- (text-nn s) n)) (format-text s) ; reformat to find the new end (j-put-items `((J-STRING compose) ; now undraw last character (J-INT ,(window-id (zone-window (text-zone s)))) (J-STRING ,(substring text (- n))) ; undraw last n chars (J-STRING ,(font-name (look-font l))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 7 QUIET OVERSTRIKE (look-mode l))) (J-INT ,(inverse-colour (look-colour l))) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kr s)) (J-INT ,(text-xx s)) (J-INT ,(text-yy s)) (J-INT ,(x (cond ((zerop (boole 1 ROTATE-180 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(y (cond ((zerop (boole 1 ROTATE-90 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,n) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) 't)) ; return t if able to do it; nil if nn <= 0 )) (defun append-text (s c) ; draw new char(s) & add to end of text (cond ((fixp c) ; this presumes s has valid delta,kr,nn (setq c (ascii c)))) (j-put-items `((J-STRING compose) ; draw new last character(s) (J-INT ,(window-id (zone-window (text-zone s)))) (J-STRING ,c) (J-STRING ,(font-name (look-font (text-look s)))) (J-INT ,(font-size (look-font (text-look s)))) (J-INT ,(boole 4 (look-mode (text-look s)) QUIET)) ; be noisy! (J-INT ,(look-colour (text-look s))) (J-INT ,(look-gap (text-look s))) (J-INT ,(look-ul (text-look s))) (J-INT ,(text-kr s)) ; this presumes s has valid delta,kr,nn (J-INT ,(text-xx s)) (J-INT ,(text-yy s)) (J-INT ,(x (cond ((zerop (boole 1 ROTATE-180 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(y (cond ((zerop (boole 1 ROTATE-90 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT -1) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) (let ((kr (j-geti)) (xx (j-geti)) (yy (j-geti)) (nn (j-geti))) (alter-text s text (concat (text-text s) c) kr kr delta (subtract-points (make-point x xx y yy) (text-start-point s)) nn (+ (text-nn s) nn))) 't) (defun append-text-scroll (s c colour) ; draw and add new char(s) (let ((w (window-id ; while scrolling zone box b in specified colour (zone-window (text-zone s)))) (b (zone-box (text-zone s))) (l (text-look s))) (cond ((fixp c) (setq c (ascii c)))) ; this presumes s has valid delta,kr,nn (j-put-items `((J-STRING compose) ; format new last character (J-INT ,w) (J-STRING ,c) (J-STRING ,(font-name (look-font l))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 7 NO-DRAW (look-mode l))) (J-INT ,(look-colour l)) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kr s)) ; this presumes s has valid delta,kr,nn (J-INT 0) (J-INT 0) (J-INT -1) (J-INT -1) (J-INT -1) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) (let ((kr (j-geti)) (xx (j-geti)) (yy (j-geti)) (nn (j-geti))) (apply 'w-scroll-rectangle (nconc (ncons (window-w (zone-window (text-zone s)))) (let ((direction (boole 1 ROTATION (look-mode l)))) (cond ((= direction ROTATE-0) (list (text-xx s) (y (ll b)) (- (x (ur b)) (text-xx s) -1) (- (y (ur b)) (y (ll b)) -1) WM-RIGHT xx)) ((= direction ROTATE-90) (list (x (ll b)) (text-yy s) (- (x (ur b)) (x (ll b)) -1) (- (y (ur b)) (text-yy s) -1) WM-UP yy)) ((= direction ROTATE-180) (list (x (ll b)) (y (ll b)) (- (text-xx s) (x (ll b)) -1) (- (y (ur b)) (y (ll b)) -1) WM-LEFT (- xx))) ((= direction ROTATE-270) (list (x (ll b)) (y (ll b)) (- (x (ur b)) (x (ll b)) -1) (- (text-yy s) (y (ll b)) -1) WM-DOWN (- yy))) )) (ncons colour))) (w-flush (window-w (zone-window (text-zone s)))) (j-put-items `((J-STRING compose) ; draw new last character (J-INT ,w) (J-STRING ,c) (J-STRING ,(font-name (look-font l))) (J-INT ,(font-size (look-font l))) (J-INT ,(boole 7 (look-mode l) QUIET)) (J-INT ,(look-colour l)) (J-INT ,(look-gap l)) (J-INT ,(look-ul l)) (J-INT ,(text-kr s)) ; this presumes s has valid delta,kr,nn (J-INT ,(text-xx s)) (J-INT ,(text-yy s)) (J-INT ,(x (cond ((zerop (boole 1 ROTATE-180 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT ,(y (cond ((zerop (boole 1 ROTATE-90 (look-mode l))) (ur (zone-box (text-zone s)))) (t (ll (zone-box (text-zone s))))))) (J-INT -1) )) (j-send (get (machine-servers (window-machine (zone-window (text-zone s)))) 'text-composer)) (alter-text s text (concat (text-text s) c) kr kr delta (add-points (make-point x xx y yy) (text-delta s)) nn (+ (text-nn s) nn)) )'t)) (defun format-text-list (sl) ; chain the text objects (do ((s (car sl) (car sl)) ; so that xx,yy,kr of one (sl (cdr sl) (cdr sl))) ; used as x,y,kl of next ((null sl) (format-text s) 't) (format-text s) (alter-text (car sl) kl (text-kr s)) (move-text (car sl) (text-end-point s)) )) (defun move-text-list (sl p) ; move whole list of text objects (do ((s (car sl) (car sl)) (sl (cdr sl) (cdr sl)) (p p (text-end-point s))) ((null s) 't) (move-text s p) )) (defun compress-text-list (sl) ; combine like-moded text objects (do ((s (car sl) (car sl)) ; to reduce communication (sl (cdr sl) (cdr sl)) (new-text nil) (new-end-point (text-start-point s)) (new-s (append (car sl) nil)) ; top-level copy (dx nil) (gap (look-gap (text-look (car sl)))) (result nil)) ((null s) (alter-text new-s text (apply 'concat (nreverse new-text)) nn -1) (nreverse (cons new-s result))) ; return new s-list (setq dx (- (x (text-start-point s)) (x new-end-point))) (cond ((and ; check most likely diffs first (or (eq dx 0) (>= dx (look-gap (text-look s)))) (= (y (text-start-point s)) (y new-end-point)) (eq (text-look s) (text-look new-s)) ) ; presume kerning doesn't matter! (cond ((plusp dx) ; horizontal movement (setq new-text (cons (implode (do ((dx (- dx gap 4) (- dx gap 4)) (result nil)) ((minusp dx) (do ((dx (+ dx 4 -1) (- dx gap 1))) ((minusp dx) (cond ((eq dx -1) (setq result (cons 1 result))))) ; 0-pixel space (setq result (cons 2 result))) ; 1-pixel space result) (setq result (cons 3 result)) ; 4-pixel space )) new-text)))) (setq new-text (cons (text-text s) new-text)) (setq new-end-point (text-end-point s)) ) (t (alter-text new-s text (apply 'concat (nreverse new-text)) nn -1 delta (subtract-points new-end-point (text-start-point new-s))) (setq result (cons new-s result)) (setq new-s (append s nil) new-text (ncons (text-text s))) (setq new-end-point (text-start-point s) gap (look-gap (text-look s))) ) ))) (defun draw-text-list (sl) (mapc '(lambda (x) (draw-text x)) sl) 't) (defun undraw-text-list (sl) (mapc '(lambda (x) (undraw-text x)) sl) 't) (defun format-draw-text-list (slist) ; format all on same line (do ((s (car slist) (car sl)) (sl (cdr slist) (cdr sl))) ((null sl) (format-draw-text s)) ; format the last one (format-draw-text s) (move-text (car sl) ; chain xx,yy,kr to next one's x,y,kl (text-end-point s)) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; text-edit.l -- rudimentary line editor for fancy character texts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; These routines provide a simple line editor with control keys reminiscent ;;; of the default EMACS key bindings. ;;; ;;; The calling program presumably has obtained a "point" event, at ;;; position "p". The cursor will be placed on the nearest character, ;;; and then input is accepted from the keyboard, until such time as a ;;; key is accepted, or a point event occurs outside the text ;;; zone boundary, or until a non-key, non-point event occurs. Another ;;; point event within the text zone causes the cursor to be re-positioned. ;;; ;;; Editing operations currently supported are: ;;; CTRL-A (ascii 1) ; control A = beginning of line ;;; CTRL-B (ascii 2) ; control B = backward-character ;;; CTRL-D (ascii 4) ; control D = delete next char ;;; CTRL-E (ascii 5) ; control E = end of line ;;; CTRL-F (ascii 6) ; control F = forward-character ;;; BACKSPACE (ascii 8) ; BACKSPACE = delete previous char ;;; CTRL-K (ascii 11) ; control K = kill to end of line ;;; CTRL-L (ascii 12) ; control L = redraw text ;;; RETURN (ascii 13) ; RETURN = "done" ;;; CTRL-T (ascii 20) ; control T = transpose previous 2 chars ;;; CTRL-Y (ascii 25) ; control Y = "yank" recently killed text (declare (specials t) (macros t)) (eval-when (compile) (load 'utilities) (load 'constants) (load 'zone) (load 'font) (load 'look) (load 'text)) (eval-when (compile eval load) (defvar BACKSPACE (ascii 8)) ; backspace char = delete previous char (defvar RETURN (ascii 13)) ; carriage return = "done" (defvar CTRL-A (ascii 1)) ; control A = beginning of line (defvar CTRL-B (ascii 2)) ; control B = backward-character (defvar CTRL-D (ascii 4)) ; control D = delete next char (defvar CTRL-E (ascii 5)) ; control E = end of line (defvar CTRL-F (ascii 6)) ; control F = forward-character (defvar CTRL-K (ascii 11)) ; control K = kill to end of line (defvar CTRL-L (ascii 12)) ; control L = redraw text (defvar CTRL-T (ascii 20)) ; control T = transpose previous 2 chars (defvar CTRL-Y (ascii 25)) ; control Y = "yank" recently killed text (defvar TYPEAHEAD-THRESHOLD 5); can type at most 5 chars -> forced feedback ) (defun edit-text (s p) ; edit a text at point p (cond ; p outside zone => nil ((not (point-in-box p (zone-box (text-zone s)))) nil) (t ; p inside zone => edit text (let ((w (window-w (zone-window (text-zone s)))) (post (append s nil)) (kill-text "")) (split-texts s post p) ; split into left and right parts (draw-cursor-leading-text post) ; highlight first char (skip-stroke-release-events w) (do ((e (w-get-next-event w) ; get an event (w-get-next-event w)) ; then keep getting events (l) (c)) ; character list, character ((eq c '#.RETURN) ; stop when is received (cond ((neq e WM-KEY) ; if not caused by key, put event back (w-put-back-event w))) (combine-texts s post) t) ; just return 't (cond ; main loop ((eq e WM-KEY) (setq c (concat (car (w-get-key w)))) ; get the character (cond ((eq c '#.BACKSPACE) ; backspace char (text-delete-previous-character s post)) ((eq c '#.CTRL-A) ; control A (text-beginning-of-line s post)) ((eq c '#.CTRL-B) ; control B (text-backward-character s post)) ((eq c '#.CTRL-D) ; control D (text-delete-next-character s post)) ((eq c '#.CTRL-E) ; control E (text-end-of-line s post)) ((eq c '#.CTRL-F) ; control F (text-forward-character s post)) ((eq c '#.CTRL-K) ; control K (text-kill-to-end-of-line s post)) ((eq c '#.CTRL-L) ; control L (text-redraw-display s post)) ((eq c '#.CTRL-T) ; control T (text-transpose-characters s post)) ((eq c '#.CTRL-Y) ; control Y (text-yank-from-killbuffer s post)) ((neq c '#.RETURN) ; not (text-insert-character s post)) (t (w-put-back-event w)) ; it's a ; put it back )) ; so loop control can get it again ((eq e WM-POINT-DEPRESSED) (setq p (w-get-point w)) (cond ; check point in zone ((point-in-box p (zone-box (text-zone s))) (draw-cursor-leading-text post) ; un-highlight char (combine-texts s post) (split-texts s post p) (draw-cursor-leading-text post) ; highlight new char (skip-stroke-release-events w)) (t (w-put-back-event w) ; outside zone => return (setq c '#.RETURN)))) ((neq e WM-CANCEL) ; an event we can't handle (w-put-back-event w) ; so put it back, then return (setq c '#.RETURN)) ))) ))) (defun input-typeahead-keys (w n brk-fcn l) ; return keys typed ahead (cond ; brk-fcn tests text ((or (zerop n) ; already have max typeahead (not (w-any-events w))) (nreverse l)) ; or there aren't any events (t (let ((x (w-get-next-event w))) ; there's an event (cond ((neq x WM-KEY) (w-put-back-event w) (nreverse l)) ; but not a keystroke (t (setq x (car (w-get-key w))) ; it's a keystroke (cond ((funcall brk-fcn x) ; is it a break char? (w-put-back-event w) (nreverse l)) ; it's a special char (t (input-typeahead-keys ; it's a regular char w (1- n) brk-fcn (cons x l))) ; tail recur for rest ))))))) (defun split-texts (s post p) ; split text s at point p (let ; yielding texts s and post (((kr delta nn) (scan-text s p))) ; scan for char pos'n (alter-text post ; text incl & after char pt'ed text (cond ((substring (text-text s) (1+ nn))) ; if it exists! ("")) ; otherwise,nothing offset (add-points (text-offset s) delta) kl kr delta (subtract-points (text-delta s) delta) nn (- (text-nn s) nn)) (alter-text s kr kr delta delta nn nn ; truncate text text (cond ((substring (text-text s) 1 nn)) (""))) )) (defun skip-stroke-release-events (w) (do ((e (w-get-next-event w) (w-get-next-event w))) ((neq e WM-POINT-STROKE) ; get events until non-point-stroke (cond ((neq e WM-POINT-RELEASED) ; should be point-release (w-put-back-event w)))) ; if not, put it back )) (defun combine-texts (s post) ; recombine texts (alter-text s text (concat (text-text s) (text-text post)) nn (+ (text-nn s) (text-nn post)) delta (add-points (text-delta s) (text-delta post)) kr (text-kr post)) (format-text s)) (defun draw-cursor-leading-text (s) ; highlight first char of text (let ((c (append s nil))) (alter-text c ; get first char text (concat (cond ((substring (text-text c) 1 1)) ; if any (t 'a)))) ; otherwise use a typical character (format-text c) (w-clear-rectangle (window-w (zone-window (text-zone c))) (text-x c) (y (ll (zone-box (text-zone c)))) (min (x (text-delta c)) (- (x (ur (zone-box (text-zone c)))) (text-x c) -1)) (- (y (ur (zone-box (text-zone c)))) (y (ll (zone-box (text-zone c)))) -1) W-XOR) (w-flush (window-w (zone-window (text-zone c)))) t)) (defun text-delete-previous-character (s post) (let ((l (input-typeahead-keys w TYPEAHEAD-THRESHOLD '(lambda (x) ; break on first non-BS (not (equal x #.(get_pname BACKSPACE)))) (ncons '#.BACKSPACE)))) (alter-text s nn (max 0 (- (text-nn s) (length l)))) (alter-text s text (cond ((substring (text-text s) 1 (text-nn s))) (""))) (format-text s) (w-scroll-rectangle (window-w (zone-window (text-zone s))) (text-xx s) (y (ll (zone-box (text-zone s)))) (- (x (ur (zone-box (text-zone s)))) (text-xx s) 1) (1+ (y (box-size (zone-box (text-zone s))))) WM-LEFT (- (x (text-start-point post)) (x (text-end-point s))) (zone-colour (text-zone s))) (w-flush (window-w (zone-window (text-zone s)))) (move-text post (text-end-point s)) (alter-text post kl (text-kr s)))) (defun text-beginning-of-line (s post) (draw-cursor-leading-text post) ; un-highlight first char (alter-text post text (concat (text-text s) (text-text post)) nn (+ (text-nn s) (text-nn post)) delta (add-points (text-delta s) (text-delta post)) kl 0 offset (text-offset s)) (alter-text s text "" nn 0 delta '(0 0) kr 0) (draw-cursor-leading-text post)) ; highlight new first char (defun text-backward-character (s post) (let ((l (input-typeahead-keys w TYPEAHEAD-THRESHOLD '(lambda (x) ; break on first non-BS (not (equal x #.(get_pname CTRL-B)))) (ncons '#.CTRL-B)))) (draw-cursor-leading-text post) ; un-highlight first char (alter-text post text (get_pname (concat (substring (text-text s) (- (length l))) (text-text post))) nn (1+ (text-nn post))) (alter-text s text (substring (text-text s) 1 (- (text-nn s) (length l))) nn (- (text-nn s) (length l))) (format-text s) (alter-text post kl (text-kr s) offset (add-points (text-offset s) (text-delta s)) delta (subtract-points (text-end-point post) (text-end-point s))) (draw-cursor-leading-text post) ; highlight new first char )) (defun text-forward-character (s post) (let ((l (input-typeahead-keys w TYPEAHEAD-THRESHOLD '(lambda (x) ; break on first non-BS (not (equal x #.(get_pname CTRL-F)))) (ncons '#.CTRL-F)))) (draw-cursor-leading-text post) ; un-highlight first char (alter-text s text (get_pname (concat (text-text s) (substring (text-text post) 1 (length l)))) nn (+ (text-nn s) (length l))) (format-text s) (alter-text post text (substring (text-text post) (1+ (length l))) nn (- (text-nn post) (length l)) kl (text-kr s) offset (add-points (text-offset s) (text-delta s)) delta (subtract-points (text-end-point post) (text-end-point s))) (draw-cursor-leading-text post) ; highlight new first char )) (defun text-end-of-line (s post) (draw-cursor-leading-text post) ; un-highlight first char (alter-text s text (concat (text-text s) (text-text post)) nn (+ (text-nn s) (text-nn post)) delta (add-points (text-delta s) (text-delta post)) kr (text-kr post)) (alter-text post text "" nn 0 offset (add-points (text-offset post) (text-delta post)) delta '(0 0) kl (text-kr s)) (draw-cursor-leading-text post)) ; highlight new first char (defun text-kill-to-end-of-line (s post) (w-clear-rectangle (window-w (zone-window (text-zone post))) (text-x post) (y (ll (zone-box (text-zone post)))) (- (x (ur (zone-box (text-zone post)))) (text-x post)) (1+ (y (box-size (zone-box (text-zone post))))) (zone-colour (text-zone post))) (setq kill-text (text-text post)) (alter-text post text "" nn 0 delta '(0 0) kl (text-kr s)) (draw-cursor-leading-text post)) ; highlight new first char (defun text-yank-from-killbuffer (s post) (append-text-scroll s kill-text (zone-colour (text-zone s))) (move-text post (text-end-point s)) (alter-text post kl (text-kr s))) (defun text-transpose-characters (s post) (let ((tmp (append s nil))) (alter-text tmp nn (- (text-nn tmp) 2)) (let (((kr delta nn) (scan-text tmp '(-1 -1)))) ; find 2nd prev char (alter-text tmp text (substring (text-text tmp) -2) offset (add-points (text-offset tmp) delta) kl kr) (format-text tmp) (w-clear-rectangle (window-w (zone-window (text-zone tmp))) (text-x tmp) (y (ll (zone-box (text-zone tmp)))) (x (text-delta tmp)) (1+ (y (box-size (zone-box (text-zone tmp))))) (zone-colour (text-zone tmp))) (w-flush (window-w (zone-window (text-zone tmp)))) (alter-text tmp text (get_pname (concat (substring (text-text tmp) 2 1) (substring (text-text tmp) 1 1)))) (format-draw-text tmp) (alter-text s text (get_pname (concat (substring (text-text s) 1 (- (text-nn s) 2)) (text-text tmp))) kr (text-kr tmp)) ))) (defun text-delete-next-character (s post) (let ((l (input-typeahead-keys w TYPEAHEAD-THRESHOLD '(lambda (x) ; break on first non-BS (not (equal x #.(get_pname CTRL-D)))) (ncons '#.CTRL-D)))) (alter-text post nn (length l)) (let (((kl delta nn) ; scan for nn'th char position (scan-text post '(-1 -1)))) (w-scroll-rectangle (window-w (zone-window (text-zone post))) (text-x post) (y (ll (zone-box (text-zone post)))) (- (x (ur (zone-box (text-zone post)))) (text-x post) 1) (1+ (y (box-size (zone-box (text-zone post))))) WM-LEFT (x delta) (zone-colour (text-zone post))) (alter-text post nn (max 0 (- (length (exploden (text-text post))) (length l))) kl kl) (alter-text post text (cond ((substring (text-text post) (- (text-nn post)))) (""))) (format-text post) (draw-cursor-leading-text post) (w-flush (window-w (zone-window (text-zone post)))) ))) (defun text-insert-character (s post) (let ((l (input-typeahead-keys w TYPEAHEAD-THRESHOLD '(lambda (x) ; break on first BS or CR (memq (concat x) '#.(list BACKSPACE RETURN))) (ncons c)))) (append-text-scroll s (concatl l) (zone-colour (text-zone s))) (move-text post (text-end-point s)) (alter-text post kl (text-kr s)))) (defun text-redraw-display (s post) (clear-zone (text-zone s) (zone-colour (text-zone s))) (w-flush (window-w (zone-window (text-zone post)))) (format-draw-text s) (alter-text post kl (text-kr s) offset (add-points (text-offset s) (text-delta s))) (format-draw-text post) (draw-cursor-leading-text post)) program interval(input,output); {dataflow simulator for real interval arithmetic} const IMem = 500; {number of instructions} DMem = 200; {number of interval variables allowed} Par = 3; {max number of paramters for an operator} Maxexp = 10; Minexp = -9; Maxinf =10000; Mininf =-10000; {Tied to values of Minman and Maxman} Maxman = 9999; Minman = -9999; {cannot exceed sqrt(maxint)} Splitman = 1000; {Smallest normalized mantisa} Digits = 4; {number of digits in mantissa} type Positive= 0..maxint; State = -1..99; {Used for holding state of operator -1:done} OpType = (print,pr,tr,soln,readr,halve,halves,linh,mult,add,intgr, less,leq,noteq,sqrr,minr,maxr,modu,absr,trig,expr,lb,ub,copy,stop); {!!} Ptr = 1..DMem; Loc = 1..IMem; Loc0 = 0..IMem; EdgeT = (hout,lin,hin,lout); {Warning this order is important in} {predicates such as gtS,geS} CardT = (finite,infinite); ExpT = Minexp..Maxexp; ManT = Mininf..Maxinf; Pflag = (PNull,PSoln,PTrace,PPrint); Sreal = record edge:EdgeT; cardinality:CardT; exp:ExpT; {exponent} mantissa:ManT; end; Int = record hi:Sreal; lo:Sreal; end; Instr = record Code:OpType; Pars: array[0..Par] of 0..DMem; end; DataMem= record D :array [Ptr] of Int; S :array [Loc] of State; LastHalve:Loc; RHalve :array [Loc] of real; end; DataFlags=record PF :array [Ptr] of Pflag; end; var Debug : (none,activity,post,trace,dump); Cut : (once,all); GlobalEnd,Verifiable:boolean; HalveThreshold:real; I : array [Loc] of Instr; {Memory holding instructions} End : Loc; {last instruction in I} ParN : array [OpType] of -1..Par; {number of parameters for each opcode. -1 means no result} ParIntersect : array [OpType] of boolean ; DInit : DataMem; {initial memory which is cleared and used in first call} DF : DataFlags; {hold flags for variables, e.g. print/trace} MaxDMem:0..DMem; Shift : array[0..Digits] of 1..maxint;{array of constant multipliers} {used for alignment etc.} Dummy :Positive; {constant intervals and Sreals} PlusInfS,MinusInfS,PlusSmallS,MinusSmallS,ZeroS, PlusFiniteS,MinusFiniteS:Sreal; Zero,All,AllFinite:Int; procedure deblank; var Ch:char; begin while (not eof) and (input^ in [' ',' ']) do read(Ch); end; procedure InitialOptions; #include '/user/profs/cleary/bin/options.i'; procedure Option; begin case Opt of 'a','A':Debug:=activity; 'd','D':Debug:=dump; 'h','H':HalveThreshold:=StringNum/100; 'n','N':Debug:=none; 'p','P':Debug:=post; 't','T':Debug:=trace; 'v','V':Verifiable:=true; end; end; begin Debug:=trace; Verifiable:=false; HalveThreshold:=67/100; Options; writeln(Debug); writeln('Verifiable:',Verifiable); writeln('Halve threshold',HalveThreshold); end;{InitialOptions} procedure NormalizeUp(E,M:integer;var S:Sreal;var Closed:boolean); begin with S do begin if M=0 then S:=ZeroS else if M>0 then begin while M>=Maxinf do begin if M mod 10 > 0 then begin Closed:=false;M:=(M div 10)+1 end else M:=M div 10; E:=E+1; end; while M < Maxinf div 10 do begin M:=M*10; E:=E-1; end; if E > Maxexp then {overflow-set to infinity} begin S:=PlusInfS; Closed:=false; end else if E < Minexp then {underflow-set to smallest positive value} begin S:=PlusSmallS; Closed:=false; end else begin cardinality:=finite;exp:=E;mantissa:=M; end; end else if M < 0 then begin while M <= Mininf do begin if M mod 10 < 0 then Closed:=false else if M mod 10 > 0 then halt; M:=M div 10; E:=E+1; end; while M > (Mininf div 10) do begin M:=M*10; E:=E-1; end; if E > Maxexp then {overflow-set to most negative value} begin S:=MinusFiniteS; Closed:=false; end else if E < Minexp then {underflow-set to zero} begin S:=ZeroS; Closed:=false; end else begin cardinality:=finite;exp:=E;mantissa:=M; end; end; end; end;{NormalizeUp} procedure NormalizeDn(E,M:integer;var S:Sreal;var Closed:boolean); begin with S do begin if M=0 then S:=ZeroS else if M>0 then begin while M >= Maxinf do begin if M mod 10 > 0 then Closed:=false else if M mod 10 < 0 then halt; M:=M div 10; E:=E+1; end; while (M < Maxinf div 10) do begin M:=M*10; E:=E-1; end; if E > Maxexp then {overflow-set to largest positive value} begin S:=PlusFiniteS; Closed:=false; end else if E < Minexp then {underflow-set to zero} begin S:=ZeroS; Closed:=false; end else begin cardinality:=finite;exp:=E;mantissa:=M; end; end else if M < 0 then begin while M <= Mininf do begin if M mod 10 < 0 then begin Closed:=false; M:=M div 10 -1;end else if M mod 10 = 0 then M:=M div 10 else halt; E:=E+1; end; while (M>Mininf div 10) do begin M:=M*10; E:=E-1; end; if E > Maxexp then {overflow} begin S:=MinusInfS; Closed:=false; end else if E < Minexp then {underflow} begin S:=MinusSmallS; Closed:=false; end else begin cardinality:=finite;exp:=E;mantissa:=M; end; end; end; end;{NormalizeDn} procedure WriteS(X:Sreal); var E,M:integer; begin with X do begin case edge of lin: write('['); lout: write('('); hin,hout: end; case cardinality of infinite: write('inf':Digits+4); finite: if mantissa = 0 then write(0:Digits+1,' ':3) else begin M:=mantissa; E:=exp; while (M mod 10 = 0) do begin M:=M div 10; E:=E+1; end; write(M:Digits+1,'e',E-Digits:2); end; end; case edge of hin: write(']'); hout:write(')'); lin,lout: end; end; end;{WriteS} procedure WriteInt(I:Int); begin with I do begin WriteS(lo); write(','); WriteS(hi); end; end;{WriteInt} procedure DumpS(X:Sreal); begin with X do write(edge:4,cardinality:9,mantissa:7,exp:3); end;{DumpS} procedure DumpInt(I:Int); begin with I do begin DumpS(lo); write(' || '); DumpS(hi); end; end;{DumpInt} procedure ReadInt(var I:Int); var Ch:char; Cll,Clu:boolean; procedure ReadSUp(var X:Sreal; var Closed:boolean); var E,M:integer; begin with X do begin deblank; case input^ of '~':begin X:=PlusInfS;read(Ch); end; '-','+','0','1','2','3','4','5','6','7','8','9': begin cardinality:=finite; read(M); read(E); E:=E+Digits; NormalizeUp(E,M,X,Closed); end; end;{case} end; end;{ReadSUp} procedure ReadSDn(var X:Sreal; var Closed:boolean); var E,M:integer; Ch:char; begin with X do begin deblank; case input^ of '~':begin X:=MinusInfS;read(Ch); end; '-','+','0','1','2','3','4','5','6','7','8','9': begin cardinality:=finite; read(M); read(E); E:=E+Digits; NormalizeDn(E,M,X,Closed); end; end;{case} end; end;{ReadSDn} begin{ReadInt} with I do begin deblank; read(Ch); case Ch of '[':Cll:=true; '(':Cll:=false; end; ReadSDn(lo,Cll);if Cll then lo.edge:=lin else lo.edge:=lout; deblank; read(Ch); assert(Ch=','); Clu:=true; ReadSUp(hi,Clu); deblank; read(Ch); case Ch of ']':if Clu then hi.edge:=hin else hi.edge:=hout; ')':hi.edge:=hout; end; end; end;{ReadInt} procedure DumpTables; var tL:Loc; tPar:0..Par; tOp:OpType; begin for tOp := print to stop do writeln(tOp:6,ParN[tOp]:2); writeln; for tL := 1 to End do with I[tL] do begin write(Code:5); for tPar := 0 to Par do if Pars[tPar] <> 0 then write(Pars[tPar]:4); writeln; end; writeln('number of memory locations used:',MaxDMem:0); writeln; end;{DumpTables} procedure AlignUp (E0:ExpT;M0:ManT;E1:ExpT;M1:ManT;var E,N0,N1:integer;var Closed:boolean); {Align mantissas M0,M1 preserving accuracy and rounding up wherever possible} {common resulting exponents in E, and mantissas in N0,N1} var D:Positive; begin if M0=0 then begin E:=E1;N0:=0;N1:=M1;end else if M1=0 then begin E:=E0;N0:=M0;N1:=0;end else if E0=E1 then begin E:=E0; N0:=M0; N1:=M1; end else if (E0>E1) then AlignUp(E1,M1,E0,M0,E,N1,N0,Closed) else begin D:=E1-E0; if D>= 2*Digits then begin N1:=M1*Maxinf; E:=E1-Digits; if M0<0 then N0:=0 else N0:=1; Closed:=false; end else if D > Digits then begin N1:=M1*Maxinf; E:=E1-Digits; if (M0 mod Shift[D-Digits]) = 0 then N0:=(M0 div Shift[D-Digits]) else if M0 > 0 then N0:=(M0 div Shift[D-Digits])+1 else N0:=(M0 div Shift[D-Digits]); end else {Digits>=D>=0} begin N1:=M1*Shift[D]; E:=E1-D; N0:=M0; end; end; end;{AlignUp} function gtS(X,Y:Sreal):boolean; {X>Y careful need to be able to compare x] and (x etc.} var gt:boolean; begin if (X.exp=Y.exp)and(X.mantissa=Y.mantissa) then gt:=X.edge>Y.edge else if X.exp = Y.exp then gt:= (X.mantissa > Y.mantissa) else if X.mantissa = 0 then gt:= 0 > Y.mantissa else if Y.mantissa = 0 then gt:= X.mantissa > 0 else if (X.mantissa>0) and (Y.mantissa>0) then gt:= (X.exp > Y.exp) else if (X.mantissa>0) and (Y.mantissa<0) then gt:= true else if (X.mantissa<0) and (Y.mantissa>0) then gt:= false else if (X.mantissa<0) and (Y.mantissa<0) then gt:= (X.exp < Y.exp) else writeln('error in gtS'); gtS:=gt; end;{gtS} function geS(X,Y:Sreal):boolean; {X>=Y careful need to be able to compare x] and (x etc.} begin if (X.exp=Y.exp)and(X.mantissa=Y.mantissa) then geS:=X.edge>=Y.edge else if X.exp = Y.exp then geS:= (X.mantissa >= Y.mantissa) else if X.mantissa = 0 then geS:= 0 >= Y.mantissa else if Y.mantissa = 0 then geS:= X.mantissa >= 0 else if (X.mantissa>0) and (Y.mantissa>0) then geS:= (X.exp > Y.exp) else if (X.mantissa>0) and (Y.mantissa<0) then geS:= true else if (X.mantissa<0) and (Y.mantissa>0) then geS:= false else if (X.mantissa<0) and (Y.mantissa<0) then geS:= (X.exp < Y.exp) else writeln('error in geS'); end;{geS} function Point(X:Int):boolean; {X=[x,x]} begin with X do Point:=(lo.edge=lin)and (hi.edge=hin) and (lo.mantissa=hi.mantissa) and (lo.exp=hi.exp); end;{Point} procedure maxS(X,Y:Sreal;var max:Sreal); begin if gtS(X,Y) then max:=X else max:=Y; end; procedure minS(X,Y:Sreal;var min:Sreal); begin if gtS(X,Y) then min:=Y else min:=X; end; procedure Inter(P,Q:Int;var R:Int); begin minS(P.hi,Q.hi,R.hi); maxS(P.lo,Q.lo,R.lo); end; function CheckHi(X:Sreal):boolean; var OK:boolean; begin OK:=true; with X do begin case cardinality of infinite: if (exp=Maxexp)and(mantissa=Maxinf) then else writeln('**Invalid hi infinity'); finite: begin if (mantissa=Maxinf) or (mantissa=Mininf) then begin OK:=false; writeln('**Invalid finite value - hi'); end; if mantissa = 0 then if (exp=0) then else begin OK:=false; writeln('**Invalid zero - hi') end else begin if (mantissa > 0) then if mantissa >= (Maxinf div 10) then {OK} else begin OK:=false; writeln('**Incorrect normalization - hi') end else{mantissa<0} if mantissa > (Mininf div 10) then begin OK:=false; writeln('**Incorrect normalization - hi') end; end; end; end;{case} if not (edge in [hin,hout]) then begin OK:=false; writeln('**hi edge value incorrect'); end; end; CheckHi:=OK; end;{CheckHi} function CheckLo(X:Sreal):boolean; var OK:boolean; begin OK:=true; with X do begin case cardinality of infinite: if (exp=Maxexp)and(mantissa=Mininf) then else writeln('**Invalid lo infinity'); finite: begin if (mantissa=Maxinf) or (mantissa=Mininf) then begin OK:=false; writeln('**Invalid finite value - hi'); end; if mantissa = 0 then if (exp=0) then else begin OK:=false; writeln('**Invalid zero - lo') end else begin if (mantissa > 0) then if mantissa >= (Maxinf div 10) then{OK} else begin OK:=false; writeln('**Incorrect normalization - lo') end else{mantissa<0} if mantissa > (Mininf div 10) then begin OK:=false; writeln('**Incorrect normalization - lo') end; end; end; end;{case} if not (edge in [lin,lout]) then begin OK:=false; writeln('**lo edge value incorrect'); end; end; CheckLo:=OK; end;{CheckLo} function CheckInt(I:Int):boolean; var OK:boolean; begin OK:=CheckHi(I.hi) and CheckLo(I.lo); if gtS(I.lo,I.hi) then begin OK:=false; writeln('**Limits out of order'); end; if not OK then begin writeln('**Error in Check'); DumpInt(I); end; CheckInt:=OK; end; procedure DumpMem(var DCurr:DataMem); var tD:Ptr; tL:Loc; begin with DCurr do begin writeln('LastHalve:',LastHalve:0); for tL:= 1 to End do writeln(tL:3,S[tL]:2,RHalve[tL]); writeln; for tD:= 1 to MaxDMem do begin write(tD:5); DumpInt(D[tD]); assert(CheckInt(D[tD])); writeln; end; writeln; end; end;{DumpMem} procedure WriteMem(var DCurr:DataMem); var tD:Ptr; begin with DCurr do begin for tD:= 1 to MaxDMem do if (DF.PF[tD] > PNull) or (Debug > activity) then begin write(tD:5); WriteInt(D[tD]); writeln; end; writeln; end; end;{WriteMem} procedure OuterExec (PC:Loc0;DCurr:DataMem;Change:boolean;First:State; var OldCounter:Positive;Level:Positive); var Counter:Positive; Fail,AllPoints,LocalChange:boolean; procedure NewOuter(F:State); begin OuterExec(PC,DCurr,Change,F,Counter,Level+1); end; {!!} procedure execprint(PC:Loc; L:Ptr; R0:Int); begin DF.PF[L]:=PSoln; writeln; write(PC:3,L:5); WriteInt(R0); writeln; end; procedure execpr(var Sr:State; L:Ptr); begin Sr:=-1; DF.PF[L]:=PPrint; end;{execpr} procedure exectr(var Sr:State; L:Ptr); begin Sr:=-1; DF.PF[L]:=PTrace; end;{exectr} procedure execsoln(var Sr:State; L:Ptr); begin Sr:=-1; DF.PF[L]:=PSoln; end;{execsoln} procedure execreadr(var Sr:State;var R0:Int); begin writeln; write('<<'); ReadInt(R0); Sr:=-1; end; function GetReal(E,M:integer):real; {convert E-exponent,M-mantissa into genuine Pascal real number} var x:real; begin x:=M/Maxinf; while E>0 do begin x:=x*10; E:=E-1; end; while E<0 do begin x:=x/10; E:=E+1; end; GetReal:=x; end;{GetReal} procedure Ratio(Lo,Hi:Sreal;var ERat,MRat:integer); {compute ratio of Hi to Lo in exponent mantissa form} begin if Lo.mantissa=0 then begin{treat zero as if smallest possible positive number} ERat:=Hi.exp-Minexp; MRat:=Hi.mantissa*10; end else if Hi.mantissa=0 then begin{treat zero as if smallest possible negative number} ERat:=Minexp-Lo.exp; MRat:=Lo.mantissa*10; end else begin ERat:=Hi.exp-Lo.exp; MRat:=(Hi.mantissa*Maxinf) div Lo.mantissa; end; end;{Ratio} function Adjacent(X:Int):boolean; {are hi and lo bounds adjacent points} begin with X do if (hi.mantissa=0) or (lo.mantissa=0) then Adjacent:= ((hi.mantissa=0)and(lo.mantissa=Mininf div 10)and(lo.exp=Minexp)) or ((lo.mantissa=0)and(hi.mantissa=Maxinf div 10)and(hi.exp=Minexp)) else Adjacent:= ((lo.exp=hi.exp)and(lo.mantissa+1=hi.mantissa)) or ((hi.exp=lo.exp+1)and(hi.mantissa=(lo.mantissa div 10)+1)) or ((hi.exp=lo.exp-1)and((hi.mantissa div 10)-1=lo.mantissa)); end;{Adjacent} procedure exechalve (var PC:Loc0;var Sr:State;var R0:Int;var OK:boolean;var Change:boolean); {Reduce range of R0 (suceeds twice for two 'halves')} var EDiff,MDiff,ERat,MRat,MidE,MidM,M0,M1,HiM,HiE:integer; Dummy:boolean; Mid:Sreal; R,D:real; OldPC:Loc; procedure AtEnd;{What to do afer a successful halve} begin DCurr.LastHalve:=PC; PC:=0; Sr:=0; end; begin{exechalve} OldPC:=PC; with R0 do begin if DCurr.LastHalve >= PC then {not our turn yet} else if (lo.mantissa = hi.mantissa) and (lo.exp=hi.exp) and (lo.edge=lin) and (hi.edge=hin) then {single point cant be divided} Sr:=-1 else if Adjacent(R0) and (((lo.edge=lout) and (hi.edge=hout)) or ((lo.cardinality=infinite)and(hi.edge=hout)) or ((hi.cardinality=infinite)and(lo.edge=lout)) ) then Sr:=-1 else if Sr=0 then begin AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; D:=GetReal(EDiff,MDiff); if D < DCurr.RHalve[PC]*HalveThreshold then {already narrowed enough dont bother} Change:=true {otherwise can terminate too early} else begin DCurr.RHalve[PC]:=D; NewOuter(1); NewOuter(2); OK:=false;{fail after both alternatives tried} end end else{Sr=1,2} if Adjacent(R0) then begin{two adjacent points - needs special care} if (hi.edge=hin) and (hi.cardinality=finite) then begin case Sr of 1:hi.edge:=hout; 2:begin lo:=hi; lo.edge:=lin; end; end; AtEnd; end else if (lo.edge=lin) and (lo.cardinality=finite) then begin case Sr of 1:begin hi:=lo; hi.edge:=hin; end; 2:lo.edge:=lout; end; AtEnd; end else {cant be narrowed} Sr:=-1; end{adjacent} else begin if (lo.mantissa < 0) and (hi.mantissa > 0) then begin MidM:=0; MidE:=0; end else begin Ratio(lo,hi,ERat,MRat); if MRat < 0 then MRat:=-MRat; R:=GetReal(ERat,MRat); (*writeln(ERat,MRat,R);*) AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; if (R > 4) or (R < 0.25) then begin{divide hi by sqrt of ratio to get midpoint} if hi.mantissa = 0 then begin HiM:=Mininf div 10; HiE:=Minexp; end else begin HiM:=hi.mantissa; HiE:=hi.exp; end; if ERat < 0 then MidE:=HiE-((ERat-1) div 2) else MidE:=HiE-(ERat div 2); if odd(ERat) then MidM:=trunc(HiM*(Maxinf div 100)/sqrt(MRat*10)) else MidM:=trunc(HiM*(Maxinf div 100)/sqrt(MRat)); (*writeln(MidE,MidM);*) end else begin{take (hi+lo)/2 as midpoint} MidM:=MDiff div 2 - M1; MidE:=EDiff; end; end; if MidM >= 0 then NormalizeDn(MidE,MidM,Mid,Dummy) else NormalizeUp(MidE,MidM,Mid,Dummy); case Sr of 1:begin hi:=Mid; hi.edge:=hout; end; 2:begin lo:=Mid; lo.edge:=lin; end; end; (*DumpInt(R0);writeln;*) AtEnd; end;{if Sr} AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; DCurr.RHalve[OldPC]:=GetReal(EDiff,MDiff); end;{with} end;{exechalve} procedure exechalves (var PC:Loc0;var Sr:State;var R0:Int;var OK:boolean;var Change:boolean); {Reduce range of R0 (suceeds twice for two 'halves')} {Simple version thats averages exponents} var EDiff,MDiff,ERat,MRat,MidE,MidM,M0,M1,HiM,HiE:integer; Dummy:boolean; Mid:Sreal; R,D:real; OldPC:Loc; procedure AtEnd;{What to do afer a successful halve} begin DCurr.LastHalve:=PC; PC:=0; Sr:=0; end; procedure Average(Lo,Hi:Sreal;var Exp:integer); {compute average of exponents allowing for zero} {infinities happen to work because of representation} var Le,He:integer; begin if Lo.mantissa = 0 then Le := Minexp else Le := Lo.exp; if Hi.mantissa = 0 then He := Minexp else He := Hi.exp; Exp:= (He + Le - 2*Minexp) div 2 + Minexp; writeln(Exp,Hi.exp,Lo.exp,Minexp,He,Le); end;{Average} begin{exechalves} OldPC:=PC; with R0 do begin if DCurr.LastHalve >= PC then {not our turn yet} else if (lo.mantissa = hi.mantissa) and (lo.exp=hi.exp) and (lo.edge=lin) and (hi.edge=hin) then {single point cant be divided} Sr:=-1 else if Adjacent(R0) and (((lo.edge=lout) and (hi.edge=hout)) or ((lo.cardinality=infinite)and(hi.edge=hout)) or ((hi.cardinality=infinite)and(lo.edge=lout)) ) then Sr:=-1 else if Sr=0 then begin AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; D:=GetReal(EDiff,MDiff); if D < DCurr.RHalve[PC]*HalveThreshold then {already narrowed enough dont bother} Change:=true {otherwise can terminate too early} else begin DCurr.RHalve[PC]:=D; NewOuter(1); NewOuter(2); OK:=false;{fail after both alternatives tried} end end else{Sr=1,2} if Adjacent(R0) then begin{two adjacent points - needs special care} if (hi.edge=hin) and (hi.cardinality=finite) then begin case Sr of 1:hi.edge:=hout; 2:begin lo:=hi; lo.edge:=lin; end; end; AtEnd; end else if (lo.edge=lin) and (lo.cardinality=finite) then begin case Sr of 1:begin hi:=lo; hi.edge:=hin; end; 2:lo.edge:=lout; end; AtEnd; end else {cant be narrowed} Sr:=-1; end{adjacent} else begin if (lo.mantissa < 0) and (hi.mantissa > 0) then begin MidM:=0; MidE:=0; end else begin Ratio(lo,hi,ERat,MRat); (*writeln(ERat,MRat,R);*) AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; if (ERat > 1) or (ERat < -1) then begin{Average exponents} if hi.mantissa <= 0 then begin MidM:= -Splitman; end else begin MidM:= Splitman; assert(lo.mantissa >= 0); end; Average(lo,hi,MidE); end else begin{take (hi+lo)/2 as midpoint} MidM:=MDiff div 2 - M1; MidE:=EDiff; end; end; if MidM >= 0 then NormalizeDn(MidE,MidM,Mid,Dummy) else NormalizeUp(MidE,MidM,Mid,Dummy); case Sr of 1:begin lo:=Mid; lo.edge:=lin; end; 2:begin hi:=Mid; hi.edge:=hout; end; end; (*DumpInt(R0);writeln;*) AtEnd; end;{if Sr} AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; DCurr.RHalve[OldPC]:=GetReal(EDiff,MDiff); end;{with} end;{exechalves} procedure execlinh (var PC:Loc0;var Sr:State;var R0:Int;var OK:boolean;var Change:boolean); {Reduce range of R0 (suceeds twice for two 'halves')} var EDiff,MDiff,MidE,MidM,M0,M1:integer; Dummy:boolean; Mid:Sreal; D:real; OldPC:Loc; procedure AtEnd;{What to do afer a successful halve} begin DCurr.LastHalve:=PC; PC:=0; Sr:=0; end; begin{execlinh} OldPC:=PC; with R0 do begin if DCurr.LastHalve >= PC then {not our turn yet} else if (lo.mantissa = hi.mantissa) and (lo.exp=hi.exp) and (lo.edge=lin) and (hi.edge=hin) then {single point cant be divided} Sr:=-1 else if Adjacent(R0) and (((lo.edge=lout) and (hi.edge=hout)) or ((lo.cardinality=infinite)and(hi.edge=hout)) or ((hi.cardinality=infinite)and(lo.edge=lout)) ) then Sr:=-1 else if Sr=0 then begin AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; D:=GetReal(EDiff,MDiff); if D < DCurr.RHalve[PC]*HalveThreshold then {already narrowed enough dont bother} Change:=true {otherwise possible to terminate early} else begin DCurr.RHalve[PC]:=D; NewOuter(1); NewOuter(2); OK:=false;{fail after both alternatives tried} end end else{Sr=1,2} if Adjacent(R0) then begin{two adjacent points - needs special care} if (hi.edge=hin) and (hi.cardinality=finite) then begin case Sr of 1:begin lo:=hi; lo.edge:=lin; end; 2:hi.edge:=hout; end; AtEnd; end else if (lo.edge=lin) and (lo.cardinality=finite) then begin case Sr of 1:lo.edge:=lout; 2:begin hi:=lo; hi.edge:=hin; end; end; AtEnd; end else {cant be narrowed} Sr:=-1; end{adjacent} else begin if (lo.mantissa < 0) and (hi.mantissa > 0) then begin MidM:=0; MidE:=0; end else begin AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; MidM:=MDiff div 2 - M1; MidE:=EDiff; end; if MidM >= 0 then NormalizeDn(MidE,MidM,Mid,Dummy) else NormalizeUp(MidE,MidM,Mid,Dummy); case Sr of 1:begin lo:=Mid; lo.edge:=lin; end; 2:begin hi:=Mid; hi.edge:=hout; end; end; AtEnd; end;{if Sr} AlignUp(hi.exp,hi.mantissa,lo.exp,-lo.mantissa,EDiff,M0,M1,Dummy); MDiff:=M0+M1; DCurr.RHalve[OldPC]:=GetReal(EDiff,MDiff); end;{with} end;{execlinh} procedure execmult(var Sr:State;T0,T1,T2:Int;var R0,R1,R2:Int;var OK:boolean); var Q0,Q1,Q2:Int; procedure multS(S0,S1:Sreal;var U,D:Sreal); var M,E:integer; Closed,Clu,Cld:boolean; begin M:=S0.mantissa*S1.mantissa; (*DumpS(S0);write('//');DumpS(S1);write(M);*) Closed:=(S0.edge in [hin,lin]) and (S1.edge in [hin,lin]); if ((S0.mantissa=0) and (S0.edge in [hin,lin])) or ((S1.mantissa=0) and (S1.edge in [hin,lin])) then Closed:=true; Clu:=Closed; Cld:=Closed; if (S0.cardinality=infinite) or (S1.cardinality=infinite) then begin if M < 0 then begin D:=MinusInfS; U:=MinusInfS; end else if M > 0 then begin D:=PlusInfS; U:=PlusInfS; end else begin {M=0} D:=ZeroS; U:=ZeroS; end; Closed:=((S0.cardinality=infinite)and(S0.edge in [hin,lin]))or ((S1.cardinality=infinite)and(S1.edge in [hin,lin])); Clu:=Closed;Cld:=Closed; end else{everybody finite} begin E:=S0.exp+S1.exp-Digits; NormalizeUp(E,M,U,Clu); NormalizeDn(E,M,D,Cld); end; if Clu then U.edge:=hin else U.edge:=hout; if Cld then D.edge:=lin else D.edge:=lout; (*writeln(E);DumpS(U);write('::');DumpS(D);writeln;*) end;{multS} procedure mult(Ta,Tb:Int;var R:Int); var U0,U1,U2,U3,U4,U5,D0,D1,D2,D3,D4,D5:Sreal; begin multS(Ta.hi,Tb.hi,U0,D0); multS(Ta.hi,Tb.lo,U1,D1); multS(Ta.lo,Tb.hi,U2,D2); multS(Ta.lo,Tb.lo,U3,D3); maxS(U0,U1,U4);maxS(U2,U3,U5);maxS(U4,U5,R.hi); minS(D0,D1,D4);minS(D2,D3,D5);minS(D4,D5,R.lo); end; procedure InvS(S:Sreal;var W:Sreal); var E,M,Rem:integer; Closed:boolean; begin Closed:= S.edge in [hin,lin]; if (S.cardinality = infinite) then W:=ZeroS else if (S.mantissa = 0) then case S.edge of hin,hout:W:=MinusInfS; lin,lout:W:=PlusInfS; end else begin M:=(Maxinf*Maxinf) div S.mantissa; Rem:=(Maxinf*Maxinf) mod S.mantissa; if Rem < 0 then halt; E:=-S.exp; case S.edge of lin,lout: begin if (Rem > 0) and (M > 0) then begin M:=M+1;Closed:=false; end; NormalizeUp(E,M,W,Closed); end; hin,hout: begin if (Rem > 0) and (M < 0) then begin M:=M-1;Closed:=false; end; NormalizeDn(E,M,W,Closed); end; end; end; if Closed then case S.edge of hin:W.edge:=lin; lin:W.edge:=hin; end else case S.edge of hin,hout:W.edge:=lout; lin,lout:W.edge:=hout; end; end;{InvS} procedure Inv(T:Int;var X:Int;Pos:boolean); {1/T positive -> X} {If 1/T splits to two intervals then use Pos to select which to use} begin if (T.lo.mantissa < 0) and (T.hi.mantissa > 0) then if (T.lo.cardinality=infinite) and (T.hi.cardinality=infinite) then X:=All else if Pos then begin InvS(T.hi,X.lo); X.hi:=PlusInfS; X.hi.edge:=hin; end else begin InvS(T.lo,X.hi); X.lo:=MinusInfS; X.lo.edge:=lin; end else begin InvS(T.hi,X.lo); InvS(T.lo,X.hi); end; end;{Inv} procedure divi(Ta,Tb:Int;var R:Int); var X:Int; begin if (Tb.lo.mantissa < 0) and (Tb.hi.mantissa > 0) then if (Ta.lo.mantissa < 0) and (Ta.hi.mantissa > 0) then { need do nothing as R will be set to [inf,inf]} else begin {if both same sign get positive side of inverse} {else get negative} Inv(Tb,X,(Ta.hi.mantissa <= 0) = (R.hi.mantissa <= 0)); mult(Ta,X,R); end else {Tb wont give split inverse} begin Inv(Tb,X,true); mult(Ta,X,R); end; (* DumpInt(Tb);writeln('//');DumpInt(X);writeln; DumpInt(Ta);writeln('\\');DumpInt(R);writeln; *) end; function Split(T:Int):boolean; begin Split:=(T.lo.mantissa<0) and (T.hi.mantissa>0) and ((T.lo.cardinality=finite) or (T.hi.cardinality=finite)); end;{Split} function Zin(T:Int):boolean; {check if 0 in range of interval} begin if (T.lo.mantissa > 0) then Zin:=false else if (T.lo.mantissa = 0) then Zin:=(T.lo.edge=lin) else if (T.hi.mantissa < 0) then Zin:=false else if (T.hi.mantissa = 0) then Zin:=(T.hi.edge=hin) else Zin:=true; end;{Zin} begin{execmult} case Sr of 0,10:begin if T2=Zero then if (T1=Zero) or (T0=Zero) then Sr:=-1 else if not Zin(T0) then begin R1:=Zero; Sr:=-1; end else if not Zin(T1) then begin R0:=Zero; Sr:=-1; end else begin NewOuter(11); NewOuter(12);OK:=false; end else if (Sr=0) then begin if (T0.hi.mantissa > 0) and (T0.lo.mantissa < 0) and Split(T1) then begin NewOuter(1); NewOuter(2); OK:=false; end else if (T1.hi.mantissa > 0) and (T1.lo.mantissa < 0) and Split(T0) then begin NewOuter(3); NewOuter(4); OK:=false; end; end; end; 1:begin R0.lo:=ZeroS; R0.lo.edge:=lin; T0:=R0; Sr:=10; end; 2:begin R0.hi:=ZeroS; R0.hi.edge:=hout; T0:=R0; Sr:=10; end; 3:begin R1.lo:=ZeroS; R1.lo.edge:=lin; T1:=R1; Sr:=10; end; 4:begin R1.hi:=ZeroS; R1.hi.edge:=hout; T1:=R1; Sr:=10; end; 11:begin R0:=Zero; Sr:=-1; end; 12:begin R1:=Zero; Sr:=-1; end; end; if OK and (Sr<>-1) then begin mult(T0,T1,Q2); Inter(R2,Q2,R2); Q1:=R1; divi(T2,T0,Q1); Inter(R1,Q1,R1); Q0:=R0; divi(T2,T1,Q0); Inter(R0,Q0,R0); Sr:=10; end; end;{execmult} procedure execadd(T0,T1,T2:Int;var R0,R1,R2:Int); procedure addhi(S0,S1:Sreal; var S2:Sreal); var Closed:boolean; Exp,M0,M1:integer; begin{addhi} with S2 do begin if (S0.cardinality=infinite)or(S1.cardinality=infinite) then begin S2:=PlusInfS; Closed:=((S0.cardinality=infinite)and(S0.edge=hin))or ((S1.cardinality=infinite)and(S1.edge=hin)); end else begin Closed:=(S0.edge=hin)and(S1.edge=hin); AlignUp(S0.exp,S0.mantissa,S1.exp,S1.mantissa,Exp,M0,M1,Closed); NormalizeUp(Exp,M0+M1,S2,Closed) end; if Closed then S2.edge:=hin else S2.edge:=hout; end; end;{addhi} procedure addlo(S0,S1:Sreal; var S2:Sreal); var Closed:boolean; Exp,M0,M1:integer; begin{addlo} with S2 do begin if (S0.cardinality=infinite)or(S1.cardinality=infinite) then begin S2:=MinusInfS; Closed:=((S0.cardinality=infinite)and(S0.edge=lin))or ((S1.cardinality=infinite)and(S1.edge=lin)); end else begin Closed:=(S0.edge=lin)and(S1.edge=lin); AlignUp(S0.exp,-S0.mantissa,S1.exp,-S1.mantissa,Exp,M0,M1,Closed); NormalizeUp(Exp,M0+M1,S2,Closed); mantissa:=-mantissa; end; if Closed then S2.edge:=lin else S2.edge:=lout; end; end;{addlo} procedure subhi(S0,S1:Sreal; var S2:Sreal); var Closed:boolean; Exp,M0,M1:integer; begin{subhi} with S2 do begin if (S0.cardinality=infinite)or(S1.cardinality=infinite) then begin S2:=PlusInfS; Closed:=((S0.cardinality=infinite)and(S0.edge=hin))or ((S1.cardinality=infinite)and(S1.edge=lin)); end else begin Closed:=(S0.edge=hin)and(S1.edge=lin); AlignUp(S0.exp,S0.mantissa,S1.exp,-S1.mantissa,Exp,M0,M1,Closed); NormalizeUp(Exp,M0+M1,S2,Closed); end; if Closed then S2.edge:=hin else S2.edge:=hout; end; end;{subhi} procedure sublo(S0,S1:Sreal; var S2:Sreal); var Closed:boolean; Exp,M0,M1:integer; begin{sublo} with S2 do begin if (S0.cardinality=infinite)or(S1.cardinality=infinite) then begin S2:=MinusInfS; Closed:=((S0.cardinality=infinite)and(S0.edge=lin))or ((S1.cardinality=infinite)and(S1.edge=hin)); end else begin Closed:=(S0.edge=lin)and(S1.edge=hin); AlignUp(S0.exp,-S0.mantissa,S1.exp,S1.mantissa,Exp,M0,M1,Closed); NormalizeUp(Exp,M0+M1,S2,Closed);mantissa:=-mantissa; end; if Closed then S2.edge:=lin else S2.edge:=lout; end; end;{sublo} begin{execadd} addhi(T0.hi,T1.hi,R2.hi); addlo(T0.lo,T1.lo,R2.lo); subhi(T2.hi,T0.lo,R1.hi); sublo(T2.lo,T0.hi,R1.lo); subhi(T2.hi,T1.lo,R0.hi); sublo(T2.lo,T1.hi,R0.lo); end;{execadd} procedure execintgr(var Sr:State; var R:Int); procedure floor (var R : Sreal); var sign , dum : boolean ; E, M ,t : integer ; begin sign := false ; with R do begin if (mantissa < 0) then begin sign := true ; mantissa := - mantissa ; end ; if (exp <= 0) then begin if sign or ((mantissa = 0) & (edge = hout)) then begin M := 1 ; sign := true ; end else M := 0 ; E := Digits ; NormalizeUp (E,M,R,dum) ; edge := hin ; end else {exp >0} if (exp <= Digits) then begin M := 1 ; E := exp ; while (E < Digits) do begin M := M * 10 ; E := E + 1 ; end ; t := mantissa mod M ; M := mantissa div M ; if (sign & ((edge = hout) or(t > 0))) then M := M + 1 ; if (not sign & (t = 0)) & (edge = hout) then M := M - 1 ; E := Digits ; NormalizeUp (E,M,R,dum) ; edge := hin ; end else if ((edge = hout)&(exp = (Digits+1))) & (not sign & (mantissa = Splitman)) then begin mantissa := Maxman ; exp := Digits ; edge := hin ; end ; if sign then mantissa := - mantissa ; end ;{with R} end ; {floor} procedure ceiling (var R : Sreal); var sign , dum : boolean ; E, M , t : integer ; begin sign := false ; with R do begin if (mantissa < 0) then begin sign := true ; mantissa := - mantissa ; end ; if (exp <= 0) then begin if sign or ((mantissa = 0) & (edge = lin)) then M := 0 else M := 1 ; E := Digits ; NormalizeDn (E,M,R,dum) ; edge := lin ; end else {exp > 0} if (exp <= Digits) then begin M := 1 ; E := exp ; while (E < Digits) do begin M := M * 10 ; E := E + 1 ; end ; t := mantissa mod M ; M := mantissa div M ; if ( not sign & ((edge = lout) or(t > 0))) then M := M + 1 ; if (sign & (t = 0)) & (edge = lout) then M := M - 1 ; E := Digits ; NormalizeDn (E,M,R,dum) ; edge := lin ; end else if ((edge = lout)&(exp = (Digits+1))) & (sign & (mantissa = Splitman)) then begin mantissa := Maxman ; exp := Digits ; edge := lin ; end ; if sign then mantissa := - mantissa ; end ;{with R} end ; {ceiling} begin with R do begin (* writeln ('IN EXECINTGR :') ; writeln ; writeln ('HI : ', hi.mantissa , hi.exp) ; writeln ; writeln ('LO : ', lo.mantissa , lo.exp) ; writeln ; *) if (hi.cardinality <> infinite) then floor (hi) ; if (lo.cardinality <> infinite) then ceiling (lo) ; if ((hi.mantissa = lo.mantissa) & (hi.exp = lo.exp)) then Sr := - 1 ; (* writeln ('OUT EXECINTGR :') ; writeln ; writeln ('HI : ', hi.mantissa , hi.exp) ; writeln ; writeln ('LO : ', lo.mantissa , lo.exp) ; writeln ; *) end ; end;{execintgr} procedure execlb (R1 : Int ; var R : Int) ; begin R := R1 ; with R.lo do if (cardinality = infinite) then R.hi := MinusFiniteS else R.hi := R.lo ; R.hi.edge := hin ; R.lo := MinusInfS ; end ; procedure execub (var X , Xd : Int) ; var Dum : Int ; begin Xd := X ; execadd (Xd, Dum, Zero, Dum, Xd, Dum) ; execlb (Xd,Xd) ; execadd (Xd, Dum, Zero, Dum, Xd, Dum) ; end ; procedure execcopy (R0 :Int; var R1:Int); begin R1:=R0; end; procedure execless(var Sr:State; var R0,R1:Int); {R0 < R1} begin if Point(R0) or Point(R1) then Sr:=-1; if gtS(R1.lo,R0.hi) then Sr:= -1 else begin R0.hi:=R1.hi; R0.hi.edge:=hout; R1.lo:=R0.lo; R1.lo.edge:=lout; end; end;{execless} procedure execleq(var Sr:State; var R0,R1:Int); {R0 =< R1} begin if Point(R0) or Point(R1) then Sr:=-1; if geS(R1.lo,R0.hi) then Sr:= -1 else begin R0.hi:=R1.hi; R1.lo:=R0.lo; end; end;{execleq} procedure execnoteq(var Sr:State; var R0,R1:Int); {R0 <> R1} begin case Sr of 0:{nothing done yet} begin if gtS(R0.lo,R1.hi) or gtS(R1.lo,R0.hi) then Sr:=-1 {no need to check in future} else begin if Point(R0) then begin OuterExec(PC,DCurr,true,1,Counter,Level+1); Sr:=2; execless(Sr,R1,R0); end else if Point(R1) then begin OuterExec(PC,DCurr,true,2,Counter,Level+1); Sr:=1; execless(Sr,R0,R1); end; end; end; 1:execless(Sr,R0,R1); 2:execless(Sr,R1,R0); end; end;{execnoteq} procedure execsqrr(var R0,R1:Int); begin{execsqrr} end;{execsqrr} procedure execminr(var R0,R1,R2:Int); begin{execminr} end;{execminr} procedure execmaxr(var R0,R1,R2:Int); procedure chmaxhi(S0,S1:Sreal; var S2:Sreal); var Closed:boolean; Exp,M0,M1:integer; begin{chmaxhi} with S2 do begin if (S0.cardinality=infinite)or(S1.cardinality=infinite) then begin S2:=PlusInfS; Closed:=((S0.cardinality=infinite)and(S0.edge=hin))or ((S1.cardinality=infinite)and(S1.edge=hin)); end else begin Closed:=(S0.edge=hin)and(S1.edge=hin); AlignUp(S0.exp,S0.mantissa,S1.exp,S1.mantissa,Exp,M0,M1,Closed); if M1 > M0 then M0 := M1 ; NormalizeUp(Exp,M0,S2,Closed) end; if Closed then S2.edge:=hin else S2.edge:=hout; end; end;{chmaxhi} procedure chmaxlo(S0,S1:Sreal; var S2:Sreal); var Closed:boolean; Exp,M0,M1:integer; begin{chmaxlo} with S2 do begin if (S0.cardinality=infinite)or(S1.cardinality=infinite) then begin S2:=MinusInfS; Closed:=((S0.cardinality=infinite)and(S0.edge=lin))or ((S1.cardinality=infinite)and(S1.edge=lin)); end else begin Closed:=(S0.edge=lin)and(S1.edge=lin); AlignUp(S0.exp,-S0.mantissa,S1.exp,-S1.mantissa,Exp,M0,M1,Closed); NormalizeUp(Exp,M0+M1,S2,Closed); mantissa:=-mantissa; end; if Closed then S2.edge:=lin else S2.edge:=lout; end; end;{addlo} begin{execmaxr} end;{execmaxr} procedure execmodu(var R0,R1,R2:Int); begin{execmodu} end;{execmodu} procedure execabsr(var R0,R1:Int); begin{execabsr} end;{execabsr} procedure exectrig(var R0,R1,R2:Int); begin{exectrig} end;{exectrig} procedure execexpr(var R0,R1:Int); begin{execexpr} end;{execexpr} function Exec(I:Instr;var PC:Loc0;var Change:boolean):boolean; var R:array[0..Par] of Int; {working registers} Sr:State; {State register} P:0..Par; E:boolean; NewPC:Loc0; TraceChange:boolean; procedure WritePars; {write out list of parameter registers for curr ins} begin with I do begin write(PC:2,Code:5,Sr:3); for P := 0 to Par do if Pars[P] <> 0 then begin write(Pars[P]:3); WriteInt(R[P]); end; writeln; end; end;{WritePars} begin{Exec} with I,DCurr do begin Counter:=Counter+1; {get parameters} for P := 0 to ParN[Code] do begin R[P]:=D[Pars[P]]; assert(CheckInt(R[P])); end; Sr:=S[PC]; if Debug >= trace then begin write(' '); WritePars; end; E:=true; Change:=false; NewPC:=PC; {!!}case Code of print: execprint(PC,Pars[0],R[0]); pr : execpr(Sr,Pars[0]); tr : exectr(Sr,Pars[0]); soln : execsoln(Sr,Pars[0]); readr: execreadr(Sr,R[0]); halve: exechalve(NewPC,Sr,R[0],E,Change); halves:exechalves(NewPC,Sr,R[0],E,Change); linh : execlinh(NewPC,Sr,R[0],E,Change); mult : execmult (Sr,R[0],R[1],R[2],R[0],R[1],R[2],E); add : execadd (R[0],R[1],R[2],R[0],R[1],R[2]); intgr: execintgr(Sr,R[0]); less : execless (Sr,R[0],R[1]); leq : execleq (Sr,R[0],R[1]); noteq: execnoteq(Sr,R[0],R[1]); sqrr : execsqrr(R[0],R[1]); minr : execminr(R[0],R[1],R[2]); maxr : execmaxr(R[0],R[1],R[2]); modu : execmodu(R[0],R[1],R[2]); absr : execabsr(R[0],R[1]); trig : exectrig(R[0],R[1],R[2]); expr : execexpr(R[0],R[1]); lb : execlb (R[0],R[1]); ub : execub (R[0],R[1]); copy : execcopy(R[0],R[1]); end; TraceChange:=false; AllPoints:=true; for P := 0 to ParN[Code] do with D[Pars[P]] do begin if DF.PF[Pars[P]]=PPrint then TraceChange:=true; assert(CheckLo(R[P].lo));assert(CheckHi(R[P].hi)); if ParIntersect [Code] then begin maxS(R[P].lo,lo,R[P].lo); minS(R[P].hi,hi,R[P].hi); end ; if gtS(R[P].lo,R[P].hi) then begin E:=false; assert(CheckLo(R[P].lo));assert(CheckHi(R[P].hi)); end else begin if D[Pars[P]] <> R[P] then begin D[Pars[P]] := R[P]; Change:=true; if DF.PF[Pars[P]] = PTrace then TraceChange:=true; end; AllPoints:=AllPoints and Point(R[P]); assert(CheckInt(R[P])); assert(CheckInt(D[Pars[P]])); end; end; if (Debug=activity) and TraceChange then writeln; if (Debug >=activity) then begin if Change then write('*') else write ('.'); end; Exec:=E; if E then begin if AllPoints then Sr:=-1; if (Sr <> S[PC]) then begin S[PC]:=Sr; Change:=true; end; if (Debug=activity) and TraceChange then WritePars; if Debug >= post then WritePars; if Debug = dump then DumpMem(DCurr); end else if Debug >= activity then begin writeln('FAILED'); write(' '); WritePars; end; PC:=NewPC; end; end;{Exec} begin{OuterExec} writeln; writeln(Level:2,'Entering Count:',OldCounter:0); OldCounter:=0; Counter:=0; Fail:=false; if First <> 0 then DCurr.S[PC]:=First; {Run simulation until failure or nothing further to be done} repeat if (PC = End) then begin PC:=1; Change:=false; DCurr.LastHalve:=1; end; while (PC < End) and not Fail and not GlobalEnd do with I[PC] do begin if DCurr.S[PC] > -1 then begin Fail:=not Exec(I[PC],PC,LocalChange); Change:=Change or LocalChange; end; PC:=PC+1; end; until Fail or (not Change) or GlobalEnd; writeln; write(Level:2,'Exiting Count:',Counter:0); if not (Fail or GlobalEnd) then begin if (Cut=once) then GlobalEnd:=true; writeln('SOLUTION'); WriteMem(DCurr); end else writeln; end;{OuterExec} procedure Clear; var tL:Loc; tD,tDF:Ptr; tPar:1..Par; DI:1..Digits; J:1..Maxexp; MaxDiff:real; begin Shift[0]:=1; for DI:= 1 to Digits do Shift[DI]:=Shift[DI-1]*10; with PlusInfS do begin edge:=hin;cardinality:=infinite;mantissa:=Maxinf; exp:=Maxexp; end; with MinusInfS do begin edge:=lin;cardinality:=infinite;mantissa:=Mininf; exp:=Maxexp; end; with PlusFiniteS do begin edge:=hin;cardinality:=finite;mantissa:=Maxman; exp:=Maxexp; end; with MinusFiniteS do begin edge:=lin;cardinality:=finite;mantissa:=Minman; exp:=Maxexp; end; with ZeroS do begin exp:=0;mantissa:=0;edge:=hin;cardinality:=finite; end; with PlusSmallS do begin exp:=Minexp;mantissa:=Maxinf div 10; cardinality:=finite; end; with MinusSmallS do begin exp:=Minexp;mantissa:=Mininf div 10; cardinality:=finite; end; with Zero do begin lo:=ZeroS;lo.edge:=lin; hi:=ZeroS;hi.edge:=hin; end; with All do begin hi:=PlusInfS; lo:=MinusInfS; end; with AllFinite do begin lo:=MinusFiniteS; hi:=PlusFiniteS; end; with DF do begin for tDF:= 1 to DMem do PF[tDF]:=PNull; end; with DInit do begin for tD:= 1 to DMem do if Verifiable then D[tD]:=AllFinite else D[tD]:=All; LastHalve:=1; MaxDiff:=2; for J:=1 to Maxexp do MaxDiff:=MaxDiff*10; for tL := 1 to IMem do begin RHalve[tL]:=MaxDiff; S[tL]:=0; with I[tL] do for tPar := 1 to Par do Pars[tPar]:=0; end; {!!} ParN[print]:=0; ParN[pr]:=0; ParN[tr]:=0; ParN[soln]:=0; ParN[halve]:=0; ParN[halves]:=0; ParN[readr]:=0; ParN[linh]:=0; ParN[mult]:=2; ParN[add]:=2; ParN[intgr]:= 0; ParN[less]:= 1; ParN[leq]:= 1; ParN[noteq]:= 1; ParN[sqrr]:= 1; ParN[minr]:=2; ParN[maxr]:=2; ParN[modu]:= 1; ParN[absr]:= 1; ParN[trig]:=2; ParN[expr]:= 1; ParN[lb]:= 1; ParN[ub]:= 1; ParN[copy]:= 1; ParN[stop]:=-1; {!!} ParIntersect[print]:= true; ParIntersect[pr]:= true; ParIntersect[tr]:= true; ParIntersect[soln]:= true; ParIntersect[halve]:=true; ParIntersect[halves]:=true; ParIntersect[readr]:=true; ParIntersect[linh]:=true; ParIntersect[mult]:=true; ParIntersect[add]:=true; ParIntersect[intgr]:= true; ParIntersect[less]:= true; ParIntersect[leq]:= true; ParIntersect[noteq]:= true; ParIntersect[sqrr]:= true; ParIntersect[minr]:= true; ParIntersect[maxr]:= true; ParIntersect[modu]:= true; ParIntersect[absr]:= true; ParIntersect[trig]:= true; ParIntersect[expr]:= true; ParIntersect[lb]:= false; ParIntersect[ub]:= false; ParIntersect[stop]:= true; ParIntersect[copy]:= true; end; end;{Clear} procedure ReadInstr; var tP:0..Par; Op:OpType; tDat:Ptr; begin with DInit do begin End:=1; MaxDMem:=0; repeat with I[End] do begin read(Op); Code:=Op; for tP := 0 to ParN[Op] do with I[End] do begin read(tDat); Pars[tP]:=tDat; if tDat>MaxDMem then MaxDMem:=tDat; if MaxDMem > DMem then begin writeln('Too many variables');halt; end; end; readln; end; End:=End+1; if End >= IMem then begin writeln('Too many instructions');halt;end; until Op = stop; End:=End-1; while not eof do {read constant values for memory locations} begin read(tDat); if tDat > DMem then writeln('Variable out of range',tDat,DMem); ReadInt(D[tDat]); readln; end; end; end;{ReadInstr} begin GlobalEnd:=false; InitialOptions; readln(Cut); writeln(Cut); Clear; { set to initial values, read instructions} ReadInstr; if Debug = dump then begin DumpTables; DumpMem(DInit); end; if Debug >= activity then WriteMem(DInit); Dummy:=0; OuterExec(1,DInit,false,0,Dummy,0); if Debug = dump then DumpMem(DInit); end. Login: ian Password: Last login: Fri Aug 28 13:48:03 from vaxb This login: Fri Aug 28 14:18:21 from vaxb 4.3 BSD+NFS UNIX #25: Fri Aug 28 08:08:07 MDT 1987 There is a New version of the Verdix Ada compiler installed on Vaxc. All persons using this compiler please contact Terry as soon as possible. Also, if there is anyone using the nyu ada or telesoft ada compilers please let Terry know, we would like to remove them from the system, if they are not being used. (we need the disk space!) Thanks. The imagen is once again operational but with reduced capacity (one of the memory boards is being repaired). Large documents may not work. vaxb!ian ttyp4 Aug 28 14:18 (vaxb) Welcome to Freedman's Input Line Editor (FILE). Version: 87-01-11 Please wait until your shell prompt appears (ESC-? for help). hi, terminal is amb-xl You are already logged in somewhere Harold as adjunct??? -- and reply to his mail rlogin vaxb -8 | tee transcript? VAXB cd ~/courses/551cd ~/courses/551 VAXB lsls assignments core info.sheet~ topics~ assignments~ info.sheet topics VAXB roff -a2 assignments; lpq -Palw2&roff -a2 assignments; lpq -Palw2& [1] 6894 VAXB cd ../670cd ../670 VAXB lsls 601.synopsis 601.synopsis~ synopsis synopsis~ temp VAXB cp ../533/info.sheet .cp ../533/info.sheet . VAXB e info.sheete info.sheet [>52;54h[>30;37;38;39l[>52;54h[>30;37;38;39lLoading time...doneP`&~X4R\.pn 0 .ls1 .ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE .sp2 .ps+2 .ce CPSC 533 \(em Artificial Intelligence .ps-2 .sp3 .LB .NP .ul Instructor. Ian H Witten, MA\ 786, 220-6780 .sp .NP .ul Office hours. Mondays and Wednesdays 15.00-16.00 .sp .NP .ul Tutorial instructor. Dave Maulsby, MA\ 358, 220-7683 .sp .NP .ul Lectures. ST 130, Tuesdays and Thursdays 9.30-10.45 .sp .NP .ul Labs. L01: SS\ 202, Mondays and Wednesdays 9.00-9.50; L02: SB\ 144A, Tuesdays and Thursdays 11.00-11.50 .sp .NP .ul Course texts .sp Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .br Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp .NP .ul Assessment .ta \w'Midterm exam (in class time) 'u .sp Midterm exam (in class time) \015% .br Final exam \030% -----Emacs: info.sheet time and load (Text Fill)----Top-------------2:20pm 3.04[1] (Text Fill)----Topno entries vaxb: sending to vaxa Rank Owner Job Files Total Size 1st ian 286 (standard input) 25202 bytes [>52;54h[>30;37;38;39l.pn 0 .ls1 .ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE .sp2 .ps+2 .ce CPSC 533 \(em Artificial Intelligence .ps-2 .sp3 .LB .NP .ul Instructor. Ian H Witten, MA\ 786, 220-6780 .sp .NP .ul Office hours. Mondays and Wednesdays 15.00-16.00 .sp .NP .ul Tutorial instructor. Dave Maulsby, MA\ 358, 220-7683 .sp .NP .ul Lectures. ST 130, Tuesdays and Thursdays 9.30-10.45 .sp .NP .ul Labs. L01: SS\ 202, Mondays and Wednesdays 9.00-9.50; L02: SB\ 144A, Tuesdays and Thursdays 11.00-11.50 .sp .NP .ul Course texts .sp Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .br Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp .NP .ul Assessment .ta \w'Midterm exam (in class time) 'u .sp Midterm exam (in class time) \015% .br Final exam \030% -----Emacs: info.sheet 2:20pm 3.04[1] (Text Fill)----Top------------ [5`[2@67**[1@0    M[12`John H. Andreae[8`[15`, MA\ 7--**-Emacs: info.sheet 2:20pm 3.04[1] (Text Fill)----Top------------ pn 0 .ls1 .ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE sp2 .ps+2 .ce CPSC 670 \(em Artificial Intelligence ps-2 sp3 LB .NP ul Instructor. John H Andreae, MA\ 7 Ian H Witten, MA\ 786, 220-6780 sp .NP .ul Office hours. Mondays and Wednesdays 15.00-16.00 sp NP .ul Tutorial instructor. Dave Maulsby, MA\ 358, 220-7683 .sp NPFind file: ~/courses/670/1pm 2.65[31pm 2.65[3~/tempo[14`temporary/andreae3 The Department welcomes John Andreae, on sabbatical from the University of Canterbury, Christchurch, New Zealand. John is a Visiting Research Associate and will be with us until the end of November. He is New Zealand's foremost researcher in Artificial Intelligence, and has a long-standing international reputation for his seminal work on the foundations of learning and the simulation of learning mechanisms. He will be teaching the first part of CPSC 670, and working with John Cleary and Bruce MacDonald (whose PhD theses he supervised in New Zealand), Brian Gaines, David Hill, Ian Witten, and anyone else who is interested!  John's office is room 782, phone 7299. He and Molly Andreae are presently staying at the MacDonald/Stodart residence.                ---Emacs: andreae3 2:21pm 2.65[3] (Text Fill)----All82, [21` [1@ [27` 220-7299  Tuesdays and Thursdays 14.00-15.00 (both 2pm 2.36[12pm 2.36[1instructors)[36`[54`Mondays and Wednesdays 15.\.NP Mark set .ul Lectures. ST 130, Tuesdays and Thursdays 9.30-10.45 .sp .NP.ul Labs. L01: SS\ 202, Mondays and Wednesdays 9.00-9.50; L02: SB\ 144A, Tuesdays and Thursdays 11.00-11.50 .sp .NP .ul Course texts .sp Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .br Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp .NP .ul Assessment .ta \w'Midterm exam (in class time) 'u .sp Midterm exam (in class time) \015% .br Final exam \030% .br Assignment 1 \010% .br Assignment 2 \010% [3` [2@??[1@?[14` [28`[1@1[1@1[1@.[2@00[1@-[1@1[2@2.[2@15 Mark set .br Project: .br \0\0\0\0interim report \010% .br \0\0\0\0final report \025%3pm 3.10[3 NP ul Office hours. uesdays and Thursdays 14.00-15.00 (both instructors) .sp NP ul Lectures. ???, Tuesdays and Thursdays 11.00-12.15 sp NP ul Course texts sp Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). brFind file: ~/courses/670/Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp .NP .ul Assessment .ta \w'Midterm exam (in class time) 'u .sp Midterm exam (in class time) \015% --**-Emacs: info.sheet 2:23pm 3.10[3] (Text Fill)---- 2%------------ 2%synopsis pn 0 ls1 .ce2 HE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE sp2 ps+2 .ce CPSC 670 \(em Artificial Intelligence ps-2 sp3 For 1987-88, this course will take place in two parts: .LB ta \w'Winter 1988 'u +\w'Dr J.A. Andreae 'u Fall 1987 Dr J.H. Andreae Machine Learning .br Winter 1988 Dr I.H. Witten Artificial Intelligence LE The parts will be assessed separately, and the first will be available as a 601 course for students wishing to take it alone. (This organization reflects a current proposal to replace CPSC 670 by several half courses in future, including CPSC 675 ``Machine Learning'' and CPSC 671 ``Artificial Intelligence''.) \c Lectures will take place on Tuesdays and Thursdays, 9.30-10.45 am. .rh "Machine Learning." This will include the following topics: LB .NP ---Emacs: synopsis 2:23pm 3.10[3] (Text Fill)----TopLB NP Dimensions of classification of machine learning problems and systems .NP Theoretical foundations of inductive inference NP Similarity-based learning: the generalization-as-search paradigm and its implementations .NP Explanation-based learning and systems which embody it NP Exploration and discovery mechanisms, functional induction and theory formation NP Learning procedural knowledge .NP Cognitive aspects of human learning. .LE The text for this part will be .LB R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1986) \fIMachine learning Volume 2\fP. Morgan Kaufmann, Los Altos, CA. .LE Other relevant books include LB Forsyth, R. and Rada, R. (1986) ul Machine learning: applications in expert systems and information retrieval.23%4pm 2.57[14pm 2.57[1 MMMMMMark set Final exam \030% .br Assignment 1 \010% .br Assignment 2 \010% .br Project: .br \0\0\0\0interim report \010% .br \0\0\0\0final report \025% .br [4`[1@ [1@\[1@w[1@'[1@T[1@e[1@r[1@m[1@ [6`[1@w[1@'[1@W[3@int[2@er[1@ [2@Te[1@r[1@m[1@ [1@ [2@ [2@'u[1@ [1@+Auto-saving...done5pm 2.14[35pm 2.14[3Fall Term Assignment 7\(12%\7\(12%[34`07\(12%[35` Pro Mark set\0\0\0\0final report \025%.br TFinal exam[2`aFinal exam[3`keFinal exam[5`-hFinal ex[8@am [7`oFinal exam[8`meFinal exam[10` exam[10` 230%230%6pm 3.05[46pm 3.05[4\30%(30%130%230%0%%M  [27` [1@\[1@0  ____.br\h'-\w'total 'u'total\ \ 100%.spMM.sp.ta \w'Demonstrations 'uMark set.br Take-home exam \022\(12% ____  .br ____ MMM.spMMMMMM[8@  [8@   pinterim report[18`rointerim report \010%[20`ginterim report[21`reinterim report[23`ssinterim report report \010%  [8@ 7pm 3.01 Mail[2] (Text Fill)----23%7pm 3.01 Mail[2] (Text Fill)---- 2%[26`  \10%010%510%0%%%%1%2%\%(%1%2% .sp.ta \w'Demonstrations 'uMark set\0\0\0\0final report \012\(12% .br \0\0\0\0final report \012\(12% .br [11`  ifinal report[18`nfinal report[19`-final report[20`cfinal repor[8@t [21`lafinal report[23`ssfinal report final report[26`prfinal report[28`efinal repor[8@t [29`sfinal report[30`efinal report[31`ntatfinal report[35`ionfinal rep[8@ort [38` report[38` [1@\[1@0[1@2[1@\[1@( 12\(12%[50`2\(12%[50`\(12%[50`(12%12%2%% .spMMMM MM 8pm 2.878pm 2.87.br \h'-\w'total 'u'total\ \ 100% .sp .sp .ta \w'Demonstrations 'u .NP .ul Guest lectures. There may be guest lectures on topics such as: .LB .NP .ul L\s-2ISP\s+2 ``Flavors'' .NP .ul an advanced AI programming environment (eg KnowledgeCraft) .NP .ul an implementation of the ``version space'' concept learning technique .NP .ul the Japanese initiatives in new generation computing. .LE .NP .ul Demonstrations. It is hoped to arrange demonstrations of .LB .NP Mark set [8@  .ul NEXPERT expert system shellMark setFall Term Assignment \0\07\(12% .br Project: .br \0\0\0\0progress report \0\05% .br \0\0\0\0final report \012\(12% .br \0\0\0\0in-class presentation \0\02\(12% .br Take-home exam \022\(12% Fall Term Assignment \0\07\(12% .br Project: .br \0\0\0\0progress report \0\05% .br \0\0\0\0final report \012\(12% .br \0\0\0\0in-class presentation \0\02\(12% .br Take-home exam \022\(12% .sp MMMMMMMMMM.sp WFall Term[2`inFall Term[4`Auto-saving...doneterFall Term[7` Term [7`[12` CAssignment[18`lAssignment[19`aAssignment[20`sAssignment[21`sAssignment[22` Assignmen[8@t [23`pAssignment[24`reAssignment[26`sAssignment[27`eAssignment[28`nAssignment[29`tAssignment[30`aAssignmen[8@t [31`tioAssignment[34`nAssignment[35` s[43`  -home exam T-home exam[10`e-home exam[11`rm-home exam[13` -home exam[14`pa-home ex[8@am [16`per-home exam[19` exam[19` [19`9pm 2.12 Mail[1.ul Mark set an implementation of the ``version space'' concept learning technique .NP ul the Japanese initiatives in new generation computing. LE .NP .ul Demonstrations. It is hoped to arrange demonstrations of LB .NP ul NEXPERT expert system shell .NP ul Xerox L\s-2ISP\s+2 Machine NP .ul Loops programming environment (film). .LE NP .ul Facilities. VAXA LE .bp sh "About the course" .sp Winston's textbook is excellent and has been widely acclaimed. I think that in the main it is quite understandable, probably too easy. You should \fIstudy it carefully\fR (not just read it casually). Set aside some time each week. Do some of the exercises. The main function of the lectures is to take you through the text, providing additional explanation where necessary. There will not be time, however, to cover everything in lectures. p This is not a course on programming, and we will not be talking much about programming in lectures. However, by the end of the course all students are expected to have a working knowledge of the L\s-2ISP\s+2 language, and assignments and projects are to be done in L\s-2ISP\s+2. People well-educated in AI need to know the basics of \fIboth\fR P\s-2ROLOG\s+2 and L\s-2ISP\s+2. Each has strengths and weaknesses that it is important to understand, and can only be appreciated properly through experience. .pp Many students will have had some prior exposure to L\s-2ISP\s+2, and all are well versed in P\s-2ROLOG\s+2. You are expected to pick up L\s-2ISP\s+2 programming by yourself. You do \fInot\fR need to become expert in L\s-2ISP\s+2. There will be no exam questions involving tricky language details \(em at most you might have to read some code or discuss pros and cons of AI programming in L\s-2ISP\s+2 vs P\s-2ROLOG\s+2 vs P\s-2ASCAL\s+2. bp sh "Planned timetable"8bp sh "Planned timetable" .sp nf ta \w'beginning 'u +3i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u .ul Week Material covered Reading Deadlines ul beginning .sp \05 Jan Introduction; L\s-2ISP\s+2 AI Ch 1 Tue Assignment 1 set L\s-2ISP\s+2 Ch 1-4 sp 12 Jan Representations; blocks worlds AI Ch 2 Tue Assignment 2 set L\s-2ISP\s+2 Ch 4-7, 13 sp 19 Jan Constraints AI Ch 3 Tue Assignment 1 due .sp 26 Jan Searching AI Ch 4 Tue Assignment 2 due L\s-2ISP\s+2 Ch 11 .sp \02 Feb Control strategies; objects, Flavors AI Ch 5 Tue Project proposa\l due L\s-2ISP\s+2 Ch 16 .sp \09 Feb More on OOP (Prolog, Smalltalk) AI Ch 6 Rule-based systems L\s-2ISP\s+2 Ch 18 s 16 Feb \fI(reading week \(em no classes)\fR 23 Feb \(em Tue Mid-term exam More on rule-based systems .sp \02 Mar Logic and planning AI Ch 7 Tue Project interim report due .sp \09 Mar Knowledge representation; AI Ch 8 using frames; CD theory L\s-2ISP\s+2 Ch 22 .sp 16 Mar Understanding natural language AI Ch 9 L\s-2ISP\s+2 Ch 19-21 .sp 23 Mar Vision??? AI Ch 10 (L\s-2ISP\s+2 Ch 10?) .sp 30 Mar Concept learning AI Ch 11 Version-space technique .sp \06 Apr Learning rules AI Ch 12 Summary Fri Project final report due .sp ??? Apr Final exam (scheduled by Registrar) .fi .bp .sh "Bibliography" .sp Here is a representative selection of recent books on AI, with a bias towards practical aspects.20Assessment .ta \w'Winter Term 'u +\w'Midterm exam (in class time) 'u .sp Fall Term Assignment \0\07\(12% .br Project: .br \0\0\0\0progress report \0\05% .br \0\0\0\0final report \012\(12% .br \0\0\0\0in-class presentation \0\02\(12% .br Take-home exam \022\(12% .sp Winter Term Class presentations \0\07\(12% .br Project: .br \0\0\0\0progress report \0\05% .br \0\0\0\0final report \012\(12% .br \0\0\0\0in-class presentation \0\02\(12% .br Term paper \022\(12% .sp ____ .br \h'-\w'total 'u'total\ \ 100% 430pm 1.44Wrote /vaxb.userb/profs/ian/courses/670/info.sheetWinter Term Class prese[8@ntationserm paper ____ .br \h'-\w'total 'u'total\ \ 100% .bp .sh "Planned timetable" .sp .nf .ta \w'beginning 'u +3i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u .ul Week Material covered Reading Deadlines .ul beginning .sp \05 Jan Introduction; L\s-2ISP\s+2 AI Ch 1 Tue Assignment 1 set L\s-2ISP\s+2 Ch 1-4 .sp -----Emacs: info.sheet 2:30pm 1.44 Mail[1] (Text Fill)---- 6%----------Emacs: info.sheet 2:30pm 1.44 Mail[1] (Text Fill)---- 6Find file: ~/courses/670/../551/info.sheet .pn 0 ls1 .ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE sp2 .ps+2 ce CPSC 551 \(em Computer Graphics I ps-2 .sp3 LB .NP ul Instructor. Ian H Witten, MA\ 786, 220-6780p NP ul Office hours. Tuesdays and Thursdays 14.00-15.00 .sp NP .ul Tutorial assistants. Jeff Allan, MA\ 324, 220-7686, and Dave Maulsby, MA\ 358, 220-7683 .sp NP<2> 2:30pm 1.44 Mail[1] (Text Fill)----TopI-search: P ...[3`l ...a ...n ...n ...e ...d ... This is not a course on programming, and we will not be talking much about programming in lectures. However, by the end of the course all students are expected to have a working knowledge of the C programing language, and assignments and projects are to be coded in C. The text gives all examples in Pascal for pedagogical reasons only; part of the assignment work involves demonstrating your understanding of algorithms by recoding them.  is the principal modern graphics programming language in use today, and anyone well-educated in computer graphics need to know how to use it and to interface with programs written in it. You are expected to pick up C programming by yourself; the TA will be more than happy to help you with language constructs and points of syntax. bp .sh "Planned timetable" .sp nf ta \w'beginning 'u +2.5i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u Week Material covered Reading Deadlines .ul beginning sp \07 Sep Thu All assignments set .sp 14 Sep 21 Sep66%Mark set Mark set.sp 21 Sep .sp 28 Sep Tue Assignment 1 due .sp \05 Oct .sp 12 Oct Thu Assignment 2 due .sp 19 Oct Thu Test 1 .sp 26 Oct .sp \02 Nov Tue Assignment 3 duep \09 Nov Thu Reading days; no class sp 16 Nov Tue Test 2 .sp 23 Nov .sp 30 Nov .sp \07 Dec Tue Test 3 Thu Assignment 4 due fi Botfi                           L\s-2ISP\s+2 Ch 4-7, 13 .sp 19 Jan Constraints AI Ch 3 Tue Assignment 1 due .sp 26 Jan Searching AI Ch 4 Tue Assignment 2 due L\s-2ISP\s+2 Ch 11 .sp \02 Feb Control strategies; objects, Flavors AI Ch 5 Tue Project proposa\l due L\s-2ISP\s+2 Ch 16 .sp \09 Feb More on OOP (Prolog, Smalltalk) AI Ch 6 Rule-based systems L\s-2ISP\s+2 Ch 18 .sp 16 Feb \fI(reading week \(em no classes)\fR .sp 23 Feb \(em Tue Mid-term exam More on rule-based systems .sp \02 Mar Logic and planning AI Ch 7 Tue Project interim report due .sp \09 Mar Knowledge representation; AI Ch 8 using frames; CD theory L\s-2ISP\s+2 Ch 22 .sp 16 Mar Understanding natural language AI Ch 9 L\s-2ISP\s+2 Ch 19-21 .sp 23 Mar Vision??? AI Ch 10 (L\s-2ISP\s+2 Ch 10?) Mark set.sp .nf .ta \w'beginning 'u +2.5i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u .ul Week Material covered Reading Deadlines .ul beginning .sp \07 Sep Thu All assignments set .sp 14 Sep .sp 21 Sep .sp 28 Sep Tue Assignment 1 due .sp \05 Oct .sp 12 Oct Thu Assignment 2 due .sp 19 Oct Thu Test 1 .sp 26 Oct .sp \02 Nov Tue Assignment 3 due .sp \09 Nov Thu Reading days; no class .sp 16 Nov Tue Test 2 .sp 23 Nov .sp 30 Nov .sp \07 Dec Tue Test 3 Thu Assignment 4 due .fi .sh "Planned timetable"**-Emacs: info.sheet 2:30pm 1.44 Mail[1] (Text Fill)---- 5 .sp nf .ta \w'beginning 'u +3i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u ul Week Material covered Reading Deadlines ul beginning sp \05 Jan Introduction; L\s-2ISP\s+2 AI Ch 1 Tue Assignment 1 set L\s-2ISP\s+2 Ch 1-4 .sp 12 Jan Representations; blocks worlds AI Ch 2 Tue Assignment 2 set L\s-2ISP\s+2 Ch 4-7, 13 sp 19 Jan Constraints AI Ch 3 Tue Assignment 1 due s 26 Jan Searching AI Ch 4 Tue Assignment 2 due L\s-2ISP\s+2 Ch 11 sp \02 Feb Control strategies; objects, Flavors AI Ch 5 Tue Project proposa\l due L\s-2ISP\s+2 Ch 16 sp \09 Feb More on OOP (Prolog, Smalltalk) AI Ch 6 Rule-based systems L\s-2ISP\s+2 Ch 18 .sp 16 Feb \fI(reading week \(em no classes)\fR .sp 23 Feb \(em Tue Mid-term exam More on rule-based systems \02 Mar Logic and planning AI Ch 7 Tue Project interim report due9 Mar Knowledge representation; AI Ch 8 using frames; CD theory L\s-2ISP\s+2 Ch 22 .sp 16 Mar Understanding natural language AI Ch 9 L\s-2ISP\s+2 Ch 19-21 3 Mar Vision??? AI Ch 10 (L\s-2ISP\s+2 Ch 10?) .sp 30 Mar Concept learning AI Ch 11 Version-space technique .sp \06 Apr Learning rules AI Ch 12 Summary Fri Project final report due .sp ??? Apr Final exam (scheduled by Registrar) .fi b .sh "Bibliography" .sp Here is a representative selection of recent books on AI, with a bias towards practical aspects. LB ti-4n11LB ti-4n Barr, A. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence\fR. Kaufmann, Los Altos, CA, \fIVolume I\fR, 1981, and \fIVolume II\fR, 1982. .sp ti-4n Bratko, I. \fIP\s-2ROLOG\s+2 programming for artificial intelligence\fR. Addison-Wesley, Wokingham, England, 1986. .sp .ti-4n Bundy, A. \fIThe computer modelling of mathematical reasoning\fR. Academic Press, London, 1983. .sp .ti-4n Bundy, A. (Editor) fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. .sp ti-4n Cohen, P.R. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence Volume III\fR. Kaufmann, Los Altos, CA, 1982. .sp ti-4n Charniak E., Riesbeck, C.K. and McDermott, D.V. \fIArtificial intelligence programming\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1980. .sp ti-4n Gevarter, W.B. \fIIntelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. .sp .ti-4n Michalski, R.S., Carbonnell, J.G., and Mitchell, T.M. (Editors) \c \fIMachine Learning\fR, Tioga, Palo Alto, CA, 1983, and \fIMachine Learning Volume II\fR, Kaufmann, Los Altos, CA, 1986. .sp .ti-4n Nilsson, N.J. fIPrinciples of artificial intelligence\fR. Tioga, Palo Alto, CA, 1980. .sp ti-4n Schank, R.C. and Riesbeck, C.K. \fIInside computer understanding: five programs plus miniatures\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1981.p ti-4n Sowa, J.F. \fIConceptual structures\fR. Addison-Wesley, Reading, Massachusetts, 1984. sp221pm 1.42 Mail[2Addison-Wesley, Reading, Massachusetts, 1984. sp .ti-4n Waterman, D.A. \fIA guide to expert systems\fR. Addison-Wesley, Reading, MA, 1985. Wilensky, R.L\s-2ISP\s+2craft\fR. W.W.Norton, New York, 1984. .sp ti-4n Winograd, T. \fILanguage as a cognitive process. Volume I \(em Syntax\fR. Addison-Wesley, Reading, Massachusetts, 1984. .sp ti-4n Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp ti-4n Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .LE bp 0 ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE .sp2 ps+2 ce CPSC 533 \(em Artificial Intelligence .ps-2 .sh "Assignment 1. Introduction to \s-2LISP\s+2" (10% of course marks) sp Fully commented code, together with answers to the questions posed in Q.3, must be handed in on Tuesday January 20th. There will be .ul no extension of this deadline, except for good, documented, medical reasons. LB "1. " .NI "1. " 1.\ \ \c Write a recursive function \s-2POWER-OF-TWO\s+2 that computes the \fIn\fRth power of two, eg (\s-2POWER-OF-TWO\s+2 100) returns 1267650600228229401496703205376. [A simple test of function-definition and recursion.] .sp .NI "1. " 2.\ \ \c Write your own version of the Lisp function \s-2ASSOC\s+2. \s-2ASSOC\s+2 ``looks up'' a value in a list of lists, and returns the first list it finds whose first element matches the desired value. For example, (\s-2ASSOC\s+2 '\s-2Y\s+2 '((\s-2X\s+2 \s-2A\s+2) (\s-2Y\s+2 \s-2B\s+2) (\s-2Z\\[70`3.sp nf a \w'beginning 'u +3i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u .ul Week Material covered Reading Deadlines .ul beginning sp \05 Jan Introduction; L\s-2ISP\s+2 AI Ch 1 Tue Assignment 1 set L\s-2ISP\s+2 Ch 1-4 12 Jan Representations; blocks worlds AI Ch 2 Tue Assignment 2 set L\s-2ISP\s+2 Ch 4-7, 13 .sp 19 Jan Constraints AI Ch 3 Tue Assignment 1 due 26 Jan Searching AI Ch 4 Tue Assignment 2 due L\s-2ISP\s+2 Ch 11 .sp \02 Feb Control strategies; objects, Flavors AI Ch 5 Tue Project proposa\l due L\s-2ISP\s+2 Ch 16 .sp 09 Feb More on OOP (Prolog, Smalltalk) AI Ch 6 Rule-based systems L\s-2ISP\s+2 Ch 18 sp 16 Feb \fI(reading week \(em no classes)\fR sp 23 Feb \(em Tue Mid-term exam More on rule-based systems \02 Mar Logic and planning AI Ch 7 Tue Project interim report due sp \09 Mar Knowledge representation; AI Ch 8 using frames; CD theory L\s-2ISP\s+2 Ch 22p 16 Mar Understanding natural language AI Ch 9 L\s-2ISP\s+2 Ch 19-21 .sp 23 Mar Vision??? AI Ch 10 (L\s-2ISP\s+2 Ch 10?) sp 30 Mar Concept learning AI Ch 11 Version-space technique sp \06 Apr Learning rules AI Ch 12 Summary Fri Project final report due .sp ??? Apr Final exam (scheduled by Registrar) fi bp .sh "Bibliography" .sp Here is a representative selection of recent books on AI, with a bias towards practical aspects. .LB .ti-4n11 MLB ti-4n Barr, A. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence\fR. Kaufmann, Los Altos, CA, \fIVolume I\fR, 1981, and \fIVolume II\fR, 1982. .sp ti-4n Bratko, I. \fIP\s-2ROLOG\s+2 programming for artificial intelligence\fR. Addison-Wesley, Wokingham, England, 1986. .sp .ti-4n Bundy, A. \fIThe computer modelling of mathematical reasoning\fR. Academic Press, London, 1983. .sp .ti-4n Bundy, A. (Editor) fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. .sp ti-4n Cohen, P.R. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence Volume III\fR. Kaufmann, Los Altos, CA, 1982. .sp ti-4n Charniak E., Riesbeck, C.K. and McDermott, D.V. \fIArtificial intelligence programming\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1980. .sp ti-4n Gevarter, W.B. \fIIntelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. .sp .ti-4n Michalski, R.S., Carbonnell, J.G., and Mitchell, T.M. (Editors) \c \fIMachine Learning\fR, Tioga, Palo Alto, CA, 1983, and \fIMachine Learning Volume II\fR, Kaufmann, Los Altos, CA, 1986. .sp .ti-4n Nilsson, N.J. fIPrinciples of artificial intelligence\fR. Tioga, Palo Alto, CA, 1980. .sp ti-4n Schank, R.C. and Riesbeck, C.K. \fIInside computer understanding: five programs plus miniatures\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1981.p ti-4n Sowa, J.F. \fIConceptual structures\fR. Addison-Wesley, Reading, Massachusetts, 1984. sp22 Msp nf .ta \w'beginning 'u +3i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u .ul Week Material covered Reading Deadlines .ul beginning sp \05 Jan Introduction; L\s-2ISP\s+2 AI Ch 1 Tue Assignment 1 set L\s-2ISP\s+2 Ch 1-4 .sp 12 Jan Representations; blocks worlds AI Ch 2 Tue Assignment 2 set L\s-2ISP\s+2 Ch 4-7, 13 .sp 19 Jan Constraints AI Ch 3 Tue Assignment 1 due .sp 26 Jan Searching AI Ch 4 Tue Assignment 2 due L\s-2ISP\s+2 Ch 11 .sp 02 Feb Control strategies; objects, Flavors AI Ch 5 Tue Project proposa\l due L\s-2ISP\s+2 Ch 16 sp \09 Feb More on OOP (Prolog, Smalltalk) AI Ch 6 Rule-based systems L\s-2ISP\s+2 Ch 18 .sp 16 Feb \fI(reading week \(em no classes)\fR sp 23 Feb \(em Tue Mid-term exam More on rule-based systems .sp \02 Mar Logic and planning AI Ch 7 Tue Project interim report due sp \09 Mar Knowledge representation; AI Ch 8 using frames; CD theory L\s-2ISP\s+2 Ch 22 .sp 16 Mar Understanding natural language AI Ch 9 L\s-2ISP\s+2 Ch 19-21 .sp 23 Mar Vision??? AI Ch 10 (L\s-2ISP\s+2 Ch 10?) .sp 30 Mar Concept learning AI Ch 11 Version-space technique .sp 06 Apr Learning rules AI Ch 12 Summary Fri Project final report due sp ??? Apr Final exam (scheduled by Registrar) .fi .bp h "Bibliography" sp Here is a representative selection of recent books on AI, with a bias towards practical aspects. .LB ti-4n11 MMMMMMMBarr, A. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence\fR. Kaufmann, Los Altos, CA, \fIVolume I\fR, 1981, and \fIVolume II\fR, 1982. .sp .ti-4n Bratko, I. \fIP\s-2ROLOG\s+2 programming for artificial intelligence\fR. Addison-Wesley, Wokingham, England, 1986. .sp .ti-4n Bundy, A. \fIThe computer modelling of mathematical reasoning\fR. Academic Press, London, 1983. .sp .ti-4n Bundy, A. (Editor) \fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. .sp .ti-4n Cohen, P.R. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence Volume III\fR. Kaufmann, Los Altos, CA, 1982. .sp .ti-4n Charniak E., Riesbeck, C.K. and McDermott, D.V. \fIArtificial intelligence programming\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1980. .sp .ti-4n Gevarter, W.B. \fIIntelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. .sp .ti-4n Michalski, R.S., Carbonnell, J.G., and Mitchell, T.M. (Editors) \c \fIMachine Learning\fR, Tioga, Palo Alto, CA, 1983, and \fIMachine Learning Volume II\fR, Kaufmann, Los Altos, CA, 1986. .sp .ti-4n Nilsson, N.J. \fIPrinciples of artificial intelligence\fR. Tioga, Palo Alto, CA, 1980. .sp .ti-4n Schank, R.C. and Riesbeck, C.K. \fIInside computer understanding: five programs plus miniatures\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1981. .sps Winter Term Class presentations \0\07\(12% br Project: .br \0\0\0\0progress report \0\05% br \0\0\0\0final report \012\(12% .br \0\0\0\0in-class presentation \0\02\(12% .br Term paper \022\(12% sp ____ .br \h'-\w'total 'u'total\ \ 100% b sh "Planned timetable" .sp .nf .ta \w'beginning 'u +2.5i +\w'L\s-2ISP\s+2 Ch 0-0, 00 'u +\w'Mon 'u ul Week Material covered Reading Deadlines .ul beginning .sp \07 Sep Thu All assignments set sp 14 Sep .sp 21 Sep 28 Sep Tue Assignment 1 due .sp 05 Oct .sp 12 Oct Thu Assignment 2 due sp 19 Oct Thu Test 1 .sp 26 Oct \02 Nov Tue Assignment 3 due .sp 09 Nov Thu Reading days; no class .sp 16 Nov Tue Test 2 sp 23 Nov .sp 30 Nov \07 Dec Tue Test 3 Thu Assignment 4 due .fi .bp h "Bibliography" 6 MMMMMMMMM[4`       [3`[7`    [7`2pm 1.13 Mail[1         .sp [7`   Thu Assignment 4 due Here is a representative selection of recent books on AI, with a bias towards   21 Sep sp 28 Sep sp \05 Oct sp 12 Oct sp 19 Oct sp 26 Oct \02 Nov sp \09 Nov s 16 Nov 23 Nov sp 30 Nov .sp \07 Dec .fi b .sh "Bibliography" Here is a representative selection of recent books on AI, with a bias towards practical aspects. .LB ti-4n Barr, A. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence\fR. Kaufmann, Los Altos, CA, \fIVolume I\fR, 1981, and \fIVolume II\fR, 1982. .sp ti-4n Bratko, I. \fIP\s-2ROLOG\s+2 programming for artificial intelligence\fR. Addison-Wesley, Wokingham, England, 1986. .ti-4n Bundy, A. fIThe computer modelling of mathematical reasoning\fR. Academic Press, London, 1983. .sp ti-4n Bundy, A. (Editor) \fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. .ti-4n Cohen, P.R. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence Volume III\fR. Kaufmann, Los Altos, CA, 1982. .ti-4n10  [38`[45`[51`[54` practical aspects.Charniak E., Riesbeck, C.K. and McDermott, D.V..Wrote /vaxb.userb/profs/ian/courses/670/info.sheet--\09 Nov 16 Nov 23 Nov 30 Nov \07 Dec fi .bp h "Bibliography" .sp Here is a representative selection of recent books on AI. .LB .ti-4n Barr, A. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence\fR. Kaufmann, Los Altos, CA, \fIVolume I\fR, 1981, and \fIVolume II\fR, 1982. .sp .ti-4n Bratko, I. \fIP\s-2ROLOG\s+2 programming for artificial intelligence\fR. Addison-Wesley, Wokingham, England, 1986. .spFind file: ~/courses/670/.ti-4n -----Emacs: info.sheet 2:32pm 1.13 Mail[1] (Text Fill)----10%-------synopsis LB .NP Dimensions of classification of machine learning problems and systems .NP Theoretical foundations of inductive inference .NP Similarity-based learning: the generalization-as-search paradigm and its implementations NP Explanation-based learning and systems which embody it NP Exploration and discovery mechanisms, functional induction and theory formation NP Learning procedural knowledge .NP Cognitive aspects of human learning. LE The text for this part will be .LB R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1986) \fIMachine learning Volume 2\fP. Morgan Kaufmann, Los Altos, CA. LE Other relevant books include .LB Forsyth, R. and Rada, R. (1986) ul Machine learning: applications in expert systems and information retrieval.synopsis 2:32pm 1.13 Mail[1] (Text Fill)----233pm 1.583pm 1.58ti-4n Bundy, A. \fIThe computer modelling of mathematical reasoning\fR. Academic Press, London, 1983. .ti-4n Bundy, A. (Editor) \fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. .sp ti-4n Cohen, P.R. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence Volume III\fR. Kaufmann, Los Altos, CA, 1982. .sp ti-4n Charniak E., Riesbeck, C.K. and McDermott, D.V. \fIArtificial intelligence programming\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1980. .sp .ti-4n Gevarter, W.B. \fIIntelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. .sp .ti-4n Michalski, R.S., Carbonnell, J.G., and Mitchell, T.M. (Editors) \c \fIMachine Learning\fR, Tioga, Palo Alto, CA, 1983, and \fIMachine Learning Volume II\fR,4 Mark set Ellis Horwood, Chichester, England. .sp R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1983) .ul Machine learning -- an artificial intelligence approach. Tioga, Palo Alto, CA. .sp T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) .ul Machine learning -- a guide to current research. Kluwer, Boston, MA. .sp Osherson, D.N., Stob, D. and Weinstein, S. (1986)34   Mark setForsyth, R. and Rada, R. (1986) .ul Machine learning: applications in expert systems and information retrieval. Ellis Horwood, Chichester, England.** [1@.[1@s[1@p Gevarter, W.B. [1@.[1@t[1@i[1@-[1@4[1@n Gevarter, W.B. \fIIntelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. .sp .ti-4n Michalski, R.S., Carbonnell, J.G., and Mitchell, T.M. (Editors) \c \fIMachine Learning\fR, Tioga, Palo Alto, CA, 1983, and \fIMachine Learning Volume II\fR, Kaufmann, Los Altos, CA, 1986. .sp .ti-4n Nilsson, N.J. \fIPrinciples of artificial intelligence\fR. Tioga, Palo Alto, CA, 1980. .sp .ti-4n7[4` Mark set 4pm 1.84pm 1.8  Mark setR.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1983) .ul Machine learning -- an artificial intelligence approach. Tioga, Palo Alto, CA. .sp T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) .ul Machine learning -- a guide to current research. Kluwer, Boston, MA. MMM\fIMachine Learning Volume II\fR, MKaufmann, Los Altos, CA, 1986. M.sp M.ti-4n MMMMM[1@.[1@t[1@i[1@-[1@4[1@n T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) [1@.[1@s[1@p T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) [1@.[1@t[1@i[1@-[1@4[1@n T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) MMMMMMMMMMMMMMMMMMMMMMMMark set  Mark setR.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1986) \fIMachine learning Volume 2\fP. Morgan Kaufmann, Los Altos, CA. sp .ti-4n M MMT.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) .ul Machine learning -- a guide to current research. Kluwer, Boston, MA. .sp .ti-4n Nilsson, N.J. \fIPrinciples of artificial intelligence\fR. Tioga, Palo Alto, CA, 1980. .sp .ti-4n Schank, R.C. and Riesbeck, C.K. \fIInside computer understanding: five programs plus miniatures\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1981. .sp20 .ti-4n Sowa, J.F. Mark set.sp .ti-4n .sp .ti-4n Msp Osherson, D.N., Stob, D. and Weinstein, S. (1986) ul Systems that learn. MIT Press, Cambridge, MA. .sp .ul Proceedings of the Fourth International Workshop on Machine Learning (June, 1987). Morgan Kaufmann, Los Altos, CA.E .rh "Artificial Intelligence." This part will review the foundations of artificial intelligence and illustrate the problem of relating formal systems to human intelligence by examining some key aspects of knowledge representation. In particular, the recently proposed theory of situational semantics will be studied in some detail to bring into focus the problems involved in representing meaning. LB .NP he AI hypothesis: that human thinking and machine computing are radically the same .NP Knowledge representation case study 1: inheritance systems .NP nowledge representation case study 2: uncertain knowledge NP A theory of meaning: situational semantics. Abstract situations,55pm 1.27 Mail[25pm 1.27 Mail[2 Mark set   Mark set Osherson, D.N., Stob, D. and Weinstein, S. (1986) .ul Systems that learn. MIT Press, Cambridge, MA. .sp .ul Proceedings of the Fourth International Workshop on Machine Learning (June, 1987). Morgan Kaufmann, Los Altos, CA. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1981. .sp .ti-4n Sowa, J.F. \fIConceptual structures\fR. Addison-Wesley, Reading, Massachusetts, 1984. .sp .ti-4n Waterman, D.A. \fIA guide to expert systems\fR. Addison-Wesley, Reading, MA, 1985.4MMM.ult.uli.ul-.ul4.uln.ul .ul NP A theory of meaning: situational semantics. Abstract situations, events, event-types, roles, constraints, constraint-types. Linguistic meaning, attitudes. Representing mental states and events. LE The text for this part will be .LB Barwise, J. and Perry, J. (1983) .ul Situations and attitudes. MIT Press, Cambridge, MA. .LE Other relevant books include .LB Cohen, P.R. (1985) .ul Heuristic reasoning about uncertainty: an artificial intelligence approach. Pitmans Advanced Program, London, England. sp Haugeland, J. (1985) .ul Artificial intelligence: the very idea. MIT Press, Cambridge, MA. sp anal, L.N. and Lemmer, J.F.\0(Editors) (1986) ul Uncertainty in artificial intelligence.78 North Holland, Amsterdam. .sp Touretzky, D. (1986) .ul The mathematics of inheritance systems. Pitman, London. .LE **-Emacs: synopsis 2:35pm 1.27 Mail[2] (Text Fill)----BotUndo!Osherson, D.N., Stob, D. and Weinstein, S. (1986)ystems that learn.sp .ul Proceedings of the Fourth International Workshop on Machine Learning (June, 1987). Morgan Kaufmann, Los Altos, CA. .LE .rh "Artificial Intelligence." This part will review the foundations of artificial intelligence and illustrate the problem of relating formal systems to human intelligence by examining some key aspects of knowledge representation. In particular, the recently proposed theory of situational semantics will be studied in some detail to bring into focus the problems involved in representing meaning. .LB NP The AI hypothesis: that human thinking and machine computing are radically the same NP Knowledge representation case study 1: inheritance systems NP Knowledge representation case study 2: uncertain knowledge .NP A theory of meaning: situational semantics. Abstract situations, events, event-types, roles, constraints, constraint-types.---Emacs: synopsis 2:35pm 1.27 Mail[2] (Text Fill)----54%  Linguistic meaning, attitudes. Representing mental states and events. .LE The text for this part will be .LB Barwise, J. and Perry, J. (1983) .ul Situations and attitudes. MIT Press, Cambridge, MA. .LE Other relevant books include .LB Cohen, P.R. (1985) .ul Heuristic reasoning about uncertainty: an artificial intelligence approach. Pitmans Advanced Program, London, England. .sp Haugeland, J. (1985) .ul Artificial intelligence: the very idea. MIT Press, Cambridge, MA. .sp Kanal, L.N. and Lemmer, J.F.\0(Editors) (1986) .ul Uncertainty in artificial intelligence. North Holland, Amsterdam.78 Mark set Machine learning: applications in expert systems and information retrieval. Ellis Horwood, Chichester, England. Gevarter, W.B. \fIIntelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. .sp ti-4n R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1983) Machine learning -- an artificial intelligence approach. Tioga, Palo Alto, CA. .sp ti-4n R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1986) \fIMachine learning Volume 2\fP. Morgan Kaufmann, Los Altos, CA. .sp ti-4n T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) .ul Machine learning -- a guide to current research. Kluwer, Boston, MA. Nilsson, N.J.Principles of artificial intelligence\fR.18 MBratko, I. \fIP\s-2ROLOG\s+2 programming for artificial intelligence\fR. Addison-Wesley, Wokingham, England, 1986. Bundy, A.The computer modelling of mathematical reasoning\fR. Academic Press, London, 1983. Bundy, A. (Editor) \fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. .sp ti-4n Cohen, P.R. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence Volume III\fR. Kaufmann, Los Altos, CA, 1982. .sp ti-4n Charniak E., Riesbeck, C.K. and McDermott, D.V..sp 26 Oct .sp \02 Nov sp \09 Nov .sp 16 Nov 23 Nov .sp 30 Nov .sp \07 Dec fi .bp .sh "Bibliography" .sp Here is a representative selection of recent books on AI. LB .ti-4n Barr, A. and Feigenbaum, E.A. (Editors) \c \fIThe handbook of Artificial Intelligence\fR. Kaufmann, Los Altos, CA, \fIVolume I\fR, 1981, and \fIVolume II\fR, 1982. Bratko, I.\s-2ROLOG\s+[17@2 programming for0 M6pm 2.436pm 2.43 MM Mark setBarwise, J. and Perry, J. (1983) .ul Situations and attitudes. MIT Press, Cambridge, MA. Addison-Wesley, Wokingham, England, 1986. .sp .ti-4n Bundy, A. \fIThe computer modelling of mathematical reasoning\fR. Academic Press, London, 1983. .sp .ti-4n Bundy, A. (Editor) \fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. .sp .ti-4n1[1@.[1@s[1@p Bratko, I. [1@.[1@t[1@i[1@-4n Bratko, I.  Mark set \fICatalogue of Artificial Intelligence tools\fR. Springer-Verlag, Berlin, 1984. sp Cohen, [3@P.R Volume III\fR.1982. .sp ti-4n Charniak E., Riesbeck, C.K. and McDermott, D.V. \fIArtificial intelligence programming\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1980. .sp .ti-4n Forsyth, R. and Rada, R. (1986) ul Machine learning: applications in expert systems and information retrieval. Ellis Horwood, Chichester, England. Gevarter, W.B.Intelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1983) .ul Machine learning -- an artificial intelligence approach. 5 Mark setCohen, P.R. (1985) .ul Heuristic reasoning about uncertainty: an artificial intelligence approach. Pitmans Advanced Program, London, England. [1@.[1@s[1@p Charniak E., Riesbeck, C.K. and McDermott, D.V. [1@.[1@t[1@i[1@-[1@4[1@n Charniak E., Riesbeck, C.K. and McDermott, D.V. MMMark set Prentice-Hall, Englewood Cliffs, NJ, 1985. .sp .ti-4n R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1983) .ulMMMMMMMMMMMMark setCharniak E., Riesbeck, C.K. and McDermott, D.V. \fIArtificial intelligence programming\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1980. .sp .ti-4n M7pm 1.97 Mail[17pm 1.97 Mail[1Gevarter, W.B. \fIIntelligent machines\fR. Prentice-Hall, Englewood Cliffs, NJ, 1985. sp .ti-4n R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1983) .ul Machine learning -- an artificial intelligence approach. Tioga, Palo Alto, CA. .sp .ti-4n R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1986) \fIMachine learning Volume 2\fP. Morgan Kaufmann, Los Altos, CA. .sp ti-4n T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) .ul Machine learning -- a guide to current research. Kluwer, Boston, MA. .sp ti-4n Nilsson, N.J. \fIPrinciples of artificial intelligence\fR. Tioga, Palo Alto, CA, 1980. Osherson, D.N., Stob, D. and Weinstein, S. (1986) .ul21 Systems that learn.MIT Press, Cambridge, MA.Mark set.sp .ti-4n .sp .ti-4n M Mark set .sp Touretzky, D. (1986) .ul The mathematics of inheritance systems. Pitman, London. .LEBotMark setHaugeland, J. (1985) .ul Artificial intelligence: the very idea. MIT Press, Cambridge, MA. .sp Kanal, L.N. and Lemmer, J.F.\0(Editors) (1986) .ul Uncertainty in artificial intelligence. North Holland, Amsterdam. MMM[1@.[1@t[1@i[1@-[1@4[1@n Kanal, L.N. and Lemmer, J.F.\0(Editors) (1986) .ti-4n T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) .ul Machine learning -- a guide to current research. Kluwer, Boston, MA. .sp .ti-4n Nilsson, N.J.Principles of artificial intelligence\fR. Tioga, Palo Alto, CA, 1980. Osherson, D.N., Stob, D. and Weinstein, S. (1986) Systems that learn. .ul Proceedings of the Fourth International Workshop on Machine Learning (June, 1987). Schank, R.C. and Riesbeck, C.K. \fIInside computer understanding: five programs plus miniatures\fR. Lawrence Erlbaum Associates, Hillsdale, New Jersey, 1981. .sp .ti-4n5Auto-saving...donesp .ti-4n Sowa, J.F. \fIConceptual structures\fR. Addison-Wesley, Reading, Massachusetts, 1984. Waterman, D.A.A guide to expert systems\fR. Addison-Wesley, Reading, MA, 1985. Wilensky, R. \fIL\s-2ISP\s+2craft\fR. W.W.Norton, New York, 1984. .sp .ti-4n Winograd, T. \fILanguage as a cognitive process. Volume I \(em Syntax\fR. Addison-Wesley, Reading, Massachusetts, 1984. .sp .ti-4n Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp .ti-4n Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition).30 .LE.bp 0Mark set.sp .ti-4n .sp .ti-4n Waterman, D.A. MM Mark set Mark setTouretzky, D. (1986) .ul The mathematics of inheritance systems. Pitman, London. 8pm 1.48 Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp .ti-4n Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). LE .bp 0 .ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE .sp2 .ps+2 .ce CPSC 533 \(em Artificial Intelligence ps-2 .sh "Assignment 1. Introduction to \s-2LISP\s+2" (10% of course marks) Fully commented code, together with answers to the questions posed in Q.3, must be handed in on Tuesday January 20th. There will be .ul no extension of this deadline, except for good, documented, medical reasons. LB "1. " .NI "1. " 1.\ \ \c8pm 1.48 Mail[1] (Text Fill)----34 Mark set.NI "1. " 1.\ \ \c Write a recursive function \s-2POWER-OF-TWO\s+2 that computes the \fIn\fRth power of two, eg (\s-2POWER-OF-TWO\s+2 100) returns 1267650600228229401496703205376. [A simple test of function-definition and recursion.] .sp .NI "1. " 2.\ \ \c Write your own version of the Lisp function \s-2ASSOC\s+2. \s-2ASSOC\s+2 ``looks up'' a value in a list of lists, and returns the first list it finds whose first element matches the desired value. For example, (\s-2ASSOC\s+2 '\s-2Y\s+2 '((\s-2X\s+2 \s-2A\s+2) (\s-2Y\s+2 \s-2B\s+2) (\s-2Z\\s+2 \s-2C\s+2))) returns (\s-2Y\s+2 \s-2B\s+2). [Another simple test of function-definition and recursion.] sp NI "1. " 3.\ \ \c In \fBProblem 4-13\fP (p.73 and p.344), Winston & Horn define \s-2OUR-INTERSECTION\s+2 as .sp -0.5 .LB nf .ta \w'\0\0'u +\w'(\s-2COND\s+2 'u +\w'('u (\s-2DEFUN\s+2 \s-2OUR-INTERSECTION\s+2 (\s-2X\s+2 \s-2Y\s+2) (\s-2COND\s+2 ((\s-2NULL\s+2 \s-2X\s+2) \s-2NIL\s+2) ((\s-2MEMBER\s+2 (\s-2CAR\s+2 \s-2X\s+2) \s-2Y\s+2) 9Mark setNote that for all projects, choice of experiments and .ul presentation and analysis of results in the final report forms a particularly important part of the assessment. Due on Friday April 10th (the last day of the Winter term). .in-4n LE I hope that it will be found useful to discuss project progress in class and demonstrate them when complete. .sp There will be .ul no extension of deadlines on the project, except for good, documented, medical reasons.               Bot.LB NP .ul Project proposal (0%) .in+4n A (nominally) two-page report which describes the project and defines its scope. Although this is not assessed, it .ul must be handed in on time. Due on Tuesday February 3rd. in-4n .NP .ul Interim report (10%) .in+4n Detailed specification of the project, with plans for implementing the program and investigating its behavior. Must describe how the program's performance is to be assessed, and what tests and analysis are planned. Due on Tuesday March 3rd. .in-4n .NP .ul Final report (25%) .in+4n Complete demonstration and documentation of what was done. Note that for all projects, choice of experiments and .ul92% Ma general frame system for knowledge representation ATN parser for a simple subset of English NP .ul a version of Marcus's deterministic wait-and-see parsing scheme .NP a semantic grammar interpreter in a particular domain .NP ul a concept learning system (eg the M procedure). LE Of course, you may suggest your own project topic. pp The project is to be undertaken as a scientific investigation. It is \fInot\fR a test of whether you can hack together a system. Grades are given for the reports, not for programs (although programs may be included in an Appendix). As well as constructing a system, you are expected to investigate and analyze its performance and report on your findings. All projects will be done in L\s-2ISP\s+2 unless there are \fIvery\fR special reasons for using another language (to be discussed and agreed with me). .pp I intend that projects will mostly be done in pairs. Assessment will be based on written documents as follows: .LB NP85 M.ul an experimental comparison of several different search procedures in a particul\ar domain .NP ul a game-playing program for some simple two-person game using the alpha-beta tre\e-searching techniquerule interpreter, and the implementation of some rudimentary rule-based syste\m in it NP .ul a system which converts well-formed formulae in first-order predicate calculus \into clausal form NP .ul a resolution theorem prover .NP .ul a STRIPS-like planner in a blocks world .NP .ul a system to simplify, differentiate, and integrate expressions in symbolic alge\bra .NP .ul a general frame system for knowledge representation0 MFully commented code, together with a brief user manual and transcript of an interactive session, must be handed in on Tuesday January 27th. There will be ul no extension of this deadline, except for good, documented, medical reasons. .sp 3 Attachment 1 blocks.l br Attachment 2 commented transcript .bp 0 .ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE .sp2 .ps+2 ce CPSC 533 \(em Artificial Intelligence .ps-2 sh "Project" (total of 35% of course marks) .pp The aim of the project is to give you hands-on experience of designing and implementing an AI program of modest size, and investigating and reporting on its performance. Possible project topics are: LB NP .ul an experimental comparison of several different search procedures in a particul\[70`75 MMMMMMMMMMar domain .NP .ul a game-playing program for some simple two-person game using the alpha-beta tre\e-searching technique .NP .ul a rule interpreter, and the implementation of some rudimentary rule-based syste\m in it .NPDEPARTMENT OF COMPUTER SCIENCE .sp2 .ps+2 .ce CPSC 533 \(em Artificial Intelligence .ps-2 .sh "Assignment 1. Introduction to \s-2LISP\s+2" (10% of course marks) .sp Fully commented code, together with answers to the questions posed in Q.3, must be handed in on Tuesday January 20th. There will be .ul no extension of this deadline, except for good, documented, medical reasons. .LB "1. "58MMMMMMMMMMMMMMMark set Possible project topics are: .LB .NP .ul an experimental comparison of several different search procedures in a particul\ar domain .NP .ul a game-playing program for some simple two-person game using the alpha-beta tre\e-searching technique .NP .ul a rule interpreter, and the implementation of some rudimentary rule-based syste\m in it .NP .ul a system which converts well-formed formulae in first-order predicate calculus \Addison-Wesley, Reading, Massachusetts, 1984. .sp .ti-4n Winston, P.H. \fIArtificial Intelligence\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .sp .ti-4n Winston, P.H. & Horn, B.K.P. \fIL\s-2ISP\s+2\fR. Addison-Wesley, Reading, Massachusetts, 1984 (second edition). .LE .bp 0 .ce2 THE UNIVERSITY OF CALGARY79pm 1.599pm 1.59 [5`6[2@70  [1@2[1@0 .NP .ul an experimental comparison of several different search procedures in a particul\ar domain .NP .ul a game-playing program for some simple two-person game using the alpha-beta tre\e-searching technique .NP .ul a rule interpreter, and the implementation of some rudimentary rule-based syste\m in it .NP .ul a system which converts well-formed formulae in first-order predicate calculus \[70`61.ul a system which converts well-formed formulae in first-order predicate calculus \into clausal form NP .ul a resolution theorem prover NP .ul a STRIPS-like planner in a blocks world .NP .ul a system to simplify, differentiate, and integrate expressions in symbolic alge\bra NP ul a general frame system for knowledge representation .NP .ul ATN parser for a simple subset of English NP .ul a version of Marcus's deterministic wait-and-see parsing schemesemantic grammar interpreter in a particular domain .NP ul a concept learning system (eg the M procedure). .LE70a concept learning system (eg the M procedure). .LE Of course, you may suggest your own project topic. pp The project is to be undertaken as a scientific investigation. It is \fInot\fR a test of whether you can hack together a system. Grades are given for the reports, not for programs (although programs may be included in an Appendix). As well as constructing a system, you are expected to investigate and analyze its performance and report on your findings. All projects will be done in L\s-2ISP\s+2 unless there are \fIvery\fR special reasons for using another language (to be discussed and agreed with me). .pp I intend that projects will mostly be done in pairs. Assessment will be based on written documents as follows: .LB Project proposal (0%) in+4n A (nominally) two-page report which describes the project and defines its scope. Although this is not assessed, it must be handed in on time. Due on Tuesday February 3rd. in-4n .NP ul7Wrote /vaxb.userb/profs/ian/courses/670/info.sheet--Loading shell...doneroff -a2                   **-Emacs: *shell* 2:39pm 1.59 Mail[1] (Shell: run)----All [5@VAXB [15`~/corseureses/670/info.sheet; lpq -Palw240pm 1.340pm 1.3 no entries vaxb: sending to vaxa Rank Owner Job Files Total Size 1st ian 287 (standard input) 20252 bytes VAXB1pm 1.50 Mail[21pm 1.50 Mail[22pm 1.232pm 1.233pm 1.38 Mail[13pm 1.38 Mail[14pm 1.54 Mail[04pm 1.54 Mail[05pm 1.37 Mail[15pm 1.37 Mail[16pm 1.256pm 1.257pm 0.87 Mail[07pm 0.87 Mail[08pm 1.17 Mail[18pm 1.17 Mail[19pm 1.31 Mail[29pm 1.31 Mail[250pm 1.4450pm 1.441pm 0.87 Mail[11pm 0.87 Mail[12pm 0.84 Mail[02pm 0.84 Mail[03pm 0.713pm 0.714pm 0.454pm 0.455pm 0.215pm 0.216pm 0.46pm 0.47pm 0.667pm 0.668pm 0.548pm 0.549pm 0.53 Mail[19pm 0.53 Mail[13:00pm 1.093:00pm 1.091pm 1.11pm 1.12pm 1.052pm 1.053pm 1.093pm 1.094pm 0.944pm 0.945pm 0.625pm 0.62C-z- rLoading rmail...doneCounting messages...20Garbage collecting...Counting messages...20donenew messages...done (1)Wrote /vaxb.userb/profs/ian/RMAIL1 new message readFrom: Danhua Mo  Date: 28 Aug 1987 14:00-MST Subject: paper To: ian@vaxb.LOCAL  Hi. I hate to bother you again, but it would be highly appreciated if you would take a look at the final draft of my paper. I put it in your mbox on the 7th floor. I am very busy at making the format right now because the deadline is on Monday. ---mo- Emacs: RMAIL 3:05pm 0.62 Mail[1] (RMAIL 38/38 Narrow) ----All------6pm 0.58[1] (RMAIL 38/38 Narrow) ----All-----6pm 0.58[1] (Text Fill)----77%-----7pm 0.87pm 0.88pm 0.708pm 0.709pm 0.73[09pm 0.73[010pm 1.27[110pm 1.27[11pm 0.931pm 0.932pm 0.58[02pm 0.58[03pm 0.99[13pm 0.99[14pm 1.00[04pm 1.00[05pm 0.95[15pm 0.95[16pm 0.906pm 0.907pm 0.97[27pm 0.97[28pm 1.48pm 1.49pm 1.04[09pm 1.04[020pm 0.82[320pm 0.82[31pm 0.64[11pm 0.64[12pm 0.99[32pm 0.99[33pm 1.23[13pm 1.23[14pm 1.12[04pm 1.12[05pm 1.72[15pm 1.72[1Date: Fri, 28 Aug 87 12:28:28 MDT From: Tim Bell To: cleary@vaxb.LOCAL, ian@vaxb.LOCAL Subject: Text compression corpusere is a list of the texts we decided on a while ago for the corpus. Could you please give me a pathname where I can get the texts that you volunteered? Also any suggestions, changes ...  ta, tim ------------------------------------------------------------------------- Text Compression Corpus abbrev source book1 Hardy - Far from the madding crowd book2 Ian's speech book paper1 Ian paper2 Ian paper3 Ian paper4 John paper5 John paper6 John news usenet sample progc C (Dan) ~100k progp Pascal (John) progm Modula-27/38,answered Narrow) ----TopFrom: Danhua Mo  Date: 28 Aug 1987 14:00-MST Subject: paper To: ian@vaxb.LOCALi. I hate to bother you again, but it would be highly appreciated if you would take a look at the final draft of my paper. I put it in your mbox on the 7th floor. I am very busy at making the format right now because the deadline is on Monday.  ---mo               8/38 Narrow) ----All---------6pm 1.75[26pm 1.75[27pm 1.217pm 1.218pm 1.19[18pm 1.19[1Mark set.pn 0 ls1 .ce2 THE UNIVERSITY OF CALGARY DEPARTMENT OF COMPUTER SCIENCE .sp2 .ps+2 .ce CPSC 670 \(em Artificial Intelligence .ps-2 .sp3 .LB NP .ul Instructor. John H Andreae, MA\ 782, 220-7299 Ian H Witten, MA\ 786, 220-6780 sp .NP ul Office hours. Tuesdays and Thursdays 14.00-15.00 (both instructors) .sp NP .ul Lectures. ???, Tuesdays and Thursdays 11.00-12.15 sp NPTop [11`s.** [36` and9pm 1.409pm 1.40     [1@M[1@T[1@A[1@ [1@2[1@5[1@6   .ul Assessment .ta \w'Winter Term 'u +\w'Midterm exam (in class time) 'u .sp Fall Term Assignment \0\07\(12% .br Project: .br \0\0\0\0progress report \0\05% .br \0\0\0\0final report \012\(12% .br \0\0\0\0in-class presentation \0\02\(12% .br Take-home exam \022\(12%  3%   Query replace: % Mark set Query replacing % with :   Project: .br \0\0\0\0progress report \0\05 br \0\0\0\0final report \012\(12 .br \0\0\0\0in-class presentation \0\02\(12 br Take-home exam \022\(12 sp Winter Term Class presentations \0\07\(12 .br Project: br \0\0\0\0progress report \0\05% .br \0\0\0\0final report \012\(12% br \0\0\0\0in-class presentation \0\02\(12% Term paper \022\(12% sp ____ h'-\w'total 'u'total\ \ 100%p .sh "Planned timetable" sp .nf730pm 1.57[230pm 1.57[2% Done [8@I-search: M ... i ....sh "Bibliography" sp Here is a representative selection of recent books on AI.c ...h ...p ti-4n augeland, J. (1985) ul Artificial intelligence: the very idea. MIT Press, Cambridge, MA. .sp ti-4n Kanal, L.N. and Lemmer, J.F.\0(Editors) (1986) ul Uncertainty in artificial intelligence. North Holland, Amsterdam. .sp ti-4n R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1983) ul Machine learning -- an artificial intelligence approach. Tioga, Palo Alto, CA. .sp ti-4n R.S. Michalski, J.G. Carbonell, and T.M. Mitchell (Editors) (1986) \fIMachine learning Volume 2\fP. Morgan Kaufmann, Los Altos, CA. sp .ti-4n T.M. Mitchell, J.G. Carbonell, and R.S. Michalski (Editors) (1986) ul Machine learning -- a guide to current research. Kluwer, Boston, MA. 35Mark set Mark set Defining kbd macro... Def) ----All Def)----35%Mark setI-search: ...[6` ^J ...Failing I-search: ^JMark setKeyboard macro defined) ----All----)----35%----Auto-saving...Keyboard macro defined1pm 2.35[51pm 2.35[52pm 1.36[22pm 1.36[23pm 1.123pm 1.124pm 0.88[14pm 0.88[15pm 0.765pm 0.766pm 0.81[26pm 0.81[27pm 0.72[17pm 0.72[18pm 0.85[28pm 0.85[29pm 0.73[19pm 0.73[140pm 1.18[240pm 1.18[21pm 0.64[11pm 0.64[12pm 1.44[22pm 1.44[23pm 1.183pm 1.184pm 1.08[14pm 1.08[15pm 0.835pm 0.836pm 0.65[26pm 0.65[27pm 0.737pm 0.738pm 0.76[18pm 0.76[19pm 0.979pm 0.9750pm 1.93[29] (RMAIL 38/38 Narrow) ----All50pm 1.93[29] (Text Fill)----35%1pm 2.281pm 2.282pm 2.40[252pm 2.40[253pm 1.71[243pm 1.71[244pm 2.29[184pm 2.29[18Loading sendmail...donemailalias...doneTo: Subject: FCC: mbox.out --text follows this line--     --Emacs: *mail* 3:54pm 2.29[18] (Mail Fill)----All g**aines stuff 5pm 4.55pm 4.56pm 4.056pm 4.057pm 3.83[177pm 3.83[178pm 4.06[208pm 4.06[209pm 4.99[189pm 4.99[184:00pm 5.10[164:00pm 5.10[161pm 4.73[181pm 4.73[18please sti leave me the Bratkostuff about extending ID3 to dealwith intervals, and the b definitive book on decision trees. Have a good trip, wherever ian 2pm 4.75[152pm 4.75[15Sending...Wrote /vaxb.userb/profs/ian/mbox.outSending...done-- Defining kbd macro... Def)----All Def)----35%Mark setI-search: ...Mark set[6` [10`[1@,[1@ Mark set[4@R.S.3pm 3.22[293pm 3.22[29I-search: ... Mark setKeyboard macro defined)----All----)----35%----C-z-Carbonell, J.G[1@.[35`[38`Mitchell, T.M[1@.  Michalski, R.S., Carbonell, J.[2@G.[39`Mitchell, T.M[1@.  Mitchell, T.M[1@. Carbonell, J.G., and Michalski, R.[2@S. Wrote /vaxb.userb/profs/ian/courses/670/info.sheet--4pm 3.074pm 3.07 Michalski, R.S., Carbonell, J.G., and Mitchell, T.M. (Editors) (1986) \fIMachine learning Volume 2\fP. Morgan Kaufmann, Los Altos, CA. Mitchell, T.M., Carbonell, J.G[23@., and Michalski, R.S. VAXB roff -a2 ~/courses/670/info.sheet; lpq -Palw2 no entries  vaxb: sending to vaxa Rank Owner Job Files Total Size 1st ian 287 (standard input) 20252 bytes VAXB        --**-Emacs: *shell* 4:04pm 3.07[29] (Shell: run)----All----------.sp .ti-4n Nilsson, N.J.41cd ~/courses/670Directory /vaxb.userb/profs/ian/courses/670/roff VAXB roff  -a2 info.sheet; lpq -Palw2 5pm 3.39[255pm 3.39[255pm 3.39[25alw2 is ready and printing Rank Owner Job Files Total Size active andrews 772 info.dvi, regs.dvi 20308 bytes vaxb: sending to vaxa Rank Owner Job Files Total SizeBotVAXB6pm 2.44[246pm 2.44[246pm 2.44[247pm 3.68[197pm 3.68[197pm 3.68[198pm 5.36[178pm 5.36[178pm 5.36[179pm 5.409pm 5.409pm 5.4010pm 4.73[1810pm 4.73[1810pm 4.73[181pm 5.09[151pm 5.09[151pm 5.09[152pm 4.73[162pm 4.73[162pm 4.73[163pm 3.97[183pm 3.97[183pm 3.97[184pm 3.09[9] (Mail Fill)----All-4pm 3.09[9] (Shell: run)----Bot-4pm 3.09[9] (Text Fill)----41%-5pm 1.71[55pm 1.71[55pm 1.71[56pm 2.38[76pm 2.38[76pm 2.38[77pm 1.75[27pm 1.75[27pm 1.75[28pm 1.00[18pm 1.00[18pm 1.00[19pm 0.669pm 0.669pm 0.6620pm 0.76[220pm 0.76[220pm 0.76[21pm 0.45[01pm 0.45[01pm 0.45[02pm 0.38[22pm 0.38[22pm 0.38[23pm 0.543pm 0.543pm 0.544pm 0.64[04pm 0.64[04pm 0.64[05pm 0.91[25pm 0.91[25pm 0.91[26pm 1.21[16pm 1.21[16pm 1.21[17pm 0.987pm 0.987pm 0.988pm 1.378pm 1.378pm 1.379pm 1.23[29pm 1.23[29pm 1.23[230pm 1.90[430pm 1.90[430pm 1.90[41pm 1.39[31pm 1.39[31pm 1.39[32pm 1.06[12pm 1.06[12pm 1.06[13pm 0.65[23pm 0.65[23pm 0.65[24pm 1.39[14pm 1.39[14pm 1.39[15pm 2.55[35pm 2.55[35pm 2.55[36pm 1.576pm 1.576pm 1.577pm 1.00[17pm 1.00[17pm 1.00[18pm 0.688pm 0.688pm 0.689pm 0.549pm 0.549pm 0.5440pm 0.9640pm 0.9640pm 0.961pm 1.37[31pm 1.37[31pm 1.37[32pm 1.28[12pm 1.28[12pm 1.28[13pm 1.93[33pm 1.93[33pm 1.93[34pm 2.10 Mail[3] (Mail Fill)----All4pm 2.10 Mail[3] (Shell: run)----Bot4pm 2.10 Mail[3] (Text Fill)----41%5pm 1.04 Mail[15pm 1.04 Mail[15pm 1.04 Mail[16pm 0.58 Mail[06pm 0.58 Mail[06pm 0.58 Mail[07pm 0.377pm 0.377pm 0.378pm 0.36 Mail[18pm 0.36 Mail[18pm 0.36 Mail[19pm 1.73 Mail[39pm 1.73 Mail[39pm 1.73 Mail[350pm 1.18 Mail[250pm 1.18 Mail[250pm 1.18 Mail[21pm 1.01pm 1.01pm 1.02pm 0.53 Mail[02pm 0.53 Mail[02pm 0.53 Mail[03pm 2.00 Mail[33pm 2.00 Mail[33pm 2.00 Mail[3g**Auto-saving...doneFrom: Danhua Mo Date: 28 Aug 1987 14:00-MST Subject: paper To: ian@vaxb.LOCAL  Hi. I hate to bother you again, but it would be highly appreciated if you would take a look at the final draft of my paper. I put it in your mbox on the 7th floor. I am very busy at making the format right now because the deadline is on Monday. ---mo- Emacs: RMAIL 4:53pm 2.00 Mail[3] (RMAIL 38/38 Narrow) ----All-----Counting new messages...done (1)Wrote /vaxb.userb/profs/ian/RMAIL1 new message readDate: Fri, 28 Aug 87 16:43:11 MDT From: Mr. Invisible To: ian@vaxb.LOCAL  # to unbundle, sh this file echo inter.c 1>&2 cat >inter.c <<'End of inter.c' #include "weird.h" #define MAXLINES 255 /* number of lines read in a time = max # of\lines of one command result */ typedef char FILENAME[MAXSTR+1]; extern char *homep; FILENAME namearray[MAXLINES+1]; /* array of file lines */ FILENAME *namep = namearray, *memp = namearray; FILE *comfp; FILE *resfp; FILE *locfp; struct rightentry *ihead, *itail; /* pointers to list of commands to be saved\*/ int lineno = 0; short done = 0, abortit = 0, save = 0, haveold = 0; inter(result, command, location) char *result, *command, *location; 9/39 Narrow) ----Top4pm 1.88[2] (RMAIL 39/39 Narrow) ----Top-----4pm 1.88[2] (Shell: run)----Bot-----4pm 1.88[2] (Text Fill)----41%-----No following nondeleted messageFrom: Danhua Mo  Date: 28 Aug 1987 14:00-MST Subject: paper To: ian@vaxb.LOCAL  Hi. I hate to bother you again, but it would be highly appreciated if you would take a look at the final draft of my paper. I put it in your mbox on the 7th floor. I am very busy at making the format right now because the deadline is on Monday.  ---mo             8/39 Narrow) ----AllDate: Fri, 28 Aug 87 16:43:11 MDT From: Mr. Invisible To: ian@vaxb.LOCAL  # to unbundle, sh this file echo inter.c 1>&2 cat >inter.c <<'End of inter.c' #include "weird.h" #define MAXLINES 255 /* number of lines read in a time = max # of\lines of one command result */ typedef char FILENAME[MAXSTR+1]; extern char *homep; FILENAME namearray[MAXLINES+1]; /* array of file lines */ FILENAME *namep = namearray, *memp = namearray; FILE *comfp; FILE *resfp; FILE *locfp; struct rightentry *ihead, *itail; /* pointers to list of commands to be saved\*/ int lineno = 0; short done = 0, abortit = 0, save = 0, haveold = 0; inter(result, command, location) char *result, *command, *location;9/39 Narrow) ----Top5pm 1.25pm 1.25pm 1.26pm 0.63[06pm 0.63[06pm 0.63[0Save file /vaxb.userb/profs/ian/RMAIL? (y or n) nCheck all saved[>52l[>37h[1] + Done ( roff -a2 assignments; lpq -Palw2 ) VAXB ^Dlogout You are still logged in somewhere qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/calgary32000066400000000000000000001000001503624047500335270ustar00rootroot00000000000000%A Abdou, I.E. %A Wong, K.Y. %D 1982 %T Analysis of linear interpolation schemes for bi-level image applications %J IBM J Research and Development %V 26 %P 667-680 %A Abell, R. %D 1981 %T Implementation of a Telidon system using Unix file structures %B The Telidon book %E D.Godfrey and E.Chang %I Press Porcepic %C Toronto, ON %P 203-209 %A Abut, H. %A Gray, R.M. %A Rebolledo, V. %D 1982 %T Vector quantization of speech and speech-like waveforms %J IEEE Trans Acoustics, Speech and Signal Processing %V Acoustics, Speech, and Signal Processing -30 %N 3 %P 423-435 %O June %K * %A Achugbue, J.O. %D 1981 %T On the line breaking problem in text formatting %J SIGOA Newsletter (Proc ACM Symposium on Text manipulation, Portland, Oregon) %V 2 %N 1/2 %P 117-121 %O Spring/Summer %A Adams, D.N. %D 1979 %T The hitchhiker's guide to the galaxy %I Pan %C London, England %A Adams, J.B. %D 1976 %T A probability model of medical reasoning and the MYCIN model %J Mathematical Biosciences %V 32 %P 177-186 %A Aho, A.V. %A Corasick, M.J. %D 1975 %T Efficient string matching: an aid to bibliographic search %J Comm ACM %V 18 %N 6 %P 333-340 %O June %A Aikins, J.S. %D 1983 %T Prototypical knowledge for expert systems %J Artificial Intelligence %V 20 %N 2 %P 163-210 %O February %K * %A Akers, G. %A Lennig, M. %D 1984 %T Intonation in text-to-speech synthesis: evaluation of algorithms %R Report %I Bell-Northern Research %C Verdun, QUE %K * %A Allebach, J.P. %A Liu, B. %D 1976 %T Analysis of halftone dot profile and aliasing in the discrete binary representation of images %J Optical Society of America %V 67 %N 9 %K * %A Allen, B.P. %A Wright, J.M. %D 1983 %T Integrating logic programs and schemata %J Proc 8th International Joint Conference on Artificial Intelligence %P 340-342 %A Allen, E.M. %D 1983 %T YAPS: yet another production system %R Report TR-1146 %I Maryland Artificial Intelligence Group, Computer Science Department, University of Maryland %C Maryland, MD %O December %K * %A Allen, J.F. %A Perrault, C.R. %D 1980 %T Analyzing intention in utterances %J Artificial Intelligence %V 15 %P 143-178 %K * %A Allen, J.F. %D 1984 %T Towards a general theory of action and time %J Artificial Intelligence %V 23 %P 123-154 %K * %A Almes, G.T. %A Black, A.P. %A Lazowska, E.L. %A Noe, J.D. %D 1985 %T The Eden system: a technical review %J IEEE Trans Software Engineering %V SE-11 %N 1 %P 43-59 %O January %K * %A Alvey, P. %D 1983 %T The problems of designing a medical expert system %J Proc Expert Systems 83 %I Churchill College %C Cambridge, England %P 30-42 %O December %K * %A Anderberg, M.R. %D 1973 %T Cluster analysis for applications %I Academic Press %C New York, NY %A Anderson, D.P. %A Hedin, R.C. %D 1982 %T Voice input/output module %J Voice Data Entry Systems Application Conference '82 %C San Mateo, CA %O September 21 %K * %A Anderson, J.R. %T Knowledge compilation: the general learning mechanism %K * %A Anderson, J.R. %A Reiser, B.J. %D 1985 %T The LISP tutor %J Byte %V 10 %N 4 %P 159-175 %O April %A Andreae, J.H. %D 1984 %T Numbers in the head %R Man-Machine Studies Progress Report UC-DSE/24 %P 5-28 %I Department of Electrical Engineering, University of Canterbury %C New Zealand %A Andreae, P.M. %D 1984 %T Constraint limited generalization: acquiring procedures from examples %J Proc American Association on Artificial Intelligence %C Austin, TX %O August %K * %A Andreae, P.M. %D 1984 %T Justified generalization: acquiring procedures from examples %R PhD Thesis %I Department of Electrical Engineering and Computer Science, MIT %A Andreae, P.M. %D 1986 %T Justified generalization %J Proc International Conference on Future Advances in Computing %C Christchurch, New Zealand %O February 17-21 %K * %A Andreka, H. %A Nemeti, I. %A Sain, I. %D 1982 %T A complete logic for reasoning about programs via nonstandard model theory I %J Theoretical Computer Science %V 17 %P 193-212 %K * %A Andreka, H. %A Nemeti, I. %A Sain, I. %D 1982 %T A complete logic for reasoning about programs via nonstandard model theory II %J Theoretical Computer Science %V 17 %P 259-278 %K * %A Andrew, A.M. %D 1981 %T Autopoiesis \(em allopoiesis interplay %E M.Zeleny %B Autopoiesis: a theory of living organization %I North Holland %C New York, NY %P 157-166 %A Anon %D 1972 %T Holography and computer generated holograms %I Mills and Boom %C London, England %K * %A ANSI %D 1983 %T Videotex/Teletext presentation level protocol syntax (Draft) %I American National Standards Committee X3 -- Information Processing Systems, Technical Committee X3L2 -- Codes and character sets %C New York, NY %O June %A Anson, E. %D 1982 %T The device model of interaction %J Computer Graphics %V 16 %N 2 %P 107-114 %O July %K * %A Aoki, M. %D 1965 %T Optimal control of partially observable markovian systems %J J Franklin Institute %V 280 %N 5 %O November %K * %A Ascher, R.N. %A Nagy, G. %D 1974 %T A means for achieving a high degree of compaction on scan-digitized printed text %J IEEE Trans Computers %V C-23 %N 11 %P 1174-1179 %O November %K * %A Ash, W.L. %D 1981 %T MXEC: parallel processing with an advanced macro facility %J Comm ACM %V 24 %N 8 %P 502-509 %K * %A Ashby, W.R. %D 1960 %T Design for a brain: the origin of adaptive behavior %I Wiley %C New York, NY %O (second edition) %A Askwall, S. %D 1985 %T Computer supported reading vs reading text on paper: a comparison of two reading situations %J IJMMS %V 22 %N 4 %P 425-439 %O April %A Atkinson, H.H. %A Gargantini, I. %A Ramanath, M.V.S. %D 1984 %T Determination of the 3D border by repeated elimination of internal surfaces %J Computing %V 32 %P 279-295 %K * %A Attardi, G. %A Simi, M. %D 1982 %T Semantics of inheritance and attributions in the description system Omega %R AI Memo 642 %I MIT Artificial Intelligence Laboratory %O January %K * %A Axelrod, R. %D 1984 %T The evolution of cooperation %I Basic Books %C New York, NY %A Backer, D. %A Gano, S. %D 1982 %T Dynamically alterable videodisk displays %J Proc Graphics Interface 82 %C Toronto, ON %P 365- %O May 17-21 %A Baecker, R. %A Marcus, A. %D 1983 %T On enhancing the interface to the source code of computer programs %J Proc ACM CHI 83 Human Factors in Computing Systems %P 251-255 %C Boston, MA %O December 12-15 %K * %A Bailey, D. %D 1985 %T University of Salford Lisp/Prolog system %J Software -- Practice and Experience %V 15 %N 6 %P 595-609 %O June %K * %A Ball, G.H. %A Hall, D.J. %D 1965 %T ISODATA, a novel method of data analysis and pattern classification %R Report AD 699616 %I Stanford Research Institute %C Stanford, CA %A Bandyopadhyay, S. %A Hughes, J.G. %A Smith, F.J. %A Sen, K. %T A generalized scientific information system %R Report %I Computer Science Department, Queen's University of Belfast %C Belfast, Northern Ireland %K * %A Barber, G.R. %D 1981 %T Record of the workshop on research in office semantics %R AI Memo 620 %I MIT %O February %K * %A Barber, G.R. %D 1982 %T Office semantics %R PhD Thesis %I MIT %O February %A Barber, G.R. %D 1983 %T Supporting organizational problem solving with a workstation %J ACM Trans Office Information Systems %V 1 %N 1 %P 45-67 %O January %K * %A Barber, G.R. %A de\|Jong, P.S. %A Hewitt, C. %D 1983 %T Semantic support for work in organizations %R AI Memo 719 %I MIT Artificial Intelligence Laboratory %O April %K * %A Barnett, J.A. %D 1981 %T Computational methods for a mathematical theory of evidence %J Proc 7th International Joint Conference on Artificial Intelligence %P 868-875 %C Vancouver, BC %O August %A Barrow, H.G. %D 1979 %T Artificial intelligence: state of the art %R Technical Note 198 %I SRI International %C Menlo Park, CA %O October %A Barsky, B.A. %A Beatty, J.C. %D 1982 %T Varying the betas in beta-splines %R Report CS-82-49 %I University of Waterloo %O December %K * %A Barwise, J. %A Perry, J. %D 1983 %T Situations and attitudes %I MIT Press %C Cambridge, MA %A Barwise, J. %D 1985 %T The situation in logic II: conditionals and conditional information %R Report CSLI-85-21 %I Center for the study of language and information, Stanford University %C Stanford, CA %O January %K * %A Bates, E. %D 1979 %T The emergence of symbols %I Academic Press %A Beer, S. %D 1980 %R Preface to \fIAutopoiesis and cognition\fR (Maturana and Varela, 1980) %A Bell, T.C. %D 1985 %T Better OPM/L text compression %R Internal Report %I Computer Science Department, University of Canterbury %C Christchurch, New Zealand %K * %A Bell, T.C. %A Moffat, A.M. %D 1986 %T A note on the DMC data compression scheme %R Internal Report %I Computer Science Department, University of Canterbury %C Christchurch, New Zealand %A Bell, T.C. %D 1986 %T An introduction to text compression %R Internal Report %I Computer Science Department, University of Canterbury %C Christchurch, New Zealand %A Bellanger, M.G. %A Daguet, J.L. %A Lepagnol, G.P. %D 1974 %T Interpolation, extrapolation, and reduction of computation speed in digital filters %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-22 %N 4 %P 231-235 %O August %K * %A Benest, I.D. %A Jones, G. %D 1982 %T Computer emulation of books %J Proc IEE Conference Man-Machine Systems %P 267-271 %C Manchester, England %O July %A Benest, I.D. %A Potok, M.H.N. %D 1984 %T Wayfinding: an approach using signposting techniques %J Behaviour and Information Technology %V 3 %N 2 %P 99-107 %K * %A Bentley, J.L. %A Friedman, J.H. %D 1979 %T Data structures for range searching %J Computing Surveys %V 11 %N 4 %P 397-409 %O December %K * %A Bentley, J.L. %D 1980 %T Multidimensional divide-and-conquer %J Comm ACM %V 23 %N 4 %P 214-229 %K * %A Bentley, J.L. %A Sleator, D.D. %A Tarjan, R.E. %A Wei, V.K. %D 1986 %T A locally adaptive data compression scheme %J Comm ACM %V 29 %N 4 %P 320-330 %O April %A Berglund, E.J. %A Cheriton, D.R. %T Amaze -- A distributed multi-player game program using the Distributed V Kernel %K * %A Bewley, W.L. %A Roberts, T.L. %A Schroit, D. %A Verplank, W.L. %D 1983 %T Human factors testing in the design of Xerox's 8010 `Star' office workstation %J Proc ACM CHI 83 Human Factors in Computing Systems %P 72-77 %C Boston, MA %O December 12-15 %K * %A Bezdek, J.C. %D 1980 %T A convergence theorem for the fuzzy ISODATA clustering algorithms %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-2 %N 1 %P 1-8 %O January %K * %A Bibel, W. %D 1983 %T Matings in matrices %J Comm ACM %V 26 %N 11 %P 844-852 %O November %K * %A Biederman, I. %D 1985 %T Human image understanding: recent research and a theory %J Computer Vision, Graphics, and Image Processing %V 32 %N 1 %P 29-73 %O October. %A Bigelow, C. %A Day, D. %D 1983 %T Digital typography %J Scientific American %V 249 %N 2 %P 106-119 %O August %K * %A Bigelow, C. %D 1984 %T Principles of font design for the personal workstation %R Research Report %I Stanford University %K * %A Bigelow, C. %D 1986 %T Notes on typeface protection %K * %A Birkhoff, G. %D 1967 %T Lattice theory %I American Mathematical Society %C Providence, RI %A Birrell, A.D. %A Levin, R. %A Needham R.M. %A Schroeder, M.D. %D 1982 %T Grapevine: an exercise in distributed computing %J Comm ACM %V 25 %N 4 %P 260-274 %O April %K * %A Birtwistle, G.M. %A Dahl, O.J. %A Myhrhaug, B. %A Nygaard, K. %D 1973 %T Simula Begin %I Auerbach %C Philadelphia, PA %A Birtwistle, G. %A Cleary, J.G. %A Joyce, J. %A Liblong, B. %A Unger, B.W. %A Witten, I.H. %A Wyvill, B.L.M. %D 1984 %T A simulation environment %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 290-296 %O May %K KConference %A Blakeslee, T.R. %D 1980 %T The right brain %I MacMillan %C London, England %A Bobrow, D.G. %D 1985 %T If Prolog is the answer, what is the question? or What it takes to support AI programming paradigms %J IEEE Trans Software Engineering %V SE-11 %N 11 %P 1401-1408 %O November %K * %A Boehm-Davis, D.A. %A Fregly, A.M. %D 1983 %T Documentation of concurrent programs %J Proc ACM CHI 83 Human Factors in Computing Systems %P 256-261 %C Boston, MA %O December 12-15 %K * %A Bonham, M. %A Witten, I.H. %D 1984 %T Towards distributed document preparation with interactive and noninteractive viewing %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 365-372 %O May %K KConference %A Bonham, M. %A Witten, I.H. %D 1985 %T Towards distributed document preparation with interactive and noninteractive viewing %J Infor %V 23 %N 4 %P 365-388 %O November %K KJournal %A Bonham, M. %A Witten, I.H. %D 1985 %T More on `A large font virtual terminal interface: a software prosthesis for the visually impaired' %J Comm ACM %V 28 %N 11 %P 1236-1237 %O November %K KCorrespondence %A Bonham, M. %A Witten, I.H. %D 1985 %T Shape \(em a unifying concept in document layout %J Proc PROTEXT II -- Second International Conference on Text Processing Systems %I Boole Press %C Dublin, Ireland %P 126-132 %O October %K KConference %A Bonner, S. %A Shin, K. %D 1982 %T A comparative study of robot languages %J IEEE Computer %V 15 %N 12 %P 82-96 %A Boose, J.H. %D 1986 %T Rapid acquisition and combination of knowledge from multiple experts in the same domain %J Proc International Conference on Future Advances in Computing %C Christchurch, New Zealand %O February 17-21 %K * %A Booth, T.L. %D 1984 %T Computer education %J IEEE Computer %V 17 %N 10 %P 57-68 %O October %K * %A Borning, A. %D 1981 %T The programming language aspects of ThingLab, a constraint-oriented simulation laboratory %J ACM Trans Programming Languages and Systems %V 3 %N 4 %P 353-387 %O October %K * %A Bouachache, B. %D 1983 %T Wigner analysis of time-varying signals %B Signal processing II: Theories and applications %E H.W.Schussler %I Elsevier Science Publishers B.V. (North Holland) %P 703-706 %K * %A Bouachache, B. %A Rodriguez, F. %D 1984 %T Recognition of time-varying signals in the time-frequency domain by means of the Wigner distribution %J Proc International Circuits and Systems Symposium %K * %A Bouachache, B. %A Whitehouse, H.J. %D 1985 %T Seismic applications of the Wigner-Ville distribution %J Proc International Circuits and Systems Symposium %C San Jose, CA %O May 5 %K * %A Boulton, P.I.P. %A Lee, E.S. %D 1983 %T The performance of Hubnet %J Proc International Electrical, Electronics Conference %V 2 %P 450-453 %C Toronto, ON %O September 26-28 %K * %A Bower, G.H. %A Black, J.B. %D 1979 %T Scripts in memory for text %J Cognitive Psychology %V 11 %P 177-220 %K * %A Brachman, R.J. %D 1983 %T What IS-A is and isn't: an analysis of taxonomic links in semantic networks %J IEEE Computer %V 16 %N 10 %P 30-36 %O October %K * %A Brachman, R.J. %A Schmolze, J.G. %D 1985 %T An overview of the KL-ONE knowledge representation scheme %J Cognitive Science %V 9 %N ii %P 171-216 %K * %A Bramer, M.A.\0(Editor) %D 1985 %T Research and development in expert systems %I Cambridge University Press %C Cambridge, England %O (Proc 4th Conference of BCS Group on Expert Systems, December 1984) %A Bramwell, B. %D 1984 %T Browsing around a manual %J Proc Canadian Information Processing Society Conference %C Calgary, AL %P 438-442 %O May %K * %A Britton, B.K. %A Black, J.B.\0(Editors) %D 1985 %T Understanding expository text: a theoretical and practical handbook for analyzing explanatory text %I Erlbaum %C Hillsdale, NJ %A Brown, K.Q. %D 1979 %T Voroni diagrams from convex hulls %J Information Processing Letters %V 9 %N 5 %P 223-228 %O December %K * %A Brown, P.J. %D 1984 %T Interactive documentation %R Internal Report %I Computing Laboratory, University of Kent %O April %K * %A Brown, J.S. %A Burton, R.R. %D 1975 %T Multiple representations of knowledge for tutorial reasoning %B Representation of Learning %E D.G. Bobrow and A. Collins %I Academic Press %C New York, NY %A Brownston, L. %A Farrell, R. %A Kant, E. %A Martin, N. %D 1985 %T Programming expert systems in OPS-5: an introduction to rule-based programming %I Addison-Wesley %C Reading, MA %A Brunner, J. %D 1975 %T The shockwave rider %I Ballantine %C New York, NY %A Bruynooghs, M. %D 1982 %T Adding redundancy to obtain more reliable and more readable Prolog programs %J Proc 1st International Logic Programming Conference %C Marseille, France %P 129-133 %O September 14-17 %K * %A Bryant, J. %D 1979 %T On the clustering of multidimensional pictorial data %J Pattern Recognition %V 11 %P 115-125 %K * %A Buchman, C. %A Berry, D.M. %T An adaptation of the Unix DITROFF for formatting bidirectional text %I Computer Science Department, University of California %C Los Angeles, CA %K * %A Bundy, A. %A Silver, B. %A Plummer, D. %D 1985 %T An analytical comparison of some rule-learning programs %J Artificial Intelligence %V 27 %P 137-181 %A Bundy, A. %D 1983 %T The computer modelling of mathematical reasoning %A Academic Press %C London, England %A Burton, R.R. %A Brown, J.S. %D 1979 %T An investigation of computer coaching for informal learning activities %J IJMMS %V 11 %N 1 %P 5-24 %O January %A Bush, V. %D 1945 %T As we may think %J Atlantic Monthly %P 101 %O July %A Byrd, R.J. %A Smith, S.E. %A de\|Jong, S.P. %D 1982 %T An actor-based programming system %J Proc SIGOA Conference on Office Information Systems %P 67-78 %C Philadelphia, PA %O June 21-23 %K * %A Campbell, F.W. %A Robson, J.G. %D 1967 %T Application of fourier analysis to the visibility of gratings %J Physiol %N 197 %P 551-566 %I University of Cambridge %K * %A Cannon, W.B. %D 1932 %T The wisdom of the body %I London %A Carroll, J.B. %D 1967 %T On sampling from a lognormal model of word-frequency distribution %B Computational analysis of present-day American English %E Kucera, H. and Francis, W.N. %I Brown University Press %C Providence, RI %P 406-424 %K * %A Carroll, J.B. %D 1966 %T Word-frequency studies and the lognormal distribution %E E.M.Zale %B Proc Conference on Language and Language Behavior %I Appleton-Century-Crofts %C New York, NY %P 213-235 %K * %A Carroll, J.M. %A Thomas, J.C. %D 1982 %T Metaphor and the cognitive representation of computing systems %J IEEE Trans Systems, Man and Cybernetics %V SMC-12 %N 2 %P 107-116 %O March/April %K * %A Carter, K.A. %D 1984 %T The Rainbow workstation in brief/A window manager for the Rainbow workstation %R Rainbow Group Note %I Computer Laboratory, University of Cambridge %O May %K * %A Casey, R.G. %A Friedman, T.D. %A Wong, K.Y. %D 1982 %T Automatic scaling of digital fonts %J IBM J Research and Development %V 26 %P 657-666 %A Casey, R.G. %A Nagy, G. %D 1984 %T Decision tree design using a probabilistic model TJ IEEE Trans Information Theory %V IT-30 %N 1 %P 93-99 %O January %K * %A Cater, J.P. %D 1983 %T Electronically speaking: computer speech generation %I Howard W. Sams %C Indianapolis, IN %A Catmull, E. %D 1981 %T New frontiers in computer animation %J American Cinematographer %P 157-163 %O October %A Cendrowska, J. %A Bramer, M.A. %D 1984 %T A rational reconstruction of the Mycin consultation system %J IJMMS %V 20 %P 229-317 %A Chapanis, A. %D 1984 %T Taming and civilizing computers %B Computer culture: the scientific, intellectual, and social impact of the computer %E Heinz R. Pagels %I New York Academy of Sciences %C New York, NY %P 202-219 %K * %A Chazelle, B. %D 1983 %T A decision procedure for optimal polyhedron partitioning %J Information Processing Letters %V 16 %P 75-78 %O February 26 %K * %A Cheeseman, P. %D 1985 %T In defense of probability %J Proc 10th International Joint Conference on Artificial Intelligence %P 100R2-1009 %A Cheriton, D.R. %A Zwaenepoel, W. %D 1983 %T The distributed V kernel and its performance for diskless workstations %R Report No STAN-CS-83-973 %I Stanford University, Computer Science Department %C Stanford, CA %O July %K * %A Christodoulakis, S %A Faloutsos, C. %D 1984 %T Design considerations for a message file server %J IEEE Trans Software Engineering %V SE-10 %N 2 %P 201-210 %O March %K * %A Ciminiere, L. %A Valenzano, A. %D 1984 %T iAPX 432 hardware fault handling mechanisms %K * %A Clancey, W.J. %D 1979 %T Tutoring rules for guiding a case method dialogue %J IJMMS %V 11 %P 25-49 %K * %A Clancey, W.J. %D 1983 %T The epistemology of a rule-based expert system \(em a framework for explanation %J Artificial Intelligence %V 20 %P 215-251 %K * %A Clancey, W.J. %A Shortliffe, E.H. \0(Editors) %D 1984 %T Readings in medical artificial intelligence %I Addison-Wesley %C Reading, MA %A Clarkson, T. %T Eye position sensor %R Section 7 of a report %I King's College %C London, England %K * %A Cleary, J.G. %D 1979 %T Analysis of an algorithm for finding nearest neighbors in Euclidean space %J ACM Trans Mathematical Software %V 5 %N 2 %P 183-192 %O June %K * %A Cleary, J.G. %D 1984 %T Compact hash tables using bidirectional linear probing %J IEEE Trans Computers %V C-33 %N 9 %P 828-834 %O September %A Cleary, J.G. %A Darragh, J.J. %D 1984 %T A fast compact representation of trees using hash tables %R Research Report 83/162/20 %I Computer Science Department, University of Calgary %O Submitted to \fIIEEE Trans Computers\fP %A Cleary, J.G. %A Witten, I.H. %D in preparation %T Universal data compression %A Clocksin, W.A. %D 1984 %T Introduction to Prolog %B Artificial Intelligence: tools, techniques, and applications %E T.O'Shea and M.Eisenstadt %I Harper and Row %C New York, NY %A Codd, E.F. %D 1968 %T Cellular automata %I Academic Press %C London, England %A Codd, E.F. %D 1978 %T How about recently? %B Databases: Improving usability and responsiveness %E B. Shneiderman (Ed.) %I Academic Press %C New York, NY %P 3-28 %A Cohen, E.S. %A Smith, E.T. %A Iverson, L.A. %D 1985 %T Constraint-based tiled windows %R Research Report %I Computer Science Department, Carnegie-Mellon University %A Cohen, J. %D 1985 %T Describing Prolog by its interpretation and compilation %J Comm ACM %V 28 %N 12 %P 1311-1324 %O December %K * %A Colby, K.M. %D 1973 %T Simulations of belief systems %E R.C.Schank and K.M.Colby %B Computer models of thought and language %I Freeman %C San Francisco, CA %P 251-286 %A Colmaurer, A. %A Colmaurer, C. %D 1983 %T Prolog en 10 figures %J TSI %V 2 %N 4 %O July-August %K * %A Colmerauer, A. %D 1985 %T Prolog in 10 figures %J Comm ACM %V 28 %N 12 %P 1296-1310 %O December %K * %A Colmaurer, A. %T An interesting subset of natural language %K * %A Comer, D.E. %A Peterson, L.L. %T Conversation-based mail %J ACM Transactions on computer systems %V 4 %N 4 %O November %K * %A Computer\|Science\|Department %D 1983 %T CPSC Student Handbook %I University of Calgary %A Coombs, M. %A Alty, J. %D 1984 %T Expert systems: an alternative paradigm %J IJMMS %V 20 %N 1 %P 21-43 %O January %K * %A Corbett, C. %D 1983 %T MC nroff/troff macros reference manual %R Report EES-MMS-1983-2 %I Department of Electrical Engineering Science, University of Essex %C Colchester, Essex, UK %K * %A Corbett, C. %D 1983 %T Figure processing within nroff %J Presented at EUUG Meeting %C Dublin, Ireland %O September %K * %A Cormack, G.V. %A Horspool, R.N. %D 1984 %T Algorithms for adaptive Huffman codes %J Information Processing Letters %V 18 %N 3 %P 159-166 %O March %K * %A Cormack, G.V. %A Horspool, R.N. %D 1985 %T Data compression using dynamic Markov modelling %R Research Report %I Computer Science Department, University of Waterloo %O April; submitted to Comm ACM %K * %A Costigan, D.M. %D 1978 %T Electronic delivery of documents and graphics %I Van Nostrand Reinhold %C New York, NY %A Coulon, D. %A Kayser, D. %D 1979 %T Construction of natural language sentence acceptors by a supervised-learning technique %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-1 %N 1 %P 94-99 %O January %K * %A Cove, J.F. %A Walsh, B.C. %D 1988 %T A taxonomy of browsing %R Working Paper 85/2 %I Computer Science Department, University of Liverpool %O April %K * %A Cox, B.J. %D 1986 %T Object oriented programming %I Addison-Wesley %C Reading, MA %A Crochiere, R.E. %A Rabiner, L.R. %D 1975 %T Optimum FIR digital filter implementations for decimation, interpolation, and narrow-band filtering %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-23 %N 5 %P 444-456 %O October %K * %A Crochiere, R.E. %A Rabiner, L.R. %D 1976 %T Further considerations in the design of decimators and interpolators %J IEEE Trans Acoustics, Speech and Signal Processing %V ASSP-24 %N 4 %P 296-311 %O August %K * %A Croft, W.B. %A Lefkowitz, L.S. %D 1984 %T Task support in an office system %J ACM Trans Office Information Systems %V 2 %N 3 %P 197-212 %O July %K * %A Croft, W.B. %D 1984 %T The role of context and adaptation in user interfaces %J IJMMS %V 21 %N 4 %P 283-292 %O October %A Csuri, C. %D 1974 %T Computer graphics and art %J Proc IEEE %O April %A Cuff, R.N. %D 1982 %T Database query using menus and natural language fragments %R PhD Thesis %I Man-Machine Systems Laboratory, Department of Electrical Engineering Science, University of Essex %C Colchester, Essex, UK %A Cuff, R.N. %D 1984 %T HERCULES: database query using natural language fragments %J Proc 3rd British National Conference on Database Systems %C Leeds %O July %K * %A Cullingford, R.E. %D 1978 %T Script application: computer understanding of newspaper stories %R PhD Thesis, Research Report 116 %I Yale University %A Cullingford, R.E. %A Krueger, M.W. %A Selfridge, M. %A Bienkowski, M.A. %D 1982 %T Automated explanations as a component of a computer-aided design system %J IEEE Trans Systems, Man and Cybernetics %V SMC-12 %N 2 %P 168-181 %O March/April %K * %A Cullingford, R.E. %A Pazzani, M.J. %D 1984 %T Word-meaning selection in multiprocess language understanding programs %J IEEE Trans Pattern Analysis and Machine Intelligence %V PAMI-6 %N 4 %P 493-509 %O July %K * %A Curry, G. %A Baer, L. %A Lipkie, D. %A Lee, B. %D 1982 %T Traits: an approach to multiple-inheritance subclassing %J ACM Conference on Office Information Systems %P 1-9 %O June %K * %A Damper, R.I. %A MacDonald, S.L. %D 1984 %T Template adaptation in speech recognition %J Proc Institute of Acoustics %V 6 %N 4 %P 293-299 %K * %A Damper, R.I. %A MacDonald, S.L. %D 1984 %T Statistical clustering procedures applied to low-cost speech recognition %J J Biomed Engineering %V 6 %P 265-271 %O October %K * %A Darragh, J.J. %A Witten, I.H. %A Cleary, J.G. %D 1983 %T Adaptive text compression to enhance a modem %R Research Report 83/132/21 %I Computer Science Department, University of Calgary %K KReport %A Davis, R. %D 1979 %T Interactive transfer of expertise: acquisition of new inference rules %J Artificial Intelligence %V 12 %N 2 %P 121-157 %K * %A Davis, R. %A Lenat, D.B. %D 1982 %T Knowledge-based systems in artificial intelligence %I McGraw Hill %C New York, NY %A Day, J.D. %A Zimmermann, H. %D 1983 %T The OSI reference model %J Proc IEEE %V 71 %N 12 %P 1334-1340 %O December %A Defude, B. %D 1984 %T Knowledge based systems versus thesaurus: an architecture problem about expert systems design %J Proc 3rd Joint BCS and ACM Symposium (King's College, Cambridge) %I Cambridge University Press %P 267-280 %O July %K * %A de\|Beaugrande, R. %D 1980 %T Text, discourse and process: towards a multidisciplinary science of texts %I Ablex Publishing Corporation %C Norwood, NJ %A de\|Jong, G. %D 1979 %T Prediction and substantiation: two processes that comprise understanding %J Proc International Joint Conference on Artificial Intelligence %C Tokyo, Japan %P 217-222 %O August %A de\|Jong, G. %D 1981 %T Generalizations based on explanations %J Proc IJCAI 81 %P 67-69 %K * %A de\|Jong, S.P. %D 1980 %T The system for business automation (SBA): a unified application development system %B Information Processing 80 %E S.H.Lavington %P 469-474 %I North Holland %K * %A de\|Leon, L. %A Harris, W.G. %A Evens, M. %D 1983 %T Is there really trouble with Unix? %J Proc ACM CHI 83 Human Factors in Computing Systems %P 125-129 %C Boston, MA %O December 12-15 %A Dietterich, T.G. %A Michalski, R.S. %D 1983 %T A comparative review of selected methods for learning from examples %B Machine learning %E R.S. Michalski, J.G. Carbonell, and T.M. Mitchell %I Tioga %P 41-81 %A Denning, P.J. %D 1982 %T Computer-based predictive writing %J Comm ACM %V 25 %N 5 %P 315-316 %O May %K * %A Denning, P.J. %D 1984 %T Educational ruminations %J Comm ACM %V 27 %N 10 %P 979-983 %O October %A Denning, P.J. %D 1985 %T The science of computing: what is Computer Science? %J American Scientist %V 73 %O January/February %K * %A Dewdney, A.K. %D 1984 %T Computer recreations %J Scientific American %V 250 %N 5 %P 14-22 %O May %A Downs, T. %A Cook, A.S. %A Rogers, G. %D 1984 %T A partitioning approach to yield estimation for large circuits and systems %J IEEE Trans Circuits and Systems %V CAS-31 %N 5 %P 472-485 %O May %K * %A Downs, T. %D 1985 %T An approach to the modeling of software testing with some applications %J IEEE Trans Software Engineering %V SE-11 %N 4 %P 375-386 %O April %K * %A Drummond, M. %D 1983 %T A proposal to study the cost-effectiveness of planning, acting, and sensing %R DAI Working paper %I Department of Artificial Intelligence, University of Edinburgh %K * %A Dubes, R. %A Jain, A.K. %D 1979 %T Validity studies in clustering methodologies %J Pattern Recognition %V 11 %P 225-254 %K * %A Duda, R. %A Gaschnig, J. %A Hart, P. %D 1979 %T Model design in the Prospector consultant system for mineral exploration %E D. Michie %B Expert systems in the microelectronic age %I Edinburgh University Press %K * %A Dumais, S. %A Landauer, T. %D 1982 %T Psychological investigations of natural terminology for command and query languages %B Directions in human/computer interactions %E Badre and Shneiderman %I Ablex Publishing Corporation %C Norwood, NJ %P 95-110 %A Dumais, S. %A Landauer, T. %D 1983 %T Using examples to describe categories %J Proc ACM CHI 83 Human Factors in Computing Systems %P 112-115 %C Boston, MA %O December 12-15 %K * %A Dunham, M.O. %A Gray, R.M. %D 1985 %T An algorithm for the design of labeled-transition finite-state vector quantization %J IEEE Trans Communications %V COM-33 %N 1 %P 83-89 %O January %K * %A Dyer, M.G. %D 1983 %T In-depth understanding %I MIT Press %C Cambridge, MA %A Dynkin, E.B. %D 1965 %T Controlled random sequences %J Theoretical Probability and its Applications %V X %N 1 %K * %A Eason, K.D. %A Damodaran, L %D 1979 %T Design procedures for user involvement and user support %J Infotech - Man Computer Communications %C London, England %A Edelsbrunner, H. %A Maurer, H.A. %D 1985 %T Finding extreme points in three dimensions and solving the post-office problem in the plane %J Information Processing Letters %V 21 %P 39-47 %O 10 July %K * %A Efron, B. %A Thisted, R. %D 1976 %T Estimating the number of unseen species: how many words did Shakespeare know? %J Biometrika %V 63 %N 3 %P 435-447 %K * %A Eisenstadt, E. %A Hasemar, T. %D 1985 %T An improved user interface for Prolog %E B.Shackel %B Human-Computer Interaction: Proceedings INTERACT 84 %I North Holland %P 109-113 %K * %A Ekeberg, O. %D 1986 %T Robust dictionary lookup using associative methods %R Research Report %I Computer Vision and Associative Pattern Processing Laboratory, Department of Computing Science, Royal Institute of Technology %C Stockholm, Sweden %K * %A Elias, P. %D 1955 %T Predictive coding: Part I and Part II %J IRE Trans Information Theory %V IT-1 %N 1 %P 16-33 %K * %A Elias, P. %D 1970 %T Bounds on performance of optimum quantizers %J IEEE Trans Information Theory %V IT-16 %N 2 %P 172-184 %O March %K * %A Elias, P. %D 1975 %T Universal codeword sets and representations of the integers %J IEEE Trans Information Theory %V IT-21 %N 2 %P 194-203 %O March %K * %A Elliott, S.J. %A Nelson, P.A. %D 1985 %T An algorithm for multichannel LMS adaptive filtering %R Research Report %I Institute of Sound and Vibration Research, University of Southampton %C Southampton, England %K * %A Ellis, C.A. %A Nutt, G.J. %D 1979 %T On the equivalence of office models %R Research Report SSL-79-8 %I Xerox PARC %O December %K * %A Ellis, C.A. %T Formal and informal models of office activity %R Research Report %I Xerox PARC %K * %A Ellis, C.A. %A Bernal, M. %D 1982 %T Officetalk-D: an experimental office information system %J Proc ACM Conference %P 131-140 %K * %A Embley, D.W. %A Nagy, G. %D 1981 %T Behavioral aspects of text editors %J Computing Surveys %V 13 %N 1 %P 33-70 %O March %K * %A Engel F.L. %A Andriessen J.J. %A Schmitz, H.J.R. %D 1983 %T What, where and whence: means for improving electronic data access %J IJMMS %V 18 %P 145-160 %A Englebart, D.C. %A English, W.K. %D 1968 %T A research center for augmenting human intellect %J Proc Fall Joint Computer Conference %V 33 %P 395-410 %I AFIPS Press %C Arlington, VA %A Ernvallqatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/canterbury000066400000000000000000124366751503624047500341570ustar00rootroot00000000000000 ALICE'S ADVENTURES IN WONDERLAND Lewis Carroll THE MILLENNIUM FULCRUM EDITION 2.9 CHAPTER I Down the Rabbit-Hole Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, `and what is the use of a book,' thought Alice `without pictures or conversation?' So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her. There was nothing so VERY remarkable in that; nor did Alice think it so VERY much out of the way to hear the Rabbit say to itself, `Oh dear! Oh dear! I shall be late!' (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT- POCKET, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge. In another moment down went Alice after it, never once considering how in the world she was to get out again. The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well. Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. She took down a jar from one of the shelves as she passed; it was labelled `ORANGE MARMALADE', but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it. `Well!' thought Alice to herself, `after such a fall as this, I shall think nothing of tumbling down stairs! How brave they'll all think me at home! Why, I wouldn't say anything about it, even if I fell off the top of the house!' (Which was very likely true.) Down, down, down. Would the fall NEVER come to an end! `I wonder how many miles I've fallen by this time?' she said aloud. `I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think--' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a VERY good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) `--yes, that's about the right distance--but then I wonder what Latitude or Longitude I've got to?' (Alice had no idea what Latitude was, or Longitude either, but thought they were nice grand words to say.) Presently she began again. `I wonder if I shall fall right THROUGH the earth! How funny it'll seem to come out among the people that walk with their heads downward! The Antipathies, I think--' (she was rather glad there WAS no one listening, this time, as it didn't sound at all the right word) `--but I shall have to ask them what the name of the country is, you know. Please, Ma'am, is this New Zealand or Australia?' (and she tried to curtsey as she spoke--fancy CURTSEYING as you're falling through the air! Do you think you could manage it?) `And what an ignorant little girl she'll think me for asking! No, it'll never do to ask: perhaps I shall see it written up somewhere.' Down, down, down. There was nothing else to do, so Alice soon began talking again. `Dinah'll miss me very much to-night, I should think!' (Dinah was the cat.) `I hope they'll remember her saucer of milk at tea-time. Dinah my dear! I wish you were down here with me! There are no mice in the air, I'm afraid, but you might catch a bat, and that's very like a mouse, you know. But do cats eat bats, I wonder?' And here Alice began to get rather sleepy, and went on saying to herself, in a dreamy sort of way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do bats eat cats?' for, you see, as she couldn't answer either question, it didn't much matter which way she put it. She felt that she was dozing off, and had just begun to dream that she was walking hand in hand with Dinah, and saying to her very earnestly, `Now, Dinah, tell me the truth: did you ever eat a bat?' when suddenly, thump! thump! down she came upon a heap of sticks and dry leaves, and the fall was over. Alice was not a bit hurt, and she jumped up on to her feet in a moment: she looked up, but it was all dark overhead; before her was another long passage, and the White Rabbit was still in sight, hurrying down it. There was not a moment to be lost: away went Alice like the wind, and was just in time to hear it say, as it turned a corner, `Oh my ears and whiskers, how late it's getting!' She was close behind it when she turned the corner, but the Rabbit was no longer to be seen: she found herself in a long, low hall, which was lit up by a row of lamps hanging from the roof. There were doors all round the hall, but they were all locked; and when Alice had been all the way down one side and up the other, trying every door, she walked sadly down the middle, wondering how she was ever to get out again. Suddenly she came upon a little three-legged table, all made of solid glass; there was nothing on it except a tiny golden key, and Alice's first thought was that it might belong to one of the doors of the hall; but, alas! either the locks were too large, or the key was too small, but at any rate it would not open any of them. However, on the second time round, she came upon a low curtain she had not noticed before, and behind it was a little door about fifteen inches high: she tried the little golden key in the lock, and to her great delight it fitted! Alice opened the door and found that it led into a small passage, not much larger than a rat-hole: she knelt down and looked along the passage into the loveliest garden you ever saw. How she longed to get out of that dark hall, and wander about among those beds of bright flowers and those cool fountains, but she could not even get her head though the doorway; `and even if my head would go through,' thought poor Alice, `it would be of very little use without my shoulders. Oh, how I wish I could shut up like a telescope! I think I could, if I only know how to begin.' For, you see, so many out-of-the-way things had happened lately, that Alice had begun to think that very few things indeed were really impossible. There seemed to be no use in waiting by the little door, so she went back to the table, half hoping she might find another key on it, or at any rate a book of rules for shutting people up like telescopes: this time she found a little bottle on it, (`which certainly was not here before,' said Alice,) and round the neck of the bottle was a paper label, with the words `DRINK ME' beautifully printed on it in large letters. It was all very well to say `Drink me,' but the wise little Alice was not going to do THAT in a hurry. `No, I'll look first,' she said, `and see whether it's marked "poison" or not'; for she had read several nice little histories about children who had got burnt, and eaten up by wild beasts and other unpleasant things, all because they WOULD not remember the simple rules their friends had taught them: such as, that a red-hot poker will burn you if you hold it too long; and that if you cut your finger VERY deeply with a knife, it usually bleeds; and she had never forgotten that, if you drink much from a bottle marked `poison,' it is almost certain to disagree with you, sooner or later. However, this bottle was NOT marked `poison,' so Alice ventured to taste it, and finding it very nice, (it had, in fact, a sort of mixed flavour of cherry-tart, custard, pine-apple, roast turkey, toffee, and hot buttered toast,) she very soon finished it off. * * * * * * * * * * * * * * * * * * * * `What a curious feeling!' said Alice; `I must be shutting up like a telescope.' And so it was indeed: she was now only ten inches high, and her face brightened up at the thought that she was now the right size for going though the little door into that lovely garden. First, however, she waited for a few minutes to see if she was going to shrink any further: she felt a little nervous about this; `for it might end, you know,' said Alice to herself, `in my going out altogether, like a candle. I wonder what I should be like then?' And she tried to fancy what the flame of a candle is like after the candle is blown out, for she could not remember ever having seen such a thing. After a while, finding that nothing more happened, she decided on going into the garden at once; but, alas for poor Alice! when she got to the door, she found he had forgotten the little golden key, and when she went back to the table for it, she found she could not possibly reach it: she could see it quite plainly through the glass, and she tried her best to climb up one of the legs of the table, but it was too slippery; and when she had tired herself out with trying, the poor little thing sat down and cried. `Come, there's no use in crying like that!' said Alice to herself, rather sharply; `I advise you to leave off this minute!' She generally gave herself very good advice, (though she very seldom followed it), and sometimes she scolded herself so severely as to bring tears into her eyes; and once she remembered trying to box her own ears for having cheated herself in a game of croquet she was playing against herself, for this curious child was very fond of pretending to be two people. `But it's no use now,' thought poor Alice, `to pretend to be two people! Why, there's hardly enough of me left to make ONE respectable person!' Soon her eye fell on a little glass box that was lying under the table: she opened it, and found in it a very small cake, on which the words `EAT ME' were beautifully marked in currants. `Well, I'll eat it,' said Alice, `and if it makes me grow larger, I can reach the key; and if it makes me grow smaller, I can creep under the door; so either way I'll get into the garden, and I don't care which happens!' She ate a little bit, and said anxiously to herself, `Which way? Which way?', holding her hand on the top of her head to feel which way it was growing, and she was quite surprised to find that she remained the same size: to be sure, this generally happens when one eats cake, but Alice had got so much into the way of expecting nothing but out-of-the-way things to happen, that it seemed quite dull and stupid for life to go on in the common way. So she set to work, and very soon finished off the cake. * * * * * * * * * * * * * * * * * * * * CHAPTER II The Pool of Tears `Curiouser and curiouser!' cried Alice (she was so much surprised, that for the moment she quite forgot how to speak good English); `now I'm opening out like the largest telescope that ever was! Good-bye, feet!' (for when she looked down at her feet, they seemed to be almost out of sight, they were getting so far off). `Oh, my poor little feet, I wonder who will put on your shoes and stockings for you now, dears? I'm sure _I_ shan't be able! I shall be a great deal too far off to trouble myself about you: you must manage the best way you can; --but I must be kind to them,' thought Alice, `or perhaps they won't walk the way I want to go! Let me see: I'll give them a new pair of boots every Christmas.' And she went on planning to herself how she would manage it. `They must go by the carrier,' she thought; `and how funny it'll seem, sending presents to one's own feet! And how odd the directions will look! ALICE'S RIGHT FOOT, ESQ. HEARTHRUG, NEAR THE FENDER, (WITH ALICE'S LOVE). Oh dear, what nonsense I'm talking!' Just then her head struck against the roof of the hall: in fact she was now more than nine feet high, and she at once took up the little golden key and hurried off to the garden door. Poor Alice! It was as much as she could do, lying down on one side, to look through into the garden with one eye; but to get through was more hopeless than ever: she sat down and began to cry again. `You ought to be ashamed of yourself,' said Alice, `a great girl like you,' (she might well say this), `to go on crying in this way! Stop this moment, I tell you!' But she went on all the same, shedding gallons of tears, until there was a large pool all round her, about four inches deep and reaching half down the hall. After a time she heard a little pattering of feet in the distance, and she hastily dried her eyes to see what was coming. It was the White Rabbit returning, splendidly dressed, with a pair of white kid gloves in one hand and a large fan in the other: he came trotting along in a great hurry, muttering to himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she be savage if I've kept her waiting!' Alice felt so desperate that she was ready to ask help of any one; so, when the Rabbit came near her, she began, in a low, timid voice, `If you please, sir--' The Rabbit started violently, dropped the white kid gloves and the fan, and skurried away into the darkness as hard as he could go. Alice took up the fan and gloves, and, as the hall was very hot, she kept fanning herself all the time she went on talking: `Dear, dear! How queer everything is to-day! And yesterday things went on just as usual. I wonder if I've been changed in the night? Let me think: was I the same when I got up this morning? I almost think I can remember feeling a little different. But if I'm not the same, the next question is, Who in the world am I? Ah, THAT'S the great puzzle!' And she began thinking over all the children she knew that were of the same age as herself, to see if she could have been changed for any of them. `I'm sure I'm not Ada,' she said, `for her hair goes in such long ringlets, and mine doesn't go in ringlets at all; and I'm sure I can't be Mabel, for I know all sorts of things, and she, oh! she knows such a very little! Besides, SHE'S she, and I'm I, and--oh dear, how puzzling it all is! I'll try if I know all the things I used to know. Let me see: four times five is twelve, and four times six is thirteen, and four times seven is--oh dear! I shall never get to twenty at that rate! However, the Multiplication Table doesn't signify: let's try Geography. London is the capital of Paris, and Paris is the capital of Rome, and Rome--no, THAT'S all wrong, I'm certain! I must have been changed for Mabel! I'll try and say "How doth the little--"' and she crossed her hands on her lap as if she were saying lessons, and began to repeat it, but her voice sounded hoarse and strange, and the words did not come the same as they used to do:-- `How doth the little crocodile Improve his shining tail, And pour the waters of the Nile On every golden scale! `How cheerfully he seems to grin, How neatly spread his claws, And welcome little fishes in With gently smiling jaws!' `I'm sure those are not the right words,' said poor Alice, and her eyes filled with tears again as she went on, `I must be Mabel after all, and I shall have to go and live in that poky little house, and have next to no toys to play with, and oh! ever so many lessons to learn! No, I've made up my mind about it; if I'm Mabel, I'll stay down here! It'll be no use their putting their heads down and saying "Come up again, dear!" I shall only look up and say "Who am I then? Tell me that first, and then, if I like being that person, I'll come up: if not, I'll stay down here till I'm somebody else"--but, oh dear!' cried Alice, with a sudden burst of tears, `I do wish they WOULD put their heads down! I am so VERY tired of being all alone here!' As she said this she looked down at her hands, and was surprised to see that she had put on one of the Rabbit's little white kid gloves while she was talking. `How CAN I have done that?' she thought. `I must be growing small again.' She got up and went to the table to measure herself by it, and found that, as nearly as she could guess, she was now about two feet high, and was going on shrinking rapidly: she soon found out that the cause of this was the fan she was holding, and she dropped it hastily, just in time to avoid shrinking away altogether. `That WAS a narrow escape!' said Alice, a good deal frightened at the sudden change, but very glad to find herself still in existence; `and now for the garden!' and she ran with all speed back to the little door: but, alas! the little door was shut again, and the little golden key was lying on the glass table as before, `and things are worse than ever,' thought the poor child, `for I never was so small as this before, never! And I declare it's too bad, that it is!' As she said these words her foot slipped, and in another moment, splash! she was up to her chin in salt water. He first idea was that she had somehow fallen into the sea, `and in that case I can go back by railway,' she said to herself. (Alice had been to the seaside once in her life, and had come to the general conclusion, that wherever you go to on the English coast you find a number of bathing machines in the sea, some children digging in the sand with wooden spades, then a row of lodging houses, and behind them a railway station.) However, she soon made out that she was in the pool of tears which she had wept when she was nine feet high. `I wish I hadn't cried so much!' said Alice, as she swam about, trying to find her way out. `I shall be punished for it now, I suppose, by being drowned in my own tears! That WILL be a queer thing, to be sure! However, everything is queer to-day.' Just then she heard something splashing about in the pool a little way off, and she swam nearer to make out what it was: at first she thought it must be a walrus or hippopotamus, but then she remembered how small she was now, and she soon made out that it was only a mouse that had slipped in like herself. `Would it be of any use, now,' thought Alice, `to speak to this mouse? Everything is so out-of-the-way down here, that I should think very likely it can talk: at any rate, there's no harm in trying.' So she began: `O Mouse, do you know the way out of this pool? I am very tired of swimming about here, O Mouse!' (Alice thought this must be the right way of speaking to a mouse: she had never done such a thing before, but she remembered having seen in her brother's Latin Grammar, `A mouse--of a mouse--to a mouse--a mouse--O mouse!' The Mouse looked at her rather inquisitively, and seemed to her to wink with one of its little eyes, but it said nothing. `Perhaps it doesn't understand English,' thought Alice; `I daresay it's a French mouse, come over with William the Conqueror.' (For, with all her knowledge of history, Alice had no very clear notion how long ago anything had happened.) So she began again: `Ou est ma chatte?' which was the first sentence in her French lesson-book. The Mouse gave a sudden leap out of the water, and seemed to quiver all over with fright. `Oh, I beg your pardon!' cried Alice hastily, afraid that she had hurt the poor animal's feelings. `I quite forgot you didn't like cats.' `Not like cats!' cried the Mouse, in a shrill, passionate voice. `Would YOU like cats if you were me?' `Well, perhaps not,' said Alice in a soothing tone: `don't be angry about it. And yet I wish I could show you our cat Dinah: I think you'd take a fancy to cats if you could only see her. She is such a dear quiet thing,' Alice went on, half to herself, as she swam lazily about in the pool, `and she sits purring so nicely by the fire, licking her paws and washing her face--and she is such a nice soft thing to nurse--and she's such a capital one for catching mice--oh, I beg your pardon!' cried Alice again, for this time the Mouse was bristling all over, and she felt certain it must be really offended. `We won't talk about her any more if you'd rather not.' `We indeed!' cried the Mouse, who was trembling down to the end of his tail. `As if I would talk on such a subject! Our family always HATED cats: nasty, low, vulgar things! Don't let me hear the name again!' `I won't indeed!' said Alice, in a great hurry to change the subject of conversation. `Are you--are you fond--of--of dogs?' The Mouse did not answer, so Alice went on eagerly: `There is such a nice little dog near our house I should like to show you! A little bright-eyed terrier, you know, with oh, such long curly brown hair! And it'll fetch things when you throw them, and it'll sit up and beg for its dinner, and all sorts of things--I can't remember half of them--and it belongs to a farmer, you know, and he says it's so useful, it's worth a hundred pounds! He says it kills all the rats and--oh dear!' cried Alice in a sorrowful tone, `I'm afraid I've offended it again!' For the Mouse was swimming away from her as hard as it could go, and making quite a commotion in the pool as it went. So she called softly after it, `Mouse dear! Do come back again, and we won't talk about cats or dogs either, if you don't like them!' When the Mouse heard this, it turned round and swam slowly back to her: its face was quite pale (with passion, Alice thought), and it said in a low trembling voice, `Let us get to the shore, and then I'll tell you my history, and you'll understand why it is I hate cats and dogs.' It was high time to go, for the pool was getting quite crowded with the birds and animals that had fallen into it: there were a Duck and a Dodo, a Lory and an Eaglet, and several other curious creatures. Alice led the way, and the whole party swam to the shore. CHAPTER III A Caucus-Race and a Long Tale They were indeed a queer-looking party that assembled on the bank--the birds with draggled feathers, the animals with their fur clinging close to them, and all dripping wet, cross, and uncomfortable. The first question of course was, how to get dry again: they had a consultation about this, and after a few minutes it seemed quite natural to Alice to find herself talking familiarly with them, as if she had known them all her life. Indeed, she had quite a long argument with the Lory, who at last turned sulky, and would only say, `I am older than you, and must know better'; and this Alice would not allow without knowing how old it was, and, as the Lory positively refused to tell its age, there was no more to be said. At last the Mouse, who seemed to be a person of authority among them, called out, `Sit down, all of you, and listen to me! I'LL soon make you dry enough!' They all sat down at once, in a large ring, with the Mouse in the middle. Alice kept her eyes anxiously fixed on it, for she felt sure she would catch a bad cold if she did not get dry very soon. `Ahem!' said the Mouse with an important air, `are you all ready? This is the driest thing I know. Silence all round, if you please! "William the Conqueror, whose cause was favoured by the pope, was soon submitted to by the English, who wanted leaders, and had been of late much accustomed to usurpation and conquest. Edwin and Morcar, the earls of Mercia and Northumbria--"' `Ugh!' said the Lory, with a shiver. `I beg your pardon!' said the Mouse, frowning, but very politely: `Did you speak?' `Not I!' said the Lory hastily. `I thought you did,' said the Mouse. `--I proceed. "Edwin and Morcar, the earls of Mercia and Northumbria, declared for him: and even Stigand, the patriotic archbishop of Canterbury, found it advisable--"' `Found WHAT?' said the Duck. `Found IT,' the Mouse replied rather crossly: `of course you know what "it" means.' `I know what "it" means well enough, when I find a thing,' said the Duck: `it's generally a frog or a worm. The question is, what did the archbishop find?' The Mouse did not notice this question, but hurriedly went on, `"--found it advisable to go with Edgar Atheling to meet William and offer him the crown. William's conduct at first was moderate. But the insolence of his Normans--" How are you getting on now, my dear?' it continued, turning to Alice as it spoke. `As wet as ever,' said Alice in a melancholy tone: `it doesn't seem to dry me at all.' `In that case,' said the Dodo solemnly, rising to its feet, `I move that the meeting adjourn, for the immediate adoption of more energetic remedies--' `Speak English!' said the Eaglet. `I don't know the meaning of half those long words, and, what's more, I don't believe you do either!' And the Eaglet bent down its head to hide a smile: some of the other birds tittered audibly. `What I was going to say,' said the Dodo in an offended tone, `was, that the best thing to get us dry would be a Caucus-race.' `What IS a Caucus-race?' said Alice; not that she wanted much to know, but the Dodo had paused as if it thought that SOMEBODY ought to speak, and no one else seemed inclined to say anything. `Why,' said the Dodo, `the best way to explain it is to do it.' (And, as you might like to try the thing yourself, some winter day, I will tell you how the Dodo managed it.) First it marked out a race-course, in a sort of circle, (`the exact shape doesn't matter,' it said,) and then all the party were placed along the course, here and there. There was no `One, two, three, and away,' but they began running when they liked, and left off when they liked, so that it was not easy to know when the race was over. However, when they had been running half an hour or so, and were quite dry again, the Dodo suddenly called out `The race is over!' and they all crowded round it, panting, and asking, `But who has won?' This question the Dodo could not answer without a great deal of thought, and it sat for a long time with one finger pressed upon its forehead (the position in which you usually see Shakespeare, in the pictures of him), while the rest waited in silence. At last the Dodo said, `EVERYBODY has won, and all must have prizes.' `But who is to give the prizes?' quite a chorus of voices asked. `Why, SHE, of course,' said the Dodo, pointing to Alice with one finger; and the whole party at once crowded round her, calling out in a confused way, `Prizes! Prizes!' Alice had no idea what to do, and in despair she put her hand in her pocket, and pulled out a box of comfits, (luckily the salt water had not got into it), and handed them round as prizes. There was exactly one a-piece all round. `But she must have a prize herself, you know,' said the Mouse. `Of course,' the Dodo replied very gravely. `What else have you got in your pocket?' he went on, turning to Alice. `Only a thimble,' said Alice sadly. `Hand it over here,' said the Dodo. Then they all crowded round her once more, while the Dodo solemnly presented the thimble, saying `We beg your acceptance of this elegant thimble'; and, when it had finished this short speech, they all cheered. Alice thought the whole thing very absurd, but they all looked so grave that she did not dare to laugh; and, as she could not think of anything to say, she simply bowed, and took the thimble, looking as solemn as she could. The next thing was to eat the comfits: this caused some noise and confusion, as the large birds complained that they could not taste theirs, and the small ones choked and had to be patted on the back. However, it was over at last, and they sat down again in a ring, and begged the Mouse to tell them something more. `You promised to tell me your history, you know,' said Alice, `and why it is you hate--C and D,' she added in a whisper, half afraid that it would be offended again. `Mine is a long and a sad tale!' said the Mouse, turning to Alice, and sighing. `It IS a long tail, certainly,' said Alice, looking down with wonder at the Mouse's tail; `but why do you call it sad?' And she kept on puzzling about it while the Mouse was speaking, so that her idea of the tale was something like this:-- `Fury said to a mouse, That he met in the house, "Let us both go to law: I will prosecute YOU. --Come, I'll take no denial; We must have a trial: For really this morning I've nothing to do." Said the mouse to the cur, "Such a trial, dear Sir, With no jury or judge, would be wasting our breath." "I'll be judge, I'll be jury," Said cunning old Fury: "I'll try the whole cause, and condemn you to death."' `You are not attending!' said the Mouse to Alice severely. `What are you thinking of?' `I beg your pardon,' said Alice very humbly: `you had got to the fifth bend, I think?' `I had NOT!' cried the Mouse, sharply and very angrily. `A knot!' said Alice, always ready to make herself useful, and looking anxiously about her. `Oh, do let me help to undo it!' `I shall do nothing of the sort,' said the Mouse, getting up and walking away. `You insult me by talking such nonsense!' `I didn't mean it!' pleaded poor Alice. `But you're so easily offended, you know!' The Mouse only growled in reply. `Please come back and finish your story!' Alice called after it; and the others all joined in chorus, `Yes, please do!' but the Mouse only shook its head impatiently, and walked a little quicker. `What a pity it wouldn't stay!' sighed the Lory, as soon as it was quite out of sight; and an old Crab took the opportunity of saying to her daughter `Ah, my dear! Let this be a lesson to you never to lose YOUR temper!' `Hold your tongue, Ma!' said the young Crab, a little snappishly. `You're enough to try the patience of an oyster!' `I wish I had our Dinah here, I know I do!' said Alice aloud, addressing nobody in particular. `She'd soon fetch it back!' `And who is Dinah, if I might venture to ask the question?' said the Lory. Alice replied eagerly, for she was always ready to talk about her pet: `Dinah's our cat. And she's such a capital one for catching mice you can't think! And oh, I wish you could see her after the birds! Why, she'll eat a little bird as soon as look at it!' This speech caused a remarkable sensation among the party. Some of the birds hurried off at once: one the old Magpie began wrapping itself up very carefully, remarking, `I really must be getting home; the night-air doesn't suit my throat!' and a Canary called out in a trembling voice to its children, `Come away, my dears! It's high time you were all in bed!' On various pretexts they all moved off, and Alice was soon left alone. `I wish I hadn't mentioned Dinah!' she said to herself in a melancholy tone. `Nobody seems to like her, down here, and I'm sure she's the best cat in the world! Oh, my dear Dinah! I wonder if I shall ever see you any more!' And here poor Alice began to cry again, for she felt very lonely and low-spirited. In a little while, however, she again heard a little pattering of footsteps in the distance, and she looked up eagerly, half hoping that the Mouse had changed his mind, and was coming back to finish his story. CHAPTER IV The Rabbit Sends in a Little Bill It was the White Rabbit, trotting slowly back again, and looking anxiously about as it went, as if it had lost something; and she heard it muttering to itself `The Duchess! The Duchess! Oh my dear paws! Oh my fur and whiskers! She'll get me executed, as sure as ferrets are ferrets! Where CAN I have dropped them, I wonder?' Alice guessed in a moment that it was looking for the fan and the pair of white kid gloves, and she very good-naturedly began hunting about for them, but they were nowhere to be seen--everything seemed to have changed since her swim in the pool, and the great hall, with the glass table and the little door, had vanished completely. Very soon the Rabbit noticed Alice, as she went hunting about, and called out to her in an angry tone, `Why, Mary Ann, what ARE you doing out here? Run home this moment, and fetch me a pair of gloves and a fan! Quick, now!' And Alice was so much frightened that she ran off at once in the direction it pointed to, without trying to explain the mistake it had made. `He took me for his housemaid,' she said to herself as she ran. `How surprised he'll be when he finds out who I am! But I'd better take him his fan and gloves--that is, if I can find them.' As she said this, she came upon a neat little house, on the door of which was a bright brass plate with the name `W. RABBIT' engraved upon it. She went in without knocking, and hurried upstairs, in great fear lest she should meet the real Mary Ann, and be turned out of the house before she had found the fan and gloves. `How queer it seems,' Alice said to herself, `to be going messages for a rabbit! I suppose Dinah'll be sending me on messages next!' And she began fancying the sort of thing that would happen: `"Miss Alice! Come here directly, and get ready for your walk!" "Coming in a minute, nurse! But I've got to see that the mouse doesn't get out." Only I don't think,' Alice went on, `that they'd let Dinah stop in the house if it began ordering people about like that!' By this time she had found her way into a tidy little room with a table in the window, and on it (as she had hoped) a fan and two or three pairs of tiny white kid gloves: she took up the fan and a pair of the gloves, and was just going to leave the room, when her eye fell upon a little bottle that stood near the looking- glass. There was no label this time with the words `DRINK ME,' but nevertheless she uncorked it and put it to her lips. `I know SOMETHING interesting is sure to happen,' she said to herself, `whenever I eat or drink anything; so I'll just see what this bottle does. I do hope it'll make me grow large again, for really I'm quite tired of being such a tiny little thing!' It did so indeed, and much sooner than she had expected: before she had drunk half the bottle, she found her head pressing against the ceiling, and had to stoop to save her neck from being broken. She hastily put down the bottle, saying to herself `That's quite enough--I hope I shan't grow any more--As it is, I can't get out at the door--I do wish I hadn't drunk quite so much!' Alas! it was too late to wish that! She went on growing, and growing, and very soon had to kneel down on the floor: in another minute there was not even room for this, and she tried the effect of lying down with one elbow against the door, and the other arm curled round her head. Still she went on growing, and, as a last resource, she put one arm out of the window, and one foot up the chimney, and said to herself `Now I can do no more, whatever happens. What WILL become of me?' Luckily for Alice, the little magic bottle had now had its full effect, and she grew no larger: still it was very uncomfortable, and, as there seemed to be no sort of chance of her ever getting out of the room again, no wonder she felt unhappy. `It was much pleasanter at home,' thought poor Alice, `when one wasn't always growing larger and smaller, and being ordered about by mice and rabbits. I almost wish I hadn't gone down that rabbit-hole--and yet--and yet--it's rather curious, you know, this sort of life! I do wonder what CAN have happened to me! When I used to read fairy-tales, I fancied that kind of thing never happened, and now here I am in the middle of one! There ought to be a book written about me, that there ought! And when I grow up, I'll write one--but I'm grown up now,' she added in a sorrowful tone; `at least there's no room to grow up any more HERE.' `But then,' thought Alice, `shall I NEVER get any older than I am now? That'll be a comfort, one way--never to be an old woman- -but then--always to have lessons to learn! Oh, I shouldn't like THAT!' `Oh, you foolish Alice!' she answered herself. `How can you learn lessons in here? Why, there's hardly room for YOU, and no room at all for any lesson-books!' And so she went on, taking first one side and then the other, and making quite a conversation of it altogether; but after a few minutes she heard a voice outside, and stopped to listen. `Mary Ann! Mary Ann!' said the voice. `Fetch me my gloves this moment!' Then came a little pattering of feet on the stairs. Alice knew it was the Rabbit coming to look for her, and she trembled till she shook the house, quite forgetting that she was now about a thousand times as large as the Rabbit, and had no reason to be afraid of it. Presently the Rabbit came up to the door, and tried to open it; but, as the door opened inwards, and Alice's elbow was pressed hard against it, that attempt proved a failure. Alice heard it say to itself `Then I'll go round and get in at the window.' `THAT you won't' thought Alice, and, after waiting till she fancied she heard the Rabbit just under the window, she suddenly spread out her hand, and made a snatch in the air. She did not get hold of anything, but she heard a little shriek and a fall, and a crash of broken glass, from which she concluded that it was just possible it had fallen into a cucumber-frame, or something of the sort. Next came an angry voice--the Rabbit's--`Pat! Pat! Where are you?' And then a voice she had never heard before, `Sure then I'm here! Digging for apples, yer honour!' `Digging for apples, indeed!' said the Rabbit angrily. `Here! Come and help me out of THIS!' (Sounds of more broken glass.) `Now tell me, Pat, what's that in the window?' `Sure, it's an arm, yer honour!' (He pronounced it `arrum.') `An arm, you goose! Who ever saw one that size? Why, it fills the whole window!' `Sure, it does, yer honour: but it's an arm for all that.' `Well, it's got no business there, at any rate: go and take it away!' There was a long silence after this, and Alice could only hear whispers now and then; such as, `Sure, I don't like it, yer honour, at all, at all!' `Do as I tell you, you coward!' and at last she spread out her hand again, and made another snatch in the air. This time there were TWO little shrieks, and more sounds of broken glass. `What a number of cucumber-frames there must be!' thought Alice. `I wonder what they'll do next! As for pulling me out of the window, I only wish they COULD! I'm sure I don't want to stay in here any longer!' She waited for some time without hearing anything more: at last came a rumbling of little cartwheels, and the sound of a good many voice all talking together: she made out the words: `Where's the other ladder?--Why, I hadn't to bring but one; Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up at this corner--No, tie 'em together first--they don't reach half high enough yet--Oh! they'll do well enough; don't be particular- -Here, Bill! catch hold of this rope--Will the roof bear?--Mind that loose slate--Oh, it's coming down! Heads below!' (a loud crash)--`Now, who did that?--It was Bill, I fancy--Who's to go down the chimney?--Nay, I shan't! YOU do it!--That I won't, then!--Bill's to go down--Here, Bill! the master says you're to go down the chimney!' `Oh! So Bill's got to come down the chimney, has he?' said Alice to herself. `Shy, they seem to put everything upon Bill! I wouldn't be in Bill's place for a good deal: this fireplace is narrow, to be sure; but I THINK I can kick a little!' She drew her foot as far down the chimney as she could, and waited till she heard a little animal (she couldn't guess of what sort it was) scratching and scrambling about in the chimney close above her: then, saying to herself `This is Bill,' she gave one sharp kick, and waited to see what would happen next. The first thing she heard was a general chorus of `There goes Bill!' then the Rabbit's voice along--`Catch him, you by the hedge!' then silence, and then another confusion of voices--`Hold up his head--Brandy now--Don't choke him--How was it, old fellow? What happened to you? Tell us all about it!' Last came a little feeble, squeaking voice, (`That's Bill,' thought Alice,) `Well, I hardly know--No more, thank ye; I'm better now--but I'm a deal too flustered to tell you--all I know is, something comes at me like a Jack-in-the-box, and up I goes like a sky-rocket!' `So you did, old fellow!' said the others. `We must burn the house down!' said the Rabbit's voice; and Alice called out as loud as she could, `If you do. I'll set Dinah at you!' There was a dead silence instantly, and Alice thought to herself, `I wonder what they WILL do next! If they had any sense, they'd take the roof off.' After a minute or two, they began moving about again, and Alice heard the Rabbit say, `A barrowful will do, to begin with.' `A barrowful of WHAT?' thought Alice; but she had not long to doubt, for the next moment a shower of little pebbles came rattling in at the window, and some of them hit her in the face. `I'll put a stop to this,' she said to herself, and shouted out, `You'd better not do that again!' which produced another dead silence. Alice noticed with some surprise that the pebbles were all turning into little cakes as they lay on the floor, and a bright idea came into her head. `If I eat one of these cakes,' she thought, `it's sure to make SOME change in my size; and as it can't possibly make me larger, it must make me smaller, I suppose.' So she swallowed one of the cakes, and was delighted to find that she began shrinking directly. As soon as she was small enough to get through the door, she ran out of the house, and found quite a crowd of little animals and birds waiting outside. The poor little Lizard, Bill, was in the middle, being held up by two guinea-pigs, who were giving it something out of a bottle. They all made a rush at Alice the moment she appeared; but she ran off as hard as she could, and soon found herself safe in a thick wood. `The first thing I've got to do,' said Alice to herself, as she wandered about in the wood, `is to grow to my right size again; and the second thing is to find my way into that lovely garden. I think that will be the best plan.' It sounded an excellent plan, no doubt, and very neatly and simply arranged; the only difficulty was, that she had not the smallest idea how to set about it; and while she was peering about anxiously among the trees, a little sharp bark just over her head made her look up in a great hurry. An enormous puppy was looking down at her with large round eyes, and feebly stretching out one paw, trying to touch her. `Poor little thing!' said Alice, in a coaxing tone, and she tried hard to whistle to it; but she was terribly frightened all the time at the thought that it might be hungry, in which case it would be very likely to eat her up in spite of all her coaxing. Hardly knowing what she did, she picked up a little bit of stick, and held it out to the puppy; whereupon the puppy jumped into the air off all its feet at once, with a yelp of delight, and rushed at the stick, and made believe to worry it; then Alice dodged behind a great thistle, to keep herself from being run over; and the moment she appeared on the other side, the puppy made another rush at the stick, and tumbled head over heels in its hurry to get hold of it; then Alice, thinking it was very like having a game of play with a cart-horse, and expecting every moment to be trampled under its feet, ran round the thistle again; then the puppy began a series of short charges at the stick, running a very little way forwards each time and a long way back, and barking hoarsely all the while, till at last it sat down a good way off, panting, with its tongue hanging out of its mouth, and its great eyes half shut. This seemed to Alice a good opportunity for making her escape; so she set off at once, and ran till she was quite tired and out of breath, and till the puppy's bark sounded quite faint in the distance. `And yet what a dear little puppy it was!' said Alice, as she leant against a buttercup to rest herself, and fanned herself with one of the leaves: `I should have liked teaching it tricks very much, if--if I'd only been the right size to do it! Oh dear! I'd nearly forgotten that I've got to grow up again! Let me see--how IS it to be managed? I suppose I ought to eat or drink something or other; but the great question is, what?' The great question certainly was, what? Alice looked all round her at the flowers and the blades of grass, but she did not see anything that looked like the right thing to eat or drink under the circumstances. There was a large mushroom growing near her, about the same height as herself; and when she had looked under it, and on both sides of it, and behind it, it occurred to her that she might as well look and see what was on the top of it. She stretched herself up on tiptoe, and peeped over the edge of the mushroom, and her eyes immediately met those of a large caterpillar, that was sitting on the top with its arms folded, quietly smoking a long hookah, and taking not the smallest notice of her or of anything else. CHAPTER V Advice from a Caterpillar The Caterpillar and Alice looked at each other for some time in silence: at last the Caterpillar took the hookah out of its mouth, and addressed her in a languid, sleepy voice. `Who are YOU?' said the Caterpillar. This was not an encouraging opening for a conversation. Alice replied, rather shyly, `I--I hardly know, sir, just at present-- at least I know who I WAS when I got up this morning, but I think I must have been changed several times since then.' `What do you mean by that?' said the Caterpillar sternly. `Explain yourself!' `I can't explain MYSELF, I'm afraid, sir' said Alice, `because I'm not myself, you see.' `I don't see,' said the Caterpillar. `I'm afraid I can't put it more clearly,' Alice replied very politely, `for I can't understand it myself to begin with; and being so many different sizes in a day is very confusing.' `It isn't,' said the Caterpillar. `Well, perhaps you haven't found it so yet,' said Alice; `but when you have to turn into a chrysalis--you will some day, you know--and then after that into a butterfly, I should think you'll feel it a little queer, won't you?' `Not a bit,' said the Caterpillar. `Well, perhaps your feelings may be different,' said Alice; `all I know is, it would feel very queer to ME.' `You!' said the Caterpillar contemptuously. `Who are YOU?' Which brought them back again to the beginning of the conversation. Alice felt a little irritated at the Caterpillar's making such VERY short remarks, and she drew herself up and said, very gravely, `I think, you ought to tell me who YOU are, first.' `Why?' said the Caterpillar. Here was another puzzling question; and as Alice could not think of any good reason, and as the Caterpillar seemed to be in a VERY unpleasant state of mind, she turned away. `Come back!' the Caterpillar called after her. `I've something important to say!' This sounded promising, certainly: Alice turned and came back again. `Keep your temper,' said the Caterpillar. `Is that all?' said Alice, swallowing down her anger as well as she could. `No,' said the Caterpillar. Alice thought she might as well wait, as she had nothing else to do, and perhaps after all it might tell her something worth hearing. For some minutes it puffed away without speaking, but at last it unfolded its arms, took the hookah out of its mouth again, and said, `So you think you're changed, do you?' `I'm afraid I am, sir,' said Alice; `I can't remember things as I used--and I don't keep the same size for ten minutes together!' `Can't remember WHAT things?' said the Caterpillar. `Well, I've tried to say "HOW DOTH THE LITTLE BUSY BEE," but it all came different!' Alice replied in a very melancholy voice. `Repeat, "YOU ARE OLD, FATHER WILLIAM,"' said the Caterpillar. Alice folded her hands, and began:-- `You are old, Father William,' the young man said, `And your hair has become very white; And yet you incessantly stand on your head-- Do you think, at your age, it is right?' `In my youth,' Father William replied to his son, `I feared it might injure the brain; But, now that I'm perfectly sure I have none, Why, I do it again and again.' `You are old,' said the youth, `as I mentioned before, And have grown most uncommonly fat; Yet you turned a back-somersault in at the door-- Pray, what is the reason of that?' `In my youth,' said the sage, as he shook his grey locks, `I kept all my limbs very supple By the use of this ointment--one shilling the box-- Allow me to sell you a couple?' `You are old,' said the youth, `and your jaws are too weak For anything tougher than suet; Yet you finished the goose, with the bones and the beak-- Pray how did you manage to do it?' `In my youth,' said his father, `I took to the law, And argued each case with my wife; And the muscular strength, which it gave to my jaw, Has lasted the rest of my life.' `You are old,' said the youth, `one would hardly suppose That your eye was as steady as ever; Yet you balanced an eel on the end of your nose-- What made you so awfully clever?' `I have answered three questions, and that is enough,' Said his father; `don't give yourself airs! Do you think I can listen all day to such stuff? Be off, or I'll kick you down stairs!' `That is not said right,' said the Caterpillar. `Not QUITE right, I'm afraid,' said Alice, timidly; `some of the words have got altered.' `It is wrong from beginning to end,' said the Caterpillar decidedly, and there was silence for some minutes. The Caterpillar was the first to speak. `What size do you want to be?' it asked. `Oh, I'm not particular as to size,' Alice hastily replied; `only one doesn't like changing so often, you know.' `I DON'T know,' said the Caterpillar. Alice said nothing: she had never been so much contradicted in her life before, and she felt that she was losing her temper. `Are you content now?' said the Caterpillar. `Well, I should like to be a LITTLE larger, sir, if you wouldn't mind,' said Alice: `three inches is such a wretched height to be.' `It is a very good height indeed!' said the Caterpillar angrily, rearing itself upright as it spoke (it was exactly three inches high). `But I'm not used to it!' pleaded poor Alice in a piteous tone. And she thought of herself, `I wish the creatures wouldn't be so easily offended!' `You'll get used to it in time,' said the Caterpillar; and it put the hookah into its mouth and began smoking again. This time Alice waited patiently until it chose to speak again. In a minute or two the Caterpillar took the hookah out of its mouth and yawned once or twice, and shook itself. Then it got down off the mushroom, and crawled away in the grass, merely remarking as it went, `One side will make you grow taller, and the other side will make you grow shorter.' `One side of WHAT? The other side of WHAT?' thought Alice to herself. `Of the mushroom,' said the Caterpillar, just as if she had asked it aloud; and in another moment it was out of sight. Alice remained looking thoughtfully at the mushroom for a minute, trying to make out which were the two sides of it; and as it was perfectly round, she found this a very difficult question. However, at last she stretched her arms round it as far as they would go, and broke off a bit of the edge with each hand. `And now which is which?' she said to herself, and nibbled a little of the right-hand bit to try the effect: the next moment she felt a violent blow underneath her chin: it had struck her foot! She was a good deal frightened by this very sudden change, but she felt that there was no time to be lost, as she was shrinking rapidly; so she set to work at once to eat some of the other bit. Her chin was pressed so closely against her foot, that there was hardly room to open her mouth; but she did it at last, and managed to swallow a morsel of the lefthand bit. * * * * * * * * * * * * * * * * * * * * `Come, my head's free at last!' said Alice in a tone of delight, which changed into alarm in another moment, when she found that her shoulders were nowhere to be found: all she could see, when she looked down, was an immense length of neck, which seemed to rise like a stalk out of a sea of green leaves that lay far below her. `What CAN all that green stuff be?' said Alice. `And where HAVE my shoulders got to? And oh, my poor hands, how is it I can't see you?' She was moving them about as she spoke, but no result seemed to follow, except a little shaking among the distant green leaves. As there seemed to be no chance of getting her hands up to her head, she tried to get her head down to them, and was delighted to find that her neck would bend about easily in any direction, like a serpent. She had just succeeded in curving it down into a graceful zigzag, and was going to dive in among the leaves, which she found to be nothing but the tops of the trees under which she had been wandering, when a sharp hiss made her draw back in a hurry: a large pigeon had flown into her face, and was beating her violently with its wings. `Serpent!' screamed the Pigeon. `I'm NOT a serpent!' said Alice indignantly. `Let me alone!' `Serpent, I say again!' repeated the Pigeon, but in a more subdued tone, and added with a kind of sob, `I've tried every way, and nothing seems to suit them!' `I haven't the least idea what you're talking about,' said Alice. `I've tried the roots of trees, and I've tried banks, and I've tried hedges,' the Pigeon went on, without attending to her; `but those serpents! There's no pleasing them!' Alice was more and more puzzled, but she thought there was no use in saying anything more till the Pigeon had finished. `As if it wasn't trouble enough hatching the eggs,' said the Pigeon; `but I must be on the look-out for serpents night and day! Why, I haven't had a wink of sleep these three weeks!' `I'm very sorry you've been annoyed,' said Alice, who was beginning to see its meaning. `And just as I'd taken the highest tree in the wood,' continued the Pigeon, raising its voice to a shriek, `and just as I was thinking I should be free of them at last, they must needs come wriggling down from the sky! Ugh, Serpent!' `But I'm NOT a serpent, I tell you!' said Alice. `I'm a--I'm a--' `Well! WHAT are you?' said the Pigeon. `I can see you're trying to invent something!' `I--I'm a little girl,' said Alice, rather doubtfully, as she remembered the number of changes she had gone through that day. `A likely story indeed!' said the Pigeon in a tone of the deepest contempt. `I've seen a good many little girls in my time, but never ONE with such a neck as that! No, no! You're a serpent; and there's no use denying it. I suppose you'll be telling me next that you never tasted an egg!' `I HAVE tasted eggs, certainly,' said Alice, who was a very truthful child; `but little girls eat eggs quite as much as serpents do, you know.' `I don't believe it,' said the Pigeon; `but if they do, why then they're a kind of serpent, that's all I can say.' This was such a new idea to Alice, that she was quite silent for a minute or two, which gave the Pigeon the opportunity of adding, `You're looking for eggs, I know THAT well enough; and what does it matter to me whether you're a little girl or a serpent?' `It matters a good deal to ME,' said Alice hastily; `but I'm not looking for eggs, as it happens; and if I was, I shouldn't want YOURS: I don't like them raw.' `Well, be off, then!' said the Pigeon in a sulky tone, as it settled down again into its nest. Alice crouched down among the trees as well as she could, for her neck kept getting entangled among the branches, and every now and then she had to stop and untwist it. After a while she remembered that she still held the pieces of mushroom in her hands, and she set to work very carefully, nibbling first at one and then at the other, and growing sometimes taller and sometimes shorter, until she had succeeded in bringing herself down to her usual height. It was so long since she had been anything near the right size, that it felt quite strange at first; but she got used to it in a few minutes, and began talking to herself, as usual. `Come, there's half my plan done now! How puzzling all these changes are! I'm never sure what I'm going to be, from one minute to another! However, I've got back to my right size: the next thing is, to get into that beautiful garden--how IS that to be done, I wonder?' As she said this, she came suddenly upon an open place, with a little house in it about four feet high. `Whoever lives there,' thought Alice, `it'll never do to come upon them THIS size: why, I should frighten them out of their wits!' So she began nibbling at the righthand bit again, and did not venture to go near the house till she had brought herself down to nine inches high. CHAPTER VI Pig and Pepper For a minute or two she stood looking at the house, and wondering what to do next, when suddenly a footman in livery came running out of the wood--(she considered him to be a footman because he was in livery: otherwise, judging by his face only, she would have called him a fish)--and rapped loudly at the door with his knuckles. It was opened by another footman in livery, with a round face, and large eyes like a frog; and both footmen, Alice noticed, had powdered hair that curled all over their heads. She felt very curious to know what it was all about, and crept a little way out of the wood to listen. The Fish-Footman began by producing from under his arm a great letter, nearly as large as himself, and this he handed over to the other, saying, in a solemn tone, `For the Duchess. An invitation from the Queen to play croquet.' The Frog-Footman repeated, in the same solemn tone, only changing the order of the words a little, `From the Queen. An invitation for the Duchess to play croquet.' Then they both bowed low, and their curls got entangled together. Alice laughed so much at this, that she had to run back into the wood for fear of their hearing her; and when she next peeped out the Fish-Footman was gone, and the other was sitting on the ground near the door, staring stupidly up into the sky. Alice went timidly up to the door, and knocked. `There's no sort of use in knocking,' said the Footman, `and that for two reasons. First, because I'm on the same side of the door as you are; secondly, because they're making such a noise inside, no one could possibly hear you.' And certainly there was a most extraordinary noise going on within--a constant howling and sneezing, and every now and then a great crash, as if a dish or kettle had been broken to pieces. `Please, then,' said Alice, `how am I to get in?' `There might be some sense in your knocking,' the Footman went on without attending to her, `if we had the door between us. For instance, if you were INSIDE, you might knock, and I could let you out, you know.' He was looking up into the sky all the time he was speaking, and this Alice thought decidedly uncivil. `But perhaps he can't help it,' she said to herself; `his eyes are so VERY nearly at the top of his head. But at any rate he might answer questions.--How am I to get in?' she repeated, aloud. `I shall sit here,' the Footman remarked, `till tomorrow--' At this moment the door of the house opened, and a large plate came skimming out, straight at the Footman's head: it just grazed his nose, and broke to pieces against one of the trees behind him. `--or next day, maybe,' the Footman continued in the same tone, exactly as if nothing had happened. `How am I to get in?' asked Alice again, in a louder tone. `ARE you to get in at all?' said the Footman. `That's the first question, you know.' It was, no doubt: only Alice did not like to be told so. `It's really dreadful,' she muttered to herself, `the way all the creatures argue. It's enough to drive one crazy!' The Footman seemed to think this a good opportunity for repeating his remark, with variations. `I shall sit here,' he said, `on and off, for days and days.' `But what am I to do?' said Alice. `Anything you like,' said the Footman, and began whistling. `Oh, there's no use in talking to him,' said Alice desperately: `he's perfectly idiotic!' And she opened the door and went in. The door led right into a large kitchen, which was full of smoke from one end to the other: the Duchess was sitting on a three-legged stool in the middle, nursing a baby; the cook was leaning over the fire, stirring a large cauldron which seemed to be full of soup. `There's certainly too much pepper in that soup!' Alice said to herself, as well as she could for sneezing. There was certainly too much of it in the air. Even the Duchess sneezed occasionally; and as for the baby, it was sneezing and howling alternately without a moment's pause. The only things in the kitchen that did not sneeze, were the cook, and a large cat which was sitting on the hearth and grinning from ear to ear. `Please would you tell me,' said Alice, a little timidly, for she was not quite sure whether it was good manners for her to speak first, `why your cat grins like that?' `It's a Cheshire cat,' said the Duchess, `and that's why. Pig!' She said the last word with such sudden violence that Alice quite jumped; but she saw in another moment that it was addressed to the baby, and not to her, so she took courage, and went on again:-- `I didn't know that Cheshire cats always grinned; in fact, I didn't know that cats COULD grin.' `They all can,' said the Duchess; `and most of 'em do.' `I don't know of any that do,' Alice said very politely, feeling quite pleased to have got into a conversation. `You don't know much,' said the Duchess; `and that's a fact.' Alice did not at all like the tone of this remark, and thought it would be as well to introduce some other subject of conversation. While she was trying to fix on one, the cook took the cauldron of soup off the fire, and at once set to work throwing everything within her reach at the Duchess and the baby --the fire-irons came first; then followed a shower of saucepans, plates, and dishes. The Duchess took no notice of them even when they hit her; and the baby was howling so much already, that it was quite impossible to say whether the blows hurt it or not. `Oh, PLEASE mind what you're doing!' cried Alice, jumping up and down in an agony of terror. `Oh, there goes his PRECIOUS nose'; as an unusually large saucepan flew close by it, and very nearly carried it off. `If everybody minded their own business,' the Duchess said in a hoarse growl, `the world would go round a deal faster than it does.' `Which would NOT be an advantage,' said Alice, who felt very glad to get an opportunity of showing off a little of her knowledge. `Just think of what work it would make with the day and night! You see the earth takes twenty-four hours to turn round on its axis--' `Talking of axes,' said the Duchess, `chop off her head!' Alice glanced rather anxiously at the cook, to see if she meant to take the hint; but the cook was busily stirring the soup, and seemed not to be listening, so she went on again: `Twenty-four hours, I THINK; or is it twelve? I--' `Oh, don't bother ME,' said the Duchess; `I never could abide figures!' And with that she began nursing her child again, singing a sort of lullaby to it as she did so, and giving it a violent shake at the end of every line: `Speak roughly to your little boy, And beat him when he sneezes: He only does it to annoy, Because he knows it teases.' CHORUS. (In which the cook and the baby joined):-- `Wow! wow! wow!' While the Duchess sang the second verse of the song, she kept tossing the baby violently up and down, and the poor little thing howled so, that Alice could hardly hear the words:-- `I speak severely to my boy, I beat him when he sneezes; For he can thoroughly enjoy The pepper when he pleases!' CHORUS. `Wow! wow! wow!' `Here! you may nurse it a bit, if you like!' the Duchess said to Alice, flinging the baby at her as she spoke. `I must go and get ready to play croquet with the Queen,' and she hurried out of the room. The cook threw a frying-pan after her as she went out, but it just missed her. Alice caught the baby with some difficulty, as it was a queer- shaped little creature, and held out its arms and legs in all directions, `just like a star-fish,' thought Alice. The poor little thing was snorting like a steam-engine when she caught it, and kept doubling itself up and straightening itself out again, so that altogether, for the first minute or two, it was as much as she could do to hold it. As soon as she had made out the proper way of nursing it, (which was to twist it up into a sort of knot, and then keep tight hold of its right ear and left foot, so as to prevent its undoing itself,) she carried it out into the open air. `IF I don't take this child away with me,' thought Alice, `they're sure to kill it in a day or two: wouldn't it be murder to leave it behind?' She said the last words out loud, and the little thing grunted in reply (it had left off sneezing by this time). `Don't grunt,' said Alice; `that's not at all a proper way of expressing yourself.' The baby grunted again, and Alice looked very anxiously into its face to see what was the matter with it. There could be no doubt that it had a VERY turn-up nose, much more like a snout than a real nose; also its eyes were getting extremely small for a baby: altogether Alice did not like the look of the thing at all. `But perhaps it was only sobbing,' she thought, and looked into its eyes again, to see if there were any tears. No, there were no tears. `If you're going to turn into a pig, my dear,' said Alice, seriously, `I'll have nothing more to do with you. Mind now!' The poor little thing sobbed again (or grunted, it was impossible to say which), and they went on for some while in silence. Alice was just beginning to think to herself, `Now, what am I to do with this creature when I get it home?' when it grunted again, so violently, that she looked down into its face in some alarm. This time there could be NO mistake about it: it was neither more nor less than a pig, and she felt that it would be quite absurd for her to carry it further. So she set the little creature down, and felt quite relieved to see it trot away quietly into the wood. `If it had grown up,' she said to herself, `it would have made a dreadfully ugly child: but it makes rather a handsome pig, I think.' And she began thinking over other children she knew, who might do very well as pigs, and was just saying to herself, `if one only knew the right way to change them--' when she was a little startled by seeing the Cheshire Cat sitting on a bough of a tree a few yards off. The Cat only grinned when it saw Alice. It looked good- natured, she thought: still it had VERY long claws and a great many teeth, so she felt that it ought to be treated with respect. `Cheshire Puss,' she began, rather timidly, as she did not at all know whether it would like the name: however, it only grinned a little wider. `Come, it's pleased so far,' thought Alice, and she went on. `Would you tell me, please, which way I ought to go from here?' `That depends a good deal on where you want to get to,' said the Cat. `I don't much care where--' said Alice. `Then it doesn't matter which way you go,' said the Cat. `--so long as I get SOMEWHERE,' Alice added as an explanation. `Oh, you're sure to do that,' said the Cat, `if you only walk long enough.' Alice felt that this could not be denied, so she tried another question. `What sort of people live about here?' `In THAT direction,' the Cat said, waving its right paw round, `lives a Hatter: and in THAT direction,' waving the other paw, `lives a March Hare. Visit either you like: they're both mad.' `But I don't want to go among mad people,' Alice remarked. `Oh, you can't help that,' said the Cat: `we're all mad here. I'm mad. You're mad.' `How do you know I'm mad?' said Alice. `You must be,' said the Cat, `or you wouldn't have come here.' Alice didn't think that proved it at all; however, she went on `And how do you know that you're mad?' `To begin with,' said the Cat, `a dog's not mad. You grant that?' `I suppose so,' said Alice. `Well, then,' the Cat went on, `you see, a dog growls when it's angry, and wags its tail when it's pleased. Now I growl when I'm pleased, and wag my tail when I'm angry. Therefore I'm mad.' `I call it purring, not growling,' said Alice. `Call it what you like,' said the Cat. `Do you play croquet with the Queen to-day?' `I should like it very much,' said Alice, `but I haven't been invited yet.' `You'll see me there,' said the Cat, and vanished. Alice was not much surprised at this, she was getting so used to queer things happening. While she was looking at the place where it had been, it suddenly appeared again. `By-the-bye, what became of the baby?' said the Cat. `I'd nearly forgotten to ask.' `It turned into a pig,' Alice quietly said, just as if it had come back in a natural way. `I thought it would,' said the Cat, and vanished again. Alice waited a little, half expecting to see it again, but it did not appear, and after a minute or two she walked on in the direction in which the March Hare was said to live. `I've seen hatters before,' she said to herself; `the March Hare will be much the most interesting, and perhaps as this is May it won't be raving mad--at least not so mad as it was in March.' As she said this, she looked up, and there was the Cat again, sitting on a branch of a tree. `Did you say pig, or fig?' said the Cat. `I said pig,' replied Alice; `and I wish you wouldn't keep appearing and vanishing so suddenly: you make one quite giddy.' `All right,' said the Cat; and this time it vanished quite slowly, beginning with the end of the tail, and ending with the grin, which remained some time after the rest of it had gone. `Well! I've often seen a cat without a grin,' thought Alice; `but a grin without a cat! It's the most curious thing I ever say in my life!' She had not gone much farther before she came in sight of the house of the March Hare: she thought it must be the right house, because the chimneys were shaped like ears and the roof was thatched with fur. It was so large a house, that she did not like to go nearer till she had nibbled some more of the lefthand bit of mushroom, and raised herself to about two feet high: even then she walked up towards it rather timidly, saying to herself `Suppose it should be raving mad after all! I almost wish I'd gone to see the Hatter instead!' CHAPTER VII A Mad Tea-Party There was a table set out under a tree in front of the house, and the March Hare and the Hatter were having tea at it: a Dormouse was sitting between them, fast asleep, and the other two were using it as a cushion, resting their elbows on it, and the talking over its head. `Very uncomfortable for the Dormouse,' thought Alice; `only, as it's asleep, I suppose it doesn't mind.' The table was a large one, but the three were all crowded together at one corner of it: `No room! No room!' they cried out when they saw Alice coming. `There's PLENTY of room!' said Alice indignantly, and she sat down in a large arm-chair at one end of the table. `Have some wine,' the March Hare said in an encouraging tone. Alice looked all round the table, but there was nothing on it but tea. `I don't see any wine,' she remarked. `There isn't any,' said the March Hare. `Then it wasn't very civil of you to offer it,' said Alice angrily. `It wasn't very civil of you to sit down without being invited,' said the March Hare. `I didn't know it was YOUR table,' said Alice; `it's laid for a great many more than three.' `Your hair wants cutting,' said the Hatter. He had been looking at Alice for some time with great curiosity, and this was his first speech. `You should learn not to make personal remarks,' Alice said with some severity; `it's very rude.' The Hatter opened his eyes very wide on hearing this; but all he SAID was, `Why is a raven like a writing-desk?' `Come, we shall have some fun now!' thought Alice. `I'm glad they've begun asking riddles.--I believe I can guess that,' she added aloud. `Do you mean that you think you can find out the answer to it?' said the March Hare. `Exactly so,' said Alice. `Then you should say what you mean,' the March Hare went on. `I do,' Alice hastily replied; `at least--at least I mean what I say--that's the same thing, you know.' `Not the same thing a bit!' said the Hatter. `You might just as well say that "I see what I eat" is the same thing as "I eat what I see"!' `You might just as well say,' added the March Hare, `that "I like what I get" is the same thing as "I get what I like"!' `You might just as well say,' added the Dormouse, who seemed to be talking in his sleep, `that "I breathe when I sleep" is the same thing as "I sleep when I breathe"!' `It IS the same thing with you,' said the Hatter, and here the conversation dropped, and the party sat silent for a minute, while Alice thought over all she could remember about ravens and writing-desks, which wasn't much. The Hatter was the first to break the silence. `What day of the month is it?' he said, turning to Alice: he had taken his watch out of his pocket, and was looking at it uneasily, shaking it every now and then, and holding it to his ear. Alice considered a little, and then said `The fourth.' `Two days wrong!' sighed the Hatter. `I told you butter wouldn't suit the works!' he added looking angrily at the March Hare. `It was the BEST butter,' the March Hare meekly replied. `Yes, but some crumbs must have got in as well,' the Hatter grumbled: `you shouldn't have put it in with the bread-knife.' The March Hare took the watch and looked at it gloomily: then he dipped it into his cup of tea, and looked at it again: but he could think of nothing better to say than his first remark, `It was the BEST butter, you know.' Alice had been looking over his shoulder with some curiosity. `What a funny watch!' she remarked. `It tells the day of the month, and doesn't tell what o'clock it is!' `Why should it?' muttered the Hatter. `Does YOUR watch tell you what year it is?' `Of course not,' Alice replied very readily: `but that's because it stays the same year for such a long time together.' `Which is just the case with MINE,' said the Hatter. Alice felt dreadfully puzzled. The Hatter's remark seemed to have no sort of meaning in it, and yet it was certainly English. `I don't quite understand you,' she said, as politely as she could. `The Dormouse is asleep again,' said the Hatter, and he poured a little hot tea upon its nose. The Dormouse shook its head impatiently, and said, without opening its eyes, `Of course, of course; just what I was going to remark myself.' `Have you guessed the riddle yet?' the Hatter said, turning to Alice again. `No, I give it up,' Alice replied: `what's the answer?' `I haven't the slightest idea,' said the Hatter. `Nor I,' said the March Hare. Alice sighed wearily. `I think you might do something better with the time,' she said, `than waste it in asking riddles that have no answers.' `If you knew Time as well as I do,' said the Hatter, `you wouldn't talk about wasting IT. It's HIM.' `I don't know what you mean,' said Alice. `Of course you don't!' the Hatter said, tossing his head contemptuously. `I dare say you never even spoke to Time!' `Perhaps not,' Alice cautiously replied: `but I know I have to beat time when I learn music.' `Ah! that accounts for it,' said the Hatter. `He won't stand beating. Now, if you only kept on good terms with him, he'd do almost anything you liked with the clock. For instance, suppose it were nine o'clock in the morning, just time to begin lessons: you'd only have to whisper a hint to Time, and round goes the clock in a twinkling! Half-past one, time for dinner!' (`I only wish it was,' the March Hare said to itself in a whisper.) `That would be grand, certainly,' said Alice thoughtfully: `but then--I shouldn't be hungry for it, you know.' `Not at first, perhaps,' said the Hatter: `but you could keep it to half-past one as long as you liked.' `Is that the way YOU manage?' Alice asked. The Hatter shook his head mournfully. `Not I!' he replied. `We quarrelled last March--just before HE went mad, you know--' (pointing with his tea spoon at the March Hare,) `--it was at the great concert given by the Queen of Hearts, and I had to sing "Twinkle, twinkle, little bat! How I wonder what you're at!" You know the song, perhaps?' `I've heard something like it,' said Alice. `It goes on, you know,' the Hatter continued, `in this way:-- "Up above the world you fly, Like a tea-tray in the sky. Twinkle, twinkle--"' Here the Dormouse shook itself, and began singing in its sleep `Twinkle, twinkle, twinkle, twinkle--' and went on so long that they had to pinch it to make it stop. `Well, I'd hardly finished the first verse,' said the Hatter, `when the Queen jumped up and bawled out, "He's murdering the time! Off with his head!"' `How dreadfully savage!' exclaimed Alice. `And ever since that,' the Hatter went on in a mournful tone, `he won't do a thing I ask! It's always six o'clock now.' A bright idea came into Alice's head. `Is that the reason so many tea-things are put out here?' she asked. `Yes, that's it,' said the Hatter with a sigh: `it's always tea-time, and we've no time to wash the things between whiles.' `Then you keep moving round, I suppose?' said Alice. `Exactly so,' said the Hatter: `as the things get used up.' `But what happens when you come to the beginning again?' Alice ventured to ask. `Suppose we change the subject,' the March Hare interrupted, yawning. `I'm getting tired of this. I vote the young lady tells us a story.' `I'm afraid I don't know one,' said Alice, rather alarmed at the proposal. `Then the Dormouse shall!' they both cried. `Wake up, Dormouse!' And they pinched it on both sides at once. The Dormouse slowly opened his eyes. `I wasn't asleep,' he said in a hoarse, feeble voice: `I heard every word you fellows were saying.' `Tell us a story!' said the March Hare. `Yes, please do!' pleaded Alice. `And be quick about it,' added the Hatter, `or you'll be asleep again before it's done.' `Once upon a time there were three little sisters,' the Dormouse began in a great hurry; `and their names were Elsie, Lacie, and Tillie; and they lived at the bottom of a well--' `What did they live on?' said Alice, who always took a great interest in questions of eating and drinking. `They lived on treacle,' said the Dormouse, after thinking a minute or two. `They couldn't have done that, you know,' Alice gently remarked; `they'd have been ill.' `So they were,' said the Dormouse; `VERY ill.' Alice tried to fancy to herself what such an extraordinary ways of living would be like, but it puzzled her too much, so she went on: `But why did they live at the bottom of a well?' `Take some more tea,' the March Hare said to Alice, very earnestly. `I've had nothing yet,' Alice replied in an offended tone, `so I can't take more.' `You mean you can't take LESS,' said the Hatter: `it's very easy to take MORE than nothing.' `Nobody asked YOUR opinion,' said Alice. `Who's making personal remarks now?' the Hatter asked triumphantly. Alice did not quite know what to say to this: so she helped herself to some tea and bread-and-butter, and then turned to the Dormouse, and repeated her question. `Why did they live at the bottom of a well?' The Dormouse again took a minute or two to think about it, and then said, `It was a treacle-well.' `There's no such thing!' Alice was beginning very angrily, but the Hatter and the March Hare went `Sh! sh!' and the Dormouse sulkily remarked, `If you can't be civil, you'd better finish the story for yourself.' `No, please go on!' Alice said very humbly; `I won't interrupt again. I dare say there may be ONE.' `One, indeed!' said the Dormouse indignantly. However, he consented to go on. `And so these three little sisters--they were learning to draw, you know--' `What did they draw?' said Alice, quite forgetting her promise. `Treacle,' said the Dormouse, without considering at all this time. `I want a clean cup,' interrupted the Hatter: `let's all move one place on.' He moved on as he spoke, and the Dormouse followed him: the March Hare moved into the Dormouse's place, and Alice rather unwillingly took the place of the March Hare. The Hatter was the only one who got any advantage from the change: and Alice was a good deal worse off than before, as the March Hare had just upset the milk-jug into his plate. Alice did not wish to offend the Dormouse again, so she began very cautiously: `But I don't understand. Where did they draw the treacle from?' `You can draw water out of a water-well,' said the Hatter; `so I should think you could draw treacle out of a treacle-well--eh, stupid?' `But they were IN the well,' Alice said to the Dormouse, not choosing to notice this last remark. `Of course they were', said the Dormouse; `--well in.' This answer so confused poor Alice, that she let the Dormouse go on for some time without interrupting it. `They were learning to draw,' the Dormouse went on, yawning and rubbing its eyes, for it was getting very sleepy; `and they drew all manner of things--everything that begins with an M--' `Why with an M?' said Alice. `Why not?' said the March Hare. Alice was silent. The Dormouse had closed its eyes by this time, and was going off into a doze; but, on being pinched by the Hatter, it woke up again with a little shriek, and went on: `--that begins with an M, such as mouse-traps, and the moon, and memory, and muchness-- you know you say things are "much of a muchness"--did you ever see such a thing as a drawing of a muchness?' `Really, now you ask me,' said Alice, very much confused, `I don't think--' `Then you shouldn't talk,' said the Hatter. This piece of rudeness was more than Alice could bear: she got up in great disgust, and walked off; the Dormouse fell asleep instantly, and neither of the others took the least notice of her going, though she looked back once or twice, half hoping that they would call after her: the last time she saw them, they were trying to put the Dormouse into the teapot. `At any rate I'll never go THERE again!' said Alice as she picked her way through the wood. `It's the stupidest tea-party I ever was at in all my life!' Just as she said this, she noticed that one of the trees had a door leading right into it. `That's very curious!' she thought. `But everything's curious today. I think I may as well go in at once.' And in she went. Once more she found herself in the long hall, and close to the little glass table. `Now, I'll manage better this time,' she said to herself, and began by taking the little golden key, and unlocking the door that led into the garden. Then she went to work nibbling at the mushroom (she had kept a piece of it in her pocked) till she was about a foot high: then she walked down the little passage: and THEN--she found herself at last in the beautiful garden, among the bright flower-beds and the cool fountains. CHAPTER VIII The Queen's Croquet-Ground A large rose-tree stood near the entrance of the garden: the roses growing on it were white, but there were three gardeners at it, busily painting them red. Alice thought this a very curious thing, and she went nearer to watch them, and just as she came up to them she heard one of them say, `Look out now, Five! Don't go splashing paint over me like that!' `I couldn't help it,' said Five, in a sulky tone; `Seven jogged my elbow.' On which Seven looked up and said, `That's right, Five! Always lay the blame on others!' `YOU'D better not talk!' said Five. `I heard the Queen say only yesterday you deserved to be beheaded!' `What for?' said the one who had spoken first. `That's none of YOUR business, Two!' said Seven. `Yes, it IS his business!' said Five, `and I'll tell him--it was for bringing the cook tulip-roots instead of onions.' Seven flung down his brush, and had just begun `Well, of all the unjust things--' when his eye chanced to fall upon Alice, as she stood watching them, and he checked himself suddenly: the others looked round also, and all of them bowed low. `Would you tell me,' said Alice, a little timidly, `why you are painting those roses?' Five and Seven said nothing, but looked at Two. Two began in a low voice, `Why the fact is, you see, Miss, this here ought to have been a RED rose-tree, and we put a white one in by mistake; and if the Queen was to find it out, we should all have our heads cut off, you know. So you see, Miss, we're doing our best, afore she comes, to--' At this moment Five, who had been anxiously looking across the garden, called out `The Queen! The Queen!' and the three gardeners instantly threw themselves flat upon their faces. There was a sound of many footsteps, and Alice looked round, eager to see the Queen. First came ten soldiers carrying clubs; these were all shaped like the three gardeners, oblong and flat, with their hands and feet at the corners: next the ten courtiers; these were ornamented all over with diamonds, and walked two and two, as the soldiers did. After these came the royal children; there were ten of them, and the little dears came jumping merrily along hand in hand, in couples: they were all ornamented with hearts. Next came the guests, mostly Kings and Queens, and among them Alice recognised the White Rabbit: it was talking in a hurried nervous manner, smiling at everything that was said, and went by without noticing her. Then followed the Knave of Hearts, carrying the King's crown on a crimson velvet cushion; and, last of all this grand procession, came THE KING AND QUEEN OF HEARTS. Alice was rather doubtful whether she ought not to lie down on her face like the three gardeners, but she could not remember every having heard of such a rule at processions; `and besides, what would be the use of a procession,' thought she, `if people had all to lie down upon their faces, so that they couldn't see it?' So she stood still where she was, and waited. When the procession came opposite to Alice, they all stopped and looked at her, and the Queen said severely `Who is this?' She said it to the Knave of Hearts, who only bowed and smiled in reply. `Idiot!' said the Queen, tossing her head impatiently; and, turning to Alice, she went on, `What's your name, child?' `My name is Alice, so please your Majesty,' said Alice very politely; but she added, to herself, `Why, they're only a pack of cards, after all. I needn't be afraid of them!' `And who are THESE?' said the Queen, pointing to the three gardeners who were lying round the rosetree; for, you see, as they were lying on their faces, and the pattern on their backs was the same as the rest of the pack, she could not tell whether they were gardeners, or soldiers, or courtiers, or three of her own children. `How should I know?' said Alice, surprised at her own courage. `It's no business of MINE.' The Queen turned crimson with fury, and, after glaring at her for a moment like a wild beast, screamed `Off with her head! Off--' `Nonsense!' said Alice, very loudly and decidedly, and the Queen was silent. The King laid his hand upon her arm, and timidly said `Consider, my dear: she is only a child!' The Queen turned angrily away from him, and said to the Knave `Turn them over!' The Knave did so, very carefully, with one foot. `Get up!' said the Queen, in a shrill, loud voice, and the three gardeners instantly jumped up, and began bowing to the King, the Queen, the royal children, and everybody else. `Leave off that!' screamed the Queen. `You make me giddy.' And then, turning to the rose-tree, she went on, `What HAVE you been doing here?' `May it please your Majesty,' said Two, in a very humble tone, going down on one knee as he spoke, `we were trying--' `I see!' said the Queen, who had meanwhile been examining the roses. `Off with their heads!' and the procession moved on, three of the soldiers remaining behind to execute the unfortunate gardeners, who ran to Alice for protection. `You shan't be beheaded!' said Alice, and she put them into a large flower-pot that stood near. The three soldiers wandered about for a minute or two, looking for them, and then quietly marched off after the others. `Are their heads off?' shouted the Queen. `Their heads are gone, if it please your Majesty!' the soldiers shouted in reply. `That's right!' shouted the Queen. `Can you play croquet?' The soldiers were silent, and looked at Alice, as the question was evidently meant for her. `Yes!' shouted Alice. `Come on, then!' roared the Queen, and Alice joined the procession, wondering very much what would happen next. `It's--it's a very fine day!' said a timid voice at her side. She was walking by the White Rabbit, who was peeping anxiously into her face. `Very,' said Alice: `--where's the Duchess?' `Hush! Hush!' said the Rabbit in a low, hurried tone. He looked anxiously over his shoulder as he spoke, and then raised himself upon tiptoe, put his mouth close to her ear, and whispered `She's under sentence of execution.' `What for?' said Alice. `Did you say "What a pity!"?' the Rabbit asked. `No, I didn't,' said Alice: `I don't think it's at all a pity. I said "What for?"' `She boxed the Queen's ears--' the Rabbit began. Alice gave a little scream of laughter. `Oh, hush!' the Rabbit whispered in a frightened tone. `The Queen will hear you! You see, she came rather late, and the Queen said--' `Get to your places!' shouted the Queen in a voice of thunder, and people began running about in all directions, tumbling up against each other; however, they got settled down in a minute or two, and the game began. Alice thought she had never seen such a curious croquet-ground in her life; it was all ridges and furrows; the balls were live hedgehogs, the mallets live flamingoes, and the soldiers had to double themselves up and to stand on their hands and feet, to make the arches. The chief difficulty Alice found at first was in managing her flamingo: she succeeded in getting its body tucked away, comfortably enough, under her arm, with its legs hanging down, but generally, just as she had got its neck nicely straightened out, and was going to give the hedgehog a blow with its head, it WOULD twist itself round and look up in her face, with such a puzzled expression that she could not help bursting out laughing: and when she had got its head down, and was going to begin again, it was very provoking to find that the hedgehog had unrolled itself, and was in the act of crawling away: besides all this, there was generally a ridge or furrow in the way wherever she wanted to send the hedgehog to, and, as the doubled-up soldiers were always getting up and walking off to other parts of the ground, Alice soon came to the conclusion that it was a very difficult game indeed. The players all played at once without waiting for turns, quarrelling all the while, and fighting for the hedgehogs; and in a very short time the Queen was in a furious passion, and went stamping about, and shouting `Off with his head!' or `Off with her head!' about once in a minute. Alice began to feel very uneasy: to be sure, she had not as yet had any dispute with the Queen, but she knew that it might happen any minute, `and then,' thought she, `what would become of me? They're dreadfully fond of beheading people here; the great wonder is, that there's any one left alive!' She was looking about for some way of escape, and wondering whether she could get away without being seen, when she noticed a curious appearance in the air: it puzzled her very much at first, but, after watching it a minute or two, she made it out to be a grin, and she said to herself `It's the Cheshire Cat: now I shall have somebody to talk to.' `How are you getting on?' said the Cat, as soon as there was mouth enough for it to speak with. Alice waited till the eyes appeared, and then nodded. `It's no use speaking to it,' she thought, `till its ears have come, or at least one of them.' In another minute the whole head appeared, and then Alice put down her flamingo, and began an account of the game, feeling very glad she had someone to listen to her. The Cat seemed to think that there was enough of it now in sight, and no more of it appeared. `I don't think they play at all fairly,' Alice began, in rather a complaining tone, `and they all quarrel so dreadfully one can't hear oneself speak--and they don't seem to have any rules in particular; at least, if there are, nobody attends to them--and you've no idea how confusing it is all the things being alive; for instance, there's the arch I've got to go through next walking about at the other end of the ground--and I should have croqueted the Queen's hedgehog just now, only it ran away when it saw mine coming!' `How do you like the Queen?' said the Cat in a low voice. `Not at all,' said Alice: `she's so extremely--' Just then she noticed that the Queen was close behind her, listening: so she went on, `--likely to win, that it's hardly worth while finishing the game.' The Queen smiled and passed on. `Who ARE you talking to?' said the King, going up to Alice, and looking at the Cat's head with great curiosity. `It's a friend of mine--a Cheshire Cat,' said Alice: `allow me to introduce it.' `I don't like the look of it at all,' said the King: `however, it may kiss my hand if it likes.' `I'd rather not,' the Cat remarked. `Don't be impertinent,' said the King, `and don't look at me like that!' He got behind Alice as he spoke. `A cat may look at a king,' said Alice. `I've read that in some book, but I don't remember where.' `Well, it must be removed,' said the King very decidedly, and he called the Queen, who was passing at the moment, `My dear! I wish you would have this cat removed!' The Queen had only one way of settling all difficulties, great or small. `Off with his head!' she said, without even looking round. `I'll fetch the executioner myself,' said the King eagerly, and he hurried off. Alice thought she might as well go back, and see how the game was going on, as she heard the Queen's voice in the distance, screaming with passion. She had already heard her sentence three of the players to be executed for having missed their turns, and she did not like the look of things at all, as the game was in such confusion that she never knew whether it was her turn or not. So she went in search of her hedgehog. The hedgehog was engaged in a fight with another hedgehog, which seemed to Alice an excellent opportunity for croqueting one of them with the other: the only difficulty was, that her flamingo was gone across to the other side of the garden, where Alice could see it trying in a helpless sort of way to fly up into a tree. By the time she had caught the flamingo and brought it back, the fight was over, and both the hedgehogs were out of sight: `but it doesn't matter much,' thought Alice, `as all the arches are gone from this side of the ground.' So she tucked it away under her arm, that it might not escape again, and went back for a little more conversation with her friend. When she got back to the Cheshire Cat, she was surprised to find quite a large crowd collected round it: there was a dispute going on between the executioner, the King, and the Queen, who were all talking at once, while all the rest were quite silent, and looked very uncomfortable. The moment Alice appeared, she was appealed to by all three to settle the question, and they repeated their arguments to her, though, as they all spoke at once, she found it very hard indeed to make out exactly what they said. The executioner's argument was, that you couldn't cut off a head unless there was a body to cut it off from: that he had never had to do such a thing before, and he wasn't going to begin at HIS time of life. The King's argument was, that anything that had a head could be beheaded, and that you weren't to talk nonsense. The Queen's argument was, that if something wasn't done about it in less than no time she'd have everybody executed, all round. (It was this last remark that had made the whole party look so grave and anxious.) Alice could think of nothing else to say but `It belongs to the Duchess: you'd better ask HER about it.' `She's in prison,' the Queen said to the executioner: `fetch her here.' And the executioner went off like an arrow. The Cat's head began fading away the moment he was gone, and, by the time he had come back with the Dutchess, it had entirely disappeared; so the King and the executioner ran wildly up and down looking for it, while the rest of the party went back to the game. CHAPTER IX The Mock Turtle's Story `You can't think how glad I am to see you again, you dear old thing!' said the Duchess, as she tucked her arm affectionately into Alice's, and they walked off together. Alice was very glad to find her in such a pleasant temper, and thought to herself that perhaps it was only the pepper that had made her so savage when they met in the kitchen. `When I'M a Duchess,' she said to herself, (not in a very hopeful tone though), `I won't have any pepper in my kitchen AT ALL. Soup does very well without--Maybe it's always pepper that makes people hot-tempered,' she went on, very much pleased at having found out a new kind of rule, `and vinegar that makes them sour--and camomile that makes them bitter--and--and barley-sugar and such things that make children sweet-tempered. I only wish people knew that: then they wouldn't be so stingy about it, you know--' She had quite forgotten the Duchess by this time, and was a little startled when she heard her voice close to her ear. `You're thinking about something, my dear, and that makes you forget to talk. I can't tell you just now what the moral of that is, but I shall remember it in a bit.' `Perhaps it hasn't one,' Alice ventured to remark. `Tut, tut, child!' said the Duchess. `Everything's got a moral, if only you can find it.' And she squeezed herself up closer to Alice's side as she spoke. Alice did not much like keeping so close to her: first, because the Duchess was VERY ugly; and secondly, because she was exactly the right height to rest her chin upon Alice's shoulder, and it was an uncomfortably sharp chin. However, she did not like to be rude, so she bore it as well as she could. `The game's going on rather better now,' she said, by way of keeping up the conversation a little. `'Tis so,' said the Duchess: `and the moral of that is--"Oh, 'tis love, 'tis love, that makes the world go round!"' `Somebody said,' Alice whispered, `that it's done by everybody minding their own business!' `Ah, well! It means much the same thing,' said the Duchess, digging her sharp little chin into Alice's shoulder as she added, `and the moral of THAT is--"Take care of the sense, and the sounds will take care of themselves."' `How fond she is of finding morals in things!' Alice thought to herself. `I dare say you're wondering why I don't put my arm round your waist,' the Duchess said after a pause: `the reason is, that I'm doubtful about the temper of your flamingo. Shall I try the experiment?' `HE might bite,' Alice cautiously replied, not feeling at all anxious to have the experiment tried. `Very true,' said the Duchess: `flamingoes and mustard both bite. And the moral of that is--"Birds of a feather flock together."' `Only mustard isn't a bird,' Alice remarked. `Right, as usual,' said the Duchess: `what a clear way you have of putting things!' `It's a mineral, I THINK,' said Alice. `Of course it is,' said the Duchess, who seemed ready to agree to everything that Alice said; `there's a large mustard-mine near here. And the moral of that is--"The more there is of mine, the less there is of yours."' `Oh, I know!' exclaimed Alice, who had not attended to this last remark, `it's a vegetable. It doesn't look like one, but it is.' `I quite agree with you,' said the Duchess; `and the moral of that is--"Be what you would seem to be"--or if you'd like it put more simply--"Never imagine yourself not to be otherwise than what it might appear to others that what you were or might have been was not otherwise than what you had been would have appeared to them to be otherwise."' `I think I should understand that better,' Alice said very politely, `if I had it written down: but I can't quite follow it as you say it.' `That's nothing to what I could say if I chose,' the Duchess replied, in a pleased tone. `Pray don't trouble yourself to say it any longer than that,' said Alice. `Oh, don't talk about trouble!' said the Duchess. `I make you a present of everything I've said as yet.' `A cheap sort of present!' thought Alice. `I'm glad they don't give birthday presents like that!' But she did not venture to say it out loud. `Thinking again?' the Duchess asked, with another dig of her sharp little chin. `I've a right to think,' said Alice sharply, for she was beginning to feel a little worried. `Just about as much right,' said the Duchess, `as pigs have to fly; and the m--' But here, to Alice's great surprise, the Duchess's voice died away, even in the middle of her favourite word `moral,' and the arm that was linked into hers began to tremble. Alice looked up, and there stood the Queen in front of them, with her arms folded, frowning like a thunderstorm. `A fine day, your Majesty!' the Duchess began in a low, weak voice. `Now, I give you fair warning,' shouted the Queen, stamping on the ground as she spoke; `either you or your head must be off, and that in about half no time! Take your choice!' The Duchess took her choice, and was gone in a moment. `Let's go on with the game,' the Queen said to Alice; and Alice was too much frightened to say a word, but slowly followed her back to the croquet-ground. The other guests had taken advantage of the Queen's absence, and were resting in the shade: however, the moment they saw her, they hurried back to the game, the Queen merely remarking that a moment's delay would cost them their lives. All the time they were playing the Queen never left off quarrelling with the other players, and shouting `Off with his head!' or `Off with her head!' Those whom she sentenced were taken into custody by the soldiers, who of course had to leave off being arches to do this, so that by the end of half an hour or so there were no arches left, and all the players, except the King, the Queen, and Alice, were in custody and under sentence of execution. Then the Queen left off, quite out of breath, and said to Alice, `Have you seen the Mock Turtle yet?' `No,' said Alice. `I don't even know what a Mock Turtle is.' `It's the thing Mock Turtle Soup is made from,' said the Queen. `I never saw one, or heard of one,' said Alice. `Come on, then,' said the Queen, `and he shall tell you his history,' As they walked off together, Alice heard the King say in a low voice, to the company generally, `You are all pardoned.' `Come, THAT'S a good thing!' she said to herself, for she had felt quite unhappy at the number of executions the Queen had ordered. They very soon came upon a Gryphon, lying fast asleep in the sun. (IF you don't know what a Gryphon is, look at the picture.) `Up, lazy thing!' said the Queen, `and take this young lady to see the Mock Turtle, and to hear his history. I must go back and see after some executions I have ordered'; and she walked off, leaving Alice alone with the Gryphon. Alice did not quite like the look of the creature, but on the whole she thought it would be quite as safe to stay with it as to go after that savage Queen: so she waited. The Gryphon sat up and rubbed its eyes: then it watched the Queen till she was out of sight: then it chuckled. `What fun!' said the Gryphon, half to itself, half to Alice. `What IS the fun?' said Alice. `Why, SHE,' said the Gryphon. `It's all her fancy, that: they never executes nobody, you know. Come on!' `Everybody says "come on!" here,' thought Alice, as she went slowly after it: `I never was so ordered about in all my life, never!' They had not gone far before they saw the Mock Turtle in the distance, sitting sad and lonely on a little ledge of rock, and, as they came nearer, Alice could hear him sighing as if his heart would break. She pitied him deeply. `What is his sorrow?' she asked the Gryphon, and the Gryphon answered, very nearly in the same words as before, `It's all his fancy, that: he hasn't got no sorrow, you know. Come on!' So they went up to the Mock Turtle, who looked at them with large eyes full of tears, but said nothing. `This here young lady,' said the Gryphon, `she wants for to know your history, she do.' `I'll tell it her,' said the Mock Turtle in a deep, hollow tone: `sit down, both of you, and don't speak a word till I've finished.' So they sat down, and nobody spoke for some minutes. Alice thought to herself, `I don't see how he can EVEN finish, if he doesn't begin.' But she waited patiently. `Once,' said the Mock Turtle at last, with a deep sigh, `I was a real Turtle.' These words were followed by a very long silence, broken only by an occasional exclamation of `Hjckrrh!' from the Gryphon, and the constant heavy sobbing of the Mock Turtle. Alice was very nearly getting up and saying, `Thank you, sir, for your interesting story,' but she could not help thinking there MUST be more to come, so she sat still and said nothing. `When we were little,' the Mock Turtle went on at last, more calmly, though still sobbing a little now and then, `we went to school in the sea. The master was an old Turtle--we used to call him Tortoise--' `Why did you call him Tortoise, if he wasn't one?' Alice asked. `We called him Tortoise because he taught us,' said the Mock Turtle angrily: `really you are very dull!' `You ought to be ashamed of yourself for asking such a simple question,' added the Gryphon; and then they both sat silent and looked at poor Alice, who felt ready to sink into the earth. At last the Gryphon said to the Mock Turtle, `Drive on, old fellow! Don't be all day about it!' and he went on in these words: `Yes, we went to school in the sea, though you mayn't believe it--' `I never said I didn't!' interrupted Alice. `You did,' said the Mock Turtle. `Hold your tongue!' added the Gryphon, before Alice could speak again. The Mock Turtle went on. `We had the best of educations--in fact, we went to school every day--' `I'VE been to a day-school, too,' said Alice; `you needn't be so proud as all that.' `With extras?' asked the Mock Turtle a little anxiously. `Yes,' said Alice, `we learned French and music.' `And washing?' said the Mock Turtle. `Certainly not!' said Alice indignantly. `Ah! then yours wasn't a really good school,' said the Mock Turtle in a tone of great relief. `Now at OURS they had at the end of the bill, "French, music, AND WASHING--extra."' `You couldn't have wanted it much,' said Alice; `living at the bottom of the sea.' `I couldn't afford to learn it.' said the Mock Turtle with a sigh. `I only took the regular course.' `What was that?' inquired Alice. `Reeling and Writhing, of course, to begin with,' the Mock Turtle replied; `and then the different branches of Arithmetic-- Ambition, Distraction, Uglification, and Derision.' `I never heard of "Uglification,"' Alice ventured to say. `What is it?' The Gryphon lifted up both its paws in surprise. `What! Never heard of uglifying!' it exclaimed. `You know what to beautify is, I suppose?' `Yes,' said Alice doubtfully: `it means--to--make--anything-- prettier.' `Well, then,' the Gryphon went on, `if you don't know what to uglify is, you ARE a simpleton.' Alice did not feel encouraged to ask any more questions about it, so she turned to the Mock Turtle, and said `What else had you to learn?' `Well, there was Mystery,' the Mock Turtle replied, counting off the subjects on his flappers, `--Mystery, ancient and modern, with Seaography: then Drawling--the Drawling-master was an old conger-eel, that used to come once a week: HE taught us Drawling, Stretching, and Fainting in Coils.' `What was THAT like?' said Alice. `Well, I can't show it you myself,' the Mock Turtle said: `I'm too stiff. And the Gryphon never learnt it.' `Hadn't time,' said the Gryphon: `I went to the Classics master, though. He was an old crab, HE was.' `I never went to him,' the Mock Turtle said with a sigh: `he taught Laughing and Grief, they used to say.' `So he did, so he did,' said the Gryphon, sighing in his turn; and both creatures hid their faces in their paws. `And how many hours a day did you do lessons?' said Alice, in a hurry to change the subject. `Ten hours the first day,' said the Mock Turtle: `nine the next, and so on.' `What a curious plan!' exclaimed Alice. `That's the reason they're called lessons,' the Gryphon remarked: `because they lessen from day to day.' This was quite a new idea to Alice, and she thought it over a little before she made her next remark. `Then the eleventh day must have been a holiday?' `Of course it was,' said the Mock Turtle. `And how did you manage on the twelfth?' Alice went on eagerly. `That's enough about lessons,' the Gryphon interrupted in a very decided tone: `tell her something about the games now.' CHAPTER X The Lobster Quadrille The Mock Turtle sighed deeply, and drew the back of one flapper across his eyes. He looked at Alice, and tried to speak, but for a minute or two sobs choked his voice. `Same as if he had a bone in his throat,' said the Gryphon: and it set to work shaking him and punching him in the back. At last the Mock Turtle recovered his voice, and, with tears running down his cheeks, he went on again:-- `You may not have lived much under the sea--' (`I haven't,' said Alice)--`and perhaps you were never even introduced to a lobster--' (Alice began to say `I once tasted--' but checked herself hastily, and said `No, never') `--so you can have no idea what a delightful thing a Lobster Quadrille is!' `No, indeed,' said Alice. `What sort of a dance is it?' `Why,' said the Gryphon, `you first form into a line along the sea-shore--' `Two lines!' cried the Mock Turtle. `Seals, turtles, salmon, and so on; then, when you've cleared all the jelly-fish out of the way--' `THAT generally takes some time,' interrupted the Gryphon. `--you advance twice--' `Each with a lobster as a partner!' cried the Gryphon. `Of course,' the Mock Turtle said: `advance twice, set to partners--' `--change lobsters, and retire in same order,' continued the Gryphon. `Then, you know,' the Mock Turtle went on, `you throw the--' `The lobsters!' shouted the Gryphon, with a bound into the air. `--as far out to sea as you can--' `Swim after them!' screamed the Gryphon. `Turn a somersault in the sea!' cried the Mock Turtle, capering wildly about. `Back to land again, and that's all the first figure,' said the Mock Turtle, suddenly dropping his voice; and the two creatures, who had been jumping about like mad things all this time, sat down again very sadly and quietly, and looked at Alice. `It must be a very pretty dance,' said Alice timidly. `Would you like to see a little of it?' said the Mock Turtle. `Very much indeed,' said Alice. `Come, let's try the first figure!' said the Mock Turtle to the Gryphon. `We can do without lobsters, you know. Which shall sing?' `Oh, YOU sing,' said the Gryphon. `I've forgotten the words.' So they began solemnly dancing round and round Alice, every now and then treading on her toes when they passed too close, and waving their forepaws to mark the time, while the Mock Turtle sang this, very slowly and sadly:-- `"Will you walk a little faster?" said a whiting to a snail. "There's a porpoise close behind us, and he's treading on my tail. See how eagerly the lobsters and the turtles all advance! They are waiting on the shingle--will you come and join the dance? Will you, won't you, will you, won't you, will you join the dance? Will you, won't you, will you, won't you, won't you join the dance? "You can really have no notion how delightful it will be When they take us up and throw us, with the lobsters, out to sea!" But the snail replied "Too far, too far!" and gave a look askance-- Said he thanked the whiting kindly, but he would not join the dance. Would not, could not, would not, could not, would not join the dance. Would not, could not, would not, could not, could not join the dance. `"What matters it how far we go?" his scaly friend replied. "There is another shore, you know, upon the other side. The further off from England the nearer is to France-- Then turn not pale, beloved snail, but come and join the dance. Will you, won't you, will you, won't you, will you join the dance? Will you, won't you, will you, won't you, won't you join the dance?"' `Thank you, it's a very interesting dance to watch,' said Alice, feeling very glad that it was over at last: `and I do so like that curious song about the whiting!' `Oh, as to the whiting,' said the Mock Turtle, `they--you've seen them, of course?' `Yes,' said Alice, `I've often seen them at dinn--' she checked herself hastily. `I don't know where Dinn may be,' said the Mock Turtle, `but if you've seen them so often, of course you know what they're like.' `I believe so,' Alice replied thoughtfully. `They have their tails in their mouths--and they're all over crumbs.' `You're wrong about the crumbs,' said the Mock Turtle: `crumbs would all wash off in the sea. But they HAVE their tails in their mouths; and the reason is--' here the Mock Turtle yawned and shut his eyes.--`Tell her about the reason and all that,' he said to the Gryphon. `The reason is,' said the Gryphon, `that they WOULD go with the lobsters to the dance. So they got thrown out to sea. So they had to fall a long way. So they got their tails fast in their mouths. So they couldn't get them out again. That's all.' `Thank you,' said Alice, `it's very interesting. I never knew so much about a whiting before.' `I can tell you more than that, if you like,' said the Gryphon. `Do you know why it's called a whiting?' `I never thought about it,' said Alice. `Why?' `IT DOES THE BOOTS AND SHOES.' the Gryphon replied very solemnly. Alice was thoroughly puzzled. `Does the boots and shoes!' she repeated in a wondering tone. `Why, what are YOUR shoes done with?' said the Gryphon. `I mean, what makes them so shiny?' Alice looked down at them, and considered a little before she gave her answer. `They're done with blacking, I believe.' `Boots and shoes under the sea,' the Gryphon went on in a deep voice, `are done with a whiting. Now you know.' `And what are they made of?' Alice asked in a tone of great curiosity. `Soles and eels, of course,' the Gryphon replied rather impatiently: `any shrimp could have told you that.' `If I'd been the whiting,' said Alice, whose thoughts were still running on the song, `I'd have said to the porpoise, "Keep back, please: we don't want YOU with us!"' `They were obliged to have him with them,' the Mock Turtle said: `no wise fish would go anywhere without a porpoise.' `Wouldn't it really?' said Alice in a tone of great surprise. `Of course not,' said the Mock Turtle: `why, if a fish came to ME, and told me he was going a journey, I should say "With what porpoise?"' `Don't you mean "purpose"?' said Alice. `I mean what I say,' the Mock Turtle replied in an offended tone. And the Gryphon added `Come, let's hear some of YOUR adventures.' `I could tell you my adventures--beginning from this morning,' said Alice a little timidly: `but it's no use going back to yesterday, because I was a different person then.' `Explain all that,' said the Mock Turtle. `No, no! The adventures first,' said the Gryphon in an impatient tone: `explanations take such a dreadful time.' So Alice began telling them her adventures from the time when she first saw the White Rabbit. She was a little nervous about it just at first, the two creatures got so close to her, one on each side, and opened their eyes and mouths so VERY wide, but she gained courage as she went on. Her listeners were perfectly quiet till she got to the part about her repeating `YOU ARE OLD, FATHER WILLIAM,' to the Caterpillar, and the words all coming different, and then the Mock Turtle drew a long breath, and said `That's very curious.' `It's all about as curious as it can be,' said the Gryphon. `It all came different!' the Mock Turtle repeated thoughtfully. `I should like to hear her try and repeat something now. Tell her to begin.' He looked at the Gryphon as if he thought it had some kind of authority over Alice. `Stand up and repeat "'TIS THE VOICE OF THE SLUGGARD,"' said the Gryphon. `How the creatures order one about, and make one repeat lessons!' thought Alice; `I might as well be at school at once.' However, she got up, and began to repeat it, but her head was so full of the Lobster Quadrille, that she hardly knew what she was saying, and the words came very queer indeed:-- `'Tis the voice of the Lobster; I heard him declare, "You have baked me too brown, I must sugar my hair." As a duck with its eyelids, so he with his nose Trims his belt and his buttons, and turns out his toes.' [later editions continued as follows When the sands are all dry, he is gay as a lark, And will talk in contemptuous tones of the Shark, But, when the tide rises and sharks are around, His voice has a timid and tremulous sound.] `That's different from what I used to say when I was a child,' said the Gryphon. `Well, I never heard it before,' said the Mock Turtle; `but it sounds uncommon nonsense.' Alice said nothing; she had sat down with her face in her hands, wondering if anything would EVER happen in a natural way again. `I should like to have it explained,' said the Mock Turtle. `She can't explain it,' said the Gryphon hastily. `Go on with the next verse.' `But about his toes?' the Mock Turtle persisted. `How COULD he turn them out with his nose, you know?' `It's the first position in dancing.' Alice said; but was dreadfully puzzled by the whole thing, and longed to change the subject. `Go on with the next verse,' the Gryphon repeated impatiently: `it begins "I passed by his garden."' Alice did not dare to disobey, though she felt sure it would all come wrong, and she went on in a trembling voice:-- `I passed by his garden, and marked, with one eye, How the Owl and the Panther were sharing a pie--' [later editions continued as follows The Panther took pie-crust, and gravy, and meat, While the Owl had the dish as its share of the treat. When the pie was all finished, the Owl, as a boon, Was kindly permitted to pocket the spoon: While the Panther received knife and fork with a growl, And concluded the banquet--] `What IS the use of repeating all that stuff,' the Mock Turtle interrupted, `if you don't explain it as you go on? It's by far the most confusing thing I ever heard!' `Yes, I think you'd better leave off,' said the Gryphon: and Alice was only too glad to do so. `Shall we try another figure of the Lobster Quadrille?' the Gryphon went on. `Or would you like the Mock Turtle to sing you a song?' `Oh, a song, please, if the Mock Turtle would be so kind,' Alice replied, so eagerly that the Gryphon said, in a rather offended tone, `Hm! No accounting for tastes! Sing her "Turtle Soup," will you, old fellow?' The Mock Turtle sighed deeply, and began, in a voice sometimes choked with sobs, to sing this:-- `Beautiful Soup, so rich and green, Waiting in a hot tureen! Who for such dainties would not stoop? Soup of the evening, beautiful Soup! Soup of the evening, beautiful Soup! Beau--ootiful Soo--oop! Beau--ootiful Soo--oop! Soo--oop of the e--e--evening, Beautiful, beautiful Soup! `Beautiful Soup! Who cares for fish, Game, or any other dish? Who would not give all else for two p ennyworth only of beautiful Soup? Pennyworth only of beautiful Soup? Beau--ootiful Soo--oop! Beau--ootiful Soo--oop! Soo--oop of the e--e--evening, Beautiful, beauti--FUL SOUP!' `Chorus again!' cried the Gryphon, and the Mock Turtle had just begun to repeat it, when a cry of `The trial's beginning!' was heard in the distance. `Come on!' cried the Gryphon, and, taking Alice by the hand, it hurried off, without waiting for the end of the song. `What trial is it?' Alice panted as she ran; but the Gryphon only answered `Come on!' and ran the faster, while more and more faintly came, carried on the breeze that followed them, the melancholy words:-- `Soo--oop of the e--e--evening, Beautiful, beautiful Soup!' CHAPTER XI Who Stole the Tarts? The King and Queen of Hearts were seated on their throne when they arrived, with a great crowd assembled about them--all sorts of little birds and beasts, as well as the whole pack of cards: the Knave was standing before them, in chains, with a soldier on each side to guard him; and near the King was the White Rabbit, with a trumpet in one hand, and a scroll of parchment in the other. In the very middle of the court was a table, with a large dish of tarts upon it: they looked so good, that it made Alice quite hungry to look at them--`I wish they'd get the trial done,' she thought, `and hand round the refreshments!' But there seemed to be no chance of this, so she began looking at everything about her, to pass away the time. Alice had never been in a court of justice before, but she had read about them in books, and she was quite pleased to find that she knew the name of nearly everything there. `That's the judge,' she said to herself, `because of his great wig.' The judge, by the way, was the King; and as he wore his crown over the wig, (look at the frontispiece if you want to see how he did it,) he did not look at all comfortable, and it was certainly not becoming. `And that's the jury-box,' thought Alice, `and those twelve creatures,' (she was obliged to say `creatures,' you see, because some of them were animals, and some were birds,) `I suppose they are the jurors.' She said this last word two or three times over to herself, being rather proud of it: for she thought, and rightly too, that very few little girls of her age knew the meaning of it at all. However, `jury-men' would have done just as well. The twelve jurors were all writing very busily on slates. `What are they doing?' Alice whispered to the Gryphon. `They can't have anything to put down yet, before the trial's begun.' `They're putting down their names,' the Gryphon whispered in reply, `for fear they should forget them before the end of the trial.' `Stupid things!' Alice began in a loud, indignant voice, but she stopped hastily, for the White Rabbit cried out, `Silence in the court!' and the King put on his spectacles and looked anxiously round, to make out who was talking. Alice could see, as well as if she were looking over their shoulders, that all the jurors were writing down `stupid things!' on their slates, and she could even make out that one of them didn't know how to spell `stupid,' and that he had to ask his neighbour to tell him. `A nice muddle their slates'll be in before the trial's over!' thought Alice. One of the jurors had a pencil that squeaked. This of course, Alice could not stand, and she went round the court and got behind him, and very soon found an opportunity of taking it away. She did it so quickly that the poor little juror (it was Bill, the Lizard) could not make out at all what had become of it; so, after hunting all about for it, he was obliged to write with one finger for the rest of the day; and this was of very little use, as it left no mark on the slate. `Herald, read the accusation!' said the King. On this the White Rabbit blew three blasts on the trumpet, and then unrolled the parchment scroll, and read as follows:-- `The Queen of Hearts, she made some tarts, All on a summer day: The Knave of Hearts, he stole those tarts, And took them quite away!' `Consider your verdict,' the King said to the jury. `Not yet, not yet!' the Rabbit hastily interrupted. `There's a great deal to come before that!' `Call the first witness,' said the King; and the White Rabbit blew three blasts on the trumpet, and called out, `First witness!' The first witness was the Hatter. He came in with a teacup in one hand and a piece of bread-and-butter in the other. `I beg pardon, your Majesty,' he began, `for bringing these in: but I hadn't quite finished my tea when I was sent for.' `You ought to have finished,' said the King. `When did you begin?' The Hatter looked at the March Hare, who had followed him into the court, arm-in-arm with the Dormouse. `Fourteenth of March, I think it was,' he said. `Fifteenth,' said the March Hare. `Sixteenth,' added the Dormouse. `Write that down,' the King said to the jury, and the jury eagerly wrote down all three dates on their slates, and then added them up, and reduced the answer to shillings and pence. `Take off your hat,' the King said to the Hatter. `It isn't mine,' said the Hatter. `Stolen!' the King exclaimed, turning to the jury, who instantly made a memorandum of the fact. `I keep them to sell,' the Hatter added as an explanation; `I've none of my own. I'm a hatter.' Here the Queen put on her spectacles, and began staring at the Hatter, who turned pale and fidgeted. `Give your evidence,' said the King; `and don't be nervous, or I'll have you executed on the spot.' This did not seem to encourage the witness at all: he kept shifting from one foot to the other, looking uneasily at the Queen, and in his confusion he bit a large piece out of his teacup instead of the bread-and-butter. Just at this moment Alice felt a very curious sensation, which puzzled her a good deal until she made out what it was: she was beginning to grow larger again, and she thought at first she would get up and leave the court; but on second thoughts she decided to remain where she was as long as there was room for her. `I wish you wouldn't squeeze so.' said the Dormouse, who was sitting next to her. `I can hardly breathe.' `I can't help it,' said Alice very meekly: `I'm growing.' `You've no right to grow here,' said the Dormouse. `Don't talk nonsense,' said Alice more boldly: `you know you're growing too.' `Yes, but I grow at a reasonable pace,' said the Dormouse: `not in that ridiculous fashion.' And he got up very sulkily and crossed over to the other side of the court. All this time the Queen had never left off staring at the Hatter, and, just as the Dormouse crossed the court, she said to one of the officers of the court, `Bring me the list of the singers in the last concert!' on which the wretched Hatter trembled so, that he shook both his shoes off. `Give your evidence,' the King repeated angrily, `or I'll have you executed, whether you're nervous or not.' `I'm a poor man, your Majesty,' the Hatter began, in a trembling voice, `--and I hadn't begun my tea--not above a week or so--and what with the bread-and-butter getting so thin--and the twinkling of the tea--' `The twinkling of the what?' said the King. `It began with the tea,' the Hatter replied. `Of course twinkling begins with a T!' said the King sharply. `Do you take me for a dunce? Go on!' `I'm a poor man,' the Hatter went on, `and most things twinkled after that--only the March Hare said--' `I didn't!' the March Hare interrupted in a great hurry. `You did!' said the Hatter. `I deny it!' said the March Hare. `He denies it,' said the King: `leave out that part.' `Well, at any rate, the Dormouse said--' the Hatter went on, looking anxiously round to see if he would deny it too: but the Dormouse denied nothing, being fast asleep. `After that,' continued the Hatter, `I cut some more bread- and-butter--' `But what did the Dormouse say?' one of the jury asked. `That I can't remember,' said the Hatter. `You MUST remember,' remarked the King, `or I'll have you executed.' The miserable Hatter dropped his teacup and bread-and-butter, and went down on one knee. `I'm a poor man, your Majesty,' he began. `You're a very poor speaker,' said the King. Here one of the guinea-pigs cheered, and was immediately suppressed by the officers of the court. (As that is rather a hard word, I will just explain to you how it was done. They had a large canvas bag, which tied up at the mouth with strings: into this they slipped the guinea-pig, head first, and then sat upon it.) `I'm glad I've seen that done,' thought Alice. `I've so often read in the newspapers, at the end of trials, "There was some attempts at applause, which was immediately suppressed by the officers of the court," and I never understood what it meant till now.' `If that's all you know about it, you may stand down,' continued the King. `I can't go no lower,' said the Hatter: `I'm on the floor, as it is.' `Then you may SIT down,' the King replied. Here the other guinea-pig cheered, and was suppressed. `Come, that finished the guinea-pigs!' thought Alice. `Now we shall get on better.' `I'd rather finish my tea,' said the Hatter, with an anxious look at the Queen, who was reading the list of singers. `You may go,' said the King, and the Hatter hurriedly left the court, without even waiting to put his shoes on. `--and just take his head off outside,' the Queen added to one of the officers: but the Hatter was out of sight before the officer could get to the door. `Call the next witness!' said the King. The next witness was the Duchess's cook. She carried the pepper-box in her hand, and Alice guessed who it was, even before she got into the court, by the way the people near the door began sneezing all at once. `Give your evidence,' said the King. `Shan't,' said the cook. The King looked anxiously at the White Rabbit, who said in a low voice, `Your Majesty must cross-examine THIS witness.' `Well, if I must, I must,' the King said, with a melancholy air, and, after folding his arms and frowning at the cook till his eyes were nearly out of sight, he said in a deep voice, `What are tarts made of?' `Pepper, mostly,' said the cook. `Treacle,' said a sleepy voice behind her. `Collar that Dormouse,' the Queen shrieked out. `Behead that Dormouse! Turn that Dormouse out of court! Suppress him! Pinch him! Off with his whiskers!' For some minutes the whole court was in confusion, getting the Dormouse turned out, and, by the time they had settled down again, the cook had disappeared. `Never mind!' said the King, with an air of great relief. `Call the next witness.' And he added in an undertone to the Queen, `Really, my dear, YOU must cross-examine the next witness. It quite makes my forehead ache!' Alice watched the White Rabbit as he fumbled over the list, feeling very curious to see what the next witness would be like, `--for they haven't got much evidence YET,' she said to herself. Imagine her surprise, when the White Rabbit read out, at the top of his shrill little voice, the name `Alice!' CHAPTER XII Alice's Evidence `Here!' cried Alice, quite forgetting in the flurry of the moment how large she had grown in the last few minutes, and she jumped up in such a hurry that she tipped over the jury-box with the edge of her skirt, upsetting all the jurymen on to the heads of the crowd below, and there they lay sprawling about, reminding her very much of a globe of goldfish she had accidentally upset the week before. `Oh, I BEG your pardon!' she exclaimed in a tone of great dismay, and began picking them up again as quickly as she could, for the accident of the goldfish kept running in her head, and she had a vague sort of idea that they must be collected at once and put back into the jury-box, or they would die. `The trial cannot proceed,' said the King in a very grave voice, `until all the jurymen are back in their proper places-- ALL,' he repeated with great emphasis, looking hard at Alice as he said do. Alice looked at the jury-box, and saw that, in her haste, she had put the Lizard in head downwards, and the poor little thing was waving its tail about in a melancholy way, being quite unable to move. She soon got it out again, and put it right; `not that it signifies much,' she said to herself; `I should think it would be QUITE as much use in the trial one way up as the other.' As soon as the jury had a little recovered from the shock of being upset, and their slates and pencils had been found and handed back to them, they set to work very diligently to write out a history of the accident, all except the Lizard, who seemed too much overcome to do anything but sit with its mouth open, gazing up into the roof of the court. `What do you know about this business?' the King said to Alice. `Nothing,' said Alice. `Nothing WHATEVER?' persisted the King. `Nothing whatever,' said Alice. `That's very important,' the King said, turning to the jury. They were just beginning to write this down on their slates, when the White Rabbit interrupted: `UNimportant, your Majesty means, of course,' he said in a very respectful tone, but frowning and making faces at him as he spoke. `UNimportant, of course, I meant,' the King hastily said, and went on to himself in an undertone, `important--unimportant-- unimportant--important--' as if he were trying which word sounded best. Some of the jury wrote it down `important,' and some `unimportant.' Alice could see this, as she was near enough to look over their slates; `but it doesn't matter a bit,' she thought to herself. At this moment the King, who had been for some time busily writing in his note-book, cackled out `Silence!' and read out from his book, `Rule Forty-two. ALL PERSONS MORE THAN A MILE HIGH TO LEAVE THE COURT.' Everybody looked at Alice. `I'M not a mile high,' said Alice. `You are,' said the King. `Nearly two miles high,' added the Queen. `Well, I shan't go, at any rate,' said Alice: `besides, that's not a regular rule: you invented it just now.' `It's the oldest rule in the book,' said the King. `Then it ought to be Number One,' said Alice. The King turned pale, and shut his note-book hastily. `Consider your verdict,' he said to the jury, in a low, trembling voice. `There's more evidence to come yet, please your Majesty,' said the White Rabbit, jumping up in a great hurry; `this paper has just been picked up.' `What's in it?' said the Queen. `I haven't opened it yet,' said the White Rabbit, `but it seems to be a letter, written by the prisoner to--to somebody.' `It must have been that,' said the King, `unless it was written to nobody, which isn't usual, you know.' `Who is it directed to?' said one of the jurymen. `It isn't directed at all,' said the White Rabbit; `in fact, there's nothing written on the OUTSIDE.' He unfolded the paper as he spoke, and added `It isn't a letter, after all: it's a set of verses.' `Are they in the prisoner's handwriting?' asked another of they jurymen. `No, they're not,' said the White Rabbit, `and that's the queerest thing about it.' (The jury all looked puzzled.) `He must have imitated somebody else's hand,' said the King. (The jury all brightened up again.) `Please your Majesty,' said the Knave, `I didn't write it, and they can't prove I did: there's no name signed at the end.' `If you didn't sign it,' said the King, `that only makes the matter worse. You MUST have meant some mischief, or else you'd have signed your name like an honest man.' There was a general clapping of hands at this: it was the first really clever thing the King had said that day. `That PROVES his guilt,' said the Queen. `It proves nothing of the sort!' said Alice. `Why, you don't even know what they're about!' `Read them,' said the King. The White Rabbit put on his spectacles. `Where shall I begin, please your Majesty?' he asked. `Begin at the beginning,' the King said gravely, `and go on till you come to the end: then stop.' These were the verses the White Rabbit read:-- `They told me you had been to her, And mentioned me to him: She gave me a good character, But said I could not swim. He sent them word I had not gone (We know it to be true): If she should push the matter on, What would become of you? I gave her one, they gave him two, You gave us three or more; They all returned from him to you, Though they were mine before. If I or she should chance to be Involved in this affair, He trusts to you to set them free, Exactly as we were. My notion was that you had been (Before she had this fit) An obstacle that came between Him, and ourselves, and it. Don't let him know she liked them best, For this must ever be A secret, kept from all the rest, Between yourself and me.' `That's the most important piece of evidence we've heard yet,' said the King, rubbing his hands; `so now let the jury--' `If any one of them can explain it,' said Alice, (she had grown so large in the last few minutes that she wasn't a bit afraid of interrupting him,) `I'll give him sixpence. _I_ don't believe there's an atom of meaning in it.' The jury all wrote down on their slates, `SHE doesn't believe there's an atom of meaning in it,' but none of them attempted to explain the paper. `If there's no meaning in it,' said the King, `that saves a world of trouble, you know, as we needn't try to find any. And yet I don't know,' he went on, spreading out the verses on his knee, and looking at them with one eye; `I seem to see some meaning in them, after all. "--SAID I COULD NOT SWIM--" you can't swim, can you?' he added, turning to the Knave. The Knave shook his head sadly. `Do I look like it?' he said. (Which he certainly did NOT, being made entirely of cardboard.) `All right, so far,' said the King, and he went on muttering over the verses to himself: `"WE KNOW IT TO BE TRUE--" that's the jury, of course-- "I GAVE HER ONE, THEY GAVE HIM TWO--" why, that must be what he did with the tarts, you know--' `But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said Alice. `Why, there they are!' said the King triumphantly, pointing to the tarts on the table. `Nothing can be clearer than THAT. Then again--"BEFORE SHE HAD THIS FIT--" you never had fits, my dear, I think?' he said to the Queen. `Never!' said the Queen furiously, throwing an inkstand at the Lizard as she spoke. (The unfortunate little Bill had left off writing on his slate with one finger, as he found it made no mark; but he now hastily began again, using the ink, that was trickling down his face, as long as it lasted.) `Then the words don't FIT you,' said the King, looking round the court with a smile. There was a dead silence. `It's a pun!' the King added in an offended tone, and everybody laughed, `Let the jury consider their verdict,' the King said, for about the twentieth time that day. `No, no!' said the Queen. `Sentence first--verdict afterwards.' `Stuff and nonsense!' said Alice loudly. `The idea of having the sentence first!' `Hold your tongue!' said the Queen, turning purple. `I won't!' said Alice. `Off with her head!' the Queen shouted at the top of her voice. Nobody moved. `Who cares for you?' said Alice, (she had grown to her full size by this time.) `You're nothing but a pack of cards!' At this the whole pack rose up into the air, and came flying down upon her: she gave a little scream, half of fright and half of anger, and tried to beat them off, and found herself lying on the bank, with her head in the lap of her sister, who was gently brushing away some dead leaves that had fluttered down from the trees upon her face. `Wake up, Alice dear!' said her sister; `Why, what a long sleep you've had!' `Oh, I've had such a curious dream!' said Alice, and she told her sister, as well as she could remember them, all these strange Adventures of hers that you have just been reading about; and when she had finished, her sister kissed her, and said, `It WAS a curious dream, dear, certainly: but now run in to your tea; it's getting late.' So Alice got up and ran off, thinking while she ran, as well she might, what a wonderful dream it had been. But her sister sat still just as she left her, leaning her head on her hand, watching the setting sun, and thinking of little Alice and all her wonderful Adventures, till she too began dreaming after a fashion, and this was her dream:-- First, she dreamed of little Alice herself, and once again the tiny hands were clasped upon her knee, and the bright eager eyes were looking up into hers--she could hear the very tones of her voice, and see that queer little toss of her head to keep back the wandering hair that WOULD always get into her eyes--and still as she listened, or seemed to listen, the whole place around her became alive the strange creatures of her little sister's dream. The long grass rustled at her feet as the White Rabbit hurried by--the frightened Mouse splashed his way through the neighbouring pool--she could hear the rattle of the teacups as the March Hare and his friends shared their never-ending meal, and the shrill voice of the Queen ordering off her unfortunate guests to execution--once more the pig-baby was sneezing on the Duchess's knee, while plates and dishes crashed around it--once more the shriek of the Gryphon, the squeaking of the Lizard's slate-pencil, and the choking of the suppressed guinea-pigs, filled the air, mixed up with the distant sobs of the miserable Mock Turtle. So she sat on, with closed eyes, and half believed herself in Wonderland, though she knew she had but to open them again, and all would change to dull reality--the grass would be only rustling in the wind, and the pool rippling to the waving of the reeds--the rattling teacups would change to tinkling sheep- bells, and the Queen's shrill cries to the voice of the shepherd boy--and the sneeze of the baby, the shriek of the Gryphon, and all thy other queer noises, would change (she knew) to the confused clamour of the busy farm-yard--while the lowing of the cattle in the distance would take the place of the Mock Turtle's heavy sobs. Lastly, she pictured to herself how this same little sister of hers would, in the after-time, be herself a grown woman; and how she would keep, through all her riper years, the simple and loving heart of her childhood: and how she would gather about her other little children, and make THEIR eyes bright and eager with many a strange tale, perhaps even with the dream of Wonderland of long ago: and how she would feel with all their simple sorrows, and find a pleasure in all their simple joys, remembering her own child-life, and the happy summer days. THE END  AS YOU LIKE IT DRAMATIS PERSONAE DUKE SENIOR living in banishment. DUKE FREDERICK his brother, an usurper of his dominions. AMIENS | | lords attending on the banished duke. JAQUES | LE BEAU a courtier attending upon Frederick. CHARLES wrestler to Frederick. OLIVER | | JAQUES (JAQUES DE BOYS:) | sons of Sir Rowland de Boys. | ORLANDO | ADAM | | servants to Oliver. DENNIS | TOUCHSTONE a clown. SIR OLIVER MARTEXT a vicar. CORIN | | shepherds. SILVIUS | WILLIAM a country fellow in love with Audrey. A person representing HYMEN. (HYMEN:) ROSALIND daughter to the banished duke. CELIA daughter to Frederick. PHEBE a shepherdess. AUDREY a country wench. Lords, pages, and attendants, &c. (Forester:) (A Lord:) (First Lord:) (Second Lord:) (First Page:) (Second Page:) SCENE Oliver's house; Duke Frederick's court; and the Forest of Arden. AS YOU LIKE IT ACT I SCENE I Orchard of Oliver's house. [Enter ORLANDO and ADAM] ORLANDO As I remember, Adam, it was upon this fashion bequeathed me by will but poor a thousand crowns, and, as thou sayest, charged my brother, on his blessing, to breed me well: and there begins my sadness. My brother Jaques he keeps at school, and report speaks goldenly of his profit: for my part, he keeps me rustically at home, or, to speak more properly, stays me here at home unkept; for call you that keeping for a gentleman of my birth, that differs not from the stalling of an ox? His horses are bred better; for, besides that they are fair with their feeding, they are taught their manage, and to that end riders dearly hired: but I, his brother, gain nothing under him but growth; for the which his animals on his dunghills are as much bound to him as I. Besides this nothing that he so plentifully gives me, the something that nature gave me his countenance seems to take from me: he lets me feed with his hinds, bars me the place of a brother, and, as much as in him lies, mines my gentility with my education. This is it, Adam, that grieves me; and the spirit of my father, which I think is within me, begins to mutiny against this servitude: I will no longer endure it, though yet I know no wise remedy how to avoid it. ADAM Yonder comes my master, your brother. ORLANDO Go apart, Adam, and thou shalt hear how he will shake me up. [Enter OLIVER] OLIVER Now, sir! what make you here? ORLANDO Nothing: I am not taught to make any thing. OLIVER What mar you then, sir? ORLANDO Marry, sir, I am helping you to mar that which God made, a poor unworthy brother of yours, with idleness. OLIVER Marry, sir, be better employed, and be naught awhile. ORLANDO Shall I keep your hogs and eat husks with them? What prodigal portion have I spent, that I should come to such penury? OLIVER Know you where your are, sir? ORLANDO O, sir, very well; here in your orchard. OLIVER Know you before whom, sir? ORLANDO Ay, better than him I am before knows me. I know you are my eldest brother; and, in the gentle condition of blood, you should so know me. The courtesy of nations allows you my better, in that you are the first-born; but the same tradition takes not away my blood, were there twenty brothers betwixt us: I have as much of my father in me as you; albeit, I confess, your coming before me is nearer to his reverence. OLIVER What, boy! ORLANDO Come, come, elder brother, you are too young in this. OLIVER Wilt thou lay hands on me, villain? ORLANDO I am no villain; I am the youngest son of Sir Rowland de Boys; he was my father, and he is thrice a villain that says such a father begot villains. Wert thou not my brother, I would not take this hand from thy throat till this other had pulled out thy tongue for saying so: thou hast railed on thyself. ADAM Sweet masters, be patient: for your father's remembrance, be at accord. OLIVER Let me go, I say. ORLANDO I will not, till I please: you shall hear me. My father charged you in his will to give me good education: you have trained me like a peasant, obscuring and hiding from me all gentleman-like qualities. The spirit of my father grows strong in me, and I will no longer endure it: therefore allow me such exercises as may become a gentleman, or give me the poor allottery my father left me by testament; with that I will go buy my fortunes. OLIVER And what wilt thou do? beg, when that is spent? Well, sir, get you in: I will not long be troubled with you; you shall have some part of your will: I pray you, leave me. ORLANDO I will no further offend you than becomes me for my good. OLIVER Get you with him, you old dog. ADAM Is 'old dog' my reward? Most true, I have lost my teeth in your service. God be with my old master! he would not have spoke such a word. [Exeunt ORLANDO and ADAM] OLIVER Is it even so? begin you to grow upon me? I will physic your rankness, and yet give no thousand crowns neither. Holla, Dennis! [Enter DENNIS] DENNIS Calls your worship? OLIVER Was not Charles, the duke's wrestler, here to speak with me? DENNIS So please you, he is here at the door and importunes access to you. OLIVER Call him in. [Exit DENNIS] 'Twill be a good way; and to-morrow the wrestling is. [Enter CHARLES] CHARLES Good morrow to your worship. OLIVER Good Monsieur Charles, what's the new news at the new court? CHARLES There's no news at the court, sir, but the old news: that is, the old duke is banished by his younger brother the new duke; and three or four loving lords have put themselves into voluntary exile with him, whose lands and revenues enrich the new duke; therefore he gives them good leave to wander. OLIVER Can you tell if Rosalind, the duke's daughter, be banished with her father? CHARLES O, no; for the duke's daughter, her cousin, so loves her, being ever from their cradles bred together, that she would have followed her exile, or have died to stay behind her. She is at the court, and no less beloved of her uncle than his own daughter; and never two ladies loved as they do. OLIVER Where will the old duke live? CHARLES They say he is already in the forest of Arden, and a many merry men with him; and there they live like the old Robin Hood of England: they say many young gentlemen flock to him every day, and fleet the time carelessly, as they did in the golden world. OLIVER What, you wrestle to-morrow before the new duke? CHARLES Marry, do I, sir; and I came to acquaint you with a matter. I am given, sir, secretly to understand that your younger brother Orlando hath a disposition to come in disguised against me to try a fall. To-morrow, sir, I wrestle for my credit; and he that escapes me without some broken limb shall acquit him well. Your brother is but young and tender; and, for your love, I would be loath to foil him, as I must, for my own honour, if he come in: therefore, out of my love to you, I came hither to acquaint you withal, that either you might stay him from his intendment or brook such disgrace well as he shall run into, in that it is a thing of his own search and altogether against my will. OLIVER Charles, I thank thee for thy love to me, which thou shalt find I will most kindly requite. I had myself notice of my brother's purpose herein and have by underhand means laboured to dissuade him from it, but he is resolute. I'll tell thee, Charles: it is the stubbornest young fellow of France, full of ambition, an envious emulator of every man's good parts, a secret and villanous contriver against me his natural brother: therefore use thy discretion; I had as lief thou didst break his neck as his finger. And thou wert best look to't; for if thou dost him any slight disgrace or if he do not mightily grace himself on thee, he will practise against thee by poison, entrap thee by some treacherous device and never leave thee till he hath ta'en thy life by some indirect means or other; for, I assure thee, and almost with tears I speak it, there is not one so young and so villanous this day living. I speak but brotherly of him; but should I anatomize him to thee as he is, I must blush and weep and thou must look pale and wonder. CHARLES I am heartily glad I came hither to you. If he come to-morrow, I'll give him his payment: if ever he go alone again, I'll never wrestle for prize more: and so God keep your worship! OLIVER Farewell, good Charles. [Exit CHARLES] Now will I stir this gamester: I hope I shall see an end of him; for my soul, yet I know not why, hates nothing more than he. Yet he's gentle, never schooled and yet learned, full of noble device, of all sorts enchantingly beloved, and indeed so much in the heart of the world, and especially of my own people, who best know him, that I am altogether misprised: but it shall not be so long; this wrestler shall clear all: nothing remains but that I kindle the boy thither; which now I'll go about. [Exit] AS YOU LIKE IT ACT I SCENE II Lawn before the Duke's palace. [Enter CELIA and ROSALIND] CELIA I pray thee, Rosalind, sweet my coz, be merry. ROSALIND Dear Celia, I show more mirth than I am mistress of; and would you yet I were merrier? Unless you could teach me to forget a banished father, you must not learn me how to remember any extraordinary pleasure. CELIA Herein I see thou lovest me not with the full weight that I love thee. If my uncle, thy banished father, had banished thy uncle, the duke my father, so thou hadst been still with me, I could have taught my love to take thy father for mine: so wouldst thou, if the truth of thy love to me were so righteously tempered as mine is to thee. ROSALIND Well, I will forget the condition of my estate, to rejoice in yours. CELIA You know my father hath no child but I, nor none is like to have: and, truly, when he dies, thou shalt be his heir, for what he hath taken away from thy father perforce, I will render thee again in affection; by mine honour, I will; and when I break that oath, let me turn monster: therefore, my sweet Rose, my dear Rose, be merry. ROSALIND From henceforth I will, coz, and devise sports. Let me see; what think you of falling in love? CELIA Marry, I prithee, do, to make sport withal: but love no man in good earnest; nor no further in sport neither than with safety of a pure blush thou mayst in honour come off again. ROSALIND What shall be our sport, then? CELIA Let us sit and mock the good housewife Fortune from her wheel, that her gifts may henceforth be bestowed equally. ROSALIND I would we could do so, for her benefits are mightily misplaced, and the bountiful blind woman doth most mistake in her gifts to women. CELIA 'Tis true; for those that she makes fair she scarce makes honest, and those that she makes honest she makes very ill-favouredly. ROSALIND Nay, now thou goest from Fortune's office to Nature's: Fortune reigns in gifts of the world, not in the lineaments of Nature. [Enter TOUCHSTONE] CELIA No? when Nature hath made a fair creature, may she not by Fortune fall into the fire? Though Nature hath given us wit to flout at Fortune, hath not Fortune sent in this fool to cut off the argument? ROSALIND Indeed, there is Fortune too hard for Nature, when Fortune makes Nature's natural the cutter-off of Nature's wit. CELIA Peradventure this is not Fortune's work neither, but Nature's; who perceiveth our natural wits too dull to reason of such goddesses and hath sent this natural for our whetstone; for always the dulness of the fool is the whetstone of the wits. How now, wit! whither wander you? TOUCHSTONE Mistress, you must come away to your father. CELIA Were you made the messenger? TOUCHSTONE No, by mine honour, but I was bid to come for you. ROSALIND Where learned you that oath, fool? TOUCHSTONE Of a certain knight that swore by his honour they were good pancakes and swore by his honour the mustard was naught: now I'll stand to it, the pancakes were naught and the mustard was good, and yet was not the knight forsworn. CELIA How prove you that, in the great heap of your knowledge? ROSALIND Ay, marry, now unmuzzle your wisdom. TOUCHSTONE Stand you both forth now: stroke your chins, and swear by your beards that I am a knave. CELIA By our beards, if we had them, thou art. TOUCHSTONE By my knavery, if I had it, then I were; but if you swear by that that is not, you are not forsworn: no more was this knight swearing by his honour, for he never had any; or if he had, he had sworn it away before ever he saw those pancakes or that mustard. CELIA Prithee, who is't that thou meanest? TOUCHSTONE One that old Frederick, your father, loves. CELIA My father's love is enough to honour him: enough! speak no more of him; you'll be whipped for taxation one of these days. TOUCHSTONE The more pity, that fools may not speak wisely what wise men do foolishly. CELIA By my troth, thou sayest true; for since the little wit that fools have was silenced, the little foolery that wise men have makes a great show. Here comes Monsieur Le Beau. ROSALIND With his mouth full of news. CELIA Which he will put on us, as pigeons feed their young. ROSALIND Then shall we be news-crammed. CELIA All the better; we shall be the more marketable. [Enter LE BEAU] Bon jour, Monsieur Le Beau: what's the news? LE BEAU Fair princess, you have lost much good sport. CELIA Sport! of what colour? LE BEAU What colour, madam! how shall I answer you? ROSALIND As wit and fortune will. TOUCHSTONE Or as the Destinies decree. CELIA Well said: that was laid on with a trowel. TOUCHSTONE Nay, if I keep not my rank,-- ROSALIND Thou losest thy old smell. LE BEAU You amaze me, ladies: I would have told you of good wrestling, which you have lost the sight of. ROSALIND You tell us the manner of the wrestling. LE BEAU I will tell you the beginning; and, if it please your ladyships, you may see the end; for the best is yet to do; and here, where you are, they are coming to perform it. CELIA Well, the beginning, that is dead and buried. LE BEAU There comes an old man and his three sons,-- CELIA I could match this beginning with an old tale. LE BEAU Three proper young men, of excellent growth and presence. ROSALIND With bills on their necks, 'Be it known unto all men by these presents.' LE BEAU The eldest of the three wrestled with Charles, the duke's wrestler; which Charles in a moment threw him and broke three of his ribs, that there is little hope of life in him: so he served the second, and so the third. Yonder they lie; the poor old man, their father, making such pitiful dole over them that all the beholders take his part with weeping. ROSALIND Alas! TOUCHSTONE But what is the sport, monsieur, that the ladies have lost? LE BEAU Why, this that I speak of. TOUCHSTONE Thus men may grow wiser every day: it is the first time that ever I heard breaking of ribs was sport for ladies. CELIA Or I, I promise thee. ROSALIND But is there any else longs to see this broken music in his sides? is there yet another dotes upon rib-breaking? Shall we see this wrestling, cousin? LE BEAU You must, if you stay here; for here is the place appointed for the wrestling, and they are ready to perform it. CELIA Yonder, sure, they are coming: let us now stay and see it. [Flourish. Enter DUKE FREDERICK, Lords, ORLANDO, CHARLES, and Attendants] DUKE FREDERICK Come on: since the youth will not be entreated, his own peril on his forwardness. ROSALIND Is yonder the man? LE BEAU Even he, madam. CELIA Alas, he is too young! yet he looks successfully. DUKE FREDERICK How now, daughter and cousin! are you crept hither to see the wrestling? ROSALIND Ay, my liege, so please you give us leave. DUKE FREDERICK You will take little delight in it, I can tell you; there is such odds in the man. In pity of the challenger's youth I would fain dissuade him, but he will not be entreated. Speak to him, ladies; see if you can move him. CELIA Call him hither, good Monsieur Le Beau. DUKE FREDERICK Do so: I'll not be by. LE BEAU Monsieur the challenger, the princesses call for you. ORLANDO I attend them with all respect and duty. ROSALIND Young man, have you challenged Charles the wrestler? ORLANDO No, fair princess; he is the general challenger: I come but in, as others do, to try with him the strength of my youth. CELIA Young gentleman, your spirits are too bold for your years. You have seen cruel proof of this man's strength: if you saw yourself with your eyes or knew yourself with your judgment, the fear of your adventure would counsel you to a more equal enterprise. We pray you, for your own sake, to embrace your own safety and give over this attempt. ROSALIND Do, young sir; your reputation shall not therefore be misprised: we will make it our suit to the duke that the wrestling might not go forward. ORLANDO I beseech you, punish me not with your hard thoughts; wherein I confess me much guilty, to deny so fair and excellent ladies any thing. But let your fair eyes and gentle wishes go with me to my trial: wherein if I be foiled, there is but one shamed that was never gracious; if killed, but one dead that was willing to be so: I shall do my friends no wrong, for I have none to lament me, the world no injury, for in it I have nothing; only in the world I fill up a place, which may be better supplied when I have made it empty. ROSALIND The little strength that I have, I would it were with you. CELIA And mine, to eke out hers. ROSALIND Fare you well: pray heaven I be deceived in you! CELIA Your heart's desires be with you! CHARLES Come, where is this young gallant that is so desirous to lie with his mother earth? ORLANDO Ready, sir; but his will hath in it a more modest working. DUKE FREDERICK You shall try but one fall. CHARLES No, I warrant your grace, you shall not entreat him to a second, that have so mightily persuaded him from a first. ORLANDO An you mean to mock me after, you should not have mocked me before: but come your ways. ROSALIND Now Hercules be thy speed, young man! CELIA I would I were invisible, to catch the strong fellow by the leg. [They wrestle] ROSALIND O excellent young man! CELIA If I had a thunderbolt in mine eye, I can tell who should down. [Shout. CHARLES is thrown] DUKE FREDERICK No more, no more. ORLANDO Yes, I beseech your grace: I am not yet well breathed. DUKE FREDERICK How dost thou, Charles? LE BEAU He cannot speak, my lord. DUKE FREDERICK Bear him away. What is thy name, young man? ORLANDO Orlando, my liege; the youngest son of Sir Rowland de Boys. DUKE FREDERICK I would thou hadst been son to some man else: The world esteem'd thy father honourable, But I did find him still mine enemy: Thou shouldst have better pleased me with this deed, Hadst thou descended from another house. But fare thee well; thou art a gallant youth: I would thou hadst told me of another father. [Exeunt DUKE FREDERICK, train, and LE BEAU] CELIA Were I my father, coz, would I do this? ORLANDO I am more proud to be Sir Rowland's son, His youngest son; and would not change that calling, To be adopted heir to Frederick. ROSALIND My father loved Sir Rowland as his soul, And all the world was of my father's mind: Had I before known this young man his son, I should have given him tears unto entreaties, Ere he should thus have ventured. CELIA Gentle cousin, Let us go thank him and encourage him: My father's rough and envious disposition Sticks me at heart. Sir, you have well deserved: If you do keep your promises in love But justly, as you have exceeded all promise, Your mistress shall be happy. ROSALIND Gentleman, [Giving him a chain from her neck] Wear this for me, one out of suits with fortune, That could give more, but that her hand lacks means. Shall we go, coz? CELIA Ay. Fare you well, fair gentleman. ORLANDO Can I not say, I thank you? My better parts Are all thrown down, and that which here stands up Is but a quintain, a mere lifeless block. ROSALIND He calls us back: my pride fell with my fortunes; I'll ask him what he would. Did you call, sir? Sir, you have wrestled well and overthrown More than your enemies. CELIA Will you go, coz? ROSALIND Have with you. Fare you well. [Exeunt ROSALIND and CELIA] ORLANDO What passion hangs these weights upon my tongue? I cannot speak to her, yet she urged conference. O poor Orlando, thou art overthrown! Or Charles or something weaker masters thee. [Re-enter LE BEAU] LE BEAU Good sir, I do in friendship counsel you To leave this place. Albeit you have deserved High commendation, true applause and love, Yet such is now the duke's condition That he misconstrues all that you have done. The duke is humorous; what he is indeed, More suits you to conceive than I to speak of. ORLANDO I thank you, sir: and, pray you, tell me this: Which of the two was daughter of the duke That here was at the wrestling? LE BEAU Neither his daughter, if we judge by manners; But yet indeed the lesser is his daughter The other is daughter to the banish'd duke, And here detain'd by her usurping uncle, To keep his daughter company; whose loves Are dearer than the natural bond of sisters. But I can tell you that of late this duke Hath ta'en displeasure 'gainst his gentle niece, Grounded upon no other argument But that the people praise her for her virtues And pity her for her good father's sake; And, on my life, his malice 'gainst the lady Will suddenly break forth. Sir, fare you well: Hereafter, in a better world than this, I shall desire more love and knowledge of you. ORLANDO I rest much bounden to you: fare you well. [Exit LE BEAU] Thus must I from the smoke into the smother; From tyrant duke unto a tyrant brother: But heavenly Rosalind! [Exit] AS YOU LIKE IT ACT I SCENE III A room in the palace. [Enter CELIA and ROSALIND] CELIA Why, cousin! why, Rosalind! Cupid have mercy! not a word? ROSALIND Not one to throw at a dog. CELIA No, thy words are too precious to be cast away upon curs; throw some of them at me; come, lame me with reasons. ROSALIND Then there were two cousins laid up; when the one should be lamed with reasons and the other mad without any. CELIA But is all this for your father? ROSALIND No, some of it is for my child's father. O, how full of briers is this working-day world! CELIA They are but burs, cousin, thrown upon thee in holiday foolery: if we walk not in the trodden paths our very petticoats will catch them. ROSALIND I could shake them off my coat: these burs are in my heart. CELIA Hem them away. ROSALIND I would try, if I could cry 'hem' and have him. CELIA Come, come, wrestle with thy affections. ROSALIND O, they take the part of a better wrestler than myself! CELIA O, a good wish upon you! you will try in time, in despite of a fall. But, turning these jests out of service, let us talk in good earnest: is it possible, on such a sudden, you should fall into so strong a liking with old Sir Rowland's youngest son? ROSALIND The duke my father loved his father dearly. CELIA Doth it therefore ensue that you should love his son dearly? By this kind of chase, I should hate him, for my father hated his father dearly; yet I hate not Orlando. ROSALIND No, faith, hate him not, for my sake. CELIA Why should I not? doth he not deserve well? ROSALIND Let me love him for that, and do you love him because I do. Look, here comes the duke. CELIA With his eyes full of anger. [Enter DUKE FREDERICK, with Lords] DUKE FREDERICK Mistress, dispatch you with your safest haste And get you from our court. ROSALIND Me, uncle? DUKE FREDERICK You, cousin Within these ten days if that thou be'st found So near our public court as twenty miles, Thou diest for it. ROSALIND I do beseech your grace, Let me the knowledge of my fault bear with me: If with myself I hold intelligence Or have acquaintance with mine own desires, If that I do not dream or be not frantic,-- As I do trust I am not--then, dear uncle, Never so much as in a thought unborn Did I offend your highness. DUKE FREDERICK Thus do all traitors: If their purgation did consist in words, They are as innocent as grace itself: Let it suffice thee that I trust thee not. ROSALIND Yet your mistrust cannot make me a traitor: Tell me whereon the likelihood depends. DUKE FREDERICK Thou art thy father's daughter; there's enough. ROSALIND So was I when your highness took his dukedom; So was I when your highness banish'd him: Treason is not inherited, my lord; Or, if we did derive it from our friends, What's that to me? my father was no traitor: Then, good my liege, mistake me not so much To think my poverty is treacherous. CELIA Dear sovereign, hear me speak. DUKE FREDERICK Ay, Celia; we stay'd her for your sake, Else had she with her father ranged along. CELIA I did not then entreat to have her stay; It was your pleasure and your own remorse: I was too young that time to value her; But now I know her: if she be a traitor, Why so am I; we still have slept together, Rose at an instant, learn'd, play'd, eat together, And wheresoever we went, like Juno's swans, Still we went coupled and inseparable. DUKE FREDERICK She is too subtle for thee; and her smoothness, Her very silence and her patience Speak to the people, and they pity her. Thou art a fool: she robs thee of thy name; And thou wilt show more bright and seem more virtuous When she is gone. Then open not thy lips: Firm and irrevocable is my doom Which I have pass'd upon her; she is banish'd. CELIA Pronounce that sentence then on me, my liege: I cannot live out of her company. DUKE FREDERICK You are a fool. You, niece, provide yourself: If you outstay the time, upon mine honour, And in the greatness of my word, you die. [Exeunt DUKE FREDERICK and Lords] CELIA O my poor Rosalind, whither wilt thou go? Wilt thou change fathers? I will give thee mine. I charge thee, be not thou more grieved than I am. ROSALIND I have more cause. CELIA Thou hast not, cousin; Prithee be cheerful: know'st thou not, the duke Hath banish'd me, his daughter? ROSALIND That he hath not. CELIA No, hath not? Rosalind lacks then the love Which teacheth thee that thou and I am one: Shall we be sunder'd? shall we part, sweet girl? No: let my father seek another heir. Therefore devise with me how we may fly, Whither to go and what to bear with us; And do not seek to take your change upon you, To bear your griefs yourself and leave me out; For, by this heaven, now at our sorrows pale, Say what thou canst, I'll go along with thee. ROSALIND Why, whither shall we go? CELIA To seek my uncle in the forest of Arden. ROSALIND Alas, what danger will it be to us, Maids as we are, to travel forth so far! Beauty provoketh thieves sooner than gold. CELIA I'll put myself in poor and mean attire And with a kind of umber smirch my face; The like do you: so shall we pass along And never stir assailants. ROSALIND Were it not better, Because that I am more than common tall, That I did suit me all points like a man? A gallant curtle-axe upon my thigh, A boar-spear in my hand; and--in my heart Lie there what hidden woman's fear there will-- We'll have a swashing and a martial outside, As many other mannish cowards have That do outface it with their semblances. CELIA What shall I call thee when thou art a man? ROSALIND I'll have no worse a name than Jove's own page; And therefore look you call me Ganymede. But what will you be call'd? CELIA Something that hath a reference to my state No longer Celia, but Aliena. ROSALIND But, cousin, what if we assay'd to steal The clownish fool out of your father's court? Would he not be a comfort to our travel? CELIA He'll go along o'er the wide world with me; Leave me alone to woo him. Let's away, And get our jewels and our wealth together, Devise the fittest time and safest way To hide us from pursuit that will be made After my flight. Now go we in content To liberty and not to banishment. [Exeunt] AS YOU LIKE IT ACT II SCENE I The Forest of Arden. [Enter DUKE SENIOR, AMIENS, and two or three Lords, like foresters] DUKE SENIOR Now, my co-mates and brothers in exile, Hath not old custom made this life more sweet Than that of painted pomp? Are not these woods More free from peril than the envious court? Here feel we but the penalty of Adam, The seasons' difference, as the icy fang And churlish chiding of the winter's wind, Which, when it bites and blows upon my body, Even till I shrink with cold, I smile and say 'This is no flattery: these are counsellors That feelingly persuade me what I am.' Sweet are the uses of adversity, Which, like the toad, ugly and venomous, Wears yet a precious jewel in his head; And this our life exempt from public haunt Finds tongues in trees, books in the running brooks, Sermons in stones and good in every thing. I would not change it. AMIENS Happy is your grace, That can translate the stubbornness of fortune Into so quiet and so sweet a style. DUKE SENIOR Come, shall we go and kill us venison? And yet it irks me the poor dappled fools, Being native burghers of this desert city, Should in their own confines with forked heads Have their round haunches gored. First Lord Indeed, my lord, The melancholy Jaques grieves at that, And, in that kind, swears you do more usurp Than doth your brother that hath banish'd you. To-day my Lord of Amiens and myself Did steal behind him as he lay along Under an oak whose antique root peeps out Upon the brook that brawls along this wood: To the which place a poor sequester'd stag, That from the hunter's aim had ta'en a hurt, Did come to languish, and indeed, my lord, The wretched animal heaved forth such groans That their discharge did stretch his leathern coat Almost to bursting, and the big round tears Coursed one another down his innocent nose In piteous chase; and thus the hairy fool Much marked of the melancholy Jaques, Stood on the extremest verge of the swift brook, Augmenting it with tears. DUKE SENIOR But what said Jaques? Did he not moralize this spectacle? First Lord O, yes, into a thousand similes. First, for his weeping into the needless stream; 'Poor deer,' quoth he, 'thou makest a testament As worldlings do, giving thy sum of more To that which had too much:' then, being there alone, Left and abandon'd of his velvet friends, ''Tis right:' quoth he; 'thus misery doth part The flux of company:' anon a careless herd, Full of the pasture, jumps along by him And never stays to greet him; 'Ay' quoth Jaques, 'Sweep on, you fat and greasy citizens; 'Tis just the fashion: wherefore do you look Upon that poor and broken bankrupt there?' Thus most invectively he pierceth through The body of the country, city, court, Yea, and of this our life, swearing that we Are mere usurpers, tyrants and what's worse, To fright the animals and to kill them up In their assign'd and native dwelling-place. DUKE SENIOR And did you leave him in this contemplation? Second Lord We did, my lord, weeping and commenting Upon the sobbing deer. DUKE SENIOR Show me the place: I love to cope him in these sullen fits, For then he's full of matter. First Lord I'll bring you to him straight. [Exeunt] AS YOU LIKE IT ACT II SCENE II A room in the palace. [Enter DUKE FREDERICK, with Lords] DUKE FREDERICK Can it be possible that no man saw them? It cannot be: some villains of my court Are of consent and sufferance in this. First Lord I cannot hear of any that did see her. The ladies, her attendants of her chamber, Saw her abed, and in the morning early They found the bed untreasured of their mistress. Second Lord My lord, the roynish clown, at whom so oft Your grace was wont to laugh, is also missing. Hisperia, the princess' gentlewoman, Confesses that she secretly o'erheard Your daughter and her cousin much commend The parts and graces of the wrestler That did but lately foil the sinewy Charles; And she believes, wherever they are gone, That youth is surely in their company. DUKE FREDERICK Send to his brother; fetch that gallant hither; If he be absent, bring his brother to me; I'll make him find him: do this suddenly, And let not search and inquisition quail To bring again these foolish runaways. [Exeunt] AS YOU LIKE IT ACT II SCENE III Before OLIVER'S house. [Enter ORLANDO and ADAM, meeting] ORLANDO Who's there? ADAM What, my young master? O, my gentle master! O my sweet master! O you memory Of old Sir Rowland! why, what make you here? Why are you virtuous? why do people love you? And wherefore are you gentle, strong and valiant? Why would you be so fond to overcome The bonny priser of the humorous duke? Your praise is come too swiftly home before you. Know you not, master, to some kind of men Their graces serve them but as enemies? No more do yours: your virtues, gentle master, Are sanctified and holy traitors to you. O, what a world is this, when what is comely Envenoms him that bears it! ORLANDO Why, what's the matter? ADAM O unhappy youth! Come not within these doors; within this roof The enemy of all your graces lives: Your brother--no, no brother; yet the son-- Yet not the son, I will not call him son Of him I was about to call his father-- Hath heard your praises, and this night he means To burn the lodging where you use to lie And you within it: if he fail of that, He will have other means to cut you off. I overheard him and his practises. This is no place; this house is but a butchery: Abhor it, fear it, do not enter it. ORLANDO Why, whither, Adam, wouldst thou have me go? ADAM No matter whither, so you come not here. ORLANDO What, wouldst thou have me go and beg my food? Or with a base and boisterous sword enforce A thievish living on the common road? This I must do, or know not what to do: Yet this I will not do, do how I can; I rather will subject me to the malice Of a diverted blood and bloody brother. ADAM But do not so. I have five hundred crowns, The thrifty hire I saved under your father, Which I did store to be my foster-nurse When service should in my old limbs lie lame And unregarded age in corners thrown: Take that, and He that doth the ravens feed, Yea, providently caters for the sparrow, Be comfort to my age! Here is the gold; And all this I give you. Let me be your servant: Though I look old, yet I am strong and lusty; For in my youth I never did apply Hot and rebellious liquors in my blood, Nor did not with unbashful forehead woo The means of weakness and debility; Therefore my age is as a lusty winter, Frosty, but kindly: let me go with you; I'll do the service of a younger man In all your business and necessities. ORLANDO O good old man, how well in thee appears The constant service of the antique world, When service sweat for duty, not for meed! Thou art not for the fashion of these times, Where none will sweat but for promotion, And having that, do choke their service up Even with the having: it is not so with thee. But, poor old man, thou prunest a rotten tree, That cannot so much as a blossom yield In lieu of all thy pains and husbandry But come thy ways; well go along together, And ere we have thy youthful wages spent, We'll light upon some settled low content. ADAM Master, go on, and I will follow thee, To the last gasp, with truth and loyalty. From seventeen years till now almost fourscore Here lived I, but now live here no more. At seventeen years many their fortunes seek; But at fourscore it is too late a week: Yet fortune cannot recompense me better Than to die well and not my master's debtor. [Exeunt] AS YOU LIKE IT ACT II SCENE IV The Forest of Arden. [Enter ROSALIND for Ganymede, CELIA for Aliena, and TOUCHSTONE] ROSALIND O Jupiter, how weary are my spirits! TOUCHSTONE I care not for my spirits, if my legs were not weary. ROSALIND I could find in my heart to disgrace my man's apparel and to cry like a woman; but I must comfort the weaker vessel, as doublet and hose ought to show itself courageous to petticoat: therefore courage, good Aliena! CELIA I pray you, bear with me; I cannot go no further. TOUCHSTONE For my part, I had rather bear with you than bear you; yet I should bear no cross if I did bear you, for I think you have no money in your purse. ROSALIND Well, this is the forest of Arden. TOUCHSTONE Ay, now am I in Arden; the more fool I; when I was at home, I was in a better place: but travellers must be content. ROSALIND Ay, be so, good Touchstone. [Enter CORIN and SILVIUS] Look you, who comes here; a young man and an old in solemn talk. CORIN That is the way to make her scorn you still. SILVIUS O Corin, that thou knew'st how I do love her! CORIN I partly guess; for I have loved ere now. SILVIUS No, Corin, being old, thou canst not guess, Though in thy youth thou wast as true a lover As ever sigh'd upon a midnight pillow: But if thy love were ever like to mine-- As sure I think did never man love so-- How many actions most ridiculous Hast thou been drawn to by thy fantasy? CORIN Into a thousand that I have forgotten. SILVIUS O, thou didst then ne'er love so heartily! If thou remember'st not the slightest folly That ever love did make thee run into, Thou hast not loved: Or if thou hast not sat as I do now, Wearying thy hearer in thy mistress' praise, Thou hast not loved: Or if thou hast not broke from company Abruptly, as my passion now makes me, Thou hast not loved. O Phebe, Phebe, Phebe! [Exit] ROSALIND Alas, poor shepherd! searching of thy wound, I have by hard adventure found mine own. TOUCHSTONE And I mine. I remember, when I was in love I broke my sword upon a stone and bid him take that for coming a-night to Jane Smile; and I remember the kissing of her batlet and the cow's dugs that her pretty chopt hands had milked; and I remember the wooing of a peascod instead of her, from whom I took two cods and, giving her them again, said with weeping tears 'Wear these for my sake.' We that are true lovers run into strange capers; but as all is mortal in nature, so is all nature in love mortal in folly. ROSALIND Thou speakest wiser than thou art ware of. TOUCHSTONE Nay, I shall ne'er be ware of mine own wit till I break my shins against it. ROSALIND Jove, Jove! this shepherd's passion Is much upon my fashion. TOUCHSTONE And mine; but it grows something stale with me. CELIA I pray you, one of you question yond man If he for gold will give us any food: I faint almost to death. TOUCHSTONE Holla, you clown! ROSALIND Peace, fool: he's not thy kinsman. CORIN Who calls? TOUCHSTONE Your betters, sir. CORIN Else are they very wretched. ROSALIND Peace, I say. Good even to you, friend. CORIN And to you, gentle sir, and to you all. ROSALIND I prithee, shepherd, if that love or gold Can in this desert place buy entertainment, Bring us where we may rest ourselves and feed: Here's a young maid with travel much oppress'd And faints for succor. CORIN Fair sir, I pity her And wish, for her sake more than for mine own, My fortunes were more able to relieve her; But I am shepherd to another man And do not shear the fleeces that I graze: My master is of churlish disposition And little recks to find the way to heaven By doing deeds of hospitality: Besides, his cote, his flocks and bounds of feed Are now on sale, and at our sheepcote now, By reason of his absence, there is nothing That you will feed on; but what is, come see. And in my voice most welcome shall you be. ROSALIND What is he that shall buy his flock and pasture? CORIN That young swain that you saw here but erewhile, That little cares for buying any thing. ROSALIND I pray thee, if it stand with honesty, Buy thou the cottage, pasture and the flock, And thou shalt have to pay for it of us. CELIA And we will mend thy wages. I like this place. And willingly could waste my time in it. CORIN Assuredly the thing is to be sold: Go with me: if you like upon report The soil, the profit and this kind of life, I will your very faithful feeder be And buy it with your gold right suddenly. [Exeunt] AS YOU LIKE IT ACT II SCENE V The Forest. [Enter AMIENS, JAQUES, and others] SONG. AMIENS Under the greenwood tree Who loves to lie with me, And turn his merry note Unto the sweet bird's throat, Come hither, come hither, come hither: Here shall he see No enemy But winter and rough weather. JAQUES More, more, I prithee, more. AMIENS It will make you melancholy, Monsieur Jaques. JAQUES I thank it. More, I prithee, more. I can suck melancholy out of a song, as a weasel sucks eggs. More, I prithee, more. AMIENS My voice is ragged: I know I cannot please you. JAQUES I do not desire you to please me; I do desire you to sing. Come, more; another stanzo: call you 'em stanzos? AMIENS What you will, Monsieur Jaques. JAQUES Nay, I care not for their names; they owe me nothing. Will you sing? AMIENS More at your request than to please myself. JAQUES Well then, if ever I thank any man, I'll thank you; but that they call compliment is like the encounter of two dog-apes, and when a man thanks me heartily, methinks I have given him a penny and he renders me the beggarly thanks. Come, sing; and you that will not, hold your tongues. AMIENS Well, I'll end the song. Sirs, cover the while; the duke will drink under this tree. He hath been all this day to look you. JAQUES And I have been all this day to avoid him. He is too disputable for my company: I think of as many matters as he, but I give heaven thanks and make no boast of them. Come, warble, come. SONG. Who doth ambition shun [All together here] And loves to live i' the sun, Seeking the food he eats And pleased with what he gets, Come hither, come hither, come hither: Here shall he see No enemy But winter and rough weather. JAQUES I'll give you a verse to this note that I made yesterday in despite of my invention. AMIENS And I'll sing it. JAQUES Thus it goes:-- If it do come to pass That any man turn ass, Leaving his wealth and ease, A stubborn will to please, Ducdame, ducdame, ducdame: Here shall he see Gross fools as he, An if he will come to me. AMIENS What's that 'ducdame'? JAQUES 'Tis a Greek invocation, to call fools into a circle. I'll go sleep, if I can; if I cannot, I'll rail against all the first-born of Egypt. AMIENS And I'll go seek the duke: his banquet is prepared. [Exeunt severally] AS YOU LIKE IT ACT II SCENE VI The forest. [Enter ORLANDO and ADAM] ADAM Dear master, I can go no further. O, I die for food! Here lie I down, and measure out my grave. Farewell, kind master. ORLANDO Why, how now, Adam! no greater heart in thee? Live a little; comfort a little; cheer thyself a little. If this uncouth forest yield any thing savage, I will either be food for it or bring it for food to thee. Thy conceit is nearer death than thy powers. For my sake be comfortable; hold death awhile at the arm's end: I will here be with thee presently; and if I bring thee not something to eat, I will give thee leave to die: but if thou diest before I come, thou art a mocker of my labour. Well said! thou lookest cheerly, and I'll be with thee quickly. Yet thou liest in the bleak air: come, I will bear thee to some shelter; and thou shalt not die for lack of a dinner, if there live any thing in this desert. Cheerly, good Adam! [Exeunt] AS YOU LIKE IT ACT II SCENE VII The forest. [A table set out. Enter DUKE SENIOR, AMIENS, and Lords like outlaws] DUKE SENIOR I think he be transform'd into a beast; For I can no where find him like a man. First Lord My lord, he is but even now gone hence: Here was he merry, hearing of a song. DUKE SENIOR If he, compact of jars, grow musical, We shall have shortly discord in the spheres. Go, seek him: tell him I would speak with him. [Enter JAQUES] First Lord He saves my labour by his own approach. DUKE SENIOR Why, how now, monsieur! what a life is this, That your poor friends must woo your company? What, you look merrily! JAQUES A fool, a fool! I met a fool i' the forest, A motley fool; a miserable world! As I do live by food, I met a fool Who laid him down and bask'd him in the sun, And rail'd on Lady Fortune in good terms, In good set terms and yet a motley fool. 'Good morrow, fool,' quoth I. 'No, sir,' quoth he, 'Call me not fool till heaven hath sent me fortune:' And then he drew a dial from his poke, And, looking on it with lack-lustre eye, Says very wisely, 'It is ten o'clock: Thus we may see,' quoth he, 'how the world wags: 'Tis but an hour ago since it was nine, And after one hour more 'twill be eleven; And so, from hour to hour, we ripe and ripe, And then, from hour to hour, we rot and rot; And thereby hangs a tale.' When I did hear The motley fool thus moral on the time, My lungs began to crow like chanticleer, That fools should be so deep-contemplative, And I did laugh sans intermission An hour by his dial. O noble fool! A worthy fool! Motley's the only wear. DUKE SENIOR What fool is this? JAQUES O worthy fool! One that hath been a courtier, And says, if ladies be but young and fair, They have the gift to know it: and in his brain, Which is as dry as the remainder biscuit After a voyage, he hath strange places cramm'd With observation, the which he vents In mangled forms. O that I were a fool! I am ambitious for a motley coat. DUKE SENIOR Thou shalt have one. JAQUES It is my only suit; Provided that you weed your better judgments Of all opinion that grows rank in them That I am wise. I must have liberty Withal, as large a charter as the wind, To blow on whom I please; for so fools have; And they that are most galled with my folly, They most must laugh. And why, sir, must they so? The 'why' is plain as way to parish church: He that a fool doth very wisely hit Doth very foolishly, although he smart, Not to seem senseless of the bob: if not, The wise man's folly is anatomized Even by the squandering glances of the fool. Invest me in my motley; give me leave To speak my mind, and I will through and through Cleanse the foul body of the infected world, If they will patiently receive my medicine. DUKE SENIOR Fie on thee! I can tell what thou wouldst do. JAQUES What, for a counter, would I do but good? DUKE SENIOR Most mischievous foul sin, in chiding sin: For thou thyself hast been a libertine, As sensual as the brutish sting itself; And all the embossed sores and headed evils, That thou with licence of free foot hast caught, Wouldst thou disgorge into the general world. JAQUES Why, who cries out on pride, That can therein tax any private party? Doth it not flow as hugely as the sea, Till that the weary very means do ebb? What woman in the city do I name, When that I say the city-woman bears The cost of princes on unworthy shoulders? Who can come in and say that I mean her, When such a one as she such is her neighbour? Or what is he of basest function That says his bravery is not of my cost, Thinking that I mean him, but therein suits His folly to the mettle of my speech? There then; how then? what then? Let me see wherein My tongue hath wrong'd him: if it do him right, Then he hath wrong'd himself; if he be free, Why then my taxing like a wild-goose flies, Unclaim'd of any man. But who comes here? [Enter ORLANDO, with his sword drawn] ORLANDO Forbear, and eat no more. JAQUES Why, I have eat none yet. ORLANDO Nor shalt not, till necessity be served. JAQUES Of what kind should this cock come of? DUKE SENIOR Art thou thus bolden'd, man, by thy distress, Or else a rude despiser of good manners, That in civility thou seem'st so empty? ORLANDO You touch'd my vein at first: the thorny point Of bare distress hath ta'en from me the show Of smooth civility: yet am I inland bred And know some nurture. But forbear, I say: He dies that touches any of this fruit Till I and my affairs are answered. JAQUES An you will not be answered with reason, I must die. DUKE SENIOR What would you have? Your gentleness shall force More than your force move us to gentleness. ORLANDO I almost die for food; and let me have it. DUKE SENIOR Sit down and feed, and welcome to our table. ORLANDO Speak you so gently? Pardon me, I pray you: I thought that all things had been savage here; And therefore put I on the countenance Of stern commandment. But whate'er you are That in this desert inaccessible, Under the shade of melancholy boughs, Lose and neglect the creeping hours of time If ever you have look'd on better days, If ever been where bells have knoll'd to church, If ever sat at any good man's feast, If ever from your eyelids wiped a tear And know what 'tis to pity and be pitied, Let gentleness my strong enforcement be: In the which hope I blush, and hide my sword. DUKE SENIOR True is it that we have seen better days, And have with holy bell been knoll'd to church And sat at good men's feasts and wiped our eyes Of drops that sacred pity hath engender'd: And therefore sit you down in gentleness And take upon command what help we have That to your wanting may be minister'd. ORLANDO Then but forbear your food a little while, Whiles, like a doe, I go to find my fawn And give it food. There is an old poor man, Who after me hath many a weary step Limp'd in pure love: till he be first sufficed, Oppress'd with two weak evils, age and hunger, I will not touch a bit. DUKE SENIOR Go find him out, And we will nothing waste till you return. ORLANDO I thank ye; and be blest for your good comfort! [Exit] DUKE SENIOR Thou seest we are not all alone unhappy: This wide and universal theatre Presents more woeful pageants than the scene Wherein we play in. JAQUES All the world's a stage, And all the men and women merely players: They have their exits and their entrances; And one man in his time plays many parts, His acts being seven ages. At first the infant, Mewling and puking in the nurse's arms. And then the whining school-boy, with his satchel And shining morning face, creeping like snail Unwillingly to school. And then the lover, Sighing like furnace, with a woeful ballad Made to his mistress' eyebrow. Then a soldier, Full of strange oaths and bearded like the pard, Jealous in honour, sudden and quick in quarrel, Seeking the bubble reputation Even in the cannon's mouth. And then the justice, In fair round belly with good capon lined, With eyes severe and beard of formal cut, Full of wise saws and modern instances; And so he plays his part. The sixth age shifts Into the lean and slipper'd pantaloon, With spectacles on nose and pouch on side, His youthful hose, well saved, a world too wide For his shrunk shank; and his big manly voice, Turning again toward childish treble, pipes And whistles in his sound. Last scene of all, That ends this strange eventful history, Is second childishness and mere oblivion, Sans teeth, sans eyes, sans taste, sans everything. [Re-enter ORLANDO, with ADAM] DUKE SENIOR Welcome. Set down your venerable burthen, And let him feed. ORLANDO I thank you most for him. ADAM So had you need: I scarce can speak to thank you for myself. DUKE SENIOR Welcome; fall to: I will not trouble you As yet, to question you about your fortunes. Give us some music; and, good cousin, sing. SONG. AMIENS Blow, blow, thou winter wind. Thou art not so unkind As man's ingratitude; Thy tooth is not so keen, Because thou art not seen, Although thy breath be rude. Heigh-ho! sing, heigh-ho! unto the green holly: Most friendship is feigning, most loving mere folly: Then, heigh-ho, the holly! This life is most jolly. Freeze, freeze, thou bitter sky, That dost not bite so nigh As benefits forgot: Though thou the waters warp, Thy sting is not so sharp As friend remember'd not. Heigh-ho! sing, &c. DUKE SENIOR If that you were the good Sir Rowland's son, As you have whisper'd faithfully you were, And as mine eye doth his effigies witness Most truly limn'd and living in your face, Be truly welcome hither: I am the duke That loved your father: the residue of your fortune, Go to my cave and tell me. Good old man, Thou art right welcome as thy master is. Support him by the arm. Give me your hand, And let me all your fortunes understand. [Exeunt] AS YOU LIKE IT ACT III SCENE I A room in the palace. [Enter DUKE FREDERICK, Lords, and OLIVER] DUKE FREDERICK Not see him since? Sir, sir, that cannot be: But were I not the better part made mercy, I should not seek an absent argument Of my revenge, thou present. But look to it: Find out thy brother, wheresoe'er he is; Seek him with candle; bring him dead or living Within this twelvemonth, or turn thou no more To seek a living in our territory. Thy lands and all things that thou dost call thine Worth seizure do we seize into our hands, Till thou canst quit thee by thy brothers mouth Of what we think against thee. OLIVER O that your highness knew my heart in this! I never loved my brother in my life. DUKE FREDERICK More villain thou. Well, push him out of doors; And let my officers of such a nature Make an extent upon his house and lands: Do this expediently and turn him going. [Exeunt] AS YOU LIKE IT ACT III SCENE II The forest. [Enter ORLANDO, with a paper] ORLANDO Hang there, my verse, in witness of my love: And thou, thrice-crowned queen of night, survey With thy chaste eye, from thy pale sphere above, Thy huntress' name that my full life doth sway. O Rosalind! these trees shall be my books And in their barks my thoughts I'll character; That every eye which in this forest looks Shall see thy virtue witness'd every where. Run, run, Orlando; carve on every tree The fair, the chaste and unexpressive she. [Exit] [Enter CORIN and TOUCHSTONE] CORIN And how like you this shepherd's life, Master Touchstone? TOUCHSTONE Truly, shepherd, in respect of itself, it is a good life, but in respect that it is a shepherd's life, it is naught. In respect that it is solitary, I like it very well; but in respect that it is private, it is a very vile life. Now, in respect it is in the fields, it pleaseth me well; but in respect it is not in the court, it is tedious. As is it a spare life, look you, it fits my humour well; but as there is no more plenty in it, it goes much against my stomach. Hast any philosophy in thee, shepherd? CORIN No more but that I know the more one sickens the worse at ease he is; and that he that wants money, means and content is without three good friends; that the property of rain is to wet and fire to burn; that good pasture makes fat sheep, and that a great cause of the night is lack of the sun; that he that hath learned no wit by nature nor art may complain of good breeding or comes of a very dull kindred. TOUCHSTONE Such a one is a natural philosopher. Wast ever in court, shepherd? CORIN No, truly. TOUCHSTONE Then thou art damned. CORIN Nay, I hope. TOUCHSTONE Truly, thou art damned like an ill-roasted egg, all on one side. CORIN For not being at court? Your reason. TOUCHSTONE Why, if thou never wast at court, thou never sawest good manners; if thou never sawest good manners, then thy manners must be wicked; and wickedness is sin, and sin is damnation. Thou art in a parlous state, shepherd. CORIN Not a whit, Touchstone: those that are good manners at the court are as ridiculous in the country as the behavior of the country is most mockable at the court. You told me you salute not at the court, but you kiss your hands: that courtesy would be uncleanly, if courtiers were shepherds. TOUCHSTONE Instance, briefly; come, instance. CORIN Why, we are still handling our ewes, and their fells, you know, are greasy. TOUCHSTONE Why, do not your courtier's hands sweat? and is not the grease of a mutton as wholesome as the sweat of a man? Shallow, shallow. A better instance, I say; come. CORIN Besides, our hands are hard. TOUCHSTONE Your lips will feel them the sooner. Shallow again. A more sounder instance, come. CORIN And they are often tarred over with the surgery of our sheep: and would you have us kiss tar? The courtier's hands are perfumed with civet. TOUCHSTONE Most shallow man! thou worms-meat, in respect of a good piece of flesh indeed! Learn of the wise, and perpend: civet is of a baser birth than tar, the very uncleanly flux of a cat. Mend the instance, shepherd. CORIN You have too courtly a wit for me: I'll rest. TOUCHSTONE Wilt thou rest damned? God help thee, shallow man! God make incision in thee! thou art raw. CORIN Sir, I am a true labourer: I earn that I eat, get that I wear, owe no man hate, envy no man's happiness, glad of other men's good, content with my harm, and the greatest of my pride is to see my ewes graze and my lambs suck. TOUCHSTONE That is another simple sin in you, to bring the ewes and the rams together and to offer to get your living by the copulation of cattle; to be bawd to a bell-wether, and to betray a she-lamb of a twelvemonth to a crooked-pated, old, cuckoldly ram, out of all reasonable match. If thou beest not damned for this, the devil himself will have no shepherds; I cannot see else how thou shouldst 'scape. CORIN Here comes young Master Ganymede, my new mistress's brother. [Enter ROSALIND, with a paper, reading] ROSALIND From the east to western Ind, No jewel is like Rosalind. Her worth, being mounted on the wind, Through all the world bears Rosalind. All the pictures fairest lined Are but black to Rosalind. Let no fair be kept in mind But the fair of Rosalind. TOUCHSTONE I'll rhyme you so eight years together, dinners and suppers and sleeping-hours excepted: it is the right butter-women's rank to market. ROSALIND Out, fool! TOUCHSTONE For a taste: If a hart do lack a hind, Let him seek out Rosalind. If the cat will after kind, So be sure will Rosalind. Winter garments must be lined, So must slender Rosalind. They that reap must sheaf and bind; Then to cart with Rosalind. Sweetest nut hath sourest rind, Such a nut is Rosalind. He that sweetest rose will find Must find love's prick and Rosalind. This is the very false gallop of verses: why do you infect yourself with them? ROSALIND Peace, you dull fool! I found them on a tree. TOUCHSTONE Truly, the tree yields bad fruit. ROSALIND I'll graff it with you, and then I shall graff it with a medlar: then it will be the earliest fruit i' the country; for you'll be rotten ere you be half ripe, and that's the right virtue of the medlar. TOUCHSTONE You have said; but whether wisely or no, let the forest judge. [Enter CELIA, with a writing] ROSALIND Peace! Here comes my sister, reading: stand aside. CELIA [Reads] Why should this a desert be? For it is unpeopled? No: Tongues I'll hang on every tree, That shall civil sayings show: Some, how brief the life of man Runs his erring pilgrimage, That the stretching of a span Buckles in his sum of age; Some, of violated vows 'Twixt the souls of friend and friend: But upon the fairest boughs, Or at every sentence end, Will I Rosalinda write, Teaching all that read to know The quintessence of every sprite Heaven would in little show. Therefore Heaven Nature charged That one body should be fill'd With all graces wide-enlarged: Nature presently distill'd Helen's cheek, but not her heart, Cleopatra's majesty, Atalanta's better part, Sad Lucretia's modesty. Thus Rosalind of many parts By heavenly synod was devised, Of many faces, eyes and hearts, To have the touches dearest prized. Heaven would that she these gifts should have, And I to live and die her slave. ROSALIND O most gentle pulpiter! what tedious homily of love have you wearied your parishioners withal, and never cried 'Have patience, good people!' CELIA How now! back, friends! Shepherd, go off a little. Go with him, sirrah. TOUCHSTONE Come, shepherd, let us make an honourable retreat; though not with bag and baggage, yet with scrip and scrippage. [Exeunt CORIN and TOUCHSTONE] CELIA Didst thou hear these verses? ROSALIND O, yes, I heard them all, and more too; for some of them had in them more feet than the verses would bear. CELIA That's no matter: the feet might bear the verses. ROSALIND Ay, but the feet were lame and could not bear themselves without the verse and therefore stood lamely in the verse. CELIA But didst thou hear without wondering how thy name should be hanged and carved upon these trees? ROSALIND I was seven of the nine days out of the wonder before you came; for look here what I found on a palm-tree. I was never so be-rhymed since Pythagoras' time, that I was an Irish rat, which I can hardly remember. CELIA Trow you who hath done this? ROSALIND Is it a man? CELIA And a chain, that you once wore, about his neck. Change you colour? ROSALIND I prithee, who? CELIA O Lord, Lord! it is a hard matter for friends to meet; but mountains may be removed with earthquakes and so encounter. ROSALIND Nay, but who is it? CELIA Is it possible? ROSALIND Nay, I prithee now with most petitionary vehemence, tell me who it is. CELIA O wonderful, wonderful, and most wonderful wonderful! and yet again wonderful, and after that, out of all hooping! ROSALIND Good my complexion! dost thou think, though I am caparisoned like a man, I have a doublet and hose in my disposition? One inch of delay more is a South-sea of discovery; I prithee, tell me who is it quickly, and speak apace. I would thou couldst stammer, that thou mightst pour this concealed man out of thy mouth, as wine comes out of a narrow- mouthed bottle, either too much at once, or none at all. I prithee, take the cork out of thy mouth that may drink thy tidings. CELIA So you may put a man in your belly. ROSALIND Is he of God's making? What manner of man? Is his head worth a hat, or his chin worth a beard? CELIA Nay, he hath but a little beard. ROSALIND Why, God will send more, if the man will be thankful: let me stay the growth of his beard, if thou delay me not the knowledge of his chin. CELIA It is young Orlando, that tripped up the wrestler's heels and your heart both in an instant. ROSALIND Nay, but the devil take mocking: speak, sad brow and true maid. CELIA I' faith, coz, 'tis he. ROSALIND Orlando? CELIA Orlando. ROSALIND Alas the day! what shall I do with my doublet and hose? What did he when thou sawest him? What said he? How looked he? Wherein went he? What makes him here? Did he ask for me? Where remains he? How parted he with thee? and when shalt thou see him again? Answer me in one word. CELIA You must borrow me Gargantua's mouth first: 'tis a word too great for any mouth of this age's size. To say ay and no to these particulars is more than to answer in a catechism. ROSALIND But doth he know that I am in this forest and in man's apparel? Looks he as freshly as he did the day he wrestled? CELIA It is as easy to count atomies as to resolve the propositions of a lover; but take a taste of my finding him, and relish it with good observance. I found him under a tree, like a dropped acorn. ROSALIND It may well be called Jove's tree, when it drops forth such fruit. CELIA Give me audience, good madam. ROSALIND Proceed. CELIA There lay he, stretched along, like a wounded knight. ROSALIND Though it be pity to see such a sight, it well becomes the ground. CELIA Cry 'holla' to thy tongue, I prithee; it curvets unseasonably. He was furnished like a hunter. ROSALIND O, ominous! he comes to kill my heart. CELIA I would sing my song without a burden: thou bringest me out of tune. ROSALIND Do you not know I am a woman? when I think, I must speak. Sweet, say on. CELIA You bring me out. Soft! comes he not here? [Enter ORLANDO and JAQUES] ROSALIND 'Tis he: slink by, and note him. JAQUES I thank you for your company; but, good faith, I had as lief have been myself alone. ORLANDO And so had I; but yet, for fashion sake, I thank you too for your society. JAQUES God be wi' you: let's meet as little as we can. ORLANDO I do desire we may be better strangers. JAQUES I pray you, mar no more trees with writing love-songs in their barks. ORLANDO I pray you, mar no more of my verses with reading them ill-favouredly. JAQUES Rosalind is your love's name? ORLANDO Yes, just. JAQUES I do not like her name. ORLANDO There was no thought of pleasing you when she was christened. JAQUES What stature is she of? ORLANDO Just as high as my heart. JAQUES You are full of pretty answers. Have you not been acquainted with goldsmiths' wives, and conned them out of rings? ORLANDO Not so; but I answer you right painted cloth, from whence you have studied your questions. JAQUES You have a nimble wit: I think 'twas made of Atalanta's heels. Will you sit down with me? and we two will rail against our mistress the world and all our misery. ORLANDO I will chide no breather in the world but myself, against whom I know most faults. JAQUES The worst fault you have is to be in love. ORLANDO 'Tis a fault I will not change for your best virtue. I am weary of you. JAQUES By my troth, I was seeking for a fool when I found you. ORLANDO He is drowned in the brook: look but in, and you shall see him. JAQUES There I shall see mine own figure. ORLANDO Which I take to be either a fool or a cipher. JAQUES I'll tarry no longer with you: farewell, good Signior Love. ORLANDO I am glad of your departure: adieu, good Monsieur Melancholy. [Exit JAQUES] ROSALIND [Aside to CELIA] I will speak to him, like a saucy lackey and under that habit play the knave with him. Do you hear, forester? ORLANDO Very well: what would you? ROSALIND I pray you, what is't o'clock? ORLANDO You should ask me what time o' day: there's no clock in the forest. ROSALIND Then there is no true lover in the forest; else sighing every minute and groaning every hour would detect the lazy foot of Time as well as a clock. ORLANDO And why not the swift foot of Time? had not that been as proper? ROSALIND By no means, sir: Time travels in divers paces with divers persons. I'll tell you who Time ambles withal, who Time trots withal, who Time gallops withal and who he stands still withal. ORLANDO I prithee, who doth he trot withal? ROSALIND Marry, he trots hard with a young maid between the contract of her marriage and the day it is solemnized: if the interim be but a se'nnight, Time's pace is so hard that it seems the length of seven year. ORLANDO Who ambles Time withal? ROSALIND With a priest that lacks Latin and a rich man that hath not the gout, for the one sleeps easily because he cannot study, and the other lives merrily because he feels no pain, the one lacking the burden of lean and wasteful learning, the other knowing no burden of heavy tedious penury; these Time ambles withal. ORLANDO Who doth he gallop withal? ROSALIND With a thief to the gallows, for though he go as softly as foot can fall, he thinks himself too soon there. ORLANDO Who stays it still withal? ROSALIND With lawyers in the vacation, for they sleep between term and term and then they perceive not how Time moves. ORLANDO Where dwell you, pretty youth? ROSALIND With this shepherdess, my sister; here in the skirts of the forest, like fringe upon a petticoat. ORLANDO Are you native of this place? ROSALIND As the cony that you see dwell where she is kindled. ORLANDO Your accent is something finer than you could purchase in so removed a dwelling. ROSALIND I have been told so of many: but indeed an old religious uncle of mine taught me to speak, who was in his youth an inland man; one that knew courtship too well, for there he fell in love. I have heard him read many lectures against it, and I thank God I am not a woman, to be touched with so many giddy offences as he hath generally taxed their whole sex withal. ORLANDO Can you remember any of the principal evils that he laid to the charge of women? ROSALIND There were none principal; they were all like one another as half-pence are, every one fault seeming monstrous till his fellow fault came to match it. ORLANDO I prithee, recount some of them. ROSALIND No, I will not cast away my physic but on those that are sick. There is a man haunts the forest, that abuses our young plants with carving 'Rosalind' on their barks; hangs odes upon hawthorns and elegies on brambles, all, forsooth, deifying the name of Rosalind: if I could meet that fancy-monger I would give him some good counsel, for he seems to have the quotidian of love upon him. ORLANDO I am he that is so love-shaked: I pray you tell me your remedy. ROSALIND There is none of my uncle's marks upon you: he taught me how to know a man in love; in which cage of rushes I am sure you are not prisoner. ORLANDO What were his marks? ROSALIND A lean cheek, which you have not, a blue eye and sunken, which you have not, an unquestionable spirit, which you have not, a beard neglected, which you have not; but I pardon you for that, for simply your having in beard is a younger brother's revenue: then your hose should be ungartered, your bonnet unbanded, your sleeve unbuttoned, your shoe untied and every thing about you demonstrating a careless desolation; but you are no such man; you are rather point-device in your accoutrements as loving yourself than seeming the lover of any other. ORLANDO Fair youth, I would I could make thee believe I love. ROSALIND Me believe it! you may as soon make her that you love believe it; which, I warrant, she is apter to do than to confess she does: that is one of the points in the which women still give the lie to their consciences. But, in good sooth, are you he that hangs the verses on the trees, wherein Rosalind is so admired? ORLANDO I swear to thee, youth, by the white hand of Rosalind, I am that he, that unfortunate he. ROSALIND But are you so much in love as your rhymes speak? ORLANDO Neither rhyme nor reason can express how much. ROSALIND Love is merely a madness, and, I tell you, deserves as well a dark house and a whip as madmen do: and the reason why they are not so punished and cured is, that the lunacy is so ordinary that the whippers are in love too. Yet I profess curing it by counsel. ORLANDO Did you ever cure any so? ROSALIND Yes, one, and in this manner. He was to imagine me his love, his mistress; and I set him every day to woo me: at which time would I, being but a moonish youth, grieve, be effeminate, changeable, longing and liking, proud, fantastical, apish, shallow, inconstant, full of tears, full of smiles, for every passion something and for no passion truly any thing, as boys and women are for the most part cattle of this colour; would now like him, now loathe him; then entertain him, then forswear him; now weep for him, then spit at him; that I drave my suitor from his mad humour of love to a living humour of madness; which was, to forswear the full stream of the world, and to live in a nook merely monastic. And thus I cured him; and this way will I take upon me to wash your liver as clean as a sound sheep's heart, that there shall not be one spot of love in't. ORLANDO I would not be cured, youth. ROSALIND I would cure you, if you would but call me Rosalind and come every day to my cote and woo me. ORLANDO Now, by the faith of my love, I will: tell me where it is. ROSALIND Go with me to it and I'll show it you and by the way you shall tell me where in the forest you live. Will you go? ORLANDO With all my heart, good youth. ROSALIND Nay you must call me Rosalind. Come, sister, will you go? [Exeunt] AS YOU LIKE IT ACT III SCENE III The forest. [Enter TOUCHSTONE and AUDREY; JAQUES behind] TOUCHSTONE Come apace, good Audrey: I will fetch up your goats, Audrey. And how, Audrey? am I the man yet? doth my simple feature content you? AUDREY Your features! Lord warrant us! what features! TOUCHSTONE I am here with thee and thy goats, as the most capricious poet, honest Ovid, was among the Goths. JAQUES [Aside] O knowledge ill-inhabited, worse than Jove in a thatched house! TOUCHSTONE When a man's verses cannot be understood, nor a man's good wit seconded with the forward child Understanding, it strikes a man more dead than a great reckoning in a little room. Truly, I would the gods had made thee poetical. AUDREY I do not know what 'poetical' is: is it honest in deed and word? is it a true thing? TOUCHSTONE No, truly; for the truest poetry is the most feigning; and lovers are given to poetry, and what they swear in poetry may be said as lovers they do feign. AUDREY Do you wish then that the gods had made me poetical? TOUCHSTONE I do, truly; for thou swearest to me thou art honest: now, if thou wert a poet, I might have some hope thou didst feign. AUDREY Would you not have me honest? TOUCHSTONE No, truly, unless thou wert hard-favoured; for honesty coupled to beauty is to have honey a sauce to sugar. JAQUES [Aside] A material fool! AUDREY Well, I am not fair; and therefore I pray the gods make me honest. TOUCHSTONE Truly, and to cast away honesty upon a foul slut were to put good meat into an unclean dish. AUDREY I am not a slut, though I thank the gods I am foul. TOUCHSTONE Well, praised be the gods for thy foulness! sluttishness may come hereafter. But be it as it may be, I will marry thee, and to that end I have been with Sir Oliver Martext, the vicar of the next village, who hath promised to meet me in this place of the forest and to couple us. JAQUES [Aside] I would fain see this meeting. AUDREY Well, the gods give us joy! TOUCHSTONE Amen. A man may, if he were of a fearful heart, stagger in this attempt; for here we have no temple but the wood, no assembly but horn-beasts. But what though? Courage! As horns are odious, they are necessary. It is said, 'many a man knows no end of his goods:' right; many a man has good horns, and knows no end of them. Well, that is the dowry of his wife; 'tis none of his own getting. Horns? Even so. Poor men alone? No, no; the noblest deer hath them as huge as the rascal. Is the single man therefore blessed? No: as a walled town is more worthier than a village, so is the forehead of a married man more honourable than the bare brow of a bachelor; and by how much defence is better than no skill, by so much is a horn more precious than to want. Here comes Sir Oliver. [Enter SIR OLIVER MARTEXT] Sir Oliver Martext, you are well met: will you dispatch us here under this tree, or shall we go with you to your chapel? SIR OLIVER MARTEXT Is there none here to give the woman? TOUCHSTONE I will not take her on gift of any man. SIR OLIVER MARTEXT Truly, she must be given, or the marriage is not lawful. JAQUES [Advancing] Proceed, proceed I'll give her. TOUCHSTONE Good even, good Master What-ye-call't: how do you, sir? You are very well met: God 'ild you for your last company: I am very glad to see you: even a toy in hand here, sir: nay, pray be covered. JAQUES Will you be married, motley? TOUCHSTONE As the ox hath his bow, sir, the horse his curb and the falcon her bells, so man hath his desires; and as pigeons bill, so wedlock would be nibbling. JAQUES And will you, being a man of your breeding, be married under a bush like a beggar? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel and, like green timber, warp, warp. TOUCHSTONE [Aside] I am not in the mind but I were better to be married of him than of another: for he is not like to marry me well; and not being well married, it will be a good excuse for me hereafter to leave my wife. JAQUES Go thou with me, and let me counsel thee. TOUCHSTONE 'Come, sweet Audrey: We must be married, or we must live in bawdry. Farewell, good Master Oliver: not,-- O sweet Oliver, O brave Oliver, Leave me not behind thee: but,-- Wind away, Begone, I say, I will not to wedding with thee. [Exeunt JAQUES, TOUCHSTONE and AUDREY] SIR OLIVER MARTEXT 'Tis no matter: ne'er a fantastical knave of them all shall flout me out of my calling. [Exit] AS YOU LIKE IT ACT III SCENE IV The forest. [Enter ROSALIND and CELIA] ROSALIND Never talk to me; I will weep. CELIA Do, I prithee; but yet have the grace to consider that tears do not become a man. ROSALIND But have I not cause to weep? CELIA As good cause as one would desire; therefore weep. ROSALIND His very hair is of the dissembling colour. CELIA Something browner than Judas's marry, his kisses are Judas's own children. ROSALIND I' faith, his hair is of a good colour. CELIA An excellent colour: your chestnut was ever the only colour. ROSALIND And his kissing is as full of sanctity as the touch of holy bread. CELIA He hath bought a pair of cast lips of Diana: a nun of winter's sisterhood kisses not more religiously; the very ice of chastity is in them. ROSALIND But why did he swear he would come this morning, and comes not? CELIA Nay, certainly, there is no truth in him. ROSALIND Do you think so? CELIA Yes; I think he is not a pick-purse nor a horse-stealer, but for his verity in love, I do think him as concave as a covered goblet or a worm-eaten nut. ROSALIND Not true in love? CELIA Yes, when he is in; but I think he is not in. ROSALIND You have heard him swear downright he was. CELIA 'Was' is not 'is:' besides, the oath of a lover is no stronger than the word of a tapster; they are both the confirmer of false reckonings. He attends here in the forest on the duke your father. ROSALIND I met the duke yesterday and had much question with him: he asked me of what parentage I was; I told him, of as good as he; so he laughed and let me go. But what talk we of fathers, when there is such a man as Orlando? CELIA O, that's a brave man! he writes brave verses, speaks brave words, swears brave oaths and breaks them bravely, quite traverse, athwart the heart of his lover; as a puisny tilter, that spurs his horse but on one side, breaks his staff like a noble goose: but all's brave that youth mounts and folly guides. Who comes here? [Enter CORIN] CORIN Mistress and master, you have oft inquired After the shepherd that complain'd of love, Who you saw sitting by me on the turf, Praising the proud disdainful shepherdess That was his mistress. CELIA Well, and what of him? CORIN If you will see a pageant truly play'd, Between the pale complexion of true love And the red glow of scorn and proud disdain, Go hence a little and I shall conduct you, If you will mark it. ROSALIND O, come, let us remove: The sight of lovers feedeth those in love. Bring us to this sight, and you shall say I'll prove a busy actor in their play. [Exeunt] AS YOU LIKE IT ACT III SCENE V Another part of the forest. [Enter SILVIUS and PHEBE] SILVIUS Sweet Phebe, do not scorn me; do not, Phebe; Say that you love me not, but say not so In bitterness. The common executioner, Whose heart the accustom'd sight of death makes hard, Falls not the axe upon the humbled neck But first begs pardon: will you sterner be Than he that dies and lives by bloody drops? [Enter ROSALIND, CELIA, and CORIN, behind] PHEBE I would not be thy executioner: I fly thee, for I would not injure thee. Thou tell'st me there is murder in mine eye: 'Tis pretty, sure, and very probable, That eyes, that are the frail'st and softest things, Who shut their coward gates on atomies, Should be call'd tyrants, butchers, murderers! Now I do frown on thee with all my heart; And if mine eyes can wound, now let them kill thee: Now counterfeit to swoon; why now fall down; Or if thou canst not, O, for shame, for shame, Lie not, to say mine eyes are murderers! Now show the wound mine eye hath made in thee: Scratch thee but with a pin, and there remains Some scar of it; lean but upon a rush, The cicatrice and capable impressure Thy palm some moment keeps; but now mine eyes, Which I have darted at thee, hurt thee not, Nor, I am sure, there is no force in eyes That can do hurt. SILVIUS O dear Phebe, If ever,--as that ever may be near,-- You meet in some fresh cheek the power of fancy, Then shall you know the wounds invisible That love's keen arrows make. PHEBE But till that time Come not thou near me: and when that time comes, Afflict me with thy mocks, pity me not; As till that time I shall not pity thee. ROSALIND And why, I pray you? Who might be your mother, That you insult, exult, and all at once, Over the wretched? What though you have no beauty,-- As, by my faith, I see no more in you Than without candle may go dark to bed-- Must you be therefore proud and pitiless? Why, what means this? Why do you look on me? I see no more in you than in the ordinary Of nature's sale-work. 'Od's my little life, I think she means to tangle my eyes too! No, faith, proud mistress, hope not after it: 'Tis not your inky brows, your black silk hair, Your bugle eyeballs, nor your cheek of cream, That can entame my spirits to your worship. You foolish shepherd, wherefore do you follow her, Like foggy south puffing with wind and rain? You are a thousand times a properer man Than she a woman: 'tis such fools as you That makes the world full of ill-favour'd children: 'Tis not her glass, but you, that flatters her; And out of you she sees herself more proper Than any of her lineaments can show her. But, mistress, know yourself: down on your knees, And thank heaven, fasting, for a good man's love: For I must tell you friendly in your ear, Sell when you can: you are not for all markets: Cry the man mercy; love him; take his offer: Foul is most foul, being foul to be a scoffer. So take her to thee, shepherd: fare you well. PHEBE Sweet youth, I pray you, chide a year together: I had rather hear you chide than this man woo. ROSALIND He's fallen in love with your foulness and she'll fall in love with my anger. If it be so, as fast as she answers thee with frowning looks, I'll sauce her with bitter words. Why look you so upon me? PHEBE For no ill will I bear you. ROSALIND I pray you, do not fall in love with me, For I am falser than vows made in wine: Besides, I like you not. If you will know my house, 'Tis at the tuft of olives here hard by. Will you go, sister? Shepherd, ply her hard. Come, sister. Shepherdess, look on him better, And be not proud: though all the world could see, None could be so abused in sight as he. Come, to our flock. [Exeunt ROSALIND, CELIA and CORIN] PHEBE Dead Shepherd, now I find thy saw of might, 'Who ever loved that loved not at first sight?' SILVIUS Sweet Phebe,-- PHEBE Ha, what say'st thou, Silvius? SILVIUS Sweet Phebe, pity me. PHEBE Why, I am sorry for thee, gentle Silvius. SILVIUS Wherever sorrow is, relief would be: If you do sorrow at my grief in love, By giving love your sorrow and my grief Were both extermined. PHEBE Thou hast my love: is not that neighbourly? SILVIUS I would have you. PHEBE Why, that were covetousness. Silvius, the time was that I hated thee, And yet it is not that I bear thee love; But since that thou canst talk of love so well, Thy company, which erst was irksome to me, I will endure, and I'll employ thee too: But do not look for further recompense Than thine own gladness that thou art employ'd. SILVIUS So holy and so perfect is my love, And I in such a poverty of grace, That I shall think it a most plenteous crop To glean the broken ears after the man That the main harvest reaps: loose now and then A scatter'd smile, and that I'll live upon. PHEBE Know'st now the youth that spoke to me erewhile? SILVIUS Not very well, but I have met him oft; And he hath bought the cottage and the bounds That the old carlot once was master of. PHEBE Think not I love him, though I ask for him: 'Tis but a peevish boy; yet he talks well; But what care I for words? yet words do well When he that speaks them pleases those that hear. It is a pretty youth: not very pretty: But, sure, he's proud, and yet his pride becomes him: He'll make a proper man: the best thing in him Is his complexion; and faster than his tongue Did make offence his eye did heal it up. He is not very tall; yet for his years he's tall: His leg is but so so; and yet 'tis well: There was a pretty redness in his lip, A little riper and more lusty red Than that mix'd in his cheek; 'twas just the difference Between the constant red and mingled damask. There be some women, Silvius, had they mark'd him In parcels as I did, would have gone near To fall in love with him; but, for my part, I love him not nor hate him not; and yet I have more cause to hate him than to love him: For what had he to do to chide at me? He said mine eyes were black and my hair black: And, now I am remember'd, scorn'd at me: I marvel why I answer'd not again: But that's all one; omittance is no quittance. I'll write to him a very taunting letter, And thou shalt bear it: wilt thou, Silvius? SILVIUS Phebe, with all my heart. PHEBE I'll write it straight; The matter's in my head and in my heart: I will be bitter with him and passing short. Go with me, Silvius. [Exeunt] AS YOU LIKE IT ACT IV SCENE I The forest. [Enter ROSALIND, CELIA, and JAQUES] JAQUES I prithee, pretty youth, let me be better acquainted with thee. ROSALIND They say you are a melancholy fellow. JAQUES I am so; I do love it better than laughing. ROSALIND Those that are in extremity of either are abominable fellows and betray themselves to every modern censure worse than drunkards. JAQUES Why, 'tis good to be sad and say nothing. ROSALIND Why then, 'tis good to be a post. JAQUES I have neither the scholar's melancholy, which is emulation, nor the musician's, which is fantastical, nor the courtier's, which is proud, nor the soldier's, which is ambitious, nor the lawyer's, which is politic, nor the lady's, which is nice, nor the lover's, which is all these: but it is a melancholy of mine own, compounded of many simples, extracted from many objects, and indeed the sundry's contemplation of my travels, in which my often rumination wraps me m a most humorous sadness. ROSALIND A traveller! By my faith, you have great reason to be sad: I fear you have sold your own lands to see other men's; then, to have seen much and to have nothing, is to have rich eyes and poor hands. JAQUES Yes, I have gained my experience. ROSALIND And your experience makes you sad: I had rather have a fool to make me merry than experience to make me sad; and to travel for it too! [Enter ORLANDO] ORLANDO Good day and happiness, dear Rosalind! JAQUES Nay, then, God be wi' you, an you talk in blank verse. [Exit] ROSALIND Farewell, Monsieur Traveller: look you lisp and wear strange suits, disable all the benefits of your own country, be out of love with your nativity and almost chide God for making you that countenance you are, or I will scarce think you have swam in a gondola. Why, how now, Orlando! where have you been all this while? You a lover! An you serve me such another trick, never come in my sight more. ORLANDO My fair Rosalind, I come within an hour of my promise. ROSALIND Break an hour's promise in love! He that will divide a minute into a thousand parts and break but a part of the thousandth part of a minute in the affairs of love, it may be said of him that Cupid hath clapped him o' the shoulder, but I'll warrant him heart-whole. ORLANDO Pardon me, dear Rosalind. ROSALIND Nay, an you be so tardy, come no more in my sight: I had as lief be wooed of a snail. ORLANDO Of a snail? ROSALIND Ay, of a snail; for though he comes slowly, he carries his house on his head; a better jointure, I think, than you make a woman: besides he brings his destiny with him. ORLANDO What's that? ROSALIND Why, horns, which such as you are fain to be beholding to your wives for: but he comes armed in his fortune and prevents the slander of his wife. ORLANDO Virtue is no horn-maker; and my Rosalind is virtuous. ROSALIND And I am your Rosalind. CELIA It pleases him to call you so; but he hath a Rosalind of a better leer than you. ROSALIND Come, woo me, woo me, for now I am in a holiday humour and like enough to consent. What would you say to me now, an I were your very very Rosalind? ORLANDO I would kiss before I spoke. ROSALIND Nay, you were better speak first, and when you were gravelled for lack of matter, you might take occasion to kiss. Very good orators, when they are out, they will spit; and for lovers lacking--God warn us!--matter, the cleanliest shift is to kiss. ORLANDO How if the kiss be denied? ROSALIND Then she puts you to entreaty, and there begins new matter. ORLANDO Who could be out, being before his beloved mistress? ROSALIND Marry, that should you, if I were your mistress, or I should think my honesty ranker than my wit. ORLANDO What, of my suit? ROSALIND Not out of your apparel, and yet out of your suit. Am not I your Rosalind? ORLANDO I take some joy to say you are, because I would be talking of her. ROSALIND Well in her person I say I will not have you. ORLANDO Then in mine own person I die. ROSALIND No, faith, die by attorney. The poor world is almost six thousand years old, and in all this time there was not any man died in his own person, videlicit, in a love-cause. Troilus had his brains dashed out with a Grecian club; yet he did what he could to die before, and he is one of the patterns of love. Leander, he would have lived many a fair year, though Hero had turned nun, if it had not been for a hot midsummer night; for, good youth, he went but forth to wash him in the Hellespont and being taken with the cramp was drowned and the foolish coroners of that age found it was 'Hero of Sestos.' But these are all lies: men have died from time to time and worms have eaten them, but not for love. ORLANDO I would not have my right Rosalind of this mind, for, I protest, her frown might kill me. ROSALIND By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition, and ask me what you will. I will grant it. ORLANDO Then love me, Rosalind. ROSALIND Yes, faith, will I, Fridays and Saturdays and all. ORLANDO And wilt thou have me? ROSALIND Ay, and twenty such. ORLANDO What sayest thou? ROSALIND Are you not good? ORLANDO I hope so. ROSALIND Why then, can one desire too much of a good thing? Come, sister, you shall be the priest and marry us. Give me your hand, Orlando. What do you say, sister? ORLANDO Pray thee, marry us. CELIA I cannot say the words. ROSALIND You must begin, 'Will you, Orlando--' CELIA Go to. Will you, Orlando, have to wife this Rosalind? ORLANDO I will. ROSALIND Ay, but when? ORLANDO Why now; as fast as she can marry us. ROSALIND Then you must say 'I take thee, Rosalind, for wife.' ORLANDO I take thee, Rosalind, for wife. ROSALIND I might ask you for your commission; but I do take thee, Orlando, for my husband: there's a girl goes before the priest; and certainly a woman's thought runs before her actions. ORLANDO So do all thoughts; they are winged. ROSALIND Now tell me how long you would have her after you have possessed her. ORLANDO For ever and a day. ROSALIND Say 'a day,' without the 'ever.' No, no, Orlando; men are April when they woo, December when they wed: maids are May when they are maids, but the sky changes when they are wives. I will be more jealous of thee than a Barbary cock-pigeon over his hen, more clamorous than a parrot against rain, more new-fangled than an ape, more giddy in my desires than a monkey: I will weep for nothing, like Diana in the fountain, and I will do that when you are disposed to be merry; I will laugh like a hyen, and that when thou art inclined to sleep. ORLANDO But will my Rosalind do so? ROSALIND By my life, she will do as I do. ORLANDO O, but she is wise. ROSALIND Or else she could not have the wit to do this: the wiser, the waywarder: make the doors upon a woman's wit and it will out at the casement; shut that and 'twill out at the key-hole; stop that, 'twill fly with the smoke out at the chimney. ORLANDO A man that had a wife with such a wit, he might say 'Wit, whither wilt?' ROSALIND Nay, you might keep that cheque for it till you met your wife's wit going to your neighbour's bed. ORLANDO And what wit could wit have to excuse that? ROSALIND Marry, to say she came to seek you there. You shall never take her without her answer, unless you take her without her tongue. O, that woman that cannot make her fault her husband's occasion, let her never nurse her child herself, for she will breed it like a fool! ORLANDO For these two hours, Rosalind, I will leave thee. ROSALIND Alas! dear love, I cannot lack thee two hours. ORLANDO I must attend the duke at dinner: by two o'clock I will be with thee again. ROSALIND Ay, go your ways, go your ways; I knew what you would prove: my friends told me as much, and I thought no less: that flattering tongue of yours won me: 'tis but one cast away, and so, come, death! Two o'clock is your hour? ORLANDO Ay, sweet Rosalind. ROSALIND By my troth, and in good earnest, and so God mend me, and by all pretty oaths that are not dangerous, if you break one jot of your promise or come one minute behind your hour, I will think you the most pathetical break-promise and the most hollow lover and the most unworthy of her you call Rosalind that may be chosen out of the gross band of the unfaithful: therefore beware my censure and keep your promise. ORLANDO With no less religion than if thou wert indeed my Rosalind: so adieu. ROSALIND Well, Time is the old justice that examines all such offenders, and let Time try: adieu. [Exit ORLANDO] CELIA You have simply misused our sex in your love-prate: we must have your doublet and hose plucked over your head, and show the world what the bird hath done to her own nest. ROSALIND O coz, coz, coz, my pretty little coz, that thou didst know how many fathom deep I am in love! But it cannot be sounded: my affection hath an unknown bottom, like the bay of Portugal. CELIA Or rather, bottomless, that as fast as you pour affection in, it runs out. ROSALIND No, that same wicked bastard of Venus that was begot of thought, conceived of spleen and born of madness, that blind rascally boy that abuses every one's eyes because his own are out, let him be judge how deep I am in love. I'll tell thee, Aliena, I cannot be out of the sight of Orlando: I'll go find a shadow and sigh till he come. CELIA And I'll sleep. [Exeunt] AS YOU LIKE IT ACT IV SCENE II The forest. [Enter JAQUES, Lords, and Foresters] JAQUES Which is he that killed the deer? A Lord Sir, it was I. JAQUES Let's present him to the duke, like a Roman conqueror; and it would do well to set the deer's horns upon his head, for a branch of victory. Have you no song, forester, for this purpose? Forester Yes, sir. JAQUES Sing it: 'tis no matter how it be in tune, so it make noise enough. SONG. Forester What shall he have that kill'd the deer? His leather skin and horns to wear. Then sing him home; [The rest shall bear this burden] Take thou no scorn to wear the horn; It was a crest ere thou wast born: Thy father's father wore it, And thy father bore it: The horn, the horn, the lusty horn Is not a thing to laugh to scorn. [Exeunt] AS YOU LIKE IT ACT IV SCENE III The forest. [Enter ROSALIND and CELIA] ROSALIND How say you now? Is it not past two o'clock? and here much Orlando! CELIA I warrant you, with pure love and troubled brain, he hath ta'en his bow and arrows and is gone forth to sleep. Look, who comes here. [Enter SILVIUS] SILVIUS My errand is to you, fair youth; My gentle Phebe bid me give you this: I know not the contents; but, as I guess By the stern brow and waspish action Which she did use as she was writing of it, It bears an angry tenor: pardon me: I am but as a guiltless messenger. ROSALIND Patience herself would startle at this letter And play the swaggerer; bear this, bear all: She says I am not fair, that I lack manners; She calls me proud, and that she could not love me, Were man as rare as phoenix. 'Od's my will! Her love is not the hare that I do hunt: Why writes she so to me? Well, shepherd, well, This is a letter of your own device. SILVIUS No, I protest, I know not the contents: Phebe did write it. ROSALIND Come, come, you are a fool And turn'd into the extremity of love. I saw her hand: she has a leathern hand. A freestone-colour'd hand; I verily did think That her old gloves were on, but 'twas her hands: She has a huswife's hand; but that's no matter: I say she never did invent this letter; This is a man's invention and his hand. SILVIUS Sure, it is hers. ROSALIND Why, 'tis a boisterous and a cruel style. A style for-challengers; why, she defies me, Like Turk to Christian: women's gentle brain Could not drop forth such giant-rude invention Such Ethiope words, blacker in their effect Than in their countenance. Will you hear the letter? SILVIUS So please you, for I never heard it yet; Yet heard too much of Phebe's cruelty. ROSALIND She Phebes me: mark how the tyrant writes. [Reads] Art thou god to shepherd turn'd, That a maiden's heart hath burn'd? Can a woman rail thus? SILVIUS Call you this railing? ROSALIND [Reads] Why, thy godhead laid apart, Warr'st thou with a woman's heart? Did you ever hear such railing? Whiles the eye of man did woo me, That could do no vengeance to me. Meaning me a beast. If the scorn of your bright eyne Have power to raise such love in mine, Alack, in me what strange effect Would they work in mild aspect! Whiles you chid me, I did love; How then might your prayers move! He that brings this love to thee Little knows this love in me: And by him seal up thy mind; Whether that thy youth and kind Will the faithful offer take Of me and all that I can make; Or else by him my love deny, And then I'll study how to die. SILVIUS Call you this chiding? CELIA Alas, poor shepherd! ROSALIND Do you pity him? no, he deserves no pity. Wilt thou love such a woman? What, to make thee an instrument and play false strains upon thee! not to be endured! Well, go your way to her, for I see love hath made thee a tame snake, and say this to her: that if she love me, I charge her to love thee; if she will not, I will never have her unless thou entreat for her. If you be a true lover, hence, and not a word; for here comes more company. [Exit SILVIUS] [Enter OLIVER] OLIVER Good morrow, fair ones: pray you, if you know, Where in the purlieus of this forest stands A sheep-cote fenced about with olive trees? CELIA West of this place, down in the neighbour bottom: The rank of osiers by the murmuring stream Left on your right hand brings you to the place. But at this hour the house doth keep itself; There's none within. OLIVER If that an eye may profit by a tongue, Then should I know you by description; Such garments and such years: 'The boy is fair, Of female favour, and bestows himself Like a ripe sister: the woman low And browner than her brother.' Are not you The owner of the house I did inquire for? CELIA It is no boast, being ask'd, to say we are. OLIVER Orlando doth commend him to you both, And to that youth he calls his Rosalind He sends this bloody napkin. Are you he? ROSALIND I am: what must we understand by this? OLIVER Some of my shame; if you will know of me What man I am, and how, and why, and where This handkercher was stain'd. CELIA I pray you, tell it. OLIVER When last the young Orlando parted from you He left a promise to return again Within an hour, and pacing through the forest, Chewing the food of sweet and bitter fancy, Lo, what befell! he threw his eye aside, And mark what object did present itself: Under an oak, whose boughs were moss'd with age And high top bald with dry antiquity, A wretched ragged man, o'ergrown with hair, Lay sleeping on his back: about his neck A green and gilded snake had wreathed itself, Who with her head nimble in threats approach'd The opening of his mouth; but suddenly, Seeing Orlando, it unlink'd itself, And with indented glides did slip away Into a bush: under which bush's shade A lioness, with udders all drawn dry, Lay couching, head on ground, with catlike watch, When that the sleeping man should stir; for 'tis The royal disposition of that beast To prey on nothing that doth seem as dead: This seen, Orlando did approach the man And found it was his brother, his elder brother. CELIA O, I have heard him speak of that same brother; And he did render him the most unnatural That lived amongst men. OLIVER And well he might so do, For well I know he was unnatural. ROSALIND But, to Orlando: did he leave him there, Food to the suck'd and hungry lioness? OLIVER Twice did he turn his back and purposed so; But kindness, nobler ever than revenge, And nature, stronger than his just occasion, Made him give battle to the lioness, Who quickly fell before him: in which hurtling From miserable slumber I awaked. CELIA Are you his brother? ROSALIND Wast you he rescued? CELIA Was't you that did so oft contrive to kill him? OLIVER 'Twas I; but 'tis not I I do not shame To tell you what I was, since my conversion So sweetly tastes, being the thing I am. ROSALIND But, for the bloody napkin? OLIVER By and by. When from the first to last betwixt us two Tears our recountments had most kindly bathed, As how I came into that desert place:-- In brief, he led me to the gentle duke, Who gave me fresh array and entertainment, Committing me unto my brother's love; Who led me instantly unto his cave, There stripp'd himself, and here upon his arm The lioness had torn some flesh away, Which all this while had bled; and now he fainted And cried, in fainting, upon Rosalind. Brief, I recover'd him, bound up his wound; And, after some small space, being strong at heart, He sent me hither, stranger as I am, To tell this story, that you might excuse His broken promise, and to give this napkin Dyed in his blood unto the shepherd youth That he in sport doth call his Rosalind. [ROSALIND swoons] CELIA Why, how now, Ganymede! sweet Ganymede! OLIVER Many will swoon when they do look on blood. CELIA There is more in it. Cousin Ganymede! OLIVER Look, he recovers. ROSALIND I would I were at home. CELIA We'll lead you thither. I pray you, will you take him by the arm? OLIVER Be of good cheer, youth: you a man! you lack a man's heart. ROSALIND I do so, I confess it. Ah, sirrah, a body would think this was well counterfeited! I pray you, tell your brother how well I counterfeited. Heigh-ho! OLIVER This was not counterfeit: there is too great testimony in your complexion that it was a passion of earnest. ROSALIND Counterfeit, I assure you. OLIVER Well then, take a good heart and counterfeit to be a man. ROSALIND So I do: but, i' faith, I should have been a woman by right. CELIA Come, you look paler and paler: pray you, draw homewards. Good sir, go with us. OLIVER That will I, for I must bear answer back How you excuse my brother, Rosalind. ROSALIND I shall devise something: but, I pray you, commend my counterfeiting to him. Will you go? [Exeunt] AS YOU LIKE IT ACT V SCENE I The forest. [Enter TOUCHSTONE and AUDREY] TOUCHSTONE We shall find a time, Audrey; patience, gentle Audrey. AUDREY Faith, the priest was good enough, for all the old gentleman's saying. TOUCHSTONE A most wicked Sir Oliver, Audrey, a most vile Martext. But, Audrey, there is a youth here in the forest lays claim to you. AUDREY Ay, I know who 'tis; he hath no interest in me in the world: here comes the man you mean. TOUCHSTONE It is meat and drink to me to see a clown: by my troth, we that have good wits have much to answer for; we shall be flouting; we cannot hold. [Enter WILLIAM] WILLIAM Good even, Audrey. AUDREY God ye good even, William. WILLIAM And good even to you, sir. TOUCHSTONE Good even, gentle friend. Cover thy head, cover thy head; nay, prithee, be covered. How old are you, friend? WILLIAM Five and twenty, sir. TOUCHSTONE A ripe age. Is thy name William? WILLIAM William, sir. TOUCHSTONE A fair name. Wast born i' the forest here? WILLIAM Ay, sir, I thank God. TOUCHSTONE 'Thank God;' a good answer. Art rich? WILLIAM Faith, sir, so so. TOUCHSTONE 'So so' is good, very good, very excellent good; and yet it is not; it is but so so. Art thou wise? WILLIAM Ay, sir, I have a pretty wit. TOUCHSTONE Why, thou sayest well. I do now remember a saying, 'The fool doth think he is wise, but the wise man knows himself to be a fool.' The heathen philosopher, when he had a desire to eat a grape, would open his lips when he put it into his mouth; meaning thereby that grapes were made to eat and lips to open. You do love this maid? WILLIAM I do, sir. TOUCHSTONE Give me your hand. Art thou learned? WILLIAM No, sir. TOUCHSTONE Then learn this of me: to have, is to have; for it is a figure in rhetoric that drink, being poured out of a cup into a glass, by filling the one doth empty the other; for all your writers do consent that ipse is he: now, you are not ipse, for I am he. WILLIAM Which he, sir? TOUCHSTONE He, sir, that must marry this woman. Therefore, you clown, abandon,--which is in the vulgar leave,--the society,--which in the boorish is company,--of this female,--which in the common is woman; which together is, abandon the society of this female, or, clown, thou perishest; or, to thy better understanding, diest; or, to wit I kill thee, make thee away, translate thy life into death, thy liberty into bondage: I will deal in poison with thee, or in bastinado, or in steel; I will bandy with thee in faction; I will o'errun thee with policy; I will kill thee a hundred and fifty ways: therefore tremble and depart. AUDREY Do, good William. WILLIAM God rest you merry, sir. [Exit] [Enter CORIN] CORIN Our master and mistress seeks you; come, away, away! TOUCHSTONE Trip, Audrey! trip, Audrey! I attend, I attend. [Exeunt] AS YOU LIKE IT ACT V SCENE II The forest. [Enter ORLANDO and OLIVER] ORLANDO Is't possible that on so little acquaintance you should like her? that but seeing you should love her? and loving woo? and, wooing, she should grant? and will you persever to enjoy her? OLIVER Neither call the giddiness of it in question, the poverty of her, the small acquaintance, my sudden wooing, nor her sudden consenting; but say with me, I love Aliena; say with her that she loves me; consent with both that we may enjoy each other: it shall be to your good; for my father's house and all the revenue that was old Sir Rowland's will I estate upon you, and here live and die a shepherd. ORLANDO You have my consent. Let your wedding be to-morrow: thither will I invite the duke and all's contented followers. Go you and prepare Aliena; for look you, here comes my Rosalind. [Enter ROSALIND] ROSALIND God save you, brother. OLIVER And you, fair sister. [Exit] ROSALIND O, my dear Orlando, how it grieves me to see thee wear thy heart in a scarf! ORLANDO It is my arm. ROSALIND I thought thy heart had been wounded with the claws of a lion. ORLANDO Wounded it is, but with the eyes of a lady. ROSALIND Did your brother tell you how I counterfeited to swoon when he showed me your handkerchief? ORLANDO Ay, and greater wonders than that. ROSALIND O, I know where you are: nay, 'tis true: there was never any thing so sudden but the fight of two rams and Caesar's thrasonical brag of 'I came, saw, and overcame:' for your brother and my sister no sooner met but they looked, no sooner looked but they loved, no sooner loved but they sighed, no sooner sighed but they asked one another the reason, no sooner knew the reason but they sought the remedy; and in these degrees have they made a pair of stairs to marriage which they will climb incontinent, or else be incontinent before marriage: they are in the very wrath of love and they will together; clubs cannot part them. ORLANDO They shall be married to-morrow, and I will bid the duke to the nuptial. But, O, how bitter a thing it is to look into happiness through another man's eyes! By so much the more shall I to-morrow be at the height of heart-heaviness, by how much I shall think my brother happy in having what he wishes for. ROSALIND Why then, to-morrow I cannot serve your turn for Rosalind? ORLANDO I can live no longer by thinking. ROSALIND I will weary you then no longer with idle talking. Know of me then, for now I speak to some purpose, that I know you are a gentleman of good conceit: I speak not this that you should bear a good opinion of my knowledge, insomuch I say I know you are; neither do I labour for a greater esteem than may in some little measure draw a belief from you, to do yourself good and not to grace me. Believe then, if you please, that I can do strange things: I have, since I was three year old, conversed with a magician, most profound in his art and yet not damnable. If you do love Rosalind so near the heart as your gesture cries it out, when your brother marries Aliena, shall you marry her: I know into what straits of fortune she is driven; and it is not impossible to me, if it appear not inconvenient to you, to set her before your eyes tomorrow human as she is and without any danger. ORLANDO Speakest thou in sober meanings? ROSALIND By my life, I do; which I tender dearly, though I say I am a magician. Therefore, put you in your best array: bid your friends; for if you will be married to-morrow, you shall, and to Rosalind, if you will. [Enter SILVIUS and PHEBE] Look, here comes a lover of mine and a lover of hers. PHEBE Youth, you have done me much ungentleness, To show the letter that I writ to you. ROSALIND I care not if I have: it is my study To seem despiteful and ungentle to you: You are there followed by a faithful shepherd; Look upon him, love him; he worships you. PHEBE Good shepherd, tell this youth what 'tis to love. SILVIUS It is to be all made of sighs and tears; And so am I for Phebe. PHEBE And I for Ganymede. ORLANDO And I for Rosalind. ROSALIND And I for no woman. SILVIUS It is to be all made of faith and service; And so am I for Phebe. PHEBE And I for Ganymede. ORLANDO And I for Rosalind. ROSALIND And I for no woman. SILVIUS It is to be all made of fantasy, All made of passion and all made of wishes, All adoration, duty, and observance, All humbleness, all patience and impatience, All purity, all trial, all observance; And so am I for Phebe. PHEBE And so am I for Ganymede. ORLANDO And so am I for Rosalind. ROSALIND And so am I for no woman. PHEBE If this be so, why blame you me to love you? SILVIUS If this be so, why blame you me to love you? ORLANDO If this be so, why blame you me to love you? ROSALIND Who do you speak to, 'Why blame you me to love you?' ORLANDO To her that is not here, nor doth not hear. ROSALIND Pray you, no more of this; 'tis like the howling of Irish wolves against the moon. [To SILVIUS] I will help you, if I can: [To PHEBE] I would love you, if I could. To-morrow meet me all together. [To PHEBE] I will marry you, if ever I marry woman, and I'll be married to-morrow: [To ORLANDO] I will satisfy you, if ever I satisfied man, and you shall be married to-morrow: [To SILVIUS] I will content you, if what pleases you contents you, and you shall be married to-morrow. [To ORLANDO] As you love Rosalind, meet: [To SILVIUS] as you love Phebe, meet: and as I love no woman, I'll meet. So fare you well: I have left you commands. SILVIUS I'll not fail, if I live. PHEBE Nor I. ORLANDO Nor I. [Exeunt] AS YOU LIKE IT ACT V SCENE III The forest. [Enter TOUCHSTONE and AUDREY] TOUCHSTONE To-morrow is the joyful day, Audrey; to-morrow will we be married. AUDREY I do desire it with all my heart; and I hope it is no dishonest desire to desire to be a woman of the world. Here comes two of the banished duke's pages. [Enter two Pages] First Page Well met, honest gentleman. TOUCHSTONE By my troth, well met. Come, sit, sit, and a song. Second Page We are for you: sit i' the middle. First Page Shall we clap into't roundly, without hawking or spitting or saying we are hoarse, which are the only prologues to a bad voice? Second Page I'faith, i'faith; and both in a tune, like two gipsies on a horse. SONG. It was a lover and his lass, With a hey, and a ho, and a hey nonino, That o'er the green corn-field did pass In the spring time, the only pretty ring time, When birds do sing, hey ding a ding, ding: Sweet lovers love the spring. Between the acres of the rye, With a hey, and a ho, and a hey nonino These pretty country folks would lie, In spring time, &c. This carol they began that hour, With a hey, and a ho, and a hey nonino, How that a life was but a flower In spring time, &c. And therefore take the present time, With a hey, and a ho, and a hey nonino; For love is crowned with the prime In spring time, &c. TOUCHSTONE Truly, young gentlemen, though there was no great matter in the ditty, yet the note was very untuneable. First Page You are deceived, sir: we kept time, we lost not our time. TOUCHSTONE By my troth, yes; I count it but time lost to hear such a foolish song. God be wi' you; and God mend your voices! Come, Audrey. [Exeunt] AS YOU LIKE IT ACT V SCENE IV The forest. [Enter DUKE SENIOR, AMIENS, JAQUES, ORLANDO, OLIVER, and CELIA] DUKE SENIOR Dost thou believe, Orlando, that the boy Can do all this that he hath promised? ORLANDO I sometimes do believe, and sometimes do not; As those that fear they hope, and know they fear. [Enter ROSALIND, SILVIUS, and PHEBE] ROSALIND Patience once more, whiles our compact is urged: You say, if I bring in your Rosalind, You will bestow her on Orlando here? DUKE SENIOR That would I, had I kingdoms to give with her. ROSALIND And you say, you will have her, when I bring her? ORLANDO That would I, were I of all kingdoms king. ROSALIND You say, you'll marry me, if I be willing? PHEBE That will I, should I die the hour after. ROSALIND But if you do refuse to marry me, You'll give yourself to this most faithful shepherd? PHEBE So is the bargain. ROSALIND You say, that you'll have Phebe, if she will? SILVIUS Though to have her and death were both one thing. ROSALIND I have promised to make all this matter even. Keep you your word, O duke, to give your daughter; You yours, Orlando, to receive his daughter: Keep your word, Phebe, that you'll marry me, Or else refusing me, to wed this shepherd: Keep your word, Silvius, that you'll marry her. If she refuse me: and from hence I go, To make these doubts all even. [Exeunt ROSALIND and CELIA] DUKE SENIOR I do remember in this shepherd boy Some lively touches of my daughter's favour. ORLANDO My lord, the first time that I ever saw him Methought he was a brother to your daughter: But, my good lord, this boy is forest-born, And hath been tutor'd in the rudiments Of many desperate studies by his uncle, Whom he reports to be a great magician, Obscured in the circle of this forest. [Enter TOUCHSTONE and AUDREY] JAQUES There is, sure, another flood toward, and these couples are coming to the ark. Here comes a pair of very strange beasts, which in all tongues are called fools. TOUCHSTONE Salutation and greeting to you all! JAQUES Good my lord, bid him welcome: this is the motley-minded gentleman that I have so often met in the forest: he hath been a courtier, he swears. TOUCHSTONE If any man doubt that, let him put me to my purgation. I have trod a measure; I have flattered a lady; I have been politic with my friend, smooth with mine enemy; I have undone three tailors; I have had four quarrels, and like to have fought one. JAQUES And how was that ta'en up? TOUCHSTONE Faith, we met, and found the quarrel was upon the seventh cause. JAQUES How seventh cause? Good my lord, like this fellow. DUKE SENIOR I like him very well. TOUCHSTONE God 'ild you, sir; I desire you of the like. I press in here, sir, amongst the rest of the country copulatives, to swear and to forswear: according as marriage binds and blood breaks: a poor virgin, sir, an ill-favoured thing, sir, but mine own; a poor humour of mine, sir, to take that that no man else will: rich honesty dwells like a miser, sir, in a poor house; as your pearl in your foul oyster. DUKE SENIOR By my faith, he is very swift and sententious. TOUCHSTONE According to the fool's bolt, sir, and such dulcet diseases. JAQUES But, for the seventh cause; how did you find the quarrel on the seventh cause? TOUCHSTONE Upon a lie seven times removed:--bear your body more seeming, Audrey:--as thus, sir. I did dislike the cut of a certain courtier's beard: he sent me word, if I said his beard was not cut well, he was in the mind it was: this is called the Retort Courteous. If I sent him word again 'it was not well cut,' he would send me word, he cut it to please himself: this is called the Quip Modest. If again 'it was not well cut,' he disabled my judgment: this is called the Reply Churlish. If again 'it was not well cut,' he would answer, I spake not true: this is called the Reproof Valiant. If again 'it was not well cut,' he would say I lied: this is called the Counter-cheque Quarrelsome: and so to the Lie Circumstantial and the Lie Direct. JAQUES And how oft did you say his beard was not well cut? TOUCHSTONE I durst go no further than the Lie Circumstantial, nor he durst not give me the Lie Direct; and so we measured swords and parted. JAQUES Can you nominate in order now the degrees of the lie? TOUCHSTONE O sir, we quarrel in print, by the book; as you have books for good manners: I will name you the degrees. The first, the Retort Courteous; the second, the Quip Modest; the third, the Reply Churlish; the fourth, the Reproof Valiant; the fifth, the Countercheque Quarrelsome; the sixth, the Lie with Circumstance; the seventh, the Lie Direct. All these you may avoid but the Lie Direct; and you may avoid that too, with an If. I knew when seven justices could not take up a quarrel, but when the parties were met themselves, one of them thought but of an If, as, 'If you said so, then I said so;' and they shook hands and swore brothers. Your If is the only peacemaker; much virtue in If. JAQUES Is not this a rare fellow, my lord? he's as good at any thing and yet a fool. DUKE SENIOR He uses his folly like a stalking-horse and under the presentation of that he shoots his wit. [Enter HYMEN, ROSALIND, and CELIA] [Still Music] HYMEN Then is there mirth in heaven, When earthly things made even Atone together. Good duke, receive thy daughter Hymen from heaven brought her, Yea, brought her hither, That thou mightst join her hand with his Whose heart within his bosom is. ROSALIND [To DUKE SENIOR] To you I give myself, for I am yours. [To ORLANDO] To you I give myself, for I am yours. DUKE SENIOR If there be truth in sight, you are my daughter. ORLANDO If there be truth in sight, you are my Rosalind. PHEBE If sight and shape be true, Why then, my love adieu! ROSALIND I'll have no father, if you be not he: I'll have no husband, if you be not he: Nor ne'er wed woman, if you be not she. HYMEN Peace, ho! I bar confusion: 'Tis I must make conclusion Of these most strange events: Here's eight that must take hands To join in Hymen's bands, If truth holds true contents. You and you no cross shall part: You and you are heart in heart You to his love must accord, Or have a woman to your lord: You and you are sure together, As the winter to foul weather. Whiles a wedlock-hymn we sing, Feed yourselves with questioning; That reason wonder may diminish, How thus we met, and these things finish. SONG. Wedding is great Juno's crown: O blessed bond of board and bed! 'Tis Hymen peoples every town; High wedlock then be honoured: Honour, high honour and renown, To Hymen, god of every town! DUKE SENIOR O my dear niece, welcome thou art to me! Even daughter, welcome, in no less degree. PHEBE I will not eat my word, now thou art mine; Thy faith my fancy to thee doth combine. [Enter JAQUES DE BOYS] JAQUES DE BOYS Let me have audience for a word or two: I am the second son of old Sir Rowland, That bring these tidings to this fair assembly. Duke Frederick, hearing how that every day Men of great worth resorted to this forest, Address'd a mighty power; which were on foot, In his own conduct, purposely to take His brother here and put him to the sword: And to the skirts of this wild wood he came; Where meeting with an old religious man, After some question with him, was converted Both from his enterprise and from the world, His crown bequeathing to his banish'd brother, And all their lands restored to them again That were with him exiled. This to be true, I do engage my life. DUKE SENIOR Welcome, young man; Thou offer'st fairly to thy brothers' wedding: To one his lands withheld, and to the other A land itself at large, a potent dukedom. First, in this forest, let us do those ends That here were well begun and well begot: And after, every of this happy number That have endured shrewd days and nights with us Shall share the good of our returned fortune, According to the measure of their states. Meantime, forget this new-fall'n dignity And fall into our rustic revelry. Play, music! And you, brides and bridegrooms all, With measure heap'd in joy, to the measures fall. JAQUES Sir, by your patience. If I heard you rightly, The duke hath put on a religious life And thrown into neglect the pompous court? JAQUES DE BOYS He hath. JAQUES To him will I : out of these convertites There is much matter to be heard and learn'd. [To DUKE SENIOR] You to your former honour I bequeath; Your patience and your virtue well deserves it: [To ORLANDO] You to a love that your true faith doth merit: [To OLIVER] You to your land and love and great allies: [To SILVIUS] You to a long and well-deserved bed: [To TOUCHSTONE] And you to wrangling; for thy loving voyage Is but for two months victuall'd. So, to your pleasures: I am for other than for dancing measures. DUKE SENIOR Stay, Jaques, stay. JAQUES To see no pastime I what you would have I'll stay to know at your abandon'd cave. [Exit] DUKE SENIOR Proceed, proceed: we will begin these rites, As we do trust they'll end, in true delights. [A dance] AS YOU LIKE IT EPILOGUE ROSALIND It is not the fashion to see the lady the epilogue; but it is no more unhandsome than to see the lord the prologue. If it be true that good wine needs no bush, 'tis true that a good play needs no epilogue; yet to good wine they do use good bushes, and good plays prove the better by the help of good epilogues. What a case am I in then, that am neither a good epilogue nor cannot insinuate with you in the behalf of a good play! I am not furnished like a beggar, therefore to beg will not become me: my way is to conjure you; and I'll begin with the women. I charge you, O women, for the love you bear to men, to like as much of this play as please you: and I charge you, O men, for the love you bear to women--as I perceive by your simpering, none of you hates them--that between you and the women the play may please. If I were a woman I would kiss as many of you as had beards that pleased me, complexions that liked me and breaths that I defied not: and, I am sure, as many as have good beards or good faces or sweet breaths will, for my kind offer, when I make curtsy, bid me farewell. [Exeunt] Compression Pointers

Compression Pointers

Compression resources, conferences, and some research groups and companies, are listed towards the end of this page.

Use this handy form to add something to this page, or to simply say you liked this page

What's New?

Jean-loup Gailly -- Mr. gzip, PNG, CCR (1996-06-10)
MPEG Pointers and Resources
Robert M. Gray -- Signal compression, VQ, image quality evaluation (1996-04-22)
Compression and Classification Group -- ISL,EE,Stanford (1996-04-22)
Signal Processing and the International Information Infrastructure -- Web sites (1996-04-22)
Valenta, Vladimir -- (1996-04-22)
Jordan, Frederic -- Parallel Image Compression (1996-04-12)
Electro-Optical Technologies, Inc. -- Consultant (1996-04-12)
quicktime.apple.com -- Quicktime site (1996-03-11)
IBM Hardware -- Compression chips (1996-03-11)

People

A

Adler, Mark -- Info-ZIP; Zip, UnZip, gzip and zlib co-author; PNG group

B

Baker, Matthew -- Region based video compression

Bamberger, Roberto H.

Bell, Daniel -- Region based image compression

Bell, Tim -- compression, computer science for children, and computers and music.

Bellard, Fabrice -- Author of LZEXE

Berghorn, Willy

Bhaskaran, Vasudev -- Image and Video compression

Bloom, Charles -- text compression, LZ methods, PPM methods...

Brito, Roger -- Arithmetic Coding, LZW, Text Compression

Budge, Scott E. -- medical/lossy image compression

Burnett, Ian -- Speech coding, prototype waveform techniques

C

Chan, Christopher -- universal lossy source coding, adaptive VQ

Chao, Hong-yang -- Lightning strike image compressor

Chao, Stewart

Cherriman, Peter

Cheung, S.C. -- Scalable video compression algorithms (18th Feb 1996)

Christopoulos, Charilaos -- Image and Video compression

Chrysafis, Christos

Chung, Wilson C. -- R-D image and video coding, subband/wavelet, filter banks

Clark, Alan -- primary contact for V.42bis. Developed BTLZ variant of LZW

Cleary, John -- PPM, PPM*, K*

Cohn, Martin

Cormack, Gordon V. -- DMC

Cramer, Chris -- neural network image compression

D

Danskin, John -- Protocol compression, document compression (9th Feb 1996)

Davis, Geoff -- wavelets, image compression, medical

Dilger, Andreas -- fractal block coding of video sequences

E

Estes, Robert

F

Fisher, Yuval -- Fractal Image Compression

Ford, Adrian -- Subjective and Objective Compression quality (5th Mar 1996)

G

Jean-loup Gailly -- Mr. gzip, PNG, CCR (1996-06-10)

Gersho, Allen -- Vector Quantisation, Image Compression

Goertzel, Ben

Gooch, Mark -- High Performance Hardware Compression (7th Feb 1996)

Goyal, Vivek -- overcomplete representations, adaptive transform coding, VQ

Robert M. Gray -- Signal compression, VQ, image quality evaluation

H

Hafner, Ullrich -- WFA image compression

Hirschberg, Dan -- algorithm theory, compression

Holland, Scott

Horspool, R. Nigel -- text compression, ECG compression

I

Inglis, Stuart -- image compression, OCR, lossy/lossless document compression

J

Jones, Douglas -- splay-tree based compression and encryption

Jones, Simon -- Lossless compression, High Performance Hardware (7th Feb 1996)

Jordan, Frederic -- Parallel Image Compression (12th April 1996)

Jung, Robert K. -- ARJ

jutta

K

Kominek, John -- Fractal and spline based compression

Kjelso, Morten -- Main memory compression, High performance hardware

Kuhn, Markus -- JBIG implementation

Kuo, C.-C. Jay

Kuru, Esa

Kyfonidis, Theodoros

L

Lamparter, Bernd

Langdon, Glen

Larsson, Jesper -- algorithms and data structures, text compression

M

Manber, Udi

Mangen, Jean-Michel -- image compression, wavelets, satellite

Moffat, Alistair -- text and index compression, coding methods, information retrieval, document databases

Montgomery, Christopher -- OggSquish, audio compression

Mueller, Urban Dominik -- XPK system

N

Neal, Radford

Nevill-Manning, Craig

Nicholls, Jeremy

Noah, Matt -- speech, ATC, ACELP and IMBE

Nuri, Veyis -- wavelets, data compression, DSP (speech & image)

O

Oleg -- Lots of code

Ortega, Antonio -- Video compression, Packet video, Adaptive quantization

Owen, Charles

P

Provine, Joseph -- Model based coding

R

Robinson, John -- Binary Tree Predictive Coding

Roelofs, Greg -- Info-ZIP; primary UnZip author; PNG group

Rose, Kenneth

Russo, Roberto Maria -- Multiplatform Data Compression

S

Schmidt, Bill

Shaw, Sandy C.

Sharifi, Kamran -- Video over ATM networks

Shende, Sunil M.

Silverstein, D. Amnon

Smoot, Steve -- MPEG

Storer, James A.

Streit, Jurgen -- Low bitrate coding

Strutz, Tilo -- Wavelet image compressor, demonstration execs

T

Tate, Steve

Teahan, Bill -- PPM, PPM*, master of the Calgary Corpus

Thomson, Duncan -- ECG compression with ANNs

Tilton, James C.

Tomczyk, Marek

Turpin, Andrew -- Prefix Codes

V

Vetterli, Martin -- wavelets, subband coding, video compression, computational complexity

Vitter, Jeff

Voukelatos, Stathis

de Vries, Nico -- AIP-NL, UltraCompressor II development

W

Wareham, Paul -- Region-oriented video coding

Wegener, Al -- DSP, lossless audio compression and AC-2

Wei, Dong -- Wavelet compression

Williams, Ross

Witten, Ian -- PPM, mg, arithmetic coding

Wolff, Gerry

Woo, Woon-Tack -- stereo image and video compression (12th Feb 1996)

Wu, Xiaolin -- CALIC

Z

Zobel, Justin -- index compression, database compression



Conferences

Data Compression Conference (DCC), Snowbird, Utah, USA.

Resources

Where to get answers...
International Telecommunication Union (ITU) -- standards documents (CCITT)
comp.compression -- Frequently Asked Questions -- Come here 1st!
JPEG - Frequently Asked Questions
MPEG - Frequently Asked Questions
Standards - Frequenty Asked Questions
usenet newsgroup: comp.compression.research
Archive Compression Test -- Summary of all archivers
Fractal compression bibliography -- bibtex file
LZ/Complexity Seminars -- (in German)
Comparitive Compression Ratios -- Sofar...B&W, Gray Scale, Text Compression
VCN (Video, Compression, Networking) Glossary
Digital Library -- search for compression

Reports/Ph.D. Theses
Paul Howards Ph.D. thesis
The Design and Analysis of Efficient Lossless Data Compression Systems

Source code
Arithmetic coding routines
        (from Moffat, Neal and Witten, Proc. DCC, April 1995)
CACM Arithmetic coding package
        (Witten, Neal and Cleary, CACM 30:520-541, June 1987)
JBIG Source code Includes a Q-coder
Markus Kuhn's JBIG implementation
k-arithmetic coder
Lossless Data Compression toolkit 1.1
Splay Trees Code -- by Douglas W. Jones
Block compression code -- Excellent text compressor

Test Files
Test Images -- CCITT images (pbm), Lena etc. (Sun raster)
Stockholm test images -- You have to buy a CDROM, thats all I know! :-(
         mail me at singlis@cs.waikato.ac.nz if you know anything about them.
Calgary Text Compression Corpus (Text Compression, Bell, Cleary and Witten, 1990)

Research Projects, Standards & Companies

Research/Free software Groups
Compression and Classification Group -- ISL,EE,Stanford (22th April 1996)
Voice email -- Lossless audio compression (18th Feb 1996)
Electro-Optical Technologies, Inc. -- Consultant (12th April 1996)
quicktime.apple.com -- Quicktime site (11th Mar 1996)
IMAGE etc. -- Commercial image compression software (Fractals/Wavelets) (29th Feb 1996)
NCAR CCM Compression and Visualisation -- (18th Feb 1996)
SPIHT -- Wavelet Natural Image Compressor (12th Feb 1996)
Real-Time Lossless Compression Systems -- Loughborough University
Web site for Multirate Signal Processing -- University of Wisconsin, Madison
Info-ZIP -- free, portable Zip and UnZip utilities
CEDIS -- NASA, Maryland, Image/data compression
CIC-3 Image Compression -- FBI Fingerprints
Signal Compression Lab at UCSB
University of Washington compression lab -- VQ, Wavelets, Shlomo

Snippets
Signal Processing and the International Information Infrastructure -- Web sites (22th April 1996)
Increasing Web bandwith -- comparing GIF, JPEG, Fractal compression
Fractal Links on Yahoo
Digital Speech Compression GSM 06.10 RPE-LTP -- DDJ
CREW -- Continuous tone loss(y/less) wavelet compression
CALIC -- Context-based adaptive lossless image compressor
Berkeley MPEG -- MPEG tools
MPEG Pointers and Resources

Wavelets
EPIC (Efficient Pyramid Image Coder) -- by Eero Simoncelli
Tucker, Michael -- FASTWAVE, audio/image compression
HARC -- Lossy Wavelet Compression technology
UC Berkeley Wavelet Group
Khoros Wavetlet and Compression Toolbox
The Wavelet Digest
Rice DSP Publications Archive -- Wavelets, Time Frequency/Scale

Fractals
Fractal Image Compression -- Software, Pointers, Conferences
Fractal Design Corporation
New Fractal Image Compression program

Companies
IBM Hardware -- Compression chips (11th Mar 1996)
Summus Wavelet Technology -- Wavelet image and video compressors (11th Mar 1996)
Fractal Image Compression -- Mitsubishi (18th Feb 1996)
Terran Interactive -- Video compression for the Mac (1st Feb 1996)
DV Mpeg -- Windows drivers (18th Feb 1996)
Crawford Compression Services -- MPEG post-production (18th Feb 1996)
Intelligent Compression Technologies (18th Feb 1996)
Pegasus Imaging -- Compression software/dev. kits (12th Feb 1996)
Aladdin Systems -- StuffIt compression products
Stac Electronics
DCP Research -- Hardware solutions
Aware Inc. -- Specialised compression company
IVS - INRIA Videoconferencing System
Telvox Teleinformatica -- Multiplatform Data Compressor
Compression Technologies, Inc -- Canada
Optivision -- MPEG
PKWARE -- Makers of PKZIP
Multimedia Imaging Services

Audio compression
Fraunhofer Institut fr Integrierte Schaltungen
Shorten
digital speech compression
Audio compression references
SpeakFreely - compression
SpeakFreely - Contents
#ifndef lint static char Rcs_Id[] = "$Id: fields.c,v 1.7 1994/01/06 05:26:37 geoff Exp $"; #endif /* * $Log: fields.c,v $ * Revision 1.7 1994/01/06 05:26:37 geoff * Get rid of all references to System V string routines, for portability * (sigh). * * Revision 1.6 1994/01/05 20:13:43 geoff * Add the maxf parameter * * Revision 1.5 1994/01/04 02:40:21 geoff * Make the increments settable (field_line_inc and field_field_inc). * Add support for the FLD_NOSHRINK flag. * * Revision 1.4 1993/09/27 17:48:02 geoff * Fix some lint complaints and some parenthesization errors. * * Revision 1.3 1993/09/09 01:11:11 geoff * Add a return value to fieldwrite. Add support for backquotes and for * unstripped backslashes. * * Revision 1.2 1993/08/26 00:02:50 geoff * Fix a stupid null-pointer bug * * Revision 1.1 1993/08/25 21:32:05 geoff * Initial revision * */ #include #include "config.h" #include "fields.h" field_t * fieldread P ((FILE * file, char * delims, int flags, int maxf)); /* Read a line with fields from a file */ field_t * fieldmake P ((char * line, int allocated, char * delims, int flags, int maxf)); /* Make a field structure from a line */ static field_t * fieldparse P ((field_t * fieldp, char * line, char * delims, int flags, int maxf)); /* Parse the fields in a line */ static int fieldbackch P ((char * str, char ** out, int strip)); /* Process backslash sequences */ int fieldwrite P ((FILE * file, field_t * fieldp, int delim)); /* Write a line with fields to a file */ void fieldfree P ((field_t * fieldp)); /* Free a field returned by fieldread */ unsigned int field_field_inc = 20; /* Increment to increase # fields by */ unsigned int field_line_inc = 512; /* Incr to increase line length by */ #ifndef USG #define strchr index #endif /* USG */ extern void free (); extern char * malloc (); extern char * realloc (); extern char * strchr (); extern int strlen (); /* * Read one line of the given file into a buffer, break it up into * fields, and return them to the caller. The field_t structure * returned must eventually be freed with fieldfree. */ field_t * fieldread (file, delims, flags, maxf) FILE * file; /* File to read lines from */ char * delims; /* Characters to use for field delimiters */ int flags; /* Option flags; see fields.h */ int maxf; /* Maximum number of fields to parse */ { register char * linebuf; /* Buffer to hold the line read in */ int linemax; /* Maximum line buffer size */ int linesize; /* Current line buffer size */ linebuf = (char *) malloc (field_line_inc); if (linebuf == NULL) return NULL; linemax = field_line_inc; linesize = 0; /* * Read in the line. */ while (fgets (&linebuf[linesize], linemax - linesize, file) != NULL) { linesize += strlen (&linebuf[linesize]); if (linebuf[linesize - 1] == '\n') break; else { linemax += field_line_inc; linebuf = (char *) realloc (linebuf, linemax); if (linebuf == NULL) return NULL; } } if (linesize == 0) { free (linebuf); return NULL; } return fieldmake (linebuf, 1, delims, flags, maxf); } field_t * fieldmake (line, allocated, delims, flags, maxf) char * line; /* Line to make into a field structure */ int allocated; /* NZ if line allocated with malloc */ char * delims; /* Characters to use for field delimiters */ int flags; /* Option flags; see fields.h */ int maxf; /* Maximum number of fields to parse */ { register field_t * fieldp; /* Structure describing the fields */ int linesize; /* Current line buffer size */ fieldp = (field_t *) malloc (sizeof (field_t)); if (fieldp == NULL) return NULL; fieldp->nfields = 0; fieldp->linebuf = allocated ? line : NULL; fieldp->fields = NULL; fieldp->hadnl = 0; linesize = strlen (line); if (line[linesize - 1] == '\n') { line[--linesize] = '\0'; fieldp->hadnl = 1; } /* * Shrink the line buffer if necessary. */ if (allocated && (flags & FLD_NOSHRINK) == 0) { line = fieldp->linebuf = (char *) realloc (fieldp->linebuf, linesize + 1); if (fieldp->linebuf == NULL) { fieldfree (fieldp); return NULL; } } return fieldparse (fieldp, line, delims, flags, maxf); } static field_t * fieldparse (fieldp, line, delims, flags, maxf) register field_t * fieldp; /* Field structure to parse into */ register char * line; /* Line to be parsed */ char * delims; /* Characters to use for field delimiters */ int flags; /* Option flags; see fields.h */ int maxf; /* Maximum number of fields to parse */ { int fieldmax; /* Max size of fields array */ char * lineout; /* Where to store xlated char in line */ char quote; /* Quote character in use */ fieldp->nfields = 0; fieldmax = (maxf != 0 && maxf < field_field_inc) ? maxf + 2 : field_field_inc; fieldp->fields = (char **) malloc (fieldmax * sizeof (char *)); if (fieldp->fields == NULL) { fieldfree (fieldp); return NULL; } if ((flags & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES)) == FLD_SHQUOTES) flags |= FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES; while (1) { if (flags & FLD_RUNS) { while (*line != '\0' && strchr (delims, *line) != NULL) line++; /* Skip runs of delimiters */ if (*line == '\0') break; } fieldp->fields[fieldp->nfields] = lineout = line; /* * Skip to the next delimiter. At the end of skipping, "line" will * point to either a delimiter or a null byte. */ if (flags & (FLD_SHQUOTES | FLD_SNGLQUOTES | FLD_BACKQUOTES | FLD_DBLQUOTES | FLD_BACKSLASH)) { while (*line != '\0') { if (strchr (delims, *line) != NULL) break; else if (((flags & FLD_SNGLQUOTES) && *line == '\'') || ((flags & FLD_BACKQUOTES) && *line == '`') || ((flags & FLD_DBLQUOTES) && *line == '"')) { if ((flags & FLD_SHQUOTES) == 0 && line != fieldp->fields[fieldp->nfields]) quote = '\0'; else quote = *line; } else quote = '\0'; if (quote == '\0') { if (*line == '\\' && (flags & FLD_BACKSLASH)) { line++; if (*line == '\0') break; line += fieldbackch (line, &lineout, flags & FLD_STRIPQUOTES); } else *lineout++ = *line++; } else { /* Process quoted string */ if ((flags & FLD_STRIPQUOTES) == 0) *lineout++ = quote; ++line; while (*line != '\0') { if (*line == quote) { if ((flags & FLD_STRIPQUOTES) == 0) *lineout++ = quote; line++; /* Go on past quote */ if ((flags & FLD_SHQUOTES) == 0) { while (*line != '\0' && strchr (delims, *line) == NULL) line++; /* Skip to delimiter */ } break; } else if (*line == '\\') { if (flags & FLD_BACKSLASH) { line++; if (*line == '\0') break; else line += fieldbackch (line, &lineout, flags & FLD_STRIPQUOTES); } else { *lineout++ = '\\'; if (*++line == '\0') break; *lineout++ = *line; } } else *lineout++ = *line++; } } } } else { while (*line != '\0' && strchr (delims, *line) == NULL) line++; /* Skip to delimiter */ lineout = line; } fieldp->nfields++; if (*line++ == '\0') break; if (maxf != 0 && fieldp->nfields > maxf) break; *lineout = '\0'; if (fieldp->nfields >= fieldmax) { fieldmax += field_field_inc; fieldp->fields = (char **) realloc (fieldp->fields, fieldmax * sizeof (char *)); if (fieldp->fields == NULL) { fieldfree (fieldp); return NULL; } } } /* * Shrink the field pointers and return the field structure. */ if ((flags & FLD_NOSHRINK) == 0 && fieldp->nfields >= fieldmax) { fieldp->fields = (char **) realloc (fieldp->fields, (fieldp->nfields + 1) * sizeof (char *)); if (fieldp->fields == NULL) { fieldfree (fieldp); return NULL; } } fieldp->fields[fieldp->nfields] = NULL; return fieldp; } static int fieldbackch (str, out, strip) register char * str; /* First char of backslash sequence */ register char ** out; /* Where to store result */ int strip; /* NZ to convert the sequence */ { register int ch; /* Character being developed */ char * origstr; /* Original value of str */ if (!strip) { *(*out)++ = '\\'; if (*str != 'x' && *str != 'X' && (*str < '0' || *str > '7')) { *(*out)++ = *str; return *str != '\0'; } } switch (*str) { case '\0': *(*out)++ = '\0'; return 0; case 'a': *(*out)++ = '\007'; return 1; case 'b': *(*out)++ = '\b'; return 1; case 'f': *(*out)++ = '\f'; return 1; case 'n': *(*out)++ = '\n'; return 1; case 'r': *(*out)++ = '\r'; return 1; case 'v': *(*out)++ = '\v'; return 1; case 'X': case 'x': /* Hexadecimal sequence */ origstr = str++; ch = 0; if (*str >= '0' && *str <= '9') ch = *str++ - '0'; else if (*str >= 'a' && *str <= 'f') ch = *str++ - 'a' + 0xa; else if (*str >= 'A' && *str <= 'F') ch = *str++ - 'A' + 0xa; if (*str >= '0' && *str <= '9') ch = (ch << 4) | (*str++ - '0'); else if (*str >= 'a' && *str <= 'f') ch = (ch << 4) | (*str++ - 'a' + 0xa); else if (*str >= 'A' && *str <= 'F') ch = (ch << 4) | (*str++ - 'A' + 0xa); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* Octal sequence */ origstr = str; ch = *str++ - '0'; if (*str >= '0' && *str <= '7') ch = (ch << 3) | (*str++ - '0'); if (*str >= '0' && *str <= '7') ch = (ch << 3) | (*str++ - '0'); break; default: *(*out)++ = *str; return 1; } if (strip) { *(*out)++ = ch; return str - origstr; } else { for (ch = 0; origstr < str; ch++) *(*out)++ = *origstr++; return ch; } } int fieldwrite (file, fieldp, delim) FILE * file; /* File to write to */ register field_t * fieldp; /* Field structure to write */ int delim; /* Delimiter to place between fields */ { int error; /* NZ if an error occurs */ register int fieldno; /* Number of field being written */ error = 0; for (fieldno = 0; fieldno < fieldp->nfields; fieldno++) { if (fieldno != 0) error |= putc (delim, file) == EOF; error |= fputs (fieldp->fields[fieldno], file) == EOF; } if (fieldp->hadnl) error |= putc ('\n', file) == EOF; return error; } void fieldfree (fieldp) register field_t * fieldp; /* Field structure to free */ { if (fieldp == NULL) return; if (fieldp->linebuf != NULL) free ((char *) fieldp->linebuf); if (fieldp->fields != NULL) free ((char *) fieldp->fields); free ((char *) fieldp); } ;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- (define-language :grammar '(((S $any) -> (S1 $any)) ((S (Compound $s1 $s2)) -> (S1 $s1) (Conjunction) (S1 $s2)) ((S1 (Statement $v)) -> (NP $subj) (VP $subj $tense $v)) ((S1 (Acknowledge $a)) -> (Acknowledge $a)) ((S1 (Command $v)) -> (VP Self present $v)) ((S1 (Question $v)) -> (Aux $tense) (NP $subj) (VP $subj $tense $v)) ((S1 (Question $v)) -> (Be $tense) (NP $subj) (Be-Arg $subj $tense $v)) ((Be-Arg $subj $tense (Occur $tense (loc $subj $loc))) -> (Loc-Adjunct $tense (loc $subj $loc))) ((VP $subj $tense (Occur $tense $v)) -> (VP1 $subj $tense $v)) ((VP $subj $tense (Occur $tense $v)) -> (Aux $tense)(VP1 $subj present $v)) ((VP1 $subj $tense $v) -> (VP2 $subj $tense $v) (Adjunct? $v)) ((VP2 $subj $tense ($rel $subj $loc)) -> (Verb/in $rel $tense)) ((VP2 $subj $tense ($rel $subj $loc $obj)) -> (Verb/tr $rel $tense) (NP $obj)) ((VP2 $subj $tense ($rel $subj $loc $obj $obj2)) -> (Verb/di $rel $tense) (NP $obj) (NP $obj2)) ((VP2 $subj $tense (loc $subj $loc)) -> (Be $tense) (Loc-Adjunct $tense (loc $subj $loc))) ((NP $n) -> (Pronoun $n)) ((NP $n) -> (Article) (Noun $n)) ((NP $n) -> (Noun $n)) ((NP ($x $y)) -> (Number $x) (Number $y)) ((PP ($prep $n)) -> (Prep $prep) (NP $n)) ((Adjunct? $v) ->) ((Adjunct? $v) -> (Loc-Adjunct $tense $v)) #+Allegro ((Loc-Adjunct $tense ($rel $subj $loc @rest)) -> (PP $loc)) #+Allegro ((Loc-Adjunct $tense ($rel $subj $loc @rest)) -> (Adjunct $loc)) #+Lucid ((Loc-Adjunct $tense ($rel $subj $loc . $rest)) -> (PP $loc)) #+Lucid ((Loc-Adjunct $tense ($rel $subj $loc . $rest)) -> (Adjunct $loc)) ) :lexicon '( ((Acknowledge $a) -> (yes true) (no false) (maybe unknown) (huh unparsed)) ((Adjunct $loc) -> here there (nearby near) near left right up down) ((Article) -> a an the) ((Aux $tense) -> (will future) (did past) (do $finite)) ((Be $tense) -> (am present) (are present) (is present) (be $finite) (was past) (were past)) ((Conjunction) -> and --) ((Noun $n) -> gold Wumpus pit breeze stench glitter nothing) ((Number $n) -> 0 1 2 3 4 5 6 7 8 9) ((Prep $prep) -> in at to near) ((Pronoun $n) -> (you self) (me master) (I master)) ((Verb/in $rel $tense) -> (go move $finite) (went move past) (move move $finite) (move move past) (shoot shoot $finite)) ((Verb/tr $rel $tense) -> (move carry $finite) (moved carry past) (carry carry $finite) (carry carried past) (grab grab $finite) (grab grabbed past) (get grab $finite) (got grab past) (release release $finite) (release release past) (drop release $finite) (dropped release past) (shoot shoot-at $finite) (shot shoot-at past) (kill shoot-at $finite) (killed shoot-at past) (smell perceive $finite) (feel perceive $finite) (felt perceive past)) ((Verb/di $rel $tense) -> (bring bring $finite) (brought bring past) (get bring $finite) (got bring past)) )) (defparameter *sentences* '((I will shoot the wumpus at 4 4) (yes) (You went right -- I will go left) (carry the gold) (yes and no) (did you bring me the gold) (a breeze is here -- I am near 5 3) (a stench is in 3 5) (a pit is nearby) (is the wumpus near) (Did you go to 3 8) (Yes -- Nothing is there) (Shoot -- Shoot left) (Kill the wumpus -- shoot up))) (defun ss (&optional (sentences *sentences*)) "Run some test sentences, and count how many were not parsed." (count-if-not #'(lambda (s) (format t "~2&>>> ~(~{~a ~}~)~%" s) (write (second (parse s)) :pretty t)) *sentences*)) B1 Courier$ $$$$$$$$$ $ $ $ $ $$$$$$$$$$$$$$$$$$$ $!!$""$##$$$$%%$&&$''$(($))$**$++$,,$--$..$//$00$11$22$33$44$55$66$77$88$99$::$;;$<<$==$>>$??$@@$AA$BB$CC$DD$EE$FF$GG$HH$II$JJ$KK$LL$MM$NN$OO$PP$QQ$RR$SS$TT$UU$VV$WW$XX$YY$ZZ$[[$\\$]]$^^$__$``$aa$bb$cc$dd$ee$ff$gg$hh$ii$jj$kk$ll$mm$nn$oo$pp$qq$rr$ss$tt$uu$vv$ww$xx$yy$zz${{$||$}}$~~$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $à$Ġ$Š$Ơ$Ǡ$Ƞ$ɠ$ʠ$ˠ$̠$͠$Π$Ϡ$Р$Ѡ$Ҡ$Ӡ$Ԡ$ՠ$֠$נ$ؠ$٠$ڠ$۠$ܠ$ݠ$ޠ$ߠ$$$$General dd\-mmm\-yyyy hh:mm:ss0#.00\SPSS-[@RESPNUM Q1 Q1A Q1B Q2A Q2B Q2B1 Q3 Q3A Q3A1 Q3A2 Q3A3 Q3B Q3C Q3D Q3E Q4A Q4A1 Q4A2 Q4A3 Q4A4 Q4A5 Q4B A B C D E F G H I J !K "L #M $N %O &P 'Q (R )S *T +U ,V -W .X /Y 0Z 1AA 2AB 3BA 4BB 5CA 6CB 7DA 8DB 9EA :EB ;FA <FB =GA >GB ?HA @HB AIA BIB CJA DJB ETRA FTRB GTRC HTRD ITRE JTRF KTRG LTRH MTRI NTRJ OTRK PTRL QTRM RTRN SQ5 TQ5A UQ5A1 VQ5A2 WQ5A3 XQ5A4 YQ5A5 ZQ6 [Q6A \Q6C ]Q7 ^Q8 _Q8A `Q9 aQ9A bQ9B cQ9C dQ9D eQ9E fQ9F gQ9G hQ10 iQ11 jQ11AkQ11A_1lQ11A_2mQ11A_3nQ11A_4oQ11A_5pQ11A_6qQ11A_7rQ11A_8sQ11A_9tQ11A_10uQ11A_11vQ11A_12wQ11A_13xQ11A_14yQ11A_15zQ11A_16{Q11A_17|Q11A_18}Q11A_19~Q11A_20 Q11A1Q11A1_1Q11A1_2Q11A1_3Q11A1_4Q11A1_5Q11A1_6Q11A1_7Q11A1_8Q11A1_9Q11A1_10Q11A1_11Q11A1_12Q11A1_13Q11A1_14Q11A1_15Q11A1_16Q11A1_17Q11A1_18Q11A1_19Q11A1_20 Q11B Q11B1Q11B_1Q11B_2Q11B_3Q11B_4Q11B_5Q11B_6Q11B_7Q11B_8Q11B_9Q11B_10Q11B_11Q11B_12Q11B_13Q11B_14Q11B_15Q11B_16Q11B_17Q11B_18Q11B_19Q11B_20 Q11B2Q11B2_1Q11B2_2Q11B2_3Q11B2_4Q11B2_5Q11B2_6Q11B2_7Q11B2_8Q11B2_9Q11B2_10Q11B2_11Q11B2_12Q11B2_13Q11B2_14Q11B2_15Q11B2_16Q11B2_17Q11B2_18Q11B2_19Q11B2_20 Q12 Q13 Q13A1 Q13B Q14 Q14A Q15 Q15C Q15C1 Q15C2 Q15C3 Q15C4 Q15C5 Q15C6 Q16 Q17 Q18 Q19 Q20 Q21 Q21A Q21A1 Q21B Q21B1 Q22 Q22A1 Q22B Q22B1CTRLTMNT LANGDIVISIONONEYRUPONEYRDWNFVEYRUPFVEYRDWNINCOMEVAR00001         b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  ^             <                         $       b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                            '                                   K                     '                                           ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              ;                       Y                                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               6                        !        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 0u              b                               b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 0u              (                                 b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          b              <                 '  '    ,        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  k             /                        Z          b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       @                                          b                                  @    #        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       p                                          b              7                   p             b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b                          #                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^# _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 a              K                        -        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 A              6                        [        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b                        )       b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^* _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              )                                b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              /                        $          b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 P              <                       . *      b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _  ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              R                        \        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               /                                                                 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                @              Y                       %         b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              2                        *         b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^* _ `@ a b c d e f g h i j  k l m n o p q r s t u v w x y z { | } ~                                                                               3                         /         b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _  ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 P              H                        & )         b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^) _`O@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              H                                  b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _ `y a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                !A              E                        ^ (       b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              A                        _           b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               8                   b  b   0 2       b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^2 _ `Hq a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              P                                b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `y a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               F                        `          b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j| k l m n o p q r s t u v w x y z { | } ~                                                                 b              0                 |             b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               *                       a         b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                                2                         !1 ! ! ! ! ! ! !b ! !  !  !  !  !  ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !  !! !" !# !$ !% !& !' !( !) !* !+ !, !- !. !/ !0 !1 !2 !3 !4 !5 !6 !7 !8 !9 !: !; !< != !> !? !@ !A !B !C !D !E !F !G !H !I !J !K !L !M !N !O !P !Q !R!S !T !U !V !W !X !Y !Z ![ !\ !] !^ !_ !` !a !b !c !d !e !f !g !h !i !j !k !l !m !n !o !p !q !r !s !t !u !v !w !x !y !z !{ !| !} !~ ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !b ! ! ! ! ! ! ! ! ! ! ! ! ! !: !  ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! "' "# " " " " " " "b "  "  "  "  "  " " " " " " " " " " " " " " " " " " "  "! "" "# "$ "% "& "' "( ") "* "+ ", "- ". "/ "0 "1 "2 "3 "4 "5 "6 "7 "8 "9 ": "; "< "= "> "? "@ "A "B "C "D "E "F "G "H "I "J "K "L "M "N "O "P "Q "R"S "T "U "V "W "X "Y "Z "[ "\ "] "^  "_ "` "a "b "c "d "e "f "g "h "i "j "k "l "m "n "o "p "q "r "s "t "u "v "w "x "y "z "{ "| "} "~ " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "b " " " " " " " " " " " " " "J "  " " " " " " " " " " " " " " " "b " " " " " # # # # # # # # #b #  #  #  #  #  # # # # # # # # # # # # # # # # # # #  #! #" ## #$ #% #& #' #( #) #* #+ #, #- #. #/ #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 #: #; #< #= #> #? #@ #A #B #C #D #E #F #G #H #I #J #K #L #M #N #O #P #Q #R#S #T #U #V #W #X #Y #Z #[ #\ #] #^ #_ #` #a #b #c #d #e #f #g #h #i #j #k #l #m #n #o #p #q #r #s #t #u #v #w #x #y #z #{ #| #} #~ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #' # # # # # # # # # # # # # # # # # # # # #b # # # # # # # # # # # # # #6 #  # # # # # # # # # # # # # # # # # # #' # # $ $ $ $ $ $ $ $ $b $  $  $  $  $  $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $  $! $" $# $$ $% $& $' $( $) $* $+ $, $- $. $/ $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $: $; $< $= $> $? $@ $A $B $C $D $E $F $G $H $I $J $K $L $M $N $O $P $Q $R$S $T $U $V $W $X $Y $Z $[ $\ $] $^ $_ $` $a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z ${ $| $} $~ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $^ $ $ $ $ $ $ $ $ $ $ $ $ $# $  $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % % % % % % %  % %b %  %  %  %  %  % % % % % % % % % % % % % % % % % % %  %! %" %# %$ %% %& %' %( %) %* %+ %, %- %. %/ %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %: %; %< %= %> %? %@ %A %B %C %D %E %F %G %H %I %J %K %L %M %N %O %P %Q %R%S %T %U %V %W %X %Y %Z %[ %\ %] %^ %_ %`P %a %b %c %d %e %f %g %h %i %j  %k %l %m %n %o %p %q %r %s %t %u %v %w %x %y %z %{ %| %} %~ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %P % % % % % % % % % % % % % %= %  % % % % % % % % % % % % % % % %  % % % % % &M &# & & & & & & &b &  &  &  &  &  & & & & & & & & & & & & & & & & & & &  &! &" &# &$ &% && &' &( &) &* &+ &, &- &. &/ &0 &1 &2 &3 &4 &5 &6 &7 &8 &9 &: &; &< &= &> &? &@ &A &B &C &D &E &F &G &H &I &J &K &L &M &N &O &P &Q &R&S &T &U &V &W &X &Y &Z &[ &\ &] &^ &_&`O@ &a &b &c &d &e &f &g &h &i &j &k &l &m &n &o &p &q &r &s &t &u &v &w &x &y &z &{ &| &} &~ & & & & & & & & & & & & & & & & & & & & & & &' & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &b & & & & & & & & & & & & & &I &  & & & & & & & & & & & & & & & &b & &' & & & ' '( ' ' ' ' ' ' 'b '  '  '  '  '  ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '  '! '" '# '$ '% '& '' '( ') '* '+ ', '- '. '/ '0 '1 '2 '3 '4 '5 '6 '7 '8 '9 ': '; '< '= '> '? '@ 'A 'B 'C 'D 'E 'F 'G 'H 'I 'J 'K 'L 'M 'N 'O 'P 'Q 'R'S 'T 'U 'V 'W 'X 'Y 'Z '[ '\ '] '^( '_ '`P 'a 'b 'c 'd 'e 'f 'g 'h 'i 'j 'k 'l 'm 'n 'o 'p 'q 'r 's 't 'u 'v 'w 'x 'y 'z '{ '| '} '~ ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' 'b ' ' ' ' ' ' ' ' ' ' ' ' ' '( '  ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ( ( ( ( ( ( ( (b ( (  (  (  (  (  ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (  (! (" (# ($ (% (& (' (( () (* (+ (, (- (. (/ (0 (1 (2 (3 (4 (5 (6 (7 (8 (9 (: (; (< (= (> (? (@ (A (B (C (D (E (F (G (H (I (J (K (L (M (N (O (P (Q (R(S (T (U (V (W (X (Y (Z ([ (\ (] (^ (_ (` (a (b (c (d (e (f (g (h (i (j (k (l (m (n (o (p (q (r (s (t (u (v (w (x (y (z ({ (| (} (~ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (a ( ( ( ( ( ( ( ( ( ( ( ( ( ($ (  ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( )b )  ) ) ) ) ) ) )b )  )  )  )  )  ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )  )! )" )# )$ )% )& )' )( )) )* )+ ), )- ). )/ )0 )1 )2 )3 )4 )5 )6 )7 )8 )9 ): ); )< )= )> )? )@ )A )B )C )D )E )F )G )H )I )J )K )L )M )N )O )P )Q )R)S )T )U )V )W )X )Y )Z )[ )\ )] )^b )_ )` )a )b )c )d )e )f )g )h )i )j )k )l )m )n )o )p )q )r )s )t )u )v )w )x )y )z ){ )| )} )~ ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )b ) ) ) ) ) ) ) ) ) ) ) ) ) )b )b )  ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) *N * * * * * * * *b *  *  *  *  *  * * * * * * * * * * * * * * * * * * *  *! *" *# *$ *% *& *' *( *) ** *+ *, *- *. */ *0 *1 *2 *3 *4 *5 *6 *7 *8 *9 *: *; *< *= *> *? *@ *A *B *C *D *E *F *G *H *I *J *K *L *M *N *O *P *Q *R*S *T *U *V *W *X *Y *Z *[ *\ *] *^ *_ *` *a *b *c *d *e *f *g *h *i *j *k *l *m *n *o *p *q *r *s *t *u *v *w *x *y *z *{ *| *} *~ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *b * * * * * * * * * * * * * *H *  * * * * * * * * * * * * * * * * *b * *b * * + + + + + + + +b + +  +  +  +  +  + + + + + + + + + + + + + + + + + + +  +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +: +; +< += +> +? +@ +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R+S +T +U +V +W +X +Y +Z +[ +\ +] +^ +_ +` +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +{ +| +} +~ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +b + + + + + + + + + + + + + +b +  +  + + + + + + + + + + + + + + + +a + + + + , ,# , , , , , , ,b ,  ,  ,  ,  ,  , , , , , , , , , , , , , , , , , , ,  ,! ," ,# ,$ ,% ,& ,' ,( ,) ,* ,+ ,, ,- ,. ,/ ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,: ,; ,< ,= ,> ,? ,@ ,A ,B ,C ,D ,E ,F ,G ,H ,I ,J ,K ,L ,M ,N ,O ,P ,Q ,R,S ,T ,U ,V ,W ,X ,Y ,Z ,[ ,\ ,] ,^# ,_ ,` ,a ,b ,c ,d ,e ,f ,g ,h ,i ,j ,k ,l ,m ,n ,o ,p ,q ,r ,s ,t ,u ,v ,w ,x ,y ,z ,{ ,| ,} ,~ , , , , , , , , , , , , , , , , , , , , , , ,  , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,b , , , , , , , , , , , , , ,E ,  , , , , , , , , , , , , , , , , , ,  , , , -c -( - - - - - - -b -  -  -  -  -  - - - - - - - - - - - - - - - - - - -  -! -" -# -$ -% -& -' -( -) -* -+ -, -- -. -/ -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -: -; -< -= -> -? -@ -A -B -C -D -E -F -G -H -I -J -K -L -M -N -O -P -Q -R-S -T -U -V -W -X -Y -Z -[ -\ -] -^  -_ -` -a -b -c -d -e -f -g -h -i -j -k -l -m -n -o -p -q -r -s -t -u -v -w -x -y -z -{ -| -} -~ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0u - - - - - - - - - - - - - -, - - - - - - - - - - - - - - - - - - - - - - . . . . . . . . .b .  .  .  .  .  . . . . . . . . . . . . . . . . . . .  .! ." .# .$ .% .& .' .( .) .* .+ ., .- .. ./ .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .: .; .< .= .> .? .@ .A .B .C .D .E .F .G .H .I .J .K .L .M .N .O .P .Q .R.S .T .U .V .W .X .Y .Z .[ .\ .] .^ ._ .` .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .p .q .r .s .t .u .v .w .x .y .z .{ .| .} .~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .b . . . . . . . . . . . . . .A . . . . . . . . . . . . . . . . . . . . . . / /# / / / / / / / / b /  /  /  /  / / / / / / / / / / / / / / / / / / /  /! /" /# /$ /% /& /' /( /) /* /+ /, /- /. // /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /: /; /< /= /> /? /@ /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R/S /T /U /V /W /X /Y /Z /[ /\ /] /^ /_ /` /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /{ /| /} /~ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /b / / / / / / / / / / / / / /K /  / / / / / / / / / / / / / / / / / / / / / 0 0( 0 0 0 0 0 0 0 0 b 0  0  0  0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0! 0" 0# 0$ 0% 0& 0' 0( 0) 0* 0+ 0, 0- 0. 0/ 00 01 02 03 04 05 06 07 08 09 0: 0; 0< 0= 0> 0? 0@ 0A 0B 0C 0D 0E 0F 0G 0H 0I 0J 0K 0L 0M 0N 0O 0P 0Q 0R0S 0T 0U 0V 0W 0X 0Y 0Z 0[ 0\ 0] 0^  0_ 0`} 0a 0b 0c 0d 0e 0f 0g 0h 0i 0j 0k 0l 0m 0n 0o 0p 0q 0r 0s 0t 0u 0v 0w 0x 0y 0z 0{ 0| 0} 0~ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0@ 0 0 0 0 0 0 0 0 0 0 0 0 0 0? 0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1  1 1 1 1 1 1 1b 1  1  1  1  1  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  1! 1" 1# 1$ 1% 1& 1' 1( 1) 1* 1+ 1, 1- 1. 1/ 10 11 12 13 14 15 16 17 18 19 1: 1; 1< 1= 1> 1? 1@ 1A 1B 1C 1D 1E 1F 1G 1H 1I 1J 1K 1L 1M 1N 1O 1P 1Q 1R1S 1T 1U 1V 1W 1X 1Y 1Z 1[ 1\ 1] 1^  1_ 1`@ 1a 1b 1c 1d 1e 1f 1g 1h 1i 1j 1k 1l 1m 1n 1o 1p 1q 1r 1s 1t 1u 1v 1w 1x 1y 1z 1{ 1| 1} 1~ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1@ 1 1 1 1 1 1 1 1 1 1 1 1 1 13 1  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2P 2# 2 2 2 2 2 2 2b 2  2  2  2  2  2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2  2! 2" 2# 2$ 2% 2& 2' 2( 2) 2* 2+ 2, 2- 2. 2/ 20 21 22 23 24 25 26 27 28 29 2: 2; 2< 2= 2> 2? 2@ 2A 2B 2C 2D 2E 2F 2G 2H 2I 2J 2K 2L 2M 2N 2O 2P 2Q 2R2S 2T 2U 2V 2W 2X 2Y 2Z 2[ 2\ 2] 2^# 2_ 2` 2a 2b 2c 2d 2e 2f 2g 2h 2i 2j 2k 2l 2m 2n 2o 2p 2q 2r 2s 2t 2u 2v 2w 2x 2y 2z 2{ 2| 2} 2~ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2b 2 2 2 2 2 2 2 2 2 2 2 2 2 2V 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2b 2 2b 2 2 32 3 3 3 3 3 3 3 3 3  3  3  3  3  3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3  3! 3" 3# 3$ 3% 3& 3' 3( 3) 3* 3+ 3, 3- 3. 3/ 30 31 32 33 34 35 36 37 38 39 3: 3; 3< 3= 3> 3? 3@ 3A 3B 3C 3D 3E 3F 3G 3H 3I 3J 3K 3L 3M 3N 3O 3P 3Q 3R3S 3T 3U 3V 3W 3X 3Y 3Z 3[ 3\ 3] 3^ 3_3`@ 3a 3b 3c 3d 3e 3f 3g 3h 3i 3j 3k 3l 3m 3n 3o 3p 3q 3r 3s 3t 3u 3v 3w 3x 3y 3z 3{ 3| 3} 3~ 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 33@ 3 3 3 3 3 3 3 3 3 3 3 3 3 3= 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4d 4! 4 4 4 4 4 4 4b 4  4  4  4  4  4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4  4! 4" 4# 4$ 4% 4& 4' 4( 4) 4* 4+ 4, 4- 4. 4/ 40 41 42 43 44 45 46 47 48 49 4: 4; 4< 4= 4> 4? 4@ 4A 4B 4C 4D 4E 4F 4G 4H 4I 4J 4K 4L 4M 4N 4O 4P 4Q 4R4S 4T 4U 4V 4W 4X 4Y 4Z 4[ 4\ 4] 4^! 4_ 4` 4a 4b 4c 4d 4e 4f 4g 4h 4i 4j 4k 4l 4m 4n 4o 4p 4q 4r 4s 4t 4u 4v 4w 4x 4y 4z 4{ 4| 4} 4~ 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4? 4  4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 b 5  5  5  5  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5  5! 5" 5# 5$ 5% 5& 5' 5( 5) 5* 5+ 5, 5- 5. 5/ 50 51 52 53 54 55 56 57 58 59 5: 5; 5< 5= 5> 5? 5@ 5A 5B 5C 5D 5E 5F 5G 5H 5I 5J 5K 5L 5M 5N 5O 5P 5Q 5R5S 5T 5U 5V 5W 5X 5Y 5Z 5[ 5\ 5] 5^ 5_ 5` 5a 5b 5c 5d 5e 5f 5g 5h 5i 5j' 5k 5l 5m 5n 5o 5p 5q 5r 5s 5t 5u 5v 5w 5x 5y 5z 5{ 5| 5} 5~ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5' 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5: 5  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5' 5 5' 5 5 5 6" 6( 6 6 6 6 6 6 6b 6  6  6  6  6  6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6  6! 6" 6# 6$ 6% 6& 6' 6( 6) 6* 6+ 6, 6- 6. 6/ 60 61 62 63 64 65 66 67 68 69 6: 6; 6< 6= 6> 6? 6@ 6A 6B 6C 6D 6E 6F 6G 6H 6I 6J 6K 6L 6M 6N 6O 6P 6Q 6R6S 6T 6U 6V 6W 6X 6Y 6Z 6[ 6\ 6] 6^( 6_ 6` 6a 6b 6c 6d 6e 6f 6g 6h 6i 6j 6k 6l 6m 6n 6o 6p 6q 6r 6s 6t 6u 6v 6w 6x 6y 6z 6{ 6| 6} 6~ 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6b 6 6 6 6 6 6 6 6 6 6 6 6 6 6b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7b 7  7  7  7  7  7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7  7! 7" 7# 7$ 7% 7& 7' 7( 7) 7* 7+ 7, 7- 7. 7/ 70 71 72 73 74 75 76 77 78 79 7: 7; 7< 7= 7> 7? 7@ 7A 7B 7C 7D 7E 7F 7G 7H 7I 7J 7K 7L 7M 7N 7O 7P 7Q 7R7S 7T 7U 7V 7W 7X 7Y 7Z 7[ 7\ 7] 7^ 7_ 7` 7a 7b 7c 7d 7e 7f 7g 7h 7i 7j 7k 7l 7m 7n 7o 7p 7q 7r 7s 7t 7u 7v 7w 7x 7y 7z 7{ 7| 7} 7~ 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7@ 7 7 7 7 7 7 7 7 7 7 7 7 7 7L 7  7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8$ 8 8 8 8 8 8b 8 8  8  8  8  8  8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8  8! 8" 8# 8$ 8% 8& 8' 8( 8) 8* 8+ 8, 8- 8. 8/ 80 81 82 83 84 85 86 87 88 89 8: 8; 8< 8= 8> 8? 8@ 8A 8B 8C 8D 8E 8F 8G 8H 8I 8J 8K 8L 8M 8N 8O 8P 8Q 8R8S 8T 8U 8V 8W 8X 8Y 8Z 8[ 8\ 8] 8^$ 8_  8`P 8a 8b 8c 8d 8e 8f 8g 8h 8i 8j  8k 8l 8m 8n 8o 8p 8q 8r 8s 8t 8u 8v 8w 8x 8y 8z 8{ 8| 8} 8~ 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8' 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8b 8 8 8 8 8 8 8 8 8 8 8 8 8 8? 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8  8 8' 8 8 8 9 9 9 9 9 9  9 9 9 9 b 9  9  9  9  9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9  9! 9" 9# 9$ 9% 9& 9' 9( 9) 9* 9+ 9, 9- 9. 9/ 90 91 92 93 94 95 96 97 98 99 9: 9; 9< 9= 9> 9? 9@ 9A 9B 9C 9D 9E 9F 9G 9H 9I 9J 9K 9L 9M 9N 9O 9P 9Q 9R9S 9T 9U 9V 9W 9X 9Y 9Z 9[ 9\ 9] 9^ 9_ 9` 9a 9b 9c 9d 9e 9f 9g 9h 9i 9j' 9k 9l 9m 9n 9o 9p 9q 9r 9s 9t 9u 9v 9w 9x 9y 9z 9{ 9| 9} 9~ 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9' 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9b 9 9 9 9 9 9 9 9 9 9 9 9 9 91 9  9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9' 9 9' 9 9 9 :3 : : : : : : : : : b :  :  :  :  : : : : : : : : : : : : : : : : : : :  :! :" :# :$ :% :& :' :( :) :* :+ :, :- :. :/ :0 :1 :2 :3 :4 :5 :6 :7 :8 :9 :: :; :< := :> :? :@ :A :B :C :D :E :F :G :H :I :J :K :L :M :N :O :P :Q :R:S :T :U :V :W :X :Y :Z :[ :\ :] :^ :_ :`@ :a :b :c :d :e :f :g :h :i :j :k :l :m :n :o :p :q :r :s :t :u :v :w :x :y :z :{ :| :} :~ : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :@ : : : : : : : : : : : : : :E : : : : : : : : : : : : : : : :  : : : : : : ;4 ; ; ; ; ; ; ;b ; ;  ;  ;  ;  ;  ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;  ;! ;" ;# ;$ ;% ;& ;' ;( ;) ;* ;+ ;, ;- ;. ;/ ;0 ;1 ;2 ;3 ;4 ;5 ;6 ;7 ;8 ;9 ;: ;; ;< ;= ;> ;? ;@ ;A ;B ;C ;D ;E ;F ;G ;H ;I ;J ;K ;L ;M ;N ;O ;P ;Q ;R;S ;T ;U ;V ;W ;X ;Y ;Z ;[ ;\ ;] ;^ ;_;`@ ;a ;b ;c ;d ;e ;f ;g ;h ;i ;j ;k ;l ;m ;n ;o ;p ;q ;r ;s ;t ;u ;v ;w ;x ;y ;z ;{ ;| ;} ;~ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;b ; ; ; ; ; ; ; ; ; ; ; ; ; ;9 ;  ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; < <- < < < < < < <b <  <  <  <  <  < < < < < < < < < < < < < < < < < < <  <! <" <# <$ <% <& <' <( <) <* <+ <, <- <. </ <0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <: <; << <= <> <? <@ <A <B <C <D <E <F <G <H <I <J <K <L <M <N <O <P <Q <R<S <T <U <V <W <X <Y <Z <[ <\ <] <^ <_ <`P <a <b <c <d <e <f <g <h <i <j <k <l <m <n <o <p <q <r <s <t <u <v <w <x <y <z <{ <| <} <~ < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <b < < < < < < < < < < < < < <J < < < < < < < < < < < < < < < < <b < < < < < =e =( = = = = = = =b =  =  =  =  =  = = = = = = = = = = = = = = = = = = =  =! =" =# =$ =% =& =' =( =) =* =+ =, =- =. =/ =0 =1 =2 =3 =4 =5 =6 =7 =8 =9 =: =; =< == => =? =@ =A =B =C =D =E =F =G =H =I =J =K =L =M =N =O =P =Q =R=S =T =U =V =W =X =Y =Z =[ =\ =] =^( =_ =` =a =b =c =d =e =f =g =h =i =j =k =l =m =n =o =p =q =r =s =t =u =v =w =x =y =z ={ =| =} =~ = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =b = = = = = = = = = = = = = =; =  = = =  = = = = = = = = = = = = = = = = = = > > > > > >  > >b > >  >  >  >  >  > > > > > > > > > > > > > > > > > > >  >! >" ># >$ >% >& >' >( >) >* >+ >, >- >. >/ >0 >1 >2 >3 >4 >5 >6 >7 >8 >9 >: >; >< >= >> >? >@ >A >B >C >D >E >F >G >H >I >J >K >L >M >N >O >P >Q >R>S >T >U >V >W >X >Y >Z >[ >\ >] >^ >_ >` >a >b >c >d >e >f >g >h >i >j' >k >l >m >n >o >p >q >r >s >t >u >v >w >x >y >z >{ >| >} >~ > > > > > > > > > > > > > > > > > > > > > > >' > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >b > > > > > > > > > > > > > >, > > > > > > > > > > > > > > > > >' > >' > > > ? ?  ? ? ? ? ? ? ?b ?  ?  ?  ?  ?  ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ?! ?" ?# ?$ ?% ?& ?' ?( ?) ?* ?+ ?, ?- ?. ?/ ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?: ?; ?< ?= ?> ?? ?@ ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R?S ?T ?U ?V ?W ?X ?Y ?Z ?[ ?\ ?] ?^  ?_ ?` ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z ?{ ?| ?} ?~ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?b ? ? ? ? ? ? ? ? ? ? ? ? ? ?b ?  ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @ @ @ @ @ @ @ @ @b @  @  @  @  @  @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @  @! @" @# @$ @% @& @' @( @) @* @+ @, @- @. @/ @0 @1 @2 @3 @4 @5 @6 @7 @8 @9 @: @; @< @= @> @? @@ @A @B @C @D @E @F @G @H @I @J @K @L @M @N @O @P @Q @R@S @T @U @V @W @X @Y @Z @[ @\ @] @^ @_ @`` @a @b @c @d @e @f @g @h @i @j @k @l @m @n @o @p @q @r @s @t @u @v @w @x @y @z @{ @| @} @~ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @' @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @b @ @ @ @ @ @ @ @ @ @ @ @ @ @8 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @' @ @ A A A A A A  A A Ab A  A  A  A  A  A A A A A A A A A A A A A A A A A A A  A! A" A# A$ A% A& A' A( A) A* A+ A, A- A. A/ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A: A; A< A= A> A? A@ AA AB AC AD AE AF AG AH AI AJ AK AL AM AN AO AP AQ ARAS AT AU AV AW AX AY AZ A[ A\ A] A^ A_ A`p Aa Ab Ac Ad Ae Af Ag Ah Ai Aj Ak Al Am An Ao Ap Aq Ar As At Au Av Aw Ax Ay Az A{ A| A} A~ A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A Ab A A A A A A A A A A A A A A> A A A A A A A A A A A A A A A A A A A A A A B B# B B B B B B B B b B  B  B  B  B B B B B B B B B B B B B B B B B B B  B! B" B# B$ B% B& B' B( B) B* B+ B, B- B. B/ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B: B; B< B= B> B? B@ BA BB BC BD BE BF BG BH BI BJ BK BL BM BN BO BP BQ BRBS BT BU BV BW BX BY BZ B[ B\ B] B^ B_ B`0u Ba Bb Bc Bd Be Bf Bg Bh Bi Bj Bk Bl Bm Bn Bo Bp Bq Br Bs Bt Bu Bv Bw Bx By Bz B{ B| B} B~ B B B B B B B B B B B B B B B B B B B B B B B  B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B N B B B B B B B B B B B B B B< B B B B B B B B B B B B B B B B B B B  B B B Cf C C C C C C C Cb C  C  C  C  C  C C C C C C C C C C C C C C C C C C C  C! C" C# C$ C% C& C' C( C) C* C+ C, C- C. C/ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C: C; C< C= C> C? C@ CA CB CC CD CE CF CG CH CI CJ CK CL CM CN CO CP CQ CRCS CT CU CV CW CX CY CZ C[ C\ C] C^ C_ C` Ca Cb Cc Cd Ce Cf Cg Ch Ci Cj Ck Cl Cm Cn Co Cp Cq Cr Cs Ct Cu Cv Cw Cx Cy Cz C{ C| C} C~ C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C Cb C C C C C C C C C C C C C C C  C C C C C C C C C C C C C C C C C C C C C D D D D D D  D D Db D  D  D  D  D  D D D D D D D D D D D D D D D D D D D  D! D" D# D$ D% D& D' D( D) D* D+ D, D- D. D/ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 D: D; D< D= D> D? D@ DA DB DC DD DE DF DG DH DI DJ DK DL DM DN DO DP DQ DRDS DT DU DV DW DX DY DZ D[ D\ D] D^ D_D`O@ Da Db Dc Dd De Df Dg Dh Di Dj Dk Dl Dm Dn Do Dp Dq Dr Ds Dt Du Dv Dw Dx Dy Dz D{ D| D} D~ D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D Db D D D D D D D D D D D D D D- D  D D D D D D D D D D D D D D D D D D D D D EQ E E E E E E E E E b E  E  E  E  E E E E E E E E E E E E E E E E E E E  E! E" E# E$ E% E& E' E( E) E* E+ E, E- E. E/ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 E: E; E< E= E> E? E@ EA EB EC ED EE EF EG EH EI EJ EK EL EM EN EO EP EQ ERES ET EU EV EW EX EY EZ E[ E\ E] E^ E_ E`p Ea Eb Ec Ed Ee Ef Eg Eh Ei Ej Ek El Em En Eo Ep Eq Er Es Et Eu Ev Ew Ex Ey Ez E{ E| E} E~ E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E0u E E E E E E E E E E E E E E9 E  E E E E E E E E E E E E E E E E E E E E E F F F F F F F F Fb F  F  F  F  F  F F F F F F F F F F F F F F F F F F F  F! F" F# F$ F% F& F' F( F) F* F+ F, F- F. F/ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F: F; F< F= F> F? F@ FA FB FC FD FE FF FG FH FI FJ FK FL FM FN FO FP FQ FRFS FT FU FV FW FX FY FZ F[ F\ F] F^ F_ F` Fa Fb Fc Fd Fe Ff Fg Fh Fi Fj Fk Fl Fm Fn Fo Fp Fq Fr Fs Ft Fu Fv Fw Fx Fy Fz F{ F| F} F~ F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F Fb F F F F F F F F F F F F F F@ F F F F F F F F F F F F F F F F F F F F F F G  G G G G G G  G Gb G  G  G  G  G  G G G G G G G G G G G G G G G G G G G  G! G" G# G$ G% G& G' G( G) G* G+ G, G- G. G/ G0 G1 G2 G3 G4 G5 G6 G7 G8 G9 G: G; G< G= G> G? G@ GA GB GC GD GE GF GG GH GI GJ GK GL GM GN GO GP GQ GRGS GT GU GV GW GX GY GZ G[ G\ G] G^ G_ G`h Ga Gb Gc Gd Ge Gf Gg Gh Gi Gj Gk Gl Gm Gn Go Gp Gq Gr Gs Gt Gu Gv Gw Gx Gy Gz G{ G| G} G~ G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G Gb G G G G G G G G G G G G G G% G  G G G G G G G G G G G G G G G G G G G G G H H H H H H H Hb H H  H  H  H  H  H H H H H H H H H H H H H H H H H H H  H! H" H# H$ H% H& H' H( H) H* H+ H, H- H. H/ H0 H1 H2 H3 H4 H5 H6 H7 H8 H9 H: H; H< H= H> H? H@ HA HB HC HD HE HF HG HH HI HJ HK HL HM HN HO HP HQ HRHS HT HU HV HW HX HY HZ H[ H\ H] H^ H_ H`P Ha Hb Hc Hd He Hf Hg Hh Hi Hj Hk Hl Hm Hn Ho Hp Hq Hr Hs Ht Hu Hv Hw Hx Hy Hz H{ H| H} H~ H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H Hb H H H H H H H H H H H H H HD H H H H H H H H H H H H H H H H H H H H H H I I I I I I  I Ib I I  I  I  I  I  I I I I I I I I I I I I I I I I I I I  I! I" I# I$ I% I& I' I( I) I* I+ I, I- I. I/ I0 I1 I2 I3 I4 I5 I6 I7 I8 I9 I: I; I< I= I> I? I@ IA IB IC ID IE IF IG IH II IJ IK IL IM IN IO IP IQ IRIS IT IU IV IW IX IY IZ I[ I\ I] I^ I_ I`ȯ Ia Ib Ic Id Ie If Ig Ih Ii Ij Ik Il Im In Io Ip Iq Ir Is It Iu Iv Iw Ix Iy Iz I{ I| I} I~ I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I Ib I I I I I I I I I I I I I IH I I I I I I I I I I I I I I I I I I I Ib I I J5 J J J J J J  J Jb J  J  J  J  J  J J J J J J J J J J J J J J J J J J J  J! J" J# J$ J% J& J' J( J) J* J+ J, J- J. J/ J0 J1 J2 J3 J4 J5 J6 J7 J8 J9 J: J; J< J= J> J? J@ JA JB JC JD JE JF JG JH JI JJ JK JL JM JN JO JP JQ JRJS JT JU JV JW JX JY JZ J[ J\ J] J^ J_ J` Ja Jb Jc Jd Je Jf Jg Jh Ji Jj Jk Jl Jm Jn Jo Jp Jq Jr Js Jt Ju Jv Jw Jx Jy Jz J{ J| J} J~ J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J Jb J J J J J J J J J J J J J J7 J J J J J J J J J J J J J J J J J J J J J J Kg K K K K K K K Kb K  K  K  K  K  K K K K K K K K K K K K K K K K K K K  K! K" K# K$ K% K& K' K( K) K* K+ K, K- K. K/ K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 K: K; K< K= K> K? K@ KA KB KC KD KE KF KG KH KI KJ KK KL KM KN KO KP KQ KRKS KT KU KV KW KX KY KZ K[ K\ K] K^ K_K`@ Ka Kb Kc Kd Ke Kf Kg Kh Ki Kj Kk Kl Km Kn Ko Kp Kq Kr Ks Kt Ku Kv Kw Kx Ky Kz K{ K| K} K~ K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K. K K K K K K K K K K K K K K K K K K K K K K L L L L L L L L L L  L  L  L  L  L L L L L L L L L L L L L L L L L L L  L! L" L# L$ L% L& L' L( L) L* L+ L, L- L. L/ L0 L1 L2 L3 L4 L5 L6 L7 L8 L9 L: L; L< L= L> L? L@ LA LB LC LD LE LF LG LH LI LJ LK LL LM LN LO LP LQ LRLS LT LU LV LW LX LY LZ L[ L\ L] L^ L_ L` La Lb Lc Ld Le Lf Lg Lh Li Lj Lk Ll Lm Ln Lo Lp Lq Lr Ls Lt Lu Lv Lw Lx Ly Lz L{ L| L} L~ L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L' L L L L L L L L L L L L L L L L L L L L L* L L L L L L L L L L L L L L L  L L L L L L L L L L L L L L L L L L L' L L MR M M M M M M Mb M M  M  M  M  M  M M M M M M M M M M M M M M M M M M M  M! M" M# M$ M% M& M' M( M) M* M+ M, M- M. M/ M0 M1 M2 M3 M4 M5 M6 M7 M8 M9 M: M; M< M= M> M? M@ MA MB MC MD ME MF MG MH MI MJ MK ML MM MN MO MP MQ MRMS MT MU MV MW MX MY MZ M[ M\ M] M^( M_ M` Ma Mb Mc Md Me Mf Mg Mh Mi Mj Mk Ml Mm Mn Mo Mp Mq Mr Ms Mt Mu Mv Mw Mx My Mz M{ M| M} M~ M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M Mb M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M Mb M Mb M M M N N  N  N N N N  N Nb N  N  N  N  N  N N N N N N N N N N N N N N N N N N N  N! N" N# N$ N% N& N' N( N) N* N+ N, N- N. N/ N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 N: N; N< N= N> N? N@ NA NB NC ND NE NF NG NH NI NJ NK NL NM NN NO NP NQ NRNS NT NU NV NW NX NY NZ N[ N\ N] N^! N_ N` Na Nb Nc Nd Ne Nf Ng Nh Ni Nj Nk Nl Nm Nn No Np Nq Nr Ns Nt Nu Nv Nw Nx Ny Nz N{ N| N} N~ N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N Nb N N N N N N N N N N N N N NP N N N N N N N N N N N N N N N N N N N N N N O O O O O O O O O O b O  O  O  O  O O O O O O O O O O O O O O O O O O O  O! O" O# O$ O% O& O' O( O) O* O+ O, O- O. O/ O0 O1 O2 O3 O4 O5 O6 O7 O8 O9 O: O; O< O= O> O? O@ OA OB OC OD OE OF OG OH OI OJ OK OL OM ON OO OP OQ OROS OT OU OV OW OX OY OZ O[ O\ O] O^ O_ O` Oa Ob Oc Od Oe Of Og Oh Oi Oj Ok Ol Om On Oo Op Oq Or Os Ot Ou Ov Ow Ox Oy Oz O{ O| O} O~ O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O2 O O O O O O O O O O O O O O O O O O O O O O P P P P P P P Pb P P  P  P  P  P  P P P P P P P P P P P P P P P P P P P  P! P" P# P$ P% P& P' P( P) P* P+ P, P- P. P/ P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P: P; P< P= P> P? P@ PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PRPS PT PU PV PW PX PY PZ P[ P\ P] P^ P_ P` Pa Pb Pc Pd Pe Pf Pg Ph Pi Pj Pk Pl Pm Pn Po Pp Pq Pr Ps Pt Pu Pv Pw Px Py Pz P{ P| P} P~ P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P Pb P P P P P P P P P P P P P P? P  P P P P P P P P P P P P P P P P P P P P P Q Q# Q Q! Q Q Q  Q Qb Q  Q  Q  Q  Q  Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q  Q! Q" Q# Q$ Q% Q& Q' Q( Q) Q* Q+ Q, Q- Q. Q/ Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q: Q; Q< Q= Q> Q? Q@ QA QB QC QD QE QF QG QH QI QJ QK QL QM QN QO QP QQ QRQS QT QU QV QW QX QY QZ Q[ Q\ Q] Q^# Q_ Q` Qa Qb Qc Qd Qe Qf Qg Qh Qi Qj Qk Ql Qm Qn Qo Qp Qq Qr Qs Qt Qu Qv Qw Qx Qy Qz Q{ Q| Q} Q~ Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Qȯ Q Q Q Q Q Q Q Q Q Q Q Q Q QG Q  Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q R( R( R R R R R R Rb R  R  R  R  R  R R R R R R R R R R R R R R R R R R R  R! R" R# R$ R% R& R' R( R) R* R+ R, R- R. R/ R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R: R; R< R= R> R? R@ RA RB RC RD RE RF RG RH RI RJ RK RL RM RN RO RP RQ RRRS RT RU RV RW RX RY RZ R[ R\ R] R^  R_  R`ȯ Ra Rb Rc Rd Re Rf Rg Rh Ri Rj Rk Rl Rm Rn Ro Rp Rq Rr Rs Rt Ru Rv Rw Rx Ry Rz R{ R| R} R~ R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R Rb R R R R R R R R R R R R R RG R  R R R R R R R R R R R R R R R R R R R R R S S S S S S S S S S  S  S  S  S  S S S S S S S S S S S S S S S S S S S  S! S" S# S$ S% S& S' S( S) S* S+ S, S- S. S/ S0 S1 S2 S3 S4 S5 S6 S7 S8 S9 S: S; S< S= S> S? S@ SA SB SC SD SE SF SG SH SI SJ SK SL SM SN SO SP SQ SRSS ST SU SV SW SX SY SZ S[ S\ S] S^ S_ S` Sa Sb Sc Sd Se Sf Sg Sh Si Sj Sk Sl Sm Sn So Sp Sq Sr Ss St Su Sv Sw Sx Sy Sz S{ S| S} S~ S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S? S S S S S S S S S S S S S S  S S S S S S S S S S S S S S S S S S S S S T6 T% T T T T T T Tb T  T  T  T  T  T T T T T T T T T T T T T T T T T T T  T! T" T# T$ T% T& T' T( T) T* T+ T, T- T. T/ T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T: T; T< T= T> T? T@ TA TB TC TD TE TF TG TH TI TJ TK TL TM TN TO TP TQ TRTS TT TU TV TW TX TY TZ T[ T\ T] T^ T_ T` Ta Tb Tc Td Te Tf Tg Th Ti Tj Tk Tl Tm Tn To Tp Tq Tr Ts Tt Tu Tv Tw Tx Ty Tz T{ T| T} T~ T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T` T T T T T T T T T T T T T TA T  T T T T T T T T T T T T T T T T T T T T T U U2 U U U U U U Ub U  U  U  U  U  U U U U U U U U U U U U U U U U U U U  U! U" U# U$ U% U& U' U( U) U* U+ U, U- U. U/ U0 U1 U2 U3 U4 U5 U6 U7 U8 U9 U: U; U< U= U> U? U@ UA UB UC UD UE UF UG UH UI UJ UK UL UM UN UO UP UQ URUS UT UU UV UW UX UY UZ U[ U\ U] U^2 U_ U` Ua Ub Uc Ud Ue Uf Ug Uh Ui Uj Uk Ul Um Un Uo Up Uq Ur Us Ut Uu Uv Uw Ux Uy Uz U{ U| U} U~ U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U Ub U U U U U U U U U U U U U UD U U U U U U U U U U U U U U U U U Ub U Ub U U VS V# V V V V V V Vb V  V  V  V  V  V V V V V V V V V V V V V V V V V V V  V! V" V# V$ V% V& V' V( V) V* V+ V, V- V. V/ V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V: V; V< V= V> V? V@ VA VB VC VD VE VF VG VH VI VJ VK VL VM VN VO VP VQ VRVS VT VU VV VW VX VY VZ V[ V\ V] V^  V_ V`( Va Vb Vc Vd Ve Vf Vg Vh Vi Vj Vk Vl Vm Vn Vo Vp Vq Vr Vs Vt Vu Vv Vw Vx Vy Vz V{ V| V} V~ V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V VE V  V V V V V V V V V V V V V V V V V V V V V W  W W W W W  W W Wb W  W  W  W  W  W W W W W W W W W W W W W W W W W W W  W! W" W# W$ W% W& W' W( W) W* W+ W, W- W. W/ W0 W1 W2 W3 W4 W5 W6 W7 W8 W9 W: W; W< W= W> W? W@ WA WB WC WD WE WF WG WH WI WJ WK WL WM WN WO WP WQ WRWS WT WU WV WW WX WY WZ W[ W\ W] W^ W_ W` Wa Wb Wc Wd We Wf Wg Wh Wi Wj Wk Wl Wm Wn Wo Wp Wq Wr Ws Wt Wu Wv Ww Wx Wy Wz W{ W| W} W~ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W WWOA W W W W W W W W W W W W W W5 W W W W W W W W W W W W W W W W W W W W W W X) X( X X X X  X X X X  X  X  X  X  X X X X X X X X X X X X X X X X X X X  X! X" X# X$ X% X& X' X( X) X* X+ X, X- X. X/ X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X: X; X< X= X> X? X@ XA XB XC XD XE XF XG XH XI XJ XK XL XM XN XO XP XQ XRXS XT XU XV XW XX XY XZ X[ X\ X] X^( X_ X` Xa Xb Xc Xd Xe Xf Xg Xh Xi Xj Xk Xl Xm Xn Xo Xp Xq Xr Xs Xt Xu Xv Xw Xx Xy Xz X{ X| X} X~ X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X Xb X X X X X X X X X X X X X XH X  X X X X X X X X X X X X X X X X X X X X X Y Y' Y Y Y Y Y Y Y Y b Y  Y  Y  Y  Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y  Y! Y" Y# Y$ Y% Y& Y' Y( Y) Y* Y+ Y, Y- Y. Y/ Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Y9 Y: Y; Y< Y= Y> Y? Y@ YA YB YC YD YE YF YG YH YI YJ YK YL YM YN YO YP YQ YRYS YT YU YV YW YX YY YZ Y[ Y\ Y] Y^/ Y_ Y` Ya Yb Yc Yd Ye Yf Yg Yh Yi Yj Yk Yl Ym Yn Yo Yp Yq Yr Ys Yt Yu Yv Yw Yx Yy Yz Y{ Y| Y} Y~ Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Yb Y Y Y Y Y Y Y Y Y Y Y Y Y YH Y  Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Z7 Z Z Z Z Z Z Z Zb Z  Z  Z  Z  Z  Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z  Z! Z" Z# Z$ Z% Z& Z' Z( Z) Z* Z+ Z, Z- Z. Z/ Z0 Z1 Z2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z: Z; Z< Z= Z> Z? Z@ ZA ZB ZC ZD ZE ZF ZG ZH ZI ZJ ZK ZL ZM ZN ZO ZP ZQ ZRZS ZT ZU ZV ZW ZX ZY ZZ Z[ Z\ Z] Z^ Z_ Z` Za Zb Zc Zd Ze Zf Zg Zh Zi Zj Zk Zl Zm Zn Zo Zp Zq Zr Zs Zt Zu Zv Zw Zx Zy Zz Z{ Z| Z} Z~ Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Zb Z Z Z Z Z Z Z Z Z Z Z Z Z ZK Z  Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z [ [ [ [ [ [ [ [b [ [  [  [  [  [  [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [  [! [" [# [$ [% [& [' [( [) [* [+ [, [- [. [/ [0 [1 [2 [3 [4 [5 [6 [7 [8 [9 [: [; [< [= [> [? [@ [A [B [C [D [E [F [G [H [I [J [K [L [M [N [O [P [Q [R[S [T [U [V [W [X [Y [Z [[ [\ [] [^b [_ [` [a [b [c [d [e [f [g [h [i [j [k [l [m [n [o [p [q [r [s [t [u [v [w [x [y [z [{ [| [} [~ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [0u [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ \  \ \ \ \ \ \ \b \ \  \  \  \  \  \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \  \! \" \# \$ \% \& \' \( \) \* \+ \, \- \. \/ \0 \1 \2 \3 \4 \5 \6 \7 \8 \9 \: \; \< \= \> \? \@ \A \B \C \D \E \F \G \H \I \J \K \L \M \N \O \P \Q \R\S \T \U \V \W \X \Y \Z \[ \\ \] \^" \_ \`P \a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y \z \{ \| \} \~ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \' \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \P \ \ \ \ \ \ \ \ \ \ \ \ \ \E \  \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \' \ \ \ ] ]' ] ] ] ] ] ]b ] ]  ]  ]  ]  ]  ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]  ]! ]" ]# ]$ ]% ]& ]' ]( ]) ]* ]+ ], ]- ]. ]/ ]0 ]1 ]2 ]3 ]4 ]5 ]6 ]7 ]8 ]9 ]: ]; ]< ]= ]> ]? ]@ ]A ]B ]C ]D ]E ]F ]G ]H ]I ]J ]K ]L ]M ]N ]O ]P ]Q ]R]S ]T ]U ]V ]W ]X ]Y ]Z ][ ]\ ]] ]^' ]_ ]` ]a ]b ]c ]d ]e ]f ]g ]h ]i ]j ]k ]l ]m ]n ]o ]p ]q ]r ]s ]t ]u ]v ]w ]x ]y ]z ]{ ]| ]} ]~ ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]b ] ] ] ] ] ] ] ] ] ] ] ] ] ]b ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]b ] ] ] ^ ^  ^ ^ ^ ^ ^ ^ ^b ^  ^  ^  ^  ^  ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^  ^! ^" ^# ^$ ^% ^& ^' ^( ^) ^* ^+ ^, ^- ^. ^/ ^0 ^1 ^2 ^3 ^4 ^5 ^6 ^7 ^8 ^9 ^: ^; ^< ^= ^> ^? ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O ^P ^Q ^R^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^" ^_ ^`] ^a ^b ^c ^d ^e ^f ^g ^h ^i ^j ^k ^l ^m ^n ^o ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^a ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^" ^ ^  ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ _ _ _ _ _ _ _ _ _ _ b _  _  _  _  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _  _! _" _# _$ _% _& _' _( _) _* _+ _, _- _. _/ _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _: _; _< _= _> _? _@ _A _B _C _D _E _F _G _H _I _J _K _L _M _N _O _P _Q _R_S _T _U _V _W _X _Y _Z _[ _\ _] _^ __ _` _a _b _c _d _e _f _g _h _i _j _k _l _m _n _o _p _q _r _s _t _u _v _w _x _y _z _{ _| _} _~ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ` ` ` ` ` ` ` ` ` ` b `  `  `  `  ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `  `! `" `# `$ `% `& `' `( `) `* `+ `, `- `. `/ `0 `1 `2 `3 `4 `5 `6 `7 `8 `9 `: `; `< `= `> `? `@ `A `B `C `D `E `F `G `H `I `J `K `L `M `N `O `P `Q `R`S `T `U `V `W `X `Y `Z `[ `\ `] `^ `_ ``0u `a `b `c `d `e `f `g `h `i `j `k `l `m `n `o `p `q `r `s `t `u `v `w `x `y `z `{ `| `} `~ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `' ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `7 `  ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `' ` ` ` a a a a a a a a ab a  a  a  a  a  a a a a a a a a a a a a a a a a a a a  a! a" a# a$ a% a& a' a( a) a* a+ a, a- a. a/ a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a: a; a< a= a> a? a@ aA aB aC aD aE aF aG aH aI aJ aK aL aM aN aO aP aQ aRaS aT aU aV aW aX aY aZ a[ a\ a] a^ a_ a` aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az a{ a| a} a~ a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a ab a a a a a a a a a a a a a aE a a a a a a a a a a a a a a a a a a a a a a b b# b b b b b b bb b  b  b  b  b  b b b b b b b b b b b b b b b b b b b  b! b" b# b$ b% b& b' b( b) b* b+ b, b- b. b/ b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b: b; b< b= b> b? b@ bA bB bC bD bE bF bG bH bI bJ bK bL bM bN bO bP bQ bRbS bT bU bV bW bX bY bZ b[ b\ b] b^# b_ b`@ ba bb bc bd be bf bg bh bi bj bk bl bm bn bo bp bq br bs bt bu bv bw bx by bz b{ b| b} b~ b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b bb b b b b b b b b b b b b b bL b b b b b b b b b b b b b b b b ba b b b b b c8 c! c c c c c c cb c  c  c  c  c  c c c c c c c c c c c c c c c c c c c  c! c" c# c$ c% c& c' c( c) c* c+ c, c- c. c/ c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c: c; c< c= c> c? c@ cA cB cC cD cE cF cG cH cI cJ cK cL cM cN cO cP cQ cRcS cT cU cV cW cX cY cZ c[ c\ c] c^ c_ c` ca cb cc cd ce cf cg ch ci cjH  ck cl cm cn co cp cq cr cs ct cu cv cw cx cy cz c{ c| c} c~ c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c@ c c c c c c c c c c c c c c? c c c c c c c c c c c c c c c c cH  c c c c c d d  d  d d d d d d d b d  d  d  d  d d d d d d d d d d d d d d d d d d d  d! d" d# d$ d% d& d' d( d) d* d+ d, d- d. d/ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d: d; d< d= d> d? d@ dA dB dC dD dE dF dG dH dI dJ dK dL dM dN dO dP dQ dRdS dT dU dV dW dX dY dZ d[ d\ d] d^  d_ d`O@ da db dc dd de df dg dh di dj dk dl dm dn do dp dq dr ds dt du dv dw dx dy dz d{ d| d} d~ d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d dd@ d d d d d d d d d d d d d d$ d  d d d d d d d d d d d d d d d d d d d d d e e e e e e e e eb e  e  e  e  e  e e e e e e e e e e e e e e e e e e e  e! e" e# e$ e% e& e' e( e) e* e+ e, e- e. e/ e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 e: e; e< e= e> e? e@ eA eB eC eD eE eF eG eH eI eJ eK eL eM eN eO eP eQ eReS eT eU eV eW eX eY eZ e[ e\ e] e^ e_ e` ea eb ec ed ee ef eg eh ei ej ek el em en eo ep eq er es et eu ev ew ex ey ez e{ e| e} e~ e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e eb e e e e e e e e e e e e e e< e  e e e e e e e e e e e e e e e e e e e e e f f f f f f  f fb f f  f  f  f  f  f f f f f f f f f f f f f f f f f f f  f! f" f# f$ f% f& f' f( f) f* f+ f, f- f. f/ f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f: f; f< f= f> f? f@ fA fB fC fD fE fF fG fH fI fJ fK fL fM fN fO fP fQ fRfS fT fU fV fW fX fY fZ f[ f\ f] f^ f_ f`@ fa fb fc fd fe ff fg fh fi fj@ fk fl fm fn fo fp fq fr fs ft fu fv fw fx fy fz f{ f| f} f~ f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f fP f f f f f f f f f f f f f fD f  f f f f f f f f f f f f f f f f@ f f f f f gU g g g g g g g g g b g  g  g  g  g g g g g g g g g g g g g g g g g g g  g! g" g# g$ g% g& g' g( g) g* g+ g, g- g. g/ g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 g: g; g< g= g> g? g@ gA gB gC gD gE gF gG gH gI gJ gK gL gM gN gO gP gQ gRgS gT gU gV gW gX gY gZ g[ g\ g] g^ g_ g` ga gb gc gd ge gf gg gh gi gj gk gl gm gn go gp gq gr gs gt gu gv gw gx gy gz g{ g| g} g~ g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g^ g g g g g g g g g g g g g$ g g g g g g g g g g g g g g g g g g g g g g h h h h h h h hb h h  h  h  h  h  h h h h h h h h h h h h h h h h h h h  h! h" h# h$ h% h& h' h( h) h* h+ h, h- h. h/ h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h: h; h< h= h> h? h@ hA hB hC hD hE hF hG hH hI hJ hK hL hM hN hO hP hQ hRhS hT hU hV hW hX hY hZ h[ h\  h] h^ h_ h` ha hb hc hd he hf hg hh hi hj(# hk hl hm hn ho hp hq hr hs ht hu hv hw hx hy hz h{ h| h} h~ h h h h h h h h h h h h h h h h h h h h h h h(# h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h h hP h h h h h h h h h h h h h h. h h h h h h h h h h h h h h h h h(# h h(# h h h i* i i i i i i  i ib i  i  i  i  i  i i i i i i i i i i i i i i i i i i i  i! i" i# i$ i% i& i' i( i) i* i+ i, i- i. i/ i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i: i; i< i= i> i? i@ iA iB iC iD iE iF iG iH iI iJ iK iL iM iN iO iP iQ iRiS iT iU iV iW iX iY iZ i[ i\ i] i^ i_ i` ia ib ic id ie if ig ih ii ij ik il im in io ip iq ir is it iu iv iw ix iy iz i{ i| i} i~ i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i ib i i i i i i i i i i i i i iG i  i i i i i i i i i i i i i i i i i i i i i j j j j j j j j jb j  j  j  j  j  j j j j j j j j j j j j j j j j j j j  j! j" j# j$ j% j& j' j( j) j* j+ j, j- j. j/ j0 j1 j2 j3 j4 j5 j6 j7 j8 j9 j: j; j< j= j> j? j@ jA jB jC jD jE jF jG jH jI jJ jK jL jM jN jO jP jQ jRjS jT jU jV jW jX jY jZ j[ j\ j] j^ j_ j` ja jb jc jd je jf jg jh ji jj jk jl jm jn jo jp jq jr js jt ju jv jw jx jy jz j{ j| j} j~ j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j j8 j j j j j j j j j j j j j j j j  j j j j j j k k( k k k k k kb k k  k  k  k  k  k k k k k k k k k k k k k k k k k k k  k! k" k# k$ k% k& k' k( k) k* k+ k, k- k. k/ k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 k: k; k< k= k> k? k@ kA kB kC kD kE kF kG kH kI kJ kK kL kM kN kO kP kQ kRkS kT kU kV kW kX kY kZ k[ k\ k] k^( k_ k` ka kb kc kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx ky kz k{ k| k} k~ k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k kb k k k k k k k k k k k k k kG k  k k k k k k k k k k k k k k k kb k kb k k k l l* l l l l l l l l  l  l  l  l  l l l l l l l l l l l l l l l l l l l  l! l" l# l$ l% l& l' l( l) l* l+ l, l- l. l/ l0 l1 l2 l3 l4 l5 l6 l7 l8 l9 l: l; l< l= l> l? l@ lA lB lC lD lE lF lG lH lI lJ lK lL lM lN lO lP lQ lRlS lT lU lV lW lX lY lZ l[ l\ l] l^( l_ l` la lb lc ld le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz l{ l| l} l~ l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l l lb l l l l l l l l l l l l l lQ l l l l l l l l l l l l l l l l l l l l l l m m m m m m m m mb m  m  m  m  m  m m m m m m m m m m m m m m m m m m m  m! m" m# m$ m% m& m' m( m) m* m+ m, m- m. m/ m0 m1 m2 m3 m4 m5 m6 m7 m8 m9 m: m; m< m= m> m? m@ mA mB mC mD mE mF mG mH mI mJ mK mL mM mN mO mP mQ mRmS mT mU mV mW mX mY mZ m[ m\ m] m^ m_ m` ma mb mc md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx my mz m{ m| m} m~ m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m mb m m m m m m m m m m m m m m0 m m m m m m m m m m m m m m m m m m m m m m n9 n n n n n n n nb n  n  n  n  n  n n n n n n n n n n n n n n n n n n n  n! n" n# n$ n% n& n' n( n) n* n+ n, n- n. n/ n0 n1 n2 n3 n4 n5 n6 n7 n8 n9 n: n; n< n= n> n? n@ nA nB nC nD nE nF nG nH nI nJ nK nL nM nN nO nP nQ nRnS nT nU nV nW nX nY nZ n[ n\ n] n^ n_ n` na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu nv nw nx ny nz n{ n| n} n~ n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n nȯ n n n n n n n n n n n n n nD n  n n n n n n n n n n n n n n n n n n n n n oj o o  o o o o o o o b o  o  o  o  o o o o o o o o o o o o o o o o o o o  o! o" o# o$ o% o& o' o( o) o* o+ o, o- o. o/ o0 o1 o2 o3 o4 o5 o6 o7 o8 o9 o: o; o< o= o> o? o@ oA oB oC oD oE oF oG oH oI oJ oK oL oM oN oO oP oQ oRoS oT oU oV oW oX oY oZ o[ o\ o] o^ o_  o`ȯ oa ob oc od oe of og oh oi oj ok ol om on oo op oq or os ot ou ov ow ox oy oz o{ o| o} o~ o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o oA o o o o o o o o o o o o o o o o o o o o o o p p p p p p p p pb p  p  p  p  p  p p p p p p p p p p p p p p p p p p p  p! p" p# p$ p% p& p' p( p) p* p+ p, p- p. p/ p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p: p; p< p= p> p? p@ pA pB pC pD pE pF pG pH pI pJ pK pL pM pN pO pP pQ pRpS pT pU pV pW pX pY pZ p[ p\ p] p^ p_ p` pa pb pc pd pe pf pg ph pi pj pk pl pm pn po pp pq pr ps pt pu pv pw px py pz p{ p| p} p~ p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p pb p p p p p p p p p p p p p p9 p  p p p p p p p p p p p p p p p p p p p p p q q  q q q q q q qb q  q  q  q  q  q q q q q q q q q q q q q q q q q q q  q! q" q# q$ q% q& q' q( q) q* q+ q, q- q. q/ q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q: q; q< q= q> q? q@ qA qB qC qD qE qF qG qH qI qJ qK qL qM qN qO qP qQ qRqS qT qU qV qW qX qY qZ q[ q\ q] q^  q_ q` qa qb qc qd qe qf qg qh qi qj qk ql qm qn qo qp qq qr qs qt qu qv qw qx qy qz q{ q| q} q~ q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q qb q q q q q q q q q q q q q qb qa q q q q q q q q q q q q q q q q q q q q q r r r r r r  r r r r b r  r  r  r  r r r r r r r r r r r r r r r r r r r  r! r" r# r$ r% r& r' r( r) r* r+ r, r- r. r/ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r: r; r< r= r> r? r@ rA rB rC rD rE rF rG rH rI rJ rK rL rM rN rO rP rQ rRrS rT rU rV rW rX rY rZ r[ r\ r] r^ r_ r`P ra rb rc rd re rf rg rh ri rj rk rl rm rn ro rp rq rr rs rt ru rv rw rx ry rz r{ r| r} r~ r' r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r` r r r r r r r r r r r r r r9 r  r r r r r r r r r r r r r r r r' r r r r r s+ s  s s s s s sb s s  s  s  s  s  s s s s s s s s s s s s s s s s s s s  s! s" s# s$ s% s& s' s( s) s* s+ s, s- s. s/ s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s: s; s< s= s> s? s@ sA sB sC sD sE sF sG sH sI sJ sK sL sM sN sO sP sQ sRsS sT sU sV sW sX sY sZ s[ s\ s] s^ s_ s` sa sb sc sd se sf sg sh si sj sk sl sm sn so sp sq sr ss st su sv sw sx sy sz s{ s| s} s~ s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s sE s s s s s s s s s s s s sW s  s s s s s s s s s s s s s s s s s s s s s t t  t t t t t t tb t  t  t  t  t  t t t t t t t t t t t t t t t t t t t  t! t" t# t$ t% t& t' t( t) t* t+ t, t- t. t/ t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t: t; t< t= t> t? t@ tA tB tC tD tE tF tG tH tI tJ tK tL tM tN tO tP tQ tRtS tT tU tV tW tX tY tZ t[ t\ t] t^ t_ t` ta tb tc td te tf tg th ti tj tk tl tm tn to tp tq tr ts tt tu tv tw tx ty tz t{ t| t} t~ t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t t` t t t t t t t t t t t t t t% t t t t t t t t t t t t t t t t t t t t  t t u u u u u u u u ub u  u  u  u  u  u u u u u u u u u u u u u u u u u u u  u! u" u# u$ u% u& u' u( u) u* u+ u, u- u. u/ u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 u: u; u< u= u> u? u@ uA uB uC uD uE uF uG uH uI uJ uK uL uM uN uO uP uQ uRuS uT uU uV uW uX uY uZ u[ u\ u] u^  u_ u` ua ub uc ud ue uf ug uh ui uj uk ul um un uo up uq ur us ut uu uv uw ux uy uz u{ u| u} u~ u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u u ub u u u u u u u u u u u u u u& u u u u u u u u u u u u u u u u ub u u u u u v v( v v v v v v vb v  v  v  v  v  v v v v v v v v v v v v v v v v v v v  v! v" v# v$ v% v& v' v( v) v* v+ v, v- v. v/ v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v: v; v< v= v> v? v@ vA vB vC vD vE vF vG vH vI vJ vK vL vM vN vO vP vQ vRvS vT vU vV vW vX vY vZ v[ v\ v] v^ v_ v` N va vb vc vd ve vf vg vh vi vj  vk vl vm vn vo vp vq vr vs vt vu vv vw vx vy vz v{ v| v} v~ v v v v v v v v v v v v v v v v v v v v v v v  v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v vb v v v v v v v v v v v v v vJ v  v v v v v v v v v v v v v v v v  v v  v v v w w( w w w w w w wb w  w  w  w  w  w w w w w w w w w w w w w w w w w w w  w! w" w# w$ w% w& w' w( w) w* w+ w, w- w. w/ w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 w: w; w< w= w> w? w@ wA wB wC wD wE wF wG wH wI wJ wK wL wM wN wO wP wQ wRwS wT wU wV wW wX wY wZ w[ w\ w] w^( w_ w`` wa wb wc wd we wf wg wh wi wj wk wl wm wn wo wp wq wr ws wt wu wv ww wx wy wz w{ w| w} w~ w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w wb w w w w w w w w w w w w w wF w  w w w w w w w w w w w w w w w w w wb w w w x x x x x x x x x x b x  x  x  x  x x x x x x x x x x x x x x x x x x x  x! x" x# x$ x% x& x' x( x) x* x+ x, x- x. x/ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x: x; x< x= x> x? x@ xA xB xC xD xE xF xG xH xI xJ xK xL xM xN xO xP xQ xRxS xT xU xV xW xX xY xZ x[ x\ x] x^ x_ x` xa xb xc xd xe xf xg xh xi xj xk xl xm xn xo xp xq xr xs xt xu xv xw xx xy xz x{ x| x} x~ x' x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x' x x x x x x x x x x x x x x x x x x x x xP x x x x x x x x x x x x x x1 x x x x x x x x x x x x x x x x x' x x x' x x yk y  y y y y y y y y  y  y  y  y  y y y y y y y y y y y y y y y y y y y  y! y" y# y$ y% y& y' y( y) y* y+ y, y- y. y/ y0 y1 y2 y3 y4 y5 y6 y7 y8 y9 y: y; y< y= y> y? y@ yA yB yC yD yE yF yG yH yI yJ yK yL yM yN yO yP yQ yRyS yT yU yV yW yX yY yZ y[ y\ y] y^  y_ y`0u ya yb yc yd ye yf yg yh yi yj yk yl ym yn yo yp yq yr ys yt yu yv yw yx yy yz y{ y| y} y~ y y y y y y y y y y y y y y y y y y y y y y y' y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y, y y y y y y y y y y y y y y y y  y y y' y y y z z z z z z z z zb z  z  z  z  z  z z z z z z z z z z z z z z z z z z z  z! z" z# z$ z% z& z' z( z) z* z+ z, z- z. z/ z0 z1 z2 z3 z4 z5 z6 z7 z8 z9 z: z; z< z= z> z? z@ zA zB zC zD zE zF zG zH zI zJ zK zL zM zN zO zP zQ zRzS zT zU zV zW zX zY zZ z[ z\ z] z^ z_ z`` za zb zc zd ze zf zg zh zi zj zk zl zm zn zo zp zq zr zs zt zu zv zw zx zy zz z{ z| z} z~ z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z zb z z z z z z z z z z z z z z< z z z z z z z z z z z z z z z z zb z zb z z z { { { { { { { { { { b {  {  {  {  { { { { { { { { { { { { { { { { { { {  {! {" {# {$ {% {& {' {( {) {* {+ {, {- {. {/ {0 {1 {2 {3 {4 {5 {6 {7 {8 {9 {: {; {< {= {> {? {@ {A {B {C {D {E {F {G {H {I {J {K {L {M {N {O {P {Q {R{S {T {U {V {W {X {Y {Z {[ {\ {] {^ {_ {`P {a {b {c {d {e {f {g {h {i {j {k {l {m {n {o {p {q {r {s {t {u {v {w {x {y {z {{ {| {} {~ { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { {ȯ { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { | | | | | | | | | | b |  |  |  |  | | | | | | | | | | | | | | | | | | |  |! |" |# |$ |% |& |' |( |) |* |+ |, |- |. |/ |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |: |; |< |= |> |? |@ |A |B |C |D |E |F |G |H |I |J |K |L |M |N |O |P |Q |R|S |T |U |V |W |X |Y |Z |[ |\ |] |^ |_ |` |a |b |c |d |e |f |g |h |i |j |k |l |m |n |o |p |q |r |s |t |u |v |w |x |y |z |{ || |} |~ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |b | | | | | | | | | | | | | |D |  | | | | | | | | | | | | | | | |b | |b | | | }, }( } } } } } } }b }  }  }  }  }  } } } } } } } } } } } } } } } } } } }  }! }" }# }$ }% }& }' }( }) }* }+ }, }- }. }/ }0 }1 }2 }3 }4 }5 }6 }7 }8 }9 }: }; }< }= }> }? }@ }A }B }C }D }E }F }G }H }I }J }K }L }M }N }O }P }Q }R}S }T }U }V }W }X }Y }Z }[ }\ }] }^( }_ }` }a }b }c }d }e }f }g }h }i }j }k }l }m }n }o }p }q }r }s }t }u }v }w }x }y }z }{ }| }} }~ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }b } } } } } } } } } } } } } }@ }  } } } } } } } } } } } } } } } } } } } } } ~ ~ ~ ~ ~ ~ ~ ~b ~ ~  ~  ~  ~  ~  ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~  ~! ~" ~# ~$ ~% ~& ~' ~( ~) ~* ~+ ~, ~- ~. ~/ ~0 ~1 ~2 ~3 ~4 ~5 ~6 ~7 ~8 ~9 ~: ~; ~< ~= ~> ~? ~@ ~A ~B ~C ~D ~E ~F ~G ~H ~I ~J ~K ~L ~M ~N ~O ~P ~Q ~R~S ~T ~U ~V ~W ~X ~Y ~Z ~[ ~\ ~] ~^ ~_ ~` ~a ~b ~c ~d ~e ~f ~g ~h ~i ~j ~k ~l ~m ~n ~o ~p ~q ~r ~s ~t ~u ~v ~w ~x ~y ~z ~{ ~| ~} ~~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~b ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~  ~ ~ ~ ~ ~ ~ ;        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `: a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 8J              ?                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j  k l m n o p q r s t u v w x y z { | } ~                                                                  0u              ?                                  b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              /                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `X a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              C                   b b           b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  b                                    b    (      b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              A                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`O@ a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                                                                 `              ?                 '              b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  N              7                         (       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       '                                                        Q                    '              b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j| k l m n o p q r s t u v w x y z { | } ~                       p                                          ȯ              ,                  |  p            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              @                              b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 P                                            b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b                                 b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 @              <                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`x.A a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 '              6                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              =                  b       !       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^! _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               N                    b     (       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j  k l m n o p q r s t u v w x y z { | } ~                       X                                          b              E                     X     (       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _ `P a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          b              D                  '  '    V #       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^# _ `> a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 hB              :                          #       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                            @                     P              D                    @    $       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `P a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 @              M                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j(# k l m n o p q r s t u v w x y z { | } ~                                                                 b                                (#  b    W                                 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                            p                     0u              >                    p            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               D                         &        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _ `p a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              B                                                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              K                     b     #       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                x.A              1                 b             b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  b              4                                  b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 `              4                  b  b    X        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               G                       Y         b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                O@              b                           !      b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  ^                                            b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              G                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ '                                                               jA              8                 '       '       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              A                               b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 @              C                  b              b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  N              E                   b            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              J                                 b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               ?                    b            b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  ^                                            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              8                    b            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b     a         Q                   b     !       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              C                  b  b            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              4                                                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`O@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              =                       l        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                                                       . "       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^" _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               A                        #       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^# _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              G                 b  b    \         b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              T                               b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 `              %                       /          b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              M                       ]         b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              @                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `P a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       '                                          P                                  '             b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  '                                     m        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ p                                           p                     0u              2                 p   p   0        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                @              +                        (       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              B                    b     '       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^' _ `ȯ a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                                                                 b              E                 '                                       ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 `              ?                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       '                                          `              6                   '             b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               *                        '                                 ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^' _  ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              D                       n        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              >                                                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `: a b c d e f g h i j  k l m n o p q r s t u v w x y z { | } ~                                                                 b              *                                b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              <                 b      < (       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              ;                  b  b            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              ;                  b  b    1        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               -                       o       b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               B                   a           b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               3                        _         b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^b _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b                                              b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                                                      a        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  w             ;                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       '                                          b              8                    '             b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              &                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                O@              6                     b   b         b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              G                       p (       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                   b              @                          #       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              N                         )       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^) _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               G                               b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ                                             b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `P a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              =                                 b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 @              D                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              0                        c        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              B                        (        b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _ `P a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          P              D                 '  '    2        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              6                        q        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              F a                 b  b     (        b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^) _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              B                 b              b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       '                                          0u              ;                    '           b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               "                        d       b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              /                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` N a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  N              A                       r #       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ `P a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                                                                 b              D                 '  a           b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                @              4                       3         b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          @              7                 '  '           b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               b                              b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              2                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                @              7                                                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `p a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                            X                                   ;                    X           b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       @                                          0u                                 @           b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^% _`O@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b                                b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               ,                       e +       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^# _`jA a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       '                                          b              N                   '    ^        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`j@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                L@              3                        t        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 0u              #                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `0u a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              -                          (       b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               (                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               F                                b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                                +                        "          b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b                                      u   !     b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              +                 b  b     #      b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^# _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b a                               b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                                                      4        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                       '                                          b              F                   '     (        b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^( _`O@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                O@              K                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j  k l m n o p q r s t u v w x y z { | } ~                                                                 b              (                     b             b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \  ] ^  _`O@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                O@                                              b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          @              D                  '  '            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 P              @                        >          b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b                       h *      b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^* _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              b a                b               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               ,                       ?       b                          ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               G                               b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 0u              2                       5        b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               3                        @         b                        ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b                  b  b            b                         ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               /                         )         b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^) _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              )                         $       b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^$ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               F                        A        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               1                       B       b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               b b                               b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          P              3                 '  '            b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`j@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              (                       6        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               %                   b  b           b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `P a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              -                        # #      b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^b _ ` a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          b                                '  '    $         b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              :                  b  b             b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                   '             "                          %       b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^% _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              A                          !    b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                                                       7        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                                                                 @              >                 '  b              b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                                                       %          b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              C                              b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `P a b c d e f g h i j  k l m n o p q r s t u v w x y z { | } ~                       '                                          @              ;                    '    & (      b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              U                        9        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                @                                b  b    '            b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               b                               b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _`@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              /                       !          b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                O@              =                                   b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^  _ ``m a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              b                          #         b                             ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 ȯ              D                        "        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               *                       v       b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^# _ `ȯ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              A                         #       b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               3                        D &       b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^& _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              I                                b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `@ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  P                                       $        b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                               2                        X 2                                       ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^2 _ ` a b c d e f g h i j' k l m n o p q r s t u v w x y z { | } ~                       '                                          b              K                 '  '           b                                ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q RS T U V W X Y Z [ \ ] ^ _ `Hq a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                 b              2                                 b                               ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^  _ `p a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~                                                                  a              E                        !E ! ! ! ! ! ! !b ! !  !  !  !  !  ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !  !! !" !# !$ !% !& !' !( !) !* !+ !, !- !. !/ !0 !1 !2 !3 !4 !5 !6 !7 !8 !9 !: !; !< != !> !? !@ !A !B !C !D !E !F !G !H !I !J !K !L !M !N !O !P !Q !R!S !T !U !V !W !X !Y !Z ![ !\ !] !^ !_ !` !a !b !c !d !e !f !g !h !i !j !k !l !m !n !o !p !q !r !s !t !u !v !w !x !y !z !{ !| !} !~ ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !b ! ! ! ! ! ! ! ! ! ! ! ! ! !b !a !  ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! "f " " " " " " " "b "  "  "  "  "  " " " " " " " " " " " " " " " " " " "  "! "" "# "$ "% "& "' "( ") "* "+ ", "- ". "/ "0 "1 "2 "3 "4 "5 "6 "7 "8 "9 ": "; "< "= "> "? "@ "A "B "C "D "E "F "G "H "I "J "K "L "M "N "O "P "Q "R"S "T "U "V "W "X "Y "Z "[ "\ "] "^ "_ "` "a "b "c "d "e "f "g "h "i "j "k "l "m "n "o "p "q "r "s "t "u "v "w "x "y "z "{ "| "} "~ " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "b " " " " " " " " " " " " " "9 "  " " " " " " " " " " " " " " " " " " " " " #  # # # # # # # #b #  #  #  #  #  # # # # # # # # # # # # # # # # # # #  #! #" ## #$ #% #& #' #( #) #* #+ #, #- #. #/ #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 #: #; #< #= #> #? #@ #A #B #C #D #E #F #G #H #I #J #K #L #M #N #O #P #Q #R#S #T #U #V #W #X #Y #Z #[ #\ #] #^ #_ #`a #a #b #c #d #e #f #g #h #i #j #k #l #m #n #o #p #q #r #s #t #u #v #w #x #y #z #{ #| #} #~ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #a # # # # # # # # # # # # # #2 #  # # # # # # # # # # # # # # # # # # # # # $% $ $ $ $ $ $ $ $b $  $  $  $  $  $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $  $! $" $# $$ $% $& $' $( $) $* $+ $, $- $. $/ $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $: $; $< $= $> $? $@ $A $B $C $D $E $F $G $H $I $J $K $L $M $N $O $P $Q $R$S $T $U $V $W $X $Y $Z $[ $\ $] $^ $_ $` $a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z ${ $| $} $~ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $. $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % %' % % % % % %b % %  %  %  %  %  % % % % % % % % % % % % % % % % % % %  %! %" %# %$ %% %& %' %( %) %* %+ %, %- %. %/ %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %: %; %< %= %> %? %@ %A %B %C %D %E %F %G %H %I %J %K %L %M %N %O %P %Q %R%S %T %U %V %W %X %Y %Z %[ %\ %] %^8 %_ %` %a %b %c %d %e %f %g %h %i %j %k %l %m %n %o %p %q %r %s %t %u %v %w %x %y %z %{ %| %} %~ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %Q %b %  % %  % % % % % % % % % % % %  % % % % % % &x &# & & & & & & &b &  &  &  &  &  & & & & & & & & & & & & & & & & & & &  &! &" &# &$ &% && &' &( &) &* &+ &, &- &. &/ &0 &1 &2 &3 &4 &5 &6 &7 &8 &9 &: &; &< &= &> &? &@ &A &B &C &D &E &F &G &H &I &J &K &L &M &N &O &P &Q &R&S &T &U &V &W &X &Y &Z &[ &\ &] &^# &_  &`X &a &b &c &d &e &f &g &h &i &j &k &l &m &n &o &p &q &r &s &t &u &v &w &x &y &z &{ &| &} &~ & & & & & & & & & & & & & & & & & & & & & & &' & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &? & & & & & & & & & & & & & & & & & & &' & & & ' ' ' ' ' ' ' ' 'b '  '  '  '  '  ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '  '! '" '# '$ '% '& '' '( ') '* '+ ', '- '. '/ '0 '1 '2 '3 '4 '5 '6 '7 '8 '9 ': '; '< '= '> '? '@ 'A 'B 'C 'D 'E 'F 'G 'H 'I 'J 'K 'L 'M 'N 'O 'P 'Q 'R'S 'T 'U 'V 'W 'X 'Y 'Z '[ '\ '] '^ '_ '` 'a 'b 'c 'd 'e 'f 'g 'h 'i 'j 'k 'l 'm 'n 'o 'p 'q 'r 's 't 'u 'v 'w 'x 'y 'z '{ '| '} '~ ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' 'b ' ' ' ' ' ' ' ' ' ' ' ' ' '9 ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' (g ( ( ( ( ( ( ( (b (  (  (  (  (  ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (  (! (" (# ($ (% (& (' (( () (* (+ (, (- (. (/ (0 (1 (2 (3 (4 (5 (6 (7 (8 (9 (: (; (< (= (> (? (@ (A (B (C (D (E (F (G (H (I (J (K (L (M (N (O (P (Q (R(S (T (U (V (W (X (Y (Z ([ (\ (] (^ (_ (`@ (a (b (c (d (e (f (g (h (i (j (k (l (m (n (o (p (q (r (s (t (u (v (w (x (y (z ({ (| (} (~ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (b ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( )F ) ) ) ) ) ) ) ) ) b )  )  )  )  ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )  )! )" )# )$ )% )& )' )( )) )* )+ ), )- ). )/ )0 )1 )2 )3 )4 )5 )6 )7 )8 )9 ): ); )< )= )> )? )@ )A )B )C )D )E )F )G )H )I )J )K )L )M )N )O )P )Q )R)S )T )U )V )W )X )Y )Z )[ )\ )] )^ )_ )` )a )b )c )d )e )f )g )h )i )j )k )l )m )n )o )p )q )r )s )t )u )v )w )x )y )z ){ )| )} )~ ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )b ) ) ) ) ) ) ) ) ) ) ) ) ) ) )  ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) *L * * * * * * * *b *  *  *  *  *  * * * * * * * * * * * * * * * * * * *  *! *" *# *$ *% *& *' *( *) ** *+ *, *- *. */ *0 *1 *2 *3 *4 *5 *6 *7 *8 *9 *: *; *< *= *> *? *@ *A *B *C *D *E *F *G *H *I *J *K *L *M *N *O *P *Q *R*S *T *U *V *W *X *Y *Z *[ *\ *] *^ *_ *`P *a *b *c *d *e *f *g *h *i *j *k *l *m *n *o *p *q *r *s *t *u *v *w *x *y *z *{ *| *} *~ * * * * * * * * * * * * * * * * * * * * * * *x * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *P * * * * * * * * * * * * * *> * * * * * * * * * * * * * * * * * * *x * * * +: +* + + + + + + + + b +  +  +  +  + + + + + + + + + + + + + + + + + + +  +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +: +; +< += +> +? +@ +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R+S +T +U +V +W +X +Y +Z +[ +\ +] +^ +_ +` +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +{ +| +} +~ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +* +  + + + + + + + + + + + + + + + + + + + + + ,! , , , , , , , ,b ,  ,  ,  ,  ,  , , , , , , , , , , , , , , , , , , ,  ,! ," ,# ,$ ,% ,& ,' ,( ,) ,* ,+ ,, ,- ,. ,/ ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,: ,; ,< ,= ,> ,? ,@ ,A ,B ,C ,D ,E ,F ,G ,H ,I ,J ,K ,L ,M ,N ,O ,P ,Q ,R,S ,T ,U ,V ,W ,X ,Y ,Z ,[ ,\ ,] ,^# ,_,`@ ,a ,b ,c ,d ,e ,f ,g ,h ,i ,j ,k ,l ,m ,n ,o ,p ,q ,r ,s ,t ,u ,v ,w ,x ,y ,z ,{ ,| ,} ,~ , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,P , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,  , , , , , , - - - - - - - -b - -  -  -  -  -  - - - - - - - - - - - - - - - - - - -  -! -" -# -$ -% -& -' -( -) -* -+ -, -- -. -/ -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -: -; -< -= -> -? -@ -A -B -C -D -E -F -G -H -I -J -K -L -M -N -O -P -Q -R-S -T -U -V -W -X -Y -Z -[ -\ -] -^ -_ -` -a -b -c -d -e -f -g -h -i -j -k -l -m -n -o -p -q -r -s -t -u -v -w -x -y -z -{ -| -} -~ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -0u - - - - - - - - - - - - - -9 - - - - - - - - - - - - - - - - - - - - - - . . . . . . . . .b .  .  .  .  .  . . . . . . . . . . . . . . . . . . .  .! ." .# .$ .% .& .' .( .) .* .+ ., .- .. ./ .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .: .; .< .= .> .? .@ .A .B .C .D .E .F .G .H .I .J .K .L .M .N .O .P .Q .R.S .T .U .V .W .X .Y .Z .[ .\ .] .^ ._ .`ȯ .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .p .q .r .s .t .u .v .w .x .y .z .{ .| .} .~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .ȯ . . . . . . . . . . . . . .H .  . . . . . . . . . . . . . . . . . . . . . /& / / / / / / / /b /  /  /  /  /  / / / / / / / / / / / / / / / / / / /  /! /" /# /$ /% /& /' /( /) /* /+ /, /- /. // /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /: /; /< /= /> /? /@ /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R/S /T /U /V /W /X /Y /Z /[ /\ /] /^  /_/`@ /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /{ /| /} /~ / / / / / / / / / / / / / / / / / / / / / / /  / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / //@@ / / / / / / / / / / / / / /5 / / / / / / / / / / / / / / / /  / / /  / / / 0' 0 0 0 0 0  0 0 0 0 b 0  0  0  0  0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0! 0" 0# 0$ 0% 0& 0' 0( 0) 0* 0+ 0, 0- 0. 0/ 00 01 02 03 04 05 06 07 08 09 0: 0; 0< 0= 0> 0? 0@ 0A 0B 0C 0D 0E 0F 0G 0H 0I 0J 0K 0L 0M 0N 0O 0P 0Q 0R0S 0T 0U 0V 0W 0X 0Y 0Z 0[ 0\  0] 0^ 0_ 0` 0a 0b 0c 0d 0e 0f 0g 0h 0i 0j 0k 0l 0m 0n 0o 0p 0q 0r 0s 0t 0u 0v 0w 0x 0y 0z 0{ 0| 0} 0~ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0^ 0 0 0 0 0 0 0 0 0 0 0 0 0$ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1z 1 1 1 1 1 1 1 1 1 b 1  1  1  1  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1  1! 1" 1# 1$ 1% 1& 1' 1( 1) 1* 1+ 1, 1- 1. 1/ 10 11 12 13 14 15 16 17 18 19 1: 1; 1< 1= 1> 1? 1@ 1A 1B 1C 1D 1E 1F 1G 1H 1I 1J 1K 1L 1M 1N 1O 1P 1Q 1R1S 1T 1U 1V 1W 1X 1Y 1Z 1[ 1\ 1] 1^ 1_ 1`@ 1a 1b 1c 1d 1e 1f 1g 1h 1i 1j 1k 1l 1m 1n 1o 1p 1q 1r 1s 1t 1u 1v 1w 1x 1y 1z 1{ 1| 1} 1~ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11O@ 1 1 1 1 1 1 1 1 1 1 1 1 1 18 1  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2h 2 2 2 2 2 2 2 2 2 b 2  2  2  2  2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2  2! 2" 2# 2$ 2% 2& 2' 2( 2) 2* 2+ 2, 2- 2. 2/ 20 21 22 23 24 25 26 27 28 29 2: 2; 2< 2= 2> 2? 2@ 2A 2B 2C 2D 2E 2F 2G 2H 2I 2J 2K 2L 2M 2N 2O 2P 2Q 2R2S 2T 2U 2V 2W 2X 2Y 2Z 2[ 2\ 2] 2^ 2_ 2` 2a 2b 2c 2d 2e 2f 2g 2h 2i 2j 2k 2l 2m 2n 2o 2p 2q 2r 2s 2t 2u 2v 2w 2x 2y 2z 2{ 2| 2} 2~ 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 28 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3  3  3  3  3  3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3  3! 3" 3# 3$ 3% 3& 3' 3( 3) 3* 3+ 3, 3- 3. 3/ 30 31 32 33 34 35 36 37 38 39 3: 3; 3< 3= 3> 3? 3@ 3A 3B 3C 3D 3E 3F 3G 3H 3I 3J 3K 3L 3M 3N 3O 3P 3Q 3R3S 3T 3U 3V 3W 3X 3Y 3Z 3[ 3\ 3] 3^ 3_ 3` 3a 3b 3c 3d 3e 3f 3g 3h 3i 3j 3k 3l 3m 3n 3o 3p 3q 3r 3s 3t 3u 3v 3w 3x 3y 3z 3{ 3| 3} 3~ 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3G 3  3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4G 4 4 4 4 4 4 4 4 4 b 4  4  4  4  4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4  4! 4" 4# 4$ 4% 4& 4' 4( 4) 4* 4+ 4, 4- 4. 4/ 40 41 42 43 44 45 46 47 48 49 4: 4; 4< 4= 4> 4? 4@ 4A 4B 4C 4D 4E 4F 4G 4H 4I 4J 4K 4L 4M 4N 4O 4P 4Q 4R4S 4T 4U 4V 4W 4X 4Y 4Z 4[ 4\ 4] 4^ 4_ 4`P 4a 4b 4c 4d 4e 4f 4g 4h 4i 4j 4k 4l 4m 4n 4o 4p 4q 4r 4s 4t 4u 4v 4w 4x 4y 4z 4{ 4| 4} 4~ 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4P 4 4 4 4 4 4 4 4 4 4 4 4 4 44 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5" 5 5 5 5 5 5 5 5b 5  5  5  5  5  5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5  5! 5" 5# 5$ 5% 5& 5' 5( 5) 5* 5+ 5, 5- 5. 5/ 50 51 52 53 54 55 56 57 58 59 5: 5; 5< 5= 5> 5? 5@ 5A 5B 5C 5D 5E 5F 5G 5H 5I 5J 5K 5L 5M 5N 5O 5P 5Q 5R5S 5T 5U 5V 5W 5X 5Y 5Z 5[ 5\ 5] 5^ 5_5`1@ 5a 5b 5c 5d 5e 5f 5g 5h 5i 5j 5k 5l 5m 5n 5o 5p 5q 5r 5s 5t 5u 5v 5w 5x 5y 5z 5{ 5| 5} 5~ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 55@ 5 5 5 5 5 5 5 5 5 5 5 5 5 57 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6| 6# 6 6 6 6 6  6 6 6  6  6  6  6  6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6  6! 6" 6# 6$ 6% 6& 6' 6( 6) 6* 6+ 6, 6- 6. 6/ 60 61 62 63 64 65 66 67 68 69 6: 6; 6< 6= 6> 6? 6@ 6A 6B 6C 6D 6E 6F 6G 6H 6I 6J 6K 6L 6M 6N 6O 6P 6Q 6R6S 6T 6U 6V 6W 6X 6Y 6Z 6[ 6\ 6] 6^ 6_ 6` 6a 6b 6c 6d 6e 6f 6g 6h 6i 6j 6k 6l 6m 6n 6o 6p 6q 6r 6s 6t 6u 6v 6w 6x 6y 6z 6{ 6| 6} 6~ 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6" 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7i 7 7 7 7 7 7 7 7b 7  7  7  7  7  7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7  7! 7" 7# 7$ 7% 7& 7' 7( 7) 7* 7+ 7, 7- 7. 7/ 70 71 72 73 74 75 76 77 78 79 7: 7; 7< 7= 7> 7? 7@ 7A 7B 7C 7D 7E 7F 7G 7H 7I 7J 7K 7L 7M 7N 7O 7P 7Q 7R7S 7T 7U 7V 7W 7X 7Y 7Z 7[ 7\ 7] 7^ 7_7`@ 7a 7b 7c 7d 7e 7f 7g 7h 7i 7j 7k 7l 7m 7n 7o 7p 7q 7r 7s 7t 7u 7v 7w 7x 7y 7z 7{ 7| 7} 7~ 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 77)A 7 7 7 7 7 7 7 7 7 7 7 7 7 7* 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8H 8! 8 8 8 8 8 8 8 8 b 8  8  8  8  8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8  8! 8" 8# 8$ 8% 8& 8' 8( 8) 8* 8+ 8, 8- 8. 8/ 80 81 82 83 84 85 86 87 88 89 8: 8; 8< 8= 8> 8? 8@ 8A 8B 8C 8D 8E 8F 8G 8H 8I 8J 8K 8L 8M 8N 8O 8P 8Q 8R8S 8T 8U 8V 8W 8X 8Y 8Z 8[ 8\ 8] 8^! 8_ 8` 8a 8b 8c 8d 8e 8f 8g 8h 8i 8j 8k 8l 8m 8n 8o 8p 8q 8r 8s 8t 8u 8v 8w 8x 8y 8z 8{ 8| 8} 8~ 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8b 8 8 8 8 8 8 8 8 8 8 8 8 8 8! 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9$ 9 9 9 9 9 9 9 9b 9  9  9  9  9  9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9  9! 9" 9# 9$ 9% 9& 9' 9( 9) 9* 9+ 9, 9- 9. 9/ 90 91 92 93 94 95 96 97 98 99 9: 9; 9< 9= 9> 9? 9@ 9A 9B 9C 9D 9E 9F 9G 9H 9I 9J 9K 9L 9M 9N 9O 9P 9Q 9R9S 9T 9U 9V 9W 9X 9Y 9Z 9[ 9\ 9] 9^ 9_ 9`p 9a 9b 9c 9d 9e 9f 9g 9h 9i 9j 9k 9l 9m 9n 9o 9p 9q 9r 9s 9t 9u 9v 9w 9x 9y 9z 9{ 9| 9} 9~ 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 96 9  9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 :% : : : : : : : :b :  :  :  :  :  : : : : : : : : : : : : : : : : : : :  :! :" :# :$ :% :& :' :( :) :* :+ :, :- :. :/ :0 :1 :2 :3 :4 :5 :6 :7 :8 :9 :: :; :< := :> :? :@ :A :B :C :D :E :F :G :H :I :J :K :L :M :N :O :P :Q :R:S :T :U :V :W :X :Y :Z :[ :\ :] :^ :_ :` :a :b :c :d :e :f :g :h :i :j :k :l :m :n :o :p :q :r :s :t :u :v :w :x :y :z :{ :| :} :~ : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :T : : : : : : : : : : : : :7 :  : : : : : : : : : : : : : : : : : : : : : ; ; ; ; ; ; ; ;b ; ;  ;  ;  ;  ;  ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;  ;! ;" ;# ;$ ;% ;& ;' ;( ;) ;* ;+ ;, ;- ;. ;/ ;0 ;1 ;2 ;3 ;4 ;5 ;6 ;7 ;8 ;9 ;: ;; ;< ;= ;> ;? ;@ ;A ;B ;C ;D ;E ;F ;G ;H ;I ;J ;K ;L ;M ;N ;O ;P ;Q ;R;S ;T ;U ;V ;W ;X ;Y ;Z ;[ ;\ ;] ;^ ;_ ;`ȯ ;a ;b ;c ;d ;e ;f ;g ;h ;i ;j ;k ;l ;m ;n ;o ;p ;q ;r ;s ;t ;u ;v ;w ;x ;y ;z ;{ ;| ;} ;~ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;@ ;  ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; <( < < < < < < <b < <  <  <  <  <  < < < < < < < < < < < < < < < < < < <  <! <" <# <$ <% <& <' <( <) <* <+ <, <- <. </ <0 <1 <2 <3 <4 <5 <6 <7 <8 <9 <: <; << <= <> <? <@ <A <B <C <D <E <F <G <H <I <J <K <L <M <N <O <P <Q <R<S <T <U <V <W <X <Y <Z <[ <\ <] <^ <_ <` <a <b <c <d <e <f <g <h <i <j <k <l <m <n <o <p <q <r <s <t <u <v <w <x <y <z <{ <| <} <~ < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < <7 < < < < < < < < < < < < < < < < < < < < < < =} = = = = = = = =b =  =  =  =  =  = = = = = = = = = = = = = = = = = = =  =! =" =# =$ =% =& =' =( =) =* =+ =, =- =. =/ =0 =1 =2 =3 =4 =5 =6 =7 =8 =9 =: =; =< == => =? =@ =A =B =C =D =E =F =G =H =I =J =K =L =M =N =O =P =Q =R=S =T =U =V =W =X =Y =Z =[ =\ =] =^ =_ =` =a =b =c =d =e =f =g =h =i =j =k =l =m =n =o =p =q =r =s =t =u =v =w =x =y =z ={ =| =} =~ = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ' = = = = = = = = = = = = =b =  = = = = = = = = = = = = = = = = = = = = = > > > > > > > >b > >  >  >  >  >  > > > > > > > > > > > > > > > > > > >  >! >" ># >$ >% >& >' >( >) >* >+ >, >- >. >/ >0 >1 >2 >3 >4 >5 >6 >7 >8 >9 >: >; >< >= >> >? >@ >A >B >C >D >E >F >G >H >I >J >K >L >M >N >O >P >Q >R>S >T >U >V >W >X >Y >Z >[ >\ >] >^ >_ >` >a >b >c >d >e >f >g >h >i >j >k >l >m >n >o >p >q >r >s >t >u >v >w >x >y >z >{ >| >} >~ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >b > > > > > > > > > > > > > >6 > > > > > > > > > > > > > > > > > > > > > > ?~ ? ? ? ? ? ? ? ? ?  ?  ?  ?  ?  ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?  ?! ?" ?# ?$ ?% ?& ?' ?( ?) ?* ?+ ?, ?- ?. ?/ ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?: ?; ?< ?= ?> ?? ?@ ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R?S ?T ?U ?V ?W ?X ?Y ?Z ?[ ?\ ?] ?^ ?_ ?` ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z ?{ ?| ?} ?~ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6 ? ? ? ? ? ? ? ? ? ? ? ? ? ?% ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @j @ @ @ @ @ @ @ @ @ b @  @  @  @  @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @  @! @" @# @$ @% @& @' @( @) @* @+ @, @- @. @/ @0 @1 @2 @3 @4 @5 @6 @7 @8 @9 @: @; @< @= @> @? @@ @A @B @C @D @E @F @G @H @I @J @K @L @M @N @O @P @Q @R@S @T @U @V @W @X @Y @Z @[ @\ @] @^ @_ @` @a @b @c @d @e @f @g @h @i @j @k @l @m @n @o @p @q @r @s @t @u @v @w @x @y @z @{ @| @} @~ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @9 @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ A* A A A A A A A Ab A  A  A  A  A  A A A A A A A A A A A A A A A A A A A  A! A" A# A$ A% A& A' A( A) A* A+ A, A- A. A/ A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A: A; A< A= A> A? A@ AA AB AC AD AE AF AG AH AI AJ AK AL AM AN AO AP AQ ARAS AT AU AV AW AX AY AZ A[ A\ A] A^ A_ A` Aa Ab Ac Ad Ae Af Ag Ah Ai Aj Ak Al Am An Ao Ap Aq Ar As At Au Av Aw Ax Ay Az A{ A| A} A~ A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A? A  A A A A A A A A A A A A A A A A A A A A A B B B B B B B Bb B B  B  B  B  B  B B B B B B B B B B B B B B B B B B B  B! B" B# B$ B% B& B' B( B) B* B+ B, B- B. B/ B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B: B; B< B= B> B? B@ BA BB BC BD BE BF BG BH BI BJ BK BL BM BN BO BP BQ BRBS BT BU BV BW BX BY BZ B[ B\ B] B^ B_ B` Ba Bb Bc Bd Be Bf Bg Bh Bi Bj Bk Bl Bm Bn Bo Bp Bq Br Bs Bt Bu Bv Bw Bx By Bz B{ B| B} B~ B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B B ' B B B B B B B B B B B B B7 B  B B B B B B B B B B B B B B B B B B B B B Ck C C C C C C C Cb C  C  C  C  C  C C C C C C C C C C C C C C C C C C C  C! C" C# C$ C% C& C' C( C) C* C+ C, C- C. C/ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C: C; C< C= C> C? C@ CA CB CC CD CE CF CG CH CI CJ CK CL CM CN CO CP CQ CRCS CT CU CV CW CX CY CZ C[ C\ C] C^ C_ C` Ca Cb Cc Cd Ce Cf Cg Ch Ci Cj Ck Cl Cm Cn Co Cp Cq Cr Cs Ct Cu Cv Cw Cx Cy Cz C{ C| C} C~ C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C# C C C C C C C C C C C C C C C C C C C C C C D D  D D D D D D D D b D  D  D  D  D D D D D D D D D D D D D D D D D D D  D! D" D# D$ D% D& D' D( D) D* D+ D, D- D. D/ D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 D: D; D< D= D> D? D@ DA DB DC DD DE DF DG DH DI DJ DK DL DM DN DO DP DQ DRDS DT DU DV DW DX DY DZ D[ D\ D] D^  D_ D` Da Db Dc Dd De Df Dg Dh Di Dj Dk Dl Dm Dn Do Dp Dq Dr Ds Dt Du Dv Dw Dx Dy Dz D{ D| D} D~ D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D D0u D D D D D D D D D D D D D D< D  D D D D D D D D D D D D D D D D D D D D D El E  E E E E E E Eb E  E  E  E  E  E E E E E E E E E E E E E E E E E E E  E! E" E# E$ E% E& E' E( E) E* E+ E, E- E. E/ E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 E: E; E< E= E> E? E@ EA EB EC ED EE EF EG EH EI EJ EK EL EM EN EO EP EQ ERES ET EU EV EW EX EY EZ E[ E\ E] E^  E_ E` Ea Eb Ec Ed Ee Ef Eg Eh Ei Ej Ek El Em En Eo Ep Eq Er Es Et Eu Ev Ew Ex Ey Ez E{ E| E} E~ E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E Eb E E E E E E E E E E E E E E5 E  E E E E E E E E E E E E E E E E E E E E E Fm F F F F F F F F F b F  F  F  F  F F F F F F F F F F F F F F F F F F F  F! F" F# F$ F% F& F' F( F) F* F+ F, F- F. F/ F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F: F; F< F= F> F? F@ FA FB FC FD FE FF FG FH FI FJ FK FL FM FN FO FP FQ FRFS FT FU FV FW FX FY FZ F[ F\ F] F^ F_F`@ Fa Fb Fc Fd Fe Ff Fg Fh Fi Fj Fk Fl Fm Fn Fo Fp Fq Fr Fs Ft Fu Fv Fw Fx Fy Fz F{ F| F} F~ F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F F Fb F F F F F F F F F F F F F F7 F  F F F F F F F F F F F F F F F F F F F F F Gn G( G G G G G G Gb G  G  G  G  G  G G G G G G G G G G G G G G G G G G G  G! G" G# G$ G% G& G' G( G) G* G+ G, G- G. G/ G0 G1 G2 G3 G4 G5 G6 G7 G8 G9 G: G; G< G= G> G? G@ GA GB GC GD GE GF GG GH GI GJ GK GL GM GN GO GP GQ GRGS GT GU GV GW GX GY GZ G[ G\ G] G^ G_ G`0u Ga Gb Gc Gd Ge Gf Gg Gh Gi Gj Gk Gl Gm Gn Go Gp Gq Gr Gs Gt Gu Gv Gw Gx Gy Gz G{ G| G} G~ G G G G G G G G G G G G G G G G G G G G G G G  G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G Ga G G G G G G G G G G G G G G< G  G G G G G G G G G G G G G G G G G G  G G G H H H H H H H H Hb H  H  H  H  H  H H H H H H H H H H H H H H H H H H H  H! H" H# H$ H% H& H' H( H) H* H+ H, H- H. H/ H0 H1 H2 H3 H4 H5 H6 H7 H8 H9 H: H; H< H= H> H? H@ HA HB HC HD HE HF HG HH HI HJ HK HL HM HN HO HP HQ HRHS HT HU HV HW HX HY HZ H[ H\ H] H^ H_ H` Ha Hb Hc Hd He Hf Hg Hh Hi Hj Hk Hl Hm Hn Ho Hp Hq Hr Hs Ht Hu Hv Hw Hx Hy Hz H{ H| H} H~ H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H H HI H  H H H H H H H H H H H H H H H H H H H H H I I  I I I I I Ib I I  I  I  I  I  I I I I I I I I I I I I I I I I I I I  I! I" I# I$ I% I& I' I( I) I* I+ I, I- I. I/ I0 I1 I2 I3 I4 I5 I6 I7 I8 I9 I: I; I< I= I> I? I@ IA IB IC ID IE IF IG IH II IJ IK IL IM IN IO IP IQ IRIS IT IU IV IW IX IY IZ I[ I\ I] I^b I_ I` Ia Ib Ic Id Ie If Ig Ih Ii Ij Ik Il Im In Io Ip Iq Ir Is It Iu Iv Iw Ix Iy Iz I{ I| I} I~ I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I Ib I I I I I I I I I I I I I I$ I  I I I I I I I I I I I I I I I I I I I I I J: J0 J J J J J Jb J J  J  J  J  J  J J J J J J J J J J J J J J J J J J J  J! J" J# J$ J% J& J' J( J) J* J+ J, J- J. J/ J0 J1 J2 J3 J4 J5 J6 J7 J8 J9 J: J; J< J= J> J? J@ JA JB JC JD JE JF JG JH JI JJ JK JL JM JN JO JP JQ JRJS JT JU JV JW JX JY JZ J[ J\ J] J^  J_ J`P Ja Jb Jc Jd Je Jf Jg Jh Ji Jj Jk Jl Jm Jn Jo Jp Jq Jr Js Jt Ju Jv Jw Jx Jy Jz J{ J| J} J~ J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J J Jb J J J J J J J J J J J J J JK J  J J J J J J J J J J J J J J J J J J J J J K& K+ K K K K K K Kb K  K  K  K  K  K K K K K K K K K K K K K K K K K K K  K! K" K# K$ K% K& K' K( K) K* K+ K, K- K. K/ K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 K: K; K< K= K> K? K@ KA KB KC KD KE KF KG KH KI KJ KK KL KM KN KO KP KQ KRKS KT KU KV KW KX KY KZ K[ K\ K] K^b K_ K` Ka Kb Kc Kd Ke Kf Kg Kh Ki Kj Kk Kl Km Kn Ko Kp Kq Kr Ks Kt Ku Kv Kw Kx Ky Kz K{ K| K} K~ K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K K Kb K K K K K K K K K K K K K KH K  K K K K K K K K K K K K K K K K K K K K K Lo L L L L L L L Lb L  L  L  L  L  L L L L L L L L L L L L L L L L L L L  L! L" L# L$ L% L& L' L( L) L* L+ L, L- L. L/ L0 L1 L2 L3 L4 L5 L6 L7 L8 L9 L: L; L< L= L> L? L@ LA LB LC LD LE LF LG LH LI LJ LK LL LM LN LO LP LQ LRLS LT LU LV LW LX LY LZ L[ L\ L] L^ L_ L` La Lb Lc Ld Le Lf Lg Lh Li Lj Lk Ll Lm Ln Lo Lp Lq Lr Ls Lt Lu Lv Lw Lx Ly Lz L{ L| L} L~ L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L Lb L L L L L L L L L L L L L Lb L  L L L L L L L L L L L L L L L L L L L L L M; M M M M M M M M M  M  M  M  M  M M M M M M M M M M M M M M M M M M M  M! M" M# M$ M% M& M' M( M) M* M+ M, M- M. M/ M0 M1 M2 M3 M4 M5 M6 M7 M8 M9 M: M; M< M= M> M? M@ MA MB MC MD ME MF MG MH MI MJ MK ML MM MN MO MP MQ MRMS MT MU MV MW MX MY MZ M[ M\ M] M^b M_ M`0u Ma Mb Mc Md Me Mf Mg Mh Mi Mj Mk Ml Mm Mn Mo Mp Mq Mr Ms Mt Mu Mv Mw Mx My Mz M{ M| M} M~ M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M M MP M M M M M M M M M M M M M M M  M M M M M M M M M M M M M M M M M M M M M N( N" N N N N N N Nb N  N  N  N  N  N N N N N N N N N N N N N N N N N N N  N! N" N# N$ N% N& N' N( N) N* N+ N, N- N. N/ N0 N1 N2 N3 N4 N5 N6 N7 N8 N9 N: N; N< N= N> N? N@ NA NB NC ND NE NF NG NH NI NJ NK NL NM NN NO NP NQ NRNS NT NU NV NW NX NY NZ N[ N\ N] N^  N_ N` Na Nb Nc Nd Ne Nf Ng Nh Ni Nj Nk Nl Nm Nn No Np Nq Nr Ns Nt Nu Nv Nw Nx Ny Nz N{ N| N} N~ N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N NP N N N N N N N N N N N N N NE N  N N N N N N N N N N N N N N N N N N N N N O O O  O O O O O O O b O  O  O  O  O O O O O O O O O O O O O O O O O O O  O! O" O# O$ O% O& O' O( O) O* O+ O, O- O. O/ O0 O1 O2 O3 O4 O5 O6 O7 O8 O9 O: O; O< O= O> O? O@ OA OB OC OD OE OF OG OH OI OJ OK OL OM ON OO OP OQ OROS OT OU OV OW OX OY OZ O[ O\ O] O^ O_ O` Oa Ob Oc Od Oe Of Og Oh Oi Oj Ok Ol Om On Oo Op Oq Or Os Ot Ou Ov Ow Ox Oy Oz O{ O| O} O~ O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O~ O O O O O O O O O O O O O> O  O O O O O O O O O O O O O O O O O O O O O P P P P P P P P Pb P  P  P  P  P  P P P P P P P P P P P P P P P P P P P  P! P" P# P$ P% P& P' P( P) P* P+ P, P- P. P/ P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P: P; P< P= P> P? P@ PA PB PC PD PE PF PG PH PI PJ PK PL PM PN PO PP PQ PRPS PT PU PV PW PX PY PZ P[ P\ P] P^ P_ P`( Pa Pb Pc Pd Pe Pf Pg Ph Pi Pj Pk Pl Pm Pn Po Pp Pq Pr Ps Pt Pu Pv Pw Px Py Pz P{ P| P} P~ P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P Pb P P P P P P P P P P P P P PH P P P P P P P P P P P P P P P P P P P P P P Q< Q Q Q Q Q Q Q Qb Q  Q  Q  Q  Q  Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q  Q! Q" Q# Q$ Q% Q& Q' Q( Q) Q* Q+ Q, Q- Q. Q/ Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q: Q; Q< Q= Q> Q? Q@ QA QB QC QD QE QF QG QH QI QJ QK QL QM QN QO QP QQ QRQS QT QU QV QW QX QY QZ Q[ Q\ Q] Q^ Q_ Q` Qa Qb Qc Qd Qe Qf Qg Qh Qi Qj Qk Ql Qm Qn Qo Qp Qq Qr Qs Qt Qu Qv Qw Qx Qy Qz Q{ Q| Q} Q~ Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Qb Q Q Q Q Q Q Q Q Q Q Q Q Q Q< Q  Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q R) R R R R R R R Rb R  R  R  R  R  R R R R R R R R R R R R R R R R R R R  R! R" R# R$ R% R& R' R( R) R* R+ R, R- R. R/ R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R: R; R< R= R> R? R@ RA RB RC RD RE RF RG RH RI RJ RK RL RM RN RO RP RQ RRRS RT RU RV RW RX RY RZ R[ R\ R] R^ R_ R` Ra Rb Rc Rd Re Rf Rg Rh Ri Rj Rk Rl Rm Rn Ro Rp Rq Rr Rs Rt Ru Rv Rw Rx Ry Rz R{ R| R} R~ R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R R] R R R R R R R R R R R R R R; R R R R R R R R R R R R R R R R R R R R R R Sp S S S S S S Sb S S  S  S  S  S  S S S S S S S S S S S S S S S S S S S  S! S" S# S$ S% S& S' S( S) S* S+ S, S- S. S/ S0 S1 S2 S3 S4 S5 S6 S7 S8 S9 S: S; S< S= S> S? S@ SA SB SC SD SE SF SG SH SI SJ SK SL SM SN SO SP SQ SRSS ST SU SV SW SX SY SZ S[ S\ S] S^ S_ S` Sa Sb Sc Sd Se Sf Sg Sh Si Sj Sk Sl Sm Sn So Sp Sq Sr Ss St Su Sv Sw Sx Sy Sz S{ S| S} S~ S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S Sb S S S S S S S S S S S S S S< S  S S S S S S S S S S S S S S S  S S S S S S T T T T T T T T T T b T  T  T  T  T T T T T T T T T T T T T T T T T T T  T! T" T# T$ T% T& T' T( T) T* T+ T, T- T. T/ T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T: T; T< T= T> T? T@ TA TB TC TD TE TF TG TH TI TJ TK TL TM TN TO TP TQ TRTS TT TU TV TW TX TY TZ T[ T\ T] T^ T_ T` Ta Tb Tc Td Te Tf Tg Th Ti Tj Tk Tl Tm Tn To Tp Tq Tr Ts Tt Tu Tv Tw Tx Ty Tz T{ T| T} T~ T T T T T T T T T T T T T T T T T T T T T T T  T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T Tb T T T T T T T T T T T T T T9 T T T T T T T T T T T T T T T T T T T  T T T Uq U U U U U U U Ub U  U  U  U  U  U U U U U U U U U U U U U U U U U U U  U! U" U# U$ U% U& U' U( U) U* U+ U, U- U. U/ U0 U1 U2 U3 U4 U5 U6 U7 U8 U9 U: U; U< U= U> U? U@ UA UB UC UD UE UF UG UH UI UJ UK UL UM UN UO UP UQ URUS UT UU UV UW UX UY UZ U[ U\ U] U^ U_U`O@ Ua Ub Uc Ud Ue Uf Ug Uh Ui Uj Uk Ul Um Un Uo Up Uq Ur Us Ut Uu Uv Uw Ux Uy Uz U{ U| U} U~ U U U U U U U U U U U U U U U U U U U U U U U| U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U U Ub U U U U U U U U U U U U U U< U  U U U U U U U U U U U U U U U U U U| U U U V V  V V V V V V Vb V  V  V  V  V  V V V V V V V V V V V V V V V V V V V  V! V" V# V$ V% V& V' V( V) V* V+ V, V- V. V/ V0 V1 V2 V3 V4 V5 V6 V7 V8 V9 V: V; V< V= V> V? V@ VA VB VC VD VE VF VG VH VI VJ VK VL VM VN VO VP VQ VRVS VT VU VV VW VX VY VZ V[ V\ V] V^  V_ V` Va Vb Vc Vd Ve Vf Vg Vh Vi Vj Vk Vl Vm Vn Vo Vp Vq Vr Vs Vt Vu Vv Vw Vx Vy Vz V{ V| V} V~ V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V Vb V V V V V V V V V V V V V V< V  V V V V V V V V V V V V V V V V V V V V V W= W W W W W W W  W W b W  W  W  W  W W W W W W W W W W W W W W W W W W W  W! W" W# W$ W% W& W' W( W) W* W+ W, W- W. W/ W0 W1 W2 W3 W4 W5 W6 W7 W8 W9 W: W; W< W= W> W? W@ WA WB WC WD WE WF WG WH WI WJ WK WL WM WN WO WP WQ WRWS WT WU WV WW WX WY WZ W[ W\ W] W^ W_ W` Wa Wb Wc Wd We Wf Wg Wh Wi Wj Wk Wl Wm Wn Wo Wp Wq Wr Ws Wt Wu Wv Ww Wx Wy Wz W{ W| W} W~ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W Wb W W W W W W W W W W W W W W; W  W W W W W W W W W W W W W W W W W W W W W X> X X X X X X Xb X X  X  X  X  X  X X X X X X X X X X X X X X X X X X X  X! X" X# X$ X% X& X' X( X) X* X+ X, X- X. X/ X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X: X; X< X= X> X? X@ XA XB XC XD XE XF XG XH XI XJ XK XL XM XN XO XP XQ XRXS XT XU XV XW XX XY XZ X[ X\ X] X^ X_ X` Xa Xb Xc Xd Xe Xf Xg Xh Xi Xj Xk Xl Xm Xn Xo Xp Xq Xr Xs Xt Xu Xv Xw Xx Xy Xz X{ X| X} X~ X X X X X X X X X X X X X X X X X X X X X X X(# X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X Xb X X X X X X X X X X X X X X6 X  X X X X X X X X X X X X X X X X X X(# X X X Y* Y Y Y Y Y Y Y Yb Y  Y  Y  Y  Y  Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y  Y! Y" Y# Y$ Y% Y& Y' Y( Y) Y* Y+ Y, Y- Y. Y/ Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Y9 Y: Y; Y< Y= Y> Y? Y@ YA YB YC YD YE YF YG YH YI YJ YK YL YM YN YO YP YQ YRYS YT YU YV YW YX YY YZ Y[ Y\ Y] Y^ Y_ Y` Ya Yb Yc Yd Ye Yf Yg Yh Yi Yj Yk Yl Ym Yn Yo Yp Yq Yr Ys Yt Yu Yv Yw Yx Yy Yz Y{ Y| Y} Y~ Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Yb Y Y Y Y Y Y Y Y Y Y Y Y Y YG Y  Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Z+ Z Z Z Z Z Z Z Zb Z  Z  Z  Z  Z  Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z  Z! Z" Z# Z$ Z% Z& Z' Z( Z) Z* Z+ Z, Z- Z. Z/ Z0 Z1 Z2 Z3 Z4 Z5 Z6 Z7 Z8 Z9 Z: Z; Z< Z= Z> Z? Z@ ZA ZB ZC ZD ZE ZF ZG ZH ZI ZJ ZK ZL ZM ZN ZO ZP ZQ ZRZS ZT ZU ZV ZW ZX ZY ZZ Z[ Z\ Z] Z^ Z_ Z` Za Zb Zc Zd Ze Zf Zg Zh Zi Zj Zk Zl Zm Zn Zo Zp The Project Gutenberg Etext of LOC WORKSHOP ON ELECTRONIC TEXTS WORKSHOP ON ELECTRONIC TEXTS PROCEEDINGS Edited by James Daly 9-10 June 1992 Library of Congress Washington, D.C. Supported by a Grant from the David and Lucile Packard Foundation *** *** *** ****** *** *** *** TABLE OF CONTENTS Acknowledgements Introduction Proceedings Welcome Prosser Gifford and Carl Fleischhauer Session I. Content in a New Form: Who Will Use It and What Will They Do? James Daly (Moderator) Avra Michelson, Overview Susan H. Veccia, User Evaluation Joanne Freeman, Beyond the Scholar Discussion Session II. Show and Tell Jacqueline Hess (Moderator) Elli Mylonas, Perseus Project Discussion Eric M. Calaluca, Patrologia Latina Database Carl Fleischhauer and Ricky Erway, American Memory Discussion Dorothy Twohig, The Papers of George Washington Discussion Maria L. Lebron, The Online Journal of Current Clinical Trials Discussion Lynne K. Personius, Cornell mathematics books Discussion Session III. Distribution, Networks, and Networking: Options for Dissemination Robert G. Zich (Moderator) Clifford A. Lynch Discussion Howard Besser Discussion Ronald L. Larsen Edwin B. Brownrigg Discussion Session IV. Image Capture, Text Capture, Overview of Text and Image Storage Formats William L. Hooton (Moderator) A) Principal Methods for Image Capture of Text: direct scanning, use of microform Anne R. Kenney Pamela Q.J. Andre Judith A. Zidar Donald J. Waters Discussion B) Special Problems: bound volumes, conservation, reproducing printed halftones George Thoma Carl Fleischhauer Discussion C) Image Standards and Implications for Preservation Jean Baronas Patricia Battin Discussion D) Text Conversion: OCR vs. rekeying, standards of accuracy and use of imperfect texts, service bureaus Michael Lesk Ricky Erway Judith A. Zidar Discussion Session V. Approaches to Preparing Electronic Texts Susan Hockey (Moderator) Stuart Weibel Discussion C.M. Sperberg-McQueen Discussion Eric M. Calaluca Discussion Session VI. Copyright Issues Marybeth Peters Session VII. Conclusion Prosser Gifford (Moderator) General discussion Appendix I: Program Appendix II: Abstracts Appendix III: Directory of Participants *** *** *** ****** *** *** *** Acknowledgements I would like to thank Carl Fleischhauer and Prosser Gifford for the opportunity to learn about areas of human activity unknown to me a scant ten months ago, and the David and Lucile Packard Foundation for supporting that opportunity. The help given by others is acknowledged on a separate page. 19 October 1992 *** *** *** ****** *** *** *** INTRODUCTION The Workshop on Electronic Texts (1) drew together representatives of various projects and interest groups to compare ideas, beliefs, experiences, and, in particular, methods of placing and presenting historical textual materials in computerized form. Most attendees gained much in insight and outlook from the event. But the assembly did not form a new nation, or, to put it another way, the diversity of projects and interests was too great to draw the representatives into a cohesive, action-oriented body.(2) Everyone attending the Workshop shared an interest in preserving and providing access to historical texts. But within this broad field the attendees represented a variety of formal, informal, figurative, and literal groups, with many individuals belonging to more than one. These groups may be defined roughly according to the following topics or activities: * Imaging * Searchable coded texts * National and international computer networks * CD-ROM production and dissemination * Methods and technology for converting older paper materials into electronic form * Study of the use of digital materials by scholars and others This summary is arranged thematically and does not follow the actual sequence of presentations. NOTES: (1) In this document, the phrase electronic text is used to mean any computerized reproduction or version of a document, book, article, or manuscript (including images), and not merely a machine- readable or machine-searchable text. (2) The Workshop was held at the Library of Congress on 9-10 June 1992, with funding from the David and Lucile Packard Foundation. The document that follows represents a summary of the presentations made at the Workshop and was compiled by James DALY. This introduction was written by DALY and Carl FLEISCHHAUER. PRESERVATION AND IMAGING Preservation, as that term is used by archivists,(3) was most explicitly discussed in the context of imaging. Anne KENNEY and Lynne PERSONIUS explained how the concept of a faithful copy and the user-friendliness of the traditional book have guided their project at Cornell University.(4) Although interested in computerized dissemination, participants in the Cornell project are creating digital image sets of older books in the public domain as a source for a fresh paper facsimile or, in a future phase, microfilm. The books returned to the library shelves are high-quality and useful replacements on acid-free paper that should last a long time. To date, the Cornell project has placed little or no emphasis on creating searchable texts; one would not be surprised to find that the project participants view such texts as new editions, and thus not as faithful reproductions. In her talk on preservation, Patricia BATTIN struck an ecumenical and flexible note as she endorsed the creation and dissemination of a variety of types of digital copies. Do not be too narrow in defining what counts as a preservation element, BATTIN counseled; for the present, at least, digital copies made with preservation in mind cannot be as narrowly standardized as, say, microfilm copies with the same objective. Setting standards precipitously can inhibit creativity, but delay can result in chaos, she advised. In part, BATTIN's position reflected the unsettled nature of image-format standards, and attendees could hear echoes of this unsettledness in the comments of various speakers. For example, Jean BARONAS reviewed the status of several formal standards moving through committees of experts; and Clifford LYNCH encouraged the use of a new guideline for transmitting document images on Internet. Testimony from participants in the National Agricultural Library's (NAL) Text Digitization Program and LC's American Memory project highlighted some of the challenges to the actual creation or interchange of images, including difficulties in converting preservation microfilm to digital form. Donald WATERS reported on the progress of a master plan for a project at Yale University to convert books on microfilm to digital image sets, Project Open Book (POB). The Workshop offered rather less of an imaging practicum than planned, but "how-to" hints emerge at various points, for example, throughout KENNEY's presentation and in the discussion of arcana such as thresholding and dithering offered by George THOMA and FLEISCHHAUER. NOTES: (3) Although there is a sense in which any reproductions of historical materials preserve the human record, specialists in the field have developed particular guidelines for the creation of acceptable preservation copies. (4) Titles and affiliations of presenters are given at the beginning of their respective talks and in the Directory of Participants (Appendix III). THE MACHINE-READABLE TEXT: MARKUP AND USE The sections of the Workshop that dealt with machine-readable text tended to be more concerned with access and use than with preservation, at least in the narrow technical sense. Michael SPERBERG-McQUEEN made a forceful presentation on the Text Encoding Initiative's (TEI) implementation of the Standard Generalized Markup Language (SGML). His ideas were echoed by Susan HOCKEY, Elli MYLONAS, and Stuart WEIBEL. While the presentations made by the TEI advocates contained no practicum, their discussion focused on the value of the finished product, what the European Community calls reusability, but what may also be termed durability. They argued that marking up--that is, coding--a text in a well-conceived way will permit it to be moved from one computer environment to another, as well as to be used by various users. Two kinds of markup were distinguished: 1) procedural markup, which describes the features of a text (e.g., dots on a page), and 2) descriptive markup, which describes the structure or elements of a document (e.g., chapters, paragraphs, and front matter). The TEI proponents emphasized the importance of texts to scholarship. They explained how heavily coded (and thus analyzed and annotated) texts can underlie research, play a role in scholarly communication, and facilitate classroom teaching. SPERBERG-McQUEEN reminded listeners that a written or printed item (e.g., a particular edition of a book) is merely a representation of the abstraction we call a text. To concern ourselves with faithfully reproducing a printed instance of the text, SPERBERG-McQUEEN argued, is to concern ourselves with the representation of a representation ("images as simulacra for the text"). The TEI proponents' interest in images tends to focus on corollary materials for use in teaching, for example, photographs of the Acropolis to accompany a Greek text. By the end of the Workshop, SPERBERG-McQUEEN confessed to having been converted to a limited extent to the view that electronic images constitute a promising alternative to microfilming; indeed, an alternative probably superior to microfilming. But he was not convinced that electronic images constitute a serious attempt to represent text in electronic form. HOCKEY and MYLONAS also conceded that their experience at the Pierce Symposium the previous week at Georgetown University and the present conference at the Library of Congress had compelled them to reevaluate their perspective on the usefulness of text as images. Attendees could see that the text and image advocates were in constructive tension, so to say. Three nonTEI presentations described approaches to preparing machine-readable text that are less rigorous and thus less expensive. In the case of the Papers of George Washington, Dorothy TWOHIG explained that the digital version will provide a not-quite-perfect rendering of the transcribed text--some 135,000 documents, available for research during the decades while the perfect or print version is completed. Members of the American Memory team and the staff of NAL's Text Digitization Program (see below) also outlined a middle ground concerning searchable texts. In the case of American Memory, contractors produce texts with about 99-percent accuracy that serve as "browse" or "reference" versions of written or printed originals. End users who need faithful copies or perfect renditions must refer to accompanying sets of digital facsimile images or consult copies of the originals in a nearby library or archive. American Memory staff argued that the high cost of producing 100-percent accurate copies would prevent LC from offering access to large parts of its collections. THE MACHINE-READABLE TEXT: METHODS OF CONVERSION Although the Workshop did not include a systematic examination of the methods for converting texts from paper (or from facsimile images) into machine-readable form, nevertheless, various speakers touched upon this matter. For example, WEIBEL reported that OCLC has experimented with a merging of multiple optical character recognition systems that will reduce errors from an unacceptable rate of 5 characters out of every l,000 to an unacceptable rate of 2 characters out of every l,000. Pamela ANDRE presented an overview of NAL's Text Digitization Program and Judith ZIDAR discussed the technical details. ZIDAR explained how NAL purchased hardware and software capable of performing optical character recognition (OCR) and text conversion and used its own staff to convert texts. The process, ZIDAR said, required extensive editing and project staff found themselves considering alternatives, including rekeying and/or creating abstracts or summaries of texts. NAL reckoned costs at $7 per page. By way of contrast, Ricky ERWAY explained that American Memory had decided from the start to contract out conversion to external service bureaus. The criteria used to select these contractors were cost and quality of results, as opposed to methods of conversion. ERWAY noted that historical documents or books often do not lend themselves to OCR. Bound materials represent a special problem. In her experience, quality control--inspecting incoming materials, counting errors in samples--posed the most time-consuming aspect of contracting out conversion. ERWAY reckoned American Memory's costs at $4 per page, but cautioned that fewer cost-elements had been included than in NAL's figure. OPTIONS FOR DISSEMINATION The topic of dissemination proper emerged at various points during the Workshop. At the session devoted to national and international computer networks, LYNCH, Howard BESSER, Ronald LARSEN, and Edwin BROWNRIGG highlighted the virtues of Internet today and of the network that will evolve from Internet. Listeners could discern in these narratives a vision of an information democracy in which millions of citizens freely find and use what they need. LYNCH noted that a lack of standards inhibits disseminating multimedia on the network, a topic also discussed by BESSER. LARSEN addressed the issues of network scalability and modularity and commented upon the difficulty of anticipating the effects of growth in orders of magnitude. BROWNRIGG talked about the ability of packet radio to provide certain links in a network without the need for wiring. However, the presenters also called attention to the shortcomings and incongruities of present-day computer networks. For example: 1) Network use is growing dramatically, but much network traffic consists of personal communication (E-mail). 2) Large bodies of information are available, but a user's ability to search across their entirety is limited. 3) There are significant resources for science and technology, but few network sources provide content in the humanities. 4) Machine-readable texts are commonplace, but the capability of the system to deal with images (let alone other media formats) lags behind. A glimpse of a multimedia future for networks, however, was provided by Maria LEBRON in her overview of the Online Journal of Current Clinical Trials (OJCCT), and the process of scholarly publishing on-line. The contrasting form of the CD-ROM disk was never systematically analyzed, but attendees could glean an impression from several of the show-and-tell presentations. The Perseus and American Memory examples demonstrated recently published disks, while the descriptions of the IBYCUS version of the Papers of George Washington and Chadwyck-Healey's Patrologia Latina Database (PLD) told of disks to come. According to Eric CALALUCA, PLD's principal focus has been on converting Jacques-Paul Migne's definitive collection of Latin texts to machine-readable form. Although everyone could share the network advocates' enthusiasm for an on-line future, the possibility of rolling up one's sleeves for a session with a CD-ROM containing both textual materials and a powerful retrieval engine made the disk seem an appealing vessel indeed. The overall discussion suggested that the transition from CD-ROM to on-line networked access may prove far slower and more difficult than has been anticipated. WHO ARE THE USERS AND WHAT DO THEY DO? Although concerned with the technicalities of production, the Workshop never lost sight of the purposes and uses of electronic versions of textual materials. As noted above, those interested in imaging discussed the problematical matter of digital preservation, while the TEI proponents described how machine-readable texts can be used in research. This latter topic received thorough treatment in the paper read by Avra MICHELSON. She placed the phenomenon of electronic texts within the context of broader trends in information technology and scholarly communication. Among other things, MICHELSON described on-line conferences that represent a vigorous and important intellectual forum for certain disciplines. Internet now carries more than 700 conferences, with about 80 percent of these devoted to topics in the social sciences and the humanities. Other scholars use on-line networks for "distance learning." Meanwhile, there has been a tremendous growth in end-user computing; professors today are less likely than their predecessors to ask the campus computer center to process their data. Electronic texts are one key to these sophisticated applications, MICHELSON reported, and more and more scholars in the humanities now work in an on-line environment. Toward the end of the Workshop, Michael LESK presented a corollary to MICHELSON's talk, reporting the results of an experiment that compared the work of one group of chemistry students using traditional printed texts and two groups using electronic sources. The experiment demonstrated that in the event one does not know what to read, one needs the electronic systems; the electronic systems hold no advantage at the moment if one knows what to read, but neither do they impose a penalty. DALY provided an anecdotal account of the revolutionizing impact of the new technology on his previous methods of research in the field of classics. His account, by extrapolation, served to illustrate in part the arguments made by MICHELSON concerning the positive effects of the sudden and radical transformation being wrought in the ways scholars work. Susan VECCIA and Joanne FREEMAN delineated the use of electronic materials outside the university. The most interesting aspect of their use, FREEMAN said, could be seen as a paradox: teachers in elementary and secondary schools requested access to primary source materials but, at the same time, found that "primariness" itself made these materials difficult for their students to use. OTHER TOPICS Marybeth PETERS reviewed copyright law in the United States and offered advice during a lively discussion of this subject. But uncertainty remains concerning the price of copyright in a digital medium, because a solution remains to be worked out concerning management and synthesis of copyrighted and out-of-copyright pieces of a database. As moderator of the final session of the Workshop, Prosser GIFFORD directed discussion to future courses of action and the potential role of LC in advancing them. Among the recommendations that emerged were the following: * Workshop participants should 1) begin to think about working with image material, but structure and digitize it in such a way that at a later stage it can be interpreted into text, and 2) find a common way to build text and images together so that they can be used jointly at some stage in the future, with appropriate network support, because that is how users will want to access these materials. The Library might encourage attempts to bring together people who are working on texts and images. * A network version of American Memory should be developed or consideration should be given to making the data in it available to people interested in doing network multimedia. Given the current dearth of digital data that is appealing and unencumbered by extremely complex rights problems, developing a network version of American Memory could do much to help make network multimedia a reality. * Concerning the thorny issue of electronic deposit, LC should initiate a catalytic process in terms of distributed responsibility, that is, bring together the distributed organizations and set up a study group to look at all the issues related to electronic deposit and see where we as a nation should move. For example, LC might attempt to persuade one major library in each state to deal with its state equivalent publisher, which might produce a cooperative project that would be equitably distributed around the country, and one in which LC would be dealing with a minimal number of publishers and minimal copyright problems. LC must also deal with the concept of on-line publishing, determining, among other things, how serials such as OJCCT might be deposited for copyright. * Since a number of projects are planning to carry out preservation by creating digital images that will end up in on-line or near-line storage at some institution, LC might play a helpful role, at least in the near term, by accelerating how to catalog that information into the Research Library Information Network (RLIN) and then into OCLC, so that it would be accessible. This would reduce the possibility of multiple institutions digitizing the same work. CONCLUSION The Workshop was valuable because it brought together partisans from various groups and provided an occasion to compare goals and methods. The more committed partisans frequently communicate with others in their groups, but less often across group boundaries. The Workshop was also valuable to attendees--including those involved with American Memory--who came less committed to particular approaches or concepts. These attendees learned a great deal, and plan to select and employ elements of imaging, text-coding, and networked distribution that suit their respective projects and purposes. Still, reality rears its ugly head: no breakthrough has been achieved. On the imaging side, one confronts a proliferation of competing data-interchange standards and a lack of consensus on the role of digital facsimiles in preservation. In the realm of machine-readable texts, one encounters a reasonably mature standard but methodological difficulties and high costs. These latter problems, of course, represent a special impediment to the desire, as it is sometimes expressed in the popular press, "to put the [contents of the] Library of Congress on line." In the words of one participant, there was "no solution to the economic problems--the projects that are out there are surviving, but it is going to be a lot of work to transform the information industry, and so far the investment to do that is not forthcoming" (LESK, per litteras). *** *** *** ****** *** *** *** PROCEEDINGS WELCOME +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ GIFFORD * Origin of Workshop in current Librarian's desire to make LC's collections more widely available * Desiderata arising from the prospect of greater interconnectedness * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ After welcoming participants on behalf of the Library of Congress, American Memory (AM), and the National Demonstration Lab, Prosser GIFFORD, director for scholarly programs, Library of Congress, located the origin of the Workshop on Electronic Texts in a conversation he had had considerably more than a year ago with Carl FLEISCHHAUER concerning some of the issues faced by AM. On the assumption that numerous other people were asking the same questions, the decision was made to bring together as many of these people as possible to ask the same questions together. In a deeper sense, GIFFORD said, the origin of the Workshop lay in the desire of the current Librarian of Congress, James H. Billington, to make the collections of the Library, especially those offering unique or unusual testimony on aspects of the American experience, available to a much wider circle of users than those few people who can come to Washington to use them. This meant that the emphasis of AM, from the outset, has been on archival collections of the basic material, and on making these collections themselves available, rather than selected or heavily edited products. From AM's emphasis followed the questions with which the Workshop began: who will use these materials, and in what form will they wish to use them. But an even larger issue deserving mention, in GIFFORD's view, was the phenomenal growth in Internet connectivity. He expressed the hope that the prospect of greater interconnectedness than ever before would lead to: 1) much more cooperative and mutually supportive endeavors; 2) development of systems of shared and distributed responsibilities to avoid duplication and to ensure accuracy and preservation of unique materials; and 3) agreement on the necessary standards and development of the appropriate directories and indices to make navigation straightforward among the varied resources that are, and increasingly will be, available. In this connection, GIFFORD requested that participants reflect from the outset upon the sorts of outcomes they thought the Workshop might have. Did those present constitute a group with sufficient common interests to propose a next step or next steps, and if so, what might those be? They would return to these questions the following afternoon. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLEISCHHAUER * Core of Workshop concerns preparation and production of materials * Special challenge in conversion of textual materials * Quality versus quantity * Do the several groups represented share common interests? * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Carl FLEISCHHAUER, coordinator, American Memory, Library of Congress, emphasized that he would attempt to represent the people who perform some of the work of converting or preparing materials and that the core of the Workshop had to do with preparation and production. FLEISCHHAUER then drew a distinction between the long term, when many things would be available and connected in the ways that GIFFORD described, and the short term, in which AM not only has wrestled with the issue of what is the best course to pursue but also has faced a variety of technical challenges. FLEISCHHAUER remarked AM's endeavors to deal with a wide range of library formats, such as motion picture collections, sound-recording collections, and pictorial collections of various sorts, especially collections of photographs. In the course of these efforts, AM kept coming back to textual materials--manuscripts or rare printed matter, bound materials, etc. Text posed the greatest conversion challenge of all. Thus, the genesis of the Workshop, which reflects the problems faced by AM. These problems include physical problems. For example, those in the library and archive business deal with collections made up of fragile and rare manuscript items, bound materials, especially the notoriously brittle bound materials of the late nineteenth century. These are precious cultural artifacts, however, as well as interesting sources of information, and LC desires to retain and conserve them. AM needs to handle things without damaging them. Guillotining a book to run it through a sheet feeder must be avoided at all costs. Beyond physical problems, issues pertaining to quality arose. For example, the desire to provide users with a searchable text is affected by the question of acceptable level of accuracy. One hundred percent accuracy is tremendously expensive. On the other hand, the output of optical character recognition (OCR) can be tremendously inaccurate. Although AM has attempted to find a middle ground, uncertainty persists as to whether or not it has discovered the right solution. Questions of quality arose concerning images as well. FLEISCHHAUER contrasted the extremely high level of quality of the digital images in the Cornell Xerox Project with AM's efforts to provide a browse-quality or access-quality image, as opposed to an archival or preservation image. FLEISCHHAUER therefore welcomed the opportunity to compare notes. FLEISCHHAUER observed in passing that conversations he had had about networks have begun to signal that for various forms of media a determination may be made that there is a browse-quality item, or a distribution-and-access-quality item that may coexist in some systems with a higher quality archival item that would be inconvenient to send through the network because of its size. FLEISCHHAUER referred, of course, to images more than to searchable text. As AM considered those questions, several conceptual issues arose: ought AM occasionally to reproduce materials entirely through an image set, at other times, entirely through a text set, and in some cases, a mix? There probably would be times when the historical authenticity of an artifact would require that its image be used. An image might be desirable as a recourse for users if one could not provide 100-percent accurate text. Again, AM wondered, as a practical matter, if a distinction could be drawn between rare printed matter that might exist in multiple collections--that is, in ten or fifteen libraries. In such cases, the need for perfect reproduction would be less than for unique items. Implicit in his remarks, FLEISCHHAUER conceded, was the admission that AM has been tilting strongly towards quantity and drawing back a little from perfect quality. That is, it seemed to AM that society would be better served if more things were distributed by LC--even if they were not quite perfect--than if fewer things, perfectly represented, were distributed. This was stated as a proposition to be tested, with responses to be gathered from users. In thinking about issues related to reproduction of materials and seeing other people engaged in parallel activities, AM deemed it useful to convene a conference. Hence, the Workshop. FLEISCHHAUER thereupon surveyed the several groups represented: 1) the world of images (image users and image makers); 2) the world of text and scholarship and, within this group, those concerned with language--FLEISCHHAUER confessed to finding delightful irony in the fact that some of the most advanced thinkers on computerized texts are those dealing with ancient Greek and Roman materials; 3) the network world; and 4) the general world of library science, which includes people interested in preservation and cataloging. FLEISCHHAUER concluded his remarks with special thanks to the David and Lucile Packard Foundation for its support of the meeting, the American Memory group, the Office for Scholarly Programs, the National Demonstration Lab, and the Office of Special Events. He expressed the hope that David Woodley Packard might be able to attend, noting that Packard's work and the work of the foundation had sponsored a number of projects in the text area. ****** SESSION I. CONTENT IN A NEW FORM: WHO WILL USE IT AND WHAT WILL THEY DO? +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DALY * Acknowledgements * A new Latin authors disk * Effects of the new technology on previous methods of research * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Serving as moderator, James DALY acknowledged the generosity of all the presenters for giving of their time, counsel, and patience in planning the Workshop, as well as of members of the American Memory project and other Library of Congress staff, and the David and Lucile Packard Foundation and its executive director, Colburn S. Wilbur. DALY then recounted his visit in March to the Center for Electronic Texts in the Humanities (CETH) and the Department of Classics at Rutgers University, where an old friend, Lowell Edmunds, introduced him to the department's IBYCUS scholarly personal computer, and, in particular, the new Latin CD-ROM, containing, among other things, almost all classical Latin literary texts through A.D. 200. Packard Humanities Institute (PHI), Los Altos, California, released this disk late in 1991, with a nominal triennial licensing fee. Playing with the disk for an hour or so at Rutgers brought home to DALY at once the revolutionizing impact of the new technology on his previous methods of research. Had this disk been available two or three years earlier, DALY contended, when he was engaged in preparing a commentary on Book 10 of Virgil's Aeneid for Cambridge University Press, he would not have required a forty-eight-square-foot table on which to spread the numerous, most frequently consulted items, including some ten or twelve concordances to key Latin authors, an almost equal number of lexica to authors who lacked concordances, and where either lexica or concordances were lacking, numerous editions of authors antedating and postdating Virgil. Nor, when checking each of the average six to seven words contained in the Virgilian hexameter for its usage elsewhere in Virgil's works or other Latin authors, would DALY have had to maintain the laborious mechanical process of flipping through these concordances, lexica, and editions each time. Nor would he have had to frequent as often the Milton S. Eisenhower Library at the Johns Hopkins University to consult the Thesaurus Linguae Latinae. Instead of devoting countless hours, or the bulk of his research time, to gathering data concerning Virgil's use of words, DALY--now freed by PHI's Latin authors disk from the tyrannical, yet in some ways paradoxically happy scholarly drudgery-- would have been able to devote that same bulk of time to analyzing and interpreting Virgilian verbal usage. Citing Theodore Brunner, Gregory Crane, Elli MYLONAS, and Avra MICHELSON, DALY argued that this reversal in his style of work, made possible by the new technology, would perhaps have resulted in better, more productive research. Indeed, even in the course of his browsing the Latin authors disk at Rutgers, its powerful search, retrieval, and highlighting capabilities suggested to him several new avenues of research into Virgil's use of sound effects. This anecdotal account, DALY maintained, may serve to illustrate in part the sudden and radical transformation being wrought in the ways scholars work. ****** ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MICHELSON * Elements related to scholarship and technology * Electronic texts within the context of broader trends within information technology and scholarly communication * Evaluation of the prospects for the use of electronic texts * Relationship of electronic texts to processes of scholarly communication in humanities research * New exchange formats created by scholars * Projects initiated to increase scholarly access to converted text * Trend toward making electronic resources available through research and education networks * Changes taking place in scholarly communication among humanities scholars * Network-mediated scholarship transforming traditional scholarly practices * Key information technology trends affecting the conduct of scholarly communication over the next decade * The trend toward end-user computing * The trend toward greater connectivity * Effects of these trends * Key transformations taking place * Summary of principal arguments * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Avra MICHELSON, Archival Research and Evaluation Staff, National Archives and Records Administration (NARA), argued that establishing who will use electronic texts and what they will use them for involves a consideration of both information technology and scholarship trends. This consideration includes several elements related to scholarship and technology: 1) the key trends in information technology that are most relevant to scholarship; 2) the key trends in the use of currently available technology by scholars in the nonscientific community; and 3) the relationship between these two very distinct but interrelated trends. The investment in understanding this relationship being made by information providers, technologists, and public policy developers, as well as by scholars themselves, seems to be pervasive and growing, MICHELSON contended. She drew on collaborative work with Jeff Rothenberg on the scholarly use of technology. MICHELSON sought to place the phenomenon of electronic texts within the context of broader trends within information technology and scholarly communication. She argued that electronic texts are of most use to researchers to the extent that the researchers' working context (i.e., their relevant bibliographic sources, collegial feedback, analytic tools, notes, drafts, etc.), along with their field's primary and secondary sources, also is accessible in electronic form and can be integrated in ways that are unique to the on-line environment. Evaluation of the prospects for the use of electronic texts includes two elements: 1) an examination of the ways in which researchers currently are using electronic texts along with other electronic resources, and 2) an analysis of key information technology trends that are affecting the long-term conduct of scholarly communication. MICHELSON limited her discussion of the use of electronic texts to the practices of humanists and noted that the scientific community was outside the panel's overview. MICHELSON examined the nature of the current relationship of electronic texts in particular, and electronic resources in general, to what she maintained were, essentially, five processes of scholarly communication in humanities research. Researchers 1) identify sources, 2) communicate with their colleagues, 3) interpret and analyze data, 4) disseminate their research findings, and 5) prepare curricula to instruct the next generation of scholars and students. This examination would produce a clearer understanding of the synergy among these five processes that fuels the tendency of the use of electronic resources for one process to stimulate its use for other processes of scholarly communication. For the first process of scholarly communication, the identification of sources, MICHELSON remarked the opportunity scholars now enjoy to supplement traditional word-of-mouth searches for sources among their colleagues with new forms of electronic searching. So, for example, instead of having to visit the library, researchers are able to explore descriptions of holdings in their offices. Furthermore, if their own institutions' holdings prove insufficient, scholars can access more than 200 major American library catalogues over Internet, including the universities of California, Michigan, Pennsylvania, and Wisconsin. Direct access to the bibliographic databases offers intellectual empowerment to scholars by presenting a comprehensive means of browsing through libraries from their homes and offices at their convenience. The second process of communication involves communication among scholars. Beyond the most common methods of communication, scholars are using E-mail and a variety of new electronic communications formats derived from it for further academic interchange. E-mail exchanges are growing at an astonishing rate, reportedly 15 percent a month. They currently constitute approximately half the traffic on research and education networks. Moreover, the global spread of E-mail has been so rapid that it is now possible for American scholars to use it to communicate with colleagues in close to 140 other countries. Other new exchange formats created by scholars and operating on Internet include more than 700 conferences, with about 80 percent of these devoted to topics in the social sciences and humanities. The rate of growth of these scholarly electronic conferences also is astonishing. From l990 to l991, 200 new conferences were identified on Internet. From October 1991 to June 1992, an additional 150 conferences in the social sciences and humanities were added to this directory of listings. Scholars have established conferences in virtually every field, within every different discipline. For example, there are currently close to 600 active social science and humanities conferences on topics such as art and architecture, ethnomusicology, folklore, Japanese culture, medical education, and gifted and talented education. The appeal to scholars of communicating through these conferences is that, unlike any other medium, electronic conferences today provide a forum for global communication with peers at the front end of the research process. Interpretation and analysis of sources constitutes the third process of scholarly communication that MICHELSON discussed in terms of texts and textual resources. The methods used to analyze sources fall somewhere on a continuum from quantitative analysis to qualitative analysis. Typically, evidence is culled and evaluated using methods drawn from both ends of this continuum. At one end, quantitative analysis involves the use of mathematical processes such as a count of frequencies and distributions of occurrences or, on a higher level, regression analysis. At the other end of the continuum, qualitative analysis typically involves nonmathematical processes oriented toward language interpretation or the building of theory. Aspects of this work involve the processing--either manual or computational--of large and sometimes massive amounts of textual sources, although the use of nontextual sources as evidence, such as photographs, sound recordings, film footage, and artifacts, is significant as well. Scholars have discovered that many of the methods of interpretation and analysis that are related to both quantitative and qualitative methods are processes that can be performed by computers. For example, computers can count. They can count brush strokes used in a Rembrandt painting or perform regression analysis for understanding cause and effect. By means of advanced technologies, computers can recognize patterns, analyze text, and model concepts. Furthermore, computers can complete these processes faster with more sources and with greater precision than scholars who must rely on manual interpretation of data. But if scholars are to use computers for these processes, source materials must be in a form amenable to computer-assisted analysis. For this reason many scholars, once they have identified the sources that are key to their research, are converting them to machine-readable form. Thus, a representative example of the numerous textual conversion projects organized by scholars around the world in recent years to support computational text analysis is the TLG, the Thesaurus Linguae Graecae. This project is devoted to converting the extant ancient texts of classical Greece. (Editor's note: according to the TLG Newsletter of May l992, TLG was in use in thirty-two different countries. This figure updates MICHELSON's previous count by one.) The scholars performing these conversions have been asked to recognize that the electronic sources they are converting for one use possess value for other research purposes as well. As a result, during the past few years, humanities scholars have initiated a number of projects to increase scholarly access to converted text. So, for example, the Text Encoding Initiative (TEI), about which more is said later in the program, was established as an effort by scholars to determine standard elements and methods for encoding machine-readable text for electronic exchange. In a second effort to facilitate the sharing of converted text, scholars have created a new institution, the Center for Electronic Texts in the Humanities (CETH). The center estimates that there are 8,000 series of source texts in the humanities that have been converted to machine-readable form worldwide. CETH is undertaking an international search for converted text in the humanities, compiling it into an electronic library, and preparing bibliographic descriptions of the sources for the Research Libraries Information Network's (RLIN) machine-readable data file. The library profession has begun to initiate large conversion projects as well, such as American Memory. While scholars have been making converted text available to one another, typically on disk or on CD-ROM, the clear trend is toward making these resources available through research and education networks. Thus, the American and French Research on the Treasury of the French Language (ARTFL) and the Dante Project are already available on Internet. MICHELSON summarized this section on interpretation and analysis by noting that: 1) increasing numbers of humanities scholars in the library community are recognizing the importance to the advancement of scholarship of retrospective conversion of source materials in the arts and humanities; and 2) there is a growing realization that making the sources available on research and education networks maximizes their usefulness for the analysis performed by humanities scholars. The fourth process of scholarly communication is dissemination of research findings, that is, publication. Scholars are using existing research and education networks to engineer a new type of publication: scholarly-controlled journals that are electronically produced and disseminated. Although such journals are still emerging as a communication format, their number has grown, from approximately twelve to thirty-six during the past year (July 1991 to June 1992). Most of these electronic scholarly journals are devoted to topics in the humanities. As with network conferences, scholarly enthusiasm for these electronic journals stems from the medium's unique ability to advance scholarship in a way that no other medium can do by supporting global feedback and interchange, practically in real time, early in the research process. Beyond scholarly journals, MICHELSON remarked the delivery of commercial full-text products, such as articles in professional journals, newsletters, magazines, wire services, and reference sources. These are being delivered via on-line local library catalogues, especially through CD-ROMs. Furthermore, according to MICHELSON, there is general optimism that the copyright and fees issues impeding the delivery of full text on existing research and education networks soon will be resolved. The final process of scholarly communication is curriculum development and instruction, and this involves the use of computer information technologies in two areas. The first is the development of computer-oriented instructional tools, which includes simulations, multimedia applications, and computer tools that are used to assist in the analysis of sources in the classroom, etc. The Perseus Project, a database that provides a multimedia curriculum on classical Greek civilization, is a good example of the way in which entire curricula are being recast using information technologies. It is anticipated that the current difficulty in exchanging electronically computer-based instructional software, which in turn makes it difficult for one scholar to build upon the work of others, will be resolved before too long. Stand-alone curricular applications that involve electronic text will be sharable through networks, reinforcing their significance as intellectual products as well as instructional tools. The second aspect of electronic learning involves the use of research and education networks for distance education programs. Such programs interactively link teachers with students in geographically scattered locations and rely on the availability of electronic instructional resources. Distance education programs are gaining wide appeal among state departments of education because of their demonstrated capacity to bring advanced specialized course work and an array of experts to many classrooms. A recent report found that at least 32 states operated at least one statewide network for education in 1991, with networks under development in many of the remaining states. MICHELSON summarized this section by noting two striking changes taking place in scholarly communication among humanities scholars. First is the extent to which electronic text in particular, and electronic resources in general, are being infused into each of the five processes described above. As mentioned earlier, there is a certain synergy at work here. The use of electronic resources for one process tends to stimulate its use for other processes, because the chief course of movement is toward a comprehensive on-line working context for humanities scholars that includes on-line availability of key bibliographies, scholarly feedback, sources, analytical tools, and publications. MICHELSON noted further that the movement toward a comprehensive on-line working context for humanities scholars is not new. In fact, it has been underway for more than forty years in the humanities, since Father Roberto Busa began developing an electronic concordance of the works of Saint Thomas Aquinas in 1949. What we are witnessing today, MICHELSON contended, is not the beginning of this on-line transition but, for at least some humanities scholars, the turning point in the transition from a print to an electronic working context. Coinciding with the on-line transition, the second striking change is the extent to which research and education networks are becoming the new medium of scholarly communication. The existing Internet and the pending National Education and Research Network (NREN) represent the new meeting ground where scholars are going for bibliographic information, scholarly dialogue and feedback, the most current publications in their field, and high-level educational offerings. Traditional scholarly practices are undergoing tremendous transformations as a result of the emergence and growing prominence of what is called network-mediated scholarship. MICHELSON next turned to the second element of the framework she proposed at the outset of her talk for evaluating the prospects for electronic text, namely the key information technology trends affecting the conduct of scholarly communication over the next decade: 1) end-user computing and 2) connectivity. End-user computing means that the person touching the keyboard, or performing computations, is the same as the person who initiates or consumes the computation. The emergence of personal computers, along with a host of other forces, such as ubiquitous computing, advances in interface design, and the on-line transition, is prompting the consumers of computation to do their own computing, and is thus rendering obsolete the traditional distinction between end users and ultimate users. The trend toward end-user computing is significant to consideration of the prospects for electronic texts because it means that researchers are becoming more adept at doing their own computations and, thus, more competent in the use of electronic media. By avoiding programmer intermediaries, computation is becoming central to the researcher's thought process. This direct involvement in computing is changing the researcher's perspective on the nature of research itself, that is, the kinds of questions that can be posed, the analytical methodologies that can be used, the types and amount of sources that are appropriate for analyses, and the form in which findings are presented. The trend toward end-user computing means that, increasingly, electronic media and computation are being infused into all processes of humanities scholarship, inspiring remarkable transformations in scholarly communication. The trend toward greater connectivity suggests that researchers are using computation increasingly in network environments. Connectivity is important to scholarship because it erases the distance that separates students from teachers and scholars from their colleagues, while allowing users to access remote databases, share information in many different media, connect to their working context wherever they are, and collaborate in all phases of research. The combination of the trend toward end-user computing and the trend toward connectivity suggests that the scholarly use of electronic resources, already evident among some researchers, will soon become an established feature of scholarship. The effects of these trends, along with ongoing changes in scholarly practices, point to a future in which humanities researchers will use computation and electronic communication to help them formulate ideas, access sources, perform research, collaborate with colleagues, seek peer review, publish and disseminate results, and engage in many other professional and educational activities. In summary, MICHELSON emphasized four points: 1) A portion of humanities scholars already consider electronic texts the preferred format for analysis and dissemination. 2) Scholars are using these electronic texts, in conjunction with other electronic resources, in all the processes of scholarly communication. 3) The humanities scholars' working context is in the process of changing from print technology to electronic technology, in many ways mirroring transformations that have occurred or are occurring within the scientific community. 4) These changes are occurring in conjunction with the development of a new communication medium: research and education networks that are characterized by their capacity to advance scholarship in a wholly unique way. MICHELSON also reiterated her three principal arguments: l) Electronic texts are best understood in terms of the relationship to other electronic resources and the growing prominence of network-mediated scholarship. 2) The prospects for electronic texts lie in their capacity to be integrated into the on-line network of electronic resources that comprise the new working context for scholars. 3) Retrospective conversion of portions of the scholarly record should be a key strategy as information providers respond to changes in scholarly communication practices. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ VECCIA * AM's evaluation project and public users of electronic resources * AM and its design * Site selection and evaluating the Macintosh implementation of AM * Characteristics of the six public libraries selected * Characteristics of AM's users in these libraries * Principal ways AM is being used * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Susan VECCIA, team leader, and Joanne FREEMAN, associate coordinator, American Memory, Library of Congress, gave a joint presentation. First, by way of introduction, VECCIA explained her and FREEMAN's roles in American Memory (AM). Serving principally as an observer, VECCIA has assisted with the evaluation project of AM, placing AM collections in a variety of different sites around the country and helping to organize and implement that project. FREEMAN has been an associate coordinator of AM and has been involved principally with the interpretative materials, preparing some of the electronic exhibits and printed historical information that accompanies AM and that is requested by users. VECCIA and FREEMAN shared anecdotal observations concerning AM with public users of electronic resources. Notwithstanding a fairly structured evaluation in progress, both VECCIA and FREEMAN chose not to report on specifics in terms of numbers, etc., because they felt it was too early in the evaluation project to do so. AM is an electronic archive of primary source materials from the Library of Congress, selected collections representing a variety of formats-- photographs, graphic arts, recorded sound, motion pictures, broadsides, and soon, pamphlets and books. In terms of the design of this system, the interpretative exhibits have been kept separate from the primary resources, with good reason. Accompanying this collection are printed documentation and user guides, as well as guides that FREEMAN prepared for teachers so that they may begin using the content of the system at once. VECCIA described the evaluation project before talking about the public users of AM, limiting her remarks to public libraries, because FREEMAN would talk more specifically about schools from kindergarten to twelfth grade (K-12). Having started in spring 1991, the evaluation currently involves testing of the Macintosh implementation of AM. Since the primary goal of this evaluation is to determine the most appropriate audience or audiences for AM, very different sites were selected. This makes evaluation difficult because of the varying degrees of technology literacy among the sites. AM is situated in forty-four locations, of which six are public libraries and sixteen are schools. Represented among the schools are elementary, junior high, and high schools. District offices also are involved in the evaluation, which will conclude in summer 1993. VECCIA focused the remainder of her talk on the six public libraries, one of which doubles as a state library. They represent a range of geographic areas and a range of demographic characteristics. For example, three are located in urban settings, two in rural settings, and one in a suburban setting. A range of technical expertise is to be found among these facilities as well. For example, one is an "Apple library of the future," while two others are rural one-room libraries--in one, AM sits at the front desk next to a tractor manual. All public libraries have been extremely enthusiastic, supportive, and appreciative of the work that AM has been doing. VECCIA characterized various users: Most users in public libraries describe themselves as general readers; of the students who use AM in the public libraries, those in fourth grade and above seem most interested. Public libraries in rural sites tend to attract retired people, who have been highly receptive to AM. Users tend to fall into two additional categories: people interested in the content and historical connotations of these primary resources, and those fascinated by the technology. The format receiving the most comments has been motion pictures. The adult users in public libraries are more comfortable with IBM computers, whereas young people seem comfortable with either IBM or Macintosh, although most of them seem to come from a Macintosh background. This same tendency is found in the schools. What kinds of things do users do with AM? In a public library there are two main goals or ways that AM is being used: as an individual learning tool, and as a leisure activity. Adult learning was one area that VECCIA would highlight as a possible application for a tool such as AM. She described a patron of a rural public library who comes in every day on his lunch hour and literally reads AM, methodically going through the collection image by image. At the end of his hour he makes an electronic bookmark, puts it in his pocket, and returns to work. The next day he comes in and resumes where he left off. Interestingly, this man had never been in the library before he used AM. In another small, rural library, the coordinator reports that AM is a popular activity for some of the older, retired people in the community, who ordinarily would not use "those things,"--computers. Another example of adult learning in public libraries is book groups, one of which, in particular, is using AM as part of its reading on industrialization, integration, and urbanization in the early 1900s. One library reports that a family is using AM to help educate their children. In another instance, individuals from a local museum came in to use AM to prepare an exhibit on toys of the past. These two examples emphasize the mission of the public library as a cultural institution, reaching out to people who do not have the same resources available to those who live in a metropolitan area or have access to a major library. One rural library reports that junior high school students in large numbers came in one afternoon to use AM for entertainment. A number of public libraries reported great interest among postcard collectors in the Detroit collection, which was essentially a collection of images used on postcards around the turn of the century. Train buffs are similarly interested because that was a time of great interest in railroading. People, it was found, relate to things that they know of firsthand. For example, in both rural public libraries where AM was made available, observers reported that the older people with personal remembrances of the turn of the century were gravitating to the Detroit collection. These examples served to underscore MICHELSON's observation re the integration of electronic tools and ideas--that people learn best when the material relates to something they know. VECCIA made the final point that in many cases AM serves as a public-relations tool for the public libraries that are testing it. In one case, AM is being used as a vehicle to secure additional funding for the library. In another case, AM has served as an inspiration to the staff of a major local public library in the South to think about ways to make its own collection of photographs more accessible to the public. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FREEMAN * AM and archival electronic resources in a school environment * Questions concerning context * Questions concerning the electronic format itself * Computer anxiety * Access and availability of the system * Hardware * Strengths gained through the use of archival resources in schools * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Reiterating an observation made by VECCIA, that AM is an archival resource made up of primary materials with very little interpretation, FREEMAN stated that the project has attempted to bridge the gap between these bare primary materials and a school environment, and in that cause has created guided introductions to AM collections. Loud demand from the educational community, chiefly from teachers working with the upper grades of elementary school through high school, greeted the announcement that AM would be tested around the country. FREEMAN reported not only on what was learned about AM in a school environment, but also on several universal questions that were raised concerning archival electronic resources in schools. She discussed several strengths of this type of material in a school environment as opposed to a highly structured resource that offers a limited number of paths to follow. FREEMAN first raised several questions about using AM in a school environment. There is often some difficulty in developing a sense of what the system contains. Many students sit down at a computer resource and assume that, because AM comes from the Library of Congress, all of American history is now at their fingertips. As a result of that sort of mistaken judgment, some students are known to conclude that AM contains nothing of use to them when they look for one or two things and do not find them. It is difficult to discover that middle ground where one has a sense of what the system contains. Some students grope toward the idea of an archive, a new idea to them, since they have not previously experienced what it means to have access to a vast body of somewhat random information. Other questions raised by FREEMAN concerned the electronic format itself. For instance, in a school environment it is often difficult both for teachers and students to gain a sense of what it is they are viewing. They understand that it is a visual image, but they do not necessarily know that it is a postcard from the turn of the century, a panoramic photograph, or even machine-readable text of an eighteenth-century broadside, a twentieth-century printed book, or a nineteenth-century diary. That distinction is often difficult for people in a school environment to grasp. Because of that, it occasionally becomes difficult to draw conclusions from what one is viewing. FREEMAN also noted the obvious fear of the computer, which constitutes a difficulty in using an electronic resource. Though students in general did not suffer from this anxiety, several older students feared that they were computer-illiterate, an assumption that became self-fulfilling when they searched for something but failed to find it. FREEMAN said she believed that some teachers also fear computer resources, because they believe they lack complete control. FREEMAN related the example of teachers shooing away students because it was not their time to use the system. This was a case in which the situation had to be extremely structured so that the teachers would not feel that they had lost their grasp on what the system contained. A final question raised by FREEMAN concerned access and availability of the system. She noted the occasional existence of a gap in communication between school librarians and teachers. Often AM sits in a school library and the librarian is the person responsible for monitoring the system. Teachers do not always take into their world new library resources about which the librarian is excited. Indeed, at the sites where AM had been used most effectively within a library, the librarian was required to go to specific teachers and instruct them in its use. As a result, several AM sites will have in-service sessions over a summer, in the hope that perhaps, with a more individualized link, teachers will be more likely to use the resource. A related issue in the school context concerned the number of workstations available at any one location. Centralization of equipment at the district level, with teachers invited to download things and walk away with them, proved unsuccessful because the hours these offices were open were also school hours. Another issue was hardware. As VECCIA observed, a range of sites exists, some technologically advanced and others essentially acquiring their first computer for the primary purpose of using it in conjunction with AM's testing. Users at technologically sophisticated sites want even more sophisticated hardware, so that they can perform even more sophisticated tasks with the materials in AM. But once they acquire a newer piece of hardware, they must learn how to use that also; at an unsophisticated site it takes an extremely long time simply to become accustomed to the computer, not to mention the program offered with the computer. All of these small issues raise one large question, namely, are systems like AM truly rewarding in a school environment, or do they simply act as innovative toys that do little more than spark interest? FREEMAN contended that the evaluation project has revealed several strengths that were gained through the use of archival resources in schools, including: * Psychic rewards from using AM as a vast, rich database, with teachers assigning various projects to students--oral presentations, written reports, a documentary, a turn-of-the-century newspaper-- projects that start with the materials in AM but are completed using other resources; AM thus is used as a research tool in conjunction with other electronic resources, as well as with books and items in the library where the system is set up. * Students are acquiring computer literacy in a humanities context. * This sort of system is overcoming the isolation between disciplines that often exists in schools. For example, many English teachers are requiring their students to write papers on historical topics represented in AM. Numerous teachers have reported that their students are learning critical thinking skills using the system. * On a broader level, AM is introducing primary materials, not only to students but also to teachers, in an environment where often simply none exist--an exciting thing for the students because it helps them learn to conduct research, to interpret, and to draw their own conclusions. In learning to conduct research and what it means, students are motivated to seek knowledge. That relates to another positive outcome--a high level of personal involvement of students with the materials in this system and greater motivation to conduct their own research and draw their own conclusions. * Perhaps the most ironic strength of these kinds of archival electronic resources is that many of the teachers AM interviewed were desperate, it is no exaggeration to say, not only for primary materials but for unstructured primary materials. These would, they thought, foster personally motivated research, exploration, and excitement in their students. Indeed, these materials have done just that. Ironically, however, this lack of structure produces some of the confusion to which the newness of these kinds of resources may also contribute. The key to effective use of archival products in a school environment is a clear, effective introduction to the system and to what it contains. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Nothing known, quantitatively, about the number of humanities scholars who must see the original versus those who would settle for an edited transcript, or about the ways in which humanities scholars are using information technology * Firm conclusions concerning the manner and extent of the use of supporting materials in print provided by AM to await completion of evaluative study * A listener's reflections on additional applications of electronic texts * Role of electronic resources in teaching elementary research skills to students * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the discussion that followed the presentations by MICHELSON, VECCIA, and FREEMAN, additional points emerged. LESK asked if MICHELSON could give any quantitative estimate of the number of humanities scholars who must see or want to see the original, or the best possible version of the material, versus those who typically would settle for an edited transcript. While unable to provide a figure, she offered her impressions as an archivist who has done some reference work and has discussed this issue with other archivists who perform reference, that those who use archives and those who use primary sources for what would be considered very high-level scholarly research, as opposed to, say, undergraduate papers, were few in number, especially given the public interest in using primary sources to conduct genealogical or avocational research and the kind of professional research done by people in private industry or the federal government. More important in MICHELSON's view was that, quantitatively, nothing is known about the ways in which, for example, humanities scholars are using information technology. No studies exist to offer guidance in creating strategies. The most recent study was conducted in 1985 by the American Council of Learned Societies (ACLS), and what it showed was that 50 percent of humanities scholars at that time were using computers. That constitutes the extent of our knowledge. Concerning AM's strategy for orienting people toward the scope of electronic resources, FREEMAN could offer no hard conclusions at this point, because she and her colleagues were still waiting to see, particularly in the schools, what has been made of their efforts. Within the system, however, AM has provided what are called electronic exhibits- -such as introductions to time periods and materials--and these are intended to offer a student user a sense of what a broadside is and what it might tell her or him. But FREEMAN conceded that the project staff would have to talk with students next year, after teachers have had a summer to use the materials, and attempt to discover what the students were learning from the materials. In addition, FREEMAN described supporting materials in print provided by AM at the request of local teachers during a meeting held at LC. These included time lines, bibliographies, and other materials that could be reproduced on a photocopier in a classroom. Teachers could walk away with and use these, and in this way gain a better understanding of the contents. But again, reaching firm conclusions concerning the manner and extent of their use would have to wait until next year. As to the changes she saw occurring at the National Archives and Records Administration (NARA) as a result of the increasing emphasis on technology in scholarly research, MICHELSON stated that NARA at this point was absorbing the report by her and Jeff Rothenberg addressing strategies for the archival profession in general, although not for the National Archives specifically. NARA is just beginning to establish its role and what it can do. In terms of changes and initiatives that NARA can take, no clear response could be given at this time. GREENFIELD remarked two trends mentioned in the session. Reflecting on DALY's opening comments on how he could have used a Latin collection of text in an electronic form, he said that at first he thought most scholars would be unwilling to do that. But as he thought of that in terms of the original meaning of research--that is, having already mastered these texts, researching them for critical and comparative purposes--for the first time, the electronic format made a lot of sense. GREENFIELD could envision growing numbers of scholars learning the new technologies for that very aspect of their scholarship and for convenience's sake. Listening to VECCIA and FREEMAN, GREENFIELD thought of an additional application of electronic texts. He realized that AM could be used as a guide to lead someone to original sources. Students cannot be expected to have mastered these sources, things they have never known about before. Thus, AM is leading them, in theory, to a vast body of information and giving them a superficial overview of it, enabling them to select parts of it. GREENFIELD asked if any evidence exists that this resource will indeed teach the new user, the K-12 students, how to do research. Scholars already know how to do research and are applying these new tools. But he wondered why students would go beyond picking out things that were most exciting to them. FREEMAN conceded the correctness of GREENFIELD's observation as applied to a school environment. The risk is that a student would sit down at a system, play with it, find some things of interest, and then walk away. But in the relatively controlled situation of a school library, much will depend on the instructions a teacher or a librarian gives a student. She viewed the situation not as one of fine-tuning research skills but of involving students at a personal level in understanding and researching things. Given the guidance one can receive at school, it then becomes possible to teach elementary research skills to students, which in fact one particular librarian said she was teaching her fifth graders. FREEMAN concluded that introducing the idea of following one's own path of inquiry, which is essentially what research entails, involves more than teaching specific skills. To these comments VECCIA added the observation that the individual teacher and the use of a creative resource, rather than AM itself, seemed to make the key difference. Some schools and some teachers are making excellent use of the nature of critical thinking and teaching skills, she said. Concurring with these remarks, DALY closed the session with the thought that the more that producers produced for teachers and for scholars to use with their students, the more successful their electronic products would prove. ****** SESSION II. SHOW AND TELL Jacqueline HESS, director, National Demonstration Laboratory, served as moderator of the "show-and-tell" session. She noted that a question-and-answer period would follow each presentation. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MYLONAS * Overview and content of Perseus * Perseus' primary materials exist in a system-independent, archival form * A concession * Textual aspects of Perseus * Tools to use with the Greek text * Prepared indices and full-text searches in Perseus * English-Greek word search leads to close study of words and concepts * Navigating Perseus by tracing down indices * Using the iconography to perform research * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Elli MYLONAS, managing editor, Perseus Project, Harvard University, first gave an overview of Perseus, a large, collaborative effort based at Harvard University but with contributors and collaborators located at numerous universities and colleges in the United States (e.g., Bowdoin, Maryland, Pomona, Chicago, Virginia). Funded primarily by the Annenberg/CPB Project, with additional funding from Apple, Harvard, and the Packard Humanities Institute, among others, Perseus is a multimedia, hypertextual database for teaching and research on classical Greek civilization, which was released in February 1992 in version 1.0 and distributed by Yale University Press. Consisting entirely of primary materials, Perseus includes ancient Greek texts and translations of those texts; catalog entries--that is, museum catalog entries, not library catalog entries--on vases, sites, coins, sculpture, and archaeological objects; maps; and a dictionary, among other sources. The number of objects and the objects for which catalog entries exist are accompanied by thousands of color images, which constitute a major feature of the database. Perseus contains approximately 30 megabytes of text, an amount that will double in subsequent versions. In addition to these primary materials, the Perseus Project has been building tools for using them, making access and navigation easier, the goal being to build part of the electronic environment discussed earlier in the morning in which students or scholars can work with their sources. The demonstration of Perseus will show only a fraction of the real work that has gone into it, because the project had to face the dilemma of what to enter when putting something into machine-readable form: should one aim for very high quality or make concessions in order to get the material in? Since Perseus decided to opt for very high quality, all of its primary materials exist in a system-independent--insofar as it is possible to be system-independent--archival form. Deciding what that archival form would be and attaining it required much work and thought. For example, all the texts are marked up in SGML, which will be made compatible with the guidelines of the Text Encoding Initiative (TEI) when they are issued. Drawings are postscript files, not meeting international standards, but at least designed to go across platforms. Images, or rather the real archival forms, consist of the best available slides, which are being digitized. Much of the catalog material exists in database form--a form that the average user could use, manipulate, and display on a personal computer, but only at great cost. Thus, this is where the concession comes in: All of this rich, well-marked-up information is stripped of much of its content; the images are converted into bit-maps and the text into small formatted chunks. All this information can then be imported into HyperCard and run on a mid-range Macintosh, which is what Perseus users have. This fact has made it possible for Perseus to attain wide use fairly rapidly. Without those archival forms the HyperCard version being demonstrated could not be made easily, and the project could not have the potential to move to other forms and machines and software as they appear, none of which information is in Perseus on the CD. Of the numerous multimedia aspects of Perseus, MYLONAS focused on the textual. Part of what makes Perseus such a pleasure to use, MYLONAS said, is this effort at seamless integration and the ability to move around both visual and textual material. Perseus also made the decision not to attempt to interpret its material any more than one interprets by selecting. But, MYLONAS emphasized, Perseus is not courseware: No syllabus exists. There is no effort to define how one teaches a topic using Perseus, although the project may eventually collect papers by people who have used it to teach. Rather, Perseus aims to provide primary material in a kind of electronic library, an electronic sandbox, so to say, in which students and scholars who are working on this material can explore by themselves. With that, MYLONAS demonstrated Perseus, beginning with the Perseus gateway, the first thing one sees upon opening Perseus--an effort in part to solve the contextualizing problem--which tells the user what the system contains. MYLONAS demonstrated only a very small portion, beginning with primary texts and running off the CD-ROM. Having selected Aeschylus' Prometheus Bound, which was viewable in Greek and English pretty much in the same segments together, MYLONAS demonstrated tools to use with the Greek text, something not possible with a book: looking up the dictionary entry form of an unfamiliar word in Greek after subjecting it to Perseus' morphological analysis for all the texts. After finding out about a word, a user may then decide to see if it is used anywhere else in Greek. Because vast amounts of indexing support all of the primary material, one can find out where else all forms of a particular Greek word appear-- often not a trivial matter because Greek is highly inflected. Further, since the story of Prometheus has to do with the origins of sacrifice, a user may wish to study and explore sacrifice in Greek literature; by typing sacrifice into a small window, a user goes to the English-Greek word list--something one cannot do without the computer (Perseus has indexed the definitions of its dictionary)--the string sacrifice appears in the definitions of these sixty-five words. One may then find out where any of those words is used in the work(s) of a particular author. The English definitions are not lemmatized. All of the indices driving this kind of usage were originally devised for speed, MYLONAS observed; in other words, all that kind of information-- all forms of all words, where they exist, the dictionary form they belong to--were collected into databases, which will expedite searching. Then it was discovered that one can do things searching in these databases that could not be done searching in the full texts. Thus, although there are full-text searches in Perseus, much of the work is done behind the scenes, using prepared indices. Re the indexing that is done behind the scenes, MYLONAS pointed out that without the SGML forms of the text, it could not be done effectively. Much of this indexing is based on the structures that are made explicit by the SGML tagging. It was found that one of the things many of Perseus' non-Greek-reading users do is start from the dictionary and then move into the close study of words and concepts via this kind of English-Greek word search, by which means they might select a concept. This exercise has been assigned to students in core courses at Harvard--to study a concept by looking for the English word in the dictionary, finding the Greek words, and then finding the words in the Greek but, of course, reading across in the English. That tells them a great deal about what a translation means as well. Should one also wish to see images that have to do with sacrifice, that person would go to the object key word search, which allows one to perform a similar kind of index retrieval on the database of archaeological objects. Without words, pictures are useless; Perseus has not reached the point where it can do much with images that are not cataloged. Thus, although it is possible in Perseus with text and images to navigate by knowing where one wants to end up--for example, a red-figure vase from the Boston Museum of Fine Arts--one can perform this kind of navigation very easily by tracing down indices. MYLONAS illustrated several generic scenes of sacrifice on vases. The features demonstrated derived from Perseus 1.0; version 2.0 will implement even better means of retrieval. MYLONAS closed by looking at one of the pictures and noting again that one can do a great deal of research using the iconography as well as the texts. For instance, students in a core course at Harvard this year were highly interested in Greek concepts of foreigners and representations of non-Greeks. So they performed a great deal of research, both with texts (e.g., Herodotus) and with iconography on vases and coins, on how the Greeks portrayed non-Greeks. At the same time, art historians who study iconography were also interested, and were able to use this material. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Indexing and searchability of all English words in Perseus * Several features of Perseus 1.0 * Several levels of customization possible * Perseus used for general education * Perseus' effects on education * Contextual information in Perseus * Main challenge and emphasis of Perseus * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Several points emerged in the discussion that followed MYLONAS's presentation. Although MYLONAS had not demonstrated Perseus' ability to cross-search documents, she confirmed that all English words in Perseus are indexed and can be searched. So, for example, sacrifice could have been searched in all texts, the historical essay, and all the catalogue entries with their descriptions--in short, in all of Perseus. Boolean logic is not in Perseus 1.0 but will be added to the next version, although an effort is being made not to restrict Perseus to a database in which one just performs searching, Boolean or otherwise. It is possible to move laterally through the documents by selecting a word one is interested in and selecting an area of information one is interested in and trying to look that word up in that area. Since Perseus was developed in HyperCard, several levels of customization are possible. Simple authoring tools exist that allow one to create annotated paths through the information, which are useful for note-taking and for guided tours for teaching purposes and for expository writing. With a little more ingenuity it is possible to begin to add or substitute material in Perseus. Perseus has not been used so much for classics education as for general education, where it seemed to have an impact on the students in the core course at Harvard (a general required course that students must take in certain areas). Students were able to use primary material much more. The Perseus Project has an evaluation team at the University of Maryland that has been documenting Perseus' effects on education. Perseus is very popular, and anecdotal evidence indicates that it is having an effect at places other than Harvard, for example, test sites at Ball State University, Drury College, and numerous small places where opportunities to use vast amounts of primary data may not exist. One documented effect is that archaeological, anthropological, and philological research is being done by the same person instead of by three different people. The contextual information in Perseus includes an overview essay, a fairly linear historical essay on the fifth century B.C. that provides links into the primary material (e.g., Herodotus, Thucydides, and Plutarch), via small gray underscoring (on the screen) of linked passages. These are handmade links into other material. To different extents, most of the production work was done at Harvard, where the people and the equipment are located. Much of the collaborative activity involved data collection and structuring, because the main challenge and the emphasis of Perseus is the gathering of primary material, that is, building a useful environment for studying classical Greece, collecting data, and making it useful. Systems-building is definitely not the main concern. Thus, much of the work has involved writing essays, collecting information, rewriting it, and tagging it. That can be done off site. The creative link for the overview essay as well as for both systems and data was collaborative, and was forged via E-mail and paper mail with professors at Pomona and Bowdoin. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CALALUCA * PLD's principal focus and contribution to scholarship * Various questions preparatory to beginning the project * Basis for project * Basic rule in converting PLD * Concerning the images in PLD * Running PLD under a variety of retrieval softwares * Encoding the database a hard-fought issue * Various features demonstrated * Importance of user documentation * Limitations of the CD-ROM version * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Eric CALALUCA, vice president, Chadwyck-Healey, Inc., demonstrated a software interpretation of the Patrologia Latina Database (PLD). PLD's principal focus from the beginning of the project about three-and-a-half years ago was on converting Migne's Latin series, and in the end, CALALUCA suggested, conversion of the text will be the major contribution to scholarship. CALALUCA stressed that, as possibly the only private publishing organization at the Workshop, Chadwyck-Healey had sought no federal funds or national foundation support before embarking upon the project, but instead had relied upon a great deal of homework and marketing to accomplish the task of conversion. Ever since the possibilities of computer-searching have emerged, scholars in the field of late ancient and early medieval studies (philosophers, theologians, classicists, and those studying the history of natural law and the history of the legal development of Western civilization) have been longing for a fully searchable version of Western literature, for example, all the texts of Augustine and Bernard of Clairvaux and Boethius, not to mention all the secondary and tertiary authors. Various questions arose, CALALUCA said. Should one convert Migne? Should the database be encoded? Is it necessary to do that? How should it be delivered? What about CD-ROM? Since this is a transitional medium, why even bother to create software to run on a CD-ROM? Since everybody knows people will be networking information, why go to the trouble--which is far greater with CD-ROM than with the production of magnetic data? Finally, how does one make the data available? Can many of the hurdles to using electronic information that some publishers have imposed upon databases be eliminated? The PLD project was based on the principle that computer-searching of texts is most effective when it is done with a large database. Because PLD represented a collection that serves so many disciplines across so many periods, it was irresistible. The basic rule in converting PLD was to do no harm, to avoid the sins of intrusion in such a database: no introduction of newer editions, no on-the-spot changes, no eradicating of all possible falsehoods from an edition. Thus, PLD is not the final act in electronic publishing for this discipline, but simply the beginning. The conversion of PLD has evoked numerous unanticipated questions: How will information be used? What about networking? Can the rights of a database be protected? Should one protect the rights of a database? How can it be made available? Those converting PLD also tried to avoid the sins of omission, that is, excluding portions of the collections or whole sections. What about the images? PLD is full of images, some are extremely pious nineteenth-century representations of the Fathers, while others contain highly interesting elements. The goal was to cover all the text of Migne (including notes, in Greek and in Hebrew, the latter of which, in particular, causes problems in creating a search structure), all the indices, and even the images, which are being scanned in separately searchable files. Several North American institutions that have placed acquisition requests for the PLD database have requested it in magnetic form without software, which means they are already running it without software, without anything demonstrated at the Workshop. What cannot practically be done is go back and reconvert and re-encode data, a time-consuming and extremely costly enterprise. CALALUCA sees PLD as a database that can, and should, be run under a variety of retrieval softwares. This will permit the widest possible searches. Consequently, the need to produce a CD-ROM of PLD, as well as to develop software that could handle some 1.3 gigabyte of heavily encoded text, developed out of conversations with collection development and reference librarians who wanted software both compassionate enough for the pedestrian but also capable of incorporating the most detailed lexicographical studies that a user desires to conduct. In the end, the encoding and conversion of the data will prove the most enduring testament to the value of the project. The encoding of the database was also a hard-fought issue: Did the database need to be encoded? Were there normative structures for encoding humanist texts? Should it be SGML? What about the TEI--will it last, will it prove useful? CALALUCA expressed some minor doubts as to whether a data bank can be fully TEI-conformant. Every effort can be made, but in the end to be TEI-conformant means to accept the need to make some firm encoding decisions that can, indeed, be disputed. The TEI points the publisher in a proper direction but does not presume to make all the decisions for him or her. Essentially, the goal of encoding was to eliminate, as much as possible, the hindrances to information-networking, so that if an institution acquires a database, everybody associated with the institution can have access to it. CALALUCA demonstrated a portion of Volume 160, because it had the most anomalies in it. The software was created by Electronic Book Technologies of Providence, RI, and is called Dynatext. The software works only with SGML-coded data. Viewing a table of contents on the screen, the audience saw how Dynatext treats each element as a book and attempts to simplify movement through a volume. Familiarity with the Patrologia in print (i.e., the text, its source, and the editions) will make the machine-readable versions highly useful. (Software with a Windows application was sought for PLD, CALALUCA said, because this was the main trend for scholarly use.) CALALUCA also demonstrated how a user can perform a variety of searches and quickly move to any part of a volume; the look-up screen provides some basic, simple word-searching. CALALUCA argued that one of the major difficulties is not the software. Rather, in creating a product that will be used by scholars representing a broad spectrum of computer sophistication, user documentation proves to be the most important service one can provide. CALALUCA next illustrated a truncated search under mysterium within ten words of virtus and how one would be able to find its contents throughout the entire database. He said that the exciting thing about PLD is that many of the applications in the retrieval software being written for it will exceed the capabilities of the software employed now for the CD-ROM version. The CD-ROM faces genuine limitations, in terms of speed and comprehensiveness, in the creation of a retrieval software to run it. CALALUCA said he hoped that individual scholars will download the data, if they wish, to their personal computers, and have ready access to important texts on a constant basis, which they will be able to use in their research and from which they might even be able to publish. (CALALUCA explained that the blue numbers represented Migne's column numbers, which are the standard scholarly references. Pulling up a note, he stated that these texts were heavily edited and the image files would appear simply as a note as well, so that one could quickly access an image.) ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLEISCHHAUER/ERWAY * Several problems with which AM is still wrestling * Various search and retrieval capabilities * Illustration of automatic stemming and a truncated search * AM's attempt to find ways to connect cataloging to the texts * AM's gravitation towards SGML * Striking a balance between quantity and quality * How AM furnishes users recourse to images * Conducting a search in a full-text environment * Macintosh and IBM prototypes of AM * Multimedia aspects of AM * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ A demonstration of American Memory by its coordinator, Carl FLEISCHHAUER, and Ricky ERWAY, associate coordinator, Library of Congress, concluded the morning session. Beginning with a collection of broadsides from the Continental Congress and the Constitutional Convention, the only text collection in a presentable form at the time of the Workshop, FLEISCHHAUER highlighted several of the problems with which AM is still wrestling. (In its final form, the disk will contain two collections, not only the broadsides but also the full text with illustrations of a set of approximately 300 African-American pamphlets from the period 1870 to 1910.) As FREEMAN had explained earlier, AM has attempted to use a small amount of interpretation to introduce collections. In the present case, the contractor, a company named Quick Source, in Silver Spring, MD., used software called Toolbook and put together a modestly interactive introduction to the collection. Like the two preceding speakers, FLEISCHHAUER argued that the real asset was the underlying collection. FLEISCHHAUER proceeded to describe various search and retrieval capabilities while ERWAY worked the computer. In this particular package the "go to" pull-down allowed the user in effect to jump out of Toolbook, where the interactive program was located, and enter the third-party software used by AM for this text collection, which is called Personal Librarian. This was the Windows version of Personal Librarian, a software application put together by a company in Rockville, Md. Since the broadsides came from the Revolutionary War period, a search was conducted using the words British or war, with the default operator reset as or. FLEISCHHAUER demonstrated both automatic stemming (which finds other forms of the same root) and a truncated search. One of Personal Librarian's strongest features, the relevance ranking, was represented by a chart that indicated how often words being sought appeared in documents, with the one receiving the most "hits" obtaining the highest score. The "hit list" that is supplied takes the relevance ranking into account, making the first hit, in effect, the one the software has selected as the most relevant example. While in the text of one of the broadside documents, FLEISCHHAUER remarked AM's attempt to find ways to connect cataloging to the texts, which it does in different ways in different manifestations. In the case shown, the cataloging was pasted on: AM took MARC records that were written as on-line records right into one of the Library's mainframe retrieval programs, pulled them out, and handed them off to the contractor, who massaged them somewhat to display them in the manner shown. One of AM's questions is, Does the cataloguing normally performed in the mainframe work in this context, or had AM ought to think through adjustments? FLEISCHHAUER made the additional point that, as far as the text goes, AM has gravitated towards SGML (he pointed to the boldface in the upper part of the screen). Although extremely limited in its ability to translate or interpret SGML, Personal Librarian will furnish both bold and italics on screen; a fairly easy thing to do, but it is one of the ways in which SGML is useful. Striking a balance between quantity and quality has been a major concern of AM, with accuracy being one of the places where project staff have felt that less than 100-percent accuracy was not unacceptable. FLEISCHHAUER cited the example of the standard of the rekeying industry, namely 99.95 percent; as one service bureau informed him, to go from 99.95 to 100 percent would double the cost. FLEISCHHAUER next demonstrated how AM furnishes users recourse to images, and at the same time recalled LESK's pointed question concerning the number of people who would look at those images and the number who would work only with the text. If the implication of LESK's question was sound, FLEISCHHAUER said, it raised the stakes for text accuracy and reduced the value of the strategy for images. Contending that preservation is always a bugaboo, FLEISCHHAUER demonstrated several images derived from a scan of a preservation microfilm that AM had made. He awarded a grade of C at best, perhaps a C minus or a C plus, for how well it worked out. Indeed, the matter of learning if other people had better ideas about scanning in general, and, in particular, scanning from microfilm, was one of the factors that drove AM to attempt to think through the agenda for the Workshop. Skew, for example, was one of the issues that AM in its ignorance had not reckoned would prove so difficult. Further, the handling of images of the sort shown, in a desktop computer environment, involved a considerable amount of zooming and scrolling. Ultimately, AM staff feel that perhaps the paper copy that is printed out might be the most useful one, but they remain uncertain as to how much on-screen reading users will do. Returning to the text, FLEISCHHAUER asked viewers to imagine a person who might be conducting a search in a full-text environment. With this scenario, he proceeded to illustrate other features of Personal Librarian that he considered helpful; for example, it provides the ability to notice words as one reads. Clicking the "include" button on the bottom of the search window pops the words that have been highlighted into the search. Thus, a user can refine the search as he or she reads, re-executing the search and continuing to find things in the quest for materials. This software not only contains relevance ranking, Boolean operators, and truncation, it also permits one to perform word algebra, so to say, where one puts two or three words in parentheses and links them with one Boolean operator and then a couple of words in another set of parentheses and asks for things within so many words of others. Until they became acquainted recently with some of the work being done in classics, the AM staff had not realized that a large number of the projects that involve electronic texts were being done by people with a profound interest in language and linguistics. Their search strategies and thinking are oriented to those fields, as is shown in particular by the Perseus example. As amateur historians, the AM staff were thinking more of searching for concepts and ideas than for particular words. Obviously, FLEISCHHAUER conceded, searching for concepts and ideas and searching for words may be two rather closely related things. While displaying several images, FLEISCHHAUER observed that the Macintosh prototype built by AM contains a greater diversity of formats. Echoing a previous speaker, he said that it was easier to stitch things together in the Macintosh, though it tended to be a little more anemic in search and retrieval. AM, therefore, increasingly has been investigating sophisticated retrieval engines in the IBM format. FLEISCHHAUER demonstrated several additional examples of the prototype interfaces: One was AM's metaphor for the network future, in which a kind of reading-room graphic suggests how one would be able to go around to different materials. AM contains a large number of photographs in analog video form worked up from a videodisc, which enable users to make copies to print or incorporate in digital documents. A frame-grabber is built into the system, making it possible to bring an image into a window and digitize or print it out. FLEISCHHAUER next demonstrated sound recording, which included texts. Recycled from a previous project, the collection included sixty 78-rpm phonograph records of political speeches that were made during and immediately after World War I. These constituted approximately three hours of audio, as AM has digitized it, which occupy 150 megabytes on a CD. Thus, they are considerably compressed. From the catalogue card, FLEISCHHAUER proceeded to a transcript of a speech with the audio available and with highlighted text following it as it played. A photograph has been added and a transcription made. Considerable value has been added beyond what the Library of Congress normally would do in cataloguing a sound recording, which raises several questions for AM concerning where to draw lines about how much value it can afford to add and at what point, perhaps, this becomes more than AM could reasonably do or reasonably wish to do. FLEISCHHAUER also demonstrated a motion picture. As FREEMAN had reported earlier, the motion picture materials have proved the most popular, not surprisingly. This says more about the medium, he thought, than about AM's presentation of it. Because AM's goal was to bring together things that could be used by historians or by people who were curious about history, turn-of-the-century footage seemed to represent the most appropriate collections from the Library of Congress in motion pictures. These were the very first films made by Thomas Edison's company and some others at that time. The particular example illustrated was a Biograph film, brought in with a frame-grabber into a window. A single videodisc contains about fifty titles and pieces of film from that period, all of New York City. Taken together, AM believes, they provide an interesting documentary resource. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Using the frame-grabber in AM * Volume of material processed and to be processed * Purpose of AM within LC * Cataloguing and the nature of AM's material * SGML coding and the question of quality versus quantity * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the question-and-answer period that followed FLEISCHHAUER's presentation, several clarifications were made. AM is bringing in motion pictures from a videodisc. The frame-grabber devices create a window on a computer screen, which permits users to digitize a single frame of the movie or one of the photographs. It produces a crude, rough-and-ready image that high school students can incorporate into papers, and that has worked very nicely in this way. Commenting on FLEISCHHAUER's assertion that AM was looking more at searching ideas than words, MYLONAS argued that without words an idea does not exist. FLEISCHHAUER conceded that he ought to have articulated his point more clearly. MYLONAS stated that they were in fact both talking about the same thing. By searching for words and by forcing people to focus on the word, the Perseus Project felt that they would get them to the idea. The way one reviews results is tailored more to one kind of user than another. Concerning the total volume of material that has been processed in this way, AM at this point has in retrievable form seven or eight collections, all of them photographic. In the Macintosh environment, for example, there probably are 35,000-40,000 photographs. The sound recordings number sixty items. The broadsides number about 300 items. There are 500 political cartoons in the form of drawings. The motion pictures, as individual items, number sixty to seventy. AM also has a manuscript collection, the life history portion of one of the federal project series, which will contain 2,900 individual documents, all first-person narratives. AM has in process about 350 African-American pamphlets, or about 12,000 printed pages for the period 1870-1910. Also in the works are some 4,000 panoramic photographs. AM has recycled a fair amount of the work done by LC's Prints and Photographs Division during the Library's optical disk pilot project in the 1980s. For example, a special division of LC has tooled up and thought through all the ramifications of electronic presentation of photographs. Indeed, they are wheeling them out in great barrel loads. The purpose of AM within the Library, it is hoped, is to catalyze several of the other special collection divisions which have no particular experience with, in some cases, mixed feelings about, an activity such as AM. Moreover, in many cases the divisions may be characterized as not only lacking experience in "electronifying" things but also in automated cataloguing. MARC cataloguing as practiced in the United States is heavily weighted toward the description of monograph and serial materials, but is much thinner when one enters the world of manuscripts and things that are held in the Library's music collection and other units. In response to a comment by LESK, that AM's material is very heavily photographic, and is so primarily because individual records have been made for each photograph, FLEISCHHAUER observed that an item-level catalog record exists, for example, for each photograph in the Detroit Publishing collection of 25,000 pictures. In the case of the Federal Writers Project, for which nearly 3,000 documents exist, representing information from twenty-six different states, AM with the assistance of Karen STUART of the Manuscript Division will attempt to find some way not only to have a collection-level record but perhaps a MARC record for each state, which will then serve as an umbrella for the 100-200 documents that come under it. But that drama remains to be enacted. The AM staff is conservative and clings to cataloguing, though of course visitors tout artificial intelligence and neural networks in a manner that suggests that perhaps one need not have cataloguing or that much of it could be put aside. The matter of SGML coding, FLEISCHHAUER conceded, returned the discussion to the earlier treated question of quality versus quantity in the Library of Congress. Of course, text conversion can be done with 100-percent accuracy, but it means that when one's holdings are as vast as LC's only a tiny amount will be exposed, whereas permitting lower levels of accuracy can lead to exposing or sharing larger amounts, but with the quality correspondingly impaired. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TWOHIG * A contrary experience concerning electronic options * Volume of material in the Washington papers and a suggestion of David Packard * Implications of Packard's suggestion * Transcribing the documents for the CD-ROM * Accuracy of transcriptions * The CD-ROM edition of the Founding Fathers documents * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Finding encouragement in a comment of MICHELSON's from the morning session--that numerous people in the humanities were choosing electronic options to do their work--Dorothy TWOHIG, editor, The Papers of George Washington, opened her illustrated talk by noting that her experience with literary scholars and numerous people in editing was contrary to MICHELSON's. TWOHIG emphasized literary scholars' complete ignorance of the technological options available to them or their reluctance or, in some cases, their downright hostility toward these options. After providing an overview of the five Founding Fathers projects (Jefferson at Princeton, Franklin at Yale, John Adams at the Massachusetts Historical Society, and Madison down the hall from her at the University of Virginia), TWOHIG observed that the Washington papers, like all of the projects, include both sides of the Washington correspondence and deal with some 135,000 documents to be published with extensive annotation in eighty to eighty-five volumes, a project that will not be completed until well into the next century. Thus, it was with considerable enthusiasm several years ago that the Washington Papers Project (WPP) greeted David Packard's suggestion that the papers of the Founding Fathers could be published easily and inexpensively, and to the great benefit of American scholarship, via CD-ROM. In pragmatic terms, funding from the Packard Foundation would expedite the transcription of thousands of documents waiting to be put on disk in the WPP offices. Further, since the costs of collecting, editing, and converting the Founding Fathers documents into letterpress editions were running into the millions of dollars, and the considerable staffs involved in all of these projects were devoting their careers to producing the work, the Packard Foundation's suggestion had a revolutionary aspect: Transcriptions of the entire corpus of the Founding Fathers papers would be available on CD-ROM to public and college libraries, even high schools, at a fraction of the cost-- $100-$150 for the annual license fee--to produce a limited university press run of 1,000 of each volume of the published papers at $45-$150 per printed volume. Given the current budget crunch in educational systems and the corresponding constraints on librarians in smaller institutions who wish to add these volumes to their collections, producing the documents on CD-ROM would likely open a greatly expanded audience for the papers. TWOHIG stressed, however, that development of the Founding Fathers CD-ROM is still in its infancy. Serious software problems remain to be resolved before the material can be put into readable form. Funding from the Packard Foundation resulted in a major push to transcribe the 75,000 or so documents of the Washington papers remaining to be transcribed onto computer disks. Slides illustrated several of the problems encountered, for example, the present inability of CD-ROM to indicate the cross-outs (deleted material) in eighteenth century documents. TWOHIG next described documents from various periods in the eighteenth century that have been transcribed in chronological order and delivered to the Packard offices in California, where they are converted to the CD-ROM, a process that is expected to consume five years to complete (that is, reckoning from David Packard's suggestion made several years ago, until about July 1994). TWOHIG found an encouraging indication of the project's benefits in the ongoing use made by scholars of the search functions of the CD-ROM, particularly in reducing the time spent in manually turning the pages of the Washington papers. TWOHIG next furnished details concerning the accuracy of transcriptions. For instance, the insertion of thousands of documents on the CD-ROM currently does not permit each document to be verified against the original manuscript several times as in the case of documents that appear in the published edition. However, the transcriptions receive a cursory check for obvious typos, the misspellings of proper names, and other errors from the WPP CD-ROM editor. Eventually, all documents that appear in the electronic version will be checked by project editors. Although this process has met with opposition from some of the editors on the grounds that imperfect work may leave their offices, the advantages in making this material available as a research tool outweigh fears about the misspelling of proper names and other relatively minor editorial matters. Completion of all five Founding Fathers projects (i.e., retrievability and searchability of all of the documents by proper names, alternate spellings, or varieties of subjects) will provide one of the richest sources of this size for the history of the United States in the latter part of the eighteenth century. Further, publication on CD-ROM will allow editors to include even minutiae, such as laundry lists, not included in the printed volumes. It seems possible that the extensive annotation provided in the printed volumes eventually will be added to the CD-ROM edition, pending negotiations with the publishers of the papers. At the moment, the Founding Fathers CD-ROM is accessible only on the IBYCUS, a computer developed out of the Thesaurus Linguae Graecae project and designed for the use of classical scholars. There are perhaps 400 IBYCUS computers in the country, most of which are in university classics departments. Ultimately, it is anticipated that the CD-ROM edition of the Founding Fathers documents will run on any IBM-compatible or Macintosh computer with a CD-ROM drive. Numerous changes in the software will also occur before the project is completed. (Editor's note: an IBYCUS was unavailable to demonstrate the CD-ROM.) ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Several additional features of WPP clarified * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Discussion following TWOHIG's presentation served to clarify several additional features, including (1) that the project's primary intellectual product consists in the electronic transcription of the material; (2) that the text transmitted to the CD-ROM people is not marked up; (3) that cataloging and subject-indexing of the material remain to be worked out (though at this point material can be retrieved by name); and (4) that because all the searching is done in the hardware, the IBYCUS is designed to read a CD-ROM which contains only sequential text files. Technically, it then becomes very easy to read the material off and put it on another device. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LEBRON * Overview of the history of the joint project between AAAS and OCLC * Several practices the on-line environment shares with traditional publishing on hard copy * Several technical and behavioral barriers to electronic publishing * How AAAS and OCLC arrived at the subject of clinical trials * Advantages of the electronic format and other features of OJCCT * An illustrated tour of the journal * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Maria LEBRON, managing editor, The Online Journal of Current Clinical Trials (OJCCT), presented an illustrated overview of the history of the joint project between the American Association for the Advancement of Science (AAAS) and the Online Computer Library Center, Inc. (OCLC). The joint venture between AAAS and OCLC owes its beginning to a reorganization launched by the new chief executive officer at OCLC about three years ago and combines the strengths of these two disparate organizations. In short, OJCCT represents the process of scholarly publishing on line. LEBRON next discussed several practices the on-line environment shares with traditional publishing on hard copy--for example, peer review of manuscripts--that are highly important in the academic world. LEBRON noted in particular the implications of citation counts for tenure committees and grants committees. In the traditional hard-copy environment, citation counts are readily demonstrable, whereas the on-line environment represents an ethereal medium to most academics. LEBRON remarked several technical and behavioral barriers to electronic publishing, for instance, the problems in transmission created by special characters or by complex graphics and halftones. In addition, she noted economic limitations such as the storage costs of maintaining back issues and market or audience education. Manuscripts cannot be uploaded to OJCCT, LEBRON explained, because it is not a bulletin board or E-mail, forms of electronic transmission of information that have created an ambience clouding people's understanding of what the journal is attempting to do. OJCCT, which publishes peer-reviewed medical articles dealing with the subject of clinical trials, includes text, tabular material, and graphics, although at this time it can transmit only line illustrations. Next, LEBRON described how AAAS and OCLC arrived at the subject of clinical trials: It is 1) a highly statistical discipline that 2) does not require halftones but can satisfy the needs of its audience with line illustrations and graphic material, and 3) there is a need for the speedy dissemination of high-quality research results. Clinical trials are research activities that involve the administration of a test treatment to some experimental unit in order to test its usefulness before it is made available to the general population. LEBRON proceeded to give additional information on OJCCT concerning its editor-in-chief, editorial board, editorial content, and the types of articles it publishes (including peer-reviewed research reports and reviews), as well as features shared by other traditional hard-copy journals. Among the advantages of the electronic format are faster dissemination of information, including raw data, and the absence of space constraints because pages do not exist. (This latter fact creates an interesting situation when it comes to citations.) Nor are there any issues. AAAS's capacity to download materials directly from the journal to a subscriber's printer, hard drive, or floppy disk helps ensure highly accurate transcription. Other features of OJCCT include on-screen alerts that allow linkage of subsequently published documents to the original documents; on-line searching by subject, author, title, etc.; indexing of every single word that appears in an article; viewing access to an article by component (abstract, full text, or graphs); numbered paragraphs to replace page counts; publication in Science every thirty days of indexing of all articles published in the journal; typeset-quality screens; and Hypertext links that enable subscribers to bring up Medline abstracts directly without leaving the journal. After detailing the two primary ways to gain access to the journal, through the OCLC network and Compuserv if one desires graphics or through the Internet if just an ASCII file is desired, LEBRON illustrated the speedy editorial process and the coding of the document using SGML tags after it has been accepted for publication. She also gave an illustrated tour of the journal, its search-and-retrieval capabilities in particular, but also including problems associated with scanning in illustrations, and the importance of on-screen alerts to the medical profession re retractions or corrections, or more frequently, editorials, letters to the editors, or follow-up reports. She closed by inviting the audience to join AAAS on 1 July, when OJCCT was scheduled to go on-line. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Additional features of OJCCT * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ In the lengthy discussion that followed LEBRON's presentation, these points emerged: * The SGML text can be tailored as users wish. * All these articles have a fairly simple document definition. * Document-type definitions (DTDs) were developed and given to OJCCT for coding. * No articles will be removed from the journal. (Because there are no back issues, there are no lost issues either. Once a subscriber logs onto the journal he or she has access not only to the currently published materials, but retrospectively to everything that has been published in it. Thus the table of contents grows bigger. The date of publication serves to distinguish between currently published materials and older materials.) * The pricing system for the journal resembles that for most medical journals: for 1992, $95 for a year, plus telecommunications charges (there are no connect time charges); for 1993, $110 for the entire year for single users, though the journal can be put on a local area network (LAN). However, only one person can access the journal at a time. Site licenses may come in the future. * AAAS is working closely with colleagues at OCLC to display mathematical equations on screen. * Without compromising any steps in the editorial process, the technology has reduced the time lag between when a manuscript is originally submitted and the time it is accepted; the review process does not differ greatly from the standard six-to-eight weeks employed by many of the hard-copy journals. The process still depends on people. * As far as a preservation copy is concerned, articles will be maintained on the computer permanently and subscribers, as part of their subscription, will receive a microfiche-quality archival copy of everything published during that year; in addition, reprints can be purchased in much the same way as in a hard-copy environment. Hard copies are prepared but are not the primary medium for the dissemination of the information. * Because OJCCT is not yet on line, it is difficult to know how many people would simply browse through the journal on the screen as opposed to downloading the whole thing and printing it out; a mix of both types of users likely will result. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PERSONIUS * Developments in technology over the past decade * The CLASS Project * Advantages for technology and for the CLASS Project * Developing a network application an underlying assumption of the project * Details of the scanning process * Print-on-demand copies of books * Future plans include development of a browsing tool * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Lynne PERSONIUS, assistant director, Cornell Information Technologies for Scholarly Information Services, Cornell University, first commented on the tremendous impact that developments in technology over the past ten years--networking, in particular--have had on the way information is handled, and how, in her own case, these developments have counterbalanced Cornell's relative geographical isolation. Other significant technologies include scanners, which are much more sophisticated than they were ten years ago; mass storage and the dramatic savings that result from it in terms of both space and money relative to twenty or thirty years ago; new and improved printing technologies, which have greatly affected the distribution of information; and, of course, digital technologies, whose applicability to library preservation remains at issue. Given that context, PERSONIUS described the College Library Access and Storage System (CLASS) Project, a library preservation project, primarily, and what has been accomplished. Directly funded by the Commission on Preservation and Access and by the Xerox Corporation, which has provided a significant amount of hardware, the CLASS Project has been working with a development team at Xerox to develop a software application tailored to library preservation requirements. Within Cornell, participants in the project have been working jointly with both library and information technologies. The focus of the project has been on reformatting and saving books that are in brittle condition. PERSONIUS showed Workshop participants a brittle book, and described how such books were the result of developments in papermaking around the beginning of the Industrial Revolution. The papermaking process was changed so that a significant amount of acid was introduced into the actual paper itself, which deteriorates as it sits on library shelves. One of the advantages for technology and for the CLASS Project is that the information in brittle books is mostly out of copyright and thus offers an opportunity to work with material that requires library preservation, and to create and work on an infrastructure to save the material. Acknowledging the familiarity of those working in preservation with this information, PERSONIUS noted that several things are being done: the primary preservation technology used today is photocopying of brittle material. Saving the intellectual content of the material is the main goal. With microfilm copy, the intellectual content is preserved on the assumption that in the future the image can be reformatted in any other way that then exists. An underlying assumption of the CLASS Project from the beginning was that it would develop a network application. Project staff scan books at a workstation located in the library, near the brittle material. An image-server filing system is located at a distance from that workstation, and a printer is located in another building. All of the materials digitized and stored on the image-filing system are cataloged in the on-line catalogue. In fact, a record for each of these electronic books is stored in the RLIN database so that a record exists of what is in the digital library throughout standard catalogue procedures. In the future, researchers working from their own workstations in their offices, or their networks, will have access--wherever they might be--through a request server being built into the new digital library. A second assumption is that the preferred means of finding the material will be by looking through a catalogue. PERSONIUS described the scanning process, which uses a prototype scanner being developed by Xerox and which scans a very high resolution image at great speed. Another significant feature, because this is a preservation application, is the placing of the pages that fall apart one for one on the platen. Ordinarily, a scanner could be used with some sort of a document feeder, but because of this application that is not feasible. Further, because CLASS is a preservation application, after the paper replacement is made there, a very careful quality control check is performed. An original book is compared to the printed copy and verification is made, before proceeding, that all of the image, all of the information, has been captured. Then, a new library book is produced: The printed images are rebound by a commercial binder and a new book is returned to the shelf. Significantly, the books returned to the library shelves are beautiful and useful replacements on acid-free paper that should last a long time, in effect, the equivalent of preservation photocopies. Thus, the project has a library of digital books. In essence, CLASS is scanning and storing books as 600 dot-per-inch bit-mapped images, compressed using Group 4 CCITT (i.e., the French acronym for International Consultative Committee for Telegraph and Telephone) compression. They are stored as TIFF files on an optical filing system that is composed of a database used for searching and locating the books and an optical jukebox that stores 64 twelve-inch platters. A very-high-resolution printed copy of these books at 600 dots per inch is created, using a Xerox DocuTech printer to make the paper replacements on acid-free paper. PERSONIUS maintained that the CLASS Project presents an opportunity to introduce people to books as digital images by using a paper medium. Books are returned to the shelves while people are also given the ability to print on demand--to make their own copies of books. (PERSONIUS distributed copies of an engineering journal published by engineering students at Cornell around 1900 as an example of what a print-on-demand copy of material might be like. This very cheap copy would be available to people to use for their own research purposes and would bridge the gap between an electronic work and the paper that readers like to have.) PERSONIUS then attempted to illustrate a very early prototype of networked access to this digital library. Xerox Corporation has developed a prototype of a view station that can send images across the network to be viewed. The particular library brought down for demonstration contained two mathematics books. CLASS is developing and will spend the next year developing an application that allows people at workstations to browse the books. Thus, CLASS is developing a browsing tool, on the assumption that users do not want to read an entire book from a workstation, but would prefer to be able to look through and decide if they would like to have a printed copy of it. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Re retrieval software * "Digital file copyright" * Scanning rate during production * Autosegmentation * Criteria employed in selecting books for scanning * Compression and decompression of images * OCR not precluded * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the question-and-answer period that followed her presentation, PERSONIUS made these additional points: * Re retrieval software, Cornell is developing a Unix-based server as well as clients for the server that support multiple platforms (Macintosh, IBM and Sun workstations), in the hope that people from any of those platforms will retrieve books; a further operating assumption is that standard interfaces will be used as much as possible, where standards can be put in place, because CLASS considers this retrieval software a library application and would like to be able to look at material not only at Cornell but at other institutions. * The phrase "digital file copyright by Cornell University" was added at the advice of Cornell's legal staff with the caveat that it probably would not hold up in court. Cornell does not want people to copy its books and sell them but would like to keep them available for use in a library environment for library purposes. * In production the scanner can scan about 300 pages per hour, capturing 600 dots per inch. * The Xerox software has filters to scan halftone material and avoid the moire patterns that occur when halftone material is scanned. Xerox has been working on hardware and software that would enable the scanner itself to recognize this situation and deal with it appropriately--a kind of autosegmentation that would enable the scanner to handle halftone material as well as text on a single page. * The books subjected to the elaborate process described above were selected because CLASS is a preservation project, with the first 500 books selected coming from Cornell's mathematics collection, because they were still being heavily used and because, although they were in need of preservation, the mathematics library and the mathematics faculty were uncomfortable having them microfilmed. (They wanted a printed copy.) Thus, these books became a logical choice for this project. Other books were chosen by the project's selection committees for experiments with the technology, as well as to meet a demand or need. * Images will be decompressed before they are sent over the line; at this time they are compressed and sent to the image filing system and then sent to the printer as compressed images; they are returned to the workstation as compressed 600-dpi images and the workstation decompresses and scales them for display--an inefficient way to access the material though it works quite well for printing and other purposes. * CLASS is also decompressing on Macintosh and IBM, a slow process right now. Eventually, compression and decompression will take place on an image conversion server. Trade-offs will be made, based on future performance testing, concerning where the file is compressed and what resolution image is sent. * OCR has not been precluded; images are being stored that have been scanned at a high resolution, which presumably would suit them well to an OCR process. Because the material being scanned is about 100 years old and was printed with less-than-ideal technologies, very early and preliminary tests have not produced good results. But the project is capturing an image that is of sufficient resolution to be subjected to OCR in the future. Moreover, the system architecture and the system plan have a logical place to store an OCR image if it has been captured. But that is not being done now. ****** SESSION III. DISTRIBUTION, NETWORKS, AND NETWORKING: OPTIONS FOR DISSEMINATION +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ZICH * Issues pertaining to CD-ROMs * Options for publishing in CD-ROM * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Robert ZICH, special assistant to the associate librarian for special projects, Library of Congress, and moderator of this session, first noted the blessed but somewhat awkward circumstance of having four very distinguished people representing networks and networking or at least leaning in that direction, while lacking anyone to speak from the strongest possible background in CD-ROMs. ZICH expressed the hope that members of the audience would join the discussion. He stressed the subtitle of this particular session, "Options for Dissemination," and, concerning CD-ROMs, the importance of determining when it would be wise to consider dissemination in CD-ROM versus networks. A shopping list of issues pertaining to CD-ROMs included: the grounds for selecting commercial publishers, and in-house publication where possible versus nonprofit or government publication. A similar list for networks included: determining when one should consider dissemination through a network, identifying the mechanisms or entities that exist to place items on networks, identifying the pool of existing networks, determining how a producer would choose between networks, and identifying the elements of a business arrangement in a network. Options for publishing in CD-ROM: an outside publisher versus self-publication. If an outside publisher is used, it can be nonprofit, such as the Government Printing Office (GPO) or the National Technical Information Service (NTIS), in the case of government. The pros and cons associated with employing an outside publisher are obvious. Among the pros, there is no trouble getting accepted. One pays the bill and, in effect, goes one's way. Among the cons, when one pays an outside publisher to perform the work, that publisher will perform the work it is obliged to do, but perhaps without the production expertise and skill in marketing and dissemination that some would seek. There is the body of commercial publishers that do possess that kind of expertise in distribution and marketing but that obviously are selective. In self-publication, one exercises full control, but then one must handle matters such as distribution and marketing. Such are some of the options for publishing in the case of CD-ROM. In the case of technical and design issues, which are also important, there are many matters which many at the Workshop already knew a good deal about: retrieval system requirements and costs, what to do about images, the various capabilities and platforms, the trade-offs between cost and performance, concerns about local-area networkability, interoperability, etc. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LYNCH * Creating networked information is different from using networks as an access or dissemination vehicle * Networked multimedia on a large scale does not yet work * Typical CD-ROM publication model a two-edged sword * Publishing information on a CD-ROM in the present world of immature standards * Contrast between CD-ROM and network pricing * Examples demonstrated earlier in the day as a set of insular information gems * Paramount need to link databases * Layering to become increasingly necessary * Project NEEDS and the issues of information reuse and active versus passive use * X-Windows as a way of differentiating between network access and networked information * Barriers to the distribution of networked multimedia information * Need for good, real-time delivery protocols * The question of presentation integrity in client-server computing in the academic world * Recommendations for producing multimedia +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Clifford LYNCH, director, Library Automation, University of California, opened his talk with the general observation that networked information constituted a difficult and elusive topic because it is something just starting to develop and not yet fully understood. LYNCH contended that creating genuinely networked information was different from using networks as an access or dissemination vehicle and was more sophisticated and more subtle. He invited the members of the audience to extrapolate, from what they heard about the preceding demonstration projects, to what sort of a world of electronics information--scholarly, archival, cultural, etc.--they wished to end up with ten or fifteen years from now. LYNCH suggested that to extrapolate directly from these projects would produce unpleasant results. Putting the issue of CD-ROM in perspective before getting into generalities on networked information, LYNCH observed that those engaged in multimedia today who wish to ship a product, so to say, probably do not have much choice except to use CD-ROM: networked multimedia on a large scale basically does not yet work because the technology does not exist. For example, anybody who has tried moving images around over the Internet knows that this is an exciting touch-and-go process, a fascinating and fertile area for experimentation, research, and development, but not something that one can become deeply enthusiastic about committing to production systems at this time. This situation will change, LYNCH said. He differentiated CD-ROM from the practices that have been followed up to now in distributing data on CD-ROM. For LYNCH the problem with CD-ROM is not its portability or its slowness but the two-edged sword of having the retrieval application and the user interface inextricably bound up with the data, which is the typical CD-ROM publication model. It is not a case of publishing data but of distributing a typically stand-alone, typically closed system, all--software, user interface, and data--on a little disk. Hence, all the between-disk navigational issues as well as the impossibility in most cases of integrating data on one disk with that on another. Most CD-ROM retrieval software does not network very gracefully at present. However, in the present world of immature standards and lack of understanding of what network information is or what the ground rules are for creating or using it, publishing information on a CD-ROM does add value in a very real sense. LYNCH drew a contrast between CD-ROM and network pricing and in doing so highlighted something bizarre in information pricing. A large institution such as the University of California has vendors who will offer to sell information on CD-ROM for a price per year in four digits, but for the same data (e.g., an abstracting and indexing database) on magnetic tape, regardless of how many people may use it concurrently, will quote a price in six digits. What is packaged with the CD-ROM in one sense adds value--a complete access system, not just raw, unrefined information--although it is not generally perceived that way. This is because the access software, although it adds value, is viewed by some people, particularly in the university environment where there is a very heavy commitment to networking, as being developed in the wrong direction. Given that context, LYNCH described the examples demonstrated as a set of insular information gems--Perseus, for example, offers nicely linked information, but would be very difficult to integrate with other databases, that is, to link together seamlessly with other source files from other sources. It resembles an island, and in this respect is similar to numerous stand-alone projects that are based on videodiscs, that is, on the single-workstation concept. As scholarship evolves in a network environment, the paramount need will be to link databases. We must link personal databases to public databases, to group databases, in fairly seamless ways--which is extremely difficult in the environments under discussion with copies of databases proliferating all over the place. The notion of layering also struck LYNCH as lurking in several of the projects demonstrated. Several databases in a sense constitute information archives without a significant amount of navigation built in. Educators, critics, and others will want a layered structure--one that defines or links paths through the layers to allow users to reach specific points. In LYNCH's view, layering will become increasingly necessary, and not just within a single resource but across resources (e.g., tracing mythology and cultural themes across several classics databases as well as a database of Renaissance culture). This ability to organize resources, to build things out of multiple other things on the network or select pieces of it, represented for LYNCH one of the key aspects of network information. Contending that information reuse constituted another significant issue, LYNCH commended to the audience's attention Project NEEDS (i.e., National Engineering Education Delivery System). This project's objective is to produce a database of engineering courseware as well as the components that can be used to develop new courseware. In a number of the existing applications, LYNCH said, the issue of reuse (how much one can take apart and reuse in other applications) was not being well considered. He also raised the issue of active versus passive use, one aspect of which is how much information will be manipulated locally by users. Most people, he argued, may do a little browsing and then will wish to print. LYNCH was uncertain how these resources would be used by the vast majority of users in the network environment. LYNCH next said a few words about X-Windows as a way of differentiating between network access and networked information. A number of the applications demonstrated at the Workshop could be rewritten to use X across the network, so that one could run them from any X-capable device- -a workstation, an X terminal--and transact with a database across the network. Although this opens up access a little, assuming one has enough network to handle it, it does not provide an interface to develop a program that conveniently integrates information from multiple databases. X is a viewing technology that has limits. In a real sense, it is just a graphical version of remote log-in across the network. X-type applications represent only one step in the progression towards real access. LYNCH next discussed barriers to the distribution of networked multimedia information. The heart of the problem is a lack of standards to provide the ability for computers to talk to each other, retrieve information, and shuffle it around fairly casually. At the moment, little progress is being made on standards for networked information; for example, present standards do not cover images, digital voice, and digital video. A useful tool kit of exchange formats for basic texts is only now being assembled. The synchronization of content streams (i.e., synchronizing a voice track to a video track, establishing temporal relations between different components in a multimedia object) constitutes another issue for networked multimedia that is just beginning to receive attention. Underlying network protocols also need some work; good, real-time delivery protocols on the Internet do not yet exist. In LYNCH's view, highly important in this context is the notion of networked digital object IDs, the ability of one object on the network to point to another object (or component thereof) on the network. Serious bandwidth issues also exist. LYNCH was uncertain if billion-bit-per-second networks would prove sufficient if numerous people ran video in parallel. LYNCH concluded by offering an issue for database creators to consider, as well as several comments about what might constitute good trial multimedia experiments. In a networked information world the database builder or service builder (publisher) does not exercise the same extensive control over the integrity of the presentation; strange programs "munge" with one's data before the user sees it. Serious thought must be given to what guarantees integrity of presentation. Part of that is related to where one draws the boundaries around a networked information service. This question of presentation integrity in client-server computing has not been stressed enough in the academic world, LYNCH argued, though commercial service providers deal with it regularly. Concerning multimedia, LYNCH observed that good multimedia at the moment is hideously expensive to produce. He recommended producing multimedia with either very high sale value, or multimedia with a very long life span, or multimedia that will have a very broad usage base and whose costs therefore can be amortized among large numbers of users. In this connection, historical and humanistically oriented material may be a good place to start, because it tends to have a longer life span than much of the scientific material, as well as a wider user base. LYNCH noted, for example, that American Memory fits many of the criteria outlined. He remarked the extensive discussion about bringing the Internet or the National Research and Education Network (NREN) into the K-12 environment as a way of helping the American educational system. LYNCH closed by noting that the kinds of applications demonstrated struck him as excellent justifications of broad-scale networking for K-12, but that at this time no "killer" application exists to mobilize the K-12 community to obtain connectivity. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Dearth of genuinely interesting applications on the network a slow-changing situation * The issue of the integrity of presentation in a networked environment * Several reasons why CD-ROM software does not network * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the discussion period that followed LYNCH's presentation, several additional points were made. LYNCH reiterated even more strongly his contention that, historically, once one goes outside high-end science and the group of those who need access to supercomputers, there is a great dearth of genuinely interesting applications on the network. He saw this situation changing slowly, with some of the scientific databases and scholarly discussion groups and electronic journals coming on as well as with the availability of Wide Area Information Servers (WAIS) and some of the databases that are being mounted there. However, many of those things do not seem to have piqued great popular interest. For instance, most high school students of LYNCH's acquaintance would not qualify as devotees of serious molecular biology. Concerning the issue of the integrity of presentation, LYNCH believed that a couple of information providers have laid down the law at least on certain things. For example, his recollection was that the National Library of Medicine feels strongly that one needs to employ the identifier field if he or she is to mount a database commercially. The problem with a real networked environment is that one does not know who is reformatting and reprocessing one's data when one enters a client server mode. It becomes anybody's guess, for example, if the network uses a Z39.50 server, or what clients are doing with one's data. A data provider can say that his contract will only permit clients to have access to his data after he vets them and their presentation and makes certain it suits him. But LYNCH held out little expectation that the network marketplace would evolve in that way, because it required too much prior negotiation. CD-ROM software does not network for a variety of reasons, LYNCH said. He speculated that CD-ROM publishers are not eager to have their products really hook into wide area networks, because they fear it will make their data suppliers nervous. Moreover, until relatively recently, one had to be rather adroit to run a full TCP/IP stack plus applications on a PC-size machine, whereas nowadays it is becoming easier as PCs grow bigger and faster. LYNCH also speculated that software providers had not heard from their customers until the last year or so, or had not heard from enough of their customers. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BESSER * Implications of disseminating images on the network; planning the distribution of multimedia documents poses two critical implementation problems * Layered approach represents the way to deal with users' capabilities * Problems in platform design; file size and its implications for networking * Transmission of megabyte size images impractical * Compression and decompression at the user's end * Promising trends for compression * A disadvantage of using X-Windows * A project at the Smithsonian that mounts images on several networks * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Howard BESSER, School of Library and Information Science, University of Pittsburgh, spoke primarily about multimedia, focusing on images and the broad implications of disseminating them on the network. He argued that planning the distribution of multimedia documents posed two critical implementation problems, which he framed in the form of two questions: 1) What platform will one use and what hardware and software will users have for viewing of the material? and 2) How can one deliver a sufficiently robust set of information in an accessible format in a reasonable amount of time? Depending on whether network or CD-ROM is the medium used, this question raises different issues of storage, compression, and transmission. Concerning the design of platforms (e.g., sound, gray scale, simple color, etc.) and the various capabilities users may have, BESSER maintained that a layered approach was the way to deal with users' capabilities. A result would be that users with less powerful workstations would simply have less functionality. He urged members of the audience to advocate standards and accompanying software that handle layered functionality across a wide variety of platforms. BESSER also addressed problems in platform design, namely, deciding how large a machine to design for situations when the largest number of users have the lowest level of the machine, and one desires higher functionality. BESSER then proceeded to the question of file size and its implications for networking. He discussed still images in the main. For example, a digital color image that fills the screen of a standard mega-pel workstation (Sun or Next) will require one megabyte of storage for an eight-bit image or three megabytes of storage for a true color or twenty-four-bit image. Lossless compression algorithms (that is, computational procedures in which no data is lost in the process of compressing [and decompressing] an image--the exact bit-representation is maintained) might bring storage down to a third of a megabyte per image, but not much further than that. The question of size makes it difficult to fit an appropriately sized set of these images on a single disk or to transmit them quickly enough on a network. With these full screen mega-pel images that constitute a third of a megabyte, one gets 1,000-3,000 full-screen images on a one-gigabyte disk; a standard CD-ROM represents approximately 60 percent of that. Storing images the size of a PC screen (just 8 bit color) increases storage capacity to 4,000-12,000 images per gigabyte; 60 percent of that gives one the size of a CD-ROM, which in turn creates a major problem. One cannot have full-screen, full-color images with lossless compression; one must compress them or use a lower resolution. For megabyte-size images, anything slower than a T-1 speed is impractical. For example, on a fifty-six-kilobaud line, it takes three minutes to transfer a one-megabyte file, if it is not compressed; and this speed assumes ideal circumstances (no other user contending for network bandwidth). Thus, questions of disk access, remote display, and current telephone connection speed make transmission of megabyte-size images impractical. BESSER then discussed ways to deal with these large images, for example, compression and decompression at the user's end. In this connection, the issues of how much one is willing to lose in the compression process and what image quality one needs in the first place are unknown. But what is known is that compression entails some loss of data. BESSER urged that more studies be conducted on image quality in different situations, for example, what kind of images are needed for what kind of disciplines, and what kind of image quality is needed for a browsing tool, an intermediate viewing tool, and archiving. BESSER remarked two promising trends for compression: from a technical perspective, algorithms that use what is called subjective redundancy employ principles from visual psycho-physics to identify and remove information from the image that the human eye cannot perceive; from an interchange and interoperability perspective, the JPEG (i.e., Joint Photographic Experts Group, an ISO standard) compression algorithms also offer promise. These issues of compression and decompression, BESSER argued, resembled those raised earlier concerning the design of different platforms. Gauging the capabilities of potential users constitutes a primary goal. BESSER advocated layering or separating the images from the applications that retrieve and display them, to avoid tying them to particular software. BESSER detailed several lessons learned from his work at Berkeley with Imagequery, especially the advantages and disadvantages of using X-Windows. In the latter category, for example, retrieval is tied directly to one's data, an intolerable situation in the long run on a networked system. Finally, BESSER described a project of Jim Wallace at the Smithsonian Institution, who is mounting images in a extremely rudimentary way on the Compuserv and Genie networks and is preparing to mount them on America On Line. Although the average user takes over thirty minutes to download these images (assuming a fairly fast modem), nevertheless, images have been downloaded 25,000 times. BESSER concluded his talk with several comments on the business arrangement between the Smithsonian and Compuserv. He contended that not enough is known concerning the value of images. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Creating digitized photographic collections nearly impossible except with large organizations like museums * Need for study to determine quality of images users will tolerate * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the brief exchange between LESK and BESSER that followed, several clarifications emerged. LESK argued that the photographers were far ahead of BESSER: It is almost impossible to create such digitized photographic collections except with large organizations like museums, because all the photographic agencies have been going crazy about this and will not sign licensing agreements on any sort of reasonable terms. LESK had heard that National Geographic, for example, had tried to buy the right to use some image in some kind of educational production for $100 per image, but the photographers will not touch it. They want accounting and payment for each use, which cannot be accomplished within the system. BESSER responded that a consortium of photographers, headed by a former National Geographic photographer, had started assembling its own collection of electronic reproductions of images, with the money going back to the cooperative. LESK contended that BESSER was unnecessarily pessimistic about multimedia images, because people are accustomed to low-quality images, particularly from video. BESSER urged the launching of a study to determine what users would tolerate, what they would feel comfortable with, and what absolutely is the highest quality they would ever need. Conceding that he had adopted a dire tone in order to arouse people about the issue, BESSER closed on a sanguine note by saying that he would not be in this business if he did not think that things could be accomplished. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LARSEN * Issues of scalability and modularity * Geometric growth of the Internet and the role played by layering * Basic functions sustaining this growth * A library's roles and functions in a network environment * Effects of implementation of the Z39.50 protocol for information retrieval on the library system * The trade-off between volumes of data and its potential usage * A snapshot of current trends * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Ronald LARSEN, associate director for information technology, University of Maryland at College Park, first addressed the issues of scalability and modularity. He noted the difficulty of anticipating the effects of orders-of-magnitude growth, reflecting on the twenty years of experience with the Arpanet and Internet. Recalling the day's demonstrations of CD-ROM and optical disk material, he went on to ask if the field has yet learned how to scale new systems to enable delivery and dissemination across large-scale networks. LARSEN focused on the geometric growth of the Internet from its inception circa 1969 to the present, and the adjustments required to respond to that rapid growth. To illustrate the issue of scalability, LARSEN considered computer networks as including three generic components: computers, network communication nodes, and communication media. Each component scales (e.g., computers range from PCs to supercomputers; network nodes scale from interface cards in a PC through sophisticated routers and gateways; and communication media range from 2,400-baud dial-up facilities through 4.5-Mbps backbone links, and eventually to multigigabit-per-second communication lines), and architecturally, the components are organized to scale hierarchically from local area networks to international-scale networks. Such growth is made possible by building layers of communication protocols, as BESSER pointed out. By layering both physically and logically, a sense of scalability is maintained from local area networks in offices, across campuses, through bridges, routers, campus backbones, fiber-optic links, etc., up into regional networks and ultimately into national and international networks. LARSEN then illustrated the geometric growth over a two-year period-- through September 1991--of the number of networks that comprise the Internet. This growth has been sustained largely by the availability of three basic functions: electronic mail, file transfer (ftp), and remote log-on (telnet). LARSEN also reviewed the growth in the kind of traffic that occurs on the network. Network traffic reflects the joint contributions of a larger population of users and increasing use per user. Today one sees serious applications involving moving images across the network--a rarity ten years ago. LARSEN recalled and concurred with BESSER's main point that the interesting problems occur at the application level. LARSEN then illustrated a model of a library's roles and functions in a network environment. He noted, in particular, the placement of on-line catalogues onto the network and patrons obtaining access to the library increasingly through local networks, campus networks, and the Internet. LARSEN supported LYNCH's earlier suggestion that we need to address fundamental questions of networked information in order to build environments that scale in the information sense as well as in the physical sense. LARSEN supported the role of the library system as the access point into the nation's electronic collections. Implementation of the Z39.50 protocol for information retrieval would make such access practical and feasible. For example, this would enable patrons in Maryland to search California libraries, or other libraries around the world that are conformant with Z39.50 in a manner that is familiar to University of Maryland patrons. This client-server model also supports moving beyond secondary content into primary content. (The notion of how one links from secondary content to primary content, LARSEN said, represents a fundamental problem that requires rigorous thought.) After noting numerous network experiments in accessing full-text materials, including projects supporting the ordering of materials across the network, LARSEN revisited the issue of transmitting high-density, high-resolution color images across the network and the large amounts of bandwidth they require. He went on to address the bandwidth and synchronization problems inherent in sending full-motion video across the network. LARSEN illustrated the trade-off between volumes of data in bytes or orders of magnitude and the potential usage of that data. He discussed transmission rates (particularly, the time it takes to move various forms of information), and what one could do with a network supporting multigigabit-per-second transmission. At the moment, the network environment includes a composite of data-transmission requirements, volumes and forms, going from steady to bursty (high-volume) and from very slow to very fast. This aggregate must be considered in the design, construction, and operation of multigigabyte networks. LARSEN's objective is to use the networks and library systems now being constructed to increase access to resources wherever they exist, and thus, to evolve toward an on-line electronic virtual library. LARSEN concluded by offering a snapshot of current trends: continuing geometric growth in network capacity and number of users; slower development of applications; and glacial development and adoption of standards. The challenge is to design and develop each new application system with network access and scalability in mind. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BROWNRIGG * Access to the Internet cannot be taken for granted * Packet radio and the development of MELVYL in 1980-81 in the Division of Library Automation at the University of California * Design criteria for packet radio * A demonstration project in San Diego and future plans * Spread spectrum * Frequencies at which the radios will run and plans to reimplement the WAIS server software in the public domain * Need for an infrastructure of radios that do not move around * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Edwin BROWNRIGG, executive director, Memex Research Institute, first polled the audience in order to seek out regular users of the Internet as well as those planning to use it some time in the future. With nearly everybody in the room falling into one category or the other, BROWNRIGG made a point re access, namely that numerous individuals, especially those who use the Internet every day, take for granted their access to it, the speeds with which they are connected, and how well it all works. However, as BROWNRIGG discovered between 1987 and 1989 in Australia, if one wants access to the Internet but cannot afford it or has some physical boundary that prevents her or him from gaining access, it can be extremely frustrating. He suggested that because of economics and physical barriers we were beginning to create a world of haves and have-nots in the process of scholarly communication, even in the United States. BROWNRIGG detailed the development of MELVYL in academic year 1980-81 in the Division of Library Automation at the University of California, in order to underscore the issue of access to the system, which at the outset was extremely limited. In short, the project needed to build a network, which at that time entailed use of satellite technology, that is, putting earth stations on campus and also acquiring some terrestrial links from the State of California's microwave system. The installation of satellite links, however, did not solve the problem (which actually formed part of a larger problem involving politics and financial resources). For while the project team could get a signal onto a campus, it had no means of distributing the signal throughout the campus. The solution involved adopting a recent development in wireless communication called packet radio, which combined the basic notion of packet-switching with radio. The project used this technology to get the signal from a point on campus where it came down, an earth station for example, into the libraries, because it found that wiring the libraries, especially the older marble buildings, would cost $2,000-$5,000 per terminal. BROWNRIGG noted that, ten years ago, the project had neither the public policy nor the technology that would have allowed it to use packet radio in any meaningful way. Since then much had changed. He proceeded to detail research and development of the technology, how it is being deployed in California, and what direction he thought it would take. The design criteria are to produce a high-speed, one-time, low-cost, high-quality, secure, license-free device (packet radio) that one can plug in and play today, forget about it, and have access to the Internet. By high speed, BROWNRIGG meant 1 megabyte and 1.5 megabytes. Those units have been built, he continued, and are in the process of being type-certified by an independent underwriting laboratory so that they can be type-licensed by the Federal Communications Commission. As is the case with citizens band, one will be able to purchase a unit and not have to worry about applying for a license. The basic idea, BROWNRIGG elaborated, is to take high-speed radio data transmission and create a backbone network that at certain strategic points in the network will "gateway" into a medium-speed packet radio (i.e., one that runs at 38.4 kilobytes), so that perhaps by 1994-1995 people, like those in the audience for the price of a VCR could purchase a medium-speed radio for the office or home, have full network connectivity to the Internet, and partake of all its services, with no need for an FCC license and no regular bill from the local common carrier. BROWNRIGG presented several details of a demonstration project currently taking place in San Diego and described plans, pending funding, to install a full-bore network in the San Francisco area. This network will have 600 nodes running at backbone speeds, and 100 of these nodes will be libraries, which in turn will be the gateway ports to the 38.4 kilobyte radios that will give coverage for the neighborhoods surrounding the libraries. BROWNRIGG next explained Part 15.247, a new rule within Title 47 of the Code of Federal Regulations enacted by the FCC in 1985. This rule challenged the industry, which has only now risen to the occasion, to build a radio that would run at no more than one watt of output power and use a fairly exotic method of modulating the radio wave called spread spectrum. Spread spectrum in fact permits the building of networks so that numerous data communications can occur simultaneously, without interfering with each other, within the same wide radio channel. BROWNRIGG explained that the frequencies at which the radios would run are very short wave signals. They are well above standard microwave and radar. With a radio wave that small, one watt becomes a tremendous punch per bit and thus makes transmission at reasonable speed possible. In order to minimize the potential for congestion, the project is undertaking to reimplement software which has been available in the networking business and is taken for granted now, for example, TCP/IP, routing algorithms, bridges, and gateways. In addition, the project plans to take the WAIS server software in the public domain and reimplement it so that one can have a WAIS server on a Mac instead of a Unix machine. The Memex Research Institute believes that libraries, in particular, will want to use the WAIS servers with packet radio. This project, which has a team of about twelve people, will run through 1993 and will include the 100 libraries already mentioned as well as other professionals such as those in the medical profession, engineering, and law. Thus, the need is to create an infrastructure of radios that do not move around, which, BROWNRIGG hopes, will solve a problem not only for libraries but for individuals who, by and large today, do not have access to the Internet from their homes and offices. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Project operating frequencies * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During a brief discussion period, which also concluded the day's proceedings, BROWNRIGG stated that the project was operating in four frequencies. The slow speed is operating at 435 megahertz, and it would later go up to 920 megahertz. With the high-speed frequency, the one-megabyte radios will run at 2.4 gigabits, and 1.5 will run at 5.7. At 5.7, rain can be a factor, but it would have to be tropical rain, unlike what falls in most parts of the United States. ****** SESSION IV. IMAGE CAPTURE, TEXT CAPTURE, OVERVIEW OF TEXT AND IMAGE STORAGE FORMATS William HOOTON, vice president of operations, I-NET, moderated this session. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ KENNEY * Factors influencing development of CXP * Advantages of using digital technology versus photocopy and microfilm * A primary goal of CXP; publishing challenges * Characteristics of copies printed * Quality of samples achieved in image capture * Several factors to be considered in choosing scanning * Emphasis of CXP on timely and cost-effective production of black-and-white printed facsimiles * Results of producing microfilm from digital files * Advantages of creating microfilm * Details concerning production * Costs * Role of digital technology in library preservation * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Anne KENNEY, associate director, Department of Preservation and Conservation, Cornell University, opened her talk by observing that the Cornell Xerox Project (CXP) has been guided by the assumption that the ability to produce printed facsimiles or to replace paper with paper would be important, at least for the present generation of users and equipment. She described three factors that influenced development of the project: 1) Because the project has emphasized the preservation of deteriorating brittle books, the quality of what was produced had to be sufficiently high to return a paper replacement to the shelf. CXP was only interested in using: 2) a system that was cost-effective, which meant that it had to be cost-competitive with the processes currently available, principally photocopy and microfilm, and 3) new or currently available product hardware and software. KENNEY described the advantages that using digital technology offers over both photocopy and microfilm: 1) The potential exists to create a higher quality reproduction of a deteriorating original than conventional light-lens technology. 2) Because a digital image is an encoded representation, it can be reproduced again and again with no resulting loss of quality, as opposed to the situation with light-lens processes, in which there is discernible difference between a second and a subsequent generation of an image. 3) A digital image can be manipulated in a number of ways to improve image capture; for example, Xerox has developed a windowing application that enables one to capture a page containing both text and illustrations in a manner that optimizes the reproduction of both. (With light-lens technology, one must choose which to optimize, text or the illustration; in preservation microfilming, the current practice is to shoot an illustrated page twice, once to highlight the text and the second time to provide the best capture for the illustration.) 4) A digital image can also be edited, density levels adjusted to remove underlining and stains, and to increase legibility for faint documents. 5) On-screen inspection can take place at the time of initial setup and adjustments made prior to scanning, factors that substantially reduce the number of retakes required in quality control. A primary goal of CXP has been to evaluate the paper output printed on the Xerox DocuTech, a high-speed printer that produces 600-dpi pages from scanned images at a rate of 135 pages a minute. KENNEY recounted several publishing challenges to represent faithful and legible reproductions of the originals that the 600-dpi copy for the most part successfully captured. For example, many of the deteriorating volumes in the project were heavily illustrated with fine line drawings or halftones or came in languages such as Japanese, in which the buildup of characters comprised of varying strokes is difficult to reproduce at lower resolutions; a surprising number of them came with annotations and mathematical formulas, which it was critical to be able to duplicate exactly. KENNEY noted that 1) the copies are being printed on paper that meets the ANSI standards for performance, 2) the DocuTech printer meets the machine and toner requirements for proper adhesion of print to page, as described by the National Archives, and thus 3) paper product is considered to be the archival equivalent of preservation photocopy. KENNEY then discussed several samples of the quality achieved in the project that had been distributed in a handout, for example, a copy of a print-on-demand version of the 1911 Reed lecture on the steam turbine, which contains halftones, line drawings, and illustrations embedded in text; the first four loose pages in the volume compared the capture capabilities of scanning to photocopy for a standard test target, the IEEE standard 167A 1987 test chart. In all instances scanning proved superior to photocopy, though only slightly more so in one. Conceding the simplistic nature of her review of the quality of scanning to photocopy, KENNEY described it as one representation of the kinds of settings that could be used with scanning capabilities on the equipment CXP uses. KENNEY also pointed out that CXP investigated the quality achieved with binary scanning only, and noted the great promise in gray scale and color scanning, whose advantages and disadvantages need to be examined. She argued further that scanning resolutions and file formats can represent a complex trade-off between the time it takes to capture material, file size, fidelity to the original, and on-screen display; and printing and equipment availability. All these factors must be taken into consideration. CXP placed primary emphasis on the production in a timely and cost-effective manner of printed facsimiles that consisted largely of black-and-white text. With binary scanning, large files may be compressed efficiently and in a lossless manner (i.e., no data is lost in the process of compressing [and decompressing] an image--the exact bit-representation is maintained) using Group 4 CCITT (i.e., the French acronym for International Consultative Committee for Telegraph and Telephone) compression. CXP was getting compression ratios of about forty to one. Gray-scale compression, which primarily uses JPEG, is much less economical and can represent a lossy compression (i.e., not lossless), so that as one compresses and decompresses, the illustration is subtly changed. While binary files produce a high-quality printed version, it appears 1) that other combinations of spatial resolution with gray and/or color hold great promise as well, and 2) that gray scale can represent a tremendous advantage for on-screen viewing. The quality associated with binary and gray scale also depends on the equipment used. For instance, binary scanning produces a much better copy on a binary printer. Among CXP's findings concerning the production of microfilm from digital files, KENNEY reported that the digital files for the same Reed lecture were used to produce sample film using an electron beam recorder. The resulting film was faithful to the image capture of the digital files, and while CXP felt that the text and image pages represented in the Reed lecture were superior to that of the light-lens film, the resolution readings for the 600 dpi were not as high as standard microfilming. KENNEY argued that the standards defined for light-lens technology are not totally transferable to a digital environment. Moreover, they are based on definition of quality for a preservation copy. Although making this case will prove to be a long, uphill struggle, CXP plans to continue to investigate the issue over the course of the next year. KENNEY concluded this portion of her talk with a discussion of the advantages of creating film: it can serve as a primary backup and as a preservation master to the digital file; it could then become the print or production master and service copies could be paper, film, optical disks, magnetic media, or on-screen display. Finally, KENNEY presented details re production: * Development and testing of a moderately-high resolution production scanning workstation represented a third goal of CXP; to date, 1,000 volumes have been scanned, or about 300,000 images. * The resulting digital files are stored and used to produce hard-copy replacements for the originals and additional prints on demand; although the initial costs are high, scanning technology offers an affordable means for reformatting brittle material. * A technician in production mode can scan 300 pages per hour when performing single-sheet scanning, which is a necessity when working with truly brittle paper; this figure is expected to increase significantly with subsequent iterations of the software from Xerox; a three-month time-and-cost study of scanning found that the average 300-page book would take about an hour and forty minutes to scan (this figure included the time for setup, which involves keying in primary bibliographic data, going into quality control mode to define page size, establishing front-to-back registration, and scanning sample pages to identify a default range of settings for the entire book--functions not dissimilar to those performed by filmers or those preparing a book for photocopy). * The final step in the scanning process involved rescans, which happily were few and far between, representing well under 1 percent of the total pages scanned. In addition to technician time, CXP costed out equipment, amortized over four years, the cost of storing and refreshing the digital files every four years, and the cost of printing and binding, book-cloth binding, a paper reproduction. The total amounted to a little under $65 per single 300-page volume, with 30 percent overhead included--a figure competitive with the prices currently charged by photocopy vendors. Of course, with scanning, in addition to the paper facsimile, one is left with a digital file from which subsequent copies of the book can be produced for a fraction of the cost of photocopy, with readers afforded choices in the form of these copies. KENNEY concluded that digital technology offers an electronic means for a library preservation effort to pay for itself. If a brittle-book program included the means of disseminating reprints of books that are in demand by libraries and researchers alike, the initial investment in capture could be recovered and used to preserve additional but less popular books. She disclosed that an economic model for a self-sustaining program could be developed for CXP's report to the Commission on Preservation and Access (CPA). KENNEY stressed that the focus of CXP has been on obtaining high quality in a production environment. The use of digital technology is viewed as an affordable alternative to other reformatting options. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ANDRE * Overview and history of NATDP * Various agricultural CD-ROM products created inhouse and by service bureaus * Pilot project on Internet transmission * Additional products in progress * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Pamela ANDRE, associate director for automation, National Agricultural Text Digitizing Program (NATDP), National Agricultural Library (NAL), presented an overview of NATDP, which has been underway at NAL the last four years, before Judith ZIDAR discussed the technical details. ANDRE defined agricultural information as a broad range of material going from basic and applied research in the hard sciences to the one-page pamphlets that are distributed by the cooperative state extension services on such things as how to grow blueberries. NATDP began in late 1986 with a meeting of representatives from the land-grant library community to deal with the issue of electronic information. NAL and forty-five of these libraries banded together to establish this project--to evaluate the technology for converting what were then source documents in paper form into electronic form, to provide access to that digital information, and then to distribute it. Distributing that material to the community--the university community as well as the extension service community, potentially down to the county level--constituted the group's chief concern. Since January 1988 (when the microcomputer-based scanning system was installed at NAL), NATDP has done a variety of things, concerning which ZIDAR would provide further details. For example, the first technology considered in the project's discussion phase was digital videodisc, which indicates how long ago it was conceived. Over the four years of this project, four separate CD-ROM products on four different agricultural topics were created, two at a scanning-and-OCR station installed at NAL, and two by service bureaus. Thus, NATDP has gained comparative information in terms of those relative costs. Each of these products contained the full ASCII text as well as page images of the material, or between 4,000 and 6,000 pages of material on these disks. Topics included aquaculture, food, agriculture and science (i.e., international agriculture and research), acid rain, and Agent Orange, which was the final product distributed (approximately eighteen months before the Workshop). The third phase of NATDP focused on delivery mechanisms other than CD-ROM. At the suggestion of Clifford LYNCH, who was a technical consultant to the project at this point, NATDP became involved with the Internet and initiated a project with the help of North Carolina State University, in which fourteen of the land-grant university libraries are transmitting digital images over the Internet in response to interlibrary loan requests--a topic for another meeting. At this point, the pilot project had been completed for about a year and the final report would be available shortly after the Workshop. In the meantime, the project's success had led to its extension. (ANDRE noted that one of the first things done under the program title was to select a retrieval package to use with subsequent products; Windows Personal Librarian was the package of choice after a lengthy evaluation.) Three additional products had been planned and were in progress: 1) An arrangement with the American Society of Agronomy--a professional society that has published the Agronomy Journal since about 1908--to scan and create bit-mapped images of its journal. ASA granted permission first to put and then to distribute this material in electronic form, to hold it at NAL, and to use these electronic images as a mechanism to deliver documents or print out material for patrons, among other uses. Effectively, NAL has the right to use this material in support of its program. (Significantly, this arrangement offers a potential cooperative model for working with other professional societies in agriculture to try to do the same thing--put the journals of particular interest to agriculture research into electronic form.) 2) An extension of the earlier product on aquaculture. 3) The George Washington Carver Papers--a joint project with Tuskegee University to scan and convert from microfilm some 3,500 images of Carver's papers, letters, and drawings. It was anticipated that all of these products would appear no more than six months after the Workshop. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ZIDAR * (A separate arena for scanning) * Steps in creating a database * Image capture, with and without performing OCR * Keying in tracking data * Scanning, with electronic and manual tracking * Adjustments during scanning process * Scanning resolutions * Compression * De-skewing and filtering * Image capture from microform: the papers and letters of George Washington Carver * Equipment used for a scanning system * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Judith ZIDAR, coordinator, National Agricultural Text Digitizing Program (NATDP), National Agricultural Library (NAL), illustrated the technical details of NATDP, including her primary responsibility, scanning and creating databases on a topic and putting them on CD-ROM. (ZIDAR remarked a separate arena from the CD-ROM projects, although the processing of the material is nearly identical, in which NATDP is also scanning material and loading it on a Next microcomputer, which in turn is linked to NAL's integrated library system. Thus, searches in NAL's bibliographic database will enable people to pull up actual page images and text for any documents that have been entered.) In accordance with the session's topic, ZIDAR focused her illustrated talk on image capture, offering a primer on the three main steps in the process: 1) assemble the printed publications; 2) design the database (database design occurs in the process of preparing the material for scanning; this step entails reviewing and organizing the material, defining the contents--what will constitute a record, what kinds of fields will be captured in terms of author, title, etc.); 3) perform a certain amount of markup on the paper publications. NAL performs this task record by record, preparing work sheets or some other sort of tracking material and designing descriptors and other enhancements to be added to the data that will not be captured from the printed publication. Part of this process also involves determining NATDP's file and directory structure: NATDP attempts to avoid putting more than approximately 100 images in a directory, because placing more than that on a CD-ROM would reduce the access speed. This up-front process takes approximately two weeks for a 6,000-7,000-page database. The next step is to capture the page images. How long this process takes is determined by the decision whether or not to perform OCR. Not performing OCR speeds the process, whereas text capture requires greater care because of the quality of the image: it has to be straighter and allowance must be made for text on a page, not just for the capture of photographs. NATDP keys in tracking data, that is, a standard bibliographic record including the title of the book and the title of the chapter, which will later either become the access information or will be attached to the front of a full-text record so that it is searchable. Images are scanned from a bound or unbound publication, chiefly from bound publications in the case of NATDP, however, because often they are the only copies and the publications are returned to the shelves. NATDP usually scans one record at a time, because its database tracking system tracks the document in that way and does not require further logical separating of the images. After performing optical character recognition, NATDP moves the images off the hard disk and maintains a volume sheet. Though the system tracks electronically, all the processing steps are also tracked manually with a log sheet. ZIDAR next illustrated the kinds of adjustments that one can make when scanning from paper and microfilm, for example, redoing images that need special handling, setting for dithering or gray scale, and adjusting for brightness or for the whole book at one time. NATDP is scanning at 300 dots per inch, a standard scanning resolution. Though adequate for capturing text that is all of a standard size, 300 dpi is unsuitable for any kind of photographic material or for very small text. Many scanners allow for different image formats, TIFF, of course, being a de facto standard. But if one intends to exchange images with other people, the ability to scan other image formats, even if they are less common, becomes highly desirable. CCITT Group 4 is the standard compression for normal black-and-white images, JPEG for gray scale or color. ZIDAR recommended 1) using the standard compressions, particularly if one attempts to make material available and to allow users to download images and reuse them from CD-ROMs; and 2) maintaining the ability to output an uncompressed image, because in image exchange uncompressed images are more likely to be able to cross platforms. ZIDAR emphasized the importance of de-skewing and filtering as requirements on NATDP's upgraded system. For instance, scanning bound books, particularly books published by the federal government whose pages are skewed, and trying to scan them straight if OCR is to be performed, is extremely time-consuming. The same holds for filtering of poor-quality or older materials. ZIDAR described image capture from microform, using as an example three reels from a sixty-seven-reel set of the papers and letters of George Washington Carver that had been produced by Tuskegee University. These resulted in approximately 3,500 images, which NATDP had had scanned by its service contractor, Science Applications International Corporation (SAIC). NATDP also created bibliographic records for access. (NATDP did not have such specialized equipment as a microfilm scanner. Unfortunately, the process of scanning from microfilm was not an unqualified success, ZIDAR reported: because microfilm frame sizes vary, occasionally some frames were missed, which without spending much time and money could not be recaptured. OCR could not be performed from the scanned images of the frames. The bleeding in the text simply output text, when OCR was run, that could not even be edited. NATDP tested for negative versus positive images, landscape versus portrait orientation, and single- versus dual-page microfilm, none of which seemed to affect the quality of the image; but also on none of them could OCR be performed. In selecting the microfilm they would use, therefore, NATDP had other factors in mind. ZIDAR noted two factors that influenced the quality of the images: 1) the inherent quality of the original and 2) the amount of size reduction on the pages. The Carver papers were selected because they are informative and visually interesting, treat a single subject, and are valuable in their own right. The images were scanned and divided into logical records by SAIC, then delivered, and loaded onto NATDP's system, where bibliographic information taken directly from the images was added. Scanning was completed in summer 1991 and by the end of summer 1992 the disk was scheduled to be published. Problems encountered during processing included the following: Because the microfilm scanning had to be done in a batch, adjustment for individual page variations was not possible. The frame size varied on account of the nature of the material, and therefore some of the frames were missed while others were just partial frames. The only way to go back and capture this material was to print out the page with the microfilm reader from the missing frame and then scan it in from the page, which was extremely time-consuming. The quality of the images scanned from the printout of the microfilm compared unfavorably with that of the original images captured directly from the microfilm. The inability to perform OCR also was a major disappointment. At the time, computer output microfilm was unavailable to test. The equipment used for a scanning system was the last topic addressed by ZIDAR. The type of equipment that one would purchase for a scanning system included: a microcomputer, at least a 386, but preferably a 486; a large hard disk, 380 megabyte at minimum; a multi-tasking operating system that allows one to run some things in batch in the background while scanning or doing text editing, for example, Unix or OS/2 and, theoretically, Windows; a high-speed scanner and scanning software that allows one to make the various adjustments mentioned earlier; a high-resolution monitor (150 dpi ); OCR software and hardware to perform text recognition; an optical disk subsystem on which to archive all the images as the processing is done; file management and tracking software. ZIDAR opined that the software one purchases was more important than the hardware and might also cost more than the hardware, but it was likely to prove critical to the success or failure of one's system. In addition to a stand-alone scanning workstation for image capture, then, text capture requires one or two editing stations networked to this scanning station to perform editing. Editing the text takes two or three times as long as capturing the images. Finally, ZIDAR stressed the importance of buying an open system that allows for more than one vendor, complies with standards, and can be upgraded. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ WATERS *Yale University Library's master plan to convert microfilm to digital imagery (POB) * The place of electronic tools in the library of the future * The uses of images and an image library * Primary input from preservation microfilm * Features distinguishing POB from CXP and key hypotheses guiding POB * Use of vendor selection process to facilitate organizational work * Criteria for selecting vendor * Finalists and results of process for Yale * Key factor distinguishing vendors * Components, design principles, and some estimated costs of POB * Role of preservation materials in developing imaging market * Factors affecting quality and cost * Factors affecting the usability of complex documents in image form * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Donald WATERS, head of the Systems Office, Yale University Library, reported on the progress of a master plan for a project at Yale to convert microfilm to digital imagery, Project Open Book (POB). Stating that POB was in an advanced stage of planning, WATERS detailed, in particular, the process of selecting a vendor partner and several key issues under discussion as Yale prepares to move into the project itself. He commented first on the vision that serves as the context of POB and then described its purpose and scope. WATERS sees the library of the future not necessarily as an electronic library but as a place that generates, preserves, and improves for its clients ready access to both intellectual and physical recorded knowledge. Electronic tools must find a place in the library in the context of this vision. Several roles for electronic tools include serving as: indirect sources of electronic knowledge or as "finding" aids (the on-line catalogues, the article-level indices, registers for documents and archives); direct sources of recorded knowledge; full-text images; and various kinds of compound sources of recorded knowledge (the so-called compound documents of Hypertext, mixed text and image, mixed-text image format, and multimedia). POB is looking particularly at images and an image library, the uses to which images will be put (e.g., storage, printing, browsing, and then use as input for other processes), OCR as a subsequent process to image capture, or creating an image library, and also possibly generating microfilm. While input will come from a variety of sources, POB is considering especially input from preservation microfilm. A possible outcome is that the film and paper which provide the input for the image library eventually may go off into remote storage, and that the image library may be the primary access tool. The purpose and scope of POB focus on imaging. Though related to CXP, POB has two features which distinguish it: 1) scale--conversion of 10,000 volumes into digital image form; and 2) source--conversion from microfilm. Given these features, several key working hypotheses guide POB, including: 1) Since POB is using microfilm, it is not concerned with the image library as a preservation medium. 2) Digital imagery can improve access to recorded knowledge through printing and network distribution at a modest incremental cost of microfilm. 3) Capturing and storing documents in a digital image form is necessary to further improvements in access. (POB distinguishes between the imaging, digitizing process and OCR, which at this stage it does not plan to perform.) Currently in its first or organizational phase, POB found that it could use a vendor selection process to facilitate a good deal of the organizational work (e.g., creating a project team and advisory board, confirming the validity of the plan, establishing the cost of the project and a budget, selecting the materials to convert, and then raising the necessary funds). POB developed numerous selection criteria, including: a firm committed to image-document management, the ability to serve as systems integrator in a large-scale project over several years, interest in developing the requisite software as a standard rather than a custom product, and a willingness to invest substantial resources in the project itself. Two vendors, DEC and Xerox, were selected as finalists in October 1991, and with the support of the Commission on Preservation and Access, each was commissioned to generate a detailed requirements analysis for the project and then to submit a formal proposal for the completion of the project, which included a budget and costs. The terms were that POB would pay the loser. The results for Yale of involving a vendor included: broad involvement of Yale staff across the board at a relatively low cost, which may have long-term significance in carrying out the project (twenty-five to thirty university people are engaged in POB); better understanding of the factors that affect corporate response to markets for imaging products; a competitive proposal; and a more sophisticated view of the imaging markets. The most important factor that distinguished the vendors under consideration was their identification with the customer. The size and internal complexity of the company also was an important factor. POB was looking at large companies that had substantial resources. In the end, the process generated for Yale two competitive proposals, with Xerox's the clear winner. WATERS then described the components of the proposal, the design principles, and some of the costs estimated for the process. Components are essentially four: a conversion subsystem, a network-accessible storage subsystem for 10,000 books (and POB expects 200 to 600 dpi storage), browsing stations distributed on the campus network, and network access to the image printers. Among the design principles, POB wanted conversion at the highest possible resolution. Assuming TIFF files, TIFF files with Group 4 compression, TCP/IP, and ethernet network on campus, POB wanted a client-server approach with image documents distributed to the workstations and made accessible through native workstation interfaces such as Windows. POB also insisted on a phased approach to implementation: 1) a stand-alone, single-user, low-cost entry into the business with a workstation focused on conversion and allowing POB to explore user access; 2) movement into a higher-volume conversion with network-accessible storage and multiple access stations; and 3) a high-volume conversion, full-capacity storage, and multiple browsing stations distributed throughout the campus. The costs proposed for start-up assumed the existence of the Yale network and its two DocuTech image printers. Other start-up costs are estimated at $1 million over the three phases. At the end of the project, the annual operating costs estimated primarily for the software and hardware proposed come to about $60,000, but these exclude costs for labor needed in the conversion process, network and printer usage, and facilities management. Finally, the selection process produced for Yale a more sophisticated view of the imaging markets: the management of complex documents in image form is not a preservation problem, not a library problem, but a general problem in a broad, general industry. Preservation materials are useful for developing that market because of the qualities of the material. For example, much of it is out of copyright. The resolution of key issues such as the quality of scanning and image browsing also will affect development of that market. The technology is readily available but changing rapidly. In this context of rapid change, several factors affect quality and cost, to which POB intends to pay particular attention, for example, the various levels of resolution that can be achieved. POB believes it can bring resolution up to 600 dpi, but an interpolation process from 400 to 600 is more likely. The variation quality in microfilm will prove to be a highly important factor. POB may reexamine the standards used to film in the first place by looking at this process as a follow-on to microfilming. Other important factors include: the techniques available to the operator for handling material, the ways of integrating quality control into the digitizing work flow, and a work flow that includes indexing and storage. POB's requirement was to be able to deal with quality control at the point of scanning. Thus, thanks to Xerox, POB anticipates having a mechanism which will allow it not only to scan in batch form, but to review the material as it goes through the scanner and control quality from the outset. The standards for measuring quality and costs depend greatly on the uses of the material, including subsequent OCR, storage, printing, and browsing. But especially at issue for POB is the facility for browsing. This facility, WATERS said, is perhaps the weakest aspect of imaging technology and the most in need of development. A variety of factors affect the usability of complex documents in image form, among them: 1) the ability of the system to handle the full range of document types, not just monographs but serials, multi-part monographs, and manuscripts; 2) the location of the database of record for bibliographic information about the image document, which POB wants to enter once and in the most useful place, the on-line catalog; 3) a document identifier for referencing the bibliographic information in one place and the images in another; 4) the technique for making the basic internal structure of the document accessible to the reader; and finally, 5) the physical presentation on the CRT of those documents. POB is ready to complete this phase now. One last decision involves deciding which material to scan. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * TIFF files constitute de facto standard * NARA's experience with image conversion software and text conversion * RFC 1314 * Considerable flux concerning available hardware and software solutions * NAL through-put rate during scanning * Window management questions * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ In the question-and-answer period that followed WATERS's presentation, the following points emerged: * ZIDAR's statement about using TIFF files as a standard meant de facto standard. This is what most people use and typically exchange with other groups, across platforms, or even occasionally across display software. * HOLMES commented on the unsuccessful experience of NARA in attempting to run image-conversion software or to exchange between applications: What are supposedly TIFF files go into other software that is supposed to be able to accept TIFF but cannot recognize the format and cannot deal with it, and thus renders the exchange useless. Re text conversion, he noted the different recognition rates obtained by substituting the make and model of scanners in NARA's recent test of an "intelligent" character-recognition product for a new company. In the selection of hardware and software, HOLMES argued, software no longer constitutes the overriding factor it did until about a year ago; rather it is perhaps important to look at both now. * Danny Cohen and Alan Katz of the University of Southern California Information Sciences Institute began circulating as an Internet RFC (RFC 1314) about a month ago a standard for a TIFF interchange format for Internet distribution of monochrome bit-mapped images, which LYNCH said he believed would be used as a de facto standard. * FLEISCHHAUER's impression from hearing these reports and thinking about AM's experience was that there is considerable flux concerning available hardware and software solutions. HOOTON agreed and commented at the same time on ZIDAR's statement that the equipment employed affects the results produced. One cannot draw a complete conclusion by saying it is difficult or impossible to perform OCR from scanning microfilm, for example, with that device, that set of parameters, and system requirements, because numerous other people are accomplishing just that, using other components, perhaps. HOOTON opined that both the hardware and the software were highly important. Most of the problems discussed today have been solved in numerous different ways by other people. Though it is good to be cognizant of various experiences, this is not to say that it will always be thus. * At NAL, the through-put rate of the scanning process for paper, page by page, performing OCR, ranges from 300 to 600 pages per day; not performing OCR is considerably faster, although how much faster is not known. This is for scanning from bound books, which is much slower. * WATERS commented on window management questions: DEC proposed an X-Windows solution which was problematical for two reasons. One was POB's requirement to be able to manipulate images on the workstation and bring them down to the workstation itself and the other was network usage. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ THOMA * Illustration of deficiencies in scanning and storage process * Image quality in this process * Different costs entailed by better image quality * Techniques for overcoming various de-ficiencies: fixed thresholding, dynamic thresholding, dithering, image merge * Page edge effects * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ George THOMA, chief, Communications Engineering Branch, National Library of Medicine (NLM), illustrated several of the deficiencies discussed by the previous speakers. He introduced the topic of special problems by noting the advantages of electronic imaging. For example, it is regenerable because it is a coded file, and real-time quality control is possible with electronic capture, whereas in photographic capture it is not. One of the difficulties discussed in the scanning and storage process was image quality which, without belaboring the obvious, means different things for maps, medical X-rays, or broadcast television. In the case of documents, THOMA said, image quality boils down to legibility of the textual parts, and fidelity in the case of gray or color photo print-type material. Legibility boils down to scan density, the standard in most cases being 300 dpi. Increasing the resolution with scanners that perform 600 or 1200 dpi, however, comes at a cost. Better image quality entails at least four different kinds of costs: 1) equipment costs, because the CCD (i.e., charge-couple device) with greater number of elements costs more; 2) time costs that translate to the actual capture costs, because manual labor is involved (the time is also dependent on the fact that more data has to be moved around in the machine in the scanning or network devices that perform the scanning as well as the storage); 3) media costs, because at high resolutions larger files have to be stored; and 4) transmission costs, because there is just more data to be transmitted. But while resolution takes care of the issue of legibility in image quality, other deficiencies have to do with contrast and elements on the page scanned or the image that needed to be removed or clarified. Thus, THOMA proceeded to illustrate various deficiencies, how they are manifested, and several techniques to overcome them. Fixed thresholding was the first technique described, suitable for black-and-white text, when the contrast does not vary over the page. One can have many different threshold levels in scanning devices. Thus, THOMA offered an example of extremely poor contrast, which resulted from the fact that the stock was a heavy red. This is the sort of image that when microfilmed fails to provide any legibility whatsoever. Fixed thresholding is the way to change the black-to-red contrast to the desired black-to-white contrast. Other examples included material that had been browned or yellowed by age. This was also a case of contrast deficiency, and correction was done by fixed thresholding. A final example boils down to the same thing, slight variability, but it is not significant. Fixed thresholding solves this problem as well. The microfilm equivalent is certainly legible, but it comes with dark areas. Though THOMA did not have a slide of the microfilm in this case, he did show the reproduced electronic image. When one has variable contrast over a page or the lighting over the page area varies, especially in the case where a bound volume has light shining on it, the image must be processed by a dynamic thresholding scheme. One scheme, dynamic averaging, allows the threshold level not to be fixed but to be recomputed for every pixel from the neighboring characteristics. The neighbors of a pixel determine where the threshold should be set for that pixel. THOMA showed an example of a page that had been made deficient by a variety of techniques, including a burn mark, coffee stains, and a yellow marker. Application of a fixed-thresholding scheme, THOMA argued, might take care of several deficiencies on the page but not all of them. Performing the calculation for a dynamic threshold setting, however, removes most of the deficiencies so that at least the text is legible. Another problem is representing a gray level with black-and-white pixels by a process known as dithering or electronic screening. But dithering does not provide good image quality for pure black-and-white textual material. THOMA illustrated this point with examples. Although its suitability for photoprint is the reason for electronic screening or dithering, it cannot be used for every compound image. In the document that was distributed by CXP, THOMA noticed that the dithered image of the IEEE test chart evinced some deterioration in the text. He presented an extreme example of deterioration in the text in which compounded documents had to be set right by other techniques. The technique illustrated by the present example was an image merge in which the page is scanned twice and the settings go from fixed threshold to the dithering matrix; the resulting images are merged to give the best results with each technique. THOMA illustrated how dithering is also used in nonphotographic or nonprint materials with an example of a grayish page from a medical text, which was reproduced to show all of the gray that appeared in the original. Dithering provided a reproduction of all the gray in the original of another example from the same text. THOMA finally illustrated the problem of bordering, or page-edge, effects. Books and bound volumes that are placed on a photocopy machine or a scanner produce page-edge effects that are undesirable for two reasons: 1) the aesthetics of the image; after all, if the image is to be preserved, one does not necessarily want to keep all of its deficiencies; 2) compression (with the bordering problem THOMA illustrated, the compression ratio deteriorated tremendously). One way to eliminate this more serious problem is to have the operator at the point of scanning window the part of the image that is desirable and automatically turn all of the pixels out of that picture to white. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ FLEISCHHAUER * AM's experience with scanning bound materials * Dithering * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Carl FLEISCHHAUER, coordinator, American Memory, Library of Congress, reported AM's experience with scanning bound materials, which he likened to the problems involved in using photocopying machines. Very few devices in the industry offer book-edge scanning, let alone book cradles. The problem may be unsolvable, FLEISCHHAUER said, because a large enough market does not exist for a preservation-quality scanner. AM is using a Kurzweil scanner, which is a book-edge scanner now sold by Xerox. Devoting the remainder of his brief presentation to dithering, FLEISCHHAUER related AM's experience with a contractor who was using unsophisticated equipment and software to reduce moire patterns from printed halftones. AM took the same image and used the dithering algorithm that forms part of the same Kurzweil Xerox scanner; it disguised moire patterns much more effectively. FLEISCHHAUER also observed that dithering produces a binary file which is useful for numerous purposes, for example, printing it on a laser printer without having to "re-halftone" it. But it tends to defeat efficient compression, because the very thing that dithers to reduce moire patterns also tends to work against compression schemes. AM thought the difference in image quality was worth it. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Relative use as a criterion for POB's selection of books to be converted into digital form * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the discussion period, WATERS noted that one of the criteria for selecting books among the 10,000 to be converted into digital image form would be how much relative use they would receive--a subject still requiring evaluation. The challenge will be to understand whether coherent bodies of material will increase usage or whether POB should seek material that is being used, scan that, and make it more accessible. POB might decide to digitize materials that are already heavily used, in order to make them more accessible and decrease wear on them. Another approach would be to provide a large body of intellectually coherent material that may be used more in digital form than it is currently used in microfilm. POB would seek material that was out of copyright. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BARONAS * Origin and scope of AIIM * Types of documents produced in AIIM's standards program * Domain of AIIM's standardization work * AIIM's structure * TC 171 and MS23 * Electronic image management standards * Categories of EIM standardization where AIIM standards are being developed * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Jean BARONAS, senior manager, Department of Standards and Technology, Association for Information and Image Management (AIIM), described the not-for-profit association and the national and international programs for standardization in which AIIM is active. Accredited for twenty-five years as the nation's standards development organization for document image management, AIIM began life in a library community developing microfilm standards. Today the association maintains both its library and business-image management standardization activities--and has moved into electronic image-management standardization (EIM). BARONAS defined the program's scope. AIIM deals with: 1) the terminology of standards and of the technology it uses; 2) methods of measurement for the systems, as well as quality; 3) methodologies for users to evaluate and measure quality; 4) the features of apparatus used to manage and edit images; and 5) the procedures used to manage images. BARONAS noted that three types of documents are produced in the AIIM standards program: the first two, accredited by the American National Standards Institute (ANSI), are standards and standard recommended practices. Recommended practices differ from standards in that they contain more tutorial information. A technical report is not an ANSI standard. Because AIIM's policies and procedures for developing standards are approved by ANSI, its standards are labeled ANSI/AIIM, followed by the number and title of the standard. BARONAS then illustrated the domain of AIIM's standardization work. For example, AIIM is the administrator of the U.S. Technical Advisory Group (TAG) to the International Standards Organization's (ISO) technical committee, TC l7l Micrographics and Optical Memories for Document and Image Recording, Storage, and Use. AIIM officially works through ANSI in the international standardization process. BARONAS described AIIM's structure, including its board of directors, its standards board of twelve individuals active in the image-management industry, its strategic planning and legal admissibility task forces, and its National Standards Council, which is comprised of the members of a number of organizations who vote on every AIIM standard before it is published. BARONAS pointed out that AIIM's liaisons deal with numerous other standards developers, including the optical disk community, office and publishing systems, image-codes-and-character set committees, and the National Information Standards Organization (NISO). BARONAS illustrated the procedures of TC l7l, which covers all aspects of image management. When AIIM's national program has conceptualized a new project, it is usually submitted to the international level, so that the member countries of TC l7l can simultaneously work on the development of the standard or the technical report. BARONAS also illustrated a classic microfilm standard, MS23, which deals with numerous imaging concepts that apply to electronic imaging. Originally developed in the l970s, revised in the l980s, and revised again in l991, this standard is scheduled for another revision. MS23 is an active standard whereby users may propose new density ranges and new methods of evaluating film images in the standard's revision. BARONAS detailed several electronic image-management standards, for instance, ANSI/AIIM MS44, a quality-control guideline for scanning 8.5" by 11" black-and-white office documents. This standard is used with the IEEE fax image--a continuous tone photographic image with gray scales, text, and several continuous tone pictures--and AIIM test target number 2, a representative document used in office document management. BARONAS next outlined the four categories of EIM standardization in which AIIM standards are being developed: transfer and retrieval, evaluation, optical disc and document scanning applications, and design and conversion of documents. She detailed several of the main projects of each: 1) in the category of image transfer and retrieval, a bi-level image transfer format, ANSI/AIIM MS53, which is a proposed standard that describes a file header for image transfer between unlike systems when the images are compressed using G3 and G4 compression; 2) the category of image evaluation, which includes the AIIM-proposed TR26 tutorial on image resolution (this technical report will treat the differences and similarities between classical or photographic and electronic imaging); 3) design and conversion, which includes a proposed technical report called "Forms Design Optimization for EIM" (this report considers how general-purpose business forms can be best designed so that scanning is optimized; reprographic characteristics such as type, rules, background, tint, and color will likewise be treated in the technical report); 4) disk and document scanning applications includes a project a) on planning platters and disk management, b) on generating an application profile for EIM when images are stored and distributed on CD-ROM, and c) on evaluating SCSI2, and how a common command set can be generated for SCSI2 so that document scanners are more easily integrated. (ANSI/AIIM MS53 will also apply to compressed images.) ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ BATTIN * The implications of standards for preservation * A major obstacle to successful cooperation * A hindrance to access in the digital environment * Standards a double-edged sword for those concerned with the preservation of the human record * Near-term prognosis for reliable archival standards * Preservation concerns for electronic media * Need for reconceptualizing our preservation principles * Standards in the real world and the politics of reproduction * Need to redefine the concept of archival and to begin to think in terms of life cycles * Cooperation and the La Guardia Eight * Concerns generated by discussions on the problems of preserving text and image * General principles to be adopted in a world without standards * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Patricia BATTIN, president, the Commission on Preservation and Access (CPA), addressed the implications of standards for preservation. She listed several areas where the library profession and the analog world of the printed book had made enormous contributions over the past hundred years--for example, in bibliographic formats, binding standards, and, most important, in determining what constitutes longevity or archival quality. Although standards have lightened the preservation burden through the development of national and international collaborative programs, nevertheless, a pervasive mistrust of other people's standards remains a major obstacle to successful cooperation, BATTIN said. The zeal to achieve perfection, regardless of the cost, has hindered rather than facilitated access in some instances, and in the digital environment, where no real standards exist, has brought an ironically just reward. BATTIN argued that standards are a double-edged sword for those concerned with the preservation of the human record, that is, the provision of access to recorded knowledge in a multitude of media as far into the future as possible. Standards are essential to facilitate interconnectivity and access, but, BATTIN said, as LYNCH pointed out yesterday, if set too soon they can hinder creativity, expansion of capability, and the broadening of access. The characteristics of standards for digital imagery differ radically from those for analog imagery. And the nature of digital technology implies continuing volatility and change. To reiterate, precipitous standard-setting can inhibit creativity, but delayed standard-setting results in chaos. Since in BATTIN'S opinion the near-term prognosis for reliable archival standards, as defined by librarians in the analog world, is poor, two alternatives remain: standing pat with the old technology, or reconceptualizing. Preservation concerns for electronic media fall into two general domains. One is the continuing assurance of access to knowledge originally generated, stored, disseminated, and used in electronic form. This domain contains several subdivisions, including 1) the closed, proprietary systems discussed the previous day, bundled information such as electronic journals and government agency records, and electronically produced or captured raw data; and 2) the application of digital technologies to the reformatting of materials originally published on a deteriorating analog medium such as acid paper or videotape. The preservation of electronic media requires a reconceptualizing of our preservation principles during a volatile, standardless transition which may last far longer than any of us envision today. BATTIN urged the necessity of shifting focus from assessing, measuring, and setting standards for the permanence of the medium to the concept of managing continuing access to information stored on a variety of media and requiring a variety of ever-changing hardware and software for access--a fundamental shift for the library profession. BATTIN offered a primer on how to move forward with reasonable confidence in a world without standards. Her comments fell roughly into two sections: 1) standards in the real world and 2) the politics of reproduction. In regard to real-world standards, BATTIN argued the need to redefine the concept of archive and to begin to think in terms of life cycles. In the past, the naive assumption that paper would last forever produced a cavalier attitude toward life cycles. The transient nature of the electronic media has compelled people to recognize and accept upfront the concept of life cycles in place of permanency. Digital standards have to be developed and set in a cooperative context to ensure efficient exchange of information. Moreover, during this transition period, greater flexibility concerning how concepts such as backup copies and archival copies in the CXP are defined is necessary, or the opportunity to move forward will be lost. In terms of cooperation, particularly in the university setting, BATTIN also argued the need to avoid going off in a hundred different directions. The CPA has catalyzed a small group of universities called the La Guardia Eight--because La Guardia Airport is where meetings take place--Harvard, Yale, Cornell, Princeton, Penn State, Tennessee, Stanford, and USC, to develop a digital preservation consortium to look at all these issues and develop de facto standards as we move along, instead of waiting for something that is officially blessed. Continuing to apply analog values and definitions of standards to the digital environment, BATTIN said, will effectively lead to forfeiture of the benefits of digital technology to research and scholarship. Under the second rubric, the politics of reproduction, BATTIN reiterated an oft-made argument concerning the electronic library, namely, that it is more difficult to transform than to create, and nowhere is that belief expressed more dramatically than in the conversion of brittle books to new media. Preserving information published in electronic media involves making sure the information remains accessible and that digital information is not lost through reproduction. In the analog world of photocopies and microfilm, the issue of fidelity to the original becomes paramount, as do issues of "Whose fidelity?" and "Whose original?" BATTIN elaborated these arguments with a few examples from a recent study conducted by the CPA on the problems of preserving text and image. Discussions with scholars, librarians, and curators in a variety of disciplines dependent on text and image generated a variety of concerns, for example: 1) Copy what is, not what the technology is capable of. This is very important for the history of ideas. Scholars wish to know what the author saw and worked from. And make available at the workstation the opportunity to erase all the defects and enhance the presentation. 2) The fidelity of reproduction--what is good enough, what can we afford, and the difference it makes--issues of subjective versus objective resolution. 3) The differences between primary and secondary users. Restricting the definition of primary user to the one in whose discipline the material has been published runs one headlong into the reality that these printed books have had a host of other users from a host of other disciplines, who not only were looking for very different things, but who also shared values very different from those of the primary user. 4) The relationship of the standard of reproduction to new capabilities of scholarship--the browsing standard versus an archival standard. How good must the archival standard be? Can a distinction be drawn between potential users in setting standards for reproduction? Archival storage, use copies, browsing copies--ought an attempt to set standards even be made? 5) Finally, costs. How much are we prepared to pay to capture absolute fidelity? What are the trade-offs between vastly enhanced access, degrees of fidelity, and costs? These standards, BATTIN concluded, serve to complicate further the reproduction process, and add to the long list of technical standards that are necessary to ensure widespread access. Ways to articulate and analyze the costs that are attached to the different levels of standards must be found. Given the chaos concerning standards, which promises to linger for the foreseeable future, BATTIN urged adoption of the following general principles: * Strive to understand the changing information requirements of scholarly disciplines as more and more technology is integrated into the process of research and scholarly communication in order to meet future scholarly needs, not to build for the past. Capture deteriorating information at the highest affordable resolution, even though the dissemination and display technologies will lag. * Develop cooperative mechanisms to foster agreement on protocols for document structure and other interchange mechanisms necessary for widespread dissemination and use before official standards are set. * Accept that, in a transition period, de facto standards will have to be developed. * Capture information in a way that keeps all options open and provides for total convertibility: OCR, scanning of microfilm, producing microfilm from scanned documents, etc. * Work closely with the generators of information and the builders of networks and databases to ensure that continuing accessibility is a primary concern from the beginning. * Piggyback on standards under development for the broad market, and avoid library-specific standards; work with the vendors, in order to take advantage of that which is being standardized for the rest of the world. * Concentrate efforts on managing permanence in the digital world, rather than perfecting the longevity of a particular medium. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Additional comments on TIFF * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the brief discussion period that followed BATTIN's presentation, BARONAS explained that TIFF was not developed in collaboration with or under the auspices of AIIM. TIFF is a company product, not a standard, is owned by two corporations, and is always changing. BARONAS also observed that ANSI/AIIM MS53, a bi-level image file transfer format that allows unlike systems to exchange images, is compatible with TIFF as well as with DEC's architecture and IBM's MODCA/IOCA. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HOOTON * Several questions to be considered in discussing text conversion * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HOOTON introduced the final topic, text conversion, by noting that it is becoming an increasingly important part of the imaging business. Many people now realize that it enhances their system to be able to have more and more character data as part of their imaging system. Re the issue of OCR versus rekeying, HOOTON posed several questions: How does one get text into computer-readable form? Does one use automated processes? Does one attempt to eliminate the use of operators where possible? Standards for accuracy, he said, are extremely important: it makes a major difference in cost and time whether one sets as a standard 98.5 percent acceptance or 99.5 percent. He mentioned outsourcing as a possibility for converting text. Finally, what one does with the image to prepare it for the recognition process is also important, he said, because such preparation changes how recognition is viewed, as well as facilitates recognition itself. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LESK * Roles of participants in CORE * Data flow * The scanning process * The image interface * Results of experiments involving the use of electronic resources and traditional paper copies * Testing the issue of serendipity * Conclusions * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Michael LESK, executive director, Computer Science Research, Bell Communications Research, Inc. (Bellcore), discussed the Chemical Online Retrieval Experiment (CORE), a cooperative project involving Cornell University, OCLC, Bellcore, and the American Chemical Society (ACS). LESK spoke on 1) how the scanning was performed, including the unusual feature of page segmentation, and 2) the use made of the text and the image in experiments. Working with the chemistry journals (because ACS has been saving its typesetting tapes since the mid-1970s and thus has a significant back-run of the most important chemistry journals in the United States), CORE is attempting to create an automated chemical library. Approximately a quarter of the pages by square inch are made up of images of quasi-pictorial material; dealing with the graphic components of the pages is extremely important. LESK described the roles of participants in CORE: 1) ACS provides copyright permission, journals on paper, journals on microfilm, and some of the definitions of the files; 2) at Bellcore, LESK chiefly performs the data preparation, while Dennis Egan performs experiments on the users of chemical abstracts, and supplies the indexing and numerous magnetic tapes; 3) Cornell provides the site of the experiment; 4) OCLC develops retrieval software and other user interfaces. Various manufacturers and publishers have furnished other help. Concerning data flow, Bellcore receives microfilm and paper from ACS; the microfilm is scanned by outside vendors, while the paper is scanned inhouse on an Improvision scanner, twenty pages per minute at 300 dpi, which provides sufficient quality for all practical uses. LESK would prefer to have more gray level, because one of the ACS journals prints on some colored pages, which creates a problem. Bellcore performs all this scanning, creates a page-image file, and also selects from the pages the graphics, to mix with the text file (which is discussed later in the Workshop). The user is always searching the ASCII file, but she or he may see a display based on the ASCII or a display based on the images. LESK illustrated how the program performs page analysis, and the image interface. (The user types several words, is presented with a list-- usually of the titles of articles contained in an issue--that derives from the ASCII, clicks on an icon and receives an image that mirrors an ACS page.) LESK also illustrated an alternative interface, based on text on the ASCII, the so-called SuperBook interface from Bellcore. LESK next presented the results of an experiment conducted by Dennis Egan and involving thirty-six students at Cornell, one third of them undergraduate chemistry majors, one third senior undergraduate chemistry majors, and one third graduate chemistry students. A third of them received the paper journals, the traditional paper copies and chemical abstracts on paper. A third received image displays of the pictures of the pages, and a third received the text display with pop-up graphics. The students were given several questions made up by some chemistry professors. The questions fell into five classes, ranging from very easy to very difficult, and included questions designed to simulate browsing as well as a traditional information retrieval-type task. LESK furnished the following results. In the straightforward question search--the question being, what is the phosphorus oxygen bond distance and hydroxy phosphate?--the students were told that they could take fifteen minutes and, then, if they wished, give up. The students with paper took more than fifteen minutes on average, and yet most of them gave up. The students with either electronic format, text or image, received good scores in reasonable time, hardly ever had to give up, and usually found the right answer. In the browsing study, the students were given a list of eight topics, told to imagine that an issue of the Journal of the American Chemical Society had just appeared on their desks, and were also told to flip through it and to find topics mentioned in the issue. The average scores were about the same. (The students were told to answer yes or no about whether or not particular topics appeared.) The errors, however, were quite different. The students with paper rarely said that something appeared when it had not. But they often failed to find something actually mentioned in the issue. The computer people found numerous things, but they also frequently said that a topic was mentioned when it was not. (The reason, of course, was that they were performing word searches. They were finding that words were mentioned and they were concluding that they had accomplished their task.) This question also contained a trick to test the issue of serendipity. The students were given another list of eight topics and instructed, without taking a second look at the journal, to recall how many of this new list of eight topics were in this particular issue. This was an attempt to see if they performed better at remembering what they were not looking for. They all performed about the same, paper or electronics, about 62 percent accurate. In short, LESK said, people were not very good when it came to serendipity, but they were no worse at it with computers than they were with paper. (LESK gave a parenthetical illustration of the learning curve of students who used SuperBook.) The students using the electronic systems started off worse than the ones using print, but by the third of the three sessions in the series had caught up to print. As one might expect, electronics provide a much better means of finding what one wants to read; reading speeds, once the object of the search has been found, are about the same. Almost none of the students could perform the hard task--the analogous transformation. (It would require the expertise of organic chemists to complete.) But an interesting result was that the students using the text search performed terribly, while those using the image system did best. That the text search system is driven by text offers the explanation. Everything is focused on the text; to see the pictures, one must press on an icon. Many students found the right article containing the answer to the question, but they did not click on the icon to bring up the right figure and see it. They did not know that they had found the right place, and thus got it wrong. The short answer demonstrated by this experiment was that in the event one does not know what to read, one needs the electronic systems; the electronic systems hold no advantage at the moment if one knows what to read, but neither do they impose a penalty. LESK concluded by commenting that, on one hand, the image system was easy to use. On the other hand, the text display system, which represented twenty man-years of work in programming and polishing, was not winning, because the text was not being read, just searched. The much easier system is highly competitive as well as remarkably effective for the actual chemists. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ERWAY * Most challenging aspect of working on AM * Assumptions guiding AM's approach * Testing different types of service bureaus * AM's requirement for 99.95 percent accuracy * Requirements for text-coding * Additional factors influencing AM's approach to coding * Results of AM's experience with rekeying * Other problems in dealing with service bureaus * Quality control the most time-consuming aspect of contracting out conversion * Long-term outlook uncertain * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ To Ricky ERWAY, associate coordinator, American Memory, Library of Congress, the constant variety of conversion projects taking place simultaneously represented perhaps the most challenging aspect of working on AM. Thus, the challenge was not to find a solution for text conversion but a tool kit of solutions to apply to LC's varied collections that need to be converted. ERWAY limited her remarks to the process of converting text to machine-readable form, and the variety of LC's text collections, for example, bound volumes, microfilm, and handwritten manuscripts. Two assumptions have guided AM's approach, ERWAY said: 1) A desire not to perform the conversion inhouse. Because of the variety of formats and types of texts, to capitalize the equipment and have the talents and skills to operate them at LC would be extremely expensive. Further, the natural inclination to upgrade to newer and better equipment each year made it reasonable for AM to focus on what it did best and seek external conversion services. Using service bureaus also allowed AM to have several types of operations take place at the same time. 2) AM was not a technology project, but an effort to improve access to library collections. Hence, whether text was converted using OCR or rekeying mattered little to AM. What mattered were cost and accuracy of results. AM considered different types of service bureaus and selected three to perform several small tests in order to acquire a sense of the field. The sample collections with which they worked included handwritten correspondence, typewritten manuscripts from the 1940s, and eighteenth-century printed broadsides on microfilm. On none of these samples was OCR performed; they were all rekeyed. AM had several special requirements for the three service bureaus it had engaged. For instance, any errors in the original text were to be retained. Working from bound volumes or anything that could not be sheet-fed also constituted a factor eliminating companies that would have performed OCR. AM requires 99.95 percent accuracy, which, though it sounds high, often means one or two errors per page. The initial batch of test samples contained several handwritten materials for which AM did not require text-coding. The results, ERWAY reported, were in all cases fairly comparable: for the most part, all three service bureaus achieved 99.95 percent accuracy. AM was satisfied with the work but surprised at the cost. As AM began converting whole collections, it retained the requirement for 99.95 percent accuracy and added requirements for text-coding. AM needed to begin performing work more than three years ago before LC requirements for SGML applications had been established. Since AM's goal was simply to retain any of the intellectual content represented by the formatting of the document (which would be lost if one performed a straight ASCII conversion), AM used "SGML-like" codes. These codes resembled SGML tags but were used without the benefit of document-type definitions. AM found that many service bureaus were not yet SGML-proficient. Additional factors influencing the approach AM took with respect to coding included: 1) the inability of any known microcomputer-based user-retrieval software to take advantage of SGML coding; and 2) the multiple inconsistencies in format of the older documents, which confirmed AM in its desire not to attempt to force the different formats to conform to a single document-type definition (DTD) and thus create the need for a separate DTD for each document. The five text collections that AM has converted or is in the process of converting include a collection of eighteenth-century broadsides, a collection of pamphlets, two typescript document collections, and a collection of 150 books. ERWAY next reviewed the results of AM's experience with rekeying, noting again that because the bulk of AM's materials are historical, the quality of the text often does not lend itself to OCR. While non-English speakers are less likely to guess or elaborate or correct typos in the original text, they are also less able to infer what we would; they also are nearly incapable of converting handwritten text. Another disadvantage of working with overseas keyers is that they are much less likely to telephone with questions, especially on the coding, with the result that they develop their own rules as they encounter new situations. Government contracting procedures and time frames posed a major challenge to performing the conversion. Many service bureaus are not accustomed to retaining the image, even if they perform OCR. Thus, questions of image format and storage media were somewhat novel to many of them. ERWAY also remarked other problems in dealing with service bureaus, for example, their inability to perform text conversion from the kind of microfilm that LC uses for preservation purposes. But quality control, in ERWAY's experience, was the most time-consuming aspect of contracting out conversion. AM has been attempting to perform a 10-percent quality review, looking at either every tenth document or every tenth page to make certain that the service bureaus are maintaining 99.95 percent accuracy. But even if they are complying with the requirement for accuracy, finding errors produces a desire to correct them and, in turn, to clean up the whole collection, which defeats the purpose to some extent. Even a double entry requires a character-by-character comparison to the original to meet the accuracy requirement. LC is not accustomed to publish imperfect texts, which makes attempting to deal with the industry standard an emotionally fraught issue for AM. As was mentioned in the previous day's discussion, going from 99.95 to 99.99 percent accuracy usually doubles costs and means a third keying or another complete run-through of the text. Although AM has learned much from its experiences with various collections and various service bureaus, ERWAY concluded pessimistically that no breakthrough has been achieved. Incremental improvements have occurred in some of the OCR technology, some of the processes, and some of the standards acceptances, which, though they may lead to somewhat lower costs, do not offer much encouragement to many people who are anxiously awaiting the day that the entire contents of LC are available on-line. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ZIDAR * Several answers to why one attempts to perform full-text conversion * Per page cost of performing OCR * Typical problems encountered during editing * Editing poor copy OCR vs. rekeying * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Judith ZIDAR, coordinator, National Agricultural Text Digitizing Program (NATDP), National Agricultural Library (NAL), offered several answers to the question of why one attempts to perform full-text conversion: 1) Text in an image can be read by a human but not by a computer, so of course it is not searchable and there is not much one can do with it. 2) Some material simply requires word-level access. For instance, the legal profession insists on full-text access to its material; with taxonomic or geographic material, which entails numerous names, one virtually requires word-level access. 3) Full text permits rapid browsing and searching, something that cannot be achieved in an image with today's technology. 4) Text stored as ASCII and delivered in ASCII is standardized and highly portable. 5) People just want full-text searching, even those who do not know how to do it. NAL, for the most part, is performing OCR at an actual cost per average-size page of approximately $7. NAL scans the page to create the electronic image and passes it through the OCR device. ZIDAR next rehearsed several typical problems encountered during editing. Praising the celerity of her student workers, ZIDAR observed that editing requires approximately five to ten minutes per page, assuming that there are no large tables to audit. Confusion among the three characters I, 1, and l, constitutes perhaps the most common problem encountered. Zeroes and O's also are frequently confused. Double M's create a particular problem, even on clean pages. They are so wide in most fonts that they touch, and the system simply cannot tell where one letter ends and the other begins. Complex page formats occasionally fail to columnate properly, which entails rescanning as though one were working with a single column, entering the ASCII, and decolumnating for better searching. With proportionally spaced text, OCR can have difficulty discerning what is a space and what are merely spaces between letters, as opposed to spaces between words, and therefore will merge text or break up words where it should not. ZIDAR said that it can often take longer to edit a poor-copy OCR than to key it from scratch. NAL has also experimented with partial editing of text, whereby project workers go into and clean up the format, removing stray characters but not running a spell-check. NAL corrects typos in the title and authors' names, which provides a foothold for searching and browsing. Even extremely poor-quality OCR (e.g., 60-percent accuracy) can still be searched, because numerous words are correct, while the important words are probably repeated often enough that they are likely to be found correct somewhere. Librarians, however, cannot tolerate this situation, though end users seem more willing to use this text for searching, provided that NAL indicates that it is unedited. ZIDAR concluded that rekeying of text may be the best route to take, in spite of numerous problems with quality control and cost. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Modifying an image before performing OCR * NAL's costs per page *AM's costs per page and experience with Federal Prison Industries * Elements comprising NATDP's costs per page * OCR and structured markup * Distinction between the structure of a document and its representation when put on the screen or printed * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HOOTON prefaced the lengthy discussion that followed with several comments about modifying an image before one reaches the point of performing OCR. For example, in regard to an application containing a significant amount of redundant data, such as form-type data, numerous companies today are working on various kinds of form renewal, prior to going through a recognition process, by using dropout colors. Thus, acquiring access to form design or using electronic means are worth considering. HOOTON also noted that conversion usually makes or breaks one's imaging system. It is extremely important, extremely costly in terms of either capital investment or service, and determines the quality of the remainder of one's system, because it determines the character of the raw material used by the system. Concerning the four projects undertaken by NAL, two inside and two performed by outside contractors, ZIDAR revealed that an in-house service bureau executed the first at a cost between $8 and $10 per page for everything, including building of the database. The project undertaken by the Consultative Group on International Agricultural Research (CGIAR) cost approximately $10 per page for the conversion, plus some expenses for the software and building of the database. The Acid Rain Project--a two-disk set produced by the University of Vermont, consisting of Canadian publications on acid rain--cost $6.70 per page for everything, including keying of the text, which was double keyed, scanning of the images, and building of the database. The in-house project offered considerable ease of convenience and greater control of the process. On the other hand, the service bureaus know their job and perform it expeditiously, because they have more people. As a useful comparison, ERWAY revealed AM's costs as follows: $0.75 cents to $0.85 cents per thousand characters, with an average page containing 2,700 characters. Requirements for coding and imaging increase the costs. Thus, conversion of the text, including the coding, costs approximately $3 per page. (This figure does not include the imaging and database-building included in the NAL costs.) AM also enjoyed a happy experience with Federal Prison Industries, which precluded the necessity of going through the request-for-proposal process to award a contract, because it is another government agency. The prisoners performed AM's rekeying just as well as other service bureaus and proved handy as well. AM shipped them the books, which they would photocopy on a book-edge scanner. They would perform the markup on photocopies, return the books as soon as they were done with them, perform the keying, and return the material to AM on WORM disks. ZIDAR detailed the elements that constitute the previously noted cost of approximately $7 per page. Most significant is the editing, correction of errors, and spell-checkings, which though they may sound easy to perform require, in fact, a great deal of time. Reformatting text also takes a while, but a significant amount of NAL's expenses are for equipment, which was extremely expensive when purchased because it was one of the few systems on the market. The costs of equipment are being amortized over five years but are still quite high, nearly $2,000 per month. HOCKEY raised a general question concerning OCR and the amount of editing required (substantial in her experience) to generate the kind of structured markup necessary for manipulating the text on the computer or loading it into any retrieval system. She wondered if the speakers could extend the previous question about the cost-benefit of adding or exerting structured markup. ERWAY noted that several OCR systems retain italics, bolding, and other spatial formatting. While the material may not be in the format desired, these systems possess the ability to remove the original materials quickly from the hands of the people performing the conversion, as well as to retain that information so that users can work with it. HOCKEY rejoined that the current thinking on markup is that one should not say that something is italic or bold so much as why it is that way. To be sure, one needs to know that something was italicized, but how can one get from one to the other? One can map from the structure to the typographic representation. FLEISCHHAUER suggested that, given the 100 million items the Library holds, it may not be possible for LC to do more than report that a thing was in italics as opposed to why it was italics, although that may be desirable in some contexts. Promising to talk a bit during the afternoon session about several experiments OCLC performed on automatic recognition of document elements, and which they hoped to extend, WEIBEL said that in fact one can recognize the major elements of a document with a fairly high degree of reliability, at least as good as OCR. STEVENS drew a useful distinction between standard, generalized markup (i.e., defining for a document-type definition the structure of the document), and what he termed a style sheet, which had to do with italics, bolding, and other forms of emphasis. Thus, two different components are at work, one being the structure of the document itself (its logic), and the other being its representation when it is put on the screen or printed. ****** SESSION V. APPROACHES TO PREPARING ELECTRONIC TEXTS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HOCKEY * Text in ASCII and the representation of electronic text versus an image * The need to look at ways of using markup to assist retrieval * The need for an encoding format that will be reusable and multifunctional +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Susan HOCKEY, director, Center for Electronic Texts in the Humanities (CETH), Rutgers and Princeton Universities, announced that one talk (WEIBEL's) was moved into this session from the morning and that David Packard was unable to attend. The session would attempt to focus more on what one can do with a text in ASCII and the representation of electronic text rather than just an image, what one can do with a computer that cannot be done with a book or an image. It would be argued that one can do much more than just read a text, and from that starting point one can use markup and methods of preparing the text to take full advantage of the capability of the computer. That would lead to a discussion of what the European Community calls REUSABILITY, what may better be termed DURABILITY, that is, how to prepare or make a text that will last a long time and that can be used for as many applications as possible, which would lead to issues of improving intellectual access. HOCKEY urged the need to look at ways of using markup to facilitate retrieval, not just for referencing or to help locate an item that is retrieved, but also to put markup tags in a text to help retrieve the thing sought either with linguistic tagging or interpretation. HOCKEY also argued that little advancement had occurred in the software tools currently available for retrieving and searching text. She pressed the desideratum of going beyond Boolean searches and performing more sophisticated searching, which the insertion of more markup in the text would facilitate. Thinking about electronic texts as opposed to images means considering material that will never appear in print form, or print will not be its primary form, that is, material which only appears in electronic form. HOCKEY alluded to the history and the need for markup and tagging and electronic text, which was developed through the use of computers in the humanities; as MICHELSON had observed, Father Busa had started in 1949 to prepare the first-ever text on the computer. HOCKEY remarked several large projects, particularly in Europe, for the compilation of dictionaries, language studies, and language analysis, in which people have built up archives of text and have begun to recognize the need for an encoding format that will be reusable and multifunctional, that can be used not just to print the text, which may be assumed to be a byproduct of what one wants to do, but to structure it inside the computer so that it can be searched, built into a Hypertext system, etc. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ WEIBEL * OCLC's approach to preparing electronic text: retroconversion, keying of texts, more automated ways of developing data * Project ADAPT and the CORE Project * Intelligent character recognition does not exist * Advantages of SGML * Data should be free of procedural markup; descriptive markup strongly advocated * OCLC's interface illustrated * Storage requirements and costs for putting a lot of information on line * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Stuart WEIBEL, senior research scientist, Online Computer Library Center, Inc. (OCLC), described OCLC's approach to preparing electronic text. He argued that the electronic world into which we are moving must accommodate not only the future but the past as well, and to some degree even the present. Thus, starting out at one end with retroconversion and keying of texts, one would like to move toward much more automated ways of developing data. For example, Project ADAPT had to do with automatically converting document images into a structured document database with OCR text as indexing and also a little bit of automatic formatting and tagging of that text. The CORE project hosted by Cornell University, Bellcore, OCLC, the American Chemical Society, and Chemical Abstracts, constitutes WEIBEL's principal concern at the moment. This project is an example of converting text for which one already has a machine-readable version into a format more suitable for electronic delivery and database searching. (Since Michael LESK had previously described CORE, WEIBEL would say little concerning it.) Borrowing a chemical phrase, de novo synthesis, WEIBEL cited the Online Journal of Current Clinical Trials as an example of de novo electronic publishing, that is, a form in which the primary form of the information is electronic. Project ADAPT, then, which OCLC completed a couple of years ago and in fact is about to resume, is a model in which one takes page images either in paper or microfilm and converts them automatically to a searchable electronic database, either on-line or local. The operating assumption is that accepting some blemishes in the data, especially for retroconversion of materials, will make it possible to accomplish more. Not enough money is available to support perfect conversion. WEIBEL related several steps taken to perform image preprocessing (processing on the image before performing optical character recognition), as well as image postprocessing. He denied the existence of intelligent character recognition and asserted that what is wanted is page recognition, which is a long way off. OCLC has experimented with merging of multiple optical character recognition systems that will reduce errors from an unacceptable rate of 5 characters out of every l,000 to an unacceptable rate of 2 characters out of every l,000, but it is not good enough. It will never be perfect. Concerning the CORE Project, WEIBEL observed that Bellcore is taking the topography files, extracting the page images, and converting those topography files to SGML markup. LESK hands that data off to OCLC, which builds that data into a Newton database, the same system that underlies the on-line system in virtually all of the reference products at OCLC. The long-term goal is to make the systems interoperable so that not just Bellcore's system and OCLC's system can access this data, but other systems can as well, and the key to that is the Z39.50 common command language and the full-text extension. Z39.50 is fine for MARC records, but is not enough to do it for full text (that is, make full texts interoperable). WEIBEL next outlined the critical role of SGML for a variety of purposes, for example, as noted by HOCKEY, in the world of extremely large databases, using highly structured data to perform field searches. WEIBEL argued that by building the structure of the data in (i.e., the structure of the data originally on a printed page), it becomes easy to look at a journal article even if one cannot read the characters and know where the title or author is, or what the sections of that document would be. OCLC wants to make that structure explicit in the database, because it will be important for retrieval purposes. The second big advantage of SGML is that it gives one the ability to build structure into the database that can be used for display purposes without contaminating the data with instructions about how to format things. The distinction lies between procedural markup, which tells one where to put dots on the page, and descriptive markup, which describes the elements of a document. WEIBEL believes that there should be no procedural markup in the data at all, that the data should be completely unsullied by information about italics or boldness. That should be left up to the display device, whether that display device is a page printer or a screen display device. By keeping one's database free of that kind of contamination, one can make decisions down the road, for example, reorganize the data in ways that are not cramped by built-in notions of what should be italic and what should be bold. WEIBEL strongly advocated descriptive markup. As an example, he illustrated the index structure in the CORE data. With subsequent illustrated examples of markup, WEIBEL acknowledged the common complaint that SGML is hard to read in its native form, although markup decreases considerably once one gets into the body. Without the markup, however, one would not have the structure in the data. One can pass markup through a LaTeX processor and convert it relatively easily to a printed version of the document. WEIBEL next illustrated an extremely cluttered screen dump of OCLC's system, in order to show as much as possible the inherent capability on the screen. (He noted parenthetically that he had become a supporter of X-Windows as a result of the progress of the CORE Project.) WEIBEL also illustrated the two major parts of the interface: l) a control box that allows one to generate lists of items, which resembles a small table of contents based on key words one wishes to search, and 2) a document viewer, which is a separate process in and of itself. He demonstrated how to follow links through the electronic database simply by selecting the appropriate button and bringing them up. He also noted problems that remain to be accommodated in the interface (e.g., as pointed out by LESK, what happens when users do not click on the icon for the figure). Given the constraints of time, WEIBEL omitted a large number of ancillary items in order to say a few words concerning storage requirements and what will be required to put a lot of things on line. Since it is extremely expensive to reconvert all of this data, especially if it is just in paper form (and even if it is in electronic form in typesetting tapes), he advocated building journals electronically from the start. In that case, if one only has text graphics and indexing (which is all that one needs with de novo electronic publishing, because there is no need to go back and look at bit-maps of pages), one can get 10,000 journals of full text, or almost 6 million pages per year. These pages can be put in approximately 135 gigabytes of storage, which is not all that much, WEIBEL said. For twenty years, something less than three terabytes would be required. WEIBEL calculated the costs of storing this information as follows: If a gigabyte costs approximately $1,000, then a terabyte costs approximately $1 million to buy in terms of hardware. One also needs a building to put it in and a staff like OCLC to handle that information. So, to support a terabyte, multiply by five, which gives $5 million per year for a supported terabyte of data. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Tapes saved by ACS are the typography files originally supporting publication of the journal * Cost of building tagged text into the database * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the question-and-answer period that followed WEIBEL's presentation, these clarifications emerged. The tapes saved by the American Chemical Society are the typography files that originally supported the publication of the journal. Although they are not tagged in SGML, they are tagged in very fine detail. Every single sentence is marked, all the registry numbers, all the publications issues, dates, and volumes. No cost figures on tagging material on a per-megabyte basis were available. Because ACS's typesetting system runs from tagged text, there is no extra cost per article. It was unknown what it costs ACS to keyboard the tagged text rather than just keyboard the text in the cheapest process. In other words, since one intends to publish things and will need to build tagged text into a typography system in any case, if one does that in such a way that it can drive not only typography but an electronic system (which is what ACS intends to do--move to SGML publishing), the marginal cost is zero. The marginal cost represents the cost of building tagged text into the database, which is small. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SPERBERG-McQUEEN * Distinction between texts and computers * Implications of recognizing that all representation is encoding * Dealing with complicated representations of text entails the need for a grammar of documents * Variety of forms of formal grammars * Text as a bit-mapped image does not represent a serious attempt to represent text in electronic form * SGML, the TEI, document-type declarations, and the reusability and longevity of data * TEI conformance explicitly allows extension or modification of the TEI tag set * Administrative background of the TEI * Several design goals for the TEI tag set * An absolutely fixed requirement of the TEI Guidelines * Challenges the TEI has attempted to face * Good texts not beyond economic feasibility * The issue of reproducibility or processability * The issue of mages as simulacra for the text redux * One's model of text determines what one's software can do with a text and has economic consequences * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Prior to speaking about SGML and markup, Michael SPERBERG-McQUEEN, editor, Text Encoding Initiative (TEI), University of Illinois-Chicago, first drew a distinction between texts and computers: Texts are abstract cultural and linguistic objects while computers are complicated physical devices, he said. Abstract objects cannot be placed inside physical devices; with computers one can only represent text and act upon those representations. The recognition that all representation is encoding, SPERBERG-McQUEEN argued, leads to the recognition of two things: 1) The topic description for this session is slightly misleading, because there can be no discussion of pros and cons of text-coding unless what one means is pros and cons of working with text with computers. 2) No text can be represented in a computer without some sort of encoding; images are one way of encoding text, ASCII is another, SGML yet another. There is no encoding without some information loss, that is, there is no perfect reproduction of a text that allows one to do away with the original. Thus, the question becomes, What is the most useful representation of text for a serious work? This depends on what kind of serious work one is talking about. The projects demonstrated the previous day all involved highly complex information and fairly complex manipulation of the textual material. In order to use that complicated information, one has to calculate it slowly or manually and store the result. It needs to be stored, therefore, as part of one's representation of the text. Thus, one needs to store the structure in the text. To deal with complicated representations of text, one needs somehow to control the complexity of the representation of a text; that means one needs a way of finding out whether a document and an electronic representation of a document is legal or not; and that means one needs a grammar of documents. SPERBERG-McQUEEN discussed the variety of forms of formal grammars, implicit and explicit, as applied to text, and their capabilities. He argued that these grammars correspond to different models of text that different developers have. For example, one implicit model of the text is that there is no internal structure, but just one thing after another, a few characters and then perhaps a start-title command, and then a few more characters and an end-title command. SPERBERG-McQUEEN also distinguished several kinds of text that have a sort of hierarchical structure that is not very well defined, which, typically, corresponds to grammars that are not very well defined, as well as hierarchies that are very well defined (e.g., the Thesaurus Linguae Graecae) and extremely complicated things such as SGML, which handle strictly hierarchical data very nicely. SPERBERG-McQUEEN conceded that one other model not illustrated on his two displays was the model of text as a bit-mapped image, an image of a page, and confessed to having been converted to a limited extent by the Workshop to the view that electronic images constitute a promising, probably superior alternative to microfilming. But he was not convinced that electronic images represent a serious attempt to represent text in electronic form. Many of their problems stem from the fact that they are not direct attempts to represent the text but attempts to represent the page, thus making them representations of representations. In this situation of increasingly complicated textual information and the need to control that complexity in a useful way (which begs the question of the need for good textual grammars), one has the introduction of SGML. With SGML, one can develop specific document-type declarations for specific text types or, as with the TEI, attempts to generate general document-type declarations that can handle all sorts of text. The TEI is an attempt to develop formats for text representation that will ensure the kind of reusability and longevity of data discussed earlier. It offers a way to stay alive in the state of permanent technological revolution. It has been a continuing challenge in the TEI to create document grammars that do some work in controlling the complexity of the textual object but also allowing one to represent the real text that one will find. Fundamental to the notion of the TEI is that TEI conformance allows one the ability to extend or modify the TEI tag set so that it fits the text that one is attempting to represent. SPERBERG-McQUEEN next outlined the administrative background of the TEI. The TEI is an international project to develop and disseminate guidelines for the encoding and interchange of machine-readable text. It is sponsored by the Association for Computers in the Humanities, the Association for Computational Linguistics, and the Association for Literary and Linguistic Computing. Representatives of numerous other professional societies sit on its advisory board. The TEI has a number of affiliated projects that have provided assistance by testing drafts of the guidelines. Among the design goals for the TEI tag set, the scheme first of all must meet the needs of research, because the TEI came out of the research community, which did not feel adequately served by existing tag sets. The tag set must be extensive as well as compatible with existing and emerging standards. In 1990, version 1.0 of the Guidelines was released (SPERBERG-McQUEEN illustrated their contents). SPERBERG-McQUEEN noted that one problem besetting electronic text has been the lack of adequate internal or external documentation for many existing electronic texts. The TEI guidelines as currently formulated contain few fixed requirements, but one of them is this: There must always be a document header, an in-file SGML tag that provides 1) a bibliographic description of the electronic object one is talking about (that is, who included it, when, what for, and under which title); and 2) the copy text from which it was derived, if any. If there was no copy text or if the copy text is unknown, then one states as much. Version 2.0 of the Guidelines was scheduled to be completed in fall 1992 and a revised third version is to be presented to the TEI advisory board for its endorsement this coming winter. The TEI itself exists to provide a markup language, not a marked-up text. Among the challenges the TEI has attempted to face is the need for a markup language that will work for existing projects, that is, handle the level of markup that people are using now to tag only chapter, section, and paragraph divisions and not much else. At the same time, such a language also will be able to scale up gracefully to handle the highly detailed markup which many people foresee as the future destination of much electronic text, and which is not the future destination but the present home of numerous electronic texts in specialized areas. SPERBERG-McQUEEN dismissed the lowest-common-denominator approach as unable to support the kind of applications that draw people who have never been in the public library regularly before, and make them come back. He advocated more interesting text and more intelligent text. Asserting that it is not beyond economic feasibility to have good texts, SPERBERG-McQUEEN noted that the TEI Guidelines listing 200-odd tags contains tags that one is expected to enter every time the relevant textual feature occurs. It contains all the tags that people need now, and it is not expected that everyone will tag things in the same way. The question of how people will tag the text is in large part a function of their reaction to what SPERBERG-McQUEEN termed the issue of reproducibility. What one needs to be able to reproduce are the things one wants to work with. Perhaps a more useful concept than that of reproducibility or recoverability is that of processability, that is, what can one get from an electronic text without reading it again in the original. He illustrated this contention with a page from Jan Comenius's bilingual Introduction to Latin. SPERBERG-McQUEEN returned at length to the issue of images as simulacra for the text, in order to reiterate his belief that in the long run more than images of pages of particular editions of the text are needed, because just as second-generation photocopies and second-generation microfilm degenerate, so second-generation representations tend to degenerate, and one tends to overstress some relatively trivial aspects of the text such as its layout on the page, which is not always significant, despite what the text critics might say, and slight other pieces of information such as the very important lexical ties between the English and Latin versions of Comenius's bilingual text, for example. Moreover, in many crucial respects it is easy to fool oneself concerning what a scanned image of the text will accomplish. For example, in order to study the transmission of texts, information concerning the text carrier is necessary, which scanned images simply do not always handle. Further, even the high-quality materials being produced at Cornell use much of the information that one would need if studying those books as physical objects. It is a choice that has been made. It is an arguably justifiable choice, but one does not know what color those pen strokes in the margin are or whether there was a stain on the page, because it has been filtered out. One does not know whether there were rips in the page because they do not show up, and on a couple of the marginal marks one loses half of the mark because the pen is very light and the scanner failed to pick it up, and so what is clearly a checkmark in the margin of the original becomes a little scoop in the margin of the facsimile. Standard problems for facsimile editions, not new to electronics, but also true of light-lens photography, and are remarked here because it is important that we not fool ourselves that even if we produce a very nice image of this page with good contrast, we are not replacing the manuscript any more than microfilm has replaced the manuscript. The TEI comes from the research community, where its first allegiance lies, but it is not just an academic exercise. It has relevance far beyond those who spend all of their time studying text, because one's model of text determines what one's software can do with a text. Good models lead to good software. Bad models lead to bad software. That has economic consequences, and it is these economic consequences that have led the European Community to help support the TEI, and that will lead, SPERBERG-McQUEEN hoped, some software vendors to realize that if they provide software with a better model of the text they can make a killing. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Implications of different DTDs and tag sets * ODA versus SGML * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ During the discussion that followed, several additional points were made. Neither AAP (i.e., Association of American Publishers) nor CALS (i.e., Computer-aided Acquisition and Logistics Support) has a document-type definition for ancient Greek drama, although the TEI will be able to handle that. Given this state of affairs and assuming that the technical-journal producers and the commercial vendors decide to use the other two types, then an institution like the Library of Congress, which might receive all of their publications, would have to be able to handle three different types of document definitions and tag sets and be able to distinguish among them. Office Document Architecture (ODA) has some advantages that flow from its tight focus on office documents and clear directions for implementation. Much of the ODA standard is easier to read and clearer at first reading than the SGML standard, which is extremely general. What that means is that if one wants to use graphics in TIFF and ODA, one is stuck, because ODA defines graphics formats while TIFF does not, whereas SGML says the world is not waiting for this work group to create another graphics format. What is needed is an ability to use whatever graphics format one wants. The TEI provides a socket that allows one to connect the SGML document to the graphics. The notation that the graphics are in is clearly a choice that one needs to make based on her or his environment, and that is one advantage. SGML is less megalomaniacal in attempting to define formats for all kinds of information, though more megalomaniacal in attempting to cover all sorts of documents. The other advantage is that the model of text represented by SGML is simply an order of magnitude richer and more flexible than the model of text offered by ODA. Both offer hierarchical structures, but SGML recognizes that the hierarchical model of the text that one is looking at may not have been in the minds of the designers, whereas ODA does not. ODA is not really aiming for the kind of document that the TEI wants to encompass. The TEI can handle the kind of material ODA has, as well as a significantly broader range of material. ODA seems to be very much focused on office documents, which is what it started out being called-- office document architecture. ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CALALUCA * Text-encoding from a publisher's perspective * Responsibilities of a publisher * Reproduction of Migne's Latin series whole and complete with SGML tags based on perceived need and expected use * Particular decisions arising from the general decision to produce and publish PLD * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ The final speaker in this session, Eric CALALUCA, vice president, Chadwyck-Healey, Inc., spoke from the perspective of a publisher re text-encoding, rather than as one qualified to discuss methods of encoding data, and observed that the presenters sitting in the room, whether they had chosen to or not, were acting as publishers: making choices, gathering data, gathering information, and making assessments. CALALUCA offered the hard-won conviction that in publishing very large text files (such as PLD), one cannot avoid making personal judgments of appropriateness and structure. In CALALUCA's view, encoding decisions stem from prior judgments. Two notions have become axioms for him in the consideration of future sources for electronic publication: 1) electronic text publishing is as personal as any other kind of publishing, and questions of if and how to encode the data are simply a consequence of that prior decision; 2) all personal decisions are open to criticism, which is unavoidable. CALALUCA rehearsed his role as a publisher or, better, as an intermediary between what is viewed as a sound idea and the people who would make use of it. Finding the specialist to advise in this process is the core of that function. The publisher must monitor and hug the fine line between giving users what they want and suggesting what they might need. One responsibility of a publisher is to represent the desires of scholars and research librarians as opposed to bullheadedly forcing them into areas they would not choose to enter. CALALUCA likened the questions being raised today about data structure and standards to the decisions faced by the Abbe Migne himself during production of the Patrologia series in the mid-nineteenth century. Chadwyck-Healey's decision to reproduce Migne's Latin series whole and complete with SGML tags was also based upon a perceived need and an expected use. In the same way that Migne's work came to be far more than a simple handbook for clerics, PLD is already far more than a database for theologians. It is a bedrock source for the study of Western civilization, CALALUCA asserted. In regard to the decision to produce and publish PLD, the editorial board offered direct judgments on the question of appropriateness of these texts for conversion, their encoding and their distribution, and concluded that the best possible project was one that avoided overt intrusions or exclusions in so important a resource. Thus, the general decision to transmit the original collection as clearly as possible with the widest possible avenues for use led to other decisions: 1) To encode the data or not, SGML or not, TEI or not. Again, the expected user community asserted the need for normative tagging structures of important humanities texts, and the TEI seemed the most appropriate structure for that purpose. Research librarians, who are trained to view the larger impact of electronic text sources on 80 or 90 or 100 doctoral disciplines, loudly approved the decision to include tagging. They see what is coming better than the specialist who is completely focused on one edition of Ambrose's De Anima, and they also understand that the potential uses exceed present expectations. 2) What will be tagged and what will not. Once again, the board realized that one must tag the obvious. But in no way should one attempt to identify through encoding schemes every single discrete area of a text that might someday be searched. That was another decision. Searching by a column number, an author, a word, a volume, permitting combination searches, and tagging notations seemed logical choices as core elements. 3) How does one make the data available? Tieing it to a CD-ROM edition creates limitations, but a magnetic tape file that is very large, is accompanied by the encoding specifications, and that allows one to make local modifications also allows one to incorporate any changes one may desire within the bounds of private research, though exporting tag files from a CD-ROM could serve just as well. Since no one on the board could possibly anticipate each and every way in which a scholar might choose to mine this data bank, it was decided to satisfy the basics and make some provisions for what might come. 4) Not to encode the database would rob it of the interchangeability and portability these important texts should accommodate. For CALALUCA, the extensive options presented by full-text searching require care in text selection and strongly support encoding of data to facilitate the widest possible search strategies. Better software can always be created, but summoning the resources, the people, and the energy to reconvert the text is another matter. PLD is being encoded, captured, and distributed, because to Chadwyck-Healey and the board it offers the widest possible array of future research applications that can be seen today. CALALUCA concluded by urging the encoding of all important text sources in whatever way seems most appropriate and durable at the time, without blanching at the thought that one's work may require emendation in the future. (Thus, Chadwyck-Healey produced a very large humanities text database before the final release of the TEI Guidelines.) ****** +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DISCUSSION * Creating texts with markup advocated * Trends in encoding * The TEI and the issue of interchangeability of standards * A misconception concerning the TEI * Implications for an institution like LC in the event that a multiplicity of DTDs develops * Producing images as a first step towards possible conversion to full text through character recognition * The AAP tag sets as a common starting point and the need for caution * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HOCKEY prefaced the discussion that followed with several comments in favor of creating texts with markup and on trends in encoding. In the future, when many more texts are available for on-line searching, real problems in finding what is wanted will develop, if one is faced with millions of words of data. It therefore becomes important to consider putting markup in texts to help searchers home in on the actual things they wish to retrieve. Various approaches to refining retrieval methods toward this end include building on a computer version of a dictionary and letting the computer look up words in it to obtain more information about the semantic structure or semantic field of a word, its grammatical structure, and syntactic structure. HOCKEY commented on the present keen interest in the encoding world in creating: 1) machine-readable versions of dictionaries that can be initially tagged in SGML, which gives a structure to the dictionary entry; these entries can then be converted into a more rigid or otherwise different database structure inside the computer, which can be treated as a dynamic tool for searching mechanisms; 2) large bodies of text to study the language. In order to incorporate more sophisticated mechanisms, more about how words behave needs to be known, which can be learned in part from information in dictionaries. However, the last ten years have seen much interest in studying the structure of printed dictionaries converted into computer-readable form. The information one derives about many words from those is only partial, one or two definitions of the common or the usual meaning of a word, and then numerous definitions of unusual usages. If the computer is using a dictionary to help retrieve words in a text, it needs much more information about the common usages, because those are the ones that occur over and over again. Hence the current interest in developing large bodies of text in computer-readable form in order to study the language. Several projects are engaged in compiling, for example, 100 million words. HOCKEY described one with which she was associated briefly at Oxford University involving compilation of 100 million words of British English: about 10 percent of that will contain detailed linguistic tagging encoded in SGML; it will have word class taggings, with words identified as nouns, verbs, adjectives, or other parts of speech. This tagging can then be used by programs which will begin to learn a bit more about the structure of the language, and then, can go to tag more text. HOCKEY said that the more that is tagged accurately, the more one can refine the tagging process and thus the bigger body of text one can build up with linguistic tagging incorporated into it. Hence, the more tagging or annotation there is in the text, the more one may begin to learn about language and the more it will help accomplish more intelligent OCR. She recommended the development of software tools that will help one begin to understand more about a text, which can then be applied to scanning images of that text in that format and to using more intelligence to help one interpret or understand the text. HOCKEY posited the need to think about common methods of text-encoding for a long time to come, because building these large bodies of text is extremely expensive and will only be done once. In the more general discussion on approaches to encoding that followed, these points were made: BESSER identified the underlying problem with standards that all have to struggle with in adopting a standard, namely, the tension between a very highly defined standard that is very interchangeable but does not work for everyone because something is lacking, and a standard that is less defined, more open, more adaptable, but less interchangeable. Contending that the way in which people use SGML is not sufficiently defined, BESSER wondered 1) if people resist the TEI because they think it is too defined in certain things they do not fit into, and 2) how progress with interchangeability can be made without frightening people away. SPERBERG-McQUEEN replied that the published drafts of the TEI had met with surprisingly little objection on the grounds that they do not allow one to handle X or Y or Z. Particular concerns of the affiliated projects have led, in practice, to discussions of how extensions are to be made; the primary concern of any project has to be how it can be represented locally, thus making interchange secondary. The TEI has received much criticism based on the notion that everything in it is required or even recommended, which, as it happens, is a misconception from the beginning, because none of it is required and very little is actually actively recommended for all cases, except that one document one's source. SPERBERG-McQUEEN agreed with BESSER about this trade-off: all the projects in a set of twenty TEI-conformant projects will not necessarily tag the material in the same way. One result of the TEI will be that the easiest problems will be solved--those dealing with the external form of the information; but the problem that is hardest in interchange is that one is not encoding what another wants, and vice versa. Thus, after the adoption of a common notation, the differences in the underlying conceptions of what is interesting about texts become more visible. The success of a standard like the TEI will lie in the ability of the recipient of interchanged texts to use some of what it contains and to add the information that was not encoded that one wants, in a layered way, so that texts can be gradually enriched and one does not have to put in everything all at once. Hence, having a well-behaved markup scheme is important. STEVENS followed up on the paradoxical analogy that BESSER alluded to in the example of the MARC records, namely, the formats that are the same except that they are different. STEVENS drew a parallel between document-type definitions and MARC records for books and serials and maps, where one has a tagging structure and there is a text-interchange. STEVENS opined that the producers of the information will set the terms for the standard (i.e., develop document-type definitions for the users of their products), creating a situation that will be problematical for an institution like the Library of Congress, which will have to deal with the DTDs in the event that a multiplicity of them develops. Thus, numerous people are seeking a standard but cannot find the tag set that will be acceptable to them and their clients. SPERBERG-McQUEEN agreed with this view, and said that the situation was in a way worse: attempting to unify arbitrary DTDs resembled attempting to unify a MARC record with a bibliographic record done according to the Prussian instructions. According to STEVENS, this situation occurred very early in the process. WATERS recalled from early discussions on Project Open Book the concern of many people that merely by producing images, POB was not really enhancing intellectual access to the material. Nevertheless, not wishing to overemphasize the opposition between imaging and full text, WATERS stated that POB views getting the images as a first step toward possibly converting to full text through character recognition, if the technology is appropriate. WATERS also emphasized that encoding is involved even with a set of images. SPERBERG-McQUEEN agreed with WATERS that one can create an SGML document consisting wholly of images. At first sight, organizing graphic images with an SGML document may not seem to offer great advantages, but the advantages of the scheme WATERS described would be precisely that ability to move into something that is more of a multimedia document: a combination of transcribed text and page images. WEIBEL concurred in this judgment, offering evidence from Project ADAPT, where a page is divided into text elements and graphic elements, and in fact the text elements are organized by columns and lines. These lines may be used as the basis for distributing documents in a network environment. As one develops software intelligent enough to recognize what those elements are, it makes sense to apply SGML to an image initially, that may, in fact, ultimately become more and more text, either through OCR or edited OCR or even just through keying. For WATERS, the labor of composing the document and saying this set of documents or this set of images belongs to this document constitutes a significant investment. WEIBEL also made the point that the AAP tag sets, while not excessively prescriptive, offer a common starting point; they do not define the structure of the documents, though. They have some recommendations about DTDs one could use as examples, but they do just suggest tag sets. For example, the CORE project attempts to use the AAP markup as much as possible, but there are clearly areas where structure must be added. That in no way contradicts the use of AAP tag sets. SPERBERG-McQUEEN noted that the TEI prepared a long working paper early on about the AAP tag set and what it lacked that the TEI thought it needed, and a fairly long critique of the naming conventions, which has led to a very different style of naming in the TEI. He stressed the importance of the opposition between prescriptive markup, the kind that a publisher or anybody can do when producing documents de novo, and descriptive markup, in which one has to take what the text carrier provides. In these particular tag sets it is easy to overemphasize this opposition, because the AAP tag set is extremely flexible. Even if one just used the DTDs, they allow almost anything to appear almost anywhere. ****** SESSION VI. COPYRIGHT ISSUES +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PETERS * Several cautions concerning copyright in an electronic environment * Review of copyright law in the United States * The notion of the public good and the desirability of incentives to promote it * What copyright protects * Works not protected by copyright * The rights of copyright holders * Publishers' concerns in today's electronic environment * Compulsory licenses * The price of copyright in a digital medium and the need for cooperation * Additional clarifications * Rough justice oftentimes the outcome in numerous copyright matters * Copyright in an electronic society * Copyright law always only sets up the boundaries; anything can be changed by contract * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Marybeth PETERS, policy planning adviser to the Register of Copyrights, Library of Congress, made several general comments and then opened the floor to discussion of subjects of interest to the audience. Having attended several sessions in an effort to gain a sense of what people did and where copyright would affect their lives, PETERS expressed the following cautions: * If one takes and converts materials and puts them in new forms, then, from a copyright point of view, one is creating something and will receive some rights. * However, if what one is converting already exists, a question immediately arises about the status of the materials in question. * Putting something in the public domain in the United States offers some freedom from anxiety, but distributing it throughout the world on a network is another matter, even if one has put it in the public domain in the United States. Re foreign laws, very frequently a work can be in the public domain in the United States but protected in other countries. Thus, one must consider all of the places a work may reach, lest one unwittingly become liable to being faced with a suit for copyright infringement, or at least a letter demanding discussion of what one is doing. PETERS reviewed copyright law in the United States. The U.S. Constitution effectively states that Congress has the power to enact copyright laws for two purposes: 1) to encourage the creation and dissemination of intellectual works for the good of society as a whole; and, significantly, 2) to give creators and those who package and disseminate materials the economic rewards that are due them. Congress strives to strike a balance, which at times can become an emotional issue. The United States has never accepted the notion of the natural right of an author so much as it has accepted the notion of the public good and the desirability of incentives to promote it. This state of affairs, however, has created strains on the international level and is the reason for several of the differences in the laws that we have. Today the United States protects almost every kind of work that can be called an expression of an author. The standard for gaining copyright protection is simply originality. This is a low standard and means that a work is not copied from something else, as well as shows a certain minimal amount of authorship. One can also acquire copyright protection for making a new version of preexisting material, provided it manifests some spark of creativity. However, copyright does not protect ideas, methods, systems--only the way that one expresses those things. Nor does copyright protect anything that is mechanical, anything that does not involve choice, or criteria concerning whether or not one should do a thing. For example, the results of a process called declicking, in which one mechanically removes impure sounds from old recordings, are not copyrightable. On the other hand, the choice to record a song digitally and to increase the sound of violins or to bring up the tympani constitutes the results of conversion that are copyrightable. Moreover, if a work is protected by copyright in the United States, one generally needs the permission of the copyright owner to convert it. Normally, who will own the new--that is, converted- -material is a matter of contract. In the absence of a contract, the person who creates the new material is the author and owner. But people do not generally think about the copyright implications until after the fact. PETERS stressed the need when dealing with copyrighted works to think about copyright in advance. One's bargaining power is much greater up front than it is down the road. PETERS next discussed works not protected by copyright, for example, any work done by a federal employee as part of his or her official duties is in the public domain in the United States. The issue is not wholly free of doubt concerning whether or not the work is in the public domain outside the United States. Other materials in the public domain include: any works published more than seventy-five years ago, and any work published in the United States more than twenty-eight years ago, whose copyright was not renewed. In talking about the new technology and putting material in a digital form to send all over the world, PETERS cautioned, one must keep in mind that while the rights may not be an issue in the United States, they may be in different parts of the world, where most countries previously employed a copyright term of the life of the author plus fifty years. PETERS next reviewed the economics of copyright holding. Simply, economic rights are the rights to control the reproduction of a work in any form. They belong to the author, or in the case of a work made for hire, the employer. The second right, which is critical to conversion, is the right to change a work. The right to make new versions is perhaps one of the most significant rights of authors, particularly in an electronic world. The third right is the right to publish the work and the right to disseminate it, something that everyone who deals in an electronic medium needs to know. The basic rule is if a copy is sold, all rights of distribution are extinguished with the sale of that copy. The key is that it must be sold. A number of companies overcome this obstacle by leasing or renting their product. These companies argue that if the material is rented or leased and not sold, they control the uses of a work. The fourth right, and one very important in a digital world, is a right of public performance, which means the right to show the work sequentially. For example, copyright owners control the showing of a CD-ROM product in a public place such as a public library. The reverse side of public performance is something called the right of public display. Moral rights also exist, which at the federal level apply only to very limited visual works of art, but in theory may apply under contract and other principles. Moral rights may include the right of an author to have his or her name on a work, the right of attribution, and the right to object to distortion or mutilation--the right of integrity. The way copyright law is worded gives much latitude to activities such as preservation; to use of material for scholarly and research purposes when the user does not make multiple copies; and to the generation of facsimile copies of unpublished works by libraries for themselves and other libraries. But the law does not allow anyone to become the distributor of the product for the entire world. In today's electronic environment, publishers are extremely concerned that the entire world is networked and can obtain the information desired from a single copy in a single library. Hence, if there is to be only one sale, which publishers may choose to live with, they will obtain their money in other ways, for example, from access and use. Hence, the development of site licenses and other kinds of agreements to cover what publishers believe they should be compensated for. Any solution that the United States takes today has to consider the international arena. Noting that the United States is a member of the Berne Convention and subscribes to its provisions, PETERS described the permissions process. She also defined compulsory licenses. A compulsory license, of which the United States has had a few, builds into the law the right to use a work subject to certain terms and conditions. In the international arena, however, the ability to use compulsory licenses is extremely limited. Thus, clearinghouses and other collectives comprise one option that has succeeded in providing for use of a work. Often overlooked when one begins to use copyrighted material and put products together is how expensive the permissions process and managing it is. According to PETERS, the price of copyright in a digital medium, whatever solution is worked out, will include managing and assembling the database. She strongly recommended that publishers and librarians or people with various backgrounds cooperate to work out administratively feasible systems, in order to produce better results. In the lengthy question-and-answer period that followed PETERS's presentation, the following points emerged: * The Copyright Office maintains that anything mechanical and totally exhaustive probably is not protected. In the event that what an individual did in developing potentially copyrightable material is not understood, the Copyright Office will ask about the creative choices the applicant chose to make or not to make. As a practical matter, if one believes she or he has made enough of those choices, that person has a right to assert a copyright and someone else must assert that the work is not copyrightable. The more mechanical, the more automatic, a thing is, the less likely it is to be copyrightable. * Nearly all photographs are deemed to be copyrightable, but no one worries about them much, because everyone is free to take the same image. Thus, a photographic copyright represents what is called a "thin" copyright. The photograph itself must be duplicated, in order for copyright to be violated. * The Copyright Office takes the position that X-rays are not copyrightable because they are mechanical. It can be argued whether or not image enhancement in scanning can be protected. One must exercise care with material created with public funds and generally in the public domain. An article written by a federal employee, if written as part of official duties, is not copyrightable. However, control over a scientific article written by a National Institutes of Health grantee (i.e., someone who receives money from the U.S. government), depends on NIH policy. If the government agency has no policy (and that policy can be contained in its regulations, the contract, or the grant), the author retains copyright. If a provision of the contract, grant, or regulation states that there will be no copyright, then it does not exist. When a work is created, copyright automatically comes into existence unless something exists that says it does not. * An enhanced electronic copy of a print copy of an older reference work in the public domain that does not contain copyrightable new material is a purely mechanical rendition of the original work, and is not copyrightable. * Usually, when a work enters the public domain, nothing can remove it. For example, Congress recently passed into law the concept of automatic renewal, which means that copyright on any work published between l964 and l978 does not have to be renewed in order to receive a seventy-five-year term. But any work not renewed before 1964 is in the public domain. * Concerning whether or not the United States keeps track of when authors die, nothing was ever done, nor is anything being done at the moment by the Copyright Office. * Software that drives a mechanical process is itself copyrightable. If one changes platforms, the software itself has a copyright. The World Intellectual Property Organization will hold a symposium 28 March through 2 April l993, at Harvard University, on digital technology, and will study this entire issue. If one purchases a computer software package, such as MacPaint, and creates something new, one receives protection only for that which has been added. PETERS added that often in copyright matters, rough justice is the outcome, for example, in collective licensing, ASCAP (i.e., American Society of Composers, Authors, and Publishers), and BMI (i.e., Broadcast Music, Inc.), where it may seem that the big guys receive more than their due. Of course, people ought not to copy a creative product without paying for it; there should be some compensation. But the truth of the world, and it is not a great truth, is that the big guy gets played on the radio more frequently than the little guy, who has to do much more until he becomes a big guy. That is true of every author, every composer, everyone, and, unfortunately, is part of life. Copyright always originates with the author, except in cases of works made for hire. (Most software falls into this category.) When an author sends his article to a journal, he has not relinquished copyright, though he retains the right to relinquish it. The author receives absolutely everything. The less prominent the author, the more leverage the publisher will have in contract negotiations. In order to transfer the rights, the author must sign an agreement giving them away. In an electronic society, it is important to be able to license a writer and work out deals. With regard to use of a work, it usually is much easier when a publisher holds the rights. In an electronic era, a real problem arises when one is digitizing and making information available. PETERS referred again to electronic licensing clearinghouses. Copyright ought to remain with the author, but as one moves forward globally in the electronic arena, a middleman who can handle the various rights becomes increasingly necessary. The notion of copyright law is that it resides with the individual, but in an on-line environment, where a work can be adapted and tinkered with by many individuals, there is concern. If changes are authorized and there is no agreement to the contrary, the person who changes a work owns the changes. To put it another way, the person who acquires permission to change a work technically will become the author and the owner, unless some agreement to the contrary has been made. It is typical for the original publisher to try to control all of the versions and all of the uses. Copyright law always only sets up the boundaries. Anything can be changed by contract. ****** SESSION VII. CONCLUSION +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ GENERAL DISCUSSION * Two questions for discussion * Different emphases in the Workshop * Bringing the text and image partisans together * Desiderata in planning the long-term development of something * Questions surrounding the issue of electronic deposit * Discussion of electronic deposit as an allusion to the issue of standards * Need for a directory of preservation projects in digital form and for access to their digitized files * CETH's catalogue of machine-readable texts in the humanities * What constitutes a publication in the electronic world? * Need for LC to deal with the concept of on-line publishing * LC's Network Development Office exploring the limits of MARC as a standard in terms of handling electronic information * Magnitude of the problem and the need for distributed responsibility in order to maintain and store electronic information * Workshop participants to be viewed as a starting point * Development of a network version of AM urged * A step toward AM's construction of some sort of apparatus for network access * A delicate and agonizing policy question for LC * Re the issue of electronic deposit, LC urged to initiate a catalytic process in terms of distributed responsibility * Suggestions for cooperative ventures * Commercial publishers' fears * Strategic questions for getting the image and text people to think through long-term cooperation * Clarification of the driving force behind both the Perseus and the Cornell Xerox projects * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ In his role as moderator of the concluding session, GIFFORD raised two questions he believed would benefit from discussion: 1) Are there enough commonalities among those of us that have been here for two days so that we can see courses of action that should be taken in the future? And, if so, what are they and who might take them? 2) Partly derivative from that, but obviously very dangerous to LC as host, do you see a role for the Library of Congress in all this? Of course, the Library of Congress holds a rather special status in a number of these matters, because it is not perceived as a player with an economic stake in them, but are there roles that LC can play that can help advance us toward where we are heading? Describing himself as an uninformed observer of the technicalities of the last two days, GIFFORD detected three different emphases in the Workshop: 1) people who are very deeply committed to text; 2) people who are almost passionate about images; and 3) a few people who are very committed to what happens to the networks. In other words, the new networking dimension, the accessibility of the processability, the portability of all this across the networks. How do we pull those three together? Adding a question that reflected HOCKEY's comment that this was the fourth workshop she had attended in the previous thirty days, FLEISCHHAUER wondered to what extent this meeting had reinvented the wheel, or if it had contributed anything in the way of bringing together a different group of people from those who normally appear on the workshop circuit. HOCKEY confessed to being struck at this meeting and the one the Electronic Pierce Consortium organized the previous week that this was a coming together of people working on texts and not images. Attempting to bring the two together is something we ought to be thinking about for the future: How one can think about working with image material to begin with, but structuring it and digitizing it in such a way that at a later stage it can be interpreted into text, and find a common way of building text and images together so that they can be used jointly in the future, with the network support to begin there because that is how people will want to access it. In planning the long-term development of something, which is what is being done in electronic text, HOCKEY stressed the importance not only of discussing the technical aspects of how one does it but particularly of thinking about what the people who use the stuff will want to do. But conversely, there are numerous things that people start to do with electronic text or material that nobody ever thought of in the beginning. LESK, in response to the question concerning the role of the Library of Congress, remarked the often suggested desideratum of having electronic deposit: Since everything is now computer-typeset, an entire decade of material that was machine-readable exists, but the publishers frequently did not save it; has LC taken any action to have its copyright deposit operation start collecting these machine-readable versions? In the absence of PETERS, GIFFORD replied that the question was being actively considered but that that was only one dimension of the problem. Another dimension is the whole question of the integrity of the original electronic document. It becomes highly important in science to prove authorship. How will that be done? ERWAY explained that, under the old policy, to make a claim for a copyright for works that were published in electronic form, including software, one had to submit a paper copy of the first and last twenty pages of code--something that represented the work but did not include the entire work itself and had little value to anyone. As a temporary measure, LC has claimed the right to demand electronic versions of electronic publications. This measure entails a proactive role for the Library to say that it wants a particular electronic version. Publishers then have perhaps a year to submit it. But the real problem for LC is what to do with all this material in all these different formats. Will the Library mount it? How will it give people access to it? How does LC keep track of the appropriate computers, software, and media? The situation is so hard to control, ERWAY said, that it makes sense for each publishing house to maintain its own archive. But LC cannot enforce that either. GIFFORD acknowledged LESK's suggestion that establishing a priority offered the solution, albeit a fairly complicated one. But who maintains that register?, he asked. GRABER noted that LC does attempt to collect a Macintosh version and the IBM-compatible version of software. It does not collect other versions. But while true for software, BYRUM observed, this reply does not speak to materials, that is, all the materials that were published that were on somebody's microcomputer or driver tapes at a publishing office across the country. LC does well to acquire specific machine-readable products selectively that were intended to be machine-readable. Materials that were in machine-readable form at one time, BYRUM said, would be beyond LC's capability at the moment, insofar as attempting to acquire, organize, and preserve them are concerned--and preservation would be the most important consideration. In this connection, GIFFORD reiterated the need to work out some sense of distributive responsibility for a number of these issues, which inevitably will require significant cooperation and discussion. Nobody can do it all. LESK suggested that some publishers may look with favor on LC beginning to serve as a depository of tapes in an electronic manuscript standard. Publishers may view this as a service that they did not have to perform and they might send in tapes. However, SPERBERG-McQUEEN countered, although publishers have had equivalent services available to them for a long time, the electronic text archive has never turned away or been flooded with tapes and is forever sending feedback to the depositor. Some publishers do send in tapes. ANDRE viewed this discussion as an allusion to the issue of standards. She recommended that the AAP standard and the TEI, which has already been somewhat harmonized internationally and which also shares several compatibilities with the AAP, be harmonized to ensure sufficient compatibility in the software. She drew the line at saying LC ought to be the locus or forum for such harmonization. Taking the group in a slightly different direction, but one where at least in the near term LC might play a helpful role, LYNCH remarked the plans of a number of projects to carry out preservation by creating digital images that will end up in on-line or near-line storage at some institution. Presumably, LC will link this material somehow to its on-line catalog in most cases. Thus, it is in a digital form. LYNCH had the impression that many of these institutions would be willing to make those files accessible to other people outside the institution, provided that there is no copyright problem. This desideratum will require propagating the knowledge that those digitized files exist, so that they can end up in other on-line catalogs. Although uncertain about the mechanism for achieving this result, LYNCH said that it warranted scrutiny because it seemed to be connected to some of the basic issues of cataloging and distribution of records. It would be foolish, given the amount of work that all of us have to do and our meager resources, to discover multiple institutions digitizing the same work. Re microforms, LYNCH said, we are in pretty good shape. BATTIN called this a big problem and noted that the Cornell people (who had already departed) were working on it. At issue from the beginning was to learn how to catalog that information into RLIN and then into OCLC, so that it would be accessible. That issue remains to be resolved. LYNCH rejoined that putting it into OCLC or RLIN was helpful insofar as somebody who is thinking of performing preservation activity on that work could learn about it. It is not necessarily helpful for institutions to make that available. BATTIN opined that the idea was that it not only be for preservation purposes but for the convenience of people looking for this material. She endorsed LYNCH's dictum that duplication of this effort was to be avoided by every means. HOCKEY informed the Workshop about one major current activity of CETH, namely a catalogue of machine-readable texts in the humanities. Held on RLIN at present, the catalogue has been concentrated on ASCII as opposed to digitized images of text. She is exploring ways to improve the catalogue and make it more widely available, and welcomed suggestions about these concerns. CETH owns the records, which are not just restricted to RLIN, and can distribute them however it wishes. Taking up LESK's earlier question, BATTIN inquired whether LC, since it is accepting electronic files and designing a mechanism for dealing with that rather than putting books on shelves, would become responsible for the National Copyright Depository of Electronic Materials. Of course that could not be accomplished overnight, but it would be something LC could plan for. GIFFORD acknowledged that much thought was being devoted to that set of problems and returned the discussion to the issue raised by LYNCH--whether or not putting the kind of records that both BATTIN and HOCKEY have been talking about in RLIN is not a satisfactory solution. It seemed to him that RLIN answered LYNCH's original point concerning some kind of directory for these kinds of materials. In a situation where somebody is attempting to decide whether or not to scan this or film that or to learn whether or not someone has already done so, LYNCH suggested, RLIN is helpful, but it is not helpful in the case of a local, on-line catalogue. Further, one would like to have her or his system be aware that that exists in digital form, so that one can present it to a patron, even though one did not digitize it, if it is out of copyright. The only way to make those linkages would be to perform a tremendous amount of real-time look-up, which would be awkward at best, or periodically to yank the whole file from RLIN and match it against one's own stuff, which is a nuisance. But where, ERWAY inquired, does one stop including things that are available with Internet, for instance, in one's local catalogue? It almost seems that that is LC's means to acquire access to them. That represents LC's new form of library loan. Perhaps LC's new on-line catalogue is an amalgamation of all these catalogues on line. LYNCH conceded that perhaps that was true in the very long term, but was not applicable to scanning in the short term. In his view, the totals cited by Yale, 10,000 books over perhaps a four-year period, and 1,000-1,500 books from Cornell, were not big numbers, while searching all over creation for relatively rare occurrences will prove to be less efficient. As GIFFORD wondered if this would not be a separable file on RLIN and could be requested from them, BATTIN interjected that it was easily accessible to an institution. SEVERTSON pointed out that that file, cum enhancements, was available with reference information on CD-ROM, which makes it a little more available. In HOCKEY's view, the real question facing the Workshop is what to put in this catalogue, because that raises the question of what constitutes a publication in the electronic world. (WEIBEL interjected that Eric Joule in OCLC's Office of Research is also wrestling with this particular problem, while GIFFORD thought it sounded fairly generic.) HOCKEY contended that a majority of texts in the humanities are in the hands of either a small number of large research institutions or individuals and are not generally available for anyone else to access at all. She wondered if these texts ought to be catalogued. After argument proceeded back and forth for several minutes over why cataloguing might be a necessary service, LEBRON suggested that this issue involved the responsibility of a publisher. The fact that someone has created something electronically and keeps it under his or her control does not constitute publication. Publication implies dissemination. While it would be important for a scholar to let other people know that this creation exists, in many respects this is no different from an unpublished manuscript. That is what is being accessed in there, except that now one is not looking at it in the hard-copy but in the electronic environment. LEBRON expressed puzzlement at the variety of ways electronic publishing has been viewed. Much of what has been discussed throughout these two days has concerned CD-ROM publishing, whereas in the on-line environment that she confronts, the constraints and challenges are very different. Sooner or later LC will have to deal with the concept of on-line publishing. Taking up the comment ERWAY made earlier about storing copies, LEBRON gave her own journal as an example. How would she deposit OJCCT for copyright?, she asked, because the journal will exist in the mainframe at OCLC and people will be able to access it. Here the situation is different, ownership versus access, and is something that arises with publication in the on-line environment, faster than is sometimes realized. Lacking clear answers to all of these questions herself, LEBRON did not anticipate that LC would be able to take a role in helping to define some of them for quite a while. GREENFIELD observed that LC's Network Development Office is attempting, among other things, to explore the limits of MARC as a standard in terms of handling electronic information. GREENFIELD also noted that Rebecca GUENTHER from that office gave a paper to the American Society for Information Science (ASIS) summarizing several of the discussion papers that were coming out of the Network Development Office. GREENFIELD said he understood that that office had a list-server soliciting just the kind of feedback received today concerning the difficulties of identifying and cataloguing electronic information. GREENFIELD hoped that everybody would be aware of that and somehow contribute to that conversation. Noting two of LC's roles, first, to act as a repository of record for material that is copyrighted in this country, and second, to make materials it holds available in some limited form to a clientele that goes beyond Congress, BESSER suggested that it was incumbent on LC to extend those responsibilities to all the things being published in electronic form. This would mean eventually accepting electronic formats. LC could require that at some point they be in a certain limited set of formats, and then develop mechanisms for allowing people to access those in the same way that other things are accessed. This does not imply that they are on the network and available to everyone. LC does that with most of its bibliographic records, BESSER said, which end up migrating to the utility (e.g., OCLC) or somewhere else. But just as most of LC's books are available in some form through interlibrary loan or some other mechanism, so in the same way electronic formats ought to be available to others in some format, though with some copyright considerations. BESSER was not suggesting that these mechanisms be established tomorrow, only that they seemed to fall within LC's purview, and that there should be long-range plans to establish them. Acknowledging that those from LC in the room agreed with BESSER concerning the need to confront difficult questions, GIFFORD underscored the magnitude of the problem of what to keep and what to select. GIFFORD noted that LC currently receives some 31,000 items per day, not counting electronic materials, and argued for much more distributed responsibility in order to maintain and store electronic information. BESSER responded that the assembled group could be viewed as a starting point, whose initial operating premise could be helping to move in this direction and defining how LC could do so, for example, in areas of standardization or distribution of responsibility. FLEISCHHAUER added that AM was fully engaged, wrestling with some of the questions that pertain to the conversion of older historical materials, which would be one thing that the Library of Congress might do. Several points mentioned by BESSER and several others on this question have a much greater impact on those who are concerned with cataloguing and the networking of bibliographic information, as well as preservation itself. Speaking directly to AM, which he considered was a largely uncopyrighted database, LYNCH urged development of a network version of AM, or consideration of making the data in it available to people interested in doing network multimedia. On account of the current great shortage of digital data that is both appealing and unencumbered by complex rights problems, this course of action could have a significant effect on making network multimedia a reality. In this connection, FLEISCHHAUER reported on a fragmentary prototype in LC's Office of Information Technology Services that attempts to associate digital images of photographs with cataloguing information in ways that work within a local area network--a step, so to say, toward AM's construction of some sort of apparatus for access. Further, AM has attempted to use standard data forms in order to help make that distinction between the access tools and the underlying data, and thus believes that the database is networkable. A delicate and agonizing policy question for LC, however, which comes back to resources and unfortunately has an impact on this, is to find some appropriate, honorable, and legal cost-recovery possibilities. A certain skittishness concerning cost-recovery has made people unsure exactly what to do. AM would be highly receptive to discussing further LYNCH's offer to test or demonstrate its database in a network environment, FLEISCHHAUER said. Returning the discussion to what she viewed as the vital issue of electronic deposit, BATTIN recommended that LC initiate a catalytic process in terms of distributed responsibility, that is, bring together the distributed organizations and set up a study group to look at all these issues and see where we as a nation should move. The broader issues of how we deal with the management of electronic information will not disappear, but only grow worse. LESK took up this theme and suggested that LC attempt to persuade one major library in each state to deal with its state equivalent publisher, which might produce a cooperative project that would be equitably distributed around the country, and one in which LC would be dealing with a minimal number of publishers and minimal copyright problems. GRABER remarked the recent development in the scientific community of a willingness to use SGML and either deposit or interchange on a fairly standardized format. He wondered if a similar movement was taking place in the humanities. Although the National Library of Medicine found only a few publishers to cooperate in a like venture two or three years ago, a new effort might generate a much larger number willing to cooperate. KIMBALL recounted his unit's (Machine-Readable Collections Reading Room) troubles with the commercial publishers of electronic media in acquiring materials for LC's collections, in particular the publishers' fear that they would not be able to cover their costs and would lose control of their products, that LC would give them away or sell them and make profits from them. He doubted that the publishing industry was prepared to move into this area at the moment, given its resistance to allowing LC to use its machine-readable materials as the Library would like. The copyright law now addresses compact disk as a medium, and LC can request one copy of that, or two copies if it is the only version, and can request copies of software, but that fails to address magazines or books or anything like that which is in machine-readable form. GIFFORD acknowledged the thorny nature of this issue, which he illustrated with the example of the cumbersome process involved in putting a copy of a scientific database on a LAN in LC's science reading room. He also acknowledged that LC needs help and could enlist the energies and talents of Workshop participants in thinking through a number of these problems. GIFFORD returned the discussion to getting the image and text people to think through together where they want to go in the long term. MYLONAS conceded that her experience at the Pierce Symposium the previous week at Georgetown University and this week at LC had forced her to reevaluate her perspective on the usefulness of text as images. MYLONAS framed the issues in a series of questions: How do we acquire machine-readable text? Do we take pictures of it and perform OCR on it later? Is it important to obtain very high-quality images and text, etc.? FLEISCHHAUER agreed with MYLONAS's framing of strategic questions, adding that a large institution such as LC probably has to do all of those things at different times. Thus, the trick is to exercise judgment. The Workshop had added to his and AM's considerations in making those judgments. Concerning future meetings or discussions, MYLONAS suggested that screening priorities would be helpful. WEIBEL opined that the diversity reflected in this group was a sign both of the health and of the immaturity of the field, and more time would have to pass before we convince one another concerning standards. An exchange between MYLONAS and BATTIN clarified the point that the driving force behind both the Perseus and the Cornell Xerox projects was the preservation of knowledge for the future, not simply for particular research use. In the case of Perseus, MYLONAS said, the assumption was that the texts would not be entered again into electronically readable form. SPERBERG-McQUEEN added that a scanned image would not serve as an archival copy for purposes of preservation in the case of, say, the Bill of Rights, in the sense that the scanned images are effectively the archival copies for the Cornell mathematics books. *** *** *** ****** *** *** *** Appendix I: PROGRAM WORKSHOP ON ELECTRONIC TEXTS 9-10 June 1992 Library of Congress Washington, D.C. Supported by a Grant from the David and Lucile Packard Foundation Tuesday, 9 June 1992 NATIONAL DEMONSTRATION LAB, ATRIUM, LIBRARY MADISON 8:30 AM Coffee and Danish, registration 9:00 AM Welcome Prosser Gifford, Director for Scholarly Programs, and Carl Fleischhauer, Coordinator, American Memory, Library of Congress 9:l5 AM Session I. Content in a New Form: Who Will Use It and What Will They Do? Broad description of the range of electronic information. Characterization of who uses it and how it is or may be used. In addition to a look at scholarly uses, this session will include a presentation on use by students (K-12 and college) and the general public. Moderator: James Daly Avra Michelson, Archival Research and Evaluation Staff, National Archives and Records Administration (Overview) Susan H. Veccia, Team Leader, American Memory, User Evaluation, and Joanne Freeman, Associate Coordinator, American Memory, Library of Congress (Beyond the scholar) 10:30- 11:00 AM Break 11:00 AM Session II. Show and Tell. Each presentation to consist of a fifteen-minute statement/show; group discussion will follow lunch. Moderator: Jacqueline Hess, Director, National Demonstration Lab 1. A classics project, stressing texts and text retrieval more than multimedia: Perseus Project, Harvard University Elli Mylonas, Managing Editor 2. Other humanities projects employing the emerging norms of the Text Encoding Initiative (TEI): Chadwyck-Healey's The English Poetry Full Text Database and/or Patrologia Latina Database Eric M. Calaluca, Vice President, Chadwyck-Healey, Inc. 3. American Memory Carl Fleischhauer, Coordinator, and Ricky Erway, Associate Coordinator, Library of Congress 4. Founding Fathers example from Packard Humanities Institute: The Papers of George Washington, University of Virginia Dorothy Twohig, Managing Editor, and/or David Woodley Packard 5. An electronic medical journal offering graphics and full-text searchability: The Online Journal of Current Clinical Trials, American Association for the Advancement of Science Maria L. Lebron, Managing Editor 6. A project that offers facsimile images of pages but omits searchable text: Cornell math books Lynne K. Personius, Assistant Director, Cornell Information Technologies for Scholarly Information Sources, Cornell University 12:30 PM Lunch (Dining Room A, Library Madison 620. Exhibits available.) 1:30 PM Session II. Show and Tell (Cont'd.). 3:00- 3:30 PM Break 3:30- 5:30 PM Session III. Distribution, Networks, and Networking: Options for Dissemination. Published disks: University presses and public-sector publishers, private-sector publishers Computer networks Moderator: Robert G. Zich, Special Assistant to the Associate Librarian for Special Projects, Library of Congress Clifford A. Lynch, Director, Library Automation, University of California Howard Besser, School of Library and Information Science, University of Pittsburgh Ronald L. Larsen, Associate Director of Libraries for Information Technology, University of Maryland at College Park Edwin B. Brownrigg, Executive Director, Memex Research Institute 6:30 PM Reception (Montpelier Room, Library Madison 619.) ****** Wednesday, 10 June 1992 DINING ROOM A, LIBRARY MADISON 620 8:30 AM Coffee and Danish 9:00 AM Session IV. Image Capture, Text Capture, Overview of Text and Image Storage Formats. Moderator: William L. Hooton, Vice President of Operations, I-NET A) Principal Methods for Image Capture of Text: Direct scanning Use of microform Anne R. Kenney, Assistant Director, Department of Preservation and Conservation, Cornell University Pamela Q.J. Andre, Associate Director, Automation, and Judith A. Zidar, Coordinator, National Agricultural Text Digitizing Program (NATDP), National Agricultural Library (NAL) Donald J. Waters, Head, Systems Office, Yale University Library B) Special Problems: Bound volumes Conservation Reproducing printed halftones Carl Fleischhauer, Coordinator, American Memory, Library of Congress George Thoma, Chief, Communications Engineering Branch, National Library of Medicine (NLM) 10:30- 11:00 AM Break 11:00 AM Session IV. Image Capture, Text Capture, Overview of Text and Image Storage Formats (Cont'd.). C) Image Standards and Implications for Preservation Jean Baronas, Senior Manager, Department of Standards and Technology, Association for Information and Image Management (AIIM) Patricia Battin, President, The Commission on Preservation and Access (CPA) D) Text Conversion: OCR vs. rekeying Standards of accuracy and use of imperfect texts Service bureaus Stuart Weibel, Senior Research Specialist, Online Computer Library Center, Inc. (OCLC) Michael Lesk, Executive Director, Computer Science Research, Bellcore Ricky Erway, Associate Coordinator, American Memory, Library of Congress Pamela Q.J. Andre, Associate Director, Automation, and Judith A. Zidar, Coordinator, National Agricultural Text Digitizing Program (NATDP), National Agricultural Library (NAL) 12:30- 1:30 PM Lunch 1:30 PM Session V. Approaches to Preparing Electronic Texts. Discussion of approaches to structuring text for the computer; pros and cons of text coding, description of methods in practice, and comparison of text-coding methods. Moderator: Susan Hockey, Director, Center for Electronic Texts in the Humanities (CETH), Rutgers and Princeton Universities David Woodley Packard C.M. Sperberg-McQueen, Editor, Text Encoding Initiative (TEI), University of Illinois-Chicago Eric M. Calaluca, Vice President, Chadwyck-Healey, Inc. 3:30- 4:00 PM Break 4:00 PM Session VI. Copyright Issues. Marybeth Peters, Policy Planning Adviser to the Register of Copyrights, Library of Congress 5:00 PM Session VII. Conclusion. General discussion. What topics were omitted or given short shrift that anyone would like to talk about now? Is there a "group" here? What should the group do next, if anything? What should the Library of Congress do next, if anything? Moderator: Prosser Gifford, Director for Scholarly Programs, Library of Congress 6:00 PM Adjourn *** *** *** ****** *** *** *** Appendix II: ABSTRACTS SESSION I Avra MICHELSON Forecasting the Use of Electronic Texts by Social Sciences and Humanities Scholars This presentation explores the ways in which electronic texts are likely to be used by the non-scientific scholarly community. Many of the remarks are drawn from a report the speaker coauthored with Jeff Rothenberg, a computer scientist at The RAND Corporation. The speaker assesses 1) current scholarly use of information technology and 2) the key trends in information technology most relevant to the research process, in order to predict how social sciences and humanities scholars are apt to use electronic texts. In introducing the topic, current use of electronic texts is explored broadly within the context of scholarly communication. From the perspective of scholarly communication, the work of humanities and social sciences scholars involves five processes: 1) identification of sources, 2) communication with colleagues, 3) interpretation and analysis of data, 4) dissemination of research findings, and 5) curriculum development and instruction. The extent to which computation currently permeates aspects of scholarly communication represents a viable indicator of the prospects for electronic texts. The discussion of current practice is balanced by an analysis of key trends in the scholarly use of information technology. These include the trends toward end-user computing and connectivity, which provide a framework for forecasting the use of electronic texts through this millennium. The presentation concludes with a summary of the ways in which the nonscientific scholarly community can be expected to use electronic texts, and the implications of that use for information providers. Susan VECCIA and Joanne FREEMAN Electronic Archives for the Public: Use of American Memory in Public and School Libraries This joint discussion focuses on nonscholarly applications of electronic library materials, specifically addressing use of the Library of Congress American Memory (AM) program in a small number of public and school libraries throughout the United States. AM consists of selected Library of Congress primary archival materials, stored on optical media (CD-ROM/videodisc), and presented with little or no editing. Many collections are accompanied by electronic introductions and user's guides offering background information and historical context. Collections represent a variety of formats including photographs, graphic arts, motion pictures, recorded sound, music, broadsides and manuscripts, books, and pamphlets. In 1991, the Library of Congress began a nationwide evaluation of AM in different types of institutions. Test sites include public libraries, elementary and secondary school libraries, college and university libraries, state libraries, and special libraries. Susan VECCIA and Joanne FREEMAN will discuss their observations on the use of AM by the nonscholarly community, using evidence gleaned from this ongoing evaluation effort. VECCIA will comment on the overall goals of the evaluation project, and the types of public and school libraries included in this study. Her comments on nonscholarly use of AM will focus on the public library as a cultural and community institution, often bridging the gap between formal and informal education. FREEMAN will discuss the use of AM in school libraries. Use by students and teachers has revealed some broad questions about the use of electronic resources, as well as definite benefits gained by the "nonscholar." Topics will include the problem of grasping content and context in an electronic environment, the stumbling blocks created by "new" technologies, and the unique skills and interests awakened through use of electronic resources. SESSION II Elli MYLONAS The Perseus Project: Interactive Sources and Studies in Classical Greece The Perseus Project (5) has just released Perseus 1.0, the first publicly available version of its hypertextual database of multimedia materials on classical Greece. Perseus is designed to be used by a wide audience, comprised of readers at the student and scholar levels. As such, it must be able to locate information using different strategies, and it must contain enough detail to serve the different needs of its users. In addition, it must be delivered so that it is affordable to its target audience. [These problems and the solutions we chose are described in Mylonas, "An Interface to Classical Greek Civilization," JASIS 43:2, March 1992.] In order to achieve its objective, the project staff decided to make a conscious separation between selecting and converting textual, database, and image data on the one hand, and putting it into a delivery system on the other. That way, it is possible to create the electronic data without thinking about the restrictions of the delivery system. We have made a great effort to choose system-independent formats for our data, and to put as much thought and work as possible into structuring it so that the translation from paper to electronic form will enhance the value of the data. [A discussion of these solutions as of two years ago is in Elli Mylonas, Gregory Crane, Kenneth Morrell, and D. Neel Smith, "The Perseus Project: Data in the Electronic Age," in Accessing Antiquity: The Computerization of Classical Databases, J. Solomon and T. Worthen (eds.), University of Arizona Press, in press.] Much of the work on Perseus is focused on collecting and converting the data on which the project is based. At the same time, it is necessary to provide means of access to the information, in order to make it usable, and them to investigate how it is used. As we learn more about what students and scholars from different backgrounds do with Perseus, we can adjust our data collection, and also modify the system to accommodate them. In creating a delivery system for general use, we have tried to avoid favoring any one type of use by allowing multiple forms of access to and navigation through the system. The way text is handled exemplifies some of these principles. All text in Perseus is tagged using SGML, following the guidelines of the Text Encoding Initiative (TEI). This markup is used to index the text, and process it so that it can be imported into HyperCard. No SGML markup remains in the text that reaches the user, because currently it would be too expensive to create a system that acts on SGML in real time. However, the regularity provided by SGML is essential for verifying the content of the texts, and greatly speeds all the processing performed on them. The fact that the texts exist in SGML ensures that they will be relatively easy to port to different hardware and software, and so will outlast the current delivery platform. Finally, the SGML markup incorporates existing canonical reference systems (chapter, verse, line, etc.); indexing and navigation are based on these features. This ensures that the same canonical reference will always resolve to the same point within a text, and that all versions of our texts, regardless of delivery platform (even paper printouts) will function the same way. In order to provide tools for users, the text is processed by a morphological analyzer, and the results are stored in a database. Together with the index, the Greek-English Lexicon, and the index of all the English words in the definitions of the lexicon, the morphological analyses comprise a set of linguistic tools that allow users of all levels to work with the textual information, and to accomplish different tasks. For example, students who read no Greek may explore a concept as it appears in Greek texts by using the English-Greek index, and then looking up works in the texts and translations, or scholars may do detailed morphological studies of word use by using the morphological analyses of the texts. Because these tools were not designed for any one use, the same tools and the same data can be used by both students and scholars. NOTES: (5) Perseus is based at Harvard University, with collaborators at several other universities. The project has been funded primarily by the Annenberg/CPB Project, as well as by Harvard University, Apple Computer, and others. It is published by Yale University Press. Perseus runs on Macintosh computers, under the HyperCard program. Eric CALALUCA Chadwyck-Healey embarked last year on two distinct yet related full-text humanities database projects. The English Poetry Full-Text Database and the Patrologia Latina Database represent new approaches to linguistic research resources. The size and complexity of the projects present problems for electronic publishers, but surmountable ones if they remain abreast of the latest possibilities in data capture and retrieval software techniques. The issues which required address prior to the commencement of the projects were legion: 1. Editorial selection (or exclusion) of materials in each database 2. Deciding whether or not to incorporate a normative encoding structure into the databases? A. If one is selected, should it be SGML? B. If SGML, then the TEI? 3. Deliver as CD-ROM, magnetic tape, or both? 4. Can one produce retrieval software advanced enough for the postdoctoral linguist, yet accessible enough for unattended general use? Should one try? 5. Re fair and liberal networking policies, what are the risks to an electronic publisher? 6. How does the emergence of national and international education networks affect the use and viability of research projects requiring high investment? Do the new European Community directives concerning database protection necessitate two distinct publishing projects, one for North America and one for overseas? From new notions of "scholarly fair use" to the future of optical media, virtually every issue related to electronic publishing was aired. The result is two projects which have been constructed to provide the quality research resources with the fewest encumbrances to use by teachers and private scholars. Dorothy TWOHIG In spring 1988 the editors of the papers of George Washington, John Adams, Thomas Jefferson, James Madison, and Benjamin Franklin were approached by classics scholar David Packard on behalf of the Packard Humanities Foundation with a proposal to produce a CD-ROM edition of the complete papers of each of the Founding Fathers. This electronic edition will supplement the published volumes, making the documents widely available to students and researchers at reasonable cost. We estimate that our CD-ROM edition of Washington's Papers will be substantially completed within the next two years and ready for publication. Within the next ten years or so, similar CD-ROM editions of the Franklin, Adams, Jefferson, and Madison papers also will be available. At the Library of Congress's session on technology, I would like to discuss not only the experience of the Washington Papers in producing the CD-ROM edition, but the impact technology has had on these major editorial projects. Already, we are editing our volumes with an eye to the material that will be readily available in the CD-ROM edition. The completed electronic edition will provide immense possibilities for the searching of documents for information in a way never possible before. The kind of technical innovations that are currently available and on the drawing board will soon revolutionize historical research and the production of historical documents. Unfortunately, much of this new technology is not being used in the planning stages of historical projects, simply because many historians are aware only in the vaguest way of its existence. At least two major new historical editing projects are considering microfilm editions, simply because they are not aware of the possibilities of electronic alternatives and the advantages of the new technology in terms of flexibility and research potential compared to microfilm. In fact, too many of us in history and literature are still at the stage of struggling with our PCs. There are many historical editorial projects in progress presently, and an equal number of literary projects. While the two fields have somewhat different approaches to textual editing, there are ways in which electronic technology can be of service to both. Since few of the editors involved in the Founding Fathers CD-ROM editions are technical experts in any sense, I hope to point out in my discussion of our experience how many of these electronic innovations can be used successfully by scholars who are novices in the world of new technology. One of the major concerns of the sponsors of the multitude of new scholarly editions is the limited audience reached by the published volumes. Most of these editions are being published in small quantities and the publishers' price for them puts them out of the reach not only of individual scholars but of most public libraries and all but the largest educational institutions. However, little attention is being given to ways in which technology can bypass conventional publication to make historical and literary documents more widely available. What attracted us most to the CD-ROM edition of The Papers of George Washington was the fact that David Packard's aim was to make a complete edition of all of the 135,000 documents we have collected available in an inexpensive format that would be placed in public libraries, small colleges, and even high schools. This would provide an audience far beyond our present 1,000-copy, $45 published edition. Since the CD-ROM edition will carry none of the explanatory annotation that appears in the published volumes, we also feel that the use of the CD-ROM will lead many researchers to seek out the published volumes. In addition to ignorance of new technical advances, I have found that too many editors--and historians and literary scholars--are resistant and even hostile to suggestions that electronic technology may enhance their work. I intend to discuss some of the arguments traditionalists are advancing to resist technology, ranging from distrust of the speed with which it changes (we are already wondering what is out there that is better than CD-ROM) to suspicion of the technical language used to describe electronic developments. Maria LEBRON The Online Journal of Current Clinical Trials, a joint venture of the American Association for the Advancement of Science (AAAS) and the Online Computer Library Center, Inc. (OCLC), is the first peer-reviewed journal to provide full text, tabular material, and line illustrations on line. This presentation will discuss the genesis and start-up period of the journal. Topics of discussion will include historical overview, day-to-day management of the editorial peer review, and manuscript tagging and publication. A demonstration of the journal and its features will accompany the presentation. Lynne PERSONIUS Cornell University Library, Cornell Information Technologies, and Xerox Corporation, with the support of the Commission on Preservation and Access, and Sun Microsystems, Inc., have been collaborating in a project to test a prototype system for recording brittle books as digital images and producing, on demand, high-quality archival paper replacements. The project goes beyond that, however, to investigate some of the issues surrounding scanning, storing, retrieving, and providing access to digital images in a network environment. The Joint Study in Digital Preservation began in January 1990. Xerox provided the College Library Access and Storage System (CLASS) software, a prototype 600-dots-per-inch (dpi) scanner, and the hardware necessary to support network printing on the DocuTech printer housed in Cornell's Computing and Communications Center (CCC). The Cornell staff using the hardware and software became an integral part of the development and testing process for enhancements to the CLASS software system. The collaborative nature of this relationship is resulting in a system that is specifically tailored to the preservation application. A digital library of 1,000 volumes (or approximately 300,000 images) has been created and is stored on an optical jukebox that resides in CCC. The library includes a collection of select mathematics monographs that provides mathematics faculty with an opportunity to use the electronic library. The remaining volumes were chosen for the library to test the various capabilities of the scanning system. One project objective is to provide users of the Cornell library and the library staff with the ability to request facsimiles of digitized images or to retrieve the actual electronic image for browsing. A prototype viewing workstation has been created by Xerox, with input into the design by a committee of Cornell librarians and computer professionals. This will allow us to experiment with patron access to the images that make up the digital library. The viewing station provides search, retrieval, and (ultimately) printing functions with enhancements to facilitate navigation through multiple documents. Cornell currently is working to extend access to the digital library to readers using workstations from their offices. This year is devoted to the development of a network resident image conversion and delivery server, and client software that will support readers who use Apple Macintosh computers, IBM windows platforms, and Sun workstations. Equipment for this development was provided by Sun Microsystems with support from the Commission on Preservation and Access. During the show-and-tell session of the Workshop on Electronic Texts, a prototype view station will be demonstrated. In addition, a display of original library books that have been digitized will be available for review with associated printed copies for comparison. The fifteen-minute overview of the project will include a slide presentation that constitutes a "tour" of the preservation digitizing process. The final network-connected version of the viewing station will provide library users with another mechanism for accessing the digital library, and will also provide the capability of viewing images directly. This will not require special software, although a powerful computer with good graphics will be needed. The Joint Study in Digital Preservation has generated a great deal of interest in the library community. Unfortunately, or perhaps fortunately, this project serves to raise a vast number of other issues surrounding the use of digital technology for the preservation and use of deteriorating library materials, which subsequent projects will need to examine. Much work remains. SESSION III Howard BESSER Networking Multimedia Databases What do we have to consider in building and distributing databases of visual materials in a multi-user environment? This presentation examines a variety of concerns that need to be addressed before a multimedia database can be set up in a networked environment. In the past it has not been feasible to implement databases of visual materials in shared-user environments because of technological barriers. Each of the two basic models for multi-user multimedia databases has posed its own problem. The analog multimedia storage model (represented by Project Athena's parallel analog and digital networks) has required an incredibly complex (and expensive) infrastructure. The economies of scale that make multi-user setups cheaper per user served do not operate in an environment that requires a computer workstation, videodisc player, and two display devices for each user. The digital multimedia storage model has required vast amounts of storage space (as much as one gigabyte per thirty still images). In the past the cost of such a large amount of storage space made this model a prohibitive choice as well. But plunging storage costs are finally making this second alternative viable. If storage no longer poses such an impediment, what do we need to consider in building digitally stored multi-user databases of visual materials? This presentation will examine the networking and telecommunication constraints that must be overcome before such databases can become commonplace and useful to a large number of people. The key problem is the vast size of multimedia documents, and how this affects not only storage but telecommunications transmission time. Anything slower than T-1 speed is impractical for files of 1 megabyte or larger (which is likely to be small for a multimedia document). For instance, even on a 56 Kb line it would take three minutes to transfer a 1-megabyte file. And these figures assume ideal circumstances, and do not take into consideration other users contending for network bandwidth, disk access time, or the time needed for remote display. Current common telephone transmission rates would be completely impractical; few users would be willing to wait the hour necessary to transmit a single image at 2400 baud. This necessitates compression, which itself raises a number of other issues. In order to decrease file sizes significantly, we must employ lossy compression algorithms. But how much quality can we afford to lose? To date there has been only one significant study done of image-quality needs for a particular user group, and this study did not look at loss resulting from compression. Only after identifying image-quality needs can we begin to address storage and network bandwidth needs. Experience with X-Windows-based applications (such as Imagequery, the University of California at Berkeley image database) demonstrates the utility of a client-server topology, but also points to the limitation of current software for a distributed environment. For example, applications like Imagequery can incorporate compression, but current X implementations do not permit decompression at the end user's workstation. Such decompression at the host computer alleviates storage capacity problems while doing nothing to address problems of telecommunications bandwidth. We need to examine the effects on network through-put of moving multimedia documents around on a network. We need to examine various topologies that will help us avoid bottlenecks around servers and gateways. Experience with applications such as these raise still broader questions. How closely is the multimedia document tied to the software for viewing it? Can it be accessed and viewed from other applications? Experience with the MARC format (and more recently with the Z39.50 protocols) shows how useful it can be to store documents in a form in which they can be accessed by a variety of application software. Finally, from an intellectual-access standpoint, we need to address the issue of providing access to these multimedia documents in interdisciplinary environments. We need to examine terminology and indexing strategies that will allow us to provide access to this material in a cross-disciplinary way. Ronald LARSEN Directions in High-Performance Networking for Libraries The pace at which computing technology has advanced over the past forty years shows no sign of abating. Roughly speaking, each five-year period has yielded an order-of-magnitude improvement in price and performance of computing equipment. No fundamental hurdles are likely to prevent this pace from continuing for at least the next decade. It is only in the past five years, though, that computing has become ubiquitous in libraries, affecting all staff and patrons, directly or indirectly. During these same five years, communications rates on the Internet, the principal academic computing network, have grown from 56 kbps to 1.5 Mbps, and the NSFNet backbone is now running 45 Mbps. Over the next five years, communication rates on the backbone are expected to exceed 1 Gbps. Growth in both the population of network users and the volume of network traffic has continued to grow geometrically, at rates approaching 15 percent per month. This flood of capacity and use, likened by some to "drinking from a firehose," creates immense opportunities and challenges for libraries. Libraries must anticipate the future implications of this technology, participate in its development, and deploy it to ensure access to the world's information resources. The infrastructure for the information age is being put in place. Libraries face strategic decisions about their role in the development, deployment, and use of this infrastructure. The emerging infrastructure is much more than computers and communication lines. It is more than the ability to compute at a remote site, send electronic mail to a peer across the country, or move a file from one library to another. The next five years will witness substantial development of the information infrastructure of the network. In order to provide appropriate leadership, library professionals must have a fundamental understanding of and appreciation for computer networking, from local area networks to the National Research and Education Network (NREN). This presentation addresses these fundamentals, and how they relate to libraries today and in the near future. Edwin BROWNRIGG Electronic Library Visions and Realities The electronic library has been a vision desired by many--and rejected by some--since Vannevar Bush coined the term memex to describe an automated, intelligent, personal information system. Variations on this vision have included Ted Nelson's Xanadau, Alan Kay's Dynabook, and Lancaster's "paperless library," with the most recent incarnation being the "Knowledge Navigator" described by John Scully of Apple. But the reality of library service has been less visionary and the leap to the electronic library has eluded universities, publishers, and information technology files. The Memex Research Institute (MemRI), an independent, nonprofit research and development organization, has created an Electronic Library Program of shared research and development in order to make the collective vision more concrete. The program is working toward the creation of large, indexed publicly available electronic image collections of published documents in academic, special, and public libraries. This strategic plan is the result of the first stage of the program, which has been an investigation of the information technologies available to support such an effort, the economic parameters of electronic service compared to traditional library operations, and the business and political factors affecting the shift from print distribution to electronic networked access. The strategic plan envisions a combination of publicly searchable access databases, image (and text) document collections stored on network "file servers," local and remote network access, and an intellectual property management-control system. This combination of technology and information content is defined in this plan as an E-library or E-library collection. Some participating sponsors are already developing projects based on MemRI's recommended directions. The E-library strategy projected in this plan is a visionary one that can enable major changes and improvements in academic, public, and special library service. This vision is, though, one that can be realized with today's technology. At the same time, it will challenge the political and social structure within which libraries operate: in academic libraries, the traditional emphasis on local collections, extending to accreditation issues; in public libraries, the potential of electronic branch and central libraries fully available to the public; and for special libraries, new opportunities for shared collections and networks. The environment in which this strategic plan has been developed is, at the moment, dominated by a sense of library limits. The continued expansion and rapid growth of local academic library collections is now clearly at an end. Corporate libraries, and even law libraries, are faced with operating within a difficult economic climate, as well as with very active competition from commercial information sources. For example, public libraries may be seen as a desirable but not critical municipal service in a time when the budgets of safety and health agencies are being cut back. Further, libraries in general have a very high labor-to-cost ratio in their budgets, and labor costs are still increasing, notwithstanding automation investments. It is difficult for libraries to obtain capital, startup, or seed funding for innovative activities, and those technology-intensive initiatives that offer the potential of decreased labor costs can provoke the opposition of library staff. However, libraries have achieved some considerable successes in the past two decades by improving both their service and their credibility within their organizations--and these positive changes have been accomplished mostly with judicious use of information technologies. The advances in computing and information technology have been well-chronicled: the continuing precipitous drop in computing costs, the growth of the Internet and private networks, and the explosive increase in publicly available information databases. For example, OCLC has become one of the largest computer network organizations in the world by creating a cooperative cataloging network of more than 6,000 libraries worldwide. On-line public access catalogs now serve millions of users on more than 50,000 dedicated terminals in the United States alone. The University of California MELVYL on-line catalog system has now expanded into an index database reference service and supports more than six million searches a year. And, libraries have become the largest group of customers of CD-ROM publishing technology; more than 30,000 optical media publications such as those offered by InfoTrac and Silver Platter are subscribed to by U.S. libraries. This march of technology continues and in the next decade will result in further innovations that are extremely difficult to predict. What is clear is that libraries can now go beyond automation of their order files and catalogs to automation of their collections themselves--and it is possible to circumvent the fiscal limitations that appear to obtain today. This Electronic Library Strategic Plan recommends a paradigm shift in library service, and demonstrates the steps necessary to provide improved library services with limited capacities and operating investments. SESSION IV-A Anne KENNEY The Cornell/Xerox Joint Study in Digital Preservation resulted in the recording of 1,000 brittle books as 600-dpi digital images and the production, on demand, of high-quality and archivally sound paper replacements. The project, which was supported by the Commission on Preservation and Access, also investigated some of the issues surrounding scanning, storing, retrieving, and providing access to digital images in a network environment. Anne Kenney will focus on some of the issues surrounding direct scanning as identified in the Cornell Xerox Project. Among those to be discussed are: image versus text capture; indexing and access; image-capture capabilities; a comparison to photocopy and microfilm; production and cost analysis; storage formats, protocols, and standards; and the use of this scanning technology for preservation purposes. The 600-dpi digital images produced in the Cornell Xerox Project proved highly acceptable for creating paper replacements of deteriorating originals. The 1,000 scanned volumes provided an array of image-capture challenges that are common to nineteenth-century printing techniques and embrittled material, and that defy the use of text-conversion processes. These challenges include diminished contrast between text and background, fragile and deteriorated pages, uneven printing, elaborate type faces, faint and bold text adjacency, handwritten text and annotations, nonRoman languages, and a proliferation of illustrated material embedded in text. The latter category included high-frequency and low-frequency halftones, continuous tone photographs, intricate mathematical drawings, maps, etchings, reverse-polarity drawings, and engravings. The Xerox prototype scanning system provided a number of important features for capturing this diverse material. Technicians used multiple threshold settings, filters, line art and halftone definitions, autosegmentation, windowing, and software-editing programs to optimize image capture. At the same time, this project focused on production. The goal was to make scanning as affordable and acceptable as photocopying and microfilming for preservation reformatting. A time-and-cost study conducted during the last three months of this project confirmed the economic viability of digital scanning, and these findings will be discussed here. From the outset, the Cornell Xerox Project was predicated on the use of nonproprietary standards and the use of common protocols when standards did not exist. Digital files were created as TIFF images which were compressed prior to storage using Group 4 CCITT compression. The Xerox software is MS DOS based and utilizes off-the shelf programs such as Microsoft Windows and Wang Image Wizard. The digital library is designed to be hardware-independent and to provide interchangeability with other institutions through network connections. Access to the digital files themselves is two-tiered: Bibliographic records for the computer files are created in RLIN and Cornell's local system and access into the actual digital images comprising a book is provided through a document control structure and a networked image file-server, both of which will be described. The presentation will conclude with a discussion of some of the issues surrounding the use of this technology as a preservation tool (storage, refreshing, backup). Pamela ANDRE and Judith ZIDAR The National Agricultural Library (NAL) has had extensive experience with raster scanning of printed materials. Since 1987, the Library has participated in the National Agricultural Text Digitizing Project (NATDP) a cooperative effort between NAL and forty-five land grant university libraries. An overview of the project will be presented, giving its history and NAL's strategy for the future. An in-depth discussion of NATDP will follow, including a description of the scanning process, from the gathering of the printed materials to the archiving of the electronic pages. The type of equipment required for a stand-alone scanning workstation and the importance of file management software will be discussed. Issues concerning the images themselves will be addressed briefly, such as image format; black and white versus color; gray scale versus dithering; and resolution. Also described will be a study currently in progress by NAL to evaluate the usefulness of converting microfilm to electronic images in order to improve access. With the cooperation of Tuskegee University, NAL has selected three reels of microfilm from a collection of sixty-seven reels containing the papers, letters, and drawings of George Washington Carver. The three reels were converted into 3,500 electronic images using a specialized microfilm scanner. The selection, filming, and indexing of this material will be discussed. Donald WATERS Project Open Book, the Yale University Library's effort to convert 10, 000 books from microfilm to digital imagery, is currently in an advanced state of planning and organization. The Yale Library has selected a major vendor to serve as a partner in the project and as systems integrator. In its proposal, the successful vendor helped isolate areas of risk and uncertainty as well as key issues to be addressed during the life of the project. The Yale Library is now poised to decide what material it will convert to digital image form and to seek funding, initially for the first phase and then for the entire project. The proposal that Yale accepted for the implementation of Project Open Book will provide at the end of three phases a conversion subsystem, browsing stations distributed on the campus network within the Yale Library, a subsystem for storing 10,000 books at 200 and 600 dots per inch, and network access to the image printers. Pricing for the system implementation assumes the existence of Yale's campus ethernet network and its high-speed image printers, and includes other requisite hardware and software, as well as system integration services. Proposed operating costs include hardware and software maintenance, but do not include estimates for the facilities management of the storage devices and image servers. Yale selected its vendor partner in a formal process, partly funded by the Commission for Preservation and Access. Following a request for proposal, the Yale Library selected two vendors as finalists to work with Yale staff to generate a detailed analysis of requirements for Project Open Book. Each vendor used the results of the requirements analysis to generate and submit a formal proposal for the entire project. This competitive process not only enabled the Yale Library to select its primary vendor partner but also revealed much about the state of the imaging industry, about the varying, corporate commitments to the markets for imaging technology, and about the varying organizational dynamics through which major companies are responding to and seeking to develop these markets. Project Open Book is focused specifically on the conversion of images from microfilm to digital form. The technology for scanning microfilm is readily available but is changing rapidly. In its project requirements, the Yale Library emphasized features of the technology that affect the technical quality of digital image production and the costs of creating and storing the image library: What levels of digital resolution can be achieved by scanning microfilm? How does variation in the quality of microfilm, particularly in film produced to preservation standards, affect the quality of the digital images? What technologies can an operator effectively and economically apply when scanning film to separate two-up images and to control for and correct image imperfections? How can quality control best be integrated into digitizing work flow that includes document indexing and storage? The actual and expected uses of digital images--storage, browsing, printing, and OCR--help determine the standards for measuring their quality. Browsing is especially important, but the facilities available for readers to browse image documents is perhaps the weakest aspect of imaging technology and most in need of development. As it defined its requirements, the Yale Library concentrated on some fundamental aspects of usability for image documents: Does the system have sufficient flexibility to handle the full range of document types, including monographs, multi-part and multivolume sets, and serials, as well as manuscript collections? What conventions are necessary to identify a document uniquely for storage and retrieval? Where is the database of record for storing bibliographic information about the image document? How are basic internal structures of documents, such as pagination, made accessible to the reader? How are the image documents physically presented on the screen to the reader? The Yale Library designed Project Open Book on the assumption that microfilm is more than adequate as a medium for preserving the content of deteriorated library materials. As planning in the project has advanced, it is increasingly clear that the challenge of digital image technology and the key to the success of efforts like Project Open Book is to provide a means of both preserving and improving access to those deteriorated materials. SESSION IV-B George THOMA In the use of electronic imaging for document preservation, there are several issues to consider, such as: ensuring adequate image quality, maintaining substantial conversion rates (through-put), providing unique identification for automated access and retrieval, and accommodating bound volumes and fragile material. To maintain high image quality, image processing functions are required to correct the deficiencies in the scanned image. Some commercially available systems include these functions, while some do not. The scanned raw image must be processed to correct contrast deficiencies-- both poor overall contrast resulting from light print and/or dark background, and variable contrast resulting from stains and bleed-through. Furthermore, the scan density must be adequate to allow legibility of print and sufficient fidelity in the pseudo-halftoned gray material. Borders or page-edge effects must be removed for both compactibility and aesthetics. Page skew must be corrected for aesthetic reasons and to enable accurate character recognition if desired. Compound images consisting of both two-toned text and gray-scale illustrations must be processed appropriately to retain the quality of each. SESSION IV-C Jean BARONAS Standards publications being developed by scientists, engineers, and business managers in Association for Information and Image Management (AIIM) standards committees can be applied to electronic image management (EIM) processes including: document (image) transfer, retrieval and evaluation; optical disk and document scanning; and document design and conversion. When combined with EIM system planning and operations, standards can assist in generating image databases that are interchangeable among a variety of systems. The applications of different approaches for image-tagging, indexing, compression, and transfer often cause uncertainty concerning EIM system compatibility, calibration, performance, and upward compatibility, until standard implementation parameters are established. The AIIM standards that are being developed for these applications can be used to decrease the uncertainty, successfully integrate imaging processes, and promote "open systems." AIIM is an accredited American National Standards Institute (ANSI) standards developer with more than twenty committees comprised of 300 volunteers representing users, vendors, and manufacturers. The standards publications that are developed in these committees have national acceptance and provide the basis for international harmonization in the development of new International Organization for Standardization (ISO) standards. This presentation describes the development of AIIM's EIM standards and a new effort at AIIM, a database on standards projects in a wide framework of imaging industries including capture, recording, processing, duplication, distribution, display, evaluation, and preservation. The AIIM Imagery Database will cover imaging standards being developed by many organizations in many different countries. It will contain standards publications' dates, origins, related national and international projects, status, key words, and abstracts. The ANSI Image Technology Standards Board requested that such a database be established, as did the ISO/International Electrotechnical Commission Joint Task Force on Imagery. AIIM will take on the leadership role for the database and coordinate its development with several standards developers. Patricia BATTIN Characteristics of standards for digital imagery: * Nature of digital technology implies continuing volatility. * Precipitous standard-setting not possible and probably not desirable. * Standards are a complex issue involving the medium, the hardware, the software, and the technical capacity for reproductive fidelity and clarity. * The prognosis for reliable archival standards (as defined by librarians) in the foreseeable future is poor. Significant potential and attractiveness of digital technology as a preservation medium and access mechanism. Productive use of digital imagery for preservation requires a reconceptualizing of preservation principles in a volatile, standardless world. Concept of managing continuing access in the digital environment rather than focusing on the permanence of the medium and long-term archival standards developed for the analog world. Transition period: How long and what to do? * Redefine "archival." * Remove the burden of "archival copy" from paper artifacts. * Use digital technology for storage, develop management strategies for refreshing medium, hardware and software. * Create acid-free paper copies for transition period backup until we develop reliable procedures for ensuring continuing access to digital files. SESSION IV-D Stuart WEIBEL The Role of SGML Markup in the CORE Project (6) The emergence of high-speed telecommunications networks as a basic feature of the scholarly workplace is driving the demand for electronic document delivery. Three distinct categories of electronic publishing/republishing are necessary to support access demands in this emerging environment: 1.) Conversion of paper or microfilm archives to electronic format 2.) Conversion of electronic files to formats tailored to electronic retrieval and display 3.) Primary electronic publishing (materials for which the electronic version is the primary format) OCLC has experimental or product development activities in each of these areas. Among the challenges that lie ahead is the integration of these three types of information stores in coherent distributed systems. The CORE (Chemistry Online Retrieval Experiment) Project is a model for the conversion of large text and graphics collections for which electronic typesetting files are available (category 2). The American Chemical Society has made available computer typography files dating from 1980 for its twenty journals. This collection of some 250 journal-years is being converted to an electronic format that will be accessible through several end-user applications. The use of Standard Generalized Markup Language (SGML) offers the means to capture the structural richness of the original articles in a way that will support a variety of retrieval, navigation, and display options necessary to navigate effectively in very large text databases. An SGML document consists of text that is marked up with descriptive tags that specify the function of a given element within the document. As a formal language construct, an SGML document can be parsed against a document-type definition (DTD) that unambiguously defines what elements are allowed and where in the document they can (or must) occur. This formalized map of article structure allows the user interface design to be uncoupled from the underlying database system, an important step toward interoperability. Demonstration of this separability is a part of the CORE project, wherein user interface designs born of very different philosophies will access the same database. NOTES: (6) The CORE project is a collaboration among Cornell University's Mann Library, Bell Communications Research (Bellcore), the American Chemical Society (ACS), the Chemical Abstracts Service (CAS), and OCLC. Michael LESK The CORE Electronic Chemistry Library A major on-line file of chemical journal literature complete with graphics is being developed to test the usability of fully electronic access to documents, as a joint project of Cornell University, the American Chemical Society, the Chemical Abstracts Service, OCLC, and Bellcore (with additional support from Sun Microsystems, Springer-Verlag, DigitaI Equipment Corporation, Sony Corporation of America, and Apple Computers). Our file contains the American Chemical Society's on-line journals, supplemented with the graphics from the paper publication. The indexing of the articles from Chemical Abstracts Documents is available in both image and text format, and several different interfaces can be used. Our goals are (1) to assess the effectiveness and acceptability of electronic access to primary journals as compared with paper, and (2) to identify the most desirable functions of the user interface to an electronic system of journals, including in particular a comparison of page-image display with ASCII display interfaces. Early experiments with chemistry students on a variety of tasks suggest that searching tasks are completed much faster with any electronic system than with paper, but that for reading all versions of the articles are roughly equivalent. Pamela ANDRE and Judith ZIDAR Text conversion is far more expensive and time-consuming than image capture alone. NAL's experience with optical character recognition (OCR) will be related and compared with the experience of having text rekeyed. What factors affect OCR accuracy? How accurate does full text have to be in order to be useful? How do different users react to imperfect text? These are questions that will be explored. For many, a service bureau may be a better solution than performing the work inhouse; this will also be discussed. SESSION VI Marybeth PETERS Copyright law protects creative works. Protection granted by the law to authors and disseminators of works includes the right to do or authorize the following: reproduce the work, prepare derivative works, distribute the work to the public, and publicly perform or display the work. In addition, copyright owners of sound recordings and computer programs have the right to control rental of their works. These rights are not unlimited; there are a number of exceptions and limitations. An electronic environment places strains on the copyright system. Copyright owners want to control uses of their work and be paid for any use; the public wants quick and easy access at little or no cost. The marketplace is working in this area. Contracts, guidelines on electronic use, and collective licensing are in use and being refined. Issues concerning the ability to change works without detection are more difficult to deal with. Questions concerning the integrity of the work and the status of the changed version under the copyright law are to be addressed. These are public policy issues which require informed dialogue. *** *** *** ****** *** *** *** Appendix III: DIRECTORY OF PARTICIPANTS PRESENTERS: Pamela Q.J. Andre Associate Director, Automation National Agricultural Library 10301 Baltimore Boulevard Beltsville, MD 20705-2351 Phone: (301) 504-6813 Fax: (301) 504-7473 E-mail: INTERNET: PANDRE@ASRR.ARSUSDA.GOV Jean Baronas, Senior Manager Department of Standards and Technology Association for Information and Image Management (AIIM) 1100 Wayne Avenue, Suite 1100 Silver Spring, MD 20910 Phone: (301) 587-8202 Fax: (301) 587-2711 Patricia Battin, President The Commission on Preservation and Access 1400 16th Street, N.W. Suite 740 Washington, DC 20036-2217 Phone: (202) 939-3400 Fax: (202) 939-3407 E-mail: CPA@GWUVM.BITNET Howard Besser Centre Canadien d'Architecture (Canadian Center for Architecture) 1920, rue Baile Montreal, Quebec H3H 2S6 CANADA Phone: (514) 939-7001 Fax: (514) 939-7020 E-mail: howard@lis.pitt.edu Edwin B. Brownrigg, Executive Director Memex Research Institute 422 Bonita Avenue Roseville, CA 95678 Phone: (916) 784-2298 Fax: (916) 786-7559 E-mail: BITNET: MEMEX@CALSTATE.2 Eric M. Calaluca, Vice President Chadwyck-Healey, Inc. 1101 King Street Alexandria, VA 223l4 Phone: (800) 752-05l5 Fax: (703) 683-7589 James Daly 4015 Deepwood Road Baltimore, MD 21218-1404 Phone: (410) 235-0763 Ricky Erway, Associate Coordinator American Memory Library of Congress Phone: (202) 707-6233 Fax: (202) 707-3764 Carl Fleischhauer, Coordinator American Memory Library of Congress Phone: (202) 707-6233 Fax: (202) 707-3764 Joanne Freeman 2000 Jefferson Park Avenue, No. 7 Charlottesville, VA 22903 Prosser Gifford Director for Scholarly Programs Library of Congress Phone: (202) 707-1517 Fax: (202) 707-9898 E-mail: pgif@seq1.loc.gov Jacqueline Hess, Director National Demonstration Laboratory for Interactive Information Technologies Library of Congress Phone: (202) 707-4157 Fax: (202) 707-2829 Susan Hockey, Director Center for Electronic Texts in the Humanities (CETH) Alexander Library Rutgers University 169 College Avenue New Brunswick, NJ 08903 Phone: (908) 932-1384 Fax: (908) 932-1386 E-mail: hockey@zodiac.rutgers.edu William L. Hooton, Vice President Business & Technical Development Imaging & Information Systems Group I-NET 6430 Rockledge Drive, Suite 400 Bethesda, MD 208l7 Phone: (301) 564-6750 Fax: (513) 564-6867 Anne R. Kenney, Associate Director Department of Preservation and Conservation 701 Olin Library Cornell University Ithaca, NY 14853 Phone: (607) 255-6875 Fax: (607) 255-9346 E-mail: LYDY@CORNELLA.BITNET Ronald L. Larsen Associate Director for Information Technology University of Maryland at College Park Room B0224, McKeldin Library College Park, MD 20742-7011 Phone: (301) 405-9194 Fax: (301) 314-9865 E-mail: rlarsen@libr.umd.edu Maria L. Lebron, Managing Editor The Online Journal of Current Clinical Trials l333 H Street, N.W. Washington, DC 20005 Phone: (202) 326-6735 Fax: (202) 842-2868 E-mail: PUBSAAAS@GWUVM.BITNET Michael Lesk, Executive Director Computer Science Research Bell Communications Research, Inc. Rm 2A-385 445 South Street Morristown, NJ 07960-l9l0 Phone: (201) 829-4070 Fax: (201) 829-5981 E-mail: lesk@bellcore.com (Internet) or bellcore!lesk (uucp) Clifford A. Lynch Director, Library Automation University of California, Office of the President 300 Lakeside Drive, 8th Floor Oakland, CA 94612-3350 Phone: (510) 987-0522 Fax: (510) 839-3573 E-mail: calur@uccmvsa Avra Michelson National Archives and Records Administration NSZ Rm. 14N 7th & Pennsylvania, N.W. Washington, D.C. 20408 Phone: (202) 501-5544 Fax: (202) 501-5533 E-mail: tmi@cu.nih.gov Elli Mylonas, Managing Editor Perseus Project Department of the Classics Harvard University 319 Boylston Hall Cambridge, MA 02138 Phone: (617) 495-9025, (617) 495-0456 (direct) Fax: (617) 496-8886 E-mail: Elli@IKAROS.Harvard.EDU or elli@wjh12.harvard.edu David Woodley Packard Packard Humanities Institute 300 Second Street, Suite 201 Los Altos, CA 94002 Phone: (415) 948-0150 (PHI) Fax: (415) 948-5793 Lynne K. Personius, Assistant Director Cornell Information Technologies for Scholarly Information Sources 502 Olin Library Cornell University Ithaca, NY 14853 Phone: (607) 255-3393 Fax: (607) 255-9346 E-mail: JRN@CORNELLC.BITNET Marybeth Peters Policy Planning Adviser to the Register of Copyrights Library of Congress Office LM 403 Phone: (202) 707-8350 Fax: (202) 707-8366 C. Michael Sperberg-McQueen Editor, Text Encoding Initiative Computer Center (M/C 135) University of Illinois at Chicago Box 6998 Chicago, IL 60680 Phone: (312) 413-0317 Fax: (312) 996-6834 E-mail: u35395@uicvm..cc.uic.edu or u35395@uicvm.bitnet George R. Thoma, Chief Communications Engineering Branch National Library of Medicine 8600 Rockville Pike Bethesda, MD 20894 Phone: (301) 496-4496 Fax: (301) 402-0341 E-mail: thoma@lhc.nlm.nih.gov Dorothy Twohig, Editor The Papers of George Washington 504 Alderman Library University of Virginia Charlottesville, VA 22903-2498 Phone: (804) 924-0523 Fax: (804) 924-4337 Susan H. Veccia, Team leader American Memory, User Evaluation Library of Congress American Memory Evaluation Project Phone: (202) 707-9104 Fax: (202) 707-3764 E-mail: svec@seq1.loc.gov Donald J. Waters, Head Systems Office Yale University Library New Haven, CT 06520 Phone: (203) 432-4889 Fax: (203) 432-7231 E-mail: DWATERS@YALEVM.BITNET or DWATERS@YALEVM.YCC.YALE.EDU Stuart Weibel, Senior Research Scientist OCLC 6565 Frantz Road Dublin, OH 43017 Phone: (614) 764-608l Fax: (614) 764-2344 E-mail: INTERNET: Stu@rsch.oclc.org Robert G. Zich Special Assistant to the Associate Librarian for Special Projects Library of Congress Phone: (202) 707-6233 Fax: (202) 707-3764 E-mail: rzic@seq1.loc.gov Judith A. Zidar, Coordinator National Agricultural Text Digitizing Program Information Systems Division National Agricultural Library 10301 Baltimore Boulevard Beltsville, MD 20705-2351 Phone: (301) 504-6813 or 504-5853 Fax: (301) 504-7473 E-mail: INTERNET: JZIDAR@ASRR.ARSUSDA.GOV OBSERVERS: Helen Aguera, Program Officer Division of Research Room 318 National Endowment for the Humanities 1100 Pennsylvania Avenue, N.W. Washington, D.C. 20506 Phone: (202) 786-0358 Fax: (202) 786-0243 M. Ellyn Blanton, Deputy Director National Demonstration Laboratory for Interactive Information Technologies Library of Congress Phone: (202) 707-4157 Fax: (202) 707-2829 Charles M. Dollar National Archives and Records Administration NSZ Rm. 14N 7th & Pennsylvania, N.W. Washington, DC 20408 Phone: (202) 501-5532 Fax: (202) 501-5512 Jeffrey Field, Deputy to the Director Division of Preservation and Access Room 802 National Endowment for the Humanities 1100 Pennsylvania Avenue, N.W. Washington, DC 20506 Phone: (202) 786-0570 Fax: (202) 786-0243 Lorrin Garson American Chemical Society Research and Development Department 1155 16th Street, N.W. Washington, D.C. 20036 Phone: (202) 872-4541 Fax: E-mail: INTERNET: LRG96@ACS.ORG William M. Holmes, Jr. National Archives and Records Administration NSZ Rm. 14N 7th & Pennsylvania, N.W. Washington, DC 20408 Phone: (202) 501-5540 Fax: (202) 501-5512 E-mail: WHOLMES@AMERICAN.EDU Sperling Martin Information Resource Management 20030 Doolittle Street Gaithersburg, MD 20879 Phone: (301) 924-1803 Michael Neuman, Director The Center for Text and Technology Academic Computing Center 238 Reiss Science Building Georgetown University Washington, DC 20057 Phone: (202) 687-6096 Fax: (202) 687-6003 E-mail: neuman@guvax.bitnet, neuman@guvax.georgetown.edu Barbara Paulson, Program Officer Division of Preservation and Access Room 802 National Endowment for the Humanities 1100 Pennsylvania Avenue, N.W. Washington, DC 20506 Phone: (202) 786-0577 Fax: (202) 786-0243 Allen H. Renear Senior Academic Planning Analyst Brown University Computing and Information Services 115 Waterman Street Campus Box 1885 Providence, R.I. 02912 Phone: (401) 863-7312 Fax: (401) 863-7329 E-mail: BITNET: Allen@BROWNVM or INTERNET: Allen@brownvm.brown.edu Susan M. Severtson, President Chadwyck-Healey, Inc. 1101 King Street Alexandria, VA 223l4 Phone: (800) 752-05l5 Fax: (703) 683-7589 Frank Withrow U.S. Department of Education 555 New Jersey Avenue, N.W. Washington, DC 20208-5644 Phone: (202) 219-2200 Fax: (202) 219-2106 (LC STAFF) Linda L. Arret Machine-Readable Collections Reading Room LJ 132 (202) 707-1490 John D. Byrum, Jr. Descriptive Cataloging Division LM 540 (202) 707-5194 Mary Jane Cavallo Science and Technology Division LA 5210 (202) 707-1219 Susan Thea David Congressional Research Service LM 226 (202) 707-7169 Robert Dierker Senior Adviser for Multimedia Activities LM 608 (202) 707-6151 William W. Ellis Associate Librarian for Science and Technology LM 611 (202) 707-6928 Ronald Gephart Manuscript Division LM 102 (202) 707-5097 James Graber Information Technology Services LM G51 (202) 707-9628 Rich Greenfield American Memory LM 603 (202) 707-6233 Rebecca Guenther Network Development LM 639 (202) 707-5092 Kenneth E. Harris Preservation LM G21 (202) 707-5213 Staley Hitchcock Manuscript Division LM 102 (202) 707-5383 Bohdan Kantor Office of Special Projects LM 612 (202) 707-0180 John W. Kimball, Jr Machine-Readable Collections Reading Room LJ 132 (202) 707-6560 Basil Manns Information Technology Services LM G51 (202) 707-8345 Sally Hart McCallum Network Development LM 639 (202) 707-6237 Dana J. Pratt Publishing Office LM 602 (202) 707-6027 Jane Riefenhauser American Memory LM 603 (202) 707-6233 William Z. Schenck Collections Development LM 650 (202) 707-7706 Chandru J. Shahani Preservation Research and Testing Office (R&T) LM G38 (202) 707-5607 William J. Sittig Collections Development LM 650 (202) 707-7050 Paul Smith Manuscript Division LM 102 (202) 707-5097 James L. Stevens Information Technology Services LM G51 (202) 707-9688 Karen Stuart Manuscript Division LM 130 (202) 707-5389 Tamara Swora Preservation Microfilming Office LM G05 (202) 707-6293 Sarah Thomas Collections Cataloging LM 642 (202) 707-5333 END ************************************************************* Note: This file has been edited for use on computer networks. This editing required the removal of diacritics, underlining, and fonts such as italics and bold. kde 11/92 [A few of the italics (when used for emphasis) were replaced by CAPS mh] *End of The Project Gutenberg Etext of LOC WORKSHOP ON ELECTRONIC ETEXTS This is the February 1992 Project Gutenberg release of: Paradise Lost by John Milton The oldest etext known to Project Gutenberg (ca. 1964-1965) (If you know of any older ones, please let us know.) Introduction (one page) This etext was originally created in 1964-1965 according to Dr. Joseph Raben of Queens College, NY, to whom it is attributed by Project Gutenberg. We had heard of this etext for years but it was not until 1991 that we actually managed to track it down to a specific location, and then it took months to convince people to let us have a copy, then more months for them actually to do the copying and get it to us. Then another month to convert to something we could massage with our favorite 486 in DOS. After that is was only a matter of days to get it into this shape you will see below. The original was, of course, in CAPS only, and so were all the other etexts of the 60's and early 70's. Don't let anyone fool you into thinking any etext with both upper and lower case is an original; all those original Project Gutenberg etexts were also in upper case and were translated or rewritten many times to get them into their current condition. They have been worked on by many people throughout the world. In the course of our searches for Professor Raben and his etext we were never able to determine where copies were or which of a variety of editions he may have used as a source. We did get a little information here and there, but even after we received a copy of the etext we were unwilling to release it without first determining that it was in fact Public Domain and finding Raben to verify this and get his permission. Interested enough, in a totally unrelated action to our searches for him, the professor subscribed to the Project Gutenberg listserver and we happened, by accident, to notice his name. (We don't really look at every subscription request as the computers usually handle them.) The etext was then properly identified, copyright analyzed, and the current edition prepared. To give you an estimation of the difference in the original and what we have today: the original was probably entered on cards commonly known at the time as "IBM cards" (Do Not Fold, Spindle or Mutilate) and probably took in excess of 100,000 of them. A single card could hold 80 characters (hence 80 characters is an accepted standard for so many computer margins), and the entire original edition we received in all caps was over 800,000 chars in length, including line enumeration, symbols for caps and the punctuation marks, etc., since they were not available keyboard characters at the time (probably the keyboards operated at baud rates of around 113, meaning the typists had to type slowly for the keyboard to keep up). This is the second version of Paradise Lost released by Project Gutenberg. The first was released as our October, 1991 etext. Paradise Lost Book I Of Man's first disobedience, and the fruit Of that forbidden tree whose mortal taste Brought death into the World, and all our woe, With loss of Eden, till one greater Man Restore us, and regain the blissful seat, Sing, Heavenly Muse, that, on the secret top Of Oreb, or of Sinai, didst inspire That shepherd who first taught the chosen seed In the beginning how the heavens and earth Rose out of Chaos: or, if Sion hill Delight thee more, and Siloa's brook that flowed Fast by the oracle of God, I thence Invoke thy aid to my adventurous song, That with no middle flight intends to soar Above th' Aonian mount, while it pursues Things unattempted yet in prose or rhyme. And chiefly thou, O Spirit, that dost prefer Before all temples th' upright heart and pure, Instruct me, for thou know'st; thou from the first Wast present, and, with mighty wings outspread, Dove-like sat'st brooding on the vast Abyss, And mad'st it pregnant: what in me is dark Illumine, what is low raise and support; That, to the height of this great argument, I may assert Eternal Providence, And justify the ways of God to men. Say first--for Heaven hides nothing from thy view, Nor the deep tract of Hell--say first what cause Moved our grand parents, in that happy state, Favoured of Heaven so highly, to fall off From their Creator, and transgress his will For one restraint, lords of the World besides. Who first seduced them to that foul revolt? Th' infernal Serpent; he it was whose guile, Stirred up with envy and revenge, deceived The mother of mankind, what time his pride Had cast him out from Heaven, with all his host Of rebel Angels, by whose aid, aspiring To set himself in glory above his peers, He trusted to have equalled the Most High, If he opposed, and with ambitious aim Against the throne and monarchy of God, Raised impious war in Heaven and battle proud, With vain attempt. Him the Almighty Power Hurled headlong flaming from th' ethereal sky, With hideous ruin and combustion, down To bottomless perdition, there to dwell In adamantine chains and penal fire, Who durst defy th' Omnipotent to arms. Nine times the space that measures day and night To mortal men, he, with his horrid crew, Lay vanquished, rolling in the fiery gulf, Confounded, though immortal. But his doom Reserved him to more wrath; for now the thought Both of lost happiness and lasting pain Torments him: round he throws his baleful eyes, That witnessed huge affliction and dismay, Mixed with obdurate pride and steadfast hate. At once, as far as Angels ken, he views The dismal situation waste and wild. A dungeon horrible, on all sides round, As one great furnace flamed; yet from those flames No light; but rather darkness visible Served only to discover sights of woe, Regions of sorrow, doleful shades, where peace And rest can never dwell, hope never comes That comes to all, but torture without end Still urges, and a fiery deluge, fed With ever-burning sulphur unconsumed. Such place Eternal Justice has prepared For those rebellious; here their prison ordained In utter darkness, and their portion set, As far removed from God and light of Heaven As from the centre thrice to th' utmost pole. Oh how unlike the place from whence they fell! There the companions of his fall, o'erwhelmed With floods and whirlwinds of tempestuous fire, He soon discerns; and, weltering by his side, One next himself in power, and next in crime, Long after known in Palestine, and named Beelzebub. To whom th' Arch-Enemy, And thence in Heaven called Satan, with bold words Breaking the horrid silence, thus began:-- "If thou beest he--but O how fallen! how changed From him who, in the happy realms of light Clothed with transcendent brightness, didst outshine Myriads, though bright!--if he whom mutual league, United thoughts and counsels, equal hope And hazard in the glorious enterprise Joined with me once, now misery hath joined In equal ruin; into what pit thou seest From what height fallen: so much the stronger proved He with his thunder; and till then who knew The force of those dire arms? Yet not for those, Nor what the potent Victor in his rage Can else inflict, do I repent, or change, Though changed in outward lustre, that fixed mind, And high disdain from sense of injured merit, That with the Mightiest raised me to contend, And to the fierce contentions brought along Innumerable force of Spirits armed, That durst dislike his reign, and, me preferring, His utmost power with adverse power opposed In dubious battle on the plains of Heaven, And shook his throne. What though the field be lost? All is not lost--the unconquerable will, And study of revenge, immortal hate, And courage never to submit or yield: And what is else not to be overcome? That glory never shall his wrath or might Extort from me. To bow and sue for grace With suppliant knee, and deify his power Who, from the terror of this arm, so late Doubted his empire--that were low indeed; That were an ignominy and shame beneath This downfall; since, by fate, the strength of Gods, And this empyreal sybstance, cannot fail; Since, through experience of this great event, In arms not worse, in foresight much advanced, We may with more successful hope resolve To wage by force or guile eternal war, Irreconcilable to our grand Foe, Who now triumphs, and in th' excess of joy Sole reigning holds the tyranny of Heaven." So spake th' apostate Angel, though in pain, Vaunting aloud, but racked with deep despair; And him thus answered soon his bold compeer:-- "O Prince, O Chief of many throned Powers That led th' embattled Seraphim to war Under thy conduct, and, in dreadful deeds Fearless, endangered Heaven's perpetual King, And put to proof his high supremacy, Whether upheld by strength, or chance, or fate, Too well I see and rue the dire event That, with sad overthrow and foul defeat, Hath lost us Heaven, and all this mighty host In horrible destruction laid thus low, As far as Gods and heavenly Essences Can perish: for the mind and spirit remains Invincible, and vigour soon returns, Though all our glory extinct, and happy state Here swallowed up in endless misery. But what if he our Conqueror (whom I now Of force believe almighty, since no less Than such could have o'erpowered such force as ours) Have left us this our spirit and strength entire, Strongly to suffer and support our pains, That we may so suffice his vengeful ire, Or do him mightier service as his thralls By right of war, whate'er his business be, Here in the heart of Hell to work in fire, Or do his errands in the gloomy Deep? What can it the avail though yet we feel Strength undiminished, or eternal being To undergo eternal punishment?" Whereto with speedy words th' Arch-Fiend replied:-- "Fallen Cherub, to be weak is miserable, Doing or suffering: but of this be sure-- To do aught good never will be our task, But ever to do ill our sole delight, As being the contrary to his high will Whom we resist. If then his providence Out of our evil seek to bring forth good, Our labour must be to pervert that end, And out of good still to find means of evil; Which ofttimes may succeed so as perhaps Shall grieve him, if I fail not, and disturb His inmost counsels from their destined aim. But see! the angry Victor hath recalled His ministers of vengeance and pursuit Back to the gates of Heaven: the sulphurous hail, Shot after us in storm, o'erblown hath laid The fiery surge that from the precipice Of Heaven received us falling; and the thunder, Winged with red lightning and impetuous rage, Perhaps hath spent his shafts, and ceases now To bellow through the vast and boundless Deep. Let us not slip th' occasion, whether scorn Or satiate fury yield it from our Foe. Seest thou yon dreary plain, forlorn and wild, The seat of desolation, void of light, Save what the glimmering of these livid flames Casts pale and dreadful? Thither let us tend From off the tossing of these fiery waves; There rest, if any rest can harbour there; And, re-assembling our afflicted powers, Consult how we may henceforth most offend Our enemy, our own loss how repair, How overcome this dire calamity, What reinforcement we may gain from hope, If not, what resolution from despair." Thus Satan, talking to his nearest mate, With head uplift above the wave, and eyes That sparkling blazed; his other parts besides Prone on the flood, extended long and large, Lay floating many a rood, in bulk as huge As whom the fables name of monstrous size, Titanian or Earth-born, that warred on Jove, Briareos or Typhon, whom the den By ancient Tarsus held, or that sea-beast Leviathan, which God of all his works Created hugest that swim th' ocean-stream. Him, haply slumbering on the Norway foam, The pilot of some small night-foundered skiff, Deeming some island, oft, as seamen tell, With fixed anchor in his scaly rind, Moors by his side under the lee, while night Invests the sea, and wished morn delays. So stretched out huge in length the Arch-fiend lay, Chained on the burning lake; nor ever thence Had risen, or heaved his head, but that the will And high permission of all-ruling Heaven Left him at large to his own dark designs, That with reiterated crimes he might Heap on himself damnation, while he sought Evil to others, and enraged might see How all his malice served but to bring forth Infinite goodness, grace, and mercy, shewn On Man by him seduced, but on himself Treble confusion, wrath, and vengeance poured. Forthwith upright he rears from off the pool His mighty stature; on each hand the flames Driven backward slope their pointing spires, and,rolled In billows, leave i' th' midst a horrid vale. Then with expanded wings he steers his flight Aloft, incumbent on the dusky air, That felt unusual weight; till on dry land He lights--if it were land that ever burned With solid, as the lake with liquid fire, And such appeared in hue as when the force Of subterranean wind transprots a hill Torn from Pelorus, or the shattered side Of thundering Etna, whose combustible And fuelled entrails, thence conceiving fire, Sublimed with mineral fury, aid the winds, And leave a singed bottom all involved With stench and smoke. Such resting found the sole Of unblest feet. Him followed his next mate; Both glorying to have scaped the Stygian flood As gods, and by their own recovered strength, Not by the sufferance of supernal Power. "Is this the region, this the soil, the clime," Said then the lost Archangel, "this the seat That we must change for Heaven?--this mournful gloom For that celestial light? Be it so, since he Who now is sovereign can dispose and bid What shall be right: farthest from him is best Whom reason hath equalled, force hath made supreme Above his equals. Farewell, happy fields, Where joy for ever dwells! Hail, horrors! hail, Infernal world! and thou, profoundest Hell, Receive thy new possessor--one who brings A mind not to be changed by place or time. The mind is its own place, and in itself Can make a Heaven of Hell, a Hell of Heaven. What matter where, if I be still the same, And what I should be, all but less than he Whom thunder hath made greater? Here at least We shall be free; th' Almighty hath not built Here for his envy, will not drive us hence: Here we may reigh secure; and, in my choice, To reign is worth ambition, though in Hell: Better to reign in Hell than serve in Heaven. But wherefore let we then our faithful friends, Th' associates and co-partners of our loss, Lie thus astonished on th' oblivious pool, And call them not to share with us their part In this unhappy mansion, or once more With rallied arms to try what may be yet Regained in Heaven, or what more lost in Hell?" So Satan spake; and him Beelzebub Thus answered:--"Leader of those armies bright Which, but th' Omnipotent, none could have foiled! If once they hear that voice, their liveliest pledge Of hope in fears and dangers--heard so oft In worst extremes, and on the perilous edge Of battle, when it raged, in all assaults Their surest signal--they will soon resume New courage and revive, though now they lie Grovelling and prostrate on yon lake of fire, As we erewhile, astounded and amazed; No wonder, fallen such a pernicious height!" He scare had ceased when the superior Fiend Was moving toward the shore; his ponderous shield, Ethereal temper, massy, large, and round, Behind him cast. The broad circumference Hung on his shoulders like the moon, whose orb Through optic glass the Tuscan artist views At evening, from the top of Fesole, Or in Valdarno, to descry new lands, Rivers, or mountains, in her spotty globe. His spear--to equal which the tallest pine Hewn on Norwegian hills, to be the mast Of some great ammiral, were but a wand-- He walked with, to support uneasy steps Over the burning marl, not like those steps On Heaven's azure; and the torrid clime Smote on him sore besides, vaulted with fire. Nathless he so endured, till on the beach Of that inflamed sea he stood, and called His legions--Angel Forms, who lay entranced Thick as autumnal leaves that strow the brooks In Vallombrosa, where th' Etrurian shades High over-arched embower; or scattered sedge Afloat, when with fierce winds Orion armed Hath vexed the Red-Sea coast, whose waves o'erthrew Busiris and his Memphian chivalry, While with perfidious hatred they pursued The sojourners of Goshen, who beheld From the safe shore their floating carcases And broken chariot-wheels. So thick bestrown, Abject and lost, lay these, covering the flood, Under amazement of their hideous change. He called so loud that all the hollow deep Of Hell resounded:--"Princes, Potentates, Warriors, the Flower of Heaven--once yours; now lost, If such astonishment as this can seize Eternal Spirits! Or have ye chosen this place After the toil of battle to repose Your wearied virtue, for the ease you find To slumber here, as in the vales of Heaven? Or in this abject posture have ye sworn To adore the Conqueror, who now beholds Cherub and Seraph rolling in the flood With scattered arms and ensigns, till anon His swift pursuers from Heaven-gates discern Th' advantage, and, descending, tread us down Thus drooping, or with linked thunderbolts Transfix us to the bottom of this gulf? Awake, arise, or be for ever fallen!" They heard, and were abashed, and up they sprung Upon the wing, as when men wont to watch On duty, sleeping found by whom they dread, Rouse and bestir themselves ere well awake. Nor did they not perceive the evil plight In which they were, or the fierce pains not feel; Yet to their General's voice they soon obeyed Innumerable. As when the potent rod Of Amram's son, in Egypt's evil day, Waved round the coast, up-called a pitchy cloud Of locusts, warping on the eastern wind, That o'er the realm of impious Pharaoh hung Like Night, and darkened all the land of Nile; So numberless were those bad Angels seen Hovering on wing under the cope of Hell, 'Twixt upper, nether, and surrounding fires; Till, as a signal given, th' uplifted spear Of their great Sultan waving to direct Their course, in even balance down they light On the firm brimstone, and fill all the plain: A multitude like which the populous North Poured never from her frozen loins to pass Rhene or the Danaw, when her barbarous sons Came like a deluge on the South, and spread Beneath Gibraltar to the Libyan sands. Forthwith, form every squadron and each band, The heads and leaders thither haste where stood Their great Commander--godlike Shapes, and Forms Excelling human; princely Dignities; And Powers that erst in Heaven sat on thrones, Though on their names in Heavenly records now Be no memorial, blotted out and rased By their rebellion from the Books of Life. Nor had they yet among the sons of Eve Got them new names, till, wandering o'er the earth, Through God's high sufferance for the trial of man, By falsities and lies the greatest part Of mankind they corrupted to forsake God their Creator, and th' invisible Glory of him that made them to transform Oft to the image of a brute, adorned With gay religions full of pomp and gold, And devils to adore for deities: Then were they known to men by various names, And various idols through the heathen world. Say, Muse, their names then known, who first, who last, Roused from the slumber on that fiery couch, At their great Emperor's call, as next in worth Came singly where he stood on the bare strand, While the promiscuous crowd stood yet aloof? The chief were those who, from the pit of Hell Roaming to seek their prey on Earth, durst fix Their seats, long after, next the seat of God, Their altars by his altar, gods adored Among the nations round, and durst abide Jehovah thundering out of Sion, throned Between the Cherubim; yea, often placed Within his sanctuary itself their shrines, Abominations; and with cursed things His holy rites and solemn feasts profaned, And with their darkness durst affront his light. First, Moloch, horrid king, besmeared with blood Of human sacrifice, and parents' tears; Though, for the noise of drums and timbrels loud, Their children's cries unheard that passed through fire To his grim idol. Him the Ammonite Worshiped in Rabba and her watery plain, In Argob and in Basan, to the stream Of utmost Arnon. Nor content with such Audacious neighbourhood, the wisest heart Of Solomon he led by fraoud to build His temple right against the temple of God On that opprobrious hill, and made his grove The pleasant valley of Hinnom, Tophet thence And black Gehenna called, the type of Hell. Next Chemos, th' obscene dread of Moab's sons, From Aroar to Nebo and the wild Of southmost Abarim; in Hesebon And Horonaim, Seon's real, beyond The flowery dale of Sibma clad with vines, And Eleale to th' Asphaltic Pool: Peor his other name, when he enticed Israel in Sittim, on their march from Nile, To do him wanton rites, which cost them woe. Yet thence his lustful orgies he enlarged Even to that hill of scandal, by the grove Of Moloch homicide, lust hard by hate, Till good Josiah drove them thence to Hell. With these came they who, from the bordering flood Of old Euphrates to the brook that parts Egypt from Syrian ground, had general names Of Baalim and Ashtaroth--those male, These feminine. For Spirits, when they please, Can either sex assume, or both; so soft And uncompounded is their essence pure, Not tried or manacled with joint or limb, Nor founded on the brittle strength of bones, Like cumbrous flesh; but, in what shape they choose, Dilated or condensed, bright or obscure, Can execute their airy purposes, And works of love or enmity fulfil. For those the race of Israel oft forsook Their Living Strength, and unfrequented left His righteous altar, bowing lowly down To bestial gods; for which their heads as low Bowed down in battle, sunk before the spear Of despicable foes. With these in troop Came Astoreth, whom the Phoenicians called Astarte, queen of heaven, with crescent horns; To whose bright image nigntly by the moon Sidonian virgins paid their vows and songs; In Sion also not unsung, where stood Her temple on th' offensive mountain, built By that uxorious king whose heart, though large, Beguiled by fair idolatresses, fell To idols foul. Thammuz came next behind, Whose annual wound in Lebanon allured The Syrian damsels to lament his fate In amorous ditties all a summer's day, While smooth Adonis from his native rock Ran purple to the sea, supposed with blood Of Thammuz yearly wounded: the love-tale Infected Sion's daughters with like heat, Whose wanton passions in the sacred proch Ezekiel saw, when, by the vision led, His eye surveyed the dark idolatries Of alienated Judah. Next came one Who mourned in earnest, when the captive ark Maimed his brute image, head and hands lopt off, In his own temple, on the grunsel-edge, Where he fell flat and shamed his worshippers: Dagon his name, sea-monster,upward man And downward fish; yet had his temple high Reared in Azotus, dreaded through the coast Of Palestine, in Gath and Ascalon, And Accaron and Gaza's frontier bounds. Him followed Rimmon, whose delightful seat Was fair Damascus, on the fertile banks Of Abbana and Pharphar, lucid streams. He also against the house of God was bold: A leper once he lost, and gained a king-- Ahaz, his sottish conqueror, whom he drew God's altar to disparage and displace For one of Syrian mode, whereon to burn His odious offerings, and adore the gods Whom he had vanquished. After these appeared A crew who, under names of old renown-- Osiris, Isis, Orus, and their train-- With monstrous shapes and sorceries abused Fanatic Egypt and her priests to seek Their wandering gods disguised in brutish forms Rather than human. Nor did Israel scape Th' infection, when their borrowed gold composed The calf in Oreb; and the rebel king Doubled that sin in Bethel and in Dan, Likening his Maker to the grazed ox-- Jehovah, who, in one night, when he passed From Egypt marching, equalled with one stroke Both her first-born and all her bleating gods. Belial came last; than whom a Spirit more lewd Fell not from Heaven, or more gross to love Vice for itself. To him no temple stood Or altar smoked; yet who more oft than he In temples and at altars, when the priest Turns atheist, as did Eli's sons, who filled With lust and violence the house of God? In courts and palaces he also reigns, And in luxurious cities, where the noise Of riot ascends above their loftiest towers, And injury and outrage; and, when night Darkens the streets, then wander forth the sons Of Belial, flown with insolence and wine. Witness the streets of Sodom, and that night In Gibeah, when the hospitable door Exposed a matron, to avoid worse rape. These were the prime in order and in might: The rest were long to tell; though far renowned Th' Ionian gods--of Javan's issue held Gods, yet confessed later than Heaven and Earth, Their boasted parents;--Titan, Heaven's first-born, With his enormous brood, and birthright seized By younger Saturn: he from mightier Jove, His own and Rhea's son, like measure found; So Jove usurping reigned. These, first in Crete And Ida known, thence on the snowy top Of cold Olympus ruled the middle air, Their highest heaven; or on the Delphian cliff, Or in Dodona, and through all the bounds Of Doric land; or who with Saturn old Fled over Adria to th' Hesperian fields, And o'er the Celtic roamed the utmost Isles. All these and more came flocking; but with looks Downcast and damp; yet such wherein appeared Obscure some glimpse of joy to have found their Chief Not in despair, to have found themselves not lost In loss itself; which on his countenance cast Like doubtful hue. But he, his wonted pride Soon recollecting, with high words, that bore Semblance of worth, not substance, gently raised Their fainting courage, and dispelled their fears. Then straight commands that, at the warlike sound Of trumpets loud and clarions, be upreared His mighty standard. That proud honour claimed Azazel as his right, a Cherub tall: Who forthwith from the glittering staff unfurled Th' imperial ensign; which, full high advanced, Shone like a meteor streaming to the wind, With gems and golden lustre rich emblazed, Seraphic arms and trophies; all the while Sonorous metal blowing martial sounds: At which the universal host up-sent A shout that tore Hell's concave, and beyond Frighted the reign of Chaos and old Night. All in a moment through the gloom were seen Ten thousand banners rise into the air, With orient colours waving: with them rose A forest huge of spears; and thronging helms Appeared, and serried shields in thick array Of depth immeasurable. Anon they move In perfect phalanx to the Dorian mood Of flutes and soft recorders--such as raised To height of noblest temper heroes old Arming to battle, and instead of rage Deliberate valour breathed, firm, and unmoved With dread of death to flight or foul retreat; Nor wanting power to mitigate and swage With solemn touches troubled thoughts, and chase Anguish and doubt and fear and sorrow and pain From mortal or immortal minds. Thus they, Breathing united force with fixed thought, Moved on in silence to soft pipes that charmed Their painful steps o'er the burnt soil. And now Advanced in view they stand--a horrid front Of dreadful length and dazzling arms, in guise Of warriors old, with ordered spear and shield, Awaiting what command their mighty Chief Had to impose. He through the armed files Darts his experienced eye, and soon traverse The whole battalion views--their order due, Their visages and stature as of gods; Their number last he sums. And now his heart Distends with pride, and, hardening in his strength, Glories: for never, since created Man, Met such embodied force as, named with these, Could merit more than that small infantry Warred on by cranes--though all the giant brood Of Phlegra with th' heroic race were joined That fought at Thebes and Ilium, on each side Mixed with auxiliar gods; and what resounds In fable or romance of Uther's son, Begirt with British and Armoric knights; And all who since, baptized or infidel, Jousted in Aspramont, or Montalban, Damasco, or Marocco, or Trebisond, Or whom Biserta sent from Afric shore When Charlemain with all his peerage fell By Fontarabbia. Thus far these beyond Compare of mortal prowess, yet observed Their dread Commander. He, above the rest In shape and gesture proudly eminent, Stood like a tower. His form had yet not lost All her original brightness, nor appeared Less than Archangel ruined, and th' excess Of glory obscured: as when the sun new-risen Looks through the horizontal misty air Shorn of his beams, or, from behind the moon, In dim eclipse, disastrous twilight sheds On half the nations, and with fear of change Perplexes monarchs. Darkened so, yet shone Above them all th' Archangel: but his face Deep scars of thunder had intrenched, and care Sat on his faded cheek, but under brows Of dauntless courage, and considerate pride Waiting revenge. Cruel his eye, but cast Signs of remorse and passion, to behold The fellows of his crime, the followers rather (Far other once beheld in bliss), condemned For ever now to have their lot in pain-- Millions of Spirits for his fault amerced Of Heaven, and from eteranl splendours flung For his revolt--yet faithful how they stood, Their glory withered; as, when heaven's fire Hath scathed the forest oaks or mountain pines, With singed top their stately growth, though bare, Stands on the blasted heath. He now prepared To speak; whereat their doubled ranks they bend From wing to wing, and half enclose him round With all his peers: attention held them mute. Thrice he assayed, and thrice, in spite of scorn, Tears, such as Angels weep, burst forth: at last Words interwove with sighs found out their way:-- "O myriads of immortal Spirits! O Powers Matchless, but with th' Almighth!--and that strife Was not inglorious, though th' event was dire, As this place testifies, and this dire change, Hateful to utter. But what power of mind, Forseeing or presaging, from the depth Of knowledge past or present, could have feared How such united force of gods, how such As stood like these, could ever know repulse? For who can yet believe, though after loss, That all these puissant legions, whose exile Hath emptied Heaven, shall fail to re-ascend, Self-raised, and repossess their native seat? For me, be witness all the host of Heaven, If counsels different, or danger shunned By me, have lost our hopes. But he who reigns Monarch in Heaven till then as one secure Sat on his throne, upheld by old repute, Consent or custom, and his regal state Put forth at full, but still his strength concealed-- Which tempted our attempt, and wrought our fall. Henceforth his might we know, and know our own, So as not either to provoke, or dread New war provoked: our better part remains To work in close design, by fraud or guile, What force effected not; that he no less At length from us may find, who overcomes By force hath overcome but half his foe. Space may produce new Worlds; whereof so rife There went a fame in Heaven that he ere long Intended to create, and therein plant A generation whom his choice regard Should favour equal to the Sons of Heaven. Thither, if but to pry, shall be perhaps Our first eruption--thither, or elsewhere; For this infernal pit shall never hold Celestial Spirits in bondage, nor th' Abyss Long under darkness cover. But these thoughts Full counsel must mature. Peace is despaired; For who can think submission? War, then, war Open or understood, must be resolved." He spake; and, to confirm his words, outflew Millions of flaming swords, drawn from the thighs Of mighty Cherubim; the sudden blaze Far round illumined Hell. Highly they raged Against the Highest, and fierce with grasped arms Clashed on their sounding shields the din of war, Hurling defiance toward the vault of Heaven. There stood a hill not far, whose grisly top Belched fire and rolling smoke; the rest entire Shone with a glossy scurf--undoubted sign That in his womb was hid metallic ore, The work of sulphur. Thither, winged with speed, A numerous brigade hastened: as when bands Of pioneers, with spade and pickaxe armed, Forerun the royal camp, to trench a field, Or cast a rampart. Mammon led them on-- Mammon, the least erected Spirit that fell From Heaven; for even in Heaven his looks and thoughts Were always downward bent, admiring more The riches of heaven's pavement, trodden gold, Than aught divine or holy else enjoyed In vision beatific. By him first Men also, and by his suggestion taught, Ransacked the centre, and with impious hands Rifled the bowels of their mother Earth For treasures better hid. Soon had his crew Opened into the hill a spacious wound, And digged out ribs of gold. Let none admire That riches grow in Hell; that soil may best Deserve the precious bane. And here let those Who boast in mortal things, and wondering tell Of Babel, and the works of Memphian kings, Learn how their greatest monuments of fame And strength, and art, are easily outdone By Spirits reprobate, and in an hour What in an age they, with incessant toil And hands innumerable, scarce perform. Nigh on the plain, in many cells prepared, That underneath had veins of liquid fire Sluiced from the lake, a second multitude With wondrous art founded the massy ore, Severing each kind, and scummed the bullion-dross. A third as soon had formed within the ground A various mould, and from the boiling cells By strange conveyance filled each hollow nook; As in an organ, from one blast of wind, To many a row of pipes the sound-board breathes. Anon out of the earth a fabric huge Rose like an exhalation, with the sound Of dulcet symphonies and voices sweet-- Built like a temple, where pilasters round Were set, and Doric pillars overlaid With golden architrave; nor did there want Cornice or frieze, with bossy sculptures graven; The roof was fretted gold. Not Babylon Nor great Alcairo such magnificence Equalled in all their glories, to enshrine Belus or Serapis their gods, or seat Their kings, when Egypt with Assyria strove In wealth and luxury. Th' ascending pile Stood fixed her stately height, and straight the doors, Opening their brazen folds, discover, wide Within, her ample spaces o'er the smooth And level pavement: from the arched roof, Pendent by subtle magic, many a row Of starry lamps and blazing cressets, fed With naptha and asphaltus, yielded light As from a sky. The hasty multitude Admiring entered; and the work some praise, And some the architect. His hand was known In Heaven by many a towered structure high, Where sceptred Angels held their residence, And sat as Princes, whom the supreme King Exalted to such power, and gave to rule, Each in his Hierarchy, the Orders bright. Nor was his name unheard or unadored In ancient Greece; and in Ausonian land Men called him Mulciber; and how he fell From Heaven they fabled, thrown by angry Jove Sheer o'er the crystal battlements: from morn To noon he fell, from noon to dewy eve, A summer's day, and with the setting sun Dropt from the zenith, like a falling star, On Lemnos, th' Aegaean isle. Thus they relate, Erring; for he with this rebellious rout Fell long before; nor aught aviled him now To have built in Heaven high towers; nor did he scape By all his engines, but was headlong sent, With his industrious crew, to build in Hell. Meanwhile the winged Heralds, by command Of sovereign power, with awful ceremony And trumpet's sound, throughout the host proclaim A solemn council forthwith to be held At Pandemonium, the high capital Of Satan and his peers. Their summons called From every band and squared regiment By place or choice the worthiest: they anon With hundreds and with thousands trooping came Attended. All access was thronged; the gates And porches wide, but chief the spacious hall (Though like a covered field, where champions bold Wont ride in armed, and at the Soldan's chair Defied the best of Paynim chivalry To mortal combat, or career with lance), Thick swarmed, both on the ground and in the air, Brushed with the hiss of rustling wings. As bees In spring-time, when the Sun with Taurus rides. Pour forth their populous youth about the hive In clusters; they among fresh dews and flowers Fly to and fro, or on the smoothed plank, The suburb of their straw-built citadel, New rubbed with balm, expatiate, and confer Their state-affairs: so thick the airy crowd Swarmed and were straitened; till, the signal given, Behold a wonder! They but now who seemed In bigness to surpass Earth's giant sons, Now less than smallest dwarfs, in narrow room Throng numberless--like that pygmean race Beyond the Indian mount; or faery elves, Whose midnight revels, by a forest-side Or fountain, some belated peasant sees, Or dreams he sees, while overhead the Moon Sits arbitress, and nearer to the Earth Wheels her pale course: they, on their mirth and dance Intent, with jocund music charm his ear; At once with joy and fear his heart rebounds. Thus incorporeal Spirits to smallest forms Reduced their shapes immense, and were at large, Though without number still, amidst the hall Of that infernal court. But far within, And in their own dimensions like themselves, The great Seraphic Lords and Cherubim In close recess and secret conclave sat, A thousand demi-gods on golden seats, Frequent and full. After short silence then, And summons read, the great consult began. Book II High on a throne of royal state, which far Outshone the wealth or Ormus and of Ind, Or where the gorgeous East with richest hand Showers on her kings barbaric pearl and gold, Satan exalted sat, by merit raised To that bad eminence; and, from despair Thus high uplifted beyond hope, aspires Beyond thus high, insatiate to pursue Vain war with Heaven; and, by success untaught, His proud imaginations thus displayed:-- "Powers and Dominions, Deities of Heaven!-- For, since no deep within her gulf can hold Immortal vigour, though oppressed and fallen, I give not Heaven for lost: from this descent Celestial Virtues rising will appear More glorious and more dread than from no fall, And trust themselves to fear no second fate!-- Me though just right, and the fixed laws of Heaven, Did first create your leader--next, free choice With what besides in council or in fight Hath been achieved of merit--yet this loss, Thus far at least recovered, hath much more Established in a safe, unenvied throne, Yielded with full consent. The happier state In Heaven, which follows dignity, might draw Envy from each inferior; but who here Will envy whom the highest place exposes Foremost to stand against the Thunderer's aim Your bulwark, and condemns to greatest share Of endless pain? Where there is, then, no good For which to strive, no strife can grow up there From faction: for none sure will claim in Hell Precedence; none whose portion is so small Of present pain that with ambitious mind Will covet more! With this advantage, then, To union, and firm faith, and firm accord, More than can be in Heaven, we now return To claim our just inheritance of old, Surer to prosper than prosperity Could have assured us; and by what best way, Whether of open war or covert guile, We now debate. Who can advise may speak." He ceased; and next him Moloch, sceptred king, Stood up--the strongest and the fiercest Spirit That fought in Heaven, now fiercer by despair. His trust was with th' Eternal to be deemed Equal in strength, and rather than be less Cared not to be at all; with that care lost Went all his fear: of God, or Hell, or worse, He recked not, and these words thereafter spake:-- "My sentence is for open war. Of wiles, More unexpert, I boast not: them let those Contrive who need, or when they need; not now. For, while they sit contriving, shall the rest-- Millions that stand in arms, and longing wait The signal to ascend--sit lingering here, Heaven's fugitives, and for their dwelling-place Accept this dark opprobrious den of shame, The prison of his ryranny who reigns By our delay? No! let us rather choose, Armed with Hell-flames and fury, all at once O'er Heaven's high towers to force resistless way, Turning our tortures into horrid arms Against the Torturer; when, to meet the noise Of his almighty engine, he shall hear Infernal thunder, and, for lightning, see Black fire and horror shot with equal rage Among his Angels, and his throne itself Mixed with Tartarean sulphur and strange fire, His own invented torments. But perhaps The way seems difficult, and steep to scale With upright wing against a higher foe! Let such bethink them, if the sleepy drench Of that forgetful lake benumb not still, That in our porper motion we ascend Up to our native seat; descent and fall To us is adverse. Who but felt of late, When the fierce foe hung on our broken rear Insulting, and pursued us through the Deep, With what compulsion and laborious flight We sunk thus low? Th' ascent is easy, then; Th' event is feared! Should we again provoke Our stronger, some worse way his wrath may find To our destruction, if there be in Hell Fear to be worse destroyed! What can be worse Than to dwell here, driven out from bliss, condemned In this abhorred deep to utter woe! Where pain of unextinguishable fire Must exercise us without hope of end The vassals of his anger, when the scourge Inexorably, and the torturing hour, Calls us to penance? More destroyed than thus, We should be quite abolished, and expire. What fear we then? what doubt we to incense His utmost ire? which, to the height enraged, Will either quite consume us, and reduce To nothing this essential--happier far Than miserable to have eternal being!-- Or, if our substance be indeed divine, And cannot cease to be, we are at worst On this side nothing; and by proof we feel Our power sufficient to disturb his Heaven, And with perpetual inroads to alarm, Though inaccessible, his fatal throne: Which, if not victory, is yet revenge." He ended frowning, and his look denounced Desperate revenge, and battle dangerous To less than gods. On th' other side up rose Belial, in act more graceful and humane. A fairer person lost not Heaven; he seemed For dignity composed, and high exploit. But all was false and hollow; though his tongue Dropped manna, and could make the worse appear The better reason, to perplex and dash Maturest counsels: for his thoughts were low-- To vice industrious, but to nobler deeds Timorous and slothful. Yet he pleased the ear, And with persuasive accent thus began:-- "I should be much for open war, O Peers, As not behind in hate, if what was urged Main reason to persuade immediate war Did not dissuade me most, and seem to cast Ominous conjecture on the whole success; When he who most excels in fact of arms, In what he counsels and in what excels Mistrustful, grounds his courage on despair And utter dissolution, as the scope Of all his aim, after some dire revenge. First, what revenge? The towers of Heaven are filled With armed watch, that render all access Impregnable: oft on the bodering Deep Encamp their legions, or with obscure wing Scout far and wide into the realm of Night, Scorning surprise. Or, could we break our way By force, and at our heels all Hell should rise With blackest insurrection to confound Heaven's purest light, yet our great Enemy, All incorruptible, would on his throne Sit unpolluted, and th' ethereal mould, Incapable of stain, would soon expel Her mischief, and purge off the baser fire, Victorious. Thus repulsed, our final hope Is flat despair: we must exasperate Th' Almighty Victor to spend all his rage; And that must end us; that must be our cure-- To be no more. Sad cure! for who would lose, Though full of pain, this intellectual being, Those thoughts that wander through eternity, To perish rather, swallowed up and lost In the wide womb of uncreated Night, Devoid of sense and motion? And who knows, Let this be good, whether our angry Foe Can give it, or will ever? How he can Is doubtful; that he never will is sure. Will he, so wise, let loose at once his ire, Belike through impotence or unaware, To give his enemies their wish, and end Them in his anger whom his anger saves To punish endless? 'Wherefore cease we, then?' Say they who counsel war; 'we are decreed, Reserved, and destined to eternal woe; Whatever doing, what can we suffer more, What can we suffer worse?' Is this, then, worst-- Thus sitting, thus consulting, thus in arms? What when we fled amain, pursued and struck With Heaven's afflicting thunder, and besought The Deep to shelter us? This Hell then seemed A refuge from those wounds. Or when we lay Chained on the burning lake? That sure was worse. What if the breath that kindled those grim fires, Awaked, should blow them into sevenfold rage, And plunge us in the flames; or from above Should intermitted vengeance arm again His red right hand to plague us? What if all Her stores were opened, and this firmament Of Hell should spout her cataracts of fire, Impendent horrors, threatening hideous fall One day upon our heads; while we perhaps, Designing or exhorting glorious war, Caught in a fiery tempest, shall be hurled, Each on his rock transfixed, the sport and prey Or racking whirlwinds, or for ever sunk Under yon boiling ocean, wrapt in chains, There to converse with everlasting groans, Unrespited, unpitied, unreprieved, Ages of hopeless end? This would be worse. War, therefore, open or concealed, alike My voice dissuades; for what can force or guile With him, or who deceive his mind, whose eye Views all things at one view? He from Heaven's height All these our motions vain sees and derides, Not more almighty to resist our might Than wise to frustrate all our plots and wiles. Shall we, then, live thus vile--the race of Heaven Thus trampled, thus expelled, to suffer here Chains and these torments? Better these than worse, By my advice; since fate inevitable Subdues us, and omnipotent decree, The Victor's will. To suffer, as to do, Our strength is equal; nor the law unjust That so ordains. This was at first resolved, If we were wise, against so great a foe Contending, and so doubtful what might fall. I laugh when those who at the spear are bold And venturous, if that fail them, shrink, and fear What yet they know must follow--to endure Exile, or igominy, or bonds, or pain, The sentence of their Conqueror. This is now Our doom; which if we can sustain and bear, Our Supreme Foe in time may much remit His anger, and perhaps, thus far removed, Not mind us not offending, satisfied With what is punished; whence these raging fires Will slacken, if his breath stir not their flames. Our purer essence then will overcome Their noxious vapour; or, inured, not feel; Or, changed at length, and to the place conformed In temper and in nature, will receive Familiar the fierce heat; and, void of pain, This horror will grow mild, this darkness light; Besides what hope the never-ending flight Of future days may bring, what chance, what change Worth waiting--since our present lot appears For happy though but ill, for ill not worst, If we procure not to ourselves more woe." Thus Belial, with words clothed in reason's garb, Counselled ignoble ease and peaceful sloth, Not peace; and after him thus Mammon spake:-- "Either to disenthrone the King of Heaven We war, if war be best, or to regain Our own right lost. Him to unthrone we then May hope, when everlasting Fate shall yield To fickle Chance, and Chaos judge the strife. The former, vain to hope, argues as vain The latter; for what place can be for us Within Heaven's bound, unless Heaven's Lord supreme We overpower? Suppose he should relent And publish grace to all, on promise made Of new subjection; with what eyes could we Stand in his presence humble, and receive Strict laws imposed, to celebrate his throne With warbled hyms, and to his Godhead sing Forced hallelujahs, while he lordly sits Our envied sovereign, and his altar breathes Ambrosial odours and ambrosial flowers, Our servile offerings? This must be our task In Heaven, this our delight. How wearisome Eternity so spent in worship paid To whom we hate! Let us not then pursue, By force impossible, by leave obtained Unacceptable, though in Heaven, our state Of splendid vassalage; but rather seek Our own good from ourselves, and from our own Live to ourselves, though in this vast recess, Free and to none accountable, preferring Hard liberty before the easy yoke Of servile pomp. Our greatness will appear Then most conspicuous when great things of small, Useful of hurtful, prosperous of adverse, We can create, and in what place soe'er Thrive under evil, and work ease out of pain Through labour and endurance. This deep world Of darkness do we dread? How oft amidst Thick clouds and dark doth Heaven's all-ruling Sire Choose to reside, his glory unobscured, And with the majesty of darkness round Covers his throne, from whence deep thunders roar. Mustering their rage, and Heaven resembles Hell! As he our darkness, cannot we his light Imitate when we please? This desert soil Wants not her hidden lustre, gems and gold; Nor want we skill or art from whence to raise Magnificence; and what can Heaven show more? Our torments also may, in length of time, Become our elements, these piercing fires As soft as now severe, our temper changed Into their temper; which must needs remove The sensible of pain. All things invite To peaceful counsels, and the settled state Of order, how in safety best we may Compose our present evils, with regard Of what we are and where, dismissing quite All thoughts of war. Ye have what I advise." He scarce had finished, when such murmur filled Th' assembly as when hollow rocks retain The sound of blustering winds, which all night long Had roused the sea, now with hoarse cadence lull Seafaring men o'erwatched, whose bark by chance Or pinnace, anchors in a craggy bay After the tempest. Such applause was heard As Mammon ended, and his sentence pleased, Advising peace: for such another field They dreaded worse than Hell; so much the fear Of thunder and the sword of Michael Wrought still within them; and no less desire To found this nether empire, which might rise, By policy and long process of time, In emulation opposite to Heaven. Which when Beelzebub perceived--than whom, Satan except, none higher sat--with grave Aspect he rose, and in his rising seemed A pillar of state. Deep on his front engraven Deliberation sat, and public care; And princely counsel in his face yet shone, Majestic, though in ruin. Sage he stood With Atlantean shoulders, fit to bear The weight of mightiest monarchies; his look Drew audience and attention still as night Or summer's noontide air, while thus he spake:-- "Thrones and Imperial Powers, Offspring of Heaven, Ethereal Virtues! or these titles now Must we renounce, and, changing style, be called Princes of Hell? for so the popular vote Inclines--here to continue, and build up here A growing empire; doubtless! while we dream, And know not that the King of Heaven hath doomed This place our dungeon, not our safe retreat Beyond his potent arm, to live exempt From Heaven's high jurisdiction, in new league Banded against his throne, but to remain In strictest bondage, though thus far removed, Under th' inevitable curb, reserved His captive multitude. For he, to be sure, In height or depth, still first and last will reign Sole king, and of his kingdom lose no part By our revolt, but over Hell extend His empire, and with iron sceptre rule Us here, as with his golden those in Heaven. What sit we then projecting peace and war? War hath determined us and foiled with loss Irreparable; terms of peace yet none Vouchsafed or sought; for what peace will be given To us enslaved, but custody severe, And stripes and arbitrary punishment Inflicted? and what peace can we return, But, to our power, hostility and hate, Untamed reluctance, and revenge, though slow, Yet ever plotting how the Conqueror least May reap his conquest, and may least rejoice In doing what we most in suffering feel? Nor will occasion want, nor shall we need With dangerous expedition to invade Heaven, whose high walls fear no assault or siege, Or ambush from the Deep. What if we find Some easier enterprise? There is a place (If ancient and prophetic fame in Heaven Err not)--another World, the happy seat Of some new race, called Man, about this time To be created like to us, though less In power and excellence, but favoured more Of him who rules above; so was his will Pronounced among the Gods, and by an oath That shook Heaven's whole circumference confirmed. Thither let us bend all our thoughts, to learn What creatures there inhabit, of what mould Or substance, how endued, and what their power And where their weakness: how attempted best, By force of subtlety. Though Heaven be shut, And Heaven's high Arbitrator sit secure In his own strength, this place may lie exposed, The utmost border of his kingdom, left To their defence who hold it: here, perhaps, Some advantageous act may be achieved By sudden onset--either with Hell-fire To waste his whole creation, or possess All as our own, and drive, as we were driven, The puny habitants; or, if not drive, Seduce them to our party, that their God May prove their foe, and with repenting hand Abolish his own works. This would surpass Common revenge, and interrupt his joy In our confusion, and our joy upraise In his disturbance; when his darling sons, Hurled headlong to partake with us, shall curse Their frail original, and faded bliss-- Faded so soon! Advise if this be worth Attempting, or to sit in darkness here Hatching vain empires." Thus beelzebub Pleaded his devilish counsel--first devised By Satan, and in part proposed: for whence, But from the author of all ill, could spring So deep a malice, to confound the race Of mankind in one root, and Earth with Hell To mingle and involve, done all to spite The great Creator? But their spite still serves His glory to augment. The bold design Pleased highly those infernal States, and joy Sparkled in all their eyes: with full assent They vote: whereat his speech he thus renews:-- "Well have ye judged, well ended long debate, Synod of Gods, and, like to what ye are, Great things resolved, which from the lowest deep Will once more lift us up, in spite of fate, Nearer our ancient seat--perhaps in view Of those bright confines, whence, with neighbouring arms, And opportune excursion, we may chance Re-enter Heaven; or else in some mild zone Dwell, not unvisited of Heaven's fair light, Secure, and at the brightening orient beam Purge off this gloom: the soft delicious air, To heal the scar of these corrosive fires, Shall breathe her balm. But, first, whom shall we send In search of this new World? whom shall we find Sufficient? who shall tempt with wandering feet The dark, unbottomed, infinite Abyss, And through the palpable obscure find out His uncouth way, or spread his airy flight, Upborne with indefatigable wings Over the vast abrupt, ere he arrive The happy Isle? What strength, what art, can then Suffice, or what evasion bear him safe, Through the strict senteries and stations thick Of Angels watching round? Here he had need All circumspection: and we now no less Choice in our suffrage; for on whom we send The weight of all, and our last hope, relies." This said, he sat; and expectation held His look suspense, awaiting who appeared To second, or oppose, or undertake The perilous attempt. But all sat mute, Pondering the danger with deep thoughts; and each In other's countenance read his own dismay, Astonished. None among the choice and prime Of those Heaven-warring champions could be found So hardy as to proffer or accept, Alone, the dreadful voyage; till, at last, Satan, whom now transcendent glory raised Above his fellows, with monarchal pride Conscious of highest worth, unmoved thus spake:-- "O Progeny of Heaven! Empyreal Thrones! With reason hath deep silence and demur Seized us, though undismayed. Long is the way And hard, that out of Hell leads up to light. Our prison strong, this huge convex of fire, Outrageous to devour, immures us round Ninefold; and gates of burning adamant, Barred over us, prohibit all egress. These passed, if any pass, the void profound Of unessential Night receives him next, Wide-gaping, and with utter loss of being Threatens him, plunged in that abortive gulf. If thence he scape, into whatever world, Or unknown region, what remains him less Than unknown dangers, and as hard escape? But I should ill become this throne, O Peers, And this imperial sovereignty, adorned With splendour, armed with power, if aught proposed And judged of public moment in the shape Of difficulty or danger, could deter Me from attempting. Wherefore do I assume These royalties, and not refuse to reign, Refusing to accept as great a share Of hazard as of honour, due alike To him who reigns, and so much to him due Of hazard more as he above the rest High honoured sits? Go, therefore, mighty Powers, Terror of Heaven, though fallen; intend at home, While here shall be our home, what best may ease The present misery, and render Hell More tolerable; if there be cure or charm To respite, or deceive, or slack the pain Of this ill mansion: intermit no watch Against a wakeful foe, while I abroad Through all the coasts of dark destruction seek Deliverance for us all. This enterprise None shall partake with me." Thus saying, rose The Monarch, and prevented all reply; Prudent lest, from his resolution raised, Others among the chief might offer now, Certain to be refused, what erst they feared, And, so refused, might in opinion stand His rivals, winning cheap the high repute Which he through hazard huge must earn. But they Dreaded not more th' adventure than his voice Forbidding; and at once with him they rose. Their rising all at once was as the sound Of thunder heard remote. Towards him they bend With awful reverence prone, and as a God Extol him equal to the Highest in Heaven. Nor failed they to express how much they praised That for the general safety he despised His own: for neither do the Spirits damned Lose all their virtue; lest bad men should boast Their specious deeds on earth, which glory excites, Or close ambition varnished o'er with zeal. Thus they their doubtful consultations dark Ended, rejoicing in their matchless Chief: As, when from mountain-tops the dusky clouds Ascending, while the north wind sleeps, o'erspread Heaven's cheerful face, the louring element Scowls o'er the darkened landscape snow or shower, If chance the radiant sun, with farewell sweet, Extend his evening beam, the fields revive, The birds their notes renew, and bleating herds Attest their joy, that hill and valley rings. O shame to men! Devil with devil damned Firm concord holds; men only disagree Of creatures rational, though under hope Of heavenly grace, and, God proclaiming peace, Yet live in hatred, enmity, and strife Among themselves, and levy cruel wars Wasting the earth, each other to destroy: As if (which might induce us to accord) Man had not hellish foes enow besides, That day and night for his destruction wait! The Stygian council thus dissolved; and forth In order came the grand infernal Peers: Midst came their mighty Paramount, and seemed Alone th' antagonist of Heaven, nor less Than Hell's dread Emperor, with pomp supreme, And god-like imitated state: him round A globe of fiery Seraphim enclosed With bright emblazonry, and horrent arms. Then of their session ended they bid cry With trumpet's regal sound the great result: Toward the four winds four speedy Cherubim Put to their mouths the sounding alchemy, By herald's voice explained; the hollow Abyss Heard far adn wide, and all the host of Hell With deafening shout returned them loud acclaim. Thence more at ease their minds, and somewhat raised By false presumptuous hope, the ranged Powers Disband; and, wandering, each his several way Pursues, as inclination or sad choice Leads him perplexed, where he may likeliest find Truce to his restless thoughts, and entertain The irksome hours, till his great Chief return. Part on the plain, or in the air sublime, Upon the wing or in swift race contend, As at th' Olympian games or Pythian fields; Part curb their fiery steeds, or shun the goal With rapid wheels, or fronted brigades form: As when, to warn proud cities, war appears Waged in the troubled sky, and armies rush To battle in the clouds; before each van Prick forth the airy knights, and couch their spears, Till thickest legions close; with feats of arms From either end of heaven the welkin burns. Others, with vast Typhoean rage, more fell, Rend up both rocks and hills, and ride the air In whirlwind; Hell scarce holds the wild uproar:-- As when Alcides, from Oechalia crowned With conquest, felt th' envenomed robe, and tore Through pain up by the roots Thessalian pines, And Lichas from the top of Oeta threw Into th' Euboic sea. Others, more mild, Retreated in a silent valley, sing With notes angelical to many a harp Their own heroic deeds, and hapless fall By doom of battle, and complain that Fate Free Virtue should enthrall to Force or Chance. Their song was partial; but the harmony (What could it less when Spirits immortal sing?) Suspended Hell, and took with ravishment The thronging audience. In discourse more sweet (For Eloquence the Soul, Song charms the Sense) Others apart sat on a hill retired, In thoughts more elevate, and reasoned high Of Providence, Foreknowledge, Will, and Fate-- Fixed fate, free will, foreknowledge absolute, And found no end, in wandering mazes lost. Of good and evil much they argued then, Of happiness and final misery, Passion and apathy, and glory and shame: Vain wisdom all, and false philosophy!-- Yet, with a pleasing sorcery, could charm Pain for a while or anguish, and excite Fallacious hope, or arm th' obdured breast With stubborn patience as with triple steel. Another part, in squadrons and gross bands, On bold adventure to discover wide That dismal world, if any clime perhaps Might yield them easier habitation, bend Four ways their flying march, along the banks Of four infernal rivers, that disgorge Into the burning lake their baleful streams-- Abhorred Styx, the flood of deadly hate; Sad Acheron of sorrow, black and deep; Cocytus, named of lamentation loud Heard on the rueful stream; fierce Phlegeton, Whose waves of torrent fire inflame with rage. Far off from these, a slow and silent stream, Lethe, the river of oblivion, rolls Her watery labyrinth, whereof who drinks Forthwith his former state and being forgets-- Forgets both joy and grief, pleasure and pain. Beyond this flood a frozen continent Lies dark and wild, beat with perpetual storms Of whirlwind and dire hail, which on firm land Thaws not, but gathers heap, and ruin seems Of ancient pile; all else deep snow and ice, A gulf profound as that Serbonian bog Betwixt Damiata and Mount Casius old, Where armies whole have sunk: the parching air Burns frore, and cold performs th' effect of fire. Thither, by harpy-footed Furies haled, At certain revolutions all the damned Are brought; and feel by turns the bitter change Of fierce extremes, extremes by change more fierce, From beds of raging fire to starve in ice Their soft ethereal warmth, and there to pine Immovable, infixed, and frozen round Periods of time,--thence hurried back to fire. They ferry over this Lethean sound Both to and fro, their sorrow to augment, And wish and struggle, as they pass, to reach The tempting stream, with one small drop to lose In sweet forgetfulness all pain and woe, All in one moment, and so near the brink; But Fate withstands, and, to oppose th' attempt, Medusa with Gorgonian terror guards The ford, and of itself the water flies All taste of living wight, as once it fled The lip of Tantalus. Thus roving on In confused march forlorn, th' adventurous bands, With shuddering horror pale, and eyes aghast, Viewed first their lamentable lot, and found No rest. Through many a dark and dreary vale They passed, and many a region dolorous, O'er many a frozen, many a fiery alp, Rocks, caves, lakes, fens, bogs, dens, and shades of death-- A universe of death, which God by curse Created evil, for evil only good; Where all life dies, death lives, and Nature breeds, Perverse, all monstrous, all prodigious things, Obominable, inutterable, and worse Than fables yet have feigned or fear conceived, Gorgons, and Hydras, and Chimeras dire. Meanwhile the Adversary of God and Man, Satan, with thoughts inflamed of highest design, Puts on swift wings, and toward the gates of Hell Explores his solitary flight: sometimes He scours the right hand coast, sometimes the left; Now shaves with level wing the deep, then soars Up to the fiery concave towering high. As when far off at sea a fleet descried Hangs in the clouds, by equinoctial winds Close sailing from Bengala, or the isles Of Ternate and Tidore, whence merchants bring Their spicy drugs; they on the trading flood, Through the wide Ethiopian to the Cape, Ply stemming nightly toward the pole: so seemed Far off the flying Fiend. At last appear Hell-bounds, high reaching to the horrid roof, And thrice threefold the gates; three folds were brass, Three iron, three of adamantine rock, Impenetrable, impaled with circling fire, Yet unconsumed. Before the gates there sat On either side a formidable Shape. The one seemed woman to the waist, and fair, But ended foul in many a scaly fold, Voluminous and vast--a serpent armed With mortal sting. About her middle round A cry of Hell-hounds never-ceasing barked With wide Cerberean mouths full loud, and rung A hideous peal; yet, when they list, would creep, If aught disturbed their noise, into her womb, And kennel there; yet there still barked and howled Within unseen. Far less abhorred than these Vexed Scylla, bathing in the sea that parts Calabria from the hoarse Trinacrian shore; Nor uglier follow the night-hag, when, called In secret, riding through the air she comes, Lured with the smell of infant blood, to dance With Lapland witches, while the labouring moon Eclipses at their charms. The other Shape-- If shape it might be called that shape had none Distinguishable in member, joint, or limb; Or substance might be called that shadow seemed, For each seemed either--black it stood as Night, Fierce as ten Furies, terrible as Hell, And shook a dreadful dart: what seemed his head The likeness of a kingly crown had on. Satan was now at hand, and from his seat The monster moving onward came as fast With horrid strides; Hell trembled as he strode. Th' undaunted Fiend what this might be admired-- Admired, not feared (God and his Son except, Created thing naught valued he nor shunned), And with disdainful look thus first began:-- "Whence and what art thou, execrable Shape, That dar'st, though grim and terrible, advance Thy miscreated front athwart my way To yonder gates? Through them I mean to pass, That be assured, without leave asked of thee. Retire; or taste thy folly, and learn by proof, Hell-born, not to contend with Spirits of Heaven." To whom the Goblin, full of wrath, replied:-- "Art thou that traitor Angel? art thou he, Who first broke peace in Heaven and faith, till then Unbroken, and in proud rebellious arms Drew after him the third part of Heaven's sons, Conjured against the Highest--for which both thou And they, outcast from God, are here condemned To waste eternal days in woe and pain? And reckon'st thou thyself with Spirits of Heaven Hell-doomed, and breath'st defiance here and scorn, Where I reign king, and, to enrage thee more, Thy king and lord? Back to thy punishment, False fugitive; and to thy speed add wings, Lest with a whip of scorpions I pursue Thy lingering, or with one stroke of this dart Strange horror seize thee, and pangs unfelt before." So spake the grisly Terror, and in shape, So speaking and so threatening, grew tenfold, More dreadful and deform. On th' other side, Incensed with indignation, Satan stood Unterrified, and like a comet burned, That fires the length of Ophiuchus huge In th' arctic sky, and from his horrid hair Shakes pestilence and war. Each at the head Levelled his deadly aim; their fatal hands No second stroke intend; and such a frown Each cast at th' other as when two black clouds, With heaven's artillery fraught, came rattling on Over the Caspian,--then stand front to front Hovering a space, till winds the signal blow To join their dark encounter in mid-air. So frowned the mighty combatants that Hell Grew darker at their frown; so matched they stood; For never but once more was wither like To meet so great a foe. And now great deeds Had been achieved, whereof all Hell had rung, Had not the snaky Sorceress, that sat Fast by Hell-gate and kept the fatal key, Risen, and with hideous outcry rushed between. "O father, what intends thy hand," she cried, "Against thy only son? What fury, O son, Possesses thee to bend that mortal dart Against thy father's head? And know'st for whom? For him who sits above, and laughs the while At thee, ordained his drudge to execute Whate'er his wrath, which he calls justice, bids-- His wrath, which one day will destroy ye both!" She spake, and at her words the hellish Pest Forbore: then these to her Satan returned:-- "So strange thy outcry, and thy words so strange Thou interposest, that my sudden hand, Prevented, spares to tell thee yet by deeds What it intends, till first I know of thee What thing thou art, thus double-formed, and why, In this infernal vale first met, thou call'st Me father, and that phantasm call'st my son. I know thee not, nor ever saw till now Sight more detestable than him and thee." T' whom thus the Portress of Hell-gate replied:-- "Hast thou forgot me, then; and do I seem Now in thine eye so foul?--once deemed so fair In Heaven, when at th' assembly, and in sight Of all the Seraphim with thee combined In bold conspiracy against Heaven's King, All on a sudden miserable pain Surprised thee, dim thine eyes and dizzy swum In darkness, while thy head flames thick and fast Threw forth, till on the left side opening wide, Likest to thee in shape and countenance bright, Then shining heavenly fair, a goddess armed, Out of thy head I sprung. Amazement seized All th' host of Heaven; back they recoiled afraid At first, and called me Sin, and for a sign Portentous held me; but, familiar grown, I pleased, and with attractive graces won The most averse--thee chiefly, who, full oft Thyself in me thy perfect image viewing, Becam'st enamoured; and such joy thou took'st With me in secret that my womb conceived A growing burden. Meanwhile war arose, And fields were fought in Heaven: wherein remained (For what could else?) to our Almighty Foe Clear victory; to our part loss and rout Through all the Empyrean. Down they fell, Driven headlong from the pitch of Heaven, down Into this Deep; and in the general fall I also: at which time this powerful key Into my hands was given, with charge to keep These gates for ever shut, which none can pass Without my opening. Pensive here I sat Alone; but long I sat not, till my womb, Pregnant by thee, and now excessive grown, Prodigious motion felt and rueful throes. At last this odious offspring whom thou seest, Thine own begotten, breaking violent way, Tore through my entrails, that, with fear and pain Distorted, all my nether shape thus grew Transformed: but he my inbred enemy Forth issued, brandishing his fatal dart, Made to destroy. I fled, and cried out Death! Hell trembled at the hideous name, and sighed From all her caves, and back resounded Death! I fled; but he pursued (though more, it seems, Inflamed with lust than rage), and, swifter far, Me overtook, his mother, all dismayed, And, in embraces forcible and foul Engendering with me, of that rape begot These yelling monsters, that with ceaseless cry Surround me, as thou saw'st--hourly conceived And hourly born, with sorrow infinite To me; for, when they list, into the womb That bred them they return, and howl, and gnaw My bowels, their repast; then, bursting forth Afresh, with conscious terrors vex me round, That rest or intermission none I find. Before mine eyes in opposition sits Grim Death, my son and foe, who set them on, And me, his parent, would full soon devour For want of other prey, but that he knows His end with mine involved, and knows that I Should prove a bitter morsel, and his bane, Whenever that shall be: so Fate pronounced. But thou, O father, I forewarn thee, shun His deadly arrow; neither vainly hope To be invulnerable in those bright arms, Through tempered heavenly; for that mortal dint, Save he who reigns above, none can resist." She finished; and the subtle Fiend his lore Soon learned, now milder, and thus answered smooth:-- "Dear daughter--since thou claim'st me for thy sire, And my fair son here show'st me, the dear pledge Of dalliance had with thee in Heaven, and joys Then sweet, now sad to mention, through dire change Befallen us unforeseen, unthought-of--know, I come no enemy, but to set free From out this dark and dismal house of pain Both him and thee, and all the heavenly host Of Spirits that, in our just pretences armed, Fell with us from on high. From them I go This uncouth errand sole, and one for all Myself expose, with lonely steps to tread Th' unfounded Deep, and through the void immense To search, with wandering quest, a place foretold Should be--and, by concurring signs, ere now Created vast and round--a place of bliss In the purlieus of Heaven; and therein placed A race of upstart creatures, to supply Perhaps our vacant room, though more removed, Lest Heaven, surcharged with potent multitude, Might hap to move new broils. Be this, or aught Than this more secret, now designed, I haste To know; and, this once known, shall soon return, And bring ye to the place where thou and Death Shall dwell at ease, and up and down unseen Wing silently the buxom air, embalmed With odours. There ye shall be fed and filled Immeasurably; all things shall be your prey." He ceased; for both seemed highly pleased, and Death Grinned horrible a ghastly smile, to hear His famine should be filled, and blessed his maw Destined to that good hour. No less rejoiced His mother bad, and thus bespake her sire:-- "The key of this infernal Pit, by due And by command of Heaven's all-powerful King, I keep, by him forbidden to unlock These adamantine gates; against all force Death ready stands to interpose his dart, Fearless to be o'ermatched by living might. But what owe I to his commands above, Who hates me, and hath hither thrust me down Into this gloom of Tartarus profound, To sit in hateful office here confined, Inhabitant of Heaven and heavenly born-- Here in perpetual agony and pain, With terrors and with clamours compassed round Of mine own brood, that on my bowels feed? Thou art my father, thou my author, thou My being gav'st me; whom should I obey But thee? whom follow? Thou wilt bring me soon To that new world of light and bliss, among The gods who live at ease, where I shall reign At thy right hand voluptuous, as beseems Thy daughter and thy darling, without end." Thus saying, from her side the fatal key, Sad instrument of all our woe, she took; And, towards the gate rolling her bestial train, Forthwith the huge portcullis high up-drew, Which, but herself, not all the Stygian Powers Could once have moved; then in the key-hole turns Th' intricate wards, and every bolt and bar Of massy iron or solid rock with ease Unfastens. On a sudden open fly, With impetuous recoil and jarring sound, Th' infernal doors, and on their hinges grate Harsh thunder, that the lowest bottom shook Of Erebus. She opened; but to shut Excelled her power: the gates wide open stood, That with extended wings a bannered host, Under spread ensigns marching, mibht pass through With horse and chariots ranked in loose array; So wide they stood, and like a furnace-mouth Cast forth redounding smoke and ruddy flame. Before their eyes in sudden view appear The secrets of the hoary Deep--a dark Illimitable ocean, without bound, Without dimension; where length, breadth, and height, And time, and place, are lost; where eldest Night And Chaos, ancestors of Nature, hold Eternal anarchy, amidst the noise Of endless wars, and by confusion stand. For Hot, Cold, Moist, and Dry, four champions fierce, Strive here for mastery, and to battle bring Their embryon atoms: they around the flag Of each his faction, in their several clans, Light-armed or heavy, sharp, smooth, swift, or slow, Swarm populous, unnumbered as the sands Of Barca or Cyrene's torrid soil, Levied to side with warring winds, and poise Their lighter wings. To whom these most adhere He rules a moment: Chaos umpire sits, And by decision more embroils the fray By which he reigns: next him, high arbiter, Chance governs all. Into this wild Abyss, The womb of Nature, and perhaps her grave, Of neither sea, nor shore, nor air, nor fire, But all these in their pregnant causes mixed Confusedly, and which thus must ever fight, Unless th' Almighty Maker them ordain His dark materials to create more worlds-- Into this wild Abyss the wary Fiend Stood on the brink of Hell and looked a while, Pondering his voyage; for no narrow frith He had to cross. Nor was his ear less pealed With noises loud and ruinous (to compare Great things with small) than when Bellona storms With all her battering engines, bent to rase Some capital city; or less than if this frame Of Heaven were falling, and these elements In mutiny had from her axle torn The steadfast Earth. At last his sail-broad vans He spread for flight, and, in the surging smoke Uplifted, spurns the ground; thence many a league, As in a cloudy chair, ascending rides Audacious; but, that seat soon failing, meets A vast vacuity. All unawares, Fluttering his pennons vain, plumb-down he drops Ten thousand fathom deep, and to this hour Down had been falling, had not, by ill chance, The strong rebuff of some tumultuous cloud, Instinct with fire and nitre, hurried him As many miles aloft. That fury stayed-- Quenched in a boggy Syrtis, neither sea, Nor good dry land--nigh foundered, on he fares, Treading the crude consistence, half on foot, Half flying; behoves him now both oar and sail. As when a gryphon through the wilderness With winged course, o'er hill or moory dale, Pursues the Arimaspian, who by stealth Had from his wakeful custody purloined The guarded gold; so eagerly the Fiend O'er bog or steep, through strait, rough, dense, or rare, With head, hands, wings, or feet, pursues his way, And swims, or sinks, or wades, or creeps, or flies. At length a universal hubbub wild Of stunning sounds, and voices all confused, Borne through the hollow dark, assaults his ear With loudest vehemence. Thither he plies Undaunted, to meet there whatever Power Or Spirit of the nethermost Abyss Might in that noise reside, of whom to ask Which way the nearest coast of darkness lies Bordering on light; when straight behold the throne Of Chaos, and his dark pavilion spread Wide on the wasteful Deep! With him enthroned Sat sable-vested Night, eldest of things, The consort of his reign; and by them stood Orcus and Ades, and the dreaded name Of Demogorgon; Rumour next, and Chance, And Tumult, and Confusion, all embroiled, And Discord with a thousand various mouths. T' whom Satan, turning boldly, thus:--"Ye Powers And Spirtis of this nethermost Abyss, Chaos and ancient Night, I come no spy With purpose to explore or to disturb The secrets of your realm; but, by constraint Wandering this darksome desert, as my way Lies through your spacious empire up to light, Alone and without guide, half lost, I seek, What readiest path leads where your gloomy bounds Confine with Heaven; or, if some other place, From your dominion won, th' Ethereal King Possesses lately, thither to arrive I travel this profound. Direct my course: Directed, no mean recompense it brings To your behoof, if I that region lost, All usurpation thence expelled, reduce To her original darkness and your sway (Which is my present journey), and once more Erect the standard there of ancient Night. Yours be th' advantage all, mine the revenge!" Thus Satan; and him thus the Anarch old, With faltering speech and visage incomposed, Answered: "I know thee, stranger, who thou art-- *** That mighty leading Angel, who of late Made head against Heaven's King, though overthrown. I saw and heard; for such a numerous host Fled not in silence through the frighted Deep, With ruin upon ruin, rout on rout, Confusion worse confounded; and Heaven-gates Poured out by millions her victorious bands, Pursuing. I upon my frontiers here Keep residence; if all I can will serve That little which is left so to defend, Encroached on still through our intestine broils Weakening the sceptre of old Night: first, Hell, Your dungeon, stretching far and wide beneath; Now lately Heaven and Earth, another world Hung o'er my realm, linked in a golden chain To that side Heaven from whence your legions fell! If that way be your walk, you have not far; So much the nearer danger. Go, and speed; Havoc, and spoil, and ruin, are my gain." He ceased; and Satan stayed not to reply, But, glad that now his sea should find a shore, With fresh alacrity and force renewed Springs upward, like a pyramid of fire, Into the wild expanse, and through the shock Of fighting elements, on all sides round Environed, wins his way; harder beset And more endangered than when Argo passed Through Bosporus betwixt the justling rocks, Or when Ulysses on the larboard shunned Charybdis, and by th' other whirlpool steered. So he with difficulty and labour hard Moved on, with difficulty and labour he; But, he once passed, soon after, when Man fell, Strange alteration! Sin and Death amain, Following his track (such was the will of Heaven) Paved after him a broad and beaten way Over the dark Abyss, whose boiling gulf Tamely endured a bridge of wondrous length, From Hell continued, reaching th' utmost orb Of this frail World; by which the Spirits perverse With easy intercourse pass to and fro To tempt or punish mortals, except whom God and good Angels guard by special grace. But now at last the sacred influence Of light appears, and from the walls of Heaven Shoots far into the bosom of dim Night A glimmering dawn. Here Nature first begins Her farthest verge, and Chaos to retire, As from her outmost works, a broken foe, With tumult less and with less hostile din; That Satan with less toil, and now with ease, Wafts on the calmer wave by dubious light, And, like a weather-beaten vessel, holds Gladly the port, though shrouds and tackle torn; Or in the emptier waste, resembling air, Weighs his spread wings, at leisure to behold Far off th' empyreal Heaven, extended wide In circuit, undetermined square or round, With opal towers and battlements adorned Of living sapphire, once his native seat; And, fast by, hanging in a golden chain, This pendent World, in bigness as a star Of smallest magnitude close by the moon. Thither, full fraught with mischievous revenge, Accursed, and in a cursed hour, he hies. Book III Hail, holy Light, offspring of Heaven firstborn, Or of the Eternal coeternal beam May I express thee unblam'd? since God is light, And never but in unapproached light Dwelt from eternity, dwelt then in thee Bright effluence of bright essence increate. Or hear"st thou rather pure ethereal stream, Whose fountain who shall tell? before the sun, Before the Heavens thou wert, and at the voice Of God, as with a mantle, didst invest *** The rising world of waters dark and deep, Won from the void and formless infinite. Thee I re-visit now with bolder wing, Escap'd the Stygian pool, though long detain'd In that obscure sojourn, while in my flight Through utter and through middle darkness borne, With other notes than to the Orphean lyre I sung of Chaos and eternal Night; Taught by the heavenly Muse to venture down The dark descent, and up to re-ascend, Though hard and rare: Thee I revisit safe, And feel thy sovran vital lamp; but thou Revisit'st not these eyes, that roll in vain To find thy piercing ray, and find no dawn; So thick a drop serene hath quench'd their orbs, Or dim suffusion veil'd. Yet not the more Cease I to wander, where the Muses haunt, Clear spring, or shady grove, or sunny hill, Smit with the love of sacred song; but chief Thee, Sion, and the flowery brooks beneath, That wash thy hallow'd feet, and warbling flow, Nightly I visit: nor sometimes forget So were I equall'd with them in renown, Thy sovran command, that Man should find grace; Blind Thamyris, and blind Maeonides, And Tiresias, and Phineus, prophets old: Then feed on thoughts, that voluntary move Harmonious numbers; as the wakeful bird Sings darkling, and in shadiest covert hid Tunes her nocturnal note. Thus with the year Seasons return; but not to me returns Day, or the sweet approach of even or morn, Or sight of vernal bloom, or summer's rose, Or flocks, or herds, or human face divine; But cloud instead, and ever-during dark Surrounds me, from the cheerful ways of men Cut off, and for the book of knowledge fair Presented with a universal blank Of nature's works to me expung'd and ras'd, And wisdom at one entrance quite shut out. So much the rather thou, celestial Light, Shine inward, and the mind through all her powers Irradiate; there plant eyes, all mist from thence Purge and disperse, that I may see and tell Of things invisible to mortal sight. Now had the Almighty Father from above, From the pure empyrean where he sits High thron'd above all highth, bent down his eye His own works and their works at once to view: About him all the Sanctities of Heaven Stood thick as stars, and from his sight receiv'd Beatitude past utterance; on his right The radiant image of his glory sat, His only son; on earth he first beheld Our two first parents, yet the only two Of mankind in the happy garden plac'd Reaping immortal fruits of joy and love, Uninterrupted joy, unrivall'd love, In blissful solitude; he then survey'd Hell and the gulf between, and Satan there Coasting the wall of Heaven on this side Night In the dun air sublime, and ready now To stoop with wearied wings, and willing feet, On the bare outside of this world, that seem'd Firm land imbosom'd, without firmament, Uncertain which, in ocean or in air. Him God beholding from his prospect high, Wherein past, present, future, he beholds, Thus to his only Son foreseeing spake. Only begotten Son, seest thou what rage Transports our Adversary? whom no bounds Prescrib'd no bars of Hell, nor all the chains Heap'd on him there, nor yet the main abyss Wide interrupt, can hold; so bent he seems On desperate revenge, that shall redound Upon his own rebellious head. And now, Through all restraint broke loose, he wings his way Not far off Heaven, in the precincts of light, Directly towards the new created world, And man there plac'd, with purpose to assay If him by force he can destroy, or, worse, By some false guile pervert; and shall pervert; For man will hearken to his glozing lies, And easily transgress the sole command, Sole pledge of his obedience: So will fall He and his faithless progeny: Whose fault? Whose but his own? ingrate, he had of me All he could have; I made him just and right, Sufficient to have stood, though free to fall. Such I created all the ethereal Powers And Spirits, both them who stood, and them who fail'd; Freely they stood who stood, and fell who fell. Not free, what proof could they have given sincere Of true allegiance, constant faith or love, Where only what they needs must do appear'd, Not what they would? what praise could they receive? What pleasure I from such obedience paid, When will and reason (reason also is choice) Useless and vain, of freedom both despoil'd, Made passive both, had serv'd necessity, Not me? they therefore, as to right belong$ 'd, So were created, nor can justly accuse Their Maker, or their making, or their fate, As if predestination over-rul'd Their will dispos'd by absolute decree Or high foreknowledge they themselves decreed Their own revolt, not I; if I foreknew, Foreknowledge had no influence on their fault, Which had no less proved certain unforeknown. So without least impulse or shadow of fate, Or aught by me immutably foreseen, They trespass, authors to themselves in all Both what they judge, and what they choose; for so I form'd them free: and free they must remain, Till they enthrall themselves; I else must change Their nature, and revoke the high decree Unchangeable, eternal, which ordain'd $THeir freedom: they themselves ordain'd their fall. The first sort by their own suggestion fell, Self-tempted, self-deprav'd: Man falls, deceiv'd By the other first: Man therefore shall find grace, The other none: In mercy and justice both, Through Heaven and Earth, so shall my glory excel; But Mercy, first and last, shall brightest shine. Thus while God spake, ambrosial fragrance fill'd All Heaven, and in the blessed Spirits elect Sense of new joy ineffable diffus'd. Beyond compare the Son of God was seen Most glorious; in him all his Father shone Substantially express'd; and in his face Divine compassion visibly appear'd, Love without end, and without measure grace, Which uttering, thus he to his Father spake. O Father, gracious was that word which clos'd Thy sovran command, that Man should find grace; , that Man should find grace; For which both Heaven and earth shall high extol Thy praises, with the innumerable sound Of hymns and sacred songs, wherewith thy throne Encompass'd shall resound thee ever blest. For should Man finally be lost, should Man, Thy creature late so lov'd, thy youngest son, Fall circumvented thus by fraud, though join'd With his own folly? that be from thee far, That far be from thee, Father, who art judge Of all things made, and judgest only right. Or shall the Adversary thus obtain His end, and frustrate thine? shall he fulfill His malice, and thy goodness bring to nought, Or proud return, though to his heavier doom, Yet with revenge accomplish'd, and to Hell Draw after him the whole race of mankind, By him corrupted? or wilt thou thyself Abolish thy creation, and unmake For him, what for thy glory thou hast made? So should thy goodness and thy greatness both Be question'd and blasphem'd without defence. To whom the great Creator thus replied. O son, in whom my soul hath chief delight, Son of my bosom, Son who art alone. My word, my wisdom, and effectual might, All hast thou spoken as my thoughts are, all As my eternal purpose hath decreed; Man shall not quite be lost, but sav'd who will; Yet not of will in him, but grace in me Freely vouchsaf'd; once more I will renew His lapsed powers, though forfeit; and enthrall'd By sin to foul exorbitant desires; Upheld by me, yet once more he shall stand On even ground against his mortal foe; By me upheld, that he may know how frail His fallen condition is, and to me owe All his deliverance, and to none but me. Some I have chosen of peculiar grace, Elect above the rest; so is my will: The rest shall hear me call, and oft be warn'd Their sinful state, and to appease betimes The incensed Deity, while offer'd grace Invites; for I will clear their senses dark, What may suffice, and soften stony hearts To pray, repent, and bring obedience due. To prayer, repentance, and obedience due, Though but endeavour'd with sincere intent, Mine ear shall not be slow, mine eye not shut. And I will place within them as a guide, My umpire Conscience; whom if they will hear, Light after light, well us'd, they shall attain, And to the end, persisting, safe arrive. This my long sufferance, and my day of grace, They who neglect and scorn, shall never taste; But hard be harden'd, blind be blinded more, That they may stumble on, and deeper fall; And none but such from mercy I exclude. But yet all is not done; Man disobeying, Disloyal, breaks his fealty, and sins Against the high supremacy of Heaven, Affecting God-head, and, so losing all, To expiate his treason hath nought left, But to destruction sacred and devote, He, with his whole posterity, must die, Die he or justice must; unless for him Some other able, and as willing, pay The rigid satisfaction, death for death. Say, heavenly Powers, where shall we find such love? Which of you will be mortal, to redeem Man's mortal crime, and just the unjust to save? Dwells in all Heaven charity so dear? And silence was in Heaven: $ on Man's behalf He ask'd, but all the heavenly quire stood mute, Patron or intercessour none appear'd, Much less that durst upon his own head draw The deadly forfeiture, and ransom set. And now without redemption all mankind Must have been lost, adjudg'd to Death and Hell By doom severe, had not the Son of God, In whom the fulness dwells of love divine, His dearest mediation thus renew'd. Father, thy word is past, Man shall find grace; And shall grace not find means, that finds her way, The speediest of thy winged messengers, To visit all thy creatures, and to all Comes unprevented, unimplor'd, unsought? Happy for Man, so coming; he her aid Can never seek, once dead in sins, and lost; Atonement for himself, or offering meet, Indebted and undone, hath none to bring; Behold me then: me for him, life for life I offer: on me let thine anger fall; Account me Man; I for his sake will leave Thy bosom, and this glory next to thee Freely put off, and for him lastly die Well pleased; on me let Death wreak all his rage. Under his gloomy power I shall not long Lie vanquished. Thou hast given me to possess Life in myself for ever; by thee I live; Though now to Death I yield, and am his due, All that of me can die, yet, that debt paid, $ thou wilt not leave me in the loathsome grave His prey, nor suffer my unspotted soul For ever with corruption there to dwell; But I shall rise victorious, and subdue My vanquisher, spoiled of his vaunted spoil. Death his death's wound shall then receive, and stoop Inglorious, of his mortal sting disarmed; I through the ample air in triumph high Shall lead Hell captive maugre Hell, and show The powers of darkness bound. Thou, at the sight Pleased, out of Heaven shalt look down and smile, While, by thee raised, I ruin all my foes; Death last, and with his carcase glut the grave; Then, with the multitude of my redeemed, Shall enter Heaven, long absent, and return, Father, to see thy face, wherein no cloud Of anger shall remain, but peace assured And reconcilement: wrath shall be no more Thenceforth, but in thy presence joy entire. His words here ended; but his meek aspect Silent yet spake, and breathed immortal love To mortal men, above which only shone Filial obedience: as a sacrifice Glad to be offered, he attends the will Of his great Father. Admiration seized All Heaven, what this might mean, and whither tend, Wondering; but soon th' Almighty thus replied. O thou in Heaven and Earth the only peace Found out for mankind under wrath, O thou My sole complacence! Well thou know'st how dear To me are all my works; nor Man the least, Though last created, that for him I spare Thee from my bosom and right hand, to save, By losing thee a while, the whole race lost. 00021053 Thou, therefore, whom thou only canst redeem, Their nature also to thy nature join; And be thyself Man among men on Earth, Made flesh, when time shall be, of virgin seed, By wondrous birth; be thou in Adam's room The head of all mankind, though Adam's son. As in him perish all men, so in thee, As from a second root, shall be restored As many as are restored, without thee none. His crime makes guilty all his sons; thy merit, Imputed, shall absolve them who renounce Their own both righteous and unrighteous deeds, And live in thee transplanted, and from thee Receive new life. So Man, as is most just, Shall satisfy for Man, be judged and die, And dying rise, and rising with him raise His brethren, ransomed with his own dear life. So heavenly love shall outdo hellish hate, Giving to death, and dying to redeem, So dearly to redeem what hellish hate So easily destroyed, and still destroys In those who, when they may, accept not grace. Nor shalt thou, by descending to assume Man's nature, lessen or degrade thine own. Because thou hast, though throned in highest bliss Equal to God, and equally enjoying God-like fruition, quitted all, to save A world from utter loss, and hast been found By merit more than birthright Son of God, Found worthiest to be so by being good, Far more than great or high; because in thee Love hath abounded more than glory abounds; Therefore thy humiliation shall exalt With thee thy manhood also to this throne: Here shalt thou sit incarnate, here shalt reign Both God and Man, Son both of God and Man, Anointed universal King; all power I give thee; reign for ever, and assume Thy merits; under thee, as head supreme, Thrones, Princedoms, Powers, Dominions, I reduce: All knees to thee shall bow, of them that bide In Heaven, or Earth, or under Earth in Hell. When thou, attended gloriously from Heaven, Shalt in the sky appear, and from thee send The summoning Arch-Angels to proclaim Thy dread tribunal; forthwith from all winds, The living, and forthwith the cited dead Of all past ages, to the general doom Shall hasten; such a peal shall rouse their sleep. Then, all thy saints assembled, thou shalt judge Bad Men and Angels; they, arraigned, shall sink Beneath thy sentence; Hell, her numbers full, Thenceforth shall be for ever shut. Mean while The world shall burn, and from her ashes spring New Heaven and Earth, wherein the just shall dwell, And, after all their tribulations long, See golden days, fruitful of golden deeds, With joy and peace triumphing, and fair truth. Then thou thy regal scepter shalt lay by, For regal scepter then no more shall need, God shall be all in all. But, all ye Gods, Adore him, who to compass all this dies; Adore the Son, and honour him as me. No sooner had the Almighty ceased, but all The multitude of Angels, with a shout Loud as from numbers without number, sweet As from blest voices, uttering joy, Heaven rung With jubilee, and loud Hosannas filled The eternal regions: Lowly reverent Towards either throne they bow, and to the ground With solemn adoration down they cast Their crowns inwove with amarant and gold; Immortal amarant, a flower which once In Paradise, fast by the tree of life, Began to bloom; but soon for man's offence To Heaven removed, where first it grew, there grows, And flowers aloft shading the fount of life, And where the river of bliss through midst of Heaven Rolls o'er Elysian flowers her amber stream; With these that never fade the Spirits elect Bind their resplendent locks inwreathed with beams; Now in loose garlands thick thrown off, the bright Pavement, that like a sea of jasper shone, Impurpled with celestial roses smiled. Then, crowned again, their golden harps they took, Harps ever tuned, that glittering by their side Like quivers hung, and with preamble sweet Of charming symphony they introduce Their sacred song, and waken raptures high; No voice exempt, no voice but well could join Melodious part, such concord is in Heaven. Thee, Father, first they sung Omnipotent, Immutable, Immortal, Infinite, Eternal King; the Author of all being, Fonntain of light, thyself invisible Amidst the glorious brightness where thou sit'st Throned inaccessible, but when thou shadest The full blaze of thy beams, and, through a cloud Drawn round about thee like a radiant shrine, Dark with excessive bright thy skirts appear, Yet dazzle Heaven, that brightest Seraphim Approach not, but with both wings veil their eyes. Thee next they sang of all creation first, Begotten Son, Divine Similitude, In whose conspicuous countenance, without cloud Made visible, the Almighty Father shines, Whom else no creature can behold; on thee Impressed the effulgence of his glory abides, Transfused on thee his ample Spirit rests. He Heaven of Heavens and all the Powers therein By thee created; and by thee threw down The aspiring Dominations: Thou that day Thy Father's dreadful thunder didst not spare, Nor stop thy flaming chariot-wheels, that shook Heaven's everlasting frame, while o'er the necks Thou drovest of warring Angels disarrayed. Back from pursuit thy Powers with loud acclaim Thee only extolled, Son of thy Father's might, To execute fierce vengeance on his foes, Not so on Man: Him through their malice fallen, Father of mercy and grace, thou didst not doom So strictly, but much more to pity incline: No sooner did thy dear and only Son Perceive thee purposed not to doom frail Man So strictly, but much more to pity inclined, He to appease thy wrath, and end the strife Of mercy and justice in thy face discerned, Regardless of the bliss wherein he sat Second to thee, offered himself to die For Man's offence. O unexampled love, Love no where to be found less than Divine! Hail, Son of God, Saviour of Men! Thy name Shall be the copious matter of my song Henceforth, and never shall my heart thy praise Forget, nor from thy Father's praise disjoin. Thus they in Heaven, above the starry sphere, Their happy hours in joy and hymning spent. Mean while upon the firm opacous globe Of this round world, whose first convex divides The luminous inferiour orbs, enclosed From Chaos, and the inroad of Darkness old, Satan alighted walks: A globe far off It seemed, now seems a boundless continent Dark, waste, and wild, under the frown of Night Starless exposed, and ever-threatening storms Of Chaos blustering round, inclement sky; Save on that side which from the wall of Heaven, Though distant far, some small reflection gains Of glimmering air less vexed with tempest loud: Here walked the Fiend at large in spacious field. As when a vultur on Imaus bred, Whose snowy ridge the roving Tartar bounds, Dislodging from a region scarce of prey To gorge the flesh of lambs or yeanling kids, On hills where flocks are fed, flies toward the springs Of Ganges or Hydaspes, Indian streams; But in his way lights on the barren plains Of Sericana, where Chineses drive With sails and wind their cany waggons light: So, on this windy sea of land, the Fiend Walked up and down alone, bent on his prey; Alone, for other creature in this place, Living or lifeless, to be found was none; None yet, but store hereafter from the earth Up hither like aereal vapours flew Of all things transitory and vain, when sin With vanity had filled the works of men: Both all things vain, and all who in vain things Built their fond hopes of glory or lasting fame, Or happiness in this or the other life; All who have their reward on earth, the fruits Of painful superstition and blind zeal, Nought seeking but the praise of men, here find Fit retribution, empty as their deeds; All the unaccomplished works of Nature's hand, Abortive, monstrous, or unkindly mixed, Dissolved on earth, fleet hither, and in vain, Till final dissolution, wander here; Not in the neighbouring moon as some have dreamed; Those argent fields more likely habitants, Translated Saints, or middle Spirits hold Betwixt the angelical and human kind. Hither of ill-joined sons and daughters born First from the ancient world those giants came With many a vain exploit, though then renowned: The builders next of Babel on the plain Of Sennaar, and still with vain design, New Babels, had they wherewithal, would build: Others came single; he, who, to be deemed A God, leaped fondly into Aetna flames, Empedocles; and he, who, to enjoy Plato's Elysium, leaped into the sea, Cleombrotus; and many more too long, Embryos, and idiots, eremites, and friars White, black, and gray, with all their trumpery. Here pilgrims roam, that strayed so far to seek In Golgotha him dead, who lives in Heaven; And they, who to be sure of Paradise, Dying, put on the weeds of Dominick, Or in Franciscan think to pass disguised; They pass the planets seven, and pass the fixed, And that crystalling sphere whose balance weighs The trepidation talked, and that first moved; And now Saint Peter at Heaven's wicket seems To wait them with his keys, and now at foot Of Heaven's ascent they lift their feet, when lo A violent cross wind from either coast Blows them transverse, ten thousand leagues awry Into the devious air: Then might ye see Cowls, hoods, and habits, with their wearers, tost And fluttered into rags; then reliques, beads, Indulgences, dispenses, pardons, bulls, The sport of winds: All these, upwhirled aloft, Fly o'er the backside of the world far off Into a Limbo large and broad, since called The Paradise of Fools, to few unknown Long after; now unpeopled, and untrod. All this dark globe the Fiend found as he passed, And long he wandered, till at last a gleam Of dawning light turned thither-ward in haste His travelled steps: far distant he descries Ascending by degrees magnificent Up to the wall of Heaven a structure high; At top whereof, but far more rich, appeared The work as of a kingly palace-gate, With frontispiece of diamond and gold Embellished; thick with sparkling orient gems The portal shone, inimitable on earth By model, or by shading pencil, drawn. These stairs were such as whereon Jacob saw Angels ascending and descending, bands Of guardians bright, when he from Esau fled To Padan-Aram, in the field of Luz Dreaming by night under the open sky And waking cried, This is the gate of Heaven. Each stair mysteriously was meant, nor stood There always, but drawn up to Heaven sometimes Viewless; and underneath a bright sea flowed Of jasper, or of liquid pearl, whereon Who after came from earth, failing arrived Wafted by Angels, or flew o'er the lake Rapt in a chariot drawn by fiery steeds. The stairs were then let down, whether to dare The Fiend by easy ascent, or aggravate His sad exclusion from the doors of bliss: Direct against which opened from beneath, Just o'er the blissful seat of Paradise, A passage down to the Earth, a passage wide, Wider by far than that of after-times Over mount Sion, and, though that were large, Over the Promised Land to God so dear; By which, to visit oft those happy tribes, On high behests his angels to and fro Passed frequent, and his eye with choice regard From Paneas, the fount of Jordan's flood, To Beersaba, where the Holy Land Borders on Egypt and the Arabian shore; So wide the opening seemed, where bounds were set To darkness, such as bound the ocean wave. Satan from hence, now on the lower stair, That scaled by steps of gold to Heaven-gate, Looks down with wonder at the sudden view Of all this world at once. As when a scout, Through dark?;nd desart ways with?oeril gone All?might,?;t?kast by break of cheerful dawn Obtains the brow of some high-climbing hill, Which to his eye discovers unaware The goodly prospect of some foreign land First seen, or some renowned metropolis With glistering spires and pinnacles adorned, Which now the rising sun gilds with his beams: Such wonder seised, though after Heaven seen, The Spirit malign, but much more envy seised, At sight of all this world beheld so fair. Round he surveys (and well might, where he stood So high above the circling canopy Of night's extended shade,) from eastern point Of Libra to the fleecy star that bears Andromeda far off Atlantick seas Beyond the horizon; then from pole to pole He views in breadth, and without longer pause Down right into the world's first region throws His flight precipitant, and winds with ease Through the pure marble air his oblique way Amongst innumerable stars, that shone Stars distant, but nigh hand seemed other worlds; Or other worlds they seemed, or happy isles, Like those Hesperian gardens famed of old, Fortunate fields, and groves, and flowery vales, Thrice happy isles; but who dwelt happy there He staid not to inquire: Above them all The golden sun, in splendour likest Heaven, Allured his eye; thither his course he bends Through the calm firmament, (but up or down, By center, or eccentrick, hard to tell, Or longitude,) where the great luminary Aloof the vulgar constellations thick, That from his lordly eye keep distance due, Dispenses light from far; they, as they move Their starry dance in numbers that compute Days, months, and years, towards his all-cheering lamp Turn swift their various motions, or are turned By his magnetick beam, that gently warms The universe, and to each inward part With gentle penetration, though unseen, Shoots invisible virtue even to the deep; So wonderously was set his station bright. There lands the Fiend, a spot like which perhaps Astronomer in the sun's lucent orb Through his glazed optick tube yet never saw. The place he found beyond expression bright, Compared with aught on earth, metal or stone; Not all parts like, but all alike informed With radiant light, as glowing iron with fire; If metal, part seemed gold, part silver clear; If stone, carbuncle most or chrysolite, Ruby or topaz, to the twelve that shone In Aaron's breast-plate, and a stone besides Imagined rather oft than elsewhere seen, That stone, or like to that which here below Philosophers in vain so long have sought, In vain, though by their powerful art they bind Volatile Hermes, and call up unbound In various shapes old Proteus from the sea, Drained through a limbeck to his native form. What wonder then if fields and regions here Breathe forth Elixir pure, and rivers run Potable gold, when with one virtuous touch The arch-chemick sun, so far from us remote, Produces, with terrestrial humour mixed, Here in the dark so many precious things Of colour glorious, and effect so rare? Here matter new to gaze the Devil met Undazzled; far and wide his eye commands; For sight no obstacle found here, nor shade, But all sun-shine, as when his beams at noon Culminate from the equator, as they now Shot upward still direct, whence no way round Shadow from body opaque can fall; and the air, No where so clear, sharpened his visual ray To objects distant far, whereby he soon Saw within ken a glorious Angel stand, The same whom John saw also in the sun: His back was turned, but not his brightness hid; Of beaming sunny rays a golden tiar Circled his head, nor less his locks behind Illustrious on his shoulders fledge with wings Lay waving round; on some great charge employed He seemed, or fixed in cogitation deep. Glad was the Spirit impure, as now in hope To find who might direct his wandering flight To Paradise, the happy seat of Man, His journey's end and our beginning woe. But first he casts to change his proper shape, Which else might work him danger or delay: And now a stripling Cherub he appears, Not of the prime, yet such as in his face Youth smiled celestial, and to every limb Suitable grace diffused, so well he feigned: Under a coronet his flowing hair In curls on either cheek played; wings he wore Of many a coloured plume, sprinkled with gold; His habit fit for speed succinct, and held Before his decent steps a silver wand. He drew not nigh unheard; the Angel bright, Ere he drew nigh, his radiant visage turned, Admonished by his ear, and straight was known The Arch-Angel Uriel, one of the seven Who in God's presence, nearest to his throne, Stand ready at command, and are his eyes That run through all the Heavens, or down to the Earth Bear his swift errands over moist and dry, O'er sea and land: him Satan thus accosts. Uriel, for thou of those seven Spirits that stand In sight of God's high throne, gloriously bright, The first art wont his great authentick will Interpreter through highest Heaven to bring, Where all his sons thy embassy attend; And here art likeliest by supreme decree Like honour to obtain, and as his eye To visit oft this new creation round; Unspeakable desire to see, and know All these his wonderous works, but chiefly Man, His chief delight and favour, him for whom All these his works so wonderous he ordained, Hath brought me from the quires of Cherubim Alone thus wandering. Brightest Seraph, tell In which of all these shining orbs hath Man His fixed seat, or fixed seat hath none, But all these shining orbs his choice to dwell; That I may find him, and with secret gaze Or open admiration him behold, On whom the great Creator hath bestowed Worlds, and on whom hath all these graces poured; That both in him and all things, as is meet, The universal Maker we may praise; Who justly hath driven out his rebel foes To deepest Hell, and, to repair that loss, Created this new happy race of Men To serve him better: Wise are all his ways. So spake the false dissembler unperceived; For neither Man nor Angel can discern Hypocrisy, the only evil that walks Invisible, except to God alone, By his permissive will, through Heaven and Earth: And oft, though wisdom wake, suspicion sleeps At wisdom's gate, and to simplicity Resigns her charge, while goodness thinks no ill Where no ill seems: Which now for once beguiled Uriel, though regent of the sun, and held The sharpest-sighted Spirit of all in Heaven; Who to the fraudulent impostor foul, In his uprightness, answer thus returned. Fair Angel, thy desire, which tends to know The works of God, thereby to glorify The great Work-master, leads to no excess That reaches blame, but rather merits praise The more it seems excess, that led thee hither From thy empyreal mansion thus alone, To witness with thine eyes what some perhaps, Contented with report, hear only in Heaven: For wonderful indeed are all his works, Pleasant to know, and worthiest to be all Had in remembrance always with delight; But what created mind can comprehend Their number, or the wisdom infinite That brought them forth, but hid their causes deep? I saw when at his word the formless mass, This world's material mould, came to a heap: Confusion heard his voice, and wild uproar Stood ruled, stood vast infinitude confined; Till at his second bidding Darkness fled, Light shone, and order from disorder sprung: Swift to their several quarters hasted then The cumbrous elements, earth, flood, air, fire; And this ethereal quintessence of Heaven Flew upward, spirited with various forms, That rolled orbicular, and turned to stars Numberless, as thou seest, and how they move; Each had his place appointed, each his course; The rest in circuit walls this universe. Look downward on that globe, whose hither side With light from hence, though but reflected, shines; That place is Earth, the seat of Man; that light His day, which else, as the other hemisphere, Night would invade; but there the neighbouring moon So call that opposite fair star) her aid Timely interposes, and her monthly round Still ending, still renewing, through mid Heaven, With borrowed light her countenance triform Hence fills and empties to enlighten the Earth, And in her pale dominion checks the night. That spot, to which I point, is Paradise, Adam's abode; those lofty shades, his bower. Thy way thou canst not miss, me mine requires. Thus said, he turned; and Satan, bowing low, As to superiour Spirits is wont in Heaven, Where honour due and reverence none neglects, Took leave, and toward the coast of earth beneath, Down from the ecliptick, sped with hoped success, Throws his steep flight in many an aery wheel; Nor staid, till on Niphates' top he lights. Book IV O, for that warning voice, which he, who saw The Apocalypse, heard cry in Heaven aloud, Then when the Dragon, put to second rout, Came furious down to be revenged on men, Woe to the inhabitants on earth! that now, While time was, our first parents had been warned The coming of their secret foe, and 'scaped, Haply so 'scaped his mortal snare: For now Satan, now first inflamed with rage, came down, The tempter ere the accuser of mankind, To wreak on innocent frail Man his loss Of that first battle, and his flight to Hell: Yet, not rejoicing in his speed, though bold Far off and fearless, nor with cause to boast, Begins his dire attempt; which nigh the birth Now rolling boils in his tumultuous breast, And like a devilish engine back recoils Upon himself; horrour and doubt distract His troubled thoughts, and from the bottom stir The Hell within him; for within him Hell He brings, and round about him, nor from Hell One step, no more than from himself, can fly By change of place: Now conscience wakes despair, That slumbered; wakes the bitter memory Of what he was, what is, and what must be Worse; of worse deeds worse sufferings must ensue. Sometimes towards Eden, which now in his view Lay pleasant, his grieved look he fixes sad; Sometimes towards Heaven, and the full-blazing sun, Which now sat high in his meridian tower: Then, much revolving, thus in sighs began. O thou, that, with surpassing glory crowned, Lookest from thy sole dominion like the God Of this new world; at whose sight all the stars Hide their diminished heads; to thee I call, But with no friendly voice, and add thy name, Of Sun! to tell thee how I hate thy beams, That bring to my remembrance from what state I fell, how glorious once above thy sphere; Till pride and worse ambition threw me down Warring in Heaven against Heaven's matchless King: Ah, wherefore! he deserved no such return From me, whom he created what I was In that bright eminence, and with his good Upbraided none; nor was his service hard. What could be less than to afford him praise, The easiest recompence, and pay him thanks, How due! yet all his good proved ill in me, And wrought but malice; lifted up so high I sdeined subjection, and thought one step higher Would set me highest, and in a moment quit The debt immense of endless gratitude, So burdensome still paying, still to owe, Forgetful what from him I still received, And understood not that a grateful mind By owing owes not, but still pays, at once Indebted and discharged; what burden then O, had his powerful destiny ordained Me some inferiour Angel, I had stood Then happy; no unbounded hope had raised Ambition! Yet why not some other Power As great might have aspired, and me, though mean, Drawn to his part; but other Powers as great Fell not, but stand unshaken, from within Or from without, to all temptations armed. Hadst thou the same free will and power to stand? Thou hadst: whom hast thou then or what to accuse, But Heaven's free love dealt equally to all? Be then his love accursed, since love or hate, To me alike, it deals eternal woe. Nay, cursed be thou; since against his thy will Chose freely what it now so justly rues. Me miserable! which way shall I fly Infinite wrath, and infinite despair? Which way I fly is Hell; myself am Hell; And, in the lowest deep, a lower deep Still threatening to devour me opens wide, To which the Hell I suffer seems a Heaven. O, then, at last relent: Is there no place Left for repentance, none for pardon left? None left but by submission; and that word Disdain forbids me, and my dread of shame Among the Spirits beneath, whom I seduced With other promises and other vaunts Than to submit, boasting I could subdue The Omnipotent. Ay me! they little know How dearly I abide that boast so vain, Under what torments inwardly I groan, While they adore me on the throne of Hell. With diadem and scepter high advanced, The lower still I fall, only supreme In misery: Such joy ambition finds. But say I could repent, and could obtain, By act of grace, my former state; how soon Would highth recall high thoughts, how soon unsay What feigned submission swore? Ease would recant Vows made in pain, as violent and void. For never can true reconcilement grow, Where wounds of deadly hate have pierced so deep: Which would but lead me to a worse relapse And heavier fall: so should I purchase dear Short intermission bought with double smart. This knows my Punisher; therefore as far From granting he, as I from begging, peace; All hope excluded thus, behold, in stead Mankind created, and for him this world. So farewell, hope; and with hope farewell, fear; Farewell, remorse! all good to me is lost; Evil, be thou my good; by thee at least Divided empire with Heaven's King I hold, By thee, and more than half perhaps will reign; As Man ere long, and this new world, shall know. Thus while he spake, each passion dimmed his face Thrice changed with pale, ire, envy, and despair; Which marred his borrowed visage, and betrayed Him counterfeit, if any eye beheld. For heavenly minds from such distempers foul Are ever clear. Whereof he soon aware, Each perturbation smoothed with outward calm, Artificer of fraud; and was the first That practised falsehood under saintly show, Deep malice to conceal, couched with revenge: Yet not enough had practised to deceive Uriel once warned; whose eye pursued him down The way he went, and on the Assyrian mount Saw him disfigured, more than could befall Spirit of happy sort; his gestures fierce He marked and mad demeanour, then alone, As he supposed, all unobserved, unseen. So on he fares, and to the border comes Of Eden, where delicious Paradise, Now nearer, crowns with her enclosure green, As with a rural mound, the champaign head Of a steep wilderness, whose hairy sides Access denied; and overhead upgrew Insuperable height of loftiest shade, Cedar, and pine, and fir, and branching palm, A sylvan scene, and, as the ranks ascend, Shade above shade, a woody theatre Of stateliest view. Yet higher than their tops The verdurous wall of Paradise upsprung; 00081429 Which to our general sire gave prospect large Into his nether empire neighbouring round. And higher than that wall a circling row Of goodliest trees, loaden with fairest fruit, Blossoms and fruits at once of golden hue, Appeared, with gay enamelled colours mixed: On which the sun more glad impressed his beams Than in fair evening cloud, or humid bow, When God hath showered the earth; so lovely seemed That landskip: And of pure now purer air Meets his approach, and to the heart inspires Vernal delight and joy, able to drive All sadness but despair: Now gentle gales, Fanning their odoriferous wings, dispense Native perfumes, and whisper whence they stole Those balmy spoils. As when to them who fail Beyond the Cape of Hope, and now are past Mozambick, off at sea north-east winds blow Sabean odours from the spicy shore Of Araby the blest; with such delay Well pleased they slack their course, and many a league Cheered with the grateful smell old Ocean smiles: So entertained those odorous sweets the Fiend, Who came their bane; though with them better pleased Than Asmodeus with the fishy fume That drove him, though enamoured, from the spouse Of Tobit's son, and with a vengeance sent From Media post to Egypt, there fast bound. Now to the ascent of that steep savage hill Satan had journeyed on, pensive and slow; But further way found none, so thick entwined, As one continued brake, the undergrowth Of shrubs and tangling bushes had perplexed All path of man or beast that passed that way. One gate there only was, and that looked east On the other side: which when the arch-felon saw, Due entrance he disdained; and, in contempt, At one flight bound high over-leaped all bound Of hill or highest wall, and sheer within Lights on his feet. As when a prowling wolf, Whom hunger drives to seek new haunt for prey, Watching where shepherds pen their flocks at eve In hurdled cotes amid the field secure, Leaps o'er the fence with ease into the fold: Or as a thief, bent to unhoard the cash Of some rich burgher, whose substantial doors, Cross-barred and bolted fast, fear no assault, In at the window climbs, or o'er the tiles: So clomb this first grand thief into God's fold; So since into his church lewd hirelings climb. Thence up he flew, and on the tree of life, The middle tree and highest there that grew, Sat like a cormorant; yet not true life Thereby regained, but sat devising death To them who lived; nor on the virtue thought Of that life-giving plant, but only used For prospect, what well used had been the pledge Of immortality. So little knows Any, but God alone, to value right The good before him, but perverts best things To worst abuse, or to their meanest use. Beneath him with new wonder now he views, To all delight of human sense exposed, In narrow room, Nature's whole wealth, yea more, A Heaven on Earth: For blissful Paradise Of God the garden was, by him in the east Of Eden planted; Eden stretched her line From Auran eastward to the royal towers Of great Seleucia, built by Grecian kings, Of where the sons of Eden long before Dwelt in Telassar: In this pleasant soil His far more pleasant garden God ordained; Out of the fertile ground he caused to grow All trees of noblest kind for sight, smell, taste; And all amid them stood the tree of life, High eminent, blooming ambrosial fruit Of vegetable gold; and next to life, Our death, the tree of knowledge, grew fast by, Knowledge of good bought dear by knowing ill. Southward through Eden went a river large, Nor changed his course, but through the shaggy hill Passed underneath ingulfed; for God had thrown That mountain as his garden-mould high raised Upon the rapid current, which, through veins Of porous earth with kindly thirst up-drawn, Rose a fresh fountain, and with many a rill Watered the garden; thence united fell Down the steep glade, and met the nether flood, Which from his darksome passage now appears, And now, divided into four main streams, Runs diverse, wandering many a famous realm And country, whereof here needs no account; But rather to tell how, if Art could tell, How from that sapphire fount the crisped brooks, Rolling on orient pearl and sands of gold, With mazy errour under pendant shades Ran nectar, visiting each plant, and fed Flowers worthy of Paradise, which not nice Art In beds and curious knots, but Nature boon Poured forth profuse on hill, and dale, and plain, Both where the morning sun first warmly smote The open field, and where the unpierced shade Imbrowned the noontide bowers: Thus was this place A happy rural seat of various view; Groves whose rich trees wept odorous gums and balm, Others whose fruit, burnished with golden rind, Hung amiable, Hesperian fables true, If true, here only, and of delicious taste: Betwixt them lawns, or level downs, and flocks Grazing the tender herb, were interposed, Or palmy hillock; or the flowery lap Of some irriguous valley spread her store, Flowers of all hue, and without thorn the rose: Another side, umbrageous grots and caves Of cool recess, o'er which the mantling vine Lays forth her purple grape, and gently creeps Luxuriant; mean while murmuring waters fall Down the slope hills, dispersed, or in a lake, That to the fringed bank with myrtle crowned Her crystal mirrour holds, unite their streams. The birds their quire apply; airs, vernal airs, Breathing the smell of field and grove, attune The trembling leaves, while universal Pan, Knit with the Graces and the Hours in dance, Led on the eternal Spring. Not that fair field Of Enna, where Proserpine gathering flowers, Herself a fairer flower by gloomy Dis Was gathered, which cost Ceres all that pain To seek her through the world; nor that sweet grove Of Daphne by Orontes, and the inspired Castalian spring, might with this Paradise Of Eden strive; nor that Nyseian isle Girt with the river Triton, where old Cham, Whom Gentiles Ammon call and Libyan Jove, Hid Amalthea, and her florid son Young Bacchus, from his stepdame Rhea's eye; Nor where Abassin kings their issue guard, Mount Amara, though this by some supposed True Paradise under the Ethiop line By Nilus' head, enclosed with shining rock, A whole day's journey high, but wide remote From this Assyrian garden, where the Fiend Saw, undelighted, all delight, all kind Of living creatures, new to sight, and strange Two of far nobler shape, erect and tall, Godlike erect, with native honour clad In naked majesty seemed lords of all: And worthy seemed; for in their looks divine The image of their glorious Maker shone, Truth, wisdom, sanctitude severe and pure, (Severe, but in true filial freedom placed,) Whence true authority in men; though both Not equal, as their sex not equal seemed; For contemplation he and valour formed; For softness she and sweet attractive grace; He for God only, she for God in him: His fair large front and eye sublime declared Absolute rule; and hyacinthine locks Round from his parted forelock manly hung Clustering, but not beneath his shoulders broad: She, as a veil, down to the slender waist Her unadorned golden tresses wore Dishevelled, but in wanton ringlets waved As the vine curls her tendrils, which implied Subjection, but required with gentle sway, And by her yielded, by him best received, Yielded with coy submission, modest pride, And sweet, reluctant, amorous delay. Nor those mysterious parts were then concealed; Then was not guilty shame, dishonest shame Of nature's works, honour dishonourable, Sin-bred, how have ye troubled all mankind With shows instead, mere shows of seeming pure, And banished from man's life his happiest life, Simplicity and spotless innocence! So passed they naked on, nor shunned the sight Of God or Angel; for they thought no ill: So hand in hand they passed, the loveliest pair, That ever since in love's embraces met; Adam the goodliest man of men since born His sons, the fairest of her daughters Eve. Under a tuft of shade that on a green Stood whispering soft, by a fresh fountain side They sat them down; and, after no more toil Of their sweet gardening labour than sufficed To recommend cool Zephyr, and made ease More easy, wholesome thirst and appetite More grateful, to their supper-fruits they fell, Nectarine fruits which the compliant boughs Yielded them, side-long as they sat recline On the soft downy bank damasked with flowers: The savoury pulp they chew, and in the rind, Still as they thirsted, scoop the brimming stream; Nor gentle purpose, nor endearing smiles Wanted, nor youthful dalliance, as beseems Fair couple, linked in happy nuptial league, Alone as they. About them frisking played All beasts of the earth, since wild, and of all chase In wood or wilderness, forest or den; Sporting the lion ramped, and in his paw Dandled the kid; bears, tigers, ounces, pards, Gambolled before them; the unwieldy elephant, To make them mirth, used all his might, and wreathed His?kithetmroboscis; close the serpent sly, Insinuating, wove with Gordian twine His braided train, and of his fatal guile Gave proof unheeded; others on the grass Couched, and now filled with pasture gazing sat, Or bedward ruminating; for the sun, Declined, was hasting now with prone career To the ocean isles, and in the ascending scale Of Heaven the stars that usher evening rose: When Satan still in gaze, as first he stood, Scarce thus at length failed speech recovered sad. O Hell! what do mine eyes with grief behold! Into our room of bliss thus high advanced Creatures of other mould, earth-born perhaps, Not Spirits, yet to heavenly Spirits bright Little inferiour; whom my thoughts pursue With wonder, and could love, so lively shines In them divine resemblance, and such grace The hand that formed them on their shape hath poured. Ah! gentle pair, ye little think how nigh Your change approaches, when all these delights Will vanish, and deliver ye to woe; More woe, the more your taste is now of joy; Happy, but for so happy ill secured Long to continue, and this high seat your Heaven Ill fenced for Heaven to keep out such a foe As now is entered; yet no purposed foe To you, whom I could pity thus forlorn, Though I unpitied: League with you I seek, And mutual amity, so strait, so close, That I with you must dwell, or you with me Henceforth; my dwelling haply may not please, Like this fair Paradise, your sense; yet such Accept your Maker's work; he gave it me, Which I as freely give: Hell shall unfold, To entertain you two, her widest gates, And send forth all her kings; there will be room, Not like these narrow limits, to receive Your numerous offspring; if no better place, Thank him who puts me loth to this revenge On you who wrong me not for him who wronged. And should I at your harmless innocence Melt, as I do, yet publick reason just, Honour and empire with revenge enlarged, By conquering this new world, compels me now To do what else, though damned, I should abhor. So spake the Fiend, and with necessity, The tyrant's plea, excused his devilish deeds. Then from his lofty stand on that high tree Down he alights among the sportful herd Of those four-footed kinds, himself now one, Now other, as their shape served best his end Nearer to view his prey, and, unespied, To mark what of their state he more might learn, By word or action marked. About them round A lion now he stalks with fiery glare; Then as a tiger, who by chance hath spied In some purlieu two gentle fawns at play, Straight couches close, then, rising, changes oft His couchant watch, as one who chose his ground, Whence rushing, he might surest seize them both, Griped in each paw: when, Adam first of men To first of women Eve thus moving speech, Turned him, all ear to hear new utterance flow. Sole partner, and sole part, of all these joys, Dearer thyself than all; needs must the Power That made us, and for us this ample world, Be infinitely good, and of his good As liberal and free as infinite; That raised us from the dust, and placed us here In all this happiness, who at his hand Have nothing merited, nor can perform Aught whereof he hath need; he who requires From us no other service than to keep This one, this easy charge, of all the trees In Paradise that bear delicious fruit So various, not to taste that only tree Of knowledge, planted by the tree of life; So near grows death to life, whate'er death is, Some dreadful thing no doubt; for well thou knowest God hath pronounced it death to taste that tree, The only sign of our obedience left, Among so many signs of power and rule Conferred upon us, and dominion given Over all other creatures that possess Earth, air, and sea. Then let us not think hard One easy prohibition, who enjoy Free leave so large to all things else, and choice Unlimited of manifold delights: But let us ever praise him, and extol His bounty, following our delightful task, To prune these growing plants, and tend these flowers, Which were it toilsome, yet with thee were sweet. To whom thus Eve replied. O thou for whom And from whom I was formed, flesh of thy flesh, And without whom am to no end, my guide And head! what thou hast said is just and right. For we to him indeed all praises owe, And daily thanks; I chiefly, who enjoy So far the happier lot, enjoying thee Pre-eminent by so much odds, while thou Like consort to thyself canst no where find. That day I oft remember, when from sleep I first awaked, and found myself reposed Under a shade on flowers, much wondering where And what I was, whence thither brought, and how. Not distant far from thence a murmuring sound Of waters issued from a cave, and spread Into a liquid plain, then stood unmoved Pure as the expanse of Heaven; I thither went With unexperienced thought, and laid me down On the green bank, to look into the clear Smooth lake, that to me seemed another sky. As I bent down to look, just opposite A shape within the watery gleam appeared, Bending to look on me: I started back, It started back; but pleased I soon returned, Pleased it returned as soon with answering looks Of sympathy and love: There I had fixed Mine eyes till now, and pined with vain desire, Had not a voice thus warned me; 'What thou seest, 'What there thou seest, fair Creature, is thyself; 'With thee it came and goes: but follow me, 'And I will bring thee where no shadow stays 'Thy coming, and thy soft embraces, he 'Whose image thou art; him thou shalt enjoy 'Inseparably thine, to him shalt bear 'Multitudes like thyself, and thence be called 'Mother of human race.' What could I do, But follow straight, invisibly thus led? Till I espied thee, fair indeed and tall, Under a platane; yet methought less fair, Less winning soft, less amiably mild, Than that smooth watery image: Back I turned; Thou following cryedst aloud, 'Return, fair Eve; 'Whom flyest thou? whom thou flyest, of him thou art, 'His flesh, his bone; to give thee being I lent 'Out of my side to thee, nearest my heart, 'Substantial life, to have thee by my side 'Henceforth an individual solace dear; 'Part of my soul I seek thee, and thee claim 'My other half:' With that thy gentle hand Seised mine: I yielded;and from that time see How beauty is excelled by manly grace, And wisdom, which alone is truly fair. So spake our general mother, and with eyes Of conjugal attraction unreproved, And meek surrender, half-embracing leaned On our first father; half her swelling breast Naked met his, under the flowing gold Of her loose tresses hid: he in delight Both of her beauty, and submissive charms, Smiled with superiour love, as Jupiter On Juno smiles, when he impregns the clouds That shed Mayflowers; and pressed her matron lip With kisses pure: Aside the Devil turned For envy; yet with jealous leer malign Eyed them askance, and to himself thus plained. Sight hateful, sight tormenting! thus these two, Imparadised in one another's arms, The happier Eden, shall enjoy their fill Of bliss on bliss; while I to Hell am thrust, Where neither joy nor love, but fierce desire, Among our other torments not the least, Still unfulfilled with pain of longing pines. Yet let me not forget what I have gained From their own mouths: All is not theirs, it seems; One fatal tree there stands, of knowledge called, Forbidden them to taste: Knowledge forbidden Suspicious, reasonless. Why should their Lord Envy them that? Can it be sin to know? Can it be death? And do they only stand By ignorance? Is that their happy state, The proof of their obedience and their faith? O fair foundation laid whereon to build Their ruin! hence I will excite their minds With more desire to know, and to reject Envious commands, invented with design To keep them low, whom knowledge might exalt Equal with Gods: aspiring to be such, They taste and die: What likelier can ensue But first with narrow search I must walk round This garden, and no corner leave unspied; A chance but chance may lead where I may meet Some wandering Spirit of Heaven by fountain side, Or in thick shade retired, from him to draw What further would be learned. Live while ye may, Yet happy pair; enjoy, till I return, Short pleasures, for long woes are to succeed! So saying, his proud step he scornful turned, But with sly circumspection, and began Through wood, through waste, o'er hill, o'er dale, his roam Mean while in utmost longitude, where Heaven With earth and ocean meets, the setting sun Slowly descended, and with right aspect Against the eastern gate of Paradise Levelled his evening rays: It was a rock Of alabaster, piled up to the clouds, Conspicuous far, winding with one ascent Accessible from earth, one entrance high; The rest was craggy cliff, that overhung Still as it rose, impossible to climb. Betwixt these rocky pillars Gabriel sat, Chief of the angelick guards, awaiting night; About him exercised heroick games The unarmed youth of Heaven, but nigh at hand Celestial armoury, shields, helms, and spears, Hung high with diamond flaming, and with gold. Thither came Uriel, gliding through the even On a sun-beam, swift as a shooting star In autumn thwarts the night, when vapours fired Impress the air, and shows the mariner From what point of his compass to beware Impetuous winds: He thus began in haste. Gabriel, to thee thy course by lot hath given Charge and strict watch, that to this happy place No evil thing approach or enter in. This day at highth of noon came to my sphere A Spirit, zealous, as he seemed, to know More of the Almighty's works, and chiefly Man, God's latest image: I described his way Bent all on speed, and marked his aery gait; But in the mount that lies from Eden north, Where he first lighted, soon discerned his looks Alien from Heaven, with passions foul obscured: Mine eye pursued him still, but under shade Lost sight of him: One of the banished crew, I fear, hath ventured from the deep, to raise New troubles; him thy care must be to find. To whom the winged warriour thus returned. Uriel, no wonder if thy perfect sight, Amid the sun's bright circle where thou sitst, See far and wide: In at this gate none pass The vigilance here placed, but such as come Well known from Heaven; and since meridian hour No creature thence: If Spirit of other sort, So minded, have o'er-leaped these earthly bounds On purpose, hard thou knowest it to exclude Spiritual substance with corporeal bar. But if within the circuit of these walks, In whatsoever shape he lurk, of whom Thou tellest, by morrow dawning I shall know. So promised he; and Uriel to his charge Returned on that bright beam, whose point now raised Bore him slope downward to the sun now fallen Beneath the Azores; whether the prime orb, Incredible how swift, had thither rolled Diurnal, or this less volubil earth, By shorter flight to the east, had left him there Arraying with reflected purple and gold The clouds that on his western throne attend. Now came still Evening on, and Twilight gray Had in her sober livery all things clad; Silence accompanied; for beast and bird, They to their grassy couch, these to their nests Were slunk, all but the wakeful nightingale; She all night long her amorous descant sung; Silence was pleased: Now glowed the firmament With living sapphires: Hesperus, that led The starry host, rode brightest, till the moon, Rising in clouded majesty, at length Apparent queen unveiled her peerless light, And o'er the dark her silver mantle threw. When Adam thus to Eve. Fair Consort, the hour Of night, and all things now retired to rest, Mind us of like repose; since God hath set Labour and rest, as day and night, to men Successive; and the timely dew of sleep, Now falling with soft slumbrous weight, inclines Our eye-lids: Other creatures all day long Rove idle, unemployed, and less need rest; Man hath his daily work of body or mind Appointed, which declares his dignity, And the regard of Heaven on all his ways; While other animals unactive range, And of their doings God takes no account. To-morrow, ere fresh morning streak the east With first approach of light, we must be risen, And at our pleasant labour, to reform Yon flowery arbours, yonder alleys green, Our walk at noon, with branches overgrown, That mock our scant manuring, and require More hands than ours to lop their wanton growth: Those blossoms also, and those dropping gums, That lie bestrown, unsightly and unsmooth, Ask riddance, if we mean to tread with ease; Mean while, as Nature wills, night bids us rest. To whom thus Eve, with perfect beauty adorned My Author and Disposer, what thou bidst Unargued I obey: So God ordains; God is thy law, thou mine: To know no more Is woman's happiest knowledge, and her praise. With thee conversing I forget all time; All seasons, and their change, all please alike. Sweet is the breath of Morn, her rising sweet, With charm of earliest birds: pleasant the sun, When first on this delightful land he spreads His orient beams, on herb, tree, fruit, and flower, Glistering with dew; fragrant the fertile earth After soft showers; and sweet the coming on Of grateful Evening mild; then silent Night, With this her solemn bird, and this fair moon, And these the gems of Heaven, her starry train: But neither breath of Morn, when she ascends With charm of earliest birds; nor rising sun On this delightful land; nor herb, fruit, flower, Glistering with dew; nor fragrance after showers; Nor grateful Evening mild; nor silent Night, With this her solemn bird, nor walk by moon, Or glittering star-light, without thee is sweet. But wherefore all night long shine these? for whom This glorious sight, when sleep hath shut all eyes? To whom our general ancestor replied. Daughter of God and Man, accomplished Eve, These have their course to finish round the earth, By morrow evening, and from land to land In order, though to nations yet unborn, Ministring light prepared, they set and rise; Lest total Darkness should by night regain Her old possession, and extinguish life In Nature and all things; which these soft fires Not only enlighten, but with kindly heat Of various influence foment and warm, Temper or nourish, or in part shed down Their stellar virtue on all kinds that grow On earth, made hereby apter to receive Perfection from the sun's more potent ray. These then, though unbeheld in deep of night, Shine not in vain; nor think, though men were none, That Heaven would want spectators, God want praise: Millions of spiritual creatures walk the earth Unseen, both when we wake, and when we sleep: All these with ceaseless praise his works behold Both day and night: How often from the steep Of echoing hill or thicket have we heard Celestial voices to the midnight air, Sole, or responsive each to others note, Singing their great Creator? oft in bands While they keep watch, or nightly rounding walk, With heavenly touch of instrumental sounds In full harmonick number joined, their songs Divide the night, and lift our thoughts to Heaven. Thus talking, hand in hand alone they passed On to their blissful bower: it was a place Chosen by the sovran Planter, when he framed All things to Man's delightful use; the roof Of thickest covert was inwoven shade Laurel and myrtle, and what higher grew Of firm and fragrant leaf; on either side Acanthus, and each odorous bushy shrub, Fenced up the verdant wall; each beauteous flower, Iris all hues, roses, and jessamin, Reared high their flourished heads between, and wrought Mosaick; underfoot the violet, Crocus, and hyacinth, with rich inlay Broidered the ground, more coloured than with stone Of costliest emblem: Other creature here, Bird, beast, insect, or worm, durst enter none, Such was their awe of Man. In shadier bower More sacred and sequestered, though but feigned, Pan or Sylvanus never slept, nor Nymph Nor Faunus haunted. Here, in close recess, With flowers, garlands, and sweet-smelling herbs, Espoused Eve decked first her nuptial bed; And heavenly quires the hymenaean sung, What day the genial Angel to our sire Brought her in naked beauty more adorned, More lovely, than Pandora, whom the Gods Endowed with all their gifts, and O! too like In sad event, when to the unwiser son Of Japhet brought by Hermes, she ensnared Mankind with her fair looks, to be avenged On him who had stole Jove's authentick fire. Thus, at their shady lodge arrived, both stood, Both turned, and under open sky adored The God that made both sky, air, earth, and heaven, Which they beheld, the moon's resplendent globe, And starry pole: Thou also madest the night, Maker Omnipotent, and thou the day, Which we, in our appointed work employed, Have finished, happy in our mutual help And mutual love, the crown of all our bliss Ordained by thee; and this delicious place For us too large, where thy abundance wants Partakers, and uncropt falls to the ground. But thou hast promised from us two a race To fill the earth, who shall with us extol Thy goodness infinite, both when we wake, And when we seek, as now, thy gift of sleep. This said unanimous, and other rites Observing none, but adoration pure Which God likes best, into their inmost bower Handed they went; and, eased the putting off These troublesome disguises which we wear, Straight side by side were laid; nor turned, I ween, Adam from his fair spouse, nor Eve the rites Mysterious of connubial love refused: Whatever hypocrites austerely talk Of purity, and place, and innocence, Defaming as impure what God declares Pure, and commands to some, leaves free to all. Our Maker bids encrease; who bids abstain But our Destroyer, foe to God and Man? Hail, wedded Love, mysterious law, true source Of human offspring, sole propriety In Paradise of all things common else! By thee adulterous Lust was driven from men Among the bestial herds to range; by thee Founded in reason, loyal, just, and pure, Relations dear, and all the charities Of father, son, and brother, first were known. Far be it, that I should write thee sin or blame, Or think thee unbefitting holiest place, Perpetual fountain of domestick sweets, Whose bed is undefiled and chaste pronounced, Present, or past, as saints and patriarchs used. Here Love his golden shafts employs, here lights His constant lamp, and waves his purple wings, Reigns here and revels; not in the bought smile Of harlots, loveless, joyless, unendeared, Casual fruition; nor in court-amours, Mixed dance, or wanton mask, or midnight ball, Or serenate, which the starved lover sings To his proud fair, best quitted with disdain. These, lulled by nightingales, embracing slept, And on their naked limbs the flowery roof Showered roses, which the morn repaired. Sleep on, Blest pair; and O!yet happiest, if ye seek No happier state, and know to know no more. Now had night measured with her shadowy cone Half way up hill this vast sublunar vault, And from their ivory port the Cherubim, Forth issuing at the accustomed hour, stood armed To their night watches in warlike parade; When Gabriel to his next in power thus spake. Uzziel, half these draw off, and coast the south With strictest watch; these other wheel the north; Our circuit meets full west. As flame they part, Half wheeling to the shield, half to the spear. From these, two strong and subtle Spirits he called That near him stood, and gave them thus in charge. Ithuriel and Zephon, with winged speed Search through this garden, leave unsearched no nook; But chiefly where those two fair creatures lodge, Now laid perhaps asleep, secure of harm. This evening from the sun's decline arrived, Who tells of some infernal Spirit seen Hitherward bent (who could have thought?) escaped The bars of Hell, on errand bad no doubt: Such, where ye find, seise fast, and hither bring. So saying, on he led his radiant files, Dazzling the moon; these to the bower direct In search of whom they sought: Him there they found Squat like a toad, close at the ear of Eve, Assaying by his devilish art to reach The organs of her fancy, and with them forge Illusions, as he list, phantasms and dreams; Or if, inspiring venom, he might taint The animal spirits, that from pure blood arise Like gentle breaths from rivers pure, thence raise At least distempered, discontented thoughts, Vain hopes, vain aims, inordinate desires, Blown up with high conceits ingendering pride. Him thus intent Ithuriel with his spear Touched lightly; for no falshood can endure Touch of celestial temper, but returns Of force to its own likeness: Up he starts Discovered and surprised. As when a spark Lights on a heap of nitrous powder, laid Fit for the tun some magazine to store Against a rumoured war, the smutty grain, With sudden blaze diffused, inflames the air; So started up in his own shape the Fiend. Back stept those two fair Angels, half amazed So sudden to behold the grisly king; Yet thus, unmoved with fear, accost him soon. Which of those rebel Spirits adjudged to Hell Comest thou, escaped thy prison? and, transformed, Why sat'st thou like an enemy in wait, Here watching at the head of these that sleep? Know ye not then said Satan, filled with scorn, Know ye not me? ye knew me once no mate For you, there sitting where ye durst not soar: Not to know me argues yourselves unknown, The lowest of your throng; or, if ye know, Why ask ye, and superfluous begin Your message, like to end as much in vain? To whom thus Zephon, answering scorn with scorn. Think not, revolted Spirit, thy shape the same, Or undiminished brightness to be known, As when thou stoodest in Heaven upright and pure; That glory then, when thou no more wast good, Departed from thee; and thou resemblest now Thy sin and place of doom obscure and foul. But come, for thou, be sure, shalt give account To him who sent us, whose charge is to keep This place inviolable, and these from harm. So spake the Cherub; and his grave rebuke, Severe in youthful beauty, added grace Invincible: Abashed the Devil stood, And felt how awful goodness is, and saw Virtue in her shape how lovely; saw, and pined His loss; but chiefly to find here observed His lustre visibly impaired; yet seemed Undaunted. If I must contend, said he, Best with the best, the sender, not the sent, Or all at once; more glory will be won, Or less be lost. Thy fear, said Zephon bold, Will save us trial what the least can do Single against thee wicked, and thence weak. The Fiend replied not, overcome with rage; But, like a proud steed reined, went haughty on, Champing his iron curb: To strive or fly He held it vain; awe from above had quelled His heart, not else dismayed. Now drew they nigh The western point, where those half-rounding guards Just met, and closing stood in squadron joined, A waiting next command. To whom their Chief, Gabriel, from the front thus called aloud. O friends! I hear the tread of nimble feet Hasting this way, and now by glimpse discern Ithuriel and Zephon through the shade; And with them comes a third of regal port, But faded splendour wan; who by his gait And fierce demeanour seems the Prince of Hell, Not likely to part hence without contest; Stand firm, for in his look defiance lours. He scarce had ended, when those two approached, And brief related whom they brought, where found, How busied, in what form and posture couched. To whom with stern regard thus Gabriel spake. Why hast thou, Satan, broke the bounds prescribed To thy transgressions, and disturbed the charge Of others, who approve not to transgress By thy example, but have power and right To question thy bold entrance on this place; Employed, it seems, to violate sleep, and those Whose dwelling God hath planted here in bliss! To whom thus Satan with contemptuous brow. Gabriel? thou hadst in Heaven the esteem of wise, And such I held thee; but this question asked Puts me in doubt. Lives there who loves his pain! Who would not, finding way, break loose from Hell, Though thither doomed! Thou wouldst thyself, no doubt And boldly venture to whatever place Farthest from pain, where thou mightst hope to change Torment with ease, and soonest recompense Dole with delight, which in this place I sought; To thee no reason, who knowest only good, But evil hast not tried: and wilt object His will who bounds us! Let him surer bar His iron gates, if he intends our stay In that dark durance: Thus much what was asked. The rest is true, they found me where they say; But that implies not violence or harm. Thus he in scorn. The warlike Angel moved, Disdainfully half smiling, thus replied. O loss of one in Heaven to judge of wise Since Satan fell, whom folly overthrew, And now returns him from his prison 'scaped, Gravely in doubt whether to hold them wise Or not, who ask what boldness brought him hither Unlicensed from his bounds in Hell prescribed; So wise he judges it to fly from pain However, and to 'scape his punishment! So judge thou still, presumptuous! till the wrath, Which thou incurrest by flying, meet thy flight Sevenfold, and scourge that wisdom back to Hell, Which taught thee yet no better, that no pain Can equal anger infinite provoked. But wherefore thou alone? wherefore with thee Came not all hell broke loose? or thou than they Less hardy to endure? Courageous Chief! The first in flight from pain! hadst thou alleged To thy deserted host this cause of flight, Thou surely hadst not come sole fugitive. To which the Fiend thus answered, frowning stern. Not that I less endure, or shrink from pain, Insulting Angel! well thou knowest I stood Thy fiercest, when in battle to thy aid The blasting vollied thunder made all speed, And seconded thy else not dreaded spear. But still thy words at random, as before, Argue thy inexperience what behoves From hard assays and ill successes past A faithful leader, not to hazard all Through ways of danger by himself untried: I, therefore, I alone first undertook To wing the desolate abyss, and spy This new created world, whereof in Hell Fame is not silent, here in hope to find Better abode, and my afflicted Powers To settle here on earth, or in mid air; Though for possession put to try once more What thou and thy gay legions dare against; Whose easier business were to serve their Lord High up in Heaven, with songs to hymn his throne, And practised distances to cringe, not fight, To whom the warriour Angel soon replied. To say and straight unsay, pretending first Wise to fly pain, professing next the spy, Argues no leader but a liear traced, Satan, and couldst thou faithful add? O name, O sacred name of faithfulness profaned! Faithful to whom? to thy rebellious crew? Army of Fiends, fit body to fit head. Was this your discipline and faith engaged, Your military obedience, to dissolve Allegiance to the acknowledged Power supreme? And thou, sly hypocrite, who now wouldst seem Patron of liberty, who more than thou Once fawned, and cringed, and servily adored Heaven's awful Monarch? wherefore, but in hope To dispossess him, and thyself to reign? But mark what I arreed thee now, Avant; Fly neither whence thou fledst! If from this hour Within these hallowed limits thou appear, Back to the infernal pit I drag thee chained, And seal thee so, as henceforth not to scorn The facile gates of Hell too slightly barred. So threatened he; but Satan to no threats Gave heed, but waxing more in rage replied. Then when I am thy captive talk of chains, Proud limitary Cherub! but ere then Far heavier load thyself expect to feel From my prevailing arm, though Heaven's King Ride on thy wings, and thou with thy compeers, Us'd to the yoke, drawest his triumphant wheels In progress through the road of Heaven star-paved. While thus he spake, the angelick squadron bright Turned fiery red, sharpening in mooned horns Their phalanx, and began to hem him round With ported spears, as thick as when a field Of Ceres ripe for harvest waving bends Her bearded grove of ears, which way the wind Sways them; the careful plowman doubting stands, Left on the threshing floor his hopeless sheaves Prove chaff. On the other side, Satan, alarmed, Collecting all his might, dilated stood, Like Teneriff or Atlas, unremoved: His stature reached the sky, and on his crest Sat Horrour plumed; nor wanted in his grasp What seemed both spear and shield: Now dreadful deeds Might have ensued, nor only Paradise In this commotion, but the starry cope Of Heaven perhaps, or all the elements At least had gone to wrack, disturbed and torn With violence of this conflict, had not soon The Eternal, to prevent such horrid fray, Hung forth in Heaven his golden scales, yet seen Betwixt Astrea and the Scorpion sign, Wherein all things created first he weighed, The pendulous round earth with balanced air In counterpoise, now ponders all events, Battles and realms: In these he put two weights, The sequel each of parting and of fight: The latter quick up flew, and kicked the beam, Which Gabriel spying, thus bespake the Fiend. Satan, I know thy strength, and thou knowest mine; Neither our own, but given: What folly then To boast what arms can do? since thine no more Than Heaven permits, nor mine, though doubled now To trample thee as mire: For proof look up, And read thy lot in yon celestial sign; Where thou art weighed, and shown how light, how weak, If thou resist. The Fiend looked up, and knew His mounted scale aloft: Nor more;but fled Murmuring, and with him fled the shades of night. Book V Now Morn, her rosy steps in the eastern clime Advancing, sowed the earth with orient pearl, When Adam waked, so customed; for his sleep Was aery-light, from pure digestion bred, And temperate vapours bland, which the only sound Of leaves and fuming rills, Aurora's fan, Lightly dispersed, and the shrill matin song Of birds on every bough; so much the more His wonder was to find unwakened Eve With tresses discomposed, and glowing cheek, As through unquiet rest: He, on his side Leaning half raised, with looks of cordial love Hung over her enamoured, and beheld Beauty, which, whether waking or asleep, Shot forth peculiar graces; then with voice Mild, as when Zephyrus on Flora breathes, Her hand soft touching, whispered thus. Awake, My fairest, my espoused, my latest found, Heaven's last best gift, my ever new delight! Awake: The morning shines, and the fresh field Calls us; we lose the prime, to mark how spring Our tender plants, how blows the citron grove, What drops the myrrh, and what the balmy reed, How nature paints her colours, how the bee Sits on the bloom extracting liquid sweet. Such whispering waked her, but with startled eye On Adam, whom embracing, thus she spake. O sole in whom my thoughts find all repose, My glory, my perfection! glad I see Thy face, and morn returned; for I this night (Such night till this I never passed) have dreamed, If dreamed, not, as I oft am wont, of thee, Works of day past, or morrow's next design, But of offence and trouble, which my mind Knew never till this irksome night: Methought, Close at mine ear one called me forth to walk With gentle voice; I thought it thine: It said, 'Why sleepest thou, Eve? now is the pleasant time, 'The cool, the silent, save where silence yields 'To the night-warbling bird, that now awake 'Tunes sweetest his love-laboured song; now reigns 'Full-orbed the moon, and with more pleasing light 'Shadowy sets off the face of things; in vain, 'If none regard; Heaven wakes with all his eyes, 'Whom to behold but thee, Nature's desire? 'In whose sight all things joy, with ravishment 'Attracted by thy beauty still to gaze.' I rose as at thy call, but found thee not; To find thee I directed then my walk; And on, methought, alone I passed through ways That brought me on a sudden to the tree Of interdicted knowledge: fair it seemed, Much fairer to my fancy than by day: And, as I wondering looked, beside it stood One shaped and winged like one of those from Heaven By us oft seen; his dewy locks distilled Ambrosia; on that tree he also gazed; And 'O fair plant,' said he, 'with fruit surcharged, 'Deigns none to ease thy load, and taste thy sweet, 'Nor God, nor Man? Is knowledge so despised? 'Or envy, or what reserve forbids to taste? 'Forbid who will, none shall from me withhold 'Longer thy offered good; why else set here? This said, he paused not, but with venturous arm He plucked, he tasted; me damp horrour chilled At such bold words vouched with a deed so bold: But he thus, overjoyed; 'O fruit divine, 'Sweet of thyself, but much more sweet thus cropt, 'Forbidden here, it seems, as only fit 'For Gods, yet able to make Gods of Men: 'And why not Gods of Men; since good, the more 'Communicated, more abundant grows, 'The author not impaired, but honoured more? 'Here, happy creature, fair angelick Eve! 'Partake thou also; happy though thou art, 'Happier thou mayest be, worthier canst not be: 'Taste this, and be henceforth among the Gods 'Thyself a Goddess, not to earth confined, 'But sometimes in the air, as we, sometimes 'Ascend to Heaven, by merit thine, and see 'What life the Gods live there, and such live thou!' So saying, he drew nigh, and to me held, Even to my mouth of that same fruit held part Which he had plucked; the pleasant savoury smell So quickened appetite, that I, methought, Could not but taste. Forthwith up to the clouds With him I flew, and underneath beheld The earth outstretched immense, a prospect wide And various: Wondering at my flight and change To this high exaltation; suddenly My guide was gone, and I, methought, sunk down, And fell asleep; but O, how glad I waked To find this but a dream! Thus Eve her night Related, and thus Adam answered sad. Best image of myself, and dearer half, The trouble of thy thoughts this night in sleep Affects me equally; nor can I like This uncouth dream, of evil sprung, I fear; Yet evil whence? in thee can harbour none, Created pure. But know that in the soul Are many lesser faculties, that serve Reason as chief; among these Fancy next Her office holds; of all external things Which the five watchful senses represent, She forms imaginations, aery shapes, Which Reason, joining or disjoining, frames All what we affirm or what deny, and call Our knowledge or opinion; then retires Into her private cell, when nature rests. Oft in her absence mimick Fancy wakes To imitate her; but, misjoining shapes, Wild work produces oft, and most in dreams; Ill matching words and deeds long past or late. Some such resemblances, methinks, I find Of our last evening's talk, in this thy dream, But with addition strange; yet be not sad. Evil into the mind of God or Man May come and go, so unreproved, and leave No spot or blame behind: Which gives me hope That what in sleep thou didst abhor to dream, Waking thou never will consent to do. Be not disheartened then, nor cloud those looks, That wont to be more cheerful and serene, Than when fair morning first smiles on the world; And let us to our fresh employments rise Among the groves, the fountains, and the flowers That open now their choisest bosomed smells, Reserved from night, and kept for thee in store. So cheered he his fair spouse, and she was cheered; But silently a gentle tear let fall From either eye, and wiped them with her hair; Two other precious drops that ready stood, Each in their crystal sluice, he ere they fell Kissed, as the gracious signs of sweet remorse And pious awe, that feared to have offended. So all was cleared, and to the field they haste. But first, from under shady arborous roof Soon as they forth were come to open sight Of day-spring, and the sun, who, scarce up-risen, With wheels yet hovering o'er the ocean-brim, Shot parallel to the earth his dewy ray, Discovering in wide landskip all the east Of Paradise and Eden's happy plains, Lowly they bowed adoring, and began Their orisons, each morning duly paid In various style; for neither various style Nor holy rapture wanted they to praise Their Maker, in fit strains pronounced, or sung Unmeditated; such prompt eloquence Flowed from their lips, in prose or numerous verse, More tuneable than needed lute or harp To add more sweetness; and they thus began. These are thy glorious works, Parent of good, Almighty! Thine this universal frame, Thus wonderous fair; Thyself how wonderous then! Unspeakable, who sitst above these heavens To us invisible, or dimly seen In these thy lowest works; yet these declare Thy goodness beyond thought, and power divine. Speak, ye who best can tell, ye sons of light, Angels; for ye behold him, and with songs And choral symphonies, day without night, Circle his throne rejoicing; ye in Heaven On Earth join all ye Creatures to extol Him first, him last, him midst, and without end. Fairest of stars, last in the train of night, If better thou belong not to the dawn, Sure pledge of day, that crownest the smiling morn With thy bright circlet, praise him in thy sphere, While day arises, that sweet hour of prime. Thou Sun, of this great world both eye and soul, Acknowledge him thy greater; sound his praise In thy eternal course, both when thou climbest, And when high noon hast gained, and when thou fallest. Moon, that now meetest the orient sun, now flyest, With the fixed Stars, fixed in their orb that flies; And ye five other wandering Fires, that move In mystick dance not without song, resound His praise, who out of darkness called up light. Air, and ye Elements, the eldest birth Of Nature's womb, that in quaternion run Perpetual circle, multiform; and mix And nourish all things; let your ceaseless change Vary to our great Maker still new praise. Ye Mists and Exhalations, that now rise From hill or steaming lake, dusky or gray, Till the sun paint your fleecy skirts with gold, In honour to the world's great Author rise; Whether to deck with clouds the uncoloured sky, Or wet the thirsty earth with falling showers, Rising or falling still advance his praise. His praise, ye Winds, that from four quarters blow, Breathe soft or loud; and, wave your tops, ye Pines, With every plant, in sign of worship wave. Fountains, and ye that warble, as ye flow, Melodious murmurs, warbling tune his praise. Join voices, all ye living Souls: Ye Birds, That singing up to Heaven-gate ascend, Bear on your wings and in your notes his praise. Ye that in waters glide, and ye that walk The earth, and stately tread, or lowly creep; Witness if I be silent, morn or even, To hill, or valley, fountain, or fresh shade, Made vocal by my song, and taught his praise. Hail, universal Lord, be bounteous still To give us only good; and if the night Have gathered aught of evil, or concealed, Disperse it, as now light dispels the dark! So prayed they innocent, and to their thoughts Firm peace recovered soon, and wonted calm. On to their morning's rural work they haste, Among sweet dews and flowers; where any row Of fruit-trees over-woody reached too far Their pampered boughs, and needed hands to check Fruitless embraces: or they led the vine To wed her elm; she, spoused, about him twines Her marriageable arms, and with him brings Her dower, the adopted clusters, to adorn His barren leaves. Them thus employed beheld With pity Heaven's high King, and to him called Raphael, the sociable Spirit, that deigned To travel with Tobias, and secured His marriage with the seventimes-wedded maid. Raphael, said he, thou hearest what stir on Earth Satan, from Hell 'scaped through the darksome gulf, Hath raised in Paradise; and how disturbed This night the human pair; how he designs In them at once to ruin all mankind. Go therefore, half this day as friend with friend Converse with Adam, in what bower or shade Thou findest him from the heat of noon retired, To respite his day-labour with repast, Or with repose; and such discourse bring on, As may advise him of his happy state, Happiness in his power left free to will, Left to his own free will, his will though free, Yet mutable; whence warn him to beware He swerve not, too secure: Tell him withal His danger, and from whom; what enemy, Late fallen himself from Heaven, is plotting now The fall of others from like state of bliss; By violence? no, for that shall be withstood; But by deceit and lies: This let him know, Lest, wilfully transgressing, he pretend Surprisal, unadmonished, unforewarned. So spake the Eternal Father, and fulfilled All justice: Nor delayed the winged Saint After his charge received; but from among Thousand celestial Ardours, where he stood Veiled with his gorgeous wings, up springing light, Flew through the midst of Heaven; the angelick quires, On each hand parting, to his speed gave way Through all the empyreal road; till, at the gate Of Heaven arrived, the gate self-opened wide On golden hinges turning, as by work Divine the sovran Architect had framed. From hence no cloud, or, to obstruct his sight, Star interposed, however small he sees, Not unconformed to other shining globes, Earth, and the garden of God, with cedars crowned Above all hills. As when by night the glass Of Galileo, less assured, observes Imagined lands and regions in the moon: Or pilot, from amidst the Cyclades Delos or Samos first appearing, kens A cloudy spot. Down thither prone in flight He speeds, and through the vast ethereal sky Sails between worlds and worlds, with steady wing Now on the polar winds, then with quick fan Winnows the buxom air; till, within soar Of towering eagles, to all the fowls he seems A phoenix, gazed by all as that sole bird, When, to enshrine his reliques in the Sun's Bright temple, to Egyptian Thebes he flies. At once on the eastern cliff of Paradise He lights, and to his proper shape returns A Seraph winged: Six wings he wore, to shade His lineaments divine; the pair that clad Each shoulder broad, came mantling o'er his breast With regal ornament; the middle pair Girt like a starry zone his waist, and round Skirted his loins and thighs with downy gold And colours dipt in Heaven; the third his feet Shadowed from either heel with feathered mail, Sky-tinctured grain. Like Maia's son he stood, And shook his plumes, that heavenly fragrance filled The circuit wide. Straight knew him all the bands Of Angels under watch; and to his state, And to his message high, in honour rise; For on some message high they guessed him bound. Their glittering tents he passed, and now is come Into the blissful field, through groves of myrrh, And flowering odours, cassia, nard, and balm; A wilderness of sweets; for Nature here Wantoned as in her prime, and played at will Her virgin fancies pouring forth more sweet, Wild above rule or art, enormous bliss. Him through the spicy forest onward come Adam discerned, as in the door he sat Of his cool bower, while now the mounted sun Shot down direct his fervid rays to warm Earth's inmost womb, more warmth than Adam needs: And Eve within, due at her hour prepared For dinner savoury fruits, of taste to please True appetite, and not disrelish thirst Of nectarous draughts between, from milky stream, Berry or grape: To whom thus Adam called. Haste hither, Eve, and worth thy sight behold Eastward among those trees, what glorious shape Comes this way moving; seems another morn Risen on mid-noon; some great behest from Heaven To us perhaps he brings, and will vouchsafe This day to be our guest. But go with speed, And, what thy stores contain, bring forth, and pour Abundance, fit to honour and receive Our heavenly stranger: Well we may afford Our givers their own gifts, and large bestow From large bestowed, where Nature multiplies Her fertile growth, and by disburthening grows More fruitful, which instructs us not to spare. To whom thus Eve. Adam, earth's hallowed mould, Of God inspired! small store will serve, where store, All seasons, ripe for use hangs on the stalk; Save what by frugal storing firmness gains To nourish, and superfluous moist consumes: But I will haste, and from each bough and brake, Each plant and juciest gourd, will pluck such choice To entertain our Angel-guest, as he Beholding shall confess, that here on Earth God hath dispensed his bounties as in Heaven. So saying, with dispatchful looks in haste She turns, on hospitable thoughts intent What choice to choose for delicacy best, What order, so contrived as not to mix Tastes, not well joined, inelegant, but bring Taste after taste upheld with kindliest change; Bestirs her then, and from each tender stalk Whatever Earth, all-bearing mother, yields In India East or West, or middle shore In Pontus or the Punick coast, or where Alcinous reigned, fruit of all kinds, in coat Rough, or smooth rind, or bearded husk, or shell, She gathers, tribute large, and on the board Heaps with unsparing hand; for drink the grape She crushes, inoffensive must, and meaths From many a berry, and from sweet kernels pressed She tempers dulcet creams; nor these to hold Wants her fit vessels pure; then strows the ground With rose and odours from the shrub unfumed. Mean while our primitive great sire, to meet His God-like guest, walks forth, without more train Accompanied than with his own complete Perfections; in himself was all his state, More solemn than the tedious pomp that waits On princes, when their rich retinue long Of horses led, and grooms besmeared with gold, Dazzles the croud, and sets them all agape. Nearer his presence Adam, though not awed, Yet with submiss approach and reverence meek, As to a superiour nature bowing low, Thus said. Native of Heaven, for other place None can than Heaven such glorious shape contain; Since, by descending from the thrones above, Those happy places thou hast deigned a while To want, and honour these, vouchsafe with us Two only, who yet by sovran gift possess This spacious ground, in yonder shady bower To rest; and what the garden choicest bears To sit and taste, till this meridian heat Be over, and the sun more cool decline. Whom thus the angelick Virtue answered mild. Adam, I therefore came; nor art thou such Created, or such place hast here to dwell, As may not oft invite, though Spirits of Heaven, To visit thee; lead on then where thy bower O'ershades; for these mid-hours, till evening rise, I have at will. So to the sylvan lodge They came, that like Pomona's arbour smiled, With flowerets decked, and fragrant smells; but Eve, Undecked save with herself, more lovely fair Than Wood-Nymph, or the fairest Goddess feigned Of three that in mount Ida naked strove, Stood to entertain her guest from Heaven; no veil She needed, virtue-proof; no thought infirm Altered her cheek. On whom the Angel Hail Bestowed, the holy salutation used Long after to blest Mary, second Eve. Hail, Mother of Mankind, whose fruitful womb Shall fill the world more numerous with thy sons, Than with these various fruits the trees of God Have heaped this table!--Raised of grassy turf Their table was, and mossy seats had round, And on her ample square from side to side All autumn piled, though spring and autumn here Danced hand in hand. A while discourse they hold; No fear lest dinner cool; when thus began Our author. Heavenly stranger, please to taste These bounties, which our Nourisher, from whom All perfect good, unmeasured out, descends, To us for food and for delight hath caused The earth to yield; unsavoury food perhaps To spiritual natures; only this I know, That one celestial Father gives to all. To whom the Angel. Therefore what he gives (Whose praise be ever sung) to Man in part Spiritual, may of purest Spirits be found No ingrateful food: And food alike those pure Intelligential substances require, As doth your rational; and both contain Within them every lower faculty Of sense, whereby they hear, see, smell, touch, taste, Tasting concoct, digest, assimilate, And corporeal to incorporeal turn. For know, whatever was created, needs To be sustained and fed: Of elements The grosser feeds the purer, earth the sea, Earth and the sea feed air, the air those fires Ethereal, and as lowest first the moon; Whence in her visage round those spots, unpurged Vapours not yet into her substance turned. Nor doth the moon no nourishment exhale From her moist continent to higher orbs. The sun that light imparts to all, receives From all his alimental recompence In humid exhalations, and at even Sups with the ocean. Though in Heaven the trees Of life ambrosial fruitage bear, and vines Yield nectar; though from off the boughs each morn We brush mellifluous dews, and find the ground Covered with pearly grain: Yet God hath here Varied his bounty so with new delights, As may compare with Heaven; and to taste Think not I shall be nice. So down they sat, And to their viands fell; nor seemingly The Angel, nor in mist, the common gloss Of Theologians; but with keen dispatch Of real hunger, and concoctive heat To transubstantiate: What redounds, transpires Through Spirits with ease; nor wonder;if by fire Of sooty coal the empirick alchemist Can turn, or holds it possible to turn, Metals of drossiest ore to perfect gold, As from the mine. Mean while at table Eve Ministered naked, and their flowing cups With pleasant liquours crowned: O innocence Deserving Paradise! if ever, then, Then had the sons of God excuse to have been Enamoured at that sight; but in those hearts Love unlibidinous reigned, nor jealousy Was understood, the injured lover's hell. Thus when with meats and drinks they had sufficed, Not burdened nature, sudden mind arose In Adam, not to let the occasion pass Given him by this great conference to know Of things above his world, and of their being Who dwell in Heaven, whose excellence he saw Transcend his own so far; whose radiant forms, Divine effulgence, whose high power, so far Exceeded human; and his wary speech Thus to the empyreal minister he framed. Inhabitant with God, now know I well Thy favour, in this honour done to Man; Under whose lowly roof thou hast vouchsafed To enter, and these earthly fruits to taste, Food not of Angels, yet accepted so, As that more willingly thou couldst not seem At Heaven's high feasts to have fed: yet what compare To whom the winged Hierarch replied. O Adam, One Almighty is, from whom All things proceed, and up to him return, If not depraved from good, created all Such to perfection, one first matter all, Endued with various forms, various degrees Of substance, and, in things that live, of life; But more refined, more spiritous, and pure, As nearer to him placed, or nearer tending Each in their several active spheres assigned, Till body up to spirit work, in bounds Proportioned to each kind. So from the root Springs lighter the green stalk, from thence the leaves More aery, last the bright consummate flower Spirits odorous breathes: flowers and their fruit, Man's nourishment, by gradual scale sublimed, To vital spirits aspire, to animal, To intellectual; give both life and sense, Fancy and understanding; whence the soul Reason receives, and reason is her being, Discursive, or intuitive; discourse Is oftest yours, the latter most is ours, Differing but in degree, of kind the same. Wonder not then, what God for you saw good If I refuse not, but convert, as you To proper substance. Time may come, when Men With Angels may participate, and find No inconvenient diet, nor too light fare; And from these corporal nutriments perhaps Your bodies may at last turn all to spirit, Improved by tract of time, and, winged, ascend Ethereal, as we; or may, at choice, Here or in heavenly Paradises dwell; If ye be found obedient, and retain Unalterably firm his love entire, Whose progeny you are. Mean while enjoy Your fill what happiness this happy state Can comprehend, incapable of more. To whom the patriarch of mankind replied. O favourable Spirit, propitious guest, Well hast thou taught the way that might direct Our knowledge, and the scale of nature set From center to circumference; whereon, In contemplation of created things, By steps we may ascend to God. But say, What meant that caution joined, If ye be found Obedient? Can we want obedience then To him, or possibly his love desert, Who formed us from the dust and placed us here Full to the utmost measure of what bliss Human desires can seek or apprehend? To whom the Angel. Son of Heaven and Earth, Attend! That thou art happy, owe to God; That thou continuest such, owe to thyself, That is, to thy obedience; therein stand. This was that caution given thee; be advised. God made thee perfect, not immutable; And good he made thee, but to persevere He left it in thy power; ordained thy will By nature free, not over-ruled by fate Inextricable, or strict necessity: Our voluntary service he requires, Not our necessitated; such with him Finds no acceptance, nor can find; for how Can hearts, not free, be tried whether they serve Willing or no, who will but what they must By destiny, and can no other choose? Myself, and all the angelick host, that stand In sight of God, enthroned, our happy state Hold, as you yours, while our obedience holds; On other surety none: Freely we serve, Because we freely love, as in our will To love or not; in this we stand or fall: And some are fallen, to disobedience fallen, And so from Heaven to deepest Hell; O fall From what high state of bliss, into what woe! To whom our great progenitor. Thy words Attentive, and with more delighted ear, Divine instructer, I have heard, than when Cherubick songs by night from neighbouring hills Aereal musick send: Nor knew I not To be both will and deed created free; Yet that we never shall forget to love Our Maker, and obey him whose command Single is yet so just, my constant thoughts Assured me, and still assure: Though what thou tellest Hath passed in Heaven, some doubt within me move, But more desire to hear, if thou consent, The full relation, which must needs be strange, Worthy of sacred silence to be heard; And we have yet large day, for scarce the sun Hath finished half his journey, and scarce begins His other half in the great zone of Heaven. Thus Adam made request; and Raphael, After short pause assenting, thus began. High matter thou enjoinest me, O prime of men, Sad task and hard: For how shall I relate To human sense the invisible exploits Of warring Spirits? how, without remorse, The ruin of so many glorious once And perfect while they stood? how last unfold The secrets of another world, perhaps Not lawful to reveal? yet for thy good This is dispensed; and what surmounts the reach Of human sense, I shall delineate so, By likening spiritual to corporal forms, As may express them best; though what if Earth Be but a shadow of Heaven, and things therein Each to other like, more than on earth is thought? As yet this world was not, and Chaos wild Reigned where these Heavens now roll, where Earth now rests Upon her center poised; when on a day (For time, though in eternity, applied To motion, measures all things durable By present, past, and future,) on such day As Heaven's great year brings forth, the empyreal host Of Angels by imperial summons called, Innumerable before the Almighty's throne Forthwith, from all the ends of Heaven, appeared Under their Hierarchs in orders bright: Ten thousand thousand ensigns high advanced, Standards and gonfalons 'twixt van and rear Stream in the air, and for distinction serve Of hierarchies, of orders, and degrees; Or in their glittering tissues bear imblazed Holy memorials, acts of zeal and love Recorded eminent. Thus when in orbs Of circuit inexpressible they stood, Orb within orb, the Father Infinite, By whom in bliss imbosomed sat the Son, Amidst as from a flaming mount, whose top Brightness had made invisible, thus spake. Hear, all ye Angels, progeny of light, Thrones, Dominations, Princedoms, Virtues, Powers; Hear my decree, which unrevoked shall stand. This day I have begot whom I declare My only Son, and on this holy hill Him have anointed, whom ye now behold At my right hand; your head I him appoint; And by myself have sworn, to him shall bow All knees in Heaven, and shall confess him Lord: Under his great vice-gerent reign abide United, as one individual soul, For ever happy: Him who disobeys, Me disobeys, breaks union, and that day, Cast out from God and blessed vision, falls Into utter darkness, deep ingulfed, his place Ordained without redemption, without end. So spake the Omnipotent, and with his words All seemed well pleased; all seemed, but were not all. That day, as other solemn days, they spent In song and dance about the sacred hill; Mystical dance, which yonder starry sphere Of planets, and of fixed, in all her wheels Resembles nearest, mazes intricate, Eccentrick, intervolved, yet regular Then most, when most irregular they seem; And in their motions harmony divine So smooths her charming tones, that God's own ear Listens delighted. Evening now approached, (For we have also our evening and our morn, We ours for change delectable, not need;) Forthwith from dance to sweet repast they turn Desirous; all in circles as they stood, Tables are set, and on a sudden piled With Angels food, and rubied nectar flows In pearl, in diamond, and massy gold, Fruit of delicious vines, the growth of Heaven. On flowers reposed, and with fresh flowerets crowned, They eat, they drink, and in communion sweet Quaff immortality and joy, secure Of surfeit, where full measure only bounds Excess, before the all-bounteous King, who showered With copious hand, rejoicing in their joy. Now when ambrosial night with clouds exhaled From that high mount of God, whence light and shade Spring both, the face of brightest Heaven had changed To grateful twilight, (for night comes not there In darker veil,) and roseat dews disposed All but the unsleeping eyes of God to rest; Wide over all the plain, and wider far Than all this globous earth in plain outspread, (Such are the courts of God) the angelick throng, Dispersed in bands and files, their camp extend By living streams among the trees of life, Pavilions numberless, and sudden reared, Celestial tabernacles, where they slept Fanned with cool winds; save those, who, in their course, Melodious hymns about the sovran throne Alternate all night long: but not so waked Satan; so call him now, his former name Is heard no more in Heaven; he of the first, If not the first Arch-Angel, great in power, In favour and pre-eminence, yet fraught With envy against the Son of God, that day Honoured by his great Father, and proclaimed Messiah King anointed, could not bear Through pride that sight, and thought himself impaired. Deep malice thence conceiving and disdain, Soon as midnight brought on the dusky hour Friendliest to sleep and silence, he resolved With all his legions to dislodge, and leave Unworshipt, unobeyed, the throne supreme, Contemptuous; and his next subordinate Awakening, thus to him in secret spake. Sleepest thou, Companion dear? What sleep can close Thy eye-lids? and rememberest what decree Of yesterday, so late hath passed the lips Of Heaven's Almighty. Thou to me thy thoughts Wast wont, I mine to thee was wont to impart; Both waking we were one; how then can now Thy sleep dissent? New laws thou seest imposed; New laws from him who reigns, new minds may raise In us who serve, new counsels to debate What doubtful may ensue: More in this place To utter is not safe. Assemble thou Of all those myriads which we lead the chief; Tell them, that by command, ere yet dim night Her shadowy cloud withdraws, I am to haste, And all who under me their banners wave, Homeward, with flying march, where we possess The quarters of the north; there to prepare Fit entertainment to receive our King, The great Messiah, and his new commands, Who speedily through all the hierarchies Intends to pass triumphant, and give laws. So spake the false Arch-Angel, and infused Bad influence into the unwary breast Of his associate: He together calls, Or several one by one, the regent Powers, Under him Regent; tells, as he was taught, That the Most High commanding, now ere night, Now ere dim night had disincumbered Heaven, The great hierarchal standard was to move; Tells the suggested cause, and casts between Ambiguous words and jealousies, to sound Or taint integrity: But all obeyed The wonted signal, and superiour voice Of their great Potentate; for great indeed His name, and high was his degree in Heaven; His countenance, as the morning-star that guides The starry flock, allured them, and with lies Drew after him the third part of Heaven's host. Mean while the Eternal eye, whose sight discerns Abstrusest thoughts, from forth his holy mount, And from within the golden lamps that burn Nightly before him, saw without their light Rebellion rising; saw in whom, how spread Among the sons of morn, what multitudes Were banded to oppose his high decree; And, smiling, to his only Son thus said. Son, thou in whom my glory I behold In full resplendence, Heir of all my might, Nearly it now concerns us to be sure Of our Omnipotence, and with what arms We mean to hold what anciently we claim Of deity or empire: Such a foe Is rising, who intends to erect his throne Equal to ours, throughout the spacious north; Nor so content, hath in his thought to try In battle, what our power is, or our right. Let us advise, and to this hazard draw With speed what force is left, and all employ In our defence; lest unawares we lose This our high place, our sanctuary, our hill. To whom the Son with calm aspect and clear, Lightning divine, ineffable, serene, Made answer. Mighty Father, thou thy foes Justly hast in derision, and, secure, Laughest at their vain designs and tumults vain, Matter to me of glory, whom their hate Illustrates, when they see all regal power Given me to quell their pride, and in event Know whether I be dextrous to subdue Thy rebels, or be found the worst in Heaven. So spake the Son; but Satan, with his Powers, Far was advanced on winged speed; an host Innumerable as the stars of night, Or stars of morning, dew-drops, which the sun Impearls on every leaf and every flower. Regions they passed, the mighty regencies Of Seraphim, and Potentates, and Thrones, In their triple degrees; regions to which All thy dominion, Adam, is no more Than what this garden is to all the earth, And all the sea, from one entire globose Stretched into longitude; which having passed, At length into the limits of the north They came; and Satan to his royal seat High on a hill, far blazing, as a mount Raised on a mount, with pyramids and towers From diamond quarries hewn, and rocks of gold; The palace of great Lucifer, (so call That structure in the dialect of men Interpreted,) which not long after, he Affecting all equality with God, In imitation of that mount whereon Messiah was declared in sight of Heaven, The Mountain of the Congregation called; For thither he assembled all his train, Pretending so commanded to consult About the great reception of their King, Thither to come, and with calumnious art Of counterfeited truth thus held their ears. Thrones, Dominations, Princedoms, Virtues, Powers; If these magnifick titles yet remain Not merely titular, since by decree Another now hath to himself engrossed All power, and us eclipsed under the name Of King anointed, for whom all this haste Of midnight-march, and hurried meeting here, This only to consult how we may best, With what may be devised of honours new, Receive him coming to receive from us Knee-tribute yet unpaid, prostration vile! Too much to one! but double how endured, To one, and to his image now proclaimed? But what if better counsels might erect Our minds, and teach us to cast off this yoke? Will ye submit your necks, and choose to bend The supple knee? Ye will not, if I trust To know ye right, or if ye know yourselves Natives and sons of Heaven possessed before By none; and if not equal all, yet free, Equally free; for orders and degrees Jar not with liberty, but well consist. Who can in reason then, or right, assume Monarchy over such as live by right His equals, if in power and splendour less, In freedom equal? or can introduce Law and edict on us, who without law Err not? much less for this to be our Lord, And look for adoration, to the abuse Of those imperial titles, which assert Our being ordained to govern, not to serve. Thus far his bold discourse without controul Had audience; when among the Seraphim Abdiel, than whom none with more zeal adored The Deity, and divine commands obeyed, Stood up, and in a flame of zeal severe The current of his fury thus opposed. O argument blasphemous, false, and proud! Words which no ear ever to hear in Heaven Expected, least of all from thee, Ingrate, In place thyself so high above thy peers. Canst thou with impious obloquy condemn The just decree of God, pronounced and sworn, That to his only Son, by right endued With regal scepter, every soul in Heaven Shall bend the knee, and in that honour due Confess him rightful King? unjust, thou sayest, Flatly unjust, to bind with laws the free, And equal over equals to let reign, One over all with unsucceeded power. Shalt thou give law to God? shalt thou dispute With him the points of liberty, who made Thee what thou art, and formed the Powers of Heaven Such as he pleased, and circumscribed their being? Yet, by experience taught, we know how good, And of our good and of our dignity How provident he is; how far from thought To make us less, bent rather to exalt Our happy state, under one head more near United. But to grant it thee unjust, That equal over equals monarch reign: Thyself, though great and glorious, dost thou count, Or all angelick nature joined in one, Equal to him begotten Son? by whom, As by his Word, the Mighty Father made All things, even thee; and all the Spirits of Heaven By him created in their bright degrees, Crowned them with glory, and to their glory named Thrones, Dominations, Princedoms, Virtues, Powers, Essential Powers; nor by his reign obscured, But more illustrious made; since he the head One of our number thus reduced becomes; His laws our laws; all honour to him done Returns our own. Cease then this impious rage, And tempt not these; but hasten to appease The incensed Father, and the incensed Son, While pardon may be found in time besought. So spake the fervent Angel; but his zeal None seconded, as out of season judged, Or singular and rash: Whereat rejoiced The Apostate, and, more haughty, thus replied. That we were formed then sayest thou? and the work Of secondary hands, by task transferred From Father to his Son? strange point and new! Doctrine which we would know whence learned: who saw When this creation was? rememberest thou Thy making, while the Maker gave thee being? We know no time when we were not as now; Know none before us, self-begot, self-raised By our own quickening power, when fatal course Had circled his full orb, the birth mature Of this our native Heaven, ethereal sons. Our puissance is our own; our own right hand Shall teach us highest deeds, by proof to try Who is our equal: Then thou shalt behold Whether by supplication we intend Address, and to begirt the almighty throne Beseeching or besieging. This report, These tidings carry to the anointed King; And fly, ere evil intercept thy flight. He said; and, as the sound of waters deep, Hoarse murmur echoed to his words applause Through the infinite host; nor less for that The flaming Seraph fearless, though alone Encompassed round with foes, thus answered bold. O alienate from God, O Spirit accursed, Forsaken of all good! I see thy fall Determined, and thy hapless crew involved In this perfidious fraud, contagion spread Both of thy crime and punishment: Henceforth No more be troubled how to quit the yoke Of God's Messiah; those indulgent laws Will not be now vouchsafed; other decrees Against thee are gone forth without recall; That golden scepter, which thou didst reject, Is now an iron rod to bruise and break Thy disobedience. Well thou didst advise; Yet not for thy advice or threats I fly These wicked tents devoted, lest the wrath Impendent, raging into sudden flame, Distinguish not: For soon expect to feel His thunder on thy head, devouring fire. Then who created thee lamenting learn, When who can uncreate thee thou shalt know. So spake the Seraph Abdiel, faithful found Among the faithless, faithful only he; Among innumerable false, unmoved, Unshaken, unseduced, unterrified, His loyalty he kept, his love, his zeal; Nor number, nor example, with him wrought To swerve from truth, or change his constant mind, Though single. From amidst them forth he passed, Long way through hostile scorn, which he sustained Superiour, nor of violence feared aught; And, with retorted scorn, his back he turned On those proud towers to swift destruction doomed. Book VI All night the dreadless Angel, unpursued, Through Heaven's wide champain held his way; till Morn, Waked by the circling Hours, with rosy hand Unbarred the gates of light. There is a cave Within the mount of God, fast by his throne, Where light and darkness in perpetual round Lodge and dislodge by turns, which makes through Heaven Grateful vicissitude, like day and night; Light issues forth, and at the other door Obsequious darkness enters, till her hour To veil the Heaven, though darkness there might well Seem twilight here: And now went forth the Morn Such as in highest Heaven arrayed in gold Empyreal; from before her vanished Night, Shot through with orient beams; when all the plain Covered with thick embattled squadrons bright, Chariots, and flaming arms, and fiery steeds, Reflecting blaze on blaze, first met his view: War he perceived, war in procinct; and found Already known what he for news had thought To have reported: Gladly then he mixed Among those friendly Powers, who him received With joy and acclamations loud, that one, That of so many myriads fallen, yet one Returned not lost. On to the sacred hill They led him high applauded, and present Before the seat supreme; from whence a voice, From midst a golden cloud, thus mild was heard. Servant of God. Well done; well hast thou fought The better fight, who single hast maintained Against revolted multitudes the cause Of truth, in word mightier than they in arms; And for the testimony of truth hast borne Universal reproach, far worse to bear Than violence; for this was all thy care To stand approved in sight of God, though worlds Judged thee perverse: The easier conquest now Remains thee, aided by this host of friends, Back on thy foes more glorious to return, Than scorned thou didst depart; and to subdue By force, who reason for their law refuse, Right reason for their law, and for their King Messiah, who by right of merit reigns. Go, Michael, of celestial armies prince, And thou, in military prowess next, Gabriel, lead forth to battle these my sons Invincible; lead forth my armed Saints, By thousands and by millions, ranged for fight, Equal in number to that Godless crew Rebellious: Them with fire and hostile arms Fearless assault; and, to the brow of Heaven Pursuing, drive them out from God and bliss, Into their place of punishment, the gulf Of Tartarus, which ready opens wide His fiery Chaos to receive their fall. So spake the Sovran Voice, and clouds began To darken all the hill, and smoke to roll In dusky wreaths, reluctant flames, the sign Of wrath awaked; nor with less dread the loud Ethereal trumpet from on high 'gan blow: At which command the Powers militant, That stood for Heaven, in mighty quadrate joined Of union irresistible, moved on In silence their bright legions, to the sound Of instrumental harmony, that breathed Heroick ardour to adventurous deeds Under their God-like leaders, in the cause Of God and his Messiah. On they move Indissolubly firm; nor obvious hill, Nor straitening vale, nor wood, nor stream, divides Their perfect ranks; for high above the ground Their march was, and the passive air upbore Their nimble tread; as when the total kind Of birds, in orderly array on wing, Came summoned over Eden to receive Their names of thee; so over many a tract Of Heaven they marched, and many a province wide, Tenfold the length of this terrene: At last, Far in the horizon to the north appeared From skirt to skirt a fiery region, stretched In battailous aspect, and nearer view Bristled with upright beams innumerable Of rigid spears, and helmets thronged, and shields Various, with boastful argument portrayed, The banded Powers of Satan hasting on With furious expedition; for they weened That self-same day, by fight or by surprise, To win the mount of God, and on his throne To set the Envier of his state, the proud Aspirer; but their thoughts proved fond and vain In the mid way: Though strange to us it seemed At first, that Angel should with Angel war, And in fierce hosting meet, who wont to meet So oft in festivals of joy and love Unanimous, as sons of one great Sire, Hymning the Eternal Father: But the shout Of battle now began, and rushing sound Of onset ended soon each milder thought. High in the midst, exalted as a God, The Apostate in his sun-bright chariot sat, Idol of majesty divine, enclosed With flaming Cherubim, and golden shields; Then lighted from his gorgeous throne, for now "twixt host and host but narrow space was left, A dreadful interval, and front to front Presented stood in terrible array Of hideous length: Before the cloudy van, On the rough edge of battle ere it joined, Satan, with vast and haughty strides advanced, Came towering, armed in adamant and gold; Abdiel that sight endured not, where he stood Among the mightiest, bent on highest deeds, And thus his own undaunted heart explores. O Heaven! that such resemblance of the Highest Should yet remain, where faith and realty Remain not: Wherefore should not strength and might There fail where virtue fails, or weakest prove Where boldest, though to fight unconquerable? His puissance, trusting in the Almighty's aid, I mean to try, whose reason I have tried Unsound and false; nor is it aught but just, That he, who in debate of truth hath won, Should win in arms, in both disputes alike Victor; though brutish that contest and foul, When reason hath to deal with force, yet so Most reason is that reason overcome. So pondering, and from his armed peers Forth stepping opposite, half-way he met His daring foe, at this prevention more Incensed, and thus securely him defied. Proud, art thou met? thy hope was to have reached The highth of thy aspiring unopposed, The throne of God unguarded, and his side Abandoned, at the terrour of thy power Or potent tongue: Fool!not to think how vain Against the Omnipotent to rise in arms; Who out of smallest things could, without end, Have raised incessant armies to defeat Thy folly; or with solitary hand Reaching beyond all limit, at one blow, Unaided, could have finished thee, and whelmed Thy legions under darkness: But thou seest All are not of thy train; there be, who faith Prefer, and piety to God, though then To thee not visible, when I alone Seemed in thy world erroneous to dissent From all: My sect thou seest;now learn too late How few sometimes may know, when thousands err. Whom the grand foe, with scornful eye askance, Thus answered. Ill for thee, but in wished hour Of my revenge, first sought for, thou returnest From flight, seditious Angel! to receive Thy merited reward, the first assay Of this right hand provoked, since first that tongue, Inspired with contradiction, durst oppose A third part of the Gods, in synod met Their deities to assert; who, while they feel Vigour divine within them, can allow Omnipotence to none. But well thou comest Before thy fellows, ambitious to win From me some plume, that thy success may show Destruction to the rest: This pause between, (Unanswered lest thou boast) to let thee know, At first I thought that Liberty and Heaven To heavenly souls had been all one; but now I see that most through sloth had rather serve, Ministring Spirits, trained up in feast and song! Such hast thou armed, the minstrelsy of Heaven, Servility with freedom to contend, As both their deeds compared this day shall prove. To whom in brief thus Abdiel stern replied. Apostate! still thou errest, nor end wilt find Of erring, from the path of truth remote: Unjustly thou depravest it with the name Of servitude, to serve whom God ordains, Or Nature: God and Nature bid the same, When he who rules is worthiest, and excels Them whom he governs. This is servitude, To serve the unwise, or him who hath rebelled Against his worthier, as thine now serve thee, Thyself not free, but to thyself enthralled; Yet lewdly darest our ministring upbraid. Reign thou in Hell, thy kingdom; let me serve In Heaven God ever blest, and his divine Behests obey, worthiest to be obeyed; Yet chains in Hell, not realms, expect: Mean while From me returned, as erst thou saidst, from flight, This greeting on thy impious crest receive. So saying, a noble stroke he lifted high, Which hung not, but so swift with tempest fell On the proud crest of Satan, that no sight, Nor motion of swift thought, less could his shield, Such ruin intercept: Ten paces huge He back recoiled; the tenth on bended knee His massy spear upstaid; as if on earth Winds under ground, or waters forcing way, Sidelong had pushed a mountain from his seat, Half sunk with all his pines. Amazement seised The rebel Thrones, but greater rage, to see Thus foiled their mightiest; ours joy filled, and shout, Presage of victory, and fierce desire Of battle: Whereat Michael bid sound The Arch-Angel trumpet; through the vast of Heaven It sounded, and the faithful armies rung Hosanna to the Highest: Nor stood at gaze The adverse legions, nor less hideous joined The horrid shock. Now storming fury rose, And clamour such as heard in Heaven till now Was never; arms on armour clashing brayed Horrible discord, and the madding wheels Of brazen chariots raged; dire was the noise Of conflict; over head the dismal hiss Of fiery darts in flaming vollies flew, And flying vaulted either host with fire. So under fiery cope together rushed Both battles main, with ruinous assault And inextinguishable rage. All Heaven Resounded; and had Earth been then, all Earth Had to her center shook. What wonder? when Millions of fierce encountering Angels fought On either side, the least of whom could wield These elements, and arm him with the force Of all their regions: How much more of power Army against army numberless to raise Dreadful combustion warring, and disturb, Though not destroy, their happy native seat; Had not the Eternal King Omnipotent, From his strong hold of Heaven, high over-ruled And limited their might; though numbered such As each divided legion might have seemed A numerous host; in strength each armed hand A legion; led in fight, yet leader seemed Each warriour single as in chief, expert When to advance, or stand, or turn the sway Of battle, open when, and when to close The ridges of grim war: No thought of flight, None of retreat, no unbecoming deed That argued fear; each on himself relied, As only in his arm the moment lay Of victory: Deeds of eternal fame Were done, but infinite; for wide was spread That war and various; sometimes on firm ground A standing fight, then, soaring on main wing, Tormented all the air; all air seemed then Conflicting fire. Long time in even scale The battle hung; till Satan, who that day Prodigious power had shown, and met in arms No equal, ranging through the dire attack Of fighting Seraphim confused, at length Saw where the sword of Michael smote, and felled Squadrons at once; with huge two-handed sway Brandished aloft, the horrid edge came down Wide-wasting; such destruction to withstand He hasted, and opposed the rocky orb Of tenfold adamant, his ample shield, A vast circumference. At his approach The great Arch-Angel from his warlike toil Surceased, and glad, as hoping here to end Intestine war in Heaven, the arch-foe subdued Or captive dragged in chains, with hostile frown And visage all inflamed first thus began. Author of evil, unknown till thy revolt, Unnamed in Heaven, now plenteous as thou seest These acts of hateful strife, hateful to all, Though heaviest by just measure on thyself, And thy adherents: How hast thou disturbed Heaven's blessed peace, and into nature brought Misery, uncreated till the crime Of thy rebellion! how hast thou instilled Thy malice into thousands, once upright And faithful, now proved false! But think not here To trouble holy rest; Heaven casts thee out From all her confines. Heaven, the seat of bliss, Brooks not the works of violence and war. Hence then, and evil go with thee along, Thy offspring, to the place of evil, Hell; Thou and thy wicked crew! there mingle broils, Ere this avenging sword begin thy doom, Or some more sudden vengeance, winged from God, Precipitate thee with augmented pain. So spake the Prince of Angels; to whom thus The Adversary. Nor think thou with wind Of aery threats to awe whom yet with deeds Thou canst not. Hast thou turned the least of these To flight, or if to fall, but that they rise Unvanquished, easier to transact with me That thou shouldst hope, imperious, and with threats To chase me hence? err not, that so shall end The strife which thou callest evil, but we style The strife of glory; which we mean to win, Or turn this Heaven itself into the Hell Thou fablest; here however to dwell free, If not to reign: Mean while thy utmost force, And join him named Almighty to thy aid, I fly not, but have sought thee far and nigh. They ended parle, and both addressed for fight Unspeakable; for who, though with the tongue Of Angels, can relate, or to what things Liken on earth conspicuous, that may lift Human imagination to such highth Of Godlike power? for likest Gods they seemed, Stood they or moved, in stature, motion, arms, Fit to decide the empire of great Heaven. Now waved their fiery swords, and in the air Made horrid circles; two broad suns their shields Blazed opposite, while Expectation stood In horrour: From each hand with speed retired, Where erst was thickest fight, the angelick throng, And left large field, unsafe within the wind Of such commotion; such as, to set forth Great things by small, if, nature's concord broke, Among the constellations war were sprung, Two planets, rushing from aspect malign Of fiercest opposition, in mid sky Should combat, and their jarring spheres confound. Together both with next to almighty arm Up-lifted imminent, one stroke they aimed That might determine, and not need repeat, As not of power at once; nor odds appeared In might or swift prevention: But the sword Of Michael from the armoury of God Was given him tempered so, that neither keen Nor solid might resist that edge: it met The sword of Satan, with steep force to smite Descending, and in half cut sheer; nor staid, But with swift wheel reverse, deep entering, shared All his right side: Then Satan first knew pain, And writhed him to and fro convolved; so sore The griding sword with discontinuous wound Passed through him: But the ethereal substance closed, Not long divisible; and from the gash A stream of necturous humour issuing flowed Sanguine, such as celestial Spirits may bleed, And all his armour stained, ere while so bright. Forthwith on all sides to his aid was run By Angels many and strong, who interposed Defence, while others bore him on their shields Back to his chariot, where it stood retired From off the files of war: There they him laid Gnashing for anguish, and despite, and shame, To find himself not matchless, and his pride Humbled by such rebuke, so far beneath His confidence to equal God in power. Yet soon he healed; for Spirits that live throughout Vital in every part, not as frail man In entrails, heart of head, liver or reins, Cannot but by annihilating die; Nor in their liquid texture mortal wound Receive, no more than can the fluid air: All heart they live, all head, all eye, all ear, All intellect, all sense; and, as they please, They limb themselves, and colour, shape, or size Assume, as?kikes them best, condense or rare. Mean while in other parts like deeds deserved Memorial, where the might of Gabriel fought, And with fierce ensigns pierced the deep array Of Moloch, furious king; who him defied, And at his chariot-wheels to drag him bound Threatened, nor from the Holy One of Heaven Refrained his tongue blasphemous; but anon Down cloven to the waist, with shattered arms And uncouth pain fled bellowing. On each wing Uriel, and Raphael, his vaunting foe, Though huge, and in a rock of diamond armed, Vanquished Adramelech, and Asmadai, Two potent Thrones, that to be less than Gods Disdained, but meaner thoughts learned in their flight, Mangled with ghastly wounds through plate and mail. Nor stood unmindful Abdiel to annoy The atheist crew, but with redoubled blow Ariel, and Arioch, and the violence Of Ramiel scorched and blasted, overthrew. I might relate of thousands, and their names Eternize here on earth; but those elect Angels, contented with their fame in Heaven, Seek not the praise of men: The other sort, In might though wonderous and in acts of war, Nor of renown less eager, yet by doom Cancelled from Heaven and sacred memory, Nameless in dark oblivion let them dwell. For strength from truth divided, and from just, Illaudable, nought merits but dispraise And ignominy; yet to glory aspires Vain-glorious, and through infamy seeks fame: Therefore eternal silence be their doom. And now, their mightiest quelled, the battle swerved, With many an inroad gored; deformed rout Entered, and foul disorder; all the ground With shivered armour strown, and on a heap Chariot and charioteer lay overturned, And fiery-foaming steeds; what stood, recoiled O'er-wearied, through the faint Satanick host Defensive scarce, or with pale fear surprised, Then first with fear surprised, and sense of pain, Fled ignominious, to such evil brought By sin of disobedience; till that hour Not liable to fear, or flight, or pain. Far otherwise the inviolable Saints, In cubick phalanx firm, advanced entire, Invulnerable, impenetrably armed; Such high advantages their innocence Gave them above their foes; not to have sinned, Not to have disobeyed; in fight they stood Unwearied, unobnoxious to be pained By wound, though from their place by violence moved, Now Night her course began, and, over Heaven Inducing darkness, grateful truce imposed, And silence on the odious din of war: Under her cloudy covert both retired, Victor and vanquished: On the foughten field Michael and his Angels prevalent Encamping, placed in guard their watches round, Cherubick waving fires: On the other part, Satan with his rebellious disappeared, Far in the dark dislodged; and, void of rest, His potentates to council called by night; And in the midst thus undismayed began. O now in danger tried, now known in arms Not to be overpowered, Companions dear, Found worthy not of liberty alone, Too mean pretence! but what we more affect, Honour, dominion, glory, and renown; Who have sustained one day in doubtful fight, (And if one day, why not eternal days?) What Heaven's Lord had powerfullest to send Against us from about his throne, and judged Sufficient to subdue us to his will, But proves not so: Then fallible, it seems, Of future we may deem him, though till now Omniscient thought. True is, less firmly armed, Some disadvantage we endured and pain, Till now not known, but, known, as soon contemned; Since now we find this our empyreal form Incapable of mortal injury, Imperishable, and, though pierced with wound, Soon closing, and by native vigour healed. Of evil then so small as easy think The remedy; perhaps more valid arms, Weapons more violent, when next we meet, May serve to better us, and worse our foes, Or equal what between us made the odds, In nature none: If other hidden cause Left them superiour, while we can preserve Unhurt our minds, and understanding sound, Due search and consultation will disclose. He sat; and in the assembly next upstood Nisroch, of Principalities the prime; As one he stood escaped from cruel fight, Sore toiled, his riven arms to havock hewn, And cloudy in aspect thus answering spake. Deliverer from new Lords, leader to free Enjoyment of our right as Gods; yet hard For Gods, and too unequal work we find, Against unequal arms to fight in pain, Against unpained, impassive; from which evil Ruin must needs ensue; for what avails Valour or strength, though matchless, quelled with pain Which all subdues, and makes remiss the hands Of mightiest? Sense of pleasure we may well Spare out of life perhaps, and not repine, But live content, which is the calmest life: But pain is perfect misery, the worst Of evils, and, excessive, overturns All patience. He, who therefore can invent With what more forcible we may offend Our yet unwounded enemies, or arm Ourselves with like defence, to me deserves No less than for deliverance what we owe. Whereto with look composed Satan replied. Not uninvented that, which thou aright Believest so main to our success, I bring. Which of us who beholds the bright surface Of this ethereous mould whereon we stand, This continent of spacious Heaven, adorned With plant, fruit, flower ambrosial, gems, and gold; Whose eye so superficially surveys These things, as not to mind from whence they grow Deep under ground, materials dark and crude, Of spiritous and fiery spume, till touched With Heaven's ray, and tempered, they shoot forth So beauteous, opening to the ambient light? These in their dark nativity the deep Shall yield us, pregnant with infernal flame; Which, into hollow engines, long and round, Thick rammed, at the other bore with touch of fire Dilated and infuriate, shall send forth From far, with thundering noise, among our foes Such implements of mischief, as shall dash To pieces, and o'erwhelm whatever stands Adverse, that they shall fear we have disarmed The Thunderer of his only dreaded bolt. Nor long shall be our labour; yet ere dawn, Effect shall end our wish. Mean while revive; Abandon fear; to strength and counsel joined Think nothing hard, much less to be despaired. He ended, and his words their drooping cheer Enlightened, and their languished hope revived. The invention all admired, and each, how he To be the inventer missed; so easy it seemed Once found, which yet unfound most would have thought Impossible: Yet, haply, of thy race In future days, if malice should abound, Some one intent on mischief, or inspired With devilish machination, might devise Like instrument to plague the sons of men For sin, on war and mutual slaughter bent. Forthwith from council to the work they flew; None arguing stood; innumerable hands Were ready; in a moment up they turned Wide the celestial soil, and saw beneath The originals of nature in their crude Conception; sulphurous and nitrous foam They found, they mingled, and, with subtle art, Concocted and adusted they reduced To blackest grain, and into store conveyed: Part hidden veins digged up (nor hath this earth Entrails unlike) of mineral and stone, Whereof to found their engines and their balls Of missive ruin; part incentive reed Provide, pernicious with one touch to fire. So all ere day-spring, under conscious night, Secret they finished, and in order set, With silent circumspection, unespied. Now when fair morn orient in Heaven appeared, Up rose the victor-Angels, and to arms The matin trumpet sung: In arms they stood Of golden panoply, refulgent host, Soon banded; others from the dawning hills Look round, and scouts each coast light-armed scour, Each quarter to descry the distant foe, Where lodged, or whither fled, or if for fight, In motion or in halt: Him soon they met Under spread ensigns moving nigh, in slow But firm battalion; back with speediest sail Zophiel, of Cherubim the swiftest wing, Came flying, and in mid air aloud thus cried. Arm, Warriours, arm for fight; the foe at hand, Whom fled we thought, will save us long pursuit This day; fear not his flight;so thick a cloud He comes, and settled in his face I see Sad resolution, and secure: Let each His adamantine coat gird well, and each Fit well his helm, gripe fast his orbed shield, Borne even or high; for this day will pour down, If I conjecture aught, no drizzling shower, But rattling storm of arrows barbed with fire. So warned he them, aware themselves, and soon In order, quit of all impediment; Instant without disturb they took alarm, And onward moved embattled: When behold! Not distant far with heavy pace the foe Approaching gross and huge, in hollow cube Training his devilish enginery, impaled On every side with shadowing squadrons deep, To hide the fraud. At interview both stood A while; but suddenly at head appeared Satan, and thus was heard commanding loud. Vanguard, to right and left the front unfold; That all may see who hate us, how we seek Peace and composure, and with open breast Stand ready to receive them, if they like Our overture; and turn not back perverse: But that I doubt; however witness, Heaven! Heaven, witness thou anon! while we discharge Freely our part: ye, who appointed stand Do as you have in charge, and briefly touch What we propound, and loud that all may hear! So scoffing in ambiguous words, he scarce Had ended; when to right and left the front Divided, and to either flank retired: Which to our eyes discovered, new and strange, A triple mounted row of pillars laid On wheels (for like to pillars most they seemed, Or hollowed bodies made of oak or fir, With branches lopt, in wood or mountain felled,) Brass, iron, stony mould, had not their mouths With hideous orifice gaped on us wide, Portending hollow truce: At each behind A Seraph stood, and in his hand a reed Stood waving tipt with fire; while we, suspense, Collected stood within our thoughts amused, Not long; for sudden all at once their reeds Put forth, and to a narrow vent applied With nicest touch. Immediate in a flame, But soon obscured with smoke, all Heaven appeared, From those deep-throated engines belched, whose roar Embowelled with outrageous noise the air, And all her entrails tore, disgorging foul Their devilish glut, chained thunderbolts and hail Of iron globes; which, on the victor host Levelled, with such impetuous fury smote, That, whom they hit, none on their feet might stand, Though standing else as rocks, but down they fell By thousands, Angel on Arch-Angel rolled; The sooner for their arms; unarmed, they might Have easily, as Spirits, evaded swift By quick contraction or remove; but now Foul dissipation followed, and forced rout; Nor served it to relax their serried files. What should they do? if on they rushed, repulse Repeated, and indecent overthrow Doubled, would render them yet more despised, And to their foes a laughter; for in view Stood ranked of Seraphim another row, In posture to displode their second tire Of thunder: Back defeated to return They worse abhorred. Satan beheld their plight, And to his mates thus in derision called. O Friends! why come not on these victors proud Ere while they fierce were coming; and when we, To entertain them fair with open front And breast, (what could we more?) propounded terms Of composition, straight they changed their minds, Flew off, and into strange vagaries fell, As they would dance; yet for a dance they seemed Somewhat extravagant and wild; perhaps For joy of offered peace: But I suppose, If our proposals once again were heard, We should compel them to a quick result. To whom thus Belial, in like gamesome mood. Leader! the terms we sent were terms of weight, Of hard contents, and full of force urged home; Such as we might perceive amused them all, And stumbled many: Who receives them right, Had need from head to foot well understand; Not understood, this gift they have besides, They show us when our foes walk not upright. So they among themselves in pleasant vein Stood scoffing, hightened in their thoughts beyond All doubt of victory: Eternal Might To match with their inventions they presumed So easy, and of his thunder made a scorn, And all his host derided, while they stood A while in trouble: But they stood not long; Rage prompted them at length, and found them arms Against such hellish mischief fit to oppose. Forthwith (behold the excellence, the power, Which God hath in his mighty Angels placed!) Their arms away they threw, and to the hills (For Earth hath this variety from Heaven Of pleasure situate in hill and dale,) Light as the lightning glimpse they ran, they flew; From their foundations loosening to and fro, They plucked the seated hills, with all their load, Rocks, waters, woods, and by the shaggy tops Up-lifting bore them in their hands: Amaze, Be sure, and terrour, seized the rebel host, When coming towards them so dread they saw The bottom of the mountains upward turned; Till on those cursed engines' triple-row They saw them whelmed, and all their confidence Under the weight of mountains buried deep; Themselves invaded next, and on their heads Main promontories flung, which in the air Came shadowing, and oppressed whole legions armed; Their armour helped their harm, crushed in and bruised Into their substance pent, which wrought them pain Implacable, and many a dolorous groan; Long struggling underneath, ere they could wind Out of such prison, though Spirits of purest light, Purest at first, now gross by sinning grown. The rest, in imitation, to like arms Betook them, and the neighbouring hills uptore: So hills amid the air encountered hills, Hurled to and fro with jaculation dire; That under ground they fought in dismal shade; Infernal noise! war seemed a civil game To this uproar; horrid confusion heaped Upon confusion rose: And now all Heaven Had gone to wrack, with ruin overspread; Had not the Almighty Father, where he sits Shrined in his sanctuary of Heaven secure, Consulting on the sum of things, foreseen This tumult, and permitted all, advised: That his great purpose he might so fulfil, To honour his anointed Son avenged Upon his enemies, and to declare All power on him transferred: Whence to his Son, The Assessour of his throne, he thus began. Effulgence of my glory, Son beloved, Son, in whose face invisible is beheld Visibly, what by Deity I am; And in whose hand what by decree I do, Second Omnipotence! two days are past, Two days, as we compute the days of Heaven, Since Michael and his Powers went forth to tame These disobedient: Sore hath been their fight, As likeliest was, when two such foes met armed; For to themselves I left them; and thou knowest, Equal in their creation they were formed, Save what sin hath impaired; which yet hath wrought Insensibly, for I suspend their doom; Whence in perpetual fight they needs must last Endless, and no solution will be found: War wearied hath performed what war can do, And to disordered rage let loose the reins With mountains, as with weapons, armed; which makes Wild work in Heaven, and dangerous to the main. Two days are therefore past, the third is thine; For thee I have ordained it; and thus far Have suffered, that the glory may be thine Of ending this great war, since none but Thou Can end it. Into thee such virtue and grace Immense I have transfused, that all may know In Heaven and Hell thy power above compare; And, this perverse commotion governed thus, To manifest thee worthiest to be Heir Of all things; to be Heir, and to be King By sacred unction, thy deserved right. Go then, Thou Mightiest, in thy Father's might; Ascend my chariot, guide the rapid wheels That shake Heaven's basis, bring forth all my war, My bow and thunder, my almighty arms Gird on, and sword upon thy puissant thigh; Pursue these sons of darkness, drive them out From all Heaven's bounds into the utter deep: There let them learn, as likes them, to despise God, and Messiah his anointed King. He said, and on his Son with rays direct Shone full; he all his Father full expressed Ineffably into his face received; And thus the Filial Godhead answering spake. O Father, O Supreme of heavenly Thrones, First, Highest, Holiest, Best; thou always seek'st To glorify thy Son, I always thee, As is most just: This I my glory account, My exaltation, and my whole delight, That thou, in me well pleased, declarest thy will Fulfilled, which to fulfil is all my bliss. Scepter and power, thy giving, I assume, And gladlier shall resign, when in the end Thou shalt be all in all, and I in thee For ever; and in me all whom thou lovest: But whom thou hatest, I hate, and can put on Thy terrours, as I put thy mildness on, Image of thee in all things; and shall soon, Armed with thy might, rid Heaven of these rebelled; To their prepared ill mansion driven down, To chains of darkness, and the undying worm; That from thy just obedience could revolt, Whom to obey is happiness entire. Then shall thy Saints unmixed, and from the impure Far separate, circling thy holy mount, Unfeigned Halleluiahs to thee sing, Hymns of high praise, and I among them Chief. So said, he, o'er his scepter bowing, rose From the right hand of Glory where he sat; And the third sacred morn began to shine, Dawning through Heaven. Forth rushed with whirlwind sound The chariot of Paternal Deity, Flashing thick flames, wheel within wheel undrawn, Itself instinct with Spirit, but convoyed By four Cherubick shapes; four faces each Had wonderous; as with stars, their bodies all And wings were set with eyes; with eyes the wheels Of beryl, and careering fires between; Over their heads a crystal firmament, Whereon a sapphire throne, inlaid with pure Amber, and colours of the showery arch. He, in celestial panoply all armed Of radiant Urim, work divinely wrought, Ascended; at his right hand Victory Sat eagle-winged; beside him hung his bow And quiver with three-bolted thunder stored; And from about him fierce effusion rolled Of smoke, and bickering flame, and sparkles dire: Attended with ten thousand thousand Saints, He onward came; far off his coming shone; And twenty thousand (I their number heard) Chariots of God, half on each hand, were seen; He on the wings of Cherub rode sublime On the crystalline sky, in sapphire throned, Illustrious far and wide; but by his own First seen: Them unexpected joy surprised, When the great ensign of Messiah blazed Aloft by Angels borne, his sign in Heaven; Under whose conduct Michael soon reduced His army, circumfused on either wing, Under their Head imbodied all in one. Before him Power Divine his way prepared; At his command the uprooted hills retired Each to his place; they heard his voice, and went Obsequious; Heaven his wonted face renewed, And with fresh flowerets hill and valley smiled. This saw his hapless foes, but stood obdured, And to rebellious fight rallied their Powers, Insensate, hope conceiving from despair. In heavenly Spirits could such perverseness dwell? But to convince the proud what signs avail, Or wonders move the obdurate to relent? They, hardened more by what might most reclaim, Grieving to see his glory, at the sight Took envy; and, aspiring to his highth, Stood re-embattled fierce, by force or fraud Weening to prosper, and at length prevail Against God and Messiah, or to fall In universal ruin last; and now To final battle drew, disdaining flight, Or faint retreat; when the great Son of God To all his host on either hand thus spake. Stand still in bright array, ye Saints; here stand, Ye Angels armed; this day from battle rest: Faithful hath been your warfare, and of God Accepted, fearless in his righteous cause; And as ye have received, so have ye done, Invincibly: But of this cursed crew The punishment to other hand belongs; Vengeance is his, or whose he sole appoints: Number to this day's work is not ordained, Nor multitude; stand only, and behold God's indignation on these godless poured By me; not you, but me, they have despised, Yet envied; against me is all their rage, Because the Father, to whom in Heaven s'preme Kingdom, and power, and glory appertains, Hath honoured me, according to his will. Therefore to me their doom he hath assigned; That they may have their wish, to try with me In battle which the stronger proves; they all, Or I alone against them; since by strength They measure all, of other excellence Not emulous, nor care who them excels; Nor other strife with them do I vouchsafe. So spake the Son, and into terrour changed His countenance too severe to be beheld, And full of wrath bent on his enemies. At once the Four spread out their starry wings With dreadful shade contiguous, and the orbs Of his fierce chariot rolled, as with the sound Of torrent floods, or of a numerous host. He on his impious foes right onward drove, Gloomy as night; under his burning wheels The stedfast empyrean shook throughout, All but the throne itself of God. Full soon Among them he arrived; in his right hand Grasping ten thousand thunders, which he sent Before him, such as in their souls infixed Plagues: They, astonished, all resistance lost, All courage; down their idle weapons dropt: O'er shields, and helms, and helmed heads he rode Of Thrones and mighty Seraphim prostrate, That wished the mountains now might be again Thrown on them, as a shelter from his ire. Nor less on either side tempestuous fell His arrows, from the fourfold-visaged Four Distinct with eyes, and from the living wheels Distinct alike with multitude of eyes; One Spirit in them ruled; and every eye Glared lightning, and shot forth pernicious fire Among the accursed, that withered all their strength, And of their wonted vigour left them drained, Exhausted, spiritless, afflicted, fallen. Yet half his strength he put not forth, but checked His thunder in mid volley; for he meant Not to destroy, but root them out of Heaven: The overthrown he raised, and as a herd Of goats or timorous flock together thronged Drove them before him thunder-struck, pursued With terrours, and with furies, to the bounds And crystal wall of Heaven; which, opening wide, Rolled inward, and a spacious gap disclosed Into the wasteful deep: The monstrous sight Struck them with horrour backward, but far worse Urged them behind: Headlong themselves they threw Down from the verge of Heaven; eternal wrath Burnt after them to the bottomless pit. Hell heard the unsufferable noise, Hell saw Heaven ruining from Heaven, and would have fled Affrighted; but strict Fate had cast too deep Her dark foundations, and too fast had bound. Nine days they fell: Confounded Chaos roared, And felt tenfold confusion in their fall Through his wild anarchy, so huge a rout Incumbered him with ruin: Hell at last Yawning received them whole, and on them closed; Hell, their fit habitation, fraught with fire Unquenchable, the house of woe and pain. Disburdened Heaven rejoiced, and soon repaired Her mural breach, returning whence it rolled. Sole victor, from the expulsion of his foes, Messiah his triumphal chariot turned: To meet him all his Saints, who silent stood Eye-witnesses of his almighty acts, With jubilee advanced; and, as they went, Shaded with branching palm, each Order bright, Sung triumph, and him sung victorious King, Son, Heir, and Lord, to him dominion given, Worthiest to reign: He, celebrated, rode Triumphant through mid Heaven, into the courts And temple of his Mighty Father throned On high; who into glory him received, Where now he sits at the right hand of bliss. Thus, measuring things in Heaven by things on Earth, At thy request, and that thou mayest beware By what is past, to thee I have revealed What might have else to human race been hid; The discord which befel, and war in Heaven Among the angelick Powers, and the deep fall Of those too high aspiring, who rebelled With Satan; he who envies now thy state, Who now is plotting how he may seduce Thee also from obedience, that, with him Bereaved of happiness, thou mayest partake His punishment, eternal misery; Which would be all his solace and revenge, As a despite done against the Most High, Thee once to gain companion of his woe. But listen not to his temptations, warn Thy weaker; let it profit thee to have heard, By terrible example, the reward Of disobedience; firm they might have stood, Yet fell; remember, and fear to transgress. Book VII Descend from Heaven, Urania, by that name If rightly thou art called, whose voice divine Following, above the Olympian hill I soar, Above the flight of Pegasean wing! The meaning, not the name, I call: for thou Nor of the Muses nine, nor on the top Of old Olympus dwellest; but, heavenly-born, Before the hills appeared, or fountain flowed, Thou with eternal Wisdom didst converse, Wisdom thy sister, and with her didst play In presence of the Almighty Father, pleased With thy celestial song. Up led by thee Into the Heaven of Heavens I have presumed, An earthly guest, and drawn empyreal air, Thy tempering: with like safety guided down Return me to my native element: Lest from this flying steed unreined, (as once Bellerophon, though from a lower clime,) Dismounted, on the Aleian field I fall, Erroneous there to wander, and forlorn. Half yet remains unsung, but narrower bound Within the visible diurnal sphere; Standing on earth, not rapt above the pole, More safe I sing with mortal voice, unchanged To hoarse or mute, though fallen on evil days, On evil days though fallen, and evil tongues; In darkness, and with dangers compassed round, And solitude; yet not alone, while thou Visitest my slumbers nightly, or when morn Purples the east: still govern thou my song, Urania, and fit audience find, though few. But drive far off the barbarous dissonance Of Bacchus and his revellers, the race Of that wild rout that tore the Thracian bard In Rhodope, where woods and rocks had ears To rapture, till the savage clamour drowned Both harp and voice; nor could the Muse defend Her son. So fail not thou, who thee implores: For thou art heavenly, she an empty dream. Say, Goddess, what ensued when Raphael, The affable Arch-Angel, had forewarned Adam, by dire example, to beware Apostasy, by what befel in Heaven To those apostates; lest the like befall In Paradise to Adam or his race, Charged not to touch the interdicted tree, If they transgress, and slight that sole command, So easily obeyed amid the choice Of all tastes else to please their appetite, Though wandering. He, with his consorted Eve, The story heard attentive, and was filled With admiration and deep muse, to hear Of things so high and strange; things, to their thought So unimaginable, as hate in Heaven, And war so near the peace of God in bliss, With such confusion: but the evil, soon Driven back, redounded as a flood on those From whom it sprung; impossible to mix With blessedness. Whence Adam soon repealed The doubts that in his heart arose: and now Led on, yet sinless, with desire to know What nearer might concern him, how this world Of Heaven and Earth conspicuous first began; When, and whereof created; for what cause; What within Eden, or without, was done Before his memory; as one whose drouth Yet scarce allayed still eyes the current stream, Whose liquid murmur heard new thirst excites, Proceeded thus to ask his heavenly guest. Great things, and full of wonder in our ears, Far differing from this world, thou hast revealed, Divine interpreter! by favour sent Down from the empyrean, to forewarn Us timely of what might else have been our loss, Unknown, which human knowledge could not reach; For which to the infinitely Good we owe Immortal thanks, and his admonishment Receive, with solemn purpose to observe Immutably his sovran will, the end Of what we are. But since thou hast vouchsafed Gently, for our instruction, to impart Things above earthly thought, which yet concerned Our knowing, as to highest wisdom seemed, Deign to descend now lower, and relate What may no less perhaps avail us known, How first began this Heaven which we behold Distant so high, with moving fires adorned Innumerable; and this which yields or fills All space, the ambient air wide interfused Embracing round this floried Earth; what cause Moved the Creator, in his holy rest Through all eternity, so late to build In Chaos; and the work begun, how soon Absolved; if unforbid thou mayest unfold What we, not to explore the secrets ask Of his eternal empire, but the more To magnify his works, the more we know. And the great light of day yet wants to run Much of his race though steep; suspense in Heaven, Held by thy voice, thy potent voice, he hears, And longer will delay to hear thee tell His generation, and the rising birth Of Nature from the unapparent Deep: Or if the star of evening and the moon Haste to thy audience, Night with her will bring, Silence; and Sleep, listening to thee, will watch; Or we can bid his absence, till thy song End, and dismiss thee ere the morning shine. Thus Adam his illustrious guest besought: And thus the Godlike Angel answered mild. This also thy request, with caution asked, Obtain; though to recount almighty works What words or tongue of Seraph can suffice, Or heart of man suffice to comprehend? Yet what thou canst attain, which best may serve To glorify the Maker, and infer Thee also happier, shall not be withheld Thy hearing; such commission from above I have received, to answer thy desire Of knowledge within bounds; beyond, abstain To ask; nor let thine own inventions hope Things not revealed, which the invisible King, Only Omniscient, hath suppressed in night; To none communicable in Earth or Heaven: Enough is left besides to search and know. But knowledge is as food, and needs no less Her temperance over appetite, to know In measure what the mind may well contain; Oppresses else with surfeit, and soon turns Wisdom to folly, as nourishment to wind. Know then, that, after Lucifer from Heaven (So call him, brighter once amidst the host Of Angels, than that star the stars among,) Fell with his flaming legions through the deep Into his place, and the great Son returned Victorious with his Saints, the Omnipotent Eternal Father from his throne beheld Their multitude, and to his Son thus spake. At least our envious Foe hath failed, who thought All like himself rebellious, by whose aid This inaccessible high strength, the seat Of Deity supreme, us dispossessed, He trusted to have seised, and into fraud Drew many, whom their place knows here no more: Yet far the greater part have kept, I see, Their station; Heaven, yet populous, retains Number sufficient to possess her realms Though wide, and this high temple to frequent With ministeries due, and solemn rites: But, lest his heart exalt him in the harm Already done, to have dispeopled Heaven, My damage fondly deemed, I can repair That detriment, if such it be to lose Self-lost; and in a moment will create Another world, out of one man a race Of men innumerable, there to dwell, Not here; till, by degrees of merit raised, They open to themselves at length the way Up hither, under long obedience tried; And Earth be changed to Heaven, and Heaven to Earth, One kingdom, joy and union without end. Mean while inhabit lax, ye Powers of Heaven; And thou my Word, begotten Son, by thee This I perform; speak thou, and be it done! My overshadowing Spirit and Might with thee I send along; ride forth, and bid the Deep Within appointed bounds be Heaven and Earth; Boundless the Deep, because I Am who fill Infinitude, nor vacuous the space. Though I, uncircumscribed myself, retire, And put not forth my goodness, which is free To act or not, Necessity and Chance Approach not me, and what I will is Fate. So spake the Almighty, and to what he spake His Word, the Filial Godhead, gave effect. Immediate are the acts of God, more swift Than time or motion, but to human ears Cannot without process of speech be told, So told as earthly notion can receive. Great triumph and rejoicing was in Heaven, When such was heard declared the Almighty's will; Glory they sung to the Most High, good will To future men, and in their dwellings peace; Glory to Him, whose just avenging ire Had driven out the ungodly from his sight And the habitations of the just; to Him Glory and praise, whose wisdom had ordained Good out of evil to create; instead Of Spirits malign, a better race to bring Into their vacant room, and thence diffuse His good to worlds and ages infinite. So sang the Hierarchies: Mean while the Son On his great expedition now appeared, Girt with Omnipotence, with radiance crowned Of Majesty Divine; sapience and love Immense, and all his Father in him shone. About his chariot numberless were poured Cherub, and Seraph, Potentates, and Thrones, And Virtues, winged Spirits, and chariots winged From the armoury of God; where stand of old Myriads, between two brazen mountains lodged Against a solemn day, harnessed at hand, Celestial equipage; and now came forth Spontaneous, for within them Spirit lived, Attendant on their Lord: Heaven opened wide Her ever-during gates, harmonious sound On golden hinges moving, to let forth The King of Glory, in his powerful Word And Spirit, coming to create new worlds. On heavenly ground they stood; and from the shore They viewed the vast immeasurable abyss Outrageous as a sea, dark, wasteful, wild, Up from the bottom turned by furious winds And surging waves, as mountains, to assault Heaven's highth, and with the center mix the pole. Silence, ye troubled Waves, and thou Deep, peace, Said then the Omnifick Word; your discord end! Nor staid; but, on the wings of Cherubim Uplifted, in paternal glory rode Far into Chaos, and the world unborn; For Chaos heard his voice: Him all his train Followed in bright procession, to behold Creation, and the wonders of his might. Then staid the fervid wheels, and in his hand He took the golden compasses, prepared In God's eternal store, to circumscribe This universe, and all created things: One foot he centered, and the other turned Round through the vast profundity obscure; And said, Thus far extend, thus far thy bounds, This be thy just circumference, O World! Thus God the Heaven created, thus the Earth, Matter unformed and void: Darkness profound Covered the abyss: but on the watery calm His brooding wings the Spirit of God outspread, And vital virtue infused, and vital warmth Throughout the fluid mass; but downward purged The black tartareous cold infernal dregs, Adverse to life: then founded, then conglobed Like things to like; the rest to several place Disparted, and between spun out the air; And Earth self-balanced on her center hung. Let there be light, said God; and forthwith Light Ethereal, first of things, quintessence pure, Sprung from the deep; and from her native east To journey through the aery gloom began, Sphered in a radiant cloud, for yet the sun Was not; she in a cloudy tabernacle Sojourned the while. God saw the light was good; And light from darkness by the hemisphere Divided: light the Day, and darkness Night, He named. Thus was the first day even and morn: Nor past uncelebrated, nor unsung By the celestial quires, when orient light Exhaling first from darkness they beheld; Birth-day of Heaven and Earth; with joy and shout The hollow universal orb they filled, And touched their golden harps, and hymning praised God and his works; Creator him they sung, Both when first evening was, and when first morn. Again, God said, Let there be firmament Amid the waters, and let it divide The waters from the waters; and God made The firmament, expanse of liquid, pure, Transparent, elemental air, diffused In circuit to the uttermost convex Of this great round; partition firm and sure, The waters underneath from those above Dividing: for as earth, so he the world Built on circumfluous waters calm, in wide Crystalline ocean, and the loud misrule Of Chaos far removed; lest fierce extremes Contiguous might distemper the whole frame: And Heaven he named the Firmament: So even And morning chorus sung the second day. The Earth was formed, but in the womb as yet Of waters, embryon immature involved, Appeared not: over all the face of Earth Main ocean flowed, not idle; but, with warm Prolifick humour softening all her globe, Fermented the great mother to conceive, Satiate with genial moisture; when God said, Be gathered now ye waters under Heaven Into one place, and let dry land appear. Immediately the mountains huge appear Emergent, and their broad bare backs upheave Into the clouds; their tops ascend the sky: So high as heaved the tumid hills, so low Down sunk a hollow bottom broad and deep, Capacious bed of waters: Thither they Hasted with glad precipitance, uprolled, As drops on dust conglobing from the dry: Part rise in crystal wall, or ridge direct, For haste; such flight the great command impressed On the swift floods: As armies at the call Of trumpet (for of armies thou hast heard) Troop to their standard; so the watery throng, Wave rolling after wave, where way they found, If steep, with torrent rapture, if through plain, Soft-ebbing; nor withstood them rock or hill; But they, or under ground, or circuit wide With serpent errour wandering, found their way, And on the washy oose deep channels wore; Easy, ere God had bid the ground be dry, All but within those banks, where rivers now Stream, and perpetual draw their humid train. The dry land, Earth; and the great receptacle Of congregated waters, he called Seas: And saw that it was good; and said, Let the Earth Put forth the verdant grass, herb yielding seed, And fruit-tree yielding fruit after her kind, Whose seed is in herself upon the Earth. He scarce had said, when the bare Earth, till then Desart and bare, unsightly, unadorned, Brought forth the tender grass, whose verdure clad Her universal face with pleasant green; Then herbs of every leaf, that sudden flowered Opening their various colours, and made gay Her bosom, smelling sweet: and, these scarce blown, Forth flourished thick the clustering vine, forth crept The swelling gourd, up stood the corny reed Embattled in her field, and the humble shrub, And bush with frizzled hair implicit: Last Rose, as in dance, the stately trees, and spread Their branches hung with copious fruit, or gemmed Their blossoms: With high woods the hills were crowned; With tufts the valleys, and each fountain side; With borders long the rivers: that Earth now Seemed like to Heaven, a seat where Gods might dwell, Or wander with delight, and love to haunt Her sacred shades: though God had yet not rained Upon the Earth, and man to till the ground None was; but from the Earth a dewy mist Went up, and watered all the ground, and each Plant of the field; which, ere it was in the Earth, God made, and every herb, before it grew On the green stem: God saw that it was good: So even and morn recorded the third day. Again the Almighty spake, Let there be lights High in the expanse of Heaven, to divide The day from night; and let them be for signs, For seasons, and for days, and circling years; And let them be for lights, as I ordain Their office in the firmament of Heaven, To give light on the Earth; and it was so. And God made two great lights, great for their use To Man, the greater to have rule by day, The less by night, altern; and made the stars, And set them in the firmament of Heaven To illuminate the Earth, and rule the day In their vicissitude, and rule the night, And light from darkness to divide. God saw, Surveying his great work, that it was good: For of celestial bodies first the sun A mighty sphere he framed, unlightsome first, Though of ethereal mould: then formed the moon Globose, and every magnitude of stars, And sowed with stars the Heaven, thick as a field: Of light by far the greater part he took, Transplanted from her cloudy shrine, and placed In the sun's orb, made porous to receive And drink the liquid light; firm to retain Her gathered beams, great palace now of light. Hither, as to their fountain, other stars Repairing, in their golden urns draw light, And hence the morning-planet gilds her horns; By tincture or reflection they augment Their small peculiar, though from human sight So far remote, with diminution seen, First in his east the glorious lamp was seen, Regent of day, and all the horizon round Invested with bright rays, jocund to run His longitude through Heaven's high road; the gray Dawn, and the Pleiades, before him danced, Shedding sweet influence: Less bright the moon, But opposite in levelled west was set, His mirrour, with full face borrowing her light From him; for other light she needed none In that aspect, and still that distance keeps Till night; then in the east her turn she shines, Revolved on Heaven's great axle, and her reign With thousand lesser lights dividual holds, With thousand thousand stars, that then appeared Spangling the hemisphere: Then first adorned With their bright luminaries that set and rose, Glad evening and glad morn crowned the fourth day. And God said, Let the waters generate Reptile with spawn abundant, living soul: And let fowl fly above the Earth, with wings Displayed on the open firmament of Heaven. And God created the great whales, and each Soul living, each that crept, which plenteously The waters generated by their kinds; And every bird of wing after his kind; And saw that it was good, and blessed them, saying. Be fruitful, multiply, and in the seas, And lakes, and running streams, the waters fill; And let the fowl be multiplied, on the Earth. Forthwith the sounds and seas, each creek and bay, With fry innumerable swarm, and shoals Of fish that with their fins, and shining scales, Glide under the green wave, in sculls that oft Bank the mid sea: part single, or with mate, Graze the sea-weed their pasture, and through groves Of coral stray; or, sporting with quick glance, Show to the sun their waved coats dropt with gold; Or, in their pearly shells at ease, attend Moist nutriment; or under rocks their food In jointed armour watch: on smooth the seal And bended dolphins play: part huge of bulk Wallowing unwieldy, enormous in their gait, Tempest the ocean: there leviathan, Hugest of living creatures, on the deep Stretched like a promontory sleeps or swims, And seems a moving land; and at his gills Draws in, and at his trunk spouts out, a sea. Mean while the tepid caves, and fens, and shores, Their brood as numerous hatch, from the egg that soon Bursting with kindly rupture forth disclosed Their callow young; but feathered soon and fledge They summed their pens; and, soaring the air sublime, With clang despised the ground, under a cloud In prospect; there the eagle and the stork On cliffs and cedar tops their eyries build: Part loosely wing the region, part more wise In common, ranged in figure, wedge their way, Intelligent of seasons, and set forth Their aery caravan, high over seas Flying, and over lands, with mutual wing Easing their flight; so steers the prudent crane Her annual voyage, borne on winds; the air Floats as they pass, fanned with unnumbered plumes: From branch to branch the smaller birds with song Solaced the woods, and spread their painted wings Till even; nor then the solemn nightingale Ceased warbling, but all night tun'd her soft lays: Others, on silver lakes and rivers, bathed Their downy breast; the swan with arched neck, Between her white wings mantling proudly, rows Her state with oary feet; yet oft they quit The dank, and, rising on stiff pennons, tower The mid aereal sky: Others on ground Walked firm; the crested cock whose clarion sounds The silent hours, and the other whose gay train Adorns him, coloured with the florid hue Of rainbows and starry eyes. The waters thus With fish replenished, and the air with fowl, Evening and morn solemnized the fifth day. The sixth, and of creation last, arose With evening harps and matin; when God said, Let the Earth bring forth soul living in her kind, Cattle, and creeping things, and beast of the Earth, Each in their kind. The Earth obeyed, and straight Opening her fertile womb teemed at a birth Innumerous living creatures, perfect forms, Limbed and full grown: Out of the ground up rose, As from his lair, the wild beast where he wons In forest wild, in thicket, brake, or den; Among the trees in pairs they rose, they walked: The cattle in the fields and meadows green: Those rare and solitary, these in flocks Pasturing at once, and in broad herds upsprung. The grassy clods now calved; now half appeared The tawny lion, pawing to get free His hinder parts, then springs as broke from bonds, And rampant shakes his brinded mane; the ounce, The libbard, and the tiger, as the mole Rising, the crumbled earth above them threw In hillocks: The swift stag from under ground Bore up his branching head: Scarce from his mould Behemoth biggest born of earth upheaved His vastness: Fleeced the flocks and bleating rose, As plants: Ambiguous between sea and land The river-horse, and scaly crocodile. At once came forth whatever creeps the ground, Insect or worm: those waved their limber fans For wings, and smallest lineaments exact In all the liveries decked of summer's pride With spots of gold and purple, azure and green: These, as a line, their long dimension drew, Streaking the ground with sinuous trace; not all Minims of nature; some of serpent-kind, Wonderous in length and corpulence, involved Their snaky folds, and added wings. First crept The parsimonious emmet, provident Of future; in small room large heart enclosed; Pattern of just equality perhaps Hereafter, joined in her popular tribes Of commonalty: Swarming next appeared The female bee, that feeds her husband drone Deliciously, and builds her waxen cells With honey stored: The rest are numberless, And thou their natures knowest, and gavest them names, Needless to thee repeated; nor unknown The serpent, subtlest beast of all the field, Of huge extent sometimes, with brazen eyes And hairy mane terrifick, though to thee Not noxious, but obedient at thy call. Now Heaven in all her glory shone, and rolled Her motions, as the great first Mover's hand First wheeled their course: Earth in her rich attire Consummate lovely smiled; air, water, earth, By fowl, fish, beast, was flown, was swum, was walked, Frequent; and of the sixth day yet remained: There wanted yet the master-work, the end Of all yet done; a creature, who, not prone And brute as other creatures, but endued With sanctity of reason, might erect His stature, and upright with front serene Govern the rest, self-knowing; and from thence Magnanimous to correspond with Heaven, But grateful to acknowledge whence his good Descends, thither with heart, and voice, and eyes Directed in devotion, to adore And worship God Supreme, who made him chief Of all his works: therefore the Omnipotent Eternal Father (for where is not he Present?) thus to his Son audibly spake. Let us make now Man in our image, Man In our similitude, and let them rule Over the fish and fowl of sea and air, Beast of the field, and over all the Earth, And every creeping thing that creeps the ground. This said, he formed thee, Adam, thee, O Man, Dust of the ground, and in thy nostrils breathed The breath of life; in his own image he Created thee, in the image of God Express; and thou becamest a living soul. Male he created thee; but thy consort Female, for race; then blessed mankind, and said, Be fruitful, multiply, and fill the Earth; Subdue it, and throughout dominion hold Over fish of the sea, and fowl of the air, And every living thing that moves on the Earth. Wherever thus created, for no place Is yet distinct by name, thence, as thou knowest, He brought thee into this delicious grove, This garden, planted with the trees of God, Delectable both to behold and taste; And freely all their pleasant fruit for food Gave thee; all sorts are here that all the Earth yields, Variety without end; but of the tree, Which, tasted, works knowledge of good and evil, Thou mayest not; in the day thou eatest, thou diest; Death is the penalty imposed; beware, And govern well thy appetite; lest Sin Surprise thee, and her black attendant Death. Here finished he, and all that he had made Viewed, and behold all was entirely good; So even and morn accomplished the sixth day: Yet not till the Creator from his work Desisting, though unwearied, up returned, Up to the Heaven of Heavens, his high abode; Thence to behold this new created world, The addition of his empire, how it showed In prospect from his throne, how good, how fair, Answering his great idea. Up he rode Followed with acclamation, and the sound Symphonious of ten thousand harps, that tuned Angelick harmonies: The earth, the air Resounded, (thou rememberest, for thou heardst,) The heavens and all the constellations rung, The planets in their station listening stood, While the bright pomp ascended jubilant. Open, ye everlasting gates! they sung, Open, ye Heavens! your living doors;let in The great Creator from his work returned Magnificent, his six days work, a World; Open, and henceforth oft; for God will deign To visit oft the dwellings of just men, Delighted; and with frequent intercourse Thither will send his winged messengers On errands of supernal grace. So sung The glorious train ascending: He through Heaven, That opened wide her blazing portals, led To God's eternal house direct the way; A broad and ample road, whose dust is gold And pavement stars, as stars to thee appear, Seen in the galaxy, that milky way, Which nightly, as a circling zone, thou seest Powdered with stars. And now on Earth the seventh Evening arose in Eden, for the sun Was set, and twilight from the east came on, Forerunning night; when at the holy mount Of Heaven's high-seated top, the imperial throne Of Godhead, fixed for ever firm and sure, The Filial Power arrived, and sat him down With his great Father; for he also went Invisible, yet staid, (such privilege Hath Omnipresence) and the work ordained, Author and End of all things; and, from work Now resting, blessed and hallowed the seventh day, As resting on that day from all his work, But not in silence holy kept: the harp Had work and rested not; the solemn pipe, And dulcimer, all organs of sweet stop, All sounds on fret by string or golden wire, Tempered soft tunings, intermixed with voice Choral or unison: of incense clouds, Fuming from golden censers, hid the mount. Creation and the six days acts they sung: Great are thy works, Jehovah! infinite Thy power! what thought can measure thee, or tongue Relate thee! Greater now in thy return Than from the giant Angels: Thee that day Thy thunders magnified; but to create Is greater than created to destroy. Who can impair thee, Mighty King, or bound Thy empire! Easily the proud attempt Of Spirits apostate, and their counsels vain, Thou hast repelled; while impiously they thought Thee to diminish, and from thee withdraw The number of thy worshippers. Who seeks To lessen thee, against his purpose serves To manifest the more thy might: his evil Thou usest, and from thence createst more good. Witness this new-made world, another Heaven From Heaven-gate not far, founded in view On the clear hyaline, the glassy sea; Of amplitude almost immense, with stars Numerous, and every star perhaps a world Of destined habitation; but thou knowest Their seasons: among these the seat of Men, Earth, with her nether ocean circumfused, Their pleasant dwelling-place. Thrice happy Men, And sons of Men, whom God hath thus advanced! Created in his image, there to dwell And worship him; and in reward to rule Over his works, on earth, in sea, or air, And multiply a race of worshippers Holy and just: Thrice happy, if they know Their happiness, and persevere upright! So sung they, and the empyrean rung With halleluiahs: Thus was sabbath kept. And thy request think now fulfilled, that asked How first this world and face of things began, And what before thy memory was done From the beginning; that posterity, Informed by thee, might know: If else thou seekest Aught, not surpassing human measure, say. Book VIII The Angel ended, and in Adam's ear So charming left his voice, that he a while Thought him still speaking, still stood fixed to hear; Then, as new waked, thus gratefully replied. What thanks sufficient, or what recompence Equal, have I to render thee, divine Historian, who thus largely hast allayed The thirst I had of knowledge, and vouchsafed This friendly condescension to relate Things, else by me unsearchable; now heard With wonder, but delight, and, as is due, With glory attributed to the high Creator! Something yet of doubt remains, Which only thy solution can resolve. When I behold this goodly frame, this world, Of Heaven and Earth consisting; and compute Their magnitudes; this Earth, a spot, a grain, An atom, with the firmament compared And all her numbered stars, that seem to roll Spaces incomprehensible, (for such Their distance argues, and their swift return Diurnal,) merely to officiate light Round this opacous Earth, this punctual spot, One day and night; in all her vast survey Useless besides; reasoning I oft admire, How Nature wise and frugal could commit Such disproportions, with superfluous hand So many nobler bodies to create, Greater so manifold, to this one use, For aught appears, and on their orbs impose Such restless revolution day by day Repeated; while the sedentary Earth, That better might with far less compass move, Served by more noble than herself, attains Her end without least motion, and receives, As tribute, such a sumless journey brought Of incorporeal speed, her warmth and light; Speed, to describe whose swiftness number fails. So spake our sire, and by his countenance seemed Entering on studious thoughts abstruse; which Eve Perceiving, where she sat retired in sight, With lowliness majestick from her seat, And grace that won who saw to wish her stay, Rose, and went forth among her fruits and flowers, To visit how they prospered, bud and bloom, Her nursery; they at her coming sprung, And, touched by her fair tendance, gladlier grew. Yet went she not, as not with such discourse Delighted, or not capable her ear Of what was high: such pleasure she reserved, Adam relating, she sole auditress; Her husband the relater she preferred Before the Angel, and of him to ask Chose rather; he, she knew, would intermix Grateful digressions, and solve high dispute With conjugal caresses: from his lip Not words alone pleased her. O! when meet now Such pairs, in love and mutual honour joined? With Goddess-like demeanour forth she went, Not unattended; for on her, as Queen, A pomp of winning Graces waited still, And from about her shot darts of desire Into all eyes, to wish her still in sight. And Raphael now, to Adam's doubt proposed, Benevolent and facile thus replied. To ask or search, I blame thee not; for Heaven Is as the book of God before thee set, Wherein to read his wonderous works, and learn His seasons, hours, or days, or months, or years: This to attain, whether Heaven move or Earth, Imports not, if thou reckon right; the rest From Man or Angel the great Architect Did wisely to conceal, and not divulge His secrets to be scanned by them who ought Rather admire; or, if they list to try Conjecture, he his fabrick of the Heavens Hath left to their disputes, perhaps to move His laughter at their quaint opinions wide Hereafter; when they come to model Heaven And calculate the stars, how they will wield The mighty frame; how build, unbuild, contrive To save appearances; how gird the sphere With centrick and eccentrick scribbled o'er, Cycle and epicycle, orb in orb: Already by thy reasoning this I guess, Who art to lead thy offspring, and supposest That bodies bright and greater should not serve The less not bright, nor Heaven such journeys run, Earth sitting still, when she alone receives The benefit: Consider first, that great Or bright infers not excellence: the Earth Though, in comparison of Heaven, so small, Nor glistering, may of solid good contain More plenty than the sun that barren shines; Whose virtue on itself works no effect, But in the fruitful Earth; there first received, His beams, unactive else, their vigour find. Yet not to Earth are those bright luminaries Officious; but to thee, Earth's habitant. And for the Heaven's wide circuit, let it speak The Maker's high magnificence, who built So spacious, and his line stretched out so far; That Man may know he dwells not in his own; An edifice too large for him to fill, Lodged in a small partition; and the rest Ordained for uses to his Lord best known. The swiftness of those circles attribute, Though numberless, to his Omnipotence, That to corporeal substances could add Speed almost spiritual: Me thou thinkest not slow, Who since the morning-hour set out from Heaven Where God resides, and ere mid-day arrived In Eden; distance inexpressible By numbers that have name. But this I urge, Admitting motion in the Heavens, to show Invalid that which thee to doubt it moved; Not that I so affirm, though so it seem To thee who hast thy dwelling here on Earth. God, to remove his ways from human sense, Placed Heaven from Earth so far, that earthly sight, If it presume, might err in things too high, And no advantage gain. What if the sun Be center to the world; and other stars, By his attractive virtue and their own Incited, dance about him various rounds? Their wandering course now high, now low, then hid, Progressive, retrograde, or standing still, In six thou seest; and what if seventh to these The planet earth, so stedfast though she seem, Insensibly three different motions move? Which else to several spheres thou must ascribe, Moved contrary with thwart obliquities; Or save the sun his labour, and that swift Nocturnal and diurnal rhomb supposed, Invisible else above all stars, the wheel Of day and night; which needs not thy belief, If earth, industrious of herself, fetch day Travelling east, and with her part averse From the sun's beam meet night, her other part Still luminous by his ray. What if that light, Sent from her through the wide transpicuous air, To the terrestrial moon be as a star, Enlightening her by day, as she by night This earth? reciprocal, if land be there, Fields and inhabitants: Her spots thou seest As clouds, and clouds may rain, and rain produce Fruits in her softened soil for some to eat Allotted there; and other suns perhaps, With their attendant moons, thou wilt descry, Communicating male and female light; Which two great sexes animate the world, Stored in each orb perhaps with some that live. For such vast room in Nature unpossessed By living soul, desart and desolate, Only to shine, yet scarce to contribute Each orb a glimpse of light, conveyed so far Down to this habitable, which returns Light back to them, is obvious to dispute. But whether thus these things, or whether not; But whether the sun, predominant in Heaven, Rise on the earth; or earth rise on the sun; He from the east his flaming road begin; Or she from west her silent course advance, With inoffensive pace that spinning sleeps On her soft axle, while she paces even, And bears thee soft with the smooth hair along; Sollicit not thy thoughts with matters hid; Leave them to God above; him serve, and fear! Of other creatures, as him pleases best, Wherever placed, let him dispose; joy thou In what he gives to thee, this Paradise And thy fair Eve; Heaven is for thee too high To know what passes there; be lowly wise: Think only what concerns thee, and thy being; Dream not of other worlds, what creatures there Live, in what state, condition, or degree; Contented that thus far hath been revealed Not of Earth only, but of highest Heaven. To whom thus Adam, cleared of doubt, replied. How fully hast thou satisfied me, pure Intelligence of Heaven, Angel serene! And, freed from intricacies, taught to live The easiest way; nor with perplexing thoughts To interrupt the sweet of life, from which God hath bid dwell far off all anxious cares, And not molest us; unless we ourselves Seek them with wandering thoughts, and notions vain. But apt the mind or fancy is to rove Unchecked, and of her roving is no end; Till warned, or by experience taught, she learn, That, not to know at large of things remote From use, obscure and subtle; but, to know That which before us lies in daily life, Is the prime wisdom: What is more, is fume, Or emptiness, or fond impertinence: And renders us, in things that most concern, Unpractised, unprepared, and still to seek. Therefore from this high pitch let us descend A lower flight, and speak of things at hand Useful; whence, haply, mention may arise Of something not unseasonable to ask, By sufferance, and thy wonted favour, deigned. Thee I have heard relating what was done Ere my remembrance: now, hear me relate My story, which perhaps thou hast not heard; And day is not yet spent; till then thou seest How subtly to detain thee I devise; Inviting thee to hear while I relate; Fond! were it not in hope of thy reply: For, while I sit with thee, I seem in Heaven; And sweeter thy discourse is to my ear Than fruits of palm-tree pleasantest to thirst And hunger both, from labour, at the hour Of sweet repast; they satiate, and soon fill, Though pleasant; but thy words, with grace divine Imbued, bring to their sweetness no satiety. To whom thus Raphael answered heavenly meek. Nor are thy lips ungraceful, Sire of men, Nor tongue ineloquent; for God on thee Abundantly his gifts hath also poured Inward and outward both, his image fair: Speaking, or mute, all comeliness and grace Attends thee; and each word, each motion, forms; Nor less think we in Heaven of thee on Earth Than of our fellow-servant, and inquire Gladly into the ways of God with Man: For God, we see, hath honoured thee, and set On Man his equal love: Say therefore on; For I that day was absent, as befel, Bound on a voyage uncouth and obscure, Far on excursion toward the gates of Hell; Squared in full legion (such command we had) To see that none thence issued forth a spy, Or enemy, while God was in his work; Lest he, incensed at such eruption bold, Destruction with creation might have mixed. Not that they durst without his leave attempt; But us he sends upon his high behests For state, as Sovran King; and to inure Our prompt obedience. Fast we found, fast shut, The dismal gates, and barricadoed strong; But long ere our approaching heard within Noise, other than the sound of dance or song, Torment, and loud lament, and furious rage. Glad we returned up to the coasts of light Ere sabbath-evening: so we had in charge. But thy relation now; for I attend, Pleased with thy words no less than thou with mine. So spake the Godlike Power, and thus our Sire. For Man to tell how human life began Is hard; for who himself beginning knew Desire with thee still longer to converse Induced me. As new waked from soundest sleep, Soft on the flowery herb I found me laid, In balmy sweat; which with his beams the sun Soon dried, and on the reeking moisture fed. Straight toward Heaven my wondering eyes I turned, And gazed a while the ample sky; till, raised By quick instinctive motion, up I sprung, As thitherward endeavouring, and upright Stood on my feet: about me round I saw Hill, dale, and shady woods, and sunny plains, And liquid lapse of murmuring streams; by these, Creatures that lived and moved, and walked, or flew; Birds on the branches warbling; all things smiled; With fragrance and with joy my heart o'erflowed. Myself I then perused, and limb by limb Surveyed, and sometimes went, and sometimes ran With supple joints, as lively vigour led: But who I was, or where, or from what cause, Knew not; to speak I tried, and forthwith spake; My tongue obeyed, and readily could name Whate'er I saw. Thou Sun, said I, fair light, And thou enlightened Earth, so fresh and gay, Ye Hills, and Dales, ye Rivers, Woods, and Plains, And ye that live and move, fair Creatures, tell, Tell, if ye saw, how I came thus, how here?-- Not of myself;--by some great Maker then, In goodness and in power pre-eminent: Tell me, how may I know him, how adore, From whom I have that thus I move and live, And feel that I am happier than I know.-- While thus I called, and strayed I knew not whither, From where I first drew air, and first beheld This happy light; when, answer none returned, On a green shady bank, profuse of flowers, Pensive I sat me down: There gentle sleep First found me, and with soft oppression seised My droused sense, untroubled, though I thought I then was passing to my former state Insensible, and forthwith to dissolve: When suddenly stood at my head a dream, Whose inward apparition gently moved My fancy to believe I yet had being, And lived: One came, methought, of shape divine, And said, 'Thy mansion wants thee, Adam; rise, 'First Man, of men innumerable ordained 'First Father! called by thee, I come thy guide 'To the garden of bliss, thy seat prepared.' So saying, by the hand he took me raised, And over fields and waters, as in air Smooth-sliding without step, last led me up A woody mountain; whose high top was plain, A circuit wide, enclosed, with goodliest trees Planted, with walks, and bowers; that what I saw Of Earth before scarce pleasant seemed. Each tree, Loaden with fairest fruit that hung to the eye Tempting, stirred in me sudden appetite To pluck and eat; whereat I waked, and found Before mine eyes all real, as the dream Had lively shadowed: Here had new begun My wandering, had not he, who was my guide Up hither, from among the trees appeared, Presence Divine. Rejoicing, but with awe, In adoration at his feet I fell Submiss: He reared me, and 'Whom thou soughtest I am,' Said mildly, 'Author of all this thou seest 'Above, or round about thee, or beneath. 'This Paradise I give thee, count it thine 'To till and keep, and of the fruit to eat: 'Of every tree that in the garden grows 'Eat freely with glad heart; fear here no dearth: 'But of the tree whose operation brings 'Knowledge of good and ill, which I have set 'The pledge of thy obedience and thy faith, 'Amid the garden by the tree of life, 'Remember what I warn thee, shun to taste, 'And shun the bitter consequence: for know, 'The day thou eatest thereof, my sole command 'Transgressed, inevitably thou shalt die, 'From that day mortal; and this happy state 'Shalt lose, expelled from hence into a world 'Of woe and sorrow.' Sternly he pronounced The rigid interdiction, which resounds Yet dreadful in mine ear, though in my choice Not to incur; but soon his clear aspect Returned, and gracious purpose thus renewed. 'Not only these fair bounds, but all the Earth 'To thee and to thy race I give; as lords 'Possess it, and all things that therein live, 'Or live in sea, or air; beast, fish, and fowl. 'In sign whereof, each bird and beast behold 'After their kinds; I bring them to receive 'From thee their names, and pay thee fealty 'With low subjection; understand the same 'Of fish within their watery residence, 'Not hither summoned, since they cannot change 'Their element, to draw the thinner air.' As thus he spake, each bird and beast behold Approaching two and two; these cowering low With blandishment; each bird stooped on his wing. I named them, as they passed, and understood Their nature, with such knowledge God endued My sudden apprehension: But in these I found not what methought I wanted still; And to the heavenly Vision thus presumed. O, by what name, for thou above all these, Above mankind, or aught than mankind higher, Surpassest far my naming; how may I Adore thee, Author of this universe, And all this good to man? for whose well being So amply, and with hands so liberal, Thou hast provided all things: But with me I see not who partakes. In solitude What happiness, who can enjoy alone, Or, all enjoying, what contentment find? Thus I presumptuous; and the Vision bright, As with a smile more brightened, thus replied. What callest thou solitude? Is not the Earth With various living creatures, and the air Replenished, and all these at thy command To come and play before thee? Knowest thou not Their language and their ways? They also know, And reason not contemptibly: With these Find pastime, and bear rule; thy realm is large. So spake the Universal Lord, and seemed So ordering: I, with leave of speech implored, And humble deprecation, thus replied. Let not my words offend thee, Heavenly Power; My Maker, be propitious while I speak. Hast thou not made me here thy substitute, And these inferiour far beneath me set? Among unequals what society Can sort, what harmony, or true delight? Which must be mutual, in proportion due Given and received; but, in disparity The one intense, the other still remiss, Cannot well suit with either, but soon prove Tedious alike: Of fellowship I speak Such as I seek, fit to participate All rational delight: wherein the brute Cannot be human consort: They rejoice Each with their kind, lion with lioness; So fitly them in pairs thou hast combined: Much less can bird with beast, or fish with fowl So well converse, nor with the ox the ape; Worse then can man with beast, and least of all. Whereto the Almighty answered, not displeased. A nice and subtle happiness, I see, Thou to thyself proposest, in the choice Of thy associates, Adam! and wilt taste No pleasure, though in pleasure, solitary. What thinkest thou then of me, and this my state? Seem I to thee sufficiently possessed Of happiness, or not? who am alone From all eternity; for none I know Second to me or like, equal much less. How have I then with whom to hold converse, Save with the creatures which I made, and those To me inferiour, infinite descents Beneath what other creatures are to thee? He ceased; I lowly answered. To attain The highth and depth of thy eternal ways All human thoughts come short, Supreme of things! Thou in thyself art perfect, and in thee Is no deficience found: Not so is Man, But in degree; the cause of his desire By conversation with his like to help Or solace his defects. No need that thou Shouldst propagate, already Infinite; And through all numbers absolute, though One: But Man by number is to manifest His single imperfection, and beget Like of his like, his image multiplied, In unity defective; which requires Collateral love, and dearest amity. Thou in thy secresy although alone, Best with thyself accompanied, seekest not Social communication; yet, so pleased, Canst raise thy creature to what highth thou wilt Of union or communion, deified: I, by conversing, cannot these erect From prone; nor in their ways complacence find. Thus I emboldened spake, and freedom used Permissive, and acceptance found; which gained This answer from the gracious Voice Divine. Thus far to try thee, Adam, I was pleased; And find thee knowing, not of beasts alone, Which thou hast rightly named, but of thyself; Expressing well the spirit within thee free, My image, not imparted to the brute; Whose fellowship therefore unmeet for thee Good reason was thou freely shouldst dislike; And be so minded still: I, ere thou spakest, Knew it not good for Man to be alone; And no such company as then thou sawest Intended thee; for trial only brought, To see how thou couldest judge of fit and meet: What next I bring shall please thee, be assured, Thy likeness, thy fit help, thy other self, Thy wish exactly to thy heart's desire. He ended, or I heard no more; for now My earthly by his heavenly overpowered, Which it had long stood under, strained to the highth In that celestial colloquy sublime, As with an object that excels the sense Dazzled and spent, sunk down; and sought repair Of sleep, which instantly fell on me, called By Nature as in aid, and closed mine eyes. Mine eyes he closed, but open left the cell Of fancy, my internal sight; by which, Abstract as in a trance, methought I saw, Though sleeping, where I lay, and saw the shape Still glorious before whom awake I stood: Who stooping opened my left side, and took From thence a rib, with cordial spirits warm, And life-blood streaming fresh; wide was the wound, But suddenly with flesh filled up and healed: The rib he formed and fashioned with his hands; Under his forming hands a creature grew, Man-like, but different sex; so lovely fair, That what seemed fair in all the world, seemed now Mean, or in her summed up, in her contained And in her looks; which from that time infused Sweetness into my heart, unfelt before, And into all things from her air inspired The spirit of love and amorous delight. She disappeared, and left me dark; I waked To find her, or for ever to deplore Her loss, and other pleasures all abjure: When out of hope, behold her, not far off, Such as I saw her in my dream, adorned With what all Earth or Heaven could bestow To make her amiable: On she came, Led by her heavenly Maker, though unseen, And guided by his voice; nor uninformed Of nuptial sanctity, and marriage rites: Grace was in all her steps, Heaven in her eye, In every gesture dignity and love. I, overjoyed, could not forbear aloud. This turn hath made amends; thou hast fulfilled Thy words, Creator bounteous and benign, Giver of all things fair! but fairest this Of all thy gifts! nor enviest. I now see Bone of my bone, flesh of my flesh, myself Before me: Woman is her name;of Man Extracted: for this cause he shall forego Father and mother, and to his wife adhere; And they shall be one flesh, one heart, one soul. She heard me thus; and though divinely brought, Yet innocence, and virgin modesty, Her virtue, and the conscience of her worth, That would be wooed, and not unsought be won, Not obvious, not obtrusive, but, retired, The more desirable; or, to say all, Nature herself, though pure of sinful thought, Wrought in her so, that, seeing me, she turned: I followed her; she what was honour knew, And with obsequious majesty approved My pleaded reason. To the nuptial bower I led her blushing like the morn: All Heaven, And happy constellations, on that hour Shed their selectest influence; the Earth Gave sign of gratulation, and each hill; Joyous the birds; fresh gales and gentle airs Whispered it to the woods, and from their wings Flung rose, flung odours from the spicy shrub, Disporting, till the amorous bird of night Sung spousal, and bid haste the evening-star On his hill top, to light the bridal lamp. Thus have I told thee all my state, and brought My story to the sum of earthly bliss, Which I enjoy; and must confess to find In all things else delight indeed, but such As, used or not, works in the mind no change, Nor vehement desire; these delicacies I mean of taste, sight, smell, herbs, fruits, and flowers, Walks, and the melody of birds: but here Far otherwise, transported I behold, Transported touch; here passion first I felt, Commotion strange! in all enjoyments else Superiour and unmoved; here only weak Against the charm of Beauty's powerful glance. Or Nature failed in me, and left some part Not proof enough such object to sustain; Or, from my side subducting, took perhaps More than enough; at least on her bestowed Too much of ornament, in outward show Elaborate, of inward less exact. For well I understand in the prime end Of Nature her the inferiour, in the mind And inward faculties, which most excel; In outward also her resembling less His image who made both, and less expressing The character of that dominion given O'er other creatures: Yet when I approach Her loveliness, so absolute she seems And in herself complete, so well to know Her own, that what she wills to do or say, Seems wisest, virtuousest, discreetest, best: All higher knowledge in her presence falls Degraded; Wisdom in discourse with her Loses discountenanced, and like Folly shows; Authority and Reason on her wait, As one intended first, not after made Occasionally; and, to consummate all, Greatness of mind and Nobleness their seat Build in her loveliest, and create an awe About her, as a guard angelick placed. To whom the Angel with contracted brow. Accuse not Nature, she hath done her part; Do thou but thine; and be not diffident Of Wisdom; she deserts thee not, if thou Dismiss not her, when most thou needest her nigh, By attributing overmuch to things Less excellent, as thou thyself perceivest. For, what admirest thou, what transports thee so, An outside? fair, no doubt, and worthy well Thy cherishing, thy honouring, and thy love; Not thy subjection: Weigh with her thyself; Then value: Oft-times nothing profits more Than self-esteem, grounded on just and right Well managed; of that skill the more thou knowest, The more she will acknowledge thee her head, And to realities yield all her shows: Made so adorn for thy delight the more, So awful, that with honour thou mayest love Thy mate, who sees when thou art seen least wise. But if the sense of touch, whereby mankind Is propagated, seem such dear delight Beyond all other; think the same vouchsafed To cattle and each beast; which would not be To them made common and divulged, if aught Therein enjoyed were worthy to subdue The soul of man, or passion in him move. What higher in her society thou findest Attractive, human, rational, love still; In loving thou dost well, in passion not, Wherein true love consists not: Love refines The thoughts, and heart enlarges; hath his seat In reason, and is judicious; is the scale By which to heavenly love thou mayest ascend, Not sunk in carnal pleasure; for which cause, Among the beasts no mate for thee was found. To whom thus, half abashed, Adam replied. Neither her outside formed so fair, nor aught In procreation common to all kinds, (Though higher of the genial bed by far, And with mysterious reverence I deem,) So much delights me, as those graceful acts, Those thousand decencies, that daily flow From all her words and actions mixed with love And sweet compliance, which declare unfeigned Union of mind, or in us both one soul; Harmony to behold in wedded pair More grateful than harmonious sound to the ear. Yet these subject not; I to thee disclose What inward thence I feel, not therefore foiled, Who meet with various objects, from the sense Variously representing; yet, still free, Approve the best, and follow what I approve. To love, thou blamest me not; for Love, thou sayest, Leads up to Heaven, is both the way and guide; Bear with me then, if lawful what I ask: Love not the heavenly Spirits, and how their love Express they? by looks only? or do they mix Irradiance, virtual or immediate touch? To whom the Angel, with a smile that glowed Celestial rosy red, Love's proper hue, Answered. Let it suffice thee that thou knowest Us happy, and without love no happiness. Whatever pure thou in the body enjoyest, (And pure thou wert created) we enjoy In eminence; and obstacle find none Of membrane, joint, or limb, exclusive bars; Easier than air with air, if Spirits embrace, Total they mix, union of pure with pure Desiring, nor restrained conveyance need, As flesh to mix with flesh, or soul with soul. But I can now no more; the parting sun Beyond the Earth's green Cape and verdant Isles Hesperian sets, my signal to depart. Be strong, live happy, and love! But, first of all, Him, whom to love is to obey, and keep His great command; take heed lest passion sway Thy judgement to do aught, which else free will Would not admit: thine, and of all thy sons, The weal or woe in thee is placed; beware! I in thy persevering shall rejoice, And all the Blest: Stand fast;to stand or fall Free in thine own arbitrement it lies. Perfect within, no outward aid require; And all temptation to transgress repel. So saying, he arose; whom Adam thus Followed with benediction. Since to part, Go, heavenly guest, ethereal Messenger, Sent from whose sovran goodness I adore! Gentle to me and affable hath been Thy condescension, and shall be honoured ever With grateful memory: Thou to mankind Be good and friendly still, and oft return! So parted they; the Angel up to Heaven From the thick shade, and Adam to his bower. Book IX No more of talk where God or Angel guest With Man, as with his friend, familiar us'd, To sit indulgent, and with him partake Rural repast; permitting him the while Venial discourse unblam'd. I now must change Those notes to tragick; foul distrust, and breach Disloyal on the part of Man, revolt, And disobedience: on the part of Heaven Now alienated, distance and distaste, Anger and just rebuke, and judgement given, That brought into this world a world of woe, Sin and her shadow Death, and Misery Death's harbinger: Sad talk!yet argument Not less but more heroick than the wrath Of stern Achilles on his foe pursued Thrice fugitive about Troy wall; or rage Of Turnus for Lavinia disespous'd; Or Neptune's ire, or Juno's, that so long Perplexed the Greek, and Cytherea's son: 00482129 If answerable style I can obtain Of my celestial patroness, who deigns Her nightly visitation unimplor'd, And dictates to me slumbering; or inspires Easy my unpremeditated verse: Since first this subject for heroick song Pleas'd me long choosing, and beginning late; Not sedulous by nature to indite Wars, hitherto the only argument Heroick deem'd chief mastery to dissect With long and tedious havock fabled knights In battles feign'd; the better fortitude Of patience and heroick martyrdom Unsung; or to describe races and games, Or tilting furniture, imblazon'd shields, Impresses quaint, caparisons and steeds, Bases and tinsel trappings, gorgeous knights At joust and tournament; then marshall'd feast Serv'd up in hall with sewers and seneshals; The skill of artifice or office mean, Not that which justly gives heroick name To person, or to poem. Me, of these Nor skill'd nor studious, higher argument Remains; sufficient of itself to raise That name, unless an age too late, or cold Climate, or years, damp my intended wing Depress'd; and much they may, if all be mine, Not hers, who brings it nightly to my ear. The sun was sunk, and after him the star Of Hesperus, whose office is to bring Twilight upon the earth, short arbiter "twixt day and night, and now from end to end Night's hemisphere had veil'd the horizon round: When satan, who late fled before the threats Of Gabriel out of Eden, now improv'd In meditated fraud and malice, bent On Man's destruction, maugre what might hap Of heavier on himself, fearless returned From compassing the earth; cautious of day, Since Uriel, regent of the sun, descried His entrance, and foreworned the Cherubim That kept their watch; thence full of anguish driven, The space of seven continued nights he rode With darkness; thrice the equinoctial line He circled; four times crossed the car of night From pole to pole, traversing each colure; On the eighth returned; and, on the coast averse From entrance or Cherubick watch, by stealth Found unsuspected way. There was a place, Now not, though sin, not time, first wrought the change, Where Tigris, at the foot of Paradise, Into a gulf shot under ground, till part Rose up a fountain by the tree of life: In with the river sunk, and with it rose Satan, involved in rising mist; then sought Where to lie hid; sea he had searched, and land, From Eden over Pontus and the pool Maeotis, up beyond the river Ob; Downward as far antarctick; and in length, West from Orontes to the ocean barred At Darien ; thence to the land where flows Ganges and Indus: Thus the orb he roamed With narrow search; and with inspection deep Considered every creature, which of all Most opportune might serve his wiles; and found The Serpent subtlest beast of all the field. Him after long debate, irresolute Of thoughts revolved, his final sentence chose Fit vessel, fittest imp of fraud, in whom To enter, and his dark suggestions hide From sharpest sight: for, in the wily snake Whatever sleights, none would suspicious mark, As from his wit and native subtlety Proceeding; which, in other beasts observed, Doubt might beget of diabolick power Active within, beyond the sense of brute. Thus he resolved, but first from inward grief His bursting passion into plaints thus poured. More justly, seat worthier of Gods, as built With second thoughts, reforming what was old! O Earth, how like to Heaven, if not preferred For what God, after better, worse would build? Terrestrial Heaven, danced round by other Heavens That shine, yet bear their bright officious lamps, Light above light, for thee alone, as seems, In thee concentring all their precious beams Of sacred influence! As God in Heaven Is center, yet extends to all; so thou, Centring, receivest from all those orbs: in thee, Not in themselves, all their known virtue appears Productive in herb, plant, and nobler birth Of creatures animate with gradual life Of growth, sense, reason, all summed up in Man. With what delight could I have walked thee round, If I could joy in aught, sweet interchange Of hill, and valley, rivers, woods, and plains, Now land, now sea and shores with forest crowned, Rocks, dens, and caves! But I in none of these Find place or refuge; and the more I see Pleasures about me, so much more I feel Torment within me, as from the hateful siege Of contraries: all good to me becomes Bane, and in Heaven much worse would be my state. But neither here seek I, no nor in Heaven To dwell, unless by mastering Heaven's Supreme; Nor hope to be myself less miserable By what I seek, but others to make such As I, though thereby worse to me redound: For only in destroying I find ease To my relentless thoughts; and, him destroyed, Or won to what may work his utter loss, For whom all this was made, all this will soon Follow, as to him linked in weal or woe; In woe then; that destruction wide may range: To me shall be the glory sole among The infernal Powers, in one day to have marred What he, Almighty styled, six nights and days Continued making; and who knows how long Before had been contriving? though perhaps Not longer than since I, in one night, freed From servitude inglorious well nigh half The angelick name, and thinner left the throng Of his adorers: He, to be avenged, And to repair his numbers thus impaired, Whether such virtue spent of old now failed More Angels to create, if they at least Are his created, or, to spite us more, Determined to advance into our room A creature formed of earth, and him endow, Exalted from so base original, With heavenly spoils, our spoils: What he decreed, He effected; Man he made, and for him built Magnificent this world, and earth his seat, Him lord pronounced; and, O indignity! Subjected to his service angel-wings, And flaming ministers to watch and tend Their earthly charge: Of these the vigilance I dread; and, to elude, thus wrapt in mist Of midnight vapour glide obscure, and pry In every bush and brake, where hap may find The serpent sleeping; in whose mazy folds To hide me, and the dark intent I bring. O foul descent! that I, who erst contended With Gods to sit the highest, am now constrained Into a beast; and, mixed with bestial slime, This essence to incarnate and imbrute, That to the highth of Deity aspired! But what will not ambition and revenge Descend to? Who aspires, must down as low As high he soared; obnoxious, first or last, To basest things. Revenge, at first though sweet, Bitter ere long, back on itself recoils: Let it; I reck not, so it light well aimed, Since higher I fall short, on him who next Provokes my envy, this new favourite Of Heaven, this man of clay, son of despite, Whom, us the more to spite, his Maker raised From dust: Spite then with spite is best repaid. So saying, through each thicket dank or dry, Like a black mist low-creeping, he held on His midnight-search, where soonest he might find The serpent; him fast-sleeping soon he found In labyrinth of many a round self-rolled, His head the midst, well stored with subtile wiles: Not yet in horrid shade or dismal den, Nor nocent yet; but, on the grassy herb, Fearless unfeared he slept: in at his mouth The Devil entered; and his brutal sense, In heart or head, possessing, soon inspired With act intelligential; but his sleep Disturbed not, waiting close the approach of morn. Now, when as sacred light began to dawn In Eden on the humid flowers, that breathed Their morning incense, when all things, that breathe, From the Earth's great altar send up silent praise To the Creator, and his nostrils fill With grateful smell, forth came the human pair, And joined their vocal worship to the quire Of creatures wanting voice; that done, partake The season prime for sweetest scents and airs: Then commune, how that day they best may ply Their growing work: for much their work out-grew The hands' dispatch of two gardening so wide, And Eve first to her husband thus began. Adam, well may we labour still to dress This garden, still to tend plant, herb, and flower, Our pleasant task enjoined; but, till more hands Aid us, the work under our labour grows, Luxurious by restraint; what we by day Lop overgrown, or prune, or prop, or bind, One night or two with wanton growth derides Tending to wild. Thou therefore now advise, Or bear what to my mind first thoughts present: Let us divide our labours; thou, where choice Leads thee, or where most needs, whether to wind The woodbine round this arbour, or direct The clasping ivy where to climb; while I, In yonder spring of roses intermixed With myrtle, find what to redress till noon: For, while so near each other thus all day Our task we choose, what wonder if so near Looks intervene and smiles, or object new Casual discourse draw on; which intermits Our day's work, brought to little, though begun Early, and the hour of supper comes unearned? To whom mild answer Adam thus returned. Sole Eve, associate sole, to me beyond Compare above all living creatures dear! Well hast thou motioned, well thy thoughts employed, How we might best fulfil the work which here God hath assigned us; nor of me shalt pass Unpraised: for nothing lovelier can be found In woman, than to study houshold good, And good works in her husband to promote. Yet not so strictly hath our Lord imposed Labour, as to debar us when we need Refreshment, whether food, or talk between, Food of the mind, or this sweet intercourse Of looks and smiles; for smiles from reason flow, To brute denied, and are of love the food; Love, not the lowest end of human life. For not to irksome toil, but to delight, He made us, and delight to reason joined. These paths and bowers doubt not but our joint hands Will keep from wilderness with ease, as wide As we need walk, till younger hands ere long Assist us; But, if much converse perhaps Thee satiate, to short absence I could yield: For solitude sometimes is best society, And short retirement urges sweet return. But other doubt possesses me, lest harm Befall thee severed from me; for thou knowest What hath been warned us, what malicious foe Envying our happiness, and of his own Despairing, seeks to work us woe and shame By sly assault; and somewhere nigh at hand Watches, no doubt, with greedy hope to find His wish and best advantage, us asunder; Hopeless to circumvent us joined, where each To other speedy aid might lend at need: Whether his first design be to withdraw Our fealty from God, or to disturb Conjugal love, than which perhaps no bliss Enjoyed by us excites his envy more; Or this, or worse, leave not the faithful side That gave thee being, still shades thee, and protects. The wife, where danger or dishonour lurks, Safest and seemliest by her husband stays, Who guards her, or with her the worst endures. To whom the virgin majesty of Eve, As one who loves, and some unkindness meets, With sweet austere composure thus replied. Offspring of Heaven and Earth, and all Earth's Lord! That such an enemy we have, who seeks Our ruin, both by thee informed I learn, And from the parting Angel over-heard, As in a shady nook I stood behind, Just then returned at shut of evening flowers. But, that thou shouldst my firmness therefore doubt To God or thee, because we have a foe May tempt it, I expected not to hear. His violence thou fearest not, being such As we, not capable of death or pain, Can either not receive, or can repel. His fraud is then thy fear; which plain infers Thy equal fear, that my firm faith and love Can by his fraud be shaken or seduced; Thoughts, which how found they harbour in thy breast, Adam, mis-thought of her to thee so dear? To whom with healing words Adam replied. Daughter of God and Man, immortal Eve! For such thou art; from sin and blame entire: Not diffident of thee do I dissuade Thy absence from my sight, but to avoid The attempt itself, intended by our foe. For he who tempts, though in vain, at least asperses The tempted with dishonour foul; supposed Not incorruptible of faith, not proof Against temptation: Thou thyself with scorn And anger wouldst resent the offered wrong, Though ineffectual found: misdeem not then, If such affront I labour to avert From thee alone, which on us both at once The enemy, though bold, will hardly dare; Or daring, first on me the assault shall light. Nor thou his malice and false guile contemn; Subtle he needs must be, who could seduce Angels; nor think superfluous other's aid. I, from the influence of thy looks, receive Access in every virtue; in thy sight More wise, more watchful, stronger, if need were Of outward strength; while shame, thou looking on, Shame to be overcome or over-reached, Would utmost vigour raise, and raised unite. Why shouldst not thou like sense within thee feel When I am present, and thy trial choose With me, best witness of thy virtue tried? So spake domestick Adam in his care And matrimonial love; but Eve, who thought Less attributed to her faith sincere, Thus her reply with accent sweet renewed. If this be our condition, thus to dwell In narrow circuit straitened by a foe, Subtle or violent, we not endued Single with like defence, wherever met; How are we happy, still in fear of harm? But harm precedes not sin: only our foe, Tempting, affronts us with his foul esteem Of our integrity: his foul esteem Sticks no dishonour on our front, but turns Foul on himself; then wherefore shunned or feared By us? who rather double honour gain From his surmise proved false; find peace within, Favour from Heaven, our witness, from the event. And what is faith, love, virtue, unassayed Alone, without exteriour help sustained? Let us not then suspect our happy state Left so imperfect by the Maker wise, As not secure to single or combined. Frail is our happiness, if this be so, And Eden were no Eden, thus exposed. To whom thus Adam fervently replied. O Woman, best are all things as the will Of God ordained them: His creating hand Nothing imperfect or deficient left Of all that he created, much less Man, Or aught that might his happy state secure, Secure from outward force; within himself The danger lies, yet lies within his power: Against his will he can receive no harm. But God left free the will; for what obeys Reason, is free; and Reason he made right, But bid her well be ware, and still erect; Lest, by some fair-appearing good surprised, She dictate false; and mis-inform the will To do what God expressly hath forbid. Not then mistrust, but tender love, enjoins, That I should mind thee oft; and mind thou me. Firm we subsist, yet possible to swerve; Since Reason not impossibly may meet Some specious object by the foe suborned, And fall into deception unaware, Not keeping strictest watch, as she was warned. Seek not temptation then, which to avoid Were better, and most likely if from me Thou sever not: Trial will come unsought. Wouldst thou approve thy constancy, approve First thy obedience; the other who can know, Not seeing thee attempted, who attest? But, if thou think, trial unsought may find Us both securer than thus warned thou seemest, Go; for thy stay, not free, absents thee more; Go in thy native innocence, rely On what thou hast of virtue; summon all! For God towards thee hath done his part, do thine. So spake the patriarch of mankind; but Eve Persisted; yet submiss, though last, replied. With thy permission then, and thus forewarned Chiefly by what thy own last reasoning words Touched only; that our trial, when least sought, May find us both perhaps far less prepared, The willinger I go, nor much expect A foe so proud will first the weaker seek; So bent, the more shall shame him his repulse. Thus saying, from her husband's hand her hand Soft she withdrew; and, like a Wood-Nymph light, Oread or Dryad, or of Delia's train, Betook her to the groves; but Delia's self In gait surpassed, and Goddess-like deport, Though not as she with bow and quiver armed, But with such gardening tools as Art yet rude, Guiltless of fire, had formed, or Angels brought. To Pales, or Pomona, thus adorned, Likest she seemed, Pomona when she fled Vertumnus, or to Ceres in her prime, Yet virgin of Proserpina from Jove. Her long with ardent look his eye pursued Delighted, but desiring more her stay. Oft he to her his charge of quick return Repeated; she to him as oft engaged To be returned by noon amid the bower, And all things in best order to invite Noontide repast, or afternoon's repose. O much deceived, much failing, hapless Eve, Of thy presumed return! event perverse! Thou never from that hour in Paradise Foundst either sweet repast, or sound repose; Such ambush, hid among sweet flowers and shades, Waited with hellish rancour imminent To intercept thy way, or send thee back Despoiled of innocence, of faith, of bliss! For now, and since first break of dawn, the Fiend, Mere serpent in appearance, forth was come; And on his quest, where likeliest he might find The only two of mankind, but in them The whole included race, his purposed prey. In bower and field he sought, where any tuft Of grove or garden-plot more pleasant lay, Their tendance, or plantation for delight; By fountain or by shady rivulet He sought them both, but wished his hap might find Eve separate; he wished, but not with hope Of what so seldom chanced; when to his wish, Beyond his hope, Eve separate he spies, Veiled in a cloud of fragrance, where she stood, Half spied, so thick the roses blushing round About her glowed, oft stooping to support Each flower of slender stalk, whose head, though gay Carnation, purple, azure, or specked with gold, Hung drooping unsustained; them she upstays Gently with myrtle band, mindless the while Herself, though fairest unsupported flower, From her best prop so far, and storm so nigh. Nearer he drew, and many a walk traversed Of stateliest covert, cedar, pine, or palm; Then voluble and bold, now hid, now seen, Among thick-woven arborets, and flowers Imbordered on each bank, the hand of Eve: Spot more delicious than those gardens feigned Or of revived Adonis, or renowned Alcinous, host of old Laertes' son; Or that, not mystick, where the sapient king Held dalliance with his fair Egyptian spouse. Much he the place admired, the person more. As one who long in populous city pent, Where houses thick and sewers annoy the air, Forth issuing on a summer's morn, to breathe Among the pleasant villages and farms Adjoined, from each thing met conceives delight; The smell of grain, or tedded grass, or kine, Or dairy, each rural sight, each rural sound; If chance, with nymph-like step, fair virgin pass, What pleasing seemed, for her now pleases more; She most, and in her look sums all delight: Such pleasure took the Serpent to behold This flowery plat, the sweet recess of Eve Thus early, thus alone: Her heavenly form Angelick, but more soft, and feminine, Her graceful innocence, her every air Of gesture, or least action, overawed His malice, and with rapine sweet bereaved His fierceness of the fierce intent it brought: That space the Evil-one abstracted stood From his own evil, and for the time remained Stupidly good; of enmity disarmed, Of guile, of hate, of envy, of revenge: But the hot Hell that always in him burns, Though in mid Heaven, soon ended his delight, And tortures him now more, the more he sees Of pleasure, not for him ordained: then soon Fierce hate he recollects, and all his thoughts Of mischief, gratulating, thus excites. Thoughts, whither have ye led me! with what sweet Compulsion thus transported, to forget What hither brought us! hate, not love;nor hope Of Paradise for Hell, hope here to taste Of pleasure; but all pleasure to destroy, Save what is in destroying; other joy To me is lost. Then, let me not let pass Occasion which now smiles; behold alone The woman, opportune to all attempts, Her husband, for I view far round, not nigh, Whose higher intellectual more I shun, And strength, of courage haughty, and of limb Heroick built, though of terrestrial mould; Foe not informidable! exempt from wound, I not; so much hath Hell debased, and pain Enfeebled me, to what I was in Heaven. She fair, divinely fair, fit love for Gods! Not terrible, though terrour be in love And beauty, not approached by stronger hate, Hate stronger, under show of love well feigned; The way which to her ruin now I tend. So spake the enemy of mankind, enclosed In serpent, inmate bad! and toward Eve Addressed his way: not with indented wave, Prone on the ground, as since; but on his rear, Circular base of rising folds, that towered Fold above fold, a surging maze! his head Crested aloft, and carbuncle his eyes; With burnished neck of verdant gold, erect Amidst his circling spires, that on the grass Floated redundant: pleasing was his shape And lovely; never since of serpent-kind Lovelier, not those that in Illyria changed, Hermione and Cadmus, or the god In Epidaurus; nor to which transformed Ammonian Jove, or Capitoline, was seen; He with Olympias; this with her who bore Scipio, the highth of Rome. With tract oblique At first, as one who sought access, but feared To interrupt, side-long he works his way. As when a ship, by skilful steersmen wrought Nigh river's mouth or foreland, where the wind Veers oft, as oft so steers, and shifts her sail: So varied he, and of his tortuous train Curled many a wanton wreath in sight of Eve, To lure her eye; she, busied, heard the sound Of rusling leaves, but minded not, as used To such disport before her through the field, From every beast; more duteous at her call, Than at Circean call the herd disguised. He, bolder now, uncalled before her stood, But as in gaze admiring: oft he bowed His turret crest, and sleek enamelled neck, Fawning; and licked the ground whereon she trod. His gentle dumb expression turned at length The eye of Eve to mark his play; he, glad Of her attention gained, with serpent-tongue Organick, or impulse of vocal air, His fraudulent temptation thus began. Wonder not, sovran Mistress, if perhaps Thou canst, who art sole wonder! much less arm Thy looks, the Heaven of mildness, with disdain, Displeased that I approach thee thus, and gaze Insatiate; I thus single;nor have feared Thy awful brow, more awful thus retired. Fairest resemblance of thy Maker fair, Thee all things living gaze on, all things thine By gift, and thy celestial beauty adore With ravishment beheld! there best beheld, Where universally admired; but here In this enclosure wild, these beasts among, Beholders rude, and shallow to discern Half what in thee is fair, one man except, Who sees thee? and what is one? who should be seen A Goddess among Gods, adored and served By Angels numberless, thy daily train. So glozed the Tempter, and his proem tuned: Into the heart of Eve his words made way, Though at the voice much marvelling; at length, Not unamazed, she thus in answer spake. What may this mean? language of man pronounced By tongue of brute, and human sense expressed? The first, at least, of these I thought denied To beasts; whom God, on their creation-day, Created mute to all articulate sound: The latter I demur; for in their looks Much reason, and in their actions, oft appears. Thee, Serpent, subtlest beast of all the field I knew, but not with human voice endued; Redouble then this miracle, and say, How camest thou speakable of mute, and how To me so friendly grown above the rest Of brutal kind, that daily are in sight? Say, for such wonder claims attention due. To whom the guileful Tempter thus replied. Empress of this fair world, resplendent Eve! Easy to me it is to tell thee all What thou commandest; and right thou shouldst be obeyed: I was at first as other beasts that graze The trodden herb, of abject thoughts and low, As was my food; nor aught but food discerned Or sex, and apprehended nothing high: Till, on a day roving the field, I chanced A goodly tree far distant to behold Loaden with fruit of fairest colours mixed, Ruddy and gold: I nearer drew to gaze; When from the boughs a savoury odour blown, Grateful to appetite, more pleased my sense Than smell of sweetest fennel, or the teats Of ewe or goat dropping with milk at even, Unsucked of lamb or kid, that tend their play. To satisfy the sharp desire I had Of tasting those fair apples, I resolved Not to defer; hunger and thirst at once, Powerful persuaders, quickened at the scent Of that alluring fruit, urged me so keen. About the mossy trunk I wound me soon; For, high from ground, the branches would require Thy utmost reach or Adam's: Round the tree All other beasts that saw, with like desire Longing and envying stood, but could not reach. Amid the tree now got, where plenty hung Tempting so nigh, to pluck and eat my fill I spared not; for, such pleasure till that hour, At feed or fountain, never had I found. Sated at length, ere long I might perceive Strange alteration in me, to degree Of reason in my inward powers; and speech Wanted not long; though to this shape retained. Thenceforth to speculations high or deep I turned my thoughts, and with capacious mind Considered all things visible in Heaven, Or Earth, or Middle; all things fair and good: But all that fair and good in thy divine Semblance, and in thy beauty's heavenly ray, United I beheld; no fair to thine Equivalent or second! which compelled Me thus, though importune perhaps, to come And gaze, and worship thee of right declared Sovran of creatures, universal Dame! So talked the spirited sly Snake; and Eve, Yet more amazed, unwary thus replied. Serpent, thy overpraising leaves in doubt The virtue of that fruit, in thee first proved: But say, where grows the tree? from hence how far? For many are the trees of God that grow In Paradise, and various, yet unknown To us; in such abundance lies our choice, As leaves a greater store of fruit untouched, Still hanging incorruptible, till men Grow up to their provision, and more hands Help to disburden Nature of her birth. To whom the wily Adder, blithe and glad. Empress, the way is ready, and not long; Beyond a row of myrtles, on a flat, Fast by a fountain, one small thicket past Of blowing myrrh and balm: if thou accept My conduct, I can bring thee thither soon Lead then, said Eve. He, leading, swiftly rolled In tangles, and made intricate seem straight, To mischief swift. Hope elevates, and joy Brightens his crest; as when a wandering fire, Compact of unctuous vapour, which the night Condenses, and the cold environs round, Kindled through agitation to a flame, Which oft, they say, some evil Spirit attends, Hovering and blazing with delusive light, Misleads the amazed night-wanderer from his way To bogs and mires, and oft through pond or pool; There swallowed up and lost, from succour far. So glistered the dire Snake, and into fraud Led Eve, our credulous mother, to the tree Of prohibition, root of all our woe; Which when she saw, thus to her guide she spake. Serpent, we might have spared our coming hither, Fruitless to me, though fruit be here to excess, The credit of whose virtue rest with thee; Wonderous indeed, if cause of such effects. But of this tree we may not taste nor touch; God so commanded, and left that command Sole daughter of his voice; the rest, we live Law to ourselves; our reason is our law. To whom the Tempter guilefully replied. Indeed! hath God then said that of the fruit Of all these garden-trees ye shall not eat, Yet Lords declared of all in earth or air$? To whom thus Eve, yet sinless. Of the fruit Of each tree in the garden we may eat; But of the fruit of this fair tree amidst The garden, God hath said, Ye shall not eat Thereof, nor shall ye touch it, lest ye die. She scarce had said, though brief, when now more bold The Tempter, but with show of zeal and love To Man, and indignation at his wrong, New part puts on; and, as to passion moved, Fluctuates disturbed, yet comely and in act Raised, as of some great matter to begin. As when of old some orator renowned, In Athens or free Rome, where eloquence Flourished, since mute! to some great cause addressed, Stood in himself collected; while each part, Motion, each act, won audience ere the tongue; Sometimes in highth began, as no delay Of preface brooking, through his zeal of right: So standing, moving, or to highth up grown, The Tempter, all impassioned, thus began. O sacred, wise, and wisdom-giving Plant, Mother of science! now I feel thy power Within me clear; not only to discern Things in their causes, but to trace the ways Of highest agents, deemed however wise. Queen of this universe! do not believe Those rigid threats of death: ye shall not die: How should you? by the fruit? it gives you life To knowledge; by the threatener? look on me, Me, who have touched and tasted; yet both live, And life more perfect have attained than Fate Meant me, by venturing higher than my lot. Shall that be shut to Man, which to the Beast Is open? or will God incense his ire For such a petty trespass? and not praise Rather your dauntless virtue, whom the pain Of death denounced, whatever thing death be, Deterred not from achieving what might lead To happier life, knowledge of good and evil; Of good, how just? of evil, if what is evil Be real, why not known, since easier shunned? God therefore cannot hurt ye, and be just; Not just, not God; not feared then, nor obeyed: Your fear itself of death removes the fear. Why then was this forbid? Why, but to awe; Why, but to keep ye low and ignorant, His worshippers? He knows that in the day Ye eat thereof, your eyes that seem so clear, Yet are but dim, shall perfectly be then Opened and cleared, and ye shall be as Gods, Knowing both good and evil, as they know. That ye shall be as Gods, since I as Man, Internal Man, is but proportion meet; I, of brute, human; ye, of human, Gods. So ye shall die perhaps, by putting off Human, to put on Gods; death to be wished, Though threatened, which no worse than this can bring. And what are Gods, that Man may not become As they, participating God-like food? The Gods are first, and that advantage use On our belief, that all from them proceeds: I question it; for this fair earth I see, Warmed by the sun, producing every kind; Them, nothing: if they all things, who enclosed Knowledge of good and evil in this tree, That whoso eats thereof, forthwith attains Wisdom without their leave? and wherein lies The offence, that Man should thus attain to know? What can your knowledge hurt him, or this tree Impart against his will, if all be his? Or is it envy? and can envy dwell In heavenly breasts? These, these, and many more Causes import your need of this fair fruit. Goddess humane, reach then, and freely taste! He ended; and his words, replete with guile, Into her heart too easy entrance won: Fixed on the fruit she gazed, which to behold Might tempt alone; and in her ears the sound Yet rung of his persuasive words, impregned With reason, to her seeming, and with truth: Mean while the hour of noon drew on, and waked An eager appetite, raised by the smell So savoury of that fruit, which with desire, Inclinable now grown to touch or taste, Solicited her longing eye; yet first Pausing a while, thus to herself she mused. Great are thy virtues, doubtless, best of fruits, Though kept from man, and worthy to be admired; Whose taste, too long forborn, at first assay Gave elocution to the mute, and taught The tongue not made for speech to speak thy praise: Thy praise he also, who forbids thy use, Conceals not from us, naming thee the tree Of knowledge, knowledge both of good and evil; Forbids us then to taste! but his forbidding Commends thee more, while it infers the good By thee communicated, and our want: For good unknown sure is not had; or, had And yet unknown, is as not had at all. In plain then, what forbids he but to know, Forbids us good, forbids us to be wise? Such prohibitions bind not. But, if death Bind us with after-bands, what profits then Our inward freedom? In the day we eat Of this fair fruit, our doom is, we shall die! How dies the Serpent? he hath eaten and lives, And knows, and speaks, and reasons, and discerns, Irrational till then. For us alone Was death invented? or to us denied This intellectual food, for beasts reserved? For beasts it seems: yet that one beast which first Hath tasted envies not, but brings with joy The good befallen him, author unsuspect, Friendly to man, far from deceit or guile. What fear I then? rather, what know to fear Under this ignorance of good and evil, Of God or death, of law or penalty? Here grows the cure of all, this fruit divine, Fair to the eye, inviting to the taste, Of virtue to make wise: What hinders then To reach, and feed at once both body and mind? So saying, her rash hand in evil hour Forth reaching to the fruit, she plucked, she eat! Earth felt the wound; and Nature from her seat, Sighing through all her works, gave signs of woe, That all was lost. Back to the thicket slunk The guilty Serpent; and well might;for Eve, Intent now wholly on her taste, nought else Regarded; such delight till then, as seemed, In fruit she never tasted, whether true Or fancied so, through expectation high Of knowledge; not was Godhead from her thought. Greedily she ingorged without restraint, And knew not eating death: Satiate at length, And hightened as with wine, jocund and boon, Thus to herself she pleasingly began. O sovran, virtuous, precious of all trees In Paradise! of operation blest To sapience, hitherto obscured, infamed. And thy fair fruit let hang, as to no end Created; but henceforth my early care, Not without song, each morning, and due praise, Shall tend thee, and the fertile burden ease Of thy full branches offered free to all; Till, dieted by thee, I grow mature In knowledge, as the Gods, who all things know; Though others envy what they cannot give: For, had the gift been theirs, it had not here Thus grown. Experience, next, to thee I owe, Best guide; not following thee, I had remained In ignorance; thou openest wisdom's way, And givest access, though secret she retire. And I perhaps am secret: Heaven is high, High, and remote to see from thence distinct Each thing on Earth; and other care perhaps May have diverted from continual watch Our great Forbidder, safe with all his spies About him. But to Adam in what sort Shall I appear? shall I to him make known As yet my change, and give him to partake Full happiness with me, or rather not, But keeps the odds of knowledge in my power Without copartner? so to add what wants In female sex, the more to draw his love, And render me more equal; and perhaps, A thing not undesirable, sometime Superiour; for, inferiour, who is free This may be well: But what if God have seen, And death ensue? then I shall be no more! And Adam, wedded to another Eve, Shall live with her enjoying, I extinct; A death to think! Confirmed then I resolve, Adam shall share with me in bliss or woe: So dear I love him, that with him all deaths I could endure, without him live no life. So saying, from the tree her step she turned; But first low reverence done, as to the Power That dwelt within, whose presence had infused Into the plant sciential sap, derived From nectar, drink of Gods. Adam the while, Waiting desirous her return, had wove Of choicest flowers a garland, to adorn Her tresses, and her rural labours crown; As reapers oft are wont their harvest-queen. Great joy he promised to his thoughts, and new Solace in her return, so long delayed: Yet oft his heart, divine of something ill, Misgave him; he the faltering measure felt; And forth to meet her went, the way she took That morn when first they parted: by the tree Of knowledge he must pass; there he her met, Scarce from the tree returning; in her hand A bough of fairest fruit, that downy smiled, New gathered, and ambrosial smell diffused. To him she hasted; in her face excuse Came prologue, and apology too prompt; Which, with bland words at will, she thus addressed. Hast thou not wondered, Adam, at my stay? Thee I have missed, and thought it long, deprived Thy presence; agony of love till now Not felt, nor shall be twice; for never more Mean I to try, what rash untried I sought, The pain of absence from thy sight. But strange Hath been the cause, and wonderful to hear: This tree is not, as we are told, a tree Of danger tasted, nor to evil unknown Opening the way, but of divine effect To open eyes, and make them Gods who taste; And hath been tasted such: The serpent wise, Or not restrained as we, or not obeying, Hath eaten of the fruit; and is become, Not dead, as we are threatened, but thenceforth Endued with human voice and human sense, Reasoning to admiration; and with me Persuasively hath so prevailed, that I Have also tasted, and have also found The effects to correspond; opener mine eyes, Dim erst, dilated spirits, ampler heart, And growing up to Godhead; which for thee Chiefly I sought, without thee can despise. For bliss, as thou hast part, to me is bliss; Tedious, unshared with thee, and odious soon. Thou therefore also taste, that equal lot May join us, equal joy, as equal love; Lest, thou not tasting, different degree Disjoin us, and I then too late renounce Deity for thee, when Fate will not permit. Thus Eve with countenance blithe her story told; But in her cheek distemper flushing glowed. On the other side Adam, soon as he heard The fatal trespass done by Eve, amazed, Astonied stood and blank, while horrour chill Ran through his veins, and all his joints relaxed; From his slack hand the garland wreathed for Eve Down dropt, and all the faded roses shed: Speechless he stood and pale, till thus at length First to himself he inward silence broke. O fairest of Creation, last and best Of all God's works, Creature in whom excelled Whatever can to sight or thought be formed, Holy, divine, good, amiable, or sweet! How art thou lost! how on a sudden lost, Defaced, deflowered, and now to death devote! Rather, how hast thou yielded to transgress The strict forbiddance, how to violate The sacred fruit forbidden! Some cursed fraud Of enemy hath beguiled thee, yet unknown, And me with thee hath ruined; for with thee Certain my resolution is to die: How can I live without thee! how forego Thy sweet converse, and love so dearly joined, To live again in these wild woods forlorn! Should God create another Eve, and I Another rib afford, yet loss of thee Would never from my heart: no, no!I feel The link of Nature draw me: flesh of flesh, Bone of my bone thou art, and from thy state Mine never shall be parted, bliss or woe. So having said, as one from sad dismay Recomforted, and after thoughts disturbed Submitting to what seemed remediless, Thus in calm mood his words to Eve he turned. Bold deed thou hast presumed, adventurous Eve, And peril great provoked, who thus hast dared, Had it been only coveting to eye That sacred fruit, sacred to abstinence, Much more to taste it under ban to touch. But past who can recall, or done undo? Not God Omnipotent, nor Fate; yet so Perhaps thou shalt not die, perhaps the fact Is not so heinous now, foretasted fruit, Profaned first by the serpent, by him first Made common, and unhallowed, ere our taste; Nor yet on him found deadly; yet he lives; Lives, as thou saidst, and gains to live, as Man, Higher degree of life; inducement strong To us, as likely tasting to attain Proportional ascent; which cannot be But to be Gods, or Angels, demi-Gods. Nor can I think that God, Creator wise, Though threatening, will in earnest so destroy Us his prime creatures, dignified so high, Set over all his works; which in our fall, For us created, needs with us must fail, Dependant made; so God shall uncreate, Be frustrate, do, undo, and labour lose; Not well conceived of God, who, though his power Creation could repeat, yet would be loth Us to abolish, lest the Adversary Triumph, and say; "Fickle their state whom God "Most favours; who can please him long? Me first "He ruined, now Mankind; whom will he next?" Matter of scorn, not to be given the Foe. However I with thee have fixed my lot, Certain to undergo like doom: If death Consort with thee, death is to me as life; So forcible within my heart I feel The bond of Nature draw me to my own; My own in thee, for what thou art is mine; Our state cannot be severed; we are one, One flesh; to lose thee were to lose myself. So Adam; and thus Eve to him replied. O glorious trial of exceeding love, Illustrious evidence, example high! Engaging me to emulate; but, short Of thy perfection, how shall I attain, Adam, from whose dear side I boast me sprung, And gladly of our union hear thee speak, One heart, one soul in both; whereof good proof This day affords, declaring thee resolved, Rather than death, or aught than death more dread, Shall separate us, linked in love so dear, To undergo with me one guilt, one crime, If any be, of tasting this fair fruit; Whose virtue for of good still good proceeds, Direct, or by occasion, hath presented This happy trial of thy love, which else So eminently never had been known? Were it I thought death menaced would ensue This my attempt, I would sustain alone The worst, and not persuade thee, rather die Deserted, than oblige thee with a fact Pernicious to thy peace; chiefly assured Remarkably so late of thy so true, So faithful, love unequalled: but I feel Far otherwise the event; not death, but life Augmented, opened eyes, new hopes, new joys, Taste so divine, that what of sweet before Hath touched my sense, flat seems to this, and harsh. On my experience, Adam, freely taste, And fear of death deliver to the winds. So saying, she embraced him, and for joy Tenderly wept; much won, that he his love Had so ennobled, as of choice to incur Divine displeasure for her sake, or death. In recompence for such compliance bad Such recompence best merits from the bough She gave him of that fair enticing fruit With liberal hand: he scrupled not to eat, Against his better knowledge; not deceived, But fondly overcome with female charm. Earth trembled from her entrails, as again In pangs; and Nature gave a second groan; Sky loured; and, muttering thunder, some sad drops Wept at completing of the mortal sin Original: while Adam took no thought, Eating his fill; nor Eve to iterate Her former trespass feared, the more to sooth Him with her loved society; that now, As with new wine intoxicated both, They swim in mirth, and fancy that they feel Divinity within them breeding wings, Wherewith to scorn the earth: But that false fruit Far other operation first displayed, Carnal desire inflaming; he on Eve Began to cast lascivious eyes; she him As wantonly repaid; in lust they burn: Till Adam thus 'gan Eve to dalliance move. Eve, now I see thou art exact of taste, And elegant, of sapience no small part; Since to each meaning savour we apply, And palate call judicious; I the praise Yield thee, so well this day thou hast purveyed. Much pleasure we have lost, while we abstained From this delightful fruit, nor known till now True relish, tasting; if such pleasure be In things to us forbidden, it might be wished, For this one tree had been forbidden ten. But come, so well refreshed, now let us play, As meet is, after such delicious fare; For never did thy beauty, since the day I saw thee first and wedded thee, adorned With all perfections, so inflame my sense With ardour to enjoy thee, fairer now Than ever; bounty of this virtuous tree! So said he, and forbore not glance or toy Of amorous intent; well understood Of Eve, whose eye darted contagious fire. Her hand he seised; and to a shady bank, Thick over-head with verdant roof imbowered, He led her nothing loth; flowers were the couch, Pansies, and violets, and asphodel, And hyacinth; Earth's freshest softest lap. There they their fill of love and love's disport Took largely, of their mutual guilt the seal, The solace of their sin; till dewy sleep Oppressed them, wearied with their amorous play, Soon as the force of that fallacious fruit, That with exhilarating vapour bland About their spirits had played, and inmost powers Made err, was now exhaled; and grosser sleep, Bred of unkindly fumes, with conscious dreams Incumbered, now had left them; up they rose As from unrest; and, each the other viewing, Soon found their eyes how opened, and their minds How darkened; innocence, that as a veil Had shadowed them from knowing ill, was gone; Just confidence, and native righteousness, And honour, from about them, naked left To guilty Shame; he covered, but his robe Uncovered more. So rose the Danite strong, Herculean Samson, from the harlot-lap Of Philistean Dalilah, and waked Shorn of his strength. They destitute and bare Of all their virtue: Silent, and in face Confounded, long they sat, as strucken mute: Till Adam, though not less than Eve abashed, At length gave utterance to these words constrained. O Eve, in evil hour thou didst give ear To that false worm, of whomsoever taught To counterfeit Man's voice; true in our fall, False in our promised rising; since our eyes Opened we find indeed, and find we know Both good and evil; good lost, and evil got; Bad fruit of knowledge, if this be to know; Which leaves us naked thus, of honour void, Of innocence, of faith, of purity, Our wonted ornaments now soiled and stained, And in our faces evident the signs Of foul concupiscence; whence evil store; Even shame, the last of evils; of the first Be sure then.--How shall I behold the face Henceforth of God or Angel, erst with joy And rapture so oft beheld? Those heavenly shapes Will dazzle now this earthly with their blaze Insufferably bright. O! might I here In solitude live savage; in some glade Obscured, where highest woods, impenetrable To star or sun-light, spread their umbrage broad And brown as evening: Cover me, ye Pines! Ye Cedars, with innumerable boughs Hide me, where I may never see them more!-- But let us now, as in bad plight, devise What best may for the present serve to hide The parts of each from other, that seem most To shame obnoxious, and unseemliest seen; Some tree, whose broad smooth leaves together sewed, And girded on our loins, may cover round Those middle parts; that this new comer, Shame, There sit not, and reproach us as unclean. So counselled he, and both together went Into the thickest wood; there soon they chose The fig-tree; not that kind for fruit renowned, But such as at this day, to Indians known, In Malabar or Decan spreads her arms Branching so broad and long, that in the ground The bended twigs take root, and daughters grow About the mother tree, a pillared shade High over-arched, and echoing walks between: There oft the Indian herdsman, shunning heat, Shelters in cool, and tends his pasturing herds At loop-holes cut through thickest shade: Those leaves They gathered, broad as Amazonian targe; And, with what skill they had, together sewed, To gird their waist; vain covering, if to hide Their guilt and dreaded shame! O, how unlike To that first naked glory! Such of late Columbus found the American, so girt With feathered cincture; naked else, and wild Among the trees on isles and woody shores. Thus fenced, and, as they thought, their shame in part Covered, but not at rest or ease of mind, They sat them down to weep; nor only tears Rained at their eyes, but high winds worse within Began to rise, high passions, anger, hate, Mistrust, suspicion, discord; and shook sore Their inward state of mind, calm region once And full of peace, now tost and turbulent: For Understanding ruled not, and the Will Heard not her lore; both in subjection now To sensual Appetite, who from beneath Usurping over sovran Reason claimed Superiour sway: From thus distempered breast, Adam, estranged in look and altered style, Speech intermitted thus to Eve renewed. Would thou hadst hearkened to my words, and staid With me, as I besought thee, when that strange Desire of wandering, this unhappy morn, I know not whence possessed thee; we had then Remained still happy; not, as now, despoiled Of all our good; shamed, naked, miserable! Let none henceforth seek needless cause to approve The faith they owe; when earnestly they seek Such proof, conclude, they then begin to fail. To whom, soon moved with touch of blame, thus Eve. What words have passed thy lips, Adam severe! Imputest thou that to my default, or will Of wandering, as thou callest it, which who knows But might as ill have happened thou being by, Or to thyself perhaps? Hadst thou been there, Or here the attempt, thou couldst not have discerned Fraud in the Serpent, speaking as he spake; No ground of enmity between us known, Why he should mean me ill, or seek to harm. Was I to have never parted from thy side? As good have grown there still a lifeless rib. Being as I am, why didst not thou, the head, Command me absolutely not to go, Going into such danger, as thou saidst? Too facile then, thou didst not much gainsay; Nay, didst permit, approve, and fair dismiss. Hadst thou been firm and fixed in thy dissent, Neither had I transgressed, nor thou with me. To whom, then first incensed, Adam replied. Is this the love, is this the recompence Of mine to thee, ingrateful Eve! expressed Immutable, when thou wert lost, not I; Who might have lived, and joyed immortal bliss, Yet willingly chose rather death with thee? And am I now upbraided as the cause Of thy transgressing? Not enough severe, It seems, in thy restraint: What could I more I warned thee, I admonished thee, foretold The danger, and the lurking enemy That lay in wait; beyond this, had been force; And force upon free will hath here no place. But confidence then bore thee on; secure Either to meet no danger, or to find Matter of glorious trial; and perhaps I also erred, in overmuch admiring What seemed in thee so perfect, that I thought No evil durst attempt thee; but I rue The errour now, which is become my crime, And thou the accuser. Thus it shall befall Him, who, to worth in women overtrusting, Lets her will rule: restraint she will not brook; And, left to herself, if evil thence ensue, She first his weak indulgence will accuse. Thus they in mutual accusation spent The fruitless hours, but neither self-condemning; And of their vain contest appeared no end. Book X Mean while the heinous and despiteful act Of Satan, done in Paradise; and how He, in the serpent, had perverted Eve, Her husband she, to taste the fatal fruit, Was known in Heaven; for what can 'scape the eye Of God all-seeing, or deceive his heart Omniscient? who, in all things wise and just, Hindered not Satan to attempt the mind Of Man, with strength entire and free will armed, Complete to have discovered and repulsed Whatever wiles of foe or seeming friend. For still they knew, and ought to have still remembered, The high injunction, not to taste that fruit, Whoever tempted; which they not obeying, (Incurred what could they less?) the penalty; And, manifold in sin, deserved to fall. Up into Heaven from Paradise in haste The angelick guards ascended, mute, and sad, For Man; for of his state by this they knew, Much wondering how the subtle Fiend had stolen Entrance unseen. Soon as the unwelcome news From Earth arrived at Heaven-gate, displeased All were who heard; dim sadness did not spare That time celestial visages, yet, mixed With pity, violated not their bliss. About the new-arrived, in multitudes The ethereal people ran, to hear and know How all befel: They towards the throne supreme, Accountable, made haste, to make appear, With righteous plea, their utmost vigilance And easily approved; when the Most High Eternal Father, from his secret cloud, Amidst in thunder uttered thus his voice. Assembled Angels, and ye Powers returned From unsuccessful charge; be not dismayed, Nor troubled at these tidings from the earth, Which your sincerest care could not prevent; Foretold so lately what would come to pass, When first this tempter crossed the gulf from Hell. I told ye then he should prevail, and speed On his bad errand; Man should be seduced, And flattered out of all, believing lies Against his Maker; no decree of mine Concurring to necessitate his fall, Or touch with lightest moment of impulse His free will, to her own inclining left In even scale. But fallen he is; and now What rests, but that the mortal sentence pass On his transgression,--death denounced that day? Which he presumes already vain and void, Because not yet inflicted, as he feared, By some immediate stroke; but soon shall find Forbearance no acquittance, ere day end. Justice shall not return as bounty scorned. But whom send I to judge them? whom but thee, Vicegerent Son? To thee I have transferred All judgement, whether in Heaven, or Earth, or Hell. Easy it may be seen that I intend Mercy colleague with justice, sending thee Man's friend, his Mediator, his designed Both ransom and Redeemer voluntary, And destined Man himself to judge Man fallen. So spake the Father; and, unfolding bright Toward the right hand his glory, on the Son Blazed forth unclouded Deity: He full Resplendent all his Father manifest Expressed, and thus divinely answered mild. Father Eternal, thine is to decree; Mine, both in Heaven and Earth, to do thy will Supreme; that thou in me, thy Son beloved, Mayest ever rest well pleased. I go to judge On earth these thy transgressours; but thou knowest, Whoever judged, the worst on me must light, When time shall be; for so I undertook Before thee; and, not repenting, this obtain Of right, that I may mitigate their doom On me derived; yet I shall temper so Justice with mercy, as may illustrate most Them fully satisfied, and thee appease. Attendance none shall need, nor train, where none Are to behold the judgement, but the judged, Those two; the third best absent is condemned, Convict by flight, and rebel to all law: Conviction to the serpent none belongs. Thus saying, from his radiant seat he rose Of high collateral glory: Him Thrones, and Powers, Princedoms, and Dominations ministrant, Accompanied to Heaven-gate; from whence Eden, and all the coast, in prospect lay. Down he descended straight; the speed of Gods Time counts not, though with swiftest minutes winged. Now was the sun in western cadence low From noon, and gentle airs, due at their hour, To fan the earth now waked, and usher in The evening cool; when he, from wrath more cool, Came the mild Judge, and Intercessour both, To sentence Man: The voice of God they heard Now walking in the garden, by soft winds Brought to their ears, while day declined; they heard, And from his presence hid themselves among The thickest trees, both man and wife; till God, Approaching, thus to Adam called aloud. Where art thou, Adam, wont with joy to meet My coming seen far off? I miss thee here, Not pleased, thus entertained with solitude, Where obvious duty ere while appeared unsought: Or come I less conspicuous, or what change Absents thee, or what chance detains?--Come forth! He came; and with him Eve, more loth, though first To offend; discountenanced both, and discomposed; Love was not in their looks, either to God, Or to each other; but apparent guilt, And shame, and perturbation, and despair, Anger, and obstinacy, and hate, and guile. Whence Adam, faltering long, thus answered brief. I heard thee in the garden, and of thy voice Afraid, being naked, hid myself. To whom The gracious Judge without revile replied. My voice thou oft hast heard, and hast not feared, But still rejoiced; how is it now become So dreadful to thee? That thou art naked, who Hath told thee? Hast thou eaten of the tree, Whereof I gave thee charge thou shouldst not eat? To whom thus Adam sore beset replied. O Heaven! in evil strait this day I stand Before my Judge; either to undergo Myself the total crime, or to accuse My other self, the partner of my life; Whose failing, while her faith to me remains, I should conceal, and not expose to blame By my complaint: but strict necessity Subdues me, and calamitous constraint; Lest on my head both sin and punishment, However insupportable, be all Devolved; though should I hold my peace, yet thou Wouldst easily detect what I conceal.-- This Woman, whom thou madest to be my help, And gavest me as thy perfect gift, so good, So fit, so acceptable, so divine, That from her hand I could suspect no ill, And what she did, whatever in itself, Her doing seemed to justify the deed; She gave me of the tree, and I did eat. To whom the Sovran Presence thus replied. Was she thy God, that her thou didst obey Before his voice? or was she made thy guide, Superiour, or but equal, that to her Thou didst resign thy manhood, and the place Wherein God set thee above her made of thee, And for thee, whose perfection far excelled Hers in all real dignity? Adorned She was indeed, and lovely, to attract Thy love, not thy subjection; and her gifts Were such, as under government well seemed; Unseemly to bear rule; which was thy part And person, hadst thou known thyself aright. So having said, he thus to Eve in few. Say, Woman, what is this which thou hast done? To whom sad Eve, with shame nigh overwhelmed, Confessing soon, yet not before her Judge Bold or loquacious, thus abashed replied. The Serpent me beguiled, and I did eat. Which when the Lord God heard, without delay To judgement he proceeded on the accused Serpent, though brute; unable to transfer The guilt on him, who made him instrument Of mischief, and polluted from the end Of his creation; justly then accursed, As vitiated in nature: More to know Concerned not Man, (since he no further knew) Nor altered his offence; yet God at last To Satan first in sin his doom applied, Though in mysterious terms, judged as then best: And on the Serpent thus his curse let fall. Because thou hast done this, thou art accursed Above all cattle, each beast of the field; Upon thy belly groveling thou shalt go, And dust shalt eat all the days of thy life. Between thee and the woman I will put Enmity, and between thine and her seed; Her seed shall bruise thy head, thou bruise his heel. So spake this oracle, then verified When Jesus, Son of Mary, second Eve, Saw Satan fall, like lightning, down from Heaven, Prince of the air; then, rising from his grave Spoiled Principalities and Powers, triumphed In open show; and, with ascension bright, Captivity led captive through the air, The realm itself of Satan, long usurped; Whom he shall tread at last under our feet; Even he, who now foretold his fatal bruise; And to the Woman thus his sentence turned. Thy sorrow I will greatly multiply By thy conception; children thou shalt bring In sorrow forth; and to thy husband's will Thine shall submit; he over thee shall rule. On Adam last thus judgement he pronounced. Because thou hast hearkened to the voice of thy wife, And eaten of the tree, concerning which I charged thee, saying, Thou shalt not eat thereof: Cursed is the ground for thy sake; thou in sorrow Shalt eat thereof, all the days of thy life; Thorns also and thistles it shall bring thee forth Unbid; and thou shalt eat the herb of the field; In the sweat of thy face shalt thou eat bread, Till thou return unto the ground; for thou Out of the ground wast taken, know thy birth, For dust thou art, and shalt to dust return. So judged he Man, both Judge and Saviour sent; And the instant stroke of death, denounced that day, Removed far off; then, pitying how they stood Before him naked to the air, that now Must suffer change, disdained not to begin Thenceforth the form of servant to assume; As when he washed his servants feet; so now, As father of his family, he clad Their nakedness with skins of beasts, or slain, Or as the snake with youthful coat repaid; And thought not much to clothe his enemies; Nor he their outward only with the skins Of beasts, but inward nakedness, much more. Opprobrious, with his robe of righteousness, Arraying, covered from his Father's sight. To him with swift ascent he up returned, Into his blissful bosom reassumed In glory, as of old; to him appeased All, though all-knowing, what had passed with Man Recounted, mixing intercession sweet. Mean while, ere thus was sinned and judged on Earth, Within the gates of Hell sat Sin and Death, In counterview within the gates, that now Stood open wide, belching outrageous flame Far into Chaos, since the Fiend passed through, Sin opening; who thus now to Death began. O Son, why sit we here each other viewing Idly, while Satan, our great author, thrives In other worlds, and happier seat provides For us, his offspring dear? It cannot be But that success attends him; if mishap, Ere this he had returned, with fury driven By his avengers; since no place like this Can fit his punishment, or their revenge. Methinks I feel new strength within me rise, Wings growing, and dominion given me large Beyond this deep; whatever draws me on, Or sympathy, or some connatural force, Powerful at greatest distance to unite, With secret amity, things of like kind, By secretest conveyance. Thou, my shade Inseparable, must with me along; For Death from Sin no power can separate. But, lest the difficulty of passing back Stay his return perhaps over this gulf Impassable, impervious; let us try Adventurous work, yet to thy power and mine Not unagreeable, to found a path Over this main from Hell to that new world, Where Satan now prevails; a monument Of merit high to all the infernal host, Easing their passage hence, for intercourse, Or transmigration, as their lot shall lead. Nor can I miss the way, so strongly drawn By this new-felt attraction and instinct. Whom thus the meager Shadow answered soon. Go, whither Fate, and inclination strong, Leads thee; I shall not lag behind, nor err The way, thou leading; such a scent I draw Of carnage, prey innumerable, and taste The savour of death from all things there that live: Nor shall I to the work thou enterprisest Be wanting, but afford thee equal aid. So saying, with delight he snuffed the smell Of mortal change on earth. As when a flock Of ravenous fowl, though many a league remote, Against the day of battle, to a field, Where armies lie encamped, come flying, lured With scent of living carcasses designed For death, the following day, in bloody fight: So scented the grim Feature, and upturned His nostril wide into the murky air; Sagacious of his quarry from so far. Then both from out Hell-gates, into the waste Wide anarchy of Chaos, damp and dark, Flew diverse; and with power (their power was great) Hovering upon the waters, what they met Solid or slimy, as in raging sea Tost up and down, together crouded drove, From each side shoaling towards the mouth of Hell; As when two polar winds, blowing adverse Upon the Cronian sea, together drive Mountains of ice, that stop the imagined way Beyond Petsora eastward, to the rich Cathaian coast. The aggregated soil Death with his mace petrifick, cold and dry, As with a trident, smote; and fixed as firm As Delos, floating once; the rest his look Bound with Gorgonian rigour not to move; And with Asphaltick slime, broad as the gate, Deep to the roots of Hell the gathered beach They fastened, and the mole immense wrought on Over the foaming deep high-arched, a bridge Of length prodigious, joining to the wall Immoveable of this now fenceless world, Forfeit to Death; from hence a passage broad, Smooth, easy, inoffensive, down to Hell. So, if great things to small may be compared, Xerxes, the liberty of Greece to yoke, From Susa, his Memnonian palace high, Came to the sea: and, over Hellespont Bridging his way, Europe with Asia joined, And scourged with many a stroke the indignant waves. Now had they brought the work by wonderous art Pontifical, a ridge of pendant rock, Over the vexed abyss, following the track Of Satan to the self-same place where he First lighted from his wing, and landed safe From out of Chaos, to the outside bare Of this round world: With pins of adamant And chains they made all fast, too fast they made And durable! And now in little space The confines met of empyrean Heaven, And of this World; and, on the left hand, Hell With long reach interposed; three several ways In sight, to each of these three places led. And now their way to Earth they had descried, To Paradise first tending; when, behold! Satan, in likeness of an Angel bright, Betwixt the Centaur and the Scorpion steering His zenith, while the sun in Aries rose: Disguised he came; but those his children dear Their parent soon discerned, though in disguise. He, after Eve seduced, unminded slunk Into the wood fast by; and, changing shape, To observe the sequel, saw his guileful act By Eve, though all unweeting, seconded Upon her husband; saw their shame that sought Vain covertures; but when he saw descend The Son of God to judge them, terrified He fled; not hoping to escape, but shun The present; fearing, guilty, what his wrath Might suddenly inflict; that past, returned By night, and listening where the hapless pair Sat in their sad discourse, and various plaint, Thence gathered his own doom; which understood Not instant, but of future time, with joy And tidings fraught, to Hell he now returned; And at the brink of Chaos, near the foot Of this new wonderous pontifice, unhoped Met, who to meet him came, his offspring dear. Great joy was at their meeting, and at sight Of that stupendious bridge his joy encreased. Long he admiring stood, till Sin, his fair Enchanting daughter, thus the silence broke. O Parent, these are thy magnifick deeds, Thy trophies! which thou viewest as not thine own; Thou art their author, and prime architect: For I no sooner in my heart divined, My heart, which by a secret harmony Still moves with thine, joined in connexion sweet, That thou on earth hadst prospered, which thy looks Now also evidence, but straight I felt, Though distant from thee worlds between, yet felt, That I must after thee, with this thy son; Such fatal consequence unites us three! Hell could no longer hold us in our bounds, Nor this unvoyageable gulf obscure Detain from following thy illustrious track. Thou hast achieved our liberty, confined Within Hell-gates till now; thou us impowered To fortify thus far, and overlay, With this portentous bridge, the dark abyss. Thine now is all this world; thy virtue hath won What thy hands builded not; thy wisdom gained With odds what war hath lost, and fully avenged Our foil in Heaven; here thou shalt monarch reign, There didst not; there let him still victor sway, As battle hath adjudged; from this new world Retiring, by his own doom alienated; And henceforth monarchy with thee divide Of all things, parted by the empyreal bounds, His quadrature, from thy orbicular world; Or try thee now more dangerous to his throne. Whom thus the Prince of darkness answered glad. Fair Daughter, and thou Son and Grandchild both; High proof ye now have given to be the race Of Satan (for I glory in the name, Antagonist of Heaven's Almighty King,) Amply have merited of me, of all The infernal empire, that so near Heaven's door Triumphal with triumphal act have met, Mine, with this glorious work; and made one realm, Hell and this world, one realm, one continent Of easy thorough-fare. Therefore, while I Descend through darkness, on your road with ease, To my associate Powers, them to acquaint With these successes, and with them rejoice; You two this way, among these numerous orbs, All yours, right down to Paradise descend; There dwell, and reign in bliss; thence on the earth Dominion exercise and in the air, Chiefly on Man, sole lord of all declared; Him first make sure your thrall, and lastly kill. My substitutes I send ye, and create Plenipotent on earth, of matchless might Issuing from me: on your joint vigour now My hold of this new kingdom all depends, Through Sin to Death exposed by my exploit. If your joint power prevail, the affairs of Hell No detriment need fear; go, and be strong! So saying he dismissed them; they with speed Their course through thickest constellations held, Spreading their bane; the blasted stars looked wan, And planets, planet-struck, real eclipse Then suffered. The other way Satan went down The causey to Hell-gate: On either side Disparted Chaos overbuilt exclaimed, And with rebounding surge the bars assailed, That scorned his indignation: Through the gate, Wide open and unguarded, Satan passed, And all about found desolate; for those, Appointed to sit there, had left their charge, Flown to the upper world; the rest were all Far to the inland retired, about the walls Of Pandemonium; city and proud seat Of Lucifer, so by allusion called Of that bright star to Satan paragoned; There kept their watch the legions, while the Grand In council sat, solicitous what chance Might intercept their emperour sent; so he Departing gave command, and they observed. As when the Tartar from his Russian foe, By Astracan, over the snowy plains, Retires; or Bactrin Sophi, from the horns Of Turkish crescent, leaves all waste beyond The realm of Aladule, in his retreat To Tauris or Casbeen: So these, the late Heaven-banished host, left desart utmost Hell Many a dark league, reduced in careful watch Round their metropolis; and now expecting Each hour their great adventurer, from the search Of foreign worlds: He through the midst unmarked, In show plebeian Angel militant Of lowest order, passed; and from the door Of that Plutonian hall, invisible Ascended his high throne; which, under state Of richest texture spread, at the upper end Was placed in regal lustre. Down a while He sat, and round about him saw unseen: At last, as from a cloud, his fulgent head And shape star-bright appeared, or brighter; clad With what permissive glory since his fall Was left him, or false glitter: All amazed At that so sudden blaze the Stygian throng Bent their aspect, and whom they wished beheld, Their mighty Chief returned: loud was the acclaim: Forth rushed in haste the great consulting peers, Raised from their dark Divan, and with like joy Congratulant approached him; who with hand Silence, and with these words attention, won. Thrones, Dominations, Princedoms, Virtues, Powers; For in possession such, not only of right, I call ye, and declare ye now; returned Successful beyond hope, to lead ye forth Triumphant out of this infernal pit Abominable, accursed, the house of woe, And dungeon of our tyrant: Now possess, As Lords, a spacious world, to our native Heaven Little inferiour, by my adventure hard With peril great achieved. Long were to tell What I have done; what suffered;with what pain Voyaged th' unreal, vast, unbounded deep Of horrible confusion; over which By Sin and Death a broad way now is paved, To expedite your glorious march; but I Toiled out my uncouth passage, forced to ride The untractable abyss, plunged in the womb Of unoriginal Night and Chaos wild; That, jealous of their secrets, fiercely opposed My journey strange, with clamorous uproar Protesting Fate supreme; thence how I found The new created world, which fame in Heaven Long had foretold, a fabrick wonderful Of absolute perfection! therein Man Placed in a Paradise, by our exile Made happy: Him by fraud I have seduced From his Creator; and, the more to encrease Your wonder, with an apple; he, thereat Offended, worth your laughter! hath given up Both his beloved Man, and all his world, To Sin and Death a prey, and so to us, Without our hazard, labour, or alarm; To range in, and to dwell, and over Man To rule, as over all he should have ruled. True is, me also he hath judged, or rather Me not, but the brute serpent in whose shape Man I deceived: that which to me belongs, Is enmity which he will put between Me and mankind; I am to bruise his heel; His seed, when is not set, shall bruise my head: A world who would not purchase with a bruise, Or much more grievous pain?--Ye have the account Of my performance: What remains, ye Gods, But up, and enter now into full bliss? So having said, a while he stood, expecting Their universal shout, and high applause, To fill his ear; when, contrary, he hears On all sides, from innumerable tongues, A dismal universal hiss, the sound Of publick scorn; he wondered, but not long Had leisure, wondering at himself now more, His visage drawn he felt to sharp and spare; His arms clung to his ribs; his legs entwining Each other, till supplanted down he fell A monstrous serpent on his belly prone, Reluctant, but in vain; a greater power Now ruled him, punished in the shape he sinned, According to his doom: he would have spoke, But hiss for hiss returned with forked tongue To forked tongue; for now were all transformed Alike, to serpents all, as accessories To his bold riot: Dreadful was the din Of hissing through the hall, thick swarming now With complicated monsters head and tail, Scorpion, and Asp, and Amphisbaena dire, Cerastes horned, Hydrus, and Elops drear, And Dipsas; (not so thick swarmed once the soil Bedropt with blood of Gorgon, or the isle Ophiusa,) but still greatest he the midst, Now Dragon grown, larger than whom the sun Ingendered in the Pythian vale or slime, Huge Python, and his power no less he seemed Above the rest still to retain; they all Him followed, issuing forth to the open field, Where all yet left of that revolted rout, Heaven-fallen, in station stood or just array; Sublime with expectation when to see In triumph issuing forth their glorious Chief; They saw, but other sight instead! a croud Of ugly serpents; horrour on them fell, And horrid sympathy; for, what they saw, They felt themselves, now changing; down their arms, Down fell both spear and shield; down they as fast; And the dire hiss renewed, and the dire form Catched, by contagion; like in punishment, As in their crime. Thus was the applause they meant, Turned to exploding hiss, triumph to shame Cast on themselves from their own mouths. There stood A grove hard by, sprung up with this their change, His will who reigns above, to aggravate Their penance, laden with fair fruit, like that Which grew in Paradise, the bait of Eve Used by the Tempter: on that prospect strange Their earnest eyes they fixed, imagining For one forbidden tree a multitude Now risen, to work them further woe or shame; Yet, parched with scalding thirst and hunger fierce, Though to delude them sent, could not abstain; But on they rolled in heaps, and, up the trees Climbing, sat thicker than the snaky locks That curled Megaera: greedily they plucked The fruitage fair to sight, like that which grew Near that bituminous lake where Sodom flamed; This more delusive, not the touch, but taste Deceived; they, fondly thinking to allay Their appetite with gust, instead of fruit Chewed bitter ashes, which the offended taste With spattering noise rejected: oft they assayed, Hunger and thirst constraining; drugged as oft, With hatefullest disrelish writhed their jaws, With soot and cinders filled; so oft they fell Into the same illusion, not as Man Whom they triumphed once lapsed. Thus were they plagued And worn with famine, long and ceaseless hiss, Till their lost shape, permitted, they resumed; Yearly enjoined, some say, to undergo, This annual humbling certain numbered days, To dash their pride, and joy, for Man seduced. However, some tradition they dispersed Among the Heathen, of their purchase got, And fabled how the Serpent, whom they called Ophion, with Eurynome, the wide-- Encroaching Eve perhaps, had first the rule Of high Olympus; thence by Saturn driven And Ops, ere yet Dictaean Jove was born. Mean while in Paradise the hellish pair Too soon arrived; Sin, there in power before, Once actual; now in body, and to dwell Habitual habitant; behind her Death, Close following pace for pace, not mounted yet On his pale horse: to whom Sin thus began. Second of Satan sprung, all-conquering Death! What thinkest thou of our empire now, though earned With travel difficult, not better far Than still at Hell's dark threshold to have sat watch, Unnamed, undreaded, and thyself half starved? Whom thus the Sin-born monster answered soon. To me, who with eternal famine pine, Alike is Hell, or Paradise, or Heaven; There best, where most with ravine I may meet; Which here, though plenteous, all too little seems To stuff this maw, this vast unhide-bound corps. To whom the incestuous mother thus replied. Thou therefore on these herbs, and fruits, and flowers, Feed first; on each beast next, and fish, and fowl; No homely morsels! and, whatever thing The sithe of Time mows down, devour unspared; Till I, in Man residing, through the race, His thoughts, his looks, words, actions, all infect; And season him thy last and sweetest prey. This said, they both betook them several ways, Both to destroy, or unimmortal make All kinds, and for destruction to mature Sooner or later; which the Almighty seeing, From his transcendent seat the Saints among, To those bright Orders uttered thus his voice. See, with what heat these dogs of Hell advance To waste and havock yonder world, which I So fair and good created; and had still Kept in that state, had not the folly of Man Let in these wasteful furies, who impute Folly to me; so doth the Prince of Hell And his adherents, that with so much ease I suffer them to enter and possess A place so heavenly; and, conniving, seem To gratify my scornful enemies, That laugh, as if, transported with some fit Of passion, I to them had quitted all, At random yielded up to their misrule; And know not that I called, and drew them thither, My Hell-hounds, to lick up the draff and filth Which Man's polluting sin with taint hath shed On what was pure; til, crammed and gorged, nigh burst With sucked and glutted offal, at one sling Of thy victorious arm, well-pleasing Son, Both Sin, and Death, and yawning Grave, at last, Through Chaos hurled, obstruct the mouth of Hell For ever, and seal up his ravenous jaws. Then Heaven and Earth renewed shall be made pure To sanctity, that shall receive no stain: Till then, the curse pronounced on both precedes. He ended, and the heavenly audience loud Sung Halleluiah, as the sound of seas, Through multitude that sung: Just are thy ways, Righteous are thy decrees on all thy works; Who can extenuate thee? Next, to the Son, Destined Restorer of mankind, by whom New Heaven and Earth shall to the ages rise, Or down from Heaven descend.--Such was their song; While the Creator, calling forth by name His mighty Angels, gave them several charge, As sorted best with present things. The sun Had first his precept so to move, so shine, As might affect the earth with cold and heat Scarce tolerable; and from the north to call Decrepit winter; from the south to bring Solstitial summer's heat. To the blanc moon Her office they prescribed; to the other five Their planetary motions, and aspects, In sextile, square, and trine, and opposite, Of noxious efficacy, and when to join In synod unbenign; and taught the fixed Their influence malignant when to shower, Which of them rising with the sun, or falling, Should prove tempestuous: To the winds they set Their corners, when with bluster to confound Sea, air, and shore; the thunder when to roll With terrour through the dark aereal hall. Some say, he bid his Angels turn ascanse The poles of earth, twice ten degrees and more, From the sun's axle; they with labour pushed Oblique the centrick globe: Some say, the sun Was bid turn reins from the equinoctial road Like distant breadth to Taurus with the seven Atlantick Sisters, and the Spartan Twins, Up to the Tropick Crab: thence down amain By Leo, and the Virgin, and the Scales, As deep as Capricorn; to bring in change Of seasons to each clime; else had the spring Perpetual smiled on earth with vernant flowers, Equal in days and nights, except to those Beyond the polar circles; to them day Had unbenighted shone, while the low sun, To recompense his distance, in their sight Had rounded still the horizon, and not known Or east or west; which had forbid the snow From cold Estotiland, and south as far Beneath Magellan. At that tasted fruit The sun, as from Thyestean banquet, turned His course intended; else, how had the world Inhabited, though sinless, more than now, Avoided pinching cold and scorching heat? These changes in the Heavens, though slow, produced Like change on sea and land; sideral blast, Vapour, and mist, and exhalation hot, Corrupt and pestilent: Now from the north Of Norumbega, and the Samoed shore, Bursting their brazen dungeon, armed with ice, And snow, and hail, and stormy gust and flaw, Boreas, and Caecias, and Argestes loud, And Thrascias, rend the woods, and seas upturn; With adverse blast upturns them from the south Notus, and Afer black with thunderous clouds From Serraliona; thwart of these, as fierce, Forth rush the Levant and the Ponent winds, Eurus and Zephyr, with their lateral noise, Sirocco and Libecchio. Thus began Outrage from lifeless things; but Discord first, Daughter of Sin, among the irrational Death introduced, through fierce antipathy: Beast now with beast 'gan war, and fowl with fowl, And fish with fish; to graze the herb all leaving, Devoured each other; nor stood much in awe Of Man, but fled him; or, with countenance grim, Glared on him passing. These were from without The growing miseries, which Adam saw Already in part, though hid in gloomiest shade, To sorrow abandoned, but worse felt within; And, in a troubled sea of passion tost, Thus to disburden sought with sad complaint. O miserable of happy! Is this the end Of this new glorious world, and me so late The glory of that glory, who now become Accursed, of blessed? hide me from the face Of God, whom to behold was then my highth Of happiness!--Yet well, if here would end The misery; I deserved it, and would bear My own deservings; but this will not serve: All that I eat or drink, or shall beget, Is propagated curse. O voice, once heard Delightfully, Encrease and multiply; Now death to hear! for what can I encrease, Or multiply, but curses on my head? Who of all ages to succeed, but, feeling The evil on him brought by me, will curse My head? Ill fare our ancestor impure, For this we may thank Adam! but his thanks Shall be the execration: so, besides Mine own that bide upon me, all from me Shall with a fierce reflux on me rebound; On me, as on their natural center, light Heavy, though in their place. O fleeting joys Of Paradise, dear bought with lasting woes! Did I request thee, Maker, from my clay To mould me Man? did I solicit thee From darkness to promote me, or here place In this delicious garden? As my will Concurred not to my being, it were but right And equal to reduce me to my dust; Desirous to resign and render back All I received; unable to perform Thy terms too hard, by which I was to hold The good I sought not. To the loss of that, Sufficient penalty, why hast thou added The sense of endless woes? Inexplicable Why am I mocked with death, and lengthened out To deathless pain? How gladly would I meet Mortality my sentence, and be earth Insensible! How glad would lay me down As in my mother's lap! There I should rest, And sleep secure; his dreadful voice no more Would thunder in my ears; no fear of worse To me, and to my offspring, would torment me With cruel expectation. Yet one doubt Pursues me still, lest all I cannot die; Lest that pure breath of life, the spirit of Man Which God inspired, cannot together perish With this corporeal clod; then, in the grave, Or in some other dismal place, who knows But I shall die a living death? O thought Horrid, if true! Yet why? It was but breath Of life that sinned; what dies but what had life And sin? The body properly had neither, All of me then shall die: let this appease The doubt, since human reach no further knows. For though the Lord of all be infinite, Is his wrath also? Be it, Man is not so, But mortal doomed. How can he exercise Wrath without end on Man, whom death must end? Can he make deathless death? That were to make Strange contradiction, which to God himself Impossible is held; as argument Of weakness, not of power. Will he draw out, For anger's sake, finite to infinite, In punished Man, to satisfy his rigour, Satisfied never? That were to extend His sentence beyond dust and Nature's law; By which all causes else, according still To the reception of their matter, act; Not to the extent of their own sphere. But say That death be not one stroke, as I supposed, Bereaving sense, but endless misery From this day onward; which I feel begun Both in me, and without me; and so last To perpetuity;--Ay me!that fear Comes thundering back with dreadful revolution On my defenceless head; both Death and I Am found eternal, and incorporate both; Nor I on my part single; in me all Posterity stands cursed: Fair patrimony That I must leave ye, Sons! O, were I able To waste it all myself, and leave ye none! So disinherited, how would you bless Me, now your curse! Ah, why should all mankind, For one man's fault, thus guiltless be condemned, It guiltless? But from me what can proceed, But all corrupt; both mind and will depraved Not to do only, but to will the same With me? How can they then acquitted stand In sight of God? Him, after all disputes, Forced I absolve: all my evasions vain, And reasonings, though through mazes, lead me still But to my own conviction: first and last On me, me only, as the source and spring Of all corruption, all the blame lights due; So might the wrath! Fond wish!couldst thou support That burden, heavier than the earth to bear; Than all the world much heavier, though divided With that bad Woman? Thus, what thou desirest, And what thou fearest, alike destroys all hope Of refuge, and concludes thee miserable Beyond all past example and future; To Satan only like both crime and doom. O Conscience! into what abyss of fears And horrours hast thou driven me; out of which I find no way, from deep to deeper plunged! Thus Adam to himself lamented loud, Through the still night; not now, as ere Man fell, Wholesome, and cool, and mild, but with black air Accompanied; with damps, and dreadful gloom; Which to his evil conscience represented All things with double terrour: On the ground Outstretched he lay, on the cold ground; and oft Cursed his creation; Death as oft accused Of tardy execution, since denounced The day of his offence. Why comes not Death, Said he, with one thrice-acceptable stroke To end me? Shall Truth fail to keep her word, Justice Divine not hasten to be just? But Death comes not at call; Justice Divine Mends not her slowest pace for prayers or cries, O woods, O fountains, hillocks, dales, and bowers! With other echo late I taught your shades To answer, and resound far other song.-- Whom thus afflicted when sad Eve beheld, Desolate where she sat, approaching nigh, Soft words to his fierce passion she assayed: But her with stern regard he thus repelled. Out of my sight, thou Serpent! That name best Befits thee with him leagued, thyself as false And hateful; nothing wants, but that thy shape, Like his, and colour serpentine, may show Thy inward fraud; to warn all creatures from thee Henceforth; lest that too heavenly form, pretended To hellish falshood, snare them! But for thee I had persisted happy; had not thy pride And wandering vanity, when least was safe, Rejected my forewarning, and disdained Not to be trusted; longing to be seen, Though by the Devil himself; him overweening To over-reach; but, with the serpent meeting, Fooled and beguiled; by him thou, I by thee To trust thee from my side; imagined wise, Constant, mature, proof against all assaults; And understood not all was but a show, Rather than solid virtue; all but a rib Crooked by nature, bent, as now appears, More to the part sinister, from me drawn; Well if thrown out, as supernumerary To my just number found. O! why did God, Creator wise, that peopled highest Heaven With Spirits masculine, create at last This novelty on earth, this fair defect Of nature, and not fill the world at once With Men, as Angels, without feminine; Or find some other way to generate Mankind? This mischief had not been befallen, And more that shall befall; innumerable Disturbances on earth through female snares, And strait conjunction with this sex: for either He never shall find out fit mate, but such As some misfortune brings him, or mistake; Or whom he wishes most shall seldom gain Through her perverseness, but shall see her gained By a far worse; or, if she love, withheld By parents; or his happiest choice too late Shall meet, already linked and wedlock-bound To a fell adversary, his hate or shame: Which infinite calamity shall cause To human life, and houshold peace confound. He added not, and from her turned; but Eve, Not so repulsed, with tears that ceased not flowing And tresses all disordered, at his feet Fell humble; and, embracing them, besought His peace, and thus proceeded in her plaint. Forsake me not thus, Adam! witness Heaven What love sincere, and reverence in my heart I bear thee, and unweeting have offended, Unhappily deceived! Thy suppliant I beg, and clasp thy knees; bereave me not, Whereon I live, thy gentle looks, thy aid, Thy counsel, in this uttermost distress, My only strength and stay: Forlorn of thee, Whither shall I betake me, where subsist? While yet we live, scarce one short hour perhaps, Between us two let there be peace; both joining, As joined in injuries, one enmity Against a foe by doom express assigned us, That cruel Serpent: On me exercise not Thy hatred for this misery befallen; On me already lost, me than thyself More miserable! Both have sinned;but thou Against God only; I against God and thee; And to the place of judgement will return, There with my cries importune Heaven; that all The sentence, from thy head removed, may light On me, sole cause to thee of all this woe; Me, me only, just object of his ire! She ended weeping; and her lowly plight, Immoveable, till peace obtained from fault Acknowledged and deplored, in Adam wrought Commiseration: Soon his heart relented Towards her, his life so late, and sole delight, Now at his feet submissive in distress; Creature so fair his reconcilement seeking, His counsel, whom she had displeased, his aid: As one disarmed, his anger all he lost, And thus with peaceful words upraised her soon. Unwary, and too desirous, as before, So now of what thou knowest not, who desirest The punishment all on thyself; alas! Bear thine own first, ill able to sustain His full wrath, whose thou feelest as yet least part, And my displeasure bearest so ill. If prayers Could alter high decrees, I to that place Would speed before thee, and be louder heard, That on my head all might be visited; Thy frailty and infirmer sex forgiven, To me committed, and by me exposed. But rise;--let us no more contend, nor blame Each other, blamed enough elsewhere; but strive In offices of love, how we may lighten Each other's burden, in our share of woe; Since this day's death denounced, if aught I see, Will prove no sudden, but a slow-paced evil; A long day's dying, to augment our pain; And to our seed (O hapless seed!) derived. To whom thus Eve, recovering heart, replied. Adam, by sad experiment I know How little weight my words with thee can find, Found so erroneous; thence by just event Found so unfortunate: Nevertheless, Restored by thee, vile as I am, to place Of new acceptance, hopeful to regain Thy love, the sole contentment of my heart Living or dying, from thee I will not hide What thoughts in my unquiet breast are risen, Tending to some relief of our extremes, Or end; though sharp and sad, yet tolerable, As in our evils, and of easier choice. If care of our descent perplex us most, Which must be born to certain woe, devoured By Death at last; and miserable it is To be to others cause of misery, Our own begotten, and of our loins to bring Into this cursed world a woeful race, That after wretched life must be at last Food for so foul a monster; in thy power It lies, yet ere conception to prevent The race unblest, to being yet unbegot. Childless thou art, childless remain: so Death Shall be deceived his glut, and with us two Be forced to satisfy his ravenous maw. But if thou judge it hard and difficult, Conversing, looking, loving, to abstain From love's due rights, nuptial embraces sweet; And with desire to languish without hope, Before the present object languishing With like desire; which would be misery And torment less than none of what we dread; Then, both ourselves and seed at once to free From what we fear for both, let us make short, -- Let us seek Death; -- or, he not found, supply With our own hands his office on ourselves: Why stand we longer shivering under fears, That show no end but death, and have the power, Of many ways to die the shortest choosing, Destruction with destruction to destroy? -- She ended here, or vehement despair Broke off the rest: so much of death her thoughts Had entertained, as dyed her cheeks with pale. But Adam, with such counsel nothing swayed, To better hopes his more attentive mind Labouring had raised; and thus to Eve replied. Eve, thy contempt of life and pleasure seems To argue in thee something more sublime And excellent, than what thy mind contemns; But self-destruction therefore sought, refutes That excellence thought in thee; and implies, Not thy contempt, but anguish and regret For loss of life and pleasure overloved. Or if thou covet death, as utmost end Of misery, so thinking to evade The penalty pronounced; doubt not but God Hath wiselier armed his vengeful ire, than so To be forestalled; much more I fear lest death, So snatched, will not exempt us from the pain We are by doom to pay; rather, such acts Of contumacy will provoke the Highest To make death in us live: Then let us seek Some safer resolution, which methinks I have in view, calling to mind with heed Part of our sentence, that thy seed shall bruise The Serpent's head; piteous amends! unless Be meant, whom I conjecture, our grand foe, Satan; who, in the serpent, hath contrived Against us this deceit: To crush his head Would be revenge indeed! which will be lost By death brought on ourselves, or childless days Resolved, as thou proposest; so our foe Shal 'scape his punishment ordained, and we Instead shall double ours upon our heads. No more be mentioned then of violence Against ourselves; and wilful barrenness, That cuts us off from hope; and savours only Rancour and pride, impatience and despite, Reluctance against God and his just yoke Laid on our necks. Remember with what mild And gracious temper he both heard, and judged, Without wrath or reviling; we expected Immediate dissolution, which we thought Was meant by death that day; when lo!to thee Pains only in child-bearing were foretold, And bringing forth; soon recompensed with joy, Fruit of thy womb: On me the curse aslope Glanced on the ground; with labour I must earn My bread; what harm? Idleness had been worse; My labour will sustain me; and, lest cold Or heat should injure us, his timely care Hath, unbesought, provided; and his hands Clothed us unworthy, pitying while he judged; How much more, if we pray him, will his ear Be open, and his heart to pity incline, And teach us further by what means to shun The inclement seasons, rain, ice, hail, and snow! Which now the sky, with various face, begins To show us in this mountain; while the winds Blow moist and keen, shattering the graceful locks Of these fair spreading trees; which bids us seek Some better shroud, some better warmth to cherish Our limbs benummed, ere this diurnal star Leave cold the night, how we his gathered beams Reflected may with matter sere foment; Or, by collision of two bodies, grind The air attrite to fire; as late the clouds Justling, or pushed with winds, rude in their shock, Tine the slant lightning; whose thwart flame, driven down Kindles the gummy bark of fir or pine; And sends a comfortable heat from far, Which might supply the sun: Such fire to use, And what may else be remedy or cure To evils which our own misdeeds have wrought, He will instruct us praying, and of grace Beseeching him; so as we need not fear To pass commodiously this life, sustained By him with many comforts, till we end In dust, our final rest and native home. What better can we do, than, to the place Repairing where he judged us, prostrate fall Before him reverent; and there confess Humbly our faults, and pardon beg; with tears Watering the ground, and with our sighs the air Frequenting, sent from hearts contrite, in sign Of sorrow unfeigned, and humiliation meek Book XI Undoubtedly he will relent, and turn From his displeasure; in whose look serene, When angry most he seemed and most severe, What else but favour, grace, and mercy, shone? So spake our father penitent; nor Eve Felt less remorse: they, forthwith to the place Repairing where he judged them, prostrate fell Before him reverent; and both confessed Humbly their faults, and pardon begged; with tears Watering the ground, and with their sighs the air Frequenting, sent from hearts contrite, in sign Of sorrow unfeigned, and humiliation meek. Thus they, in lowliest plight, repentant stood Praying; for from the mercy-seat above Prevenient grace descending had removed The stony from their hearts, and made new flesh Regenerate grow instead; that sighs now breathed Unutterable; which the Spirit of prayer Inspired, and winged for Heaven with speedier flight Than loudest oratory: Yet their port Not of mean suitors; nor important less Seemed their petition, than when the ancient pair In fables old, less ancient yet than these, Deucalion and chaste Pyrrha, to restore The race of mankind drowned, before the shrine Of Themis stood devout. To Heaven their prayers Flew up, nor missed the way, by envious winds Blown vagabond or frustrate: in they passed Dimensionless through heavenly doors; then clad With incense, where the golden altar fumed, By their great intercessour, came in sight Before the Father's throne: them the glad Son Presenting, thus to intercede began. See$ Father, what first-fruits on earth are sprung From thy implanted grace in Man; these sighs And prayers, which in this golden censer mixed With incense, I thy priest before thee bring; Fruits of more pleasing savour, from thy seed Sown with contrition in his heart, than those Which, his own hand manuring, all the trees Of Paradise could have produced, ere fallen From innocence. Now therefore, bend thine ear To supplication; hear his sighs, though mute; Unskilful with what words to pray, let me Interpret for him; me, his advocate And propitiation; all his works on me, Good, or not good, ingraft; my merit those Shall perfect, and for these my death shall pay. Accept me; and, in me, from these receive The smell of peace toward mankind: let him live Before thee reconciled, at least his days Numbered, though sad; till death, his doom, (which I To mitigate thus plead, not to reverse,) To better life shall yield him: where with me All my redeemed may dwell in joy and bliss; Made one with me, as I with thee am one. To whom the Father, without cloud, serene. All thy request for Man, accepted Son, Obtain; all thy request was my decree: But, longer in that Paradise to dwell, The law I gave to Nature him forbids: Those pure immortal elements, that know, No gross, no unharmonious mixture foul, Eject him, tainted now; and purge him off, As a distemper, gross, to air as gross, And mortal food; as may dispose him best For dissolution wrought by sin, that first Distempered all things, and of incorrupt Corrupted. I, at first, with two fair gifts Created him endowed; with happiness, And immortality: that fondly lost, This other served but to eternize woe; Till I provided death: so death becomes His final remedy; and, after life, Tried in sharp tribulation, and refined By faith and faithful works, to second life, Waked in the renovation of the just, Resigns him up with Heaven and Earth renewed. But let us call to synod all the Blest, Through Heaven's wide bounds: from them I will not hide My judgements; how with mankind I proceed, As how with peccant Angels late they saw, And in their state, though firm, stood more confirmed. He ended, and the Son gave signal high To the bright minister that watched; he blew His trumpet, heard in Oreb since perhaps When God descended, and perhaps once more To sound at general doom. The angelick blast Filled all the regions: from their blisful bowers Of amarantine shade, fountain or spring, By the waters of life, where'er they sat In fellowships of joy, the sons of light Hasted, resorting to the summons high; And took their seats; till from his throne supreme The Almighty thus pronounced his sovran will. O Sons, like one of us Man is become To know both good and evil, since his taste Of that defended fruit; but let him boast His knowledge of good lost, and evil got; Happier! had it sufficed him to have known Good by itself, and evil not at all. He sorrows now, repents, and prays contrite, My motions in him; longer than they move, His heart I know, how variable and vain, Self-left. Lest therefore his now bolder hand Reach also of the tree of life, and eat, And live for ever, dream at least to live For ever, to remove him I decree, And send him from the garden forth to till The ground whence he was taken, fitter soil. Michael, this my behest have thou in charge; Take to thee from among the Cherubim Thy choice of flaming warriours, lest the Fiend, Or in behalf of Man, or to invade Vacant possession, some new trouble raise: Haste thee, and from the Paradise of God Without remorse drive out the sinful pair; From hallowed ground the unholy; and denounce To them, and to their progeny, from thence Perpetual banishment. Yet, lest they faint At the sad sentence rigorously urged, (For I behold them softened, and with tears Bewailing their excess,) all terrour hide. If patiently thy bidding they obey, Dismiss them not disconsolate; reveal To Adam what shall come in future days, As I shall thee enlighten; intermix My covenant in the Woman's seed renewed; So send them forth, though sorrowing, yet in peace: And on the east side of the garden place, Where entrance up from Eden easiest climbs, Cherubick watch; and of a sword the flame Wide-waving; all approach far off to fright, And guard all passage to the tree of life: Lest Paradise a receptacle prove To Spirits foul, and all my trees their prey; With whose stolen fruit Man once more to delude. He ceased; and the arch-angelick Power prepared For swift descent; with him the cohort bright Of watchful Cherubim: four faces each Had, like a double Janus; all their shape Spangled with eyes more numerous than those Of Argus, and more wakeful than to drouse, Charmed with Arcadian pipe, the pastoral reed Of Hermes, or his opiate rod. Mean while, To re-salute the world with sacred light, Leucothea waked; and with fresh dews imbalmed The earth; when Adam and first matron Eve Had ended now their orisons, and found Strength added from above; new hope to spring Out of despair; joy, but with fear yet linked; Which thus to Eve his welcome words renewed. Eve, easily my faith admit, that all The good which we enjoy from Heaven descends; But, that from us aught should ascend to Heaven So prevalent as to concern the mind Of God high-blest, or to incline his will, Hard to belief may seem; yet this will prayer Or one short sigh of human breath, upborne Even to the seat of God. For since I sought By prayer the offended Deity to appease; Kneeled, and before him humbled all my heart; Methought I saw him placable and mild, Bending his ear; persuasion in me grew That I was heard with favour; peace returned Home to my breast, and to my memory His promise, that thy seed shall bruise our foe; Which, then not minded in dismay, yet now Assures me that the bitterness of death Is past, and we shall live. Whence hail to thee, Eve rightly called, mother of all mankind, Mother of all things living, since by thee Man is to live; and all things live for Man. To whom thus Eve with sad demeanour meek. Ill-worthy I such title should belong To me transgressour; who, for thee ordained A help, became thy snare; to me reproach Rather belongs, distrust, and all dispraise: But infinite in pardon was my Judge, That I, who first brought death on all, am graced The source of life; next favourable thou, Who highly thus to entitle me vouchsaf'st, Far other name deserving. But the field To labour calls us, now with sweat imposed, Though after sleepless night; for see!the morn, All unconcerned with our unrest, begins Her rosy progress smiling: let us forth; I never from thy side henceforth to stray, Where'er our day's work lies, though now enjoined Laborious, till day droop; while here we dwell, What can be toilsome in these pleasant walks? Here let us live, though in fallen state, content. So spake, so wished much humbled Eve; but Fate Subscribed not: Nature first gave signs, impressed On bird, beast, air; air suddenly eclipsed, After short blush of morn; nigh in her sight The bird of Jove, stooped from his aery tour, Two birds of gayest plume before him drove; Down from a hill the beast that reigns in woods, First hunter then, pursued a gentle brace, Goodliest of all the forest, hart and hind; Direct to the eastern gate was bent their flight. Adam observed, and with his eye the chase Pursuing, not unmoved, to Eve thus spake. O Eve, some further change awaits us nigh, Which Heaven, by these mute signs in Nature, shows Forerunners of his purpose; or to warn Us, haply too secure, of our discharge From penalty, because from death released Some days: how long, and what till then our life, Who knows? or more than this, that we are dust, And thither must return, and be no more? Why else this double object in our sight Of flight pursued in the air, and o'er the ground, One way the self-same hour? why in the east Darkness ere day's mid-course, and morning-light More orient in yon western cloud, that draws O'er the blue firmament a radiant white, And slow descends with something heavenly fraught? He erred not; for by this the heavenly bands Down from a sky of jasper lighted now In Paradise, and on a hill made halt; A glorious apparition, had not doubt And carnal fear that day dimmed Adam's eye. Not that more glorious, when the Angels met Jacob in Mahanaim, where he saw The field pavilioned with his guardians bright; Nor that, which on the flaming mount appeared In Dothan, covered with a camp of fire, Against the Syrian king, who to surprise One man, assassin-like, had levied war, War unproclaimed. The princely Hierarch In their bright stand there left his Powers, to seise Possession of the garden; he alone, To find where Adam sheltered, took his way, Not unperceived of Adam; who to Eve, While the great visitant approached, thus spake. Eve$ now expect great tidings, which perhaps Of us will soon determine, or impose New laws to be observed; for I descry, From yonder blazing cloud that veils the hill, One of the heavenly host; and, by his gait, None of the meanest; some great Potentate Or of the Thrones above; such majesty Invests him coming! yet not terrible, That I should fear; nor sociably mild, As Raphael, that I should much confide; But solemn and sublime; whom not to offend, With reverence I must meet, and thou retire. He ended: and the Arch-Angel soon drew nigh, Not in his shape celestial, but as man Clad to meet man; over his lucid arms A military vest of purple flowed, Livelier than Meliboean, or the grain Of Sarra, worn by kings and heroes old In time of truce; Iris had dipt the woof; His starry helm unbuckled showed him prime In manhood where youth ended; by his side, As in a glistering zodiack, hung the sword, Satan's dire dread; and in his hand the spear. Adam bowed low; he, kingly, from his state Inclined not, but his coming thus declared. Adam, Heaven's high behest no preface needs: Sufficient that thy prayers are heard; and Death, Then due by sentence when thou didst transgress, Defeated of his seisure many days Given thee of grace; wherein thou mayest repent, And one bad act with many deeds well done Mayest cover: Well may then thy Lord, appeased, Redeem thee quite from Death's rapacious claim; But longer in this Paradise to dwell Permits not: to remove thee I am come, And send thee from the garden forth to till The ground whence thou wast taken, fitter soil. He added not; for Adam at the news Heart-struck with chilling gripe of sorrow stood, That all his senses bound; Eve, who unseen Yet all had heard, with audible lament Discovered soon the place of her retire. O unexpected stroke, worse than of Death! Must I thus leave thee$ Paradise? thus leave Thee, native soil! these happy walks and shades, Fit haunt of Gods? where I had hope to spend, Quiet though sad, the respite of that day That must be mortal to us both. O flowers, That never will in other climate grow, My early visitation, and my last ;t even, which I bred up with tender hand From the first opening bud, and gave ye names! Who now shall rear ye to the sun, or rank Your tribes, and water from the ambrosial fount? Thee lastly, nuptial bower! by me adorned With what to sight or smell was sweet! from thee How shall I part, and whither wander down Into a lower world; to this obscure And wild? how shall we breathe in other air Less pure, accustomed to immortal fruits? Whom thus the Angel interrupted mild. Lament not, Eve, but patiently resign What justly thou hast lost, nor set thy heart, Thus over-fond, on that which is not thine: Thy going is not lonely; with thee goes Thy husband; whom to follow thou art bound; Where he abides, think there thy native soil. Adam, by this from the cold sudden damp Recovering, and his scattered spirits returned, To Michael thus his humble words addressed. Celestial, whether among the Thrones, or named Of them the highest; for such of shape may seem Prince above princes! gently hast thou told Thy message, which might else in telling wound, And in performing end us; what besides Of sorrow, and dejection, and despair, Our frailty can sustain, thy tidings bring, Departure from this happy place, our sweet Recess, and only consolation left Familiar to our eyes! all places else Inhospitable appear, and desolate; Nor knowing us, nor known: And, if by prayer Incessant I could hope to change the will Of Him who all things can, I would not cease To weary him with my assiduous cries: But prayer against his absolute decree No more avails than breath against the wind, Blown stifling back on him that breathes it forth: Therefore to his great bidding I submit. This most afflicts me, that, departing hence, As from his face I shall be hid, deprived His blessed countenance: Here I could frequent With worship place by place where he vouchsafed Presence Divine; and to my sons relate, 'On this mount he appeared; under this tree 'Stood visible; among these pines his voice 'I heard; here with him at this fountain talked: So many grateful altars I would rear Of grassy turf, and pile up every stone Of lustre from the brook, in memory, Or monument to ages; and theron Offer sweet-smelling gums, and fruits, and flowers: In yonder nether world where shall I seek His bright appearances, or foot-step trace? For though I fled him angry, yet recalled To life prolonged and promised race, I now Gladly behold though but his utmost skirts Of glory; and far off his steps adore. To whom thus Michael with regard benign. Adam, thou knowest Heaven his, and all the Earth; Not this rock only; his Omnipresence fills Land, sea, and air, and every kind that lives, Fomented by his virtual power and warmed: All the earth he gave thee to possess and rule, No despicable gift; surmise not then His presence to these narrow bounds confined Of Paradise, or Eden: this had been Perhaps thy capital seat, from whence had spread All generations; and had hither come From all the ends of the earth, to celebrate And reverence thee, their great progenitor. But this pre-eminence thou hast lost, brought down To dwell on even ground now with thy sons: Yet doubt not but in valley, and in plain, God is, as here; and will be found alike Present; and of his presence many a sign Still following thee, still compassing thee round With goodness and paternal love, his face Express, and of his steps the track divine. Which that thou mayest believe, and be confirmed Ere thou from hence depart; know, I am sent To show thee what shall come in future days To thee, and to thy offspring: good with bad Expect to hear; supernal grace contending With sinfulness of men; thereby to learn True patience, and to temper joy with fear And pious sorrow; equally inured By moderation either state to bear, Prosperous or adverse: so shalt thou lead Safest thy life, and best prepared endure Thy mortal passage when it comes.--Ascend This hill; let Eve (for I have drenched her eyes) Here sleep below; while thou to foresight wakest; As once thou sleptst, while she to life was formed. To whom thus Adam gratefully replied. Ascend, I follow thee, safe Guide, the path Thou leadest me; and to the hand of Heaven submit, However chastening; to the evil turn My obvious breast; arming to overcome By suffering, and earn rest from labour won, If so I may attain. -- So both ascend In the visions of God. It was a hill, Of Paradise the highest; from whose top The hemisphere of earth, in clearest ken, Stretched out to the amplest reach of prospect lay. Not higher that hill, nor wider looking round, Whereon, for different cause, the Tempter set Our second Adam, in the wilderness; To show him all Earth's kingdoms, and their glory. His eye might there command wherever stood City of old or modern fame, the seat Of mightiest empire, from the destined walls Of Cambalu, seat of Cathaian Can, And Samarchand by Oxus, Temir's throne, To Paquin of Sinaean kings; and thence To Agra and Lahor of great Mogul, Down to the golden Chersonese; or where The Persian in Ecbatan sat, or since In Hispahan; or where the Russian Ksar In Mosco; or the Sultan in Bizance, Turchestan-born; nor could his eye not ken The empire of Negus to his utmost port Ercoco, and the less maritim kings Mombaza, and Quiloa, and Melind, And Sofala, thought Ophir, to the realm Of Congo, and Angola farthest south; Or thence from Niger flood to Atlas mount The kingdoms of Almansor, Fez and Sus, Morocco, and Algiers, and Tremisen; On Europe thence, and where Rome was to sway The world: in spirit perhaps he also saw Rich Mexico, the seat of Montezume, And Cusco in Peru, the richer seat Of Atabalipa; and yet unspoiled Guiana, whose great city Geryon's sons Call El Dorado. But to nobler sights Michael from Adam's eyes the film removed, Which that false fruit that promised clearer sight Had bred; then purged with euphrasy and rue The visual nerve, for he had much to see; And from the well of life three drops instilled. So deep the power of these ingredients pierced, Even to the inmost seat of mental sight, That Adam, now enforced to close his eyes, Sunk down, and all his spirits became entranced; But him the gentle Angel by the hand Soon raised, and his attention thus recalled. Adam, now ope thine eyes; and first behold The effects, which thy original crime hath wrought In some to spring from thee; who never touched The excepted tree; nor with the snake conspired; Nor sinned thy sin; yet from that sin derive Corruption, to bring forth more violent deeds. His eyes he opened, and beheld a field, Part arable and tilth, whereon were sheaves New reaped; the other part sheep-walks and folds; I' the midst an altar as the land-mark stood, Rustick, of grassy sord; thither anon A sweaty reaper from his tillage brought First fruits, the green ear, and the yellow sheaf, Unculled, as came to hand; a shepherd next, More meek, came with the firstlings of his flock, Choicest and best; then, sacrificing, laid The inwards and their fat, with incense strowed, On the cleft wood, and all due rights performed: His offering soon propitious fire from Heaven Consumed with nimble glance, and grateful steam; The other's not, for his was not sincere; Whereat he inly raged, and, as they talked, Smote him into the midriff with a stone That beat out life; he fell;and, deadly pale, Groaned out his soul with gushing blood effused. Much at that sight was Adam in his heart Dismayed, and thus in haste to the Angel cried. O Teacher, some great mischief hath befallen To that meek man, who well had sacrificed; Is piety thus and pure devotion paid? To whom Michael thus, he also moved, replied. These two are brethren, Adam, and to come Out of thy loins; the unjust the just hath slain, For envy that his brother's offering found From Heaven acceptance; but the bloody fact Will be avenged; and the other's faith, approved, Lose no reward; though here thou see him die, Rolling in dust and gore. To which our sire. Alas! both for the deed, and for the cause! But have I now seen Death? Is this the way I must return to native dust? O sight Of terrour, foul and ugly to behold, Horrid to think, how horrible to feel! To whom thus Michael. Death thou hast seen In his first shape on Man; but many shapes Of Death, and many are the ways that lead To his grim cave, all dismal; yet to sense More terrible at the entrance, than within. Some, as thou sawest, by violent stroke shall die; By fire, flood, famine, by intemperance more In meats and drinks, which on the earth shall bring Diseases dire, of which a monstrous crew Before thee shall appear; that thou mayest know What misery the inabstinence of Eve Shall bring on Men. Immediately a place Before his eyes appeared, sad, noisome, dark; A lazar-house it seemed; wherein were laid Numbers of all diseased; all maladies Of ghastly spasm, or racking torture, qualms Of heart-sick agony, all feverous kinds, Convulsions, epilepsies, fierce catarrhs, Intestine stone and ulcer, colick-pangs, Demoniack phrenzy, moaping melancholy, And moon-struck madness, pining atrophy, Marasmus, and wide-wasting pestilence, Dropsies, and asthmas, and joint-racking rheums. Dire was the tossing, deep the groans; Despair Tended the sick busiest from couch to couch; And over them triumphant Death his dart Shook, but delayed to strike, though oft invoked With vows, as their chief good, and final hope. Sight so deform what heart of rock could long Dry-eyed behold? Adam could not, but wept, Though not of woman born; compassion quelled His best of man, and gave him up to tears A space, till firmer thoughts restrained excess; And, scarce recovering words, his plaint renewed. O miserable mankind, to what fall Degraded, to what wretched state reserved! Better end here unborn. Why is life given To be thus wrested from us? rather, why Obtruded on us thus? who, if we knew What we receive, would either no accept Life offered, or soon beg to lay it down; Glad to be so dismissed in peace. Can thus The image of God in Man, created once So goodly and erect, though faulty since, To such unsightly sufferings be debased Under inhuman pains? Why should not Man, Retaining still divine similitude In part, from such deformities be free, And, for his Maker's image sake, exempt? Their Maker's image, answered Michael, then Forsook them, when themselves they vilified To serve ungoverned Appetite; and took His image whom they served, a brutish vice, Inductive mainly to the sin of Eve. Therefore so abject is their punishment, Disfiguring not God's likeness, but their own; Or if his likeness, by themselves defaced; While they pervert pure Nature's healthful rules To loathsome sickness; worthily, since they God's image did not reverence in themselves. I yield it just, said Adam, and submit. But is there yet no other way, besides These painful passages, how we may come To death, and mix with our connatural dust? There is, said Michael, if thou well observe The rule of Not too much; by temperance taught, In what thou eatest and drinkest; seeking from thence Due nourishment, not gluttonous delight, Till many years over thy head return: So mayest thou live; till, like ripe fruit, thou drop Into thy mother's lap; or be with ease Gathered, nor harshly plucked; for death mature: This is Old Age; but then, thou must outlive Thy youth, thy strength, thy beauty; which will change To withered, weak, and gray; thy senses then, Obtuse, all taste of pleasure must forego, To what thou hast; and, for the air of youth, Hopeful and cheerful, in thy blood will reign A melancholy damp of cold and dry To weigh thy spirits down, and last consume The balm of life. To whom our ancestor. Henceforth I fly not death, nor would prolong Life much; bent rather, how I may be quit, Fairest and easiest, of this cumbrous charge; Which I must keep till my appointed day Of rendering up, and patiently attend My dissolution. Michael replied. Nor love thy life, nor hate; but what thou livest Live well; how long, or short, permit to Heaven: And now prepare thee for another sight. He looked, and saw a spacious plain, whereon Were tents of various hue; by some, were herds Of cattle grazing; others, whence the sound Of instruments, that made melodious chime, Was heard, of harp and organ; and, who moved Their stops and chords, was seen; his volant touch, Instinct through all proportions, low and high, Fled and pursued transverse the resonant fugue. In other part stood one who, at the forge Labouring, two massy clods of iron and brass Had melted, (whether found where casual fire Had wasted woods on mountain or in vale, Down to the veins of earth; thence gliding hot To some cave's mouth; or whether washed by stream From underground;) the liquid ore he drained Into fit moulds prepared; from which he formed First his own tools; then, what might else be wrought Fusil or graven in metal. After these, But on the hither side, a different sort From the high neighbouring hills, which was their seat, Down to the plain descended; by their guise Just men they seemed, and all their study bent To worship God aright, and know his works Not hid; nor those things last, which might preserve Freedom and peace to Men; they on the plain Long had not walked, when from the tents, behold! A bevy of fair women, richly gay In gems and wanton dress; to the harp they sung Soft amorous ditties, and in dance came on: The men, though grave, eyed them; and let their eyes Rove without rein; till, in the amorous net Fast caught, they liked; and each his liking chose; And now of love they treat, till the evening-star, Love's harbinger, appeared; then, all in heat They light the nuptial torch, and bid invoke Hymen, then first to marriage rites invoked: With feast and musick all the tents resound. Such happy interview, and fair event Of love and youth not lost, songs, garlands, flowers, And charming symphonies, attached the heart Of Adam, soon inclined to admit delight, The bent of nature; which he thus expressed. True opener of mine eyes, prime Angel blest; Much better seems this vision, and more hope Of peaceful days portends, than those two past; Those were of hate and death, or pain much worse; Here Nature seems fulfilled in all her ends. To whom thus Michael. Judge not what is best By pleasure, though to nature seeming meet; Created, as thou art, to nobler end Holy and pure, conformity divine. Those tents thou sawest so pleasant, were the tents Of wickedness, wherein shall dwell his race Who slew his brother; studious they appear Of arts that polish life, inventers rare; Unmindful of their Maker, though his Spirit Taught them; but they his gifts acknowledged none. Yet they a beauteous offspring shall beget; For that fair female troop thou sawest, that seemed Of Goddesses, so blithe, so smooth, so gay, Yet empty of all good wherein consists Woman's domestick honour and chief praise; Bred only and completed to the taste Of lustful appetence, to sing, to dance, To dress, and troll the tongue, and roll the eye: To these that sober race of men, whose lives Religious titled them the sons of God, Shall yield up all their virtue, all their fame Ignobly, to the trains and to the smiles Of these fair atheists; and now swim in joy, Erelong to swim at large; and laugh, for which The world erelong a world of tears must weep. To whom thus Adam, of short joy bereft. O pity and shame, that they, who to live well Entered so fair, should turn aside to tread Paths indirect, or in the mid way faint! But still I see the tenour of Man's woe Holds on the same, from Woman to begin. From Man's effeminate slackness it begins, Said the Angel, who should better hold his place By wisdom, and superiour gifts received. But now prepare thee for another scene. He looked, and saw wide territory spread Before him, towns, and rural works between; Cities of men with lofty gates and towers, Concourse in arms, fierce faces threatening war, Giants of mighty bone and bold emprise; Part wield their arms, part curb the foaming steed, Single or in array of battle ranged Both horse and foot, nor idly mustering stood; One way a band select from forage drives A herd of beeves, fair oxen and fair kine, From a fat meadow ground; or fleecy flock, Ewes and their bleating lambs over the plain, Their booty; scarce with life the shepherds fly, But call in aid, which makes a bloody fray; With cruel tournament the squadrons join; Where cattle pastured late, now scattered lies With carcasses and arms the ensanguined field, Deserted: Others to a city strong Lay siege, encamped; by battery, scale, and mine, Assaulting; others from the wall defend With dart and javelin, stones, and sulphurous fire; On each hand slaughter, and gigantick deeds. In other part the sceptered heralds call To council, in the city-gates; anon Gray-headed men and grave, with warriours mixed, Assemble, and harangues are heard; but soon, In factious opposition; till at last, Of middle age one rising, eminent In wise deport, spake much of right and wrong, Of justice, or religion, truth, and peace, And judgement from above: him old and young Exploded, and had seized with violent hands, Had not a cloud descending snatched him thence Unseen amid the throng: so violence Proceeded, and oppression, and sword-law, Through all the plain, and refuge none was found. Adam was all in tears, and to his guide Lamenting turned full sad; O!what are these, Death's ministers, not men? who thus deal death Inhumanly to men, and multiply Ten thousandfold the sin of him who slew His brother: for of whom such massacre Make they, but of their brethren; men of men But who was that just man, whom had not Heaven Rescued, had in his righteousness been lost? To whom thus Michael. These are the product Of those ill-mated marriages thou sawest; Where good with bad were matched, who of themselves Abhor to join; and, by imprudence mixed, Produce prodigious births of body or mind. Such were these giants, men of high renown; For in those days might only shall be admired, And valour and heroick virtue called; To overcome in battle, and subdue Nations, and bring home spoils with infinite Man-slaughter, shall be held the highest pitch Of human glory; and for glory done Of triumph, to be styled great conquerours Patrons of mankind, Gods, and sons of Gods; Destroyers rightlier called, and plagues of men. Thus fame shall be achieved, renown on earth; And what most merits fame, in silence hid. But he, the seventh from thee, whom thou beheldst The only righteous in a world preverse, And therefore hated, therefore so beset With foes, for daring single to be just, And utter odious truth, that God would come To judge them with his Saints; him the Most High Rapt in a balmy cloud with winged steeds Did, as thou sawest, receive, to walk with God High in salvation and the climes of bliss, Exempt from death; to show thee what reward Awaits the good; the rest what punishment; Which now direct thine eyes and soon behold. He looked, and saw the face of things quite changed; The brazen throat of war had ceased to roar; All now was turned to jollity and game, To luxury and riot, feast and dance; Marrying or prostituting, as befel, Rape or adultery, where passing fair Allured them; thence from cups to civil broils. At length a reverend sire among them came, And of their doings great dislike declared, And testified against their ways; he oft Frequented their assemblies, whereso met, Triumphs or festivals; and to them preached Conversion and repentance, as to souls In prison, under judgements imminent: But all in vain: which when he saw, he ceased Contending, and removed his tents far off; Then, from the mountain hewing timber tall, Began to build a vessel of huge bulk; Measured by cubit, length, and breadth, and highth; Smeared round with pitch; and in the side a door Contrived; and of provisions laid in large, For man and beast: when lo, a wonder strange! Of every beast, and bird, and insect small, Came sevens, and pairs; and entered in as taught Their order: last the sire and his three sons, With their four wives; and God made fast the door. Mean while the south-wind rose, and, with black wings Wide-hovering, all the clouds together drove From under Heaven; the hills to their supply Vapour, and exhalation dusk and moist, Sent up amain; and now the thickened sky Like a dark cieling stood; down rushed the rain Impetuous; and continued, till the earth No more was seen: the floating vessel swum Uplifted, and secure with beaked prow Rode tilting o'er the waves; all dwellings else Flood overwhelmed, and them with all their pomp Deep under water rolled; sea covered sea, Sea without shore; and in their palaces, Where luxury late reigned, sea-monsters whelped And stabled; of mankind, so numerous late, All left, in one small bottom swum imbarked. How didst thou grieve then, Adam, to behold The end of all thy offspring, end so sad, Depopulation! Thee another flood, Of tears and sorrow a flood, thee also drowned, And sunk thee as thy sons; till, gently reared By the Angel, on thy feet thou stoodest at last, Though comfortless; as when a father mourns His children, all in view destroyed at once; And scarce to the Angel utter'dst thus thy plaint. O visions ill foreseen! Better had I Lived ignorant of future! so had borne My part of evil only, each day's lot Enough to bear; those now, that were dispensed The burden of many ages, on me light At once, by my foreknowledge gaining birth Abortive, to torment me ere their being, With thought that they must be. Let no man seek Henceforth to be foretold, what shall befall Him or his children; evil he may be sure, Which neither his foreknowing can prevent; And he the future evil shall no less In apprehension than in substance feel, Grievous to bear: but that care now is past, Man is not whom to warn: those few escaped Famine and anguish will at last consume, Wandering that watery desart: I had hope, When violence was ceased, and war on earth, All would have then gone well; peace would have crowned With length of happy days the race of Man; But I was far deceived; for now I see Peace to corrupt no less than war to waste. How comes it thus? unfold, celestial Guide, And whether here the race of Man will end. To whom thus Michael. Those, whom last thou sawest In triumph and luxurious wealth, are they First seen in acts of prowess eminent And great exploits, but of true virtue void; Who, having spilt much blood, and done much wast Subduing nations, and achieved thereby Fame in the world, high titles, and rich prey; Shall change their course to pleasure, ease, and sloth, Surfeit, and lust; till wantonness and pride Raise out of friendship hostile deeds in peace. The conquered also, and enslaved by war, Shall, with their freedom lost, all virtue lose And fear of God; from whom their piety feigned In sharp contest of battle found no aid Against invaders; therefore, cooled in zeal, Thenceforth shall practice how to live secure, Worldly or dissolute, on what their lords Shall leave them to enjoy; for the earth shall bear More than enough, that temperance may be tried: So all shall turn degenerate, all depraved; Justice and temperance, truth and faith, forgot; One man except, the only son of light In a dark age, against example good, Against allurement, custom, and a world Offended: fearless of reproach and scorn, The grand-child, with twelve sons encreased, departs From Canaan, to a land hereafter called Egypt, divided by the river Nile; See where it flows, disgorging at seven mouths Into the sea: To sojourn in that land He comes, invited by a younger son In time of dearth; a son, whose worthy deeds Raise him to be the second in that realm Of Pharaoh: There he dies, and leaves his race Growing into a nation, and now grown Suspected to a sequent king, who seeks To stop their overgrowth, as inmate guests Or violence, he of their wicked ways Shall them admonish; and before them set The paths of righteousness, how much more safe And full of peace; denouncing wrath to come On their impenitence; and shall return Of them derided, but of God observed The one just man alive; by his command Shall build a wonderous ark, as thou beheldst, To save himself, and houshold, from amidst A world devote to universal wrack. No sooner he, with them of man and beast Select for life, shall in the ark be lodged, And sheltered round; but all the cataracts Of Heaven set open on the Earth shall pour Rain, day and night; all fountains of the deep, Broke up, shall heave the ocean to usurp Beyond all bounds; till inundation rise Above the highest hills: Then shall this mount Of Paradise by might of waves be moved Out of his place, pushed by the horned flood, With all his verdure spoiled, and trees adrift, Down the great river to the opening gulf, And there take root an island salt and bare, The haunt of seals, and orcs, and sea-mews' clang: To teach thee that God attributes to place No sanctity, if none be thither brought By men who there frequent, or therein dwell. And now, what further shall ensue, behold. He looked, and saw the ark hull on the flood, Which now abated; for the clouds were fled, Driven by a keen north-wind, that, blowing dry, Wrinkled the face of deluge, as decayed; And the clear sun on his wide watery glass Gazed hot, and of the fresh wave largely drew, As after thirst; which made their flowing shrink From standing lake to tripping ebb, that stole With soft foot towards the deep; who now had stopt His sluces, as the Heaven his windows shut. The ark no more now floats, but seems on ground, Fast on the top of some high mountain fixed. And now the tops of hills, as rocks, appear; With clamour thence the rapid currents drive, Towards the retreating sea, their furious tide. Forthwith from out the ark a raven flies, And after him, the surer messenger, A dove sent forth once and again to spy Green tree or ground, whereon his foot may light: The second time returning, in his bill An olive-leaf he brings, pacifick sign: Anon dry ground appears, and from his ark The ancient sire descends, with all his train; Then with uplifted hands, and eyes devout, Grateful to Heaven, over his head beholds A dewy cloud, and in the cloud a bow Conspicuous with three lifted colours gay, Betokening peace from God, and covenant new. Whereat the heart of Adam, erst so sad, Greatly rejoiced; and thus his joy broke forth. O thou, who future things canst represent As present, heavenly Instructer! I revive At this last sight; assured that Man shall live, With all the creatures, and their seed preserve. Far less I now lament for one whole world Of wicked sons destroyed, than I rejoice For one man found so perfect, and so just, That God vouchsafes to raise another world From him, and all his anger to forget. But say, what mean those coloured streaks in Heaven Distended, as the brow of God appeased? Or serve they, as a flowery verge, to bind The fluid skirts of that same watery cloud, Lest it again dissolve, and shower the earth? To whom the Arch-Angel. Dextrously thou aimest; So willingly doth God remit his ire, Though late repenting him of Man depraved; Grieved at his heart, when looking down he saw The whole earth filled with violence, and all flesh Corrupting each their way; yet, those removed, Such grace shall one just man find in his sight, That he relents, not to blot out mankind; And makes a covenant never to destroy The earth again by flood; nor let the sea Surpass his bounds; nor rain to drown the world, With man therein or beast; but, when he brings Over the earth a cloud, will therein set His triple-coloured bow, whereon to look, And call to mind his covenant: Day and night, Seed-time and harvest, heat and hoary frost, Shall hold their course; till fire purge all things new, Both Heaven and Earth, wherein the just shall dwell. Book XII As one who in his journey bates at noon, Though bent on speed; so here the Arch-Angel paused Betwixt the world destroyed and world restored, If Adam aught perhaps might interpose; Then, with transition sweet, new speech resumes. Thus thou hast seen one world begin, and end; And Man, as from a second stock, proceed. Much thou hast yet to see; but I perceive Thy mortal sight to fail; objects divine Must needs impair and weary human sense: Henceforth what is to come I will relate; Thou therefore give due audience, and attend. This second source of Men, while yet but few, And while the dread of judgement past remains Fresh in their minds, fearing the Deity, With some regard to what is just and right Shall lead their lives, and multiply apace; Labouring the soil, and reaping plenteous crop, Corn, wine, and oil; and, from the herd or flock, Oft sacrificing bullock, lamb, or kid, With large wine-offerings poured, and sacred feast, Shall spend their days in joy unblamed; and dwell Long time in peace, by families and tribes, Under paternal rule: till one shall rise Of proud ambitious heart; who, not content With fair equality, fraternal state, Will arrogate dominion undeserved Over his brethren, and quite dispossess Concord and law of nature from the earth; Hunting (and men not beasts shall be his game) With war, and hostile snare, such as refuse Subjection to his empire tyrannous: A mighty hunter thence he shall be styled Before the Lord; as in despite of Heaven, Or from Heaven, claiming second sovranty; And from rebellion shall derive his name, Though of rebellion others he accuse. He with a crew, whom like ambition joins With him or under him to tyrannize, Marching from Eden towards the west, shall find The plain, wherein a black bituminous gurge Boils out from under ground, the mouth of Hell: Of brick, and of that stuff, they cast to build A city and tower, whose top may reach to Heaven; And get themselves a name; lest, far dispersed In foreign lands, their memory be lost; Regardless whether good or evil fame. But God, who oft descends to visit men Unseen, and through their habitations walks To mark their doings, them beholding soon, Comes down to see their city, ere the tower Obstruct Heaven-towers, and in derision sets Upon their tongues a various spirit, to rase Quite out their native language; and, instead, To sow a jangling noise of words unknown: Forthwith a hideous gabble rises loud, Among the builders; each to other calls Not understood; till hoarse, and all in rage, As mocked they storm: great laughter was in Heaven, And looking down, to see the hubbub strange, And hear the din: Thus was the building left Ridiculous, and the work Confusion named. Whereto thus Adam, fatherly displeased. O execrable son! so to aspire Above his brethren; to himself assuming Authority usurped, from God not given: He gave us only over beast, fish, fowl, Dominion absolute; that right we hold By his donation; but man over men He made not lord; such title to himself Reserving, human left from human free. But this usurper his encroachment proud Stays not on Man; to God his tower intends Siege and defiance: Wretched man!what food Will he convey up thither, to sustain Himself and his rash army; where thin air Above the clouds will pine his entrails gross, And famish him of breath, if not of bread? To whom thus Michael. Justly thou abhorrest That son, who on the quiet state of men Such trouble brought, affecting to subdue Rational liberty; yet know withal, Since thy original lapse, true liberty Is lost, which always with right reason dwells Twinned, and from her hath no dividual being: Reason in man obscured, or not obeyed, Immediately inordinate desires, And upstart passions, catch the government From reason; and to servitude reduce Man, till then free. Therefore, since he permits Within himself unworthy powers to reign Over free reason, God, in judgement just, Subjects him from without to violent lords; Who oft as undeservedly enthrall His outward freedom: Tyranny must be; Though to the tyrant thereby no excuse. Yet sometimes nations will decline so low From virtue, which is reason, that no wrong, But justice, and some fatal curse annexed, Deprives them of their outward liberty; Their inward lost: Witness the irreverent son Of him who built the ark; who, for the shame Done to his father, heard this heavy curse, Servant of servants, on his vicious race. Thus will this latter, as the former world, Still tend from bad to worse; till God at last, Wearied with their iniquities, withdraw His presence from among them, and avert His holy eyes; resolving from thenceforth To leave them to their own polluted ways; And one peculiar nation to select From all the rest, of whom to be invoked, A nation from one faithful man to spring: Him on this side Euphrates yet residing, Bred up in idol-worship: O, that men (Canst thou believe?) should be so stupid grown, While yet the patriarch lived, who 'scaped the flood, As to forsake the living God, and fall To worship their own work in wood and stone For Gods! Yet him God the Most High vouchsafes To call by vision, from his father's house, His kindred, and false Gods, into a land Which he will show him; and from him will raise A mighty nation; and upon him shower His benediction so, that in his seed All nations shall be blest: he straight obeys; Not knowing to what land, yet firm believes: I see him, but thou canst not, with what faith He leaves his Gods, his friends, and native soil, Ur of Chaldaea, passing now the ford To Haran; after him a cumbrous train Of herds and flocks, and numerous servitude; Not wandering poor, but trusting all his wealth With God, who called him, in a land unknown. Canaan he now attains; I see his tents Pitched about Sechem, and the neighbouring plain Of Moreh; there by promise he receives Gift to his progeny of all that land, From Hameth northward to the Desart south; (Things by their names I call, though yet unnamed;) From Hermon east to the great western Sea; Mount Hermon, yonder sea; each place behold In prospect, as I point them; on the shore Mount Carmel; here, the double-founted stream, Jordan, true limit eastward; but his sons Shall dwell to Senir, that long ridge of hills. This ponder, that all nations of the earth Shall in his seed be blessed: By that seed Is meant thy great Deliverer, who shall bruise The Serpent's head; whereof to thee anon Plainlier shall be revealed. This patriarch blest, Whom faithful Abraham due time shall call, A son, and of his son a grand-child, leaves; Like him in faith, in wisdom, and renown: The grandchild, with twelve sons increased, departs From Canaan to a land hereafter called Egypt, divided by the river Nile See where it flows, disgorging at seven mouths Into the sea. To sojourn in that land He comes, invited by a younger son In time of dearth, a son whose worthy deeds Raise him to be the second in that realm Of Pharaoh. There he dies, and leaves his race Growing into a nation, and now grown Suspected to a sequent king, who seeks To stop their overgrowth, as inmate guests Too numerous; whence of guests he makes them slaves Inhospitably, and kills their infant males: Till by two brethren (these two brethren call Moses and Aaron) sent from God to claim His people from enthralment, they return, With glory and spoil, back to their promised land. But first, the lawless tyrant, who denies To know their God, or message to regard, Must be compelled by signs and judgements dire; To blood unshed the rivers must be turned; Frogs, lice, and flies, must all his palace fill With loathed intrusion, and fill all the land; His cattle must of rot and murren die; Botches and blains must all his flesh emboss, And all his people; thunder mixed with hail, Hail mixed with fire, must rend the Egyptians sky, And wheel on the earth, devouring where it rolls; What it devours not, herb, or fruit, or grain, A darksome cloud of locusts swarming down Must eat, and on the ground leave nothing green; Darkness must overshadow all his bounds, Palpable darkness, and blot out three days; Last, with one midnight stroke, all the first-born Of Egypt must lie dead. Thus with ten wounds The river-dragon tamed at length submits To let his sojourners depart, and oft Humbles his stubborn heart; but still, as ice More hardened after thaw; till, in his rage Pursuing whom he late dismissed, the sea Swallows him with his host; but them lets pass, As on dry land, between two crystal walls; Awed by the rod of Moses so to stand Divided, till his rescued gain their shore: Such wondrous power God to his saint will lend, Though present in his Angel; who shall go Before them in a cloud, and pillar of fire; By day a cloud, by night a pillar of fire; To guide them in their journey, and remove Behind them, while the obdurate king pursues: All night he will pursue; but his approach Darkness defends between till morning watch; Then through the fiery pillar, and the cloud, God looking forth will trouble all his host, And craze their chariot-wheels: when by command Moses once more his potent rod extends Over the sea; the sea his rod obeys; On their embattled ranks the waves return, And overwhelm their war: The race elect Safe toward Canaan from the shore advance Through the wild Desart, not the readiest way; Lest, entering on the Canaanite alarmed, War terrify them inexpert, and fear Return them back to Egypt, choosing rather Inglorious life with servitude; for life To noble and ignoble is more sweet Untrained in arms, where rashness leads not on. This also shall they gain by their delay In the wide wilderness; there they shall found Their government, and their great senate choose Through the twelve tribes, to rule by laws ordained: God from the mount of Sinai, whose gray top Shall tremble, he descending, will himself In thunder, lightning, and loud trumpets' sound, Ordain them laws; part, such as appertain To civil justice; part, religious rites Of sacrifice; informing them, by types And shadows, of that destined Seed to bruise The Serpent, by what means he shall achieve Mankind's deliverance. But the voice of God To mortal ear is dreadful: They beseech That Moses might report to them his will, And terrour cease; he grants what they besought, Instructed that to God is no access Without Mediator, whose high office now Moses in figure bears; to introduce One greater, of whose day he shall foretel, And all the Prophets in their age the times Of great Messiah shall sing. Thus, laws and rites Established, such delight hath God in Men Obedient to his will, that he vouchsafes Among them to set up his tabernacle; The Holy One with mortal Men to dwell: By his prescript a sanctuary is framed Of cedar, overlaid with gold; therein An ark, and in the ark his testimony, The records of his covenant; over these A mercy-seat of gold, between the wings Of two bright Cherubim; before him burn Seven lamps as in a zodiack representing The heavenly fires; over the tent a cloud Shall rest by day, a fiery gleam by night; Save when they journey, and at length they come, Conducted by his Angel, to the land Promised to Abraham and his seed:--The rest Were long to tell; how many battles fought How many kings destroyed; and kingdoms won; Or how the sun shall in mid Heaven stand still A day entire, and night's due course adjourn, Man's voice commanding, 'Sun, in Gibeon stand, 'And thou moon in the vale of Aialon, 'Till Israel overcome! so call the third From Abraham, son of Isaac; and from him His whole descent, who thus shall Canaan win. Here Adam interposed. O sent from Heaven, Enlightener of my darkness, gracious things Thou hast revealed; those chiefly, which concern Just Abraham and his seed: now first I find Mine eyes true-opening, and my heart much eased; Erewhile perplexed with thoughts, what would become Of me and all mankind: But now I see His day, in whom all nations shall be blest; Favour unmerited by me, who sought Forbidden knowledge by forbidden means. This yet I apprehend not, why to those Among whom God will deign to dwell on earth So many and so various laws are given; So many laws argue so many sins Among them; how can God with such reside? To whom thus Michael. Doubt not but that sin Will reign among them, as of thee begot; And therefore was law given them, to evince Their natural pravity, by stirring up Sin against law to fight: that when they see Law can discover sin, but not remove, Save by those shadowy expiations weak, The blood of bulls and goats, they may conclude Some blood more precious must be paid for Man; Just for unjust; that, in such righteousness To them by faith imputed, they may find Justification towards God, and peace Of conscience; which the law by ceremonies Cannot appease; nor Man the mortal part Perform; and, not performing, cannot live. So law appears imperfect; and but given With purpose to resign them, in full time, Up to a better covenant; disciplined From shadowy types to truth; from flesh to spirit; From imposition of strict laws to free Acceptance of large grace; from servile fear To filial; works of law to works of faith. And therefore shall not Moses, though of God Highly beloved, being but the minister Of law, his people into Canaan lead; But Joshua, whom the Gentiles Jesus call, His name and office bearing, who shall quell The adversary-Serpent, and bring back Through the world's wilderness long-wandered Man Safe to eternal Paradise of rest. Mean while they, in their earthly Canaan placed, Long time shall dwell and prosper, but when sins National interrupt their publick peace, Provoking God to raise them enemies; From whom as oft he saves them penitent By Judges first, then under Kings; of whom The second, both for piety renowned And puissant deeds, a promise shall receive Irrevocable, that his regal throne For ever shall endure; the like shall sing All Prophecy, that of the royal stock Of David (so I name this king) shall rise A Son, the Woman's seed to thee foretold, Foretold to Abraham, as in whom shall trust All nations; and to kings foretold, of kings The last; for of his reign shall be no end. But first, a long succession must ensue; And his next son, for wealth and wisdom famed, The clouded ark of God, till then in tents Wandering, shall in a glorious temple enshrine. Such follow him, as shall be registered Part good, part bad; of bad the longer scroll; Whose foul idolatries, and other faults Heaped to the popular sum, will so incense God, as to leave them, and expose their land, Their city, his temple, and his holy ark, With all his sacred things, a scorn and prey To that proud city, whose high walls thou sawest Left in confusion; Babylon thence called. There in captivity he lets them dwell The space of seventy years; then brings them back, Remembering mercy, and his covenant sworn To David, stablished as the days of Heaven. Returned from Babylon by leave of kings Their lords, whom God disposed, the house of God They first re-edify; and for a while In mean estate live moderate; till, grown In wealth and multitude, factious they grow; But first among the priests dissention springs, Men who attend the altar, and should most Endeavour peace: their strife pollution brings Upon the temple itself: at last they seise The scepter, and regard not David's sons; Then lose it to a stranger, that the true Anointed King Messiah might be born Barred of his right; yet at his birth a star, Unseen before in Heaven, proclaims him come; And guides the eastern sages, who inquire His place, to offer incense, myrrh, and gold: His place of birth a solemn Angel tells To simple shepherds, keeping watch by night; They gladly thither haste, and by a quire Of squadroned Angels hear his carol sung. A virgin is his mother, but his sire The power of the Most High: He shall ascend The throne hereditary, and bound his reign With Earth's wide bounds, his glory with the Heavens. He ceased, discerning Adam with such joy Surcharged, as had like grief been dewed in tears, Without the vent of words; which these he breathed. O prophet of glad tidings, finisher Of utmost hope! now clear I understand What oft my steadiest thoughts have searched in vain; Why our great Expectation should be called The seed of Woman: Virgin Mother, hail, High in the love of Heaven; yet from my loins Thou shalt proceed, and from thy womb the Son Of God Most High: so God with Man unites! Needs must the Serpent now his capital bruise Expect with mortal pain: Say where and when Their fight, what stroke shall bruise the victor's heel. To whom thus Michael. Dream not of their fight, As of a duel, or the local wounds Of head or heel: Not therefore joins the Son Manhood to Godhead, with more strength to foil Thy enemy; nor so is overcome Satan, whose fall from Heaven, a deadlier bruise, Disabled, not to give thee thy death's wound: Which he, who comes thy Saviour, shall recure, Not by destroying Satan, but his works In thee, and in thy seed: Nor can this be, But by fulfilling that which thou didst want, Obedience to the law of God, imposed On penalty of death, and suffering death; The penalty to thy transgression due, And due to theirs which out of thine will grow: So only can high Justice rest appaid. The law of God exact he shall fulfil Both by obedience and by love, though love Alone fulfil the law; thy punishment He shall endure, by coming in the flesh To a reproachful life, and cursed death; Proclaiming life to all who shall believe In his redemption; and that his obedience, Imputed, becomes theirs by faith; his merits To save them, not their own, though legal, works. For this he shall live hated, be blasphemed, Seised on by force, judged, and to death condemned A shameful and accursed, nailed to the cross By his own nation; slain for bringing life: But to the cross he nails thy enemies, The law that is against thee, and the sins Of all mankind, with him there crucified, Never to hurt them more who rightly trust In this his satisfaction; so he dies, But soon revives; Death over him no power Shall long usurp; ere the third dawning light Return, the stars of morn shall see him rise Out of his grave, fresh as the dawning light, Thy ransom paid, which Man from death redeems, His death for Man, as many as offered life Neglect not, and the benefit embrace By faith not void of works: This God-like act Annuls thy doom, the death thou shouldest have died, In sin for ever lost from life; this act Shall bruise the head of Satan, crush his strength, Defeating Sin and Death, his two main arms; And fix far deeper in his head their stings Than temporal death shall bruise the victor's heel, Or theirs whom he redeems; a death, like sleep, A gentle wafting to immortal life. Nor after resurrection shall he stay Longer on earth, than certain times to appear To his disciples, men who in his life Still followed him; to them shall leave in charge To teach all nations what of him they learned And his salvation; them who shall believe Baptizing in the profluent stream, the sign Of washing them from guilt of sin to life Pure, and in mind prepared, if so befall, For death, like that which the Redeemer died. All nations they shall teach; for, from that day, Not only to the sons of Abraham's loins Salvation shall be preached, but to the sons Of Abraham's faith wherever through the world; So in his seed all nations shall be blest. Then to the Heaven of Heavens he shall ascend With victory, triumphing through the air Over his foes and thine; there shall surprise The Serpent, prince of air, and drag in chains Through all his realm, and there confounded leave; Then enter into glory, and resume His seat at God's right hand, exalted high Above all names in Heaven; and thence shall come, When this world's dissolution shall be ripe, With glory and power to judge both quick and dead; To judge the unfaithful dead, but to reward His faithful, and receive them into bliss, Whether in Heaven or Earth; for then the Earth Shall all be Paradise, far happier place Than this of Eden, and far happier days. So spake the Arch-Angel Michael; then paused, As at the world's great period; and our sire, Replete with joy and wonder, thus replied. O Goodness infinite, Goodness immense! That all this good of evil shall produce, And evil turn to good; more wonderful Than that which by creation first brought forth Light out of darkness! Full of doubt I stand, Whether I should repent me now of sin By me done, and occasioned; or rejoice Much more, that much more good thereof shall spring; To God more glory, more good-will to Men From God, and over wrath grace shall abound. But say, if our Deliverer up to Heaven Must re-ascend, what will betide the few His faithful, left among the unfaithful herd, The enemies of truth? Who then shall guide His people, who defend? Will they not deal Worse with his followers than with him they dealt? Be sure they will, said the Angel; but from Heaven He to his own a Comforter will send, The promise of the Father, who shall dwell His Spirit within them; and the law of faith, Working through love, upon their hearts shall write, To guide them in all truth; and also arm With spiritual armour, able to resist Satan's assaults, and quench his fiery darts; What man can do against them, not afraid, Though to the death; against such cruelties With inward consolations recompensed, And oft supported so as shall amaze Their proudest persecutors: For the Spirit, Poured first on his Apostles, whom he sends To evangelize the nations, then on all Baptized, shall them with wonderous gifts endue To speak all tongues, and do all miracles, As did their Lord before them. Thus they win Great numbers of each nation to receive With joy the tidings brought from Heaven: At length Their ministry performed, and race well run, Their doctrine and their story written left, They die; but in their room, as they forewarn, Wolves shall succeed for teachers, grievous wolves, Who all the sacred mysteries of Heaven To their own vile advantages shall turn Of lucre and ambition; and the truth With superstitions and traditions taint, Left only in those written records pure, Though not but by the Spirit understood. Then shall they seek to avail themselves of names, Places, and titles, and with these to join Secular power; though feigning still to act By spiritual, to themselves appropriating The Spirit of God, promised alike and given To all believers; and, from that pretence, Spiritual laws by carnal power shall force On every conscience; laws which none shall find Left them inrolled, or what the Spirit within Shall on the heart engrave. What will they then But force the Spirit of Grace itself, and bind His consort Liberty? what, but unbuild His living temples, built by faith to stand, Their own faith, not another's? for, on earth, Who against faith and conscience can be heard Infallible? yet many will presume: Whence heavy persecution shall arise On all, who in the worship persevere Of spirit and truth; the rest, far greater part, Will deem in outward rites and specious forms Religion satisfied; Truth shall retire Bestuck with slanderous darts, and works of faith Rarely be found: So shall the world go on, To good malignant, to bad men benign; Under her own weight groaning; till the day Appear of respiration to the just, And vengeance to the wicked, at return Of him so lately promised to thy aid, The Woman's Seed; obscurely then foretold, Now ampler known thy Saviour and thy Lord; Last, in the clouds, from Heaven to be revealed In glory of the Father, to dissolve Satan with his perverted world; then raise From the conflagrant mass, purged and refined, New Heavens, new Earth, ages of endless date, Founded in righteousness, and peace, and love; To bring forth fruits, joy and eternal bliss. He ended; and thus Adam last replied. How soon hath thy prediction, Seer blest, Measured this transient world, the race of time, Till time stand fixed! Beyond is all abyss, Eternity, whose end no eye can reach. Greatly-instructed I shall hence depart; Greatly in peace of thought; and have my fill Of knowledge, what this vessel can contain; Beyond which was my folly to aspire. Henceforth I learn, that to obey is best, And love with fear the only God; to walk As in his presence; ever to observe His providence; and on him sole depend, Merciful over all his works, with good Still overcoming evil, and by small Accomplishing great things, by things deemed weak Subverting worldly strong, and worldly wise By simply meek: that suffering for truth's sake Is fortitude to highest victory, And, to the faithful, death the gate of life; Taught this by his example, whom I now Acknowledge my Redeemer ever blest. To whom thus also the Angel last replied. This having learned, thou hast attained the sum Of wisdom; hope no higher, though all the stars Thou knewest by name, and all the ethereal powers, All secrets of the deep, all Nature's works, Or works of God in Heaven, air, earth, or sea, And all the riches of this world enjoyedst, And all the rule, one empire; only add Deeds to thy knowledge answerable; add faith, Add virtue, patience, temperance; add love, By name to come called charity, the soul Of all the rest: then wilt thou not be loth To leave this Paradise, but shalt possess A Paradise within thee, happier far.-- Let us descend now therefore from this top Of speculation; for the hour precise Exacts our parting hence; and see!the guards, By me encamped on yonder hill, expect Their motion; at whose front a flaming sword, In signal of remove, waves fiercely round: We may no longer stay: go, waken Eve; Her also I with gentle dreams have calmed Portending good, and all her spirits composed To meek submission: thou, at season fit, Let her with thee partake what thou hast heard; Chiefly what may concern her faith to know, The great deliverance by her seed to come (For by the Woman's seed) on all mankind: That ye may live, which will be many days, Both in one faith unanimous, though sad, With cause, for evils past; yet much more cheered With meditation on the happy end. He ended, and they both descend the hill; Descended, Adam to the bower, where Eve Lay sleeping, ran before; but found her waked; And thus with words not sad she him received. Whence thou returnest, and whither wentest, I know; For God is also in sleep; and dreams advise, Which he hath sent propitious, some great good Presaging, since with sorrow and heart's distress Wearied I fell asleep: But now lead on; In me is no delay; with thee to go, Is to stay here; without thee here to stay, Is to go hence unwilling; thou to me Art all things under $Heaven, all places thou, Who for my wilful crime art banished hence. This further consolation yet secure I carry hence; though all by me is lost, Such favour I unworthy am vouchsafed, By me the Promised Seed shall all restore. So spake our mother Eve; and Adam heard Well pleased, but answered not: For now, too nigh The Arch-Angel stood; and, from the other hill To their fixed station, all in bright array The Cherubim descended; on the ground Gliding meteorous, as evening-mist Risen from a river o'er the marish glides, And gathers ground fast at the labourer's heel Homeward returning. High in front advanced, The brandished sword of God before them blazed, Fierce as a comet; which with torrid heat, And vapour as the Libyan air adust, Began to parch that temperate clime; whereat In either hand the hastening Angel caught Our lingering parents, and to the eastern gate Led them direct, and down the cliff as fast To the subjected plain; then disappeared. They, looking back, all the eastern side beheld Of Paradise, so late their happy seat, Waved over by that flaming brand; the gate With dreadful faces thronged, and fiery arms: Some natural tears they dropt, but wiped them soon; The world was all before them, where to choose Their place of rest, and Providence their guide: They, hand in hand, with wandering steps and slow, Through Eden took their solitary way. [The End] @@ <@xx| g |>x?p8<x?x?=|?~8??<??p??=>x?`?~xxx??9?p~xxx?߁?x~0 ?xπ?|>@`??x營x|<>|ߏߟx烿||?<ߟϟxǁ|;x?8|ϟϟx|x??ǀ~{??ߟ|Ϗ~πϟxxψO???}ߏ|Ͽπϟ|xcϏϏ??>~?Ϗ>?ϟxx燏s?>x`?~?Ͽ>?πϏ|xǀσ~??~?Ͼ|πχs|x߁?ߟ?~?`Ͽ|?ϟ???Ϗ~~>Ͽx?翀|`?~ߏ~~??||?~<@x?<x?ߟ????|p>@px@0|~<<8>?>??>>?>?>~~<?~8?><~?>|@|?|s p~??< ?~?|????|???~??~?>|~}|?~?߀|>~|>Ͽ??~|}~?~>|ߟ?>~|?>|Ϗ?|>|?>>~||}@>??~>|>>~~|>>|ߏ~|>}?>?O>>|~<π|?|}p|xxߏ ~>}?>8>~?߀|?~>|~|ߏ>χ>?~?}߃???~?π????~?????????| `?|?x|8`` y??x >x?~~8|?~>?x~?~>??>~ > `>|<|g>><<? >>??~>???>?~>~??>?>>??p~>?>>>?~}?~π>>>>>>=?|?|߇߇~?>?>>>>~}`?>~?|~π~>>>>}>~|?~߇~>~?>>>>|}??>?|~O~~>3>>>>>}>~|?|χϟ~?~|~?~~?>>>>|}>`?>~||π?~>?>~~߾>~~߀?~??~>?>???~??<~?>?~~>?|?}>8?O>??q`x>?@?|>?8??x0 ?>>??<??<>??@>{>?|??>{<?|>?>>|p?|>>|ހ?| 0?|ϟ?x?>ϟ?xx?~???Ϗ????????}|??}~~~|}?>|~|?>~|Ͽ?>~|Ͽ?À=>~|Ͽ??~~|Ͽ?>~|ϟπ~ϟ߿~ߟ????~?ߏ??? ?|=>0?y~x|?x~?x?>y~x<}?8@`|>p|>|><|><|~|||||||||x||x|||||<||<|||Ǿ|x?|8|<<x?|?<|x?|x??|?x|x?|x?|?|?8?|?8?|<>>?p||<>xp|x>xr>||>8>y8|x>~<||Ͽ~x><}?x<x|?8x?'0|?|8|8|<<|?|>|`><|>>|~|??|?x|߀|?x|x?x|>x?|<||p|||||x`|x?|?|?|?||?| `|?>||||||||||||||||| p]|><|<<><|~<<x |<8x|~8<|>8x<|`8>|>8|8x=0?|x0x?<~?p>|??|Ǐq?p>?~?|χ3<`<>|??x>~<߃<|ǟ<x<><<|x|ǿx>?x<<<xx<>?x<xx<<>~yϟ<8<LJx<<#χ>?y<|>xϞ2x<<ǜ{??8~<| ǟ>3x<<|?x<~|39|Ͽ8?|x<><?||px|???|p<@?~??p|x< <po<|><<`|>9@< |>>??8|~|8?`~8||?>#0<<?|xp?? ?p00?| ?|?p|?|`~<`?~~|`p 3|??@><????><χ>?߇y><?>?||<>>xpx??|>~?Ϟ1xxx>?>>>|?ǏsϏLJxxx~|>x>>|<<ß3ϏO燏x><||<?珏?x<<|<xǏx ><<<x><|x<xǏx?><<<<|xx?><||>|oLJx>>>?x??x><<||<3Ϗ~8y|x=>>~~???|>|>><~>~9矜?y>>>>?|>~<|~~?ϟx8|?>|?Ϗx|x<?~~???xx<|~~Ax~<8~0o|00_~|~>|>xx|x|x|<?>|p>?>?~><?`~|><?|>xx|x8x|p<>|<<<|>?|<<> px<g>yx@x g<?p<<1<>~< <3~???<<<|x>xg~||>x<?~x~xx<>|?|>x<?x>><y燀><?x<>>x><x><<|><x<x|>>|><x<gx>>>><|<Ǽx|xx<???<>><|8<ǿ|x~?|<>>>><?>~|~>xx??|><<??~>>|@ ?|>>>?|~?~~? ??~`<x<`<x| ` |px|@x|xx|x<<>px||08 <x 00`|~|>????>>~?<|0>???yxx<>>ǀpxx|<<Ǐ~xxx<|>x<|<χ<p<?|Ͽ>>>||??xxx<?|>y>?|<p<3Ϟ?|||xx|<1Ǐx>|#LJx<cx||ϟ||<s8q?π<>x>|<Ϗǀ8>?|σ>|x>?Ǐ<?y?<>ϟ??8?<a?<?88?぀x??@p0 ?>;@xx xx|8?>??xxGxw?8x |~p`x??|?σϏǏǜx>?Ϟ~??x|xxxxx<<燇x<<LJ ;><?x?x<LJ?><>xxx~p<LJ ϟx><<π>xx|9<燇|<Gyx|Ϗ?>sy?~?σxx>>??~~p?|~x<8?y>?pp?> ??>?<pps<x~x `8~?x`x<>`?x`xp|0?;??|0??x?x>?|xLJyyy>~xxgx>?燏>Ǐ0g7nj|珟pǎ<|x><<yyxLJx~8<?πyxϏ~>x<π~x<@p>p<@<?|8g8?>0<x~~>qx?pp|x><88<|>|x ~<|`<x<||<||yx<xx<q<<> ><<<|}x<xx<y 0ÀǞ<<<||y<x`x0<y<xǟ><<<|}x<xxx|<><|}|<>||y~~x??8<pp8<>>?||???8xp< 8~~??x<xgp~?<|p<x~>|xx~|88?|<|0g?88<??p~?88xx>88~?|??<>xx?80|Ϗ>ϟ<ǿxxy?<p|yLJヿx<|xx?<?p|Ϗ<x=x?xx<x?`xxx=x>xx?x8<<}|<x=xxxx<8?ǰ|燀>|9xyxxǿ8x?|χ>??x8?>|>??|x`|?@?8<><88x?>?>??>0~|???>|?>????|<~?>?xx|=Ǐ|?~ǀ|x?~~~8x<ǃLJπ>x??>?~?<~<x{<ǃ>x<<<>?~|0 ~??~σ>x<> <>??>~?|?~?>σx>x|> `<|><?>?~??~|?~??σ>|χ=>>??>?~??~|~~'σLJǀ<||~???>>||>|LJ?x~???~?~~|?߿>?|?~|~|Ǐϟ???~>>>~||~?>~|7>|ǁ?>?>~|?|~>?||~|?<>?>~||??>~|>||???>~|??|~0>?~|op?||?|p?>8>>~|?ǀ||>x??>~|~>|?y???~>~|?߿?~||??~~|?>?>~???~~~?????????~????~??>8<8<?>>> ~?<|? 88<> <<|>> ><>|~x>88?x<|?8>px#ǀ|?|?xx> pp??> |8>~?χ?|yLJx~?x=<ϟxχ?~|?<|<LJ?<ះx~|>~|g<CLJxx~>|>>>|>χ'>||<||<<LJ><<LJx~|?LJ|xx~??~?>??||<<<<<LJ|Àx~χ???~?||><<> 1LJ>|x????||<<>ñÞ>???>~>|>><>LJ>?<LJ?|<~??}߀?>}|=|>|>><<Ϗ<>>???~<?~|~?~ߟ????|||>|?><???|8|~||~ߟ???>~?~||>~~?>>x|~|||~ߟ????||>>~?|x|~||~Ϗ??>?~|>0?>| ~||~~ ߟ????8?~>x?~|~?~Ͽ>ߟ?}π??>???~|~~Ͽߟ?????~~?߿ߟ????~?????<|>ߏ~x>w 8>`>|>8>|08xx<8p<0<88x?x<x8<=|?<o{?>?`??????><>x<|?x8π>cx?χ?>x>>><|x<||x>?<=<<>xLJ<xxxx<x??ǁpπǏ?|yx9<<xpxx>x<|><<|<xxxx<xxx>x~>>>?|y<<xxx8xx>3<0πϟ~<xǃ<>xxxx|<xx0x|x?Ǐ>>?||<OLJ<|xxx|~>>x>cχ<<<}??>?߇g><|>?<Ϗx????~~πs>||>~?< {>>~||<0??>~??8<|x8|>~0 @> xχ>p>>>Ϗx?GO???>x?8;3??<xO?~>ǟyp?|<??~}<|?>8|?~}>~?~|~|??q83><<||x?<???>~}Ϗ>x~|x<<x?<>?????~?Ǐx?<8???>~?ϏǏxo~x<<x<<<o??????>~Ϗx?~x<<<3??~ߟ~>>>~|Ǐx>|<< ?<~>??~>?>?>>>~||Ϗ>yx?|<<|x?>>>~|Ǐ`<|y><<<<|xx?|>?>??>??>>>>>||Ϗ|x?~||~?~??|~~>?>>>~||Ϗ?π~~~>|>?>~??~>x?|??>>||~xϏߏ?~||<????;ߟ??ϟ>>~???|x??>????~~|χ?8`x x߿~~|~~?ߟ8x?8xy?@880|x><x>>8|< ?>|??~>@0`?>~@G????? ?  >  ????<< >>Ǐ>>??{>>8>?{<<>?>>~Ϙ<<<<<<x<???>>>}9<>><x<<< <x>|{|<<x<<><<x<????>|;<><yx<><xx0|>>ߏϏ?x|<<x<><<<??>Ϗ||><|x><0?>>Ϗ||<<<>?????>ϟ>>Ϗ|><<<>><????>>Ϗ>?>>Ϗ9}Ϟ><<?>~~?>G??߀>Ϗ?=>|??>~~<x<wǀ>ϟ?~߀?>߇Ϗ?~~0<??Ϟ?>Ϗ?|<y??????߇ϟ???|?>>>?߀?߀>>>????>|>?Ϗ?xx~>p||>@80|~7? <~>>~|@>><?|<>|}~< >?~~>~`<`x< <?>?~x`>>|  x>|?????~p~|<p>|}??>>x?>?>p?=x>|?|y?x<>|<<w??|?>Ǐy8x<|?>?>??><|y<ǟχ<<3~<<<|??????|><><ÿ<x<>|x?x<7y<?<<??~ϼ?>??||?|>}ǀ<>x>>>?>>?>?||x>x><ǀx>~Ϗ>????>>|?|>|>~}ǏyÞx<?0~~}>>>?>?>?<||x? >|~>`Ϗ>????>>||>>>|y<<>x~?>~ ?>>?>>|>~|0x?|px<þ?~<>~pϟ>??|?|>>|x|>08p?>~~?>?>|>>~~}|??<@p<???~~ߟ?????~~||pxp?>?~~ߏ????~?>??????<|~~ϟxp8A >x |>> p~0>`~x~@8~p8<|~|`|xC0 '|??p0>???`>?y 7gϏϏ??y8x??<LJ|0? ǀ8>LJLJ<~y?|???}?yxǀ8>LJ<<x??>?x8??ǃ<<?y????|?s|0xǃ><y???|>|px燃ǃ><<Gq~??p|><??p<|LJǃ<a<?~|}>?>|>>|?ǀpx|8LJLJ><s8|?>~||??|>0>?ǀ`xǃ?LJǏ>?~||?>?>y>>>?9>???>??|?|>~||?~~?>?χ??@?~|?߆>~??>??>>?χ~"``0<?>~||?{ߟ???~ ~~|?χ?{???>~x|<`>?~~|߿<??x?~~??~8?`|?À||99|l>}??<><~><?|||~???~p<><>~@~||x~|2z?~~|?~x~?~?~?~?~??>?~8?~8?|8??~8??|p??~0?|?~?|?~?|~?|~?|>?|~?|x~?|?~??|?~??~??>??~??>??~??>???~??>???>??>??>??>???>??>???~???~???~??~???~??~???~??~???~??|???~??~>??~8?|?|<|>?@?>?>8>?<?||x<?> ??><|x?<??||x|?>ǀ??>~|?>~x?>?>x?>?~xx?>?>x|?>`~x|?>1π??><~?>?sπ?<~<~>?`>x?yǀ?~>>>?>?0?~<<?>?~<?>??~?>?>?>??~<?>?><????~<????~<????~<???><??><??><???><~???><???><???><???><?><?><??><??>???><??><???><???><??~<??>>??~<?><>?~<?><>~<À?>>~<À?>>~<?><?><?><>~<?><?~<?>?~<?>?><?>?><?>>?><?>?><?>?>?>?>>?>?>?>p?>p?>>p?>p?>>p?<>p?><p?>x?>xx<xx<xx<xx<x8<>x8<x8<x8<8<8<>< <?~><8<~><< <>so?߿s~?8<sx~<??~?>|~>0~@x>}pp|<>?<?><<x<<<?<?9<9<<??|><q0<@@><><<<<<p?pp<ypp?<?`> ?<<<<<<<<<<<<<?>|8<~||>>x ~|~?yx~|~??<~<8~<>~||?~~0`Gx~0~?~??>||???x?|?~?q~~?~???c||??>~~?>~~>>|???||ߟߏ>>~|~~߸>~~??|}@?>~|ϟ~~@>~|???@@??>~|~~w?~`>~~??|ߏ|p??~~~?|~?|?Ϟ}`Ç?~p~~???0?`|~}|>?p >?8>>xp`?x q??????<;?|c???~?χ??~???~???>?>~~|???>?>|?~|????~?>?||?߀???~>?||??>?>~ ?>?||>??>?~p>?||@??????|>>||?χ<????~~~|>χ???~|??>???>>??~???x~~|???{?߀??{??{??{?}{|{p|x{`{x<<~>p{x~?>x~<|>~ߏ{8x~~ ????><??? >~???χ?~~>??>~?????߿?~~~?????>>?>>~?π????>~~~|?>||?<x}??>>~~>?~}|?<??>~~~|?>>|?~|w}??>>~~?>?߀|}?<?>>~~|;?ǿ>w|} ><???~~~9?>~ߏ|}ߟ><??~~~}?>~|}߿?>??~?~~|?>????~>???~~|???~~?>? |||}?7<8` ?;????{???>>~~>|>|?>|~? ?>||?=>|ߏ?=<ߟ}><ϟ>a??0>>>>}Ͽ??=>??߿>=>`~ᅬ? ?>??@0}?p8???8|?xy |< ?>~?p?x>p~?p?>?p??p~p?}~<?@0<<??8A?a?>?xx{?yyyyyyCyyy{y{}{<=<<????~???π???||88À`~|08À??~|?@~>|>?>??>?????>?????? >??x??À~~~?~x߀~?>?~~|?~?߀~?>~>?~<?~?߀/<?~|~>~~~|@ 80?>| ?Ç?~|??߀<<~~~>|~ǀ0A8<8<<ǀ<π<<<x?y8y| >>????ߟ矟?>?ߟ~p??ߟp???ߟs??~p|??~<|??p8?>~pxx>xxppxp8xpxpxxxxxxxxxx8888888<<??=8<8<8<8<8<<<<<<<<<>>?> ? ?<~0d8(??>>>>?>><<>><<>><<>>8>>8>>x>>x>>?>>?>>>><>?>?>????aC????>?>?>?>>>>?>>||>>?|p>>`??>>>xy?>~>>>>?>?>>>>>?>?>?>>>>>>>>?>>?>>?>>?>>??>>?>?>?>?>?>? >??>>?>?>?`>?>>>>?>>>>>?>>>>?>>>>>>?>>>>?>>>?>>?>?>>>?>>>?>?>?>>>?>>>>?>>8>?>|xx>?x>>?8x`x>><>>>~p~?g`<8xg|x>??π|x>?????w><<?<㏟><>=x{>Ϗ|?<?<8x>Ϗ|?x<?<|>Ϗ?|x<xxx<x<|>?||>|xx<x<|>Ϗϟx? ||>||<|<|>ǟ?<?y??8>8>>> x>><??????x>???>???>?|?~????>>| 0|<>88`>?>`>>>?>?>?>>0 >>>@> 88p >>>x|<>|~~>>>x|>>|>?>>@@xx8<<|><` >??#8|`|@><<p>>xx???<x8<| x?>|χ>?xw>>???>x<?<>??>9?Ϟ||||?|π8>}<<>>><xxy|<|x|<>>||<<|Oǟ!LJ<>?~>>><|x<|x<Ϗ<?x?>>?|||><||x燏>x?<>>><|>xxx?|<|xy<<|x>>>~|||O<<<|x'ǟ|<><<>?>~y||x|<|xqǟ>~p8><<<<|>?||<|y>y>>??<>??~~~??Ϗ>??|>?~??ϟ?x?>> <~|~><|?<ߏx<>> <}>><>>?>>?>?>?>?>>`>>~>>p|?>>~~>|?>>><>>>> |<?>>>| `>>wx<>xp>>?>8~?|x>>?>>???>xc#@x?>>~|>>??>|Ϗ?? >||y>>}?<x߇?>|>?>>|y<<||LJ|x?>>|s>|?xx??>|>?>>><|LJxy?|`??>|>>?|xxx???|?>|>|?>?}< }|LJxy<| ?>O ~?>||ǀ>?π>>?>|LJxy/>|>>?>><yx~x> >>??|xx?<> >~~?>???x?>|q?>><??>>G>>><?>|>>??>` >>>>>>``0>><>>p|<>>|p>?>>>|`8|~>>|x8xx>>|Oxp<xx|>>|??`gxx<>?>>|<=8?>|}>?>>|y?~<>xx>???|{<>||xx>sϿ>|x<>>||<|xx>߱>|?|<|xx<<<78>g>>|<<||x<<<>>||<|xx<<<>>|sχ|<>|||xx|<<?>>||<>|?|x|y<<~xÀ>>?||?<<|Ǹ<>~??||~~?<<>>`x|>?~~?<<>>03 ?|x<>> 0~x<|>>p<<>>>xp>>>>>>>>x>>>?|>>x>?8 >>xÀ`<>>x80 ||>>~3Àg`00<>???~?x <>~|x?~?x?>||xϟ9}><|||x|x}<>x>xxx<>9?|y>y?>||xǿ>?x{|>|||xx?|x}<>xxx<ǁx<|o>S>|xxLJ<<xx??|>>|||xx>>|x|<>xxx<>'?x}<|>>~ǟx>?xxy><>??_|xy><>|<|xx<>ǿyx>???|~>|~|ρǿ<ώ>????><|>>00}?{<||>?||?!8>p~|?>`>|< |><>~< >?|<>|>|~?~>|>|?~><? >~>>>>xx |><xx>?|<p>?0p>??`>>?>ǀ?>?>?>??>?>>>px>x|>>x>>>8>?>?<p<p8>?8x3<8p?x??``< xx>`??>?>>|??>߁><x|>><ߟ<?~||y>>><?<Ǐ>xxxy><|?LJxx|xx>|~?ǟxxxx><||<xLJx3|>xxx?>||>|Ǟxx>xxxϞ>><|x?> |LJx|x>><|x>?>LJx?>?|?LJxx|q~?>|?Ǐz>?<~???~><<?~?< <x@?>ǀ8 ~0??{y||~~<>||?>??>p>x>?>>| >><x<~|>?<?8><8><~<<`8|8>>>| x >xx~>~Ǐ??<<>~0<|??|||xy;|>~Ϗ?>||Y||w<><<<<|>x|x>s?||<χ||<><<<<<|xgx>|?||?<?||><<<|x<?||?x|><<<><|x>x|?~<||<<>x<<|x<?|||9gx~>><<|<<|xx>x><=πq|?>><<|?|<<<??{|?<?p|~??||ǃ?`|?~??~~??<~~珀> |~?8????{||>>>|<<>> @p?x80>~|x8?>`p|xx|~?pp8xxa`0x<{~||`??x8<|>x?πx{<>|~xw|||x?qǟx?<||x~ϟ?|ϟ0x9><||x|w?ǃyǏ><||x|?LJyLJ~?<>|||xxǁy@ǁ<>|||x|yLJ??||||σy`Ǐ8?||<~9`yǏ8?~8<~?> cpa_sample_code_dc_dp.c000066400000000000000000003452251503624047500363550ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_dc_dp.c * * * @ingroup sampleCompressionDpPerf * * @description * This is a sample code that uses Data Plane - Data Compression(DC) APIs. * This code preallocates a number of buffers as based on the size of each * file defined in the calgary/canterbury corpus. The preallocated buffers * are then populated with the corpus files as defined in * setup->testBuffersize. * Time stamping is started prior to the first performed DC * Operation and is stopped when all callbacks have returned. * *****************************************************************************/ #include "cpa_sample_code_utils_common.h" #include "cpa_sample_code_dc_utils.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_dc_dp.h" #include "cpa_sample_code_framework.h" #include "icp_sal_user.h" #include "icp_sal_poll.h" #include "busy_loop.h" #include "qat_perf_cycles.h" #include "qat_perf_buffer_utils.h" extern int latency_single_buffer_mode; /* set to 1 for single buffer processing */ extern char *cpaStatusToString(CpaStatus status); /* for more readable debug */ /* Backoff timer implementation variables*/ extern volatile CpaBoolean backoff_timer_g; extern volatile CpaBoolean backoff_dynamic_g; extern Cpa32U backoff_static_timer_g; static inline void printThreadDetails(single_thread_test_data_t *testSetup) __attribute__((unused)); CpaStatus setDcPollingInterval(Cpa64U pollingInterval); CpaStatus printDcPollingInterval(void); void dcDpPerformance(single_thread_test_data_t *testSetup); #define NUM_BUFS(setup) \ (setup->isUseSGL ? setup->numberOfSGLs[i] : setup->numberOfBuffers[i]) #define ZERO_PAD_ALIGNMENT (4 * 1024) #define ZERO_PAD_MS_BYTE \ ((DC_API_VERSION_AT_LEAST(3, 2) && IS_ZEROPAD_TEST()) ? 0xFF : 0x00) /***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Set the polling interval. The Polling interval is the number of successful * submissions before the driver is polled for responses * ***************************************************************************/ CpaStatus setDcPollingInterval(Cpa64U pollingInterval) { dcPollingInterval_g = pollingInterval; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setDcPollingInterval); /***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Print the polling interval. The Polling interval is the number * of successful submissions before the driver is polled for responses * ***************************************************************************/ CpaStatus printDcPollingInterval(void) { PRINT("Compression Polling Interval: %u\n", dcPollingInterval_g); return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(printDcPollingInterval); /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Callback function after a call to the DC API ******************************************************************************/ static void dcDpCallbackFunction(CpaDcDpOpData *pOpData) { CpaDcRqResults *pResults = &(pOpData->results); perf_data_t *pPerfData = (perf_data_t *)pOpData->pCallbackTag; if (CPA_STATUS_SUCCESS != pOpData->responseStatus) { PRINT_ERR( "%s Failed, status = %d, dcResult = %d, responseCount %llu \n", __func__, pOpData->responseStatus, pOpData->results.status, (long long int)pPerfData->responses); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } /* increment responses */ pPerfData->responses++; if (latency_enable) { /* Did the latency function setup the array pointer? */ if (NULL == pPerfData->response_times) { if (latency_debug) PRINT("%s: Callback for non-latency code\n", __FUNCTION__); } else { /* Have we sampled too many buffer operations? */ if (pPerfData->latencyCount > MAX_LATENCY_COUNT) { PRINT_ERR("pPerfData latencyCount > MAX_LATENCY_COUNT\n"); return; } /* Is this the buffer we calculate latency on? * And have we calculated too many for array? */ if (pPerfData->responses == pPerfData->nextCount) { int i = pPerfData->latencyCount; /* Now get the end timestamp - before any print outs */ pPerfData->response_times[i] = sampleCodeTimestamp(); pPerfData->nextCount += pPerfData->countIncrement; if (latency_debug) PRINT("%s: responses=%u, latencyCount=%d, end[i]:%llu, " "start[i]:%llu, nextCount=%u\n", __FUNCTION__, (unsigned int)pPerfData->responses, i, pPerfData->response_times[i], pPerfData->start_times[i], pPerfData->nextCount); pPerfData->latencyCount++; } } } if (CPA_DC_WDOG_TIMER_ERR == (Cpa8S)pResults->status) { PRINT_ERR("Slice hang is detected\n"); /* fw does not respond to any further requests in case of slice hang * so, exit the test */ pPerfData->numOperations = pPerfData->responses; pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } /*if we have received the pre-set numOperations, then get the clock cycle * as a timestamp and post the Semaphore to release parent thread*/ if (pPerfData->numOperations == pPerfData->responses) { pPerfData->endCyclesTimestamp = sampleCodeTimestamp(); } } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Allocate memory for PhysFlatBuffers ******************************************************************************/ static CpaStatus createBuffersDp(Cpa32U buffSize, Cpa32U numBuffs, CpaPhysFlatBuffer **pFlatBuffArray, Cpa32U nodeId, const Cpa8U msByte) { Cpa32U i = 0; for (i = 0; i < numBuffs; i++) { pFlatBuffArray[i] = qaeMemAllocNUMA( (sizeof(CpaPhysFlatBuffer)), nodeId, BYTE_ALIGNMENT_64); if (NULL == pFlatBuffArray[i]) { PRINT_ERR(" Unable to allocate flat buffer\n"); return CPA_STATUS_FAIL; } pFlatBuffArray[i]->dataLenInBytes = buffSize; /* At this point the bufferPhysAddr is not yet a physical address * We convert it to a physical address after we use it as a virtual * address */ pFlatBuffArray[i]->bufferPhysAddr = (CpaPhysicalAddr)( uintptr_t)qaeMemAllocNUMA(buffSize, nodeId, BYTE_ALIGNMENT_64); if (NULL == (void *)(uintptr_t)pFlatBuffArray[i]->bufferPhysAddr) { PRINT_ERR(" Unable to allocate flat buffer phys addr\n"); return CPA_STATUS_FAIL; } memset((SAMPLE_CODE_UINT *)(uintptr_t)pFlatBuffArray[i]->bufferPhysAddr, msByte, buffSize); } return CPA_STATUS_SUCCESS; } /** ****************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Allocate memory for OpData structures ******************************************************************************/ static CpaStatus createOpDataDp(Cpa32U numBuffs, CpaDcDpOpData **pOpDataArray, Cpa32U nodeId) { Cpa32U i = 0; for (i = 0; i < numBuffs; i++) { pOpDataArray[i] = qaeMemAllocNUMA(sizeof(CpaDcDpOpData), nodeId, BYTE_ALIGNMENT_8); if (NULL == pOpDataArray[i]) { PRINT_ERR(" Unable to allocate op data\n"); return CPA_STATUS_FAIL; } else { memset(pOpDataArray[i], 0, sizeof(CpaDcDpOpData)); } } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Free memory for SGLs ******************************************************************************/ static void freeSGLArray(CpaPhysBufferList ***sglArray, Cpa32U numberOfFiles, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; if (!sglArray) return; for (i = 0; i < numberOfFiles; i++) { if (!sglArray[i]) continue; for (j = 0; j < setup->numberOfSGLs[i]; j++) { if (!sglArray[i][j]) continue; qaeMemFreeNUMA((void **)&sglArray[i][j]); sglArray[i][j] = NULL; } qaeMemFree((void **)&sglArray[i]); sglArray[i] = NULL; } qaeMemFree((void **)&sglArray); } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Free memory for SGL Operational data ******************************************************************************/ static void freeSGLsOpData(CpaDcDpOpData ***sglsOpData, Cpa32U numberOfFiles, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; if (!sglsOpData) return; for (i = 0; i < numberOfFiles; i++) { if (!sglsOpData[i]) continue; for (j = 0; j < setup->numberOfSGLs[i]; j++) { if (!sglsOpData[i][j]) continue; qaeMemFreeNUMA((void **)&sglsOpData[i][j]); sglsOpData[i][j] = NULL; } qaeMemFree((void **)&sglsOpData[i]); sglsOpData[i] = NULL; } qaeMemFree((void **)&sglsOpData); } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Free memory for PhysFlatBuffers ******************************************************************************/ static void freeBuffersDp(CpaPhysFlatBuffer ***pFlatBuffArray, Cpa32U numberOfFiles, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; if (NULL == pFlatBuffArray) { /* Return silently */ return; } for (i = 0; i < numberOfFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { if (NULL != pFlatBuffArray[i][j]) { if (NULL != (void *)(uintptr_t)pFlatBuffArray[i][j]->bufferPhysAddr) { qaeMemFreeNUMA( (void **)&pFlatBuffArray[i][j]->bufferPhysAddr); } qaeMemFreeNUMA((void **)&pFlatBuffArray[i][j]); } } if (NULL != pFlatBuffArray[i]) { qaeMemFreeNUMA((void **)&pFlatBuffArray[i]); } } qaeMemFreeNUMA((void **)&pFlatBuffArray); } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Print out details of the current thread ******************************************************************************/ static inline void printThreadDetails(single_thread_test_data_t *testSetup) { compression_test_params_t *tmpSetup = NULL; PRINT("Thread %u, LI %u, ", testSetup->threadID, testSetup->logicalQaInstance); tmpSetup = (compression_test_params_t *)(testSetup->setupPtr); if (tmpSetup->setupData.compType == CPA_DC_DEFLATE) { if (tmpSetup->setupData.huffType == CPA_DC_HT_STATIC) { PRINT("DeflateDP Static"); } else { PRINT("DeflateDP Dynamic"); } } if (tmpSetup->dcSessDir == CPA_DC_DIR_DECOMPRESS) { PRINT(" Decompress"); } else { PRINT(" Compress"); } #ifdef RELIABILITY_MODE PRINT(" in Reliability mode"); #endif PRINT("\n"); } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Free memory for the compression op data structs ******************************************************************************/ static void freeOpDataDp(CpaDcDpOpData ***compressionOpData, Cpa32U numberOfFiles, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; if (NULL == compressionOpData) { /* Return silently */ return; } for (i = 0; i < numberOfFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { if (CPA_TRUE == setup->setNsRequest) { if ((NULL != compressionOpData[i][j]) && (NULL != compressionOpData[i][j]->pSetupData)) { qaeMemFreeNUMA( (void **)&compressionOpData[i][j]->pSetupData); } } if (NULL != compressionOpData[i][j]) { qaeMemFreeNUMA((void **)&compressionOpData[i][j]); } } if (NULL != compressionOpData[i]) { qaeMemFreeNUMA((void **)&compressionOpData[i]); } } qaeMemFreeNUMA((void **)&compressionOpData); } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Compress the corpus before we do decompression ******************************************************************************/ static CpaStatus compressCorpusPreDecomp(compression_test_params_t *setup, CpaDcDpOpData ***compressionOpData, perf_data_t *perfData) { /* Local Variable Declaration */ Cpa32U i = 0, j = 0, k = 0; Cpa32U submittedOps = 0; Cpa32U numFiles = getNumFilesInCorpus(setup->corpus); /* Status variable */ CpaStatus status = CPA_STATUS_FAIL; CpaInstanceInfo2 info2 = { 0 }; status = cpaDcInstanceGetInfo2(setup->dcInstanceHandle, &info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInstanceGetInfo2 API failed. (status = %d)\n", status); return status; } for (i = 0; i < numFiles; i++) { /* call the compress api */ for (j = 0; j < NUM_BUFS(setup); j++) { do { status = cpaDcDpEnqueueOp(compressionOpData[i][j], CPA_TRUE); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; if (info2.isPolled == CPA_TRUE) { icp_sal_DcPollDpInstance(setup->dcInstanceHandle, 0); } AVOID_SOFTLOCKUP; } if (perfData->threadReturnStatus == CPA_STATUS_FAIL) { PRINT_ERR("%s An error was detected in the callback\n", __func__); for (k = 0; k < j; k++) { if (compressionOpData[i][k]->results.status != CPA_DC_OK) { PRINT("Response %d, dcResult status %d\n", (i * j) + k, compressionOpData[i][k]->results.status); } } status = CPA_STATUS_FAIL; break; } } while (CPA_STATUS_RETRY == status); /* Check Status */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Data Compression Failed %d\n\n", status); perfData->threadReturnStatus = CPA_STATUS_FAIL; break; } if (++submittedOps == OPERATIONS_POLLING_INTERVAL) { if (info2.isPolled == CPA_TRUE) { icp_sal_DcPollDpInstance(setup->dcInstanceHandle, 0); } } } /* End of number of buffers Loop */ } /* End of number of Files Loop*/ /* While there are pending requests, continue to poll */ status = dcDpPollNumOperations(setup->performanceStats, setup->dcInstanceHandle, setup->performanceStats->numOperations); return status; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Perform EnqueueBatchOp compression *****************************************************************************/ static CpaStatus performDcDpBatchOp(compression_test_params_t *setup, CpaDcDpOpData ***compressionOpData, perf_data_t *perfData, Cpa32U numOfOpsToBatch) { /* Local Variable Declaration */ Cpa32U i = 0, j = 0, k = 0, numLoops = 0; Cpa32U compressLoops = 0; Cpa32U remainingOps = 0; Cpa32U submittedOps = 0; Cpa32U totalBuffers = 0; /* Status variable */ CpaStatus status = CPA_STATUS_FAIL; Cpa32U staticAssign = 0, busyLoopCount = 0; Cpa32U busyLoopValue = setup->performanceStats->busyLoopValue; perf_cycles_t startBusyLoop = 0, endBusyLoop = 0, totalBusyLoopCycles = 0; CpaStatus pollStatus = CPA_STATUS_SUCCESS; Cpa32U numFiles = getNumFilesInCorpus(setup->corpus); CpaInstanceInfo2 *info2 = NULL; info2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (info2 == NULL) { PRINT_ERR("Failed to allocate memory for info2\n"); return CPA_STATUS_FAIL; } /* Initialize the structure */ memset(info2, 0, sizeof(CpaInstanceInfo2)); status = cpaDcInstanceGetInfo2(setup->dcInstanceHandle, info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInstanceGetInfo2 API failed. (status = %d)\n", status); qaeMemFree((void **)&info2); return status; } /* Zero performance stats */ memset(perfData, 0, sizeof(perf_data_t)); for (i = 0; i < numFiles; i++) { totalBuffers += NUM_BUFS(setup); } setup->performanceStats->numOperations = (Cpa64U)totalBuffers * (Cpa64U)setup->numLoops; compressLoops = setup->numLoops; perfData->numLoops = setup->numLoops; /* this Barrier will waits until all the threads get to this point */ sampleCodeBarrier(); coo_init(perfData, perfData->numOperations); /* generate the start time stamp */ perfData->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < compressLoops; numLoops++) { for (i = 0; i < numFiles; i++) { /* call the compress api */ for (j = 0; j < NUM_BUFS(setup); j = j + numOfOpsToBatch) { do { /* Is the next batch size greater than the amount of * buffers that we have left */ if (j + numOfOpsToBatch > NUM_BUFS(setup)) { remainingOps = NUM_BUFS(setup) - j; } else { remainingOps = numOfOpsToBatch; } coo_req_start(perfData); status = cpaDcDpEnqueueOpBatch( remainingOps, &compressionOpData[i][j], CPA_TRUE); coo_req_stop(perfData, status); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; if (info2->isPolled == CPA_TRUE) { icp_sal_DcPollDpInstance(setup->dcInstanceHandle, 0); } AVOID_SOFTLOCKUP; } if (perfData->threadReturnStatus == CPA_STATUS_FAIL) { PRINT_ERR("%s An error was detected in the callback\n", __func__); for (k = 0; k < j; k++) { if (compressionOpData[i][k]->results.status != CPA_DC_OK) { PRINT("Response %d, dcResult status %d\n", (i * j) + k, compressionOpData[i][k]->results.status); } } status = CPA_STATUS_FAIL; break; } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { startBusyLoop = busyLoopTimeStamp(); busyLoop(busyLoopValue, &staticAssign); busyLoopCount++; endBusyLoop = busyLoopTimeStamp(); totalBusyLoopCycles = totalBusyLoopCycles + (endBusyLoop - startBusyLoop); } /* Check Status */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Data Compression Failed %d\n\n", status); perfData->threadReturnStatus = CPA_STATUS_FAIL; break; } if ((++submittedOps == OPERATIONS_POLLING_INTERVAL) && (CPA_TRUE == info2->isPolled)) { coo_poll_dp_dc( perfData, setup->dcInstanceHandle, &pollStatus); } } /* End of number of buffers Loop */ if (CPA_STATUS_SUCCESS != status) { break; } } /* End of number of Files Loop*/ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Data Compression Failed %d\n\n", status); perfData->threadReturnStatus = CPA_STATUS_FAIL; break; } } /* End of compression Loops */ if (CPA_STATUS_SUCCESS == status) { /* While there are pending requests, continue to poll */ status = dcDpPollNumOperations(setup->performanceStats, setup->dcInstanceHandle, setup->performanceStats->numOperations); } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { setup->performanceStats->totalBusyLoopCycles = totalBusyLoopCycles; setup->performanceStats->busyLoopCount = busyLoopCount; setup->performanceStats->busyLoopValue = busyLoopValue; } coo_average(perfData); coo_deinit(perfData); qaeMemFree((void **)&info2); return status; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Perform EnqueueOp compression ******************************************************************************/ static CpaStatus performDcDpEnqueueOp(compression_test_params_t *setup, CpaDcDpOpData ***compressionOpData, perf_data_t *perfData) { /* Local Variable Declaration */ Cpa32U i = 0, j = 0, k = 0, numLoops = 0; Cpa32U numOps = 0; Cpa32U compressLoops = 0; CpaBoolean performOpNowFlag = CPA_FALSE; /* Status variable */ CpaStatus status = CPA_STATUS_FAIL; Cpa64U numOps2 = 0; Cpa32U totalBuffers = 0; Cpa64U nextPoll = dcPollingInterval_g; Cpa32U retries = 0; /* Capture busy loop before memset of performanceStats */ Cpa32U busyLoopValue = setup->performanceStats->busyLoopValue; Cpa32U staticAssign = 0, busyLoopCount = 0; Cpa32U numBusyLoops = 0; perf_cycles_t startBusyLoop = 0, endBusyLoop = 0, enqueueBusyLoop = 0; CpaStatus pollStatus = CPA_STATUS_SUCCESS; /* backoff timer parameters initialization */ Cpa32U backoff = 0; /* Counts the number of buffers submitted for compression. Only * MAX_LATENCY_COUNT of these will be 'latency buffers' whose * times are measured */ Cpa32U submissions = 0; /* set when the latency buffer is sent to accelerator */ perf_cycles_t *request_submit_start = NULL; /* set in completion service routine dcPerformCallback() */ perf_cycles_t *request_respnse_time = NULL; const Cpa32U request_mem_sz = sizeof(perf_cycles_t) * MAX_LATENCY_COUNT; Cpa32U numFiles = getNumFilesInCorpus(setup->corpus); CpaInstanceInfo2 *info2 = NULL; info2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (info2 == NULL) { PRINT_ERR("Failed to allocate memory for info2\n"); return CPA_STATUS_FAIL; } /* Initialize the structure */ memset(info2, 0, sizeof(CpaInstanceInfo2)); status = cpaDcInstanceGetInfo2(setup->dcInstanceHandle, info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInstanceGetInfo2 API failed. (status = %d)\n", status); qaeMemFree((void **)&info2); return status; } /* Zero performance stats */ memset(perfData, 0, sizeof(perf_data_t)); for (i = 0; i < numFiles; i++) { totalBuffers += NUM_BUFS(setup); } setup->performanceStats->numOperations = (Cpa64U)totalBuffers * (Cpa64U)setup->numLoops; compressLoops = setup->numLoops; perfData->numLoops = setup->numLoops; coo_init(perfData, perfData->numOperations); if (latency_enable) { if (perfData->numOperations > LATENCY_SUBMISSION_LIMIT) { PRINT_ERR("Error max submissions for latency must be <= %d\n", LATENCY_SUBMISSION_LIMIT); return CPA_STATUS_FAIL; } request_submit_start = qaeMemAlloc(request_mem_sz); request_respnse_time = qaeMemAlloc(request_mem_sz); if (request_submit_start == NULL || request_respnse_time == NULL) { PRINT_ERR("Failed to allocate memory for submission and response " "times\n"); qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); return CPA_STATUS_FAIL; } memset(request_submit_start, 0, request_mem_sz); memset(request_respnse_time, 0, request_mem_sz); /* Calculate how many buffer submissions between latency measurements.. */ perfData->countIncrement = (setup->numberOfBuffers[0] * setup->numLoops) / MAX_LATENCY_COUNT; /* .. and set the next trigger count to this */ perfData->nextCount = perfData->countIncrement; /* How many latency measurements of the MAX_LATENCY_COUNT have been * taken so far */ perfData->latencyCount = 0; /* Completion routine sets end times in the array indirectly */ perfData->response_times = request_respnse_time; perfData->start_times = request_submit_start; /* for debug */ if (latency_debug) PRINT("LATENCY_CODE: Initial nextCount %u, countIncrement %u\n", perfData->nextCount, perfData->countIncrement); } /* this Barrier will waits until all the threads get to this point */ sampleCodeBarrier(); /* generate the start time stamp */ perfData->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < compressLoops; numLoops++) { for (i = 0; i < numFiles; i++) { /* Loop through all our buffers and call EnqueueOp, until we have * enqueued numRequests, and when we do, call performOpNow to clear * the ring and actually execute the operations */ for (j = 0; j < NUM_BUFS(setup); j++) { /* if we have reached the enqueue limit or we are about to * submit the last buffer of the current corpus file then * enqueue and perform the enqueued operations now. */ if (++numOps % setup->numRequests == 0 || j + 1 == NUM_BUFS(setup)) { performOpNowFlag = CPA_TRUE; } else { performOpNowFlag = CPA_FALSE; } do { if (latency_enable) { if (submissions + 1 == perfData->nextCount) { int i = perfData->latencyCount; /* When this buffer has been processed the * 'submissions' * count will be incremented and checked in the * dcPerformCallback() * routine. So we grab it's start time now. */ if (latency_debug) PRINT("%s: status=%s submissions=%u, " "nextCount=%u, latencyCount=%d\n", __FUNCTION__, cpaStatusToString(status), submissions, perfData->nextCount, i); /* Must do this after any print outs */ /* NOTE: Will be overwritten if CPA_STATUS_RETRY */ request_submit_start[perfData->latencyCount] = sampleCodeTimestamp(); } } coo_req_start(perfData); status = cpaDcDpEnqueueOp(compressionOpData[i][j], performOpNowFlag); coo_req_stop(perfData, status); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; if (CPA_TRUE == info2->isPolled) { coo_poll_dp_dc( perfData, setup->dcInstanceHandle, &pollStatus); } nextPoll = numOps2 + dcPollingInterval_g; AVOID_SOFTLOCKUP; } if (perfData->threadReturnStatus == CPA_STATUS_FAIL) { PRINT_ERR("%s An error was detected in the callback\n", __func__); for (k = 0; k < j; k++) { if (compressionOpData[i][k]->results.status != CPA_DC_OK) { PRINT("Response %d, dcResult status %d\n", (i * j) + k, compressionOpData[i][k]->results.status); } } status = CPA_STATUS_FAIL; break; } if (CPA_STATUS_RETRY == status) { if (backoff_timer_g && backoff_dynamic_g) { /* * Backoff a bit if submission was unsuccessful */ for (k = 1; k <= backoff; k++) { /* * do nothing */ __asm__ volatile("nop"); } /* * increase the backoff interval after the * unsuccessful submission. * if the backoff is too big, set it 0 (this is done * for the large packets as they keep device busy * and backoff could became unnecessary long) */ if (backoff < DP_BACKOFF_TIMER_MAX) { backoff += DP_BACKOFF_STEP_FORWARD; } else { backoff = 0; } } else { /* if requested just to wait certain number of busy * loop cycles (static timer) */ if (backoff_timer_g) { for (k = 1; k <= backoff_static_timer_g; k++) { /* * do nothing */ __asm__ volatile("nop"); } } } } else { if (backoff_timer_g && backoff_dynamic_g) { /* decrease the backoff value after the successful * submission */ if (backoff > DP_BACKOFF_STEP_BACK) { backoff -= DP_BACKOFF_STEP_BACK; } } } } while (CPA_STATUS_RETRY == status); if (latency_enable) { /* Another buffer has been submitted to the accelerator */ submissions++; /* Have we been requested to process one buffer at a time. * This * will result in no retries and so the best latency times. */ if (latency_single_buffer_mode != 0) { /* Must now wait until this buffer is processed by the * CPM */ while (perfData->responses != submissions) { /* Keep polling until compression of the buffer * completes * and dcPerformCallback() increments * perfData->responses */ if (info2->isPolled == CPA_TRUE) { icp_sal_DcPollDpInstance( setup->dcInstanceHandle, 0); } } } } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g && performOpNowFlag) { if (busyLoopValue > 0) { startBusyLoop = busyLoopTimeStamp(); busyLoop(busyLoopValue, &staticAssign); endBusyLoop = busyLoopTimeStamp(); enqueueBusyLoop += endBusyLoop - startBusyLoop; startBusyLoop = 0; endBusyLoop = 0; } busyLoopCount++; } ++numOps2; if ((numOps2 == nextPoll) || (numOps % OPERATIONS_POLLING_INTERVAL == 0)) { if (CPA_TRUE == info2->isPolled) { coo_poll_dp_dc( perfData, setup->dcInstanceHandle, &pollStatus); } if (CPA_STATUS_FAIL == pollStatus) { status = CPA_STATUS_FAIL; PRINT_ERR("icp_sal_DcPollDpInstance Failed %d\n\n", status); } if (numOps2 == nextPoll) { nextPoll = numOps2 + dcPollingInterval_g; } } /* Check Status */ if (CPA_STATUS_SUCCESS != status) { break; } } /* End of number of buffers Loop */ if (CPA_STATUS_UNSUPPORTED == status) { PRINT("Data Compression unsupported %d\n\n", status); perfData->threadReturnStatus = CPA_STATUS_UNSUPPORTED; numCreatedThreads_g --; status = CPA_STATUS_UNSUPPORTED; break; } else if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Data Compression Failed %d\n\n", status); perfData->threadReturnStatus = CPA_STATUS_FAIL; status = CPA_STATUS_FAIL; return status; } } /* End of number of Files Loop*/ if (CPA_STATUS_SUCCESS != status) { break; } } /* End of compression Loops */ if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { if (busyLoopValue > 0 && busyLoopCount > 0) { busyLoopTimeStamp(); startBusyLoop = busyLoopTimeStamp(); for (numBusyLoops = 0; numBusyLoops < busyLoopCount; numBusyLoops++) { busyLoop(busyLoopValue, &staticAssign); } endBusyLoop = busyLoopTimeStamp(); } } /* While there are pending requests, continue to poll */ if (CPA_STATUS_SUCCESS != dcDpPollNumOperationsRetries(setup->performanceStats, setup->dcInstanceHandle, setup->performanceStats->numOperations, &retries)) { PRINT_ERR("dcDpPollNumOperationsRetries Failed \n"); status = CPA_STATUS_FAIL; } setup->performanceStats->pollRetries += retries; if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { setup->performanceStats->busyLoopValue = busyLoopValue; setup->performanceStats->busyLoopCount = busyLoopCount; setup->performanceStats->totalBusyLoopCycles = enqueueBusyLoop; /* Since all responses could have already been processed before calling * dcDpPollNumOperationsRetries, we need to ensure we only count the * latest busy loop in case it was actually needed */ if (setup->performanceStats->endCyclesTimestamp > endBusyLoop) { setup->performanceStats->totalBusyLoopCycles += endBusyLoop - startBusyLoop; } setup->performanceStats->offloadCycles = (setup->performanceStats->endCyclesTimestamp - setup->performanceStats->startCyclesTimestamp) - setup->performanceStats->totalBusyLoopCycles; do_div(setup->performanceStats->offloadCycles, setup->performanceStats->responses); } if (latency_enable) { if (latency_debug) PRINT("%s: Calculating min, max and ave latencies...\n", __FUNCTION__); perfData->minLatency = MAX_LATENCY_LIMIT; /* Will be less than this */ perfData->maxLatency = 0; /* Will be more than this */ /* Let's accumulate in 'aveLatency' all the individual 'latency' * times. Typically, there should be MAX_LATENCY_COUNT of these. * We also calculate min/max so we can get a sense of the variance. */ for (i = 0; i < perfData->latencyCount; i++) { perf_cycles_t latency = perfData->response_times[i] - request_submit_start[i]; perfData->aveLatency += latency; if (latency < perfData->minLatency) perfData->minLatency = latency; if (latency > perfData->maxLatency) perfData->maxLatency = latency; if (latency_debug) PRINT("%d, end[i]:%llu, start[i]:%llu, min:%llu, ave:%llu, " "max:%llu\n", i, perfData->response_times[i], request_submit_start[i], perfData->minLatency, perfData->aveLatency, perfData->maxLatency); } if (perfData->latencyCount > 0) { /* Then scale down this accumulated value to get the average. * This will be reported by dcPrintStats() at the end of the test */ do_div(perfData->aveLatency, perfData->latencyCount); } qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); } coo_average(perfData); coo_deinit(perfData); qaeMemFree((void **)&info2); return status; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Main executing function which selects the operation type to be performed( * Enqueue/Batch) and the direction of the operation(compress/decompress) ******************************************************************************/ static CpaStatus PerformOp(compression_test_params_t *setup, CpaDcDpOpData ***compressionOpData, CpaDcDpOpData ***decompressionOpData, perf_data_t *perfData) { CpaStatus status = CPA_STATUS_FAIL; switch (setup->dpTestType) { case DC_DP_ENQUEUEING: if (CPA_DC_DIR_COMPRESS == setup->dcSessDir) { status = performDcDpEnqueueOp(setup, compressionOpData, perfData); if ((latency_enable) && (latency_debug)) { PRINT("%s: performDcDpEnqueueOp() returns=%d\n", __FUNCTION__, (int)status); } } else { status = performDcDpEnqueueOp(setup, decompressionOpData, perfData); } break; case DC_DP_BATCHING: if (CPA_DC_DIR_COMPRESS == setup->dcSessDir) { status = performDcDpBatchOp( setup, compressionOpData, perfData, setup->numRequests); } else { status = performDcDpBatchOp( setup, decompressionOpData, perfData, setup->numRequests); } break; default: PRINT_ERR("Neither enqueueing or batching mode\n"); return CPA_STATUS_FAIL; } return status; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Used for profiling IA offload cost. * * Phase One:Iterates over the main perform function, increasing the number * of busy loop cycles(BUSY_LOOP_INCREMENT) on each iteration until no retries * occur. * * Phase Two: Continues to iterate over the main perform function, increasing * the number of busy loop cycles on each iteration until performance is * affected then steps back to the last increment value, i.e. the last * increment step(BUSY_LOOP_INCREMENT) before performance was affected. *****************************************************************************/ static CpaStatus performOffloadCalculation(compression_test_params_t *setup, CpaDcDpOpData ***compressionOpData, CpaDcDpOpData ***decompressionOpData, perf_data_t *perfData) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32S baseThroughput = 0, currentThroughput = 0; Cpa32U packetSize = 0, lowerBound = 0, upperBound = 0; perf_data_t *pPerfData = setup->performanceStats; pPerfData->busyLoopValue = 1; packetSize = setup->bufferSize; baseThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* Find the lower bound(retries) and upper bound(no retries) for subsequent * binary search. */ while (CPA_STATUS_SUCCESS == status && pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue; pPerfData->busyLoopValue = pPerfData->busyLoopValue << 1; /* PERFORM OP */ status = PerformOp(setup, compressionOpData, decompressionOpData, perfData); } upperBound = pPerfData->busyLoopValue; /* Binary Search for no retries and maintaining throughput */ do { pPerfData->busyLoopValue = (upperBound + lowerBound) / 2; /* PERFORM OP */ status = PerformOp(setup, compressionOpData, decompressionOpData, perfData); currentThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* If no retries and we're within ERROR_MARGIN (0.1%) of base throughput */ if (pPerfData->retries == 0 && (withinMargin(baseThroughput, currentThroughput, ERROR_MARGIN) == 1)) { break; } /* If we see retries */ else if (pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue + 1; } /* Else retries are zero, but throughput has been affected. */ else { upperBound = pPerfData->busyLoopValue - 1; } } while (CPA_STATUS_SUCCESS == status && pPerfData->retries != 0); return status; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Helper function which builds performance setup for SGL scenario. Existing * flat buffer lists are divided to groups using global configurable variable * dcDpNumFlatsPerSGL_g. For each SGL proper OpData for compression, * decompression and comparison are created. * ******************************************************************************/ static CpaStatus buildSGLsSetupFromFlats( compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, Cpa32U nodeId, Cpa32U numFiles, perf_data_t *perfData, CpaPhysFlatBuffer ***srcFlatBuffArray, CpaPhysFlatBuffer ***dstFlatBuffArray, CpaPhysFlatBuffer ***cmpFlatBuffArray, /* In-outs */ CpaDcDpOpData ****compSGLOpDataTblOut, CpaDcDpOpData ****decompSGLOpDataTblOut, /* In-outs - just for cleanup */ CpaPhysBufferList ****compSGLArrayOut, CpaPhysBufferList ****decompSGLArrayOut) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U fileCtr; CpaDcDpOpData ***compOpDataArray = NULL; CpaDcDpOpData ***decompOpDataTbl = NULL; CpaPhysBufferList ***compSGLArray = NULL; CpaPhysBufferList ***decompSGLArray = NULL; Cpa32U totalSGLs = 0; /* Operational data table for each file */ compOpDataArray = (CpaDcDpOpData ***)qaeMemAlloc(numFiles * sizeof(CpaDcDpOpData *)); memset(compOpDataArray, 0x00, numFiles * sizeof(CpaDcDpOpData *)); /* Store SGLs for i.a. cleanup purpose */ compSGLArray = (CpaPhysBufferList ***)qaeMemAlloc( numFiles * sizeof(CpaPhysBufferList *)); memset(compSGLArray, 0x00, numFiles * sizeof(CpaDcDpOpData *)); decompSGLArray = (CpaPhysBufferList ***)qaeMemAlloc( numFiles * sizeof(CpaPhysBufferList *)); memset(decompSGLArray, 0x00, numFiles * sizeof(CpaDcDpOpData *)); /* Set required SGLs number - such like numberOfBuffers */ setup->numberOfSGLs = (Cpa32U *)qaeMemAlloc(numFiles * sizeof(Cpa32U)); for (fileCtr = 0; fileCtr < numFiles; fileCtr++) { CpaDcDpOpData **opDataSubArray = NULL; Cpa32U sglsCtr, sglsNum; Cpa32U flatsCtr, flatsNum; /* Number of flats per file */ flatsNum = setup->numberOfBuffers[fileCtr]; /* Round down - to use only fully populated SGLs */ sglsNum = flatsNum / setup->numFlatsPerSGL; setup->numberOfSGLs[fileCtr] = sglsNum; /* Create OP data for particular SGL*/ opDataSubArray = (CpaDcDpOpData **)qaeMemAlloc(sglsNum * sizeof(CpaDcDpOpData *)); memset(opDataSubArray, 0x00, sglsNum * sizeof(CpaDcDpOpData *)); compOpDataArray[fileCtr] = opDataSubArray; /* Create subset of SGL for SGLs table */ compSGLArray[fileCtr] = qaeMemAlloc(sglsNum * sizeof(CpaPhysBufferList *)); decompSGLArray[fileCtr] = qaeMemAlloc(sglsNum * sizeof(CpaPhysBufferList *)); for (sglsCtr = 0, flatsCtr = 0; sglsCtr < sglsNum; sglsCtr++, totalSGLs++) { CpaPhysBufferList *srcSGL = NULL; CpaPhysBufferList *dstSGL = NULL; Cpa32U bytesToCompress = 0; Cpa32U bytesInDstBuffer = 0; CpaDcDpOpData *pOpData = NULL; Cpa32U i; /* Create opData for each request */ pOpData = (CpaDcDpOpData *)qaeMemAllocNUMA( sizeof(CpaDcDpOpData), nodeId, BYTE_ALIGNMENT_64); memset(pOpData, 0x00, sizeof(CpaDcDpOpData)); /* Store newly created OP data in op data table */ opDataSubArray[sglsCtr] = pOpData; /* Create source and destination SGL */ srcSGL = qaeMemAllocNUMA( (sizeof(CpaPhysBufferList) + (setup->numFlatsPerSGL * sizeof(CpaPhysFlatBuffer))), nodeId, BYTE_ALIGNMENT_64); srcSGL->numBuffers = setup->numFlatsPerSGL; dstSGL = qaeMemAllocNUMA( (sizeof(CpaPhysBufferList) + (setup->numFlatsPerSGL * sizeof(CpaPhysFlatBuffer))), nodeId, BYTE_ALIGNMENT_64); dstSGL->numBuffers = setup->numFlatsPerSGL; /* Store SGL in table for i.a. cleanup purpose */ compSGLArray[fileCtr][sglsCtr] = srcSGL; decompSGLArray[fileCtr][sglsCtr] = dstSGL; /* Fill up SGL using already set flat buffers */ for (i = 0; i < setup->numFlatsPerSGL && flatsCtr < flatsNum; flatsCtr++, i++) { /* Source SGL */ srcSGL->flatBuffers[i].bufferPhysAddr = (CpaPhysicalAddr)virtAddrToDevAddr( (void *)(uintptr_t)srcFlatBuffArray[fileCtr][flatsCtr] ->bufferPhysAddr, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); srcSGL->flatBuffers[i].dataLenInBytes = srcFlatBuffArray[fileCtr][flatsCtr]->dataLenInBytes; bytesToCompress += srcSGL->flatBuffers[i].dataLenInBytes; /* Destination SGL */ dstSGL->flatBuffers[i].bufferPhysAddr = (CpaPhysicalAddr)virtAddrToDevAddr( (void *)(uintptr_t)dstFlatBuffArray[fileCtr][flatsCtr] ->bufferPhysAddr, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); dstSGL->flatBuffers[i].dataLenInBytes = dstFlatBuffArray[fileCtr][flatsCtr]->dataLenInBytes; bytesInDstBuffer += dstSGL->flatBuffers[i].dataLenInBytes; } /* DC_COMP_FLATS_PER_SGL */ pOpData->srcBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( srcSGL, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); pOpData->destBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( dstSGL, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); /* Buffer lengths */ pOpData->bufferLenToCompress = bytesToCompress; pOpData->bufferLenForData = bytesInDstBuffer; pOpData->srcBufferLen = CPA_DP_BUFLIST; pOpData->destBufferLen = CPA_DP_BUFLIST; /* This physical */ pOpData->thisPhys = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)virtAddrToDevAddr( pOpData, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); /* CnVnR settings, make it in-line with "FLAT" code */ pOpData->compressAndVerify = CPA_TRUE; pOpData->compressAndVerifyAndRecover = CPA_TRUE; /* Basic settings */ pOpData->dcInstance = setup->dcInstanceHandle; pOpData->pSessionHandle = pSessionHandle; pOpData->pCallbackTag = perfData; pOpData->sessDirection = CPA_DC_DIR_COMPRESS; } /* SGL per file enumeration */ } /* Files enumeration */ *compSGLArrayOut = compSGLArray; *decompSGLArrayOut = decompSGLArray; *compSGLOpDataTblOut = compOpDataArray; /* ready to go */ if (CPA_DC_DIR_COMPRESS == setup->dcSessDir) { perfData->numOperations = (Cpa64U)totalSGLs * setup->numFlatsPerSGL * (Cpa64U)setup->numLoops; perfData->responses = 0; goto exit; } /* * De-compression case */ /* Compress whole set of OpData to swap to buffers */ perfData->numOperations = totalSGLs; status = compressCorpusPreDecomp(setup, compOpDataArray, perfData); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not compress corpus before Decompression = %d \n", status); status = CPA_STATUS_FAIL; goto cleanup; } /* Create decompression OpData table for each file */ decompOpDataTbl = (CpaDcDpOpData ***)qaeMemAlloc(numFiles * sizeof(CpaDcDpOpData *)); memset(decompOpDataTbl, 0x00, numFiles * sizeof(CpaDcDpOpData *)); /* Create test comparison OpData table for each file */ for (fileCtr = 0; fileCtr < numFiles; fileCtr++) { CpaDcDpOpData **opDataSubArray = NULL; Cpa32U sglsCtr, sglsNum; sglsNum = setup->numberOfSGLs[fileCtr]; opDataSubArray = (CpaDcDpOpData **)qaeMemAlloc(sglsNum * sizeof(CpaDcDpOpData *)); memset(opDataSubArray, 0x00, sglsNum * sizeof(CpaDcDpOpData *)); decompOpDataTbl[fileCtr] = opDataSubArray; for (sglsCtr = 0; sglsCtr < setup->numberOfSGLs[fileCtr]; sglsCtr++) { CpaDcDpOpData *pCompOpData = NULL; CpaDcDpOpData *pOpData = NULL; CpaPhysBufferList *compSGL = NULL; Cpa32U i; pCompOpData = compOpDataArray[fileCtr][sglsCtr]; /* Create opData for each request */ pOpData = (CpaDcDpOpData *)qaeMemAllocNUMA( sizeof(CpaDcDpOpData), nodeId, BYTE_ALIGNMENT_64); memset(pOpData, 0x00, sizeof(CpaDcDpOpData)); opDataSubArray[sglsCtr] = pOpData; /* Set cmpBuffers in destination SGL */ compSGL = compSGLArray[fileCtr][sglsCtr]; for (i = 0; i < setup->numFlatsPerSGL; i++) { CpaPhysFlatBuffer *cmpFlat = cmpFlatBuffArray[fileCtr] [sglsCtr * setup->numFlatsPerSGL + i]; compSGL->flatBuffers[i].bufferPhysAddr = (CpaPhysicalAddr)virtAddrToDevAddr( (void *)(uintptr_t)cmpFlat->bufferPhysAddr, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); } /* Flip buffers */ pOpData->destBuffer = pCompOpData->srcBuffer; pOpData->destBufferLen = pCompOpData->srcBufferLen; /* Place physical pointer to destination SGL */ pOpData->srcBuffer = pCompOpData->destBuffer; pOpData->srcBufferLen = pCompOpData->destBufferLen; pOpData->bufferLenToCompress = pCompOpData->results.produced; pOpData->bufferLenForData = pCompOpData->results.consumed; pOpData->sessDirection = CPA_DC_DIR_COMPRESS; /* This physical */ pOpData->thisPhys = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)virtAddrToDevAddr( pOpData, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); /* CnVnR settings, make it in-line with "FLAT" code */ pOpData->compressAndVerify = CPA_TRUE; pOpData->compressAndVerifyAndRecover = CPA_TRUE; /* Basic settings */ pOpData->dcInstance = setup->dcInstanceHandle; pOpData->pSessionHandle = pSessionHandle; pOpData->pCallbackTag = perfData; pOpData->sessDirection = CPA_DC_DIR_DECOMPRESS; } } perfData->numOperations = (Cpa64U)totalSGLs * setup->numFlatsPerSGL * (Cpa64U)setup->numLoops; perfData->responses = 0; *decompSGLOpDataTblOut = decompOpDataTbl; exit: return status; cleanup: freeSGLsOpData(compOpDataArray, numFiles, setup); freeSGLsOpData(decompOpDataTbl, numFiles, setup); freeSGLArray(compSGLArray, numFiles, setup); freeSGLArray(decompSGLArray, numFiles, setup); return status; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Main executing function which allocates/frees memory which is required, * and performs Enqueue/Batch operations as required ******************************************************************************/ static CpaStatus dcDpPerformSGL(compression_test_params_t *setup) { /* Looping control variables */ Cpa32U i = 0, j = 0; /* Status variable */ CpaStatus status = CPA_STATUS_SUCCESS; /* NUMA node ID */ Cpa32U nodeId = 0; /* File data pointer */ Cpa8U *fileDataPtr = NULL; /* Performance data Structure */ perf_data_t *perfData = NULL; /* Buffer size */ Cpa32U bufferSize = 0; /* Dest Buffer size */ Cpa32U destBufferSize = 0; /* Session size */ Cpa32U sessionSize = 0; /* Session handle */ CpaDcSessionHandle *pSessionHandle = NULL; CpaBoolean sessionInitialized = CPA_FALSE; /* Buffer counters */ Cpa32U amountOfFullBuffers = 0; /* SGL opData */ CpaDcDpOpData ***compressionOpDataSGL = NULL; CpaDcDpOpData ***decompressionOpDataSGL = NULL; /* Declare src, dst & comp buffers */ CpaPhysFlatBuffer ***srcFlatBuffArray = NULL; CpaPhysFlatBuffer ***dstFlatBuffArray = NULL; CpaPhysFlatBuffer ***cmpFlatBuffArray = NULL; /* Declare src, dst SGLs */ CpaPhysBufferList ***compSGLArray = NULL; CpaPhysBufferList ***decompSGLArray = NULL; Cpa32U numFiles = 0; const corpus_file_t *fileArray = NULL; if (NULL == setup) { PRINT_ERR("Test Setup Pointer is NULL\n"); return CPA_STATUS_FAIL; } numFiles = getNumFilesInCorpus(setup->corpus); fileArray = getFilesInCorpus(setup->corpus); perfData = setup->performanceStats; bufferSize = setup->bufferSize; /* Check what NUMA node we are on in order to allocate memory */ status = sampleCodeDcGetNode(setup->dcInstanceHandle, &nodeId); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to get Node ID\n"); goto exit; } srcFlatBuffArray = qaeMemAllocNUMA( (numFiles * sizeof(CpaPhysFlatBuffer *)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == srcFlatBuffArray) { status = CPA_STATUS_FAIL; goto exit; } dstFlatBuffArray = qaeMemAllocNUMA( (numFiles * sizeof(CpaPhysFlatBuffer *)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == dstFlatBuffArray) { PRINT_ERR("unable to allocate dstFlatBuffArray \n"); status = CPA_STATUS_FAIL; goto exit; } cmpFlatBuffArray = qaeMemAllocNUMA( (numFiles * sizeof(CpaPhysFlatBuffer *)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == cmpFlatBuffArray) { PRINT_ERR("unable to allocate cmpFlatBuffArray \n"); status = CPA_STATUS_FAIL; goto exit; } /* populate the flat buffer array with number of buffers required * for each file and allocate the memory */ for (i = 0; i < numFiles; i++) { /* allocate the memory for src, destination and compare buffers * for each file */ srcFlatBuffArray[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaPhysFlatBuffer *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == srcFlatBuffArray[i]) { PRINT_ERR("Unable to allocate Memory for srcFlatBuffArray\n "); status = CPA_STATUS_FAIL; goto exit; } dstFlatBuffArray[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaPhysFlatBuffer *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == dstFlatBuffArray[i]) { PRINT_ERR("Unable to allocate Memory for dstFlatBuffArray\n "); status = CPA_STATUS_FAIL; goto exit; } cmpFlatBuffArray[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaPhysFlatBuffer *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == cmpFlatBuffArray[i]) { PRINT_ERR("Unable to allocate Memory for cmpFlatBuffArray\n "); status = CPA_STATUS_FAIL; goto exit; } } /* For compression,the destination buffer size is obtained using * Compress Bound API. * NOTE: For SGL we need to estimate destination buffer for bunch of * buffers composed in single SGL. */ status = qatGetCompressBoundDestinationBufferSize( setup, bufferSize * setup->numFlatsPerSGL, &destBufferSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to get the destination buffer size using Compress " "Bound API\n"); goto exit; } /* Allocate flat buffers for each file */ for (i = 0; i < numFiles; i++) { status = createBuffersDp(bufferSize, setup->numberOfBuffers[i], srcFlatBuffArray[i], nodeId, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create flat buffers for srcFlatBuffArray\n"); goto exit; } status = createBuffersDp(destBufferSize, setup->numberOfBuffers[i], dstFlatBuffArray[i], nodeId, ZERO_PAD_MS_BYTE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create buffers for dstFlatBuffArray\n"); goto exit; } if (setup->disableAdditionalCmpbufferSize == CPA_FALSE) { /* For reliability mode we need to allocate double the space to * extract the SW compressed data into*/ status = createBuffersDp((bufferSize * EXTRA_BUFFER), setup->numberOfBuffers[i], cmpFlatBuffArray[i], nodeId, 0); } else { /* For performance use cases additional buffer size is not required * to be added to the cmp buffer, as there is no SW checks*/ status = createBuffersDp(bufferSize, setup->numberOfBuffers[i], cmpFlatBuffArray[i], nodeId, 0); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create buffers for cmpFlatBuffArray\n"); goto exit; } } /* Copy data into Flat Buffers from the corpus structure */ for (i = 0; i < numFiles; i++) { fileDataPtr = fileArray[i].corpusBinaryData; /* get the number of full Buffers */ amountOfFullBuffers = (fileArray[i].corpusBinaryDataLen) / bufferSize; /* Copy the data into Flat buffers */ for (j = 0; j < amountOfFullBuffers; j++) { memcpy(((void *)(uintptr_t)srcFlatBuffArray[i][j]->bufferPhysAddr), fileDataPtr, bufferSize); fileDataPtr += bufferSize; } fileDataPtr = NULL; } setup->setupData.sessDirection = CPA_DC_DIR_COMBINED; /* Get Size for DC Session */ status = cpaDcDpGetSessionSize( setup->dcInstanceHandle, &(setup->setupData), &sessionSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetSessionSize() returned %d status.\n", status); goto exit; } /* Allocate Memory for DC Session */ pSessionHandle = (CpaDcSessionHandle)qaeMemAllocNUMA( (sessionSize), nodeId, BYTE_ALIGNMENT_64); if (NULL == pSessionHandle) { PRINT_ERR("Unable to allocate Memory for Session Handle\n"); goto exit; } /* Setup and init Session */ status = cpaDcDpInitSession( setup->dcInstanceHandle, pSessionHandle, &(setup->setupData)); if ((latency_enable) && (latency_debug)) { PRINT( "%s: cpaDcDpInitSession() returns=%d\n", __FUNCTION__, (int)status); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Problem in session creation: status = %d \n", status); goto exit; } sessionInitialized = CPA_TRUE; /* CnV Error Injection */ /* Register a callback function */ status = cpaDcDpRegCbFunc(setup->dcInstanceHandle, (CpaDcDpCallbackFn)dcDpCallbackFunction); if ((latency_enable) && (latency_debug)) { PRINT("%s: cpaDcDpRegCbFunc() returns=%d\n", __FUNCTION__, (int)status); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to register callback fn, status = %d \n", status); status = CPA_STATUS_FAIL; goto exit; } status = buildSGLsSetupFromFlats(setup, pSessionHandle, nodeId, numFiles, perfData, srcFlatBuffArray, dstFlatBuffArray, cmpFlatBuffArray, &compressionOpDataSGL, &decompressionOpDataSGL, &compSGLArray, &decompSGLArray); if (CPA_STATUS_SUCCESS != status) { goto exit; } status = PerformOp( setup, compressionOpDataSGL, decompressionOpDataSGL, perfData); if ((latency_enable) && (latency_debug)) { PRINT("%s: PerformOp() returns=%d\n", __FUNCTION__, (int)status); } if (CPA_STATUS_SUCCESS != status) { status = CPA_STATUS_FAIL; goto exit; } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { status = performOffloadCalculation( setup, compressionOpDataSGL, decompressionOpDataSGL, perfData); } /* Record the bytes consumed and produced from the compressionOpData * structures for later printing. */ dcDpSetBytesProducedAndConsumed(compressionOpDataSGL, perfData, setup); exit: if (CPA_TRUE != sessionInitialized) { if (sampleRemoveDcDpSession(setup->dcInstanceHandle, pSessionHandle)) { PRINT_ERR("Unable to remove compression session\n"); } } if (pSessionHandle) qaeMemFreeNUMA((void **)&pSessionHandle); /* Free allocated src, dst & cmp memory */ if (srcFlatBuffArray) freeBuffersDp(srcFlatBuffArray, numFiles, setup); if (dstFlatBuffArray) freeBuffersDp(dstFlatBuffArray, numFiles, setup); if (cmpFlatBuffArray) freeBuffersDp(cmpFlatBuffArray, numFiles, setup); /* Free SGL related memory */ freeSGLsOpData(compressionOpDataSGL, numFiles, setup); freeSGLsOpData(decompressionOpDataSGL, numFiles, setup); freeSGLArray(compSGLArray, numFiles, setup); freeSGLArray(decompSGLArray, numFiles, setup); return status; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Main executing function which allocates/frees memory which is required, * and performs Enqueue/Batch operations as required ******************************************************************************/ static CpaStatus dcDpPerform(compression_test_params_t *setup) { /* Looping control variables */ Cpa32U i = 0, j = 0; /* Status variable */ CpaStatus status = CPA_STATUS_SUCCESS; /* NUMA node ID */ Cpa32U nodeId = 0; /* File data pointer */ Cpa8U *fileDataPtr = NULL; /* Performance data Structure */ perf_data_t *perfData = NULL; /* Total num of buffers */ Cpa32U totalBuffs = 0; /* Buffer size */ Cpa32U bufferSize = 0; /* Dest Buffer size */ Cpa32U destBufferSize = 0; /* Session size */ Cpa32U sessionSize = 0; /* Session handle */ CpaDcSessionHandle *pSessionHandle = NULL; Cpa32U removeStatus = 0; /* Session direction */ CpaDcSessionDir dcSessDirReq = CPA_DC_DIR_COMPRESS; /* Buffer counters */ Cpa32U amountOfFullBuffers = 0; /* Two dimensional array of CpaDcDpOpData pointers which will be used to * reference values from a 2 dimensional array through the corpus file and * buffer number */ CpaDcDpOpData ***compressionOpData = NULL; CpaDcDpOpData ***decompressionOpData = NULL; /* Declare src, dst & comp buffers */ CpaPhysFlatBuffer ***srcFlatBuffArray = NULL; CpaPhysFlatBuffer ***dstFlatBuffArray = NULL; CpaPhysFlatBuffer ***cmpFlatBuffArray = NULL; Cpa32U numFiles = 0; const corpus_file_t *fileArray = NULL; if (NULL == setup) { PRINT_ERR("Test Setup Pointer is NULL\n"); return CPA_STATUS_FAIL; } numFiles = getNumFilesInCorpus(setup->corpus); fileArray = getFilesInCorpus(setup->corpus); dcSessDirReq = setup->dcSessDir; perfData = setup->performanceStats; bufferSize = setup->bufferSize; /* Check what NUMA node we are on in order to allocate memory */ status = sampleCodeDcGetNode(setup->dcInstanceHandle, &nodeId); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to get Node ID\n"); return status; } srcFlatBuffArray = qaeMemAllocNUMA( (numFiles * sizeof(CpaPhysFlatBuffer **)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == srcFlatBuffArray) { PRINT_ERR("unable to allocate srcFlatBuffArray\n"); return CPA_STATUS_FAIL; } dstFlatBuffArray = qaeMemAllocNUMA( (numFiles * sizeof(CpaPhysFlatBuffer **)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == dstFlatBuffArray) { qaeMemFreeNUMA((void **)&srcFlatBuffArray); PRINT_ERR("unable to allocate dstFlatBuffArray \n"); return CPA_STATUS_FAIL; } cmpFlatBuffArray = qaeMemAllocNUMA( (numFiles * sizeof(CpaPhysFlatBuffer **)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == cmpFlatBuffArray) { qaeMemFreeNUMA((void **)&srcFlatBuffArray); qaeMemFreeNUMA((void **)&dstFlatBuffArray); PRINT_ERR("unable to allocate cmpFlatBuffArray \n"); return CPA_STATUS_FAIL; } compressionOpData = qaeMemAllocNUMA( (numFiles * sizeof(CpaDcDpOpData **)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == compressionOpData) { qaeMemFreeNUMA((void **)&srcFlatBuffArray); qaeMemFreeNUMA((void **)&dstFlatBuffArray); qaeMemFreeNUMA((void **)&cmpFlatBuffArray); PRINT_ERR("unable to allocate compressionOpData \n"); return CPA_STATUS_FAIL; } decompressionOpData = qaeMemAllocNUMA( (numFiles * sizeof(CpaDcDpOpData **)), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == decompressionOpData) { qaeMemFreeNUMA((void **)&srcFlatBuffArray); qaeMemFreeNUMA((void **)&dstFlatBuffArray); qaeMemFreeNUMA((void **)&cmpFlatBuffArray); qaeMemFreeNUMA((void **)&compressionOpData); PRINT_ERR("unable to allocate decompressionOpData \n"); return CPA_STATUS_FAIL; } /* populate the flat buffer array with number of buffers required * for each file and allocate the memory */ for (i = 0; i < numFiles; i++) { /* add up the number of buffers required for * complete corpus, this counter will be used to get the * number of call backs invoked */ totalBuffs += setup->numberOfBuffers[i]; /* allocate the memory for src, destination and compare buffers * for each file */ srcFlatBuffArray[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaPhysFlatBuffer *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == srcFlatBuffArray[i]) { PRINT_ERR("Unable to allocate Memory for srcFlatBuffArray\n "); freeBuffersDp(srcFlatBuffArray, i, setup); freeBuffersDp(dstFlatBuffArray, i, setup); freeBuffersDp(cmpFlatBuffArray, i, setup); freeOpDataDp(compressionOpData, i, setup); freeOpDataDp(decompressionOpData, i, setup); return CPA_STATUS_FAIL; } dstFlatBuffArray[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaPhysFlatBuffer *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == dstFlatBuffArray[i]) { PRINT_ERR("Unable to allocate Memory for dstFlatBuffArray\n "); freeBuffersDp(srcFlatBuffArray, i, setup); freeBuffersDp(dstFlatBuffArray, i, setup); freeBuffersDp(cmpFlatBuffArray, i, setup); freeOpDataDp(compressionOpData, i, setup); freeOpDataDp(decompressionOpData, i, setup); return CPA_STATUS_FAIL; } cmpFlatBuffArray[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaPhysFlatBuffer *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == cmpFlatBuffArray[i]) { PRINT_ERR("Unable to allocate Memory for cmpFlatBuffArray\n "); freeBuffersDp(srcFlatBuffArray, i, setup); freeBuffersDp(dstFlatBuffArray, i, setup); freeBuffersDp(cmpFlatBuffArray, i, setup); freeOpDataDp(compressionOpData, i, setup); freeOpDataDp(decompressionOpData, i, setup); return CPA_STATUS_FAIL; } compressionOpData[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaDcDpOpData *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == compressionOpData[i]) { PRINT_ERR("Unable to allocate Memory for compressionOpData\n "); freeBuffersDp(srcFlatBuffArray, i, setup); freeBuffersDp(dstFlatBuffArray, i, setup); freeBuffersDp(cmpFlatBuffArray, i, setup); freeOpDataDp(compressionOpData, i, setup); freeOpDataDp(decompressionOpData, i, setup); return CPA_STATUS_FAIL; } decompressionOpData[i] = qaeMemAllocNUMA( (setup->numberOfBuffers[i] * (sizeof(CpaDcDpOpData *))), nodeId, BYTE_ALIGNMENT_64); /* Check for NULL */ if (NULL == decompressionOpData[i]) { PRINT_ERR("Unable to allocate Memory for decompressionOpData\n "); freeBuffersDp(srcFlatBuffArray, i, setup); freeBuffersDp(dstFlatBuffArray, i, setup); freeBuffersDp(cmpFlatBuffArray, i, setup); freeOpDataDp(compressionOpData, i, setup); freeOpDataDp(decompressionOpData, i, setup); return CPA_STATUS_FAIL; } } { /* For compression,the destination buffer size is obtained using * Compress Bound API.*/ status = qatGetCompressBoundDestinationBufferSize( setup, bufferSize, &destBufferSize); if (CPA_STATUS_UNSUPPORTED == status) { PRINT("Algoritham Unsupported on this instance\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_UNSUPPORTED; } else if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "Unable to get the destination buffer size using Compress " "Bound API\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } } /* Allocate flat buffers for each file */ for (i = 0; i < numFiles; i++) { status = createBuffersDp(bufferSize, setup->numberOfBuffers[i], srcFlatBuffArray[i], nodeId, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create flat buffers for srcFlatBuffArray\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } status = createOpDataDp( setup->numberOfBuffers[i], compressionOpData[i], nodeId); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create compression opdata\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } status = createBuffersDp(destBufferSize, setup->numberOfBuffers[i], dstFlatBuffArray[i], nodeId, ZERO_PAD_MS_BYTE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create buffers for dstFlatBuffArray\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } if (setup->disableAdditionalCmpbufferSize == CPA_FALSE) { /* For reliabilty mode we need to allocate double the space to * extract the SW compressed data into*/ status = createBuffersDp((bufferSize * EXTRA_BUFFER), setup->numberOfBuffers[i], cmpFlatBuffArray[i], nodeId, 0); } else { /* For performance use cases additional buffer size is not required * to be added to the cmp buffer, as there is no SW checks*/ status = createBuffersDp(bufferSize, setup->numberOfBuffers[i], cmpFlatBuffArray[i], nodeId, 0); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create buffers for cmpFlatBuffArray\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } status = createOpDataDp( setup->numberOfBuffers[i], decompressionOpData[i], nodeId); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to create decompression opdata\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } } /* Copy data into Flat Buffers from the corpus structure */ for (i = 0; i < numFiles; i++) { fileDataPtr = fileArray[i].corpusBinaryData; /* get the number of full Buffers */ amountOfFullBuffers = (fileArray[i].corpusBinaryDataLen) / bufferSize; /* Copy the data into Flat buffers */ for (j = 0; j < amountOfFullBuffers; j++) { memcpy(((void *)(uintptr_t)srcFlatBuffArray[i][j]->bufferPhysAddr), fileDataPtr, bufferSize); fileDataPtr += bufferSize; } fileDataPtr = NULL; } if (CPA_FALSE == setup->setNsRequest) { /*LZ4S doesn't support COMBINED sessDirection*/ if ((setup->setupData.compType != CPA_DC_LZ4S) ) { setup->setupData.sessDirection = CPA_DC_DIR_COMBINED; } /* Get Size for DC Session */ status = cpaDcDpGetSessionSize( setup->dcInstanceHandle, &(setup->setupData), &sessionSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetSessionSize() returned %d status.\n", status); return CPA_STATUS_FAIL; } /* Allocate Memory for DC Session */ pSessionHandle = (CpaDcSessionHandle)qaeMemAllocNUMA( (sessionSize), nodeId, BYTE_ALIGNMENT_64); if (NULL == pSessionHandle) { PRINT_ERR("Unable to allocate Memory for Session Handle\n"); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } /* Setup and init Session */ status = cpaDcDpInitSession( setup->dcInstanceHandle, pSessionHandle, &(setup->setupData)); if ((latency_enable) && (latency_debug)) { PRINT("%s: cpaDcDpInitSession() returns=%d\n", __FUNCTION__, (int)status); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Problem in session creation: status = %d \n", status); qaeMemFreeNUMA((void **)&pSessionHandle); freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return CPA_STATUS_FAIL; } } /*CnV Error Injection */ /* Register a callback function */ status = cpaDcDpRegCbFunc(setup->dcInstanceHandle, (CpaDcDpCallbackFn)dcDpCallbackFunction); if ((latency_enable) && (latency_debug)) { PRINT("%s: cpaDcDpRegCbFunc() returns=%d\n", __FUNCTION__, (int)status); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to register callback fn, status = %d \n", status); status = CPA_STATUS_FAIL; goto exit; } /* Populate OpData struct */ for (i = 0; i < numFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { compressionOpData[i][j]->dcInstance = setup->dcInstanceHandle; compressionOpData[i][j]->pSessionHandle = pSessionHandle; compressionOpData[i][j]->srcBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( (void *)(uintptr_t)srcFlatBuffArray[i][j]->bufferPhysAddr, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); compressionOpData[i][j]->destBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( (void *)(uintptr_t)dstFlatBuffArray[i][j]->bufferPhysAddr, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); compressionOpData[i][j]->srcBufferLen = srcFlatBuffArray[i][j]->dataLenInBytes; compressionOpData[i][j]->destBufferLen = dstFlatBuffArray[i][j]->dataLenInBytes; /* Even though we are using CpaFlatBuffers we also have to set the * bufferLenToCompress and bufferLenForData fields which are used to * support CpaBufferList where srcBufferLen/destBufferLen take the * value CPA_DP_BUFLIST. */ compressionOpData[i][j]->bufferLenToCompress = srcFlatBuffArray[i][j]->dataLenInBytes; compressionOpData[i][j]->bufferLenForData = dstFlatBuffArray[i][j]->dataLenInBytes; compressionOpData[i][j]->pCallbackTag = perfData; compressionOpData[i][j]->sessDirection = CPA_DC_DIR_COMPRESS; SET_DC_DP_CNV_PARAMS_DEFAULT(compressionOpData[i][j]); compressionOpData[i][j]->thisPhys = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)virtAddrToDevAddr( compressionOpData[i][j], setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); if (CPA_TRUE == setup->setNsRequest) { compressionOpData[i][j]->pSetupData = (CpaDcNsSetupData *)qaeMemAllocNUMA( sizeof(CpaDcNsSetupData), 0, 64); if (NULL == compressionOpData[i][j]->pSetupData) { PRINT_ERR("Unable to allocate Memory for " "compressionOpData->pSetupData\n "); freeBuffersDp(srcFlatBuffArray, i, setup); freeBuffersDp(dstFlatBuffArray, i, setup); freeBuffersDp(cmpFlatBuffArray, i, setup); freeOpDataDp(compressionOpData, i, setup); freeOpDataDp(decompressionOpData, i, setup); return CPA_STATUS_FAIL; } compressionOpData[i][j]->pSetupData->compLevel = setup->setupData.compLevel; compressionOpData[i][j]->pSetupData->compType = setup->setupData.compType; compressionOpData[i][j]->pSetupData->huffType = setup->setupData.huffType; compressionOpData[i][j]->pSetupData->autoSelectBestHuffmanTree = setup->setupData.autoSelectBestHuffmanTree; compressionOpData[i][j]->pSetupData->sessDirection = CPA_DC_DIR_COMPRESS; compressionOpData[i][j]->pSetupData->sessState = setup->setupData.sessState; if (CPA_DC_LZ4 == setup->setupData.compType || CPA_DC_LZ4S == setup->setupData.compType) { compressionOpData[i][j]->pSetupData->checksum = CPA_DC_XXHASH32; } } } } if (CPA_DC_DIR_COMPRESS == dcSessDirReq) { /* Our compression session is already set up. We need to set our * number of operations and then we are ready to batch or enqueue */ perfData->numOperations = (Cpa64U)totalBuffs * (Cpa64U)setup->numLoops; } else if (CPA_DC_DIR_DECOMPRESS == dcSessDirReq) { perfData->numOperations = totalBuffs; { /* Compress the corpus so we can de-compress it */ status = compressCorpusPreDecomp(setup, compressionOpData, perfData); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not compress corpus before Decompression = %d \n", status); status = CPA_STATUS_FAIL; goto exit; } /* Swap the data in OpData structs */ for (i = 0; i < numFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { /* Update the compressed buffers length */ dstFlatBuffArray[i][j]->dataLenInBytes = compressionOpData[i][j]->results.produced; decompressionOpData[i][j]->dcInstance = setup->dcInstanceHandle; decompressionOpData[i][j]->pSessionHandle = pSessionHandle; { decompressionOpData[i][j]->srcBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( (void *)(uintptr_t)dstFlatBuffArray[i][j] ->bufferPhysAddr, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); } decompressionOpData[i][j] ->destBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( (void *)(uintptr_t)cmpFlatBuffArray[i][j]->bufferPhysAddr, setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); decompressionOpData[i][j]->srcBufferLen = dstFlatBuffArray[i][j]->dataLenInBytes; decompressionOpData[i][j]->destBufferLen = cmpFlatBuffArray[i][j]->dataLenInBytes; /* Even though we are using CpaFlatBuffers we also have to set * the bufferLenToCompress and bufferLenForData fields which are * used to support CpaBufferList where * srcBufferLen/destBufferLen take the value CPA_DP_BUFLIST. */ decompressionOpData[i][j]->bufferLenToCompress = dstFlatBuffArray[i][j]->dataLenInBytes; decompressionOpData[i][j]->bufferLenForData = cmpFlatBuffArray[i][j]->dataLenInBytes; decompressionOpData[i][j]->sessDirection = CPA_DC_DIR_DECOMPRESS; decompressionOpData[i][j]->pCallbackTag = perfData; SET_DC_DP_CNV_PARAMS_DEFAULT(decompressionOpData[i][j]); decompressionOpData[i][j]->thisPhys = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)virtAddrToDevAddr( decompressionOpData[i][j], setup->dcInstanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION); if (CPA_TRUE == setup->setNsRequest) { decompressionOpData[i][j]->pSetupData = (CpaDcNsSetupData *)qaeMemAllocNUMA( sizeof(CpaDcNsSetupData), 0, 64); if (NULL == compressionOpData[i][j]->pSetupData) { PRINT_ERR("Unable to allocate Memory for " "compressionOpData->pSetupData\n "); freeBuffersDp(srcFlatBuffArray, i, setup); freeBuffersDp(dstFlatBuffArray, i, setup); freeBuffersDp(cmpFlatBuffArray, i, setup); freeOpDataDp(compressionOpData, i, setup); freeOpDataDp(decompressionOpData, i, setup); return CPA_STATUS_FAIL; } decompressionOpData[i][j]->pSetupData->compLevel = setup->setupData.compLevel; decompressionOpData[i][j]->pSetupData->compType = setup->setupData.compType; decompressionOpData[i][j]->pSetupData->huffType = setup->setupData.huffType; decompressionOpData[i][j] ->pSetupData->autoSelectBestHuffmanTree = setup->setupData.autoSelectBestHuffmanTree; decompressionOpData[i][j]->pSetupData->sessDirection = CPA_DC_DIR_DECOMPRESS; decompressionOpData[i][j]->pSetupData->sessState = setup->setupData.sessState; if (CPA_DC_LZ4 == setup->setupData.compType || CPA_DC_LZ4S == setup->setupData.compType) { decompressionOpData[i][j]->pSetupData->checksum = CPA_DC_XXHASH32; } } } } /* Update the number of operations/responses for the expected for the * pre decompression stage */ perfData->numOperations = (Cpa64U)totalBuffs * (Cpa64U)setup->numLoops; perfData->responses = 0; } status = PerformOp(setup, compressionOpData, decompressionOpData, perfData); if ((latency_enable) && (latency_debug)) { PRINT("%s: PerformOp() returns=%d\n", __FUNCTION__, (int)status); } if (CPA_STATUS_SUCCESS != status) { status = CPA_STATUS_FAIL; goto exit; } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { status = performOffloadCalculation( setup, compressionOpData, decompressionOpData, perfData); } /* Record the bytes consumed and produced from the compressionOpData * structures for later printing. */ dcDpSetBytesProducedAndConsumed(compressionOpData, perfData, setup); exit: if (CPA_FALSE == setup->setNsRequest) { if (CPA_STATUS_SUCCESS != status) { removeStatus = sampleRemoveDcDpSession(setup->dcInstanceHandle, pSessionHandle); } if (CPA_STATUS_SUCCESS != removeStatus) { PRINT_ERR("Unable to remove compression session\n"); } qaeMemFreeNUMA((void **)&pSessionHandle); } /* Free allocated src, dst & cmp memory */ freeBuffersDp(srcFlatBuffArray, numFiles, setup); freeBuffersDp(dstFlatBuffArray, numFiles, setup); freeBuffersDp(cmpFlatBuffArray, numFiles, setup); /* Free OpData structures */ freeOpDataDp(compressionOpData, numFiles, setup); freeOpDataDp(decompressionOpData, numFiles, setup); return status; } /** ***************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * Setup a compression thread for a given packet size. ******************************************************************************/ void dcDpPerformance(single_thread_test_data_t *testSetup) { compression_test_params_t dcSetup = {0}; compression_test_params_t *tmpSetup = NULL; Cpa16U numInstances = 0; CpaInstanceHandle *instances = NULL; CpaStatus status = CPA_STATUS_FAIL; CpaDcInstanceCapabilities capabilities = {0}; CpaInstanceInfo2 *instanceInfo = NULL; #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) int fd = -1; #endif /* Get the setup pointer */ tmpSetup = (compression_test_params_t *)(testSetup->setupPtr); /* update the setup structure with setup parameters */ memcpy(&dcSetup.requestOps, &tmpSetup->requestOps, sizeof(CpaDcOpData)); dcSetup.bufferSize = tmpSetup->bufferSize; dcSetup.corpus = tmpSetup->corpus; dcSetup.setupData = tmpSetup->setupData; dcSetup.dcSessDir = tmpSetup->dcSessDir; dcSetup.syncFlag = tmpSetup->syncFlag; dcSetup.dpTestType = tmpSetup->dpTestType; dcSetup.numRequests = tmpSetup->numRequests; dcSetup.numLoops = tmpSetup->numLoops; dcSetup.isDpApi = CPA_TRUE; dcSetup.disableAdditionalCmpbufferSize = tmpSetup->disableAdditionalCmpbufferSize; dcSetup.threadID = testSetup->threadID; /*give our thread a unique memory location to store performance stats*/ dcSetup.performanceStats = testSetup->performanceStats; dcSetup.performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; dcSetup.setNsRequest = tmpSetup->setNsRequest; dcSetup.isUseSGL = tmpSetup->isUseSGL; dcSetup.numFlatsPerSGL = tmpSetup->numFlatsPerSGL; dcSetup.bufferSize = tmpSetup->bufferSize; /*initialize number of buffers with NULL*/ dcSetup.numberOfBuffers = NULL; dcSetup.numberOfSGLs = NULL; status = calculateRequireBuffers(&dcSetup); /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space is does * nothing, but kernel space threads do not start * until we call startThreads anyway */ startBarrier(); if (CPA_STATUS_SUCCESS != status) { PRINT("Error calculating required buffers\n"); goto exit; } instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate Memory for instanceInfo"); goto exit; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); /*Initialize the statsPrintFunc to NULL, the dcPrintStats function will * be assigned if compression completes successfully */ testSetup->statsPrintFunc = NULL; /* Get the number of instances */ { status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR(" Unable to get number of DC instances\n"); goto exit; } if (0 == numInstances) { PRINT_ERR(" DC Instances are not present\n"); goto exit; } instances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == instances) { PRINT_ERR("Unable to allocate Memory for Instances\n"); goto exit; } /*get the instance handles so that we can start * our thread on the selected instance */ status = cpaDcGetInstances(numInstances, instances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("get instances failed"); goto exit; } } /* give our thread a logical quick assist instance to use * use % to wrap around the max number of instances*/ dcSetup.dcInstanceHandle = instances[(testSetup->logicalQaInstance) % numInstances]; /*check if dynamic compression is supported*/ status = cpaDcQueryCapabilities(dcSetup.dcInstanceHandle, &capabilities); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaDcQueryCapabilities failed", __func__, __LINE__); goto exit; } if (CPA_FALSE == capabilities.dynamicHuffman && tmpSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("Dynamic is not supported on logical instance %d\n", (testSetup->logicalQaInstance) % numInstances); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } status = cpaDcInstanceGetInfo2(dcSetup.dcInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaDcInstanceGetInfo2 failed", __func__, __LINE__); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } #if !defined(SC_BSD_UPSTREAM) if (instanceInfo->isPolled == CPA_FALSE) { PRINT("Data-Plane operations not supported on non-polled instances\n"); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } #endif if (CPA_STATUS_SUCCESS != qatDcGetPreTestRecoveryCount( &dcSetup, &capabilities, testSetup->performanceStats)) { testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (CPA_TRUE == dcSetup.useXlt && ASYNC == dcSetup.syncFlag) { PRINT("Async mode not supported in Xlt[%d]\n", dcSetup.useXlt); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&instances); qaeMemFree((void **)&dcSetup.numberOfBuffers); qaeMemFree((void **)&instanceInfo); if (dcSetup.numberOfSGLs) qaeMemFree((void **)&dcSetup.numberOfSGLs); sampleCodeThreadExit(); } #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) status = icp_sal_DcGetFileDescriptor(dcSetup.dcInstanceHandle, &fd); if (CPA_STATUS_SUCCESS == status) { PRINT("Data-Plane operations not supported on Epoll instances\n"); qaeMemFree((void **)&instances); qaeMemFree((void **)&dcSetup.numberOfBuffers); qaeMemFree((void **)&instanceInfo); if (dcSetup.numberOfSGLs) qaeMemFree((void **)&dcSetup.numberOfSGLs); icp_sal_DcPutFileDescriptor(dcSetup.dcInstanceHandle, fd); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_UNSUPPORTED; /*set the print function that can be used to print * statistics at the end of the test * */ testSetup->statsPrintFunc = (stats_print_func_t)stopDcServicesFromPrintStats; sampleCodeThreadExit(); } #endif /*launch function that does all the work*/ if (!dcSetup.isUseSGL) { status = dcDpPerform(&dcSetup); } else { status = dcDpPerformSGL(&dcSetup); } if (CPA_STATUS_UNSUPPORTED == status) { dcPrintTestData(&dcSetup); PRINT("Compression Thread %u Unsupported\n", testSetup->threadID); numCreatedThreads_g--; testSetup->performanceStats->threadReturnStatus = CPA_STATUS_UNSUPPORTED; } else if (CPA_STATUS_SUCCESS != status) { dcPrintTestData(&dcSetup); PRINT_ERR("Compression Thread %u FAILED\n", testSetup->threadID); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { qatDcGetPostTestRecoveryCount(&dcSetup, testSetup->performanceStats); } if ((CPA_STATUS_SUCCESS == status) && (CPA_STATUS_FAIL != testSetup->performanceStats->threadReturnStatus)) { /*set the print function that can be used to print * statistics at the end of the test * */ testSetup->statsPrintFunc = (stats_print_func_t)dcPrintStats; } exit: if (dcSetup.numberOfBuffers != NULL) { qaeMemFree((void **)&dcSetup.numberOfBuffers); } if (dcSetup.numberOfSGLs != NULL) { qaeMemFree((void **)&dcSetup.numberOfSGLs); } if (instances != NULL) { qaeMemFree((void **)&instances); } if (instanceInfo != NULL) { qaeMemFree((void **)&instanceInfo); } sampleCodeThreadComplete(testSetup->threadID); } EXPORT_SYMBOL(dcDpPerformance); /** ***************************************************************************** * @ingroup checkDcNonPollingInstance * * @description * Check for Non Polling DC Instance. ******************************************************************************/ static CpaStatus checkDcNonPollingInstance(CpaBoolean *polled) { Cpa16U numInstances = 0; CpaInstanceHandle *instances = NULL; CpaStatus status = CPA_STATUS_FAIL; CpaInstanceInfo2 instanceInfo = {0}; int i = 0; /* Get the number of instances */ status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to get number of DC instances\n"); return CPA_STATUS_FAIL; } if (0 == numInstances) { PRINT_ERR("DC Instances are not present\n"); return CPA_STATUS_FAIL; } instances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == instances) { PRINT_ERR("Unable to allocate Memory for Instances\n"); return CPA_STATUS_FAIL; } /*get the instance handles */ status = cpaDcGetInstances(numInstances, instances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("get instances failed"); goto exit; } for (i = 0; i < numInstances; i++) { status = cpaDcInstanceGetInfo2(instances[i], &instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInstanceGetInfo2 failed"); status = CPA_STATUS_FAIL; goto exit; } if (instanceInfo.isPolled == CPA_FALSE) { *polled = CPA_FALSE; status = CPA_STATUS_SUCCESS; goto exit; } } exit: if (instances != NULL) { qaeMemFree((void **)&instances); } return status; } /** ***************************************************************************** * @ingroup checkDecompNonPollingInstance * * @description * Check for Non Polling Decomp Instance. ******************************************************************************/ /** ***************************************************************************** * * External Function Interfaces * ******************************************************************************/ /** **************************************************************************** * @ingroup sampleCompressionDpPerf * * @description * setup a Compression Data Plane API test * This function needs to be called from main to setup a compression test. * The framework createThreads function is then used to propagate this setup * across cores using different compression logical instances *****************************************************************************/ CpaStatus setupDcDpTest(CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcHuffType huffmanType, Cpa32U windowSize, Cpa32U testBufferSize, corpus_type_t corpusType, sync_mode_t syncFlag, dp_request_type_t dpTestType, Cpa32U numRequests, Cpa32U numLoops) { compression_test_params_t *dcSetup = NULL; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numberOfBuffersPerFile = 0, i = 0; Cpa32U numFiles = getNumFilesInCorpus(corpusType); const corpus_file_t *const fileArray = getFilesInCorpus(corpusType); CpaBoolean polled = CPA_TRUE; /* Ensure that the number of threads created do not exceed the amount of * threads supported by the sample code framework. */ if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } { status = checkDcNonPollingInstance(&polled); } if (CPA_STATUS_SUCCESS != status) { return CPA_STATUS_FAIL; } #if !defined(SC_BSD_UPSTREAM) if (polled == CPA_FALSE) { PRINT("Data-Plane operations not supported on non-polled instances\n"); return CPA_STATUS_SUCCESS; } #endif status = populateCorpus(testBufferSize, corpusType); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to Populate corpus file\n"); return CPA_STATUS_FAIL; } { /* * Create DC instances handles, allocate temporary memory for dynamic * compression and create polling threads(if enabled in configuration) * */ status = startDcServices(DYNAMIC_BUFFER_AREA, TEMP_NUM_BUFFS); if (CPA_STATUS_SUCCESS != status) { PRINT("Error in Starting Dc Services\n"); return CPA_STATUS_FAIL; } } /* Get the framework setup pointer */ /* thread_setup_g is a multi-dimensional array that * stores the setup for all thread * variations in an array of characters. * we store our test setup at the * start of the second array ie index 0. * There maybe multi thread types * (setups) running as counted by testTypeCount_g*/ /* thread_setup_g is a multi-dimensional char array * we need to cast it to the * Compression structure */ dcSetup = (compression_test_params_t *)&thread_setup_g[testTypeCount_g][0]; INIT_OPDATA_DEFAULT(&dcSetup->requestOps); /* Set the performance function to the actual performance function * that actually does all the performance */ dcSetup->setNsRequest = isNsRequest_g; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)dcDpPerformance; /* update the setup_g with buffersize */ testSetupData_g[testTypeCount_g].packetSize = testBufferSize; /* Data compression setup data */ dcSetup->setupData.compLevel = compLevel; dcSetup->setupData.compType = algorithm; { dcSetup->setupData.sessDirection = CPA_DC_DIR_COMPRESS; } dcSetup->setupData.checksum = gChecksum; #ifdef SC_ENABLE_DYNAMIC_COMPRESSION dcSetup->setupData.huffType = huffmanType; #else dcSetup->setupData.huffType = CPA_DC_HT_STATIC; #endif dcSetup->setupData.sessState = CPA_DC_STATELESS; #if DC_API_VERSION_LESS_THAN(1, 6) dcSetup->setupData.deflateWindowSize = DEFAULT_COMPRESSION_WINDOW_SIZE; #endif dcSetup->corpus = corpusType; dcSetup->bufferSize = testBufferSize; dcSetup->dcSessDir = direction; dcSetup->syncFlag = syncFlag; dcSetup->dpTestType = dpTestType; dcSetup->numRequests = numRequests; dcSetup->numLoops = numLoops; dcSetup->setupData.autoSelectBestHuffmanTree = CPA_DC_ASB_DISABLED; dcSetup->isDpApi = CPA_TRUE; dcSetup->disableAdditionalCmpbufferSize = disableAdditionalCmpbufferSize_g; /* Ensure that the numbers of buffers required for each file is less * than or equal to the batch/enqueue amount. */ for (i = 0; i < numFiles; i++) { numberOfBuffersPerFile = fileArray[i].corpusBinaryDataLen / testBufferSize; if (fileArray[i].corpusBinaryDataLen % testBufferSize != 0) { numberOfBuffersPerFile++; } if (numberOfBuffersPerFile < numRequests) { PRINT_ERR("The batch/enqueue amount (%d) specified exceeds the" " number of buffers available (%d)\n", numRequests, numberOfBuffersPerFile); return CPA_STATUS_FAIL; } } return status; } cpa_sample_code_dc_dp.h000066400000000000000000000132301503624047500363460ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_dc_dp.h * * @defgroup compressionThreads * * @ingroup compressionThreads * * @description * Contains function prototypes and #defines used throughout code * and macros * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_DC_DP_H_ #define CPA_SAMPLE_CODE_DC_DP_H_ #include "cpa.h" #include "cpa_dc.h" #include "cpa_dc_dp.h" #include "cpa_sample_code_dc_perf.h" /* step back for the dynamic algorithm */ #define DP_BACKOFF_STEP_BACK 20 /* step forward for the dynamic algorithm */ #define DP_BACKOFF_STEP_FORWARD 10 * DP_BACKOFF_STEP_BACK /* maximum value of the dynamic backoff delay */ #define DP_BACKOFF_TIMER_MAX 10000 /** * ***************************************************************************** * @ingroup compressionThreads * setupDpDcTest * * @description * this API is the main API called by the framework, this is configures * data structure before starting the performance threads * @threadSafe * No * * @param[out] None * * @param[in] algorithm Algorithm used for compression/decompression * @param[in] direction session direction * @param[in] compLevel compression Level * @param[in] HuffmanType HuffMantype Dynamic/static * @param[in] testBuffersize size of the flat Buffer to use * @param[in] corpusType type of corpus Calgary/Canterbury corpus * @param[in] syncFlag synchronous/Asynchronous operation * @param[in] dpTestType If set to DC_DP_BATCHING, then the number of * requests to batch is set by the numRequests * parameter. * If set to DC_DP_ENQUEUEING, then a single * request is Enqueued. * @param[in] numRequests How many requests to submit in a single call for * Batch Mode, currently > 1 requests is not * supported in Enqueue Mode. * @param[in] numloops Number of loops to compress or decompress ******************************************************************************/ CpaStatus setupDcDpTest(CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcHuffType huffmanType, Cpa32U windowSize, Cpa32U testBufferSize, corpus_type_t corpusType, sync_mode_t syncFlag, dp_request_type_t dpTestType, Cpa32U numRequests, Cpa32U numLoops); #endif /* CPA_SAMPLE_CODE_DC_DP_H_ */ cpa_sample_code_dc_perf.h000066400000000000000000001117151503624047500367060ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_dc_perf.h * * @defgroup compressionThreads * * @ingroup compressionThreads * * @description * Contains function prototypes and #defines used throughout code * and macros * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_DC_PERF_H_ #define CPA_SAMPLE_CODE_DC_PERF_H_ #include "cpa.h" #include "cpa_dc.h" #ifdef SC_CHAINING_ENABLED #include "cpa_dc_chain.h" #endif #include "cpa_cy_sym.h" #include "cpa_sample_code_framework.h" #include "../common/qat_perf_utils.h" /* ******************************************************************************* * General performance code settings ******************************************************************************* */ #define MIN_DC_LOOPS (1) #define DEFAULT_DC_LOOPS (100) /* Common macro definitions */ #ifndef DC_API_VERSION_AT_LEAST #define DC_API_VERSION_AT_LEAST(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR > major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR >= minor)) #endif #ifndef DC_API_VERSION_LESS_THAN #define DC_API_VERSION_LESS_THAN(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR < major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR < minor)) #endif /* Dynamic number of buffers to be created while initializing the Compression * session */ #define TEMP_NUM_BUFFS (5) #define MIN_BUFFER_SIZE (15) /* Extra buffer */ #define EXTRA_BUFFER (2) #define MIN_DST_BUFFER_SIZE (8192) #define MIN_DST_BUFFER_SIZE_GEN4 (1026) #define DEFAULT_INCLUDE_LZ4 (0) #define DEFAULT_COMPRESSION_LOOPS (100) #if DC_API_VERSION_LESS_THAN(1, 6) #define DEFAULT_COMPRESSION_WINDOW_SIZE (7) #endif #if DC_API_VERSION_AT_LEAST(3, 1) #define DEFAULT_COMPRESSION_WINDOW_SIZE (0) #endif #define INITIAL_RESPONSE_COUNT (-1) #define SCALING_FACTOR_100 (100) #define SCALING_FACTOR_1000 (1000) #define BASE_10 (10) #define DYNAMIC_BUFFER_AREA (0x20000) #define SINGLE_REQUEST (1) #define SINGLE_LOOP (1) #define ONE_BUFFER_DC (1) /* 1 MByte all zeros corpus. Enables calibrating latencies among different * buffer sizes */ #define ZEROS_CORPUS_LENGTH (64 * 1024 * 16) /* Defining the available compression levels */ #define SAMPLE_CODE_CPA_DC_L1 (CPA_DC_L1) #define SAMPLE_CODE_CPA_DC_L2 (CPA_DC_L2) #define SAMPLE_CODE_CPA_DC_L3 (CPA_DC_L3) #define SAMPLE_CODE_CPA_DC_L4 (CPA_DC_L4) #define SAMPLE_CODE_CPA_DC_L5 (CPA_DC_L5) #define SAMPLE_CODE_CPA_DC_L6 (CPA_DC_L6) #define SAMPLE_CODE_CPA_DC_L7 (CPA_DC_L7) #define SAMPLE_CODE_CPA_DC_L8 (CPA_DC_L8) #define SAMPLE_CODE_CPA_DC_L9 (CPA_DC_L9) #if DC_API_VERSION_AT_LEAST(3, 0) #define SAMPLE_CODE_CPA_DC_L10 (CPA_DC_L10) #define SAMPLE_CODE_CPA_DC_L11 (CPA_DC_L11) #define SAMPLE_CODE_CPA_DC_L12 (CPA_DC_L12) #endif /* the following are defined in the framework, these are used for setup only * and are not to be used in functions not thread safe */ #ifdef USER_SPACE extern Cpa8U (*thread_setup_g)[MAX_SETUP_STRUCT_SIZE_IN_BYTES]; extern thread_creation_data_t *testSetupData_g; extern sample_code_thread_t *threads_g; #else extern Cpa8U thread_setup_g[MAX_THREAD_VARIATION][MAX_SETUP_STRUCT_SIZE_IN_BYTES]; extern thread_creation_data_t testSetupData_g[MAX_THREAD_VARIATION]; extern sample_code_thread_t threads_g[MAX_THREADS]; #endif extern Cpa32U testTypeCount_g; /** * ***************************************************************************** * @ingroup compressionThreads * Corpus Setup Data. * @description * This ENUM contains data relating to corpus type. * The client needs pass corpus type to setup * * ****************************************************************************/ typedef enum _corpusType { /* Canterbury Corpus */ CANTERBURY_CORPUS = 0, /* Calgary Corpus*/ CALGARY_CORPUS, RANDOM, SIGN_OF_LIFE_CORPUS, CALGARY_SIX_FILES, CALGARY_FULL_SET, ZERO_LENGTH_FILE, OVERFLOW_FILE, OVERFLOW_AND_ZERO_FILE, CORPUS_TYPE_EXTENDED, /*All Corpus type should added above * CORPUS_TYPE_INVALID. */ CORPUS_TYPE_INVALID } corpus_type_t; #define MAX_NUM_CORPUS_TYPE CORPUS_TYPE_INVALID /** * ***************************************************************************** * @ingroup compressionThreads * corpus file data. * @description * This structure contains data relating to setup corpus file. * This structure is updated for each file in the corpus by performance * API. * * **************************************************************************** * */ typedef struct corpus_file_s { /* Corpus data in char format */ Cpa8U *corpusBinaryData; /* Corpus data length */ Cpa32U corpusBinaryDataLen; } corpus_file_t; /** * ***************************************************************************** * @ingroup compressionThreads * enum for Data Plane Request Type * @description * This ENUM will be used to specify whether the compression operations * are enqueued by the driver a single request at a time or in batches of * multiple requests. * The client needs pass provide this information in the setup * * ****************************************************************************/ typedef enum _dpRequestType { /*Synchronous flag*/ DC_DP_BATCHING = 0, DC_DP_ENQUEUEING } dp_request_type_t; /** * ***************************************************************************** * @ingroup compressionThreads * compression setup Data. * @description * This structure contains setup data relating to setup compression End2End * feature * * ****************************************************************************/ typedef struct qat_dc_e2e_s { Cpa32U swInputChecksum; Cpa32U swOutputChecksum; Cpa64U swInputChecksum64b; Cpa64U swOutputChecksum64b; CpaCrcData compCrcData; } qat_dc_e2e_t; /** * ***************************************************************************** * @ingroup compressionThreads * compression setup Data. * @description * This structure contains data relating to setup compression performance * tests.The client needs to fill this structure before calling performance * API * * ****************************************************************************/ typedef struct compression_test_params_s { /* Session Direction */ CpaDcSessionDir dcSessDir; /*number of CpaBufferLists to allocate/submit and loop over*/ Cpa32U numLists; /*compression instance handle of service that has already been started*/ CpaInstanceHandle dcInstanceHandle; CpaInstanceHandle dcChainReadInsHandle; /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /* Performance setup data for initializing sessions */ CpaDcSessionSetupData setupData; /* Corpus Type */ corpus_type_t corpus; Cpa32U corpusFileIndex; /*Buffer Size */ Cpa32U bufferSize; /* Synchronous Flag */ sync_mode_t syncFlag; /* Number of Loops */ Cpa32U numLoops; /*rate limit variable*/ Cpa32U compRate; Cpa32U sleepTime; CpaBoolean specific_sleeptime_flag; CpaBoolean adjustSleepTimeEnabled; /* Request type (Batch or Enqueue) */ dp_request_type_t dpTestType; /* Number of requests to submit before processing */ Cpa32U numRequests; /* Array of buffers required, indexed by corpus file number */ Cpa32U *numberOfBuffers; /* Array of SGLs required, indexed by corpus file number */ Cpa32U *numberOfSGLs; /* Unique thread ID based on the order in which the thread was created */ Cpa32U threadID; /* identifies if Data Plane API is used */ CpaBoolean isDpApi; /*store the numa nodeId that the thread is running on*/ Cpa32U node; /*alignment of buffers to be allocated for this setup*/ Cpa32U alignment; Cpa32U fileSize[20]; // session per file array of FileSize provides the fileSize for each session Cpa32U sessions; Cpa32U inputListSize; Cpa32U *packetSizeInBytesArray; Cpa32U outputListSize; Cpa32U *numberOfOutputLists; Cpa32U flatBuffSize; CpaDcFlush flushFlag; CpaBoolean useStatefulLite; CpaBoolean useE2E; CpaDcOpData requestOps; /*pointer to function capable of printing our stat related to specific * test variation */ compute_test_result_func_t passCriteria; /* Set this flag to CPA_TRUE to induce overflow and handle it * by setting the destination buffer to be less than source * buffer. */ CpaBoolean induceOverflow; #if defined(SC_CHAINING_ENABLED) || defined(SC_CHAINING_EXT_ENABLED) CpaDcChainOperations chainOperation; CpaBoolean legacyChainRequest; CpaBoolean appendCRC; CpaBoolean testIntegrity; /* Initial Value Length */ Cpa32U symIvLength; Cpa8U numSessions; CpaBoolean keyDerive; #endif /*the logicalQaInstance for the cipher to use*/ Cpa32U logicalQaInstance; #if defined(SC_WITH_QAT20) || defined(SC_WITH_QAT20_UPSTREAM) #if DC_API_VERSION_AT_LEAST(3, 2) #if !defined(SC_BSD_UPSTREAM) /**performanceStats; /*check perf_data pointer is valid*/ if (NULL == pPerfData) { PRINT_ERR("Invalid data in CallbackTag\n"); return; } pPerfData->responses++; /*check status */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "%s Failed, status = %d, responseCount %llu, submissions %u\n", __func__, status, (long long int)pPerfData->responses, pPerfData->submissions); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } if (latency_enable) { /* Did we setup the array pointer? */ QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS( pPerfData->response_times, pPerfData->threadReturnStatus); /*Have we sampled too many buffer operations?*/ if (pPerfData->latencyCount >= MAX_LATENCY_COUNT) { PRINT_ERR("max latency count exceeded\n"); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } /* Is this the buffer we calculate latency on? * And have we calculated too many for array? */ if (pPerfData->threadReturnStatus == CPA_STATUS_SUCCESS && pPerfData->responses == pPerfData->nextCount && pPerfData->latencyCount < MAX_LATENCY_COUNT) { int i = pPerfData->latencyCount; /*Now get the end timestamp - before any print outs*/ pPerfData->response_times[i] = sampleCodeTimestamp(); pPerfData->nextCount += pPerfData->countIncrement; pPerfData->latencyCount++; } } if ((CPA_TRUE == gUseStatefulLite) || (CPA_DC_STATEFUL == test_struct->setupData.sessState) || #if (DC_API_VERSION_AT_LEAST(3, 2)) (reliability_g && ((CPA_TRUE == test_struct->useE2E) || (CPA_TRUE == test_struct->useE2EVerify))) || #else (CPA_TRUE == test_struct->useE2E) || (CPA_TRUE == test_struct->useE2EVerify) || #endif (CPA_TRUE == test_struct->useStatefulLite)) { sampleCodeSemaphorePost(&pPerfData->comp); } /* Release the semaphore if all the responses are gathered. * In case of failure, the number of responses will be for * submissions that had happened till the point of failure. */ if ((pPerfData->responses >= pPerfData->numOperations) || (pPerfData->threadReturnStatus != CPA_STATUS_SUCCESS && pPerfData->responses >= pPerfData->submissions)) { /* generate end of the cycle stamp for Corpus */ pPerfData->endCyclesTimestamp = sampleCodeTimestamp(); sampleCodeSemaphorePost(&pPerfData->comp); } } Cpa32U expansionFactor_g = 1; EXPORT_SYMBOL(expansionFactor_g); #ifdef ZERO_BYTE_LAST_REQUEST CpaBoolean zeroByteLastRequest_g = CPA_FALSE; #endif extern int signOfLife; /* Global array of polling threads */ sample_code_thread_t *dcPollingThread_g = NULL; /* Number of Compression instances enabled for polling */ Cpa32U numDcPolledInstances_g = 0; /* Global array of instance handles */ CpaInstanceHandle *dcInstances_g = NULL; /* Number of Compression instances available */ Cpa16U numDcInstances_g = 0; /* Flag to indicate if the DC services are started */ volatile CpaBoolean dc_service_started_g = CPA_FALSE; /* Flag to indicate if the DC polling threads have been created */ volatile CpaBoolean dc_polling_started_g = CPA_FALSE; /* flag to define weather to use zlib to compress data before decompression*/ CpaBoolean useZlib_g = CPA_FALSE; EXPORT_SYMBOL(useZlib_g); /* Dynamic Buffer List buffer list used to start DC Services */ CpaBufferList ***pInterBuffList_g = NULL; #ifdef SC_ENABLE_DYNAMIC_COMPRESSION CpaDcHuffType huffmanType_g = CPA_DC_HT_FULL_DYNAMIC; #else CpaDcHuffType huffmanType_g = CPA_DC_HT_STATIC; #endif EXPORT_SYMBOL(huffmanType_g); #define SINGLE_INTER_BUFF_LIST (1) #ifndef DO_CRYPTO Cpa32U getThroughput(Cpa64U numPackets, Cpa32U packetSize, perf_cycles_t cycles) { unsigned long long bytesSent = 0; unsigned long long time = cycles; unsigned long long rate = 0; /* declare frequency in kiloHertz*/ Cpa32U freq = sampleCodeGetCpuFreq(); bytesSent = packetSize; bytesSent = bytesSent * numPackets; /*get time in milli seconds by dividing numberOfClockCycles by frequency * in kilohertz ie: cycles/(cycles/millsec) = time (mSec) */ do_div(time, freq); /*check that the sample time was not to small*/ if (time == 0) { PRINT_ERR("Sample time is too small to calculate throughput\n"); return 0; } /*set rate to be bytesSent, once we perform the do_div rate changes from * bytes to bytes/milli second or kiloBytes/second*/ rate = bytesSent; /*rate in kBps*/ do_div(rate, time); /*check that the rate is high enough to convert to Megabits per second*/ if (rate == 0) { PRINT_ERR("no data was sent to calculate throughput\n"); return 0; } /* convert Kilobytes/second to Kilobits/second*/ rate = rate * NUM_BITS_IN_BYTE; /*then convert rate from Kilobits/second to Megabits/second*/ do_div(rate, KILOBITS_IN_MEGABITS); return (Cpa32U)rate; } #endif /* not DO_CRYPTO */ static void freeDcBufferList(CpaBufferList **buffListArray, Cpa32U numberOfBufferList) { Cpa32U i = 0, j = 0; Cpa32U numberOfBuffers = 0; for (i = 0; i < numberOfBufferList; i++) { if (buffListArray[i] != NULL) { numberOfBuffers = buffListArray[i]->numBuffers; if (buffListArray[i]->pBuffers != NULL) { for (j = 0; j < numberOfBuffers; j++) { if (buffListArray[i]->pBuffers[j].pData != NULL) { qaeMemFreeNUMA( (void **)&buffListArray[i]->pBuffers[j].pData); buffListArray[i]->pBuffers[j].pData = NULL; } } qaeMemFreeNUMA((void **)&buffListArray[i]->pBuffers); buffListArray[i]->pBuffers = NULL; } if (buffListArray[i]->pPrivateMetaData != NULL) { qaeMemFreeNUMA((void **)&buffListArray[i]->pPrivateMetaData); } } } } static char *canterburyFileNames[] = { /* Single Canterbury corpus file is a concatenation of the following * files: "alice29.txt", "asyoulik.txt", "cp.html", "fields.c","grammar.lsp", "kennedy.xls", "lcet10.txt" , "plrabn12.txt", "ptt5" */ "canterbury"}; static char *calgaryFullFileNames[] = { /* Single Calgary corpus file is a concatenation of the following * files: */ "bib", "book1", "book2", "geo", "news", "obj1", "obj2", "paper1", "paper2", "paper3", "paper4", "paper5", "paper6", "pic", "progc", "progl", "progp", "trans"}; static char *calgarySixFileNames[] = {"paper4", "paper5", "paper4", "paper5", "paper5", "paper4"}; static char *calgaryFileNames[] = { /* Single Calgary file is a concatenation of all files * in calgaryFullFileNames. */ "calgary"}; static char *signOfLifeFile[] = {/* 1st 32k of calgary corpus file */ "calgary32"}; static char *zeroLengthFilenames[] = {"zero1", "progp", "paper4", "zero2", "obj1", "zero3"}; static char *overflowFileNames[] = {"paper4", "bib", "book1", "book2", "geo", "news"}; static char *overflowAndZeroFileNames[] = {"zero1", "book1", "zero2", "book2", "news", "zero2"}; #define CORPUS_DATA_EMPTY \ { \ NULL, NULL, 0, CPA_FALSE \ } #define CORPUS_DATA_INIT(name) \ { \ NULL, name, sizeof(name) / sizeof(name[0]), CPA_FALSE \ } #define CORPUS_TO_STR(corpus) #corpus #define CORPUS_STR(corpus) CORPUS_TO_STR(corpus) static corpusInfo corpus[] = { [CANTERBURY_CORPUS] = { CANTERBURY_CORPUS, CORPUS_STR(CANTERBURY_CORPUS), CORPUS_DATA_INIT(canterburyFileNames) }, [CALGARY_CORPUS] = { CALGARY_CORPUS, CORPUS_STR(CALGARY_CORPUS), CORPUS_DATA_INIT(calgaryFileNames) }, [RANDOM] = { RANDOM, CORPUS_STR(RANDOM), CORPUS_DATA_EMPTY }, [SIGN_OF_LIFE_CORPUS] = { SIGN_OF_LIFE_CORPUS, CORPUS_STR(SIGN_OF_LIFE_CORPUS), CORPUS_DATA_INIT(signOfLifeFile) }, [CALGARY_SIX_FILES] = { CALGARY_SIX_FILES, CORPUS_STR(CALGARY_SIX_FILES), CORPUS_DATA_INIT(calgarySixFileNames) }, [CALGARY_FULL_SET] = { CALGARY_FULL_SET, CORPUS_STR(CALGARY_FULL_SET), CORPUS_DATA_INIT(calgaryFullFileNames) }, [ZERO_LENGTH_FILE] = { ZERO_LENGTH_FILE, CORPUS_STR(ZERO_LENGTH_FILE), CORPUS_DATA_INIT(zeroLengthFilenames) }, [OVERFLOW_FILE] = { OVERFLOW_FILE, CORPUS_STR(OVERFLOW_FILE), CORPUS_DATA_INIT(overflowFileNames) }, [OVERFLOW_AND_ZERO_FILE] = { OVERFLOW_AND_ZERO_FILE, CORPUS_STR(OVERFLOW_AND_ZERO_FILE), CORPUS_DATA_INIT(overflowAndZeroFileNames) }, [CORPUS_TYPE_EXTENDED] = { CORPUS_TYPE_EXTENDED, CORPUS_STR(CORPUS_TYPE_EXTENDED), CORPUS_DATA_EMPTY }, /*All Corpus type should added above * CORPUS_TYPE_INVALID. */ [CORPUS_TYPE_INVALID] = { CORPUS_TYPE_INVALID, CORPUS_STR(CORPUS_TYPE_INVALID), CORPUS_DATA_EMPTY } }; #define CHECK_CORPUS_TYPE_AND_RETURN(type, status) \ do \ { \ if ((type) < 0 || (type) >= MAX_NUM_CORPUS_TYPE) \ { \ PRINT_ERR("Invalid corpus Type %d\n", corpusType); \ return status; \ } \ } while (0) static CpaStatus populateCorpusInternal(corpus_type_t corpusType) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numFiles = 0, i = 0; char **pCorpusFileNamesArray = NULL; corpus_file_t *pCorpusFile = NULL; CHECK_CORPUS_TYPE_AND_RETURN(corpusType, CPA_STATUS_FAIL); if (corpus[corpusType].corpusData.read == CPA_FALSE) { pCorpusFileNamesArray = corpus[corpusType].corpusData.fileNameArray; numFiles = corpus[corpusType].corpusData.numFilesInCorpus; if (numFiles == 0) { PRINT_ERR("No files in corpus %s. Failed to populate\n", corpus[corpusType].corpusName); return CPA_STATUS_FAIL; } if (pCorpusFileNamesArray == NULL) { PRINT_ERR( "No File Names present for Corpus %s. Failed to populate\n", corpus[corpusType].corpusName); return CPA_STATUS_FAIL; } /* allocate the memory for the corpus file structure */ pCorpusFile = qaeMemAlloc(numFiles * sizeof(corpus_file_t)); if (NULL == pCorpusFile) { PRINT_ERR(" Unable to allocate Memory for " "corpus structure\n"); return CPA_STATUS_FAIL; } for (i = 0; i < numFiles; i++) { switch (corpusType) { default: status = getCorpusFile(&pCorpusFile[i].corpusBinaryData, pCorpusFileNamesArray[i], &pCorpusFile[i].corpusBinaryDataLen); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Get \"%s\" Corpus File Failed\n", pCorpusFileNamesArray[i]); qaeMemFree((void **)&pCorpusFile); return CPA_STATUS_FAIL; } } corpus[corpusType].corpusData.fileArray = pCorpusFile; corpus[corpusType].corpusData.read = CPA_TRUE; } return status; } CpaStatus populateCorpus(Cpa32U buffSize, corpus_type_t corpusType) { return populateCorpusInternal(corpusType); } EXPORT_SYMBOL(populateCorpus); inline Cpa32U getNumFilesInCorpus(corpus_type_t corpusType) { CHECK_CORPUS_TYPE_AND_RETURN(corpusType, 0); return corpus[corpusType].corpusData.numFilesInCorpus; } EXPORT_SYMBOL(getNumFilesInCorpus); inline char **getFileNamesInCorpus(corpus_type_t corpusType) { CHECK_CORPUS_TYPE_AND_RETURN(corpusType, NULL); return corpus[corpusType].corpusData.fileNameArray; } EXPORT_SYMBOL(getFileNamesInCorpus); inline const corpus_file_t *getFilesInCorpus(corpus_type_t corpusType) { if (corpus[corpusType].corpusData.read == CPA_FALSE) { populateCorpusInternal(corpusType); } return corpus[corpusType].corpusData.fileArray; } EXPORT_SYMBOL(getFilesInCorpus); inline const char *getCorpusName(corpus_type_t corpusType) { static const char *unknownCorpus = "UNKNOWN CORPUS"; CHECK_CORPUS_TYPE_AND_RETURN(corpusType, unknownCorpus); return corpus[corpusType].corpusName; } inline const char *getFileNameInCorpus(corpus_type_t corpusType, Cpa32U fileIndex) { static const char *unknownCorpusFile = "UNKNOWN CORPUS FILE"; CHECK_CORPUS_TYPE_AND_RETURN(corpusType, unknownCorpusFile); return corpus[corpusType].corpusData.fileNameArray[fileIndex]; } inline corpus_type_t getCorpusTypeFromName(const char *name, const unsigned long name_max_size) { corpus_type_t type = 0; for (; type < MAX_NUM_CORPUS_TYPE; type++) { if (strncmp(name, corpus[type].corpusName, name_max_size) == 0) { return type; } } return CORPUS_TYPE_INVALID; } void setCorpusType(corpus_type_t type) { extCorpusInfo.corpusType = type; } EXPORT_SYMBOL(setCorpusType); corpus_type_t getCorpusType(void) { return extCorpusInfo.corpusType; } void setCorpusFileIndex(Cpa32U index) { extCorpusInfo.corpusFileIndex = index; } EXPORT_SYMBOL(setCorpusFileIndex); Cpa32U getCorpusFileIndex(void) { return extCorpusInfo.corpusFileIndex; } compute_test_result_func_t getPassCriteria(void) { return pfuncPassCriteria; } void setPassCriteria(compute_test_result_func_t pfunc) { pfuncPassCriteria = pfunc; } EXPORT_SYMBOL(setPassCriteria); Cpa32U getSetupCnVRequestFlag(void) { return setupCnVRequestFlag; } EXPORT_SYMBOL(getSetupCnVRequestFlag); void setSetupCnVRequestFlag(Cpa32U flag) { setupCnVRequestFlag = flag; } EXPORT_SYMBOL(setSetupCnVRequestFlag); CpaStatus startDcServices(Cpa32U buffSize, Cpa32U numBuffs) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U size = 0; Cpa32U i = 0, k = 0; Cpa32U nodeId = 0; Cpa32U nProcessorsOnline = 0; Cpa16U numBuffers = 0; CpaBufferList **tempBufferList = NULL; /*if the service started flag is false*/ if (dc_service_started_g == CPA_FALSE) { /* Get the number of DC Instances */ status = cpaDcGetNumInstances(&numDcInstances_g); /* Check the status */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to Get Number of DC instances\n"); return CPA_STATUS_FAIL; } /* Check if at least one DC instance are present */ if (0 == numDcInstances_g) { PRINT_ERR(" DC Instances are not present\n"); return CPA_STATUS_FAIL; } /* Allocate memory for all the instances */ dcInstances_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * numDcInstances_g); /* Check For NULL */ if (NULL == dcInstances_g) { PRINT_ERR(" Unable to allocate memory for Instances \n"); return CPA_STATUS_FAIL; } /* Get DC Instances */ status = cpaDcGetInstances(numDcInstances_g, dcInstances_g); /* Check Status */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to Get DC instances\n"); qaeMemFree((void **)&dcInstances_g); return CPA_STATUS_FAIL; } /* Allocate the buffer list pointers to the number of Instances * this buffer list list is used only in case of dynamic * compression */ pInterBuffList_g = (CpaBufferList ***)qaeMemAlloc( numDcInstances_g * sizeof(CpaBufferList **)); /* Check For NULL */ if (NULL == pInterBuffList_g) { PRINT_ERR("Unable to allocate dynamic buffer List\n"); qaeMemFree((void **)&dcInstances_g); return CPA_STATUS_FAIL; } /* Initialize memory for buffer lists */ memset( pInterBuffList_g, 0, numDcInstances_g * sizeof(CpaBufferList **)); /* Start the Loop to create Buffer List for each instance*/ for (i = 0; i < numDcInstances_g; i++) { /* get the Node ID for each instance Handle */ status = sampleCodeDcGetNode(dcInstances_g[i], &nodeId); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to get NodeId\n"); qaeMemFree((void **)&dcInstances_g); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } status = cpaDcGetNumIntermediateBuffers(dcInstances_g[i], &numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to allocate Memory for Dynamic Buffer\n"); qaeMemFree((void **)&dcInstances_g); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } if (numBuffers > 0) { /* allocate the buffer list memory for the dynamic Buffers * only applicable for CPM prior to gen4 as it is done in HW */ pInterBuffList_g[i] = qaeMemAllocNUMA(sizeof(CpaBufferList *) * numBuffers, nodeId, BYTE_ALIGNMENT_64); if (NULL == pInterBuffList_g[i]) { PRINT_ERR("Unable to allocate Memory for Dynamic Buffer\n"); qaeMemFree((void **)&dcInstances_g); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } /* get the size of the Private meta data * needed to create Buffer List */ status = cpaDcBufferListGetMetaSize( dcInstances_g[i], numBuffers, &size); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Get Meta Size Data Failed\n"); qaeMemFree((void **)&dcInstances_g); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } } tempBufferList = pInterBuffList_g[i]; for (k = 0; k < numBuffers; k++) { tempBufferList[k] = (CpaBufferList *)qaeMemAllocNUMA( sizeof(CpaBufferList), nodeId, BYTE_ALIGNMENT_64); if (NULL == tempBufferList[k]) { PRINT(" %s:: Unable to allocate memory for " "tempBufferList\n", __FUNCTION__); qaeMemFree((void **)&dcInstances_g); freeDcBufferList(tempBufferList, k + 1); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } tempBufferList[k]->pPrivateMetaData = qaeMemAllocNUMA(size, nodeId, BYTE_ALIGNMENT_64); if (NULL == tempBufferList[k]->pPrivateMetaData) { PRINT(" %s:: Unable to allocate memory for " "pPrivateMetaData\n", __FUNCTION__); qaeMemFree((void **)&dcInstances_g); freeDcBufferList(tempBufferList, k + 1); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } tempBufferList[k]->numBuffers = ONE_BUFFER_DC; /* allocate flat buffers */ tempBufferList[k]->pBuffers = qaeMemAllocNUMA( (sizeof(CpaFlatBuffer)), nodeId, BYTE_ALIGNMENT_64); if (NULL == tempBufferList[k]->pBuffers) { PRINT_ERR("Unable to allocate memory for pBuffers\n"); qaeMemFree((void **)&dcInstances_g); freeDcBufferList(tempBufferList, k + 1); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } tempBufferList[k]->pBuffers[0].pData = qaeMemAllocNUMA( (size_t)expansionFactor_g * EXTRA_BUFFER * buffSize, nodeId, BYTE_ALIGNMENT_64); if (NULL == tempBufferList[k]->pBuffers[0].pData) { PRINT_ERR("Unable to allocate Memory for pBuffers\n"); qaeMemFree((void **)&dcInstances_g); freeDcBufferList(tempBufferList, k + 1); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } tempBufferList[k]->pBuffers[0].dataLenInBytes = expansionFactor_g * EXTRA_BUFFER * buffSize; } /* When starting the DC Instance, the API expects that the * private meta data should be greater than the dataLength */ /* Configure memory Configuration Function */ status = cpaDcSetAddressTranslation( dcInstances_g[i], (CpaVirtualToPhysical)qaeVirtToPhysNUMA); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error setting memory config for instance\n"); qaeMemFree((void **)&dcInstances_g); freeDcBufferList(pInterBuffList_g[i], numBuffers); qaeMemFreeNUMA((void **)&pInterBuffList_g[i]); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } /* Start DC Instance */ status = cpaDcStartInstance( dcInstances_g[i], numBuffers, pInterBuffList_g[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to start DC Instance\n"); qaeMemFree((void **)&dcInstances_g); freeDcBufferList(pInterBuffList_g[i], numBuffers); qaeMemFreeNUMA((void **)&pInterBuffList_g[i]); qaeMemFree((void **)&pInterBuffList_g); return CPA_STATUS_FAIL; } } /*set the started flag to true*/ dc_service_started_g = CPA_TRUE; } /*determine number of cores on system and limit the number of cores to be * used to be the smaller of the numberOf Instances or the number of cores*/ nProcessorsOnline = sampleCodeGetNumberOfCpus(); if (nProcessorsOnline > numDcInstances_g) { setCoreLimit(numDcInstances_g); } return status; } EXPORT_SYMBOL(startDcServices); void freeCorpus(void) { Cpa32U i = 0; corpus_type_t corpusType = 0; Cpa32U numFiles = 0; corpus_file_t *pCorpusFile = NULL; for (; corpusType < MAX_NUM_CORPUS_TYPE; corpusType++) { pCorpusFile = corpus[corpusType].corpusData.fileArray; numFiles = getNumFilesInCorpus(corpusType); if (numFiles == 0 || pCorpusFile == NULL) { continue; } for (i = 0; i < numFiles; i++) { if (NULL != pCorpusFile[i].corpusBinaryData) { qaeMemFree((void **)&pCorpusFile[i].corpusBinaryData); pCorpusFile[i].corpusBinaryData = NULL; } } /* Free corpus File Structure */ qaeMemFree((void **)&pCorpusFile); corpus[corpusType].corpusData.fileArray = NULL; corpus[corpusType].corpusData.read = CPA_FALSE; } return; } /*stop all acceleration services*/ CpaStatus stopDcServices(void) { Cpa32U i = 0, j = 0; CpaStatus status = CPA_STATUS_SUCCESS; CpaBufferList **tempBufferList = NULL; Cpa16U numBuffers = 0; /*stop only if the services is in a started state*/ if (dc_service_started_g == CPA_TRUE) { for (i = 0; i < numDcInstances_g; i++) { /* Free the Dynamic Buffers allocated * while starting DC Services */ tempBufferList = pInterBuffList_g[i]; status = cpaDcGetNumIntermediateBuffers(dcInstances_g[i], &numBuffers); for (j = 0; j < numBuffers; j++) { qaeMemFreeNUMA((void **)&tempBufferList[j]->pBuffers->pData); qaeMemFreeNUMA((void **)&tempBufferList[j]->pPrivateMetaData); qaeMemFreeNUMA((void **)&tempBufferList[j]->pBuffers); qaeMemFreeNUMA((void **)&tempBufferList[j]); } if (NULL != pInterBuffList_g[i]) { /* free the buffer List*/ qaeMemFreeNUMA((void **)&pInterBuffList_g[i]); } /*stop all instances*/ cpaDcStopInstance(dcInstances_g[i]); } qaeMemFree((void **)&pInterBuffList_g); /*set the service started flag to false*/ dc_service_started_g = CPA_FALSE; } /* Free the corpus Data */ freeCorpus(); if (dc_polling_started_g == CPA_TRUE) { /* set polling flag to false */ dc_polling_started_g = CPA_FALSE; /* Wait for all threads_g to complete */ for (i = 0; i < numDcPolledInstances_g; i++) { sampleCodeThreadJoin(&dcPollingThread_g[i]); } if (numDcPolledInstances_g > 0) { qaeMemFree((void **)&dcPollingThread_g); numDcPolledInstances_g = 0; } } if (dcInstances_g != NULL) { qaeMemFree((void **)&dcInstances_g); dcInstances_g = NULL; } return status; } CpaStatus calculateRequireBuffers(compression_test_params_t *dcSetup) { Cpa32U numberOfBuffers = 0, i = 0; Cpa32U numFiles = getNumFilesInCorpus(dcSetup->corpus); const corpus_file_t *const pCorpusFile = getFilesInCorpus(dcSetup->corpus); if (dcSetup->corpusFileIndex >= numFiles) { dcSetup->corpusFileIndex = 0; } dcSetup->numberOfBuffers = qaeMemAlloc(numFiles * sizeof(Cpa32U)); if (NULL == dcSetup->numberOfBuffers) { PRINT("Could not allocate memory for dcSetup numberOfBuffers array"); return CPA_STATUS_FAIL; } for (i = 0; i < numFiles; i++) { /*get number of full sized buffers, ignoring the last bit less than * the full buffer size*/ if (pCorpusFile[i].corpusBinaryDataLen < dcSetup->bufferSize) { PRINT("Warning the input file size(%d) is less than the specified " "buffer size(%d), results may be skewed\n", pCorpusFile[i].corpusBinaryDataLen, dcSetup->bufferSize); numberOfBuffers = 1; } else { numberOfBuffers = pCorpusFile[i].corpusBinaryDataLen / dcSetup->bufferSize; } dcSetup->numberOfBuffers[i] = numberOfBuffers; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(calculateRequireBuffers); CpaStatus dcCreatePollingThreadsIfPollingIsEnabled(void) { CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa16U i = 0, j = 0, numCreatedPollingThreads = 0; Cpa32U coreAffinity = 0; CpaStatus status = CPA_STATUS_SUCCESS; performance_func_t *pollFnArr = NULL; #ifdef SC_CORE_NUM_POLICY Cpa32U numCores = 0; numCores = sampleCodeGetNumberOfCpus(); if (numCores <= 0) { PRINT_ERR("sampleCodeGetNumberOfCpus() failed\n"); return CPA_STATUS_FAIL; } #endif #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) int fd = -1; #endif if (CPA_FALSE == dc_polling_started_g) { instanceInfo2 = qaeMemAlloc(numDcInstances_g * sizeof(CpaInstanceInfo2)); if (NULL == instanceInfo2) { PRINT_ERR("Failed to allocate memory for pInstanceInfo2"); return CPA_STATUS_FAIL; } pollFnArr = qaeMemAlloc(numDcInstances_g * sizeof(performance_func_t)); if (NULL == pollFnArr) { PRINT_ERR("Failed to allocate memory for polling functions\n"); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } for (i = 0; i < numDcInstances_g; i++) { status = cpaDcInstanceGetInfo2(dcInstances_g[i], &instanceInfo2[i]); if (CPA_STATUS_SUCCESS != status) { qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } pollFnArr[i] = NULL; if (CPA_TRUE == instanceInfo2[i].isPolled) { numDcPolledInstances_g++; #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) status = icp_sal_DcGetFileDescriptor(dcInstances_g[i], &fd); if (CPA_STATUS_SUCCESS == status) { pollFnArr[i] = sampleCodeDcEventPoll; icp_sal_DcPutFileDescriptor(dcInstances_g[i], fd); continue; } else if (CPA_STATUS_FAIL == status) { PRINT_ERR("Error getting file descriptor for Event based " "instance #%d\n", i); qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } /* else feature is unsupported and sampleCodeDcPoll() is to be * used. */ #endif pollFnArr[i] = sampleCodeDcPoll; } } if (0 == numDcPolledInstances_g) { qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_SUCCESS; } dcPollingThread_g = qaeMemAlloc(numDcPolledInstances_g * sizeof(sample_code_thread_t)); if (NULL == dcPollingThread_g) { PRINT_ERR("Failed to allocate memory for polling threads\n"); qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } for (i = 0; i < numDcInstances_g; i++) { if (NULL != pollFnArr[i]) { status = sampleCodeThreadCreate( &dcPollingThread_g[numCreatedPollingThreads], NULL, pollFnArr[i], dcInstances_g[i]); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error starting polling thread %d\n", status); /*attempt to stop any started service, we don't check status * as some instances may not have been started and * this might return fail*/ qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } /*loop of the instanceInfo coreAffinity bitmask to find * the core affinity*/ for (j = 0; j < CPA_MAX_CORES; j++) { if (CPA_BITMAP_BIT_TEST(instanceInfo2[i].coreAffinity, j)) { #if defined(USER_SPACE) coreAffinity = j; #else coreAffinity = j + 1; #endif break; } } #ifdef SC_CORE_NUM_POLICY if (numDcInstances_g % numCores == 0) { /* To avoid recalculated and original core * assignment equality */ coreAffinity = (coreAffinity + numDcInstances_g + 1) % numCores; } else { coreAffinity = (coreAffinity + numDcInstances_g) % numCores; } #endif sampleCodeThreadBind( &dcPollingThread_g[numCreatedPollingThreads], coreAffinity); sampleCodeThreadStart( &dcPollingThread_g[numCreatedPollingThreads]); numCreatedPollingThreads++; } } qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); dc_polling_started_g = CPA_TRUE; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(dcCreatePollingThreadsIfPollingIsEnabled); inline CpaStatus dcDpPollNumOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations) { Cpa32U retries; return dcDpPollNumOperationsRetries( pPerfData, instanceHandle, numOperations, &retries); } CpaStatus dcDpPollNumOperationsRetries(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations, Cpa32U *retries) { CpaStatus status = CPA_STATUS_FAIL; perf_cycles_t startCycles = 0, totalCycles = 0; Cpa32U freq = sampleCodeGetCpuFreq(); CpaInstanceInfo2 info2 = { 0 }; *retries = 0; startCycles = sampleCodeTimestamp(); status = cpaDcInstanceGetInfo2(instanceHandle, &info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInstanceGetInfo2 failed. (status = %d)\n", status); return status; } while (pPerfData->responses != numOperations) { if (CPA_TRUE == info2.isPolled) { coo_poll_dp_dc(pPerfData, instanceHandle, &status); /* in case when polling is used to process request's response which is not handled by coo measurement */ if (CPA_STATUS_FAIL == status) status = icp_sal_DcPollDpInstance(instanceHandle, 0); } if (CPA_STATUS_FAIL == status) { PRINT_ERR("Error polling instance\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_RETRY == status) { (*retries)++; AVOID_SOFTLOCKUP; } totalCycles = (sampleCodeTimestamp() - startCycles); if (totalCycles > 0) { do_div(totalCycles, freq); } if (totalCycles > SAMPLE_CODE_WAIT_DEFAULT) { PRINT_ERR("Timeout on polling remaining Operations\n"); PRINT("Expected %llu responses, revieved %llu\n", (unsigned long long)numOperations, (unsigned long long)pPerfData->responses); return CPA_STATUS_FAIL; } } return CPA_STATUS_SUCCESS; } /* If an error has occurred in-between the submissions loop, * wait for all in-flight requests has been processed. * Post this function, memory resources that are used by the * SAL library are de-allocated. */ CpaStatus waitForInflightRequestAfterError(perf_data_t *perfData) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U tryLoops = 0; /* Give 3 tries to collect all the responses while waiting on the * semaphore. The ASYNC callback should release the semaphore * only when the responses are equal to expected number of operation. * If an error occurs in between, the subsequent submission of requests * is stopped and hence the response will always be less than expected * number of operation, meaning the semaphore is never released by the * callback function. Hence it should be timing out always here. */ while ((perfData->responses < perfData->submissions) && tryLoops < 3) { status = sampleCodeSemaphoreWait(&perfData->comp, SAMPLE_CODE_WAIT_DEFAULT); tryLoops++; } if (perfData->responses < perfData->submissions) { PRINT_ERR("WARNING: Not all in-flight requests collected! " "Submissions: %u, Responses: %llu\n", perfData->submissions, (unsigned long long)perfData->responses); if (status == CPA_STATUS_SUCCESS) { PRINT_ERR(" \tWait Semaphore released!\n"); } return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus waitForSemaphore(perf_data_t *perfData) { Cpa64S responsesReceived = INITIAL_RESPONSE_COUNT; CpaStatus status = CPA_STATUS_SUCCESS; /*wait for the callback to receive all responses and free the * semaphore, or if in sync mode, the semaphore should already be free*/ while (sampleCodeSemaphoreWait(&perfData->comp, SAMPLE_CODE_WAIT_DEFAULT) != CPA_STATUS_SUCCESS) { if (INITIAL_RESPONSE_COUNT != responsesReceived && responsesReceived != (Cpa64S)perfData->numOperations && responsesReceived == (Cpa64S)perfData->responses) { PRINT_ERR("System is not responding\n"); PRINT("Responses expected/received: %llu/%llu\n", (unsigned long long)perfData->numOperations, (unsigned long long)perfData->responses); status = CPA_STATUS_FAIL; break; } else { responsesReceived = perfData->responses; } } return status; } EXPORT_SYMBOL(waitForSemaphore); CpaStatus sampleCodeDcGetNode(CpaInstanceHandle instanceHandle, Cpa32U *node) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceInfo2 pInstanceInfo2; status = cpaDcInstanceGetInfo2(instanceHandle, &pInstanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to get Node affinity\n"); return status; } *node = pInstanceInfo2.nodeAffinity; return status; } EXPORT_SYMBOL(sampleCodeDcGetNode); /* Change to a compression callback tag with parameter for poll interval */ void sampleCodeDcPoll(CpaInstanceHandle instanceHandle_in) { CpaStatus status = CPA_STATUS_FAIL; #ifdef USER_SPACE struct timespec reqTime, remTime; reqTime.tv_sec = 0; reqTime.tv_nsec = dcPollingThreadsInterval_g; #endif while (dc_service_started_g == CPA_TRUE) { /*poll for 0 means process all packets on the ET ring */ status = icp_sal_DcPollInstance(instanceHandle_in, 0); if (CPA_STATUS_SUCCESS == status || CPA_STATUS_RETRY == status) { /* do nothing */ } else { PRINT_ERR("ERROR icp_sal_DcPollInstance returned status %d\n", status); error_flag_g = CPA_TRUE; break; } #ifdef USER_SPACE nanosleep(&reqTime, &remTime); #else sampleCodeSleepMilliSec(DEFAULT_POLL_INTERVAL_KERNEL); #endif } sampleCodeThreadExit(); } CpaStatus stopDcServicesFromPrintStats(thread_creation_data_t *dummy_ptr) { CpaStatus status = CPA_STATUS_SUCCESS; /* stop DC Services */ status = stopDcServices(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to stop DC services\n"); } return status; } EXPORT_SYMBOL(stopDcServicesFromPrintStats); CpaStatus dcPrintStats(thread_creation_data_t *data) { perf_cycles_t numOfCycles = {0}; perf_data_t stats = {0}; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; Cpa32U throughput = 0; Cpa32U bytesConsumed = 0, bytesProduced = 0; Cpa32U averageNumLoops = 0; compression_test_params_t *dcSetup = (compression_test_params_t *)data->setupPtr; Cpa32U numberOfUnsupportedThreads = 0; Cpa32U totalThreadsRan = 0; /* stop DC Services */ status = stopDcServices(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to stop DC services\n"); return status; } memset(&stats, 0, sizeof(perf_data_t)); stats.averagePacketSizeInBytes = data->packetSize; /* get the longest start time and longest End time * from the performance stats structure */ getLongestCycleCount(&stats, data->performanceStats, data->numberOfThreads); /* Get the total number of responses, bytes consumed and bytes produced * for all the threads */ for (i = 0; i < data->numberOfThreads; i++) { if (CPA_STATUS_UNSUPPORTED == data->performanceStats[i]->threadReturnStatus) { numberOfUnsupportedThreads++; } else if (CPA_STATUS_FAIL == data->performanceStats[i]->threadReturnStatus) { return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == data->performanceStats[i]->threadReturnStatus) { if (!signOfLife) { if (latency_enable) { /* Accumulate over all tests. Before using later we divide * by number of threads: data->numberOfThreads*/ stats.minLatency += data->performanceStats[i]->minLatency; stats.aveLatency += data->performanceStats[i]->aveLatency; stats.maxLatency += data->performanceStats[i]->maxLatency; } if (latency_debug) { /* NOTE: These numbers are in CPU cycles here */ PRINT(", minLatency: %llu, aveLatency: %llu, maxLatency: %llu", data->performanceStats[i]->minLatency, data->performanceStats[i]->aveLatency, data->performanceStats[i]->maxLatency); PRINT("\n"); } } if (iaCycleCount_g) { stats.offloadCycles += data->performanceStats[i]->offloadCycles; } averageNumLoops += data->performanceStats[i]->numLoops; stats.retries += data->performanceStats[i]->retries; stats.responses += data->performanceStats[i]->responses; bytesConsumed += data->performanceStats[i]->bytesConsumedPerLoop; bytesProduced += data->performanceStats[i]->bytesProducedPerLoop; dcSetup->numLoops = data->performanceStats[i]->numLoops; clearPerfStats(data->performanceStats[i]); } } totalThreadsRan = data->numberOfThreads - numberOfUnsupportedThreads; /* get the maximum number of cycles Required */ numOfCycles = (stats.endCyclesTimestamp - stats.startCyclesTimestamp); /*don't assume that all threads submitted all loops * if the averageNumLoops does not equal the plan then that means * the thread exited early, so we need to use the average to calculate the * throughput*/ if (totalThreadsRan != 0) { do_div(averageNumLoops, totalThreadsRan); } if (averageNumLoops != dcSetup->numLoops) { dcSetup->numLoops = averageNumLoops; } /* Print Statistics */ dcPrintTestData(dcSetup); PRINT("Number of threads %d\n", data->numberOfThreads); if (numberOfUnsupportedThreads) { PRINT("Unsupported Threads %u\n", numberOfUnsupportedThreads); } PRINT("Total Threads ran %u\n", totalThreadsRan); PRINT("Total Responses %llu\n", (unsigned long long)stats.responses); PRINT("Total Retries %llu\n", (unsigned long long)stats.retries); PRINT("Clock Cycles Start %llu\n", stats.startCyclesTimestamp); PRINT("Clock Cycles End %llu\n", stats.endCyclesTimestamp); if (!signOfLife) { PRINT("Total Cycles %llu\n", numOfCycles); PRINT("CPU Frequency(kHz) %u\n", sampleCodeGetCpuFreq()); throughput = getDcThroughput(bytesConsumed, numOfCycles, dcSetup->numLoops); { PRINT("Throughput(Mbps) %u\n", throughput); } dcCalculateAndPrintCompressionRatio(bytesConsumed, bytesProduced); if (iaCycleCount_g && (totalThreadsRan != 0)) { do_div(stats.offloadCycles, totalThreadsRan); PRINT("Avg Offload Cycles %llu\n", stats.offloadCycles); } if (latency_enable && (totalThreadsRan != 0)) { perf_cycles_t statsLatency = 0; perf_cycles_t cpuFreqKHz = sampleCodeGetCpuFreq(); /* Display how long it took on average to process a buffer in uSecs * Also include min/max to show variance */ do_div(stats.minLatency, totalThreadsRan); statsLatency = 1000 * stats.minLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Min. Latency (uSecs) %llu\n", statsLatency); do_div(stats.aveLatency, totalThreadsRan); statsLatency = 1000 * stats.aveLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Ave. Latency (uSecs) %llu\n", statsLatency); do_div(stats.maxLatency, totalThreadsRan); statsLatency = 1000 * stats.maxLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Max. Latency (uSecs) %llu\n", statsLatency); } } return status; } EXPORT_SYMBOL(dcPrintStats); #ifdef SC_CHAINING_ENABLED CpaStatus dcChainPrintStats(thread_creation_data_t *data) { perf_cycles_t numOfCycles = {0}; perf_data_t stats = {0}; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; Cpa32U throughput = 0, currentThroughput = 0; Cpa32U bytesConsumed = 0, bytesProduced = 0; Cpa32U averageNumLoops = 0; compression_test_params_t *dcSetup = (compression_test_params_t *)data->setupPtr; /* stop DC Services */ status = stopDcServices(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to stop DC services\n"); return status; } memset(&stats, 0, sizeof(perf_data_t)); stats.averagePacketSizeInBytes = data->packetSize; /* get the longest start time and longest End time * from the performance stats structure */ getLongestCycleCount(&stats, data->performanceStats, data->numberOfThreads); /* Get the total number of responses, bytes consumed and bytes produced * for all the threads */ for (i = 0; i < data->numberOfThreads; i++) { if (CPA_STATUS_FAIL == data->performanceStats[i]->threadReturnStatus) { return CPA_STATUS_FAIL; } if (!signOfLife) { numOfCycles = data->performanceStats[i]->endCyclesTimestamp - data->performanceStats[i]->startCyclesTimestamp; throughput = getDcThroughput(data->performanceStats[i]->bytesConsumedPerLoop, numOfCycles, data->performanceStats[i]->numLoops); PRINT( "Thread: %u, Retries: %llu, throughput: %u, consumedPerLoop %u,\ numLoops %u", i, (unsigned long long)data->performanceStats[i]->retries, throughput, data->performanceStats[i]->bytesConsumedPerLoop, data->performanceStats[i]->numLoops); if (latency_enable) { /* NOTE: These numbers are in CPU cycles here */ PRINT(", minLatency: %llu, aveLatency: %llu, maxLatency: %llu", data->performanceStats[i]->minLatency, data->performanceStats[i]->aveLatency, data->performanceStats[i]->maxLatency); /* Accumulate over all tests. Before using later we divide * by number of threads: data->numberOfThreads*/ stats.minLatency += data->performanceStats[i]->minLatency; stats.aveLatency += data->performanceStats[i]->aveLatency; stats.maxLatency += data->performanceStats[i]->maxLatency; } PRINT("\n"); } averageNumLoops += data->performanceStats[i]->numLoops; stats.retries += data->performanceStats[i]->retries; stats.responses += data->performanceStats[i]->responses; bytesConsumed += data->performanceStats[i]->bytesConsumedPerLoop; bytesProduced += data->performanceStats[i]->bytesProducedPerLoop; dcSetup->numLoops = data->performanceStats[i]->numLoops; currentThroughput += data->performanceStats[i]->currentThroughput; clearPerfStats(data->performanceStats[i]); } /* get the maximum number of cycles Required */ numOfCycles = (stats.endCyclesTimestamp - stats.startCyclesTimestamp); /*don't assume that all threads submitted all loops * if the averageNumLoops does not equal the plan then that means * the thread exited early, so we need to use the average to calculate the * throughput*/ if (data->numberOfThreads != 0) { do_div(averageNumLoops, data->numberOfThreads); } if (averageNumLoops != dcSetup->numLoops) { dcSetup->numLoops = averageNumLoops; } /* Print Statistics */ dcChainPrintTestData(dcSetup); PRINT("Number of threads %d\n", data->numberOfThreads); PRINT("Total Responses %llu\n", (unsigned long long)stats.responses); PRINT("Total Retries %llu\n", (unsigned long long)stats.retries); PRINT("Clock Cycles Start %llu\n", stats.startCyclesTimestamp); PRINT("Clock Cycles End %llu\n", stats.endCyclesTimestamp); if (!signOfLife) { PRINT("Total Cycles %llu\n", numOfCycles); PRINT("CPU Frequency(kHz) %u\n", sampleCodeGetCpuFreq()); throughput = getDcThroughput(bytesConsumed, numOfCycles, dcSetup->numLoops); if (sleepTime_enable) { PRINT("Throughput(Mbps) %u\n", currentThroughput); } else { PRINT("Throughput(Mbps) %u\n", throughput); } dcCalculateAndPrintCompressionRatio(bytesConsumed, bytesProduced); if (latency_enable && (data->numberOfThreads != 0)) { perf_cycles_t statsLatency = 0; perf_cycles_t cpuFreqKHz = sampleCodeGetCpuFreq(); /* Display how long it took on average to process a buffer in uSecs * Also include min/max to show variance */ do_div(stats.minLatency, data->numberOfThreads); statsLatency = 1000 * stats.minLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Min. Latency (uSecs) %llu\n", statsLatency); do_div(stats.aveLatency, data->numberOfThreads); statsLatency = 1000 * stats.aveLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Ave. Latency (uSecs) %llu\n", statsLatency); do_div(stats.maxLatency, data->numberOfThreads); statsLatency = 1000 * stats.maxLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Max. Latency (uSecs) %llu\n", statsLatency); } } return status; } EXPORT_SYMBOL(dcChainPrintStats); #endif void dcPrintTestData(compression_test_params_t *dcSetup) { PRINT("API "); if (dcSetup->isDpApi) { PRINT("Data_Plane\n"); } else { PRINT("Traditional\n"); } PRINT("Session State "); switch (dcSetup->setupData.sessState) { case (CPA_DC_STATEFUL): PRINT("STATEFUL\n"); break; case (CPA_DC_STATELESS): PRINT("STATELESS\n"); break; default: PRINT("Unsupported %d\n", dcSetup->setupData.sessState); break; } PRINT("Algorithm "); switch (dcSetup->setupData.compType) { case (CPA_DC_DEFLATE): PRINT("DEFLATE\n"); break; #if DC_API_VERSION_AT_LEAST(3, 1) case (CPA_DC_LZ4): PRINT("CPA_DC_LZ4\n"); break; case (CPA_DC_LZ4S): PRINT("CPA_DC_LZ4S\n"); break; #endif default: PRINT("Unsupported %d\n", dcSetup->setupData.compType); break; } PRINT("Huffman Type "); switch (dcSetup->setupData.huffType) { case (CPA_DC_HT_STATIC): PRINT("STATIC\n"); break; case (CPA_DC_HT_FULL_DYNAMIC): PRINT("DYNAMIC\n"); break; default: PRINT("Unsupported %d\n", dcSetup->setupData.huffType); break; } PRINT("Mode "); switch (dcSetup->syncFlag) { case (SYNC): PRINT("SYNCHRONOUS\n"); break; case (ASYNC): PRINT("ASYNCHRONOUS\n"); break; default: PRINT("Unsupported %d\n", dcSetup->syncFlag); break; } if ((CPA_DC_STATELESS == dcSetup->setupData.sessState) && (CPA_DC_DIR_COMPRESS == dcSetup->dcSessDir)) { PRINT("CNV Enabled "); switch (dcSetup->requestOps.compressAndVerify) { case (CPA_TRUE): PRINT("YES\n"); break; case (CPA_FALSE): PRINT("NO\n"); break; default: PRINT("Not known\n"); break; } } PRINT("Direction "); switch (dcSetup->dcSessDir) { case (CPA_DC_DIR_COMPRESS): PRINT("COMPRESS"); break; case (CPA_DC_DIR_DECOMPRESS): PRINT("DECOMPRESS"); break; case (CPA_DC_DIR_COMBINED): PRINT("COMBINED"); break; default: PRINT("Unsupported %d\n", dcSetup->setupData.sessDirection); break; } if (useZlib_g) { PRINT("(from SW lib compressed data)\n"); } else { PRINT("\n"); } if (dcSetup->isUseSGL) { PRINT("Packet Size %d x %d\n", dcSetup->numFlatsPerSGL, dcSetup->bufferSize); } else { PRINT("Packet Size %d\n", dcSetup->bufferSize); } PRINT("Compression Level %d\n", dcSetup->setupData.compLevel); PRINT("Corpus "); PRINT("%s\n", getCorpusName(dcSetup->corpus)); PRINT("Corpus Filename "); PRINT("%s\n", getFileNameInCorpus(dcSetup->corpus, dcSetup->corpusFileIndex)); #if DC_API_VERSION_AT_LEAST(2, 2) PRINT("CNV Recovery Enabled "); switch (CNV_RECOVERY(&dcSetup->requestOps)) { case (CPA_TRUE): PRINT("YES\n"); break; case (CPA_FALSE): PRINT("NO\n"); break; default: PRINT("Not known\n"); break; } #endif } EXPORT_SYMBOL(dcPrintTestData); #if defined(SC_CHAINING_ENABLED) || defined(SC_CHAINING_EXT_ENABLED) void dcChainPrintTestData(compression_test_params_t *chainSetup) { PRINT("API "); if (chainSetup->isDpApi) { PRINT("Data_Plane\n"); } else { PRINT("Traditional\n"); } PRINT("Algorithm Chaining "); switch (chainSetup->chainOperation) { case (CPA_DC_CHAIN_HASH_THEN_COMPRESS): if (chainSetup->symSetupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SHA1 && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_STATIC) { PRINT("SHA1 Stateless Static Compression Chaining\n"); } else if (chainSetup->symSetupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SHA224 && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_STATIC) { PRINT("SHA2-224 Stateless Static Compression Chaining\n"); } else if (chainSetup->symSetupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SHA256 && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_STATIC) { PRINT("SHA2-256 Stateless Static Compression Chaining\n"); } else if (chainSetup->symSetupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SHA1 && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("SHA1 Stateless Dynamic Compression Chaining\n"); } else if (chainSetup->symSetupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SHA224 && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("SHA2-224 Stateless Dynamic Compression Chaining\n"); } else if (chainSetup->symSetupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SHA256 && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("SHA2-256 Stateless Dynamic Compression Chaining\n"); } else { PRINT("Unsupported Algorithm Chaining\n"); } break; case (CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT): if (chainSetup->symSetupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CBC && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_STATIC) { PRINT("Static Stateless Compress AES_CBC Encrypt Chaining\n"); } break; case (CPA_DC_CHAIN_COMPRESS_THEN_AEAD): if (chainSetup->symSetupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("Dynamic Stateless Compress AES_GCM Encrypt Chaining\n"); } break; case (CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS): if (chainSetup->symSetupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM && chainSetup->setupData.sessState == CPA_DC_STATELESS && chainSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("Dynamic Stateless AES_GCM Decrypt Decompression " "Chaining\n"); } break; default: PRINT("Unsupported %d\n", chainSetup->chainOperation); break; } PRINT("Mode "); switch (chainSetup->syncFlag) { case (SYNC): PRINT("SYNCHRONOUS\n"); break; case (ASYNC): PRINT("ASYNCHRONOUS\n"); break; default: PRINT("Unsupported %d\n", chainSetup->syncFlag); break; } if ((CPA_DC_STATELESS == chainSetup->setupData.sessState) && (CPA_DC_DIR_COMPRESS == chainSetup->dcSessDir)) { PRINT("CNV Enabled "); switch (chainSetup->requestOps.compressAndVerify) { case (CPA_TRUE): PRINT("YES\n"); break; case (CPA_FALSE): PRINT("NO\n"); break; default: PRINT("Not known\n"); break; } } PRINT("Direction "); switch (chainSetup->dcSessDir) { case (CPA_DC_DIR_COMPRESS): PRINT("COMPRESS"); break; case (CPA_DC_DIR_DECOMPRESS): PRINT("DECOMPRESS"); break; case (CPA_DC_DIR_COMBINED): PRINT("COMBINED"); break; default: PRINT("Unsupported %d\n", chainSetup->setupData.sessDirection); break; } if (useZlib_g) { PRINT("(from SW lib compressed data)\n"); } else { PRINT("\n"); } PRINT("Packet Size %d\n", chainSetup->bufferSize); PRINT("Compression Level %d\n", chainSetup->setupData.compLevel); PRINT("Corpus "); PRINT("%s\n", getCorpusName(chainSetup->corpus)); PRINT("Corpus Filename "); PRINT("%s\n", getFileNameInCorpus(chainSetup->corpus, chainSetup->corpusFileIndex)); #if (CPA_DC_API_VERSION_NUM_MAJOR > 1) && (CPA_DC_API_VERSION_NUM_MINOR > 1) PRINT("CNV Recovery Enabled "); switch (CNV_RECOVERY(&chainSetup->requestOps)) { case (CPA_TRUE): PRINT("YES\n"); break; case (CPA_FALSE): PRINT("NO\n"); break; default: PRINT("Not known\n"); break; } #endif } EXPORT_SYMBOL(dcChainPrintTestData); #endif void dcDpSetBytesProducedAndConsumed(CpaDcDpOpData ***opdata, perf_data_t *perfData, compression_test_params_t *setup) { Cpa32U i = 0, j = 0, numSamples; Cpa32U numFiles = getNumFilesInCorpus(setup->corpus); for (i = 0; i < numFiles; i++) { if (setup->isUseSGL) numSamples = setup->numberOfSGLs[i]; else numSamples = setup->numberOfBuffers[i]; for (j = 0; j < numSamples; j++) { perfData->bytesConsumedPerLoop += opdata[i][j]->results.consumed; perfData->bytesProducedPerLoop += opdata[i][j]->results.produced; } } } void dcSetBytesProducedAndConsumed(CpaDcRqResults ***cmpResult, perf_data_t *perfData, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; Cpa32U numFiles = getNumFilesInCorpus(setup->corpus); for (i = 0; i < numFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { perfData->bytesConsumedPerLoop += cmpResult[i][j]->consumed; perfData->bytesProducedPerLoop += cmpResult[i][j]->produced; } } } EXPORT_SYMBOL(dcSetBytesProducedAndConsumed); CpaStatus dcCalculateAndPrintCompressionRatio(Cpa32U bytesConsumed, Cpa32U bytesProduced) { #ifdef KERNEL_SPACE Cpa32U ratio = 0, remainder = 0; #endif if (0 == bytesConsumed) { PRINT("Divide by zero error on calculating compression ratio\n"); return CPA_STATUS_FAIL; } #ifdef USER_SPACE PRINT("Compression Ratio %.04f\n", ((float)bytesProduced / bytesConsumed)); return CPA_STATUS_SUCCESS; #else ratio = bytesProduced * SCALING_FACTOR_1000; do_div(ratio, bytesConsumed); remainder = ratio % BASE_10; ratio = bytesProduced * SCALING_FACTOR_100; do_div(ratio, bytesConsumed); PRINT("Compression Ratio 0.%d%d\n", ratio, remainder); return CPA_STATUS_SUCCESS; #endif } Cpa32U getDcThroughput(Cpa32U totalBytes, perf_cycles_t cycles, Cpa32U numOfLoops) { unsigned long long bytesSent = 0; unsigned long long time = cycles; unsigned long long rate = 0; /* declare frequency in kiloHertz*/ Cpa32U freq = sampleCodeGetCpuFreq(); bytesSent = totalBytes; /*get time in milli seconds by dividing numberOfClockCycles by frequency * in kilohertz ie: cycles/(cycles/millsec) = time (mSec) */ do_div(time, freq); /*check that the sample time was not to small*/ if (time == 0) { PRINT_ERR("Sample time is too small to calculate throughput\n"); return 0; } /*set rate to be bytesSent, once we perform the do_div rate changes from * bytes to bytes/milli second or kiloBytes/second*/ rate = bytesSent * numOfLoops; /*rate in kBps*/ do_div(rate, time); /*check that the rate is high enough to convert to Megabits per second*/ if (rate == 0) { PRINT_ERR("no data was sent to calculate throughput\n"); return 0; } /* convert Kilobytes/second to Kilobits/second*/ rate = rate * NUM_BITS_IN_BYTE; /*then convert rate from Kilobits/second to Megabits/second*/ do_div(rate, KILOBITS_IN_MEGABITS); return (Cpa32U)rate; } /*This function tells the compression sample code to use zLib software to * compress the data prior to calling the decompression*/ CpaStatus useZlib(void) { #ifdef USE_ZLIB useZlib_g = CPA_TRUE; #else #endif return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(useZlib); /*This function tells the compression sample code to use zLib software to * compress the data prior to calling the decompression*/ CpaStatus useAccelCompression(void) { useZlib_g = CPA_FALSE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(useAccelCompression); #ifdef ZERO_BYTE_LAST_REQUEST CpaStatus enableZeroByteRequest(void) { zeroByteLastRequest_g = CPA_TRUE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(enableZeroByteRequest); CpaStatus disableZeroByteRequest(void) { zeroByteLastRequest_g = CPA_FALSE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(disableZeroByteRequest); #endif /***************************************************************************** * * @description * Poll the number of dc operations * ***************************************************************************/ CpaStatus dcPollNumOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations) { CpaStatus status = CPA_STATUS_FAIL; perf_cycles_t startCycles = 0, totalCycles = 0; Cpa32U freq = sampleCodeGetCpuFreq(); startCycles = sampleCodeTimestamp(); while (pPerfData->responses != numOperations) { coo_poll_trad_dc(pPerfData, instanceHandle, &status); if (CPA_STATUS_FAIL == status) { PRINT_ERR("Error polling instance\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_RETRY == status) { AVOID_SOFTLOCKUP; } totalCycles = (sampleCodeTimestamp() - startCycles); if (totalCycles > 0) { do_div(totalCycles, freq); } if (totalCycles > SAMPLE_CODE_WAIT_DEFAULT) { PRINT_ERR("Timeout on polling remaining Operations\n"); return CPA_STATUS_FAIL; } } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(dcPollNumOperations); CpaStatus dynamicHuffmanEnabled(CpaInstanceHandle *dcInstanceHandle, CpaBoolean *isEnabled) { CpaDcInstanceCapabilities capabilities = {0}; CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle pLocalDcInstanceHandle = NULL; Cpa16U numInstances = 0; /* Initialize to CPA_FALSE */ *isEnabled = CPA_FALSE; if (NULL == dcInstanceHandle) { status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to check if dynamic Huffman is enabled, " "cpaDcGetNumInstances failed with status: %d\n", status); return CPA_STATUS_FAIL; } if (0 == numInstances) { PRINT_ERR("Unable to check if dynamic Huffman is enabled, " "No DC instances available"); return CPA_STATUS_FAIL; } status = cpaDcGetInstances(1, &pLocalDcInstanceHandle); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to check if dynamic Huffman is enabled, " "cpaDcGetInstances failed with status: %d" "\n", status); return CPA_STATUS_FAIL; } } else { pLocalDcInstanceHandle = *dcInstanceHandle; } status = cpaDcQueryCapabilities(pLocalDcInstanceHandle, &capabilities); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to check if dynamic Huffman is enabled, " "cpaDcQueryCapabilities failed with status: %d" "\n", status); return CPA_STATUS_FAIL; } if (CPA_TRUE == capabilities.dynamicHuffman) { *isEnabled = CPA_TRUE; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(dynamicHuffmanEnabled); CpaStatus dcSampleCreateStatefulContextBuffer(Cpa32U buffSize, Cpa32U metaSize, CpaBufferList **pBuffListArray, Cpa32U nodeId) { CpaStatus status = CPA_STATUS_SUCCESS; *pBuffListArray = qaeMemAllocNUMA((sizeof(CpaBufferList)), nodeId, BYTE_ALIGNMENT_64); if (NULL == (*pBuffListArray)) { PRINT_ERR(" Unable to allocate Buffers List Array\n"); return CPA_STATUS_FAIL; } (*pBuffListArray)->numBuffers = ONE_BUFFER_DC; (*pBuffListArray)->pBuffers = qaeMemAllocNUMA((sizeof(CpaFlatBuffer)), nodeId, BYTE_ALIGNMENT_64); if (NULL == (*pBuffListArray)->pBuffers) { PRINT_ERR(" Unable to allocate Flat Buffers\n"); qaeMemFreeNUMA((void **)pBuffListArray); return CPA_STATUS_FAIL; } if (metaSize) { (*pBuffListArray)->pPrivateMetaData = (Cpa8U *)qaeMemAllocNUMA(metaSize, nodeId, BYTE_ALIGNMENT_64); if (NULL == (*pBuffListArray)->pPrivateMetaData) { PRINT_ERR(" Unable to allocate pPrivateMetaData Buffers\n"); qaeMemFreeNUMA((void **)&(*pBuffListArray)->pBuffers); qaeMemFreeNUMA((void **)pBuffListArray); return CPA_STATUS_FAIL; } } else { (*pBuffListArray)->pPrivateMetaData = NULL; } /* Allocate Flat buffer for each buffer List */ (*pBuffListArray)->pBuffers->dataLenInBytes = buffSize; if (0 == buffSize) { (*pBuffListArray)->pBuffers->pData = NULL; } else { (*pBuffListArray)->pBuffers->pData = qaeMemAllocNUMA(buffSize, nodeId, BYTE_ALIGNMENT_64); if (NULL == (*pBuffListArray)->pBuffers->pData) { PRINT(" Unable to allocate Flat buffer\n"); qaeMemFreeNUMA((void **)&(*pBuffListArray)->pPrivateMetaData); qaeMemFreeNUMA((void **)&(*pBuffListArray)->pBuffers); qaeMemFreeNUMA((void **)pBuffListArray); return CPA_STATUS_FAIL; } memset((*pBuffListArray)->pBuffers->pData, 0, buffSize); } return status; } EXPORT_SYMBOL(dcSampleCreateStatefulContextBuffer); CpaStatus dcSampleFreeStatefulContextBuffer3(CpaBufferList *pBuffListArray) { CpaStatus status = CPA_STATUS_SUCCESS; if (NULL == pBuffListArray) { PRINT_ERR(" Buffers List Array is NULL\n"); /* Return Silent */ return CPA_STATUS_FAIL; } if (NULL != pBuffListArray->pPrivateMetaData) { qaeMemFreeNUMA((void **)&pBuffListArray->pPrivateMetaData); } if (NULL != pBuffListArray->pBuffers) { if (NULL != pBuffListArray->pBuffers->pData) { qaeMemFreeNUMA((void **)&pBuffListArray->pBuffers->pData); } qaeMemFreeNUMA((void **)&pBuffListArray->pBuffers); } if (NULL != pBuffListArray) { qaeMemFreeNUMA((void **)&pBuffListArray); } return status; } void freeBuffers(CpaBufferList ***pBuffListArray, Cpa32U numberOfFiles, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; if (NULL == pBuffListArray) { /* Return Silent */ return; } if (0 != numberOfFiles) { for (i = 0; i < numberOfFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { if (NULL != pBuffListArray[i][j]->pBuffers->pData) { qaeMemFreeNUMA( (void **)&pBuffListArray[i][j]->pBuffers->pData); if (NULL != pBuffListArray[i][j]->pBuffers->pData) { PRINT( "Could not free bufferList[%d][%d]->pData\n", i, j); } } if (NULL != pBuffListArray[i][j]->pPrivateMetaData) { qaeMemFreeNUMA( (void **)&pBuffListArray[i][j]->pPrivateMetaData); if (NULL != pBuffListArray[i][j]->pPrivateMetaData) { PRINT("Could not free " "bufferList[%d][%d]->pPrivateMetaData\n", i, j); } } if (NULL != pBuffListArray[i][j]->pBuffers) { qaeMemFree((void **)&pBuffListArray[i][j]->pBuffers); if (NULL != pBuffListArray[i][j]->pBuffers) { PRINT("Could not free bufferList[%d][%d]->pBuffers\n", i, j); } } if (NULL != pBuffListArray[i][j]) { qaeMemFree((void **)&pBuffListArray[i][j]); if (NULL != pBuffListArray[i][j]) { PRINT("Could not free bufferList[%d][%d]\n", i, j); } } } if (NULL != pBuffListArray[i]) { qaeMemFree((void **)&pBuffListArray[i]); if (NULL != pBuffListArray[i]) { PRINT("Could not free bufferList[%d]\n", i); } } } } qaeMemFree((void **)&pBuffListArray); if (NULL != pBuffListArray) { PRINT("Could not free bufferList\n"); } return; } CpaStatus createBuffers(Cpa32U buffSize, Cpa32U numBuffs, CpaBufferList **pBuffListArray, Cpa32U nodeId) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; for (i = 0; i < numBuffs; i++) { pBuffListArray[i] = qaeMemAlloc(sizeof(CpaBufferList)); if (NULL == pBuffListArray[i]) { PRINT_ERR("Unable to allocate pBuffListArray[%d]\n", i); return CPA_STATUS_FAIL; } pBuffListArray[i]->pBuffers = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pBuffListArray[i]->pBuffers) { PRINT_ERR("Unable to allocate pBuffListArray[%d]->pBuffers\n", i); return CPA_STATUS_FAIL; } /* Allocate Flat buffer for each buffer List */ pBuffListArray[i]->pBuffers->dataLenInBytes = buffSize; pBuffListArray[i]->pBuffers->pData = qaeMemAllocNUMA(buffSize, nodeId, BYTE_ALIGNMENT_64); if (NULL == pBuffListArray[i]->pBuffers->pData) { PRINT_ERR("Unable to allocate pBuffListArray[%d]->pBuffers.pData\n", i); return CPA_STATUS_FAIL; } memset(pBuffListArray[i]->pBuffers->pData, 0, buffSize); pBuffListArray[i]->numBuffers = ONE_BUFFER_DC; } return status; } void freeResults(CpaDcRqResults ***ppDcResult, Cpa32U numFiles, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; if (NULL == ppDcResult) { /* Return Silent */ return; } if (0 != numFiles) { for (i = 0; i < numFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { if (NULL != ppDcResult[i][j]) { qaeMemFree((void **)&ppDcResult[i][j]); } } if (NULL != ppDcResult[i]) { qaeMemFree((void **)&ppDcResult[i]); } } } qaeMemFree((void **)&ppDcResult); } void freeCbTags(dc_callbacktag_t ***callbackTag, Cpa32U numFiles, compression_test_params_t *setup) { Cpa32U i = 0, j = 0; if (NULL == callbackTag) { /* Return Silent */ return; } if (0 != numFiles) { for (i = 0; i < numFiles; i++) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { if (NULL != callbackTag[i][j]) { qaeMemFreeNUMA((void **)&callbackTag[i][j]); } } if (NULL != callbackTag[i]) { qaeMemFreeNUMA((void **)&callbackTag[i]); } } } qaeMemFreeNUMA((void **)&callbackTag); } CpaStatus sampleRemoveDcDpSession(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa16U retries = 0; Cpa32U delay = REMOVE_SESSION_WAIT; /* * We do a incremental sleep starting from 50 micro secs and * by incrementing the sleep time by twice the previous value * for each retry. Total sleep time would be 1.6 secs * for 15 number of retries which would be enough for all * in-flight requests to get processed. */ do { status = cpaDcDpRemoveSession(dcInstance, pSessionHandle); delay *= 2; sleepNano(delay * 1000); } while ((CPA_STATUS_RETRY == status) && (MAX_SESSION_REMOVE_RETRIES >= ++retries)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Remove session failed with status %d\n", status); status = CPA_STATUS_FAIL; } return status; } EXPORT_SYMBOL(sampleRemoveDcDpSession); cpa_sample_code_dc_utils.h000066400000000000000000000562521503624047500371160ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_dc_utils.h * * @defgroup compressionThreads * * @ingroup compressionThreads * * @description * Contains function prototypes and #defines used throughout code * and macros * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_DC_UTILS_H_ #define CPA_SAMPLE_CODE_DC_UTILS_H_ #include "cpa_sample_code_dc_perf.h" #include "cpa.h" #include "cpa_dc.h" #include "cpa_dc_dp.h" #include "cpa_sample_code_framework.h" #include "qat_compression_cnv_utils.h" #ifdef USER_SPACE #include "zlib.h" #else #include #include #include #include #include #endif /* Common macro definitions */ #ifndef DC_API_VERSION_AT_LEAST #define DC_API_VERSION_AT_LEAST(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR > major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR >= minor)) #endif #define DC_API_VERSION_LESS_THAN(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR < major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR < minor)) #define TEMP_NUM_BUFFS (5) #define MIN_BUFFER_SIZE (15) #define KILOBITS_IN_MEGABITS (1000) #define OPERATIONS_POLLING_INTERVAL (10) extern Cpa32U dcPollingInterval_g; extern CpaBoolean gUseStatefulLite; extern CpaDcChecksum gChecksum; extern CpaDcAutoSelectBest gAutoSelectBestMode; extern CpaBoolean testOverFlow_g; extern volatile CpaBoolean dc_service_started_g; extern CpaBoolean gRetainPartials; extern CpaBoolean disableAdditionalCmpbufferSize_g; extern volatile CpaBoolean enableDcDpFlatsToSGLConv_g; extern volatile Cpa32U dcDpNumFlatsPerSGL_g; #if DC_API_VERSION_AT_LEAST(3, 2) extern volatile Cpa32U dcDpPartialReadBufferMask_g; extern volatile CpaBoolean dcDpEnableZeroPad_g; #define IS_PARTREAD_TEST() \ ((dcDpPartialReadBufferMask_g > 0) ? CPA_TRUE : CPA_FALSE) #define IS_ZEROPAD_TEST() (dcDpEnableZeroPad_g) #endif /* DC_API_VERSION_AT_LEAST(3, 2) */ extern Cpa32U getThroughput(Cpa64U numPackets, Cpa32U packetSize, perf_cycles_t cycles); #if DC_API_VERSION_AT_LEAST(3, 1) extern volatile CpaBoolean LZ4BlockIndependence_g; #endif void dcPerformCallback(void *pCallbackTag, CpaStatus status); void dcReadPerformCallback(void *pCallbackTag, CpaStatus status); CpaStatus setAutoSelectBestMode(CpaDcAutoSelectBest mode); CpaStatus disableAdditionalCmpbufferSize(CpaBoolean value); CpaStatus compareBuffers2(CpaBufferList ***ppSrc, CpaBufferList ***ppDst, CpaBufferList ***ppComp, compression_test_params_t *setup); /* corpus Data structure */ extern CpaBoolean useZlib_g; extern Cpa32U expansionFactor_g; extern CpaDcHuffType huffmanType_g; #ifdef ZERO_BYTE_LAST_REQUEST extern CpaBoolean zeroByteLastRequest_g; CpaStatus enableZeroByteRequest(void); CpaStatus disableZeroByteRequest(void); #endif /* Used by ZLIB */ #define DEFLATE_DEF_LEVEL (Z_DEFAULT_COMPRESSION) #define DEFLATE_DEF_WINBITS (15) #define DEFLATE_DEF_MEMLEVEL (8) #define CPA_CRC64_POLYNOMIAL1 0x42F0E1EBA9EA3693ULL #define CPA_CRC64_POLYNOMIAL2 0x9A6C9329AC4BC9B5ULL #define CPA_CRC32_POLYNOMIAL1 (((Cpa64U)(0x04c11db7)) << 32) #define CPA_CRC32_POLYNOMIAL2 (((Cpa64U)(0x1EDC6F41)) << 32) #define CPA_CRC64_XOROUT_0 0x0ULL #define CPA_CRC64_XOROUT_1 0xFFFFFFFFFFFFFFFFULL #define CPA_CRC64_XOROUT_2 0x9465776698231213ULL #define CPA_CRC32_XOROUT_1 (((Cpa64U)(0xffffffff)) << 32) #define CPA_CRC32_XOROUT_2 ((Cpa64U)(0xffffffff)) #define CPA_CRC64_INITIAL_VALUE_0 0x0ULL #define CPA_CRC64_INITIAL_VALUE_1 0x6386926455673254ULL #define CPA_CRC32_INITIAL_VALUE_1 (((Cpa64U)(0xffffffff)) << 32) #define CHECK_AND_STOPDCSERVICES() \ if (dc_service_started_g == CPA_TRUE) \ { \ stopDcServices(); \ } #ifndef DO_CRYPTO /** ***************************************************************************** * @ingroup compressionThreads * getThroughput * * @description * get the throughput in Megabits per second * =(numPackets*packetSize)*(cycles/cpu_frequency) *****************************************************************************/ Cpa32U getThroughput(Cpa64U numPackets, Cpa32U packetSize, perf_cycles_t cycles); #endif /** * ***************************************************************************** * @ingroup compressionThreads * populateCorpus * * @description * this API populates the specified corpus to the corpus data structure * @threadSafe * No * * @param[out] status * * @param[in] buffSize size of the flat buffer * @param[in] corpusType corpus type to load * ******************************************************************************/ CpaStatus populateCorpus(Cpa32U buffSize, corpus_type_t corpusType); /** * ***************************************************************************** * @ingroup compressionThreads * startDcServices * * @description * this API starts the Data compression services if not already started * @threadSafe * No * * * @param[in] buffsize buffer size for intermittent buffers * @param[in] numBuffs number of intermittent Buffers required * ******************************************************************************/ CpaStatus startDcServices(Cpa32U buffSize, Cpa32U numBuffs); /** * ***************************************************************************** * @ingroup compressionThreads * freeCorpus * * @description * this API frees the corpus global data structure. * @threadSafe * No * ******************************************************************************/ void freeCorpus(void); /** * ***************************************************************************** * @ingroup compressionThreads * startDcServices * * @description * this API stops the Data compression services. * @threadSafe * No * ******************************************************************************/ CpaStatus stopDcServices(void); /** * ***************************************************************************** * @ingroup compressionThreads * startDcServices * * @description * this API stops the Data compression services. * @threadSafe * No * @param[in] data pointer to test data structure * ******************************************************************************/ CpaStatus stopDcServicesFromPrintStats(thread_creation_data_t *data); /** * ***************************************************************************** * @ingroup compressionThreads * claculateRequireBuffers * * @description * this API calculates the number of flat buffer required for the corpus * and populates the setup->numberOfBuffers array * @threadSafe * No * * @param[out] status * * @param[in] pointer to compression_test_params_t * ******************************************************************************/ CpaStatus calculateRequireBuffers(compression_test_params_t *setup); /** ***************************************************************************** * @ingroup compressionThreads * dcCreatePollingThreadsIfPollingIsEnabled * * @description * This function checks whether each instance handle is set for polling * and will allocate create and start the same number polling threads * as they are polling instances. * @pre numInstances_g is set and all instances have been started. * @post numPolledInstances_g is set by the function to the number of polling * instances available. * *****************************************************************************/ CpaStatus dcCreatePollingThreadsIfPollingIsEnabled(void); /** * ***************************************************************************** * @ingroup compressionThreads * dcDpPollNumOperations * * @description * Poll for remaining operations, this function will timeout after * SAMPLE_CODE_WAIT_DEFAULT have elapsed. * * @threadSafe * No * * @param[in] perfData pointer to performance structure * @param[in] instanceHandle API CpaInstanceHandle * @param[in] numOperations Number of operations to poll for * * @retval CPA_STATUS_SUCCESS No operations to poll for or all remaining * operations have been polled. * @retval CPA_STATUS_FAIL Failure from polling operation or timeout. ******************************************************************************/ CpaStatus dcDpPollNumOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations); /** * ***************************************************************************** * @ingroup compressionThreads * dcDpPollNumOperationsRetries * * @description * Poll for remaining operations, this function will timeout after * SAMPLE_CODE_WAIT_DEFAULT have elapsed. * * @threadSafe * No * * @param[in] perfData pointer to performance structure * @param[in] instanceHandle API CpaInstanceHandle * @param[in] numOperations Number of operations to poll for * @param[out] numOperations Number of retries * @param[out] retries Number of retries * * @retval CPA_STATUS_SUCCESS No operations to poll for or all remaining * operations have been polled. * @retval CPA_STATUS_FAIL Failure from polling operation or timeout. ******************************************************************************/ CpaStatus dcDpPollNumOperationsRetries(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations, Cpa32U *retries); /** * ***************************************************************************** * @ingroup compressionThreads * wait for semaphore * * @description * this API waits for the semaphore for 30 seconds and checks * if the responses are still pending, if the responses are still pending * wait for another 30 secs and returns error if the responses are not * increased * * @threadSafe * Yes * * @param[in] perfData pointer to performance structure * ******************************************************************************/ CpaStatus waitForSemaphore(perf_data_t *perfData); /** * ***************************************************************************** * @ingroup compressionThreads * sampleCodeDcGetNode * * @description * this API determines the CPU node for the instance handle * * @threadSafe * No * * @param[in] instanceHandle DC instance Handle * @param[out] node node ID of the instance * ******************************************************************************/ CpaStatus sampleCodeDcGetNode(CpaInstanceHandle instanceHandle, Cpa32U *node); /** * ***************************************************************************** * @ingroup compressionThreads * sampleCodePoll * * @description * this API repeatedly calls the QA API poll function * @threadSafe * No * * @param[in] instanceHandle DC instance Handle * ******************************************************************************/ void sampleCodeDcPoll(CpaInstanceHandle instanceHandle_in); /** * ***************************************************************************** * @ingroup compressionThreads * dcPrintstats * * @description * this API prints performance data like number of CPU cycles * consumed for an Operation * @threadSafe * No * * @param[in] data pointer to test data structure * ******************************************************************************/ CpaStatus dcPrintStats(thread_creation_data_t *data); /** * ***************************************************************************** * @ingroup chainingThreads * chainPrintstats * * @description * this API prints performance data like number of CPU cycles * consumed for an Operation * @threadSafe * No * * @param[in] data pointer to test data structure * ******************************************************************************/ CpaStatus dcChainPrintStats(thread_creation_data_t *data); /** * ***************************************************************************** * @ingroup compressionThreads * dcPrintTestData * * @description * this API prints the setup data used to execute the compression test * @threadSafe * No * * @param[in] setup pointer to compression test data structure * ******************************************************************************/ void dcPrintTestData(compression_test_params_t *setup); /** * ***************************************************************************** * @ingroup chainingThreads * dcChainPrintTestData * * @description * this API prints the setup data used to execute the chaining test * @threadSafe * No * * @param[in] setup pointer to chaining test data structure * ******************************************************************************/ void dcChainPrintTestData(compression_test_params_t *setup); /** * ***************************************************************************** * @ingroup compressionThreads * dcDpSetBytesProducedAndConsumed * * @description * This function aggregates the total bytes consumed and produced as * reported by the driver in the opData structures (a separate opData * structure is used for each buffer submitted) and stores them in the * perfData totalBytesConsumed and totalBytesProduced fields. * @threadSafe * No * * @param[in] opData 2D array of pointers to a CpaDcDpOpData structure * @param[in,out] perfData pointer to performance structure * @param[in] pointer to compression_test_params_t structure. * * ******************************************************************************/ void dcDpSetBytesProducedAndConsumed(CpaDcDpOpData ***opData, perf_data_t *perfData, compression_test_params_t *setup); /** * ***************************************************************************** * @ingroup compressionThreads * dcSetBytesProducedAndConsumed * * @description * This function aggregates the total bytes consumed and produced as * reported by the driver in the cmpResult structures (a separate cmpResult * structure is used for each buffer submitted) and stores them in the * perfData totalBytesConsumed and totalBytesProduced fields. * @threadSafe * No * * @param[in] cmpResult 2D array of pointers to a CpaDcRqResults structure * @param[in] perfData pointer to performance structure * @param[in] pointer to compression_test_params_t structure. * * ******************************************************************************/ void dcSetBytesProducedAndConsumed(CpaDcRqResults ***cmpResult, perf_data_t *perfData, compression_test_params_t *setup); /** * ***************************************************************************** * @ingroup compressionThreads * dcCalculateAndPrintCompressionRatio * * @description * this API calculates and prints the compression ratio * @threadSafe * No * * @param[in] bytesConsumed Total number of bytes consumed for compression * @param[in] bytesProduced Total number of bytes produced after compression * ******************************************************************************/ CpaStatus dcCalculateAndPrintCompressionRatio(Cpa32U bytesConsumed, Cpa32U bytesProduced); /** ***************************************************************************** * @ingroup compressionThreads * getDcThroughput * * @description * get the throughput in Megabits per second * * @param[in] totalBytes Total number of bytes consumed by all threads * @param[in] cycles Total number of clock cycles * @param[in] numOfLoops Number of loops specified for compression operation *****************************************************************************/ Cpa32U getDcThroughput(Cpa32U totalBytes, perf_cycles_t cycles, Cpa32U numOfLoops); /** ***************************************************************************** * @ingroup compressionThreads * dynamicHuffmanEnabled * * @description * Determines if a given instance has Dynamic Huffman enabled. * * @param[in] dcInstanceHandle Pointer to CpaInstanceHandle. If * dcInstanceHandle is NULL a local instance, i.e. the * first instance from cpaDcGetNumInstances() will be * used to determine if dynamic Huffman is enabled. * @param[in,out] isEnabled Pointer to CpaBoolean. When set to CPA_TRUE * the instance handle has dynamic Huffman enabled. * Will be set to CPA_FALSE for all error conditions * or where CpaDcInstanceCapabilities.dynamicHuffman * is CPA_FALSE. * @retval CPA_STATUS_SUCCESS Instance query for dynamic compression succeeded * @retval CPA_STATUS_FAIL Instance query for dynamic compression failed *****************************************************************************/ CpaStatus dynamicHuffmanEnabled(CpaInstanceHandle *dcInstanceHandle, CpaBoolean *isEnabled); /*This function tells the compression sample code to use zLib software to * compress the data prior to calling the decompression*/ CpaStatus useZlib(void); /*This function tells the compression sample code to use zLib software to * compress the data prior to calling the decompression*/ CpaStatus useAccelCompression(void); CpaStatus dcPollNumOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations); CpaStatus dcSampleCreateStatefulContextBuffer(Cpa32U buffSize, Cpa32U metaSize, CpaBufferList **pBuffListArray, Cpa32U nodeId); CpaStatus dcSampleFreeStatefulContextBuffer3(CpaBufferList *pBuffListArray); CpaStatus waitForInflightRequestAfterError(perf_data_t *perfData); void measureNano(Cpa32U); Cpa32U getNumFilesInCorpus(corpus_type_t corpus); char **getFileNamesInCorpus(corpus_type_t corpus); const corpus_file_t *getFilesInCorpus(corpus_type_t corpusType); const char *getCorpusName(corpus_type_t corpusType); corpus_type_t getCorpusTypeFromName(const char *name, const unsigned long name_max_size); const char *getFileNameInCorpus(corpus_type_t corpusType, Cpa32U fileIndex); void setCorpusType(corpus_type_t type); corpus_type_t getCorpusType(void); void setCorpusFileIndex(Cpa32U index); Cpa32U getCorpusFileIndex(void); Cpa32U getSetupCnVRequestFlag(void); void setSetupCnVRequestFlag(Cpa32U flag); void setDcPollingThreadsInterval(long interval); /** * ***************************************************************************** * @ingroup compressionThreads * sampleRemoveDcDpSession * * @description * This function check and removes the compression session. * * @param[out] status * * @param[in] dcInstance Instance handle * @param[in] pSessionHandle Session handle * ******************************************************************************/ CpaStatus sampleRemoveDcDpSession(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle); #endif /* CPA_SAMPLE_CODE_DC_UTILS_H_ */ cpa_sample_code_zlib.c000066400000000000000000000257361503624047500362460ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_zlib.c * * * @ingroup sample_code * * @description * This is sample code that uses zlib to compress/decompress data. *****************************************************************************/ #include "cpa_dc.h" #include "cpa_sample_code_utils_common.h" #include "cpa_sample_code_dc_utils.h" #ifdef USER_SPACE #include "zlib.h" #else #include #include #endif #include "qat_compression_zlib.h" #ifdef USER_SPACE CpaStatus deflate_init(struct z_stream_s *stream) { #ifdef USE_ZLIB int ret = 0; stream->zalloc = (alloc_func)0; stream->zfree = (free_func)0; stream->opaque = (voidpf)0; stream->next_in = Z_NULL; stream->next_out = Z_NULL; stream->avail_in = stream->avail_out = stream->total_out = 0; stream->adler = 0; ret = deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED, -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, Z_DEFAULT_STRATEGY); if (ret != Z_OK) { PRINT_ERR("Error in deflateInit2\n"); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } /*Compress Date on a zlib stream*/ CpaStatus deflate_compress(struct z_stream_s *stream, const Cpa8U *src, Cpa32U slen, Cpa8U *dst, Cpa32U dlen, int deflate_type) { #ifdef USE_ZLIB int ret = 0; stream->next_in = (Cpa8U *)src; stream->avail_in = slen; stream->next_out = (Cpa8U *)dst; stream->avail_out = dlen; ret = deflate(stream, deflate_type); if (ret != Z_STREAM_END && ret != Z_OK) { PRINT_ERR("Error in zlib_deflate, ret = %d\n", ret); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } CpaStatus inflate_init(z_stream *stream, CpaDcSessionState sessState) { #ifdef USE_ZLIB int ret = 0; stream->zalloc = (alloc_func)0; stream->zfree = (free_func)0; stream->opaque = (voidpf)0; stream->next_in = Z_NULL; stream->next_out = Z_NULL; stream->avail_in = stream->avail_out = stream->total_out = 0; stream->adler = 0; ret = inflateInit2(stream, -DEFLATE_DEF_WINBITS); if (ret != Z_OK) { PRINT_ERR("Error in inflateInit2, ret = %d\n", ret); return CPA_STATUS_FAIL; } if (sessState == CPA_DC_STATEFUL) { #if ZLIB_VERNUM >= 0x1234 ret = inflateReset2(stream, -DEFLATE_DEF_WINBITS); #else ret = inflateReset(stream); #endif if (ret != Z_OK) { PRINT_ERR("Error in inflateReset\n"); return CPA_STATUS_FAIL; } } #endif return CPA_STATUS_SUCCESS; } CpaStatus inflate_decompress(z_stream *stream, const Cpa8U *src, Cpa32U slen, Cpa8U *dst, Cpa32U dlen, CpaDcSessionState sessState) { #ifdef USE_ZLIB int ret = 0; int flushFlag = Z_SYNC_FLUSH; if (sessState == CPA_DC_STATELESS) { flushFlag = Z_FULL_FLUSH; } stream->next_in = (Cpa8U *)src; stream->avail_in = slen; stream->next_out = (Cpa8U *)dst; stream->avail_out = dlen; ret = inflate(stream, flushFlag); if (ret != Z_OK && ret != Z_STREAM_END) { PRINT_ERR("Error in inflate, ret = %d\n", ret); PRINT_ERR("stream msg = %s\n", stream->msg); PRINT_ERR("stream adler = %u\n", (unsigned int)stream->adler); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } /*close zlib stream*/ void deflate_destroy(struct z_stream_s *stream) { #ifdef USE_ZLIB deflateEnd(stream); #endif } /*close zlib stream*/ void inflate_destroy(struct z_stream_s *stream) { #ifdef USE_ZLIB inflateEnd(stream); #endif } #endif #ifdef KERNEL_SPACE /* initialize a zlib stream*/ CpaStatus deflate_init(struct z_stream_s *stream) { #ifdef USE_ZLIB int ret = 0; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) stream->workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)); #else stream->workspace = vmalloc(zlib_deflate_workspacesize()); #endif if (NULL == stream->workspace) { PRINT_ERR("Could not allocate zlib workspace memory\n"); return CPA_STATUS_FAIL; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) memset(stream->workspace, 0, zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)); #else memset(stream->workspace, 0, zlib_deflate_workspacesize()); #endif ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED, -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, Z_DEFAULT_STRATEGY); if (ret != Z_OK) { PRINT_ERR("Error in zlib_deflateInit2\n"); vfree(stream->workspace); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(deflate_init); /*Compress Date on a zlib stream*/ CpaStatus deflate_compress(struct z_stream_s *stream, const Cpa8U *src, Cpa32U slen, Cpa8U *dst, Cpa32U dlen, int inflate_type) { #ifdef USE_ZLIB int ret = 0; stream->next_in = (Cpa8U *)src; stream->avail_in = slen; stream->next_out = (Cpa8U *)dst; stream->avail_out = dlen; ret = zlib_deflate(stream, inflate_type); if (ret != Z_STREAM_END && ret != Z_OK) { PRINT_ERR("Error in zlib_deflate, ret = %d\n", ret); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(deflate_compress); /*close zlib stream*/ void deflate_destroy(struct z_stream_s *stream) { #ifdef USE_ZLIB zlib_deflateEnd(stream); vfree(stream->workspace); #endif } EXPORT_SYMBOL(deflate_destroy); CpaStatus inflate_init(z_stream *stream, CpaDcSessionState sessState) { #ifdef USE_ZLIB int ret = 0; stream->workspace = vmalloc(zlib_inflate_workspacesize()); if (NULL == stream->workspace) { PRINT_ERR("Could not allocate zlib workspace memory\n"); return CPA_STATUS_FAIL; } memset(stream->workspace, 0, zlib_inflate_workspacesize()); ret = zlib_inflateInit2(stream, -MAX_WBITS); if (ret != Z_OK) { PRINT_ERR("Error in zlib_inflateInit2, ret = %d\n", ret); return CPA_STATUS_FAIL; } if (sessState == CPA_DC_STATEFUL) { ret = zlib_inflateReset(stream); if (ret != Z_OK) { PRINT_ERR("Error in zlib_inflateReset, ret = %d\n", ret); return CPA_STATUS_FAIL; } } #endif return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(inflate_init); CpaStatus inflate_decompress(z_stream *stream, const Cpa8U *src, Cpa32U slen, Cpa8U *dst, Cpa32U dlen, CpaDcSessionState sessState) { #ifdef USE_ZLIB int ret = 0; int flushFlag = Z_SYNC_FLUSH; if (sessState == CPA_DC_STATELESS) { flushFlag = Z_FULL_FLUSH; } stream->next_in = (Cpa8U *)src; stream->avail_in = slen; stream->next_out = (Cpa8U *)dst; stream->avail_out = dlen; ret = zlib_inflate(stream, flushFlag); if (ret != Z_OK && ret != Z_STREAM_END) { PRINT_ERR("Error in zlib_inflate, ret = %d\n", ret); PRINT_ERR("stream msg = %s\n", stream->msg); PRINT_ERR("stream adler = %u\n", (unsigned int)stream->adler); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(inflate_decompress); /*close zlib stream*/ void inflate_destroy(struct z_stream_s *stream) { #ifdef USE_ZLIB zlib_inflateEnd(stream); if (stream->workspace != NULL) { vfree(stream->workspace); } #endif } EXPORT_SYMBOL(inflate_destroy); #endif qat_chaining_main.c000066400000000000000000002316211503624047500355510ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qat_chaining_main.c * * * @ingroup compressionThreads * * @description * This is a sample code that uses chaining APIs. * This code preallocates a number of buffers as based on the size of each * file defined in the calgary/canterbury corpus. The preallocated buffers * are then populated with the corpus files as define in * setup->testBuffersize. * Time stamping is started prior to the first performed chaining * Operation and is stopped when all callbacks have returned. *****************************************************************************/ #include "cpa_sample_code_utils_common.h" #include "cpa_sample_code_dc_perf.h" #include "cpa_sample_code_dc_utils.h" #include "qat_compression_main.h" #include "cpa_sample_code_crypto_utils.h" #include "qat_perf_cycles.h" #include "qat_perf_sleeptime.h" #include "qat_compression_e2e.h" #ifdef USER_SPACE #include #include #else #include #include #include #include #endif #ifdef USER_SPACE #include #else #include #endif #include "icp_sal_poll.h" static CpaStatus qatDcChainInduceOverflow(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaBufferList *srcBufferListArray, CpaBufferList *destBufferListArray, CpaBufferList *cmpBufferListArray, CpaDcChainRqResults *resultArray, CpaDcChainOpData *chainOpDataArray); extern int latency_enable; extern int latency_debug; extern int latency_single_buffer_mode; #define COUNT_RESPONSES dcPerformCallback(setup, status) static inline void bufferDump(Cpa8U *pBuffer, Cpa32U bufferLength) { int i = 0; for (i = 0; i < bufferLength; i++) { if (i && (i % 16 == 0)) { PRINT("\n"); } PRINT("%02X", pBuffer[i]); } PRINT("\n"); } CpaStatus compareBuffers2(CpaBufferList ***ppSrc, CpaBufferList ***ppDst, CpaBufferList ***ppComp, compression_test_params_t *setup); static Cpa32U crc32_checksum(Cpa32U inputChecksum, Cpa8U *pData, Cpa32U length) { Cpa32U resultChecksum = 0; #ifdef KERNEL_SPACE resultChecksum = crc32(inputChecksum ^ CRC32_XOR_VALUE, pData, length) ^ CRC32_XOR_VALUE; #else resultChecksum = crc32(inputChecksum, pData, length); #endif return resultChecksum; } void computeSglChecksum(CpaBufferList *inputBuff, const Cpa32U computationSize, const CpaDcChecksum checksumType, Cpa32U *swChecksum) { Cpa32U numBuffs = 0; Cpa32U lenLeft = 0; Cpa32U totalLen = 0; for (numBuffs = 0; numBuffs < inputBuff->numBuffers; numBuffs++) { totalLen += inputBuff->pBuffers[numBuffs].dataLenInBytes; if (totalLen > computationSize) { totalLen -= inputBuff->pBuffers[numBuffs].dataLenInBytes; lenLeft = computationSize - totalLen; if (CPA_DC_CRC32 == checksumType) { *swChecksum = crc32_checksum( *swChecksum, inputBuff->pBuffers[numBuffs].pData, lenLeft); } break; } else { lenLeft = inputBuff->pBuffers[numBuffs].dataLenInBytes; } if (CPA_DC_CRC32 == checksumType) { *swChecksum = crc32_checksum( *swChecksum, inputBuff->pBuffers[numBuffs].pData, lenLeft); } } } extern Cpa32U dcPollingInterval_g; #define DOUBLE_SUBMISSIONS (2) extern char *cpaStatusToString(CpaStatus status); static CpaStatus checkAdler32Checksum(Cpa8U *inputBuff, Cpa32U inputBufferLen, CpaDcChainRqResults *results, Cpa32U *swChecksum) { #ifdef USER_SPACE /* Calculate s/w checksum */ *swChecksum = adler32(*swChecksum, inputBuff, inputBufferLen); if (results->adler32 != *swChecksum) { PRINT("s/w checksum: %X h/w checksum: %X\n", *swChecksum, results->adler32); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } static CpaStatus checkCrc32Checksum(Cpa8U *inputBuff, Cpa32U inputBufferLen, CpaDcChainRqResults *results, Cpa32U *swChecksum) { /* Calculate s/w checksum */ *swChecksum = crc32(*swChecksum, inputBuff, inputBufferLen); if (results->crc32 != *swChecksum) { PRINT("s/w checksum: %X h/w checksum: %X\n", *swChecksum, results->crc32); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus qatDcChainSubmitRequest(compression_test_params_t *setup, CpaInstanceInfo2 *pInstanceInfo2, CpaDcSessionDir compressDirection, CpaDcSessionHandle pSessionHandle, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, Cpa32U listNum, CpaDcChainRqResults *arrayOfResults, CpaDcChainOpData *arrayOfChainOpData) { CpaStatus status = CPA_STATUS_SUCCESS; static Cpa32U staticAssign = 0; Cpa8U numSessions = setup->numSessions; if (setup->requestOps.flushFlag != setup->flushFlag) { PRINT_ERR("Setup Disparity in Flush flag." "RequestOps = %d, setup = %d\n", setup->requestOps.flushFlag, setup->flushFlag); setup->requestOps.flushFlag = setup->flushFlag; } do { /*To use reliability code, I set CpaBoolean reliability_g = CPA_TRUE * in cpa_sample_code_framework.c and defined USE_ZLIB from * command line */ qatStartLatencyMeasurement(setup->performanceStats, setup->performanceStats->submissions); coo_req_start(setup->performanceStats); status = cpaDcChainPerformOp( setup->dcInstanceHandle, pSessionHandle, &arrayOfSrcBufferLists[listNum], &arrayOfDestBufferLists[listNum], setup->chainOperation, numSessions, &arrayOfChainOpData[listNum * setup->numSessions], &arrayOfResults[listNum], (void *)setup); coo_req_stop(setup->performanceStats, status); if (CPA_STATUS_RETRY == status) { qatDcRetryHandler(setup, pInstanceInfo2); /*check if sleeptime defined if yes then perform sleep in 100k intervals */ if ((sleepTime_enable) && (setup->sleepTime != 0)) { sleep_parsing(setup->sleepTime); } /*context switch to give firmware time to process*/ AVOID_SOFTLOCKUP; } /*check the results structure for any failed responses * caught by the callback function*/ qatDcChainResponseStatusCheck(setup, arrayOfResults, listNum, &status); } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { busyLoop(setup->performanceStats->busyLoopValue, &staticAssign); setup->performanceStats->busyLoopCount++; } return status; } EXPORT_SYMBOL(qatDcChainSubmitRequest); /* chaining performance measurement function to compress a file for 'n' number * of loops * */ CpaStatus qatDcChainCompressData(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaDcSessionDir compressDirection, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcChainRqResults *arrayOfResults, CpaDcChainOpData *arrayOfChainOpData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceInfo2 instanceInfo2 = {0}; Cpa32U numLoops = 0; Cpa32U listNum = 0; Cpa32U previousChecksum = 0; sleeptime_data_t sleeptime_data = {0}; sleeptime_data.firstRunFlag = 1; /* init checksum */ if (CPA_DC_ADLER32 == gChecksum) { previousChecksum = 1; } else if (CPA_DC_CRC32 == gChecksum) { previousChecksum = 0; } QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfSrcBufferLists, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfDestBufferLists, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfCmpBufferLists, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfResults, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfChainOpData, status); if (CPA_STATUS_SUCCESS == status) { status = qatCompressionE2EInit(setup); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS("qatCompressionE2EInit", status); } if (CPA_STATUS_SUCCESS == status) { setup->flushFlag = CPA_DC_FLUSH_FINAL; qatPerfInitStats(setup->performanceStats, setup->numLists, setup->numLoops, dcPollingInterval_g); status = qatInitLatency( setup->performanceStats, setup->numLists, setup->numLoops); } if (CPA_STATUS_SUCCESS == status) { /*get the instance2 info, this is used to determine if the instance * being used is polled*/ status = cpaDcInstanceGetInfo2(setup->dcInstanceHandle, &instanceInfo2); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS("cpaDcInstanceGetInfo2", status); } if (status == CPA_STATUS_SUCCESS) { /*Initialize the semaphore, the callback function is responsible for * posting the semaphore once all responses are received*/ /* Completion used in callback */ status = sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS("sampleCodeSemaphoreInit", status); } if (status == CPA_STATUS_SUCCESS) { /* this Barrier will waits until all the threads get to this point * this is to ensure that all threads that we measure performance on * start submitting at the same time*/ sampleCodeBarrier(); /* generate the start time stamps */ setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); sleeptime_data.startLoopTimestamp = setup->performanceStats->startCyclesTimestamp; /*loop over compressing a file numLoop times*/ for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { /*loop over lists that store the file*/ for (listNum = 0; listNum < setup->numLists; listNum++) { /*exit loop mechanism to leave early if numLoops is large * note that this might not work if the we get stuck in the * do-while loop below*/ checkStopTestExitFlag(setup->performanceStats, &setup->numLoops, &setup->numLists, numLoops); qatCompressionSetFlushFlag(setup, listNum); /*for stateful-lite carry over checksum from previous request*/ if ((CPA_TRUE == setup->useStatefulLite) || (CPA_DC_STATEFUL == setup->setupData.sessState)) { arrayOfResults[listNum].crc32 = previousChecksum; } /*submit request*/ status = qatDcChainSubmitRequest(setup, &instanceInfo2, compressDirection, pSessionHandle, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, listNum, arrayOfResults, arrayOfChainOpData); /* Check submit status and update thread status*/ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Data Compression Failed %d\n\n", status); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; /*break out of inner loop*/ break; } setup->performanceStats->submissions++; qatLatencyPollForResponses(setup->performanceStats, setup->performanceStats->submissions, setup->dcInstanceHandle, CPA_FALSE, CPA_FALSE); if (poll_inline_g && instanceInfo2.isPolled) { /*poll every 'n' requests as set by * dcPollingInterval_g*/ if (setup->performanceStats->submissions == setup->performanceStats->nextPoll) { qatDcPollAndSetNextPollCounter(setup); } } /* check if synchronous flag is set, * if set, invoke the callback API * the driver does not use the callback in sync mode * the sample code uses the callback function to count the * responses and post the semaphore */ if (SYNC == setup->syncFlag) { COUNT_RESPONSES; } /* End of SYNC Flag Check */ if (CPA_STATUS_SUCCESS == status) { status = qatDcChainE2EVerify(setup, &arrayOfSrcBufferLists[listNum], &arrayOfDestBufferLists[listNum], &arrayOfResults[listNum]); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s returned status: %d\n", "qatDcChainE2EVerify", status); break; } } /* number of lists/requests in a file */ if (CPA_STATUS_SUCCESS != status) { setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; /*break out of outerloop(numLoops)*/ break; } if ((numLoops % QAT_COMP_MIN_LOOPS_FOR_SLEEP_CONTROL == QAT_COMP_MIN_LOOPS_FOR_SLEEP_CONTROL - 1) && (sleepTime_enable) && (setup->specific_sleeptime_flag == CPA_FALSE)) { adjustSleeptime(setup->performanceStats, &sleeptime_data, &setup->compRate, &setup->sleepTime, setup->bufferSize); } } /* number of times we loop over same file */ if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2.isPolled)) { /* ** Now need to wait for all the inflight Requests. */ status = dcPollNumOperations(setup->performanceStats, setup->dcInstanceHandle, setup->performanceStats->numOperations); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("dcPollNumOperations returned an error\n"); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } } } /* Wait 30 seconds for the semaphore to be posted by the callback*/ if (CPA_STATUS_SUCCESS == status) { status = waitForSemaphore(setup->performanceStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("waitForSemaphore error\n"); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } } /*check the results structure for any failed responses * caught by the callback function*/ qatDcChainResponseStatusCheck(setup, arrayOfResults, listNum, &status); qatSummariseLatencyMeasurements(setup->performanceStats); sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); } /* if semaphoreInit was successful */ if (CPA_STATUS_SUCCESS != status) { setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } return status; } EXPORT_SYMBOL(qatDcChainCompressData); /*update in sample code framework how much data was consumed and produced by * thread*/ void dcChainScSetBytesProducedAndConsumed(CpaDcChainRqResults *result, perf_data_t *perfData, compression_test_params_t *setup, CpaDcSessionDir direction) { Cpa32U i = 0; if (direction == CPA_DC_DIR_COMPRESS) { for (i = 0; i < setup->numberOfBuffers[0]; i++) { perfData->bytesConsumedPerLoop += result[i].consumed; perfData->bytesProducedPerLoop += result[i].produced; } } else if (direction == CPA_DC_DIR_DECOMPRESS) { for (i = 0; i < setup->numberOfBuffers[0]; i++) { perfData->bytesConsumedPerLoop += result[i].produced; perfData->bytesProducedPerLoop += result[i].consumed; } } } EXPORT_SYMBOL(dcChainScSetBytesProducedAndConsumed); void dcChainOpDataMemFree(CpaDcChainOpData *pOpdata, Cpa32U numLists, Cpa32U numSessions) { Cpa32U k = 0; Cpa32U j = numSessions; CpaDcOpData *pDcOp = NULL; CpaCySymOpData *pCySymOp = NULL; for (k = 0; k < numLists; k++) { if (NULL != pOpdata) { if (pOpdata[k * j].opType == CPA_DC_CHAIN_SYMMETRIC_CRYPTO) { pCySymOp = pOpdata[k * j].pCySymOp; pDcOp = pOpdata[k * j + 1].pDcOp; } else { pCySymOp = pOpdata[k * j + 1].pCySymOp; pDcOp = pOpdata[k * j].pDcOp; } if (NULL != pCySymOp) { if (NULL != pCySymOp->pDigestResult) { qaeMemFreeNUMA((void **)&(pCySymOp->pDigestResult)); } if (NULL != pCySymOp->pIv) { qaeMemFreeNUMA((void **)&(pCySymOp->pIv)); } if (NULL != pCySymOp->pAdditionalAuthData) { qaeMemFreeNUMA((void **)&(pCySymOp->pAdditionalAuthData)); } qaeMemFree((void **)&pCySymOp); } if (NULL != pDcOp) { if (NULL != pDcOp->pCrcData) { qaeMemFreeNUMA((void **)&(pDcOp->pCrcData)); } qaeMemFree((void **)&pDcOp); } } } } CpaStatus dcChainPerformOpDataSetup(compression_test_params_t *setup, CpaBufferList *srcBufferListArray, CpaDcChainOpData *chainOpDataArray) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U listNum = 0; CpaDcOpData *pDcOp = NULL; CpaCySymOpData *pCySymOp = NULL; Cpa32U nodeId = 0; status = sampleCodeDcGetNode(setup->dcInstanceHandle, &nodeId); if (CPA_STATUS_SUCCESS != status) { setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } for (listNum = 0; listNum < setup->numLists; listNum++) { memset(&chainOpDataArray[listNum * setup->numSessions], 0, sizeof(CpaDcChainOpData) * setup->numSessions); pDcOp = qaeMemAlloc(sizeof(CpaDcOpData)); if (NULL == pDcOp) { PRINT_ERR("qaeMemAlloc for pDcOp error\n"); dcChainOpDataMemFree(chainOpDataArray, listNum, setup->numSessions); return CPA_STATUS_FAIL; } memset(pDcOp, 0, sizeof(CpaDcOpData)); pDcOp->flushFlag = CPA_DC_FLUSH_FINAL; pDcOp->compressAndVerify = setup->requestOps.compressAndVerify; pDcOp->compressAndVerifyAndRecover = setup->requestOps.compressAndVerifyAndRecover; pCySymOp = qaeMemAlloc(sizeof(CpaCySymOpData)); if (NULL == pCySymOp) { PRINT_ERR("qaeMemAlloc for pCySymOp error\n"); qaeMemFree((void **)&pDcOp); dcChainOpDataMemFree(chainOpDataArray, listNum, setup->numSessions); return CPA_STATUS_FAIL; } memset(pCySymOp, 0, sizeof(CpaCySymOpData)); pCySymOp->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pCySymOp->cryptoStartSrcOffsetInBytes = 0; pCySymOp->messageLenToCipherInBytes = srcBufferListArray[listNum].pBuffers[0].dataLenInBytes; pCySymOp->hashStartSrcOffsetInBytes = 0; pCySymOp->messageLenToHashInBytes = srcBufferListArray[listNum].pBuffers[0].dataLenInBytes; if (0 != setup->symSetupData.hashSetupData.digestResultLenInBytes) { pCySymOp->pDigestResult = qaeMemAllocNUMA( setup->symSetupData.hashSetupData.digestResultLenInBytes, nodeId, BYTE_ALIGNMENT_64); if (NULL == pCySymOp->pDigestResult) { PRINT_ERR( "qaeMemAllocNuMA for pCySymOp->pDigestResult error\n"); qaeMemFree((void **)&pDcOp); qaeMemFree((void **)&pCySymOp); dcChainOpDataMemFree( chainOpDataArray, listNum, setup->numSessions); return CPA_STATUS_FAIL; } } switch (setup->chainOperation) { case CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT: chainOpDataArray[listNum * setup->numSessions].opType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainOpDataArray[listNum * setup->numSessions].pDcOp = pDcOp; chainOpDataArray[listNum * setup->numSessions + 1].opType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainOpDataArray[listNum * setup->numSessions + 1].pCySymOp = pCySymOp; break; case CPA_DC_CHAIN_DECRYPT_THEN_DECOMPRESS: chainOpDataArray[listNum * setup->numSessions].opType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainOpDataArray[listNum * setup->numSessions].pCySymOp = pCySymOp; chainOpDataArray[listNum * setup->numSessions + 1].opType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainOpDataArray[listNum * setup->numSessions + 1].pDcOp = pDcOp; break; case CPA_DC_CHAIN_HASH_THEN_COMPRESS: chainOpDataArray[listNum * setup->numSessions].opType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainOpDataArray[listNum * setup->numSessions].pCySymOp = pCySymOp; chainOpDataArray[listNum * setup->numSessions + 1].opType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainOpDataArray[listNum * setup->numSessions + 1].pDcOp = pDcOp; break; default: PRINT_ERR("Unsupported chaining operation.\n"); qaeMemFree((void **)&pDcOp); dcChainOpDataMemFree( chainOpDataArray, listNum, setup->numSessions); qaeMemFreeNUMA((void **)&(pCySymOp->pDigestResult)); qaeMemFree((void **)&pCySymOp); return CPA_STATUS_FAIL; } } return status; } /*Allocates buffers store a file for compression. The buffers are sent to * hardware, performance is recorded and stored in the setup parameter * the sample code framework prints out results after the thread completes*/ CpaStatus qatDcChainPerform(compression_test_params_t *setup) { /*** store file in array of CpaBufferLists: arrayOfSrcBufferLists[0].CpaFlatBuffer.pData <-startOfFile arrayOfSrcBufferLists[0].CpaFlatBuffer.bufferSizeInBytes . . . arrayOfSrcBufferLists[n].CpaFlatBuffer.pData <-endOfFile arrayOfSrcBufferLists[n].CpaFlatBuffer.bufferSizeInBytes where bufferSizeInBytes = testBufferSize n = numberOfLists required of the above mentioned size, required to store the file ***/ CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U *testBufferSize = setup->packetSizeInBytesArray; Cpa32U numberOfBuffersPerList = 1; /* Src Buffer list for data to be compressed */ CpaBufferList *srcBufferListArray = NULL; /* BufferList for de-compressed Data */ CpaBufferList *destBufferListArray = NULL; /* BufferList for compressed data */ CpaBufferList *cmpBufferListArray = NULL; CpaDcChainRqResults *resultArray = NULL; CpaDcSessionHandle pSessionHandle = NULL; CpaDcSessionHandle pDecompressSessionHandle = NULL; CpaDcCallbackFn dcCbFn = dcPerformCallback; Cpa32U numLoops = 0; Cpa32U listNum = 0; Cpa32U i = 0; Cpa32U nodeId = 0; Cpa32U softChecksum = 0; /* Chain operation data for compression chaining */ CpaDcChainOpData *chainOpDataArray = NULL; CpaFlatBuffer *pSWDigestBuffer = NULL; const corpus_file_t *const fileArray = getFilesInCorpus(setup->corpus); coo_init(setup->performanceStats, (Cpa64U)setup->numLists * (Cpa64U)setup->numLoops); /* Allocate memory for source & destination bufferLists */ status = qatAllocateCompressionLists(setup, &srcBufferListArray, &destBufferListArray, &cmpBufferListArray, NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate compression list arrays\n"); } /* Allocate memory for DcChain results and chainOpData */ if (CPA_STATUS_SUCCESS == status) { status = qatAllocateDcChainLists( setup, (void **)&resultArray, (void **)&chainOpDataArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate DcChain result and ChainOpLists\n"); } } /* Allocate the CpaFlatBuffers in each list */ if (CPA_STATUS_SUCCESS == status) { status = qatAllocateCompressionFlatBuffers(setup, srcBufferListArray, numberOfBuffersPerList, testBufferSize, destBufferListArray, numberOfBuffersPerList, testBufferSize, cmpBufferListArray, numberOfBuffersPerList, testBufferSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate all flat buffers for compression\n"); } } /* Copy corpus data into allocated buffers */ if (CPA_STATUS_SUCCESS == status) { status = PopulateBuffers( srcBufferListArray, setup->numLists, fileArray[setup->corpusFileIndex].corpusBinaryData, fileArray[setup->corpusFileIndex].corpusBinaryDataLen, testBufferSize); } /* Initialize the compression session to use */ if (CPA_STATUS_SUCCESS == status) { status = qatDcChainSessionInit( setup, &pSessionHandle, &pDecompressSessionHandle, dcCbFn); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("compressionSessionInit returned status %d\n", status); } } /*CNV Error Injection*/ /* Set value for chainOpData */ if (CPA_STATUS_SUCCESS == status) { status = dcChainPerformOpDataSetup( setup, srcBufferListArray, chainOpDataArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("dcChainPerformOpDataSetup returned status %d\n", status); } } /* Compress the data */ if (CPA_STATUS_SUCCESS == status) { if (setup->induceOverflow == CPA_TRUE) { status = qatDcChainInduceOverflow(setup, pSessionHandle, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray, chainOpDataArray); } else if (setup->dcSessDir == CPA_DC_DIR_COMPRESS && reliability_g == CPA_FALSE) { status = qatDcChainCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray, chainOpDataArray); qatDcChainUpdateProducedBufferLength( setup, destBufferListArray, resultArray); dcChainScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, setup->dcSessDir); } else if (setup->dcSessDir == CPA_DC_DIR_DECOMPRESS && reliability_g == CPA_FALSE) { PRINT("Chaining Decompression need to be developed\n"); status = CPA_STATUS_FAIL; } else if (setup->dcSessDir == CPA_DC_DIR_COMPRESS && reliability_g == CPA_TRUE) { /*Copy numLoops, set setup->numLoops to 1 to do repeated * compress - sw-decompress for numLoops times */ numLoops = setup->numLoops; setup->numLoops = 1; for (i = 0; i < numLoops; i++) { status = qatDcChainCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray, chainOpDataArray); qatDcChainUpdateProducedBufferLength( setup, destBufferListArray, resultArray); dcChainScSetBytesProducedAndConsumed(resultArray, setup->performanceStats, setup, setup->dcSessDir); if (CPA_STATUS_SUCCESS == status) { status = qatSwChainDecompress(setup, destBufferListArray, cmpBufferListArray, resultArray); qatDcChainUpdateProducedBufferLength( setup, cmpBufferListArray, resultArray); if (CPA_STATUS_SUCCESS == status) { status = qatCmpBuffers( setup, srcBufferListArray, cmpBufferListArray); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCmpBuffers", status); if (CPA_STATUS_SUCCESS != status) { break; } } pSWDigestBuffer = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pSWDigestBuffer) { PRINT_ERR( "Unable to allocate Memory for pSWDigestBuffer\n"); status = CPA_STATUS_FAIL; break; } pSWDigestBuffer->pData = qaeMemAllocNUMA(setup->symSetupData.hashSetupData .digestResultLenInBytes, nodeId, BYTE_ALIGNMENT_64); if (NULL == pSWDigestBuffer->pData) { PRINT_ERR("Unable to allocate Memory for " "pSWDigestBuffer->pData\n"); qaeMemFree((void **)&pSWDigestBuffer); status = CPA_STATUS_FAIL; break; } for (listNum = 0; listNum < setup->numLists; listNum++) { { status = calcSWDigest( srcBufferListArray[listNum].pBuffers, pSWDigestBuffer, setup->symSetupData.hashSetupData .hashAlgorithm); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("calcSWDigest returned status %d\n", status); } } if (CPA_STATUS_SUCCESS == status) { if (memcmp(chainOpDataArray[listNum * setup->numSessions] .pCySymOp->pDigestResult, pSWDigestBuffer->pData, setup->symSetupData.hashSetupData .digestResultLenInBytes)) { status = CPA_STATUS_FAIL; PRINT_ERR("Chaining Hash Buffers comparison " "failed\n"); PRINT("[HW Digest]\n"); bufferDump(chainOpDataArray[listNum * setup->numSessions] .pCySymOp->pDigestResult, setup->symSetupData.hashSetupData .digestResultLenInBytes); PRINT("[SW Digest]\n"); bufferDump(pSWDigestBuffer->pData, setup->symSetupData.hashSetupData .digestResultLenInBytes); } } } qaeMemFreeNUMA((void **)&(pSWDigestBuffer->pData)); qaeMemFree((void **)&pSWDigestBuffer); if (CPA_STATUS_SUCCESS == status) { /* Reset destination buffer */ status = qatCompressResetBufferList(setup, destBufferListArray, testBufferSize, CPA_FALSE); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCompressResetBufferList resets de-compression " "bufferlist", status); status = qatCompressResetBufferList(setup, cmpBufferListArray, testBufferSize, CPA_TRUE); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCompressResetBufferList resets compression " "bufferlist", status); } for (listNum = 0; listNum < setup->numLists; listNum++) { switch (setup->setupData.checksum) { case CPA_DC_NONE: break; case CPA_DC_CRC32: softChecksum = 0; status = checkCrc32Checksum( srcBufferListArray[listNum].pBuffers->pData, srcBufferListArray[listNum] .pBuffers->dataLenInBytes, &resultArray[listNum], &softChecksum); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "checkCrc32Checksum returned status %d " "for CPA_DC_CRC32 checksum\n", status); } break; case CPA_DC_ADLER32: softChecksum = 1; status = checkAdler32Checksum( srcBufferListArray[listNum].pBuffers->pData, srcBufferListArray[listNum] .pBuffers->dataLenInBytes, &resultArray[listNum], &softChecksum); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "checkAdler32Checksum returned status " "%d for CPA_DC_ADLER32 checksum\n", status); } break; case CPA_DC_CRC32_ADLER32: softChecksum = 0; status = checkCrc32Checksum( srcBufferListArray[listNum].pBuffers->pData, srcBufferListArray[listNum] .pBuffers->dataLenInBytes, &resultArray[listNum], &softChecksum); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "checkCrc32Checksum returned status %d " "for CPA_DC_CRC32_ADLER32 checksum\n", status); } softChecksum = 1; status = checkAdler32Checksum( srcBufferListArray[listNum].pBuffers->pData, srcBufferListArray[listNum] .pBuffers->dataLenInBytes, &resultArray[listNum], &softChecksum); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("checkAdler32Checksum returned " "status %d for " "CPA_DC_CRC32_ADLER32 checksum\n", status); } break; #if DC_API_VERSION_AT_LEAST(3, 0) default: PRINT_ERR( "Checksum is not currently supported, " "defaulting to no checksum\n"); setup->setupData.checksum = CPA_DC_NONE; break; #endif } } } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("qatCompressData returned status %d\n", status); break; } if (CPA_TRUE == stopTestsIsEnabled_g) { /* Check if terminated by global flag. * stop issuing new requests */ if (CPA_TRUE == exitLoopFlag_g) { break; } } } } else if (setup->dcSessDir == CPA_DC_DIR_DECOMPRESS && reliability_g == CPA_TRUE) { PRINT("Chaining Decompression need to be developed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != status) { qatDumpBufferListInfo(setup, srcBufferListArray, destBufferListArray, cmpBufferListArray, 0); } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { if (CPA_STATUS_SUCCESS != performDcChainOffloadCalculationBusyLoop(setup, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray, chainOpDataArray, dcCbFn, setup->dcSessDir, pSessionHandle)) { PRINT_ERR("performDcChainOffloadCalculationBusyLoop error\n"); } } coo_average(setup->performanceStats); coo_deinit(setup->performanceStats); /* Remove the session free the handle */ if (CPA_STATUS_SUCCESS != qatDcChainSessionTeardown( setup, &pSessionHandle, &pDecompressSessionHandle)) { PRINT_ERR("DcChainSessionTeardown error\n"); status = CPA_STATUS_FAIL; } } /* Free CpaFlatBuffers and privateMetaData in CpaBufferLists */ if (CPA_STATUS_SUCCESS != qatFreeCompressionFlatBuffers( setup, srcBufferListArray, destBufferListArray, cmpBufferListArray)) { PRINT_ERR("freeCompressionFlatBuffers error\n"); status = CPA_STATUS_FAIL; } dcChainOpDataMemFree(chainOpDataArray, setup->numLists, setup->numSessions); /* Free CpaBufferLists */ if (CPA_STATUS_SUCCESS != qatFreeCompressionLists(setup, &srcBufferListArray, &destBufferListArray, &cmpBufferListArray, NULL)) { PRINT_ERR("freeChainBuff error\n"); status = CPA_STATUS_FAIL; } /* Free CpaChainingLists */ if (CPA_STATUS_SUCCESS != qatFreeDcChainLists((void **)&resultArray, (void **)&chainOpDataArray)) { PRINT_ERR("freeChainList error\n"); status = CPA_STATUS_FAIL; } return status; } /*This is the performance thread created by the sample code framework * after registering the setupDcChainTest and calling createPeformance threads * this function copies the setup into its own local copy and then calls * scChainingPoc to measure compression performance*/ void dcChainPerformance(single_thread_test_data_t *testSetup) { compression_test_params_t dcSetup = {0}; compression_test_params_t *tmpSetup = NULL; Cpa16U numInstances = 0; CpaInstanceHandle *instances = NULL; CpaStatus status = CPA_STATUS_FAIL; Cpa32U node = 0; CpaDcInstanceCapabilities capabilities = {0}; CpaDcStats dcStats = {0}; /* Get the setup pointer */ tmpSetup = (compression_test_params_t *)(testSetup->setupPtr); testSetup->passCriteria = tmpSetup->passCriteria; dcSetup.passCriteria = tmpSetup->passCriteria; /* Update the setup structure with setup parameters */ memcpy(&dcSetup.requestOps, &tmpSetup->requestOps, sizeof(CpaDcOpData)); dcSetup.compRate = tmpSetup->compRate; dcSetup.compRate *= QAT_COMP_SCALING_FACTOR; /* Check number of threads types to look at number of threads for * Compression rate limit */ if (testSetupData_g[1].numberOfThreads > 0) { do_div(dcSetup.compRate, testSetupData_g[1].numberOfThreads); } else { do_div(dcSetup.compRate, numCreatedThreads_g); } dcSetup.specific_sleeptime_flag = tmpSetup->specific_sleeptime_flag; dcSetup.sleepTime = tmpSetup->sleepTime; dcSetup.chainOperation = tmpSetup->chainOperation; dcSetup.numSessions = tmpSetup->numSessions; dcSetup.bufferSize = tmpSetup->bufferSize; dcSetup.corpus = tmpSetup->corpus; dcSetup.setupData = tmpSetup->setupData; dcSetup.dcSessDir = tmpSetup->dcSessDir; dcSetup.syncFlag = tmpSetup->syncFlag; dcSetup.numLoops = tmpSetup->numLoops; dcSetup.useE2E = tmpSetup->useE2E; dcSetup.useE2EVerify = tmpSetup->useE2EVerify; dcSetup.disableAdditionalCmpbufferSize = tmpSetup->disableAdditionalCmpbufferSize; /* In case of E2E Verify we need to use CRC32 only */ if (dcSetup.useE2EVerify) dcSetup.setupData.checksum = CPA_DC_CRC32; /* Give our thread a unique memory location to store performance stats */ dcSetup.performanceStats = testSetup->performanceStats; dcSetup.performanceStats->numLoops = tmpSetup->numLoops; dcSetup.isDpApi = CPA_FALSE; testSetup->performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; testSetup->performanceStats->additionalStatus = CPA_STATUS_SUCCESS; dcSetup.symSetupData = tmpSetup->symSetupData; dcSetup.symIvLength = tmpSetup->symIvLength; dcSetup.legacyChainRequest = tmpSetup->legacyChainRequest; dcSetup.appendCRC = tmpSetup->appendCRC; dcSetup.testIntegrity = tmpSetup->testIntegrity; dcSetup.keyDerive = tmpSetup->keyDerive; status = calculateRequireBuffers(&dcSetup); if (CPA_STATUS_SUCCESS != status) { PRINT("Error calculating required buffers\n"); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } dcSetup.numLists = dcSetup.numberOfBuffers[dcSetup.corpusFileIndex]; if (CPA_STATUS_SUCCESS == status) { /*This barrier is to halt this thread when run in user space context, * the startThreads function releases this barrier, in kernel space is * does * nothing, but kernel space threads do not start * until we call startThreads anyway */ startBarrier(); /*Initialize the statsPrintFunc to dcChainPrintStats */ testSetup->statsPrintFunc = (stats_print_func_t)dcChainPrintStats; /* Get the number of instances */ status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR(" Unable to get number of DC instances\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { if (0 == numInstances) { PRINT_ERR(" DC Instances are not present\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { instances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == instances) { PRINT_ERR("Unable to allocate Memory for Instances\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { /* Get the instance handles so that we can start * our thread on the selected instance */ status = cpaDcGetInstances(numInstances, instances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to get DC instances\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { /* Give our thread a logical quick assist instance to use * use % to wrap around the max number of instances */ dcSetup.dcInstanceHandle = instances[(testSetup->logicalQaInstance) % numInstances]; if (enableReadInstance_g) { dcSetup.dcChainReadInsHandle = instances[(testSetup->logicalQaReadInstance) % numInstances]; } /* Find node that thread is running on */ status = sampleCodeDcGetNode(dcSetup.dcInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeDcGetNode error\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { status = allocateAndSetArrayOfPacketSizes(&(dcSetup.packetSizeInBytesArray), dcSetup.bufferSize, dcSetup.numLists); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("allocateAndSetArrayOfPacketSizes error\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } /* Check if dynamic compression is supported */ status = cpaDcQueryCapabilities(dcSetup.dcInstanceHandle, &capabilities); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaDcQueryCapabilities failed", __func__, __LINE__); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } if (CPA_FALSE == capabilities.dynamicHuffman && tmpSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("Dynamic is not supported on logical instance %d\n", (testSetup->logicalQaInstance) % numInstances); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } if (CPA_FALSE == CPA_BITMAP_BIT_TEST(capabilities.dcChainCapInfo, dcSetup.chainOperation)) { switch ((int)dcSetup.chainOperation) { case CPA_DC_CHAIN_HASH_THEN_COMPRESS: PRINT("Hash + compress chained operation is not supported on " "logical " "instance %d\n", (testSetup->logicalQaInstance) % numInstances); break; case CPA_DC_CHAIN_COMPRESS_THEN_AEAD: PRINT("Compress then Encrypt(AEAD) chained operation is not " "supported on logical " "instance %d\n", (testSetup->logicalQaInstance) % numInstances); break; case CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS: PRINT("Decrypt(AEAD) then Decompress chained operation is not " "supported on logical " "instance %d\n", (testSetup->logicalQaInstance) % numInstances); break; } QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } if (CNV_RECOVERY(&dcSetup.requestOps) == CPA_TRUE) { if (CNV_RECOVERY(&capabilities) == CPA_FALSE) { PRINT_ERR("CnVnR requested but not supported on instance\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } status = cpaDcGetStats(dcSetup.dcInstanceHandle, &dcStats); if (status == CPA_STATUS_SUCCESS) { testSetup->performanceStats->preTestRecoveryCount = GET_CNV_RECOVERY_COUNTERS(&dcStats); } else { testSetup->performanceStats->preTestRecoveryCount = 0; } } if (CPA_TRUE == dcSetup.useE2E) { PRINT("Do CRC integrity capabilities check for this instance. %d\n", testSetup->logicalQaInstance); if (CPA_FALSE == capabilities.integrityCrcs64b) { if (CPA_FALSE == capabilities.integrityCrcs) { PRINT("CRC integrity check is unsupported for this instance. " "%d\n", testSetup->logicalQaInstance); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; qaeMemFree((void **)&instances); qaeMemFree((void **)&dcSetup.numberOfBuffers); sampleCodeThreadExit(); } } } dcSetup.induceOverflow = CPA_FALSE; if (CPA_STATUS_SUCCESS == status) { /* Launch function that does all the work */ if (dcSetup.legacyChainRequest) { status = qatDcChainPerform(&dcSetup); } if (CPA_STATUS_SUCCESS != status) { dcChainPrintTestData(&dcSetup); PRINT_ERR("Compression Thread %u FAILED\n", testSetup->threadID); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /* Set the print function that can be used to print * statistics at the end of the test */ /* Update values from the framework peak ptr to thread local ptr to be * seen by print function */ testSetup->performanceStats->compRate = dcSetup.compRate; testSetup->performanceStats->sleepTime = dcSetup.sleepTime; testSetup->performanceStats->numLoops = dcSetup.numLoops; if ( (CPA_TRUE == CNV_RECOVERY(&dcSetup.requestOps))) { status = cpaDcGetStats(dcSetup.dcInstanceHandle, &dcStats); if (status == CPA_STATUS_SUCCESS) { testSetup->performanceStats->postTestRecoveryCount = GET_CNV_RECOVERY_COUNTERS(&dcStats); } else { testSetup->performanceStats->postTestRecoveryCount = 0; } } } err: if (dcSetup.packetSizeInBytesArray != NULL) { qaeMemFree((void **)&(dcSetup.packetSizeInBytesArray)); } if (instances != NULL) { qaeMemFree((void **)&instances); } if (dcSetup.numberOfBuffers != NULL) { qaeMemFree((void **)&dcSetup.numberOfBuffers); } if (CPA_STATUS_SUCCESS != status) { testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } sampleCodeThreadComplete(testSetup->threadID); } CpaStatus setupDcChainTest(CpaDcChainOperations chainOperation, Cpa8U numSessions, CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcHuffType huffmanType, CpaDcSessionState state, Cpa32U windowsSize, Cpa32U testBufferSize, corpus_type_t corpusType, sync_mode_t syncFlag, CpaCySymOp opType, CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymCipherDirection cipherDir, CpaCyPriority priority, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, Cpa32U numLoops) { compression_test_params_t *dcSetup = NULL; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sleepTime = 0; Cpa32U compRate = QAT_COMP_DEFAULT_COMP_RATE; Cpa32U corpusFileIndex = 0; /* Check that the sample code framework can register this test setup */ if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /* Check that at least 1 loop of the data set is to be submitted */ if (numLoops == 0) { PRINT_ERR("numLoops must be > 0\n"); return CPA_STATUS_FAIL; } /* Populate Corpus: copy from file on disk into memory*/ /* this method limits to compressing 1 corpus at any point in time */ if (corpusType == CORPUS_TYPE_EXTENDED) { corpusType = getCorpusType(); corpusFileIndex = getCorpusFileIndex(); } status = populateCorpus(testBufferSize, corpusType); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to load one or more corpus files, have they been " "extracted to %s?\n", SAMPLE_CODE_CORPUS_PATH); return CPA_STATUS_FAIL; } /* Start DC Services */ status = startDcServices(testBufferSize, TEMP_NUM_BUFFS); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error in Starting Dc Services\n"); return CPA_STATUS_FAIL; } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration * file */ if (CPA_STATUS_SUCCESS != dcCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } /* Get memory location from sample code framework to store setup details */ dcSetup = (compression_test_params_t *)&thread_setup_g[testTypeCount_g][0]; INIT_OPDATA_DEFAULT(&dcSetup->requestOps); /* If the setup is requesting non-default CnV behaviour for special * tests, set it accordingly. */ if (getSetupCnVRequestFlag() != CNV_FLAG_DEFAULT) { setCnVFlags(getSetupCnVRequestFlag(), &dcSetup->requestOps); } /* Set the performance function to the actual performance function * that actually does all the performance */ testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)dcChainPerformance; /* Update the setup_g with buffersize */ testSetupData_g[testTypeCount_g].packetSize = testBufferSize; /* Operation for compression chaining */ dcSetup->chainOperation = chainOperation; /* Number of sessions for compression chaining */ dcSetup->numSessions = numSessions; /* Data compression setup data */ dcSetup->setupData.compLevel = compLevel; dcSetup->setupData.compType = algorithm; dcSetup->setupData.sessDirection = direction; dcSetup->legacyChainRequest = 1; #ifdef SC_ENABLE_DYNAMIC_COMPRESSION dcSetup->setupData.huffType = huffmanType; #else dcSetup->setupData.huffType = CPA_DC_HT_STATIC; #endif dcSetup->setupData.sessState = state; dcSetup->specific_sleeptime_flag = CPA_FALSE; if (CPA_DC_STATELESS == state) { dcSetup->sleepTime = sleepTime; dcSetup->compRate = compRate; } #if DC_API_VERSION_LESS_THAN(1, 6) /* Windows size is depreciated in new versions of the QA-API */ dcSetup->setupData.deflateWindowSize = windowsSize; #endif dcSetup->corpus = corpusType; dcSetup->corpusFileIndex = corpusFileIndex; dcSetup->bufferSize = testBufferSize; dcSetup->dcSessDir = direction; dcSetup->syncFlag = syncFlag; dcSetup->numLoops = numLoops; dcSetup->isDpApi = CPA_FALSE; dcSetup->setupData.autoSelectBestHuffmanTree = gAutoSelectBestMode; dcSetup->setupData.checksum = gChecksum; dcSetup->passCriteria = getPassCriteria(); /* Stateful Compression only supports a single request in-flight for * each session. Each request can be submitted asynchronously but is * required to block until callback fires. * For the sample code we only issue Stateful requests synchronously. */ if (CPA_DC_STATEFUL == state) { PRINT_ERR("Stateful Compression not supported in this sample code\n"); } dcSetup->symSetupData.sessionPriority = priority; dcSetup->symSetupData.symOperation = opType; dcSetup->symSetupData.cipherSetupData.cipherAlgorithm = cipherAlg; dcSetup->symSetupData.cipherSetupData.cipherDirection = cipherDir; dcSetup->symSetupData.cipherSetupData.cipherKeyLenInBytes = cipherKeyLengthInBytes; dcSetup->symSetupData.hashSetupData.hashAlgorithm = hashAlg; dcSetup->symSetupData.hashSetupData.hashMode = hashMode; dcSetup->symSetupData.hashSetupData.digestResultLenInBytes = authKeyLengthInBytes; dcSetup->symSetupData.digestIsAppended = CPA_FALSE; dcSetup->symSetupData.verifyDigest = CPA_FALSE; return status; } static CpaStatus qatDcChainInduceOverflow(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaBufferList *srcBufferListArray, CpaBufferList *destBufferListArray, CpaBufferList *cmpBufferListArray, CpaDcChainRqResults *resultArray, CpaDcChainOpData *chainOpDataArray) { CpaStatus status = CPA_STATUS_FAIL; CpaDcChainRqResults *overflowResArray = NULL; Cpa32U numListOverflowed = 0; Cpa32U i, loop; const Cpa32U numLoops = setup->numLoops; const Cpa32U reductionFactor = 6; const Cpa32U lowerThresholdDstBufferSize = BUFFER_SIZE_128; Cpa32U *destBufferMemSize = NULL; const Cpa32U numLists = setup->numLists; overflowResArray = qaeMemAlloc(numLists * sizeof(CpaDcChainRqResults)); if (overflowResArray == NULL) { PRINT_ERR("Failed to Allocate Overflow Result Array\n"); return CPA_STATUS_FAIL; } destBufferMemSize = qaeMemAlloc(numLists * sizeof(Cpa32U)); if (destBufferMemSize == NULL) { PRINT_ERR("Malloc failed for size %llu\n", (unsigned long long)(numLists * sizeof(Cpa32U))); goto err; } setup->numLoops = 1; for (loop = 0; loop < numLoops; loop++) { /* Reduce the size of the destination buffer to * induce overflow */ for (i = 0; i < numLists; i++) { if (destBufferListArray[i].numBuffers > 1) { PRINT_ERR("Multiple Flat buffer per list not supported\n"); goto err; } /* Store the allocated size */ destBufferMemSize[i] = destBufferListArray[i].pBuffers[0].dataLenInBytes; /* Pretend that the capacity of Output buffer is less than input * buffer * by the amount of 2 ^ reductionFactor. */ destBufferListArray[i].pBuffers[0].dataLenInBytes = srcBufferListArray[i].pBuffers[0].dataLenInBytes >> reductionFactor; /* Adjust the length if it falls below threshold */ if (destBufferListArray[i].pBuffers[0].dataLenInBytes < lowerThresholdDstBufferSize) { destBufferListArray[i].pBuffers[0].dataLenInBytes = lowerThresholdDstBufferSize; } } /* Set value for chainOpData*/ status = qatDcChainCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray, chainOpDataArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to chaining compress Data with overflow setup\n"); goto err; } /* Check all that have overflowed and construct a new SGL to handle * remaining data. */ for (i = 0; i < numLists; i++) { if (resultArray[i].dcStatus == CPA_DC_OVERFLOW) { if (resultArray[i].consumed == 0 && resultArray[i].produced == 0) { PRINT_ERR("Overflow reported with no bytes produced or" " consumed for list: %d\n", i); status = CPA_STATUS_FAIL; goto err; } numListOverflowed++; /* Find the amount of data unconsumed */ srcBufferListArray[i].pBuffers[0].dataLenInBytes -= resultArray[i].consumed; srcBufferListArray[i].pBuffers[0].pData += resultArray[i].consumed; /* Update Output buffers for the amount of bytes produced. * From the amount of memory actually allocated for the buffer, * reduced the amount taken up by produced data. */ destBufferListArray[i].pBuffers[0].dataLenInBytes = destBufferMemSize[i] - resultArray[i].produced; destBufferListArray[i].pBuffers[0].pData += resultArray[i].produced; switch (setup->chainOperation) { case CPA_DC_CHAIN_COMPRESS_THEN_ENCRYPT: chainOpDataArray[i * setup->numSessions + 1] .pCySymOp->messageLenToCipherInBytes = srcBufferListArray[i].pBuffers[0].dataLenInBytes; break; case CPA_DC_CHAIN_DECRYPT_THEN_DECOMPRESS: chainOpDataArray[i * setup->numSessions] .pCySymOp->messageLenToCipherInBytes = srcBufferListArray[i].pBuffers[0].dataLenInBytes; break; case CPA_DC_CHAIN_HASH_THEN_COMPRESS: chainOpDataArray[i * setup->numSessions] .pCySymOp->messageLenToHashInBytes = srcBufferListArray[i].pBuffers[0].dataLenInBytes; break; default: PRINT_ERR("Unsupported chaining operation.\n"); status = CPA_STATUS_FAIL; goto err; } } else { /* The test design aims to induce overflow in each list of * the payload as the entire list array is submitted again. * However if some lists don't overflow even after output * buffer reduction, highlight the fact and ignore. */ PRINT("!!No Overflow reported for List Num: %d status: %d\n", i, resultArray[i].dcStatus); } } /* Post overflow processing for all lists*/ if (numListOverflowed == 0) { PRINT_ERR("No overflow detected for Loop count: %d\n", loop + 1); status = CPA_STATUS_FAIL; goto err; } if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to setup chaining operation data\n"); goto err; } /* Resubmits the bufferlist after updating buffers for overflow */ status = qatDcChainCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, overflowResArray, chainOpDataArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to compress unconsumed data after overflow\n"); goto err; } /* Recheck that there is no overflow now and update the produced length * to the sum of pre overflow and post overflow compression. */ for (i = 0; i < numLists; i++) { if (overflowResArray[i].dcStatus != CPA_DC_OVERFLOW) { if (overflowResArray[i].dcStatus != CPA_DC_OK) { PRINT("Status: %d reported post overflow for List %d\n", overflowResArray[i].dcStatus, i); } /* Check if the list element overflowed previously and * update accordingly. */ if (resultArray[i].dcStatus == CPA_DC_OVERFLOW) { destBufferListArray[i].pBuffers[0].dataLenInBytes = resultArray[i].produced + overflowResArray[i].produced; destBufferListArray[i].pBuffers[0].pData -= resultArray[i].produced; srcBufferListArray[i].pBuffers[0].dataLenInBytes = resultArray[i].consumed + overflowResArray[i].consumed; srcBufferListArray[i].pBuffers[0].pData -= resultArray[i].consumed; /* Update the first pass result Array to have the total of * bytes * produced and consumed from the two operations. */ resultArray[i].consumed += overflowResArray[i].consumed; resultArray[i].produced += overflowResArray[i].produced; /* Update stats here after the second call as performance * stats * are initialized on each call qatCompressData. */ setup->performanceStats->overflow++; } } /* status != OVERFLOW */ else { PRINT_ERR("Overflow reported AGAIN for list: %d\n", i); status = CPA_STATUS_FAIL; goto err; } } /* end of for loop for numLists */ /* Update the stats from with result array as it has sum * of pre and post overflow. */ dcChainScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, setup->dcSessDir); /* Perform Decompression using SW on the compressed * buffer. */ status = qatSwChainDecompress( setup, destBufferListArray, cmpBufferListArray, resultArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("SW Decompression Failed\n"); goto err; } qatDcChainUpdateProducedBufferLength( setup, cmpBufferListArray, resultArray); /* Compare the input buffer to SW decompressed buffer */ status = qatCmpBuffers(setup, srcBufferListArray, cmpBufferListArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Buffer comparison Failed for Loop count:%d\n", loop + 1); goto err; } /*reset destination buffer*/ status = qatCompressResetBufferList(setup, destBufferListArray, setup->packetSizeInBytesArray, CPA_FALSE); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to reset buffer lists\n"); goto err; } status = qatCompressResetBufferList( setup, cmpBufferListArray, setup->packetSizeInBytesArray, CPA_TRUE); if (stopTestsIsEnabled_g == CPA_TRUE && exitLoopFlag_g == CPA_TRUE) { break; } numListOverflowed = 0; } /* end of for loop for NumLoops */ err: qaeMemFree((void **)&destBufferMemSize); qaeMemFree((void **)&overflowResArray); return status; } qat_compression_cnv_utils.h000066400000000000000000000334201503624047500374160ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qat_compression_cnv_utils.h * * @defgroup compression * * @ingroup compression * * @description * Functions types and macros to determine CnV-E environment * Helper functions and macros to set the CnV flag in API * * ***************************************************************************/ #ifndef QAT_COMPRESSION_CNV_UTILS_H_ #define QAT_COMPRESSION_CNV_UTILS_H_ #ifdef USER_SPACE #include #endif #include "cpa_dc.h" #include "cpa_dc_dp.h" #define STRICT_BASE_OFFSET 16 #define LOOSE_BASE_OFFSET 0 #define STRICT_BIT_CNV (0x1 << (STRICT_BASE_OFFSET)) #define STRICT_BIT_CNVNR (0x1 << (STRICT_BASE_OFFSET + 1)) #define STRICT_BIT_CONDITIONAL_CNVNR (0x1 << (STRICT_BASE_OFFSET + 2)) #define LOOSE_BIT_CNV (0x1 << (LOOSE_BASE_OFFSET)) #define LOOSE_BIT_CNVNR (0x1 << (LOOSE_BASE_OFFSET + 1)) #define LOOSE_BIT_CONDITIONAL_CNVNR (0x1 << (LOOSE_BASE_OFFSET + 2)) /* Common macro definition for the API versions */ #ifndef DC_API_VERSION_AT_LEAST #define DC_API_VERSION_AT_LEAST(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR > major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR >= minor)) #endif /* Request Flag to set the CNV services accordingly */ /* Some of the request might not be valid for the mode but have been provided * to setup negative tests. The flag can contain request for both Strict * and Loose mode so that user does not have to query mode and set flags * accordingly. */ /* STRICT_NO_CNV : No CnV operation requested in strict mode */ #define STRICT_NO_CNV 0 /* STRICT_CNV_WITHOUT_RECOVERY : Perform CnV without Recovery in Strict mode. * The recovery is explicitly turned off so that the verification failures * are reported by the compression API. */ #define STRICT_CNV_WITHOUT_RECOVERY \ ((STRICT_BIT_CNV & ~STRICT_BIT_CNVNR) & ~STRICT_BIT_CONDITIONAL_CNVNR) /* STRICT_CNV_WITH_RECOVERY : Perform CnV with Recovery in strict mode. * Recovery is turned on WITHOUT checking the capability. This can be used * in negative tests. */ #define STRICT_CNV_WITH_RECOVERY \ ((STRICT_BIT_CNV | STRICT_BIT_CNVNR) & ~STRICT_BIT_CONDITIONAL_CNVNR) /* STRICT_CNV_CONDITIONAL_RECOVERY: Perform CnV with recovery if supported * in strict mode. The recovery is turned on only if the capability reports * that the recovery is supported else recovery is turned off. */ #define STRICT_CNV_CONDITIONAL_RECOVERY \ ((STRICT_BIT_CNV | STRICT_BIT_CNVNR) | STRICT_BIT_CONDITIONAL_CNVNR) /* LOOSE_NO_CNV : No CnV operation requested in LOOSE mode */ #define LOOSE_NO_CNV 0 /* LOOSE_CNV_WITHOUT_RECOVERY : Perform CnV without Recovery in LOOSE mode. * The recovery is explicitly turned off so that the verification failures * are reported by the compression API. */ #define LOOSE_CNV_WITHOUT_RECOVERY \ ((LOOSE_BIT_CNV & ~LOOSE_BIT_CNVNR) & ~LOOSE_BIT_CONDITIONAL_CNVNR) /* LOOSE_CNV_WITHOUT_RECOVERY : Perform CnV with Recovery in LOOSE mode. * Recovery is turned on without checking the capability. This can be used * in negative tests. */ #define LOOSE_CNV_WITH_RECOVERY \ ((LOOSE_BIT_CNV | LOOSE_BIT_CNVNR) & ~LOOSE_BIT_CONDITIONAL_CNVNR) /* LOOSE_CNV_CONDITIONAL_RECOVERY: Perform CnV with recovery if supported * in LOOSE mode. The recovery is turned on only if the capability reports * that the recovery is supported else recovery is turned off. */ #define LOOSE_CNV_CONDITIONAL_RECOVERY \ ((LOOSE_BIT_CNV | LOOSE_BIT_CNVNR) | LOOSE_BIT_CONDITIONAL_CNVNR) #define CNV_FLAG_DEFAULT (STRICT_CNV_CONDITIONAL_RECOVERY | LOOSE_NO_CNV) /* CNV mode capabilities is present in DC API version 2.1 and higher */ #if DC_API_VERSION_AT_LEAST(2, 1) #define CNV_MODE_STRICT(cap) (cap)->compressAndVerifyStrict #else #define CNV_MODE_STRICT(cap) CPA_FALSE #endif /* CNV with Recovery mode capability is present in DC API version 2.2 * and higher. This macro helps in getting cnv recovery data member in * various data structures depending on the DC API version. */ #if DC_API_VERSION_AT_LEAST(2, 2) #define DCDP_CNV(x) (x)->compressAndVerify #define SET_DCDP_CNV(x, v) (DCDP_CNV(x) = (v)) #define CNV_RECOVERY(x) (x)->compressAndVerifyAndRecover #define SET_CNV_RECOVERY(x, v) (CNV_RECOVERY(x) = v) #define GET_CNV_RECOVERY_COUNTERS(x) (x)->numCompCnvErrorsRecovered #else #define DCDP_CNV(x) (x)->reserved1 #define SET_DCDP_CNV(x, v) #define CNV_RECOVERY(x) CPA_FALSE #define SET_CNV_RECOVERY(x, v) #define GET_CNV_RECOVERY_COUNTERS(x) 0 #endif #define INIT_OPDATA_DEFAULT(x) \ INIT_OPDATA_FLAGS(x, CPA_DC_FLUSH_NONE, CNV_FLAG_DEFAULT) #define INIT_OPDATA_FLAGS(x, flush, cnvFlag) \ do \ { \ (x)->flushFlag = flush; \ (x)->inputSkipData.skipMode = CPA_DC_SKIP_DISABLED; \ (x)->outputSkipData.skipMode = CPA_DC_SKIP_DISABLED; \ setCnVFlags(cnvFlag, x); \ } while (0) #define SET_DC_DP_CNV_PARAMS_DEFAULT(x) setDcDpCnVFlags(CNV_FLAG_DEFAULT, x) static CpaStatus setCnVFlags(Cpa32U, CpaDcOpData *const) __attribute__((unused)); static CpaStatus setDcDpCnVFlags(Cpa32U req, CpaDcDpOpData *const opData) __attribute__((unused)); static const char *getCnVOpModeStr(const CpaDcOpData *const) __attribute__((unused)); static const char *getDpCnVOpModeStr(const CpaDcDpOpData *const) __attribute__((unused)); static CpaBoolean isCnVModeStrict(void) __attribute__((unused)); static const char *getCnVModeStr(const CpaBoolean cnv, const CpaBoolean cnvRecovery); static CpaStatus setCnVFlags(Cpa32U req, CpaDcOpData *const opData); static CpaStatus EvaluateCnVFlag(const CpaDcInstanceCapabilities *const cap, CpaBoolean *cnv, CpaBoolean *cnvr, Cpa32U cnvReqFlag); static CpaStatus getDcCapabilities(CpaDcInstanceCapabilities *capabilities); static CpaBoolean isCnVModeStrict(void) { CpaDcInstanceCapabilities cap = {0}; if (getDcCapabilities(&cap) != CPA_STATUS_SUCCESS) { return CPA_FALSE; } return CNV_MODE_STRICT(&cap); } static const char *getCnVOpModeStr(const CpaDcOpData *const opData) { return getCnVModeStr(opData->compressAndVerify, CNV_RECOVERY(opData)); } static const char *getDpCnVOpModeStr(const CpaDcDpOpData *const opData) { return getCnVModeStr(DCDP_CNV(opData), CNV_RECOVERY(opData)); } static const char *getCnVModeStr(const CpaBoolean cnv, const CpaBoolean cnvRecovery) { static const char *cmpOnly = "Compression Only"; static const char *cmpWithVer = "Compression with Verification"; static const char *cmpWithVerAndRec = "Compression with Verification and Recovery"; if (cnv == CPA_TRUE) { if (cnvRecovery == CPA_TRUE) { return cmpWithVerAndRec; } return cmpWithVer; } return cmpOnly; } static CpaStatus setDcDpCnVFlags(Cpa32U req, CpaDcDpOpData *const opData) { CpaDcInstanceCapabilities cap = {0}; CpaDcInstanceCapabilities *ptr = ∩ CpaBoolean cnv = CPA_FALSE; CpaBoolean cnvr = CPA_FALSE; CpaStatus status; if (getDcCapabilities(&cap) != CPA_STATUS_SUCCESS) { ptr = NULL; } status = EvaluateCnVFlag(ptr, &cnv, &cnvr, req); SET_DCDP_CNV(opData, cnv); SET_CNV_RECOVERY(opData, cnvr); return status; } static CpaStatus setCnVFlags(Cpa32U req, CpaDcOpData *const opData) { CpaDcInstanceCapabilities cap = {0}; CpaDcInstanceCapabilities *ptr = ∩ CpaBoolean cnv = CPA_FALSE; CpaBoolean cnvr = CPA_FALSE; CpaStatus status; if (getDcCapabilities(&cap) != CPA_STATUS_SUCCESS) { ptr = NULL; } status = EvaluateCnVFlag(ptr, &cnv, &cnvr, req); opData->compressAndVerify = cnv; SET_CNV_RECOVERY(opData, cnvr); return status; } static CpaStatus EvaluateCnVFlag(const CpaDcInstanceCapabilities *const cap, CpaBoolean *cnv, CpaBoolean *cnvr, Cpa32U cnvReqFlag) { CpaBoolean fwCnVRecoveryCapable = CPA_FALSE; /* Let the mode be loose by default for compatibility reasons. * for example: firmware that does not support strict/loose modes. */ CpaBoolean cnvModeStrict = CPA_FALSE; CpaBoolean cnvOpFlag = CPA_FALSE; CpaBoolean cnvnrOpFlag = CPA_FALSE; /* When capabilities are known, fill in the queried values */ if (cap != NULL) { fwCnVRecoveryCapable = CNV_RECOVERY(cap); cnvModeStrict = CNV_MODE_STRICT(cap); } if (cnvModeStrict == CPA_FALSE) { /* Set CNV Flag if Requested */ cnvOpFlag = cnvReqFlag & LOOSE_BIT_CNV ? CPA_TRUE : CPA_FALSE; /* Set CnVnR Flag if Requested */ cnvnrOpFlag = cnvReqFlag & LOOSE_BIT_CNVNR ? CPA_TRUE : CPA_FALSE; /* If CnVnR is requested on the condition that recovery should be done * only if fw supports it, update the cnvnr op flag according to the * firmware capability to do CnVnR. */ if (cnvnrOpFlag == CPA_TRUE && cnvReqFlag & LOOSE_BIT_CONDITIONAL_CNVNR) { cnvnrOpFlag = fwCnVRecoveryCapable; } } else { cnvOpFlag = cnvReqFlag & STRICT_BIT_CNV ? CPA_TRUE : CPA_FALSE; cnvnrOpFlag = cnvReqFlag & STRICT_BIT_CNVNR ? CPA_TRUE : CPA_FALSE; if (cnvnrOpFlag == CPA_TRUE && cnvReqFlag & STRICT_BIT_CONDITIONAL_CNVNR) { cnvnrOpFlag = fwCnVRecoveryCapable; } } *cnv = cnvOpFlag; *cnvr = cnvnrOpFlag; return CPA_STATUS_SUCCESS; } static CpaStatus getDcCapabilities(CpaDcInstanceCapabilities *capabilities) { CpaStatus status; CpaInstanceHandle instHandle; Cpa16U numInstances = 0; /* Get the number of instances */ status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) return CPA_STATUS_FAIL; if (numInstances == 0) return CPA_STATUS_FAIL; status = cpaDcGetInstances(1, &instHandle); if (status != CPA_STATUS_SUCCESS) return CPA_STATUS_FAIL; status = cpaDcQueryCapabilities(instHandle, capabilities); if (CPA_STATUS_SUCCESS != status) return CPA_STATUS_FAIL; return CPA_STATUS_SUCCESS; } #endif /* QAT_COMPRESSION_CNV_UTILS_H_ */ qat_compression_e2e.c000066400000000000000000000324221503624047500360570ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "qat_compression_main.h" #include "cpa_sample_code_dc_perf.h" #include "qat_perf_utils.h" #include "qat_compression_e2e.h" #ifdef KERNEL_SPACE #include #include #define CRC32_XOR_VALUE (0xffffffff) #else #include #endif CpaStatus qatCompressionE2EInit(compression_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; if (CPA_TRUE == setup->useE2E) { QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); if ((CPA_STATUS_SUCCESS == status) && (NULL == setup->e2e)) { setup->e2e = qaeMemAlloc(sizeof(qat_dc_e2e_t)); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup->e2e, status); if (CPA_STATUS_SUCCESS == status) { memset(setup->e2e, 0, sizeof(qat_dc_e2e_t)); setup->e2e->compCrcData.adler32 = 1; setup->e2e->compCrcData.crc32 = 0; setup->requestOps.integrityCrcCheck = setup->useE2E; setup->requestOps.inputSkipData.skipMode = CPA_DC_SKIP_DISABLED; setup->requestOps.outputSkipData.skipMode = CPA_DC_SKIP_DISABLED; setup->requestOps.verifyHwIntegrityCrcs = setup->useE2EVerify; setup->requestOps.pCrcData = &setup->e2e->compCrcData; } } } return status; } static Cpa32U crc32_checksum(Cpa32U inputChecksum, Cpa8U *pData, Cpa32U length) { Cpa32U resultChecksum = 0; #ifdef KERNEL_SPACE resultChecksum = crc32(inputChecksum ^ CRC32_XOR_VALUE, pData, length) ^ CRC32_XOR_VALUE; #else resultChecksum = crc32(inputChecksum, pData, length); #endif return resultChecksum; } static CpaStatus computeSglChecksum(CpaBufferList *inputBuff, const Cpa32U computationSize, const CpaDcChecksum checksumType, Cpa32U *swChecksum) { Cpa32U numBuffs = 0; Cpa32U lenLeft = 0; Cpa32U totalLen = 0; Cpa32U status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(inputBuff, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(swChecksum, status); if (CPA_STATUS_SUCCESS == status) { for (numBuffs = 0; numBuffs < inputBuff->numBuffers; numBuffs++) { totalLen += inputBuff->pBuffers[numBuffs].dataLenInBytes; if (totalLen > computationSize) { totalLen -= inputBuff->pBuffers[numBuffs].dataLenInBytes; lenLeft = computationSize - totalLen; if (CPA_DC_CRC32 == checksumType) { *swChecksum = crc32_checksum(*swChecksum, inputBuff->pBuffers[numBuffs].pData, lenLeft); } break; } else { lenLeft = inputBuff->pBuffers[numBuffs].dataLenInBytes; } if (CPA_DC_CRC32 == checksumType) { *swChecksum = crc32_checksum( *swChecksum, inputBuff->pBuffers[numBuffs].pData, lenLeft); } } } return status; } #ifdef SC_CHAINING_ENABLED CpaStatus qatDcChainE2EVerify(compression_test_params_t *setup, CpaBufferList *srcBufferList, CpaBufferList *dstBufferList, CpaDcChainRqResults *results) { CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(srcBufferList, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(dstBufferList, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(results, status); if ((CPA_STATUS_SUCCESS == status) && (CPA_TRUE == setup->useE2E)) { /* Verify integrity CRCs (iCrc + oCrc) */ /* Calculate CRC on the input buffer list.*/ status = computeSglChecksum(srcBufferList, results->consumed, CPA_DC_CRC32, &(setup->e2e->swInputChecksum)); if (CPA_STATUS_SUCCESS == status) { if (setup->requestOps.pCrcData->integrityCrc.iCrc != setup->e2e->swInputChecksum) { PRINT("Checksum error! SW input checksum: 0x%08x" " - HW checksum: 0x%08x\n", setup->e2e->swInputChecksum, setup->requestOps.pCrcData->integrityCrc.iCrc); PRINT("COMPRESSION consumed: %d, produced: %d," "checksum: 0x%08x, status: %d\n", results->consumed, results->produced, results->crc32, results->dcStatus); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /* Calculate CRC on the output buffer list.*/ status = computeSglChecksum(dstBufferList, results->produced, CPA_DC_CRC32, &(setup->e2e->swOutputChecksum)); if ((CPA_STATUS_SUCCESS == status) && (setup->requestOps.pCrcData->integrityCrc.oCrc != setup->e2e->swOutputChecksum)) { PRINT("Checksum error! SW output checksum: 0x%08x" " - HW checksum: 0x%08x\n", setup->e2e->swOutputChecksum, setup->requestOps.pCrcData->integrityCrc.oCrc); PRINT("COMPRESSION consumed: %d, produced: %d," "checksum: 0x%08x, status: %d\n", results->consumed, results->produced, results->crc32, results->dcStatus); status = CPA_STATUS_FAIL; } } } } return status; } #endif CpaStatus qatCompressionE2EVerify(compression_test_params_t *setup, CpaBufferList *srcBufferList, CpaBufferList *dstBufferList, CpaDcRqResults *results) { CpaStatus status = CPA_STATUS_SUCCESS; CpaDcInstanceCapabilities capabilities = { 0 }; CpaBufferList *tempSrcBufferList = NULL; CpaBufferList *tempDstBufferList = NULL; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(srcBufferList, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(dstBufferList, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(results, status); if ((CPA_STATUS_SUCCESS == status) && (CPA_TRUE == setup->useE2E)) { if (setup->dcSessDir == CPA_DC_DIR_COMPRESS) { tempSrcBufferList = srcBufferList; tempDstBufferList = dstBufferList; } else { tempSrcBufferList = dstBufferList; tempDstBufferList = srcBufferList; } status = cpaDcQueryCapabilities(setup->dcInstanceHandle, &capabilities); if (CPA_STATUS_SUCCESS != status) { PRINT("%s::%d cpaDcQueryCapabilities failed", __func__, __LINE__); status = CPA_STATUS_FAIL; } if ((CPA_TRUE == capabilities.integrityCrcs) && (CPA_STATUS_SUCCESS == status)) { #if DC_API_VERSION_AT_LEAST(3, 2) /* For Stateless case do not seed previous E2E checksum*/ if (setup->setupData.sessState == CPA_DC_STATELESS) { setup->e2e->swInputChecksum = 0; setup->e2e->swOutputChecksum = 0; } #endif /* Verify integrity CRCs (iCrc + oCrc) */ /* Calculate CRC on the input buffer list.*/ status = computeSglChecksum(tempSrcBufferList, results->consumed, CPA_DC_CRC32, &(setup->e2e->swInputChecksum)); if (CPA_STATUS_SUCCESS == status) { if (setup->requestOps.pCrcData->integrityCrc.iCrc != setup->e2e->swInputChecksum) { PRINT("Checksum error! SW input checksum: 0x%08x" " - HW checksum: 0x%08x\n", setup->e2e->swInputChecksum, setup->requestOps.pCrcData->integrityCrc.iCrc); PRINT("COMPRESSION consumed: %d, produced: %d," "checksum: 0x%08x, status: %d\n", results->consumed, results->produced, results->checksum, results->status); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /* Calculate CRC on the output buffer list.*/ status = computeSglChecksum(tempDstBufferList, results->produced, CPA_DC_CRC32, &(setup->e2e->swOutputChecksum)); if ((CPA_STATUS_SUCCESS == status) && (setup->requestOps.pCrcData->integrityCrc.oCrc != setup->e2e->swOutputChecksum)) { PRINT("Checksum error! SW output checksum: 0x%08x" " - HW checksum: 0x%08x\n", setup->e2e->swOutputChecksum, setup->requestOps.pCrcData->integrityCrc.oCrc); PRINT("COMPRESSION consumed: %d, produced: %d," "checksum: 0x%08x, status: %d\n", results->consumed, results->produced, results->checksum, results->status); status = CPA_STATUS_FAIL; } } } } } return status; } qat_compression_e2e.h000066400000000000000000000154551503624047500360730ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qat_compression_e2e.h * * * @ingroup sampleCode * * @description This module defines functions that show how to * use the end2end feature * * *****************************************************************************/ #ifndef QAT_COMPRESSION_E2E_H_ #define QAT_COMPRESSION_E2E_H_ /** ***************************************************************************** * @file qat_compression_e2e.h * * @ingroup sample_code * * @description initialize the e2e members in the compression * setup structure * * @param[in] setup pointer to the compress test parameters * * * @pre setup points to an allocated memory location * * @post e2e members in the setup structure are * Initialized * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL could to initialize the setup structure ****************************************************************************/ CpaStatus qatCompressionE2EInit(compression_test_params_t *setup); /** ***************************************************************************** * @file qat_compression_e2e.h * * @ingroup sample_code * * @description this function verifies the end2end status of * a compression request * * @param[in] setup pointer to the compress test parameters * @param[in] srcBufferList pointer to the source buffer that was compressed * @param[in] dstBufferList pointer to the compressed output * @param[in] results pointer to the results structure used for each * compression request on scrBufferList * * * @pre source data has already been compressed into dst * buffer * * @post internal crcs are checked * * @retval CPA_STATUS_SUCCESS dstBufferData shows no internal error occurred *on the data compressed * * * @retval CPA_STATUS_FAIL the dst data has been compromised ****************************************************************************/ CpaStatus qatCompressionE2EVerify(compression_test_params_t *setup, CpaBufferList *srcBufferList, CpaBufferList *dstBufferList, CpaDcRqResults *results); #ifdef SC_CHAINING_ENABLED /** ***************************************************************************** * @file qat_compression_e2e.h * * @ingroup sample_code * * @description this function verifies the end2end status of * a compression request * * @param[in] setup pointer to the compress test parameters * @param[in] srcBufferList pointer to the source buffer that was compressed * @param[in] dstBufferList pointer to the compressed output * @param[in] results pointer to the results structure used for each * compression request on scrBufferList * * * @pre source data has already been compressed into dst * buffer * * @post internal crcs are checked * * @retval CPA_STATUS_SUCCESS dstBufferData shows no internal error occurred *on the data compressed * * * @retval CPA_STATUS_FAIL the dst data has been compromised ****************************************************************************/ CpaStatus qatDcChainE2EVerify(compression_test_params_t *setup, CpaBufferList *srcBufferList, CpaBufferList *dstBufferList, CpaDcChainRqResults *results); #endif #endif /* QAT_COMPRESSION_E2E_H_ */ qat_compression_main.c000066400000000000000000002206341503624047500363340ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "cpa_sample_code_dc_utils.h" #include "cpa_dc.h" #include "qat_compression_main.h" #include "icp_sal_poll.h" #include "qat_perf_latency.h" #include "qat_perf_sleeptime.h" #include "qat_compression_e2e.h" #include "qat_perf_cycles.h" #include "busy_loop.h" #include "icp_sal_user.h" #include "qat_perf_utils.h" extern void dcPerformCallback(void *pCallbackTag, CpaStatus status); extern CpaStatus createStartandWaitForCompletion(Cpa32U instType); #define COUNT_RESPONSES dcPerformCallback(setup, status) #define RESET_PERF_STATS(perfStats, numLists, numLoops) \ do \ { \ perfStats->responses = 0; \ perfStats->submissions = 0; \ perfStats->retries = 0; \ perfStats->pollRetries = 0; \ perfStats->nextPoll = 0; \ perfStats->numOperations = 0; \ coo_deinit(perfStats); \ coo_init(perfStats, (Cpa64U)numLists *(Cpa64U)numLoops); \ qatFreeLatency(perfStats); \ qatInitLatency(perfStats, numLists, numLoops); \ } while (0) static CpaStatus qatInduceOverflow(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaBufferList *srcBufferListArray, CpaBufferList *destBufferListArray, CpaBufferList *cmpBufferListArray, CpaDcRqResults *resultArray); static CpaStatus setupDcCommonTest(compression_test_params_t *dcSetup, CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcSessionState state, Cpa32U testBufferSize, corpus_type_t corpusType, sync_mode_t syncFlag, Cpa32U numLoops); CpaStatus qatDcSubmitRequest(compression_test_params_t *setup, const CpaInstanceInfo2 *pInstanceInfo2, CpaDcSessionDir compressDirection, CpaDcSessionHandle pSessionHandle, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, Cpa32U listNum, CpaDcRqResults *arrayOfResults); #if DC_API_VERSION_AT_LEAST(3, 1) CpaStatus setupDcLZ4Test(CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcSessionState state, Cpa32U testBufferSize, corpus_type_t corpusType, CpaDcCompMinMatch minMatch, CpaDcCompLZ4BlockMaxSize lz4BlockMaxSize, sync_mode_t syncFlag, Cpa32U numLoops) { CpaStatus status = CPA_STATUS_SUCCESS; /* get memory location from sample code framework to store setup details*/ compression_test_params_t *dcSetup = NULL; dcSetup = (compression_test_params_t *)&thread_setup_g[testTypeCount_g][0]; /*Assign unique values used only by LZ4 */ dcSetup->setupData.minMatch = minMatch; dcSetup->setupData.lz4BlockMaxSize = lz4BlockMaxSize; dcSetup->setupData.lz4BlockIndependence = LZ4BlockIndependence_g; status = setupDcCommonTest(dcSetup, algorithm, direction, compLevel, state, testBufferSize, corpusType, syncFlag, numLoops); return status; } EXPORT_SYMBOL(setupDcLZ4Test); #endif /*register a test with the sample code framework*/ CpaStatus setupDcTest(CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcHuffType huffmanType, CpaDcSessionState state, Cpa32U windowSize, Cpa32U testBufferSize, corpus_type_t corpusType, sync_mode_t syncFlag, Cpa32U numLoops) { CpaStatus status = CPA_STATUS_SUCCESS; /* get memory location from sample code framework to store setup details*/ compression_test_params_t *dcSetup = NULL; dcSetup = (compression_test_params_t *)&thread_setup_g[testTypeCount_g][0]; /*Assign unique values used only by deflate */ #ifdef SC_ENABLE_DYNAMIC_COMPRESSION dcSetup->setupData.huffType = huffmanType; #else dcSetup->setupData.huffType = CPA_DC_HT_STATIC; #endif #if DC_API_VERSION_LESS_THAN(1, 6) /*windows size is depreciated in new versions of the QA-API*/ dcSetup->setupData.deflateWindowSize = windowSize; #endif #if DC_API_VERSION_AT_LEAST(3, 1) /*deflateWindowSize is deprecated in new versions of the QA-API*/ dcSetup->setupData.windowSize = windowSize; #endif status = setupDcCommonTest(dcSetup, algorithm, direction, compLevel, state, testBufferSize, corpusType, syncFlag, numLoops); return status; } EXPORT_SYMBOL(setupDcTest); CpaStatus setupDcStatefulTest(CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcHuffType huffmanType, Cpa32U testBufferSize, corpus_type_t corpusType, sync_mode_t syncFlag, Cpa32U numLoops) { CpaStatus status = CPA_STATUS_SUCCESS; status = setupDcTest(algorithm, direction, compLevel, huffmanType, CPA_DC_STATEFUL, DEFAULT_COMPRESSION_WINDOW_SIZE, testBufferSize, corpusType, syncFlag, numLoops); return status; } EXPORT_SYMBOL(setupDcStatefulTest); static CpaStatus setupDcCommonTest(compression_test_params_t *dcSetup, CpaDcCompType algorithm, CpaDcSessionDir direction, CpaDcCompLvl compLevel, CpaDcSessionState state, Cpa32U testBufferSize, corpus_type_t corpusType, sync_mode_t syncFlag, Cpa32U numLoops) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U corpusFileIndex = 0; /* check that the sample code framework can register this test setup */ if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /* check that at least 1 loop of the data set is to be submitted*/ if (numLoops == 0) { PRINT_ERR("numLoops must be > 0\n"); return CPA_STATUS_FAIL; } /* Populate Corpus: copy from file on disk into memory*/ /* this method limits to compressing 1 corpus at any point in time */ if (corpusType == CORPUS_TYPE_EXTENDED) { corpusType = getCorpusType(); corpusFileIndex = getCorpusFileIndex(); } status = populateCorpus(testBufferSize, corpusType); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to load one or more corpus files, have they been " "extracted to %s?\n", SAMPLE_CODE_CORPUS_PATH); return CPA_STATUS_FAIL; } /*Start DC Services */ status = startDcServices(testBufferSize, TEMP_NUM_BUFFS); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error in Starting Dc Services\n"); return CPA_STATUS_FAIL; } if (iaCycleCount_g) { #ifdef POLL_INLINE enablePollInline(); #endif } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration * file */ if (CPA_STATUS_SUCCESS != dcCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } INIT_OPDATA_DEFAULT(&dcSetup->requestOps); /* If the setup is requesting non-default CnV behaviour for special * tests, set it accordingly. */ dcSetup->setNsRequest = isNsRequest_g; if (direction == CPA_DC_DIR_COMPRESS) { dcSetup->useE2E = dataIntegrity_g; dcSetup->useE2EVerify = dataIntegrityVerify_g; } if (getSetupCnVRequestFlag() != CNV_FLAG_DEFAULT) { setCnVFlags(getSetupCnVRequestFlag(), &dcSetup->requestOps); } /* Set the performance function to the actual performance function * that actually does all the performance */ testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)dcPerformance; /* register the test buffersize */ testSetupData_g[testTypeCount_g].packetSize = testBufferSize; if (CPA_FALSE == gUseStatefulLite) { dcSetup->useStatefulLite = CPA_FALSE; } /* Data compression setup data */ dcSetup->setupData.compLevel = compLevel; dcSetup->setupData.compType = algorithm; dcSetup->setupData.sessDirection = direction; if (dcSetup->setNsRequest == CPA_TRUE) { dcSetup->setupData.sessState = CPA_DC_STATELESS; } else { dcSetup->setupData.sessState = state; } dcSetup->corpus = corpusType; dcSetup->corpusFileIndex = corpusFileIndex; dcSetup->bufferSize = testBufferSize; dcSetup->dcSessDir = direction; dcSetup->syncFlag = syncFlag; dcSetup->numLoops = numLoops; dcSetup->isDpApi = CPA_FALSE; dcSetup->disableAdditionalCmpbufferSize = disableAdditionalCmpbufferSize_g; dcSetup->setupData.autoSelectBestHuffmanTree = gAutoSelectBestMode; dcSetup->setupData.checksum = gChecksum; dcSetup->passCriteria = getPassCriteria(); return status; } /*this is the performance thread created by the sample code framework * after registering the setupScDcTest and calling createPeformance threads * this function copies the setup into its own local copy and then calls scDcPoc * to measure compression performance*/ void dcPerformance(single_thread_test_data_t *testSetup) { compression_test_params_t dcSetup = {0}; compression_test_params_t *tmpSetup = NULL; Cpa16U numInstances = 0; CpaInstanceHandle *instances = NULL; CpaStatus status = CPA_STATUS_FAIL; CpaDcInstanceCapabilities capabilities = {0}; /* Get the setup pointer */ tmpSetup = (compression_test_params_t *)(testSetup->setupPtr); testSetup->passCriteria = tmpSetup->passCriteria; dcSetup.passCriteria = tmpSetup->passCriteria; #if DC_API_VERSION_AT_LEAST(3, 2) && \ (defined(SC_WITH_QAT20) || defined(SC_WITH_QAT20_UPSTREAM)) && \ !defined(SC_BSD_UPSTREAM) dcSetup.dcSessionCrcControlData = tmpSetup->dcSessionCrcControlData; #endif /* update the setup structure with setup parameters */ memcpy(&dcSetup.requestOps, &tmpSetup->requestOps, sizeof(CpaDcOpData)); dcSetup.useStatefulLite = tmpSetup->useStatefulLite; dcSetup.bufferSize = tmpSetup->bufferSize; dcSetup.corpus = tmpSetup->corpus; dcSetup.corpusFileIndex = tmpSetup->corpusFileIndex; dcSetup.setupData = tmpSetup->setupData; dcSetup.dcSessDir = tmpSetup->dcSessDir; dcSetup.syncFlag = tmpSetup->syncFlag; dcSetup.numLoops = tmpSetup->numLoops; dcSetup.setupData.checksum = tmpSetup->setupData.checksum; dcSetup.setNsRequest = tmpSetup->setNsRequest; dcSetup.useE2E = tmpSetup->useE2E; dcSetup.useE2EVerify = tmpSetup->useE2EVerify; /*give our thread a unique memory location to store performance stats*/ dcSetup.performanceStats = testSetup->performanceStats; dcSetup.performanceStats->averagePacketSizeInBytes = testSetup->packetSize; dcSetup.performanceStats->numLoops = tmpSetup->numLoops; dcSetup.isDpApi = CPA_FALSE; dcSetup.disableAdditionalCmpbufferSize = tmpSetup->disableAdditionalCmpbufferSize; testSetup->performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; testSetup->performanceStats->additionalStatus = CPA_STATUS_SUCCESS; status = calculateRequireBuffers(&dcSetup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calculating required buffers\n"); testSetup->performanceStats->threadReturnStatus = status; return; } dcSetup.numLists = dcSetup.numberOfBuffers[dcSetup.corpusFileIndex]; if (CPA_STATUS_SUCCESS == status) { /*this barrier is to halt this thread when run in user space context, * the startThreads function releases this barrier, in kernel space is * does nothing, but kernel space threads do not start until we call * startThreads anyway */ startBarrier(); /*Initialize the statsPrintFunc to NULL, the dcPrintStats function will * be assigned if compression completes successfully */ testSetup->statsPrintFunc = NULL; /* Get the number of instances */ status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR(" Unable to get number of DC instances\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { if (0 == numInstances) { PRINT_ERR(" DC Instances are not present\n"); status = CPA_STATUS_FAIL; QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { instances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == instances) { PRINT_ERR("Unable to allocate Memory for Instances\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /*get the instance handles so that we can start * our thread on the selected instance */ status = cpaDcGetInstances(numInstances, instances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR(" Unable to get DC instances\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { /* give our thread a logical quick assist instance to use * use % to wrap around the max number of instances*/ dcSetup.dcInstanceHandle = instances[(testSetup->logicalQaInstance) % numInstances]; // find node that thread is running on status = sampleCodeDcGetNode(dcSetup.dcInstanceHandle, &dcSetup.node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeDcGetNode error\n"); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } if (CPA_STATUS_SUCCESS == status) { status = allocateAndSetArrayOfPacketSizes(&(dcSetup.packetSizeInBytesArray), dcSetup.bufferSize, dcSetup.numLists); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d allocateAndSetArrayOfPacketSizes failed", __func__, __LINE__); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } } /*check if dynamic compression is supported*/ status = cpaDcQueryCapabilities(dcSetup.dcInstanceHandle, &capabilities); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaDcQueryCapabilities failed", __func__, __LINE__); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } if (CPA_FALSE == capabilities.dynamicHuffman && tmpSetup->setupData.huffType == CPA_DC_HT_FULL_DYNAMIC) { PRINT("Dynamic is not supported on logical instance %d\n", (testSetup->logicalQaInstance) % numInstances); QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } #if DC_API_VERSION_AT_LEAST(3, 1) if ((CPA_DC_STATELESS == tmpSetup->setupData.sessState) && (CPA_DC_LZ4 == tmpSetup->setupData.compType) && ((CPA_FALSE == capabilities.statelessLZ4Compression) || (CPA_FALSE == capabilities.statelessLZ4Decompression))) { PRINT("LZ4 is not supported on logical instance %d\n", (testSetup->logicalQaInstance) % numInstances); status = CPA_STATUS_UNSUPPORTED; QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } if ((CPA_DC_STATELESS == tmpSetup->setupData.sessState) && (CPA_DC_LZ4S == tmpSetup->setupData.compType) && ((CPA_FALSE == capabilities.statelessLZ4Compression) || (CPA_FALSE == capabilities.statelessLZ4Decompression))) { PRINT("LZ4s is not supported on logical instance %d\n", (testSetup->logicalQaInstance) % numInstances); status = CPA_STATUS_UNSUPPORTED; QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } #endif if (CPA_STATUS_SUCCESS != qatDcGetPreTestRecoveryCount( &dcSetup, &capabilities, testSetup->performanceStats)) { QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); } if (CPA_TRUE == dcSetup.useE2E) { PRINT("Do CRC integrity capabilities check for this instance. %d\n", testSetup->logicalQaInstance); if (CPA_FALSE == capabilities.integrityCrcs64b) { if (CPA_FALSE == capabilities.integrityCrcs) { PRINT("CRC integrity check is unsupported for this instance. " "%d\n", testSetup->logicalQaInstance); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_UNSUPPORTED; status = CPA_STATUS_UNSUPPORTED; QAT_PERF_FAIL_WAIT_AND_GOTO_LABEL(testSetup, err); qaeMemFree((void **)&instances); qaeMemFree((void **)&dcSetup.numberOfBuffers); qaeMemFree((void **)&dcSetup.packetSizeInBytesArray); sampleCodeThreadExit(); } } } if (CPA_TRUE == dcSetup.useXlt && ASYNC == dcSetup.syncFlag) { PRINT("Async mode not supported in Xlt[%d]\n", dcSetup.useXlt); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&instances); qaeMemFree((void **)&dcSetup.numberOfBuffers); qaeMemFree((void **)&dcSetup.packetSizeInBytesArray); sampleCodeThreadExit(); } dcSetup.induceOverflow = CPA_FALSE; dcSetup.threadID = testSetup->threadID; if (CPA_STATUS_SUCCESS == status) { /*launch function that does all the work*/ status = qatDcPerform(&dcSetup); if (CPA_STATUS_SUCCESS != status) { dcPrintTestData(&dcSetup); PRINT_ERR("Compression Thread %u FAILED\n", testSetup->threadID); testSetup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /*set the print function that can be used to print * statistics at the end of the test * */ // update values from the framework peak ptr to thread local ptr to be // seen by print function testSetup->performanceStats->numLoops = dcSetup.numLoops; testSetup->statsPrintFunc = (stats_print_func_t)dcPrintStats; qatDcGetPostTestRecoveryCount(&dcSetup, testSetup->performanceStats); } if ((CPA_STATUS_SUCCESS != status) || (testSetup->performanceStats->threadReturnStatus == CPA_STATUS_FAIL)) { // In case of test failure stopDcServicesFromPrintStats function call // from waitForThreadCompletion function stops the dc services and not // print the performance stats. testSetup->statsPrintFunc = (stats_print_func_t)stopDcServicesFromPrintStats; } err: if (dcSetup.packetSizeInBytesArray != NULL) { qaeMemFree((void **)&(dcSetup.packetSizeInBytesArray)); } if (instances != NULL) { qaeMemFree((void **)&instances); } if (dcSetup.numberOfBuffers != NULL) { qaeMemFree((void **)&dcSetup.numberOfBuffers); } if (CPA_STATUS_SUCCESS != status) { testSetup->performanceStats->threadReturnStatus = status; } sampleCodeThreadComplete(testSetup->threadID); } EXPORT_SYMBOL(dcPerformance); /*allocates buffers store a file for compression. The buffers are sent to * hardware, performance is recorded and stored in the setup parameter * the sample code framework prints out results after the thread completes*/ CpaStatus qatDcPerform(compression_test_params_t *setup) { /*** store file in array of CpaBufferLists: arrayOfSrcBufferLists[0].CpaFlatBuffer.pData <-startOfFile arrayOfSrcBufferLists[0].CpaFlatBuffer.bufferSizeInBytes . . . arrayOfSrcBufferLists[n].CpaFlatBuffer.pData <-endOfFile arrayOfSrcBufferLists[n].CpaFlatBuffer.bufferSizeInBytes where bufferSizeInBytes = testBufferSize n = numberOfLists required of the above mentioned size, required to store the file ***/ CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U *testBufferSize = setup->packetSizeInBytesArray; Cpa32U numberOfBuffersPerList = dc_bufferCount_g; CpaBufferList *srcBufferListArray = NULL; CpaBufferList *destBufferListArray = NULL; CpaBufferList *cmpBufferListArray = NULL; CpaDcRqResults *resultArray = NULL; CpaDcSessionHandle pSessionHandle = NULL; CpaDcSessionHandle pDecompressSessionHandle = NULL; CpaBufferList contextBuffer = {0}; CpaDcCallbackFn dcCbFn = dcPerformCallback; Cpa32U numLoops = 0; Cpa32U i = 0; int latency_enable_flag = latency_enable; const corpus_file_t *const fileArray = getFilesInCorpus(setup->corpus); saveClearRestorePerfStats(setup->performanceStats); coo_init(setup->performanceStats, (Cpa64U)setup->numLists * (Cpa64U)setup->numLoops); // allocate memory for source & destination bufferLists and results status = qatAllocateCompressionLists(setup, &srcBufferListArray, &destBufferListArray, &cmpBufferListArray, &resultArray); // Allocate the CpaFlatBuffers in each list if (CPA_STATUS_SUCCESS == status) { status = qatAllocateCompressionFlatBuffers(setup, srcBufferListArray, numberOfBuffersPerList, testBufferSize, destBufferListArray, numberOfBuffersPerList, testBufferSize, cmpBufferListArray, numberOfBuffersPerList, testBufferSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate all flat buffers for compression\n"); } } // copy corpus data into allocated buffers if (CPA_STATUS_SUCCESS == status) { status = PopulateBuffers( srcBufferListArray, setup->numLists, fileArray[setup->corpusFileIndex].corpusBinaryData, fileArray[setup->corpusFileIndex].corpusBinaryDataLen, testBufferSize); } if (CPA_FALSE == setup->setNsRequest) { // Initialize the compression session to use if (CPA_STATUS_SUCCESS == status) { status = qatCompressionSessionInit(setup, &pSessionHandle, &pDecompressSessionHandle, &contextBuffer, dcCbFn); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("compressionSessionInit returned status %d\n", status); } } } /*CNV Error Injection*/ /* compress the data */ if (CPA_STATUS_SUCCESS == status) { if (setup->induceOverflow == CPA_TRUE) { status = qatInduceOverflow(setup, pSessionHandle, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray); } else if (setup->dcSessDir == CPA_DC_DIR_COMPRESS && reliability_g == CPA_FALSE) { status = qatCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray); qatDcUpdateProducedBufferLength( setup, destBufferListArray, resultArray); dcScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, setup->dcSessDir); } else if (setup->dcSessDir == CPA_DC_DIR_DECOMPRESS && reliability_g == CPA_FALSE) { /*copy numLoops, set setup->numLoops to 1 to compress data, then * restore setup->numLoops to measure decompress performance*/ numLoops = setup->numLoops; setup->numLoops = 1; /* below qatCompressData() is invoked to generate compressed * test data that would be used for actual DECOMPRESSION test. * Hence disabling latency and COO measurement for below * COMPRESSION operation. */ latency_enable = 0; coo_deinit(setup->performanceStats); status = qatCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray); /* Restore latency and COO measurement */ latency_enable = latency_enable_flag; coo_init(setup->performanceStats, (Cpa64U)setup->numLists * (Cpa64U)setup->numLoops); qatDcUpdateProducedBufferLength( setup, destBufferListArray, resultArray); if (CPA_STATUS_SUCCESS == status) { /*restore setup->NumLoops*/ setup->numLoops = numLoops; if (setup->e2e) { setup->e2e->swInputChecksum = 0x0; setup->e2e->swOutputChecksum = 0x0; } RESET_PERF_STATS( setup->performanceStats, setup->numLists, setup->numLoops); status = qatCompressData(setup, pDecompressSessionHandle, CPA_DC_DIR_DECOMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray); dcScSetBytesProducedAndConsumed(resultArray, setup->performanceStats, setup, setup->dcSessDir); qatDcUpdateProducedBufferLength( setup, cmpBufferListArray, resultArray); } } else if (setup->dcSessDir == CPA_DC_DIR_COMPRESS && reliability_g == CPA_TRUE) { /*copy numLoops, set setup->numLoops to 1 to do repeated * compress - sw-decompress for numLoops times*/ numLoops = setup->numLoops; setup->numLoops = 1; for (i = 0; i < numLoops; i++) { status = qatCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray); qatDcUpdateProducedBufferLength( setup, destBufferListArray, resultArray); dcScSetBytesProducedAndConsumed(resultArray, setup->performanceStats, setup, setup->dcSessDir); if (CPA_STATUS_SUCCESS == status) { status = qatSwDecompress(setup, destBufferListArray, cmpBufferListArray, resultArray); qatDcUpdateProducedBufferLength( setup, cmpBufferListArray, resultArray); if (CPA_STATUS_SUCCESS == status) { status = qatCmpBuffers( setup, srcBufferListArray, cmpBufferListArray); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCmpBuffers", status); } if (CPA_STATUS_SUCCESS == status) { /*reset destination buffer*/ status = qatCompressResetBufferList(setup, destBufferListArray, testBufferSize, CPA_FALSE); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCompressResetBufferList resets de-compression " "bufferlist", status); status = qatCompressResetBufferList(setup, cmpBufferListArray, testBufferSize, CPA_TRUE); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCompressResetBufferList resets compression " "bufferlist", status); } } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("qatCompressData returned status %d\n", status); break; } if (CPA_TRUE == stopTestsIsEnabled_g) { /* Check if terminated by global flag. * stop issuing new requests */ if (CPA_TRUE == exitLoopFlag_g) { break; } } } } else if (setup->dcSessDir == CPA_DC_DIR_DECOMPRESS && reliability_g == CPA_TRUE) { /*copy numLoops, set setup->numLoops to 1 to do repeated * swcompress-decompress for numLoops times*/ numLoops = setup->numLoops; setup->numLoops = 1; for (i = 0; i < numLoops; i++) { status = qatSwCompress(setup, srcBufferListArray, destBufferListArray, resultArray); qatDcUpdateProducedBufferLength( setup, destBufferListArray, resultArray); if (CPA_STATUS_SUCCESS == status) { status = qatCompressData(setup, pDecompressSessionHandle, CPA_DC_DIR_DECOMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray); qatDcUpdateProducedBufferLength( setup, cmpBufferListArray, resultArray); dcScSetBytesProducedAndConsumed(resultArray, setup->performanceStats, setup, setup->dcSessDir); if (CPA_STATUS_SUCCESS == status) { status = qatCmpBuffers( setup, srcBufferListArray, cmpBufferListArray); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCmpBuffers", status); } if (CPA_STATUS_SUCCESS == status) { /*reset destination buffer*/ status = qatCompressResetBufferList(setup, destBufferListArray, testBufferSize, CPA_FALSE); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS( "qatCompressResetBufferList", status); } } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("qatCompressData returned status %d\n", status); break; } if (CPA_TRUE == stopTestsIsEnabled_g) { /* Check if terminated by global flag. * stop issuing new requests */ if (CPA_TRUE == exitLoopFlag_g) { break; } } } } if (CPA_STATUS_SUCCESS != status) { qatDumpBufferListInfo(setup, srcBufferListArray, destBufferListArray, cmpBufferListArray, 0); } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { if (CPA_STATUS_SUCCESS != performOffloadCalculationBusyLoop(setup, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray, dcCbFn, setup->dcSessDir, pSessionHandle)) { PRINT_ERR("performOffloadCalculationBusyLoop error\n"); } } coo_average(setup->performanceStats); coo_deinit(setup->performanceStats); // remove the session free the handle if (CPA_FALSE == setup->setNsRequest) { if (CPA_STATUS_SUCCESS != qatCompressionSessionTeardown( setup, &pSessionHandle, &pDecompressSessionHandle)) { PRINT_ERR("compressionSessionTeardown error\n"); status = CPA_STATUS_FAIL; } } } /*free CpaFlatBuffers and privateMetaData in CpaBufferLists*/ if ((CPA_STATUS_SUCCESS != qatFreeCompressionFlatBuffers(setup, srcBufferListArray, destBufferListArray, cmpBufferListArray)) && (CPA_STATUS_SUCCESS != qatFreeFlatBuffersInList(&contextBuffer))) { PRINT_ERR("freeCompressionFlatBuffers error\n"); status = CPA_STATUS_FAIL; } // free CpaBufferLists if (CPA_STATUS_SUCCESS != qatFreeCompressionLists(setup, &srcBufferListArray, &destBufferListArray, &cmpBufferListArray, &resultArray)) { PRINT_ERR("freeCompressionLists error\n"); status = CPA_STATUS_FAIL; } return status; } EXPORT_SYMBOL(qatDcPerform); CpaStatus qatDcSubmitRequest(compression_test_params_t *setup, const CpaInstanceInfo2 *pInstanceInfo2, CpaDcSessionDir compressDirection, CpaDcSessionHandle pSessionHandle, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, Cpa32U listNum, CpaDcRqResults *arrayOfResults) { CpaStatus status = CPA_STATUS_SUCCESS; static Cpa32U staticAssign = 0; CpaDcCallbackFn dcCbFn = NULL; if (setup->requestOps.flushFlag != setup->flushFlag) { PRINT_ERR("Setup Disparity in Flush flag." "RequestOps = %d, setup = %d\n", setup->requestOps.flushFlag, setup->flushFlag); setup->requestOps.flushFlag = setup->flushFlag; } do { /*To use reliability code, I set CpaBoolean reliability_g = CPA_TRUE * in cpa_sample_code_framework.c and defined USE_ZLIB from * command line */ qatStartLatencyMeasurement(setup->performanceStats, setup->performanceStats->submissions); if (compressDirection == CPA_DC_DIR_COMPRESS) { coo_req_start(setup->performanceStats); { if (CPA_TRUE == setup->setNsRequest) { setup->setupData.sessDirection = CPA_DC_DIR_COMPRESS; if (ASYNC == setup->syncFlag) { dcCbFn = dcPerformCallback; } status = cpaDcNsCompressData(setup->dcInstanceHandle, &(setup->setupData), &arrayOfSrcBufferLists[listNum], &arrayOfDestBufferLists[listNum], &(setup->requestOps), &arrayOfResults[listNum], dcCbFn, (void *)setup); } else { status = cpaDcCompressData2(setup->dcInstanceHandle, pSessionHandle, &arrayOfSrcBufferLists[listNum], &arrayOfDestBufferLists[listNum], &(setup->requestOps), &arrayOfResults[listNum], (void *)setup); } coo_req_stop(setup->performanceStats, status); } } else if (compressDirection == CPA_DC_DIR_DECOMPRESS) { /*This is required as the cpaDcDecompressData2 function rejects * request where compressAndVerify flag is set to true. However * the setting of this flag should not matter for decompress*/ setup->requestOps.compressAndVerify = CPA_FALSE; coo_req_start(setup->performanceStats); if (CPA_TRUE == setup->setNsRequest) { setup->setupData.sessDirection = CPA_DC_DIR_DECOMPRESS; if (ASYNC == setup->syncFlag) { dcCbFn = dcPerformCallback; } status = cpaDcNsDecompressData(setup->dcInstanceHandle, &(setup->setupData), &arrayOfDestBufferLists[listNum], &arrayOfCmpBufferLists[listNum], &(setup->requestOps), &arrayOfResults[listNum], dcCbFn, (void *)setup); } else { status = cpaDcDecompressData2(setup->dcInstanceHandle, pSessionHandle, &arrayOfDestBufferLists[listNum], &arrayOfCmpBufferLists[listNum], &(setup->requestOps), &arrayOfResults[listNum], (void *)setup); } coo_req_stop(setup->performanceStats, status); } if (CPA_STATUS_RETRY == status) { qatDcRetryHandler(setup, pInstanceInfo2); /*context switch to give firmware time to process*/ AVOID_SOFTLOCKUP; } /*check the results structure for any failed responses * caught by the callback function*/ qatCompressionResponseStatusCheck( setup, arrayOfResults, listNum, &status); } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { busyLoop(setup->performanceStats->busyLoopValue, &staticAssign); setup->performanceStats->busyLoopCount++; } return status; } EXPORT_SYMBOL(qatDcSubmitRequest); /*performance measurement function to compress a file for 'n' number of loops * */ CpaStatus qatCompressData(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaDcSessionDir compressDirection, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcRqResults *arrayOfResults) { CpaStatus status = CPA_STATUS_SUCCESS; CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa32U numLoops = 0; Cpa32U listNum = 0; Cpa32U previousChecksum = 0; CpaDcChecksum checksum = CPA_DC_NONE; CpaDcStats dcStats = {0}; CpaBoolean isCnVerrorRecovered = CPA_FALSE; instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); checksum = setup->setupData.checksum; /* init checksum */ if (CPA_DC_ADLER32 == checksum) { previousChecksum = 1; } else if (CPA_DC_CRC32 == checksum) { previousChecksum = 0; } QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfSrcBufferLists, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfDestBufferLists, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfCmpBufferLists, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfResults, status); if (CPA_STATUS_SUCCESS == status) { status = qatCompressionE2EInit(setup); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS("qatCompressionE2EInit", status); } if (CPA_STATUS_SUCCESS == status) { setup->flushFlag = CPA_DC_FLUSH_FINAL; qatPerfInitStats(setup->performanceStats, setup->numLists, setup->numLoops, (setup->useStatefulLite == CPA_TRUE || setup->setupData.sessState == CPA_DC_STATEFUL) ? 1 : dcPollingInterval_g); status = qatInitLatency( setup->performanceStats, setup->numLists, setup->numLoops); } if (CPA_STATUS_SUCCESS == status) { /*get the instance2 info, this is used to determine if the instance * being used is polled*/ status = cpaDcInstanceGetInfo2(setup->dcInstanceHandle, instanceInfo2); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS("cpaDcInstanceGetInfo2", status); } if (status == CPA_STATUS_SUCCESS) { /*Initialize the semaphore, the callback function is responsible for * posting the semaphore once all responses are received*/ /* Completion used in callback */ status = sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); QAT_PERF_PRINT_ERR_FOR_NON_SUCCESS_STATUS("sampleCodeSemaphoreInit", status); } if (status == CPA_STATUS_SUCCESS) { /* this Barrier will waits until all the threads get to this point * this is to ensure that all threads that we measure performance on * start submitting at the same time*/ sampleCodeBarrier(); /* generate the start time stamps */ setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); /*loop over compressing a file numLoop times*/ for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { /*loop over lists that store the file*/ for (listNum = 0; listNum < setup->numLists; listNum++) { /*exit loop mechanism to leave early if numLoops is large * note that this might not work if the we get stuck in the * do-while loop below*/ checkStopTestExitFlag(setup->performanceStats, &setup->numLoops, &setup->numLists, numLoops); qatCompressionSetFlushFlag(setup, listNum); /* Always set the checksum equal to the previous * checksum. For stateless the previous checksum * will still be the default value which is what * we want to set it to anyway in that case. */ arrayOfResults[listNum].checksum = previousChecksum; /*submit request*/ status = qatDcSubmitRequest(setup, instanceInfo2, compressDirection, pSessionHandle, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, listNum, arrayOfResults); /* Check submit status and update thread status*/ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Data Compression Failed %d\n\n", status); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; /*break out of inner loop*/ break; } setup->performanceStats->submissions++; qatLatencyPollForResponses(setup->performanceStats, setup->performanceStats->submissions, setup->dcInstanceHandle, CPA_FALSE, CPA_FALSE); if (poll_inline_g && instanceInfo2->isPolled) { /*poll every 'n' requests as set by * dcPollingInterval_g*/ if (setup->performanceStats->submissions == setup->performanceStats->nextPoll) { qatDcPollAndSetNextPollCounter(setup); } } /* check if synchronous flag is set, * if set, invoke the callback API * the driver does not use the callback in sync mode * the sample code uses the callback function to count the * responses and post the semaphore */ if (SYNC == setup->syncFlag) { COUNT_RESPONSES; } /* End of SYNC Flag Check */ else { #if DC_API_VERSION_AT_LEAST(3, 2) if (reliability_g) #endif { if ((CPA_DC_STATELESS == setup->setupData.sessState) && (CPA_TRUE == setup->useE2E || CPA_TRUE == setup->useE2EVerify)) { status = waitForSemaphore(setup->performanceStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("waitForSemaphore error\n"); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; break; } } } } if ((CPA_TRUE == setup->useStatefulLite) || (CPA_DC_STATEFUL == setup->setupData.sessState)) { status = waitForSemaphore(setup->performanceStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("waitForSemaphore error\n"); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; break; } previousChecksum = arrayOfResults[listNum].checksum; /*check for unconsumed data*/ if ((CPA_DC_DIR_DECOMPRESS == compressDirection) && (arrayOfDestBufferLists[listNum] .pBuffers->dataLenInBytes != arrayOfResults[listNum].consumed)) { if (CPA_STATUS_SUCCESS != qatCheckAndHandleUnconsumedData( setup, arrayOfDestBufferLists, arrayOfResults, listNum, (const char *)instanceInfo2->partName)) { PRINT_ERR("Decomp did not consume all data\n"); PRINT("Input Buffersize: %u\n", arrayOfDestBufferLists[listNum] .pBuffers[0] .dataLenInBytes); PRINT("Amount Consumed: %u\n", arrayOfResults[listNum].consumed); PRINT("Amount Produced: %u\n", arrayOfResults[listNum].produced); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; setup->performanceStats->numOperations = setup->performanceStats->submissions; /*call the response thread so that the semaphore * gets posted*/ dcPerformCallback(setup, status); break; } } } if (CPA_STATUS_SUCCESS == status) { #if DC_API_VERSION_AT_LEAST(3, 2) if (reliability_g) #endif { status = qatCompressionE2EVerify( setup, &arrayOfSrcBufferLists[listNum], &arrayOfDestBufferLists[listNum], &arrayOfResults[listNum]); } } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s returned status: %d\n", "qatCompressionE2EVerify", status); break; } } /* number of lists/requests in a file */ if (CPA_STATUS_SUCCESS != status) { /*break out of outerloop(numLoops)*/ break; } } /* number of times we loop over same file */ if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = dcPollNumOperations(setup->performanceStats, setup->dcInstanceHandle, setup->performanceStats->numOperations); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("dcPollNumOperations returned an error\n"); } } } /* Wait 30 seconds for the semaphore to be posted by the callback*/ if (CPA_STATUS_SUCCESS == status) { status = waitForSemaphore(setup->performanceStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("waitForSemaphore error\n"); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } } else { /* In case of failure during submissions, all in-flight requests * should be collected before releasing memory that is used by * the SAL/Driver. This is specially true for async response * processing via callback function. */ if (!(poll_inline_g || SYNC == setup->syncFlag || CPA_TRUE == setup->useStatefulLite || CPA_DC_STATEFUL == setup->setupData.sessState)) { waitForInflightRequestAfterError(setup->performanceStats); } } if (CNV_RECOVERY(&(setup->requestOps)) == CPA_TRUE) { status = cpaDcGetStats(setup->dcInstanceHandle, &dcStats); if (status == CPA_STATUS_SUCCESS) { setup->performanceStats->postTestRecoveryCount = GET_CNV_RECOVERY_COUNTERS(&dcStats); } else { setup->performanceStats->postTestRecoveryCount = 0; } if (setup->performanceStats->postTestRecoveryCount > setup->performanceStats->preTestRecoveryCount) { isCnVerrorRecovered = CPA_TRUE; } } /* As the destination buffer size for the compression request is * obtained using the Compress Bound APIs, There should not be any * unconsumed data left in the src buffer except for the case when * FW identifies CnV Error and recovers it. Any such case is treated as * test failure*/ if (CPA_STATUS_SUCCESS == status && (CPA_DC_DIR_COMPRESS == compressDirection) && (setup->induceOverflow == CPA_FALSE) && (isCnVerrorRecovered == CPA_FALSE)) { status = qatCompressionVerifyOverflow( setup, arrayOfResults, arrayOfSrcBufferLists, listNum); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("qatCompressionVerifyOverflow Failed.\n"); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } } /*check the results structure for any failed responses * caught by the callback function*/ qatCompressionResponseStatusCheck( setup, arrayOfResults, listNum, &status); qatSummariseLatencyMeasurements(setup->performanceStats); sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); } /* if semaphoreInit was successful */ qaeMemFree((void **)&instanceInfo2); return status; } EXPORT_SYMBOL(qatCompressData); /*update in sample code framework how much data was consumed and produced by * thread*/ void dcScSetBytesProducedAndConsumed(CpaDcRqResults *result, perf_data_t *perfData, compression_test_params_t *setup, CpaDcSessionDir direction) { Cpa32U i = 0; if (direction == CPA_DC_DIR_COMPRESS) { for (i = 0; i < setup->numberOfBuffers[0]; i++) { perfData->bytesConsumedPerLoop += result[i].consumed; perfData->bytesProducedPerLoop += result[i].produced; } } else if (direction == CPA_DC_DIR_DECOMPRESS) { for (i = 0; i < setup->numberOfBuffers[0]; i++) { perfData->bytesConsumedPerLoop += result[i].produced; perfData->bytesProducedPerLoop += result[i].consumed; } } } EXPORT_SYMBOL(dcScSetBytesProducedAndConsumed); static CpaStatus qatInduceOverflow(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaBufferList *srcBufferListArray, CpaBufferList *destBufferListArray, CpaBufferList *cmpBufferListArray, CpaDcRqResults *resultArray) { CpaStatus status = CPA_STATUS_FAIL; CpaDcRqResults *overflowResArray = NULL; Cpa32U numListOverflowed = 0; Cpa32U i, loop; const Cpa32U numLoops = setup->numLoops; const Cpa32U reductionFactor = 6; Cpa32U lowerThresholdDstBufferSize = 128; Cpa32U *destBufferMemSize = NULL; const Cpa32U numLists = setup->numLists; overflowResArray = qaeMemAlloc(numLists * sizeof(CpaDcRqResults)); if (overflowResArray == NULL) { PRINT_ERR("Failed to Allocate Overflow Result Array\n"); return CPA_STATUS_FAIL; } destBufferMemSize = qaeMemAlloc(numLists * sizeof(Cpa32U)); if (destBufferMemSize == NULL) { PRINT_ERR("Malloc failed for size %llu\n", (unsigned long long)(numLists) * sizeof(Cpa32U)); goto err; } setup->numLoops = 1; for (loop = 0; loop < numLoops; loop++) { /* Reduce the size of the destination buffer to * induce overflow */ for (i = 0; i < numLists; i++) { if (destBufferListArray[i].numBuffers > 1) { PRINT_ERR("Multiple Flat buffer per list not supported\n"); goto err; } /* Store the allocated size */ destBufferMemSize[i] = destBufferListArray[i].pBuffers[0].dataLenInBytes; /* Pretend that the capacity of Output buffer is less than input * buffer * by the amount of 2 ^ reductionFactor. */ destBufferListArray[i].pBuffers[0].dataLenInBytes = srcBufferListArray[i].pBuffers[0].dataLenInBytes >> reductionFactor; /* Adjust the length if it falls below threshold */ if (destBufferListArray[i].pBuffers[0].dataLenInBytes < lowerThresholdDstBufferSize) { destBufferListArray[i].pBuffers[0].dataLenInBytes = lowerThresholdDstBufferSize; } } status = qatCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, resultArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to compress Data with overflow setup\n"); goto err; } /* Check all that have overflowed and construct a new SGL to handle * remaining data. */ for (i = 0; i < numLists; i++) { if (resultArray[i].status == CPA_DC_OVERFLOW) { if (resultArray[i].consumed == 0 && resultArray[i].produced == 0) { PRINT_ERR("Overflow reported with no bytes produced or" " consumed for list: %d\n", i); status = CPA_STATUS_FAIL; goto err; } numListOverflowed++; /* Find the amount of data unconsumed */ srcBufferListArray[i].pBuffers[0].dataLenInBytes -= resultArray[i].consumed; srcBufferListArray[i].pBuffers[0].pData += resultArray[i].consumed; /* Update Output buffers for the amount of bytes produced. * From the amount of memory actually allocated for the buffer, * reduced the amount taken up by produced data. */ destBufferListArray[i].pBuffers[0].dataLenInBytes = destBufferMemSize[i] - resultArray[i].produced; destBufferListArray[i].pBuffers[0].pData += resultArray[i].produced; } else { /* The test design aims to induce overflow in each list of * the payload as the entire list array is submitted again. * However if some lists don't overflow even after output * buffer reduction, highlight the fact and ignore. */ PRINT("No Overflow reported for List Num: %d status: %d\n", i, resultArray[i].status); } } /* Post overflow processing for all lists*/ if (numListOverflowed == 0) { PRINT_ERR("No overflow detected for Loop count: %d\n", loop + 1); status = CPA_STATUS_FAIL; goto err; } /* Resubmits the bufferlist after updating buffers for overflow */ status = qatCompressData(setup, pSessionHandle, CPA_DC_DIR_COMPRESS, srcBufferListArray, destBufferListArray, cmpBufferListArray, overflowResArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to compress unconsumed data after overflow\n"); goto err; } /* Recheck that there is no overflow now and update the produced length * to the sum of pre overflow and post overflow compression. */ for (i = 0; i < numLists; i++) { if (overflowResArray[i].status != CPA_DC_OVERFLOW) { if (overflowResArray[i].status != CPA_DC_OK) { PRINT("Status: %d reported post overflow for List %d\n", overflowResArray[i].status, i); } /* Check if the list element overflowed previously and * update accordingly. */ if (resultArray[i].status == CPA_DC_OVERFLOW) { destBufferListArray[i].pBuffers[0].dataLenInBytes = resultArray[i].produced + overflowResArray[i].produced; destBufferListArray[i].pBuffers[0].pData -= resultArray[i].produced; srcBufferListArray[i].pBuffers[0].dataLenInBytes = resultArray[i].consumed + overflowResArray[i].consumed; srcBufferListArray[i].pBuffers[0].pData -= resultArray[i].consumed; /* Update the first pass result Array to have the total of * bytes * produced and consumed from the two operations. */ resultArray[i].consumed += overflowResArray[i].consumed; resultArray[i].produced += overflowResArray[i].produced; /* Update stats here after the second call as performance * stats * are initialized on each call qatCompressData. */ setup->performanceStats->overflow++; } } /* status != OVERFLOW */ else { PRINT_ERR("Overflow reported AGAIN for list: %d\n", i); status = CPA_STATUS_FAIL; goto err; } } /* end of for loop for numLists */ /* Update the stats from with result array as it has sum * of pre and post overflow. */ dcScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, setup->dcSessDir); /* Perform Decompression using SW on the compressed * buffer. */ status = qatSwDecompress( setup, destBufferListArray, cmpBufferListArray, resultArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("SW Decompression Failed\n"); goto err; } qatDcUpdateProducedBufferLength(setup, cmpBufferListArray, resultArray); { /* Compare the input buffer to SW decompressed buffer */ status = qatCmpBuffers(setup, srcBufferListArray, cmpBufferListArray); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Buffer comparison Failed for Loop count:%d\n", loop + 1); goto err; } } /*reset destination buffer*/ status = qatCompressResetBufferList(setup, destBufferListArray, setup->packetSizeInBytesArray, CPA_FALSE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("qatCompressResetBufferList failed to reset " "de-compression bufferlist. (status = %d)\n", status); } status = qatCompressResetBufferList( setup, cmpBufferListArray, setup->packetSizeInBytesArray, CPA_TRUE); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("qatCompressResetBufferList failed to reset compression " "bufferlist. (status = %d)\n", status); } if (stopTestsIsEnabled_g == CPA_TRUE && exitLoopFlag_g == CPA_TRUE) { break; } numListOverflowed = 0; } /* end of for loop for NumLoops */ err: qaeMemFree((void **)&destBufferMemSize); qaeMemFree((void **)&overflowResArray); return status; } qat_compression_main.h000066400000000000000000002106521503624047500363400ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * These functions specify the API for compression performance code * * @remarks * * *****************************************************************************/ #ifndef QAT_COMPRESSION_MAIN #define QAT_COMPRESSION_MAIN #define QAT_COMP_MIN_LOOPS_FOR_SLEEP_CONTROL (50) #define QAT_COMP_DEFAULT_COMP_RATE (100) #define QAT_COMP_SCALING_FACTOR (1000) #define QAT_COMP_MIN_PACKET_SIZE (1024) #define QAT_COMP_LOW_SLEEPTIME_STATING_VALUE (2048) #define QAT_COMP_HIGH_SLEEPTIME_STATING_VALUE (32768) #define QAT_COMP_DEFAULT_SLEEPTIME_STARTING_VALUE (2) #define QAT_COMP_FIVE_PERCENT (50) #define QAT_COMP_THREE_PERCENT (30) #define QAT_COMP_ONE_POINT_FIVE_PERCENT (15) #define QAT_COMP_POINT_SIX_PERCENT (6) #define QAT_COMP_PACKET_SIZE_8K (8192) #define QAT_COMP_SLEEP_INTERVAL (100000) #define QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH (512) #define QAT_COMP_DUMP_BUFFER_SIZE (1024) #include "cpa.h" #include "cpa_dc.h" #include "cpa_dc_dp.h" #include "qat_perf_utils.h" #include "cpa_sample_code_dc_utils.h" #include "qat_compression_zlib.h" #include "qat_perf_latency.h" #include "qat_perf_buffer_utils.h" #include "icp_sal_poll.h" /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * free the memory used to store a list of CpaBufferLists * * @param[in] setup pointer to the compression setup * structure that the list was setup with * @param[in] srcBufferListArray array of CpaBufferLists to be freed * @param[in] destBufferListArray array of CpaBufferLists to be freed * @param[in] resultArray array of cpaDcResults to be freed * * @pre all these structures are already * allocated * * @post all memory is freed * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be freed ****************************************************************************/ CpaStatus qatFreeCompressionLists(compression_test_params_t *setup, CpaBufferList **srcBufferListArray, CpaBufferList **destBufferListArray, CpaBufferList **cpmBufferListArray, CpaDcRqResults **resultArray); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * Perform checksum validation. Compare H/W checksum in results * structure with S/W checksum calculated in the function. * * @param[in] setup pointer to the compression setup * structure that the list was setup with * @param[in] srcBufferListArray array of CpaBufferLists to calculate S/W checksum * @param[in] resultArray array of cpaDcResults for H/W checksum * @param[in] listNum Total number of Buffer lists * @param[in] compressDirection Compression Direction * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL Checksum values does not match ****************************************************************************/ CpaStatus qatCompressionValidateChecksum(compression_test_params_t *setup, CpaDcRqResults *arrayOfResults, CpaBufferList *arrayOfSrcBufferLists, Cpa32U listNum, CpaDcSessionDir compressDirection); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * This API is added to perform overflow validation of the * compression request. With the use of Compress Bound API to get * the destination buffer size for compression request, it is expected * that all the input data will be consumed successfully and there should * not be any overflow case. Overflow is considered as Failed result. * * @param[in] setup pointer to the compression setup * structure that the list was setup with * @param[in] srcBufferListArray array of CpaBufferLists to check totak input data size * @param[in] resultArray array of cpaDcResults for consumed bytes * @param[in] listNum Total number of Buffer lists * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL Overflow is observed ****************************************************************************/ CpaStatus qatCompressionVerifyOverflow(compression_test_params_t *setup, CpaDcRqResults *arrayOfResults, CpaBufferList *arrayOfSrcBufferLists, Cpa32U listNum); #ifdef SC_CHAINING_ENABLED /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * free the DcChain memory used to store a list of CpaBufferLists * * @param[in] chainResultArray array of CpaDcChainRqResults to be freed * @param[in] chainOpDataArray array of CpaDcChainOpData to be freed * * @pre all these structures are already * allocated * * @post all memory is freed * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be freed ****************************************************************************/ CpaStatus qatFreeDcChainLists(void **chainResultArray, void **chainOpDataArray); #endif /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * allocate the memory used to store a list of CpaBufferLists * * @param[in] setup pointer to the compression setup structure * @param[in] srcBufferListArray array of CpaBufferLists to be allocated * @param[in] destBufferListArray array of CpaBufferLists to be allocated * @param[in] resultArray array of cpaDcResults to be allocated * * @pre none * * @post all memory is allocated * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be * allocated ****************************************************************************/ CpaStatus qatAllocateCompressionLists(compression_test_params_t *setup, CpaBufferList **srcBufferListArray, CpaBufferList **destBufferListArray, CpaBufferList **cpmBufferListArray, CpaDcRqResults **resultArray); #ifdef SC_CHAINING_ENABLED /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * allocate the memory used to store a list of DcChain BufferLists * * @param[in] setup pointer to the compression setup structure * @param[in] chainResultArray array of CpaDcChainRqResults to be *allocated * @param[in] chainOpDataArray array of CpaDcChainOpData to be allocated * * @pre none * * @post all memory is allocated * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be * allocated ****************************************************************************/ CpaStatus qatAllocateDcChainLists(compression_test_params_t *setup, void **chainResultArray, void **chainOpDataArray); #endif /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * allocate the CpaFlatBuffers and members of the CpaBufferLists * * @param[in] setup pointer to the compression setup * structure * @param[in] srcBufferListArray array of CpaBufferLists to be allocated * @param[in] numBuffersInSrcList number of CpaFlatBuffers to be allocated * in srcBufferListArray * @param[in] sizeOfBuffersInSrcList size of CpaBufferLists to be allocated * in srcBufferLists * @param[in] destBufferListArray array of CpaBufferLists to be allocated * @param[in] numBuffersInDstList number of CpaFlatBuffers to be allocated * in dstBufferListArray * @param[in] sizeOfBuffersInDestList size of CpaBufferLists to be allocated * in destBufferLists * * @pre none * * @post all memory is allocated * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be * allocated ****************************************************************************/ CpaStatus qatAllocateCompressionFlatBuffers(compression_test_params_t *setup, CpaBufferList *srcBufferListArray, Cpa32U numBuffersInSrcList, Cpa32U *sizeOfBuffersInSrcList, CpaBufferList *destBufferListArray, Cpa32U numBuffersInDstList, Cpa32U *sizeOfBuffersInDstList, CpaBufferList *cpmBufferListArray, Cpa32U numberBuffersInCpmList, Cpa32U *sizeOfBuffersInCpmList); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * free the CpaFlatBuffers and members of the CpaBufferLists * * @param[in] setup pointer to the compression setup * structure * @param[in] srcBufferListArray array of CpaBufferLists to be freed * @param[in] destBufferListArray array of CpaBufferLists to be freed * @param[in] cpmBufferListArray array of CpaBufferLists to be freed * * @pre none * * @post all memory is allocated * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be * allocated ****************************************************************************/ CpaStatus qatFreeCompressionFlatBuffers(compression_test_params_t *setup, CpaBufferList *srcBufferListArray, CpaBufferList *destBufferListArray, CpaBufferList *cpmBufferListArray); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Initialize a session for compression service * * @param[in] setup pointer to the compression setup * structure * @param[in] pSessionHandle session handle to be allocated and * initialized * @param[in] pContextBuffer pointer to context buffer to be * allocated. The context buffer is only * used by the driver for stateful * compression * @param[in] dcCbFn callback function to be registered with * session. The callback function is called * by the driver to process responses * * @pre none * * @post compression session is initialized and * ready for use * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the session could not be * initialized ****************************************************************************/ CpaStatus qatCompressionSessionInit( compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle, CpaBufferList *pContextBuffer, CpaDcCallbackFn dcCbFn); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * Remove a compression session * * @param[in] setup pointer to the compression setup * structure * @param[in] pSessionHandle session handle to be unregistered and * freed * * @pre session is allocated and initialized * * @post compression session handle unregistered * from driver and the memory for it is * freed * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the session could not be * initialized ****************************************************************************/ CpaStatus qatCompressionSessionTeardown( compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle); #ifdef USER_SPACE #ifdef SC_CHAINING_ENABLED /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Initialize a session for chaining service * * @param[in] setup pointer to the compression setup * structure * @param[in] pSessionHandle session handle to be allocated and * initialized * @param[in] dcCbFn callback function to be registered with * session. The callback function is called * by the driver to process responses * * @pre none * * @post chaining session is initialized and * ready for use * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the session could not be * initialized ****************************************************************************/ CpaStatus qatDcChainSessionInit(compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle, CpaDcCallbackFn dcCbFn); /** ***************************************************************************** * @file qat_compression_main.h * * @defgroup sample_code * * @ingroup sampleCode * * @description * Remove a compression session * * @param[in] setup pointer to the compression setup * structure * @param[in] pSessionHandle session handle to be unregistered and * freed * * @pre session is allocated and initialized * * @post chaining session handle unregistered * from driver and the memory for it is * freed * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the session could not be * initialized ****************************************************************************/ CpaStatus qatDcChainSessionTeardown( compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle); #endif #endif /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * dump the contents of the bufferLists to files: * srcBuffer and scrBufferSizes for the uncompressed data * dstBuffer and dstBufferSizes for the compressed data and * cmpBuffer and cmpBufferSizes for the decompressed data * * @param[in] pSrc pointer to the uncomressed buffer list * @param[in] pDst pointer to the compressed buffer list * @param[in] pCmp pointer to the decompressed buffer list * @param[in] listNum Specific list number to be * structure 0 = all buffers * * @pre bufferLists are allocated and populated * with data * * @post files are dumped with bufferList info * if NULL is passed as a pointer that file * is not dumped * ****************************************************************************/ void qatDumpBufferListInfo(compression_test_params_t *setup, CpaBufferList *pSrc, CpaBufferList *pDst, CpaBufferList *pCmp, Cpa32U listNum); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * compare the contents of two bufferlists up to the length of the * srcBufferList. * * @param[in] ppSrc pointer to the source buffer list * @param[in] ppDst pointer to the destination buffer list * @param[in] setup pointer to the compression setup * structure * * @pre bufferLists are allocated and populated * with data * * @post none * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the data did not match ****************************************************************************/ CpaStatus qatCmpBuffers(compression_test_params_t *setup, CpaBufferList *pSrc, CpaBufferList *pDst); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * check the buffer if contains all zeros. * * @param[in] buf pointer to buffer * @param[in] ptkSize buffer size * * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL If buffer doesn't contains all zeros ****************************************************************************/ CpaStatus qatIsBufEmpty(Cpa8U *buf, size_t pktSize); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * dump an array of bufferLists containing compressed or decompressed * data to a binary file * * @param[in] buffListArray array of buffer lists to containing * data to be dumped to file * compress * @param[in] resultArray results structure for each bufferList * @param[in] setup pointer to the compression setup * structure * @param[in] fileName name of file to dump bufferData to * @param[in] fileNameB name of file to dump bufferSizes t0 * @param[in] list if 0 dump the entire array of lists, * otherwise dump a specific list * note: 1=index 0 into the array of lists * * @pre bufferLists are allocated and populated * with data * * @post destination buffer contains compressed * data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the data did not compress ****************************************************************************/ void qatCompressDumpToFile(compression_test_params_t *setup, CpaBufferList *buffListArray, char *fileName, char *fileNameB, Cpa32U list); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * compress source data using zlib software library * * @param[in] srcBufferListArray array of source buffer lists to * compress * @param[out] dstBufferListArray array of buffer lists to store * compressed data * @param[in] cmpResults results structure for each bufferList * @param[in] setup pointer to the compression setup * structure * * @pre bufferLists are allocated and populated * with data * * @post destination buffer contains compressed * data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the data did not compress ****************************************************************************/ CpaStatus qatSwCompress(compression_test_params_t *setup, CpaBufferList *srcBufferListArray, CpaBufferList *dstBufferListArray, CpaDcRqResults *cmpResults); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * decompress source data using zlib software library * * @param[in] srcBufferListArray array of source buffer lists to * decompress * @param[in] dstBufferListArray array of buffer lists to store * decompressed data * @param[in] cmpResults results structure for each bufferList * @param[in] setup pointer to the compression setup * structure * * @pre bufferLists are allocated and populated * with data * * @post destination buffer contains decompressed * data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the data did not compress ****************************************************************************/ CpaStatus qatSwDecompress(compression_test_params_t *setup, CpaBufferList *destBufferListArray, CpaBufferList *cmpBufferListArray, CpaDcRqResults *cmpResults); #ifdef SC_CHAINING_ENABLED /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * decompress source data using zlib software library * * @param[in] srcBufferListArray array of source buffer lists to * decompress * @param[in] dstBufferListArray array of buffer lists to store * decompressed data * @param[in] cmpResults results structure for each bufferList * @param[in] setup pointer to the compression setup * structure * * @pre bufferLists are allocated and populated * with data * * @post destination buffer contains decompressed * data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the data did not compress ****************************************************************************/ CpaStatus qatSwChainDecompress(compression_test_params_t *setup, CpaBufferList *destBuffListArray, CpaBufferList *cmpBufferListArray, CpaDcChainRqResults *cmpResults); #endif /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * this function checks if the HW behaviour is expected * if it is expected then function handles the unconsumed * data and returns CPA_STATUS_SUCCESS. If not the function * returns CPA_STATUS_FAIL * * @param[in] setup pointer to the compression setup * structure * @param[in] arrayOfDestBufferLists pointer to the bufferList to be updated * * @param[in] arrayOfResults pointer to the compression results array * * @param[in] listNum index into bufferList array containing * unconsumed data * * @param[in] partName the part name * * @pre bufferLists are allocated and populated * with data * * @post bufferList is updated with amount of * produced data * * @retval CPA_STATUS_SUCCESS HW behaviour is expected and unconsumed * data has been handled * * @retval CPA_STATUS_FAIL it is impossible to handle unconsumed * data ****************************************************************************/ CpaStatus qatCheckAndHandleUnconsumedData(compression_test_params_t *setup, CpaBufferList *arrayOfDestBufferLists, CpaDcRqResults *arrayOfResults, Cpa32U listNum, const char *partName); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * update the dataLengthInBytes field with the amount of data produced * from the compress or decompress operation * * @param[in] setup pointer to the compression setup * structure * @param[in] bufferListArray bufferList to be updated * @param[in] resultArray results structure containing the amount * of produced data * * @pre bufferLists are allocated and populated * with data * * @post bufferList is updated with amount of * produced data * ****************************************************************************/ void qatDcUpdateProducedBufferLength(compression_test_params_t *setup, CpaBufferList *bufferListArray, CpaDcRqResults *resultArray); #ifdef SC_CHAINING_ENABLED /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * update the dataLengthInBytes field with the amount of data produced * from the compress or decompress operation * * @param[in] setup pointer to the compression setup * structure * @param[in] bufferListArray bufferList to be updated * @param[in] resultArray results structure containing the amount * of produced data * * @pre bufferLists are allocated and populated * with data * * @post bufferList is updated with amount of * produced data * ****************************************************************************/ void qatDcChainUpdateProducedBufferLength(compression_test_params_t *setup, CpaBufferList *bufferListArray, CpaDcChainRqResults *resultArray); #endif /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * reset a destination buffer with all 0's so that it does not contain * compressed or decompressed data from previous use * * @param[in] setup pointer to the compression setup * structure * @param[in] buffListArray array of buffer lists to reset * @param[in] flafBufferSize pointer to an array that stores the size * of each CpaFlatBuffer in buffArrayList. * @param[in] isCmpBuffer set to true if resetting the * cmpBufferList, set to false otherwise * * @pre bufferLists are allocated and populated * with data. flatBufferSize array stores * size of each CpaFlatBuffer in * buffArrayList (as the size can be * updated to reflect the compressed data * size * * @post pData in buffer list is all 0's * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the list was not reset ****************************************************************************/ CpaStatus qatCompressResetBufferList(compression_test_params_t *setup, CpaBufferList *buffListArray, Cpa32U *flafBufferSize, CpaBoolean isCmpBuffer); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * poll for responses and set the counter for when to poll next * * @param[in] setup pointer to the compression setup * structure * @pre setup->perfStats is initialized * * @post the driver has polled for and responses * and the counter is set for when to poll * next * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the driver failed to poll ****************************************************************************/ void qatDcPollAndSetNextPollCounter(compression_test_params_t *setup); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * handles retries from the driver when submit Q's are full. Counts * retries and calls context switch to pause submission * * @param[in] setup pointer to the compression setup * structure * @param[in] instanceInfo2 instance info structure is used to * determine if the instance is use is a * polled instance * @pre setup->perfStats is initialized * * @post retry is counted, OS runs any other * thread that was waiting for CPU time * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the driver failed to poll ****************************************************************************/ void qatDcRetryHandler(compression_test_params_t *setup, const CpaInstanceInfo2 *pInstanceInfo2); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * checks if the callback function has found an error in any response. * * @param[in] setup pointer to the compression setup * structure * @param[in] arrayOfResults pointer to the arrayOfResults that is * also visible in the callback function * @param[in] listNum number of submissions that have been * made from the total number of allocated * CpaBufferLists * @param[out] status pointer to the status, which is updated * in the event of a failure detected in * response * @pre[in] all memory to pointers are allocated * * @post threadReturnStatus is checked for any * response failures * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL an error was detected a response from * the driver ****************************************************************************/ void qatCompressionResponseStatusCheck(compression_test_params_t *setup, CpaDcRqResults *arrayOfResults, Cpa32U listNum, CpaStatus *status); #ifdef SC_CHAINING_ENABLED /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * checks if the callback function has found an error in any response. * * @param[in] setup pointer to the compression setup * structure * @param[in] arrayOfResults pointer to the arrayOfResults that is * also visible in the callback function * @param[in] listNum number of submissions that have been * made from the total number of allocated * CpaBufferLists * @param[out] status pointer to the status, which is updated * in the event of a failure detected in * response * @pre[in] all memory to pointers are allocated * * @post threadReturnStatus is checked for any * response failures * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL an error was detected a response from * the driver ****************************************************************************/ void qatDcChainResponseStatusCheck(compression_test_params_t *setup, CpaDcChainRqResults *arrayOfResults, Cpa32U listNum, CpaStatus *status); #endif /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * copy the a file from disk into memory to be used for compression and * start the driver compression service. * * @param[in] testBufferSize size to break the file to be compressed * into * @param[out] corpusType enum representing the file name to be * loaded. The exact enum to file mapping * is described in the function: * populateCorpusInternal * * @pre[in] the files exist on the system in the * path /lib/firmware/ by default * * @post the file is loaded into memory, * the compression service is started * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the file could not be loaded or the * compression service could not be started ****************************************************************************/ CpaStatus populateCorpusAndStartDcService(Cpa32U testBufferSize, corpus_type_t corpusType); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * set the flush flag to the type of compression being used * * @param[in] setup pointer to the compression setup * structure * @param[out] listNum index into array of CpaBufferList. * The flushFlag may change on the last * buffer to be submitted * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the flush flag could not be set ****************************************************************************/ CpaStatus qatCompressionSetFlushFlag(compression_test_params_t *setup, Cpa32U listNum); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * allocate the memory used to store a list of CpaPhysBufferLists * * @param[in] setup pointer to the compression setup structure * @param[in] srcBufferListArray array of CpaPhysBufferLists to be allocated * to store original file * @param[in] destBufferListArray array of CpaPhysBufferLists to be allocated * to store compressed data * @param[in] cmpBufferListArray array of CpaPhysBufferLists to be allocated * to place decompressed data * @param[in] opDataCmpArray array of cpaDcResults to be allocated to * store the results of compress operations * @param[in] opDataDcmpArray array of cpaDcResults to be allocated to * store the results of decompress operations * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL memory could not be allocated ****************************************************************************/ CpaStatus qatAllocateCompressionDpLists(compression_test_params_t *setup, CpaPhysBufferList **srcBufferListArray, CpaPhysBufferList **destBufferListArray, CpaPhysBufferList **cmpBufferListArray, CpaDcDpOpData **opDataCmpArray, CpaDcDpOpData **opDataDcmpArray); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * free the memory of CpaPhysBufferLists * * @param[in] setup pointer to the compression setup structure * @param[in] srcBufferListArray array of CpaPhysBufferLists to be freed * @param[in] destBufferListArray array of CpaPhysBufferLists to be freed * @param[in] cmpBufferListArray array of CpaPhysBufferLists to be freed * @param[in] opDataCmpArray array of cpaDcResults to be freed * @param[in] opDataDcmpArray array of cpaDcResults to be freed * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL memory could not be allocated ****************************************************************************/ CpaStatus qatFreeCompressionDpLists(compression_test_params_t *setup, CpaPhysBufferList **srcBufferListArray, CpaPhysBufferList **destBufferListArray, CpaPhysBufferList **cpmBufferListArray, CpaDcDpOpData **opDataCmpArray, CpaDcDpOpData **opDataDcmpArray); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sampleCode * * @description * allocate the CpaPhysFlatBuffers and members of the CpaPhysBufferLists * * @param[in] setup pointer to the compression setup * structure * @param[in] srcBufferListArray array of CpaPhysBufferLists to be * allocated * @param[in] numBuffersInSrcList number of CpaPhysFlatBuffers to be * allocated in srcBufferListArray * @param[in] sizeOfBuffersInSrcList size of CpaPhysBufferLists to be * allocated in srcBufferLists * @param[in] destBufferListArray array of CpaPhysBufferLists to be * allocated * @param[in] numBuffersInDstList number of CpaPhysFlatBuffers to be * allocated in dstBufferListArray * @param[in] sizeOfBuffersInDestList size of CpaBufferLists to be allocated * in destBufferLists * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be * allocated ****************************************************************************/ CpaStatus qatAllocateCompressionDpFlatBuffers( compression_test_params_t *setup, CpaPhysBufferList *srcBufferListArray, Cpa32U numBuffersInSrcList, Cpa32U sizeOfBuffersInSrcList, CpaPhysBufferList *destBufferListArray, Cpa32U numBuffersInDstList, Cpa32U sizeOfBuffersInDstList, CpaPhysBufferList *cpmBufferListArray, Cpa32U numBuffersInCpmList, Cpa32U sizeOfBuffersInCpmList); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * free the CpaPhysFlatBuffers and members of the CpaPhysBufferLists * * @param[in] setup pointer to the compression setup * structure * @param[in] srcBufferListArray array of CpaPhysBufferLists to be freed * @param[in] destBufferListArray array of CpaPhysBufferLists to be freed * @param[in] cpmBufferListArray array of CpaPhysBufferLists to be freed * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL some of the memory could not be * allocated ****************************************************************************/ CpaStatus qatFreeCompressionDpFlatBuffers( compression_test_params_t *setup, CpaPhysBufferList *srcBufferListArray, CpaPhysBufferList *destBufferListArray, CpaPhysBufferList *cpmBufferListArray); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * copy the corpus data that was loaded into memory by * populateCorpusAndStartDcService into the CpaPhysFlatBuffers of * arrayOfSrcBufferLists * * @param[in] arrayOfSrcBufferLists array of cpaPhysBufferLists which * contain allocate cpaPhysBufferLists to * copy the corpus data into * * @param[in] numberOfLists number of lists in array * @param[in] corpusFilePtr pointer to where corpus data has been * loaded into memory by * populateCorpusAndStartDcService * @param[in] testBufferSize size of data that each cpaPhysFlarBuffer * is allocated and how much from * corpusFilePtr that should be copied into * each buffer * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the corpus failed to copy into buffers ****************************************************************************/ CpaStatus qatPopulateDpBuffers(CpaPhysBufferList *arrayOfSrcBufferLists, Cpa32U numberOfLists, Cpa8U *corpusFilePtr, Cpa32U testBufferSize); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * initialize a session to use for data plane compression service * * @param[in] setup pointer to the compression setup * structure * @param[in] opDataArray array of Opdata structures in which the * initialized session is stored to * @param[in] pSessionHandle pointer to the session handle that has * already been initialized by * qatCompressionSessionInit * @param[in] srcBufferListArray array of CpaPhysBufferLists that can be * assigned to the opData.srcBuffer * @param[in] destBufferListArray aarray of CpaPhysBufferLists that can be * assigned to the opData.dstBuffer * @param[in] direction direction of session * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the corpus failed to copy into buffers ****************************************************************************/ void qatCompressionDpOpDataInit(compression_test_params_t *setup, CpaDcDpOpData *opDataArray, CpaDcSessionHandle *pSessionHandle, CpaPhysBufferList *srcBufferListArray, CpaPhysBufferList *destBufferListArray, CpaDcSessionDir direction); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * compress or decompress data using QA-API * * @param[in] setup pointer to the compression setup * structure * @param[in] direction direction of session * @param[in] opDataArray array of Opdata structures in which the * Initialized session is stored to * @param[in] arrayOfXxxBufferLists array of CpaPhysBufferLists, Src * contains the source data, Dst is the * where the compressed data is written, * cmp is where decompressed data is * written * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the corpus failed to copy into buffers ****************************************************************************/ CpaStatus qatCompressDecompressDpData(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaDcSessionDir compressDirection, CpaPhysBufferList *arrayOfSrcBufferLists, CpaPhysBufferList *arrayOfDestBufferLists, CpaPhysBufferList *arrayOfcpmBufferLists, CpaDcDpOpData *opDataArray); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * update the perfData struct with the amount of bytes produced and * consumed by the ongoing compress/decompress operations * * @param[in] setup pointer to the compression setup * structure * @param[in] opDataArray array of Opdata structures in which the * Initialized session is stored to * @param[in] perfData pointer to perfData in which contains * the count of produced and consumed data * this is later used for compression ratio * calculation * ****************************************************************************/ void qatDpSetBytesProducedAndConsumed(compression_test_params_t *setup, CpaDcDpOpData *opdata, perf_data_t *perfData); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * compare two CpaPhysBufferLists to see if they contain the same data * * @param[in] setup pointer to the compression setup * structure * @param[in] ppSrc source data to compare to * @param[in] ppDst destination data to be compared * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the corpus failed to copy into buffers ****************************************************************************/ CpaStatus qatCmpDpBuffers(compression_test_params_t *setup, CpaPhysBufferList *pSrc, CpaPhysBufferList *pDst); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * use software to compress or decompress data * * @param[in] setup pointer to the compression setup * structure * @param[in] srcBufferListArray source data to be compressed * @param[in] destBufferListArray pointer to memory to write out results * @param[in] cmpResults structure to store produced and consumed * data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL the corpus failed to copy into buffers ****************************************************************************/ CpaStatus qatSwCompressDp(compression_test_params_t *setup, CpaBufferList *dstBuffListArray, CpaDcRqResults *cmpResults, CpaBufferList *srcBuffListArray); /** ***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * this is an example thread that combines the sample code functions * to show how to compress or decompress data using the QA-API * * @param[in] setup pointer to the compression setup * structure * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL failed to complete successfully ****************************************************************************/ CpaStatus qatDpMain(compression_test_params_t *setup); /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Used for profiling IA offload cost using the sleeptime method * on every retry. * * Phase One:Iterates over the main compress function, increasing the number * of sleeptime value(setup->sleepTime) on each iteration until performance is * affected within 5% different of base and current throughput * * Phase Two: Continues to iterate over the main compress function, increasing * the number of sleeptime cycles on each iteration until performance is * back to the margin of 1.5%. to do it it will increase and decrease sleeptime * value depending on the current throughput * * Function should finish with the most suitable sleeptime value for given * packet size, algorithm, compression level etc. *****************************************************************************/ CpaStatus performSleeptimeCalculation( compression_test_params_t *setup, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcRqResults *resultArray, CpaDcCallbackFn dcCbFn, CpaDcSessionDir dcSessDir, CpaDcSessionHandle pDecompressSessionHandle); /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Used for profiling IA offload cost using buy loop. * * Phase One:Iterates over the main perform function, increasing the number * of busy loop cycles(BUSY_LOOP_INCREMENT) on each iteration until no retries * occur. * * Phase Two: Continues to iterate over the main perform function, increasing * the number of busy loop cycles on each iteration until performance is * affected then steps back to the last increment value, i.e. the last * increment step(BUSY_LOOP_INCREMENT) before performance was affected. * * Phase three: Calculate Offload cycles by measuring cycles spend on busy *loop, taking it away from total cycles and dividing by number of responses. *****************************************************************************/ CpaStatus performOffloadCalculationBusyLoop( compression_test_params_t *setup, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcRqResults *resultArray, CpaDcCallbackFn dcCbFn, CpaDcSessionDir dcSessDir, CpaDcSessionHandle pSessionHandle); #ifdef SC_CHAINING_ENABLED /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Used for profiling IA offload cost using buy loop. * * Phase One:Iterates over the main perform function, increasing the number * of busy loop cycles(BUSY_LOOP_INCREMENT) on each iteration until no retries * occur. * * Phase Two: Continues to iterate over the main perform function, increasing * the number of busy loop cycles on each iteration until performance is * affected then steps back to the last increment value, i.e. the last * increment step(BUSY_LOOP_INCREMENT) before performance was affected. * * Phase three: Calculate Offload cycles by measuring cycles spend on busy *loop, taking it away from total cycles and dividing by number of responses. *****************************************************************************/ CpaStatus performDcChainOffloadCalculationBusyLoop( compression_test_params_t *setup, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcChainRqResults *resultArray, CpaDcChainOpData *chainOpData, CpaDcCallbackFn dcCbFn, CpaDcSessionDir dcSessDir, CpaDcSessionHandle pSessionHandle); #endif /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * This is the performance thread created by the sample code framework * after registering the setupScDcTest and calling createPeformance threads * this function copies the setup into its own local copy and then calls * scDcPoc to measure compression performance * * @param[in] setup pointer to the compression setup * structure * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL failed to complete successfully *****************************************************************************/ void dcPerformance(single_thread_test_data_t *testSetup); /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * This function allocates buffers store a file for compression. The buffers are * sent to hardware, performance is recorded and stored in the setup parameter * the sample code framework prints out results after the thread completes * * @param[in] setup pointer to the compression setup * structure * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL failed to complete successfully *****************************************************************************/ CpaStatus qatDcPerform(compression_test_params_t *setup); /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Performance measurement function to compress a file for 'n' number of loops * * @param[in] setup pointer to the compression setup * structure * @param[in] pSessionHandle handler for a session * @param[in] compressDirection enum variable storing the direction of *the session * @param[in] arrayOfSrcBufferLists source data to be compressed * @param[in] arrayOfDestBufferLists pointer to memory to write out results * @param[in] arrayOfCpmBufferLists pointer to memory compare results * @param[in] arrayOfResults structure to store produced and consumed * data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL failed to complete successfully *****************************************************************************/ CpaStatus qatCompressData(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaDcSessionDir compressDirection, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCpmBufferLists, CpaDcRqResults *arrayOfResults); #ifdef SC_CHAINING_ENABLED /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Chaining Performance measurement function to compress a file for 'n' number *of loops * * @param[in] setup pointer to the compression setup * structure * @param[in] pSessionHandle handler for a session * @param[in] compressDirection enum variable storing the direction of *the session * @param[in] arrayOfSrcBufferLists source data to be compressed * @param[in] arrayOfDestBufferLists pointer to memory to write out results * @param[in] arrayOfCpmBufferLists pointer to memory compare results * @param[in] arrayOfResults structure to store produced and consumed * data * @param[in] arrayOfChainOpData structure to store chain operation data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL failed to complete successfully *****************************************************************************/ CpaStatus qatDcChainCompressData(compression_test_params_t *setup, CpaDcSessionHandle pSessionHandle, CpaDcSessionDir compressDirection, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcChainRqResults *arrayOfResults, CpaDcChainOpData *arrayOfChainOpData); #endif /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Update in sample code framework how much data was consumed and produced by * thread * * @param[in] setup pointer to the compression setup * structure * @param[in] perfData pointer to the performance * data structure * @param[in] result structure to store produced and consumed * data * @param[in] direction compress direction * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL failed to complete successfully *****************************************************************************/ void dcScSetBytesProducedAndConsumed(CpaDcRqResults *result, perf_data_t *perfData, compression_test_params_t *setup, CpaDcSessionDir direction); #ifdef SC_CHAINING_ENABLED /***************************************************************************** * @file qat_compression_main.h * * @ingroup sample_code * * @description * Update in sample code framework how much data was consumed and produced by * thread * * @param[in] setup pointer to the compression setup * structure * @param[in] perfData pointer to the performance * data structure * @param[in] result structure to store produced and consumed * data * @param[in] direction compress direction * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL failed to complete successfully *****************************************************************************/ void dcChainScSetBytesProducedAndConsumed(CpaDcChainRqResults *result, perf_data_t *perfData, compression_test_params_t *setup, CpaDcSessionDir direction); #endif #endif /*QAT_COMPRESSION_MAIN_H*/ qat_compression_utils.c000066400000000000000000002320031503624047500365410ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "cpa_sample_code_dc_utils.h" #include "cpa_dc.h" #include "../common/qat_perf_buffer_utils.h" #include "qat_perf_utils.h" #include "qat_compression_main.h" #include "cpa_sample_code_framework.h" #include "qat_perf_sleeptime.h" #include "busy_loop.h" #include "qat_perf_cycles.h" #include "qat_compression_zlib.h" CpaStatus qatFreeCompressionFlatBuffer(compression_test_params_t *setup, CpaBufferList *bufferListArray); CpaStatus qatGetCompressBoundDestinationBufferSize( compression_test_params_t *setup, Cpa32U dcInputBufferSize, Cpa32U *dcDestBufferSize) { CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(dcDestBufferSize, status); { if (setup->setupData.compType == CPA_DC_DEFLATE) { status = cpaDcDeflateCompressBound(setup->dcInstanceHandle, setup->setupData.huffType, dcInputBufferSize, dcDestBufferSize); } #if DC_API_VERSION_AT_LEAST(3, 1) else if (setup->setupData.compType == CPA_DC_LZ4) { status = cpaDcLZ4CompressBound( setup->dcInstanceHandle, dcInputBufferSize, dcDestBufferSize); } else if (setup->setupData.compType == CPA_DC_LZ4S) { status = cpaDcLZ4SCompressBound( setup->dcInstanceHandle, dcInputBufferSize, dcDestBufferSize); } #endif else { PRINT_ERR("%s : Unsupported Compression Type %d\n", __func__, setup->setupData.compType); status = CPA_STATUS_FAIL; } } if (status == CPA_STATUS_SUCCESS) { setup->dcDestBufferSize = *dcDestBufferSize; } return status; } static CpaStatus qatDcGetDestBufferAdditionalSize( compression_test_params_t *setup, Cpa32U *additionalSize) { Cpa32U compDestBufferSize = 0; CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(additionalSize, status); *additionalSize = 0; status = qatGetCompressBoundDestinationBufferSize( setup, setup->bufferSize, &compDestBufferSize); if (CPA_STATUS_SUCCESS == status) { *additionalSize = compDestBufferSize - setup->bufferSize; } if (setup->setupData.sessDirection != CPA_DC_DIR_COMPRESS) { /* Save the Destination buffer size in the setup parameters for future * use*/ setup->dcDestBufferSize = *additionalSize + setup->bufferSize; } return status; } /*free the array of source and destination CpaBufferLists * free the array of results*/ CpaStatus qatFreeCompressionLists(compression_test_params_t *setup, CpaBufferList **srcBufferListArray, CpaBufferList **destBufferListArray, CpaBufferList **cpmBufferListArray, CpaDcRqResults **resultArray) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus retStatus = CPA_STATUS_SUCCESS; status = FreeArrayOfStructures((void **)srcBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free srcBufferListArray"); retStatus = CPA_STATUS_FAIL; } status = FreeArrayOfStructures((void **)destBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free destBufferListArray"); retStatus = CPA_STATUS_FAIL; } if (NULL != resultArray) { status = FreeArrayOfStructures((void **)resultArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free resultArray"); retStatus = CPA_STATUS_FAIL; } } status = FreeArrayOfStructures((void **)cpmBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free cpmBufferListArray"); retStatus = CPA_STATUS_FAIL; } return retStatus; } #ifdef SC_CHAINING_ENABLED /*free the array of chaining source and destination CpaBufferLists * free the array of chaining results*/ CpaStatus qatFreeDcChainLists(void **chainResultArray, void **chainOpDataArray) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus retStatus = CPA_STATUS_SUCCESS; if (NULL != chainResultArray) { status = FreeArrayOfStructures(chainResultArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free chainResultArray"); retStatus = CPA_STATUS_FAIL; } status = FreeArrayOfStructures(chainOpDataArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free chainOpDataArray"); retStatus = CPA_STATUS_FAIL; } } return retStatus; } #endif /*allocate the array of source and destination CpaBufferLists * allocate the array of results*/ CpaStatus qatAllocateCompressionLists(compression_test_params_t *setup, CpaBufferList **srcBufferListArray, CpaBufferList **destBufferListArray, CpaBufferList **cpmBufferListArray, CpaDcRqResults **resultArray) { CpaStatus status = CPA_STATUS_SUCCESS; status = AllocArrayOfStructures( (void **)srcBufferListArray, setup->numLists, sizeof(CpaBufferList)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate memory for srcBufferListArray\n"); } if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures((void **)destBufferListArray, setup->numLists, sizeof(CpaBufferList)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate destBufferListArray\n"); } } if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures((void **)cpmBufferListArray, setup->numLists, sizeof(CpaBufferList)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate cpmBufferListArray\n"); } } if (NULL != resultArray) { if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures( (void **)resultArray, setup->numLists, sizeof(CpaDcRqResults)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate resultArray\n"); } } } if (CPA_STATUS_SUCCESS != status) { /*something went wrong so attempt to free allocated structures * Don't capture the status here as we want to return non success anyway */ qatFreeCompressionLists(setup, srcBufferListArray, destBufferListArray, cpmBufferListArray, resultArray); } return status; } #ifdef SC_CHAINING_ENABLED /*allocate the array of source and destination dc chain Lists * allocate the array of results*/ CpaStatus qatAllocateDcChainLists(compression_test_params_t *setup, void **chainResultArray, void **chainOpDataArray) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U chainResultLen = 0; Cpa32U chainOpDataLen = 0; if (setup->legacyChainRequest) { chainResultLen = sizeof(CpaDcChainRqResults); chainOpDataLen = sizeof(CpaDcChainOpData); } if (NULL != chainResultArray) { if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures( chainResultArray, setup->numLists, chainResultLen); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate chainResultArray\n"); } } if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures(chainOpDataArray, setup->numLists * setup->numSessions, chainOpDataLen); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate chainOpDataArray\n"); } } } if (CPA_STATUS_SUCCESS != status) { /*something went wrong so attempt to free allocated structures * Don't capture the status here as we want to return non success anyway */ qatFreeDcChainLists(chainResultArray, chainOpDataArray); } return status; } #endif /*free the CpaFlatBuffers and privateMetaData in the CpaBufferLists array * for both source and destination lists*/ CpaStatus qatFreeCompressionFlatBuffers(compression_test_params_t *setup, CpaBufferList *srcBufferListArray, CpaBufferList *destBufferListArray, CpaBufferList *cpmBufferListArray) { CpaStatus status = CPA_STATUS_SUCCESS; if (CPA_STATUS_SUCCESS != freeBuffersInLists(srcBufferListArray, setup->numLists)) { PRINT_ERR("freeBuffersInLists (src) error\n"); status = CPA_STATUS_FAIL; } // keep trying to free destListArray if (CPA_STATUS_SUCCESS != freeBuffersInLists(destBufferListArray, setup->numLists)) { status = CPA_STATUS_FAIL; PRINT_ERR("freeBuffersInLists (dest) error\n"); } if (CPA_STATUS_SUCCESS != freeBuffersInLists(cpmBufferListArray, setup->numLists)) { status = CPA_STATUS_FAIL; PRINT_ERR("freeBuffersInLists (dest) error\n"); } return status; } /*free the CpaFlatBuffers and privateMetaData in the CpaBufferLists array * for both source and destination lists*/ CpaStatus qatFreeCompressionFlatBuffer(compression_test_params_t *setup, CpaBufferList *bufferListArray) { CpaStatus status = CPA_STATUS_SUCCESS; if (CPA_STATUS_SUCCESS != qatFreeFlatBuffersInList(bufferListArray)) { PRINT_ERR("freeBuffersInLists (src) error\n"); status = CPA_STATUS_FAIL; } return status; } /*allocate the CpaFlatBuffers and privateMetaData in the CpaBufferLists array * for both source and destination lists*/ CpaStatus qatAllocateCompressionFlatBuffers( compression_test_params_t *setup, CpaBufferList *srcBufferListArray, Cpa32U numBuffersInSrcList, /*affects the metaSize of CpaBufferList*/ Cpa32U *sizeOfBuffersInSrcList, /*size of CpaFlatBuffers to allocate*/ CpaBufferList *destBufferListArray, Cpa32U numBuffersInDstList, Cpa32U *sizeOfBuffersInDstList, CpaBufferList *cpmBufferListArray, Cpa32U numBuffersInCpmList, Cpa32U *sizeOfBuffersInCpmList) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U metaSize = 0; /*additional size is used to allocate extra buffer space in case compression * ends up in expanded */ Cpa32U additionalSize = 0; if (CPA_STATUS_SUCCESS == status) { // getDcMetaSize required for the src list status = cpaDcBufferListGetMetaSize( setup->dcInstanceHandle, numBuffersInSrcList, &metaSize); } if (CPA_STATUS_SUCCESS == status) { status = AllocateBuffersInLists(srcBufferListArray, setup->numLists, numBuffersInSrcList, sizeOfBuffersInSrcList, additionalSize, metaSize, setup->node, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { // getDcMetaSize required for the dest list status = cpaDcBufferListGetMetaSize( setup->dcInstanceHandle, numBuffersInDstList, &metaSize); } if (CPA_STATUS_SUCCESS == status) { /* Get Destination buffer additional size. * This additionalSize will be added to the packet size * and the total size is allocated for destination buffer */ status = qatDcGetDestBufferAdditionalSize(setup, &additionalSize); } if (CPA_STATUS_SUCCESS == status) { status = AllocateBuffersInLists(destBufferListArray, setup->numLists, numBuffersInDstList, sizeOfBuffersInDstList, additionalSize, metaSize, setup->node, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { // getDcMetaSize required for the dest list status = cpaDcBufferListGetMetaSize( setup->dcInstanceHandle, numBuffersInCpmList, &metaSize); } if (setup->disableAdditionalCmpbufferSize == CPA_FALSE) { /* For reliabilty mode we need to allocate double the space to extract * the SW compressed data into*/ additionalSize = sizeOfBuffersInCpmList[0]; } else { /* For performance use cases additional buffer size is not required * to be added to the cmp buffer, as there is no SW checks*/ additionalSize = 0; } if (CPA_STATUS_SUCCESS == status) { status = AllocateBuffersInLists(cpmBufferListArray, setup->numLists, numBuffersInCpmList, sizeOfBuffersInCpmList, additionalSize, metaSize, setup->node, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS != status) { // an error has occurred allocating memory so we need to free qatFreeCompressionFlatBuffers( setup, srcBufferListArray, destBufferListArray, cpmBufferListArray); } return status; } static CpaStatus qatAllocateCompressionFlatBuffer( compression_test_params_t *setup, CpaBufferList *bufferList, Cpa32U numBuffersInList, /*affects the metaSize of CpaBufferList*/ Cpa32U sizeOfBuffersInList) /*size of CpaFlatBuffers to allocate*/ { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U metaSize = 0; /*shared common buffer allocation with crypto means we need to declare this but its not used in compression*/ Cpa32U bufferSize = sizeOfBuffersInList; if (CPA_STATUS_SUCCESS == status) { // getDcMetaSize required for the list status = cpaDcBufferListGetMetaSize( setup->dcInstanceHandle, numBuffersInList, &metaSize); } if (CPA_STATUS_SUCCESS == status) { status = qatAllocateFlatBuffersInList(bufferList, setup->node, metaSize, numBuffersInList, bufferSize, BYTE_ALIGNMENT_64); } // not able to allocate all memory, so free any that was allocated if (CPA_STATUS_SUCCESS != status) { // an error has occurred allocating memory so we need to free qatFreeFlatBuffersInList(bufferList); } return status; } #ifdef USER_SPACE #ifdef SC_CHAINING_ENABLED /*allocate a compression session and initialize it for a Chaining thread*/ CpaStatus qatDcChainSessionInit(compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle, CpaDcCallbackFn dcCbFn) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sessionSize = 0; Cpa8U numSessions = setup->numSessions; CpaDcChainSessionSetupData chainSessionData[numSessions]; /* Assign chain session setup data */ switch (setup->chainOperation) { case CPA_DC_CHAIN_HASH_THEN_COMPRESS: chainSessionData[0].sessType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainSessionData[0].pCySetupData = &(setup->symSetupData); chainSessionData[1].sessType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainSessionData[1].pDcSetupData = &(setup->setupData); break; case CPA_DC_CHAIN_COMPRESS_THEN_AEAD: chainSessionData[0].sessType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainSessionData[0].pDcSetupData = &(setup->setupData); chainSessionData[1].sessType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainSessionData[1].pCySetupData = &(setup->symSetupData); break; case CPA_DC_CHAIN_AEAD_THEN_DECOMPRESS: chainSessionData[0].sessType = CPA_DC_CHAIN_SYMMETRIC_CRYPTO; chainSessionData[0].pCySetupData = &(setup->symSetupData); chainSessionData[1].sessType = CPA_DC_CHAIN_COMPRESS_DECOMPRESS; chainSessionData[1].pDcSetupData = &(setup->setupData); break; default: PRINT_ERR("Unsupported chaining operation.\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /* Get Size for DC Session */ status = cpaDcChainGetSessionSize(setup->dcInstanceHandle, setup->chainOperation, numSessions, chainSessionData, &sessionSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcChainGetSessionSize returned status %d\n", status); } } if (CPA_STATUS_SUCCESS == status) { /* Allocate Memory for DC Session */ *pSessionHandle = (CpaDcSessionHandle)qaeMemAllocNUMA( sessionSize, setup->node, BYTE_ALIGNMENT_64); *pDecompressSessionHandle = (CpaDcSessionHandle)qaeMemAllocNUMA( sessionSize, setup->node, BYTE_ALIGNMENT_64); if (*pSessionHandle == NULL || *pDecompressSessionHandle == NULL) { PRINT_ERR("could not allocate pSessionHandle\n"); status = CPA_STATUS_FAIL; } } if (setup->syncFlag == SYNC) { dcCbFn = NULL; } if (CPA_STATUS_SUCCESS == status) { status = cpaDcChainInitSession(setup->dcInstanceHandle, *pSessionHandle, setup->chainOperation, numSessions, chainSessionData, dcCbFn); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcChainInitSession returned status for compression " "handle %d\n", status); } } return status; } CpaStatus qatDcChainSessionTeardown( compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus retStatus = CPA_STATUS_SUCCESS; status = cpaDcChainRemoveSession(setup->dcInstanceHandle, *pSessionHandle); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcChainRemoveSession returned status %d\n", status); retStatus = CPA_STATUS_FAIL; } qaeMemFreeNUMA((void **)&(*pSessionHandle)); qaeMemFreeNUMA((void **)&(*pDecompressSessionHandle)); if (NULL != *pSessionHandle || NULL != *pDecompressSessionHandle) { PRINT_ERR("could not free pSessionHandle\n"); retStatus = CPA_STATUS_FAIL; } return retStatus; } #endif #endif /*allocate a compression session and initialize it for a compression thread*/ CpaStatus qatCompressionSessionInit( compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle, CpaBufferList *pContextBuffer, CpaDcCallbackFn dcCbFn) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sessionSize = 0; Cpa32U contextSize = 0; CpaDcSessionSetupData tempSetupData = setup->setupData; Cpa32U numberOfBuffersPerList = ONE_BUFFER_DC; Cpa8U compressionSessionInitialize = 0; Cpa8U decompressionSessionInitialize = 0; /* * Required session initialization matrix: * | Dir | Rel | Required session | * | C | 0 | C | * | C | 1 | C | * | D | 0 | CD | * | D | 1 | D | * | CD | 0 | Unsupported | * | CD | 1 | Unsupported | */ switch (setup->setupData.sessDirection) { case CPA_DC_DIR_COMPRESS: compressionSessionInitialize = 1; break; case CPA_DC_DIR_DECOMPRESS: decompressionSessionInitialize = 1; if (!reliability_g) compressionSessionInitialize = 1; break; case CPA_DC_DIR_COMBINED: status = CPA_STATUS_UNSUPPORTED; PRINT_ERR("Combined session testing unsupported\n"); break; default: break; } // cpaScInitDcSession(...) if (CPA_STATUS_SUCCESS == status) { /* Get Size for DC Session */ status = cpaDcGetSessionSize(setup->dcInstanceHandle, &(setup->setupData), &sessionSize, &contextSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetSessionSize returned status %d\n", status); } } if (CPA_STATUS_SUCCESS == status) { if (contextSize > 0) { // fill context buffer data if (CPA_STATUS_SUCCESS != qatAllocateCompressionFlatBuffer( setup, pContextBuffer, numberOfBuffersPerList, contextSize)) { PRINT_ERR("could not allocate context flat buffers for " "compression\n"); status = CPA_STATUS_FAIL; } } } if (setup->syncFlag == SYNC) { dcCbFn = NULL; } if (decompressionSessionInitialize == 1) { /* Allocate Memory for DC Session */ *pDecompressSessionHandle = (CpaDcSessionHandle)qaeMemAllocNUMA( (sessionSize + contextSize), setup->node, BYTE_ALIGNMENT_64); if (*pDecompressSessionHandle == NULL) { PRINT_ERR("could not allocate pDecompressSessionHandle\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { tempSetupData.sessDirection = CPA_DC_DIR_DECOMPRESS; status = cpaDcInitSession(setup->dcInstanceHandle, *pDecompressSessionHandle, &(tempSetupData), pContextBuffer, dcCbFn); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInitSession returned status for decompression " "handle %d\n", status); } } if (CPA_STATUS_SUCCESS == status) { setup->pSessionHandle = *pDecompressSessionHandle; } } if (compressionSessionInitialize == 1) { /* Allocate Memory for DC Session */ *pSessionHandle = (CpaDcSessionHandle)qaeMemAllocNUMA( (sessionSize + contextSize), setup->node, BYTE_ALIGNMENT_64); if (*pSessionHandle == NULL) { PRINT_ERR("could not allocate pSessionHandle\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { tempSetupData.sessDirection = CPA_DC_DIR_COMPRESS; status = cpaDcInitSession(setup->dcInstanceHandle, *pSessionHandle, &(tempSetupData), pContextBuffer, dcCbFn); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcInitSession returned status for decompression " "handle %d\n", status); } } if (CPA_STATUS_SUCCESS == status) { setup->pSessionHandle = *pSessionHandle; } } return status; } CpaStatus qatCompressionSessionTeardown( compression_test_params_t *setup, CpaDcSessionHandle *pSessionHandle, CpaDcSessionHandle *pDecompressSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus retStatus = CPA_STATUS_SUCCESS; if (*pDecompressSessionHandle != NULL) { status = cpaDcRemoveSession(setup->dcInstanceHandle, *pDecompressSessionHandle); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcRemoveSession returned status %d\n", status); retStatus = CPA_STATUS_FAIL; } qaeMemFreeNUMA((void **)&(*pDecompressSessionHandle)); if (NULL != *pDecompressSessionHandle) { PRINT_ERR("could not free pDecompressSessionHandle\n"); retStatus = CPA_STATUS_FAIL; } } if (*pSessionHandle != NULL) { status = cpaDcRemoveSession(setup->dcInstanceHandle, *pSessionHandle); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcRemoveSession returned status %d\n", status); retStatus = CPA_STATUS_FAIL; } qaeMemFreeNUMA((void **)&(*pSessionHandle)); if (NULL != *pSessionHandle) { PRINT_ERR("could not free pSessionHandle\n"); retStatus = CPA_STATUS_FAIL; } } return retStatus; } void qatDumpBufferListInfo(compression_test_params_t *setup, CpaBufferList *pSrc, CpaBufferList *pDst, CpaBufferList *pCmp, Cpa32U listNum) { if (listNum > 0) { qatCompressDumpToFile( setup, pSrc, "srcBuffer", "srcBuffSize", listNum + 1); qatCompressDumpToFile( setup, pDst, "dstBuffer", "dstBufferSize", listNum + 1); qatCompressDumpToFile( setup, pCmp, "cmpBuffer", "cmpBufferSize", listNum + 1); } qatCompressDumpToFile(setup, pSrc, "srcFile", "srcFileSize", 0); qatCompressDumpToFile(setup, pDst, "dstFile", "dstFileSize", 0); qatCompressDumpToFile(setup, pCmp, "cmpFile", "cmpFileSize", 0); } CpaStatus qatIsBufEmpty(Cpa8U *buf, size_t pktSize) { CpaStatus status = CPA_STATUS_SUCCESS; if (pktSize < (2 * sizeof(uint64_t))) { if (*buf != 0 || memcmp(buf, buf + 1, pktSize - 1) != 0) { status = CPA_STATUS_FAIL; } } else { if (memcmp(buf, buf + sizeof(uint64_t), pktSize - sizeof(uint64_t)) != 0) { status = CPA_STATUS_FAIL; } } return status; } CpaStatus qatCmpBuffers(compression_test_params_t *setup, CpaBufferList *pSrc, CpaBufferList *pDst) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0, j = 0, count = 0; Cpa8U *originalData = NULL; Cpa8U *processedData = NULL; Cpa32U sizeOfSrcFile = 0; Cpa32U sizeOfDstFile = 0; Cpa32U offset = 0; Cpa32U offset2 = 0; /* Compare the source and destination * buffers */ /*buffer sizes might vary, so tally up the total size of the src and dst * bufferLists, the total size of each should match otherwise return * an error */ for (j = 0; j < setup->numberOfBuffers[i]; j++) { sizeOfSrcFile += pSrc[j].pBuffers->dataLenInBytes; sizeOfDstFile += pDst[j].pBuffers->dataLenInBytes; } if (sizeOfSrcFile != sizeOfDstFile) { PRINT_ERR("Src(%d bytes) and Dst(%d bytes) total size does not match\n", sizeOfSrcFile, sizeOfDstFile); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { processedData = qaeMemAlloc(sizeOfDstFile); originalData = qaeMemAlloc(sizeOfSrcFile); if (NULL == processedData || NULL == originalData) { PRINT_ERR("Memory allocation failure for data comparison\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { for (j = 0; j < setup->numberOfBuffers[i]; j++) { memcpy((originalData + offset), pSrc[j].pBuffers->pData, pSrc[j].pBuffers->dataLenInBytes); memcpy((processedData + offset2), pDst[j].pBuffers->pData, pDst[j].pBuffers->dataLenInBytes); offset += pSrc[j].pBuffers->dataLenInBytes; offset2 += pDst[j].pBuffers->dataLenInBytes; if (setup->setupData.sessState == CPA_DC_STATELESS) { /*check that src and dst buffer lengths match*/ if (pSrc[j].pBuffers->dataLenInBytes != pDst[j].pBuffers->dataLenInBytes) { PRINT_ERR("src buffer length (%u) and dst buffer length " "(%u) does not match\n", pSrc[j].pBuffers->dataLenInBytes, pDst[j].pBuffers->dataLenInBytes); } /*check that src and dst data match*/ count = memcmp(pSrc[j].pBuffers->pData, pDst[j].pBuffers->pData, pDst[j].pBuffers->dataLenInBytes); if (0 != count) { PRINT_ERR( "Buffers comparison Failed j:%d, count:%d\n", j, count); qatDumpBufferListInfo(setup, pSrc, pDst, NULL, j); status = CPA_STATUS_FAIL; break; } } } /* Compare the decompressed data to original*/ count = memcmp(originalData, processedData, sizeOfDstFile); if (0 != count) { PRINT_ERR("Buffers comparison Failed i:%d, count:%d\n", i, count); status = CPA_STATUS_FAIL; } } if (NULL != processedData) { qaeMemFree((void **)&processedData); } if (NULL != originalData) { qaeMemFree((void **)&originalData); } return status; } static CpaStatus qatSwZlibCompress(compression_test_params_t *setup, CpaBufferList *srcBuffListArray, CpaBufferList *dstBuffListArray, CpaDcRqResults *cmpResults) { CpaStatus status = CPA_STATUS_SUCCESS; struct z_stream_s stream = {0}; Cpa32U j = 0; int zlibFlushflag; /* call the compress api */ for (j = 0; j < setup->numLists; j++) { memset(&stream, 0, sizeof(struct z_stream_s)); deflate_init(&stream); if ((CPA_DC_STATEFUL == setup->setupData.sessState) && (j < setup->numLists - 1)) { zlibFlushflag = Z_SYNC_FLUSH; } else { zlibFlushflag = Z_FINISH; } status = deflate_compress(&stream, srcBuffListArray[j].pBuffers->pData, srcBuffListArray[j].pBuffers->dataLenInBytes, dstBuffListArray[j].pBuffers->pData, dstBuffListArray[j].pBuffers->dataLenInBytes, zlibFlushflag); if (CPA_STATUS_SUCCESS != status) { PRINT("srcLen: %d, destLen: %d \n", srcBuffListArray[j].pBuffers->dataLenInBytes, dstBuffListArray[j].pBuffers->dataLenInBytes); break; } cmpResults[j].consumed = stream.total_in; cmpResults[j].produced = stream.total_out; deflate_destroy(&stream); } return status; } CpaStatus qatSwCompress(compression_test_params_t *setup, CpaBufferList *srcBuffListArray, CpaBufferList *dstBuffListArray, CpaDcRqResults *cmpResults) { CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(srcBuffListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(dstBuffListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(cmpResults, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); if (CPA_STATUS_SUCCESS == status) { if (setup->setupData.compType == CPA_DC_DEFLATE) { status = qatSwZlibCompress( setup, srcBuffListArray, dstBuffListArray, cmpResults); } else { PRINT_ERR("Unsupported Compression type %d\n", setup->setupData.compType); status = CPA_STATUS_FAIL; } } return status; } static CpaStatus qatHandleUnconsumedData(compression_test_params_t *setup, CpaBufferList *bufferListArray, Cpa32U listNum, Cpa32U offset, Cpa32U remainder) { CpaFlatBuffer tempFB; CpaStatus status = CPA_STATUS_SUCCESS; if (listNum == setup->numLists - 1) { PRINT_ERR("Unconsumed data not expected in the last list\n"); status = CPA_STATUS_FAIL; } else { tempFB.pData = qaeMemAllocNUMA(setup->bufferSize, setup->node, BYTE_ALIGNMENT_64); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(tempFB.pData, status); if (bufferListArray[listNum + 1].pBuffers->dataLenInBytes + remainder > setup->dcDestBufferSize) { PRINT_ERR("The unconsumed data (%d) does not fit the next buffer " "size (%d) /n", remainder + bufferListArray[listNum + 1].pBuffers->dataLenInBytes, setup->dcDestBufferSize); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { memcpy(tempFB.pData, bufferListArray[listNum + 1].pBuffers->pData, bufferListArray[listNum + 1].pBuffers->dataLenInBytes); tempFB.dataLenInBytes = bufferListArray[listNum + 1].pBuffers->dataLenInBytes; /* Copy the remaining data to the start of the next * request */ memcpy(bufferListArray[listNum + 1].pBuffers->pData, (bufferListArray[listNum].pBuffers->pData + offset), remainder); /* Copy the original data of the next request and * append to the remaining data */ memcpy((bufferListArray[listNum + 1].pBuffers->pData + remainder), tempFB.pData, tempFB.dataLenInBytes); /* Update the next request with the correct length */ bufferListArray[listNum + 1].pBuffers->dataLenInBytes = remainder + tempFB.dataLenInBytes; /* Update the current request with the correct length */ bufferListArray[listNum].pBuffers->dataLenInBytes = offset; qaeMemFreeNUMA((void **)&tempFB.pData); } } return status; } CpaStatus qatCheckAndHandleUnconsumedData(compression_test_params_t *setup, CpaBufferList *arrayOfDestBufferLists, CpaDcRqResults *arrayOfResults, Cpa32U listNum, const char *partName) { Cpa64S remainder = 0; Cpa64S offset = 0; CpaStatus status = CPA_STATUS_FAIL; remainder = arrayOfDestBufferLists[listNum].pBuffers->dataLenInBytes - arrayOfResults[listNum].consumed; offset = arrayOfDestBufferLists[listNum].pBuffers->dataLenInBytes - remainder; /*there should not be any unconsumed data for "c4xx"*/ if (strncmp(partName, "c4xx", strlen("c4xx")) == 0) { PRINT_ERR("HW did not consume the entire buffer \n"); return status; } if (remainder < 0) { /*For dh895x in case if the last buffer doesn't contain an end of *stream, fw adds tailing zeros to the buffer so the number *of consumed bytes became larger than expected.*/ if ((strncmp(partName, "dh895", strlen("dh895")) == 0) && (listNum == setup->numLists - 1) && (arrayOfDestBufferLists[listNum].pBuffers->dataLenInBytes < arrayOfResults[listNum].consumed)) { status = CPA_STATUS_SUCCESS; } } else { /*copy any unconsumed data into the next buffer*/ status = qatHandleUnconsumedData( setup, arrayOfDestBufferLists, listNum, offset, remainder); } return status; } #ifdef SC_CHAINING_ENABLED void qatDcChainUpdateProducedBufferLength(compression_test_params_t *setup, CpaBufferList *bufferListArray, CpaDcChainRqResults *resultArray) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i, j = 0; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(bufferListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(resultArray, status); if (CPA_STATUS_SUCCESS == status) { for (i = 0; i < setup->numLists; i++) { for (j = 0; j < bufferListArray->numBuffers; j++) { bufferListArray[i].pBuffers[j].dataLenInBytes = resultArray[i].produced; } } } else { PRINT_ERR("Cannot update the bufferListArray\n"); } return; } #endif void qatDcUpdateProducedBufferLength(compression_test_params_t *setup, CpaBufferList *bufferListArray, CpaDcRqResults *resultArray) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i, j = 0; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(bufferListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(resultArray, status); if (CPA_STATUS_SUCCESS == status) { for (i = 0; i < setup->numLists; i++) { for (j = 0; j < bufferListArray->numBuffers; j++) { bufferListArray[i].pBuffers[j].dataLenInBytes = resultArray[i].produced; } } } else { PRINT_ERR("Cannot update the bufferListArray\n"); } return; } CpaStatus qatCompressResetBufferList(compression_test_params_t *setup, CpaBufferList *buffListArray, Cpa32U *flafBufferSize, CpaBoolean isCmpBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i, j = 0; Cpa32U bufferSize = 0; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(buffListArray, status); if (CPA_STATUS_SUCCESS == status) { for (i = 0; i < setup->numLists; i++) { for (j = 0; j < buffListArray->numBuffers; j++) { /* Recalculate the buffer size as it can be double the * packet size. Destination buffer size is saved in setup */ if (isCmpBuffer) bufferSize = 2 * flafBufferSize[i]; else bufferSize = setup->dcDestBufferSize; buffListArray[i].pBuffers[j].dataLenInBytes = bufferSize; memset(buffListArray[i].pBuffers[j].pData, 0, bufferSize); } } } return status; } void qatCompressDumpToFile(compression_test_params_t *setup, CpaBufferList *buffListArray, char *fileName, char *fileNameB, Cpa32U list) { #ifdef USER_SPACE FILE *fp = NULL; FILE *otherFile = NULL; Cpa32U j = 0; if (NULL != buffListArray) { if (remove(fileName) == 0) { PRINT("Deleted successfully %s\n", fileName); } else { PRINT("Unable to delete the file: %s\n", fileName); } if (remove(fileNameB) == 0) { PRINT("Deleted successfully %s\n", fileNameB); } else { PRINT("Unable to delete the file: %s\n", fileNameB); } fp = fopen(fileName, "ab+"); if (NULL == fp) { PRINT("Error in opening file: %s\n", fileName); return; } otherFile = fopen(fileNameB, "w"); if (NULL == otherFile) { PRINT("Error in opening file: %s\n", fileNameB); fclose(fp); return; } if (list > 0) { fprintf(otherFile, "writing %u bytes of compressed data to file\n", buffListArray[list - 1].pBuffers[0].dataLenInBytes); if (fwrite(buffListArray[list - 1].pBuffers[0].pData, 1, buffListArray[list - 1].pBuffers[0].dataLenInBytes, fp) < buffListArray[list - 1].pBuffers[0].dataLenInBytes) { PRINT("Error in file recording\n"); fclose(otherFile); fclose(fp); return; } } else { for (j = 0; j < setup->numLists; j++) { fprintf(otherFile, "writing %u bytes of compressed data to file\n", buffListArray[j].pBuffers[0].dataLenInBytes); if (fwrite(buffListArray[j].pBuffers[0].pData, 1, buffListArray[j].pBuffers[0].dataLenInBytes, fp) < buffListArray[j].pBuffers[0].dataLenInBytes) { PRINT("Error in file recording\n"); fclose(fp); fclose(otherFile); return; } } } fflush(fp); fflush(otherFile); fclose(fp); fclose(otherFile); } #else struct file *fp = NULL; struct file *otherFile = NULL; Cpa32U j = 0; char *filepath = NULL; char *buffer = NULL; Cpa32S strSize = 0; char *firmwarePath = SAMPLE_CODE_CORPUS_PATH; filepath = qaeMemAlloc(QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH); if (NULL == filepath) { PRINT_ERR("Failed to allocate memory for filepath"); return; } buffer = qaeMemAlloc(QAT_COMP_DUMP_BUFFER_SIZE); QAT_PERF_CHECK_NULL_POINTER_AND_GOTO_LABEL(buffer, exit); memset(filepath, 0, QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH); strSize = snprintf(filepath, QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH, "%s%s", firmwarePath, fileName); QAT_PERF_CHECK_PARAM_RANGE_AND_GOTO_LABEL( strSize, 1, QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH, exit); fp = filp_open(filepath, O_CREAT | O_RDWR | O_APPEND, 0); QAT_PERF_CHECK_NULL_POINTER_AND_GOTO_LABEL(fp, exit); memset(filepath, 0, QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH); strSize = snprintf(filepath, QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH, "%s%s", firmwarePath, fileNameB); QAT_PERF_CHECK_PARAM_RANGE_AND_GOTO_LABEL( strSize, 1, QAT_COMP_DUMP_MAX_FILE_NAME_LEGNTH, exit); otherFile = filp_open(filepath, O_CREAT | O_WRONLY | O_TRUNC, 0); QAT_PERF_CHECK_NULL_POINTER_AND_GOTO_LABEL(otherFile, exit); if (NULL != buffListArray) { if (list > 0) { memset(buffer, '\0', QAT_COMP_DUMP_BUFFER_SIZE); snprintf(buffer, QAT_COMP_DUMP_BUFFER_SIZE, "writing %u bytes of compressed data to file\n", buffListArray[list - 1].pBuffers[0].dataLenInBytes); sampleCodeKernelWrite(otherFile, buffer, strnlen(buffer, QAT_COMP_DUMP_BUFFER_SIZE), &otherFile->f_pos); sampleCodeKernelWrite( fp, buffListArray[list - 1].pBuffers[0].pData, buffListArray[list - 1].pBuffers[0].dataLenInBytes, &fp->f_pos); } else { for (j = 0; j < setup->numLists; j++) { memset(buffer, '\0', QAT_COMP_DUMP_BUFFER_SIZE); snprintf(buffer, QAT_COMP_DUMP_BUFFER_SIZE, "writing %u bytes of compressed data to file\n", buffListArray[j].pBuffers[0].dataLenInBytes); sampleCodeKernelWrite( otherFile, buffer, strnlen(buffer, QAT_COMP_DUMP_BUFFER_SIZE), &otherFile->f_pos); sampleCodeKernelWrite( fp, buffListArray[j].pBuffers[0].pData, buffListArray[j].pBuffers[0].dataLenInBytes, &fp->f_pos); } } } else { PRINT("CpaFlatBuffer not allocated\n"); } exit: if (fp != NULL) { filp_close(fp, NULL); } if (otherFile != NULL) { filp_close(otherFile, NULL); } qaeMemFree((void **)&filepath); if (buffer != NULL) { qaeMemFree((void **)&buffer); } #endif return; } static CpaStatus qatSwZlibDecompress(compression_test_params_t *setup, CpaBufferList *destBuffListArray, CpaBufferList *cmpBuffListArray, CpaDcRqResults *cmpResults) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U j = 0; struct z_stream_s stream = {0}; for (j = 0; j < setup->numLists; j++) { /* For stateful session setup stream once for all the buffers * For stateless session stream is initialized for every packet */ if (setup->setupData.sessState != CPA_DC_STATEFUL || j == 0) { inflate_init(&stream, setup->setupData.sessState); } status = inflate_decompress(&stream, destBuffListArray[j].pBuffers->pData, cmpResults[j].produced, cmpBuffListArray[j].pBuffers->pData, cmpBuffListArray[j].pBuffers->dataLenInBytes, setup->setupData.sessState); if (CPA_STATUS_SUCCESS != status) { PRINT("%02x%02x%02x%02x\n", destBuffListArray[j].pBuffers->pData[0], destBuffListArray[j].pBuffers->pData[1], destBuffListArray[j].pBuffers->pData[2], destBuffListArray[j].pBuffers->pData[3]); PRINT_ERR("j: %d, srcLen: %d, destLen: %d \n", j, destBuffListArray[j].pBuffers->dataLenInBytes, cmpBuffListArray[j].pBuffers->dataLenInBytes); qatCompressDumpToFile( setup, destBuffListArray, "destBuffer", "destBuffSize", 0); break; } cmpBuffListArray[j].pBuffers[0].dataLenInBytes = stream.avail_out; /*the results passed in contain the uncompressed consumed data * and the compressed produced data, so now we swap them, so that * consumed contains the compressed data consumed by zlib and the * decompressed data produced by zlib*/ cmpResults[j].consumed = cmpResults[j].produced; cmpResults[j].produced = cmpBuffListArray[j].pBuffers->dataLenInBytes; /* Destroy the stream every time for stateless but only in the end * for stateful. */ if (setup->setupData.sessState != CPA_DC_STATEFUL || j == (setup->numLists - 1)) { inflate_destroy(&stream); } } return status; } CpaStatus qatSwDecompress(compression_test_params_t *setup, CpaBufferList *destBuffListArray, CpaBufferList *cmpBuffListArray, CpaDcRqResults *cmpResults) { CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(destBuffListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(cmpBuffListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(cmpResults, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); if (CPA_STATUS_SUCCESS == status) { if (setup->setupData.compType == CPA_DC_DEFLATE) { status = qatSwZlibDecompress( setup, destBuffListArray, cmpBuffListArray, cmpResults); } else { PRINT_ERR("Unsupported Compression type %d\n", setup->setupData.compType); status = CPA_STATUS_FAIL; } } return status; } #ifdef SC_CHAINING_ENABLED CpaStatus qatSwChainDecompress(compression_test_params_t *setup, CpaBufferList *destBuffListArray, CpaBufferList *cmpBufferListArray, CpaDcChainRqResults *cmpResults) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U j = 0; struct z_stream_s stream = {0}; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(destBuffListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(cmpBufferListArray, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(cmpResults, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); if (CPA_STATUS_SUCCESS == status) { for (j = 0; j < setup->numLists; j++) { /* For stateful session setup stream once for all the buffers * For stateless session stream is initialized for every packet */ if (setup->setupData.sessState != CPA_DC_STATEFUL || j == 0) { inflate_init(&stream, setup->setupData.sessState); } status = inflate_decompress( &stream, destBuffListArray[j].pBuffers->pData, cmpResults[j].produced, cmpBufferListArray[j].pBuffers->pData, cmpBufferListArray[j].pBuffers->dataLenInBytes, setup->setupData.sessState); if (CPA_STATUS_SUCCESS != status) { PRINT("%02x%02x%02x%02x\n", destBuffListArray[j].pBuffers->pData[0], destBuffListArray[j].pBuffers->pData[1], destBuffListArray[j].pBuffers->pData[2], destBuffListArray[j].pBuffers->pData[3]); PRINT_ERR("j: %d, srcLen: %d, destLen: %d \n", j, destBuffListArray[j].pBuffers->dataLenInBytes, cmpBufferListArray[j].pBuffers->dataLenInBytes); qatCompressDumpToFile(setup, destBuffListArray, "destBuffer", "destBuffSize", 0); break; } cmpBufferListArray[j].pBuffers[0].dataLenInBytes = stream.avail_out; /*the results passed in contain the uncompressed consumed data * and the compressed produced data, so now we swap them, so * that consumed contains the compressed data consumed by zlib * and the decompressed data produced by zlib*/ cmpResults[j].consumed = cmpResults[j].produced; cmpResults[j].produced = cmpBufferListArray[j].pBuffers->dataLenInBytes; /* Destroy the stream every time for stateless but only in the * end for stateful. */ if (setup->setupData.sessState != CPA_DC_STATEFUL || j == (setup->numLists - 1)) { inflate_destroy(&stream); } } } return status; } #endif void qatDcPollAndSetNextPollCounter(compression_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; /*poll to try and free space on q's*/ if (setup->setupData.sessState == CPA_DC_STATEFUL || CPA_TRUE == setup->useStatefulLite) { /*if stateful of stateful-lite wait for response of last request*/ while (setup->performanceStats->responses != setup->performanceStats->submissions) { /* Keep polling until compression of the buffer * completes * and dcPerformCallback2k() increments * perfData->responses */ coo_poll_trad_dc( setup->performanceStats, setup->dcInstanceHandle, &status); if (CPA_STATUS_RETRY == status) { setup->performanceStats->pollRetries++; AVOID_SOFTLOCKUP; } } setup->performanceStats->nextPoll = setup->performanceStats->submissions + 1; } else { coo_poll_trad_dc( setup->performanceStats, setup->dcInstanceHandle, &status); if (CPA_STATUS_RETRY == status) { setup->performanceStats->pollRetries++; AVOID_SOFTLOCKUP; } setup->performanceStats->nextPoll = setup->performanceStats->submissions + dcPollingInterval_g; } } void qatDcRetryHandler(compression_test_params_t *setup, const CpaInstanceInfo2 *pInstanceInfo2) { setup->performanceStats->retries++; // poll if DP API is being used, or if poll inline flag is set if ((poll_inline_g || setup->isDpApi) && (pInstanceInfo2 != NULL) && pInstanceInfo2->isPolled) { qatDcPollAndSetNextPollCounter(setup); } return; } #ifdef SC_CHAINING_ENABLED void qatDcChainResponseStatusCheck(compression_test_params_t *setup, CpaDcChainRqResults *arrayOfResults, Cpa32U listNum, CpaStatus *status) { Cpa32U i = 0; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, *status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfResults, *status); if (CPA_STATUS_SUCCESS == *status) { if (CPA_STATUS_FAIL == setup->performanceStats->threadReturnStatus) { PRINT_ERR("threadReturnStatus is set to CPA_STATUS_FAIL\n"); /*find the request that cause the fail*/ for (i = 0; i < listNum; i++) { if (CPA_DC_OK != arrayOfResults[i].dcStatus) { setup->performanceStats->additionalStatus = arrayOfResults[i].dcStatus; PRINT("Additional status in dcresults for list %d is %d\n", i, arrayOfResults[i].dcStatus); } } *status = CPA_STATUS_FAIL; } } } #endif void qatCompressionResponseStatusCheck(compression_test_params_t *setup, CpaDcRqResults *arrayOfResults, Cpa32U listNum, CpaStatus *status) { Cpa32U i = 0; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, *status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfResults, *status); setup->performanceStats->additionalStatus = CPA_STATUS_SUCCESS; if (CPA_STATUS_FAIL == setup->performanceStats->threadReturnStatus) { PRINT_ERR("threadReturnStatus is set to CPA_STATUS_FAIL\n"); /*find the request that cause the fail*/ do { if (CPA_DC_OK != arrayOfResults[i].status) { setup->performanceStats->additionalStatus = arrayOfResults[i].status; PRINT("Additional status in dcresults for list %d is %d\n", i, arrayOfResults[i].status); } } while (++i < listNum); *status = CPA_STATUS_FAIL; } } CpaStatus populateCorpusAndStartDcService(Cpa32U testBufferSize, corpus_type_t corpusType) { CpaStatus status = CPA_STATUS_SUCCESS; /* Populate Corpus: copy from file on disk into memory*/ /* this method limits to compressing 1 corpus at any point in time */ status = populateCorpus(testBufferSize, corpusType); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to load one or more corpus files, have they been " "extracted to %s?\n", SAMPLE_CODE_CORPUS_PATH); return CPA_STATUS_FAIL; } /*Start DC Services */ status = startDcServices(DYNAMIC_BUFFER_AREA, TEMP_NUM_BUFFS); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error in Starting Dc Services\n"); return CPA_STATUS_FAIL; } return status; } CpaStatus qatCompressionSetFlushFlag(compression_test_params_t *setup, Cpa32U listNum) { CpaStatus status = CPA_STATUS_SUCCESS; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); if (CPA_STATUS_SUCCESS == status) { #if DC_API_VERSION_AT_LEAST(3, 1) /* LZ4 FW requires users to set the BFINAL for every request, * * when Rolling XXHASH is disabled. * * LZ4S FW requires users to set the BFINAL for every request */ if (((setup->setupData.compType == CPA_DC_LZ4 && setup->setupData.accumulateXXHash == CPA_FALSE) || setup->setupData.compType == CPA_DC_LZ4S) && setup->setupData.sessState == CPA_DC_STATELESS) { setup->flushFlag = CPA_DC_FLUSH_FINAL; setup->requestOps.flushFlag = CPA_DC_FLUSH_FINAL; return status; } #endif /* flush flag for last request is always final for all types of * compression*/ if (listNum == (setup->numLists - 1)) { setup->flushFlag = CPA_DC_FLUSH_FINAL; setup->requestOps.flushFlag = CPA_DC_FLUSH_FINAL; } else { /*set to flush_sync for stateful otherwise flush_final*/ if ((CPA_DC_STATEFUL == setup->setupData.sessState)) { setup->flushFlag = CPA_DC_FLUSH_SYNC; setup->requestOps.flushFlag = CPA_DC_FLUSH_SYNC; } else { setup->flushFlag = CPA_DC_FLUSH_FULL; setup->requestOps.flushFlag = CPA_DC_FLUSH_FULL; } } } return status; } CpaStatus performSleeptimeCalculation(compression_test_params_t *setup, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcRqResults *resultArray, CpaDcCallbackFn dcCbFn, CpaDcSessionDir dcSessDir, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U baseThroughput = 0, currentThroughput = 0; Cpa32U packetSize = 0, lowerBound = 0, upperBound = 0; perf_data_t *pPerfData = setup->performanceStats; setup->sleepTime = 1; packetSize = setup->bufferSize; baseThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); currentThroughput = baseThroughput; /* Find the lower bound (within margin 5%) upper (outside of throughput margin) */ while (CPA_STATUS_SUCCESS == status && findSleeptimeMargin( baseThroughput, currentThroughput, QAT_COMP_FIVE_PERCENT)) { lowerBound = setup->sleepTime; setup->sleepTime = setup->sleepTime << 1; status = qatCompressData(setup, pSessionHandle, dcSessDir, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, resultArray); dcScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, dcSessDir); currentThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); } upperBound = setup->sleepTime; /* Binary Search for no retries and maintaining throughput */ while (CPA_STATUS_SUCCESS == status && lowerBound <= upperBound) { setup->sleepTime = (upperBound + lowerBound) / 2; status = qatCompressData(setup, pSessionHandle, dcSessDir, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, resultArray); dcScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, dcSessDir); currentThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); if (currentThroughput >= baseThroughput) { lowerBound = setup->sleepTime + 1; } else { /* If within ERROR_MARGIN (1.5%) of base throughput */ if ((findSleeptimeMargin(baseThroughput, currentThroughput, QAT_COMP_ONE_POINT_FIVE_PERCENT) == 1)) { break; } else { upperBound = setup->sleepTime - 1; } } } return status; } #ifdef USER_SPACE #ifdef SC_CHAINING_ENABLED CpaStatus performDcChainOffloadCalculationBusyLoop( compression_test_params_t *setup, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcChainRqResults *resultArray, CpaDcChainOpData *chainOpData, CpaDcCallbackFn dcCbFn, CpaDcSessionDir dcSessDir, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U baseThroughput = 0, currentThroughput = 0, staticAssign = 0; Cpa32U packetSize = 0, lowerBound = 0, upperBound = 0, j = 0; perf_cycles_t startBusyLoopTime = 0, endBusyLoopTime = 0; perf_data_t *pPerfData = setup->performanceStats; pPerfData->busyLoopValue = 1; packetSize = setup->packetSizeInBytesArray[0]; baseThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* Find the lower bound(retries) and upper bound(no retries) for subsequent * binary search. */ while (CPA_STATUS_SUCCESS == status && pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue; pPerfData->busyLoopValue = pPerfData->busyLoopValue << 1; status = qatDcChainCompressData(setup, pSessionHandle, dcSessDir, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, resultArray, chainOpData); dcChainScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, dcSessDir); } upperBound = pPerfData->busyLoopValue; while (CPA_STATUS_SUCCESS == status && lowerBound <= upperBound) { pPerfData->busyLoopValue = (upperBound + lowerBound) / 2; qatDcChainCompressData(setup, pSessionHandle, dcSessDir, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, resultArray, chainOpData); dcChainScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, dcSessDir); currentThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* If no retries and we're within ERROR_MARGIN (0.1%) of base throughput */ if (pPerfData->retries == 0 && (withinMargin(baseThroughput, currentThroughput, ERROR_MARGIN) == 1)) { break; } /* If we see retries */ else if (pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue + 1; } /* Else retries are zero, but throughput has been affected. */ else { upperBound = pPerfData->busyLoopValue - 1; } } busyLoopTimeStamp(); startBusyLoopTime = busyLoopTimeStamp(); for (j = 0; j < setup->performanceStats->busyLoopCount; j++) { busyLoop(setup->performanceStats->busyLoopValue, &staticAssign); } endBusyLoopTime = busyLoopTimeStamp(); setup->performanceStats->totalBusyLoopCycles = endBusyLoopTime - startBusyLoopTime; setup->performanceStats->offloadCycles = (setup->performanceStats->endCyclesTimestamp - setup->performanceStats->startCyclesTimestamp) - setup->performanceStats->totalBusyLoopCycles; do_div(setup->performanceStats->offloadCycles, setup->performanceStats->responses); return status; } #endif #endif CpaStatus performOffloadCalculationBusyLoop( compression_test_params_t *setup, CpaBufferList *arrayOfSrcBufferLists, CpaBufferList *arrayOfDestBufferLists, CpaBufferList *arrayOfCmpBufferLists, CpaDcRqResults *resultArray, CpaDcCallbackFn dcCbFn, CpaDcSessionDir dcSessDir, CpaDcSessionHandle pSessionHandle) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U baseThroughput = 0, currentThroughput = 0, staticAssign = 0; Cpa32U packetSize = 0, lowerBound = 0, upperBound = 0, j = 0; perf_cycles_t startBusyLoopTime = 0, endBusyLoopTime = 0; perf_data_t *pPerfData = setup->performanceStats; pPerfData->busyLoopValue = 1; packetSize = setup->packetSizeInBytesArray[0]; baseThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* Find the lower bound(retries) and upper bound(no retries) for subsequent * binary search. */ while (CPA_STATUS_SUCCESS == status && pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue; pPerfData->busyLoopValue = pPerfData->busyLoopValue << 1; status = qatCompressData(setup, pSessionHandle, dcSessDir, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, resultArray); dcScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, dcSessDir); } upperBound = pPerfData->busyLoopValue; while (CPA_STATUS_SUCCESS == status && lowerBound <= upperBound) { pPerfData->busyLoopValue = (upperBound + lowerBound) / 2; status = qatCompressData(setup, pSessionHandle, dcSessDir, arrayOfSrcBufferLists, arrayOfDestBufferLists, arrayOfCmpBufferLists, resultArray); dcScSetBytesProducedAndConsumed( resultArray, setup->performanceStats, setup, dcSessDir); currentThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* If no retries and we're within ERROR_MARGIN (0.1%) of base throughput */ if (pPerfData->retries == 0 && (withinMargin(baseThroughput, currentThroughput, ERROR_MARGIN) == 1)) { break; } /* If we see retries */ else if (pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue + 1; } /* Else retries are zero, but throughput has been affected. */ else { upperBound = pPerfData->busyLoopValue - 1; } } busyLoopTimeStamp(); startBusyLoopTime = busyLoopTimeStamp(); for (j = 0; j < setup->performanceStats->busyLoopCount; j++) { busyLoop(setup->performanceStats->busyLoopValue, &staticAssign); } endBusyLoopTime = busyLoopTimeStamp(); setup->performanceStats->totalBusyLoopCycles = endBusyLoopTime - startBusyLoopTime; setup->performanceStats->offloadCycles = (setup->performanceStats->endCyclesTimestamp - setup->performanceStats->startCyclesTimestamp) - setup->performanceStats->totalBusyLoopCycles; do_div(setup->performanceStats->offloadCycles, setup->performanceStats->responses); return status; } CpaStatus qatDcGetPreTestRecoveryCount(compression_test_params_t *dcSetup, CpaDcInstanceCapabilities *capabilities, perf_data_t *performanceStats) { CpaStatus status = CPA_STATUS_SUCCESS; CpaDcStats dcStats = {0}; if (CNV_RECOVERY(&(dcSetup->requestOps)) == CPA_TRUE) { if (CNV_RECOVERY(capabilities) == CPA_FALSE) { PRINT_ERR("CnVnR requested but not supported on instance\n"); return CPA_STATUS_FAIL; } status = cpaDcGetStats(dcSetup->dcInstanceHandle, &dcStats); if (status == CPA_STATUS_SUCCESS) { performanceStats->preTestRecoveryCount = GET_CNV_RECOVERY_COUNTERS(&dcStats); } else { performanceStats->preTestRecoveryCount = 0; } } return status; } void qatDcGetPostTestRecoveryCount(compression_test_params_t *dcSetup, perf_data_t *performanceStats) { CpaStatus status = CPA_STATUS_SUCCESS; CpaDcStats dcStats = {0}; if (CNV_RECOVERY(&(dcSetup->requestOps)) == CPA_TRUE) { status = cpaDcGetStats(dcSetup->dcInstanceHandle, &dcStats); if (status == CPA_STATUS_SUCCESS) { performanceStats->postTestRecoveryCount = GET_CNV_RECOVERY_COUNTERS(&dcStats); } else { performanceStats->postTestRecoveryCount = 0; } } } CpaStatus qatCompressionVerifyOverflow(compression_test_params_t *setup, CpaDcRqResults *arrayOfResults, CpaBufferList *arrayOfSrcBufferLists, Cpa32U listNum) { Cpa32U i = 0; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U totalSrcLength = 0; Cpa32U numBuffs = 0; QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(setup, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfResults, status); QAT_PERF_CHECK_NULL_POINTER_AND_UPDATE_STATUS(arrayOfSrcBufferLists, status); /*Loop through all result structures and verify consumed data size */ do { totalSrcLength = 0; for (numBuffs = 0; numBuffs < arrayOfSrcBufferLists[i].numBuffers; numBuffs++) { totalSrcLength += arrayOfSrcBufferLists[i].pBuffers[numBuffs].dataLenInBytes; } if ((arrayOfResults[i].status == CPA_DC_OVERFLOW) || (arrayOfResults[i].consumed < totalSrcLength)) { PRINT_ERR( "%s: Consumed %d out of %d bytes in the Source buffer for " "List Number %d\n", __func__, arrayOfResults[i].consumed, totalSrcLength, i); status = CPA_STATUS_FAIL; break; } } while (++i < listNum); return status; } qat_compression_zlib.h000066400000000000000000000205371503624047500363550ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/compression/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef QAT_COMPRESSION_ZLIB_H_ #define QAT_COMPRESSION_ZLIB_H_ #ifdef USER_SPACE #include "zlib.h" #else #include #endif /** ***************************************************************************** * @file qat_compression_zlib.h * * @defgroup sample_code * * @ingroup sample_code * * @description Initialize a zlib stream * * @param[in] stream zlib stream context * * @param[in] sessState initialize a stateful or stateless zlib stream * * @pre stream structure is already allocated * * @post stream is ready to be used for decompression * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL The stream could not be initialized ****************************************************************************/ CpaStatus inflate_init(z_stream *stream, CpaDcSessionState sessState); /** ***************************************************************************** * @file qat_compression_zlib.h * * @ingroup sample_code * * @description decompress data with a zlib stream * * @param[in] stream zlib stream context * @param[in] src pointer to the data to be decompressed * @param[in] slen len of data in bytes to be decompressed * @param[out] dst pointer to the decompressed output * @param[in] dlen amount of memory available for decompressed * output * @param[in] sessState initialise a stateful or stateless zlib stream * * @pre stream structure is already initialized * * @post dst contains compressed data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL The data could not be compressed ****************************************************************************/ CpaStatus inflate_decompress(z_stream *stream, const Cpa8U *src, Cpa32U slen, Cpa8U *dst, Cpa32U dlen, CpaDcSessionState sessState); /** ***************************************************************************** * @file qat_compression_zlib.h * * @ingroup sample_code * * @description destroy a zlib stream * * @param[in] stream zlib stream context * * @pre stream structure is already allocated * * @post stream can no longer be used * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL The stream could not be uninitialized ****************************************************************************/ void inflate_destroy(struct z_stream_s *stream); /** ***************************************************************************** * @file qat_compression_zlib.h * * @defgroup sample_code * * @ingroup sample_code * * @description Initialize a zlib stream * * @param[in] stream zlib stream context * * @param[in] sessState initialize a stateful or stateless zlib stream * * @pre stream structure is already allocated * * @post stream is ready to be used for compress * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL The stream could not be initialized ****************************************************************************/ CpaStatus deflate_init(z_stream *stream); /** ***************************************************************************** * @file qat_compression_zlib.h * * @ingroup sample_code * * @description compress data with a zlib stream * * @param[in] stream zlib stream context * @param[in] src pointer to the data to be compressed * @param[in] slen len of data in bytes to be compressed * @param[out] dst pointer to the compressed output * @param[in] dlen amount of memory available for compressed * output * @param[in] zfflag zlib flush flag. Please consult with zlib.h * for the allowed values * * @pre stream structure is already initialized * * @post dst contains compressed data * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL The data could not be compressed ****************************************************************************/ CpaStatus deflate_compress(z_stream *stream, const Cpa8U *src, Cpa32U slen, Cpa8U *dst, Cpa32U dlen, int zfflag); /** ***************************************************************************** * @file qat_compression_zlib.h * * @ingroup sample_code * * @description destroy a zlib stream * * @param[in] stream zlib stream context * * @pre stream structure is already allocated * * @post stream can no longer be used * * @retval CPA_STATUS_SUCCESS Function executed successfully * * @retval CPA_STATUS_FAIL The stream could not be uninitialized ****************************************************************************/ void deflate_destroy(struct z_stream_s *stream); #endif /* QAT_COMPRESSION_ZLIB_H_ */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/cpa_sample_code_main.c000066400000000000000000003375061503624047500337510ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * **************************************************************************/ /** *************************************************************************** * @file cpa_sample_code_main.c * * This file provides the main function, which calls out what to measure the * performance of * **************************************************************************/ // Local define to allow CRYPTO to be included or excluded from compilation // Redundant here (except for test purposes)as set by performance sample code // Makefile. //#define DO_CRYPTO #include "cpa_sample_code_framework.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_cy_im.h" #ifdef INCLUDE_COMPRESSION #include "cpa_dc.h" #include "cpa_sample_code_dc_perf.h" #include "cpa_sample_code_dc_utils.h" #include "cpa_sample_code_dc_dp.h" #include "qat_compression_main.h" #endif #include "cpa_sample_code_sym_perf_dp.h" #ifndef INCLUDE_COMPRESSION /*define this just so that sample code will build without compression code*/ #define MIN_DC_LOOPS (1) #ifdef __x86_64__ #define DEFAULT_DC_LOOPS (100) #else #define DEFAULT_DC_LOOPS (200) #endif #define SINGLE_REQUEST (1) #else corpus_type_t sampleCorpus; #endif #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED #ifdef SC_SM2_ENABLED #define ASYMETRIC_CODE \ (RSA_CODE | DSA_CODE | ECDSA_CODE | DH_CODE | KPT_RSA_CODE | \ KPT_ECDSA_CODE | SM2_CODE) #else /*#SC_SM2_ENABLED*/ #define ASYMETRIC_CODE \ (RSA_CODE | DSA_CODE | ECDSA_CODE | DH_CODE | KPT_RSA_CODE | KPT_ECDSA_CODE) #endif /*#SC_SM2_ENABLED*/ #else /*#SC_KPT2_ENABLED*/ #ifdef SC_SM2_ENABLED #define ASYMETRIC_CODE (RSA_CODE | DSA_CODE | ECDSA_CODE | DH_CODE | SM2_CODE) #else #define ASYMETRIC_CODE (RSA_CODE | DSA_CODE | ECDSA_CODE | DH_CODE) #endif #endif /*#SC_KPT2_ENABLED*/ #else /*#if CY_API_VERSION_AT_LEAST(3, 0)*/ #define ASYMETRIC_CODE (RSA_CODE | DSA_CODE | ECDSA_CODE | DH_CODE) #endif /*#if CY_API_VERSION_AT_LEAST(3, 0)*/ #if CY_API_VERSION_AT_LEAST(3, 0) /*add for SM3 and SM4*/ extern smx_key_size_pairs_t cipherSM4TestList[]; extern smx_key_size_pairs_t algChainSM4SM3TestList[]; extern int cipherSM4TestList_count; extern int algChainSM4SM3TestList_count; #endif #ifdef USER_SPACE extern CpaStatus qaeMemInit(void); extern void qaeMemDestroy(void); extern Cpa32U getCPUSpeed(void); extern Cpa32U updateCPUSpeed(void); int runTests; int signOfLife; int cyNumBuffers; int cyAsymLoops; int cySymLoops; int dcLoops; int includeWirelessAlgs; int configFileVersion; int runStateful; int includeLZ4; static int singleInstThread = 0; option_t optArray[MAX_NUMOPT] = { { "signOfLife", DEFAULT_SIGN_OF_LIFE }, { "runTests", RUN_ALL_TESTS }, { "cyNumBuffers", DEFAULT_CY_BUFFERS }, { "cyAsymLoops", DEFAULT_ASYM_LOOPS }, { "cySymLoops", DEFAULT_SYM_LOOPS }, { "dcLoops", DEFAULT_DC_LOOPS }, { "includeWirelessAlgs", DEFAULT_INCLUDE_WIRELESS_ALGS }, { "configFileVer", USE_V2_CONFIG_FILE }, { "runStateful", 0 }, { "useStaticPrime", 1 }, { "getLatency", 0 }, { "getOffloadCost", 0 }, { "includeLZ4", DEFAULT_INCLUDE_LZ4 }, { "compOnly", 0 }, { "singleInstThread", 0 }, { "verboseOutput", 1 } }; #define SIGN_OF_LIFE_OPT_ARRAY_POS (0) #define RUN_TEST_OPT_ARRAY_POS (1) #define NUM_BUFFERS_OPT_ARRAY_POS (2) #define ASYM_LOOPS_OPT_ARRAY_POS (3) #define SYM_LOOPS_OPT_ARRAY_POS (4) #define DC_LOOPS_OPT_ARRAY_POS (5) #define WIRELESS_ALGS_OPT_ARRAY_POS (6) #define CONFIG_FILE_OPT_ARRAY_POS (7) #define RUN_STATEFUL_ARRAY_POS (8) #define USE_STATIC_PRIME (9) #define GET_LATENCY_POS (10) #define GET_OFFLOAD_COST_POS (11) #define RUN_LZ4_TEST_POS (12) #define SINGLE_INST_THREAD_ARRAY_POS (14) #else /* #ifdef USER_SPACE */ extern int cyNumBuffers; extern int cySymLoops; extern int cyAsymLoops; extern int dcLoops; extern int runTests; extern int includeWirelessAlgs; extern int signOfLife; extern int runStateful; extern int verboseOutput; #endif /* #ifdef USER_SPACE */ /*this function contains the top level tests, it is called main to support * user space executable, otherwise it is called in kernel space by the kernel * space init upon loading of the kernel module * * A test is made of of the following: * * 1. User calls their setup Test function, to set the feature specific * parameters that will be used when threads are created * * 2. user calls createPerfomanceThreads to create the test as setup in step2 * across IA cores and acceleration units * * 3. User repeats steps 1-2 to setup more tests, ie to test co-existence of * crypto and datacompression, we call step 1-2 to setup crypto threads, then * step 1-2 again to setup data compression threads. * * 4. User calls startThreads so that the OS can start all the created threads * * 5. User waits for all threads to complete, when complete the statsPrintOut * function is called for each type of thread (the user is expect to provide * a statsPrintFunc in implementation of there setup Function used in step 1) * * 6. Repeat 1-5 for each test * */ CpaInstanceHandle *cyInst_g = NULL; CpaInstanceHandle *symCyInst_g = NULL; CpaInstanceHandle *asymCyInst_g = NULL; CpaInstanceHandle *dcInst_g = NULL; Cpa32U *cyInstMap_g = NULL; Cpa32U *symCyInstMap_g = NULL; Cpa32U *asymCyInstMap_g = NULL; Cpa32U *dcInstMap_g = NULL; Cpa32U instMap_g; Cpa16U numInst_g = 0; Cpa8U singleInstRequired_g = 0; extern Cpa32U packageIdCount_g; extern CpaBoolean devicesCounted_g; #ifdef USER_SPACE #define MAX_SAMPLE_LOOPS 5 #define ONE_KILO 1000 /* check the core frequency stability */ static CpaStatus isCoreFreqStable(void) { Cpa32U curr_freq = 0; Cpa32U prev_freq = 0; Cpa32U i = 0; getCPUSpeed(); curr_freq = sampleCodeGetCpuFreq() / ONE_KILO; prev_freq = curr_freq; for (i = 0; i < MAX_SAMPLE_LOOPS; i++) { updateCPUSpeed(); curr_freq = sampleCodeGetCpuFreq() / ONE_KILO; if (curr_freq != prev_freq) { return CPA_STATUS_FAIL; } prev_freq = curr_freq; } return CPA_STATUS_SUCCESS; } /* check if only one QAT instance is enabled*/ CpaStatus checkSingleInstance() { Cpa16U numInstances = 0; CpaStatus status = CPA_STATUS_FAIL; #ifdef DO_CRYPTO status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances > 1) { return CPA_STATUS_FAIL; } numInstances = 0; #endif /* DO_CRYPTO */ #ifdef INCLUDE_COMPRESSION status = cpaDcGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances > 1) { return CPA_STATUS_FAIL; } #endif /* INCLUDE_COMPRESSION */ return CPA_STATUS_SUCCESS; } #endif /* USER_SPACE */ /*************************************************************************** * what code to run **************************************************************************/ #define SYMMETRIC_CODE (1) #define RSA_CODE (2) #define DSA_CODE (4) #define ECDSA_CODE (8) #define DH_CODE (16) #define COMPRESSION_CODE (32) #define CHAINING_CODE (128) #if CY_API_VERSION_AT_LEAST(3, 0) #define SMx_CODE (2048) #ifdef SC_KPT2_ENABLED #define KPT_RSA_CODE (256) #define KPT_ECDSA_CODE (512) #endif #ifdef SC_SM2_ENABLED #define SM2_CODE (1024) #endif #endif #define FIRST_INSTANCE (1) /*************************************************************************** * number of simultaneous threads to run for stateful compression **************************************************************************/ #define NUMBER_SIMILTANEOUS_THREADS (16) #define NUMBER_OF_CORES_TO_USE (8) #define KASUMI_40_BYTE_BUFFER (40) /*add for SM2*/ #ifdef SC_SM2_ENABLED #define SM2_TEST_ALL_STEPS (6) #endif int main(int argc, char *argv[]) { /*These are the packet sizes to measure performance off PACKET_IMIX is an * average of a mix of packet sizes - see PACKET_IMIX definition for this * mix*/ Cpa32U lv_count = 0; Cpa16U i = 0; Cpa16S prevDevId = -1; Cpa16U testsExecuted = 0; #ifdef INCLUDE_COMPRESSION Cpa16U numDcInst = 0; Cpa32U statefulMultiThreadCoreMap[NUMBER_SIMILTANEOUS_THREADS]; Cpa32U dcBufferSize = 0; CpaBoolean dynamicEnabled = CPA_FALSE; CpaBoolean staticEnabled = CPA_TRUE; CpaDcInstanceCapabilities dcCap = {0}; #endif CpaStatus status = CPA_STATUS_FAIL; CpaStatus retStatus = CPA_STATUS_SUCCESS; #ifdef USER_SPACE #ifdef SC_CHAINING_ENABLED Cpa32U prevCnVRequestFlag = 0; #endif #endif CpaInstanceInfo2 *info = NULL; #ifdef DO_CRYPTO CpaStatus status_asym = CPA_STATUS_FAIL; CpaCySymCapabilitiesInfo symCapInfo = {{0}}; Cpa32U computeLatency = 0; CpaCyCapabilitiesInfo symCap = {0}; CpaCyCapabilitiesInfo asymCap = {0}; Cpa16U includeKasumiAlg = 0; Cpa16U includeSnow3GAlgChain = 0; Cpa16U includeAesCbcAlg = 1; Cpa16U includeAesXtsAlg = 1; Cpa16U includeAesCtrAlg = 1; Cpa16U includeAesGcmAlgChain = 1; Cpa16U includeChachaPolyAlgChain = 1; #else #ifdef USER_SPACE Cpa32U computeLatency = 0; #endif #endif #ifdef USER_SPACE char *processName = NULL; Cpa32U computeOffloadCost = 0; #endif status = allocThreadMem(); if(status == CPA_STATUS_FAIL) { PRINT_ERR("Failed to allocate memory for threads\n"); return CPA_STATUS_FAIL; } #ifdef USER_SPACE if (0 != parseArg(argc, argv, optArray, MAX_NUMOPT)) { freeThreadMem(); return 0; } signOfLife = optArray[SIGN_OF_LIFE_OPT_ARRAY_POS].optValue; runTests = optArray[RUN_TEST_OPT_ARRAY_POS].optValue; cyNumBuffers = optArray[NUM_BUFFERS_OPT_ARRAY_POS].optValue; cyAsymLoops = optArray[ASYM_LOOPS_OPT_ARRAY_POS].optValue; cySymLoops = optArray[SYM_LOOPS_OPT_ARRAY_POS].optValue; dcLoops = optArray[DC_LOOPS_OPT_ARRAY_POS].optValue; includeWirelessAlgs = optArray[WIRELESS_ALGS_OPT_ARRAY_POS].optValue; configFileVersion = optArray[CONFIG_FILE_OPT_ARRAY_POS].optValue; runStateful = optArray[RUN_STATEFUL_ARRAY_POS].optValue; computeLatency = optArray[GET_LATENCY_POS].optValue; computeOffloadCost = optArray[GET_OFFLOAD_COST_POS].optValue; includeLZ4 = optArray[RUN_LZ4_TEST_POS].optValue; singleInstThread = optArray[SINGLE_INST_THREAD_ARRAY_POS].optValue; /* Use single instance */ singleInstRequired_g = singleInstThread; if (computeLatency != 0 && computeOffloadCost != 0) { PRINT_ERR( "ERROR: Latency and Offload cost cannot be computed together\n"); return CPA_STATUS_FAIL; } if (computeLatency != 0) { /*the asym operations are generally long and it takes a while to wait * for a completion in the latency mode. Therefore we decrease it to * a smaller value*/ cyAsymLoops = 100; } if (computeLatency != 0 || computeOffloadCost != 0) { const char *const op = computeLatency != 0 ? "Latency" : "Offload Cost"; /* use single instance for latency and COO */ singleInstRequired_g = 1; /* Sign of Life has too little iteration to do * computation of latency or offload cost. Flag * a warning and continue with the test. */ if (signOfLife != 0) { PRINT("WARNING! %s computation is unavailable with signOfLife.\n", op); } #ifdef SC_PARAM_CHECK_ENABLED PRINT("WARNING! Param Check is enabled, this may effect %s computation" "\n", op); #endif #ifdef SC_STATS_ENABLED PRINT("WARNING! Stats enabled, this may effect %s computation\n", op); #endif if (CPA_STATUS_SUCCESS != isCoreFreqStable()) { PRINT("WARNING! Core frequency is not stable, this may effect %s" "computation\n", op); } } enableLatencyMeasurements(computeLatency != 0 ? 1 : 0); if (computeOffloadCost != 0) { enableCycleCount(); } else { disableCycleCount(); } useStaticPrime = optArray[USE_STATIC_PRIME].optValue; if (CPA_STATUS_SUCCESS != qaeMemInit()) { PRINT_ERR("Could not start usdm_drv for user space\n"); PRINT("Has the usdm_drv module been loaded?\n"); return CPA_STATUS_FAIL; } else { PRINT("qaeMemInit started\n"); } processName = "SSL"; if (USE_V1_CONFIG_FILE == configFileVersion) { if (CPA_STATUS_SUCCESS != icp_sal_userStart(processName)) { PRINT_ERR("Could not start sal for user space\n"); return CPA_STATUS_FAIL; } else { PRINT("icp_sal_userStart(\"%s\") started\n", processName); } } else if (USE_V2_CONFIG_FILE == configFileVersion) { if (CPA_STATUS_SUCCESS != icp_sal_userStartMultiProcess(processName, CPA_FALSE)) { PRINT_ERR("Could not start sal for user space\n"); return CPA_STATUS_FAIL; } else { PRINT("icp_sal_userStartMultiProcess(\"%s\") started\n", processName); } } else { PRINT_ERR("Invalid configFileVer specified(%d) " "valid values are 1 or 2\n", configFileVersion); return CPA_STATUS_FAIL; } #endif // USER_SPACE if (signOfLife) { cyNumBuffers = MIN_CY_BUFFERS; cySymLoops = MIN_SYM_LOOPS; cyAsymLoops = MIN_ASYM_LOOPS; dcLoops = MIN_DC_LOOPS; } #ifdef DO_CRYPTO status = cpaCyGetNumInstances(&numInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetNumInstances failed with status: %d\n", status); return status; } if (numInst_g > 0) { /* use single instance for latency and COO */ if (singleInstRequired_g) { numInst_g = 1; } /*allocate memory to store the instance handles*/ cyInst_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInst_g); if (cyInst_g == NULL) { PRINT_ERR("Failed to allocate memory for instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } /*get the instances handles and place in allocated memory*/ status = cpaCyGetInstances(numInst_g, cyInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetInstances failed with status: %d\n", status); freeInstanceMapping(); return status; } /*allocate memory for the instance core mapping*/ cyInstMap_g = qaeMemAlloc(sizeof(Cpa32U) * numInst_g); if (cyInstMap_g == NULL) { PRINT_ERR("Failed to allocate memory for instance mapping\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } info = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (info == NULL) { PRINT_ERR("Failed to allocate memory for info"); freeInstanceMapping(); return CPA_STATUS_FAIL; } memset(info, 0, sizeof(CpaInstanceInfo2)); for (i = 0; i < numInst_g; i++) { status = cpaCyInstanceGetInfo2(cyInst_g[i], info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); freeInstanceMapping(); qaeMemFree((void **)&info); return status; } if (prevDevId == info->physInstId.acceleratorId) { continue; } prevDevId = info->physInstId.acceleratorId; printDriverVersion(prevDevId); } qaeMemFree((void **)&info); if (runTests & SYMMETRIC_CODE) { status = getCryptoInstanceCapabilities(&symCap, SYM); } if (runTests & ASYMETRIC_CODE) { status_asym = getCryptoInstanceCapabilities(&asymCap, ASYM); } if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_SUCCESS != status_asym)) { PRINT_ERR("getCryptoInstanceCapabilities failed to fetch CRYPTO " "Instance Capabilities.\n"); return CPA_STATUS_FAIL; } if (symCap.symSupported == CPA_FALSE && runTests & SYMMETRIC_CODE) { PRINT("Warning! Skipping SYMMETRIC tests as they are not supported " "on Instance\n"); runTests ^= 1 << 0; PRINT("runTests=%d\n", runTests); } if (asymCap.rsaSupported == CPA_FALSE && runTests & RSA_CODE) { PRINT("Warning! Skipping RSA tests as they are not supported on " "Instance\n"); runTests ^= 1 << 1; PRINT("runTests=%d\n", runTests); } if (asymCap.dsaSupported == CPA_FALSE && runTests & DSA_CODE) { PRINT("Warning! Skipping DSA tests as they are not supported on " "Instance\n"); runTests ^= 1 << 2; PRINT("runTests=%d\n", runTests); } if (asymCap.ecdsaSupported == CPA_FALSE && runTests & ECDSA_CODE) { PRINT("Warning! Skipping ECDSA tests as they are not supported on " "Instance\n"); runTests ^= 1 << 3; PRINT("runTests=%d\n", runTests); } if (asymCap.dhSupported == CPA_FALSE && runTests & DH_CODE) { PRINT("Warning! Skipping DH tests as they are not supported on " "Instance\n"); runTests ^= 1 << 4; PRINT("runTests=%d\n", runTests); } #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (asymCap.kptSupported == CPA_FALSE && (runTests & KPT_RSA_CODE)) { PRINT( "Warning! Skipping KPT RSA tests as they are not supported on " "Instance\n"); runTests ^= 1 << 8; PRINT("runTests=%d\n", runTests); } if (asymCap.kptSupported == CPA_FALSE && (runTests & KPT_ECDSA_CODE)) { PRINT("Warning! Skipping KPT ECDSA tests as they are not supported " "on Instance\n"); runTests ^= 1 << 9; PRINT("runTests=%d\n", runTests); } #endif #ifdef SC_SM2_ENABLED if (asymCap.ecSm2Supported == CPA_FALSE && (runTests & SM2_CODE)) { PRINT("Warning! Skipping SM2 tests as they are not supported " "on Instance\n"); runTests ^= 1 << 10; PRINT("runTests=%d\n", runTests); } #endif #endif if (symCap.symSupported == CPA_TRUE && (runTests & SYMMETRIC_CODE)) { status = getCySymQueryCapabilities(&symCapInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymQueryCapabilities failed with status: %d\n", status); return status; } /* Check capabilities before running kasumi wireless alg tests */ if (1 == includeWirelessAlgs) { includeKasumiAlg = 1; includeSnow3GAlgChain = 1; if (!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_KASUMI_F8)) { PRINT( "Warning! Skipping Kasumi wireless algorithm tests as " "they are not supported on " "Instance\n"); includeKasumiAlg = 0; } if ((!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_SNOW3G_UEA2)) || (!CPA_BITMAP_BIT_TEST(symCapInfo.hashes, CPA_CY_SYM_HASH_SNOW3G_UIA2))) { PRINT("Warning! Skipping Snow3G wireless algorithm chain " "tests as they are not supported on " "Instance\n"); includeSnow3GAlgChain = 0; } } /* Check capabilities before running AES-CBC alg tests */ if (!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_AES_CBC)) { PRINT("Warning! Skipping AES-CBC algorithm tests as " "they are not supported on " "Instance\n"); includeAesCbcAlg = 0; } /* Check capabilities before running AES-XTS alg tests */ if (!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_AES_XTS)) { PRINT("Warning! Skipping AES-XTS algorithm tests as " "they are not supported on " "Instance\n"); includeAesXtsAlg = 0; } /* Check capabilities before running AES-CTR alg tests */ if (!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_AES_CTR)) { PRINT("Warning! Skipping AES-CTR algorithm tests as " "they are not supported on " "Instance\n"); includeAesCtrAlg = 0; } /* Check capabilities before running AES-GCM alg chaining tests */ if ((!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_AES_GCM)) || (!CPA_BITMAP_BIT_TEST(symCapInfo.hashes, CPA_CY_SYM_HASH_AES_GCM))) { PRINT("Warning! Skipping AES-GCM algorithm chain " "tests as they are not supported on " "Instance\n"); includeAesGcmAlgChain = 0; } /* Check capabilities before running CHACHA POLY alg chaining tests */ if ((!CPA_BITMAP_BIT_TEST(symCapInfo.ciphers, CPA_CY_SYM_CIPHER_CHACHA)) || (!CPA_BITMAP_BIT_TEST(symCapInfo.hashes, CPA_CY_SYM_HASH_POLY))) { PRINT("Warning! Skipping CHACHA POLY algorithm chain " "tests as they are not supported on " "Instance\n"); includeChachaPolyAlgChain = 0; } } } else { PRINT("There are no crypto instances\n"); /* Check if compression service need to be tested * and update the runTests accordingly. * */ if (COMPRESSION_CODE & runTests) { runTests = COMPRESSION_CODE; } } #endif /* DO_CRYPTO */ #ifdef INCLUDE_COMPRESSION status = cpaDcGetNumInstances(&numInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetNumInstances failed with status: %d\n", status); return status; } if (numInst_g > 0) { /* use single instance for latency and COO */ if (singleInstRequired_g) { numInst_g = 1; } /*allocate memory to store the instance handles*/ dcInst_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInst_g); if (dcInst_g == NULL) { PRINT_ERR("Failed to allocate memory for instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } /*get the instances handles and place in allocated memory*/ status = cpaDcGetInstances(numInst_g, dcInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetInstances failed with status: %d\n", status); freeInstanceMapping(); return status; } /*allocate memory for the instance core mapping*/ dcInstMap_g = qaeMemAlloc(sizeof(Cpa32U) * numInst_g); if (dcInstMap_g == NULL) { PRINT_ERR("Failed to allocate memory for instance mapping\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } info = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (info == NULL) { PRINT_ERR("Failed to allocate memory for info"); freeInstanceMapping(); return CPA_STATUS_FAIL; } memset(info, 0, sizeof(CpaInstanceInfo2)); for (i = 0; i < numInst_g; i++) { status = cpaDcInstanceGetInfo2(dcInst_g[i], info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); qaeMemFree((void **)&info); return status; } if (prevDevId == info->physInstId.acceleratorId) { continue; } prevDevId = info->physInstId.acceleratorId; printDriverVersion(prevDevId); } qaeMemFree((void **)&info); status = cpaDcQueryCapabilities(dcInst_g[0], &dcCap); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcQueryCapabilities failed with status: %d\n", status); return status; } } else { PRINT("There are no compression instances\n"); } #endif /* INCLUDE_COMPRESSION */ freeInstanceMapping(); #ifdef USER_SPACE if (((computeLatency != 0) || (computeOffloadCost != 0)) && (checkSingleInstance() != CPA_STATUS_SUCCESS)) { PRINT("Limiting to use single QAT Instance for %s computation\n", computeLatency != 0 ? "Latency" : "Offload Cost"); } #endif /* USER_SPACE */ #ifdef DO_CRYPTO /*************************************************************************** * SYMMETRIC PERFORMANCE **************************************************************************/ if ((SYMMETRIC_CODE & runTests) == SYMMETRIC_CODE) { if (includeAesCbcAlg) { /*AES128-CBC TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherTest(CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_128_IN_BYTES, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES256-CBC TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherTest(CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_256_IN_BYTES, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES256-CBC HMAC-SHA512 test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainTest( CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_SHA512, CPA_CY_SYM_HASH_MODE_AUTH, SHA512_AUTH_KEY_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*AES256-CBC AES-XCBC-MAC test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainTest( CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_AES_XCBC, CPA_CY_SYM_HASH_MODE_AUTH, AES_XCBC_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*AES256-CBC HMAC-SHA512 test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainDpTest( CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_SHA512, CPA_CY_SYM_HASH_MODE_AUTH, SHA512_AUTH_KEY_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*AES256-CBC AES-XCBC-MAC test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainDpTest( CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_AES_XCBC, CPA_CY_SYM_HASH_MODE_AUTH, AES_XCBC_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*AES128-CBC TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherDpTest(CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_128_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES256-CBC TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherDpTest(CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_256_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } if (includeAesXtsAlg) { /*AES128-XTS TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherTest(CPA_CY_SYM_CIPHER_AES_XTS, KEY_SIZE_256_IN_BYTES, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES256-XTS TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherTest(CPA_CY_SYM_CIPHER_AES_XTS, KEY_SIZE_512_IN_BYTES, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES128-XTS TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherDpTest(CPA_CY_SYM_CIPHER_AES_XTS, KEY_SIZE_256_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES256-XTS TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherDpTest(CPA_CY_SYM_CIPHER_AES_XTS, KEY_SIZE_512_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } if (includeAesCtrAlg) { /*AES128-CTR TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherTest(CPA_CY_SYM_CIPHER_AES_CTR, KEY_SIZE_128_IN_BYTES, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES256-CTR TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherTest(CPA_CY_SYM_CIPHER_AES_CTR, KEY_SIZE_256_IN_BYTES, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES128-CTR TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherDpTest(CPA_CY_SYM_CIPHER_AES_CTR, KEY_SIZE_128_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*AES256-CTR TEST*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherDpTest(CPA_CY_SYM_CIPHER_AES_CTR, KEY_SIZE_256_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } if (includeAesGcmAlgChain) { /*AES128-GCM AES-GCM test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainTest( CPA_CY_SYM_CIPHER_AES_GCM, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_AES_GCM, CPA_CY_SYM_HASH_MODE_AUTH, AES_GCM_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*AES256-GCM AES-GCM test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainTest( CPA_CY_SYM_CIPHER_AES_GCM, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_AES_GCM, CPA_CY_SYM_HASH_MODE_AUTH, AES_GCM_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*AES128-GCM AES-GCM test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainDpTest( CPA_CY_SYM_CIPHER_AES_GCM, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_AES_GCM, CPA_CY_SYM_HASH_MODE_AUTH, AES_GCM_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*AES256-GCM AES-GCM test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainDpTest( CPA_CY_SYM_CIPHER_AES_GCM, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_AES_GCM, CPA_CY_SYM_HASH_MODE_AUTH, AES_GCM_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ } if (includeChachaPolyAlgChain) { /*CHACHA POLY test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainTest( CPA_CY_SYM_CIPHER_CHACHA, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_POLY, CPA_CY_SYM_HASH_MODE_AUTH, POLY_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*CHACHA POLY test*/ for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainDpTest( CPA_CY_SYM_CIPHER_CHACHA, KEY_SIZE_256_IN_BYTES, CPA_CY_SYM_HASH_POLY, CPA_CY_SYM_HASH_MODE_AUTH, POLY_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ } if (includeKasumiAlg) { /*KASUMI TEST*/ for (lv_count = 0; lv_count < numWirelessPacketSizes; lv_count++) { status = setupCipherTest(CPA_CY_SYM_CIPHER_KASUMI_F8, KEY_SIZE_128_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, wirelessPacketSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*KASUMI TEST*/ for (lv_count = 0; lv_count < numWirelessPacketSizes; lv_count++) { status = setupCipherDpTest(CPA_CY_SYM_CIPHER_KASUMI_F8, KEY_SIZE_128_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, wirelessPacketSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } if (includeSnow3GAlgChain) { /*SNOW3G-UEA2 HMAC-SNOW3G-UIA2 TEST*/ for (lv_count = 0; lv_count < numWirelessPacketSizes; lv_count++) { status = setupAlgChainTest( CPA_CY_SYM_CIPHER_SNOW3G_UEA2, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_SNOW3G_UIA2, CPA_CY_SYM_HASH_MODE_AUTH, SNOW3G_UIA2_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, wirelessPacketSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ /*SNOW3G-UEA2 HMAC-SNOW3G-UIA2 TEST*/ for (lv_count = 0; lv_count < numWirelessPacketSizes; lv_count++) { status = setupAlgChainDpTest( CPA_CY_SYM_CIPHER_SNOW3G_UEA2, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_SNOW3G_UIA2, CPA_CY_SYM_HASH_MODE_AUTH, SNOW3G_UIA2_DIGEST_LENGTH_IN_BYTES, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, wirelessPacketSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*End of test*/ } } #endif /* DO_CRYPTO */ #ifdef DO_CRYPTO /************************************************************************** * RSA PERFORMANCE **************************************************************************/ if ((RSA_CODE & runTests) == RSA_CODE) { if (signOfLife) { numModSizes = ONE_PACKET; } for (lv_count = 0; lv_count < numModSizes; lv_count++) { status = setupRsaTest(modSizes[lv_count], CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2, ASYNC, cyNumBuffers, cyAsymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupRsaTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(ASYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef USER_SPACE #ifdef SC_KPT2_ENABLED /************************************************************************** * KPT RSA PERFORMANCE **************************************************************************/ if ((KPT_RSA_CODE & runTests) == KPT_RSA_CODE) { if (signOfLife) { numModSizes = ONE_PACKET; } for (lv_count = 0; lv_count < numModSizes; lv_count++) { status = setupKpt2RsaTest(modSizes[lv_count], CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2, ASYNC, cyNumBuffers, cyAsymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupKpt2RsaTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(ASYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } /*************************************************************************** * KPT ECDSA PERFORMANCE **************************************************************************/ if (((KPT_ECDSA_CODE & runTests) == KPT_ECDSA_CODE) && (computeLatency == 0)) { status = setupKpt2EcdsaTest(GFP_P384_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_PRIME, ASYNC, ECDSA_STEP_VERIFY, cyNumBuffers, cyAsymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupKpt2EcdsaTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(ASYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } #endif #endif /*USER_SPACE*/ #endif #endif /*DO_CRYPTO*/ #ifdef DO_CRYPTO /************************************************************************** * DH PERFORMANCE **************************************************************************/ if (((DH_CODE & runTests) == DH_CODE) && (computeLatency == 0)) { if (signOfLife) { numModSizes = ONE_PACKET; } for (lv_count = 0; lv_count < numModSizes; lv_count++) { status = setupDhTest(modSizes[lv_count], EXPONENT_180_BIT, ASYNC, DH_PHASE_2, cyNumBuffers, cyAsymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDhTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(ASYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } #endif /*DO_CRYPTO*/ #ifdef DO_CRYPTO /*************************************************************************** * DSA CRYPTO TESTS **************************************************************************/ if (((DSA_CODE & runTests) == DSA_CODE) && (computeLatency == 0)) { status = setupDsaTest(MODULUS_2048_BIT, EXPONENT_256_BIT, ASYNC, cyNumBuffers, cyAsymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDsaTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(ASYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } #endif /*DO_CRYPTO*/ #ifdef DO_CRYPTO /*************************************************************************** * ECDSA CRYPTO TESTS **************************************************************************/ if (((ECDSA_CODE & runTests) == ECDSA_CODE) && (computeLatency == 0)) { status = setupEcdsaTest(GFP_P384_SIZE_IN_BITS /*GFP_P192_SIZE_IN_BITS*/, CPA_CY_EC_FIELD_TYPE_PRIME, ASYNC, ECDSA_STEP_VERIFY, cyNumBuffers, cyAsymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupEcdsaTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(ASYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } #endif /*DO_CRYPTO*/ #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_SM2_ENABLED #ifdef DO_CRYPTO /*************************************************************************** * SM2 TESTS **************************************************************************/ if ((SM2_CODE & runTests) == SM2_CODE) { Cpa32U sm2_step = 0; for (sm2_step = 0; sm2_step < SM2_TEST_ALL_STEPS; sm2_step++) { status = setupSm2Test(GFP_SM2_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_PRIME, ASYNC, sm2_step, cyNumBuffers, cyAsymLoops); if (CPA_STATUS_SUCCESS != status) { switch (sm2_step) { case SM2_STEP_SIGN: PRINT_ERR("Error setting up SM2_STEP_SIGN Test"); break; case SM2_STEP_VERIFY: PRINT_ERR("Error setting up SM2_STEP_VERIFY Test"); break; case SM2_STEP_ENC: PRINT_ERR("Error setting up SM2_STEP_ENC Test"); break; case SM2_STEP_DEC: PRINT_ERR("Error setting up SM2_STEP_DEC Test"); break; case SM2_STEP_KEYEX_P1: PRINT_ERR("Error setting up SM2_STEP_KEYEX_P1 Test"); break; case SM2_STEP_KEYEX_P2: PRINT_ERR("Error setting up SM2_STEP_KEYEX_P2 Test"); break; } return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(ASYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } #endif /*DO_CRYPTO*/ #endif /*SC_SM2_ENABLED*/ #endif #ifdef INCLUDE_COMPRESSION if (signOfLife) { sampleCorpus = SIGN_OF_LIFE_CORPUS; dcBufferSize = BUFFER_SIZE_32768; } else { sampleCorpus = CALGARY_CORPUS; dcBufferSize = BUFFER_SIZE_65536; } /*************************************************************************** * START OF COMPRESSION TESTS CALGARY CORPUS **************************************************************************/ if (((COMPRESSION_CODE & runTests) == COMPRESSION_CODE) || ((CHAINING_CODE & runTests) == CHAINING_CODE)) { status = cpaDcGetNumInstances(&numDcInst); /* Check the status */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to Get Number of DC instances\n"); return CPA_STATUS_FAIL; } } /************************************************************************** * COMPRESSION TESTS CALGARY CORPUS **************************************************************************/ if ((COMPRESSION_CODE & runTests) == COMPRESSION_CODE) { if (numDcInst > 0) { disableAdditionalCmpbufferSize_g = 1; dynamicHuffmanEnabled(NULL, &dynamicEnabled); #if defined(SC_BSD_UPSTREAM) || !defined(_KERNEL) /*STATIC L1 & L3 COMPRESSION*/ if (staticEnabled) { status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_STATIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_STATIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_STATIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_STATIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /*DYNAMIC L1 & L3 COMPRESSION*/ if (dynamicEnabled) { status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_FULL_DYNAMIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_FULL_DYNAMIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_FULL_DYNAMIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_FULL_DYNAMIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } if (staticEnabled) { /*DECOMPRESSION OF ZLIB COMPRESSED DATA*/ useZlib(); status = setupDcTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L1, /*not used in this test*/ CPA_DC_HT_STATIC, /*not used in this test*/ CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, dcBufferSize, sampleCorpus, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } useAccelCompression(); } if (runStateful && dynamicEnabled) { /*STATEFUL COMPRESSION TEST*/ status = setupDcStatefulTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_FULL_DYNAMIC, BUFFER_SIZE_8192, sampleCorpus, SYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Stateful setup failed\n"); } else { testsExecuted++; } /*set the array of cores to create threads on*/ for (lv_count = 0; lv_count < sizeof(statefulMultiThreadCoreMap) / sizeof(Cpa32U); lv_count++) { statefulMultiThreadCoreMap[lv_count] = lv_count % NUMBER_OF_CORES_TO_USE; } /*create the threads using all available instances*/ status = createPerfomanceThreads( sizeof(statefulMultiThreadCoreMap) / sizeof(Cpa32U), statefulMultiThreadCoreMap, numInst_g, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads\n"); return status; } status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error starting threads\n"); return status; } status = waitForThreadCompletion(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Stateful Compression thread(s) failed\n"); return status; } } #endif /* _KERNEL */ /* Data Plane API Sample Code Test */ /*STATIC DP_API L1 & L3 COMPRESS & DECOMPRESS*/ if (staticEnabled) { status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_STATIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_STATIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_STATIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_STATIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } if (dynamicEnabled) { /*DYNAMIC DP_API L1 & L3 COMPRESS & DECOMPRESS*/ status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_FULL_DYNAMIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_FULL_DYNAMIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_FULL_DYNAMIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } status = setupDcDpTest(CPA_DC_DEFLATE, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L2, CPA_DC_HT_FULL_DYNAMIC, DEFAULT_COMPRESSION_WINDOW_SIZE, BUFFER_SIZE_8192, sampleCorpus, ASYNC, DC_DP_ENQUEUEING, SINGLE_REQUEST, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } #ifdef USER_SPACE #if DC_API_VERSION_AT_LEAST(3, 1) if (includeLZ4 == 1) { /*LZ4 Tests Compression & Decompression */ /*XXhash global flag need to be set for LZ4 tests*/ setChecksum(CPA_DC_XXHASH32); setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_STATELESS, BUFFER_SIZE_8192, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_STATELESS, BUFFER_SIZE_65536, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L9, CPA_DC_STATELESS, BUFFER_SIZE_8192, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L9, CPA_DC_STATELESS, BUFFER_SIZE_65536, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_STATELESS, BUFFER_SIZE_8192, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_STATELESS, BUFFER_SIZE_65536, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L9, CPA_DC_STATELESS, BUFFER_SIZE_8192, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setupDcLZ4Test(CPA_DC_LZ4, CPA_DC_DIR_DECOMPRESS, SAMPLE_CODE_CPA_DC_L9, CPA_DC_STATELESS, BUFFER_SIZE_65536, sampleCorpus, CPA_DC_MIN_4_BYTE_MATCH, CPA_DC_LZ4_MAX_BLOCK_SIZE_64K, ASYNC, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcLZ4Test\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } #else if (includeLZ4 == 1) { PRINT("LZ4 not supported with this API version\n"); } #endif #endif } // End of if(numDcInst>0) } // End of if((COMPRESSION_CODE & runTests)== COMPRESSION_CODE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef DO_CRYPTO /*************************************************************************** * SM3 and SM4 TESTS **************************************************************************/ if ((SMx_CODE & runTests) == SMx_CODE) { Cpa32U sm_count = 0; for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupHashTest(CPA_CY_SYM_HASH_SM3, CPA_CY_SYM_HASH_MODE_PLAIN, SM3_DIGEST_LENGTH_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupHashTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupHashDpTest(CPA_CY_SYM_HASH_SM3, CPA_CY_SYM_HASH_MODE_PLAIN, SM3_DIGEST_LENGTH_IN_BYTES, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupHashDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } for (sm_count = 0; sm_count < algChainSM4SM3TestList_count; sm_count++) { for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainTest( algChainSM4SM3TestList[sm_count].cipherAlg, algChainSM4SM3TestList[sm_count].cipherKeySizeInBytes, algChainSM4SM3TestList[sm_count].hashAlg, CPA_CY_SYM_HASH_MODE_AUTH, algChainSM4SM3TestList[sm_count].hashKeySizeInBytes, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } for (sm_count = 0; sm_count < cipherSM4TestList_count; sm_count++) { for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherTest( cipherSM4TestList[sm_count].cipherAlg, cipherSM4TestList[sm_count].cipherKeySizeInBytes, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } for (sm_count = 0; sm_count < algChainSM4SM3TestList_count; sm_count++) { for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupAlgChainDpTest( algChainSM4SM3TestList[sm_count].cipherAlg, algChainSM4SM3TestList[sm_count].cipherKeySizeInBytes, algChainSM4SM3TestList[sm_count].hashAlg, CPA_CY_SYM_HASH_MODE_AUTH, algChainSM4SM3TestList[sm_count].hashKeySizeInBytes, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupAlgChainDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } for (sm_count = 0; sm_count < cipherSM4TestList_count; sm_count++) { for (lv_count = 0; lv_count < numPacketSizes; lv_count++) { status = setupCipherDpTest( cipherSM4TestList[sm_count].cipherAlg, cipherSM4TestList[sm_count].cipherKeySizeInBytes, CPA_CY_PRIORITY_HIGH, ASYNC, packetSizes[lv_count], SYM_DP_ENQUEUEING, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, SINGLE_REQUEST, SYM_DP_SINGLE_SESSION, cyNumBuffers, cySymLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupCipherDpTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletionCrypto(SYM); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } } } #endif /*DO_CRYPTO*/ #endif #ifdef USER_SPACE #ifdef SC_CHAINING_ENABLED /* * Chaining Sample Code */ if ((CHAINING_CODE & runTests) == CHAINING_CODE) { if (numDcInst > 0) { useZlib(); prevCnVRequestFlag = getSetupCnVRequestFlag(); setSetupCnVRequestFlag(STRICT_CNV_CONDITIONAL_RECOVERY | LOOSE_CNV_CONDITIONAL_RECOVERY); if (staticEnabled) { /* sha256 + stateless static compress chaining */ status = setupDcChainTest(CPA_DC_CHAIN_HASH_THEN_COMPRESS, 2, CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_STATIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, dcBufferSize, sampleCorpus, ASYNC, CPA_CY_SYM_OP_HASH, CPA_CY_SYM_CIPHER_NULL, 0, CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT, CPA_CY_PRIORITY_NORMAL, CPA_CY_SYM_HASH_SHA256, CPA_CY_SYM_HASH_MODE_PLAIN, SHA256_DIGEST_LENGTH_IN_BYTES, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } } /* sha256 + stateless dynamic compress chaining */ status = setupDcChainTest(CPA_DC_CHAIN_HASH_THEN_COMPRESS, 2, CPA_DC_DEFLATE, CPA_DC_DIR_COMPRESS, SAMPLE_CODE_CPA_DC_L1, CPA_DC_HT_FULL_DYNAMIC, CPA_DC_STATELESS, DEFAULT_COMPRESSION_WINDOW_SIZE, dcBufferSize, sampleCorpus, ASYNC, CPA_CY_SYM_OP_HASH, CPA_CY_SYM_CIPHER_NULL, 0, CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT, CPA_CY_PRIORITY_NORMAL, CPA_CY_SYM_HASH_SHA256, CPA_CY_SYM_HASH_MODE_PLAIN, SHA256_DIGEST_LENGTH_IN_BYTES, dcLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error calling setupDcChainTest\n"); return CPA_STATUS_FAIL; } else { testsExecuted++; } status = createStartandWaitForCompletion(COMPRESSION); if (CPA_STATUS_SUCCESS != status) { retStatus = CPA_STATUS_FAIL; } setSetupCnVRequestFlag(prevCnVRequestFlag); useAccelCompression(); } } #endif #endif #endif #ifdef USER_SPACE if (CPA_STATUS_SUCCESS != icp_sal_userStop()) { PRINT_ERR("Could not stop sal for user space\n"); return CPA_STATUS_FAIL; } qaeMemDestroy(); #endif /* USER_SPACE */ freeThreadMem(); if ((retStatus == CPA_STATUS_SUCCESS) && (testsExecuted > 0)) { PRINT("Sample code completed successfully.\n"); return CPA_STATUS_SUCCESS; } if (testsExecuted == 0) { PRINT("No tests were executed.\n"); } return retStatus; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/000077500000000000000000000000001503624047500310055ustar00rootroot00000000000000cpa_sample_code_cipher_perf2.c000066400000000000000000000737331503624047500366350ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_cipher_perf.c * * @defgroup sampleCiperPerf Cipher Performance code * * @ingroup sampleCipherPerf * * @description * This file contains the main cipher performance sample code. It is * capable of performing all ciphers * * This code pre-allocates a number of buffers as defined by * setup->numBuffers. The pre-allocated buffers are then * continuously looped until the numLoops is met. * Time stamping is started prior to the * Operation and is stopped when all callbacks have returned. * The packet size and algorithm to be tested is setup using the * setupCipherTest function. The framework is used to create the threads * which calls functions here to execute cipher performance * *****************************************************************************/ #include "cpa_sample_code_crypto_utils.h" extern int signOfLife; /** ***************************************************************************** * @ingroup sampleCipherPerf * * @description * Callback function for result of perform operation * *****************************************************************************/ static void cipherPerformCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { /*we declare the callback as per the API requirements, but we only use * the pCallbackTag parameter*/ processCallback(pCallbackTag); } /** ***************************************************************************** * @ingroup sampleCipherPerf * * @description * Create a cipher session */ static CpaStatus cipherSetupSession(CpaCySymCbFunc pSymCb, Cpa8U *pCipherKey, CpaCySymSessionCtx *pSession, symmetric_test_params_t *setup) { Cpa32U sessionCtxSizeInBytes = 0; CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymSessionCtx pLocalSession = NULL; Cpa32U cipherKeyLen = 0; Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /*set the cipher key len*/ cipherKeyLen = setup->setupData.cipherSetupData.cipherKeyLenInBytes; /*generate a random cipher n key*/ generateRandomData(pCipherKey, cipherKeyLen); setup->setupData.cipherSetupData.pCipherKey = pCipherKey; /*get size for mem allocation*/ status = cpaCySymSessionCtxGetSize( setup->cyInstanceHandle, &setup->setupData, &sessionCtxSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetSize error, status: %d", status); return status; } /* allocate session memory */ pLocalSession = qaeMemAllocNUMA(sessionCtxSizeInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pLocalSession) { PRINT_ERR("Could not allocate pLocalSession memory\n"); return CPA_STATUS_FAIL; } /*zero session memory*/ memset(pLocalSession, 0, sessionCtxSizeInBytes); /* * init session with asynchronous callback- pLocalSession will contain * the session context */ status = cpaCySymInitSession( setup->cyInstanceHandle, pSymCb, &setup->setupData, pLocalSession); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymInitSession error, status: %d\n", status); qaeMemFreeNUMA((void **)&pLocalSession); return status; } *pSession = pLocalSession; return status; } /***************************************************************************** * @ingroup sampleCipherPerf * * @description * Setup cipher operation data * ****************************************************************************/ static CpaStatus cipherPerformOpDataSetup(CpaCySymSessionCtx pSessionCtx, Cpa32U *pPacketSize, CpaCySymOpData *pOpdata, symmetric_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U createCount = 0; Cpa32U node = 0; /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /*for each bufferList set the symmetric operation data*/ pOpdata->sessionCtx = pSessionCtx; pOpdata->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; /*these only need to be set for cipher and alg chaining */ pOpdata->cryptoStartSrcOffsetInBytes = 0; pOpdata->messageLenToCipherInBytes = 0; for (createCount = 0; createCount < setup->numBuffers; createCount++) { pOpdata->messageLenToCipherInBytes += pPacketSize[createCount]; } /*these only need to be set for hash and alg chaining*/ /*set IV len depending on what we are testing*/ if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CBC || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CTR || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_SNOW3G_UEA2 #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_ZUC_EEA3 #endif ) { pOpdata->ivLenInBytes = IV_LEN_FOR_16_BYTE_BLOCK_CIPHER; } else { /* in this code we always allocate the IV, but it is not always used * this reduces the if/else logic when trying to cater for as many * cipher options as possible*/ pOpdata->ivLenInBytes = IV_LEN_FOR_8_BYTE_BLOCK_CIPHER; } /*allocate NUMA aware aligned memory for IV*/ pOpdata->pIv = qaeMemAllocNUMA(pOpdata->ivLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pOpdata->pIv) { PRINT_ERR("IV is null\n"); return CPA_STATUS_FAIL; } memset(pOpdata->pIv, 0, pOpdata->ivLenInBytes); /*generate a random IV*/ generateRandomData(pOpdata->pIv, pOpdata->ivLenInBytes); return CPA_STATUS_SUCCESS; } /***************************************************************************** * @ingroup sampleCipherPerf * * @description * measures the performance of cipher encryption operations * ****************************************************************************/ static CpaStatus cipherPerform(symmetric_test_params_t *setup, perf_data_t *pSymData, Cpa32U numOfLoops, CpaCySymOpData *ppOpData, CpaBufferList *ppSrcBuffListArray, CpaCySymCipherDirection cipherDirection) { CpaBoolean verifyResult = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U loopCount = 0; Cpa32U submissions = 0; Cpa32U i = 0; perf_cycles_t request_submit_start[100] = {0}; perf_cycles_t request_respnse_time[100] = {0}; memset(pSymData, 0, sizeof(perf_data_t)); if (((setup->numBuffers * setup->numLoops) / ONE_THOUSAND_RESPONSES) > 100) { PRINT_ERR("Error max submissions for latency must be <= 1 million\n"); return CPA_STATUS_FAIL; } pSymData->response_times = request_respnse_time; /*preset the number of ops we plan to submit*/ pSymData->numOperations = numOfLoops; pSymData->retries = 0; /* Init the semaphore used in the callback */ sampleCodeSemaphoreInit(&pSymData->comp, 0); /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Get the time, collect this only for the first * request, the callback collects it for the last */ pSymData->startCyclesTimestamp = sampleCodeTimestamp(); /* loop around the preallocated buffer list*/ for (loopCount = 0; loopCount < numOfLoops; loopCount++) { /* This inner for-loop loops around the number of Buffer Lists * that have been preallocated. Once the array has completed- * exit to the outer loop to move on the next iteration of the * preallocated loop. */ do { if ((loopCount + 1) % ONE_THOUSAND_RESPONSES == 0) { request_submit_start[submissions] = sampleCodeTimestamp(); } status = cpaCySymPerformOp(setup->cyInstanceHandle, pSymData, ppOpData, ppSrcBuffListArray, ppSrcBuffListArray, /*in-place operation*/ &verifyResult); if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if ((loopCount + 1) % ONE_THOUSAND_RESPONSES == 0) { submissions++; } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp Error %d\n", status); break; } } /* end of loop */ if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSymData, setup->syncMode, setup->numBuffers, numOfLoops); } pSymData->minLatency = pSymData->response_times[0] - request_submit_start[0]; pSymData->maxLatency = pSymData->minLatency; pSymData->aveLatency = pSymData->minLatency; for (i = 1; i < submissions; i++) { if ((pSymData->response_times[i] - request_submit_start[i]) < pSymData->minLatency) { pSymData->minLatency = pSymData->response_times[i] - request_submit_start[i]; } if ((pSymData->response_times[i] - request_submit_start[i]) > pSymData->maxLatency) { pSymData->maxLatency = pSymData->response_times[i] - request_submit_start[i]; } pSymData->aveLatency += pSymData->response_times[i] - request_submit_start[i]; } if (submissions > 0) { do_div(pSymData->aveLatency, submissions); } /*clean up the callback semaphore*/ sampleCodeSemaphoreDestroy(&pSymData->comp); return status; } /***************************************************************************** * @ingroup sampleCipherPerf * * @description * Free memory allocated in the sampleCipherPerform function * ****************************************************************************/ static void cipherPerformMemFree(symmetric_test_params_t *setup, CpaBufferList *pSrcBuffListArray, CpaCySymOpData *pOpData, CpaCySymSessionCtx *pSessionCtx) { Cpa32U freeMemCount = 0; CpaBufferList *buffList = pSrcBuffListArray; /*free bufferLists: pBuffers, metaData & source data*/ if (NULL == buffList) { PRINT_ERR("bufferList Ptr is NULL\n"); } else { /* Loop through and free all buffers that have been * pre-allocated.*/ for (freeMemCount = 0; freeMemCount < setup->numBuffers; freeMemCount++) { if (NULL != buffList->pBuffers[freeMemCount].pData) { qaeMemFreeNUMA( (void **)&buffList->pBuffers[freeMemCount].pData); } } } qaeMemFreeNUMA((void **)&buffList->pPrivateMetaData); qaeMemFreeNUMA((void **)&buffList->pBuffers); qaeMemFreeNUMA((void **)&pOpData->pIv); /* free the session memory - calling code is responsible for * removing the session first*/ if (NULL != *pSessionCtx) { qaeMemFreeNUMA((void **)pSessionCtx); } } /** ***************************************************************************** * @ingroup sampleCipherPerf * * @description * Main executing function ******************************************************************************/ static CpaStatus sampleCipherPerform(symmetric_test_params_t *setup) { /* start of local variable declarations */ CpaCySymSessionCtx sessionCtx = NULL; CpaCySymOpData opData; CpaBufferList buffList; perf_data_t *pSymPerfData = NULL; CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U cipherKey[setup->setupData.cipherSetupData.cipherKeyLenInBytes]; CpaCySymCbFunc pSymCb = cipherPerformCallback; Cpa32U node = 0; Cpa32U bufferMetaSize = 0; Cpa32U createCount = 0; Cpa8U *pBufferMeta = NULL; CpaCySymCipherDirection cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return CPA_STATUS_FAIL; } /*use the preallocated performance stats to store performance data, this * points to an element in perfStats array in the framework, each thread * points to a unique element of perfStats array*/ pSymPerfData = setup->performanceStats; if (NULL == pSymPerfData) { PRINT_ERR("perf data pointer is NULL\n"); cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return CPA_STATUS_FAIL; } memset(pSymPerfData, 0, sizeof(perf_data_t)); /*init the cipher session*/ status = cipherSetupSession(pSymCb, cipherKey, &sessionCtx, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cipherSetupSession error, status %d\n", status); cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return CPA_STATUS_FAIL; } /* calculate memory size which is required for pPrivateMetaData * member of CpaBufferList */ status = cpaCyBufferListGetMetaSize( setup->cyInstanceHandle, setup->numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyBufferListGetMetaSize Failed with status: %d\n", status); return status; } buffList.pBuffers = qaeMemAllocNUMA( (sizeof(CpaFlatBuffer) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (NULL == buffList.pBuffers) { PRINT_ERR("Failed to allocate pBuffers for bufferlist\n"); cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return CPA_STATUS_FAIL; } /* Allocate memory for pPrivateMetaData */ pBufferMeta = qaeMemAllocNUMA(bufferMetaSize, node, BYTE_ALIGNMENT_64); if (NULL == pBufferMeta) { PRINT_ERR("Failed to allocate pBufferMeta memory\n"); cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return CPA_STATUS_FAIL; } /*allocate memory for bufferLists: pBuffers, meta data and source Data*/ for (createCount = 0; createCount < setup->numBuffers; createCount++) { /* Allocate aligned memory for specified packet size on the node that * the thread is running on*/ buffList.pBuffers[createCount].pData = qaeMemAllocNUMA(setup->packetSizeInBytesArray[createCount], node, BYTE_ALIGNMENT_64); if (buffList.pBuffers[createCount].pData == NULL) { PRINT_ERR("Failed to allocate packetSizeData[%u]:(%u) memory\n", createCount, setup->packetSizeInBytesArray[createCount]); cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return CPA_STATUS_FAIL; } buffList.pBuffers[createCount].dataLenInBytes = setup->packetSizeInBytesArray[createCount]; /*populate the data source with random data*/ generateRandomData(buffList.pBuffers[createCount].pData, setup->packetSizeInBytesArray[createCount]); } /* end of pre allocated buffer for loop */ /* * Fill in elements of buffer list struct. */ buffList.numBuffers = setup->numBuffers; buffList.pPrivateMetaData = pBufferMeta; /*setup the cipher operation data*/ status = cipherPerformOpDataSetup( sessionCtx, setup->packetSizeInBytesArray, &opData, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cipherPerformOpDataSetup error, status %d\n", status); cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return status; } status = cipherPerform(setup, pSymPerfData, setup->numLoops, &opData, &buffList, cipherDirection); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("symPerform error, status %d\n", status); cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return status; } /* Free up resources allocated */ if (CPA_STATUS_SUCCESS != removeSymSession(setup->cyInstanceHandle, sessionCtx)) { PRINT_ERR("Deregister session failed\n"); status = CPA_STATUS_FAIL; } cipherPerformMemFree(setup, &buffList, &opData, &sessionCtx); return status; } /** ***************************************************************************** * @ingroup sampleCipherPerf * * @description * Setup a cipher thread for a given packet size or mix ******************************************************************************/ static void sampleCipherPerformance(single_thread_test_data_t *testSetup) { symmetric_test_params_t symTestSetup; symmetric_test_params_t *pSetup = ((symmetric_test_params_t *)testSetup->setupPtr); Cpa32U loopIteration = 0; CpaStatus status = CPA_STATUS_SUCCESS; /*define the distribution of the packet mix * here we defined 2 lots of 10 sizes * later it is replicated into 100 buffers*/ Cpa32U packetMix[NUM_PACKETS_IMIX] = { BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_8992, BUFFER_SIZE_64, BUFFER_SIZE_1504}; Cpa32U *pPacketSize; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*give our thread a unique memory location to store performance stats*/ symTestSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (cyInstances == NULL) { PRINT_ERR("Error allocating memory for instance handles\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; pPacketSize = qaeMemAlloc(sizeof(Cpa32U) * pSetup->numBuffers); if (NULL == pPacketSize) { PRINT_ERR("Could not allocate memory for pPacketSize\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->packetSize == PACKET_IMIX) { /*we are testing IMIX so we copy buffer sizes from preallocated * array into symTestSetup.numBuffers*/ Cpa32U indexer = sizeof(packetMix) / sizeof(Cpa32U); for (loopIteration = 0; loopIteration < pSetup->numBuffers; loopIteration++) { pPacketSize[loopIteration] = packetMix[loopIteration % indexer]; } } else { /*we are testing a uniform bufferSize, so we set the bufferSize array * accordingly*/ for (loopIteration = 0; loopIteration < pSetup->numBuffers; loopIteration++) { pPacketSize[loopIteration] = testSetup->packetSize; } } /*cast the setup to a known structure so that we can populate our local * test setup*/ symTestSetup.setupData = pSetup->setupData; symTestSetup.numBuffers = pSetup->numBuffers; symTestSetup.numLoops = pSetup->numLoops; /*reset the stats print function to NULL, we set it to the proper function * if the test passes at the end of this function*/ testSetup->statsPrintFunc = NULL; /*assign the array of buffer sizes we are testing to the cipher test * setup*/ symTestSetup.packetSizeInBytesArray = pPacketSize; /*assign our thread a unique memory location to store performance stats*/ symTestSetup.performanceStats = testSetup->performanceStats; symTestSetup.performanceStats->averagePacketSizeInBytes = testSetup->packetSize; /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; symTestSetup.syncMode = ASYNC; /*store core affinity, this assumes logical cpu core number is the same * logicalQaInstace */ symTestSetup.performanceStats->logicalCoreAffinity = testSetup->logicalQaInstance; symTestSetup.threadID = testSetup->threadID; symTestSetup.isDpApi = pSetup->isDpApi; symTestSetup.isMultiSGL = CPA_TRUE; symTestSetup.cryptoSrcOffset = pSetup->cryptoSrcOffset; /*launch function that does all the work*/ status = sampleCipherPerform(&symTestSetup); if (CPA_STATUS_SUCCESS != status) { printSymTestType(&symTestSetup); PRINT("Test %u FAILED\n", testSetup->logicalQaInstance); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; } /*free memory and exit*/ qaeMemFree((void **)&pPacketSize); qaeMemFree((void **)&cyInstances); sampleCodeThreadComplete(testSetup->threadID); } /****************************************************************************** * @ingroup sampleCipherTest * * @description * setup a cipher test * This function needs to be called from main to setup a cipher test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ******************************************************************************/ CpaStatus setupCipherTest2(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U packetSize, Cpa32U numBuffers, Cpa32U numLoops) { /*thread_setup_g is a multidimensional global array that stores the setup * for all thread variations in an array of characters. We store our test * setup at the start of the second array ie index 0. There maybe multiple * thread types(setups) running as counted by testTypeCount_g*/ symmetric_test_params_t *symmetricSetup = NULL; Cpa8S name[] = {'S', 'Y', 'M', '\0'}; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /* Return an error if the number of packets is not modulus zero of the * number of packets to cover IMIX packet mix. */ if (packetSize == PACKET_IMIX && (numBuffers % NUM_PACKETS_IMIX) != 0) { PRINT_ERR("To ensure that the weighting of IMIX packets is correct " ", the number of buffers (%d) should be a multiple of %d\n", numBuffers, NUM_PACKETS_IMIX); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Failed to start Crypto services\n"); return CPA_STATUS_FAIL; } /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } /*as setup is a multidimensional char array we need to cast it to the * symmetric structure*/ memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); symmetricSetup = (symmetric_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)sampleCipherPerformance; testSetupData_g[testTypeCount_g].packetSize = packetSize; /*then we store the test setup in the above location*/ symmetricSetup->setupData.symOperation = CPA_CY_SYM_OP_CIPHER; symmetricSetup->setupData.sessionPriority = CPA_CY_PRIORITY_HIGH; symmetricSetup->setupData.cipherSetupData.cipherAlgorithm = cipherAlg; symmetricSetup->setupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; symmetricSetup->setupData.cipherSetupData.cipherKeyLenInBytes = cipherKeyLengthInBytes; symmetricSetup->isDpApi = CPA_FALSE; symmetricSetup->isMultiSGL = CPA_TRUE; symmetricSetup->numBuffers = numBuffers; symmetricSetup->numLoops = numLoops; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setupCipherTest2); cpa_sample_code_crypto_utils.c000066400000000000000000004642641503624047500370300ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_crypto_utils.c * * @ingroup cryptoThreads * * @description * This file contains utility functions for performance sample code * *****************************************************************************/ #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_framework.h" #include "cpa_cy_common.h" #include "cpa_cy_prime.h" #include "cpa_cy_sym.h" #include "icp_sal_poll.h" #define POLL_AND_SLEEP 1 #include "qat_perf_cycles.h" #include "qat_perf_buffer_utils.h" #ifdef USER_SPACE Cpa32U poll_type_g = 0; Cpa32U sleep_time_g = 0; #else Cpa32U poll_type_g = POLL_AND_SLEEP; Cpa32U sleep_time_g = DEFAULT_POLL_INTERVAL_MSEC; #endif CpaBoolean usePartial_g = CPA_FALSE; unsigned long long timeStampTime_g = 0; Cpa32U busyLoopMethod_g = 2; CpaBoolean timeStampInLoop = CPA_FALSE; EXPORT_SYMBOL(timeStampTime_g); long cyPollingThreadsInterval_g = 0; EXPORT_SYMBOL(cyPollingThreadsInterval_g); #define NUM_BITS_IN_MEGABIT (1000000) #define LOWEST_EVEN_NUMBER (2) #define KILOBITS_IN_MEGABITS (1000) #define MILLI_SECONDS_IN_SECOND (1000) #define SECOND_LAST_BYTE (2) #define INC_BY_TWO (2) #define RESPONSE_NOT_CHECKED (-1) #define SINGLE_SOCKET (1) #define NUM_TLS_BUFFERS (2) #define TLS_HEADER_BUFFERSIZE (13) CpaBoolean running_dsa_g = CPA_FALSE; /*flag to indicate whether a thread has started the crypto acceleration service */ volatile CpaBoolean cy_service_started_g = CPA_FALSE; volatile CpaBoolean cy_polling_started_g = CPA_FALSE; CpaCySymCipherDirection cipherDirection_g = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; volatile CpaBoolean digestAppended_g = CPA_FALSE; CpaInstanceHandle *cyInstances_g = NULL; Cpa16U numInstances_g = 0; Cpa16U numPolledInstances_g = 0; CpaBoolean allocateMemOnOppositeNode = CPA_FALSE; extern Cpa32U packageIdCount_g; CpaStatus setCyPollWaitFn(Cpa32U poll_type, Cpa32U sleep_time); CpaBoolean isFbALessThanFbB(CpaFlatBuffer *pFbA, CpaFlatBuffer *pFbB); void setBusyLoopMethod(Cpa32U method); void setTimeStampInLoop(CpaBoolean value); CpaCySymCipherDirection getCipherDirection(void); void setCipherDirection(CpaCySymCipherDirection direction); CpaStatus setDigestAppend(CpaBoolean flag); #if CY_API_VERSION_AT_LEAST(3, 0) volatile CpaBoolean asym_polling_started_g = CPA_FALSE; CpaInstanceHandle *asymInstances_g = NULL; Cpa16U numAsymInstances_g = 0; Cpa16U numAsymPolledInstances_g = 0; sample_code_thread_t *asymPollingThread_g; #endif Cpa32U packetSizes[] = {BUFFER_SIZE_64, BUFFER_SIZE_128, BUFFER_SIZE_256, BUFFER_SIZE_512, BUFFER_SIZE_1024, BUFFER_SIZE_2048, BUFFER_SIZE_4096, PACKET_IMIX}; Cpa32U numPacketSizes = sizeof(packetSizes) / sizeof(Cpa32U); EXPORT_SYMBOL(packetSizes); EXPORT_SYMBOL(numPacketSizes); Cpa32U wirelessPacketSizes[] = {BUFFER_SIZE_40, BUFFER_SIZE_64, BUFFER_SIZE_256, BUFFER_SIZE_320, BUFFER_SIZE_512, BUFFER_SIZE_1024}; Cpa32U numWirelessPacketSizes = sizeof(wirelessPacketSizes) / sizeof(Cpa32U); EXPORT_SYMBOL(wirelessPacketSizes); EXPORT_SYMBOL(numWirelessPacketSizes); Cpa32U modSizes[] = { MODULUS_2048_BIT, MODULUS_4096_BIT, }; Cpa32U numModSizes = sizeof(modSizes) / sizeof(Cpa32U); EXPORT_SYMBOL(modSizes); EXPORT_SYMBOL(numModSizes); extern int signOfLife; extern int verboseOutput; sample_code_thread_t *pollingThread_g; /* * DH prime numbers */ /* Prime numbers for different types of modulus */ static const Cpa8U m_768[] = { 0xC7, 0x3B, 0x18, 0xB5, 0x71, 0xE1, 0xE0, 0x7C, 0x70, 0x66, 0x5F, 0xD8, 0x8B, 0xD9, 0xC2, 0x55, 0x3E, 0xD7, 0x09, 0x68, 0x80, 0xF2, 0x17, 0x1A, 0x7A, 0x6D, 0xC9, 0x24, 0xF2, 0x5C, 0x84, 0x7D, 0xB4, 0xC5, 0xA5, 0x40, 0x9A, 0x3F, 0xB7, 0xBD, 0xD4, 0xD0, 0xE6, 0xA0, 0x01, 0xC5, 0x1E, 0xA7, 0x60, 0x42, 0x2D, 0xF5, 0x16, 0xAF, 0x01, 0x6C, 0xF7, 0xA5, 0x73, 0xCF, 0x36, 0xB3, 0x6E, 0x5C, 0xE7, 0x2C, 0x18, 0x19, 0x5C, 0x21, 0x40, 0x1B, 0xF4, 0xD5, 0xD9, 0xF4, 0x46, 0x08, 0xDA, 0x84, 0x0B, 0x34, 0x8F, 0x80, 0xB9, 0x7C, 0x7B, 0xAF, 0x23, 0xEA, 0x6E, 0xF2, 0x45, 0x8C, 0xC0, 0x0B}; static const Cpa8U m_1024[] = { 0xED, 0x39, 0xD7, 0x6B, 0xD0, 0x77, 0x37, 0xFB, 0x5A, 0xC1, 0x98, 0x41, 0x29, 0x58, 0xC4, 0x3E, 0xD9, 0x6A, 0x0B, 0x7C, 0x48, 0xB4, 0x59, 0x69, 0x54, 0x8F, 0x59, 0x83, 0xE0, 0x73, 0x31, 0x10, 0xA3, 0x6D, 0x5F, 0x51, 0xDA, 0xD9, 0x8D, 0xC9, 0x09, 0xD1, 0xAF, 0x93, 0xC8, 0xA4, 0x93, 0xEC, 0xF5, 0x9B, 0x3D, 0x51, 0x7F, 0x72, 0x2C, 0xFB, 0x4D, 0x72, 0x62, 0x8C, 0xA0, 0x08, 0x9D, 0xE7, 0x40, 0x67, 0x35, 0x7A, 0xB6, 0x99, 0xA7, 0x20, 0x25, 0x59, 0x04, 0x35, 0x54, 0xC1, 0x78, 0x97, 0x35, 0x8E, 0xF8, 0xF2, 0x02, 0xB2, 0x6D, 0xF3, 0xA6, 0x1B, 0xBD, 0x0F, 0xE0, 0x38, 0x99, 0x6E, 0xE0, 0x1D, 0x12, 0x4A, 0x1A, 0xC5, 0x02, 0xF8, 0x74, 0x70, 0x1B, 0x73, 0xC6, 0x52, 0x59, 0x35, 0xCF, 0xBC, 0xA9, 0x51, 0xCE, 0x87, 0xCE, 0xF1, 0x21, 0xF8, 0xB8, 0xEE, 0xF0, 0x2D, 0x84, 0xF1}; static const Cpa8U m_1536[] = { 0xF2, 0x4E, 0x75, 0x1F, 0x5F, 0x61, 0x93, 0x97, 0xBA, 0x9A, 0x5F, 0x3D, 0xF0, 0x8A, 0xF6, 0x42, 0x14, 0x26, 0x09, 0xE1, 0xFE, 0xFC, 0xC4, 0xAB, 0x7B, 0x69, 0xFD, 0x68, 0x5D, 0xD7, 0x4C, 0x7F, 0xCB, 0x36, 0xA9, 0x9A, 0x4D, 0xD8, 0x82, 0x3B, 0xCA, 0x77, 0xE0, 0x93, 0x27, 0xC5, 0x04, 0x60, 0x08, 0x60, 0x15, 0x40, 0xDF, 0x11, 0x2D, 0x40, 0x83, 0x48, 0x39, 0x46, 0x81, 0xEC, 0xA1, 0x45, 0xEA, 0x5A, 0x32, 0xE8, 0x15, 0x07, 0x59, 0x03, 0x42, 0x97, 0xCB, 0xBA, 0x0E, 0xBA, 0x9A, 0xE0, 0xF9, 0x9A, 0xA4, 0x96, 0x71, 0x62, 0x3B, 0x4D, 0xB0, 0x59, 0xFF, 0x47, 0xB5, 0x06, 0x66, 0xE7, 0x81, 0xFD, 0x1C, 0x20, 0x84, 0xF5, 0x32, 0x8D, 0xE9, 0x64, 0x32, 0xA0, 0xAD, 0x3E, 0xB2, 0xD0, 0xAB, 0xC9, 0x2B, 0x24, 0x36, 0x0C, 0x03, 0xB2, 0x95, 0x07, 0x3F, 0x97, 0x3D, 0x68, 0x05, 0x4E, 0xEE, 0xDB, 0x93, 0x58, 0x88, 0x81, 0x95, 0x6B, 0x4B, 0x52, 0x62, 0xE2, 0x4D, 0x9C, 0x1C, 0xFB, 0x0D, 0x47, 0x1B, 0xDB, 0x57, 0x3C, 0x72, 0x73, 0x71, 0x5C, 0xC3, 0x87, 0x12, 0x81, 0xE0, 0xF1, 0x70, 0x22, 0x08, 0xC2, 0x7B, 0xB0, 0x32, 0x9E, 0x30, 0x30, 0x7C, 0x86, 0x42, 0xA5, 0xB6, 0x6C, 0xAE, 0xBB, 0xD7, 0x0A, 0x69, 0x03, 0x02, 0x61, 0xEA, 0xEA, 0x72, 0x08, 0x63, 0xF9, 0x75, 0x99}; static const Cpa8U m_2048[] = { 0xE9, 0x24, 0x8E, 0x32, 0x0F, 0x73, 0xD2, 0x3E, 0xB4, 0x07, 0x57, 0xA0, 0xFC, 0xA4, 0xD6, 0xD9, 0xE4, 0xDF, 0xD1, 0xD9, 0x0D, 0x1D, 0xDA, 0x56, 0xC9, 0x53, 0x74, 0x2F, 0xC4, 0x82, 0x13, 0xFF, 0xF7, 0xF3, 0x47, 0x34, 0x70, 0x1E, 0x7D, 0x78, 0x1E, 0x38, 0x84, 0x7A, 0xDA, 0xD0, 0xDF, 0x67, 0x6F, 0xCC, 0x26, 0x6C, 0x64, 0x96, 0x19, 0x71, 0x72, 0x0F, 0x6B, 0x28, 0x1C, 0xAB, 0x95, 0xBB, 0x2F, 0xA0, 0x13, 0x51, 0x8F, 0x47, 0x5C, 0x42, 0xF3, 0xC3, 0xFA, 0x46, 0xEF, 0xFC, 0x0F, 0x4C, 0x8D, 0x01, 0x1D, 0xD5, 0x3B, 0xBF, 0x70, 0xCE, 0x83, 0xD0, 0x79, 0xB3, 0xDE, 0x84, 0xD7, 0xE0, 0x80, 0xDC, 0x44, 0x36, 0x07, 0x93, 0x50, 0x0A, 0x2F, 0x66, 0xA9, 0xD8, 0x62, 0x30, 0xB1, 0xD4, 0x6B, 0xD1, 0x86, 0x81, 0x8B, 0x03, 0xE9, 0x72, 0x12, 0xD2, 0xB9, 0xE0, 0x35, 0x99, 0x22, 0xF9, 0x17, 0x29, 0x1E, 0x8C, 0x0A, 0x1E, 0x2B, 0xCA, 0xC0, 0xE6, 0x0B, 0x6F, 0x76, 0xD7, 0x91, 0xE0, 0xD0, 0x0E, 0x6B, 0x6E, 0x10, 0xB8, 0x33, 0xB3, 0xA5, 0xB3, 0xB1, 0x4B, 0xF6, 0x3D, 0x5F, 0xE0, 0x21, 0xF6, 0x67, 0x96, 0xDA, 0x8F, 0x27, 0xA0, 0x46, 0x7B, 0xF2, 0xB4, 0x38, 0x05, 0x3C, 0x63, 0xD7, 0xD4, 0xDB, 0x24, 0x4E, 0xA4, 0x74, 0xF9, 0x00, 0xA2, 0x70, 0x5D, 0x9D, 0x7A, 0x13, 0x19, 0xF5, 0x98, 0x8A, 0x74, 0xB7, 0x84, 0xA4, 0xD3, 0xB0, 0x5F, 0x61, 0xFD, 0x90, 0xD3, 0x59, 0xDB, 0x71, 0xF8, 0x57, 0xBD, 0xDF, 0x40, 0xDC, 0x71, 0x1B, 0xFD, 0x53, 0x7A, 0x0B, 0x76, 0x23, 0xBE, 0x86, 0x46, 0xEB, 0x6B, 0x2C, 0xEE, 0x17, 0x3D, 0x4F, 0x89, 0xCA, 0xB4, 0x2A, 0x4D, 0x8B, 0x1D, 0x82, 0x3C, 0xAC, 0x33, 0x53, 0x87, 0x71, 0xB3, 0x45, 0x2A, 0x1C, 0xDD, 0xB9, 0x78, 0xBF, 0x5B}; static const Cpa8U m_3072[] = { 0xA2, 0x5F, 0xE5, 0x92, 0xE6, 0x19, 0x98, 0x9B, 0xC5, 0x37, 0xDF, 0x84, 0x83, 0x5C, 0xED, 0xEE, 0xD1, 0x0E, 0x47, 0xDB, 0x51, 0x15, 0x2E, 0x93, 0xD1, 0x19, 0x8B, 0xDF, 0x40, 0x91, 0x6D, 0x16, 0x34, 0xB3, 0xDB, 0x7B, 0xB3, 0x66, 0x6C, 0xAF, 0x0C, 0x5A, 0xCE, 0xF7, 0xB3, 0x57, 0xBE, 0x5F, 0x76, 0x1D, 0x3C, 0xD4, 0xCC, 0x11, 0x9B, 0xF4, 0x47, 0xB1, 0xCD, 0x11, 0x65, 0xCF, 0x26, 0x4A, 0x1D, 0xC5, 0x81, 0x51, 0xD4, 0x91, 0x5F, 0xD5, 0x31, 0x10, 0x8B, 0x83, 0xC5, 0x5A, 0x76, 0xA4, 0x87, 0x08, 0xB2, 0x43, 0xE1, 0x97, 0xFA, 0x06, 0x89, 0x3D, 0xC5, 0x9B, 0x61, 0x68, 0x60, 0xC5, 0x21, 0xC6, 0x47, 0xD0, 0x5E, 0xE6, 0xC5, 0xDF, 0x93, 0xE8, 0x7C, 0x63, 0xB7, 0x81, 0x38, 0x47, 0x45, 0xF2, 0x2E, 0x9A, 0xC2, 0x1E, 0xE1, 0x6F, 0xE2, 0xAD, 0xE8, 0x3A, 0xAD, 0x44, 0xF7, 0x9B, 0x3A, 0x44, 0x8B, 0x4C, 0x19, 0xED, 0x3B, 0xF9, 0x83, 0x84, 0x65, 0x21, 0x28, 0xBB, 0x03, 0x8F, 0x5C, 0x45, 0xFA, 0x44, 0x04, 0x14, 0x0B, 0x76, 0xAA, 0xE4, 0x71, 0x3E, 0xB1, 0x89, 0x9F, 0x31, 0x43, 0x41, 0x24, 0x59, 0xE1, 0x41, 0x8C, 0x75, 0x5B, 0x2B, 0xDF, 0x45, 0x44, 0x93, 0x24, 0x7B, 0xA1, 0x33, 0xFE, 0x6E, 0x76, 0xE9, 0x69, 0xEC, 0xB6, 0x90, 0x3F, 0x93, 0xD2, 0xC4, 0x70, 0x2B, 0x26, 0x72, 0xB6, 0xCF, 0xC9, 0x11, 0x90, 0xEC, 0x22, 0x45, 0x97, 0x9C, 0xEB, 0xA9, 0x82, 0x1A, 0xFD, 0x1E, 0xFC, 0x71, 0xCA, 0x6B, 0x3E, 0x33, 0x9E, 0x4E, 0x9E, 0xC2, 0x18, 0x20, 0xBF, 0x1A, 0xC2, 0x13, 0x24, 0x28, 0x7E, 0x3E, 0xFC, 0xD7, 0xEE, 0xB4, 0xD3, 0xC1, 0x82, 0xEF, 0x2B, 0x31, 0xAF, 0xB9, 0xB0, 0xCA, 0xE7, 0x33, 0x93, 0xF6, 0xB7, 0xB2, 0x77, 0x0F, 0x7A, 0xB1, 0x32, 0xE9, 0xD7, 0x62, 0x03, 0xA1, 0xCE, 0xBF, 0xF6, 0xAB, 0x77, 0x61, 0x21, 0x9A, 0x92, 0x91, 0x35, 0x50, 0x15, 0x73, 0x32, 0x3D, 0x80, 0xB7, 0x40, 0xAE, 0xBC, 0x8A, 0xD3, 0x98, 0x65, 0x90, 0x63, 0x25, 0x39, 0xB2, 0x36, 0xD0, 0xED, 0xC7, 0x02, 0x43, 0x1B, 0xE8, 0x82, 0x40, 0xBD, 0x6D, 0x33, 0x03, 0x69, 0x46, 0xFB, 0x5D, 0xC5, 0x59, 0xD5, 0x50, 0xA9, 0x32, 0x2D, 0xC8, 0x11, 0x09, 0x26, 0x0A, 0x2C, 0x82, 0xD8, 0xBF, 0x39, 0x2B, 0x85, 0xDF, 0x3A, 0x7A, 0xE8, 0xB5, 0x5E, 0xB5, 0x05, 0xA1, 0xD0, 0xAD, 0x5C, 0x17, 0xE0, 0xC3, 0xA5, 0x34, 0x29, 0x7E, 0x93, 0x2B, 0xF4, 0x7A, 0x1A, 0x51, 0x71, 0xA6, 0x22, 0x32, 0x47, 0x62, 0xE4, 0x23, 0x4E, 0xEC, 0xF0, 0x80, 0x17, 0x10, 0x69, 0x6F, 0xD7, 0x8A, 0x5C, 0x7D, 0xFF, 0x8F, 0x47, 0xCA, 0xB4, 0x1F, 0x27, 0x97, 0xBD, 0x3A, 0x8E, 0x4D}; static const Cpa8U m_4096[] = { 0xF5, 0x98, 0xBF, 0x63, 0x4A, 0xBD, 0xA9, 0x9A, 0x32, 0x45, 0x9E, 0x36, 0x2D, 0xC3, 0x1A, 0xE8, 0x62, 0xEB, 0x0F, 0xCC, 0x9E, 0x9D, 0x41, 0xE5, 0x8F, 0xEA, 0x13, 0x3F, 0xA0, 0xF5, 0xC4, 0xE1, 0xD0, 0xE4, 0x8A, 0xF8, 0x5C, 0x88, 0x64, 0xD0, 0xDA, 0x60, 0x84, 0x77, 0x5B, 0x02, 0xAD, 0x81, 0xA1, 0xEC, 0x55, 0xDD, 0xF2, 0x07, 0x45, 0x17, 0x3C, 0xE5, 0xA1, 0xA1, 0x87, 0x5B, 0xED, 0xBA, 0x20, 0xB8, 0x8D, 0x41, 0x64, 0xBD, 0x53, 0x22, 0x9A, 0x8B, 0x5D, 0xC3, 0x19, 0x75, 0x3D, 0x3A, 0xAC, 0xF2, 0x7F, 0xBF, 0x97, 0x88, 0x82, 0x6A, 0x6D, 0xC0, 0x9D, 0xFB, 0x0C, 0x88, 0xC5, 0x03, 0xE2, 0x2A, 0x4F, 0x21, 0x3A, 0x54, 0xAD, 0x51, 0xC9, 0x3A, 0x32, 0x57, 0xE1, 0x55, 0x3E, 0x25, 0x84, 0xD2, 0x95, 0xCD, 0x7D, 0x40, 0xC4, 0x99, 0x3F, 0x2C, 0xE5, 0xBF, 0x04, 0x85, 0xDB, 0xEC, 0xA4, 0xFD, 0x53, 0x6C, 0x8F, 0x44, 0x89, 0x47, 0x35, 0xDA, 0x7F, 0xCC, 0x22, 0x24, 0x2C, 0xBA, 0xDF, 0xC3, 0x45, 0x84, 0x1B, 0x9F, 0x9B, 0xD8, 0x8D, 0x9C, 0xC5, 0x36, 0x2C, 0x46, 0xA0, 0xA0, 0x11, 0x71, 0xE9, 0xA5, 0x9E, 0xFE, 0x63, 0xFB, 0xA6, 0x6E, 0x08, 0x2A, 0xF9, 0x1A, 0xF9, 0xF0, 0x95, 0x48, 0x13, 0x67, 0x32, 0x9D, 0xB3, 0xE0, 0xDB, 0xDE, 0xEA, 0x17, 0x69, 0x24, 0x2D, 0xA6, 0xE0, 0x5A, 0xCC, 0x71, 0xC6, 0x08, 0x9C, 0xAB, 0x12, 0xB7, 0x1A, 0xCC, 0xEF, 0xE2, 0x1C, 0xB8, 0xD4, 0x37, 0x3A, 0xF8, 0xF3, 0x43, 0x10, 0x41, 0x45, 0xAB, 0x65, 0x5A, 0x8E, 0xAB, 0xE0, 0x40, 0xF3, 0xD7, 0x07, 0xDF, 0x5D, 0x9A, 0x4C, 0xB4, 0x37, 0x37, 0x8F, 0x8B, 0xA1, 0xC2, 0x11, 0x14, 0xF3, 0xD6, 0x5F, 0xA2, 0x8D, 0xD8, 0x8E, 0xE5, 0x76, 0x6D, 0xFE, 0x27, 0x55, 0x12, 0xCE, 0xAC, 0x03, 0xE0, 0xF7, 0x89, 0xB0, 0xB2, 0xA5, 0xBE, 0x08, 0x5E, 0xB6, 0x76, 0xC2, 0x2C, 0xD5, 0xBE, 0xDC, 0xE8, 0x51, 0x6D, 0x9D, 0x93, 0x9F, 0xF2, 0xB5, 0x49, 0xBE, 0xED, 0xB1, 0x1D, 0xDD, 0x09, 0x2F, 0xA9, 0x66, 0x91, 0x35, 0x8F, 0xB9, 0x60, 0xC4, 0x06, 0x15, 0x28, 0xDC, 0xD7, 0x42, 0x49, 0x5C, 0x94, 0xFE, 0x17, 0xF4, 0xDC, 0x44, 0xBC, 0xC6, 0xC4, 0x05, 0x47, 0xB1, 0x44, 0xA4, 0xAC, 0xAF, 0x9E, 0x34, 0xB8, 0x2A, 0x7C, 0x22, 0xCA, 0x89, 0xF1, 0x98, 0x64, 0xDB, 0x08, 0x7F, 0x4C, 0xE0, 0xF3, 0xC1, 0x83, 0x70, 0x25, 0x7B, 0xDD, 0x73, 0x6E, 0x55, 0x72, 0xFE, 0xC2, 0x37, 0xE1, 0x8F, 0x15, 0xD5, 0xB1, 0x1A, 0x59, 0x4F, 0x30, 0xDA, 0xE8, 0xD2, 0x68, 0x7B, 0x9B, 0xFB, 0x4D, 0xBC, 0xB5, 0x43, 0xEE, 0x71, 0xAD, 0xBF, 0x2D, 0x91, 0x62, 0x2B, 0xB8, 0x03, 0x5A, 0xBC, 0x94, 0x65, 0xEA, 0x04, 0xBB, 0x52, 0x96, 0xF4, 0x8C, 0x51, 0xD0, 0xCC, 0xDB, 0xB0, 0x7D, 0x65, 0x62, 0x1E, 0x74, 0x3D, 0x5D, 0xBA, 0x66, 0x78, 0xAC, 0xCE, 0xBB, 0xE1, 0x94, 0x63, 0xBE, 0x6C, 0x5F, 0xDF, 0xF3, 0xCD, 0xAC, 0x34, 0xB3, 0xDB, 0xAF, 0x73, 0x0A, 0x7B, 0x86, 0xFB, 0xC0, 0xE3, 0x56, 0xEA, 0xDF, 0x84, 0x24, 0xB9, 0x11, 0x8C, 0x98, 0x95, 0xEB, 0x91, 0x25, 0x7B, 0x44, 0x0C, 0x43, 0xEC, 0xB3, 0x45, 0xBC, 0xA5, 0x37, 0x1F, 0x6E, 0x8A, 0x4A, 0xD8, 0xA4, 0xD3, 0x64, 0x69, 0x25, 0xD5, 0x3A, 0x4A, 0x7D, 0xC6, 0x28, 0xB8, 0x55, 0xD3, 0xD4, 0x46, 0x61, 0x83, 0x2D, 0xDD, 0xC4, 0x53, 0xC3, 0x14, 0xE1, 0x3E, 0x4B, 0xA6, 0x81, 0x37, 0xDE, 0x6A, 0xA5, 0x4F, 0x33, 0xAC, 0xFD, 0x46, 0xCA, 0x16, 0x00, 0xDA, 0x82, 0xDD, 0xD7, 0xE7, 0xE1, 0x39, 0xDF, 0x96, 0x77, 0x58, 0xE5}; /* * RSA prime numbers */ /* * 512 Bit Modulus */ /* RSA first prime */ static const Cpa8U p_512[] = {0xE7, 0x6C, 0xB1, 0x5B, 0x38, 0xF4, 0x4D, 0x43, 0x5F, 0x2A, 0xEC, 0x28, 0xF9, 0xEA, 0x8B, 0xF4, 0xB4, 0x52, 0xA8, 0x15, 0x61, 0x01, 0x88, 0x82, 0x83, 0x3A, 0xF7, 0x9D, 0x0C, 0xEE, 0x6D, 0xE7}; /* RSA second prime */ static const Cpa8U q_512[] = {0xEA, 0xB1, 0x5B, 0xA0, 0xB1, 0x68, 0x06, 0xD3, 0x2E, 0xCD, 0x21, 0xD3, 0x5D, 0x18, 0x91, 0x0B, 0x57, 0xC9, 0x03, 0x24, 0x6A, 0xC2, 0x4D, 0xB3, 0xFF, 0xAE, 0xE7, 0xEB, 0xF0, 0x91, 0x45, 0xE7}; /* * 1024 Bit Modulus */ /* RSA first prime */ static const Cpa8U p_1024[] = { 0xb7, 0x9f, 0x2c, 0x24, 0x93, 0xb4, 0xb7, 0x6f, 0x32, 0x99, 0x03, 0xd7, 0x55, 0x5b, 0x7f, 0x5f, 0x06, 0xaa, 0xa5, 0xea, 0xab, 0x26, 0x2d, 0xa1, 0xdc, 0xda, 0x81, 0x94, 0x72, 0x06, 0x72, 0xa4, 0xe0, 0x22, 0x29, 0xa0, 0xc7, 0x31, 0x50, 0xae, 0x25, 0x65, 0x56, 0xb6, 0xe6, 0xa4, 0x38, 0xa9, 0x9d, 0x55, 0xaf, 0x7a, 0xa1, 0x59, 0x45, 0xb9, 0x92, 0xc7, 0xbf, 0x41, 0x61, 0x89, 0xc7, 0x41}; /* RSA second prime */ static const Cpa8U q_1024[] = { 0xc8, 0x38, 0x7f, 0xd3, 0x8f, 0xa3, 0x3d, 0xdc, 0xea, 0x6a, 0x9d, 0xe1, 0xb2, 0xd5, 0x54, 0x10, 0x66, 0x35, 0x02, 0xdb, 0xc2, 0x25, 0x65, 0x5a, 0x93, 0x10, 0xcc, 0xea, 0xc9, 0xf4, 0xcf, 0x1b, 0xce, 0x65, 0x3e, 0xc9, 0x16, 0xd7, 0x94, 0x07, 0x7c, 0x28, 0x6a, 0xd4, 0x8c, 0x57, 0xbd, 0x26, 0xa9, 0x65, 0xbf, 0x75, 0x96, 0xb0, 0x48, 0xfd, 0x51, 0xd6, 0xa4, 0x17, 0x15, 0xe1, 0xb5, 0x17}; /* ***************************************************************/ /* 1536 Bit Modulus*/ /* ***************************************************************/ /* RSA first prime */ static const Cpa8U p_1536[] = { 0xd5, 0xd2, 0xb2, 0x2a, 0x6d, 0x45, 0x6f, 0x62, 0xa4, 0x17, 0x94, 0x2d, 0x77, 0xa8, 0x75, 0x9d, 0x04, 0x4d, 0x6f, 0x38, 0xee, 0xf2, 0xa1, 0x7a, 0x23, 0xd6, 0x95, 0x4c, 0xfd, 0x5a, 0x42, 0x0c, 0x34, 0x11, 0x37, 0xf5, 0x24, 0x8c, 0x48, 0x82, 0xc6, 0xa0, 0xd0, 0xc7, 0xef, 0xe3, 0xbd, 0x93, 0xf1, 0x0c, 0xc1, 0x3b, 0x59, 0x12, 0xe6, 0xd3, 0x1b, 0xb4, 0x58, 0x6a, 0x18, 0x1b, 0x7f, 0x05, 0x93, 0xc5, 0x96, 0x5f, 0x11, 0xbd, 0xcb, 0x40, 0xd3, 0x97, 0x67, 0xc6, 0x98, 0xfe, 0x3c, 0x84, 0x30, 0x68, 0xfd, 0xe0, 0xaf, 0x83, 0x13, 0x2f, 0x47, 0x24, 0xd9, 0xe0, 0x46, 0xb6, 0x86, 0x33}; /* RSA second prime */ static const Cpa8U q_1536[] = { 0xd5, 0xd2, 0xaf, 0x44, 0xdf, 0x74, 0xdd, 0x31, 0xea, 0x0a, 0x36, 0x5c, 0xb2, 0x3f, 0xa4, 0x1b, 0x60, 0x02, 0x7c, 0x5f, 0x3d, 0x7c, 0x7f, 0xe8, 0xe5, 0xd3, 0x7d, 0x6a, 0x25, 0x40, 0x37, 0x63, 0xbc, 0xd3, 0xc1, 0xaa, 0x6e, 0x58, 0x61, 0x69, 0x40, 0x82, 0xca, 0xcb, 0x76, 0x11, 0xd5, 0x52, 0xfd, 0xf7, 0x1d, 0xd8, 0xef, 0x18, 0x58, 0x8c, 0x50, 0x8d, 0xb6, 0x81, 0x30, 0x09, 0xce, 0xf6, 0x59, 0xaa, 0x72, 0x19, 0x9f, 0xc1, 0xc9, 0x30, 0xfa, 0x70, 0xf3, 0xa9, 0x42, 0x08, 0x92, 0x45, 0x53, 0x82, 0x5b, 0xea, 0xc8, 0x62, 0xc7, 0x43, 0xd8, 0x7d, 0xea, 0x36, 0x01, 0x50, 0x71, 0xb3}; /* ***************************************************************/ /* 2048 Bit Modulus */ /* ***************************************************************/ /* RSA first prime */ static const Cpa8U p_2048[] = { 0xDF, 0x4D, 0x4D, 0x9A, 0xF6, 0xA4, 0xBC, 0x55, 0xBD, 0xFC, 0x52, 0x03, 0xB6, 0x5F, 0x1D, 0x1B, 0xFF, 0xD2, 0xCB, 0xD5, 0xE5, 0x9C, 0x44, 0x7D, 0xBF, 0x3C, 0x23, 0xB1, 0x9B, 0x18, 0x85, 0x25, 0xBA, 0x90, 0xB8, 0x37, 0x89, 0x2A, 0xDF, 0x23, 0xD5, 0xD5, 0x23, 0xFD, 0x2A, 0xC7, 0x66, 0x98, 0xB6, 0xBC, 0xAC, 0xF0, 0x1A, 0xC5, 0x4D, 0x6E, 0x90, 0xC7, 0x74, 0x87, 0xCF, 0x50, 0xA4, 0xAD, 0xD6, 0x52, 0xAF, 0xB4, 0x10, 0x53, 0xEA, 0x21, 0xA5, 0xF5, 0xCC, 0x0A, 0x4B, 0x34, 0xD0, 0x49, 0x90, 0x62, 0x5F, 0xF7, 0x65, 0x52, 0xB1, 0x3C, 0x6A, 0x44, 0xD3, 0x1E, 0x72, 0x7D, 0x35, 0x72, 0x3B, 0xEA, 0xC4, 0x27, 0xE1, 0x35, 0x6C, 0x28, 0x73, 0xD6, 0x0A, 0x05, 0xA4, 0x8D, 0x06, 0xB2, 0x8E, 0xFE, 0xFF, 0x8E, 0x0D, 0x52, 0xB3, 0x72, 0x5E, 0xF0, 0x25, 0xA7, 0x42, 0x81, 0x05, 0x6D}; /* RSA second prime */ static const Cpa8U q_2048[] = { 0xDF, 0x4D, 0x1F, 0xD1, 0x93, 0x6D, 0xFD, 0xF3, 0x61, 0x77, 0x11, 0x08, 0x58, 0x81, 0x05, 0x21, 0x62, 0x74, 0x42, 0xA2, 0xCF, 0xAD, 0x0A, 0x0E, 0xD7, 0xCE, 0x2C, 0xFA, 0xD3, 0xD4, 0x9C, 0x93, 0x26, 0xB0, 0xE3, 0x54, 0xFF, 0x39, 0xC2, 0xED, 0x7C, 0x85, 0x10, 0x9E, 0xB9, 0x73, 0x89, 0xFD, 0xBF, 0x14, 0xD4, 0x43, 0x01, 0x8C, 0x9C, 0x35, 0x0F, 0x42, 0xCA, 0xAE, 0x2F, 0x38, 0x26, 0x90, 0xFF, 0x33, 0xF0, 0x7C, 0x9F, 0xEB, 0x32, 0x45, 0xA1, 0x4B, 0x70, 0x00, 0xEF, 0xC4, 0x76, 0x56, 0x76, 0x92, 0xC1, 0xC9, 0x91, 0xA4, 0xA4, 0x08, 0xB4, 0x8E, 0xC3, 0x0B, 0x05, 0xF8, 0x55, 0x34, 0x34, 0x14, 0xCD, 0x38, 0xA5, 0xAB, 0x47, 0x94, 0x93, 0xA9, 0x5C, 0xAB, 0x65, 0x74, 0xDA, 0x3D, 0x11, 0xF1, 0xDD, 0x1F, 0xBC, 0x83, 0x90, 0x7D, 0x78, 0x58, 0x76, 0x01, 0x57, 0x85, 0xDF, 0xEF}; /* ****************************************************************** */ /* 3072 Bit Modulus */ /* ****************************************************************** */ /* RSA first prime */ static const Cpa8U p_3072[] = { 0xc7, 0xad, 0x4f, 0xf7, 0x6b, 0x07, 0x69, 0xf3, 0x87, 0xfe, 0x33, 0x77, 0x9a, 0xb9, 0x74, 0xc8, 0xe4, 0xfa, 0x0e, 0x03, 0x70, 0x2b, 0x61, 0xba, 0x92, 0x99, 0x03, 0xca, 0xc9, 0x69, 0x39, 0x51, 0x62, 0x63, 0xf0, 0x01, 0xb8, 0x65, 0x60, 0xfa, 0xa5, 0xb2, 0x9c, 0xc7, 0xf6, 0x3e, 0x28, 0xc2, 0x79, 0xc7, 0xb6, 0xfc, 0xb3, 0x0e, 0xb6, 0xf2, 0x8e, 0x03, 0xf4, 0x44, 0xd6, 0xf7, 0x2a, 0xcd, 0x64, 0x1a, 0x05, 0xcb, 0x68, 0x51, 0x18, 0x3e, 0x2e, 0x3b, 0x94, 0x89, 0x8e, 0x12, 0x1c, 0xe5, 0x1a, 0xd1, 0xdb, 0xe6, 0xa5, 0xdb, 0xcc, 0x20, 0x04, 0x0a, 0x01, 0x46, 0xc5, 0x60, 0x42, 0x14, 0x5b, 0x6a, 0x29, 0x66, 0xbe, 0x79, 0xdd, 0x52, 0xc0, 0xcf, 0x1a, 0x23, 0x71, 0x18, 0xc6, 0xd8, 0x4e, 0x5a, 0x4f, 0xdc, 0x71, 0xbb, 0xfc, 0xed, 0xa2, 0xad, 0xd1, 0x22, 0x76, 0xfa, 0x8b, 0x11, 0x9b, 0x30, 0x04, 0xe2, 0xf0, 0x36, 0xe0, 0xe0, 0xb1, 0xdb, 0x06, 0x6b, 0x54, 0x6a, 0xca, 0xc4, 0xc5, 0xa7, 0x1b, 0x98, 0x83, 0x98, 0xa8, 0xb3, 0x20, 0xa9, 0x07, 0x57, 0xe9, 0x8c, 0xfc, 0x6c, 0x7b, 0x4a, 0xac, 0xb7, 0xcc, 0x8a, 0x1c, 0x0a, 0x34, 0x2f, 0x78, 0xd8, 0xdf, 0x3c, 0x9b, 0xd0, 0xab, 0xc2, 0x95, 0xa3, 0x3a, 0x47, 0xe7, 0xaf, 0xb3, 0x15, 0x17, 0xf7, 0xc8, 0xdd, 0xf4, 0x93}; /* RSA second prime */ static const Cpa8U q_3072[] = { 0xc7, 0xad, 0x45, 0xff, 0x44, 0xb7, 0x16, 0x4a, 0x31, 0x56, 0x67, 0x4d, 0x20, 0xa5, 0xf0, 0xab, 0x2d, 0xf0, 0x91, 0xef, 0x6f, 0x81, 0xbd, 0xe1, 0x7d, 0x4a, 0x6c, 0xe3, 0x1e, 0xf9, 0x3f, 0x1d, 0x74, 0x5a, 0xc2, 0x8f, 0x06, 0xde, 0x51, 0x26, 0xe7, 0x4a, 0xec, 0xf9, 0x56, 0xdb, 0x5b, 0xd2, 0x42, 0x0e, 0x87, 0x5a, 0x6c, 0x6d, 0x1e, 0xd5, 0x30, 0x39, 0xcf, 0xb9, 0xb0, 0x9f, 0xc4, 0x28, 0xa3, 0x6d, 0x0e, 0xd4, 0x57, 0x59, 0x4f, 0xaf, 0x92, 0xe5, 0xee, 0x69, 0xe5, 0x95, 0x8a, 0x5e, 0x40, 0xcb, 0x94, 0x0f, 0x10, 0xb8, 0xb3, 0xbb, 0x47, 0x67, 0x90, 0xda, 0xbf, 0xd4, 0xcc, 0xe9, 0x88, 0x6a, 0x16, 0xa5, 0x55, 0x5b, 0x3c, 0xc8, 0x9f, 0x82, 0xe1, 0x85, 0x57, 0x53, 0x0c, 0x58, 0x01, 0x23, 0x84, 0x47, 0x29, 0x14, 0x25, 0x2b, 0xa8, 0x67, 0x18, 0x05, 0x6e, 0x84, 0xc7, 0xb6, 0xa1, 0xce, 0x03, 0xd6, 0xc7, 0xb9, 0xf3, 0x9d, 0x0d, 0xd7, 0x92, 0xab, 0x89, 0xdd, 0xf2, 0xec, 0x2d, 0xe8, 0x7e, 0x74, 0x7d, 0x23, 0x7c, 0x6e, 0x54, 0x5a, 0x9b, 0xc6, 0xe9, 0x65, 0x26, 0x13, 0xad, 0xc4, 0xc8, 0x7b, 0x8d, 0x2e, 0x28, 0x49, 0xaa, 0xf6, 0xc6, 0xb2, 0x72, 0xaf, 0xad, 0x12, 0x4c, 0x49, 0x54, 0xc2, 0x1d, 0xd8, 0x69, 0x53, 0xa7, 0x10, 0x51, 0x00, 0x43, 0x23, 0xb3, 0xb1}; /* ****************************************************************** */ /* 4096 Bit Modulus */ /* ****************************************************************** */ /* RSA first prime */ static const Cpa8U p_4096[] = { 0xBC, 0x6E, 0xA2, 0xA5, 0xFF, 0x94, 0x78, 0x50, 0x10, 0xB4, 0xA0, 0x91, 0x5C, 0xC9, 0xC0, 0x51, 0xC0, 0x95, 0xB5, 0xEA, 0x5B, 0x9B, 0x7B, 0x81, 0xD1, 0x65, 0x83, 0xEA, 0x14, 0x0C, 0xB5, 0x7F, 0x6D, 0x04, 0xEA, 0x73, 0xA3, 0xE3, 0x76, 0xB5, 0x28, 0xA3, 0x93, 0x00, 0x23, 0xC8, 0xF4, 0xC0, 0xF8, 0xD0, 0xB3, 0xA6, 0xD7, 0xE1, 0xA5, 0x49, 0x05, 0x94, 0xFA, 0x37, 0x4B, 0x81, 0x6B, 0xEC, 0xD7, 0x82, 0x23, 0x55, 0x99, 0xE2, 0xCB, 0x45, 0x08, 0x5C, 0x77, 0x8C, 0x29, 0x81, 0x77, 0xA0, 0x1E, 0x6C, 0x73, 0xE8, 0xF4, 0x47, 0xCB, 0x31, 0xBC, 0x80, 0x60, 0x0C, 0xC5, 0xDC, 0xB0, 0x42, 0x22, 0xB9, 0xC5, 0xA3, 0x8A, 0xB7, 0x58, 0x6A, 0x22, 0xD4, 0x85, 0x61, 0x78, 0x31, 0x04, 0xCC, 0xBA, 0x8C, 0xDA, 0xA7, 0x73, 0x42, 0x80, 0x70, 0xE3, 0xD4, 0x51, 0xEB, 0xD2, 0xF1, 0xFB, 0x93, 0x3A, 0x5B, 0x09, 0x9A, 0x6E, 0xC3, 0x65, 0x95, 0xA8, 0x2B, 0x72, 0x68, 0xA2, 0x1A, 0xA7, 0x36, 0x9C, 0x04, 0xAD, 0xDB, 0xDD, 0x1B, 0xAD, 0x9A, 0x83, 0x00, 0x73, 0x12, 0xBF, 0xB4, 0xBE, 0x0D, 0xD4, 0x31, 0x42, 0xE8, 0x97, 0x1E, 0x10, 0x22, 0x64, 0x64, 0x91, 0xD0, 0xB1, 0xF4, 0xA5, 0xFA, 0x70, 0x9A, 0x5E, 0xB5, 0x9C, 0xF6, 0xA4, 0x9D, 0xE8, 0xEE, 0xD5, 0x36, 0x7A, 0x7B, 0xFF, 0x1B, 0x26, 0x2D, 0x31, 0x53, 0x24, 0xC8, 0x24, 0x68, 0x4B, 0x32, 0x21, 0x51, 0x1A, 0x78, 0xBD, 0xCA, 0xD5, 0xA4, 0xCF, 0xEA, 0xBC, 0xEC, 0x25, 0xB5, 0x6A, 0x30, 0xD0, 0x5F, 0xF6, 0x3E, 0x34, 0x95, 0xF4, 0xD8, 0x60, 0x3B, 0x59, 0x60, 0x75, 0xDC, 0x94, 0x5C, 0x3E, 0x4D, 0x5D, 0x1F, 0x37, 0x5A, 0x7D, 0x58, 0x2F, 0x9A, 0x17, 0x0D, 0xF6, 0xAD, 0x29, 0xE6, 0x27, 0x63, 0xA1, 0xDD, 0x8C, 0x4D}; /* RSA second prime */ static const Cpa8U q_4096[] = { 0xBC, 0x6E, 0xA0, 0x6C, 0xF3, 0x64, 0xBA, 0xA6, 0x67, 0x32, 0x2C, 0x3E, 0x2B, 0x6D, 0xC4, 0xD4, 0x2F, 0xC6, 0x88, 0x63, 0xFE, 0x41, 0x16, 0x4D, 0xA8, 0x6C, 0x3D, 0xF3, 0x3B, 0xFD, 0x61, 0xE0, 0x58, 0xEC, 0xFE, 0xFE, 0x7E, 0x4E, 0x5D, 0x0B, 0x01, 0x2A, 0xF6, 0x05, 0x11, 0x07, 0x97, 0xA4, 0xB5, 0x1E, 0x87, 0x6B, 0x09, 0xE1, 0x51, 0x1F, 0x0B, 0xE0, 0x80, 0xC5, 0x07, 0x8D, 0xD1, 0xC5, 0x14, 0xCE, 0x12, 0xFB, 0x35, 0xDA, 0x5D, 0x3E, 0x8C, 0x0A, 0xA6, 0x16, 0x5B, 0x13, 0x36, 0xE5, 0x91, 0xAC, 0x5B, 0xC9, 0x2D, 0xF4, 0x53, 0x26, 0xFA, 0xEF, 0xC2, 0x45, 0x94, 0xD7, 0xDA, 0x1D, 0xBA, 0x39, 0xFA, 0x99, 0xA1, 0xE6, 0xCE, 0x49, 0x28, 0xFC, 0x44, 0x22, 0xED, 0x39, 0x2B, 0xFB, 0xD2, 0x53, 0xCE, 0x5C, 0x53, 0x4A, 0xA9, 0xAE, 0x7D, 0x72, 0xA0, 0x49, 0xB1, 0x63, 0x2A, 0x8A, 0x0C, 0x73, 0xDE, 0x98, 0xE3, 0x98, 0x36, 0x6D, 0xC6, 0x64, 0xDE, 0x24, 0x88, 0x93, 0x3F, 0x6B, 0xC5, 0xFD, 0xB2, 0xE9, 0x9D, 0x10, 0xFE, 0x15, 0xA7, 0x11, 0xA9, 0x92, 0x79, 0x98, 0x0D, 0xF5, 0xC4, 0x2C, 0x16, 0xC8, 0x2E, 0x1D, 0x36, 0x5F, 0x72, 0x6F, 0x5A, 0x06, 0x63, 0x4F, 0x71, 0xEA, 0x82, 0x96, 0x22, 0x75, 0xAD, 0x59, 0xD7, 0x3E, 0x53, 0xE5, 0xE4, 0x92, 0x1C, 0x65, 0x76, 0x72, 0xC3, 0xA2, 0xE2, 0xF0, 0xC6, 0x70, 0x11, 0x2B, 0x72, 0xF8, 0x6F, 0x43, 0x20, 0x6B, 0xBC, 0xAE, 0x2F, 0xE2, 0xDF, 0x4D, 0x04, 0x06, 0x8E, 0x59, 0xD6, 0xCA, 0x5F, 0x39, 0x05, 0xCC, 0xE0, 0xC2, 0x93, 0x81, 0x6F, 0xC0, 0xA5, 0x5A, 0xB1, 0xE6, 0xCB, 0x31, 0x5E, 0xB7, 0x42, 0xD4, 0xEB, 0xCE, 0x83, 0xE2, 0xAE, 0x46, 0x5F, 0xC5, 0x74, 0x31, 0x7D, 0x58, 0x47, 0xB7, 0x84, 0x4E, 0xBF, 0x7B}; #if CY_API_VERSION_AT_LEAST(3, 0) /* add for SM3 and SM4 */ smx_key_size_pairs_t cipherSM4TestList[] = { #if defined(SC_WITH_QAT20_UPSTREAM) #if !defined(QAT_LEGACY_ALGORITHMS) { CPA_CY_SYM_CIPHER_SM4_CBC, KEY_SIZE_128_IN_BYTES, 0, 0 }, { CPA_CY_SYM_CIPHER_SM4_CTR, KEY_SIZE_128_IN_BYTES, 0, 0 } #endif #else { CPA_CY_SYM_CIPHER_SM4_ECB, KEY_SIZE_128_IN_BYTES, 0, 0 }, { CPA_CY_SYM_CIPHER_SM4_CBC, KEY_SIZE_128_IN_BYTES, 0, 0 }, { CPA_CY_SYM_CIPHER_SM4_CTR, KEY_SIZE_128_IN_BYTES, 0, 0 } #endif }; smx_key_size_pairs_t algChainSM4SM3TestList[] = { #if defined(SC_WITH_QAT20_UPSTREAM) #if !defined(QAT_LEGACY_ALGORITHMS) { CPA_CY_SYM_CIPHER_SM4_CBC, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_SM3, SM3_DIGEST_LENGTH_IN_BYTES }, { CPA_CY_SYM_CIPHER_SM4_CTR, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_SM3, SM3_DIGEST_LENGTH_IN_BYTES } #endif #else { CPA_CY_SYM_CIPHER_SM4_ECB, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_SM3, SM3_DIGEST_LENGTH_IN_BYTES }, { CPA_CY_SYM_CIPHER_SM4_CBC, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_SM3, SM3_DIGEST_LENGTH_IN_BYTES }, { CPA_CY_SYM_CIPHER_SM4_CTR, KEY_SIZE_128_IN_BYTES, CPA_CY_SYM_HASH_SM3, SM3_DIGEST_LENGTH_IN_BYTES } #endif }; int cipherSM4TestList_count = sizeof(cipherSM4TestList) / (sizeof(smx_key_size_pairs_t)); int algChainSM4SM3TestList_count = sizeof(algChainSM4SM3TestList) / (sizeof(smx_key_size_pairs_t)); #endif Cpa32U getThroughput(Cpa64U numPackets, Cpa32U packetSize, perf_cycles_t cycles) { unsigned long long bytesSent = 0; unsigned long long time = cycles; unsigned long long rate = 0; /* declare frequency in kiloHertz*/ Cpa32U freq = sampleCodeGetCpuFreq(); bytesSent = packetSize; bytesSent = bytesSent * numPackets; /*get time in milli seconds by dividing numberOfClockCycles by frequency * in kilohertz ie: cycles/(cycles/millsec) = time (mSec) */ do_div(time, freq); /*check that the sample time was not to small*/ if (time == 0) { /*if the sample time is too small, then we don't have enough data * to calculate throughput, so we return 0 to the caller*/ return 0; } /*set rate to be bytesSent, once we perform the do_div rate changes from * bytes to bytes/milli second or kiloBytes/second*/ rate = bytesSent; /*rate in kBps*/ do_div(rate, time); /*check that the rate is high enough to convert to Megabits per second*/ if (rate == 0) { /*if the rate is too small to translate to Mbps then just return 0*/ return 0; } /* convert Kilobytes/second to Kilobits/second*/ rate = rate * NUM_BITS_IN_BYTE; /*then convert rate from Kilobits/second to Megabits/second*/ do_div(rate, KILOBITS_IN_MEGABITS); return (Cpa32U)rate; } Cpa32U getOpsPerSecond(Cpa64U responses, perf_cycles_t cycles) { unsigned long long time = cycles; unsigned long long freq = sampleCodeGetCpuFreq(); /*multiply responses by 1000 so that we don't loose precision * precision is lost if we convert millisec to seconds to calculate * ops per second ie 2238 ms becomes 2 seconds the decimal place is lost*/ unsigned long long opsPerSec = responses; opsPerSec = opsPerSec * MILLI_SECONDS_IN_SECOND; /*convert cycles into time(ms)*/ do_div(time, freq); if (time == 0) { PRINT_ERR("Sample time is too small to calculate OpsPerSecond\n"); return 0; } do_div(opsPerSec, time); return opsPerSec; } EXPORT_SYMBOL(getOpsPerSecond); static void accumulateAsymPerfData(Cpa32U numberOfThreads, perf_data_t *performanceStats[], perf_data_t *stats, Cpa64U *buffersProcessed, Cpa32U *responsesPerThread) { Cpa32U i = 0; /*accumulate the responses into one perf_data_t structure*/ for (i = 0; i < numberOfThreads; i++) { stats->responses += performanceStats[i]->responses; /*is the data was submitted in multiple buffers per list, then the * number of buffers processed is number of responses multiplied * by the numberOfBuffers*/ *buffersProcessed += performanceStats[i]->responses; stats->retries += performanceStats[i]->retries; stats->numOperations += performanceStats[i]->numOperations; if (iaCycleCount_g) { stats->offloadCycles += performanceStats[i]->offloadCycles; } *responsesPerThread = performanceStats[i]->responses; clearPerfStats(performanceStats[i]); } } CpaStatus printAsymStatsAndStopServices(thread_creation_data_t *data) { Cpa32U i = 0; Cpa32U j = 0; Cpa32U k = 0; Cpa32U responsesPerThread = 0; perf_cycles_t numOfCycles = 0; perf_data_t stats = {0}; perf_data_t *stats2; Cpa32U *perfDataDeviceOffsets; Cpa32U *threadCountPerDevice; perf_data_t **tempPerformanceStats; Cpa64U buffersProcessed = 0; Cpa32U opsPerSec = 0; Cpa32U devOpsperSec = 0; Cpa32U numberOfUnsupportedThreads = 0; Cpa32U totalThreadsRan = 0; /*stop all crypto instances, There is no other place we can stop CyServices * as all other function run in thread context and its not safe to call * stopCyServices in thread context, otherwise we could stop threads that * have requests in flight. This function is called by the framework * after all threads have completed*/ stopCyServices(); stats2 = qaeMemAlloc(sizeof(perf_data_t) * (packageIdCount_g + 1)); if (NULL == stats2) { PRINT_ERR("Unable to allocate memory for stats2\n"); return CPA_STATUS_FAIL; } perfDataDeviceOffsets = qaeMemAlloc(sizeof(Cpa32U) * (packageIdCount_g + 1)); if (NULL == perfDataDeviceOffsets) { qaeMemFree((void **)&stats2); PRINT_ERR("Unable to allocate memory for perfDataDeviceOffsets\n"); return CPA_STATUS_FAIL; } threadCountPerDevice = qaeMemAlloc(sizeof(Cpa32U) * (packageIdCount_g + 1)); if (NULL == threadCountPerDevice) { qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); PRINT_ERR("Unable to allocate memory for threadCountPerDevice\n"); return CPA_STATUS_FAIL; } tempPerformanceStats = qaeMemAlloc(sizeof(perf_data_t *) * data->numberOfThreads); if (NULL == tempPerformanceStats) { qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); qaeMemFree((void **)&threadCountPerDevice); PRINT_ERR("Error in allocating memory for tempPerformanceStats\n"); return CPA_STATUS_FAIL; } for (i = 0; i < data->numberOfThreads; i++) { if (CPA_STATUS_UNSUPPORTED == data->performanceStats[i]->threadReturnStatus) { numberOfUnsupportedThreads++; } else if (CPA_STATUS_FAIL == data->performanceStats[i]->threadReturnStatus) { qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); qaeMemFree((void **)&threadCountPerDevice); qaeMemFree((void **)&tempPerformanceStats); return CPA_STATUS_FAIL; } } totalThreadsRan = data->numberOfThreads - numberOfUnsupportedThreads; /* Block to re-group the data per device */ for (j = 0; j < (packageIdCount_g + 1); j++) { for (i = 0; i < data->numberOfThreads; i++) { if (data->performanceStats[i]->packageId == j) { tempPerformanceStats[k++] = data->performanceStats[i]; } } } for (i = 0; i < data->numberOfThreads; i++) { data->performanceStats[i] = tempPerformanceStats[i]; if (latency_enable) { /* accumulate latency for all devices */ stats.aveLatency += data->performanceStats[i]->aveLatency; if (data->performanceStats[i]->maxLatency > stats.maxLatency) { stats.maxLatency = data->performanceStats[i]->maxLatency; } if (data->performanceStats[i]->minLatency < stats.minLatency) { stats.minLatency = data->performanceStats[i]->minLatency; } else { if (stats.minLatency == 0) { stats.minLatency = data->performanceStats[i]->minLatency; } } } } memset(stats2, 0, sizeof(perf_data_t) * (packageIdCount_g + 1)); stats.averagePacketSizeInBytes = data->packetSize; getLongestCycleCount2(stats2, data->performanceStats, data->numberOfThreads, perfDataDeviceOffsets, threadCountPerDevice); for (i = 0; i < (packageIdCount_g + 1); i++) { accumulateAsymPerfData( threadCountPerDevice[i], &(data->performanceStats[perfDataDeviceOffsets[i]]), &stats2[i], &buffersProcessed, &responsesPerThread); numOfCycles = (stats2[i].endCyclesTimestamp - stats2[i].startCyclesTimestamp); if (!signOfLife) { devOpsperSec = getOpsPerSecond(buffersProcessed, numOfCycles); } buffersProcessed = 0; opsPerSec += devOpsperSec; stats.numOperations += stats2[i].numOperations; stats.responses += stats2[i].responses; stats.retries += stats2[i].retries; if (iaCycleCount_g) { stats.offloadCycles += stats2[i].offloadCycles; } } PRINT("Number of Threads %u\n", data->numberOfThreads); if (numberOfUnsupportedThreads) { PRINT("Unsupported Threads %u\n", numberOfUnsupportedThreads); } PRINT("Total Threads ran %u\n", totalThreadsRan); PRINT("Total Submissions %llu\n", (unsigned long long)stats.numOperations); PRINT("Total Responses %llu\n", (unsigned long long)stats.responses); PRINT("Total Retries %llu\n", (unsigned long long)stats.retries); if (!signOfLife) { PRINT("CPU Frequency(kHz) %u\n", sampleCodeGetCpuFreq()); PRINT("Operations per second %8u\n", opsPerSec); if (iaCycleCount_g) { do_div(stats.offloadCycles, data->numberOfThreads); PRINT("Avg Offload Cycles %llu\n", stats.offloadCycles); } if (latency_enable) { perf_cycles_t statsLatency = 0; perf_cycles_t cpuFreqKHz = sampleCodeGetCpuFreq(); /* Display how long it took on average to process a buffer in uSecs * Also include min/max to show variance */ if (cpuFreqKHz != 0) { if (data->numberOfThreads != 0) { do_div(stats.aveLatency, data->numberOfThreads); statsLatency = 1000 * stats.minLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Min. Latency (uSecs) %llu\n", statsLatency); statsLatency = 1000 * stats.aveLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Ave. Latency (uSecs) %llu\n", statsLatency); statsLatency = 1000 * stats.maxLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Max. Latency (uSecs) %llu\n", statsLatency); } } } } qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); qaeMemFree((void **)&threadCountPerDevice); qaeMemFree((void **)&tempPerformanceStats); return CPA_STATUS_SUCCESS; } /***************************************************************************** * * @description * Poll the number of crypto operations * ***************************************************************************/ CpaStatus cyPollNumOperationsTimeout(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations, Cpa64U timeout) { CpaStatus status = CPA_STATUS_FAIL; perf_cycles_t startCycles = 0, totalCycles = 0; Cpa32U freq = sampleCodeGetCpuFreq(); startCycles = sampleCodeTimestamp(); while (pPerfData->responses != numOperations) { coo_poll_trad_cy(pPerfData, instanceHandle, &status); if (CPA_STATUS_FAIL == status) { PRINT_ERR("Error polling instance\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_RETRY == status) { AVOID_SOFTLOCKUP; } totalCycles = (sampleCodeTimestamp() - startCycles); if (totalCycles > 0) { do_div(totalCycles, freq); } if (totalCycles > timeout) { PRINT_ERR("Timeout on polling remaining Operations\n"); PRINT("Responses expected = %llu, received = %llu\n", (unsigned long long)numOperations, (unsigned long long)pPerfData->responses); return CPA_STATUS_FAIL; } } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(cyPollNumOperationsTimeout); /***************************************************************************** * * @description * Poll the number of crypto operations * ***************************************************************************/ CpaStatus cyPollNumOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations) { return cyPollNumOperationsTimeout( pPerfData, instanceHandle, numOperations, SAMPLE_CODE_WAIT_DEFAULT); } EXPORT_SYMBOL(cyPollNumOperations); CpaStatus setCyPollWaitFn(Cpa32U poll_type, Cpa32U sleep_time) { poll_type_g = poll_type; sleep_time_g = sleep_time; return CPA_STATUS_SUCCESS; } CpaStatus setCyPollInterval(Cpa32U interval) { cyPollingThreadsInterval_g = interval; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setCyPollInterval); static void sampleCodePoll(CpaInstanceHandle instanceHandle_in) { CpaStatus status = CPA_STATUS_FAIL; while (cy_service_started_g == CPA_TRUE) { /*poll for 0 means process all packets on the ET ring */ status = icp_sal_CyPollInstance(instanceHandle_in, 0); if (CPA_STATUS_SUCCESS == status || CPA_STATUS_RETRY == status) { /* do nothing */ } else { PRINT_ERR("WARNING icp_sal_CyPollInstance returned status %d\n", status); } switch (poll_type_g) { case POLL_AND_SLEEP: sampleCodeSleepMilliSec(sleep_time_g); break; default: AVOID_SOFTLOCKUP_POLL; } } sampleCodeThreadExit(); } /*start crypto acceleration service if its not already started*/ CpaStatus startCyServices(void) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; Cpa32U nProcessorsOnline = 0; /*if the service started flag is false*/ if (cy_service_started_g == CPA_FALSE) { /*start all crypto instances*/ status = cpaCyGetNumInstances(&numInstances_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetNumInstances failed with status: %d\n", status); return status; } if (numInstances_g > 0) { cyInstances_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances_g); if (NULL == cyInstances_g) { PRINT_ERR("Failed to allocate memory for instances\n"); return CPA_STATUS_FAIL; } status = cpaCyGetInstances(numInstances_g, cyInstances_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetInstances failed with status: %d\n", status); qaeMemFree((void **)&cyInstances_g); return status; } /*start all instances*/ for (i = 0; i < numInstances_g; i++) { status = cpaCySetAddressTranslation( cyInstances_g[i], (CpaVirtualToPhysical)qaeVirtToPhysNUMA); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error setting memory config for instance %d\n", i); qaeMemFree((void **)&cyInstances_g); return CPA_STATUS_FAIL; } status = cpaCyStartInstance(cyInstances_g[i]); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error starting crypto instance %d\n", i); /*attempt to stop any started service, we don't check status * as some instances may not have been started and this * might return fail*/ stopCyServices(); qaeMemFree((void **)&cyInstances_g); return CPA_STATUS_FAIL; } } } else { PRINT("There are no crypto instances available\n"); return CPA_STATUS_FAIL; } } /*set the started flag to true*/ cy_service_started_g = CPA_TRUE; /*determine number of cores on system and limit the number of cores to be *used to be the smaller of the numberOf Instances or the number of cores*/ nProcessorsOnline = sampleCodeGetNumberOfCpus(); if (nProcessorsOnline > numInstances_g) { setCoreLimit(numInstances_g); } /*status should be success if we get to here*/ return status; } /*stop all crypto services*/ CpaStatus stopCyServices(void) { Cpa32U i = 0; CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus returnStatus = CPA_STATUS_SUCCESS; /*stop only if the services are in a started state*/ if (cy_service_started_g == CPA_TRUE) { /*stop all instances*/ for (i = 0; i < numInstances_g; i++) { status = cpaCyStopInstance(cyInstances_g[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not stop instance: %d\n", i); /*if we fail to stop a service then something odd has happened * internally and its probably best to reboot*/ PRINT_ERR("Internal error has occur which probably can only "); PRINT(" be fixed by a reboot\n"); returnStatus = CPA_STATUS_FAIL; } } /*set the service started flag to false*/ cy_service_started_g = CPA_FALSE; } /*free the polling threads*/ if (cy_polling_started_g == CPA_TRUE) { /* set polling flag to false */ cy_polling_started_g = CPA_FALSE; /* Wait for all threads_g to complete */ for (i = 0; i < numPolledInstances_g; i++) { sampleCodeThreadJoin(&pollingThread_g[i]); } if (0 < numPolledInstances_g) { qaeMemFree((void **)&pollingThread_g); numPolledInstances_g = 0; } } if (cyInstances_g != NULL) { qaeMemFree((void **)&cyInstances_g); cyInstances_g = NULL; } #if CY_API_VERSION_AT_LEAST(3, 0) /*free the polling threads*/ if (asym_polling_started_g == CPA_TRUE) { /* set polling flag to false */ asym_polling_started_g = CPA_FALSE; /* Wait for all threads_g to complete */ for (i = 0; i < numAsymPolledInstances_g; i++) { sampleCodeThreadJoin(&asymPollingThread_g[i]); } if (0 < numAsymPolledInstances_g) { qaeMemFree((void **)&asymPollingThread_g); numAsymPolledInstances_g = 0; } } if (asymInstances_g != NULL) { qaeMemFree((void **)&asymInstances_g); asymInstances_g = NULL; } #endif return returnStatus; } CpaStatus sampleCreateBuffers(CpaInstanceHandle instanceHandle, Cpa32U packetSizeInBytes[], CpaFlatBuffer *pFlatBuffArray[], CpaBufferList *pBuffListArray[], symmetric_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U bufferMetaSize = 0; Cpa32U createBufferCount = 0; Cpa32U createListCount = 0; Cpa8U *pBufferMeta = NULL; Cpa32U node = 0; Cpa32U numBufferLists = setup->numBuffLists; Cpa32U numBuffers = 0; Cpa32U bufferSizeInBytes = 0; CpaFlatBuffer *pTempFlatBuffArray = NULL; Cpa32U lastBufferInListSize = 0; if (NULL == pFlatBuffArray) { PRINT_ERR("pFlatBuffArray is NULL\n"); return CPA_STATUS_FAIL; } if (NULL == pBuffListArray) { PRINT_ERR("pBuffListArray is NULL\n"); return CPA_STATUS_FAIL; } if (NULL == packetSizeInBytes) { PRINT_ERR("packetSizeInBytes is NULL\n"); return CPA_STATUS_FAIL; } status = sampleCodeCyGetNode(instanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to get node for instance\n"); return CPA_STATUS_FAIL; } /* Calculate number of flatbuffers in one list */ if (0 == setup->flatBufferSizeInBytes) { numBuffers = NUM_UNCHAINED_BUFFERS; } else { numBuffers = (packetSizeInBytes[0] - setup->setupData.hashSetupData.digestResultLenInBytes) / setup->flatBufferSizeInBytes; if ((setup->enableRoundOffPkt == CPA_TRUE) && ((lastBufferInListSize = ((packetSizeInBytes[0] - setup->setupData.hashSetupData.digestResultLenInBytes) % setup->flatBufferSizeInBytes)) != 0)) { numBuffers++; } } /* * calculate memory size which is required for pPrivateMetaData * member of CpaBufferList */ status = cpaCyBufferListGetMetaSize(instanceHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyBufferListGetMetaSize Failed with status: %d\n", status); return status; } /*allocate memory for bufferLists, FlatBuffers and Data*/ for (createListCount = 0; createListCount < numBufferLists; createListCount++) { /* Allocate memory for temp flat buffer Array*/ pTempFlatBuffArray = qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == pTempFlatBuffArray) { PRINT_ERR("Could not allocate pFlatBuffArray[%u]\n", createListCount); sampleFreeBuffers(pFlatBuffArray, pBuffListArray, setup); return CPA_STATUS_FAIL; } pFlatBuffArray[createListCount] = pTempFlatBuffArray; /* Allocate pData memory for each flat buffer */ for (createBufferCount = 0; createBufferCount < numBuffers; createBufferCount++) { /* Decide flat buffers Size: if setup->flatBufferSizeInBytes is 0 * for the IMIX case, * there is only single buffer in List, and bufferSizeInBytes is * equal to packetSizeInBytes */ if (0 == setup->flatBufferSizeInBytes) { /*bufferSize includes space for the digest in the case of hash * or alg chain*/ bufferSizeInBytes = packetSizeInBytes[createListCount]; } /*while not the last buffer, allocate the normal flat buffer size*/ else if (createBufferCount != numBuffers - 1) { bufferSizeInBytes = setup->flatBufferSizeInBytes; } /*else allocate flat buffer + space for digest*/ else { if ((setup->enableRoundOffPkt == CPA_TRUE) && (lastBufferInListSize != 0)) { bufferSizeInBytes = lastBufferInListSize + setup->setupData.hashSetupData.digestResultLenInBytes; } else { bufferSizeInBytes = setup->flatBufferSizeInBytes + setup->setupData.hashSetupData.digestResultLenInBytes; } } /* Allocate aligned memory for specified packet size on the node * that the thread is running on*/ pTempFlatBuffArray[createBufferCount].pData = qaeMemAllocNUMA(bufferSizeInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pTempFlatBuffArray[createBufferCount].pData) { PRINT_ERR( "Failed to allocate flatBuffer[%u].pData:(%u) memory\n", createBufferCount, bufferSizeInBytes); sampleFreeBuffers(pFlatBuffArray, pBuffListArray, setup); return CPA_STATUS_FAIL; } /*initialize dataLenInBytes for each flat buffer*/ pTempFlatBuffArray[createBufferCount].dataLenInBytes = bufferSizeInBytes; /*populate the data source with random data*/ generateRandomData(pTempFlatBuffArray[createBufferCount].pData, bufferSizeInBytes); } /*allocate memory for bufferLists, FlatBuffers and Data*/ /* Allocate memory for pPrivateMetaData */ pBufferMeta = qaeMemAllocNUMA(bufferMetaSize, node, BYTE_ALIGNMENT_64); if (NULL == pBufferMeta) { PRINT_ERR("Failed to allocate pBufferMeta memory\n"); sampleFreeBuffers(pFlatBuffArray, pBuffListArray, setup); return CPA_STATUS_FAIL; } /* Allocate memory for buffer list structure */ pBuffListArray[createListCount] = qaeMemAllocNUMA(sizeof(CpaBufferList), node, BYTE_ALIGNMENT_64); if (NULL == pBuffListArray[createListCount]) { PRINT_ERR("Failed to allocate bufferlist memory\n"); sampleFreeBuffers(pFlatBuffArray, pBuffListArray, setup); qaeMemFreeNUMA((void **)&pBufferMeta); return CPA_STATUS_FAIL; } /* * Fill in elements of buffer list struct. * For this scenario- each buffer list only * contains one buffer */ pBuffListArray[createListCount]->numBuffers = numBuffers; pBuffListArray[createListCount]->pPrivateMetaData = pBufferMeta; /* set up the pBuffers pointer */ pBuffListArray[createListCount]->pBuffers = pTempFlatBuffArray; } /* end of pre allocated buffer for loop */ /* * Return CPA_STATUS_SUCCESS if all buffers have * been correctly allocated */ return CPA_STATUS_SUCCESS; } void sampleFreeBuffers(CpaFlatBuffer *srcBuffPtrArray[], CpaBufferList *srcBuffListArray[], symmetric_test_params_t *setup) { Cpa32U freeMemListCount = 0; Cpa32U freeMemCount = 0; CpaFlatBuffer *pTempFlatBuffArray = NULL; for (freeMemListCount = 0; freeMemListCount < setup->numBuffLists; freeMemListCount++) { /* Check if bufferListArray is NULL */ if (NULL == srcBuffListArray) { break; } /* Check if bufferList is NULL */ if (NULL != srcBuffListArray[freeMemListCount]) { /* Free pPrivateMetaData if it's not NULL */ if (NULL != srcBuffListArray[freeMemListCount]->pPrivateMetaData) { qaeMemFreeNUMA( &srcBuffListArray[freeMemListCount]->pPrivateMetaData); } if (NULL == srcBuffPtrArray) { break; } pTempFlatBuffArray = srcBuffPtrArray[freeMemListCount]; /* * Loop through and free all buffers that have been * pre-allocated. */ for (freeMemCount = 0; freeMemCount < srcBuffListArray[freeMemListCount]->numBuffers; freeMemCount++) { if (NULL != pTempFlatBuffArray) { if (NULL != pTempFlatBuffArray[freeMemCount].pData) { qaeMemFreeNUMA( (void **)&pTempFlatBuffArray[freeMemCount].pData); } } } qaeMemFreeNUMA((void **)&srcBuffPtrArray[freeMemListCount]); qaeMemFreeNUMA((void **)&srcBuffListArray[freeMemListCount]); } } } /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * function to free buffer list for symmetric crypto sample code ******************************************************************************/ void dpSampleFreeBuffers(CpaBufferList **srcBuffListArray, CpaPhysBufferList **srcPhyBuffListArray, Cpa32U numBuffLists, Cpa32U numBuffers) { Cpa32U freeMemListCount = 0; Cpa32U freeMemCount = 0; CpaFlatBuffer *pTempFlatBuffArray = NULL; for (freeMemListCount = 0; freeMemListCount < numBuffLists; freeMemListCount++) { /* Check if bufferListArray is NULL */ if (NULL != srcBuffListArray) { /* Check if bufferList is NULL */ if (NULL != srcBuffListArray[freeMemListCount]) { /* Free pPrivateMetaData if it's not NULL */ if (NULL != srcBuffListArray[freeMemListCount]->pPrivateMetaData) { qaeMemFreeNUMA( &srcBuffListArray[freeMemListCount]->pPrivateMetaData); } pTempFlatBuffArray = srcBuffListArray[freeMemListCount]->pBuffers; /* * Loop through and free all buffers that have been * pre-allocated. */ for (freeMemCount = 0; freeMemCount < numBuffers; freeMemCount++) { if (NULL != pTempFlatBuffArray) { if (NULL != pTempFlatBuffArray[freeMemCount].pData) { qaeMemFreeNUMA( (void **)&pTempFlatBuffArray[freeMemCount] .pData); } } } if (NULL != pTempFlatBuffArray) { qaeMemFreeNUMA((void **)&pTempFlatBuffArray); } qaeMemFreeNUMA((void **)&srcBuffListArray[freeMemListCount]); } } if (NULL != srcPhyBuffListArray) { if (NULL != srcPhyBuffListArray[freeMemListCount]) { qaeMemFreeNUMA((void **)&srcPhyBuffListArray[freeMemListCount]); } } } } /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * function to create buffer list for symmetric crypto sample code ******************************************************************************/ CpaStatus dpSampleCreateBuffers(CpaInstanceHandle instanceHandle, Cpa32U packetSizeInBytesArray[], CpaBufferList *pBuffListArray[], CpaPhysBufferList *pPhyBuffListArray[], symmetric_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U bufferMetaSize = 0; Cpa32U createBufferCount = 0; Cpa32U createListCount = 0; Cpa8U *pBufferMeta = NULL; Cpa32U node = 0; CpaFlatBuffer *pFlatBuffArray = NULL; Cpa32U bufferSizeInBytes = 0; Cpa32U numBufferLists = setup->numBuffLists; Cpa32U numBuffers = 0; Cpa32U lastBufferInListSize = 0; if (NULL == pBuffListArray) { PRINT_ERR("pBuffListArray is NULL\n"); return CPA_STATUS_FAIL; } if (NULL == packetSizeInBytesArray) { PRINT_ERR("packetSizeInBytesArray is NULL\n"); return CPA_STATUS_FAIL; } status = sampleCodeCyGetNode(instanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to get node for instance\n"); return CPA_STATUS_FAIL; } if (setup->isTLS) { /* * For TLS, single buffer is used for getting better performance. * The first 13 bytes contains the header and the remaining * buffer contains the payload+mac+padding. */ numBuffers = NUM_UNCHAINED_BUFFERS; } else { /* Calculate number of flatbuffers in one list */ if (0 == setup->flatBufferSizeInBytes) { numBuffers = NUM_UNCHAINED_BUFFERS; } /* if packet size is not align with block size of cipher, * we need to some padding data into the buffers. */ else { numBuffers = (packetSizeInBytesArray[0] - setup->setupData.hashSetupData.digestResultLenInBytes) / setup->flatBufferSizeInBytes; lastBufferInListSize = (packetSizeInBytesArray[0] - setup->setupData.hashSetupData.digestResultLenInBytes) % setup->flatBufferSizeInBytes; if (setup->enableRoundOffPkt == CPA_TRUE && lastBufferInListSize != 0) { numBuffers++; } } } /* * calculate memory size which is required for pPrivateMetaData * member of CpaBufferList */ status = cpaCyBufferListGetMetaSize(instanceHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyBufferListGetMetaSize Failed with status: %d\n", status); return status; } for (createListCount = 0; createListCount < numBufferLists; createListCount++) { /*allocate memory for bufferLists and Data*/ /* Allocate memory for temp flat buffer Array*/ pFlatBuffArray = qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == pFlatBuffArray) { PRINT_ERR("Could not allocate pFlatBuffArray[%u]\n", createListCount); dpSampleFreeBuffers( pBuffListArray, pPhyBuffListArray, createListCount, numBuffers); return CPA_STATUS_FAIL; } /* Allocate memory for pPrivateMetaData */ pBufferMeta = qaeMemAllocNUMA(bufferMetaSize, node, BYTE_ALIGNMENT_64); if (NULL == pBufferMeta) { PRINT_ERR("Failed to allocate pBufferMeta memory\n"); dpSampleFreeBuffers( pBuffListArray, pPhyBuffListArray, createListCount, numBuffers); return CPA_STATUS_FAIL; } /* Allocate memory for buffer list structure */ pBuffListArray[createListCount] = qaeMemAllocNUMA(sizeof(CpaBufferList), node, BYTE_ALIGNMENT_64); if (NULL == pBuffListArray[createListCount]) { PRINT_ERR("Failed to allocate bufferlist memory\n"); dpSampleFreeBuffers( pBuffListArray, pPhyBuffListArray, createListCount, numBuffers); qaeMemFreeNUMA((void **)&pBufferMeta); return CPA_STATUS_FAIL; } /* * Fill in elements of buffer list struct. * For this scenario- each buffer list only * contains one buffer */ pBuffListArray[createListCount]->numBuffers = numBuffers; pBuffListArray[createListCount]->pPrivateMetaData = pBufferMeta; /* set up the pBuffers pointer */ pBuffListArray[createListCount]->pBuffers = pFlatBuffArray; /* Allocate memory for physical flat buffer list structure * total size of one Buffer list should be equal to size * sizeof(CpaPhysBufferList) + sizeof(CpaPhysFlatBuffer)* numBuffers */ pPhyBuffListArray[createListCount] = qaeMemAllocNUMA( sizeof(CpaPhysBufferList) + sizeof(CpaPhysFlatBuffer) * numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == pPhyBuffListArray[createListCount]) { PRINT_ERR("Failed to allocate bufferlist memory\n"); dpSampleFreeBuffers( pBuffListArray, pPhyBuffListArray, createListCount, numBuffers); return CPA_STATUS_FAIL; } pPhyBuffListArray[createListCount]->numBuffers = pBuffListArray[createListCount]->numBuffers; /* Allocate pData memory for each flat buffer */ for (createBufferCount = 0; createBufferCount < numBuffers; createBufferCount++) { /* Decide flat buffers Size: if setup->flatBufferSizeInBytes is 0, * there is only single buffer in List, and bufferSizeInBytes is * equal to packetSizeInBytes */ if (setup->isTLS) { /* For TLS, single flat buffer is used and the * flatBufferSizeInBytes is filled in the setup API. * The flatBufferSizeInBytes includes Header + * Packet + Mac. */ if (0 == setup->flatBufferSizeInBytes) { bufferSizeInBytes = packetSizeInBytesArray[createListCount]; } else { bufferSizeInBytes = setup->flatBufferSizeInBytes; } } else { if (0 == setup->flatBufferSizeInBytes) { bufferSizeInBytes = packetSizeInBytesArray[createListCount]; } else if (createBufferCount != numBuffers - 1) { bufferSizeInBytes = setup->flatBufferSizeInBytes; } /*else allocate flat buffer + space for digest*/ else { if ((setup->enableRoundOffPkt == CPA_TRUE) && (lastBufferInListSize != 0)) { bufferSizeInBytes = lastBufferInListSize + setup->setupData.hashSetupData .digestResultLenInBytes; } else { bufferSizeInBytes = setup->flatBufferSizeInBytes + setup->setupData.hashSetupData .digestResultLenInBytes; } } } /* Allocate aligned memory for specified packet size on the node * that the thread is running on*/ pFlatBuffArray[createBufferCount].pData = qaeMemAllocNUMA(bufferSizeInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pFlatBuffArray[createBufferCount].pData) { PRINT_ERR( "Failed to allocate flatBuffer[%u].pData:(%u) memory\n", createBufferCount, bufferSizeInBytes); dpSampleFreeBuffers(pBuffListArray, pPhyBuffListArray, createListCount, numBuffers); return CPA_STATUS_FAIL; } /*initialize dataLenInBytes for each flat buffer*/ pFlatBuffArray[createBufferCount].dataLenInBytes = bufferSizeInBytes; /*populate the data source with random data*/ generateRandomData(pFlatBuffArray[createBufferCount].pData, bufferSizeInBytes); pPhyBuffListArray[createListCount] ->flatBuffers[createBufferCount] .bufferPhysAddr = (CpaPhysicalAddr)virtAddrToDevAddr( (SAMPLE_CODE_UINT *)(uintptr_t)pFlatBuffArray[createBufferCount] .pData, instanceHandle, CPA_ACC_SVC_TYPE_CRYPTO); pPhyBuffListArray[createListCount] ->flatBuffers[createBufferCount] .dataLenInBytes = pFlatBuffArray[createBufferCount].dataLenInBytes; } } /* end of pre allocated buffer for loop */ /* * Return CPA_STATUS_SUCCESS if all buffers have * been correctly allocated */ return CPA_STATUS_SUCCESS; } void setCpaFlatBufferMSB(CpaFlatBuffer *buf) { buf->pData[0] |= MSB_SETTING; } EXPORT_SYMBOL(setCpaFlatBufferMSB); /*Function assumes each number is the same length in bytes*/ CpaBoolean isFbALessThanFbB(CpaFlatBuffer *pFbA, CpaFlatBuffer *pFbB) { Cpa32U i = 0; for (i = 0; i < pFbA->dataLenInBytes; i++) { if (pFbA->pData[i] < pFbB->pData[i]) { return CPA_TRUE; } else if (pFbB->pData[i] < pFbA->pData[i]) { return CPA_TRUE; } /*continue if equal*/ } /*buffers contain the same number*/ return CPA_FALSE; } /*Function assumes each number is the same length in bytes*/ static CpaFlatBuffer *findSmallestNumber(CpaFlatBuffer *numbers, Cpa32U numNumbers) { CpaFlatBuffer *result = numbers; Cpa32U i = 0; for (i = 0; i < numNumbers; i++) { if (CPA_TRUE == isFbALessThanFbB(result, &numbers[i])) { result = &numbers[i]; } } return result; } void makeParam1SmallerThanParam2(Cpa8U *param1, Cpa8U *param2, Cpa32U len, CpaBoolean msbSettingRequired) { Cpa32U i = 0; int startLen = 0; if (msbSettingRequired == CPA_TRUE) { /*set startLen = 1 so that next for loop starts * at 1 rather than 0, we handle element 0 here*/ startLen = 1; /*Ignoring MSB, if param2 is less then param1, and param2 is not 0, * then make param1 to be smaller than param2, and we are done*/ if (((param2[0] & (~MSB_SETTING)) <= (param1[0] & (~MSB_SETTING))) && (param2[0] & (~MSB_SETTING)) != 0) { param1[0] = param2[0] - 1; return; } /*Ignoring MSB, if param2 is 0 then param1 needs to be zero with MSB * set and we check the next index*/ else if ((param2[0] & (~MSB_SETTING)) == 0) { param1[i] = MSB_SETTING; } /* else Param1 is smaller than param2 so set i = len to skip next for * loop*/ else { return; } } for (i = startLen; i < len; i++) { /*if param2 is less then param1, and param2 is not 0, then make param1 * to be smaller than param2, and we are done*/ if ((param2[i] <= param1[i]) && param2[i] != 0) { param1[i] = param2[i] - 1; break; } /*if param2 is 0 then param1 needs to be zero and we check the next * index*/ else if (param2[i] == 0) { param1[i] = 0; } /*Param1 is smaller than param2 so we break*/ else { break; } } } void conformMillerRabinData(CpaFlatBuffer *pMR, CpaFlatBuffer *pSmallestPC, Cpa32U rounds) { Cpa32S difference = 0; Cpa8U mrLength = 0; Cpa32U i = 0; /* Get the length of the Miller Rabin Data */ mrLength = pMR->dataLenInBytes / rounds; /* Get the difference in buffer length of the Miller Rabin round and the * smallest Prime candidate */ difference = mrLength - pSmallestPC->dataLenInBytes; /* As there's a limit on the smallest buffer size used to contain the Miller * Rabin Data(MAX(64,required_buffer_size)), we still must satisfy the * conditions that Miller Rabin data is >1 and less than Prime -1. * If the Miller Rabin buffer length is greater than the smallest Prime * Candidate buffer length, we need to zero the most significant bytes of * the difference and then ensure that the actual data length is the same. */ if (difference > 0) { for (i = 0; i < rounds; i++) { memset(pMR->pData + (i * mrLength), 0, difference); /* Ensure that Miller Rabin data is less than Prime -1 */ makeParam1SmallerThanParam2(pMR->pData + (i * mrLength) + difference, pSmallestPC->pData, pSmallestPC->dataLenInBytes, CPA_FALSE); } } else { for (i = 0; i < rounds; i++) { makeParam1SmallerThanParam2(pMR->pData + (i * pSmallestPC->dataLenInBytes), pSmallestPC->pData, pSmallestPC->dataLenInBytes, CPA_FALSE); } } } /*assumption is that primeCandidate is an odd number*/ static void incrementPrimeCandidate(CpaFlatBuffer *primeCandidate) { Cpa32S i = 0; /*increment by 2 to keep the primeCandidate odd*/ if (primeCandidate->pData[primeCandidate->dataLenInBytes - 1] != 0xFF) { primeCandidate->pData[primeCandidate->dataLenInBytes - 1] += INC_BY_TWO; /*roll over did not occur we can exit*/ return; } primeCandidate->pData[primeCandidate->dataLenInBytes - 1] = 1; /*other wise roll over occurred and we need to increment the high order * bytes*/ for (i = primeCandidate->dataLenInBytes - SECOND_LAST_BYTE; i >= 0; i--) { /*if the byte is not 0xff then roll over won't occur, and we * can increment and exit*/ if (primeCandidate->pData[i] != 0xFF) { /*we can increment high order bytes by 1 because it does not * effect odd/even*/ primeCandidate->pData[i] += 1; break; } else { primeCandidate->pData[i] = 0; } } } static void primeCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean testPassed) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; if (CPA_STATUS_SUCCESS != status) { PRINT("status not successful\n"); } if (NULL == pOpData) { PRINT("pOpData is NULL\n"); } /*check perf_data pointer is valid*/ if (pPerfData == NULL) { PRINT_ERR("Invalid data in CallbackTag\n"); return; } /* response has been received */ pPerfData->responses++; /*if we have received the pre-set numOperations, then get the clock cycle * as a timestamp and post the Semaphore to release parent thread*/ if (testPassed == CPA_TRUE) { /*record the index of the prime candidate where the primeCandidate * passed the primeTest, averagePacketSize in bytes * is not the most logical variable to use, we are reusing the * averagePacketSizeInBytes member for a completely different purpose * In this case we want to know how many requests it took to find a * prime number so that we can be sure we have set the * NUM_PRIME_GENERATION_ATTEMPTS so that we find a prime 99.9% of the * time*/ pPerfData->averagePacketSizeInBytes = pPerfData->responses; } if (pPerfData->numOperations == pPerfData->responses) { /*let calling thread know that we are done*/ sampleCodeSemaphorePost(&pPerfData->comp); } } static void generatePrimeCandidates(CpaFlatBuffer *primeCandidate, Cpa32U numCandiates) { Cpa32U i = 0; /*generate a random number to test for prime*/ generateRandomData(primeCandidate[0].pData, primeCandidate[0].dataLenInBytes); /*make sure MSB is set*/ setCpaFlatBufferMSB(&primeCandidate[0]); /*at the very least prime number candidate should be odd, so we perform * OR bitwise operation to make sure value is odd*/ primeCandidate[0].pData[primeCandidate[0].dataLenInBytes - 1] |= 1; /*create set of primeCandidates starting with an odd number and * each subsequent candidate is incremented by 2*/ for (i = 1; i < numCandiates; i++) { memcpy(primeCandidate[i].pData, primeCandidate[i - 1].pData, primeCandidate[i - 1].dataLenInBytes); incrementPrimeCandidate(&primeCandidate[i]); } } /***************************************************************************** * frees any memory allocated in the generatePrime function *****************************************************************************/ #define FREE_GENPRIME_MEM() \ do \ { \ Cpa32U j = 0; \ qaeMemFreeNUMA((void **)&pPrimeTestOpData); \ qaeMemFreeNUMA((void **)&pMillerRabinData); \ for (j = 0; j < NUM_PRIME_GENERATION_ATTEMPTS; j++) \ { \ qaeMemFreeNUMA((void **)&primeCandidates[j].pData); \ } \ qaeMemFreeNUMA((void **)&primeCandidates); \ } while (0) CpaStatus generatePrime(CpaFlatBuffer *primeCandidate, CpaInstanceHandle cyInstanceHandle, asym_test_params_t *setup) { Cpa32U i = 0; Cpa32U attempt = 0; CpaStatus status = CPA_STATUS_SUCCESS; /** Default is false (meaning the number is not a prime), except if the * test explicitly says it is probably a prime */ CpaBoolean testPassed = CPA_FALSE; perf_data_t primePerfData = {0}; /** Structure containing the operational data */ CpaCyPrimeTestOpData *pPrimeTestOpData = NULL; CpaFlatBuffer *primeCandidates = NULL; /** Random numbers for Miller-Rabin */ CpaFlatBuffer pMR = {0}; CpaFlatBuffer *smallestPC = NULL; Cpa8U *pMillerRabinData = NULL; Cpa8U *pMillerRabinRound[NB_MR_ROUNDS] = {0}; Cpa32U millerRabinDataLen = 0; Cpa32U node = 0; #ifdef POLL_INLINE CpaInstanceInfo2 *instanceInfo2 = NULL; CpaBoolean isPolled = CPA_FALSE; #endif millerRabinDataLen = primeCandidate->dataLenInBytes; /* The QA API has a a limit on the minimum size( 64 bytes) of the buffer * used to contain the Miller Rabin Round data. */ MR_PRIME_LEN(millerRabinDataLen); #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } } isPolled = instanceInfo2->isPolled; qaeMemFree((void **)&instanceInfo2); #endif status = sampleCodeCyGetNode(cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return CPA_STATUS_FAIL; } primeCandidates = qaeMemAllocNUMA(sizeof(CpaFlatBuffer) * NUM_PRIME_GENERATION_ATTEMPTS, node, BYTE_ALIGNMENT_64); if (NULL == primeCandidates) { PRINT_ERR("primeCandidates is NULL\n"); return CPA_STATUS_FAIL; } pPrimeTestOpData = qaeMemAllocNUMA(sizeof(CpaCyPrimeTestOpData) * NUM_PRIME_GENERATION_ATTEMPTS, node, BYTE_ALIGNMENT_64); if (NULL == pPrimeTestOpData) { PRINT_ERR("pPrimeTestOpData is NULL\n"); FREE_GENPRIME_MEM(); return CPA_STATUS_FAIL; } for (i = 0; i < NUM_PRIME_GENERATION_ATTEMPTS; i++) { status = bufferDataMemAlloc(cyInstanceHandle, &primeCandidates[i], primeCandidate->dataLenInBytes, NULL, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate buffer\n"); FREE_GENPRIME_MEM(); return CPA_STATUS_FAIL; } } /*generate random numbers for miller rabin rounds*/ pMillerRabinData = qaeMemAllocNUMA( millerRabinDataLen * NB_MR_ROUNDS, node, BYTE_ALIGNMENT_64); if (NULL == pMillerRabinData) { PRINT_ERR("Could not allocate memory for pMillerRabinData\n"); FREE_GENPRIME_MEM(); return CPA_STATUS_FAIL; } generateRandomData(pMillerRabinData, millerRabinDataLen * NB_MR_ROUNDS); /*set pointer to each miller rabin rounds number*/ for (i = 0; i < NB_MR_ROUNDS; i++) { Cpa32U byteCheck = millerRabinDataLen - 1; pMillerRabinRound[i] = &pMillerRabinData[i * millerRabinDataLen]; /*make sure the number is greater than 1 (quick check)*/ if (1 >= pMillerRabinRound[i][byteCheck]) { generateRandomData(&(pMillerRabinRound[i][byteCheck]), 1); /*In case of failure of the random number generator!*/ if (1 >= pMillerRabinRound[i][byteCheck]) { pMillerRabinRound[i][byteCheck] += INC_BY_TWO; } } } pMR.pData = pMillerRabinData; pMR.dataLenInBytes = millerRabinDataLen * NB_MR_ROUNDS; if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate pMR pData\n"); FREE_GENPRIME_MEM(); return CPA_STATUS_FAIL; } for (i = 0; i < NUM_PRIME_GENERATION_ATTEMPTS; i++) { /* Populate the structure containing the data about the number to test: * - the number of which we want to test the primality * - its length * - perform a GCD Primality Test * - perform a Fermat Primality Test * - number of Miller-Rabin rounds to perform (from 0 to 50) * - Miller-Rabin random numbers (one for each test) * - perform a Lucas Primality Test */ pPrimeTestOpData[i].primeCandidate.pData = primeCandidates[i].pData; pPrimeTestOpData[i].primeCandidate.dataLenInBytes = primeCandidates[i].dataLenInBytes; pPrimeTestOpData[i].performGcdTest = CPA_TRUE; pPrimeTestOpData[i].performFermatTest = CPA_TRUE; pPrimeTestOpData[i].numMillerRabinRounds = NB_MR_ROUNDS; pPrimeTestOpData[i].millerRabinRandomInput.pData = pMR.pData; pPrimeTestOpData[i].millerRabinRandomInput.dataLenInBytes = pMR.dataLenInBytes; pPrimeTestOpData[i].performLucasTest = CPA_TRUE; } /*Each of miller rabin round number has to be greater than 1 and * smaller than the number to test -1 */ for (attempt = 0; attempt < NUM_PRIME_GENERATION_RETRY_ATTEMPTS; attempt++) { /*we will use the averagePacketSize to store the index of what passes * as a prime number in our array of prime candidates*/ primePerfData.averagePacketSizeInBytes = NUM_PRIME_GENERATION_ATTEMPTS + 1; primePerfData.numOperations = NUM_PRIME_GENERATION_ATTEMPTS; primePerfData.responses = 0; /* Completion used in callback */ sampleCodeSemaphoreInit(&primePerfData.comp, 0); generatePrimeCandidates(primeCandidates, NUM_PRIME_GENERATION_ATTEMPTS); /*no need to regenerate randomness - MR rounds just have to be greater than 1 and less than (Prime -1)*/ /*Find smallest prime candidate*/ smallestPC = findSmallestNumber(primeCandidates, NUM_PRIME_GENERATION_ATTEMPTS); /*make all numbers less than the smallest candidate -1 */ smallestPC->pData[smallestPC->dataLenInBytes - 1] &= ~1; conformMillerRabinData(&pMR, smallestPC, NB_MR_ROUNDS); smallestPC->pData[smallestPC->dataLenInBytes - 1] |= 1; for (i = 0; i < NUM_PRIME_GENERATION_ATTEMPTS; i++) { do { status = cpaCyPrimeTest( cyInstanceHandle, primeCallback, /* CB function */ &primePerfData, /* callback tag */ &pPrimeTestOpData[i], /* operation data */ &testPassed); /* return value: true if the number is probably a prime, false if it is not a prime */ AVOID_SOFTLOCKUP; if (CPA_STATUS_RETRY == status) { primePerfData.retries++; #ifdef POLL_INLINE if (poll_inline_g) { if (isPolled) { icp_sal_CyPollInstance(setup->cyInstanceHandle, 0); } } #endif if (RETRY_LIMIT == primePerfData.retries) { primePerfData.retries = 0; AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status || CPA_STATUS_RESOURCE == status); /*we check for resource error above because if the driver is * testing a lot of large primes, it can run out of memory pools. * In this circumstance it can be reported as a * CPA_STATUS_RESOURCE*/ if (CPA_STATUS_SUCCESS != status) { PRINT("Error Generating Prime\n"); status = CPA_STATUS_FAIL; break; } } AVOID_SOFTLOCKUP; /*the callback posts the semaphore when all requests have * been processed. If there was a fail, then the callback will never * receive the expected number of response and will never post the * semaphore*/ #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperationsTimeout(&primePerfData, setup->cyInstanceHandle, primePerfData.numOperations, SAMPLE_CODE_WAIT_PRIMES); } } #endif if (CPA_STATUS_SUCCESS == status) { if (sampleCodeSemaphoreWait(&primePerfData.comp, SAMPLE_CODE_WAIT_DEFAULT) != CPA_STATUS_SUCCESS) { PRINT_ERR("timeout or interruption in cpaCyPrimeTest\n"); status = CPA_STATUS_FAIL; } } sampleCodeSemaphoreDestroy(&primePerfData.comp); /*here we reuse averagePacketSizeInBytes for another purpose. In this * case we use it to record the index in our primeNumber candidates * that a prime was found * if the index has changed then we have found a prime number*/ if (primePerfData.averagePacketSizeInBytes != NUM_PRIME_GENERATION_ATTEMPTS + 1) { memcpy(primeCandidate->pData, primeCandidates[primePerfData.averagePacketSizeInBytes - 1] .pData, primeCandidate->dataLenInBytes); break; } else if (i == NUM_PRIME_GENERATION_ATTEMPTS - 1 && attempt == NUM_PRIME_GENERATION_RETRY_ATTEMPTS - 1 && primePerfData.averagePacketSizeInBytes == NUM_PRIME_GENERATION_ATTEMPTS + 1) { PRINT_ERR("\nPRIME NUMBER NOT FOUND\n"); status = CPA_STATUS_FAIL; } } /** Free all allocated structures before exit*/ FREE_GENPRIME_MEM(); return status; } #undef FREE_GENPRIME_MEM EXPORT_SYMBOL(generatePrime); CpaStatus generateHardCodedPrime1P(CpaFlatBuffer *primeCandidate, asym_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U modulusLenInBytes = setup->modulusSizeInBytes; if ((CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 == setup->rsaKeyRepType) || (CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2 == setup->rsaKeyRepType)) { if (modulusLenInBytes == (MODULUS_512_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, p_512, sizeof(p_512)); } else if (modulusLenInBytes == (MODULUS_1024_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, p_1024, sizeof(p_1024)); } else if (modulusLenInBytes == (MODULUS_1536_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, p_1536, sizeof(p_1536)); } else if (modulusLenInBytes == (MODULUS_2048_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, p_2048, sizeof(p_2048)); } else if (modulusLenInBytes == (MODULUS_3072_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, p_3072, sizeof(p_3072)); } else if (modulusLenInBytes == (MODULUS_4096_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, p_4096, sizeof(p_4096)); } } else { if (modulusLenInBytes == (MODULUS_768_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, m_768, sizeof(m_768)); } else if (modulusLenInBytes == (MODULUS_1024_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, m_1024, sizeof(m_1024)); } else if (modulusLenInBytes == (MODULUS_1536_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, m_1536, sizeof(m_1536)); } else if (modulusLenInBytes == (MODULUS_2048_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, m_2048, sizeof(m_2048)); } else if (modulusLenInBytes == (MODULUS_3072_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, m_3072, sizeof(m_3072)); } else if (modulusLenInBytes == (MODULUS_4096_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, m_4096, sizeof(m_4096)); } } return status; } EXPORT_SYMBOL(generateHardCodedPrime1P); CpaStatus generateHardCodedPrime2Q(CpaFlatBuffer *primeCandidate, asym_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U modulusLenInBytes = setup->modulusSizeInBytes; if (modulusLenInBytes == (MODULUS_512_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, q_512, sizeof(q_512)); } else if (modulusLenInBytes == (MODULUS_1024_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, q_1024, sizeof(q_1024)); } else if (modulusLenInBytes == (MODULUS_1536_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, q_1536, sizeof(q_1536)); } else if (modulusLenInBytes == (MODULUS_2048_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, q_2048, sizeof(q_2048)); } else if (modulusLenInBytes == (MODULUS_3072_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, q_3072, sizeof(q_3072)); } else if (modulusLenInBytes == (MODULUS_4096_BIT / NUM_BITS_IN_BYTE)) { memcpy(primeCandidate->pData, q_4096, sizeof(q_4096)); } return status; } void freeArrayFlatBufferNUMA(CpaFlatBuffer *buf, Cpa32U numBuffs) { Cpa32U i = 0; /* this function maybe called before some memory is allocated, * in which case we just return */ if (NULL == buf) { return; } for (i = 0; i < numBuffs; i++) { FREE_NUMA_MEM(buf[i].pData); } // PRINT("%d, S %p\n", __LINE__, buf); qaeMemFree((void **)&buf); } /*set hash len based on hash algorithm*/ Cpa32U setHashDigestLen(CpaCySymHashAlgorithm hashAlgorithm) { switch (hashAlgorithm) { case CPA_CY_SYM_HASH_MD5: return MD5_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_SHA1: return SHA1_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_SHA224: return SHA224_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_SHA256: return SHA256_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_SHA384: return SHA384_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_SHA512: return SHA512_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_AES_XCBC: return AES_XCBC_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_AES_CCM: return AES_CCM_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_AES_GCM: case CPA_CY_SYM_HASH_AES_GMAC: return AES_GCM_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_KASUMI_F9: return KASUMI_F9_DIGEST_RESULT_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_SNOW3G_UIA2: return SNOW3G_UIA2_DIGEST_RESULT_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_AES_CMAC: return AES_CMAC_DIGEST_LENGTH_IN_BYTES; #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 case CPA_CY_SYM_HASH_AES_CBC_MAC: return AES_CBC_MAC_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_ZUC_EIA3: return ZUC_EIA3_DIGEST_LENGTH_IN_BYTES; case CPA_CY_SYM_HASH_SHA3_256: return SHA3_DIGEST_256_LENGTH_IN_BYTES; #elif CPA_CY_API_VERSION_NUM_MINOR >= 8 case CPA_CY_SYM_HASH_AES_CBC_MAC: return AES_CBC_MAC_DIGEST_LENGTH_IN_BYTES; #endif default: PRINT_ERR("Unknown hash algorithm\n"); /*we return 0, when the the API is called it should fail with * invalid param*/ return 0; } } EXPORT_SYMBOL(setHashDigestLen); /*get hash block len for partial packet based on hash algorithm*/ Cpa32U getHashPartialPacketSize(CpaCySymHashAlgorithm hashAlgorithm, Cpa32U packetSize) { Cpa32U returnPacketSize = 0; Cpa32U blockSize = 0; Cpa32U delta = 0; switch (hashAlgorithm) { case CPA_CY_SYM_HASH_MD5: blockSize = MD5_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_SHA1: blockSize = SHA1_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_SHA224: blockSize = SHA_224_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_SHA256: blockSize = SHA_256_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_SHA384: blockSize = SHA_384_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_SHA512: blockSize = SHA_512_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_AES_XCBC: blockSize = AES_XCBC_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_SNOW3G_UIA2: blockSize = SNOW3G_UIA2_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_ZUC_EIA3: blockSize = ZUC_EIA3_BLOCK_LENGTH_IN_BYTES; break; case CPA_CY_SYM_HASH_SHA3_256: blockSize = SHA3_256_BLOCK_LENGTH_IN_BYTES; break; default: blockSize = packetSize; break; } if (packetSize < blockSize) { returnPacketSize = blockSize; PRINT("Packet Size is less than the block size for " "algo[%0d].So,scaling up to block size[%0d]\n", hashAlgorithm, packetSize); } else { delta = packetSize % blockSize; if (delta != 0) { returnPacketSize = packetSize - delta; PRINT("Packet Size is not multiple of block size for " "algo[%0d].So,scaling down to block size[%0d]\n", hashAlgorithm, packetSize); } else { returnPacketSize = packetSize; } } return returnPacketSize; } EXPORT_SYMBOL(getHashPartialPacketSize); /***************************************************************************** * frees any memory allocated in the calcDigest function *****************************************************************************/ #define FREE_CALC_DIGEST_MEM() \ do \ { \ qaeMemFreeNUMA((void **)&pSrcBuffer); \ qaeMemFreeNUMA((void **)&pBufferList); \ qaeMemFreeNUMA((void **)&pBufferMeta); \ qaeMemFreeNUMA((void **)&pOpData); \ qaeMemFreeNUMA((void **)&pSessionCtx); \ } while (0) /*calculate digest of msg using hashAlg and place it in digest*/ CpaStatus calcDigest(CpaInstanceHandle instanceHandle, CpaFlatBuffer *msg, CpaFlatBuffer *digest, CpaCySymHashAlgorithm hashAlg) { CpaStatus status = CPA_STATUS_FAIL; CpaStatus ret = CPA_STATUS_SUCCESS; Cpa32U sessionCtxSize = 0; CpaCySymSessionCtx pSessionCtx = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; Cpa8U *pBufferMeta = NULL; Cpa32U bufferMetaSize = 0; CpaBufferList *pBufferList = NULL; CpaFlatBuffer *pFlatBuffer = NULL; CpaCySymOpData *pOpData = NULL; Cpa32U bufferSize = 0; Cpa32U digestLenInBytes = 0; Cpa32U numBuffers = 1; /* only using 1 buffer in this case */ /* allocate memory for bufferlist and array of flat buffers in a contiguous * area and carve it up to reduce number of memory allocations required. */ Cpa32U bufferListMemSize = sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer)); Cpa8U *pSrcBuffer = NULL; Cpa32U node = 0; CpaCySymCbFunc symCb = NULL; perf_data_t *pPerfData = NULL; #ifdef POLL_INLINE CpaInstanceInfo2 *instanceInfo2 = NULL; CpaBoolean isPolled = CPA_FALSE; if (poll_inline_g) { pPerfData = qaeMemAlloc(sizeof(perf_data_t)); if (NULL == pPerfData) { PRINT_ERR("Error: Allocating perf_data for calcDigest\n"); return CPA_STATUS_FAIL; } pPerfData->numOperations = SINGLE_OPERATION; pPerfData->responses = 0; symCb = symPerformCallback; } #endif #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { status = cpaCyInstanceGetInfo2(instanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pPerfData); return CPA_STATUS_FAIL; } } isPolled = instanceInfo2->isPolled; qaeMemFree((void **)&instanceInfo2); #endif status = sampleCodeCyGetNode(instanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return CPA_STATUS_FAIL; } /* populate symmetric session data structure * for a plain hash operation */ sessionSetupData.sessionPriority = CPA_CY_PRIORITY_NORMAL; sessionSetupData.symOperation = CPA_CY_SYM_OP_HASH; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN; sessionSetupData.hashSetupData.hashAlgorithm = hashAlg; sessionSetupData.hashSetupData.digestResultLenInBytes = setHashDigestLen(hashAlg); sessionSetupData.verifyDigest = CPA_FALSE; digestLenInBytes = sessionSetupData.hashSetupData.digestResultLenInBytes; bufferSize = msg->dataLenInBytes + digestLenInBytes; /* Determine size of session context to allocate */ status = cpaCySymSessionCtxGetSize( instanceHandle, &sessionSetupData, &sessionCtxSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymSessionCtxGetSize failed with status %u\n", status); return CPA_STATUS_FAIL; } /* Allocate session context */ pSessionCtx = qaeMemAllocNUMA(sessionCtxSize, node, BYTE_ALIGNMENT_64); if (NULL == pSessionCtx) { PRINT_ERR("Could not allocate memory for pSessionCtx\n"); return CPA_STATUS_FAIL; } status = cpaCySymInitSession( instanceHandle, symCb, &sessionSetupData, pSessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymInitSession failed with status %u\n", status); FREE_CALC_DIGEST_MEM(); return status; } status = cpaCyBufferListGetMetaSize(instanceHandle, numBuffers, &bufferMetaSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyBufferListGetMetaSize failed with status %u\n", status); FREE_CALC_DIGEST_MEM(); return status; } pBufferMeta = qaeMemAllocNUMA(bufferMetaSize, node, BYTE_ALIGNMENT_64); if (NULL == pBufferMeta) { PRINT_ERR("could not allocate pBufferMeta\n"); FREE_CALC_DIGEST_MEM(); return CPA_STATUS_FAIL; } pBufferList = qaeMemAllocNUMA(bufferListMemSize, node, BYTE_ALIGNMENT_64); if (NULL == pBufferList) { PRINT_ERR("could not allocate pBufferMeta\n"); FREE_CALC_DIGEST_MEM(); return CPA_STATUS_FAIL; } pSrcBuffer = qaeMemAllocNUMA(bufferSize, node, BYTE_ALIGNMENT_64); if (NULL == pSrcBuffer) { PRINT_ERR("could not allocate pSrcBuffer\n"); FREE_CALC_DIGEST_MEM(); return CPA_STATUS_FAIL; } memcpy(pSrcBuffer, msg->pData, msg->dataLenInBytes); /*memory was allocated for bufferList and flatbuffer together so * the flatBuffer offset is just after the CpaBufferList*/ pFlatBuffer = (CpaFlatBuffer *)(pBufferList + 1); pBufferList->pBuffers = pFlatBuffer; pBufferList->numBuffers = 1; pBufferList->pPrivateMetaData = pBufferMeta; pFlatBuffer->dataLenInBytes = bufferSize; pFlatBuffer->pData = pSrcBuffer; pOpData = qaeMemAllocNUMA(sizeof(CpaCySymOpData), node, BYTE_ALIGNMENT_64); if (NULL == pOpData) { PRINT_ERR("could not allocate pSrcBuffer\n"); FREE_CALC_DIGEST_MEM(); return CPA_STATUS_FAIL; } pOpData->sessionCtx = pSessionCtx; pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData->hashStartSrcOffsetInBytes = 0; pOpData->messageLenToHashInBytes = msg->dataLenInBytes; /* Place digest after data in the source buffer */ pOpData->pDigestResult = pSrcBuffer + msg->dataLenInBytes; /** Perform symmetric operation */ #ifdef POLL_INLINE if (poll_inline_g) { sampleCodeSemaphoreInit(&pPerfData->comp, 0); } #endif status = cpaCySymPerformOp(instanceHandle, pPerfData, /* perform synchronous operation*/ pOpData, /* operational data struct */ pBufferList, /* source buffer list */ pBufferList, /* in-place operation*/ NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed. (status = %u)\n", status); ret = CPA_STATUS_FAIL; } #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, instanceHandle, pPerfData->numOperations); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cyPollNumOperations failed, status = %d\n", status); return CPA_STATUS_FAIL; } } sampleCodeSemaphoreDestroy(&pPerfData->comp); qaeMemFree((void **)&pPerfData); } #endif memcpy(digest->pData, pOpData->pDigestResult, digestLenInBytes); digest->dataLenInBytes = digestLenInBytes; /* Remove the session - session init has already succeeded */ status = removeSymSession(instanceHandle, pSessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("removeSymSession failed with status %u\n", status); ret = CPA_STATUS_FAIL; } FREE_CALC_DIGEST_MEM(); return ret; } #undef FREE_CALC_DIGEST_MEM CpaStatus removeSymSession(CpaInstanceHandle instanceHandle, CpaCySymSessionCtx pSessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; #if CY_API_VERSION_AT_LEAST(2, 2) /* In ASYNC mode we need to wait for * all pending request to be finished. */ { CpaBoolean sessionInUse = CPA_FALSE; Cpa32U retries = 0; /* * We do a incremental sleep starting from 50 micro secs and * by incrementing the sleep time by twice the previous value * for each retry. Total sleep time would be 1.6 secs * for 15 number of retries which would be enough for all * in-flight requests to get processed. */ Cpa64U delay = REMOVE_SESSION_WAIT; static const Cpa16U maxRetries = 15; do { status = cpaCySymSessionInUse(pSessionCtx, &sessionInUse); if (CPA_STATUS_SUCCESS == status) { if (sessionInUse == CPA_TRUE) { delay *= 2; sleepNano(delay * 1000); retries++; if (retries >= maxRetries) { break; } } else { break; } } else if (CPA_STATUS_UNSUPPORTED == status) { /* Mark success if sessionInUse not supported */ status = CPA_STATUS_SUCCESS; break; } else { PRINT_ERR("cpaCySymSessionInUse: failed - status: %d\n", status); status = CPA_STATUS_FAIL; break; } } while (1); if (CPA_STATUS_SUCCESS != status) { return status; } } #endif do { /* Linux: The session will only be removed if there are * no in-flight requests. Until then, the function will * ask to retry. This should not result in infinite loop * as all in-flight requests are guaranteed to return even * in case of QAT failure or hang. * */ status = cpaCySymRemoveSession(instanceHandle, pSessionCtx); sleepNano(REMOVE_SESSION_WAIT * 1000); } while (status == CPA_STATUS_RETRY); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Removal of session failed with status %d\n", status); status = CPA_STATUS_FAIL; } return status; } EXPORT_SYMBOL(removeSymSession); /*allocate pData of buf*/ CpaStatus bufferDataMemAlloc(CpaInstanceHandle instanceHandle, CpaFlatBuffer *buf, Cpa32U size, Cpa8U *copyData, Cpa32U sizeOfCopyData) { Cpa32U node = 0; CpaStatus status = CPA_STATUS_FAIL; if (NULL == buf) { PRINT_ERR("buf is null\n"); return CPA_STATUS_FAIL; } if ((NULL != copyData) && (sizeOfCopyData > size)) { PRINT_ERR("copy size is > allocated size\n"); return CPA_STATUS_FAIL; } /* get the node the thread is running on and allocate memory to the same * node */ status = sampleCodeCyGetNode(instanceHandle, &node); if (CPA_STATUS_SUCCESS == status) { buf->pData = (Cpa8U *)qaeMemAllocNUMA(size, node, BYTE_ALIGNMENT_64); buf->dataLenInBytes = size; if (NULL == buf->pData) { PRINT_ERR("pData allocation error\n"); return CPA_STATUS_FAIL; } if (NULL != copyData) { memcpy(buf->pData, copyData, size); } } else { PRINT_ERR("Failed to get node\n"); } return status; } CpaStatus sampleCodeCyGetNode(CpaInstanceHandle instanceHandle, Cpa32U *node) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceInfo2 instanceInfo2; status = cpaCyInstanceGetInfo2(instanceHandle, &instanceInfo2); if (status == CPA_STATUS_SUCCESS) { *node = instanceInfo2.nodeAffinity; } if (allocateMemOnOppositeNode) { *node = ~*node; *node = *node & 0x01; } return status; } void processCallback(void *pCallbackTag) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; /*check tag exists*/ if (pCallbackTag == NULL) { PRINT_ERR("CallBack Tag is a Null pointer!\n"); return; } /* response has been received */ pPerfData->responses++; if (latency_enable && pPerfData->response_times != NULL) { /* Have we sampled too many buffer operations? */ if (pPerfData->latencyCount > MAX_LATENCY_COUNT) { PRINT_ERR("pPerfData latencyCount > MAX_LATENCY_COUNT\n"); return; } /* Is this the buffer we calculate latency on? * And have we calculated too many for array? */ if (pPerfData->responses == pPerfData->nextCount) { int i = pPerfData->latencyCount; /* Now get the end timestamp - before any print outs */ pPerfData->response_times[i] = sampleCodeTimestamp(); pPerfData->nextCount += pPerfData->countIncrement; if (latency_debug) PRINT("%s: responses=%u, latencyCount=%d, end[i]:%llu, " "start[i]:%llu, nextCount=%u\n", __FUNCTION__, (unsigned int)pPerfData->responses, i, pPerfData->response_times[i], pPerfData->start_times[i], pPerfData->nextCount); pPerfData->latencyCount++; } } if (iaCycleCount_g) { /*if we have received half our number of submissions back, * take a timestamp*/ if (pPerfData->numOperations >> 1 == pPerfData->responses) { pPerfData->midCyclesTimestamp = sampleCodeTimestamp(); } } /*if we have received the pre-set numOperations, then get the clock cycle * as a timestamp and post the Semaphore to release parent thread*/ if (pPerfData->numOperations == pPerfData->responses) { pPerfData->endCyclesTimestamp = sampleCodeTimestamp(); if (CPA_STATUS_SUCCESS != sampleCodeSemaphorePost(&pPerfData->comp)) { PRINT_ERR("sampleCodeSemaphorePost Error\n"); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } } } CpaStatus allocArrayOfPointers(CpaInstanceHandle instanceHandle, void **buf, Cpa32U numBuffs) { Cpa32U node = 0; Cpa32U numBytes = 0; CpaStatus status = CPA_STATUS_SUCCESS; status = sampleCodeCyGetNode(instanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not get Node\n"); return CPA_STATUS_FAIL; } numBytes = sizeof(void **) * numBuffs; *buf = qaeMemAllocNUMA(numBytes, node, BYTE_ALIGNMENT_64); if (NULL != *buf) { memset(*buf, 0, numBytes); } else { PRINT_ERR("Error getting allocating array of pointers \n"); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus allocArrayOfVirtPointers(void **buf, Cpa32U numBuffs) { Cpa32U numBytes = 0; numBytes = sizeof(void **) * numBuffs; *buf = qaeMemAlloc(numBytes); if (NULL != *buf) { memset(*buf, 0, numBytes); } else { PRINT_ERR("Error getting allocating array of pointers \n"); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(allocArrayOfVirtPointers); CpaStatus waitForResponses(perf_data_t *perfData, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops) { Cpa64S responsesReceived = RESPONSE_NOT_CHECKED; CpaStatus status = CPA_STATUS_SUCCESS; if (SYNC == syncMode) { perfData->endCyclesTimestamp = sampleCodeTimestamp(); sampleCodeSemaphorePost(&perfData->comp); perfData->responses = (Cpa64U)numBuffers * numLoops; } /*wait for the callback to receive all responses and free the * semaphore, or if in sync mode, the semaphore should already be free*/ while (sampleCodeSemaphoreWait(&perfData->comp, SAMPLE_CODE_WAIT_DEFAULT) != CPA_STATUS_SUCCESS) { if (RESPONSE_NOT_CHECKED != responsesReceived && responsesReceived != (Cpa64S)perfData->numOperations && responsesReceived == (Cpa64S)perfData->responses) { PRINT_ERR("System is not responding\n"); PRINT("Responses expected/received: %llu/%llu\n", (unsigned long long)perfData->numOperations, (unsigned long long)perfData->responses); status = CPA_STATUS_FAIL; break; } else { responsesReceived = perfData->responses; } } return status; } CpaStatus cyCreatePollingThreadsIfPollingIsEnabled(void) { CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa16U i = 0, j = 0, numCreatedPollingThreads = 0; Cpa32U coreAffinity = 0; CpaStatus status = CPA_STATUS_SUCCESS; performance_func_t *pollFnArr = NULL; #ifdef SC_CORE_NUM_POLICY Cpa32U numCores = 0; numCores = sampleCodeGetNumberOfCpus(); if (numCores <= 0) { PRINT_ERR("sampleCodeGetNumberOfCpus() failed\n"); return CPA_STATUS_FAIL; } #endif #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) int fd = -1; #endif if (CPA_FALSE == cy_polling_started_g) { instanceInfo2 = qaeMemAlloc(numInstances_g * sizeof(CpaInstanceInfo2)); if (NULL == instanceInfo2) { PRINT_ERR("Failed to allocate memory for pInstanceInfo2\n"); return CPA_STATUS_FAIL; } pollFnArr = qaeMemAlloc(numInstances_g * sizeof(performance_func_t)); if (NULL == pollFnArr) { PRINT_ERR("Failed to allocate memory for polling functions\n"); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } for (i = 0; i < numInstances_g; i++) { status = cpaCyInstanceGetInfo2(cyInstances_g[i], &instanceInfo2[i]); if (CPA_STATUS_SUCCESS != status) { qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } pollFnArr[i] = NULL; if (CPA_TRUE == instanceInfo2[i].isPolled) { numPolledInstances_g++; #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) status = icp_sal_CyGetFileDescriptor(cyInstances_g[i], &fd); if (CPA_STATUS_SUCCESS == status) { pollFnArr[i] = sampleCodeCyEventPoll; icp_sal_CyPutFileDescriptor(cyInstances_g[i], fd); continue; } else if (CPA_STATUS_FAIL == status) { PRINT_ERR("Error getting file descriptor for Event based " "instance #%d\n", i); qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } /* else feature is unsupported and sampleCodePoll() is to be * used. */ #endif #if !defined(USER_SPACE) setCyPollWaitFn(1, 0); #endif pollFnArr[i] = sampleCodePoll; } } if (0 == numPolledInstances_g) { qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_SUCCESS; } pollingThread_g = qaeMemAlloc(numPolledInstances_g * sizeof(sample_code_thread_t)); if (NULL == pollingThread_g) { PRINT_ERR("Failed to allocate memory for polling threads\n"); qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } for (i = 0; i < numInstances_g; i++) { if (NULL != pollFnArr[i]) { status = sampleCodeThreadCreate( &pollingThread_g[numCreatedPollingThreads], NULL, pollFnArr[i], cyInstances_g[i]); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error starting polling thread %d\n", status); /*attempt to stop any started service, we don't check status * as some instances may not have been started and this * might return fail * */ qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); return CPA_STATUS_FAIL; } /*loop of the instanceInfo coreAffinity bitmask to find the core * affinity*/ for (j = 0; j < CPA_MAX_CORES; j++) { if (CPA_BITMAP_BIT_TEST(instanceInfo2[i].coreAffinity, j)) { #if defined(USER_SPACE) coreAffinity = j; #else coreAffinity = j + 1; #endif break; } } #ifdef SC_CORE_NUM_POLICY if (numInstances_g % numCores == 0) { /* To avoid recalculated and original core * assignment equality */ coreAffinity = (coreAffinity + numInstances_g + 1) % numCores; } else { coreAffinity = (coreAffinity + numInstances_g) % numCores; } #endif sampleCodeThreadBind(&pollingThread_g[numCreatedPollingThreads], coreAffinity); sampleCodeThreadStart( &pollingThread_g[numCreatedPollingThreads]); numCreatedPollingThreads++; } } qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&pollFnArr); cy_polling_started_g = CPA_TRUE; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(cyCreatePollingThreadsIfPollingIsEnabled); CpaBoolean cyCheckAllInstancesArePolled(void) { CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa16U i = 0; instanceInfo2 = qaeMemAlloc(numInstances_g * sizeof(CpaInstanceInfo2)); if (NULL == instanceInfo2) { PRINT_ERR("Failed to allocate memory for pInstanceInfo2\n"); return CPA_FALSE; } for (i = 0; i < numInstances_g; i++) { if (CPA_STATUS_SUCCESS != cpaCyInstanceGetInfo2(cyInstances_g[i], &instanceInfo2[i])) { PRINT_ERR("Call to cpaCyInstanceGetInfo2 failed\n"); qaeMemFree((void **)&instanceInfo2); return CPA_FALSE; } if (CPA_FALSE == instanceInfo2[i].isPolled) { qaeMemFree((void **)&instanceInfo2); return CPA_FALSE; } } qaeMemFree((void **)&instanceInfo2); return CPA_TRUE; } CpaStatus cyDpPollRemainingOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle) { CpaStatus status = CPA_STATUS_FAIL; perf_cycles_t startCycles = 0, totalCycles = 0; Cpa32U freq = sampleCodeGetCpuFreq(); CpaInstanceInfo2 info2 = { 0 }; status = cpaCyInstanceGetInfo2(instanceHandle, &info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 failed. (status = %d)\n", status); return CPA_STATUS_FAIL; } startCycles = sampleCodeTimestamp(); while (pPerfData->responses != pPerfData->numOperations) { if (CPA_TRUE == info2.isPolled) { status = icp_sal_CyPollDpInstance(instanceHandle, 0); if (CPA_STATUS_FAIL == status) { PRINT_ERR("Error polling instance\n"); error_flag_g = CPA_TRUE; return CPA_STATUS_FAIL; } if (CPA_STATUS_RETRY == status) { AVOID_SOFTLOCKUP; } } else { AVOID_SOFTLOCKUP; } totalCycles = (sampleCodeTimestamp() - startCycles); if (totalCycles > 0) { do_div(totalCycles, freq); } if (totalCycles > SAMPLE_CODE_WAIT_DEFAULT) { PRINT_ERR("Timeout on polling remaining Operations\n"); error_flag_g = CPA_TRUE; return CPA_STATUS_FAIL; } } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * function to print out cipher performance header ******************************************************************************/ void printCipherAlg(CpaCySymCipherSetupData cipherSetupData) { switch (cipherSetupData.cipherAlgorithm) { case CPA_CY_SYM_CIPHER_NULL: PRINT("NULL"); break; case CPA_CY_SYM_CIPHER_ARC4: PRINT("ARC4"); break; case CPA_CY_SYM_CIPHER_AES_XTS: if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_256_IN_BYTES) { PRINT("AES128-"); } else if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_512_IN_BYTES) { PRINT("AES256-"); } PRINT("XTS"); break; case CPA_CY_SYM_CIPHER_AES_ECB: case CPA_CY_SYM_CIPHER_AES_CBC: case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_AES_CCM: case CPA_CY_SYM_CIPHER_AES_GCM: if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_128_IN_BYTES) { PRINT("AES128-"); } else if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_192_IN_BYTES) { PRINT("AES192-"); } else if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_256_IN_BYTES) { PRINT("AES256-"); } else { PRINT("AES with unknown key size\n"); } if (cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_ECB) { PRINT("ECB"); } if (cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CBC) { PRINT("CBC"); } if (cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CTR) { PRINT("CTR"); } if (cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { PRINT("CCM"); } if (cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) { PRINT("GCM"); } break; case CPA_CY_SYM_CIPHER_DES_ECB: PRINT("DES-ECB"); break; case CPA_CY_SYM_CIPHER_DES_CBC: PRINT("DES-CBC"); break; case CPA_CY_SYM_CIPHER_3DES_ECB: PRINT("3DES-ECB"); break; case CPA_CY_SYM_CIPHER_3DES_CBC: PRINT("3DES-CBC"); break; case CPA_CY_SYM_CIPHER_3DES_CTR: PRINT("3DES-CTR"); break; case CPA_CY_SYM_CIPHER_KASUMI_F8: PRINT("KASUMI_F8"); break; case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: PRINT("SNOW3G_UEA2"); break; case CPA_CY_SYM_CIPHER_AES_F8: if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_256_IN_BYTES) { PRINT("AES128-"); } else if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_384_IN_BYTES) { PRINT("AES192-"); } else if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_512_IN_BYTES) { PRINT("AES256-"); } else { PRINT("AES with unknown key size\n"); } PRINT("F8"); break; #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 case CPA_CY_SYM_CIPHER_ZUC_EEA3: if (cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_256_IN_BYTES) { PRINT("ZUC256-"); } else { PRINT("ZUC-"); } PRINT("EEA3"); break; case CPA_CY_SYM_CIPHER_SM4_ECB: PRINT("SM4-ECB"); break; case CPA_CY_SYM_CIPHER_SM4_CTR: PRINT("SM4-CTR"); break; case CPA_CY_SYM_CIPHER_SM4_CBC: PRINT("SM4-CBC"); break; case CPA_CY_SYM_CIPHER_CHACHA: PRINT("CHACHA"); break; #endif /*CPA_CY_API_VERSION_NUM_MAJOR >= 2*/ default: PRINT("UNKNOWN_CIPHER %d\n", cipherSetupData.cipherAlgorithm); break; } } /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * function to print out hash performance header ******************************************************************************/ void printHashAlg(CpaCySymHashSetupData hashSetupData) { if (hashSetupData.hashMode == CPA_CY_SYM_HASH_MODE_AUTH && !(hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_AES_XCBC || hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_AES_CCM || hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_AES_GCM || hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_AES_GMAC || hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_AES_CMAC)) { PRINT("HMAC-"); } switch (hashSetupData.hashAlgorithm) { case CPA_CY_SYM_HASH_MD5: PRINT("MD5"); break; case CPA_CY_SYM_HASH_SHA1: PRINT("SHA1"); break; case CPA_CY_SYM_HASH_SHA224: PRINT("SHA2-224"); break; case CPA_CY_SYM_HASH_SHA256: PRINT("SHA2-256"); break; case CPA_CY_SYM_HASH_SHA384: PRINT("SHA2-384"); break; case CPA_CY_SYM_HASH_SHA512: PRINT("SHA2-512"); break; case CPA_CY_SYM_HASH_AES_XCBC: PRINT("AES-XCBC"); break; case CPA_CY_SYM_HASH_AES_CCM: PRINT("AES-CCM"); break; case CPA_CY_SYM_HASH_AES_GCM: PRINT("AES-GCM"); break; case CPA_CY_SYM_HASH_KASUMI_F9: PRINT("KASUMI-F9"); break; case CPA_CY_SYM_HASH_SNOW3G_UIA2: PRINT("SNOW3G-UIA2"); break; case CPA_CY_SYM_HASH_AES_CMAC: if (hashSetupData.authModeSetupData.authKeyLenInBytes == KEY_SIZE_256_IN_BYTES) { PRINT("AES256-CMAC"); } else { PRINT("AES-CMAC"); } break; case CPA_CY_SYM_HASH_AES_GMAC: PRINT("AES-GMAC"); break; #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 case CPA_CY_SYM_HASH_ZUC_EIA3: if (hashSetupData.authModeSetupData.authKeyLenInBytes == KEY_SIZE_256_IN_BYTES && hashSetupData.digestResultLenInBytes == 4) { PRINT("ZUC256-32-"); } else if (hashSetupData.authModeSetupData.authKeyLenInBytes == KEY_SIZE_256_IN_BYTES && hashSetupData.digestResultLenInBytes == 8) { PRINT("ZUC256-64-"); } else if (hashSetupData.authModeSetupData.authKeyLenInBytes == KEY_SIZE_256_IN_BYTES && hashSetupData.digestResultLenInBytes == 16) { PRINT("ZUC256-128-"); } else { PRINT("ZUC-"); } PRINT("EIA3"); break; #elif CPA_CY_API_VERSION_NUM_MINOR >= 8 case CPA_CY_SYM_HASH_AES_CBC_MAC: PRINT("AES-CBC-MAC"); break; #endif case CPA_CY_SYM_HASH_POLY: PRINT("POLY-1305"); break; case CPA_CY_SYM_HASH_SM3: PRINT("SM3"); break; default: PRINT("UNKNOWN_HASH\n"); break; } } EXPORT_SYMBOL(printHashAlg); CpaStatus stopCyServicesFromCallback(thread_creation_data_t *dummy_ptr) { CpaStatus status = CPA_STATUS_SUCCESS; /* stop CY Services */ status = stopCyServices(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Unable to stop CY services\n"); } return status; } EXPORT_SYMBOL(stopCyServicesFromCallback); /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * print out performance test type ******************************************************************************/ void printSymTestType(symmetric_test_params_t *setup) { if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER) { PRINT("Cipher "); printCipherAlg(setup->setupData.cipherSetupData); } else if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH) { PRINT("HASH "); printHashAlg(setup->setupData.hashSetupData); } else if (setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { PRINT("Algorithm Chaining - "); printCipherAlg(setup->setupData.cipherSetupData); PRINT(" "); printHashAlg(setup->setupData.hashSetupData); } PRINT("\n"); PRINT("Direction "); if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == setup->setupData.cipherSetupData.cipherDirection) { PRINT("Encrypt\n"); } else { PRINT("Decrypt\n"); } if (setup->isDpApi) { PRINT("API Data_Plane\n"); } else { PRINT("API Traditional\n"); } } static void accumulateSymPerfData(Cpa32U numberOfThreads, perf_data_t *performanceStats[], perf_data_t *stats, symmetric_test_params_t *setup, Cpa64U *buffersProcessed, Cpa32U *responsesPerThread) { Cpa32U i = 0; /*accumulate the responses into one perf_data_t structure*/ for (i = 0; i < numberOfThreads; i++) { if (!signOfLife) { if (iaCycleCount_g) { stats->offloadCycles += performanceStats[i]->offloadCycles; } if (latency_enable) { /* Accumulate over all tests. Before using later we divide * by number of threads: data->numberOfThreads*/ stats->minLatency += performanceStats[i]->minLatency; stats->aveLatency += performanceStats[i]->aveLatency; stats->maxLatency += performanceStats[i]->maxLatency; } } stats->responses += performanceStats[i]->responses; /*is the data was submitted in multiple buffers per list, then the * number of buffers processed is number of responses multiplied * by the numberOfBuffers*/ if (setup->isMultiSGL) { *buffersProcessed += performanceStats[i]->responses * setup->numBuffers; } else { *buffersProcessed += performanceStats[i]->responses; } stats->retries += performanceStats[i]->retries; stats->numOperations += performanceStats[i]->numOperations; *responsesPerThread = performanceStats[i]->responses; clearPerfStats(performanceStats[i]); } } /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * print out performance data from a collection of threads that * were all running the same setup ******************************************************************************/ CpaStatus printSymmetricPerfDataAndStopCyService(thread_creation_data_t *data) { CpaStatus status = CPA_STATUS_SUCCESS; perf_data_t stats = {0}; perf_cycles_t numOfCycles = 0; Cpa32U responsesPerThread = 0; Cpa32U thoughputSize = 0; Cpa32U devThoughput = 0; Cpa32U throughput = 0; Cpa64U buffersProcessed = 0; Cpa32U i = 0; Cpa32U j = 0; Cpa32U k = 0; symmetric_test_params_t *setup = (symmetric_test_params_t *)data->setupPtr; Cpa32U *perfDataDeviceOffsets; Cpa32U *threadCountPerDevice; perf_data_t *stats2; perf_data_t **tempPerformanceStats = NULL; Cpa32U numberOfUnsupportedThreads = 0; Cpa32U totalThreadsRan = 0; /* Cpa32U perfDataDeviceOffsets[packageIdCount_g]; Cpa32U threadCountPerDevice[packageIdCount_g]; perf_data_t stats2[packageIdCount_g]; */ /*stop crypto services if not already stopped, this is the only reasonable * location we can do this as this function is called after all threads are * complete*/ status = stopCyServices(); if (CPA_STATUS_SUCCESS != status) { /*no need to print error, stopCyServices already does it*/ return status; } stats2 = qaeMemAlloc(sizeof(perf_data_t) * (packageIdCount_g + 1)); if (NULL == stats2) { PRINT_ERR("Error allocating memory for performance stats\n"); return CPA_STATUS_FAIL; } perfDataDeviceOffsets = qaeMemAlloc(sizeof(Cpa32U) * (packageIdCount_g + 1)); if (NULL == perfDataDeviceOffsets) { PRINT_ERR("Error allocating memory for performance stats\n"); qaeMemFree((void **)&stats2); return CPA_STATUS_FAIL; } threadCountPerDevice = qaeMemAlloc(sizeof(Cpa32U) * (packageIdCount_g + 1)); if (NULL == threadCountPerDevice) { PRINT_ERR("Error allocating memory for performance stats\n"); qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); return CPA_STATUS_FAIL; } tempPerformanceStats = qaeMemAlloc(sizeof(perf_data_t *) * data->numberOfThreads); if (NULL == tempPerformanceStats) { qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); qaeMemFree((void **)&threadCountPerDevice); PRINT_ERR("Error in allocating memory for tempPerformanceStats\n"); return CPA_STATUS_FAIL; } for (i = 0; i < data->numberOfThreads; i++) { if (CPA_STATUS_UNSUPPORTED == data->performanceStats[i]->threadReturnStatus) { numberOfUnsupportedThreads++; } else if (CPA_STATUS_FAIL == data->performanceStats[i]->threadReturnStatus) { qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); qaeMemFree((void **)&threadCountPerDevice); qaeMemFree((void **)&tempPerformanceStats); return CPA_STATUS_FAIL; } } totalThreadsRan = data->numberOfThreads - numberOfUnsupportedThreads; if (totalThreadsRan == 0) { qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); qaeMemFree((void **)&threadCountPerDevice); qaeMemFree((void **)&tempPerformanceStats); return CPA_STATUS_FAIL; } /* Block to re-group the data per device */ for (j = 0; j < (packageIdCount_g + 1); j++) { for (i = 0; i < totalThreadsRan; i++) { if (data->performanceStats[i]->packageId == j) { tempPerformanceStats[k++] = data->performanceStats[i]; } } } for (i = 0; i < totalThreadsRan; i++) { data->performanceStats[i] = tempPerformanceStats[i]; } memset(stats2, 0, sizeof(perf_data_t) * (packageIdCount_g + 1)); /*point perf stats to clear structure*/ setup->performanceStats = &stats; for (i = 0; i < (packageIdCount_g + 1); i++) { setup->performanceStats = &stats2[i]; stats2[i].averagePacketSizeInBytes = data->packetSize; if (setup->performanceStats->averagePacketSizeInBytes == PACKET_IMIX) { stats2[i].averagePacketSizeInBytes = BUFFER_SIZE_1152; } } /*get our test bufferSize*/ stats.averagePacketSizeInBytes = data->packetSize; thoughputSize = data->packetSize; if (data->packetSize == PACKET_IMIX) { thoughputSize = setup->performanceStats->averagePacketSizeInBytes; } /*get the lowest and highest cycle count from the list of threads (all the * same setup executed*/ getLongestCycleCount2(stats2, data->performanceStats, totalThreadsRan, perfDataDeviceOffsets, threadCountPerDevice); /*calc the total cycles of all threads (of one setup type) took to complete * and then print out the data*/ for (i = 0; i < (packageIdCount_g + 1); i++) { accumulateSymPerfData( threadCountPerDevice[i], &(data->performanceStats[perfDataDeviceOffsets[i]]), &stats2[i], setup, &buffersProcessed, &responsesPerThread); numOfCycles = (stats2[i].endCyclesTimestamp - stats2[i].startCyclesTimestamp); if (!signOfLife) { devThoughput = getThroughput(buffersProcessed, thoughputSize, numOfCycles); } buffersProcessed = 0; throughput += devThoughput; stats.numOperations += stats2[i].numOperations; stats.responses += stats2[i].responses; stats.retries += stats2[i].retries; if (iaCycleCount_g) { stats.offloadCycles += stats2[i].offloadCycles; } if (latency_enable) { stats.minLatency += stats2[i].minLatency; stats.aveLatency += stats2[i].aveLatency; stats.maxLatency += stats2[i].maxLatency; } } printSymTestType(setup); if (data->packetSize == PACKET_IMIX) { PRINT("Packet Mix\ 40%%-64B 20%%-752B 35%% 1504B 5%%-8892B\n"); } else { PRINT("Packet Size %u\n", setup->performanceStats->averagePacketSizeInBytes); } PRINT("Number of Threads %u\n", data->numberOfThreads); if (numberOfUnsupportedThreads) { PRINT("Unsupported Threads %u\n", numberOfUnsupportedThreads); } PRINT("Total Threads ran %u\n", totalThreadsRan); PRINT("Total Submissions %llu\n", (unsigned long long)stats.numOperations); PRINT("Total Responses %llu\n", (unsigned long long)stats.responses); PRINT("Total Retries %llu\n", (unsigned long long)stats.retries); if (!signOfLife) { PRINT("CPU Frequency(kHz) %u\n", sampleCodeGetCpuFreq()); if (responsesPerThread < THROUGHPUT_MIN_SUBMISSIONS) { PRINT("Need to submit >= %u per thread for accurate throughput\n", THROUGHPUT_MIN_SUBMISSIONS); } else { PRINT("Throughput(Mbps) %u\n", throughput); } if (latency_enable) { perf_cycles_t statsLatency = 0; perf_cycles_t cpuFreqKHz = sampleCodeGetCpuFreq(); /*Display how long it took on average to process a buffer in uSecs. *Also include min/max to show variance */ do_div(stats.minLatency, totalThreadsRan); statsLatency = 1000 * stats.minLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Min. Latency (uSecs) %llu\n", statsLatency); do_div(stats.aveLatency, totalThreadsRan); statsLatency = 1000 * stats.aveLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Ave. Latency (uSecs) %llu\n", statsLatency); do_div(stats.maxLatency, totalThreadsRan); statsLatency = 1000 * stats.maxLatency; do_div(statsLatency, cpuFreqKHz); PRINT("Max. Latency (uSecs) %llu\n", statsLatency); } if (iaCycleCount_g) { do_div(stats.offloadCycles, totalThreadsRan); PRINT("Avg Offload Cycles %llu\n", (long long unsigned int)stats.offloadCycles); } } qaeMemFree((void **)&stats2); qaeMemFree((void **)&perfDataDeviceOffsets); qaeMemFree((void **)&threadCountPerDevice); qaeMemFree((void **)&tempPerformanceStats); return CPA_STATUS_SUCCESS; } /**/ CpaStatus switchCipherDirection() { PRINT("New cipher direction: "); if (cipherDirection_g == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) { PRINT("CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT\n"); cipherDirection_g = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; } else { PRINT("CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT\n"); cipherDirection_g = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(switchCipherDirection); /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Set the digestAppend flag to true or false * ***************************************************************************/ CpaStatus setDigestAppend(CpaBoolean flag) { digestAppended_g = flag; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setDigestAppend); void setBusyLoopMethod(Cpa32U method) { busyLoopMethod_g = method; return; } EXPORT_SYMBOL(busyLoopMethod_g); EXPORT_SYMBOL(setBusyLoopMethod); void setTimeStampInLoop(CpaBoolean value) { timeStampInLoop = value; return; } EXPORT_SYMBOL(timeStampInLoop); EXPORT_SYMBOL(setTimeStampInLoop); /************************************************************************ * * Name: checkCapability * * Description: Checks whether the given logical instance supports * * cipherAlg/hashAlg * * Return : True if supported, False, otherwise * ************************************************************************/ CpaBoolean checkCapability(CpaInstanceHandle *cyInstanceHandle, symmetric_test_params_t *symTestSetup) { CpaCySymCapabilitiesInfo cySymCapInfo = {}; CpaCySymCapabilitiesInfo *pCapInfo = NULL; if (!(symTestSetup->setupData.cipherSetupData.cipherAlgorithm | symTestSetup->setupData.hashSetupData.hashAlgorithm)) { return CPA_FALSE; } if (CPA_STATUS_SUCCESS != cpaCySymQueryCapabilities(cyInstanceHandle, &cySymCapInfo)) { PRINT_ERR("cpaCySymQueryCapabilities fail\n"); return CPA_FALSE; } pCapInfo = &cySymCapInfo; switch (symTestSetup->setupData.symOperation) { case CPA_CY_SYM_OP_CIPHER: if (symTestSetup->setupData.cipherSetupData.cipherAlgorithm && ((CPA_BITMAP_BIT_TEST(pCapInfo->ciphers, symTestSetup->setupData.cipherSetupData .cipherAlgorithm)) == CPA_FALSE)) { PRINT("\nUnsupported Cipher "); printCipherAlg(symTestSetup->setupData.cipherSetupData); return CPA_FALSE; } break; case CPA_CY_SYM_OP_HASH: if (symTestSetup->setupData.hashSetupData.hashAlgorithm && ((CPA_BITMAP_BIT_TEST( pCapInfo->hashes, symTestSetup->setupData.hashSetupData.hashAlgorithm)) == CPA_FALSE)) { PRINT("\nUnsupported Hash "); printHashAlg(symTestSetup->setupData.hashSetupData); return CPA_FALSE; } break; case CPA_CY_SYM_OP_ALGORITHM_CHAINING: if (symTestSetup->setupData.cipherSetupData.cipherAlgorithm && ((CPA_BITMAP_BIT_TEST(pCapInfo->ciphers, symTestSetup->setupData.cipherSetupData .cipherAlgorithm)) == CPA_FALSE)) { PRINT("\nUnsupported AlgChain "); printCipherAlg(symTestSetup->setupData.cipherSetupData); return CPA_FALSE; } if (symTestSetup->setupData.hashSetupData.hashAlgorithm && ((CPA_BITMAP_BIT_TEST( pCapInfo->hashes, symTestSetup->setupData.hashSetupData.hashAlgorithm)) == CPA_FALSE)) { PRINT("\nUnsupported AlgChain "); printHashAlg(symTestSetup->setupData.hashSetupData); return CPA_FALSE; } break; default: PRINT_ERR("\nUnsupported Sym operation: %d\n", symTestSetup->setupData.symOperation); return CPA_FALSE; } return CPA_TRUE; } EXPORT_SYMBOL(checkCapability); EXPORT_SYMBOL(setCyPollWaitFn); CpaStatus getCyInstanceCapabilities(CpaCyCapabilitiesInfo *pCap) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; cpaCyGetInstances(1, &instanceHandle); if (instanceHandle == NULL) { return CPA_STATUS_FAIL; } status = cpaCyQueryCapabilities(instanceHandle, pCap); if (CPA_STATUS_SUCCESS != status) { return status; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(getCyInstanceCapabilities); CpaStatus getCryptoInstanceCapabilities(CpaCyCapabilitiesInfo *cap, Cpa32U instType) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa16U nSymInstances = 0; Cpa16U nAsymInstances = 0; Cpa16U nCyInstances = 0; #if CY_API_VERSION_AT_LEAST(3, 0) status = cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO_SYM, &nSymInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetNumInstances failed with status: %d\n", status); return status; } status = cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO_ASYM, &nAsymInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetNumInstances failed with status: %d\n", status); return status; } status = cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO, &nCyInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetNumInstances failed with status: %d\n", status); return status; } #endif /* Sym/Asym Instances will be 0 for 1.x platforms. * Return the first Crypto Instance Capabilities */ if (nSymInstances == 0 && nAsymInstances == 0) { status = getCyInstanceCapabilities(cap); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("getCyInstanceCapabilities failed with status: %d\n", status); } return status; } #if CY_API_VERSION_AT_LEAST(3, 0) if (SYM == instType && nSymInstances > 0) { status = getSymAsymInstanceCapabilities(cap, instType); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("getSymAsymInstanceCapabilities failed with status: %d\n", status); return status; } } if (ASYM == instType && nAsymInstances > 0) { status = getSymAsymInstanceCapabilities(cap, instType); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("getSymAsymInstanceCapabilities failed with status: %d\n", status); return status; } return CPA_STATUS_SUCCESS; } if(nCyInstances > (nAsymInstances + nSymInstances)) { status = getCyInstanceCapabilities(cap); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("getCyInstanceCapabilities failed with status: %d\n", status); } return status; } #endif return status; } EXPORT_SYMBOL(getCryptoInstanceCapabilities); #if CY_API_VERSION_AT_LEAST(3, 0) CpaStatus getSymAsymInstanceCapabilities(CpaCyCapabilitiesInfo *pCap, Cpa32U instType) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; if (SYM == instType) { cpaGetInstances(CPA_ACC_SVC_TYPE_CRYPTO_SYM, 1, &instanceHandle); } else { cpaGetInstances(CPA_ACC_SVC_TYPE_CRYPTO_ASYM, 1, &instanceHandle); } if (instanceHandle == NULL) { return CPA_STATUS_UNSUPPORTED; } status = cpaCyQueryCapabilities(instanceHandle, pCap); if (CPA_STATUS_SUCCESS != status) { return status; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(getSymAsymInstanceCapabilities); #endif CpaStatus getCySymQueryCapabilities(CpaCySymCapabilitiesInfo *pCap) { CpaStatus status = CPA_STATUS_FAIL; CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; Cpa16U nSymInstances = 0; #if CY_API_VERSION_AT_LEAST(3, 0) cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO_SYM, &nSymInstances); if (nSymInstances > 0) { cpaGetInstances(CPA_ACC_SVC_TYPE_CRYPTO_SYM, 1, &instanceHandle); } #endif /* Sym Instance will be 0 for 1.x platforms. */ if (nSymInstances == 0) { status = cpaCyGetInstances(1, &instanceHandle); if (CPA_STATUS_SUCCESS != status) { return status; } } if (instanceHandle == NULL) { return CPA_STATUS_FAIL; } status = cpaCySymQueryCapabilities(instanceHandle, pCap); if (CPA_STATUS_SUCCESS != status) { return status; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(getCySymQueryCapabilities); CpaStatus getCySpecificInstanceCapabilities(CpaInstanceHandle instanceHandle, CpaCyCapabilitiesInfo *pCap) { CpaStatus status = CPA_STATUS_FAIL; if (instanceHandle == NULL) { return CPA_STATUS_FAIL; } status = cpaCyQueryCapabilities(instanceHandle, pCap); if (CPA_STATUS_SUCCESS != status) { return status; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(getCySpecificInstanceCapabilities); /* * The setupSymmetricDpTest() function has the encrypt / decrypt * direction hard coded to CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT. * Use setCipherDirection() before calling setupCipherDpTest(). */ CpaCySymCipherDirection getCipherDirection(void) { return cipherDirection_g; } EXPORT_SYMBOL(getCipherDirection); /* * The setupSymmetricDpTest() function has the encrypt / decrypt * direction hard coded to CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT. * Use setCipherDirection() before calling setupCipherDpTest(). */ void setCipherDirection(CpaCySymCipherDirection direction) { switch (direction) { case CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT: PRINT("%s: cipherDirection_g is now ENCRYPT\n", __FUNCTION__); cipherDirection_g = direction; break; case CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT: PRINT("%s: cipherDirection_g is now DECRYPT\n", __FUNCTION__); cipherDirection_g = direction; break; default: PRINT("ERROR: %s: setCipherDirection( %d ) invalid argument\n", __FUNCTION__, (int)direction); break; } } EXPORT_SYMBOL(setCipherDirection); CpaStatus sampleCodeAsymPollInstance(CpaInstanceHandle instanceHandle_in, Cpa32U response_quota) { { return icp_sal_CyPollInstance(instanceHandle_in, response_quota); } } CpaStatus sampleCodeSymPollInstance(CpaInstanceHandle instanceHandle_in, Cpa32U response_quota) { { return icp_sal_CyPollInstance(instanceHandle_in, response_quota); } } CpaStatus checkForChachapolySupport(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymCapabilitiesInfo capInfo = {{0}}; Cpa16U numCyInstances = 0; Cpa16U i = 0; CpaInstanceHandle *cyInstances = NULL; /*Get number of Crypto Instances*/ status = cpaCyGetNumInstances(&numCyInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetNumInstances failed with status: %d\n", status); return status; } if (0 == numCyInstances) { PRINT_ERR("There are no Crypto Instances available!\n"); return CPA_STATUS_FAIL; } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numCyInstances); if (NULL == cyInstances) { PRINT_ERR("Failed to allocate memory for instances\n"); return CPA_STATUS_FAIL; } status = cpaCyGetInstances(numCyInstances, cyInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetInstances failed with status: %d\n", status); qaeMemFree((void **)&cyInstances); return status; } /*Check for required Capability in all instances. Set the Success Status *if required capability is supported in any instance. */ status = CPA_STATUS_FAIL; for (i = 0; i < numCyInstances; i++) { if (CPA_STATUS_SUCCESS == cpaCySymQueryCapabilities(cyInstances[i], &capInfo)) { if (CPA_BITMAP_BIT_TEST(capInfo.ciphers, CPA_CY_SYM_CIPHER_CHACHA)) { status = CPA_STATUS_SUCCESS; break; } } } if (NULL != cyInstances) { qaeMemFree((void **)&cyInstances); } return status; } cpa_sample_code_crypto_utils.h000066400000000000000000003302331503624047500370210ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_crypto_utils.h * * @ingroup cryptoThreads * * @description * Contains function prototypes and #defines used by crypto thread functions * ***************************************************************************/ #ifndef _CRYPTO_UTILS_H_ #define _CRYPTO_UTILS_H_ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_cy_ec.h" #include "cpa_cy_rsa.h" #include "cpa_cy_dh.h" #include "cpa_cy_im.h" #include "cpa_cy_key.h" #include "cpa_cy_dsa.h" #include "qat_perf_utils.h" #include "cpa_sample_code_utils.h" #include "cpa_sample_code_framework.h" #ifdef SC_SM2_ENABLED #include "cpa_cy_ecsm2.h" #endif /* SC_SM2_ENABLED */ #ifdef USER_SPACE #include #endif #ifdef POLL_INLINE extern Cpa32U asymPollingInterval_g; #endif extern unsigned long long timeStampTime_g; extern Cpa32U busyLoopMethod_g; extern volatile CpaBoolean cy_service_started_g; extern CpaBoolean timeStampInLoop; /* ****************************************************************************** * General performance code settings ****************************************************************************** */ #define MIN_CY_BUFFERS (20) #define MIN_SYM_LOOPS (1) #define MIN_ASYM_LOOPS (1) #define DEFAULT_CY_BUFFERS (20) #define DEFAULT_SYM_LOOPS (5000) #define DEFAULT_ASYM_LOOPS (5000) #define DEFAULT_WIRELESS_FIRMWARE (0) #define DEFAULT_INCLUDE_WIRELESS_ALGS (1) #define WIRELESS_PACKET_LIMIT (4) #define SINGLE_OPERATION (1) #define REMOVE_SESSION_WAIT (50) /* KPT Stolen Key Test */ #define CY_API_VERSION_AT_LEAST(major, minor) \ (CPA_CY_API_VERSION_NUM_MAJOR > major || \ (CPA_CY_API_VERSION_NUM_MAJOR == major && \ CPA_CY_API_VERSION_NUM_MINOR >= minor)) #if CY_API_VERSION_AT_LEAST(3, 0) #include "cpa_cy_kpt.h" #endif /*Each buffer list used in crypto performance code uses NUM_UNCHAINED_BUFFERS*/ #define NUM_UNCHAINED_BUFFERS (1) /*number of times to retry before having a break from submitting requests*/ #define RETRY_LIMIT (100) #define NUM_BITS_IN_BYTE (8) /*used to set MSB of a byte, some of the QA API structures require this*/ #define MSB_SETTING (0x80) /*define minimum number of asymmetric submission per thread that * results in an accurate operations per second calculation +/- 1%*/ #define ASYM_THROUGHPUT_MIN_SUBMISSIONS (10000) /*PACKET_IMIX is an average of a mix of buffer sizes. * This is used to indicate to the crypto thread code that we want to test * a mix of buffersizes. This mix is based on: * 40% 64 Byte buffers * 20% 752 Byte buffers * 35% 1504 Byte buffers * 5% 8892 Byte buffers * */ /*PACKET_IMIX is the average size in the comment above*/ #define PACKET_IMIX (0) /* NUM_PACKETS_IMIX specifies the number of packets that constitute IMIX */ #define NUM_PACKETS_IMIX (20) /*number of buffers per buffer list * DP API in performance sample code can use flat buffers while the trad API * uses scatter gather lists and requires at least 1 CpaFlatBuffer in a list * this setting determines weather DP API uses flat buffer or CpaFlatBuffer*/ #define DEFAULT_CPA_FLAT_BUFFERS_PER_LIST (0) #define CHECK_AND_STOPCYSERVICES() \ if (cy_service_started_g == CPA_TRUE) \ { \ stopCyServices(); \ } #define DECLARE_IA_CYCLE_COUNT_VARIABLES() \ Cpa32U submissions = 0; \ Cpa32U staticAssign = 0; \ Cpa32U busyLoopCount = 0; \ Cpa32U busyLoopValue = busyLoopCounter_g; \ perf_cycles_t startBusyLoop = 0, endBusyLoop = 0; \ Cpa32U numBusyLoops = 0; \ Cpa32U index = 0; \ perf_cycles_t timeStampTime[10] = {0}; \ perf_cycles_t timeStamp2 = 0; #define BUSY_LOOP() \ submissions++; \ if (timeStampInLoop) \ { \ if (submissions % 100 == 0 && submissions <= 1000) \ { \ timeStampTime[index++] = getTimeStampTime2(); \ } \ } \ if (submissions < (setup->performanceStats->numOperations >> 1)) \ { \ if (busyLoopMethod_g == 2) \ { \ setup->performanceStats->totalBusyLoopCycles += \ busyLoop2(busyLoopCounter_g, &staticAssign); \ } \ else \ { \ busyLoop(busyLoopCounter_g, &staticAssign); \ } \ busyLoopCount++; \ } \ else \ { \ if (busyLoopMethod_g == 2) \ { \ busyLoop2(busyLoopCounter_g, &staticAssign); \ } \ else \ { \ busyLoop(busyLoopCounter_g, &staticAssign); \ busyLoopCount++; \ } \ } #define IA_CYCLE_COUNT_CALCULATION() \ setup->performanceStats->busyLoopCount = busyLoopCount; \ setup->performanceStats->busyLoopValue = busyLoopValue; \ \ if (timeStampInLoop) \ { \ for (numBusyLoops = 0; numBusyLoops < 10; numBusyLoops++) \ { \ PRINT("timeStampTime: %llu\n", timeStampTime[numBusyLoops]); \ timeStamp2 += timeStampTime[numBusyLoops]; \ } \ } \ do_div(timeStamp2, 10); \ PRINT("timestamp2: %llu\n", timeStamp2); \ \ PRINT("busyLoops: %u\n", busyLoopCount); \ if (busyLoopMethod_g == 2) \ { \ timeStampTime_g = timeStampTime_g * (busyLoopCount); \ PRINT("Mid Point Total cycles: %llu \n", \ (setup->performanceStats->midCyclesTimestamp - \ setup->performanceStats->startCyclesTimestamp)); \ PRINT("BusyLoopCycles %llu\n", \ setup->performanceStats->totalBusyLoopCycles); \ PRINT("busyLoopCount: %u \n", busyLoopCount); \ setup->performanceStats->offloadCycles = \ (setup->performanceStats->midCyclesTimestamp - \ setup->performanceStats->startCyclesTimestamp) - \ setup->performanceStats->totalBusyLoopCycles - timeStamp2; \ } \ else \ { \ busyLoopTimeStamp(); \ \ startBusyLoop = busyLoopTimeStamp(); \ for (numBusyLoops = 0; numBusyLoops < busyLoopCount; numBusyLoops++) \ { \ busyLoop(busyLoopValue, &staticAssign); \ } \ endBusyLoop = busyLoopTimeStamp(); \ \ setup->performanceStats->totalBusyLoopCycles = \ endBusyLoop - startBusyLoop; \ PRINT("BusyLoopCycles %llu\n", \ setup->performanceStats->totalBusyLoopCycles); \ setup->performanceStats->offloadCycles = \ (setup->performanceStats->endCyclesTimestamp - \ setup->performanceStats->startCyclesTimestamp) - \ setup->performanceStats->totalBusyLoopCycles; \ } \ if (setup->performanceStats->responses > 0) \ { \ do_div(setup->performanceStats->offloadCycles, \ (setup->performanceStats->responses)); \ } \ PRINT("Offload cycles %llu\n", setup->performanceStats->offloadCycles); /** ******************************************************************************* * Update numLoops and numOperations when enableStopTests is enabled * param input : loops * param output : setup, pPerfStats ******************************************************************************/ #define StopTestEnabled(loops, setup, pPerfStats) \ do \ { \ if (stopTestsIsEnabled_g) \ { \ /* Check if terminated by global flag. If yes, update \ * numOperations and numLoops */ \ if (CPA_TRUE == exitLoopFlag_g) \ { \ setup->numLoops = loops + OFFSET_LOOP_EXIT; \ pPerfStats->numOperations = \ (Cpa64U)numLoops * setup->numBuffers; \ } \ } \ } while (0) typedef enum tlspfs_sign_mode_s { TLSPFS_SIGN_MODE_RSA = 0, TLSPFS_SIGN_MODE_ECDSA } tlspfs_sign_mode_t; /*enum to define Diffie-Hellman phase*/ typedef enum dh_phase_s { DH_PHASE_1 = 0, DH_PHASE_2 } dh_phase_t; /*enum to define ECDSA step*/ typedef enum ecdsa_step_s { ECDSA_STEP_SIGNRS = 0, ECDSA_STEP_VERIFY, ECDSA_STEP_POINT_MULTIPLY } ecdsa_step_t; #ifdef SC_SM2_ENABLED /*enum to define SM2 step */ typedef enum sm2_step_s { SM2_STEP_SIGN = 0, SM2_STEP_VERIFY, SM2_STEP_ENC, SM2_STEP_DEC, SM2_STEP_KEYEX_P1, SM2_STEP_KEYEX_P2 } sm2_step_t; #endif /* SC_SM2_ENABLED */ /*enum to define DSA step*/ typedef enum dsa_step_s { DSA_STEP_SIGNRS = 0, DSA_STEP_VERIFY } dsa_step_t; #if CY_API_VERSION_AT_LEAST(3, 0) /*add for SM3 and SM4*/ typedef struct smx_key_size_pairs_s { CpaCySymCipherAlgorithm cipherAlg; Cpa32U cipherKeySizeInBytes; CpaCySymHashAlgorithm hashAlg; Cpa32U hashKeySizeInBytes; Cpa32U cipherOffset; } smx_key_size_pairs_t; /*enum to define EC-Gen step */ typedef enum ec_gen_step_s { EC_GEN_VERIFY = 0, EC_GEN_MULTIPLY } ec_gen_step_t; #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #define POLLED (2) #define DEFAULT_SAMPLE_CODE_SLEEP (2) #define DEFAULT_POLL_INTERVAL_NSEC (2100) #define DEFAULT_SLEEP_INTERVAL_NSEC (200) #define DEFAULT_POLL_INTERVAL_MSEC (2) #define DEFAULT_POLL_INTERVAL_KERNEL (0) /* ****************************************************************************** * Symmetric related performance defines ****************************************************************************** */ #define SHA1_AUTH_KEY_LENGTH_IN_BYTES (160 / NUM_BITS_IN_BYTE) #define SHA512_AUTH_KEY_LENGTH_IN_BYTES (512 / NUM_BITS_IN_BYTE) #define HASH_OFFSET_BYTES (0) #define CIPHER_OFFSET_BYTES (0) #define KEY_SIZE_32_IN_BYTES (32 / NUM_BITS_IN_BYTE) #define KEY_SIZE_64_IN_BYTES (64 / NUM_BITS_IN_BYTE) #define KEY_SIZE_96_IN_BYTES (96 / NUM_BITS_IN_BYTE) #define KEY_SIZE_128_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define KEY_SIZE_160_IN_BYTES (160 / NUM_BITS_IN_BYTE) #define KEY_SIZE_192_IN_BYTES (192 / NUM_BITS_IN_BYTE) #define KEY_SIZE_224_IN_BYTES (224 / NUM_BITS_IN_BYTE) #define KEY_SIZE_256_IN_BYTES (256 / NUM_BITS_IN_BYTE) #define KEY_SIZE_384_IN_BYTES (384 / NUM_BITS_IN_BYTE) #define KEY_SIZE_512_IN_BYTES (512 / NUM_BITS_IN_BYTE) #define MD5_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define SHA1_DIGEST_LENGTH_IN_BYTES (160 / NUM_BITS_IN_BYTE) #define SHA224_DIGEST_LENGTH_IN_BYTES (224 / NUM_BITS_IN_BYTE) #define SHA256_DIGEST_LENGTH_IN_BYTES (256 / NUM_BITS_IN_BYTE) #define SHA384_DIGEST_LENGTH_IN_BYTES (384 / NUM_BITS_IN_BYTE) #define SHA512_DIGEST_LENGTH_IN_BYTES (512 / NUM_BITS_IN_BYTE) #define AES_XCBC_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define AES_CCM_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define AES_CCM_DEFAULT_NONCE_LENGTH (104 / NUM_BITS_IN_BYTE) #define AES_CCM_MIN_AAD_ALLOC_LENGTH (256 / NUM_BITS_IN_BYTE) #define AES_GCM_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define KASUMI_F9_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define SNOW3G_UIA2_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define AES_CMAC_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define AES_CBC_MAC_DIGEST_LENGTH_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define KASUMI_F9_OR_SNOW3G_UIA2_KEY_SIZE_128_IN_BYTES (128 / NUM_BITS_IN_BYTE) #define KASUMI_F9_DIGEST_RESULT_LENGTH_IN_BYTES (32 / NUM_BITS_IN_BYTE) #define SNOW3G_UIA2_DIGEST_RESULT_LENGTH_IN_BYTES (32 / NUM_BITS_IN_BYTE) #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 /*ZUC_EIA3 produces 32bit digest*/ #define ZUC_EIA3_DIGEST_LENGTH_IN_BYTES (32 / NUM_BITS_IN_BYTE) #define SHA3_DIGEST_256_LENGTH_IN_BYTES (32) #define SHA3_256_KEYLENGTH_136_IN_BYTES (136) #endif #define MD5_BLOCK_LENGTH_IN_BYTES (64) #define SHA1_BLOCK_LENGTH_IN_BYTES (64) #define SHA_224_BLOCK_LENGTH_IN_BYTES (64) #define SHA_256_BLOCK_LENGTH_IN_BYTES (64) #define SHA_384_BLOCK_LENGTH_IN_BYTES (128) #define SHA_512_BLOCK_LENGTH_IN_BYTES (128) #define AES_XCBC_BLOCK_LENGTH_IN_BYTES (16) #define SNOW3G_UIA2_BLOCK_LENGTH_IN_BYTES (8) #define ZUC_EIA3_BLOCK_LENGTH_IN_BYTES (4) #define SHA3_256_BLOCK_LENGTH_IN_BYTES (136) #define POLY_DIGEST_LENGTH_IN_BYTES (16) /*add for SM3 and SM4*/ #define SM3_DIGEST_LENGTH_IN_BYTES (32) #define BUFFER_SIZE_0 (0) #define BUFFER_SIZE_32 (32) #define BUFFER_SIZE_40 (40) #define BUFFER_SIZE_64 (64) #define BUFFER_SIZE_128 (128) #define BUFFER_SIZE_256 (256) #define BUFFER_SIZE_304 (304) #define BUFFER_SIZE_320 (320) #define BUFFER_SIZE_512 (512) #define BUFFER_SIZE_700 (700) #define BUFFER_SIZE_752 (752) #define BUFFER_SIZE_768 (768) #define BUFFER_SIZE_1024 (1024) #define BUFFER_SIZE_1027 (1027) #define BUFFER_SIZE_1152 (1152) #define BUFFER_SIZE_1280 (1280) #define BUFFER_SIZE_1408 (1408) #define BUFFER_SIZE_1460 (1460) #define BUFFER_SIZE_1504 (1504) #define BUFFER_SIZE_1536 (1536) #define BUFFER_SIZE_2048 (2048) #define BUFFER_SIZE_4096 (4096) #define BUFFER_SIZE_7680 (7680) #define BUFFER_SIZE_8192 (8192) #define BUFFER_SIZE_8992 (8992) #define BUFFER_SIZE_16384 (16384) #define BUFFER_SIZE_32768 (32768) #define BUFFER_SIZE_65536 (65536) #define BUFFER_SIZE_131072 (131072) #define BUFFER_SIZE_1048576 (1048576) #define BUFFER_SIZE_10485760 (10485760) #define BUFFER_SIZE_1073741824 (1073741824) #define BUFFER_SIZE_2147483648 (2147483648) #define BUFFER_SIZE_4294967295 (4294967295) /*define IV len for 8 and 16 byte block ciphers*/ #define IV_LEN_FOR_8_BYTE_BLOCK_CIPHER (8) #define IV_LEN_FOR_12_BYTE_BLOCK_CIPHER (12) #define IV_LEN_FOR_16_BYTE_BLOCK_CIPHER (16) #define IV_LEN_FOR_24_BYTE_BLOCK_CIPHER (24) #define IV_LEN_FOR_12_BYTE_GCM (12) #define IV_LEN_FOR_16_BYTE_GCM (16) #define IV_LEN_FOR_12_BYTE_CHACHA (12) #define CPA_CIPHER_SPC_IV_SIZE (12) #define DIGEST_RESULT_4BYTES (4) #define THROUGHPUT_MIN_SUBMISSIONS (100000) #define DP_POLLING_TIMEOUT (200000000) /****************************************************************************** * RSA/DSA Test Params *****************************************************************************/ #define MODULUS_256_BIT (256) #define MODULUS_512_BIT (512) #define MODULUS_768_BIT (768) #define MODULUS_1024_BIT (1024) #define MODULUS_1536_BIT (1536) #define MODULUS_2048_BIT (2048) #define MODULUS_3072_BIT (3072) #define MODULUS_4096_BIT (4096) #define EXPONENT_160_BIT (160) /*we are testing 180 bit, but the API requires an even number of bytes as an * input so we round up to 184 bits*/ #define EXPONENT_180_BIT (184) #define EXPONENT_224_BIT (224) #define EXPONENT_256_BIT (256) /****************************************************************************** * EC Test Params *****************************************************************************/ /*The API requires number of bytes as input, so we round up to the nearest * byte in the actual size*/ #define GFP_P192_SIZE_IN_BITS (192) #define GFP_P192_SIZE_IN_BYTES (24) #define GFP_P224_SIZE_IN_BITS (224) #define GFP_P224_SIZE_IN_BYTES (28) #define GFP_P256_SIZE_IN_BITS (256) #define GFP_P256_SIZE_IN_BYTES (32) #define GFP_P384_SIZE_IN_BITS (384) #define GFP_P384_SIZE_IN_BYTES (48) #define GFP_P521_SIZE_IN_BITS (521) #define GFP_P521_SIZE_IN_BYTES (66) #define GFP_BP512_SIZE_IN_BITS (512) #define GFP_BP512_SIZE_IN_BYTES (64) #define GF2_B163_SIZE_IN_BITS (163) #define GF2_B163_SIZE_IN_BYTES (21) #define GF2_B233_SIZE_IN_BITS (233) #define GF2_B233_SIZE_IN_BYTES (30) #define GF2_B283_SIZE_IN_BITS (283) #define GF2_B283_SIZE_IN_BYTES (36) #define GF2_B409_SIZE_IN_BITS (409) #define GF2_B409_SIZE_IN_BYTES (52) #define GF2_B571_SIZE_IN_BITS (571) #define GF2_B571_SIZE_IN_BYTES (72) #define GF2_K163_SIZE_IN_BITS (163) #define GF2_K163_SIZE_IN_BYTES (21) #define GF2_K233_SIZE_IN_BITS (233) #define GF2_K233_SIZE_IN_BYTES (30) #define GF2_K283_SIZE_IN_BITS (283) #define GF2_K283_SIZE_IN_BYTES (36) #define GF2_K409_SIZE_IN_BITS (409) #define GF2_K409_SIZE_IN_BYTES (52) #define GF2_K571_SIZE_IN_BITS (571) #define GF2_K571_SIZE_IN_BYTES (72) #ifdef SC_SM2_ENABLED /****************************************************************************** * SM2 Test Params *****************************************************************************/ #define GFP_SM2_SIZE_IN_BYTE (32) /*According to the SM2 spec, KDF function will pad a 4-bytes counter to the * end of each data block. For a performance reason, the KDF function need * more 4-bytes memory pre-malloced for the input data. */ #define KDF_COUNTER_PADDING (4) #define GFP_SM2_COORDINATE_SIZE_IN_BYTE GFP_SM2_SIZE_IN_BYTE /*encoded point, 1 byte header + 32 bytes x coordinate + 32 bytes y coordinate */ #define GFP_SM2_POINT_SIZE_IN_BYTE (2 * GFP_SM2_SIZE_IN_BYTE + 1) /*this is used for kdf function in SM2 key exchange * 32 bytes x coordinate + 32 bytes y coordinate + 4 bytes padding counter */ #define SM3_HASH_SIZE_IN_BYTE GFP_SM2_SIZE_IN_BYTE #define HEADER_UNCOMPRESSION_POINT (0x04) #define SECRET_KEY_LEN_IN_BYTE (16) #define GFP_SM2_SIZE_IN_BITS (256) #endif /* SC_SM2_ENABLED */ #define GFP_NISTP192_BITMASK 0x1 #define GFP_NISTP224_BITMASK 0x2 #define GFP_NISTP256_BITMASK 0x4 #define GFP_NISTP384_BITMASK 0x8 #define GFP_NISTP521_BITMASK 0x10 #define GFP_BP512_BITMASK 0x20 #define GF2_NISTK163_BITMASK 0x40 #define GF2_NISTK233_BITMASK 0x80 #define GF2_NISTK283_BITMASK 0x100 #define GF2_NISTK409_BITMASK 0x200 #define GF2_NISTK571_BITMASK 0x400 #define GF2_NISTB163_BITMASK 0x800 #define GF2_NISTB233_BITMASK 0x1000 #define GF2_NISTB283_BITMASK 0x2000 #define GF2_NISTB409_BITMASK 0x4000 #define GF2_NISTB571_BITMASK 0x8000 /*the following are defined in the framework, these are used for setup only * and are not to be used in functions not thread safe*/ #ifdef USER_SPACE extern Cpa8U (*thread_setup_g)[MAX_SETUP_STRUCT_SIZE_IN_BYTES]; extern Cpa8U (*thread_name_g)[THREAD_NAME_LEN]; extern thread_creation_data_t *testSetupData_g; extern sample_code_thread_t *threads_g; extern single_thread_test_data_t *singleThreadData_g; #else extern Cpa8U thread_setup_g[MAX_THREAD_VARIATION][MAX_SETUP_STRUCT_SIZE_IN_BYTES]; extern Cpa8U thread_name_g[MAX_THREAD_VARIATION][THREAD_NAME_LEN]; extern thread_creation_data_t testSetupData_g[MAX_THREAD_VARIATION]; extern sample_code_thread_t threads_g[MAX_THREADS]; extern single_thread_test_data_t singleThreadData_g[MAX_THREADS]; #endif extern Cpa32U testTypeCount_g; extern CpaCySymCipherDirection cipherDirection_g; #define ONE_PACKET (1) extern Cpa32U numPacketSizes; extern Cpa32U numWirelessPacketSizes; extern Cpa32U numModSizes; extern Cpa32U packetSizes[]; extern Cpa32U wirelessPacketSizes[]; extern Cpa32U modSizes[]; /*define a back off mechanism to stop performance operations constantly using * up 100% CPU.*/ CpaStatus setCyPollInterval(Cpa32U interval); #if defined(KERNEL_SPACE) /*set a context switch to allow OS re-schedule thread, it also allows other *threads CPU time on the same core*/ /*note the soft lockup can be compiled out of the kernel, if that is the case * this step is not needed*/ #define AVOID_SOFTLOCKUP \ do \ { \ yield(); \ /*set_current_state(TASK_INTERRUPTIBLE); */ \ /*schedule_timeout(0 * HZ); */ \ } while (0) #define AVOID_SOFTLOCKUP_POLL AVOID_SOFTLOCKUP #else /* defined(KERNEL_SPACE) */ /* FreeBSD scheduler is not handling "busy loops" as effective as Linux * especially in multi-thread environment where few polling threads * can be assigned to single CPU core. To avoid thread starvation * sched_yields has been replaced by usleep to balance CPU time more * equal across polling threads.*/ #define AVOID_SOFTLOCKUP_POLL \ do \ { \ if (cyPollingThreadsInterval_g) \ usleep(cyPollingThreadsInterval_g); \ else \ sched_yield(); \ } while (0) #define AVOID_SOFTLOCKUP \ do \ { \ sched_yield(); \ } while (0) #endif /* ****************************************************************************** * Byte Alignment settings ****************************************************************************** */ /*these are used to align memory to a byte boundary*/ #define BYTE_ALIGNMENT_8 (8) #define BYTE_ALIGNMENT_64 (64) /*prime number generation defines*/ #define NB_MR_ROUNDS (2) #define NUM_PRIME_GENERATION_RETRY_ATTEMPTS (1000) #define NUM_PRIME_GENERATION_ATTEMPTS (100) /** ***************************************************************************** * @ingroup cryptoThreads * * @description * allocate a CpaFlatBuffer pointer some memory, allocate the pData and * copy in any data if given * *****************************************************************************/ #define ALLOC_FLAT_BUFF_DATA(instanceHandle, \ pFlatBuf, \ sizeOfData, \ pCopyData, \ sizeOfCopyData, \ FREE_MEM_FUNC) \ do \ { \ status = bufferDataMemAlloc( \ instanceHandle, pFlatBuf, sizeOfData, pCopyData, sizeOfCopyData); \ if (CPA_STATUS_SUCCESS != status) \ { \ PRINT_ERR("Failed to allocate flat buffer memory\n"); \ FREE_MEM_FUNC; \ return CPA_STATUS_FAIL; \ } \ } while (0) #define MR_PRIME_MIN_BUFF_LEN (64) /** ***************************************************************************** * @ingroup cryptoThreads * * @description * For Miller Rabin Primality Tests. The size of the buffer MUST be * * n * (MAX(64,x)) * * where: * * - n is the requested number of rounds. * - x is the minimum number of bytes required to represent the prime * candidate, i.e. x = ceiling((ceiling(log2(p)))/8). * * This macro definition performs MAX(64,x) * *****************************************************************************/ #define MR_PRIME_LEN(x) \ do \ { \ if (x < MR_PRIME_MIN_BUFF_LEN) \ { \ x = MR_PRIME_MIN_BUFF_LEN; \ } \ } while (0) /** ***************************************************************************** * @ingroup cryptoThreads * Symmetric Setup Data. * @description * This structure contains data relating to setting up a symmetric test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct symmetric_test_params_s { /*stores the setup data thread running symmetric operations*/ CpaCySymSessionSetupData setupData; /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /*pointer to an array with NUM_PRE_ALLOCATED_BUFF_LISTS elements, each * element of this array stores the CpaFlatBuffer.dataLenInBytes * size, that each CpaBufferList points at. This array is used to support * the IMIX packet variation, otherwise all elements are the same size*/ Cpa32U *packetSizeInBytesArray; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; /*number of buffer lists to be created*/ Cpa32U numBuffers; /*Flag to digestIsAppended*/ Cpa32U numBuffLists; /*number of buffer to be created, only for sym perf load */ Cpa32U numLoops; /*number of Op in one cpaCySymDpEnqueueOpBatch, if numOpDpBatch is 0, * system will run cpaCySymDpEnqueueOp, otherwise cpaCySymDpEnqueueOpBatch */ Cpa32U numSessions; /* Unique thread ID based on the order in which the thread was created */ Cpa32U digestAppend; /*Flat Buffer Size in Buffer List * if flatBufferSizeInBytes is 0, there is one Flat buffer in the list */ Cpa32U flatBufferSizeInBytes; /*number of times numBuffers is looped over performing operations*/ Cpa32U numOpDpBatch; /* number of request will execute at one time. * If numRequests is 0, the operation should be performed immediately * (performOpNow = CPA_TRUE) * otherwise, On every Nth request (e.g. N=16), the operations will be * performed. */ Cpa32U numRequests; /*numberOfSession per thread*/ Cpa32U threadID; /* Identify to output of results if calling function is DataPlane API*/ CpaBoolean isDpApi; /*crypto source offset*/ Cpa32U cryptoSrcOffset; CpaBoolean isMultiSGL; /* Initial Value Length */ Cpa32U ivLength; /* Digest verify failures */ Cpa64U initialVerifyFailures; Cpa32U submissions; Cpa32U node; /**< Variable to trigger generating of random numbers for nested has inside * of setup function to avoid mismatch caused by using shared buffers * between threads. */ CpaCySymHashNestedModeSetupData nestedSetupData; Cpa8U nestedHashInnerPrefix[SHA512_DIGEST_LENGTH_IN_BYTES]; Cpa8U nestedHashOuterPrefix[SHA512_DIGEST_LENGTH_IN_BYTES]; CpaBoolean checkCongestion; /* If flat buffer size is not divisible by 1KB then enable the packet round * off */ CpaBoolean enableRoundOffPkt; /* Identify if the test is for SSL or TLS*/ CpaBoolean isTLS; } symmetric_test_params_t; /** ***************************************************************************** * @ingroup cryptoThreads * Asymmetric Setup Data. * @description * This structure contains data relating to setting up an asymmetric test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct asym_test_params_s { /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; /*size of Modulus to test*/ Cpa32U modulusSizeInBytes; /*size of the exponent to test*/ Cpa32U exponentSizeInBytes; /*number of buffers to be created*/ Cpa32U numBuffers; /*number of times numBuffers is looped over performing operations*/ Cpa32U numLoops; /*field to select the DH phase*/ dh_phase_t phase; /*rsa key type*/ CpaCyRsaPrivateKeyRepType rsaKeyRepType; /*rsa operation*/ CpaBoolean performEncrypt; Cpa32U threadID; CpaBoolean checkCongestion; #if CY_API_VERSION_AT_LEAST(3, 0) CpaBoolean enableKPT; CpaCyKptHandle kptKeyHandle; #endif } asym_test_params_t; /** ***************************************************************************** * @ingroup cryptoThreads * DSASetup Data. * @description * This structure contains data relating to setting up a DSA test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct dsa_test_params_s { /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; /*key length L and N, FIPS 186-3 specifies L and N bit length pairs of * (1024,160), (2048,224), (2048,256), and (3072,256).*/ Cpa32U pLenInBytes; Cpa32U qLenInBytes; /*number of buffers to be created*/ Cpa32U numBuffers; /*number of times numBuffers is looped over performing operations*/ Cpa32U numLoops; /* hash algorithm to use in getting the digest of the message being * signed by DSA*/ CpaCySymHashAlgorithm hashAlg; Cpa32U threadID; } dsa_test_params_t; /** ***************************************************************************** * @ingroup cryptoThreads * ECDSA Curve structure. * @description * This structure is used to store the elliptic curve data * ****************************************************************************/ typedef struct ec_curves_s { /*size of elliptic curve*/ Cpa8U nLenInBytes; /*type of EC curve*/ CpaCyEcFieldType fieldType; /*pointers to EC curve parameters*/ Cpa8U *p; Cpa32U sizeOfp; Cpa8U *r; Cpa32U sizeOfr; Cpa8U *a; Cpa32U sizeOfa; Cpa8U *b; Cpa32U sizeOfb; Cpa8U *xg; Cpa32U sizeOfxg; Cpa8U *yg; Cpa32U sizeOfyg; } ec_curves_t; /** ***************************************************************************** * @ingroup cryptoThreads * ECDSA Setup Data. * @description * This structure contains data relating to setting up an ECDSA test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct ecdsa_test_params_s { /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; Cpa32U nLenInBytes; CpaCyEcFieldType fieldType; Cpa32U numBuffers; Cpa32U numLoops; ecdsa_step_t step; ec_curves_t *pCurve; Cpa32U threadID; #if CY_API_VERSION_AT_LEAST(3, 0) CpaBoolean enableKPT; CpaCyKptHandle kptKeyHandle; #endif } ecdsa_test_params_t; #ifdef SC_SM2_ENABLED /** * ****************************************************************************** * @ingroup cryptoThreads * SM2 Setup Data. * @description * This structure contains data relating to setting up an SM2 performance * test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct sm2_test_params_s { /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; Cpa32U nLenInBytes; CpaCyEcFieldType fieldType; Cpa32U numBuffers; Cpa32U numLoops; sm2_step_t step; CpaFlatBuffer *digest; CpaFlatBuffer *message; CpaFlatBuffer *cipher; CpaFlatBuffer *random; CpaFlatBuffer *d; CpaFlatBuffer *d2; CpaFlatBuffer *xP; CpaFlatBuffer *yP; CpaFlatBuffer *x1; CpaFlatBuffer *y1; CpaFlatBuffer *x2; CpaFlatBuffer *y2; CpaCyEcsm2VerifyOpData **verifyOp; } sm2_test_params_t; /** ****************************************************************************** * @ingroup cryptoThreads * SM2 Temp Data. * @description * This structure contains data relating to setting up an SM2 performance * test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct sm2_perf_buf_s { CpaFlatBuffer *pC1Buffer; CpaFlatBuffer *pC2Buffer; CpaFlatBuffer *pC3Buffer; CpaFlatBuffer *pHashBuffer; CpaFlatBuffer *pIntermediateBuffer; CpaFlatBuffer *pEncOutputData; CpaFlatBuffer *pDecOutputData; CpaCyEcsm2EncryptOutputData *pEncPKEOut; CpaCyEcsm2DecryptOutputData *pDecPKEOut; CpaCyEcsm2KeyExOutputData *pKeyexPKEOut; } sm2_perf_buf_t; /** ******************************************************************************* * @ingroup cryptoThreads * SM2 Callback Tag. * @description * This structure contains data relating to setting up an SM2 performance * test. * The client needs to complete the information in this structure in order * to setup a test. * * *****************************************************************************/ typedef struct sm2_perf_test_s { sm2_test_params_t *setup; sm2_perf_buf_t *perf_buffer; } sm2_perf_test_t; #endif /* SC_SM2_ENABLED */ /** ***************************************************************************** * @ingroup cryptoThreads * PLS TFS Setup Data. * @description * This structure contains data relating to setting up an PLS TFS test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct tlspfs_test_params_s { asym_test_params_t param; Cpa32U nLenInBytes; Cpa32U fieldType; Cpa32U signOp; Cpa32U signSize; } tlspfs_test_params_t; /** ***************************************************************************** * @ingroup cryptoThreads * symSessionUpdateTest * * @description * setup a test to run a session update test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus sessionUpdateTest(Cpa32U numLoops, Cpa32U numBuffers); /** ***************************************************************************** * @ingroup cryptoThreads * symSessionUpdateTestDp * * @description * setup a test to run a session update test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus sessionUpdateTestDp(Cpa32U numLoops, Cpa32U numBuffers); #if CY_API_VERSION_AT_LEAST(2, 3) /** ***************************************************************************** * @ingroup cryptoThreads * @description * This structure contains data relating to setting up an HKDF test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct hkdf_test_params_s { /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /*numberOfSession per thread*/ Cpa32U threadID; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; /* test vector used */ Cpa32U testVector; /* HKDF operation */ Cpa8U hkdfOp; /* HKDF cipherSuite */ CpaCyKeyHKDFCipherSuite cipherSuite; /* number of buffers to be generated */ Cpa32U numBuffers; /* number of loops to be generated */ Cpa32U numLoops; } hkdf_test_params_t; /** ***************************************************************************** * @ingroup ecMontEdwdsThreads * @description * This structure contains data relating to setting up an ecMontEdwds test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct ec_montedwds_test_params_s { /* pointer to pre-allocated memory for thread to store performance data */ perf_data_t *performanceStats; /* crypto instance handle of service that has already been started */ CpaInstanceHandle cyInstanceHandle; /* numberOfSession per thread */ Cpa32U threadID; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; /* generator operation used */ CpaBoolean generator; /* field type */ CpaCyEcMontEdwdsCurveType curveType; /* test vector used */ Cpa32U vector; /* number of buffers to be generated */ Cpa32U numBuffers; /* number of loops to be generated */ Cpa32U numLoops; } ec_montedwds_test_params_t; #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ #if CY_API_VERSION_AT_LEAST(3, 0) /** ***************************************************************************** * @ingroup ecGenericThreads * @description * This structure contains data relating to setting up an ecGeneric test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct ec_generic_test_params_s { /* pointer to pre-allocated memory for thread to store performance data */ perf_data_t *performanceStats; /* crypto instance handle of service that has already been started */ CpaInstanceHandle cyInstanceHandle; /* numberOfSession per thread */ Cpa32U threadID; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; /* alignment */ Cpa32U alignment; /* generator operation used */ CpaBoolean generator; /* curve bitmask*/ Cpa32U curveBitmask; /* test vector used - currently not used as only 1 vector defined */ Cpa32U vector; /* number of buffers to be generated */ Cpa32U numBuffers; /* number of loops to be generated */ Cpa32U numLoops; /* EC Gen step */ ec_gen_step_t step; } ec_generic_test_params_t; #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ /** ***************************************************************************** * @ingroup cryptoThreads * NRBG Setup Data. * @description * This structure contains data relating to setting up an NRBG test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct nrbg_test_params_s { /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /* run test using synchronous or asynchronous mode */ sync_mode_t syncMode; /* number of bytes to be generated */ Cpa32U nLenInBytes; /* number of buffers to be generated */ Cpa32U numBuffers; /* number of loops to be generated */ Cpa32U numLoops; } nrbg_test_params_t; #ifdef SC_SM2_ENABLED /** ******************************************************************************* * @ingroup cryptoThreads * setupSm2Test * * @description * setup a test to run an sm2 performance test * - should be called before createTheads framework function ******************************************************************************/ CpaStatus setupSm2Test(Cpa32U nLenInBits, CpaCyEcFieldType fieldType, sync_mode_t syncMode, sm2_step_t step, Cpa32U numBuffers, Cpa32U numLoops); #endif /* SC_SM2_ENABLED */ /** ***************************************************************************** * @ingroup cryptoThreads * Random nested hash Setup Data. * @description * This structure contains data to trigger generating of random numbers for * nested hash inside of setup function to avoid mismatch caused by * using shared buffers between * ****************************************************************************/ typedef struct nested_hash_test_setup_s { /*API nested has structure*/ CpaCySymHashNestedModeSetupData nestedSetupData; /*Flag to generate random values inside setup function */ CpaBoolean generateRandom; } nested_hash_test_setup_t; /* ***************************************************************************** * FUNCTION PROTOTYPES * ****************************************************************************/ void processCallback(void *pCallbackTag); #define FREE_NUMA_MEM(buf) \ do \ { \ /*check that the pointer is not null, for an uninitialized flat buffer \ * the pData address could be 0x00000001*/ \ if (buf != NULL) \ { \ qaeMemFreeNUMA((void **)&buf); \ } \ } while (0) /** ***************************************************************************** * @ingroup cryptoThreads * startCyServices * * @description * This function starts all Crypto services available on the system *****************************************************************************/ CpaStatus startCyServices(void); /** ***************************************************************************** * @ingroup cryptoThreads * stopCyServices * * @description * This function stops all Crypto services running on the system, * any requests in flight are canceled *****************************************************************************/ CpaStatus stopCyServices(void); /** ***************************************************************************** * @ingroup cryptoThreads * getThroughput * * @description * get the throughput in Megabits per second * =(numPackets*packetSize)*(cycles/cpu_frequency) *****************************************************************************/ Cpa32U getThroughput(Cpa64U numPackets, Cpa32U packetSize, perf_cycles_t cycles); /** ***************************************************************************** * @ingroup cryptoThreads * getOpsPerSecond * * @description * This function gets the operations completed per second. One operation is * performed per packet so this is equivalent of packets processed per * second. *****************************************************************************/ Cpa32U getOpsPerSecond(Cpa64U responses, perf_cycles_t cycles); /** ***************************************************************************** * @ingroup cryptoThreads * printAsymStatsAndStopServices * * @description * This function prints asymmetric crypto performance stats *****************************************************************************/ CpaStatus printAsymStatsAndStopServices(thread_creation_data_t *data); /** ***************************************************************************** * @ingroup cryptoThreads * setupEcdsaTest * * @description * setup a test to run an ECDSA test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupEcdsaTest(Cpa32U nLenInBits, CpaCyEcFieldType fieldType, sync_mode_t syncMode, ecdsa_step_t step, Cpa32U numBuffers, Cpa32U numLoops); #if CY_API_VERSION_AT_LEAST(3, 0) /** ***************************************************************************** * @ingroup cryptoThreads * setupKpt2EcdsaTest * * @description * setup a test to run a KPT ECDSA test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupKpt2EcdsaTest(Cpa32U nLenInBits, CpaCyEcFieldType fieldType, sync_mode_t syncMode, ecdsa_step_t step, Cpa32U numBuffers, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleECDSACode * * @description * This function frees all memory related to KPT2 data. * ****************************************************************************/ void kpt2EcdsaFreeDataMemory(CpaCyKptEcdsaSignRSOpData *pKPTSignRSOpData, CpaCyKptUnwrapContext *pKptUnwrapCtx); #endif #if CY_API_VERSION_AT_LEAST(2, 3) /** ***************************************************************************** * @ingroup cryptoThreads * * @description *****************************************************************************/ CpaStatus setupKeyGenHkdfTest(sync_mode_t syncMode, Cpa32U testVector, CpaCyKeyHKDFOp hkdfOp, CpaCyKeyHKDFCipherSuite cipherSuite, Cpa32U numBuffers, Cpa32U numLoops); /* The API version check does not guarantee if EC Mont Edwards is * supported by the driver. This function checks by making an API * call to see if the status reports CPA_STATUS_UNSUPPORTED. */ CpaBoolean isECMontEdwdsSupported(void); /** ***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * setup a test to run an ecMontEdwds test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupEcMontEdwdsTest(sync_mode_t syncMode, CpaBoolean generator, CpaCyEcMontEdwdsCurveType curveType, Cpa32U vector, Cpa32U numBuffers, Cpa32U numLoops); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ #if CY_API_VERSION_AT_LEAST(3, 0) /* The API version check does not guarantee if EC Generic Curves are * supported by the driver. This function checks by making an API * call to see if the status reports CPA_STATUS_UNSUPPORTED. */ CpaBoolean isECGenericCurveSupported(void); /** ***************************************************************************** * @ingroup ecGenericThreads * * @description * setup a test to run an ecGeneric test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupEcGenericTest(sync_mode_t syncMode, Cpa32U alignment, CpaBoolean generator, Cpa32U curveSelectedBitmask, Cpa32U vector, Cpa32U numBuffers, Cpa32U numLoops, ec_gen_step_t step); #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ /** ***************************************************************************** * @ingroup cryptoThreads * setupTlsPfsTest * * @description * setup a test to run an TLSPFS test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupTlspfsTest(Cpa32U nLenInBits, CpaCyEcFieldType fieldType, Cpa32U signOp, Cpa32U signSize, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupDsaTest * * @description * setup a test to run an DSA test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupDsaTest(Cpa32U pLenInBits, Cpa32U qLenInBits, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupDsaSignTest * * @description * setup a test to run an DSA sign only test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupDsaSignTest(Cpa32U pLenInBits, Cpa32U qLenInBits, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupRsaTest * * @description * setup a test to run an RSA test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupRsaTest(Cpa32U modulusSize, CpaCyRsaPrivateKeyRepType rsaKeyRepType, sync_mode_t syncMode, Cpa32U numBuffs, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupRsaEncryptTest * * @description * setup a test to run an RSA test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupRsaEncryptTest(Cpa32U modulusSize, CpaCyRsaPrivateKeyRepType rsaKeyRepType, sync_mode_t syncMode, Cpa32U numBuffs, Cpa32U numLoops); #if CY_API_VERSION_AT_LEAST(3, 0) /** ***************************************************************************** * @ingroup cryptoThreads * setupKpt2RsaTest * * @description * setup a test to run KPT RSA test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupKpt2RsaTest(Cpa32U modulusSize, CpaCyRsaPrivateKeyRepType rsaKeyRepType, sync_mode_t syncMode, Cpa32U numBuffs, Cpa32U numLoops); /** ***************************************************************************** * @ingroup sampleKPTRSACode * * @description * This function frees all memory related to KPT2 data. * ****************************************************************************/ void kpt2RsaFreeDataMemory(asym_test_params_t *setup, CpaCyKptUnwrapContext **pKptUnwrapCtx, CpaCyKptRsaDecryptOpData **ppKPTDecryptOpData); #endif /** ***************************************************************************** * @ingroup cryptoThreads * setupDhTest * * @description * setup a test to run an Diffie Hellman test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupDhTest(Cpa32U modSizeInBits, Cpa32U expSizeInBits, sync_mode_t syncMode, dh_phase_t phase, Cpa32U numBuffs, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupIkeRsaTest * * @description * setup a test to run an Ike RSA simulation test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupIkeRsaTest(Cpa32U modSizeInBits, Cpa32U expSizeInBits, Cpa32U numBuffs, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleSymmetricTest * * @description * setup a symmetric test * This function needs to be called from main to setup a symmetric test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ******************************************************************************/ CpaStatus setupSymmetricTest(CpaCySymOp opType, CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCyPriority priority, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, nested_hash_test_setup_t *nestedModeSetupDataPtr, Cpa32U packetSize, Cpa32U bufferSizeInBytes, Cpa32U numBuffLists, Cpa32U numLoops, Cpa32U digestAppend); /** ***************************************************************************** * @ingroup cryptoThreads * setupCipherTest * * @description * This is the setup function for performing cipher performance tests * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupCipherTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCyPriority priority, sync_mode_t useAsync, Cpa32U packetSize, Cpa32U bufferSizeInBytes, Cpa32U numBufferLists, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupHashTest * * @description * This is the setup function for performing hash performance tests * should be called before createTheads framework function *****************************************************************************/ CpaStatus setupHashTest(CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, /*used to setup hash and hmac test, authKeyLenInBytes is 0 for plain hash operation*/ Cpa32U authKeyLengthInBytes, CpaCyPriority priority, sync_mode_t useAsync, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupAlgChainTest * * @description * This is the setup function for performing symmetric algorithm chaining * performance tests * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupAlgChainTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t useAsync, Cpa32U packetSize, Cpa32U bufferSizeInBytes, Cpa32U numBufferLists, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup an IPsec scenario where payload = IP packet, the IP header is not * encrypted thus requires an offset into the buffer to test. * * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupIpSecTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test with hash in nested mode, setting the data for nested * hash. * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances *******************************************************************************/ CpaStatus setupAlgChainTestNestedMode( CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, nested_hash_test_setup_t *nestedModeSetupData, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test with High Priority * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances *******************************************************************************/ CpaStatus setupAlgChainTestHP(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test with Normal Priority * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances *******************************************************************************/ CpaStatus setupAlgChainTestNP(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupAlgChainTestHPAsync * * @description * This is the setup function for performing symmetric algorithm chaining * performance tests fixing High priority and async mode * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupAlgChainTestHPAsync(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupSessionUpdateCipher * * @description * This is the setup function for performing cipher performance tests * with session update * - should be called before createTheads framework function */ CpaStatus setupSessionUpdateCipher(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupCipherUpdateHash * * @description * This is the setup function for performing hash performance tests * with session update * - should be called before createTheads framework function */ CpaStatus setupSessionUpdateHash(CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupSessionUpdateAlgChain * * @description * This is the setup function for performing symmetric algorithm chaining * performance tests with session update * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupSessionUpdateAlgChain(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupSessionUpdateCipherDp * * @description * This is the setup function for performing cipher performance tests * with session update * - should be called before createTheads framework function */ CpaStatus setupSessionUpdateCipherDp(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupCipherUpdateHashDp * * @description * This is the setup function for performing hash performance tests * with session update * - should be called before createTheads framework function */ CpaStatus setupSessionUpdateHashDp(CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * setupSessionUpdateAlgChainDp * * @description * This is the setup function for performing symmetric algorithm chaining * performance tests with session update * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupSessionUpdateAlgChainDp(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * sampleSymmetricPerformance * * @description * This function is the thread launched by the framework * It sets up the arrayOfBuffer sizes to test, copies data * from the single_thread_test_data_t to the symmetric_test_params * structure and calls the sampleSymmetricPerform function *****************************************************************************/ void sampleSymmetricPerformance(single_thread_test_data_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * sampleSymmetricPerform * * @description * This is a thread context function that does the Symmetric session * initialization and perform operations *****************************************************************************/ CpaStatus sampleSymmetricPerform(symmetric_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * sampleCreateBuffers * * @description * Sets an array of bufferLists and flatBuffers and populates them with * random data *****************************************************************************/ CpaStatus sampleCreateBuffers(CpaInstanceHandle instanceHandle, Cpa32U packetSizeInBytes[], CpaFlatBuffer *pFlatBuffArray[], CpaBufferList *pBuffListArray[], symmetric_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * sampleFreeBuffers * * @description * This function frees the memory allocated for the array of buffer * lists and flat buffers. *****************************************************************************/ void sampleFreeBuffers(CpaFlatBuffer *srcBuffPtrArray[], CpaBufferList *srcBuffListArray[], symmetric_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * dpSampleCreateBuffers * * @description * Sets an array of physical bufferLists and physical flatBuffers and * populates them with random data *****************************************************************************/ CpaStatus dpSampleCreateBuffers(CpaInstanceHandle instanceHandle, Cpa32U packetSizeInBytesArray[], CpaBufferList *pBuffListArray[], CpaPhysBufferList *pPhyBuffListArray[], symmetric_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * dpSampleFreeBuffers * * @description * This function frees the memory allocated for the array of physical * bufferlists and physical flat buffers. *****************************************************************************/ void dpSampleFreeBuffers(CpaBufferList *srcBuffListArray[], CpaPhysBufferList *srcPhyBuffListArray[], Cpa32U numBuffLists, Cpa32U numBuffers); /** ***************************************************************************** * @ingroup cryptoThreads * sampleRsaPerform * * @description * This is a thread context function that performs the RSA operations *****************************************************************************/ CpaStatus sampleRsaPerform(asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * symPerformCallback * * @description * This functions handles a symmetric crypto request callback * *****************************************************************************/ void symPerformCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult); /** ***************************************************************************** * @ingroup cryptoThreads * rsaDecryptCallback * * @description * This function handles the requested RSA operations callback * *****************************************************************************/ void rsaDecryptCallback(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaFlatBuffer *pOut); #if CY_API_VERSION_AT_LEAST(2, 3) /***************************************************************************** * @ingroup hkdfThreads * * @description * Asymmetric callback function: This function is invoked when a * HKDF operation has been processed *****************************************************************************/ void hkdfCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut); /***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * Asymmetric callback function: This function is invoked when a * ecMontEdwds operation has been processed *****************************************************************************/ void ecMontEdwdsCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ #if CY_API_VERSION_AT_LEAST(3, 0) /***************************************************************************** * @ingroup ecGenericThreads * * @description * Asymmetric callback function: This function is invoked when a * ecGenericVerify operation has been processed *****************************************************************************/ void ecGenericVerifyCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus); /***************************************************************************** * @ingroup ecGenericThreads * * @description * Asymmetric callback function: This function is invoked when a * ecGenericMultiply operation has been processed *****************************************************************************/ void ecGenericMultiplyCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk); #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ /** ***************************************************************************** * @ingroup cryptoThreads * printSymmetricPerfDataAndStopCyService * * @description * This function prints out symmetric crypto performance stats * *****************************************************************************/ CpaStatus printSymmetricPerfDataAndStopCyService(thread_creation_data_t *data); /** ***************************************************************************** * @ingroup cryptoThreads * printRsaPerfData * * @description * This function prints out RSA CRT performance stats * *****************************************************************************/ CpaStatus printRsaCrtPerfData(thread_creation_data_t *data); /** ***************************************************************************** * @ingroup cryptoThreads * printRsaPerfData * * @description * This function prints out RSA performance stats * *****************************************************************************/ CpaStatus printRsaPerfData(thread_creation_data_t *data); /** ***************************************************************************** * @ingroup cryptoThreads * getNumCyclesPerOp * * @description * This function gets the number of cycles taken to process a packet * *****************************************************************************/ perf_cycles_t getNumCyclesPerOp(perf_cycles_t numOfCycles, Cpa32U numOperations); /** ***************************************************************************** * @ingroup cryptoThreads * setCpaFlatBufferMSB * * @description * This function ensures that the MSB (pData[0]) is set (ie 0x80) * *****************************************************************************/ void setCpaFlatBufferMSB(CpaFlatBuffer *buf); /** ***************************************************************************** * @ingroup cryptoThreads * makeParam1SmallerThanParam2 * * @description * This function takes two pointers to data of equal length and ensures * that param1 is smaller than param2, by subtracting from param1 until * it is smaller than param2. The user needs to ensure that the data * pointed for param1 and param2 is of equal length * *****************************************************************************/ void makeParam1SmallerThanParam2(Cpa8U *param1, Cpa8U *param2, Cpa32U len, CpaBoolean msbSettingRequired); /** ***************************************************************************** * @ingroup cryptoThreads * conformMillerRabinData * * @description * As there's a limit on the minimum buffer size used to contain the Miller * Rabin Data(MAX(64,required_buffer_size)), we still must satisfy the * conditions that Miller Rabin data is >1 and less than Prime -1. * If the Miller Rabin buffer length is greater than the smallest Prime * Candidate buffer length, we need to zero the most significant bytes of * the difference and ensure that the actual data length is the same. * *****************************************************************************/ void conformMillerRabinData(CpaFlatBuffer *pMR, CpaFlatBuffer *pSmallestPC, Cpa32U rounds); /** ***************************************************************************** * @ingroup cryptoThreads * generatePrime * * @description * This function generates a prime number of a length as given in the * input CpaFlatBuffer * *****************************************************************************/ CpaStatus generatePrime(CpaFlatBuffer *primeCandidate, CpaInstanceHandle cyInstanceHandle, asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * generateHardCodedPrime1P * * @description * This function generates a hardcoded prime number of a length as given * in the input CpaFlatBuffer * *****************************************************************************/ CpaStatus generateHardCodedPrime1P(CpaFlatBuffer *primeCandidate, asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * generateHardCodedPrime2Q * * @description * This function generates a hardcoded prime number of a length as given * in the input CpaFlatBuffer * *****************************************************************************/ CpaStatus generateHardCodedPrime2Q(CpaFlatBuffer *primeCandidate, asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * freeArrayFlatBufferNUMA * * @description * This function frees the pData, the pointers and array of pointers of * a multi dimensional CpaFlatBuffer array * *****************************************************************************/ void freeArrayFlatBufferNUMA(CpaFlatBuffer *buf, Cpa32U numBuffs); /** ***************************************************************************** * @ingroup cryptoThreads * setHashDigestLen * * @description * This function sets a hash digest length based on the passed in hash * algorithm * *****************************************************************************/ Cpa32U setHashDigestLen(CpaCySymHashAlgorithm hashAlgorithm); /** ***************************************************************************** * @ingroup cryptoThreads * getHashPartialPacketSize * * @description * This function gets hash partial packet size based on the input algorithm * and packet size * *****************************************************************************/ Cpa32U getHashPartialPacketSize(CpaCySymHashAlgorithm hashAlgorithm, Cpa32U packetSize); /** ***************************************************************************** * @ingroup cryptoThreads * calcDigest * * @description * This function calculates the digest of a given message * *****************************************************************************/ CpaStatus calcDigest(CpaInstanceHandle instanceHandle, CpaFlatBuffer *msg, CpaFlatBuffer *digest, CpaCySymHashAlgorithm hashAlg); /** ***************************************************************************** * @ingroup cryptoThreads * calcSWDigest * * @description * This function use IA(SW) to calculate the digest of a given message * *****************************************************************************/ CpaStatus calcSWDigest(CpaFlatBuffer *msg, CpaFlatBuffer *digest, CpaCySymHashAlgorithm hashAlg); CpaStatus getCyInstanceCapabilities(CpaCyCapabilitiesInfo *pCap); CpaStatus getCySpecificInstanceCapabilities(CpaInstanceHandle instanceHandle, CpaCyCapabilitiesInfo *pCap); CpaStatus getCryptoInstanceCapabilities(CpaCyCapabilitiesInfo *cap, Cpa32U instType); #if CY_API_VERSION_AT_LEAST(3, 0) CpaStatus getSymAsymInstanceCapabilities(CpaCyCapabilitiesInfo *pCap, Cpa32U instType); #endif CpaStatus getCySymQueryCapabilities(CpaCySymCapabilitiesInfo *pCap); /** ***************************************************************************** * @ingroup cryptoThreads * removeSymSession * * @description * This function removes symmetric session (in ASYNC mode it waits for * pending callbacks to finish). * *****************************************************************************/ CpaStatus removeSymSession(CpaInstanceHandle instanceHandle, CpaCySymSessionCtx pSessionCtx); /** ***************************************************************************** * @ingroup cryptoThreads * bufferDataMemAlloc * * @description * This function allocates physically contiguous pData memory to a * CpaFlatBuffer * *****************************************************************************/ CpaStatus bufferDataMemAlloc(CpaInstanceHandle instanceHandle, CpaFlatBuffer *buf, Cpa32U size, Cpa8U *copyData, Cpa32U sizeOfCopyData); /** ***************************************************************************** * @ingroup cryptoThreads * generateRSAKey * * @description * This function generates RSA public and private keys * *****************************************************************************/ CpaStatus generateRSAKey(CpaInstanceHandle instanceHandle, Cpa32U modulusLenInBytes, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey, asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * sampleCodeCyGetNode * * @description * This function gets the node affinity of a crypto instance * *****************************************************************************/ CpaStatus sampleCodeCyGetNode(CpaInstanceHandle instanceHandle, Cpa32U *node); /** ***************************************************************************** * @ingroup cryptoThreads * dhCallback * * @description * This function processes Diffie Hellman responses * *****************************************************************************/ void dhCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut); /** ***************************************************************************** * @ingroup cryptoThreads * dhPhase1Setup * * @description * This function sets up Diffie Hellman Phase1 data * *****************************************************************************/ CpaStatus dhPhase1Setup(asym_test_params_t *setup, CpaCyDhPhase1KeyGenOpData **pAlicePhase1, CpaCyDhPhase1KeyGenOpData **pBobPhase1, CpaFlatBuffer **pAlicePublicValue, CpaFlatBuffer **pBobPublicValue, CpaCyRsaPublicKey **pKey); /** ***************************************************************************** * @ingroup cryptoThreads * dhPhase1 * * @description * This function performs Diffie Hellman Phase1 operations * *****************************************************************************/ CpaStatus dhPhase1(CpaCyDhPhase1KeyGenOpData **pCpaDhOpDataP1, CpaFlatBuffer **pLocalOctetStringPV, asym_test_params_t *setup, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * dhPhase2Setup * * @description * This function sets up Diffie Hellman Phase2 data * *****************************************************************************/ CpaStatus dhPhase2Setup(CpaFlatBuffer *pSecretKey[], CpaCyDhPhase1KeyGenOpData *pCpaDhOpDataP1[], CpaCyDhPhase2SecretKeyGenOpData *pCpaDhOpDataP2[], CpaFlatBuffer *pLocalOctetStringPV[], asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * dhPhase2 * * @description * This function performs Diffie Hellman Phase2 operations * *****************************************************************************/ CpaStatus dhPhase2Perform(CpaFlatBuffer **pOctetStringSecretKey, CpaCyDhPhase2SecretKeyGenOpData **pCpaDhOpDataP2, asym_test_params_t *setup, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * dhMemFreePh1 * * @description * This function frees Diffie Hellman Phase1 data * *****************************************************************************/ void dhMemFreePh1(asym_test_params_t *setup, CpaCyDhPhase1KeyGenOpData **pAlicePhase1, CpaFlatBuffer **pAlicePublicValue, CpaCyDhPhase1KeyGenOpData **pBobPhase1, CpaFlatBuffer **pBobPublicValue); /** ***************************************************************************** * @ingroup cryptoThreads * dhMemFreePh2 * * @description * This function frees Diffie Hellman Phase2 data * *****************************************************************************/ void dhMemFreePh2(asym_test_params_t *setup, CpaFlatBuffer **pAliceSecretKey, CpaCyDhPhase2SecretKeyGenOpData **pAlicePhase2, CpaFlatBuffer **pBobSecretKey, CpaCyDhPhase2SecretKeyGenOpData **pBobPhase2); /** ***************************************************************************** * @ingroup cryptoThreads * rsaEncryptDataSetup * * @description * This function sets RSA encrypt operation data * *****************************************************************************/ CpaStatus rsaEncryptDataSetup(CpaFlatBuffer *pEncryptData[], CpaCyRsaEncryptOpData *pOpdata[], CpaFlatBuffer *pOutputData[], asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * rsaDecryptDataSetup * * @description * This function sets RSA decrypt operation data * *****************************************************************************/ CpaStatus rsaDecryptDataSetup(CpaFlatBuffer *pDecryptData[], CpaCyRsaDecryptOpData *pOpdata[], CpaFlatBuffer *pOutputData[], asym_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * genKeyArray * * @description * This function generates RSA keys * *****************************************************************************/ CpaStatus genKeyArray(asym_test_params_t *setup, CpaCyRsaPrivateKey *pPrivateKey[], CpaCyRsaPublicKey *pPublicKey[]); /** ***************************************************************************** * @ingroup cryptoThreads * rsaSetOpDataKeys * * @description * This copies RSA keys into the encrypt and decrypt operation data * structures * *****************************************************************************/ void rsaSetOpDataKeys(asym_test_params_t *setup, CpaCyRsaDecryptOpData *pDecryptOpData[], CpaCyRsaEncryptOpData *pEncryptOpData[], CpaCyRsaPrivateKey *pPrivateKey[], CpaCyRsaPublicKey *pPublicKey[]); /** ***************************************************************************** * @ingroup cryptoThreads * rsaFreeDataMemory * * @description * This function frees RSA encrypt and decrypt data memory * *****************************************************************************/ void rsaFreeDataMemory(asym_test_params_t *setup, CpaCyRsaDecryptOpData *pOpdata[], CpaFlatBuffer *pOutputData[], CpaCyRsaEncryptOpData *pEncryptOpdata[], CpaFlatBuffer *pInputData[]); /** ***************************************************************************** * @ingroup cryptoThreads * rsaFreeKeyMemory * * @description * This function frees RSA key memory * *****************************************************************************/ void rsaFreeKeyMemory(asym_test_params_t *setup, CpaCyRsaPrivateKey *pPrivateKey[], CpaCyRsaPublicKey *pPublicKey[]); /** ***************************************************************************** * @ingroup cryptoThreads * sampleRsaEncrypt * * @description * This function performs RSA encryption operations * *****************************************************************************/ CpaStatus sampleRsaEncrypt(asym_test_params_t *setup, CpaCyRsaEncryptOpData **pEncryptOpData, CpaFlatBuffer **pOutputData, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * sampleRsaDecrypt * * @description * This function performs RSA decryption operations * *****************************************************************************/ CpaStatus sampleRsaDecrypt(asym_test_params_t *setup, CpaCyRsaDecryptOpData **pDecryptOpData, CpaFlatBuffer **pOutputData, CpaCyRsaPrivateKey **pPrivateKey, CpaCyRsaPublicKey **pPublicKey, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * allocArrayOfPointers * * @description * This function allocates memory to an array of pointers to structures * *****************************************************************************/ CpaStatus allocArrayOfPointers(CpaInstanceHandle instanceHandle, void **buf, Cpa32U numBuffs); CpaStatus allocArrayOfVirtPointers(void **buf, Cpa32U numBuffs); /** ***************************************************************************** * @ingroup cryptoThreads * cyAllocAndSetupInstances * * @description * This function allocates memory for crypto instances * *****************************************************************************/ CpaStatus cyAllocAndSetupInstances(void); /** ***************************************************************************** * @ingroup cryptoThreads * waitForResponses * * @description * This function waits for all response submitted by crypto threads * *****************************************************************************/ CpaStatus waitForResponses(perf_data_t *perfData, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops); /** ***************************************************************************** * @ingroup cryptoThreads * cyCreatePollingThreadsIfPollingIsEnabled * * @description * This function checks whether each instance handle is set for polling * and will allocate create and start the same number polling threads * as they are polling instances. * @pre numInstances_g is set and all instances have been started. * @post numPolledInstances_g is set by the function to the number of polling * instances available. * *****************************************************************************/ CpaStatus cyCreatePollingThreadsIfPollingIsEnabled(void); /** ***************************************************************************** * @ingroup cryptoThreads * cyCheckAllInstancesArePolled * * @description * This function checks whether all CY instances are configured for polling * mode, it is used to support the Data Plane API where interrupt mode is * not supported * @pre numInstances_g is set and all instances have been started. * * @retval CPA_TRUE All instances are configured for polling * @retval CPA_FALSE At least one instance is configured for interrupt * mode or cannot inspect the CpaInstanceInfo2 * structure. * *****************************************************************************/ CpaBoolean cyCheckAllInstancesArePolled(void); /** * ***************************************************************************** * @ingroup compressionThreads * cyDpPollRemainingOperations * * @description * Poll for remaining operations, this function will timeout after * SAMPLE_CODE_WAIT_DEFAULT have elapsed. * * @threadSafe * Yes * * @param[in] perfData pointer to performance structure * @param[in] instanceHandle API CpaInstanceHandle * * @retval CPA_STATUS_SUCCESS No operations to poll for or all remaining * operations have been polled. * @retval CPA_STATUS_FAIL Failure from polling operation or timeout. ******************************************************************************/ CpaStatus cyDpPollRemainingOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle); /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * function to print out hash performance header ******************************************************************************/ void printHashAlg(CpaCySymHashSetupData hashSetupData); /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * function to print out cipher performance header ******************************************************************************/ void printCipherAlg(CpaCySymCipherSetupData cipherSetupData); /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * print out performance test type ******************************************************************************/ void printSymTestType(symmetric_test_params_t *setup); /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * print out performance data from a collection of threads that * were all running the same setup ******************************************************************************/ CpaStatus printSymmetricPerfDataAndStopCyService(thread_creation_data_t *data); CpaStatus cyPollNumOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations); CpaStatus cyPollNumOperationsTimeout(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations, Cpa64U timeout); /*switch the direction of the symmetric performance module*/ CpaStatus switchCipherDirection(void); /************************************************************************ * Name: checkCapability * Description: Checks whether the given logical instance supports * cipherAlg/hashAlg * Return : True if supported, False, otherwise ************************************************************************/ CpaBoolean checkCapability(CpaInstanceHandle *cyInstanceHandle, symmetric_test_params_t *symTestSetup); /** ***************************************************************************** * @ingroup sampleRSACode * sampleCodeAsymPollInstance * * @description * Wrapper function to crypto specific polling function which polls * an asymmetric instance. * ******************************************************************************/ CpaStatus sampleCodeAsymPollInstance(CpaInstanceHandle instanceHandle, Cpa32U response_quota); /** ***************************************************************************** * @ingroup sampleSymmetricCode * sampleCodeSymPollInstance * * @description * Wrapper function to crypto specific polling function which polls * a symmetric instance. * ******************************************************************************/ CpaStatus sampleCodeSymPollInstance(CpaInstanceHandle instanceHandle, Cpa32U response_quota); /** ******************************************************************************** * @ingroup sampleCryptoCode * stopCyServices * * @description * this API stops the Crypto services. * @threadSafe * No * @param[in] data pointer to test data structure ********************************************************************************/ CpaStatus stopCyServicesFromCallback(thread_creation_data_t *data); CpaStatus dsaGenZ(CpaInstanceHandle instanceHandle, CpaFlatBuffer *msg, CpaCySymHashAlgorithm hashAlg, CpaFlatBuffer *dsaZ); #endif /*_CRYPTO_UTILS_H_*/ /** ***************************************************************************** * @ingroup checkForChachapolySupport * * @description * helper function to check for the instances that support * CPA_CY_SYM_CIPHER_CHACHA ******************************************************************************/ CpaStatus checkForChachapolySupport(void); cpa_sample_code_dh_perf.c000066400000000000000000001515001503624047500356610ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_dh_perf.c * * @defgroup dhThreads * * @ingroup dhThreads * * @description * This is a sample code that uses Diffie-Hellman APIs. * In order to use this algorithm, 3 elements have to be set: * - a prime number p (the modulus) * - a base g * - a random value x * * This sample code defines arbitrary values for p, g and x. We simulate * two peers, Bob and Alice who wish to create a shared secret key * * Phase 1. Alices's & Bob's public value PV=g^x mod p is calculated. Both * share the same p & g values but use a different x value * * Phase 2. Based on the public value returned by the other peer, the * prime number p and Alices secret value x, the private key for Alices is * calculated * * Alices Private Key = BobsPV^x mod p * Bob's Private Key = AlicesPV^x mod p * * Again the x for Alice and Bob is different, but both should calculate * the same private key * *****************************************************************************/ #include "cpa.h" #include "cpa_types.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_utils_common.h" #include "cpa_sample_code_crypto_utils.h" #ifdef SC_DEV_INFO_ENABLED #include "cpa_dev.h" #endif #include "icp_sal_poll.h" #include "qat_perf_cycles.h" extern Cpa32U packageIdCount_g; void dhPerformance(single_thread_test_data_t *testSetup); /***************************************************************************** * @ingroup dhThreads * * @description * Asymmetric callback function: This function is invoked when a * Diffie Hellman operation has been processed *****************************************************************************/ void dhCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { processCallback(pCallbackTag); } /*************************************************************************** * @ingroup dhThreads * * @description * DH PHASE 1 Secret number generator * * this function generates the secret value x to be used in the Diffie Hellman * phase 1 operation ie x in PublicValue = g^x mod p * ****************************************************************************/ static void dhPhase1GenX(CpaCyDhPhase1KeyGenOpData *pCpaDhOpDataP1, asym_test_params_t *setup) { /*Choose x by some random method, where 0 < x < p-1*/ generateRandomData(pCpaDhOpDataP1->privateValueX.pData, pCpaDhOpDataP1->privateValueX.dataLenInBytes); /*make sure MSB is set*/ setCpaFlatBufferMSB(&(pCpaDhOpDataP1->privateValueX)); if (setup->modulusSizeInBytes == setup->exponentSizeInBytes) { makeParam1SmallerThanParam2( pCpaDhOpDataP1->privateValueX.pData, pCpaDhOpDataP1->primeP.pData, pCpaDhOpDataP1->privateValueX.dataLenInBytes, CPA_TRUE); } return; } #define FREE_DH_PHASE1_SETUP_MEM() \ dhMemFreePh1(setup, \ ppAlicePhase1, \ ppAlicePublicValue, \ ppBobPhase1, \ ppBobPublicValue) /*************************************************************************** * @ingroup dhThreads * * @description * populate 2 peers Phase1 opData with p, g & x, where p&g is shared and x is * random for each peer * * *************************************************************************/ CpaStatus dhPhase1Setup(asym_test_params_t *setup, CpaCyDhPhase1KeyGenOpData **ppAlicePhase1, CpaCyDhPhase1KeyGenOpData **ppBobPhase1, CpaFlatBuffer **ppAlicePublicValue, CpaFlatBuffer **ppBobPublicValue, CpaCyRsaPublicKey **ppPublicKey) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U i = 0; Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return CPA_STATUS_FAIL; } if (NULL == ppAlicePhase1) { PRINT_ERR("Error ppAlicePhase1 Null pointer passed\n"); return CPA_STATUS_FAIL; } if (NULL == ppAlicePublicValue) { PRINT_ERR("Error ppAlicePublicValue Null pointer passed\n"); return CPA_STATUS_FAIL; } if (NULL == ppBobPhase1) { PRINT_ERR("Error ppBobPhase1 Null pointer passed\n"); return CPA_STATUS_FAIL; } if (NULL == ppBobPublicValue) { PRINT_ERR("Error ppAlicePhase1 Null pointer passed\n"); return CPA_STATUS_FAIL; } /*set Alice phase1 opData*/ for (i = 0; i < setup->numBuffers; i++) { ppAlicePhase1[i] = qaeMemAlloc(sizeof(CpaCyDhPhase1KeyGenOpData)); /*use the pre-generated primeP if supplied*/ /*allocate p*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(ppAlicePhase1[i]->primeP), setup->modulusSizeInBytes, NULL, 0, FREE_DH_PHASE1_SETUP_MEM()); /*allocate g*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(ppAlicePhase1[i]->baseG), setup->modulusSizeInBytes, NULL, 0, FREE_DH_PHASE1_SETUP_MEM()); /*allocate exponent x*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(ppAlicePhase1[i]->privateValueX), setup->exponentSizeInBytes, NULL, 0, FREE_DH_PHASE1_SETUP_MEM()); if (ppPublicKey != NULL) { memcpy(ppAlicePhase1[i]->primeP.pData, ppPublicKey[i]->modulusN.pData, ppPublicKey[i]->modulusN.dataLenInBytes); setCpaFlatBufferMSB(&(ppAlicePhase1[i]->primeP)); ppAlicePhase1[i]->primeP.dataLenInBytes = ppPublicKey[i]->modulusN.dataLenInBytes; } else { if (useStaticPrime == 1) { /*generate hardcoded p, where p is a prime number*/ status = generateHardCodedPrime1P(&(ppAlicePhase1[i]->primeP), setup); } else { /*generate p, where p is a prime number*/ status = generatePrime(&(ppAlicePhase1[i]->primeP), setup->cyInstanceHandle, setup); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to generate primeP for phase1, %d\n", status); FREE_DH_PHASE1_SETUP_MEM(); return status; } } /*Choose g by some random method, where 0 < g < p*/ generateRandomData(ppAlicePhase1[i]->baseG.pData, ppAlicePhase1[i]->baseG.dataLenInBytes); /*make sure MSB in baseG is set and that it a smaller value than p*/ setCpaFlatBufferMSB(&(ppAlicePhase1[i]->baseG)); makeParam1SmallerThanParam2(ppAlicePhase1[i]->baseG.pData, ppAlicePhase1[i]->primeP.pData, ppAlicePhase1[i]->baseG.dataLenInBytes, CPA_TRUE); /*generate the random x value*/ dhPhase1GenX(ppAlicePhase1[i], setup); /* Allocate memory for the PublicValue buffer */ ppAlicePublicValue[i] = qaeMemAlloc(sizeof(CpaFlatBuffer)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, ppAlicePublicValue[i], setup->modulusSizeInBytes, NULL, 0, FREE_DH_PHASE1_SETUP_MEM()); /*set Bob phase1 opData*/ ppBobPhase1[i] = qaeMemAlloc(sizeof(CpaCyDhPhase1KeyGenOpData)); /* we only allocate exponent x, both clients share p & g*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(ppBobPhase1[i]->privateValueX), setup->exponentSizeInBytes, NULL, 0, FREE_DH_PHASE1_SETUP_MEM()); ppBobPhase1[i]->primeP.dataLenInBytes = setup->modulusSizeInBytes; /*both clients share the same P, so point Bobs data to Alices data*/ ppBobPhase1[i]->primeP.pData = ppAlicePhase1[i]->primeP.pData; ppBobPhase1[i]->baseG.dataLenInBytes = setup->modulusSizeInBytes; /*both clients share the same G*/ ppBobPhase1[i]->baseG.pData = ppAlicePhase1[i]->baseG.pData; dhPhase1GenX(ppBobPhase1[i], setup); /* Allocate memory for the PublicValue buffer */ ppBobPublicValue[i] = qaeMemAlloc(sizeof(CpaFlatBuffer)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, ppBobPublicValue[i], setup->modulusSizeInBytes, NULL, 0, FREE_DH_PHASE1_SETUP_MEM()); } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(dhPhase1Setup); /*************************************************************************** * @ingroup dhThreads * * @description * DH-PHASE1 * * this function performs the Diffie Hellman phase 1 operation * * *************************************************************************/ CpaStatus dhPhase1(CpaCyDhPhase1KeyGenOpData **pCpaDhOpDataP1, CpaFlatBuffer **pLocalOctetStringPV, asym_test_params_t *setup, Cpa32U numBuffers, Cpa32U numLoops) { Cpa32U loops = 0; CpaStatus status = CPA_STATUS_FAIL; Cpa32U i = 0; CpaInstanceInfo2 *instanceInfo = NULL; Cpa32U busyLoopValue = busyLoopCounter_g; perf_cycles_t startBusyLoop = 0, endBusyLoop = 0; Cpa32U busyLoopCount = 0, staticAssign = 0; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_FAIL; perf_data_t *pPerfData = setup->performanceStats; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; #endif instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); return CPA_STATUS_FAIL; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } /*pre-set the number of ops we plan to submit*/ setup->performanceStats->numOperations = (Cpa64U)numBuffers * numLoops; setup->performanceStats->responses = 0; setup->performanceStats->packageId = instanceInfo->physInstId.packageId; coo_init(setup->performanceStats, setup->performanceStats->numOperations); /* Completion used in callback */ sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); /*Should not wait at barrier if only 1 loop, as this implies Alice and we * want to measure this */ if (DH_PHASE_1 == setup->phase) { // we will execute only phase 1 sampleCodeBarrier(); setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); } /** Perform Diffie-Hellman Phase 1 operations */ for (loops = 0; loops < numLoops; loops++) { for (i = 0; i < numBuffers; i++) { do { coo_req_start(setup->performanceStats); status = cpaCyDhKeyGenPhase1( setup->cyInstanceHandle, dhCallback, /* asynchronous mode */ setup->performanceStats, /* Opaque user data; */ pCpaDhOpDataP1[i], /* Structure containing p, g and x*/ pLocalOctetStringPV[i]); /*Public value (output) */ coo_req_stop(setup->performanceStats, status); /*this is a back off mechanism to stop the code * continually submitting requests. Without this the CPU * can report a soft lockup if it continually loops * on busy*/ if (status == CPA_STATUS_RETRY) { #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo->isPolled) { sampleCodeAsymPollInstance(setup->cyInstanceHandle, 0); nextPoll = numOps + asymPollingInterval_g; } } #endif setup->performanceStats->retries++; if (RETRY_LIMIT == (setup->performanceStats->retries % (RETRY_LIMIT + 1))) { /*perform a context switch to give other processes * a go*/ AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (DH_PHASE_1 == setup->phase && CPA_CC_BUSY_LOOPS == iaCycleCount_g) { busyLoop(busyLoopValue, &staticAssign); busyLoopCount++; } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy(setup->performanceStats, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } } #endif } } #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( setup->performanceStats, setup->syncMode, numBuffers, numLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Thread %u timeout.", setup->threadID); } } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { setup->performanceStats->busyLoopCount = busyLoopCount; setup->performanceStats->busyLoopValue = busyLoopValue; busyLoopTimeStamp(); startBusyLoop = busyLoopTimeStamp(); for (i = 0; i < busyLoopCount; i++) { busyLoop(busyLoopValue, &staticAssign); } endBusyLoop = busyLoopTimeStamp(); setup->performanceStats->totalBusyLoopCycles = endBusyLoop - startBusyLoop; setup->performanceStats->offloadCycles = (setup->performanceStats->endCyclesTimestamp - setup->performanceStats->startCyclesTimestamp) - setup->performanceStats->totalBusyLoopCycles; if (setup->performanceStats->responses > 0) { do_div(setup->performanceStats->offloadCycles, setup->performanceStats->responses); } } coo_average(setup->performanceStats); coo_deinit(setup->performanceStats); sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); qaeMemFree((void **)&instanceInfo); return status; } EXPORT_SYMBOL(dhPhase1); #define FREE_DH_PHASE2_SETUP_MEM() \ do \ { \ Cpa32U j = 0; \ for (j = 0; j < setup->numBuffers; j++) \ { \ if (NULL != pSecretKey[j]) \ { \ qaeMemFreeNUMA((void **)&pSecretKey[j]->pData); \ qaeMemFree((void **)&pSecretKey[j]); \ } \ if (NULL != pCpaDhOpDataP2[j]) \ { \ qaeMemFree((void **)&pCpaDhOpDataP2[j]); \ } \ } \ } while (0); /*************************************************************************** * @ingroup dhThreads * * @description * Phase2 setup, copy the peers Public Value in the phase2 op data structure * use the same p and random number from phase 1 * * *************************************************************************/ CpaStatus dhPhase2Setup(CpaFlatBuffer *pSecretKey[], CpaCyDhPhase1KeyGenOpData *pCpaDhOpDataP1[], CpaCyDhPhase2SecretKeyGenOpData *pCpaDhOpDataP2[], CpaFlatBuffer *pLocalOctetStringPV[], asym_test_params_t *setup) { Cpa32U i = 0; Cpa32U node = 0; CpaStatus status = CPA_STATUS_FAIL; if (NULL == pSecretKey) { PRINT_ERR("Error pSecretKey Null pointer passed\n"); return CPA_STATUS_FAIL; } if (NULL == pCpaDhOpDataP1) { PRINT_ERR("Error pCpaDhOpDataP1 Null pointer passed\n"); return CPA_STATUS_FAIL; } if (NULL == pCpaDhOpDataP2) { PRINT_ERR("Error pCpaDhOpDataP2 Null pointer passed\n"); return CPA_STATUS_FAIL; } if (NULL == pLocalOctetStringPV) { PRINT_ERR("Error pLocalOctetStringPV Null pointer passed\n"); return CPA_STATUS_FAIL; } status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return CPA_STATUS_FAIL; } /** In a typical application, at this stage, the public information * (prime number, base and the public value that has just been * calculated by cpaCyDhKeyGenPhase1) would be sent to the other user. * As cpaCyDhKeyGenPhase1 runs in asynchronous mode, it is sure that the * public value has been calculated. * The user would then send back a remoteOctet value. */ for (i = 0; i < setup->numBuffers; i++) { pSecretKey[i] = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pSecretKey[i]) { PRINT_ERR("could not allocate mem for secret key %u\n", i); FREE_DH_PHASE2_SETUP_MEM(); return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pSecretKey[i], setup->modulusSizeInBytes, NULL, 0, FREE_DH_PHASE2_SETUP_MEM()); pCpaDhOpDataP2[i] = qaeMemAlloc(sizeof(CpaCyDhPhase2SecretKeyGenOpData)); if (NULL == pCpaDhOpDataP2[i]) { PRINT("pCpaDhOpDataP2[%d] is NULL \n", i); FREE_DH_PHASE2_SETUP_MEM(); return CPA_STATUS_FAIL; } memset(pCpaDhOpDataP2[i], 0, sizeof(CpaCyDhPhase2SecretKeyGenOpData)); pCpaDhOpDataP2[i]->primeP.pData = pCpaDhOpDataP1[i]->primeP.pData; pCpaDhOpDataP2[i]->primeP.dataLenInBytes = setup->modulusSizeInBytes; pCpaDhOpDataP2[i]->remoteOctetStringPV.pData = pLocalOctetStringPV[i]->pData; pCpaDhOpDataP2[i]->remoteOctetStringPV.dataLenInBytes = pLocalOctetStringPV[i]->dataLenInBytes; pCpaDhOpDataP2[i]->privateValueX.pData = pCpaDhOpDataP1[i]->privateValueX.pData; pCpaDhOpDataP2[i]->privateValueX.dataLenInBytes = pCpaDhOpDataP1[i]->privateValueX.dataLenInBytes; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(dhPhase2Setup); /*************************************************************************** * @ingroup dhThreads * * @description * perform the phase2 operation to produce the secret key * * *************************************************************************/ CpaStatus dhPhase2Perform(CpaFlatBuffer **pOctetStringSecretKey, CpaCyDhPhase2SecretKeyGenOpData **pCpaDhOpDataP2, asym_test_params_t *setup, Cpa32U numBuffers, Cpa32U numLoops) { Cpa32U i = 0; Cpa32U loops = 0; CpaStatus status = CPA_STATUS_FAIL; CpaCyGenFlatBufCbFunc cbFunc = NULL; CpaInstanceInfo2 *instanceInfo = NULL; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_FAIL; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; perf_data_t *pPerfData = setup->performanceStats; #endif DECLARE_IA_CYCLE_COUNT_VARIABLES(); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { timeStampTime_g = getTimeStampTime(); PRINT("timeStampTime_g %llu\n", timeStampTime_g); } instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); return CPA_STATUS_FAIL; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } /*pre-set the number of ops we plan to submit*/ memset(setup->performanceStats, 0, sizeof(perf_data_t)); setup->performanceStats->numOperations = (Cpa64U)numLoops * numBuffers; setup->performanceStats->responses = 0; setup->performanceStats->retries = 0; setup->performanceStats->packageId = instanceInfo->physInstId.packageId; /* Completion used in callback */ sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); coo_init(setup->performanceStats, setup->performanceStats->numOperations); if (NULL == pOctetStringSecretKey) { PRINT_ERR("Error pOctetStringSecretKey Null pointer passed\n"); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } if (NULL == pCpaDhOpDataP2) { PRINT_ERR("Error pCpaDhOpDataP2 Null pointer passed\n"); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } if (ASYNC == setup->syncMode) { cbFunc = dhCallback; } /*this barrier will wait until all threads get to this point*/ /*don't want to wait here if its alice as she only loops once*/ sampleCodeBarrier(); setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); for (loops = 0; loops < numLoops; loops++) { for (i = 0; i < numBuffers; i++) { do { coo_req_start(setup->performanceStats); status = cpaCyDhKeyGenPhase2Secret(setup->cyInstanceHandle, cbFunc, setup->performanceStats, pCpaDhOpDataP2[i], pOctetStringSecretKey[i]); coo_req_stop(setup->performanceStats, status); /* this is a back off mechanism to stop the code * continually calling the Decrypt operation when the * acceleration units are busy. Without this the CPU * can report a soft lockup if it continually loops * on busy */ if (status == CPA_STATUS_RETRY) { #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo->isPolled) { icp_sal_CyPollInstance(setup->cyInstanceHandle, 0); nextPoll = numOps + asymPollingInterval_g; } } #endif setup->performanceStats->retries++; if (RETRY_LIMIT == (setup->performanceStats->retries) % (RETRY_LIMIT + 1)) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { BUSY_LOOP(); } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy(setup->performanceStats, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } } #endif if (CPA_STATUS_SUCCESS != status) { break; } } if (CPA_STATUS_SUCCESS != status) { break; } } #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( setup->performanceStats, setup->syncMode, numBuffers, numLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Thread %u timeout.", setup->threadID); } } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { IA_CYCLE_COUNT_CALCULATION(); } coo_average(setup->performanceStats); coo_deinit(setup->performanceStats); /* Completion used in callback */ sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); qaeMemFree((void **)&instanceInfo); return status; } EXPORT_SYMBOL(dhPhase2Perform); /*************************************************************************** * @ingroup dhThreads * * @description * free the memory allocated during phase1 * * *************************************************************************/ void dhMemFreePh1(asym_test_params_t *setup, CpaCyDhPhase1KeyGenOpData **ppAlicePhase1, CpaFlatBuffer **ppAlicePublicValue, CpaCyDhPhase1KeyGenOpData **ppBobPhase1, CpaFlatBuffer **ppBobPublicValue) { Cpa32U i = 0; for (i = 0; i < setup->numBuffers; i++) { if (NULL != ppAlicePublicValue) { if (NULL != ppAlicePublicValue[i]) { qaeMemFreeNUMA((void **)&ppAlicePublicValue[i]->pData); qaeMemFree((void **)&ppAlicePublicValue[i]); } } if (NULL != ppAlicePhase1) { /* Free opData buffers */ if (NULL != ppAlicePhase1[i]) { if (NULL != ppAlicePhase1[i]->primeP.pData) qaeMemFreeNUMA((void **)&ppAlicePhase1[i]->primeP.pData); if (NULL != ppAlicePhase1[i]->baseG.pData) qaeMemFreeNUMA((void **)&ppAlicePhase1[i]->baseG.pData); if (NULL != ppAlicePhase1[i]->privateValueX.pData) qaeMemFreeNUMA( (void **)&ppAlicePhase1[i]->privateValueX.pData); qaeMemFree((void **)&ppAlicePhase1[i]); } } if (NULL != ppBobPhase1) { if (NULL != ppBobPhase1[i]) { if (NULL != ppBobPhase1[i]->privateValueX.pData) qaeMemFreeNUMA( (void **)&ppBobPhase1[i]->privateValueX.pData); qaeMemFree((void **)&ppBobPhase1[i]); } } if (NULL != ppBobPublicValue) { if (NULL != ppBobPublicValue[i]) { if (NULL != ppBobPublicValue[i]->pData) qaeMemFreeNUMA((void **)&ppBobPublicValue[i]->pData); qaeMemFree((void **)&ppBobPublicValue[i]); } } } } EXPORT_SYMBOL(dhMemFreePh1); /*************************************************************************** * @ingroup dhThreads * * @description * This function frees the phase 2 dynamic memory, since we point to some of the * memory allocated in phase1, we only need to free the private key * and the Phase2 opData * * *************************************************************************/ void dhMemFreePh2(asym_test_params_t *setup, CpaFlatBuffer **pAliceSecretKey, CpaCyDhPhase2SecretKeyGenOpData **pAlicePhase2, CpaFlatBuffer **pBobSecretKey, CpaCyDhPhase2SecretKeyGenOpData **pBobPhase2) { Cpa32U i = 0; for (i = 0; i < setup->numBuffers; i++) { if (NULL != pAliceSecretKey) { if (NULL != pAliceSecretKey[i]) { qaeMemFreeNUMA((void **)&pAliceSecretKey[i]->pData); qaeMemFree((void **)&pAliceSecretKey[i]); } } if (NULL != pBobSecretKey) { if (NULL != pBobSecretKey[i]) { qaeMemFreeNUMA((void **)&pBobSecretKey[i]->pData); qaeMemFree((void **)&pBobSecretKey[i]); } } if (NULL != pBobPhase2) { if (NULL != pBobPhase2[i]) { qaeMemFree((void **)&pBobPhase2[i]); } } if (NULL != pAlicePhase2) { if (NULL != pAlicePhase2[i]) { qaeMemFree((void **)&pAlicePhase2[i]); } } } } EXPORT_SYMBOL(dhMemFreePh2); #define DH_MEM_FREE() \ do \ { \ FREE_DH_PHASE1_SETUP_MEM(); \ qaeMemFree((void **)&ppAlicePublicValue); \ qaeMemFree((void **)&ppBobPublicValue); \ qaeMemFree((void **)&ppAlicePhase1); \ qaeMemFree((void **)&ppBobPhase1); \ dhMemFreePh2( \ setup, pAliceSecretKey, pAlicePhase2, pBobSecretKey, pBobPhase2); \ qaeMemFree((void **)&pAliceSecretKey); \ qaeMemFree((void **)&pBobSecretKey); \ qaeMemFree((void **)&pBobPhase2); \ qaeMemFree((void **)&pAlicePhase2); \ } while (0) /***************************************************************************** * @ingroup dhThreads * * @description * Perform Diffie-Hellman phase 1 and 2 operations *****************************************************************************/ static CpaStatus dhPerform(asym_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; perf_data_t *pDhData = NULL; /** Pointer that will contain the public value for Alice(returned by * cpaCyDhKeyGenPhase1) */ CpaFlatBuffer **ppAlicePublicValue = NULL; /** Pointer that will contain the public value for Bob(returned by * cpaCyDhKeyGenPhase1) */ CpaFlatBuffer **ppBobPublicValue = NULL; /** Pointer that will contain the private key created by Alice * (returned by cpaCyDhKeyGenPhase2) */ CpaFlatBuffer **pAliceSecretKey = NULL; /** Pointer that will contain the private key created by Bob * (returned by cpaCyDhKeyGenPhase2) */ CpaFlatBuffer **pBobSecretKey = NULL; CpaCyDhPhase2SecretKeyGenOpData **pAlicePhase2 = NULL; CpaCyDhPhase2SecretKeyGenOpData **pBobPhase2 = NULL; CpaCyDhPhase1KeyGenOpData **ppAlicePhase1 = NULL; CpaCyDhPhase1KeyGenOpData **ppBobPhase1 = NULL; Cpa32U node = 0; Cpa32U numLoopsPhase1 = 1; CpaBoolean stopAtPhase1 = CPA_FALSE; CpaInstanceInfo2 *instanceInfo2 = NULL; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&ppAlicePublicValue, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate ppAlicePublicValue\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&ppBobPublicValue, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate ppBobPublicValue\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&ppAlicePhase1, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate ppAlicePhase1\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&ppBobPhase1, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate ppBobPhase1\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&pAliceSecretKey, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate pAliceSecretKey\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&pBobSecretKey, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate pBobSecretKey\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&pAlicePhase2, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate pAlicePhase2\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } status = allocArrayOfVirtPointers((void **)&pBobPhase2, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate pBobPhase2\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } /*use the pre-allocate performance stats to store performance data, this * points to an element in perfStats_g array in the framework, each thread * points to a unique element of perfStats_g array, perfStats_g is a * section of memory that the framework allocates to threads to store * performance data*/ pDhData = setup->performanceStats; if (pDhData == NULL) { PRINT_ERR("perf stats pointer is NULL\n"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } memset(pDhData, 0, sizeof(perf_data_t)); instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); DH_MEM_FREE(); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2) != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); DH_MEM_FREE(); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } pDhData->packageId = instanceInfo2->physInstId.packageId; qaeMemFree((void **)&instanceInfo2); /*************************************************************************** * PHASE1 ***************************************************************************/ if (DH_PHASE_1 == setup->phase) { // we will execute only phase 1 numLoopsPhase1 = setup->numLoops; stopAtPhase1 = CPA_TRUE; } /*generate p, g & x and populate into Alice and Bobs phase1 opData * Allocate memory for public values*/ status = dhPhase1Setup(setup, ppAlicePhase1, ppBobPhase1, ppAlicePublicValue, ppBobPublicValue, NULL); if (CPA_STATUS_SUCCESS != status) { DH_MEM_FREE(); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } /*calculate Alices secret keys*/ /* we only need to loop once to calculate all secret keys, later we * loop multiple times on Bob to measure performance*/ status = dhPhase1(ppAlicePhase1, ppAlicePublicValue, setup, setup->numBuffers, 1 /*loop once over all buffers*/); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("error performing DH Phase 1 for Alice\n"); /* Free Memory */ DH_MEM_FREE(); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } status = dhPhase1(ppBobPhase1, ppBobPublicValue, setup, setup->numBuffers, numLoopsPhase1); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("error performing DH Phase 1 for Bob\n"); /* Free Memory */ DH_MEM_FREE(); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } // check if we should stop at phase 1 if (CPA_TRUE == stopAtPhase1) { /* Free Memory */ DH_MEM_FREE(); return status; } /*************************************************************************** * PHASE2 ***************************************************************************/ status = dhPhase2Setup( pAliceSecretKey, ppAlicePhase1, pAlicePhase2, ppBobPublicValue, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("error performing DH Phase 2 setup for Alice\n"); /* Free Memory */ DH_MEM_FREE(); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } status = dhPhase2Setup( pBobSecretKey, ppBobPhase1, pBobPhase2, ppAlicePublicValue, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("error performing DH Phase 2 setup for Bob\n"); /* Free Memory */ DH_MEM_FREE(); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } /*calculate Alices secret keys*/ /* we only need to loop once to calculate all private keys, later we * loop multiple times on Bob to measure performance*/ status = dhPhase2Perform(pAliceSecretKey, pAlicePhase2, setup, setup->numBuffers, 1 /*loop once over all buffers*/); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("error performing DH Phase 2 for Alice\n"); /* Free Memory */ DH_MEM_FREE(); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } /*calculate Bobs secret keys*/ status = dhPhase2Perform( pBobSecretKey, pBobPhase2, setup, setup->numBuffers, setup->numLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("error performing DH Phase 2 for Bob\n"); /* Free Memory */ DH_MEM_FREE(); setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return status; } /*check that the secret keys match*/ /*should really check at the end of each loop in bob*/ for (i = 0; i < setup->numBuffers; i++) { if (memcmp(pAliceSecretKey[i]->pData, pBobSecretKey[i]->pData, setup->modulusSizeInBytes) != 0) { PRINT_ERR("Error Secret Keys do not match %d\n", i); status = CPA_STATUS_FAIL; } } /* Free Memory */ DH_MEM_FREE(); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } /***************************************************************************** * @ingroup dhThreads * * @description * Print the diffie hellman performance stats *****************************************************************************/ static CpaStatus dhPrintStats(thread_creation_data_t *data) { if (DH_PHASE_1 == ((asym_test_params_t *)data->setupPtr)->phase) { PRINT("DIFFIE-HELLMAN PHASE 1\n"); } else { PRINT("DIFFIE-HELLMAN PHASE 2\n"); } PRINT("Modulus Size %17u\n", data->packetSize * NUM_BITS_IN_BYTE); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /***************************************************************************** * @ingroup dhThreads * * @description * This function is called by the framework to start DH performance threads *****************************************************************************/ void dhPerformance(single_thread_test_data_t *testSetup) { asym_test_params_t dhSetup = { 0 }; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; asym_test_params_t *params = (asym_test_params_t *)testSetup->setupPtr; CpaInstanceInfo2 *instanceInfo = NULL; #ifdef SC_DEV_INFO_ENABLED CpaDeviceInfo deviceInfo = {0}; #endif testSetup->passCriteria = getPassCriteria(); /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space is does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*set the print function that can be used to print stats at the end of the * test*/ testSetup->statsPrintFunc = (stats_print_func_t)dhPrintStats; /*give our thread a unique memory location to store performance stats*/ dhSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /* give our thread a logical crypto instance to use * use % to wrap around the max number of instances*/ dhSetup.threadID = testSetup->threadID; dhSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(dhSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } #ifdef SC_DEV_INFO_ENABLED /* check whether asym service enabled or not for the instance */ status = cpaGetDeviceInfo(instanceInfo->physInstId.acceleratorId, &deviceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaGetDeviceInfo failed", __func__, __LINE__); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } if (CPA_FALSE == deviceInfo.cyAsymEnabled) { PRINT_ERR("%s::%d Error! cyAsymEnabled service not enabled for the " "configured instance\n", __func__, __LINE__); dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } #endif if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } dhSetup.modulusSizeInBytes = params->modulusSizeInBytes; dhSetup.exponentSizeInBytes = params->exponentSizeInBytes; dhSetup.numBuffers = params->numBuffers; dhSetup.numLoops = params->numLoops; dhSetup.syncMode = params->syncMode; dhSetup.phase = params->phase; /*launch function that does all the work*/ status = dhPerform(&dhSetup); if (CPA_STATUS_SUCCESS != status) { sampleCodeBarrier(); PRINT("DH Thread %u FAILED\n", testSetup->threadID); } else { dhSetup.performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; } qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadComplete(testSetup->threadID); } EXPORT_SYMBOL(dhPerformance); /***************************************************************************** * @ingroup dhThreads * * @description * this function is used to setup a DH test. Once called, the framework * createThreads function can be called to created multiple DH threads over * many cores *****************************************************************************/ CpaStatus setupDhTest(Cpa32U modSizeInBits, Cpa32U expSizeInBits, sync_mode_t syncMode, dh_phase_t phase, Cpa32U numBuffs, Cpa32U numLoops) { /*thread_setup_g is a multi-dimensional array that stores the setup for all * thread * variations in an array of characters. we store our test setup at the * start of the second array ie index 0. There maybe multi thread types * (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure*/ asym_test_params_t *dhSetup = NULL; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } if (iaCycleCount_g) { #ifdef POLL_INLINE enablePollInline(); #endif } /* start polling threads if polling is enabled in the configuration file */ if (!poll_inline_g) { if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } dhSetup = (asym_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)dhPerformance; testSetupData_g[testTypeCount_g].packetSize = modSizeInBits / NUM_BITS_IN_BYTE; dhSetup->modulusSizeInBytes = modSizeInBits / NUM_BITS_IN_BYTE; dhSetup->exponentSizeInBytes = expSizeInBits / NUM_BITS_IN_BYTE; dhSetup->syncMode = syncMode; dhSetup->numBuffers = numBuffs; dhSetup->numLoops = numLoops; dhSetup->phase = phase; return CPA_STATUS_SUCCESS; } cpa_sample_code_drbg_perf.c000066400000000000000000001000641503624047500362030ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_drbg_perf.c * * @ingroup drbgPerformance * * @description * This file contains the DRBG performance functions * *****************************************************************************/ #include "cpa_sample_code_drbg_perf.h" #include "icp_sal_drbg_impl.h" /* internal data structure to be filled in personalizationString for * DRBG session setup */ typedef struct personalize_s { struct timeval tv; int tmid; } personalize_t; typedef struct nrbg_sample_data_s { CpaCyNrbgOpData opData; /* NRBG client information */ IcpSalDrbgGetEntropyInputCbFunc pClientCbFunc; void *pClientCallbackTag; void *pClientOpData; } nrbg_sample_data_t; static CpaStatus drbgRemoveSession(drbg_test_params_t *setup, CpaCyDrbgSessionSetupData *pSessionSetupData, CpaCyDrbgSessionHandle *pSessionHdl, Cpa32U numSessions); static CpaStatus drbgSetupSession(drbg_test_params_t *setup, CpaCyDrbgSessionSetupData *pSessionSetupData, CpaCyDrbgSessionHandle *pSessionHdl, Cpa32U node); static CpaStatus drbgPerformOp(drbg_test_params_t *setup, CpaCyDrbgSessionHandle *pSessionHdl, Cpa32U node); extern void nrbgUnregisterDrbgImplFunctions(void); /* Previously set GetEntropy function pointer */ static IcpSalDrbgGetEntropyInputFunc pPrevGetEntropyInputFunc = NULL; /* Previously set GetNonce function pointer */ static IcpSalDrbgGetNonceFunc pPrevGetNonceFunc = NULL; /* Previously set IsDFReq function pointer */ static IcpSalDrbgIsDFReqFunc pPrevDrbgIsDFReqFunc = NULL; /* A counter for ImplFucntion is registered or not */ /* Only when this number equal 0, then real impl function can be called*/ static int drbgImplFunctionsRegistered = 0; /* A semaphore to make the impl function register/unregister only once */ static sample_code_semaphore_t semaphoreImplFunction; /** ***************************************************************************** * @ingroup drbgPerformance * NRBG Internal Callback Function * * @description * This is an internal callback function that will be used to signal * the caller that the asynchronous operation is completed. The signal * is performed by calling the client-supplied callback function. * *****************************************************************************/ static void drbgPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { perf_data_t *pDrbgPerf = (perf_data_t *)pCallbackTag; if (NULL == pDrbgPerf) { PRINT_ERR("Invalid data in CallbackTag\n"); return; } pDrbgPerf->responses++; /* post the semaphore until all session are Okay */ if (pDrbgPerf->responses == pDrbgPerf->numOperations) { pDrbgPerf->endCyclesTimestamp = sampleCodeTimestamp(); sampleCodeSemaphorePost(&pDrbgPerf->comp); } return; } /** ***************************************************************************** * @ingroup drbgPerformance * NRBG Internal Callback Function * * @description * This is an internal callback function that will be used to signal * the caller that the asynchronous operation is completed. The signal * is performed by calling the client-supplied callback function. * *****************************************************************************/ static void nrbgCallback(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaFlatBuffer *pOut) { nrbg_sample_data_t *pNrbgData = NULL; IcpSalDrbgGetEntropyInputCbFunc pClientCb = NULL; void *pClientCallbackTag = NULL; void *pClientOpData = NULL; Cpa32U lengthReturned = 0; if (NULL == pCallbackTag) { PRINT_ERR("pCallbackTag is null"); return; } pNrbgData = (nrbg_sample_data_t *)pCallbackTag; if (CPA_STATUS_SUCCESS == status) { lengthReturned = pNrbgData->opData.lengthInBytes; } pClientCb = pNrbgData->pClientCbFunc; pClientCallbackTag = pNrbgData->pClientCallbackTag; pClientOpData = pNrbgData->pClientOpData; qaeMemFree((void **)&pNrbgData); pClientCb(pClientCallbackTag, status, pClientOpData, lengthReturned, pOut); } /*************************************************************************** * @ingroup drbgPerformance * * @description * Print the performance stats of the elliptic curve dsa operations ***************************************************************************/ static CpaStatus drbgPrintStats(thread_creation_data_t *data) { PRINT("DRBG Size %23u\n", data->packetSize); printSymmetricPerfDataAndStopCyService(data); return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup drbgPerformance * * @description * This function implements the DRBG implementation-specific * 'Get Entropy Input' function by calling cpaCyNrbgGetEntropy API. * *****************************************************************************/ static CpaStatus nrbgGetEntropy(IcpSalDrbgGetEntropyInputCbFunc pCb, void *pCallbackTag, icp_sal_drbg_get_entropy_op_data_t *pOpData, CpaFlatBuffer *pBuffer, Cpa32U *pLengthReturned) { CpaStatus status = CPA_STATUS_SUCCESS; CpaCyGenFlatBufCbFunc pNrbgCbFunc = NULL; nrbg_sample_data_t *pNrbgData = NULL; CpaCyCapabilitiesInfo cyCap; CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; /* For now use the first crypto instance - assumed to be started already */ status = cpaCyGetInstances(1, &instanceHandle); if (instanceHandle == NULL) { return CPA_STATUS_FAIL; } /* Verify that the instance has NRBG capabilities */ status = cpaCyQueryCapabilities(instanceHandle, &cyCap); if (CPA_STATUS_SUCCESS != status) { return status; } /* Check if the instance support NRBG*/ if (cyCap.nrbgSupported != CPA_TRUE) { PRINT_ERR("Instance does not support NRBG\n"); return CPA_STATUS_RESOURCE; } if (NULL == pOpData) { PRINT_ERR("Invalid parameter -- pOpData\n"); return CPA_STATUS_INVALID_PARAM; } if ((NULL == pLengthReturned) && (NULL == pCb)) { PRINT_ERR("Invalid parameter -- pLengthReturned\n"); return CPA_STATUS_INVALID_PARAM; } pNrbgData = qaeMemAlloc(sizeof(nrbg_sample_data_t)); if (NULL == pNrbgData) { PRINT_ERR("Failed to allocate pNrbgData\n"); return CPA_STATUS_FAIL; } /* number of bytes to be generated */ pNrbgData->opData.lengthInBytes = pOpData->maxLength; /* store client information */ pNrbgData->pClientCbFunc = pCb; pNrbgData->pClientCallbackTag = pCallbackTag; pNrbgData->pClientOpData = (void *)pOpData; /* use local callback function on asynchronous operation */ if (NULL != pCb) { pNrbgCbFunc = nrbgCallback; } do { /* call nrbg function to get entropy */ status = cpaCyNrbgGetEntropy(instanceHandle, pNrbgCbFunc, pNrbgData, &(pNrbgData->opData), pBuffer); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { status = (CPA_STATUS_INVALID_PARAM == status) ? status : CPA_STATUS_FAIL; PRINT_ERR("cpaCyNrbgGetEntropy failed. (status = %d)\n", status); qaeMemFree((void **)&pNrbgData); return status; } if (NULL == pCb) { *pLengthReturned = pNrbgData->opData.lengthInBytes; qaeMemFree((void **)&pNrbgData); } return CPA_STATUS_SUCCESS; } static CpaStatus nrbgGetNonce(icp_sal_drbg_get_entropy_op_data_t *pOpData, CpaFlatBuffer *pBuffer, Cpa32U *pLengthReturned) { CpaStatus status = CPA_STATUS_SUCCESS; status = nrbgGetEntropy(NULL, NULL, pOpData, pBuffer, pLengthReturned); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("nrbgGetEntropy failed. (status = %d)\n", status); } return status; } /** ***************************************************************************** * @ingroup drbgPerformance * NRBG Is Derivation Function(DF) Required Function * * @description * This function implements the DRBG implementation-specific * 'Is Derivation Function Required' function. * *****************************************************************************/ static CpaBoolean nrbgIsDFRequired(void) { return CPA_TRUE; } static CpaBoolean nrbgNotDFRequired(void) { return CPA_FALSE; } static void nrbgRegisterDrbgImplFunctions(CpaBoolean dFReq) { CpaStatus status; status = sampleCodeSemaphoreWait(&semaphoreImplFunction, SAMPLE_CODE_WAIT_FOREVER); if (CPA_STATUS_SUCCESS == status) { if (0 == drbgImplFunctionsRegistered) { pPrevGetEntropyInputFunc = icp_sal_drbgGetEntropyInputFuncRegister(nrbgGetEntropy); pPrevGetNonceFunc = icp_sal_drbgGetNonceFuncRegister(nrbgGetNonce); if (CPA_TRUE == dFReq) { pPrevDrbgIsDFReqFunc = icp_sal_drbgIsDFReqFuncRegister(nrbgIsDFRequired); } else { pPrevDrbgIsDFReqFunc = icp_sal_drbgIsDFReqFuncRegister(nrbgNotDFRequired); } /* add the register number per thread */ } drbgImplFunctionsRegistered++; sampleCodeSemaphorePost(&semaphoreImplFunction); } return; } void nrbgUnregisterDrbgImplFunctions(void) { CpaStatus status; status = sampleCodeSemaphoreWait(&semaphoreImplFunction, SAMPLE_CODE_WAIT_FOREVER); if (CPA_STATUS_SUCCESS == status) { drbgImplFunctionsRegistered--; if (0 == drbgImplFunctionsRegistered) { icp_sal_drbgGetEntropyInputFuncRegister(pPrevGetEntropyInputFunc); icp_sal_drbgGetNonceFuncRegister(pPrevGetNonceFunc); icp_sal_drbgIsDFReqFuncRegister(pPrevDrbgIsDFReqFunc); sampleCodeSemaphoreDestroy(&semaphoreImplFunction); } else { sampleCodeSemaphorePost(&semaphoreImplFunction); } } } /* * This function performs a drbg generate operation. */ static CpaStatus drbgPerformOp(drbg_test_params_t *setup, CpaCyDrbgSessionHandle *pSessionHdl, Cpa32U node) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U drbgDataSize = setup->lengthInBytes; perf_data_t *pDrbgPerf = NULL; CpaCyDrbgGenOpData *pCurOpData = NULL; CpaCyDrbgGenOpData **pOpData; Cpa8U *pDrbgData = NULL; CpaFlatBuffer *pDrbgOut; Cpa32U numLoops, numSessions; Cpa32U anyFail = 0, ses; pDrbgPerf = setup->performanceStats; numSessions = setup->numSessions; pOpData = qaeMemAlloc(sizeof(CpaCyDrbgGenOpData *) * numSessions); if (NULL == pOpData) { PRINT_ERR("Failed to alloc memory\n"); return (CPA_STATUS_FAIL); } pDrbgOut = qaeMemAlloc(sizeof(CpaFlatBuffer) * numSessions); if (NULL == pDrbgOut) { PRINT_ERR("Failed to alloc memory\n"); qaeMemFree((void **)&pOpData); return (CPA_STATUS_FAIL); } /* Init the pointer array to be 0 */ for (ses = 0; ses < numSessions; ses++) { pOpData[ses] = NULL; pDrbgOut[ses].pData = NULL; } /* allocate all memory needed */ for (ses = 0; ses < numSessions; ses++) { pDrbgData = (Cpa8U *)qaeMemAllocNUMA(drbgDataSize, node, BYTE_ALIGNMENT_64); if (NULL == pDrbgData) { anyFail++; break; } pDrbgOut[ses].pData = pDrbgData; pDrbgOut[ses].dataLenInBytes = drbgDataSize; pCurOpData = (CpaCyDrbgGenOpData *)qaeMemAlloc(sizeof(CpaCyDrbgGenOpData)); if (NULL == pCurOpData) { anyFail++; break; } memset(pCurOpData, 0, sizeof(CpaCyDrbgGenOpData)); pCurOpData->sessionHandle = pSessionHdl[ses]; pCurOpData->lengthInBytes = drbgDataSize; pCurOpData->secStrength = setup->secStrength; pCurOpData->predictionResistanceRequired = setup->predictionResistanceRequired; pCurOpData->additionalInput.dataLenInBytes = 0; pCurOpData->additionalInput.pData = NULL; pOpData[ses] = pCurOpData; } /*this barrier will wait until all threads get to this point */ sampleCodeBarrier(); if (0 == anyFail) { sampleCodeSemaphoreInit(&pDrbgPerf->comp, 0); pDrbgPerf->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { /* prepare this data structure for callback */ pDrbgPerf->responses = 0; pDrbgPerf->numOperations = numSessions; for (ses = 0; ses < numSessions; ses++) { do { status = cpaCyDrbgGen( setup->cyInstanceHandle, (void *)pDrbgPerf, /* data sent as is to the callback function*/ pOpData[ses], /* operational data struct */ &pDrbgOut[ses]); /* dst buffer list */ if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; /*if the acceleration engine is busy pause for a * moment by making a context switch*/ if (RETRY_LIMIT == (setup->performanceStats->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyDrbgGen failed. (status = %d)\n", status); break; } else { } } if (CPA_STATUS_SUCCESS == status) { if (sampleCodeSemaphoreWait(&pDrbgPerf->comp, SAMPLE_CODE_WAIT_DEFAULT) != CPA_STATUS_SUCCESS) { PRINT_ERR("timeout or interruption in cpaCyDrbgGen\n"); status = CPA_STATUS_FAIL; } } } // end of for numLoop sampleCodeSemaphoreDestroy(&pDrbgPerf->comp); } /* * At this stage, the callback function has returned, so it is * sure that the structures won't be needed any more. Free the * memory! */ for (ses = 0; ses < numSessions; ses++) { if (pOpData[ses]) { qaeMemFree((void **)&pOpData[ses]); } if (pDrbgOut[ses].pData) { qaeMemFreeNUMA((void **)&pDrbgOut[ses].pData); } } qaeMemFree((void **)&pOpData); qaeMemFree((void **)&pDrbgOut); return status; } static CpaStatus drbgSetupSession(drbg_test_params_t *setup, CpaCyDrbgSessionSetupData *pSessionSetupData, CpaCyDrbgSessionHandle *pSessionHdl, Cpa32U node) { CpaCyDrbgSessionHandle sessionHdl; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U sessionSize = 0; void *personalization; Cpa32U ses, seedLen = 0; Cpa32U numSessions; numSessions = setup->numSessions; /* Clear the pointer to be NULL */ for (ses = 0; ses < numSessions; ses++) { personalization = NULL; pSessionSetupData[ses].personalizationString.pData = NULL; pSessionSetupData[ses].personalizationString.dataLenInBytes = 0; pSessionHdl[ses] = NULL; } for (ses = 0; ses < numSessions; ses++) { pSessionSetupData[ses].predictionResistanceRequired = setup->predictionResistanceRequired; pSessionSetupData[ses].secStrength = setup->secStrength; if (setup->predictionResistanceRequired == CPA_TRUE) { personalization = qaeMemAllocNUMA(sizeof(personalize_t), node, BYTE_ALIGNMENT_64); if (NULL == personalization) { PRINT("Failed to alloc memory\n"); status = CPA_STATUS_FAIL; break; } memset(personalization, 0, sizeof(personalize_t)); pSessionSetupData[ses].personalizationString.dataLenInBytes = sizeof(personalize_t); pSessionSetupData[ses].personalizationString.pData = personalization; } status = cpaCyDrbgSessionGetSize( setup->cyInstanceHandle, &pSessionSetupData[ses], &sessionSize); if (CPA_STATUS_SUCCESS == status) { sessionHdl = qaeMemAllocNUMA(sessionSize, node, BYTE_ALIGNMENT_64); if (NULL == sessionHdl) { PRINT("Failed to create a session\n"); qaeMemFreeNUMA((void **)&personalization); status = CPA_STATUS_FAIL; break; } pSessionHdl[ses] = sessionHdl; status = cpaCyDrbgInitSession( setup->cyInstanceHandle, /* callback function for generate */ drbgPerformCallback, NULL, /* callback function for reseed */ &pSessionSetupData[ses], /* session setup data */ sessionHdl, &seedLen); } if (CPA_STATUS_SUCCESS != status) { qaeMemFreeNUMA((void **)&personalization); qaeMemFreeNUMA((void **)&sessionHdl); break; } } /* Need to remove established sessions */ if (CPA_STATUS_SUCCESS != status) { drbgRemoveSession(setup, pSessionSetupData, pSessionHdl, ses); } return (status); } /* Free the memory session in setup */ static CpaStatus drbgRemoveSession(drbg_test_params_t *setup, CpaCyDrbgSessionSetupData *pSessionSetupData, CpaCyDrbgSessionHandle *pSessionHdl, Cpa32U numSessions) { void *personalization; CpaStatus status = CPA_STATUS_SUCCESS, sessionStatus; Cpa32U ses; for (ses = 0; ses < numSessions; ses++) { do { sessionStatus = cpaCyDrbgRemoveSession(setup->cyInstanceHandle, pSessionHdl[ses]); } while (CPA_STATUS_RETRY == sessionStatus); if (pSessionHdl[ses]) { qaeMemFreeNUMA((void **)&pSessionHdl[ses]); } personalization = pSessionSetupData[ses].personalizationString.pData; if (personalization) { qaeMemFreeNUMA((void **)&personalization); } if (CPA_STATUS_SUCCESS != sessionStatus) { status = sessionStatus; } } return (status); } /** ***************************************************************************** * @ingroup drbgPerformance * drbgPerform * * @description * This function implements the DRBG implementation-specific * 'Get Entropy Input' function by calling cpaCyNrbgGetEntropy API. * *****************************************************************************/ static CpaStatus drbgPerform(drbg_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS, sessionStatus; perf_data_t *pDrbgPerf = NULL; Cpa32U node = 0; CpaCyDrbgStats64 drbgStats = {0}; CpaCyDrbgSessionHandle *pSessionHdl; CpaCyDrbgSessionSetupData *pSessionSetupData; Cpa32U numSessions; if (NULL == setup) { PRINT_ERR("Setup Pointer is NULL\n"); return CPA_STATUS_FAIL; } /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not determine node for memory allocation\n"); return status; } if (0 == setup->lengthInBytes) { PRINT_ERR("Invalid parameter -- lengthInBytes\n"); return CPA_STATUS_INVALID_PARAM; } if (0 == setup->numLoops) { PRINT_ERR("Invalid parameter -- numLoops\n"); return CPA_STATUS_INVALID_PARAM; } if (0 == setup->numSessions) { PRINT_ERR("Invalid parameter -- numSessions\n"); return CPA_STATUS_INVALID_PARAM; } if (setup->numSessions > DRBG_MAX_SESSION_PERTHREAD) { PRINT_ERR("Invalid parameter -- numSessions must less or equal %d\n", DRBG_MAX_SESSION_PERTHREAD); return CPA_STATUS_INVALID_PARAM; } numSessions = setup->numSessions; nrbgRegisterDrbgImplFunctions(setup->dFReq); pSessionSetupData = qaeMemAlloc(sizeof(CpaCyDrbgSessionSetupData) * numSessions); if (NULL == pSessionSetupData) { PRINT_ERR("Failed to alloc memory\n"); return CPA_STATUS_FAIL; } memset( pSessionSetupData, 0, sizeof(CpaCyDrbgSessionSetupData) * numSessions); pSessionHdl = qaeMemAlloc(sizeof(CpaCyDrbgSessionHandle) * numSessions); if (NULL == pSessionHdl) { PRINT_ERR("Failed to alloc memory\n"); qaeMemFree((void **)&pSessionSetupData); return CPA_STATUS_FAIL; } pDrbgPerf = setup->performanceStats; /*get memory location to write performance stats to*/ memset(pDrbgPerf, 0, sizeof(perf_data_t)); status = drbgSetupSession(setup, pSessionSetupData, pSessionHdl, node); if (CPA_STATUS_SUCCESS == status) { status = drbgPerformOp(setup, pSessionHdl, node); sessionStatus = drbgRemoveSession( setup, pSessionSetupData, pSessionHdl, numSessions); if (CPA_STATUS_SUCCESS != sessionStatus) { PRINT_ERR("DRBG remove Session Failed, status = %d\n", status); } if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } } else { sampleCodeBarrier(); } if (CPA_STATUS_SUCCESS == status) { status = cpaCyDrbgQueryStats64(setup->cyInstanceHandle, &drbgStats); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyDrbgQueryStats64 failed, status = %d\n", status); } else { } } qaeMemFree((void **)&pSessionSetupData); qaeMemFree((void **)&pSessionHdl); nrbgUnregisterDrbgImplFunctions(); /* Need to re-write the actual operations and responses */ pDrbgPerf->numOperations = setup->numLoops * numSessions; pDrbgPerf->responses = setup->numLoops * numSessions; pDrbgPerf->threadReturnStatus = status; if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } /** ***************************************************************************** * @ingroup drbgPerformance * drbgPerformance * * @description * This function is called by the framework to execute the drbgPerform * thread * *****************************************************************************/ static void drbgPerformance(single_thread_test_data_t *testSetup) { drbg_test_params_t drbgSetup; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; drbg_test_params_t *params = (drbg_test_params_t *)testSetup->setupPtr; /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway */ startBarrier(); /*give our thread a unique memory location to store performance stats */ drbgSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance */ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("Could not get any instances\n"); PRINT_ERR("DRBG Thread FAILED\n"); drbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); drbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); drbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } drbgSetup.cyInstanceHandle = cyInstances[(testSetup->logicalQaInstance) % numInstances]; drbgSetup.dFReq = params->dFReq; drbgSetup.secStrength = params->secStrength; drbgSetup.predictionResistanceRequired = params->predictionResistanceRequired; drbgSetup.lengthInBytes = params->lengthInBytes; drbgSetup.numLoops = params->numLoops; drbgSetup.numSessions = params->numSessions; /*launch function that does all the work */ status = drbgPerform(&drbgSetup); if (CPA_STATUS_SUCCESS != status) { PRINT("DRBG Thread FAILED\n"); drbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test */ testSetup->statsPrintFunc = (stats_print_func_t)drbgPrintStats; } qaeMemFree((void **)&cyInstances); // PRINT("Thread exit...\n"); sampleCodeThreadComplete(testSetup->threadID); } /** ***************************************************************************** * @ingroup drbgPerformance * setupDrbgTest * * @description * This function setups up DRBG thread. Once called the user then calls the * createThreads function which replicates this setup in threads across * several cores, each using a separate acceleration engine instances * *****************************************************************************/ CpaStatus setupDrbgTest(CpaBoolean dFReq, Cpa32U secStrength, CpaBoolean predictionResistanceRequired, Cpa32U lengthInBytes, Cpa32U numSessions, Cpa32U numLoops) { /*setup is a multi-dimensional array that stores the setup for all thread * variations in an array of characters. We store our test setup at the * start of the second array ie index 0, [][0]. * There may be multi thread types(setups) running as counted by * testTypeCount_g */ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure */ drbg_test_params_t *drbgSetup = NULL; Cpa8S name[] = {'D', 'R', 'B', '\0'}; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started */ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)drbgPerformance; testSetupData_g[testTypeCount_g].packetSize = lengthInBytes; drbgSetup = (drbg_test_params_t *)&thread_setup_g[testTypeCount_g][0]; drbgSetup->dFReq = dFReq; drbgSetup->secStrength = secStrength; drbgSetup->predictionResistanceRequired = predictionResistanceRequired; drbgSetup->lengthInBytes = lengthInBytes; drbgSetup->numSessions = numSessions; drbgSetup->numLoops = numLoops; /* a semaphore used to control impl function register */ sampleCodeSemaphoreInit(&semaphoreImplFunction, 1); return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setupDrbgTest); cpa_sample_code_drbg_perf.h000066400000000000000000000123151503624047500362110ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file cpa_sample_code_drbg_perf.h * * @defgroup sampleDrbgFunctional * * @ingroup sampleCode * * @description * Deterministic Random Bit Generation Performance Sample Code functions. * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_DRBG_PERF_H #define CPA_SAMPLE_CODE_DRBG_PERF_H #include "cpa.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_cy_drbg.h" #include "cpa_cy_nrbg.h" #include "cpa_cy_im.h" #include "icp_sal_drbg_impl.h" #define DRBG_MAX_THREAD 256 #define DRBG_MAX_SESSION_PERTHREAD 256 /** ***************************************************************************** * @ingroup cryptoThreads * DRBGSetup Data. * @description * This structure contains data relating to setting up a DRBG test. * The client needs to complete the information in this structure in order * to setup a test. * ****************************************************************************/ typedef struct drbg_test_params_s { /*pointer to pre-allocated memory for thread to store performance data*/ perf_data_t *performanceStats; /*crypto instance handle of service that has already been started*/ CpaInstanceHandle cyInstanceHandle; /* derivation function required or not */ CpaBoolean dFReq; /* security strength */ Cpa32U secStrength; /* predication Resistance Required */ CpaBoolean predictionResistanceRequired; /* length in bytes */ Cpa32U lengthInBytes; /* number of loops to be used*/ Cpa32U numLoops; Cpa32U numSessions; } drbg_test_params_t; // void nrbgRegisterDrbgImplFunctions(CpaBoolean dFReq); /** ***************************************************************************** * @ingroup cryptoThreads * setupDrbgTest * * @description * setup a test to run an DRBG test * - should be called before createTheads framework function *****************************************************************************/ CpaStatus setupDrbgTest(CpaBoolean dFReq, Cpa32U secStrength, CpaBoolean predictionResistanceRequired, Cpa32U lengthInBytes, Cpa32U numSessions, Cpa32U numLoops); #endif cpa_sample_code_dsa_perf.c000066400000000000000000002363451503624047500360500ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_dsa_perf.c * * @ingroup dsaPerformance * * @description * This file contains the DSA performance functions * *****************************************************************************/ #include "cpa_cy_dsa.h" #include "cpa_sample_code_crypto_utils.h" #ifdef POLL_INLINE #include "icp_sal_poll.h" #endif #ifdef SC_DEV_INFO_ENABLED #include "cpa_dev.h" #endif #include "qat_perf_cycles.h" #define DEFAULT_H_VALUE (2) #define ALLOC_STRUCT(ptr, size, FREE_MEM_FUNC) \ do \ { \ ptr = qaeMemAlloc(size * setup->numBuffers); \ if (NULL == ptr) \ { \ PRINT_ERR("Could not allocate memory\n"); \ FREE_MEM_FUNC; \ return CPA_STATUS_FAIL; \ } \ memset(ptr, 0, size * setup->numBuffers); \ } while (0) CpaBoolean msgFlagSym = CPA_FALSE; /***************************************************************** * Declare a static 1024/160 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U dsa_1024_160_p[] = { 0xEA, 0xE2, 0xE2, 0x08, 0xBC, 0x34, 0x79, 0xAF, 0x6C, 0xD9, 0x90, 0xC8, 0xB6, 0x17, 0x0D, 0x33, 0x31, 0xDF, 0x22, 0xBB, 0x2D, 0x54, 0x64, 0x76, 0x98, 0xD5, 0x5A, 0x53, 0xE1, 0x14, 0xBE, 0x73, 0xDA, 0x89, 0xC6, 0x2D, 0x39, 0x00, 0x69, 0xA5, 0x42, 0x14, 0x90, 0x7E, 0x2F, 0x67, 0x31, 0xF0, 0xC2, 0x4B, 0xAC, 0x7E, 0x4C, 0xCF, 0xE9, 0x48, 0xFD, 0x67, 0xD8, 0x5E, 0x6B, 0x08, 0x65, 0x55, 0x56, 0xE0, 0xB3, 0xDE, 0x62, 0x23, 0xE2, 0xCF, 0x85, 0x9E, 0x6E, 0x4D, 0x07, 0xC2, 0x95, 0xAA, 0x46, 0x1C, 0xE5, 0xE5, 0x97, 0x1F, 0x97, 0x67, 0xAC, 0x6B, 0xAB, 0x39, 0x87, 0x17, 0x66, 0x92, 0x67, 0xC1, 0x97, 0x13, 0x3F, 0xF1, 0xB3, 0x98, 0x1B, 0x73, 0x09, 0x6D, 0x58, 0x25, 0xA5, 0xEF, 0x71, 0x93, 0x99, 0x8F, 0xB0, 0x81, 0x23, 0x48, 0xAF, 0xD9, 0x3A, 0xDB, 0xDB, 0x03, 0x0E, 0xFB}; static Cpa8U dsa_1024_160_q[] = {0x9D, 0x6D, 0x96, 0xC4, 0xB8, 0x69, 0x37, 0xC1, 0x60, 0x6D, 0x6E, 0xBA, 0x37, 0x5C, 0x46, 0x25, 0x49, 0x3C, 0x50, 0x33}; /***************************************************************** * Declare a static 2048/224 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U dsa_2048_224_p[] = { 0xb9, 0x8f, 0x24, 0x95, 0x41, 0x14, 0x86, 0x5f, 0xc2, 0xaf, 0xf1, 0x80, 0x92, 0x2b, 0x33, 0x46, 0xaa, 0xcf, 0xec, 0x30, 0x90, 0x3c, 0x2b, 0xa8, 0x87, 0xd6, 0x59, 0x15, 0x14, 0xfe, 0xa1, 0xff, 0x00, 0xe6, 0x95, 0xf4, 0x7f, 0x3d, 0xa3, 0x37, 0x9e, 0x41, 0x1c, 0xd4, 0xf4, 0x00, 0x78, 0xb1, 0x68, 0x88, 0x2e, 0x32, 0xa4, 0x8e, 0xc1, 0xb5, 0x05, 0x85, 0x22, 0x4c, 0x83, 0x3a, 0x5e, 0x8e, 0x48, 0x9f, 0x62, 0x24, 0xa6, 0xb6, 0x95, 0xf1, 0xb0, 0xe3, 0xa2, 0x18, 0xc6, 0x72, 0xf3, 0xcb, 0xe1, 0x42, 0x44, 0x16, 0x3d, 0x29, 0x39, 0xb8, 0x7f, 0xf8, 0xe3, 0xe7, 0xb1, 0xd3, 0xc8, 0x06, 0x6f, 0x6f, 0x1c, 0x84, 0x94, 0x90, 0x21, 0x75, 0xe6, 0x10, 0xda, 0x5b, 0x45, 0xdf, 0xc2, 0xa2, 0xc0, 0x41, 0xb7, 0x07, 0xdf, 0x77, 0x37, 0xc5, 0xe2, 0x4b, 0x99, 0x5b, 0x09, 0x37, 0xf5, 0xc5, 0xbc, 0x85, 0x2f, 0xde, 0x6e, 0x71, 0xd6, 0xef, 0xaa, 0xc7, 0x4b, 0xbc, 0xe8, 0x5c, 0xe6, 0xcf, 0x7b, 0x2a, 0x3c, 0x70, 0xd1, 0x67, 0xc2, 0x1d, 0xae, 0xde, 0x7e, 0x6c, 0x9e, 0xfd, 0xf0, 0xee, 0x06, 0xbc, 0x29, 0xde, 0x68, 0xe1, 0xac, 0x52, 0xe5, 0xdd, 0xa5, 0xd2, 0x76, 0x12, 0x62, 0x8a, 0x66, 0x90, 0xbe, 0xc7, 0xc2, 0x42, 0xbc, 0xd0, 0xa6, 0x28, 0x47, 0xe2, 0x37, 0x86, 0xa6, 0x12, 0x7f, 0x24, 0x83, 0x99, 0x51, 0xdf, 0xec, 0x51, 0x95, 0xc9, 0x2c, 0xb2, 0x3e, 0x9c, 0x83, 0xa0, 0xd7, 0x5f, 0x18, 0xb7, 0xd9, 0x31, 0x55, 0xcb, 0x05, 0x2f, 0xb5, 0xa8, 0x6f, 0x13, 0xf3, 0x31, 0x28, 0x5b, 0x55, 0x81, 0x53, 0xc3, 0xdb, 0x06, 0x21, 0x13, 0x93, 0xd9, 0xef, 0x54, 0x36, 0x35, 0x1b, 0x39, 0x0c, 0x94, 0x8f, 0x4f, 0x78, 0x68, 0x8f, 0xbf, 0x99, 0xfd, 0x6c, 0x86, 0x71, 0xf9}; static Cpa8U dsa_2048_224_q[] = {0x8a, 0xad, 0x30, 0x8a, 0x52, 0x54, 0x0f, 0x30, 0xf9, 0xe4, 0x8b, 0x0b, 0xe0, 0xfd, 0x3e, 0x8d, 0xa1, 0xba, 0xd8, 0x07, 0x63, 0x8b, 0x40, 0x38, 0x30, 0x25, 0x81, 0x93}; /***************************************************************** * Declare a static 2048/256 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U dsa_2048_256_p[] = { 0x92, 0xf2, 0x30, 0x17, 0x69, 0x5c, 0x21, 0x41, 0x61, 0x53, 0xf9, 0x5f, 0xbe, 0x0a, 0x7b, 0x78, 0x5d, 0xec, 0xea, 0x3b, 0x93, 0xd1, 0xf0, 0xd8, 0xe8, 0x16, 0xb9, 0x47, 0x75, 0xca, 0xeb, 0xf6, 0x5a, 0x4a, 0xc9, 0x95, 0x22, 0x80, 0x38, 0x13, 0x6a, 0xd7, 0xe6, 0x21, 0x3a, 0x44, 0xd3, 0x99, 0xc0, 0xc7, 0x70, 0xf6, 0x28, 0xbe, 0x04, 0x99, 0x9b, 0xa1, 0x7d, 0x34, 0x63, 0x70, 0x0e, 0xf2, 0x23, 0xbe, 0x7c, 0xe4, 0x79, 0xe4, 0x23, 0x70, 0xdc, 0x5f, 0xd8, 0x79, 0x0e, 0x6c, 0xbf, 0x03, 0xee, 0xe4, 0x79, 0xd4, 0xce, 0xf1, 0x3d, 0x93, 0xd6, 0xd2, 0xa4, 0x2e, 0xf2, 0x28, 0x3a, 0x82, 0xb8, 0x63, 0xa5, 0xe6, 0x06, 0x99, 0xa1, 0x67, 0xc7, 0x82, 0xa9, 0x0d, 0xfd, 0xbc, 0x67, 0xb5, 0x63, 0xd8, 0xd0, 0xd2, 0xf3, 0x51, 0xe7, 0x1d, 0xfa, 0xb2, 0x9a, 0x62, 0xbf, 0x65, 0x98, 0x72, 0x28, 0x78, 0x0d, 0x3e, 0x40, 0xb6, 0x88, 0x2e, 0x1d, 0x5d, 0xbb, 0x8c, 0x70, 0x79, 0x68, 0x9e, 0x06, 0xda, 0xe9, 0xb0, 0x2f, 0xa1, 0x16, 0x83, 0x14, 0x93, 0xf9, 0x1f, 0xcd, 0x79, 0x41, 0x07, 0x42, 0x56, 0x13, 0x05, 0x29, 0xaa, 0x99, 0x7d, 0x2c, 0xad, 0xa4, 0xa8, 0xf0, 0xfb, 0x58, 0x23, 0x31, 0x89, 0xc0, 0xa0, 0xda, 0x75, 0xb1, 0xe8, 0xcb, 0x4d, 0x18, 0x99, 0xfe, 0x86, 0x3b, 0x9b, 0x2b, 0x64, 0xca, 0x79, 0xc0, 0x97, 0xd3, 0xfc, 0xb4, 0x95, 0xd2, 0x69, 0xe1, 0xb9, 0xb4, 0xbd, 0xd1, 0xfa, 0x32, 0x3d, 0x98, 0x08, 0x87, 0x03, 0x8b, 0x4c, 0x17, 0x78, 0x99, 0x73, 0xe3, 0x3d, 0x2d, 0xef, 0xe1, 0x93, 0x39, 0xda, 0x21, 0xdc, 0x23, 0x1c, 0x98, 0x56, 0x3c, 0x70, 0x60, 0x5d, 0x55, 0x17, 0x7a, 0x23, 0x35, 0x45, 0x42, 0xa6, 0x33, 0x90, 0xeb, 0x19, 0x39, 0x18, 0xd6, 0x7b}; static Cpa8U dsa_2048_256_q[] = { 0xa3, 0x4f, 0x3a, 0xaa, 0x84, 0x9b, 0x1e, 0x28, 0xd3, 0x82, 0x3b, 0x89, 0x6f, 0xb6, 0xe2, 0x0f, 0xfe, 0x07, 0xdb, 0xe4, 0x85, 0xa5, 0x81, 0x6c, 0xbb, 0x14, 0x3f, 0x97, 0xf1, 0x47, 0x6a, 0xf9}; /***************************************************************** * Declare a static 3072/256 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U dsa_3072_256_p[] = { 0xa3, 0x78, 0x53, 0xcf, 0x35, 0x04, 0x0d, 0xb2, 0x07, 0x24, 0x2b, 0xab, 0x21, 0xd0, 0xa3, 0x9a, 0xb5, 0xa5, 0x25, 0x22, 0xac, 0xb3, 0x06, 0xe4, 0xdc, 0x04, 0x7b, 0xa5, 0xb9, 0xc3, 0xe5, 0x34, 0x4a, 0x23, 0x42, 0xfd, 0x6c, 0x5d, 0x61, 0x28, 0x06, 0x90, 0xe3, 0x9a, 0x4a, 0xab, 0x7b, 0xd7, 0x25, 0x84, 0x0d, 0x95, 0xe2, 0xda, 0x53, 0xb7, 0x49, 0xfc, 0xbf, 0xcf, 0xa2, 0xd6, 0x9b, 0xf9, 0x17, 0x0b, 0x6e, 0xef, 0x65, 0xbf, 0xf7, 0xc2, 0x42, 0x8d, 0x65, 0x9f, 0xe0, 0x0c, 0x47, 0x8c, 0xa1, 0xaf, 0xf4, 0x1b, 0x10, 0x36, 0xe6, 0x8e, 0x95, 0x22, 0xaa, 0xc3, 0xee, 0xb7, 0x85, 0x15, 0xf1, 0xaf, 0x29, 0xff, 0xc1, 0x38, 0xaa, 0x27, 0x48, 0x4e, 0x12, 0xad, 0xf9, 0x2e, 0xec, 0x85, 0x1e, 0x54, 0x8f, 0x19, 0x21, 0x08, 0x14, 0xb3, 0x16, 0x64, 0x06, 0x4c, 0x4d, 0x7e, 0x30, 0xe9, 0x45, 0x49, 0x13, 0x7a, 0x0b, 0x7d, 0x06, 0x14, 0x92, 0xb6, 0xa8, 0x51, 0x7a, 0xe2, 0xed, 0xd9, 0xae, 0x31, 0x06, 0xe3, 0x5b, 0xcf, 0xea, 0x28, 0xb7, 0x3f, 0xec, 0x34, 0x16, 0xff, 0x40, 0x41, 0x65, 0x7e, 0x97, 0xad, 0x4a, 0xcb, 0x78, 0x87, 0xea, 0xf2, 0xb7, 0xa0, 0x2b, 0xcd, 0x8e, 0xe1, 0xb0, 0x5d, 0x99, 0x1e, 0x81, 0xca, 0xe7, 0x7d, 0xf2, 0xd1, 0x57, 0xdb, 0x95, 0x8f, 0xd4, 0x81, 0xc6, 0xed, 0x00, 0x47, 0xe3, 0x84, 0xdf, 0x75, 0xf0, 0x9c, 0xec, 0xca, 0x34, 0x1f, 0xb2, 0xe8, 0x38, 0xc7, 0x19, 0xaf, 0x4d, 0xd1, 0xe4, 0xf1, 0x80, 0x83, 0xbd, 0x31, 0x48, 0x74, 0xd0, 0x97, 0x7c, 0xf6, 0x1b, 0x03, 0xcc, 0xf3, 0x00, 0x2d, 0x90, 0x3f, 0x1d, 0x1f, 0x94, 0x6f, 0x47, 0x46, 0xb3, 0x04, 0x6a, 0x14, 0x4a, 0xb0, 0x75, 0x9c, 0x3f, 0x40, 0x1e, 0x31, 0x52, 0x26, 0xfe, 0x9a, 0x4e, 0x6f, 0xde, 0x00, 0xc4, 0x54, 0xe4, 0xf9, 0x0e, 0x4a, 0x14, 0x87, 0x99, 0x81, 0xd9, 0x8f, 0x6e, 0xdc, 0xa2, 0xdd, 0xab, 0xcf, 0xe0, 0x78, 0x3a, 0xe9, 0xfd, 0x84, 0xd0, 0xf2, 0xb0, 0xcb, 0x74, 0xef, 0xa8, 0x27, 0x6f, 0xbf, 0xe4, 0xa1, 0x52, 0x5d, 0x39, 0xd1, 0x28, 0x09, 0x76, 0x78, 0xa9, 0x32, 0x18, 0x9d, 0x57, 0xe1, 0x97, 0x29, 0x29, 0x5c, 0xf3, 0xb9, 0x70, 0x3b, 0x4b, 0x2a, 0x2d, 0x5e, 0x98, 0x0d, 0x90, 0xcb, 0xa7, 0xd1, 0xd1, 0x9f, 0x28, 0xea, 0xbe, 0x7a, 0x92, 0xfd, 0xc4, 0xe8, 0x00, 0x4d, 0xef, 0x05, 0x45, 0x97, 0xc4, 0x2d, 0x2e, 0x94, 0x80, 0x44, 0x90, 0xf8, 0x5a, 0xbd, 0xd1, 0x86, 0xa1, 0xef, 0x47, 0x93, 0xe9, 0x1b, 0x98, 0x59, 0x1b, 0xbb, 0xb2, 0x66, 0xbd, 0x23, 0x23, 0x60, 0x4d, 0xeb, 0x6f, 0x5a, 0xcd, 0xee, 0x43, 0xab, 0x02, 0x08, 0xa6, 0xc7}; static Cpa8U dsa_3072_256_q[] = { 0xc4, 0x06, 0xcd, 0x06, 0x69, 0xd9, 0x82, 0x2f, 0x5e, 0x41, 0x91, 0x3c, 0x9c, 0xb8, 0xa3, 0x06, 0xee, 0x25, 0x68, 0xdc, 0x22, 0x8c, 0x4a, 0x39, 0x96, 0x01, 0xe3, 0x57, 0x93, 0xf4, 0x4e, 0x41}; extern Cpa32U packageIdCount_g; void dsaGenRandom(CpaFlatBuffer *dsaRand, CpaFlatBuffer *dsaQ); CpaStatus dsaGenG(CpaInstanceHandle instanceHandle, CpaCyDsaGParamGenOpData *gOpData, CpaFlatBuffer *dsaG); CpaStatus dsaGenY(CpaInstanceHandle instanceHandle, CpaCyDsaYParamGenOpData *yOpData, CpaFlatBuffer *dsaY); CpaStatus dsaGenRS(CpaInstanceHandle instanceHandle, CpaCyDsaRSSignOpData *rsOpData, CpaFlatBuffer *dsaR, CpaFlatBuffer *dsaS); void dsaPerformance(single_thread_test_data_t *testSetup); CpaStatus dsaPerform(dsa_test_params_t *setup); void dsaSignPerformance(single_thread_test_data_t *testSetup); /** ***************************************************************************** * @ingroup dsaPerformance * dsaVerifyCb * * @description * handle callbacks due to asymmetric call of cpaDsaVerify * *****************************************************************************/ static void dsaVerifyCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus) { processCallback(pCallbackTag); } /** ***************************************************************************** * @ingroup dsaPerformance * dsaSignRSCb * * @description * handle callbacks due to asymmetric call of cpaCyDsaSignRS * *****************************************************************************/ static void dsaSignRSCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean protocolStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { processCallback(pCallbackTag); } #ifdef POLL_INLINE /** ***************************************************************************** * @ingroup dsaPerformance * dsaVerifyCb * * @description * Generic callback for asynchronous Generation of G, Y and sign R & S. * *****************************************************************************/ static void processGenCB(void *pCallbackTag, CpaStatus status, CpaBoolean protocolStatus) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; /*check perf_data pointer is valid*/ if (pPerfData == NULL) { PRINT_ERR("Invalid data in CallbackTag\n"); return; } if (CPA_FALSE == protocolStatus) { PRINT_ERR("DSA protocol checks failed\n"); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA Gen callback failed\n"); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } /* response has been received */ pPerfData->responses++; } /** ***************************************************************************** * @ingroup dsaPerformance * dsaVerifyCb * * @description * handle callbacks due to asymmetric call of cpaCyDsaGenGParam * *****************************************************************************/ static void dsaGenGCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean protocolStatus, CpaFlatBuffer *pOut) { processGenCB(pCallbackTag, status, protocolStatus); } /** ***************************************************************************** * @ingroup dsaPerformance * dsaVerifyCb * * @description * handle callbacks due to asymmetric call of cpaDsaVerify * *****************************************************************************/ static void dsaGenYCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean protocolStatus, CpaFlatBuffer *pOut) { processGenCB(pCallbackTag, status, protocolStatus); } /** ***************************************************************************** * @ingroup dsaPerformance * dsaVerifyCb * * @description * handle callbacks due to asymmetric call of cpaCyDsaSignRS * *****************************************************************************/ static void dsaGenRSCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean protocolStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { processGenCB(pCallbackTag, status, protocolStatus); } #endif /** ***************************************************************************** * @ingroup dsaPerformance * dsaGenRandom * * @description * Populate a CpaFlatBuffer with a random number which is less than Q * *****************************************************************************/ void dsaGenRandom(CpaFlatBuffer *dsaRand, CpaFlatBuffer *dsaQ) { /*generate random data */ generateRandomData(dsaRand->pData, dsaRand->dataLenInBytes); /*make sure MSB is set */ setCpaFlatBufferMSB(dsaRand); /*make sure its < q */ makeParam1SmallerThanParam2( dsaRand->pData, dsaQ->pData, dsaRand->dataLenInBytes, CPA_TRUE); } /** ***************************************************************************** * @ingroup dsaPerformance * dsaGenG * * @description * Generate the DSA G parameter * *****************************************************************************/ CpaStatus dsaGenG(CpaInstanceHandle instanceHandle, CpaCyDsaGParamGenOpData *gOpData, CpaFlatBuffer *dsaG) { CpaStatus status = CPA_STATUS_FAIL; CpaBoolean protocolStatus = CPA_FALSE; Cpa32U retries = 0; CpaCyDsaGenCbFunc cbFunc = NULL; perf_data_t *pPerfData = NULL; #ifdef POLL_INLINE CpaInstanceInfo2 instanceInfo2 = {0}; if (poll_inline_g) { cbFunc = dsaGenGCb; cbFunc = dsaGenGCb; pPerfData = qaeMemAlloc(sizeof(perf_data_t)); if (NULL == pPerfData) { PRINT_ERR("Error: Allocating perf_data for calcDigest\n"); return CPA_STATUS_FAIL; } pPerfData->numOperations = SINGLE_OPERATION; pPerfData->responses = 0; } #endif #ifdef POLL_INLINE if (poll_inline_g) { status = cpaCyInstanceGetInfo2(instanceHandle, &instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&pPerfData); return CPA_STATUS_FAIL; } } #endif do { status = cpaCyDsaGenGParam( instanceHandle, cbFunc, pPerfData, gOpData, &protocolStatus, dsaG); if (CPA_STATUS_RETRY == status) { retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small break */ if (RETRY_LIMIT == (retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2.isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, instanceHandle, pPerfData->numOperations); } if (CPA_STATUS_FAIL == pPerfData->threadReturnStatus) { PRINT_ERR("DSA protocol Status failed - for Gen \'G\'\n"); qaeMemFree((void **)&pPerfData); return CPA_STATUS_FAIL; } qaeMemFree((void **)&pPerfData); return CPA_STATUS_SUCCESS; } #endif if (CPA_FALSE == protocolStatus || CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA protocol Status failed - status: %d, " "protocolStatus: %d \n", status, protocolStatus); status = CPA_STATUS_FAIL; } return status; } /** ***************************************************************************** * @ingroup dsaPerformance * dsaGenY * * @description * Generate the DSA Y parameter * *****************************************************************************/ CpaStatus dsaGenY(CpaInstanceHandle instanceHandle, CpaCyDsaYParamGenOpData *yOpData, CpaFlatBuffer *dsaY) { CpaStatus status = CPA_STATUS_FAIL; CpaBoolean protocolStatus = CPA_FALSE; perf_data_t *pPerfData = NULL; Cpa32U retries = 0; CpaCyDsaGenCbFunc cbFunc = NULL; #ifdef POLL_INLINE CpaInstanceInfo2 instanceInfo2 = {0}; if (poll_inline_g) { cbFunc = dsaGenYCb; pPerfData = qaeMemAlloc(sizeof(perf_data_t)); if (NULL == pPerfData) { PRINT_ERR("Error: Allocating perf_data for calcDigest\n"); return CPA_STATUS_FAIL; } pPerfData->numOperations = SINGLE_OPERATION; pPerfData->responses = 0; } #endif #ifdef POLL_INLINE if (poll_inline_g) { status = cpaCyInstanceGetInfo2(instanceHandle, &instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&pPerfData); return CPA_STATUS_FAIL; } } #endif do { status = cpaCyDsaGenYParam( instanceHandle, cbFunc, pPerfData, yOpData, &protocolStatus, dsaY); if (CPA_STATUS_RETRY == status) { retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small break */ if (RETRY_LIMIT == (retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2.isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, instanceHandle, pPerfData->numOperations); } if (CPA_STATUS_FAIL == pPerfData->threadReturnStatus) { PRINT_ERR("DSA protocol Status failed - for Gen \'Y\'\n"); qaeMemFree((void **)&pPerfData); return CPA_STATUS_FAIL; } qaeMemFree((void **)&pPerfData); return CPA_STATUS_SUCCESS; } #endif if (CPA_FALSE == protocolStatus || CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA protocol Status failed - status: %d, " "protocolStatus: %d \n", status, protocolStatus); status = CPA_STATUS_FAIL; } return status; } /** ***************************************************************************** * @ingroup dsaPerformance * dsaGenRS * * @description * Generate the DSA Signature R&S * *****************************************************************************/ CpaStatus dsaGenRS(CpaInstanceHandle instanceHandle, CpaCyDsaRSSignOpData *rsOpData, CpaFlatBuffer *dsaR, CpaFlatBuffer *dsaS) { CpaStatus status = CPA_STATUS_FAIL; CpaBoolean protocolStatus = CPA_FALSE; perf_data_t *pPerfData = NULL; CpaCyDsaRSSignCbFunc rsSignCb = NULL; Cpa32U retries = 0; #ifdef POLL_INLINE CpaInstanceInfo2 instanceInfo2 = {0}; if (poll_inline_g) { rsSignCb = dsaGenRSCb; pPerfData = qaeMemAlloc(sizeof(perf_data_t)); if (NULL == pPerfData) { PRINT_ERR("Error: Allocating perf_data for calcDigest\n"); return CPA_STATUS_FAIL; } pPerfData->numOperations = SINGLE_OPERATION; pPerfData->responses = 0; } #endif #ifdef POLL_INLINE if (poll_inline_g) { status = cpaCyInstanceGetInfo2(instanceHandle, &instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&pPerfData); return CPA_STATUS_FAIL; } } #endif do { status = cpaCyDsaSignRS(instanceHandle, rsSignCb, pPerfData, rsOpData, &protocolStatus, dsaR, dsaS); if (CPA_STATUS_RETRY == status) { retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small break */ if (RETRY_LIMIT == (retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2.isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, instanceHandle, pPerfData->numOperations); } if (CPA_STATUS_FAIL == pPerfData->threadReturnStatus) { PRINT_ERR("DSA protocol Status failed - for Sign \'RS\'\n"); qaeMemFree((void **)&pPerfData); return CPA_STATUS_FAIL; } qaeMemFree((void **)&pPerfData); return CPA_STATUS_SUCCESS; } #endif if (CPA_FALSE == protocolStatus || CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA protocol Status failed - status: %d, " "protocolStatus: %d \n", status, protocolStatus); status = CPA_STATUS_FAIL; } return status; } /** ***************************************************************************** * @ingroup dsaPerformance * dsaGenZ * * @description * Generate Z, Z is the digest of the message which is used in DSA * Signature generation and also used to verify a message * *****************************************************************************/ CpaStatus dsaGenZ(CpaInstanceHandle instanceHandle, CpaFlatBuffer *msg, CpaCySymHashAlgorithm hashAlg, CpaFlatBuffer *dsaZ) { CpaStatus status = CPA_STATUS_FAIL; /* Z is: The leftmost min(N, outlen) bits of Hash(M), where: * - N is the bit length of q * - outlen is the bit length of the hash function output block * - M is the message to be signed * * when q len = length of output of hash operation: * N = outLen so Z = digest of msg */ CpaCyCapabilitiesInfo cap = {0}; status = getCySpecificInstanceCapabilities(instanceHandle, &cap); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("getCySpecificInstanceCapabilities failed with status: %d\n", status); return status; } if (cap.symSupported == CPA_FALSE) { if (msgFlagSym == CPA_FALSE) { PRINT( "DSA Warning! SYMMETRIC operation is not supported on Instance.\ Using calcSWDigest instead.\n"); msgFlagSym = CPA_TRUE; } status = calcSWDigest(msg, dsaZ, hashAlg); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA Calc SW Digest Error hashAlg %u\n", hashAlg); } } else { status = calcDigest(instanceHandle, msg, dsaZ, hashAlg); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA Calc Digest Error hashAlg %u\n", hashAlg); } } return status; } /** ***************************************************************************** * @ingroup dsaPerformance * * @description * free all memory used in DSA performance code in this file * *****************************************************************************/ static void freeDsaMem(dsa_test_params_t *setup, CpaFlatBuffer *dsaX, CpaFlatBuffer *dsaY, CpaFlatBuffer *dsaK, CpaFlatBuffer *dsaM, CpaFlatBuffer *dsaZ, CpaFlatBuffer *dsaR, CpaFlatBuffer *dsaS, CpaCyDsaVerifyOpData *verifyOpData, CpaCyDsaRSSignOpData *rsOpData, CpaFlatBuffer dsaG, CpaFlatBuffer dsaP, CpaFlatBuffer dsaH, CpaFlatBuffer dsaQ) { freeArrayFlatBufferNUMA(dsaX, setup->numBuffers); freeArrayFlatBufferNUMA(dsaY, setup->numBuffers); freeArrayFlatBufferNUMA(dsaK, setup->numBuffers); freeArrayFlatBufferNUMA(dsaM, setup->numBuffers); freeArrayFlatBufferNUMA(dsaZ, setup->numBuffers); freeArrayFlatBufferNUMA(dsaR, setup->numBuffers); freeArrayFlatBufferNUMA(dsaS, setup->numBuffers); if (NULL != verifyOpData) qaeMemFree((void **)&verifyOpData); if (NULL != rsOpData) qaeMemFree((void **)&rsOpData); /*free the normal flatBuffer pData */ qaeMemFreeNUMA((void **)&dsaG.pData); qaeMemFreeNUMA((void **)&dsaP.pData); qaeMemFreeNUMA((void **)&dsaH.pData); qaeMemFreeNUMA((void **)&dsaQ.pData); } /** ***************************************************************************** * @ingroup dsaPerformance * * @description * Macro to free all memory used in DSA performance code in this file * *****************************************************************************/ #define FREE_DSA_MEM \ freeDsaMem(setup, \ dsaX, \ dsaY, \ dsaK, \ dsaM, \ dsaZ, \ dsaR, \ dsaS, \ verifyOpData, \ NULL, \ dsaG, \ dsaP, \ dsaH, \ dsaQ) /** ***************************************************************************** * @ingroup dsaPerformance * * @description * Macro to free all memory used in DSA sign performance code in this file * *****************************************************************************/ #define FREE_DSA_SIGN_MEM \ freeDsaMem(setup, \ dsaX, \ dsaY, \ dsaK, \ dsaM, \ dsaZ, \ dsaR, \ dsaS, \ NULL, \ rsOpData, \ dsaG, \ dsaP, \ dsaH, \ dsaQ) /** ***************************************************************************** * @ingroup dsaPerformance * dsaPerform * * @description * This function generates all the DSA parameters required to perform a DSA * sign and DSA verify operation. A user defined number of random messages * are generated and signed, then the signature is verified * *****************************************************************************/ CpaStatus dsaPerform(dsa_test_params_t *setup) { Cpa32U i = 0; Cpa32U outerLoop = 0; CpaBoolean verifyStatus = CPA_TRUE; CpaStatus status = CPA_STATUS_SUCCESS; /*DSA parameters */ /*DSA Q parameter, this shall be populated by the hard coded Q at the top * of this file */ CpaFlatBuffer dsaQ = {0}; /*random number X used to generate Y and Sign R&S */ CpaFlatBuffer *dsaX = NULL; /*DSA P parameter, this shall be populated by the hard coded P at the top * of this file */ CpaFlatBuffer dsaP = {0}; /*H is used to generate G, H is hard coded to DEFAULT_H_VALUE */ CpaFlatBuffer dsaH = {0}; /* DSA G parameter used to generate Y, the signature R&S, and to verify */ CpaFlatBuffer dsaG = {0}; /*DSA Y parameter is used in the verification stage */ CpaFlatBuffer *dsaY = NULL; /*K is a random number used in the generation of signature R&S */ CpaFlatBuffer *dsaK = NULL; /*M is the message to be signed */ CpaFlatBuffer *dsaM = NULL; /*R&S is used to store the DSA Signature */ CpaFlatBuffer *dsaR = NULL; CpaFlatBuffer *dsaS = NULL; /*Z is the digest of the message in dsaM */ CpaFlatBuffer *dsaZ = NULL; perf_data_t *pDsaData = NULL; /*GCC compiler complains without the double {{}} to init the following * structures*/ CpaCyDsaGParamGenOpData gOpData = {{0, NULL}, {0, NULL}, {0, NULL}}; CpaCyDsaYParamGenOpData yOpData = {{0, NULL}, {0, NULL}, {0, NULL}}; CpaCyDsaRSSignOpData rsOpData = { {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}}; CpaCyDsaVerifyOpData *verifyOpData = NULL; Cpa8U *pDataPtr = NULL; Cpa32U sizeOfp = 0; Cpa8U *qDataPtr = NULL; Cpa32U sizeOfq = 0; Cpa32U node = 0; CpaCyDsaVerifyCbFunc cbFunc = NULL; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_SUCCESS; perf_data_t *pPerfData = setup->performanceStats; CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; #endif DECLARE_IA_CYCLE_COUNT_VARIABLES(); status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not determibne node for memory allocation\n"); goto barrier; } pDsaData = setup->performanceStats; pDsaData->threadReturnStatus = CPA_STATUS_FAIL; pDsaData->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; coo_init(pDsaData, pDsaData->numOperations); /*check the p and q input len and set the pointers to the data */ if (MODULUS_1024_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_160_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_1024_160_p; qDataPtr = dsa_1024_160_q; sizeOfp = sizeof(dsa_1024_160_p); sizeOfq = sizeof(dsa_1024_160_q); } else if (MODULUS_2048_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_224_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_2048_224_p; qDataPtr = dsa_2048_224_q; sizeOfp = sizeof(dsa_2048_224_p); sizeOfq = sizeof(dsa_2048_224_q); } else if (MODULUS_2048_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_256_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_2048_256_p; qDataPtr = dsa_2048_256_q; sizeOfp = sizeof(dsa_2048_256_p); sizeOfq = sizeof(dsa_2048_256_q); } else if (MODULUS_3072_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_256_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_3072_256_p; qDataPtr = dsa_3072_256_q; sizeOfp = sizeof(dsa_3072_256_p); sizeOfq = sizeof(dsa_3072_256_q); } else { PRINT_ERR("P & Q len not supported\n"); /*thread status is init to fail so just return fail here*/ status = CPA_STATUS_FAIL; goto barrier; } /* Completion used in callback */ sampleCodeSemaphoreInit(&pDsaData->comp, 0); /*Allocate all the buffers */ ALLOC_STRUCT(dsaX, sizeof(CpaFlatBuffer), FREE_DSA_MEM); ALLOC_STRUCT(dsaY, sizeof(CpaFlatBuffer), FREE_DSA_MEM); ALLOC_STRUCT(dsaK, sizeof(CpaFlatBuffer), FREE_DSA_MEM); ALLOC_STRUCT(dsaM, sizeof(CpaFlatBuffer), FREE_DSA_MEM); ALLOC_STRUCT(dsaR, sizeof(CpaFlatBuffer), FREE_DSA_MEM); ALLOC_STRUCT(dsaS, sizeof(CpaFlatBuffer), FREE_DSA_MEM); ALLOC_STRUCT(dsaZ, sizeof(CpaFlatBuffer), FREE_DSA_MEM); ALLOC_STRUCT(verifyOpData, sizeof(CpaCyDsaVerifyOpData), FREE_DSA_MEM); /************************************************************************ * STAGE 1 Setup up the DSA parameters, generate X, G, Y, K, Z, * generate user defined number of messages to be signed * calculate the digest of the messages * sign all the messages * setup the verification data structure **************************************************************************/ /*set Q */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaQ, setup->qLenInBytes, qDataPtr, sizeOfq, FREE_DSA_MEM); /*generate X for each buffer */ for (i = 0; i < setup->numBuffers; i++) { /*Choose X is generated by random method, where 0 < X < Q */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaX[i], setup->qLenInBytes, NULL, 0, FREE_DSA_MEM); dsaGenRandom(&dsaX[i], &dsaQ); } /*set P */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaP, setup->pLenInBytes, pDataPtr, sizeOfp, FREE_DSA_MEM); /*************************************************************************** * set genG opData and generate G * ************************************************************************/ /*H is required to genG */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaH, setup->pLenInBytes, NULL, 0, FREE_DSA_MEM); memset(dsaH.pData, 0, dsaH.dataLenInBytes); dsaH.pData[setup->pLenInBytes - 1] = DEFAULT_H_VALUE; /*allocate space for G */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaG, setup->pLenInBytes, NULL, 0, FREE_DSA_MEM); /*set opData to generate G */ gOpData.P.pData = dsaP.pData; gOpData.P.dataLenInBytes = dsaP.dataLenInBytes; gOpData.Q.pData = dsaQ.pData; gOpData.Q.dataLenInBytes = dsaQ.dataLenInBytes; gOpData.H.pData = dsaH.pData; gOpData.H.dataLenInBytes = dsaH.dataLenInBytes; status = dsaGenG(setup->cyInstanceHandle, &gOpData, &dsaG); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to generate DSA parameter G\n"); FREE_DSA_MEM; goto barrier; } /*generate a Y for each buffer */ for (i = 0; i < setup->numBuffers; i++) { /*set the opData to gen Y */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaY[i], setup->pLenInBytes, NULL, 0, FREE_DSA_MEM); yOpData.P.pData = dsaP.pData; yOpData.P.dataLenInBytes = dsaP.dataLenInBytes; yOpData.G.pData = dsaG.pData; yOpData.G.dataLenInBytes = dsaG.dataLenInBytes; yOpData.X.pData = dsaX[i].pData; yOpData.X.dataLenInBytes = dsaX[i].dataLenInBytes; status = dsaGenY(setup->cyInstanceHandle, &yOpData, &dsaY[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating Y for buffer %d\n", i); /*free all the pData buffers allocated and Array of pointers * allocated */ FREE_DSA_MEM; goto barrier; } /*Generate a random per-message value K, where 0 < K < Q. */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaK[i], setup->qLenInBytes, NULL, 0, FREE_DSA_MEM); dsaGenRandom(&dsaK[i], &dsaQ); /*generate a message to sign */ /*allocate space for message */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaM[i], setup->pLenInBytes, NULL, 0, FREE_DSA_MEM); /*allocate space for digest of message */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaZ[i], setup->qLenInBytes, NULL, 0, FREE_DSA_MEM); /*generate random message */ generateRandomData(dsaM[i].pData, dsaM[i].dataLenInBytes); /*calculate digest of message */ status = dsaGenZ( setup->cyInstanceHandle, &dsaM[i], setup->hashAlg, &dsaZ[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating Z for buffer %d\n", i); FREE_DSA_MEM; goto barrier; } /*Gen R & S signature */ rsOpData.G.pData = dsaG.pData; rsOpData.G.dataLenInBytes = dsaG.dataLenInBytes; rsOpData.K.pData = dsaK[i].pData; rsOpData.K.dataLenInBytes = dsaK[i].dataLenInBytes; rsOpData.P.pData = dsaP.pData; rsOpData.P.dataLenInBytes = dsaP.dataLenInBytes; rsOpData.Q.pData = dsaQ.pData; rsOpData.Q.dataLenInBytes = dsaQ.dataLenInBytes; rsOpData.X.pData = dsaX[i].pData; rsOpData.X.dataLenInBytes = dsaX[i].dataLenInBytes; rsOpData.Z.pData = dsaZ[i].pData; rsOpData.Z.dataLenInBytes = dsaZ[i].dataLenInBytes; ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaR[i], setup->qLenInBytes, NULL, 0, FREE_DSA_MEM); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaS[i], setup->qLenInBytes, NULL, 0, FREE_DSA_MEM); status = dsaGenRS(setup->cyInstanceHandle, &rsOpData, &dsaR[i], &dsaS[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating R&S for buffer %d\n", i); FREE_DSA_MEM; goto barrier; } /*Verify signature */ verifyOpData[i].P.pData = dsaP.pData; verifyOpData[i].P.dataLenInBytes = dsaP.dataLenInBytes; verifyOpData[i].Q.pData = dsaQ.pData; verifyOpData[i].Q.dataLenInBytes = dsaQ.dataLenInBytes; verifyOpData[i].G.pData = dsaG.pData; verifyOpData[i].G.dataLenInBytes = dsaG.dataLenInBytes; verifyOpData[i].Y.pData = dsaY[i].pData; verifyOpData[i].Y.dataLenInBytes = dsaY[i].dataLenInBytes; verifyOpData[i].Z.pData = dsaZ[i].pData; verifyOpData[i].Z.dataLenInBytes = dsaZ[i].dataLenInBytes; verifyOpData[i].R.pData = dsaR[i].pData; verifyOpData[i].R.dataLenInBytes = dsaR[i].dataLenInBytes; verifyOpData[i].S.pData = dsaS[i].pData; verifyOpData[i].S.dataLenInBytes = dsaS[i].dataLenInBytes; } /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = dsaVerifyCb; } #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); FREE_DSA_MEM; return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); FREE_DSA_MEM; qaeMemFree((void **)&instanceInfo2); status = CPA_STATUS_FAIL; } } #endif /************************************************************************ * STAGE 2 repeatedly verify all the signatures and measure the performance ************************************************************************* */ /*this barrier will wait until all threads get to this point */ barrier: sampleCodeBarrier(); /* exiting the function if any failure occurs in previous steps*/ if (CPA_STATUS_SUCCESS != status) { return status; } /* get a timestamp before submitting any requests. After submitting * all requests a final timestamp is taken in the callback function. * These two times and the number of requests submitted are used to * calculate operations per second */ pDsaData->startCyclesTimestamp = sampleCodeTimestamp(); for (outerLoop = 0; outerLoop < setup->numLoops; outerLoop++) { for (i = 0; i < setup->numBuffers; i++) { do { coo_req_start(pDsaData); status = cpaCyDsaVerify(setup->cyInstanceHandle, cbFunc, pDsaData, &verifyOpData[i], &verifyStatus); coo_req_stop(pDsaData, status); if (CPA_STATUS_RETRY == status) { #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { sampleCodeAsymPollInstance(setup->cyInstanceHandle, 0); nextPoll = numOps + asymPollingInterval_g; } } #endif pDsaData->retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small break */ if (RETRY_LIMIT == (pDsaData->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { BUSY_LOOP(); } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy( pDsaData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } } #endif /*if for some reason the DSA verify returns fail, decrease the * numOperations expected in the callback so that the code does not * wait forever */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA Verify function failed with status:%d\n", status); break; } } if (CPA_STATUS_SUCCESS != status) { break; } } #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pDsaData, setup->syncMode, setup->numBuffers, setup->numLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Thread %u timeout.", setup->threadID); } } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { IA_CYCLE_COUNT_CALCULATION(); } coo_average(pDsaData); coo_deinit(pDsaData); /*free Arrays of buffer pointers and pData */ FREE_DSA_MEM; sampleCodeSemaphoreDestroy(&pDsaData->comp); pDsaData->threadReturnStatus = status; #ifdef POLL_INLINE qaeMemFree((void **)&instanceInfo2); #endif if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } EXPORT_SYMBOL(dsaPerform); /** ***************************************************************************** * @ingroup dsaPerformance * dsaSignPerform * * @description * This function generates all the DSA parameters required to perform a DSA * sign operation. A user defined number of random messages are generated * and signed. * *****************************************************************************/ static CpaStatus dsaSignPerform(dsa_test_params_t *setup) { Cpa32U i = 0; Cpa32U outerLoop = 0; CpaBoolean protocolStatus = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; /*DSA parameters */ /*DSA Q parameter, this shall be populated by the hard coded Q at the top * of this file */ CpaFlatBuffer dsaQ = {0}; /*random number X used to generate Y and Sign R&S */ CpaFlatBuffer *dsaX = NULL; /*DSA P parameter, this shall be populated by the hard coded P at the top * of this file */ CpaFlatBuffer dsaP = {0}; /*H is used to generate G, H is hard coded to DEFAULT_H_VALUE */ CpaFlatBuffer dsaH = {0}; /* DSA G parameter used to generate Y, the signature R&S, and to verify */ CpaFlatBuffer dsaG = {0}; /*DSA Y parameter is used in the verification stage */ CpaFlatBuffer *dsaY = NULL; /*K is a random number used in the generation of signature R&S */ CpaFlatBuffer *dsaK = NULL; /*M is the message to be signed */ CpaFlatBuffer *dsaM = NULL; /*R&S is used to store the DSA Signature */ CpaFlatBuffer *dsaR = NULL; CpaFlatBuffer *dsaS = NULL; /*Z is the digest of the message in dsaM */ CpaFlatBuffer *dsaZ = NULL; perf_data_t *pDsaData = NULL; /*GCC compiler complains without the double {{}} to init the following * structures*/ CpaCyDsaGParamGenOpData gOpData = {{0, NULL}, {0, NULL}, {0, NULL}}; CpaCyDsaYParamGenOpData yOpData = {{0}}; CpaCyDsaRSSignOpData *rsOpData = NULL; Cpa8U *pDataPtr = NULL; Cpa32U sizeOfp = 0; Cpa8U *qDataPtr = NULL; Cpa32U sizeOfq = 0; Cpa32U node = 0; CpaCyDsaRSSignCbFunc cbFunc = NULL; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_SUCCESS; perf_data_t *pPerfData = setup->performanceStats; CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; #endif DECLARE_IA_CYCLE_COUNT_VARIABLES(); status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not determine node for memory allocation\n"); goto barrier; } pDsaData = setup->performanceStats; pDsaData->threadReturnStatus = CPA_STATUS_FAIL; pDsaData->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; coo_init(pDsaData, pDsaData->numOperations); /*check the p and q input len and set the pointers to the data */ if (MODULUS_1024_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_160_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_1024_160_p; qDataPtr = dsa_1024_160_q; sizeOfp = sizeof(dsa_1024_160_p); sizeOfq = sizeof(dsa_1024_160_q); } else if (MODULUS_2048_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_224_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_2048_224_p; qDataPtr = dsa_2048_224_q; sizeOfp = sizeof(dsa_2048_224_p); sizeOfq = sizeof(dsa_2048_224_q); } else if (MODULUS_2048_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_256_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_2048_256_p; qDataPtr = dsa_2048_256_q; sizeOfp = sizeof(dsa_2048_256_p); sizeOfq = sizeof(dsa_2048_256_q); } else if (MODULUS_3072_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_256_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = dsa_3072_256_p; qDataPtr = dsa_3072_256_q; sizeOfp = sizeof(dsa_3072_256_p); sizeOfq = sizeof(dsa_3072_256_q); } else { PRINT_ERR("P & Q len not supported\n"); /*thread status is init to fail so just return fail here*/ status = CPA_STATUS_FAIL; goto barrier; } /* Completion used in callback */ sampleCodeSemaphoreInit(&pDsaData->comp, 0); /*Allocate all the buffers */ ALLOC_STRUCT(dsaX, sizeof(CpaFlatBuffer), FREE_DSA_SIGN_MEM); ALLOC_STRUCT(dsaY, sizeof(CpaFlatBuffer), FREE_DSA_SIGN_MEM); ALLOC_STRUCT(dsaK, sizeof(CpaFlatBuffer), FREE_DSA_SIGN_MEM); ALLOC_STRUCT(dsaM, sizeof(CpaFlatBuffer), FREE_DSA_SIGN_MEM); ALLOC_STRUCT(dsaR, sizeof(CpaFlatBuffer), FREE_DSA_SIGN_MEM); ALLOC_STRUCT(dsaS, sizeof(CpaFlatBuffer), FREE_DSA_SIGN_MEM); ALLOC_STRUCT(dsaZ, sizeof(CpaFlatBuffer), FREE_DSA_SIGN_MEM); ALLOC_STRUCT(rsOpData, sizeof(CpaCyDsaRSSignOpData), FREE_DSA_SIGN_MEM); /************************************************************************ * STAGE 1 Setup up the DSA parameters, generate X, G, Y, K, Z, * generate user defined number of messages to be signed * calculate the digest of the messages **************************************************************************/ /*set Q */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaQ, setup->qLenInBytes, qDataPtr, sizeOfq, FREE_DSA_SIGN_MEM); /*generate X for each buffer */ for (i = 0; i < setup->numBuffers; i++) { /*Choose X is generated by random method, where 0 < X < Q */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaX[i], setup->qLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); dsaGenRandom(&dsaX[i], &dsaQ); } /*set P */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaP, setup->pLenInBytes, pDataPtr, sizeOfp, FREE_DSA_SIGN_MEM); /*************************************************************************** * set genG opData and generate G * ************************************************************************/ /*H is required to genG */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaH, setup->pLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); memset(dsaH.pData, 0, dsaH.dataLenInBytes); dsaH.pData[setup->pLenInBytes - 1] = DEFAULT_H_VALUE; /*allocate space for G */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaG, setup->pLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); /*set opData to generate G */ gOpData.P.pData = dsaP.pData; gOpData.P.dataLenInBytes = dsaP.dataLenInBytes; gOpData.Q.pData = dsaQ.pData; gOpData.Q.dataLenInBytes = dsaQ.dataLenInBytes; gOpData.H.pData = dsaH.pData; gOpData.H.dataLenInBytes = dsaH.dataLenInBytes; status = dsaGenG(setup->cyInstanceHandle, &gOpData, &dsaG); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to generate DSA parameter G\n"); FREE_DSA_SIGN_MEM; goto barrier; } /*generate a Y for each buffer */ for (i = 0; i < setup->numBuffers; i++) { /*set the opData to gen Y */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaY[i], setup->pLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); yOpData.P.pData = dsaP.pData; yOpData.P.dataLenInBytes = dsaP.dataLenInBytes; yOpData.G.pData = dsaG.pData; yOpData.G.dataLenInBytes = dsaG.dataLenInBytes; yOpData.X.pData = dsaX[i].pData; yOpData.X.dataLenInBytes = dsaX[i].dataLenInBytes; status = dsaGenY(setup->cyInstanceHandle, &yOpData, &dsaY[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating Y for buffer %d\n", i); /*free all the pData buffers allocated and Array of pointers * allocated */ FREE_DSA_SIGN_MEM; goto barrier; } /*Generate a random per-message value K, where 0 < K < Q. */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaK[i], setup->qLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); dsaGenRandom(&dsaK[i], &dsaQ); /*generate a message to sign */ /*allocate space for message */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaM[i], setup->pLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); /*allocate space for digest of message */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaZ[i], setup->qLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); /*generate random message */ generateRandomData(dsaM[i].pData, dsaM[i].dataLenInBytes); /*calculate digest of message */ status = dsaGenZ( setup->cyInstanceHandle, &dsaM[i], setup->hashAlg, &dsaZ[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating Z for buffer %d\n", i); FREE_DSA_SIGN_MEM; goto barrier; } /* Prepare data for R & S signature */ rsOpData[i].G.pData = dsaG.pData; rsOpData[i].G.dataLenInBytes = dsaG.dataLenInBytes; rsOpData[i].K.pData = dsaK[i].pData; rsOpData[i].K.dataLenInBytes = dsaK[i].dataLenInBytes; rsOpData[i].P.pData = dsaP.pData; rsOpData[i].P.dataLenInBytes = dsaP.dataLenInBytes; rsOpData[i].Q.pData = dsaQ.pData; rsOpData[i].Q.dataLenInBytes = dsaQ.dataLenInBytes; rsOpData[i].X.pData = dsaX[i].pData; rsOpData[i].X.dataLenInBytes = dsaX[i].dataLenInBytes; rsOpData[i].Z.pData = dsaZ[i].pData; rsOpData[i].Z.dataLenInBytes = dsaZ[i].dataLenInBytes; ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaR[i], setup->qLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaS[i], setup->qLenInBytes, NULL, 0, FREE_DSA_SIGN_MEM); } /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = dsaSignRSCb; } #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); FREE_DSA_SIGN_MEM; return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); FREE_DSA_SIGN_MEM; qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } } #endif /************************************************************************ * STAGE 2 repeatedly sign messages and measure the performance ************************************************************************* */ /*this barrier will wait until all threads get to this point */ barrier: sampleCodeBarrier(); /* exiting the function if any failure occurs in previous steps*/ if (CPA_STATUS_SUCCESS != status) { return status; } /* get a timestamp before submitting any requests. After submitting * all requests a final timestamp is taken in the callback function. * These two times and the number of requests submitted are used to * calculate operations per second */ pDsaData->startCyclesTimestamp = sampleCodeTimestamp(); for (outerLoop = 0; outerLoop < setup->numLoops; outerLoop++) { for (i = 0; i < setup->numBuffers; i++) { do { coo_req_start(pDsaData); status = cpaCyDsaSignRS(setup->cyInstanceHandle, cbFunc, pDsaData, &rsOpData[i], &protocolStatus, &dsaR[i], &dsaS[i]); coo_req_stop(pDsaData, status); if (CPA_STATUS_RETRY == status) { #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { sampleCodeAsymPollInstance(setup->cyInstanceHandle, 0); nextPoll = numOps + asymPollingInterval_g; } } #endif pDsaData->retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small break */ if (RETRY_LIMIT == (pDsaData->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { BUSY_LOOP(); } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy( pDsaData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } } #endif /*if for some reason the DSA sign returns fail, decrease the * numOperations expected in the callback so that the code does not * wait forever */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("DSA Sign function failed with status:%d\n", status); break; } } if (CPA_STATUS_SUCCESS != status) { break; } } #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pDsaData, setup->syncMode, setup->numBuffers, setup->numLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Thread %u timeout.", setup->threadID); } } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { IA_CYCLE_COUNT_CALCULATION(); } coo_average(pDsaData); coo_deinit(pDsaData); /*free Arrays of buffer pointers and pData */ FREE_DSA_SIGN_MEM; sampleCodeSemaphoreDestroy(&pDsaData->comp); pDsaData->threadReturnStatus = status; #ifdef POLL_INLINE qaeMemFree((void **)&instanceInfo2); #endif if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } /** ***************************************************************************** * @ingroup dsaPerformance * dsaPrintStats * * @description * Print out the DSA performance * *****************************************************************************/ static CpaStatus dsaPrintStats(thread_creation_data_t *data) { PRINT("DSA VERIFY\n"); PRINT("Modulus Size %19d\n", data->packetSize * NUM_BITS_IN_BYTE); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup dsaPerformance * dsaSignPrintStats * * @description * Print out the DSA sign only performance * *****************************************************************************/ static CpaStatus dsaSignPrintStats(thread_creation_data_t *data) { PRINT("DSA SIGN\n"); PRINT("Modulus Size %19d\n", data->packetSize * NUM_BITS_IN_BYTE); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup dsaPerformance * dsaPerformanceGen * * @description * This function is called by the framework to execute the DSA performance * thread. This is a generic function, which calls different performance * functions based on passed argument. * *****************************************************************************/ static void dsaPerformanceGen(single_thread_test_data_t *testSetup, dsa_step_t step) { dsa_test_params_t dsaSetup = {0}; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; dsa_test_params_t *params = (dsa_test_params_t *)testSetup->setupPtr; CpaInstanceInfo2 *instanceInfo = NULL; #ifdef SC_DEV_INFO_ENABLED CpaDeviceInfo deviceInfo = {0}; #endif testSetup->passCriteria = getPassCriteria(); /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway */ startBarrier(); /* * In case of error scenario, the thread will exit early. * register the print function here itself to properly exit with statistics. */ if (DSA_STEP_VERIFY == step) { testSetup->statsPrintFunc = (stats_print_func_t)dsaPrintStats; } else if (DSA_STEP_SIGNRS == step) { testSetup->statsPrintFunc = (stats_print_func_t)dsaSignPrintStats; } /*give our thread a unique memory location to store performance stats */ dsaSetup.threadID = testSetup->threadID; dsaSetup.performanceStats = testSetup->performanceStats; dsaSetup.hashAlg = params->hashAlg; dsaSetup.pLenInBytes = params->pLenInBytes; dsaSetup.qLenInBytes = params->qLenInBytes; dsaSetup.numBuffers = params->numBuffers; dsaSetup.numLoops = params->numLoops; dsaSetup.syncMode = params->syncMode; /*get the instance handles so that we can start our thread on the selected * instance */ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("Could not get any instances\n"); PRINT_ERR("DSA Thread FAILED\n"); dsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); dsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Could not allocate memory for logical instances\n"); qaeMemFree((void **)&instanceInfo); dsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cpaCyGetInstances(numInstances, cyInstances); /* give our thread a logical crypto instance to use * use % to wrap around the max number of instances */ dsaSetup.cyInstanceHandle = cyInstances[(testSetup->logicalQaInstance) % numInstances]; status = cpaCyInstanceGetInfo2(dsaSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); dsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } #ifdef SC_DEV_INFO_ENABLED /* check whether asym service enabled or not for the instance */ status = cpaGetDeviceInfo(instanceInfo->physInstId.acceleratorId, &deviceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaGetDeviceInfo failed", __func__, __LINE__); dsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } if (CPA_FALSE == deviceInfo.cyAsymEnabled) { PRINT_ERR("%s::%d Error! cyAsymEnabled service not enabled for the " "configured instance\n", __func__, __LINE__); dsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } #endif if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } dsaSetup.performanceStats->packageId = instanceInfo->physInstId.packageId; /*launch function that does all the work */ if (DSA_STEP_VERIFY == step) { status = dsaPerform(&dsaSetup); } else if (DSA_STEP_SIGNRS == step) { status = dsaSignPerform(&dsaSetup); } else { PRINT_ERR("Incorrect step"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != status) { PRINT("DSA Thread %u FAILED\n", testSetup->threadID); dsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadComplete(testSetup->threadID); } /** ***************************************************************************** * @ingroup dsaPerformance * dsaPerformance * * @description * This function is called by the framework to execute the dsaPerform * thread * *****************************************************************************/ void dsaPerformance(single_thread_test_data_t *testSetup) { dsaPerformanceGen(testSetup, DSA_STEP_VERIFY); } EXPORT_SYMBOL(dsaPerformance); /** ***************************************************************************** * @ingroup dsaPerformance * dsaSignPerformance * * @description * This function is called by the framework to execute the dsaSignPerform * thread * *****************************************************************************/ void dsaSignPerformance(single_thread_test_data_t *testSetup) { dsaPerformanceGen(testSetup, DSA_STEP_SIGNRS); } EXPORT_SYMBOL(dsaSignPerformance); /** ***************************************************************************** * @ingroup dsaPerformance * setupDsaTestGen * * @description * This function setups up a DSA thread. Once called the user then calls the * createThreads function which replicates this setup in threads across * several cores, each using a separate acceleration engine instances. * This is a generic function for setting up test, which defines different * performance functions based on passed argument. * *****************************************************************************/ static CpaStatus setupDsaTestGen(Cpa32U pLenInBits, Cpa32U qLenInBits, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops, dsa_step_t step) { /*setup is a multi-dimensional array that stores the setup for all thread * variations in an array of characters. We store our test setup at the * start of the second array ie index 0, [][0]. * There may be multi thread types(setups) running as counted by * testTypeCount_g */ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure */ dsa_test_params_t *dsaSetup = NULL; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started */ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } if (iaCycleCount_g) { #ifdef POLL_INLINE enablePollInline(); #endif timeStampTime_g = getTimeStampTime(); PRINT("timeStampTime_g %llu\n", timeStampTime_g); } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } if (DSA_STEP_VERIFY == step) { testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)dsaPerformance; } else if (DSA_STEP_SIGNRS == step) { testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)dsaSignPerformance; } else { PRINT_ERR("Incorrect step"); return CPA_STATUS_FAIL; } testSetupData_g[testTypeCount_g].packetSize = pLenInBits / NUM_BITS_IN_BYTE; dsaSetup = (dsa_test_params_t *)&thread_setup_g[testTypeCount_g][0]; /*then we store the test setup in the above location */ if (MODULUS_1024_BIT == pLenInBits && EXPONENT_160_BIT == qLenInBits) { dsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA1; } else if (MODULUS_2048_BIT == pLenInBits && EXPONENT_224_BIT == qLenInBits) { dsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA224; } else if (MODULUS_2048_BIT == pLenInBits && EXPONENT_256_BIT == qLenInBits) { dsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA256; } else if (MODULUS_3072_BIT == pLenInBits && EXPONENT_256_BIT == qLenInBits) { dsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA256; } else { PRINT_ERR("pLen & qLen combination not supported, must be 1024/160 "); PRINT("2048/224, 2048/256 or 3072/256\n"); return CPA_STATUS_FAIL; } dsaSetup->pLenInBytes = pLenInBits / NUM_BITS_IN_BYTE; dsaSetup->qLenInBytes = qLenInBits / NUM_BITS_IN_BYTE; dsaSetup->syncMode = syncMode; dsaSetup->numBuffers = numBuffers; dsaSetup->numLoops = numLoops; return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup dsaPerformance * setupDsaSignTest * * @description * This function setups up a DSA sign only test. * *****************************************************************************/ CpaStatus setupDsaSignTest(Cpa32U pLenInBits, Cpa32U qLenInBits, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops) { return setupDsaTestGen(pLenInBits, qLenInBits, syncMode, numBuffers, numLoops, DSA_STEP_SIGNRS); } /** ***************************************************************************** * @ingroup dsaPerformance * setupDsaTest * * @description * This function setups up a DSA sign & verify test. * *****************************************************************************/ CpaStatus setupDsaTest(Cpa32U pLenInBits, Cpa32U qLenInBits, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops) { return setupDsaTestGen(pLenInBits, qLenInBits, syncMode, numBuffers, numLoops, DSA_STEP_VERIFY); } cpa_sample_code_ec_curves.h000066400000000000000000000505101503624047500362340ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_ec_curves.h * * @ingroup cryptoThreads * * @description * This file contains the elliptic curve definitions as defined in * http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf * *****************************************************************************/ #ifndef CPA_SAMPLE_CODE_EC_CURVES_H #define CPA_SAMPLE_CODE_EC_CURVES_H #include "cpa_sample_code_crypto_utils.h" /************************************************************ * PRIME Space curves * * **********************************************************/ /*********** NIST P-192 CURVE ****************/ Cpa8U sample_nist_p192_p[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Cpa8U sample_nist_p192_r[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, 0xde, 0xf8, 0x36, 0x14, 0x6b, 0xc9, 0xb1, 0xb4, 0xd2, 0x28, 0x31}; Cpa8U sample_nist_p192_a[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}; Cpa8U sample_nist_p192_b[] = { 0x64, 0x21, 0x05, 0x19, 0xe5, 0x9c, 0x80, 0xe7, 0x0f, 0xa7, 0xe9, 0xab, 0x72, 0x24, 0x30, 0x49, 0xfe, 0xb8, 0xde, 0xec, 0xc1, 0x46, 0xb9, 0xb1}; Cpa8U sample_nist_p192_xg[] = { 0x18, 0x8d, 0xa8, 0x0e, 0xb0, 0x30, 0x90, 0xf6, 0x7c, 0xbf, 0x20, 0xeb, 0x43, 0xa1, 0x88, 0x00, 0xf4, 0xff, 0x0a, 0xfd, 0x82, 0xff, 0x10, 0x12}; Cpa8U sample_nist_p192_yg[] = { 0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, 0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11}; Cpa8U sample_nist_p192_k[] = { 0xaa, 0x23, 0x98, 0x33, 0x27, 0x76, 0x2f, 0x07, 0xbf, 0xa5, 0x5e, 0xaf, 0x3e, 0xfa, 0xaf, 0x72, 0x2a, 0x67, 0x6e, 0xc3, 0x58, 0xf7, 0x37, 0x80}; /*********** NIST P-224 CURVE ****************/ Cpa8U sample_nist_p224_p[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; Cpa8U sample_nist_p224_r[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xDD, 0x29, 0x45, 0x5c, 0x5c, 0x2a, 0x3d}; Cpa8U sample_nist_p224_a[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}; Cpa8U sample_nist_p224_b[] = { 0xb4, 0x05, 0x0a, 0x85, 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7, 0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4}; Cpa8U sample_nist_p224_xg[] = { 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, 0x11, 0x5c, 0x1d, 0x21}; Cpa8U sample_nist_p224_yg[] = { 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34}; Cpa8U sample_nist_p224_k[] = { 0x00, 0xd9, 0x7c, 0x31, 0x2b, 0xc0, 0x08, 0x74, 0x77, 0x82, 0x7f, 0xf5, 0x3d, 0xab, 0x27, 0x85, 0xd5, 0xeA, 0xa5, 0xca, 0x79, 0xa1, 0xea, 0xfd, 0xb7, 0x73, 0x4a, 0x11}; /*********** NIST P-256 CURVE ****************/ Cpa8U sample_nist_p256_p[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Cpa8U sample_nist_p256_r[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xBC, 0xe6, 0xFA, 0xAD, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xCA, 0xc2, 0xFC, 0x63, 0x25, 0x51}; Cpa8U sample_nist_p256_a[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}; Cpa8U sample_nist_p256_b[] = { 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b}; Cpa8U sample_nist_p256_xg[] = { 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96}; Cpa8U sample_nist_p256_yg[] = { 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}; Cpa8U sample_nist_p256_k[] = { 0x08, 0xb2, 0xd7, 0x8f, 0x1d, 0x33, 0xd6, 0x9f, 0x68, 0x9c, 0x33, 0x67, 0x9e, 0xaa, 0xa6, 0xd7, 0x06, 0xa9, 0xce, 0xd8, 0xc3, 0x4f, 0xe8, 0xda, 0xbb, 0x93, 0xd2, 0x73, 0xd6, 0x50, 0xa6, 0x83}; /*********** NIST P-384 CURVE ****************/ Cpa8U sample_nist_p384_p[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xFE, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}; Cpa8U sample_nist_p384_r[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, 0xeC, 0xeC, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73}; Cpa8U sample_nist_p384_a[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xFE, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc}; Cpa8U sample_nist_p384_b[] = { 0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b, 0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef}; Cpa8U sample_nist_p384_xg[] = { 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7}; Cpa8U sample_nist_p384_yg[] = { 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f}; Cpa8U sample_nist_p384_k[] = { 0xbf, 0xd3, 0xe3, 0xe1, 0x8d, 0x5d, 0x1d, 0x71, 0xf3, 0x1f, 0x2a, 0x93, 0xd8, 0x91, 0x75, 0xda, 0x52, 0xc6, 0x69, 0xf0, 0x9a, 0xc1, 0x7d, 0xaa, 0xeb, 0x54, 0x8d, 0xb5, 0x54, 0x0f, 0x22, 0x91, 0x5c, 0x8b, 0x54, 0x55, 0xaa, 0x4d, 0xe6, 0xa3, 0xd7, 0xfe, 0x1f, 0xca, 0x66, 0xd4, 0x8b, 0xb4}; /*********** NIST 521 CURVE ****************/ Cpa8U sample_nist_p521_p[] = { 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Cpa8U sample_nist_p521_r[] = { 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09}; Cpa8U sample_nist_p521_a[] = { 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}; Cpa8U sample_nist_p521_b[] = { 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00}; Cpa8U sample_nist_p521_xg[] = { 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66}; Cpa8U sample_nist_p521_yg[] = { 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50}; /************************************************************ * BINARY Space curves * * **********************************************************/ /*********** NIST 163 BINARY CURVE ****************/ Cpa8U sample_nist_binary_gf2_163_p[] = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9}; Cpa8U sample_nist_binary_gf2_163_a[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; Cpa8U sample_nist_binary_gf2_163_b[] = { 0x02, 0x0a, 0x60, 0x19, 0x07, 0xb8, 0xc9, 0x53, 0xca, 0x14, 0x81, 0xeb, 0x10, 0x51, 0x2f, 0x78, 0x74, 0x4a, 0x32, 0x05, 0xfd}; Cpa8U sample_nist_binary_gf2_163_xg[] = { 0x03, 0xf0, 0xeb, 0xa1, 0x62, 0x86, 0xa2, 0xd5, 0x7e, 0xa0, 0x99, 0x11, 0x68, 0xd4, 0x99, 0x46, 0x37, 0xe8, 0x34, 0x3e, 0x36}; Cpa8U sample_nist_binary_gf2_163_yg[] = { 0x00, 0xd5, 0x1f, 0xbc, 0x6c, 0x71, 0xa0, 0x09, 0x4f, 0xa2, 0xcd, 0xd5, 0x45, 0xb1, 0x1c, 0x5c, 0x0c, 0x79, 0x73, 0x24, 0xf1}; Cpa8U sample_nist_binary_gf2_163_r[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92, 0xfe, 0x77, 0xe7, 0x0c, 0x12, 0xa4, 0x23, 0x4c, 0x33}; /*********** NIST 233 BINARY CURVE ****************/ Cpa8U sample_nist_binary_gf2_233_p[] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; Cpa8U sample_nist_binary_gf2_233_a[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; Cpa8U sample_nist_binary_gf2_233_b[] = { 0x00, 0x66, 0x64, 0x7e, 0xde, 0x6c, 0x33, 0x2c, 0x7f, 0x8c, 0x09, 0x23, 0xbb, 0x58, 0x21, 0x3b, 0x33, 0x3b, 0x20, 0xe9, 0xce, 0x42, 0x81, 0xfe, 0x11, 0x5f, 0x7d, 0x8f, 0x90, 0xad}; Cpa8U sample_nist_binary_gf2_233_xg[] = { 0x00, 0xfa, 0xc9, 0xdf, 0xcb, 0xac, 0x83, 0x13, 0xbb, 0x21, 0x39, 0xf1, 0xbb, 0x75, 0x5f, 0xef, 0x65, 0xbc, 0x39, 0x1f, 0x8b, 0x36, 0xf8, 0xf8, 0xeb, 0x73, 0x71, 0xfd, 0x55, 0x8b}; Cpa8U sample_nist_binary_gf2_233_yg[] = { 0x01, 0x00, 0x6a, 0x08, 0xa4, 0x19, 0x03, 0x35, 0x06, 0x78, 0xe5, 0x85, 0x28, 0xbe, 0xbf, 0x8a, 0x0b, 0xef, 0xf8, 0x67, 0xa7, 0xca, 0x36, 0x71, 0x6f, 0x7e, 0x1, 0xf8, 0x10, 0x52}; Cpa8U sample_nist_binary_gf2_233_r[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe9, 0x74, 0xe7, 0x2f, 0x8a, 0x69, 0x22, 0x03, 0x1d, 0x26, 0x3, 0xcf, 0xe0, 0xd7}; ec_curves_t curves_g[] = { {GFP_P192_SIZE_IN_BYTES, CPA_CY_EC_FIELD_TYPE_PRIME, sample_nist_p192_p, sizeof(sample_nist_p192_p), sample_nist_p192_r, sizeof(sample_nist_p192_r), sample_nist_p192_a, sizeof(sample_nist_p192_a), sample_nist_p192_b, sizeof(sample_nist_p192_b), sample_nist_p192_xg, sizeof(sample_nist_p192_xg), sample_nist_p192_yg, sizeof(sample_nist_p192_yg)}, {GFP_P224_SIZE_IN_BYTES, CPA_CY_EC_FIELD_TYPE_PRIME, sample_nist_p224_p, sizeof(sample_nist_p224_p), sample_nist_p224_r, sizeof(sample_nist_p224_r), sample_nist_p224_a, sizeof(sample_nist_p224_a), sample_nist_p224_b, sizeof(sample_nist_p224_b), sample_nist_p224_xg, sizeof(sample_nist_p224_xg), sample_nist_p224_yg, sizeof(sample_nist_p224_yg)}, {GFP_P256_SIZE_IN_BYTES, CPA_CY_EC_FIELD_TYPE_PRIME, sample_nist_p256_p, sizeof(sample_nist_p256_p), sample_nist_p256_r, sizeof(sample_nist_p256_r), sample_nist_p256_a, sizeof(sample_nist_p256_a), sample_nist_p256_b, sizeof(sample_nist_p256_b), sample_nist_p256_xg, sizeof(sample_nist_p256_xg), sample_nist_p256_yg, sizeof(sample_nist_p256_yg)}, {GFP_P384_SIZE_IN_BYTES, CPA_CY_EC_FIELD_TYPE_PRIME, sample_nist_p384_p, sizeof(sample_nist_p384_p), sample_nist_p384_r, sizeof(sample_nist_p384_r), sample_nist_p384_a, sizeof(sample_nist_p384_a), sample_nist_p384_b, sizeof(sample_nist_p384_b), sample_nist_p384_xg, sizeof(sample_nist_p384_xg), sample_nist_p384_yg, sizeof(sample_nist_p384_yg)}, {GFP_P521_SIZE_IN_BYTES, CPA_CY_EC_FIELD_TYPE_PRIME, sample_nist_p521_p, sizeof(sample_nist_p521_p), sample_nist_p521_r, sizeof(sample_nist_p521_r), sample_nist_p521_a, sizeof(sample_nist_p521_a), sample_nist_p521_b, sizeof(sample_nist_p521_b), sample_nist_p521_xg, sizeof(sample_nist_p521_xg), sample_nist_p521_yg, sizeof(sample_nist_p521_yg)}, {GF2_B163_SIZE_IN_BYTES, CPA_CY_EC_FIELD_TYPE_BINARY, sample_nist_binary_gf2_163_p, sizeof(sample_nist_binary_gf2_163_p), sample_nist_binary_gf2_163_r, sizeof(sample_nist_binary_gf2_163_r), sample_nist_binary_gf2_163_a, sizeof(sample_nist_binary_gf2_163_a), sample_nist_binary_gf2_163_b, sizeof(sample_nist_binary_gf2_163_b), sample_nist_binary_gf2_163_xg, sizeof(sample_nist_binary_gf2_163_xg), sample_nist_binary_gf2_163_yg, sizeof(sample_nist_binary_gf2_163_yg)}, {GF2_B233_SIZE_IN_BYTES, CPA_CY_EC_FIELD_TYPE_BINARY, sample_nist_binary_gf2_233_p, sizeof(sample_nist_binary_gf2_233_p), sample_nist_binary_gf2_233_r, sizeof(sample_nist_binary_gf2_233_r), sample_nist_binary_gf2_233_a, sizeof(sample_nist_binary_gf2_233_a), sample_nist_binary_gf2_233_b, sizeof(sample_nist_binary_gf2_233_b), sample_nist_binary_gf2_233_xg, sizeof(sample_nist_binary_gf2_233_xg), sample_nist_binary_gf2_233_yg, sizeof(sample_nist_binary_gf2_233_yg)} }; typedef struct ec_pairs_s { Cpa32U curve; Cpa32U fieldType; } ec_pairs_t; ec_pairs_t ec_pairs[] = { {GFP_P192_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_PRIME}, {GFP_P224_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_PRIME}, {GFP_P256_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_PRIME}, {GFP_P384_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_PRIME}, {GFP_P521_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_PRIME}, {GF2_B163_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_BINARY}, {GF2_B233_SIZE_IN_BITS, CPA_CY_EC_FIELD_TYPE_BINARY} }; #endif cpa_sample_code_ec_montedwds_perf.c000066400000000000000000000755721503624047500377570ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/** ***************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_ec_montedwds_perf.c * * @defgroup ecMontEdwdsThreads * * @ingroup ecMontEdwdsThreads * * @description * This sample code test runs EcMontEdwds point and generator * multiplication in given amount of loops and buffers. Test measures QAT * performance in operations per second and calculates cost of offload of * EcMontEdwds function. Sample code uses generated test vectors based on * Edwards(448, 25519) and Montgomery(448, 25519) curves. Supported * EcMontEdwds operations are: generator multiplication and point * multiplication. * *****************************************************************************/ #include "cpa.h" #include "cpa_types.h" #include "cpa_sample_code_crypto_utils.h" #include "icp_sal_poll.h" #include "qat_perf_cycles.h" #include "cpa_sample_code_ec_montedwds_vectors.h" #if CY_API_VERSION_AT_LEAST(2, 3) extern Cpa32U packageIdCount_g; void ecMontEdwdsPerformance(single_thread_test_data_t *testSetup); CpaBoolean isECMontEdwdsSupported(void) { CpaStatus status = CPA_STATUS_FAIL; CpaCyCapabilitiesInfo cap = {0}; CpaBoolean isECMontEdwdsEnabled = CPA_FALSE; status = getCryptoInstanceCapabilities(&cap, ASYM); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("getCryptoInstanceCapabilities failed with status: %d\n", status); return isECMontEdwdsEnabled; } isECMontEdwdsEnabled = cap.ecEdMontSupported; return isECMontEdwdsEnabled; } EXPORT_SYMBOL(isECMontEdwdsSupported); /***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * Callback used after ecMontEdwds operation * *****************************************************************************/ void ecMontEdwdsCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { processCallback(pCallbackTag); } /*************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * Print the performance stats of the ecMontEdwds operations * ***************************************************************************/ static CpaStatus ecMontEdwdsPrintStats(thread_creation_data_t *data) { ec_montedwds_test_params_t *setup = (ec_montedwds_test_params_t *)data->setupPtr; char *generatorText = NULL; char *curveTypeText = NULL; switch (setup->generator) { case CPA_TRUE: generatorText = "Generator multiplication (kG)"; break; case CPA_FALSE: generatorText = "Point multiplication (kP)"; break; default: PRINT("Unknown ECED operation %d\n", setup->generator); break; } switch (setup->curveType) { case CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE: curveTypeText = "Montgomery 25519 curve"; break; case CPA_CY_EC_MONTEDWDS_ED25519_TYPE: curveTypeText = "Twisted Edwards 25519 curve"; break; case CPA_CY_EC_MONTEDWDS_CURVE448_TYPE: curveTypeText = "Montgomery 448 curve"; break; case CPA_CY_EC_MONTEDWDS_ED448_TYPE: curveTypeText = "Twisted Edwards 448 curve"; break; default: PRINT("Unknown ECED curve type %d\n", setup->curveType); break; } PRINT("ECMONTEDWDS TEST\n"); if (reliability_g) { PRINT("Reliability mode enabled\n"); PRINT("Vector number %d\n", setup->vector); } PRINT("Operation %s\n", generatorText); PRINT("Curve type %s\n", curveTypeText); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /*************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This function allocates data used in ecMontEdwds operations * ***************************************************************************/ static CpaStatus ecMontEdwdsAllocData( ec_montedwds_test_params_t *setup, sample_ec_montedwds_vectors_t *testVectors, CpaCyEcMontEdwdsPointMultiplyOpData **ppReturnOpData, CpaFlatBuffer **ppReturnXk, CpaFlatBuffer **ppReturnYk) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U node = 0; Cpa32U numBuffers = 0; CpaCyEcMontEdwdsPointMultiplyOpData **ppOpData = NULL; CpaFlatBuffer **ppXk = NULL; CpaFlatBuffer **ppYk = NULL; /* get the node we are running on for local memory allocation */ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /* alloc array of pointers to opData */ if (CPA_STATUS_SUCCESS == status) { status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&ppOpData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) return status; } memset(ppOpData, 0, (sizeof(CpaCyEcMontEdwdsPointMultiplyOpData *) * setup->numBuffers)); *ppReturnOpData = (CpaCyEcMontEdwdsPointMultiplyOpData *)ppOpData; /* alloc array of pointers to Xk */ if (CPA_STATUS_SUCCESS == status) { status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&ppXk, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) return status; } memset(ppXk, 0, (sizeof(CpaFlatBuffer *) * setup->numBuffers)); *ppReturnXk = (CpaFlatBuffer *)ppXk; /* alloc array of pointers to Yk */ if (CPA_STATUS_SUCCESS == status) { status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&ppYk, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) return status; } memset(ppYk, 0, (sizeof(CpaFlatBuffer *) * setup->numBuffers)); *ppReturnYk = (CpaFlatBuffer *)ppYk; if (CPA_STATUS_SUCCESS == status) { for (numBuffers = 0; numBuffers < setup->numBuffers; numBuffers++) { /* alloc memory for opData in buffer */ ppOpData[numBuffers] = qaeMemAllocNUMA(sizeof(CpaCyEcMontEdwdsPointMultiplyOpData), node, BYTE_ALIGNMENT_64); if (ppOpData[numBuffers] == NULL) return CPA_STATUS_FAIL; memset(ppOpData[numBuffers], 0, sizeof(CpaCyEcMontEdwdsPointMultiplyOpData)); /* alloc memory for opData.x.pData in buffer */ if (testVectors->xSize > 0) { ppOpData[numBuffers]->x.pData = qaeMemAllocNUMA( testVectors->xSize, node, BYTE_ALIGNMENT_64); if (ppOpData[numBuffers]->x.pData == NULL) return CPA_STATUS_FAIL; memset(ppOpData[numBuffers]->x.pData, 0, testVectors->xSize); } /* alloc memory for opData.y.pData in buffer */ if (testVectors->ySize > 0) { ppOpData[numBuffers]->y.pData = qaeMemAllocNUMA( testVectors->ySize, node, BYTE_ALIGNMENT_64); if (ppOpData[numBuffers]->y.pData == NULL) return CPA_STATUS_FAIL; memset(ppOpData[numBuffers]->y.pData, 0, testVectors->ySize); } /* alloc memory for opData.k.pData in buffer */ ppOpData[numBuffers]->k.pData = qaeMemAllocNUMA(testVectors->kSize, node, BYTE_ALIGNMENT_64); if (ppOpData[numBuffers]->k.pData == NULL) return CPA_STATUS_FAIL; memset(ppOpData[numBuffers]->k.pData, 0, testVectors->kSize); /* alloc memory for ppXk CpaFlatBuffer */ ppXk[numBuffers] = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (ppXk[numBuffers] == NULL) return CPA_STATUS_FAIL; memset(ppXk[numBuffers], 0, sizeof(CpaFlatBuffer)); /* alloc memory for Data in ppXk CpaFlatBuffer */ ppXk[numBuffers]->pData = qaeMemAllocNUMA(testVectors->uSize, node, BYTE_ALIGNMENT_64); if (ppXk[numBuffers]->pData == NULL) return CPA_STATUS_FAIL; memset(ppXk[numBuffers]->pData, 0, testVectors->uSize); /* alloc memory for ppYk CpaFlatBuffer */ ppYk[numBuffers] = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (ppYk[numBuffers] == NULL) return CPA_STATUS_FAIL; memset(ppYk[numBuffers], 0, sizeof(CpaFlatBuffer)); /* alloc memory for Data in ppYk CpaFlatBuffer */ if (testVectors->vSize > 0) { ppYk[numBuffers]->pData = qaeMemAllocNUMA( testVectors->vSize, node, BYTE_ALIGNMENT_64); if (ppYk[numBuffers]->pData == NULL) return CPA_STATUS_FAIL; memset(ppYk[numBuffers]->pData, 0, testVectors->vSize); } } } return status; } /*************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This function copies test vectors data to opData * ***************************************************************************/ static CpaStatus ecMontEdwdsSetupData( ec_montedwds_test_params_t *setup, sample_ec_montedwds_vectors_t *testVectors, CpaCyEcMontEdwdsPointMultiplyOpData **ppOpData, CpaFlatBuffer **ppXk, CpaFlatBuffer **ppYk) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numBuffers = 0; for (numBuffers = 0; numBuffers < setup->numBuffers; numBuffers++) { ppOpData[numBuffers]->generator = setup->generator; ppOpData[numBuffers]->curveType = setup->curveType; ppOpData[numBuffers]->x.dataLenInBytes = testVectors->xSize; ppOpData[numBuffers]->y.dataLenInBytes = testVectors->ySize; ppOpData[numBuffers]->k.dataLenInBytes = testVectors->kSize; ppXk[numBuffers]->dataLenInBytes = testVectors->uSize; ppYk[numBuffers]->dataLenInBytes = testVectors->vSize; if (testVectors->xSize > 0) { generateRandomData(ppOpData[numBuffers]->x.pData, testVectors->xSize); } if (testVectors->ySize > 0) { generateRandomData(ppOpData[numBuffers]->y.pData, testVectors->ySize); } generateRandomData(ppOpData[numBuffers]->k.pData, testVectors->kSize); } return status; } /*************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This function frees allocated data at the end of test * ***************************************************************************/ static void ecMontEdwdsFreeData(ec_montedwds_test_params_t *setup, CpaCyEcMontEdwdsPointMultiplyOpData **ppOpData, CpaFlatBuffer **ppXk, CpaFlatBuffer **ppYk) { Cpa32U numBuffers = 0; if (ppOpData != NULL) { for (numBuffers = 0; numBuffers < setup->numBuffers; numBuffers++) { if (ppOpData[numBuffers] != NULL) { if (ppOpData[numBuffers]->x.pData != NULL) { qaeMemFreeNUMA((void **)&ppOpData[numBuffers]->x.pData); } if (ppOpData[numBuffers]->y.pData != NULL) { qaeMemFreeNUMA((void **)&ppOpData[numBuffers]->y.pData); } if (ppOpData[numBuffers]->k.pData != NULL) { qaeMemFreeNUMA((void **)&ppOpData[numBuffers]->k.pData); } qaeMemFreeNUMA((void **)&ppOpData[numBuffers]); } } qaeMemFreeNUMA((void **)&ppOpData); } if (ppXk != NULL) { for (numBuffers = 0; numBuffers < setup->numBuffers; numBuffers++) { if (ppXk[numBuffers] != NULL) { if (ppXk[numBuffers]->pData != NULL) { qaeMemFreeNUMA((void **)&ppXk[numBuffers]->pData); } qaeMemFreeNUMA((void **)&ppXk[numBuffers]); } } qaeMemFreeNUMA((void **)&ppXk); } if (ppYk != NULL) { for (numBuffers = 0; numBuffers < setup->numBuffers; numBuffers++) { if (ppYk[numBuffers] != NULL) { if (ppYk[numBuffers]->pData != NULL) { qaeMemFreeNUMA((void **)&ppYk[numBuffers]->pData); } qaeMemFreeNUMA((void **)&ppYk[numBuffers]); } } qaeMemFreeNUMA((void **)&ppYk); } } /*************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * Main function that performs ecMontEdwds operation * ***************************************************************************/ static CpaStatus ecMontEdwdsPerform(ec_montedwds_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean multiplyStatus = CPA_FALSE; Cpa32U numLoops = 0; Cpa32U numBuffers = 0; perf_data_t *pPerfData = NULL; void *cbFunc = NULL; CpaCyEcMontEdwdsPointMultiplyOpData **ppOpData = NULL; CpaFlatBuffer **ppXk = NULL; CpaFlatBuffer **ppYk = NULL; sample_ec_montedwds_vectors_t testVectors = {0}; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_SUCCESS; CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } } #endif /* get memory location to write performance stats to */ pPerfData = setup->performanceStats; /* get the number of operations to be done in this test */ pPerfData->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; coo_init(pPerfData, pPerfData->numOperations); /* Initialise semaphore used in callback */ sampleCodeSemaphoreInit(&pPerfData->comp, 0); /* set the callback function if asynchronous mode is set */ if (ASYNC == setup->syncMode) { cbFunc = ecMontEdwdsCallback; } /* get test vectors */ if (status == CPA_STATUS_SUCCESS) { status = getEcMontEdwdsTestVectors( setup->generator, setup->curveType, setup->vector, &testVectors); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate Data\n"); status = CPA_STATUS_FAIL; } } /* alloc opData */ if (status == CPA_STATUS_SUCCESS) { status = ecMontEdwdsAllocData( setup, &testVectors, (CpaCyEcMontEdwdsPointMultiplyOpData **)&ppOpData, (CpaFlatBuffer **)&ppXk, (CpaFlatBuffer **)&ppYk); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not allocate Data\n"); status = CPA_STATUS_FAIL; } } /* setup opData */ if (status == CPA_STATUS_SUCCESS) { status = ecMontEdwdsSetupData(setup, &testVectors, ppOpData, ppXk, ppYk); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not setup Data\n"); status = CPA_STATUS_FAIL; } } if (status == CPA_STATUS_SUCCESS) { /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /*record the start time, the callback measures the end time when the * last response is received*/ pPerfData->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { for (numBuffers = 0; numBuffers < setup->numBuffers; numBuffers++) { do { coo_req_start(pPerfData); status = cpaCyEcMontEdwdsPointMultiply(setup->cyInstanceHandle, cbFunc, pPerfData, ppOpData[numBuffers], &multiplyStatus, ppXk[numBuffers], ppYk[numBuffers]); coo_req_stop(pPerfData, status); if (CPA_STATUS_RETRY == status) { #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { sampleCodeAsymPollInstance( setup->cyInstanceHandle, 0); nextPoll = numOps + asymPollingInterval_g; } } #endif pPerfData->retries++; /*if the acceleration engine is busy pause for a * moment by making a context switch*/ if (RETRY_LIMIT == (pPerfData->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyEcMontEdwdsPointMultiply function failed " "with status:%d, loop: %d, buffer: %d\n", status, numLoops, numBuffers); break; } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy(pPerfData, setup->cyInstanceHandle, &pollStatus); if (CPA_STATUS_SUCCESS != pollStatus) { PRINT_ERR( "coo_poll_trad_cy failed with status: %d\n", pollStatus); } nextPoll = numOps + asymPollingInterval_g; } } } #endif } /* End loop - numBuffers */ if (CPA_STATUS_SUCCESS != status) { break; } } /* End loop - numLoops */ #ifdef POLL_INLINE if (poll_inline_g) { if ((instanceInfo2->isPolled)) { /* Now need to wait for all the in-flight Requests */ pollStatus = cyPollNumOperations(pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); if (CPA_STATUS_SUCCESS != pollStatus) { PRINT_ERR("cyPollNumOperations failed with status: %d\n", pollStatus); status = CPA_STATUS_FAIL; } } } #endif if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pPerfData, setup->syncMode, setup->numBuffers, setup->numLoops); } } coo_average(pPerfData); coo_deinit(pPerfData); sampleCodeSemaphoreDestroy(&pPerfData->comp); ecMontEdwdsFreeData(setup, ppOpData, ppXk, ppYk); #ifdef POLL_INLINE qaeMemFree((void **)&instanceInfo2); #endif return status; } /***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This function starts performance test in thread * *****************************************************************************/ void ecMontEdwdsPerformance(single_thread_test_data_t *testSetup) { ec_montedwds_test_params_t ecMontEdwdsSetup = {0}; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; ec_montedwds_test_params_t *params = (ec_montedwds_test_params_t *)testSetup->setupPtr; CpaInstanceInfo2 *instanceInfo = NULL; /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space is does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*set the print function that can be used to print stats at the end of the * test*/ testSetup->statsPrintFunc = (stats_print_func_t)ecMontEdwdsPrintStats; /*give our thread a unique memory location to store performance stats*/ ecMontEdwdsSetup.performanceStats = testSetup->performanceStats; memset(ecMontEdwdsSetup.performanceStats, 0, sizeof(perf_data_t)); /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (cyInstances == NULL) { PRINT_ERR("Error allocating memory for instance handles\n"); ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /* give our thread a logical crypto instance to use * use % to wrap around the max number of instances*/ ecMontEdwdsSetup.threadID = testSetup->threadID; ecMontEdwdsSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); return; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(ecMontEdwdsSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&cyInstances); ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } ecMontEdwdsSetup.performanceStats->packageId = instanceInfo->physInstId.packageId; ecMontEdwdsSetup.syncMode = params->syncMode; ecMontEdwdsSetup.generator = params->generator; ecMontEdwdsSetup.curveType = params->curveType; ecMontEdwdsSetup.vector = params->vector; ecMontEdwdsSetup.numBuffers = params->numBuffers; ecMontEdwdsSetup.numLoops = params->numLoops; /*launch function that does all the work*/ status = ecMontEdwdsPerform(&ecMontEdwdsSetup); if (CPA_STATUS_SUCCESS != status) { PRINT("ECED Thread %u FAILED\n", testSetup->threadID); ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { ecMontEdwdsSetup.performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; } qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } /***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This function configures threads for ecMontEdwds performance test * *****************************************************************************/ CpaStatus setupEcMontEdwdsTest(sync_mode_t syncMode, CpaBoolean generator, CpaCyEcMontEdwdsCurveType curveType, Cpa32U vector, Cpa32U numBuffers, Cpa32U numLoops) { /* thread_setup_g is a multi-dimensional array that stores the setup for * all thread * variations in an array of characters. we store our test setup at the * start of the second array ie index 0. There maybe multi thread types * (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure*/ ec_montedwds_test_params_t *ecMontEdwdsSetup = NULL; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } /* start polling threads if polling is enabled in the configuration file */ if (!poll_inline_g) { if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } ecMontEdwdsSetup = (ec_montedwds_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)ecMontEdwdsPerformance; ecMontEdwdsSetup->syncMode = syncMode; ecMontEdwdsSetup->generator = generator; ecMontEdwdsSetup->curveType = curveType; ecMontEdwdsSetup->vector = vector; ecMontEdwdsSetup->numBuffers = numBuffers; ecMontEdwdsSetup->numLoops = numLoops; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setupEcMontEdwdsTest); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ cpa_sample_code_ec_montedwds_vectors.c000066400000000000000000002411441503624047500404760ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/** ***************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_ec_montedwds_perf.c * * @defgroup ecMontEdwdsThreads * * @ingroup ecMontEdwdsThreads * * @description * This file contains vectors used in ECED performance test * and function getEcEdTestVectors to select vectors for test * *****************************************************************************/ #include "cpa.h" #include "cpa_types.h" #include "cpa_sample_code_ec_montedwds_vectors.h" #if CY_API_VERSION_AT_LEAST(2, 3) /****************** * Edwards 448 Kg * ******************/ static Cpa8U edwards_448_kg_x[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x19, 0x70, 0xc6, 0x6b, 0xed, 0x0d, 0xed, 0x22, 0x1d, 0x15, 0xa6, 0x22, 0xbf, 0x36, 0xda, 0x9e, 0x14, 0x65, 0x70, 0x47, 0x0f, 0x17, 0x67, 0xea, 0x6d, 0xe3, 0x24, 0xa3, 0xd3, 0xa4, 0x64, 0x12, 0xae, 0x1a, 0xf7, 0x2a, 0xb6, 0x65, 0x11, 0x43, 0x3b, 0x80, 0xe1, 0x8b, 0x00, 0x93, 0x8e, 0x26, 0x26, 0xa8, 0x2b, 0xc7, 0x0c, 0xc0, 0x5e}; static Cpa8U edwards_448_kg_y[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x3f, 0x46, 0x71, 0x6e, 0xb6, 0xbc, 0x24, 0x88, 0x76, 0x20, 0x37, 0x56, 0xc9, 0xc7, 0x62, 0x4b, 0xea, 0x73, 0x73, 0x6c, 0xa3, 0x98, 0x40, 0x87, 0x78, 0x9c, 0x1e, 0x05, 0xa0, 0xc2, 0xd7, 0x3a, 0xd3, 0xff, 0x1c, 0xe6, 0x7c, 0x39, 0xc4, 0xfd, 0xbd, 0x13, 0x2c, 0x4e, 0xd7, 0xc8, 0xad, 0x98, 0x08, 0x79, 0x5b, 0xf2, 0x30, 0xfa, 0x14}; static Cpa8U edwards_448_kg_k[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xbb, 0xc0, 0x1f, 0xa7, 0x01, 0x05, 0xa7, 0x4f, 0xee, 0xce, 0x15, 0x66, 0xf5, 0xf9, 0x83, 0x74, 0xd1, 0xee, 0x1e, 0xd8, 0x36, 0xc0, 0x05, 0xb9, 0x9c, 0x51, 0x38, 0x1d, 0x5e, 0x02, 0x75, 0xee, 0xf3, 0xa4, 0x5b, 0x54, 0xf0, 0x11, 0xb4, 0x88, 0xa5, 0x72, 0xf4, 0x67, 0x66, 0xed, 0xc7, 0x8e, 0x80, 0xa0, 0xce, 0xa0, 0x30, 0x39, 0xe8}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xfe, 0x3a, 0xd2, 0x8f, 0xad, 0x21, 0x35, 0x8f, 0xf9, 0xc3, 0x69, 0xc2, 0x4b, 0x14, 0xdc, 0x01, 0x0e, 0x8e, 0x04, 0x16, 0x03, 0xde, 0xaf, 0x51, 0x51, 0x95, 0xaa, 0xc6, 0xdc, 0x63, 0xf7, 0x45, 0xec, 0xfe, 0x4b, 0x76, 0xe0, 0x77, 0x15, 0xc6, 0xc0, 0xba, 0x82, 0x2c, 0x7c, 0x79, 0xc3, 0x23, 0x4f, 0x70, 0x35, 0x90, 0x5e, 0xa9, 0x88}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, 0xf5, 0xd7, 0xa9, 0x38, 0x54, 0xb0, 0xe9, 0x78, 0xd7, 0x1a, 0xd6, 0xd0, 0xc3, 0xec, 0xb9, 0x36, 0x00, 0x73, 0xbc, 0xf1, 0x8e, 0xf1, 0x62, 0xbb, 0x07, 0x01, 0x5d, 0x5a, 0xa7, 0xc3, 0x55, 0x5c, 0x4a, 0xbc, 0x1d, 0xf2, 0x7f, 0x22, 0x64, 0x69, 0x06, 0xfe, 0x78, 0xbd, 0x65, 0xe4, 0x27, 0xfb, 0xd5, 0x0e, 0x85, 0x89, 0x65, 0x76, 0xa0}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x5e, 0x3e, 0x64, 0xc6, 0x39, 0x86, 0x0f, 0xe2, 0x8c, 0xe3, 0xa4, 0xb1, 0x10, 0x50, 0xc7, 0x8d, 0xe3, 0x6f, 0x4c, 0x77, 0x50, 0xeb, 0x69, 0xc8, 0x08, 0x84, 0xc7, 0xb7, 0x3d, 0xea, 0xf5, 0x7c, 0x27, 0x1b, 0x63, 0xe7, 0x6f, 0xc0, 0xf9, 0xbf, 0xca, 0x11, 0xa2, 0x3f, 0xac, 0xdf, 0x27, 0xbd, 0x69, 0x7d, 0x12, 0x97, 0x1f, 0x6d, 0xd0}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x24, 0x92, 0x79, 0x7a, 0xe5, 0x96, 0x7f, 0xad, 0xf0, 0xbd, 0xcf, 0x3a, 0xe7, 0x6b, 0x8d, 0xe3, 0x19, 0x09, 0xd0, 0x7e, 0x26, 0x6e, 0xce, 0x0c, 0x2a, 0xdd, 0x25, 0x86, 0x4e, 0xf9, 0x7d, 0xd5, 0x3b, 0xae, 0x57, 0xe7, 0xd4, 0xcc, 0x85, 0x55, 0xdd, 0xb7, 0xa5, 0xa9, 0xe6, 0xf7, 0xe4, 0x1c, 0x2f, 0xc0, 0xb2, 0x52, 0x9b, 0xf7, 0x2c}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x1d, 0x28, 0x0a, 0xc6, 0x5e, 0x3c, 0x96, 0x49, 0x7f, 0xd3, 0x1a, 0x2b, 0xb5, 0xc2, 0x37, 0xb2, 0xd3, 0x50, 0x81, 0x4a, 0x6b, 0x88, 0x8d, 0x5e, 0x1f, 0x1a, 0x35, 0x78, 0x75, 0x4f, 0x99, 0xdf, 0xa6, 0xfc, 0x10, 0x57, 0xc5, 0x5f, 0x32, 0x19, 0x75, 0xab, 0x1f, 0x3f, 0xc1, 0x38, 0xfe, 0x22, 0x40, 0x2d, 0x0e, 0xd2, 0xec, 0x3c, 0x24}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x0e, 0x31, 0xe8, 0x79, 0xa9, 0xb2, 0x33, 0xbe, 0x19, 0x20, 0x92, 0xf6, 0xab, 0xa2, 0x49, 0xd3, 0x6c, 0x5b, 0x45, 0xcf, 0xfd, 0x45, 0x71, 0xe5, 0xf7, 0x3a, 0xea, 0x4e, 0x7a, 0x69, 0x08, 0xee, 0x67, 0x50, 0x90, 0x94, 0x9e, 0xf7, 0x85, 0x88, 0xf5, 0x21, 0x91, 0xe6, 0x55, 0xc6, 0x20, 0x43, 0x90, 0x14, 0xe7, 0x64, 0x1e, 0xbe, 0x80}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x4a, 0x9a, 0x57, 0x90, 0x44, 0x6b, 0xdf, 0xd5, 0x7d, 0xc7, 0x32, 0xa4, 0xee, 0x89, 0x9b, 0x20, 0xfd, 0x1f, 0xbe, 0x00, 0xb0, 0xe9, 0xf7, 0x04, 0x4e, 0x4b, 0x94, 0x50, 0xa9, 0x86, 0xba, 0x61, 0x87, 0xec, 0xaf, 0x4a, 0x06, 0x75, 0x2a, 0xcb, 0x02, 0xa6, 0x02, 0x0e, 0x99, 0x70, 0x91, 0x0c, 0x5c, 0x48, 0x98, 0x68, 0xc3, 0x01, 0x80}}; static Cpa8U edwards_448_kg_u[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x2f, 0x7d, 0x05, 0x80, 0xfd, 0x8e, 0x88, 0xf3, 0xfc, 0x8e, 0xcd, 0x47, 0xf4, 0x34, 0x99, 0xb0, 0x00, 0x0f, 0xaf, 0x1e, 0x84, 0xd0, 0xc2, 0x28, 0x37, 0x36, 0xc9, 0x91, 0xc4, 0xa6, 0x44, 0x47, 0xce, 0x4e, 0x8d, 0x8a, 0x6c, 0x74, 0x01, 0x0b, 0xaf, 0x72, 0x6e, 0xf2, 0x00, 0x06, 0xbc, 0xf1, 0xfa, 0x99, 0x0e, 0x7a, 0x82, 0x22, 0x87}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xff, 0xd9, 0xb5, 0x3d, 0x3b, 0xff, 0x14, 0x1f, 0x68, 0xcf, 0x02, 0x48, 0x02, 0x0a, 0x14, 0xe2, 0xf1, 0xab, 0xa4, 0x33, 0x25, 0x8c, 0x33, 0xc2, 0x90, 0x60, 0x7f, 0x78, 0xea, 0xb2, 0xc6, 0xb9, 0x69, 0xbd, 0xf2, 0x26, 0x77, 0x5b, 0xa7, 0xdb, 0x74, 0xbc, 0xf2, 0x0f, 0xfd, 0xda, 0xb9, 0xd3, 0xad, 0xa6, 0xb2, 0x3a, 0x0e, 0xe8, 0x57}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xce, 0xd0, 0xba, 0x06, 0xc2, 0x93, 0xe6, 0x41, 0x46, 0x7b, 0x5f, 0xbd, 0xfd, 0x5f, 0x4d, 0x53, 0x99, 0x06, 0x79, 0x60, 0xd5, 0x2f, 0x25, 0x9a, 0x58, 0x1d, 0xd6, 0x81, 0x77, 0xb6, 0xb8, 0xe0, 0x7c, 0xdd, 0x04, 0x4e, 0xa2, 0xbe, 0xca, 0x47, 0xbb, 0xf1, 0x94, 0x86, 0x42, 0x70, 0x6a, 0x13, 0x52, 0x0f, 0xca, 0x34, 0x74, 0x14, 0xf4}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x4c, 0x1e, 0x5e, 0x9a, 0x83, 0x47, 0x0f, 0xc7, 0x82, 0xed, 0x6d, 0xff, 0xf9, 0x03, 0x6d, 0x9d, 0x27, 0xad, 0x2e, 0x57, 0xbf, 0x76, 0xb8, 0x78, 0xe9, 0x7e, 0x11, 0xf4, 0x8a, 0x3a, 0xaf, 0x32, 0x32, 0xc3, 0x5b, 0x64, 0x8a, 0xb6, 0x11, 0x01, 0xfe, 0x06, 0x33, 0xd4, 0x41, 0x5f, 0xb1, 0x9e, 0x79, 0x0e, 0xc7, 0x19, 0xe9, 0xae, 0x89}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x7b, 0x86, 0x4b, 0x4c, 0xeb, 0x6e, 0xc3, 0xf3, 0x9a, 0x62, 0x01, 0x5a, 0xe4, 0xdf, 0xba, 0xad, 0x5f, 0x7d, 0x27, 0x45, 0x56, 0xb1, 0x8e, 0x39, 0x2f, 0x04, 0x03, 0x9c, 0x29, 0x5a, 0x28, 0xda, 0x2d, 0xe6, 0x2c, 0xa4, 0x05, 0x71, 0x74, 0x35, 0x31, 0x23, 0x7f, 0xb5, 0xdd, 0x33, 0x84, 0xfe, 0x56, 0x14, 0x1f, 0x26, 0xcb, 0x33, 0xa9}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xda, 0xbb, 0xa6, 0x5b, 0x22, 0x20, 0x7b, 0x5a, 0x3f, 0x12, 0xe4, 0xd1, 0x8b, 0x9a, 0x71, 0x26, 0x90, 0x3e, 0x72, 0x5c, 0xe0, 0xc3, 0xdc, 0x3d, 0x79, 0x63, 0x21, 0x17, 0xc9, 0xfb, 0x06, 0x74, 0xf1, 0xeb, 0xb8, 0x1b, 0x09, 0x97, 0x26, 0x6a, 0x08, 0xb8, 0xbb, 0xb0, 0xa6, 0x24, 0xaa, 0xe9, 0xe1, 0x22, 0x97, 0xfc, 0x59, 0x67, 0xa8}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xc8, 0x23, 0xe1, 0x8a, 0x36, 0x52, 0xca, 0x5c, 0xab, 0xb1, 0x45, 0xda, 0x4e, 0xe3, 0xf7, 0xbe, 0x12, 0x6e, 0x6f, 0x72, 0x10, 0xdb, 0x91, 0x61, 0xe1, 0xd4, 0x5c, 0xb9, 0x65, 0x59, 0x19, 0xa3, 0x38, 0x64, 0xc7, 0xd2, 0x1e, 0x00, 0xf9, 0xb9, 0x45, 0x3a, 0x79, 0xf0, 0x77, 0x6e, 0x8d, 0xec, 0x22, 0x5e, 0x68, 0xa8, 0xf6, 0x50, 0x12}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x41, 0x13, 0xbd, 0xb2, 0x2e, 0x7f, 0xfd, 0xe4, 0xd8, 0x3b, 0x2d, 0xcb, 0xeb, 0x2a, 0x42, 0x0b, 0xc1, 0xba, 0xa4, 0xd2, 0xc0, 0x34, 0xdf, 0x3e, 0x63, 0xac, 0xbd, 0x31, 0xc4, 0xaa, 0x42, 0xf8, 0x69, 0x28, 0x0f, 0xec, 0xd4, 0xb2, 0x34, 0xc8, 0x48, 0xf8, 0x1e, 0x64, 0xac, 0xb8, 0x63, 0x0e, 0x9e, 0x67, 0xfa, 0x01, 0xbe, 0xb8, 0xc2}}; static Cpa8U edwards_448_kg_v[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x25, 0xe8, 0xaf, 0xbe, 0x1a, 0xfa, 0xd1, 0x6c, 0x0f, 0xe5, 0xf1, 0x3d, 0x78, 0xd6, 0x1b, 0x06, 0xc7, 0x46, 0x9b, 0x76, 0x24, 0xf1, 0xed, 0x78, 0x67, 0xe9, 0x80, 0x5d, 0xa7, 0x0e, 0x8a, 0x1f, 0x0e, 0xa7, 0x85, 0x24, 0x34, 0xa1, 0x1d, 0x6a, 0xd4, 0x6a, 0x61, 0xec, 0x87, 0xe7, 0x2c, 0xfd, 0x61, 0xb4, 0x59, 0x9b, 0x44, 0xd7, 0x5f}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x3a, 0x4c, 0x7b, 0x62, 0x60, 0x51, 0x23, 0x9c, 0x16, 0x82, 0xcb, 0xa4, 0x8e, 0x43, 0xb8, 0x02, 0x28, 0x74, 0x00, 0xeb, 0x01, 0xea, 0x6a, 0x86, 0xc0, 0x98, 0x67, 0x6c, 0x0c, 0xfa, 0x2b, 0x37, 0xc0, 0x58, 0x93, 0x5d, 0xa5, 0x34, 0xc8, 0x0a, 0xcd, 0x7e, 0x5f, 0x54, 0x31, 0xe5, 0x6a, 0x45, 0xff, 0xcd, 0x30, 0xf4, 0x28, 0xba, 0x43}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x47, 0x64, 0x69, 0x00, 0x8b, 0x1d, 0x9f, 0x7e, 0x5f, 0xcb, 0xa4, 0x3e, 0x54, 0x1a, 0x13, 0xe7, 0x1c, 0xd7, 0x61, 0xe1, 0xfc, 0x65, 0xe3, 0xb1, 0x28, 0x93, 0x6e, 0xa3, 0x55, 0x9b, 0x10, 0xa0, 0x67, 0x4b, 0xd8, 0x1c, 0xc0, 0xaa, 0x90, 0x6c, 0xb8, 0x10, 0x1b, 0x83, 0x9a, 0x49, 0xf3, 0x1b, 0x5a, 0xf3, 0x78, 0x9e, 0xea, 0xdc}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x17, 0x98, 0xf0, 0x9e, 0x14, 0x5e, 0xd7, 0x6b, 0x72, 0x61, 0x53, 0x94, 0x9b, 0xd1, 0x94, 0x6f, 0x6e, 0xe4, 0xb6, 0x68, 0xe9, 0xd8, 0x24, 0xdc, 0x4a, 0xd4, 0x3f, 0xee, 0x10, 0x95, 0xcc, 0x63, 0x7c, 0x5d, 0x01, 0xfc, 0xc5, 0x6b, 0x8d, 0x79, 0x5e, 0x6f, 0x75, 0x40, 0x77, 0x18, 0x30, 0x1f, 0xcc, 0xf2, 0xc6, 0xa0, 0x6d, 0xa1, 0x3b}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x57, 0xfa, 0x5d, 0xe6, 0x4b, 0x17, 0x7b, 0xc0, 0xc6, 0x13, 0x8e, 0x93, 0xa0, 0x1c, 0x38, 0x9f, 0x4d, 0x6b, 0x17, 0x9e, 0xc5, 0x5d, 0x5c, 0x81, 0xb3, 0x7b, 0x4f, 0x29, 0xda, 0x61, 0x23, 0x53, 0x22, 0x3a, 0x9d, 0x2d, 0x11, 0xa8, 0xe5, 0xbe, 0xae, 0x7b, 0x46, 0xf0, 0x29, 0x20, 0x77, 0xa5, 0x93, 0xa4, 0x0a, 0x9b, 0x07, 0xda, 0xb3}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x08, 0x8a, 0xbd, 0x28, 0xcb, 0x06, 0x09, 0xb5, 0x3f, 0x3b, 0xb0, 0x9b, 0x09, 0x1b, 0x26, 0xbd, 0xdf, 0xa1, 0xf4, 0x8b, 0x80, 0xd6, 0x39, 0x3a, 0xc5, 0x8a, 0x6f, 0xa2, 0x83, 0x34, 0x16, 0xdd, 0xf1, 0xa9, 0x20, 0x2c, 0x13, 0xc6, 0xb1, 0x0a, 0x56, 0xe5, 0xcf, 0x63, 0x83, 0x7f, 0x2c, 0x80, 0xab, 0xdb, 0x8e, 0xf5, 0x05, 0x97, 0xdf}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xed, 0xd4, 0xf3, 0x2e, 0x86, 0x90, 0x76, 0x0e, 0xc8, 0x9e, 0x2e, 0xe2, 0x81, 0x3d, 0x8a, 0x79, 0x65, 0xae, 0x08, 0x2b, 0x40, 0x12, 0xfe, 0x9b, 0x6b, 0x93, 0xa9, 0x43, 0xff, 0x6b, 0x6f, 0x18, 0x25, 0x8f, 0xa0, 0x86, 0x24, 0xef, 0xe2, 0x71, 0x41, 0xbe, 0x18, 0xe7, 0xd9, 0x5d, 0x9f, 0x07, 0xe2, 0xcf, 0x4d, 0x01, 0x6f, 0x75, 0x79}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x8c, 0x83, 0x37, 0x87, 0xc3, 0x1c, 0xf1, 0xcd, 0xf8, 0xae, 0xec, 0x4e, 0xf6, 0x56, 0x0c, 0x5c, 0x68, 0x5d, 0x1c, 0xb8, 0xff, 0x8e, 0xa0, 0x9d, 0x79, 0x0e, 0xec, 0xe1, 0xec, 0x44, 0xad, 0x14, 0xb1, 0x8b, 0x57, 0x58, 0xf2, 0x01, 0x08, 0xeb, 0x3f, 0xfc, 0xad, 0x9b, 0xcc, 0xdb, 0xff, 0x94, 0xac, 0xa5, 0x70, 0x8a, 0x2e, 0x1b, 0xa8}}; /******************** * Edwards 25519 Kg * ********************/ static Cpa8U edwards_25519_kg_x[32] = { 0x21, 0x69, 0x36, 0xd3, 0xcd, 0x6e, 0x53, 0xfe, 0xc0, 0xa4, 0xe2, 0x31, 0xfd, 0xd6, 0xdc, 0x5c, 0x69, 0x2c, 0xc7, 0x60, 0x95, 0x25, 0xa7, 0xb2, 0xc9, 0x56, 0x2d, 0x60, 0x8f, 0x25, 0xd5, 0x1a}; static Cpa8U edwards_25519_kg_y[32] = { 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x58}; static Cpa8U edwards_25519_kg_k[8][32] = { {0x4f, 0xe9, 0x4d, 0x90, 0x06, 0xf0, 0x20, 0xa5, 0xa3, 0xc0, 0x80, 0xd9, 0x68, 0x27, 0xff, 0xfd, 0x3c, 0x01, 0x0a, 0xc0, 0xf1, 0x2e, 0x7a, 0x42, 0xcb, 0x33, 0x28, 0x4f, 0x86, 0x83, 0x7c, 0x30}, {0x51, 0x2e, 0x50, 0x2e, 0xb0, 0x24, 0x9a, 0x25, 0x5e, 0x1c, 0x82, 0x7f, 0x3b, 0x6b, 0x6c, 0x7f, 0x0a, 0x79, 0xf4, 0xca, 0x85, 0x75, 0xa9, 0x15, 0x28, 0xd5, 0x82, 0x58, 0xd7, 0x9e, 0xbd, 0x68}, {0x5c, 0xa9, 0x1e, 0x99, 0x81, 0xa1, 0x25, 0x13, 0x1b, 0xf5, 0xc2, 0xc5, 0x4e, 0x7f, 0x4d, 0xba, 0x11, 0x3d, 0xc2, 0x15, 0x5b, 0xa5, 0x23, 0x90, 0x84, 0x02, 0xd9, 0x5e, 0x75, 0x8b, 0x9a, 0x90}, {0x7c, 0xc3, 0x94, 0xb7, 0x80, 0xe3, 0xcc, 0x85, 0x8a, 0x53, 0xc2, 0xe4, 0x23, 0xa6, 0xdb, 0x1d, 0x78, 0x00, 0xb7, 0x4b, 0x31, 0x8e, 0x55, 0xb2, 0x55, 0x3c, 0x13, 0x9d, 0xb9, 0xf1, 0xc9, 0xb0}, {0x77, 0x76, 0x48, 0xb1, 0x87, 0xed, 0xb5, 0xee, 0xa5, 0x44, 0x67, 0xd6, 0x61, 0x6e, 0xf1, 0x0c, 0x29, 0x79, 0x43, 0xbd, 0x9b, 0x22, 0x5a, 0xf9, 0x48, 0x0a, 0x18, 0x94, 0x64, 0xbc, 0x77, 0xa8}, {0x79, 0xf2, 0x90, 0x14, 0x7a, 0xbb, 0x17, 0x07, 0x38, 0x80, 0x1f, 0x1e, 0x3e, 0x91, 0x8d, 0xbc, 0x01, 0x7a, 0x7e, 0xd1, 0x79, 0x85, 0x66, 0x29, 0x73, 0x27, 0x30, 0x3e, 0x7f, 0xb9, 0x9c, 0x60}, {0x78, 0xe6, 0x71, 0x17, 0xe6, 0xc8, 0x4b, 0x78, 0x35, 0xfc, 0xf4, 0xff, 0x07, 0x15, 0x7f, 0x7a, 0xc2, 0x1c, 0xc0, 0xc7, 0xe5, 0xf2, 0xbe, 0xfd, 0x85, 0x5b, 0x48, 0x76, 0x32, 0x81, 0xec, 0x10}, {0x41, 0xb2, 0x55, 0xea, 0x7a, 0x35, 0x18, 0x8e, 0xb1, 0x72, 0x7f, 0xaa, 0xed, 0x75, 0x6b, 0x04, 0x3e, 0x67, 0xcb, 0x25, 0xe9, 0x14, 0xd4, 0xf8, 0xa4, 0xde, 0x16, 0x08, 0x0d, 0xd9, 0xd7, 0x70}}; static Cpa8U edwards_25519_kg_u[8][32] = { {0x55, 0xd0, 0xe0, 0x9a, 0x2b, 0x9d, 0x34, 0x29, 0x22, 0x97, 0xe0, 0x8d, 0x60, 0xd0, 0xf6, 0x20, 0xc5, 0x13, 0xd4, 0x72, 0x53, 0x18, 0x7c, 0x24, 0xb1, 0x27, 0x86, 0xbd, 0x77, 0x76, 0x45, 0xce}, {0x74, 0xad, 0x28, 0x20, 0x5b, 0x4f, 0x38, 0x4b, 0xc0, 0x81, 0x3e, 0x65, 0x85, 0x86, 0x4e, 0x52, 0x80, 0x85, 0xf9, 0x1f, 0xb6, 0xa5, 0x09, 0x6f, 0x24, 0x4a, 0xe0, 0x1e, 0x57, 0xde, 0x43, 0xae}, {0x61, 0x21, 0x3a, 0xa2, 0xdc, 0x9d, 0x68, 0x83, 0x3f, 0x65, 0xd1, 0xb4, 0x8d, 0xcf, 0x85, 0x98, 0x18, 0x23, 0x6f, 0x17, 0x34, 0xe3, 0xe9, 0xb9, 0x45, 0xa9, 0xff, 0x54, 0x86, 0xcd, 0xbd, 0x02}, {0x4f, 0x30, 0xcc, 0x0d, 0xb3, 0xd9, 0x9a, 0xd8, 0xae, 0x1b, 0x3a, 0x69, 0x69, 0x37, 0xfe, 0xdf, 0x45, 0x8c, 0x2c, 0x72, 0x32, 0xd9, 0x12, 0xfc, 0x5f, 0x0f, 0xd8, 0x7f, 0x64, 0xb8, 0x88, 0x0c}, {0x15, 0xda, 0xf1, 0x5d, 0x98, 0xe9, 0xa7, 0xce, 0xc9, 0xa0, 0xd9, 0x49, 0xaa, 0x8a, 0x10, 0x10, 0x44, 0xc0, 0x71, 0xef, 0x22, 0x4e, 0x23, 0xc3, 0x37, 0x6a, 0x6c, 0xfa, 0xf5, 0x88, 0xf8, 0xb1}, {0x77, 0xac, 0x8b, 0xf2, 0x94, 0xc8, 0x4f, 0xf0, 0x87, 0x20, 0x60, 0x83, 0x8b, 0x2c, 0x72, 0xc2, 0xd4, 0xcb, 0x75, 0x86, 0x4a, 0x07, 0x0f, 0x3f, 0x3e, 0x57, 0xbb, 0x91, 0xd0, 0x85, 0x3a, 0x2c}, {0x28, 0xea, 0x2a, 0xb7, 0xb7, 0x31, 0x69, 0xd1, 0xeb, 0x05, 0x37, 0x70, 0xcc, 0x4c, 0x90, 0xcc, 0xfd, 0x10, 0x09, 0xbe, 0x19, 0x4b, 0xa5, 0x2c, 0x4c, 0x3a, 0xf9, 0x95, 0xf4, 0x1e, 0xa6, 0xde}, {0x3a, 0x9e, 0x95, 0xd1, 0x8a, 0xcb, 0xc3, 0xef, 0x5e, 0x28, 0xec, 0x77, 0xb9, 0x63, 0xc4, 0x00, 0xdc, 0xdb, 0x07, 0xd9, 0x8b, 0x26, 0xa2, 0x9d, 0x3f, 0xb7, 0xf4, 0xe3, 0xa0, 0xa1, 0xf0, 0x40}}; static Cpa8U edwards_25519_kg_v[8][32] = { {0x1a, 0x51, 0x07, 0xf7, 0x68, 0x1a, 0x02, 0xaf, 0x25, 0x23, 0xa6, 0xda, 0xf3, 0x72, 0xe1, 0x0e, 0x3a, 0x07, 0x64, 0xc9, 0xd3, 0xfe, 0x4b, 0xd5, 0xb7, 0x0a, 0xb1, 0x82, 0x01, 0x98, 0x5a, 0xd7}, {0x0c, 0x66, 0xf4, 0x2a, 0xf1, 0x55, 0xcd, 0xc0, 0x8c, 0x96, 0xc4, 0x2e, 0xcf, 0x2c, 0x98, 0x9c, 0xbc, 0x7e, 0x1b, 0x4d, 0xa7, 0x0a, 0xb7, 0x92, 0x5a, 0x89, 0x43, 0xe8, 0xc3, 0x17, 0x40, 0x3d}, {0x25, 0x80, 0x90, 0x48, 0x15, 0x91, 0xeb, 0x5d, 0xac, 0x03, 0x33, 0xba, 0x13, 0xed, 0x16, 0x08, 0x58, 0xf0, 0x30, 0x02, 0xd0, 0x7e, 0xa4, 0x8d, 0xa3, 0xa1, 0x18, 0x62, 0x8e, 0xcd, 0x51, 0xfc}, {0x57, 0x70, 0xa5, 0x1a, 0xdc, 0xf2, 0xf5, 0xbc, 0x40, 0xd4, 0x4d, 0x11, 0x76, 0x5d, 0x24, 0x3b, 0x5d, 0x94, 0xce, 0x63, 0x97, 0xb7, 0x7c, 0x6c, 0x3a, 0x61, 0xf2, 0xce, 0x5b, 0x18, 0x1a, 0xe6}, {0x27, 0x33, 0x02, 0xd9, 0x92, 0x1f, 0x00, 0x8e, 0xeb, 0x2a, 0x15, 0x8b, 0x87, 0xdb, 0xab, 0xea, 0x53, 0x23, 0x47, 0x28, 0x31, 0xc4, 0x5d, 0xe2, 0x86, 0x31, 0x53, 0xc4, 0x02, 0xc1, 0xda, 0xc0}, {0x01, 0x5f, 0xfb, 0x9b, 0x89, 0x7f, 0xbc, 0x0d, 0xf5, 0x5b, 0x30, 0xb8, 0xaa, 0xbb, 0x86, 0x48, 0x53, 0x5b, 0x76, 0xe9, 0x5b, 0x59, 0xb1, 0x9b, 0x86, 0x4b, 0x80, 0x66, 0x07, 0xaf, 0x53, 0xe2}, {0x3d, 0x64, 0xe3, 0x3e, 0xb8, 0x87, 0x50, 0x2b, 0x0b, 0x64, 0xe1, 0x60, 0x52, 0x61, 0x6d, 0xe1, 0x54, 0xcc, 0x85, 0xd1, 0x33, 0x4a, 0x44, 0xbe, 0xf2, 0xd7, 0x05, 0x05, 0xa4, 0xbf, 0xcf, 0xfb}, {0x63, 0x8a, 0x17, 0x90, 0x8b, 0x6d, 0x35, 0xab, 0xbf, 0x02, 0x39, 0x3b, 0x01, 0x74, 0xe7, 0x63, 0xd9, 0x1a, 0xde, 0x93, 0xf0, 0x8b, 0x88, 0x89, 0xba, 0xaa, 0x67, 0x6e, 0xa3, 0xe3, 0xa5, 0x98}}; /****************** * Edwards 448 Kp * ******************/ static Cpa8U edwards_448_kp_x[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x2f, 0x7d, 0x05, 0x80, 0xfd, 0x8e, 0x88, 0xf3, 0xfc, 0x8e, 0xcd, 0x47, 0xf4, 0x34, 0x99, 0xb0, 0x00, 0x0f, 0xaf, 0x1e, 0x84, 0xd0, 0xc2, 0x28, 0x37, 0x36, 0xc9, 0x91, 0xc4, 0xa6, 0x44, 0x47, 0xce, 0x4e, 0x8d, 0x8a, 0x6c, 0x74, 0x01, 0x0b, 0xaf, 0x72, 0x6e, 0xf2, 0x00, 0x06, 0xbc, 0xf1, 0xfa, 0x99, 0x0e, 0x7a, 0x82, 0x22, 0x87}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xff, 0xd9, 0xb5, 0x3d, 0x3b, 0xff, 0x14, 0x1f, 0x68, 0xcf, 0x02, 0x48, 0x02, 0x0a, 0x14, 0xe2, 0xf1, 0xab, 0xa4, 0x33, 0x25, 0x8c, 0x33, 0xc2, 0x90, 0x60, 0x7f, 0x78, 0xea, 0xb2, 0xc6, 0xb9, 0x69, 0xbd, 0xf2, 0x26, 0x77, 0x5b, 0xa7, 0xdb, 0x74, 0xbc, 0xf2, 0x0f, 0xfd, 0xda, 0xb9, 0xd3, 0xad, 0xa6, 0xb2, 0x3a, 0x0e, 0xe8, 0x57}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xce, 0xd0, 0xba, 0x06, 0xc2, 0x93, 0xe6, 0x41, 0x46, 0x7b, 0x5f, 0xbd, 0xfd, 0x5f, 0x4d, 0x53, 0x99, 0x06, 0x79, 0x60, 0xd5, 0x2f, 0x25, 0x9a, 0x58, 0x1d, 0xd6, 0x81, 0x77, 0xb6, 0xb8, 0xe0, 0x7c, 0xdd, 0x04, 0x4e, 0xa2, 0xbe, 0xca, 0x47, 0xbb, 0xf1, 0x94, 0x86, 0x42, 0x70, 0x6a, 0x13, 0x52, 0x0f, 0xca, 0x34, 0x74, 0x14, 0xf4}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x4c, 0x1e, 0x5e, 0x9a, 0x83, 0x47, 0x0f, 0xc7, 0x82, 0xed, 0x6d, 0xff, 0xf9, 0x03, 0x6d, 0x9d, 0x27, 0xad, 0x2e, 0x57, 0xbf, 0x76, 0xb8, 0x78, 0xe9, 0x7e, 0x11, 0xf4, 0x8a, 0x3a, 0xaf, 0x32, 0x32, 0xc3, 0x5b, 0x64, 0x8a, 0xb6, 0x11, 0x01, 0xfe, 0x06, 0x33, 0xd4, 0x41, 0x5f, 0xb1, 0x9e, 0x79, 0x0e, 0xc7, 0x19, 0xe9, 0xae, 0x89}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x7b, 0x86, 0x4b, 0x4c, 0xeb, 0x6e, 0xc3, 0xf3, 0x9a, 0x62, 0x01, 0x5a, 0xe4, 0xdf, 0xba, 0xad, 0x5f, 0x7d, 0x27, 0x45, 0x56, 0xb1, 0x8e, 0x39, 0x2f, 0x04, 0x03, 0x9c, 0x29, 0x5a, 0x28, 0xda, 0x2d, 0xe6, 0x2c, 0xa4, 0x05, 0x71, 0x74, 0x35, 0x31, 0x23, 0x7f, 0xb5, 0xdd, 0x33, 0x84, 0xfe, 0x56, 0x14, 0x1f, 0x26, 0xcb, 0x33, 0xa9}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xda, 0xbb, 0xa6, 0x5b, 0x22, 0x20, 0x7b, 0x5a, 0x3f, 0x12, 0xe4, 0xd1, 0x8b, 0x9a, 0x71, 0x26, 0x90, 0x3e, 0x72, 0x5c, 0xe0, 0xc3, 0xdc, 0x3d, 0x79, 0x63, 0x21, 0x17, 0xc9, 0xfb, 0x06, 0x74, 0xf1, 0xeb, 0xb8, 0x1b, 0x09, 0x97, 0x26, 0x6a, 0x08, 0xb8, 0xbb, 0xb0, 0xa6, 0x24, 0xaa, 0xe9, 0xe1, 0x22, 0x97, 0xfc, 0x59, 0x67, 0xa8}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0xc8, 0x23, 0xe1, 0x8a, 0x36, 0x52, 0xca, 0x5c, 0xab, 0xb1, 0x45, 0xda, 0x4e, 0xe3, 0xf7, 0xbe, 0x12, 0x6e, 0x6f, 0x72, 0x10, 0xdb, 0x91, 0x61, 0xe1, 0xd4, 0x5c, 0xb9, 0x65, 0x59, 0x19, 0xa3, 0x38, 0x64, 0xc7, 0xd2, 0x1e, 0x00, 0xf9, 0xb9, 0x45, 0x3a, 0x79, 0xf0, 0x77, 0x6e, 0x8d, 0xec, 0x22, 0x5e, 0x68, 0xa8, 0xf6, 0x50, 0x12}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x41, 0x13, 0xbd, 0xb2, 0x2e, 0x7f, 0xfd, 0xe4, 0xd8, 0x3b, 0x2d, 0xcb, 0xeb, 0x2a, 0x42, 0x0b, 0xc1, 0xba, 0xa4, 0xd2, 0xc0, 0x34, 0xdf, 0x3e, 0x63, 0xac, 0xbd, 0x31, 0xc4, 0xaa, 0x42, 0xf8, 0x69, 0x28, 0x0f, 0xec, 0xd4, 0xb2, 0x34, 0xc8, 0x48, 0xf8, 0x1e, 0x64, 0xac, 0xb8, 0x63, 0x0e, 0x9e, 0x67, 0xfa, 0x01, 0xbe, 0xb8, 0xc2}}; static Cpa8U edwards_448_kp_y[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x25, 0xe8, 0xaf, 0xbe, 0x1a, 0xfa, 0xd1, 0x6c, 0x0f, 0xe5, 0xf1, 0x3d, 0x78, 0xd6, 0x1b, 0x06, 0xc7, 0x46, 0x9b, 0x76, 0x24, 0xf1, 0xed, 0x78, 0x67, 0xe9, 0x80, 0x5d, 0xa7, 0x0e, 0x8a, 0x1f, 0x0e, 0xa7, 0x85, 0x24, 0x34, 0xa1, 0x1d, 0x6a, 0xd4, 0x6a, 0x61, 0xec, 0x87, 0xe7, 0x2c, 0xfd, 0x61, 0xb4, 0x59, 0x9b, 0x44, 0xd7, 0x5f}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x3a, 0x4c, 0x7b, 0x62, 0x60, 0x51, 0x23, 0x9c, 0x16, 0x82, 0xcb, 0xa4, 0x8e, 0x43, 0xb8, 0x02, 0x28, 0x74, 0x00, 0xeb, 0x01, 0xea, 0x6a, 0x86, 0xc0, 0x98, 0x67, 0x6c, 0x0c, 0xfa, 0x2b, 0x37, 0xc0, 0x58, 0x93, 0x5d, 0xa5, 0x34, 0xc8, 0x0a, 0xcd, 0x7e, 0x5f, 0x54, 0x31, 0xe5, 0x6a, 0x45, 0xff, 0xcd, 0x30, 0xf4, 0x28, 0xba, 0x43}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x47, 0x64, 0x69, 0x00, 0x8b, 0x1d, 0x9f, 0x7e, 0x5f, 0xcb, 0xa4, 0x3e, 0x54, 0x1a, 0x13, 0xe7, 0x1c, 0xd7, 0x61, 0xe1, 0xfc, 0x65, 0xe3, 0xb1, 0x28, 0x93, 0x6e, 0xa3, 0x55, 0x9b, 0x10, 0xa0, 0x67, 0x4b, 0xd8, 0x1c, 0xc0, 0xaa, 0x90, 0x6c, 0xb8, 0x10, 0x1b, 0x83, 0x9a, 0x49, 0xf3, 0x1b, 0x5a, 0xf3, 0x78, 0x9e, 0xea, 0xdc}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x17, 0x98, 0xf0, 0x9e, 0x14, 0x5e, 0xd7, 0x6b, 0x72, 0x61, 0x53, 0x94, 0x9b, 0xd1, 0x94, 0x6f, 0x6e, 0xe4, 0xb6, 0x68, 0xe9, 0xd8, 0x24, 0xdc, 0x4a, 0xd4, 0x3f, 0xee, 0x10, 0x95, 0xcc, 0x63, 0x7c, 0x5d, 0x01, 0xfc, 0xc5, 0x6b, 0x8d, 0x79, 0x5e, 0x6f, 0x75, 0x40, 0x77, 0x18, 0x30, 0x1f, 0xcc, 0xf2, 0xc6, 0xa0, 0x6d, 0xa1, 0x3b}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x57, 0xfa, 0x5d, 0xe6, 0x4b, 0x17, 0x7b, 0xc0, 0xc6, 0x13, 0x8e, 0x93, 0xa0, 0x1c, 0x38, 0x9f, 0x4d, 0x6b, 0x17, 0x9e, 0xc5, 0x5d, 0x5c, 0x81, 0xb3, 0x7b, 0x4f, 0x29, 0xda, 0x61, 0x23, 0x53, 0x22, 0x3a, 0x9d, 0x2d, 0x11, 0xa8, 0xe5, 0xbe, 0xae, 0x7b, 0x46, 0xf0, 0x29, 0x20, 0x77, 0xa5, 0x93, 0xa4, 0x0a, 0x9b, 0x07, 0xda, 0xb3}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x08, 0x8a, 0xbd, 0x28, 0xcb, 0x06, 0x09, 0xb5, 0x3f, 0x3b, 0xb0, 0x9b, 0x09, 0x1b, 0x26, 0xbd, 0xdf, 0xa1, 0xf4, 0x8b, 0x80, 0xd6, 0x39, 0x3a, 0xc5, 0x8a, 0x6f, 0xa2, 0x83, 0x34, 0x16, 0xdd, 0xf1, 0xa9, 0x20, 0x2c, 0x13, 0xc6, 0xb1, 0x0a, 0x56, 0xe5, 0xcf, 0x63, 0x83, 0x7f, 0x2c, 0x80, 0xab, 0xdb, 0x8e, 0xf5, 0x05, 0x97, 0xdf}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xed, 0xd4, 0xf3, 0x2e, 0x86, 0x90, 0x76, 0x0e, 0xc8, 0x9e, 0x2e, 0xe2, 0x81, 0x3d, 0x8a, 0x79, 0x65, 0xae, 0x08, 0x2b, 0x40, 0x12, 0xfe, 0x9b, 0x6b, 0x93, 0xa9, 0x43, 0xff, 0x6b, 0x6f, 0x18, 0x25, 0x8f, 0xa0, 0x86, 0x24, 0xef, 0xe2, 0x71, 0x41, 0xbe, 0x18, 0xe7, 0xd9, 0x5d, 0x9f, 0x07, 0xe2, 0xcf, 0x4d, 0x01, 0x6f, 0x75, 0x79}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x8c, 0x83, 0x37, 0x87, 0xc3, 0x1c, 0xf1, 0xcd, 0xf8, 0xae, 0xec, 0x4e, 0xf6, 0x56, 0x0c, 0x5c, 0x68, 0x5d, 0x1c, 0xb8, 0xff, 0x8e, 0xa0, 0x9d, 0x79, 0x0e, 0xec, 0xe1, 0xec, 0x44, 0xad, 0x14, 0xb1, 0x8b, 0x57, 0x58, 0xf2, 0x01, 0x08, 0xeb, 0x3f, 0xfc, 0xad, 0x9b, 0xcc, 0xdb, 0xff, 0x94, 0xac, 0xa5, 0x70, 0x8a, 0x2e, 0x1b, 0xa8}}; static Cpa8U edwards_448_kp_k[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x79, 0xde, 0x16, 0x3f, 0xfe, 0x49, 0x98, 0x66, 0x1c, 0x2d, 0x46, 0xd9, 0xdf, 0x0f, 0xff, 0xa8, 0x6e, 0x5f, 0xe7, 0x18, 0xef, 0xc5, 0xa6, 0xca, 0x51, 0xe7, 0xe9, 0x58, 0xba, 0x02, 0x87, 0x18, 0x61, 0x23, 0xf9, 0xf0, 0xd3, 0x95, 0x7a, 0x43, 0x5c, 0x13, 0xb3, 0x65, 0xa5, 0xa1, 0x1f, 0x4c, 0x76, 0x3a, 0xc0, 0x71, 0x26, 0xae}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xa7, 0x37, 0xef, 0x5f, 0x95, 0xae, 0xaf, 0xb2, 0xf3, 0x27, 0xb8, 0x45, 0x3e, 0x18, 0xe3, 0xac, 0x96, 0x09, 0x1f, 0x3c, 0x13, 0xdd, 0x13, 0xf0, 0x2e, 0xbd, 0xb0, 0x10, 0x92, 0x91, 0x01, 0x08, 0x49, 0x04, 0xa9, 0x63, 0xe3, 0x8c, 0x32, 0xf7, 0x30, 0x4d, 0x3f, 0x3e, 0x33, 0x7f, 0xb9, 0x58, 0x8b, 0xca, 0x22, 0xc6, 0x17, 0x45, 0xec}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x55, 0xc6, 0x46, 0x35, 0x30, 0x9a, 0xf7, 0x19, 0x6a, 0x40, 0x2c, 0x8b, 0x30, 0x0b, 0x87, 0x8d, 0x41, 0xf5, 0x33, 0xa4, 0x09, 0xb6, 0xf2, 0x7c, 0x61, 0xe4, 0x09, 0xc4, 0x45, 0x3a, 0xf4, 0x0c, 0x60, 0x25, 0xc7, 0x17, 0x0a, 0x02, 0x5d, 0xb1, 0xcd, 0x6f, 0x40, 0x85, 0x6d, 0xb6, 0x92, 0x7a, 0x98, 0xc1, 0x84, 0x95, 0xef, 0x5b, 0xb5}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x09, 0x0a, 0x6a, 0xb7, 0xe7, 0x0b, 0x99, 0x3b, 0xce, 0xb5, 0x61, 0x52, 0x77, 0xf9, 0x75, 0x92, 0x88, 0x19, 0x85, 0xb7, 0x4e, 0xb9, 0x4d, 0x9e, 0x63, 0x21, 0xf6, 0xa5, 0x8e, 0x5b, 0x75, 0x94, 0xe6, 0x8a, 0x54, 0x52, 0xe6, 0xd4, 0xa8, 0x98, 0x75, 0x16, 0x77, 0x8d, 0x2e, 0x3b, 0x55, 0x7c, 0xfc, 0x76, 0x3d, 0x67, 0xaa, 0xe7, 0xc9}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x46, 0x4f, 0x1a, 0x10, 0xa9, 0xa7, 0x59, 0xe7, 0x04, 0x70, 0xd1, 0x54, 0x4d, 0x3e, 0xd7, 0xf6, 0x1c, 0xd0, 0xe8, 0x80, 0x71, 0xc6, 0x92, 0x28, 0xc5, 0x5f, 0xc3, 0xe8, 0xe6, 0x98, 0xab, 0x71, 0x4f, 0xb8, 0xbb, 0xe6, 0x0c, 0x72, 0xee, 0xba, 0x57, 0xee, 0x23, 0x67, 0x1d, 0xc3, 0x7a, 0x10, 0x7d, 0x25, 0x15, 0x27, 0xe9, 0x3b, 0xa6}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x26, 0xaf, 0x77, 0xfb, 0x26, 0xcc, 0x01, 0x77, 0x5d, 0xb9, 0x47, 0x97, 0x5a, 0x5e, 0x5f, 0xe5, 0xf3, 0x4c, 0xbb, 0xd9, 0xd7, 0x5f, 0x4d, 0x30, 0x0c, 0x0f, 0xc9, 0x79, 0xb4, 0x18, 0xf9, 0x4a, 0xb1, 0x86, 0x40, 0x40, 0x59, 0x44, 0x68, 0x6d, 0x92, 0x94, 0x17, 0xf0, 0x75, 0xfa, 0x9c, 0x2c, 0x50, 0xa3, 0x16, 0xba, 0x9f, 0xbe, 0x35}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0e, 0x6b, 0x23, 0x05, 0x08, 0x04, 0xb8, 0x46, 0x10, 0x81, 0x37, 0xf5, 0x8f, 0x59, 0x6c, 0x66, 0x2c, 0x7d, 0x4d, 0x26, 0xc5, 0x93, 0x9a, 0x13, 0x00, 0xab, 0xb5, 0x25, 0x46, 0xc7, 0xde, 0x5c, 0xd4, 0x26, 0x53, 0x49, 0x2b, 0x80, 0x32, 0xd5, 0x25, 0x5d, 0x36, 0x2e, 0x1b, 0xdb, 0xad, 0x3d, 0x9f, 0x15, 0x33, 0x43, 0x8e, 0x8b, 0x2b}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xcf, 0x04, 0x7f, 0x8b, 0xde, 0xe7, 0x6a, 0x68, 0x11, 0x61, 0xb8, 0xde, 0xfa, 0xe4, 0x9c, 0x03, 0x81, 0xad, 0x19, 0x9e, 0xd8, 0xb5, 0x0a, 0x2a, 0x5d, 0xc3, 0x1f, 0x80, 0x90, 0x32, 0x21, 0x70, 0xae, 0x9b, 0xc3, 0x25, 0xf9, 0x39, 0xec, 0xd0, 0x1c, 0x92, 0x94, 0x35, 0x9e, 0xd6, 0x69, 0x3a, 0x42, 0xc7, 0xc6, 0xb8, 0xbc, 0x57, 0xb0}}; static Cpa8U edwards_448_kp_u[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xb1, 0xfe, 0xe3, 0x1d, 0x2a, 0x0e, 0x7c, 0x50, 0x08, 0x48, 0xbf, 0x8f, 0x55, 0x03, 0xc0, 0xe7, 0x5d, 0x62, 0x85, 0xdd, 0x25, 0x83, 0xf2, 0xde, 0x69, 0xba, 0xa5, 0x34, 0x4a, 0x79, 0x38, 0x77, 0x42, 0xab, 0x20, 0x80, 0xf5, 0xe0, 0x48, 0xac, 0xd4, 0x59, 0x95, 0xa0, 0x54, 0x53, 0x61, 0x7f, 0xf4, 0x33, 0x9b, 0xa4, 0xbb, 0x4f, 0x33}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x19, 0x12, 0x3d, 0x62, 0xae, 0xed, 0x39, 0xdd, 0x78, 0x36, 0x95, 0x59, 0x68, 0x58, 0x75, 0xa1, 0x24, 0x77, 0x39, 0xfa, 0x4a, 0xe4, 0x28, 0x40, 0x14, 0x65, 0xfe, 0xab, 0xb0, 0xbc, 0x11, 0x66, 0x65, 0x7f, 0x0d, 0xa9, 0x3d, 0x64, 0xf9, 0xaf, 0x28, 0xe5, 0x6e, 0x78, 0xec, 0x67, 0x4e, 0x62, 0xf6, 0x84, 0x98, 0x0b, 0x37, 0xab, 0x04}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x88, 0xb6, 0x24, 0x68, 0x71, 0x50, 0x66, 0x62, 0x8f, 0xb6, 0xea, 0x52, 0x2b, 0xcb, 0x5f, 0xa6, 0x97, 0x0c, 0x33, 0x59, 0x28, 0x52, 0x72, 0xec, 0xca, 0xff, 0xfd, 0x48, 0xee, 0x6c, 0xe7, 0xb4, 0x6b, 0x69, 0x2c, 0x41, 0x23, 0xb9, 0x34, 0x33, 0xf9, 0x86, 0x36, 0x80, 0x4c, 0x56, 0x3c, 0x1b, 0x83, 0xa6, 0xa9, 0x55, 0x16, 0x76}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0xf6, 0x31, 0xdd, 0x2f, 0x80, 0x29, 0x8d, 0x6e, 0x7b, 0xb0, 0x7d, 0x64, 0x05, 0x80, 0x96, 0x02, 0x5a, 0xa0, 0x68, 0x72, 0x6f, 0xf3, 0xfc, 0x14, 0xe8, 0x47, 0x16, 0xec, 0xa7, 0x61, 0x8e, 0xd5, 0x39, 0xef, 0x28, 0x3d, 0x01, 0x96, 0x62, 0x60, 0xc1, 0x2a, 0x25, 0xef, 0x26, 0x8b, 0x52, 0x9e, 0xd6, 0x48, 0x3d, 0xbb, 0x00, 0x0e, 0x68}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xae, 0xf6, 0xf9, 0x3b, 0x35, 0x07, 0x5e, 0xf8, 0xba, 0x46, 0xd2, 0x6e, 0x93, 0xde, 0x3a, 0xf4, 0x8e, 0x77, 0x29, 0xbd, 0x73, 0x4e, 0x33, 0x66, 0x6f, 0x92, 0xee, 0xaf, 0x0a, 0x1a, 0x58, 0x26, 0xe9, 0x7f, 0xa5, 0x42, 0xec, 0x46, 0x08, 0x5a, 0xf5, 0x32, 0x65, 0xc1, 0x94, 0x4a, 0x0c, 0x44, 0x38, 0xf4, 0x41, 0xd9, 0x39, 0x0e, 0x05}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x3a, 0x32, 0x55, 0x9b, 0x17, 0x0a, 0x5b, 0xf4, 0x04, 0x03, 0x78, 0x27, 0x3f, 0x14, 0x03, 0x68, 0x08, 0x2b, 0xc8, 0x9d, 0xd6, 0xfa, 0x9a, 0x50, 0x33, 0x02, 0xe5, 0x93, 0x60, 0x84, 0xff, 0x8d, 0xd2, 0x0f, 0x7c, 0x56, 0xf9, 0xd3, 0x1f, 0xa5, 0xeb, 0x35, 0x24, 0xe2, 0xef, 0x3b, 0xa0, 0x58, 0x12, 0x02, 0xec, 0x03, 0x6c, 0x93, 0xf5}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x5f, 0x05, 0x57, 0x8d, 0xfd, 0x11, 0xb6, 0x70, 0xef, 0x3f, 0x8a, 0x7f, 0xa6, 0xa8, 0xfa, 0x95, 0x0e, 0x80, 0x95, 0xaf, 0xdf, 0x0c, 0x1a, 0xfe, 0x85, 0x33, 0x87, 0xee, 0x42, 0x96, 0x15, 0xfc, 0xeb, 0x87, 0xbf, 0xee, 0x92, 0x6d, 0x6c, 0x5f, 0xed, 0x6a, 0x1b, 0x04, 0xb4, 0xde, 0x3b, 0x28, 0x3e, 0x8d, 0xb0, 0xd5, 0x2f, 0x07, 0xcc}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x83, 0x13, 0x65, 0x92, 0xe4, 0x1c, 0x0d, 0x0a, 0xd2, 0x4b, 0x5f, 0x2c, 0xd7, 0x26, 0x83, 0xad, 0x31, 0x2b, 0xd2, 0x6b, 0x3e, 0xb7, 0xfb, 0x73, 0x7b, 0xac, 0xcd, 0xce, 0xd1, 0x54, 0x17, 0xc6, 0x3d, 0x0e, 0x90, 0xdb, 0xf0, 0x5f, 0xdd, 0x0b, 0x52, 0x4a, 0x49, 0xa2, 0xb1, 0x46, 0x59, 0x3c, 0xff, 0xe9, 0x79, 0xd4, 0x14, 0xa7, 0x49}}; static Cpa8U edwards_448_kp_v[8][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0xc5, 0x7b, 0x02, 0x90, 0x55, 0x48, 0x1a, 0x04, 0xf5, 0x37, 0x78, 0x22, 0x54, 0xc5, 0xe9, 0x38, 0x10, 0x80, 0xca, 0x28, 0x56, 0xfe, 0x51, 0xfa, 0x91, 0x41, 0x44, 0x26, 0xec, 0x8e, 0xa3, 0xe3, 0xc7, 0x91, 0xf7, 0x75, 0x28, 0x7e, 0xa3, 0xd4, 0x63, 0xa7, 0x7c, 0x54, 0xd9, 0xbe, 0xff, 0x74, 0xb1, 0xf3, 0x96, 0xe6, 0x2e, 0x2d, 0x8b}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x5c, 0xf7, 0x2d, 0xfb, 0x25, 0x0e, 0xcf, 0x6c, 0xfd, 0x15, 0x84, 0x9a, 0x49, 0xec, 0xa3, 0xec, 0x64, 0xb2, 0x17, 0xc4, 0x93, 0xa5, 0x44, 0x6d, 0xf8, 0xbc, 0x43, 0xa5, 0x00, 0xc8, 0x59, 0x81, 0xf2, 0x4f, 0x4e, 0xcb, 0xc1, 0x1b, 0xcb, 0x23, 0x36, 0xe3, 0xa8, 0xdc, 0x15, 0xef, 0xe7, 0x67, 0xab, 0x78, 0xea, 0x5d, 0x1e, 0xe2, 0x53}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xdc, 0xad, 0x56, 0x11, 0xd2, 0x24, 0xf4, 0x5e, 0x68, 0xaa, 0x54, 0x95, 0xdb, 0x37, 0xfe, 0x0b, 0xc9, 0xf3, 0x9d, 0xf3, 0x4e, 0x06, 0xb4, 0x58, 0x6b, 0x95, 0xbf, 0xae, 0x2d, 0x63, 0x80, 0x0c, 0xdf, 0xf2, 0xe0, 0xd3, 0x6f, 0xc4, 0x1c, 0x7a, 0x6c, 0x11, 0x36, 0x94, 0x74, 0x07, 0x17, 0x27, 0x33, 0xcf, 0x53, 0x8a, 0x31, 0x90, 0xab}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0xff, 0xc6, 0xd4, 0x40, 0xde, 0x9f, 0x99, 0xb4, 0x11, 0x20, 0xe7, 0xa3, 0x5a, 0xdc, 0x2e, 0xfb, 0x19, 0xce, 0x23, 0x44, 0x1e, 0x06, 0x4c, 0xf7, 0x65, 0xaa, 0xd4, 0x87, 0x6c, 0x0d, 0x17, 0x61, 0x87, 0xe8, 0x20, 0x60, 0xdb, 0xd5, 0xc6, 0xc8, 0x2b, 0x39, 0x67, 0x6c, 0x91, 0xa4, 0x36, 0x4d, 0x59, 0x6d, 0xeb, 0x65, 0x5f, 0x2a, 0x7e}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xc5, 0x58, 0xb3, 0xad, 0xfb, 0x4e, 0x54, 0xa8, 0x03, 0xc8, 0x82, 0x12, 0xe9, 0xee, 0x10, 0x4f, 0xb3, 0x1e, 0x1e, 0x4b, 0xdb, 0x3a, 0xda, 0x78, 0xad, 0x75, 0xc7, 0x22, 0xbd, 0x1b, 0xbb, 0x15, 0xc6, 0xf3, 0x5b, 0x0a, 0x65, 0x1c, 0xd8, 0x73, 0xc5, 0x18, 0x27, 0xdc, 0x8c, 0x8a, 0xe7, 0x74, 0x57, 0x69, 0x14, 0xd0, 0x5e, 0x27, 0x52}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xb9, 0xf4, 0xe6, 0x98, 0xec, 0x6f, 0xe9, 0xf1, 0x86, 0x1e, 0xe2, 0xea, 0xd9, 0xb3, 0x0d, 0x47, 0x5c, 0x76, 0x3a, 0x1d, 0x74, 0xda, 0xf2, 0x54, 0xcc, 0x0b, 0x85, 0x57, 0x96, 0x19, 0x0e, 0xf2, 0x88, 0x18, 0x3f, 0xcc, 0xad, 0xed, 0x42, 0xef, 0x52, 0x19, 0x9d, 0x39, 0x6d, 0x2e, 0x64, 0x5d, 0x4a, 0x18, 0xda, 0x84, 0xb0, 0x85, 0x04}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x91, 0xb0, 0x81, 0x67, 0x00, 0x3c, 0xa9, 0xa1, 0x0b, 0x6d, 0xf2, 0x0d, 0x63, 0x84, 0x92, 0x86, 0x53, 0x0b, 0xde, 0x07, 0x2b, 0x07, 0xe2, 0x9b, 0x8a, 0x47, 0xd0, 0x26, 0xff, 0xa5, 0x07, 0x77, 0x85, 0x6f, 0x7a, 0x34, 0xbb, 0xb7, 0x82, 0x7c, 0x1a, 0x42, 0x5d, 0x95, 0xb7, 0x86, 0x8f, 0xcf, 0x09, 0x75, 0x0f, 0xc0, 0x73, 0xea, 0x61}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x3c, 0x6b, 0xa0, 0xbb, 0xd7, 0xc9, 0x7a, 0xc4, 0xf2, 0xfa, 0xdd, 0x38, 0x19, 0xb1, 0x41, 0xc1, 0x08, 0x66, 0x1a, 0x40, 0xc1, 0x75, 0x6f, 0xc9, 0x8f, 0xb4, 0xd4, 0x1a, 0x84, 0x69, 0xff, 0x4c, 0x1c, 0x32, 0xaf, 0xb7, 0xeb, 0xdb, 0xcb, 0xdc, 0x0e, 0x1a, 0xc3, 0xd1, 0xda, 0xda, 0x7c, 0x68, 0xce, 0x52, 0x7e, 0x78, 0xcf, 0xf1, 0x21}}; /******************** * Edwards 25519 Kp * ********************/ static Cpa8U edwards_25519_kp_x[7][32] = { {0x55, 0xd0, 0xe0, 0x9a, 0x2b, 0x9d, 0x34, 0x29, 0x22, 0x97, 0xe0, 0x8d, 0x60, 0xd0, 0xf6, 0x20, 0xc5, 0x13, 0xd4, 0x72, 0x53, 0x18, 0x7c, 0x24, 0xb1, 0x27, 0x86, 0xbd, 0x77, 0x76, 0x45, 0xce}, {0x74, 0xad, 0x28, 0x20, 0x5b, 0x4f, 0x38, 0x4b, 0xc0, 0x81, 0x3e, 0x65, 0x85, 0x86, 0x4e, 0x52, 0x80, 0x85, 0xf9, 0x1f, 0xb6, 0xa5, 0x09, 0x6f, 0x24, 0x4a, 0xe0, 0x1e, 0x57, 0xde, 0x43, 0xae}, {0x61, 0x21, 0x3a, 0xa2, 0xdc, 0x9d, 0x68, 0x83, 0x3f, 0x65, 0xd1, 0xb4, 0x8d, 0xcf, 0x85, 0x98, 0x18, 0x23, 0x6f, 0x17, 0x34, 0xe3, 0xe9, 0xb9, 0x45, 0xa9, 0xff, 0x54, 0x86, 0xcd, 0xbd, 0x02}, {0x4f, 0x30, 0xcc, 0x0d, 0xb3, 0xd9, 0x9a, 0xd8, 0xae, 0x1b, 0x3a, 0x69, 0x69, 0x37, 0xfe, 0xdf, 0x45, 0x8c, 0x2c, 0x72, 0x32, 0xd9, 0x12, 0xfc, 0x5f, 0x0f, 0xd8, 0x7f, 0x64, 0xb8, 0x88, 0x0c}, {0x15, 0xda, 0xf1, 0x5d, 0x98, 0xe9, 0xa7, 0xce, 0xc9, 0xa0, 0xd9, 0x49, 0xaa, 0x8a, 0x10, 0x10, 0x44, 0xc0, 0x71, 0xef, 0x22, 0x4e, 0x23, 0xc3, 0x37, 0x6a, 0x6c, 0xfa, 0xf5, 0x88, 0xf8, 0xb1}, {0x77, 0xac, 0x8b, 0xf2, 0x94, 0xc8, 0x4f, 0xf0, 0x87, 0x20, 0x60, 0x83, 0x8b, 0x2c, 0x72, 0xc2, 0xd4, 0xcb, 0x75, 0x86, 0x4a, 0x07, 0x0f, 0x3f, 0x3e, 0x57, 0xbb, 0x91, 0xd0, 0x85, 0x3a, 0x2c}, {0x3a, 0x9e, 0x95, 0xd1, 0x8a, 0xcb, 0xc3, 0xef, 0x5e, 0x28, 0xec, 0x77, 0xb9, 0x63, 0xc4, 0x00, 0xdc, 0xdb, 0x07, 0xd9, 0x8b, 0x26, 0xa2, 0x9d, 0x3f, 0xb7, 0xf4, 0xe3, 0xa0, 0xa1, 0xf0, 0x40}}; static Cpa8U edwards_25519_kp_y[7][32] = { {0x1a, 0x51, 0x07, 0xf7, 0x68, 0x1a, 0x02, 0xaf, 0x25, 0x23, 0xa6, 0xda, 0xf3, 0x72, 0xe1, 0x0e, 0x3a, 0x07, 0x64, 0xc9, 0xd3, 0xfe, 0x4b, 0xd5, 0xb7, 0x0a, 0xb1, 0x82, 0x01, 0x98, 0x5a, 0xd7}, {0x0c, 0x66, 0xf4, 0x2a, 0xf1, 0x55, 0xcd, 0xc0, 0x8c, 0x96, 0xc4, 0x2e, 0xcf, 0x2c, 0x98, 0x9c, 0xbc, 0x7e, 0x1b, 0x4d, 0xa7, 0x0a, 0xb7, 0x92, 0x5a, 0x89, 0x43, 0xe8, 0xc3, 0x17, 0x40, 0x3d}, {0x25, 0x80, 0x90, 0x48, 0x15, 0x91, 0xeb, 0x5d, 0xac, 0x03, 0x33, 0xba, 0x13, 0xed, 0x16, 0x08, 0x58, 0xf0, 0x30, 0x02, 0xd0, 0x7e, 0xa4, 0x8d, 0xa3, 0xa1, 0x18, 0x62, 0x8e, 0xcd, 0x51, 0xfc}, {0x57, 0x70, 0xa5, 0x1a, 0xdc, 0xf2, 0xf5, 0xbc, 0x40, 0xd4, 0x4d, 0x11, 0x76, 0x5d, 0x24, 0x3b, 0x5d, 0x94, 0xce, 0x63, 0x97, 0xb7, 0x7c, 0x6c, 0x3a, 0x61, 0xf2, 0xce, 0x5b, 0x18, 0x1a, 0xe6}, {0x27, 0x33, 0x02, 0xd9, 0x92, 0x1f, 0x00, 0x8e, 0xeb, 0x2a, 0x15, 0x8b, 0x87, 0xdb, 0xab, 0xea, 0x53, 0x23, 0x47, 0x28, 0x31, 0xc4, 0x5d, 0xe2, 0x86, 0x31, 0x53, 0xc4, 0x02, 0xc1, 0xda, 0xc0}, {0x01, 0x5f, 0xfb, 0x9b, 0x89, 0x7f, 0xbc, 0x0d, 0xf5, 0x5b, 0x30, 0xb8, 0xaa, 0xbb, 0x86, 0x48, 0x53, 0x5b, 0x76, 0xe9, 0x5b, 0x59, 0xb1, 0x9b, 0x86, 0x4b, 0x80, 0x66, 0x07, 0xaf, 0x53, 0xe2}, {0x63, 0x8a, 0x17, 0x90, 0x8b, 0x6d, 0x35, 0xab, 0xbf, 0x02, 0x39, 0x3b, 0x01, 0x74, 0xe7, 0x63, 0xd9, 0x1a, 0xde, 0x93, 0xf0, 0x8b, 0x88, 0x89, 0xba, 0xaa, 0x67, 0x6e, 0xa3, 0xe3, 0xa5, 0x98}}; static Cpa8U edwards_25519_kp_k[7][32] = { {0x04, 0x54, 0x52, 0x2e, 0x16, 0x7e, 0x3e, 0x8a, 0x13, 0x2c, 0xec, 0x31, 0x61, 0x25, 0xd8, 0xf8, 0x6c, 0xdf, 0x00, 0xc6, 0xe7, 0x04, 0x05, 0x29, 0x3d, 0x19, 0x96, 0x4c, 0x8e, 0xbc, 0xea, 0x86}, {0x03, 0x5c, 0xe3, 0x07, 0xf6, 0x52, 0x45, 0x10, 0x11, 0x0b, 0x4e, 0xa1, 0xc8, 0xaf, 0x0e, 0x81, 0xfb, 0x70, 0x51, 0x18, 0xeb, 0xcf, 0x88, 0x69, 0x12, 0xf8, 0xd2, 0xd8, 0x7b, 0x57, 0x76, 0xb3}, {0x06, 0x0a, 0xb5, 0x1a, 0x60, 0xe3, 0xf1, 0xce, 0xb6, 0x05, 0x49, 0x47, 0x9b, 0x15, 0x2a, 0xe2, 0xf4, 0xa4, 0x1d, 0x9d, 0xd8, 0xda, 0x0f, 0x6c, 0x3e, 0xf2, 0x89, 0x2d, 0x51, 0x11, 0x8e, 0x95}, {0x08, 0x03, 0xd9, 0x31, 0x3e, 0xa9, 0x31, 0x38, 0x4c, 0x19, 0xb0, 0x14, 0x0e, 0x96, 0x54, 0xe5, 0xe9, 0xa8, 0xc2, 0x4d, 0xa9, 0x9f, 0xf0, 0xb1, 0x2b, 0x78, 0x68, 0x9e, 0xb1, 0xab, 0xa2, 0x65}, {0x03, 0x9d, 0x0a, 0x5c, 0x18, 0xd7, 0xa4, 0x52, 0xfe, 0x09, 0xad, 0x56, 0xe6, 0x78, 0x6e, 0xf0, 0x40, 0xde, 0xce, 0x96, 0xb6, 0xea, 0x3c, 0xd4, 0x98, 0x9b, 0x3e, 0x44, 0x01, 0x4e, 0x66, 0xcc}, {0x00, 0xc5, 0xda, 0x12, 0xaa, 0x3b, 0x14, 0x47, 0x32, 0x3f, 0x3e, 0x07, 0x6d, 0x63, 0xf7, 0x18, 0xa8, 0x26, 0xdb, 0x16, 0x3c, 0xfb, 0xe7, 0x61, 0x53, 0x65, 0xb9, 0x93, 0x90, 0x13, 0xf7, 0xab}, {0x00, 0x98, 0xdb, 0x9d, 0x1c, 0x24, 0x2d, 0xec, 0x82, 0x48, 0x46, 0xc7, 0x8a, 0x94, 0x83, 0x61, 0x26, 0x15, 0xc9, 0x2f, 0x67, 0x4e, 0x6f, 0x2c, 0xf3, 0x15, 0x16, 0x4b, 0x32, 0xca, 0xbb, 0xb1}}; static Cpa8U edwards_25519_kp_u[7][32] = { {0x7f, 0xa3, 0xaa, 0xef, 0x0a, 0x60, 0x4a, 0x9a, 0x4c, 0x2a, 0x9b, 0x83, 0xfa, 0xe0, 0x2f, 0xb0, 0x6a, 0x02, 0xa1, 0x9c, 0x94, 0x3e, 0x3a, 0xf8, 0x94, 0xce, 0x58, 0x56, 0xc8, 0x93, 0x6f, 0x22}, {0x0d, 0x96, 0x8d, 0xd4, 0x6d, 0xe0, 0xff, 0x98, 0xf4, 0xa6, 0x91, 0x6e, 0x60, 0xf8, 0x4c, 0x80, 0x68, 0x44, 0x4d, 0xbc, 0x2d, 0x93, 0xf5, 0xd3, 0xb9, 0xcf, 0x06, 0xda, 0xde, 0x04, 0xa9, 0x94}, {0x56, 0xdd, 0xbc, 0x2f, 0x15, 0x1c, 0xa7, 0x46, 0x19, 0xe8, 0x47, 0x26, 0xf5, 0x22, 0xc6, 0x7c, 0x47, 0x42, 0x4b, 0x89, 0xdb, 0x11, 0x10, 0xaa, 0xf4, 0xb1, 0xf9, 0xdf, 0xbd, 0x78, 0xd2, 0xbc}, {0x7b, 0x9e, 0xaa, 0xf6, 0x4c, 0x3f, 0x5c, 0x59, 0x89, 0x43, 0x3a, 0x7d, 0xcb, 0x78, 0xed, 0xca, 0xb3, 0xf2, 0x28, 0xd6, 0x3d, 0x49, 0x93, 0x85, 0x6b, 0x8e, 0x03, 0x97, 0x19, 0xd8, 0x35, 0x77}, {0x30, 0x60, 0xc6, 0xac, 0x57, 0xa8, 0x4c, 0xa8, 0x52, 0x46, 0xd5, 0x78, 0x44, 0xfe, 0xe7, 0x30, 0x8f, 0xdb, 0x6f, 0xc1, 0x52, 0x15, 0xeb, 0xe7, 0x52, 0xfb, 0xe1, 0x73, 0xa6, 0xde, 0x01, 0xf3}, {0x45, 0xdb, 0x2d, 0x41, 0x3f, 0x62, 0x2d, 0x40, 0x40, 0x08, 0x3e, 0xe1, 0xc7, 0xec, 0xd0, 0x04, 0xd7, 0x9f, 0x47, 0x40, 0x69, 0x1d, 0x45, 0xd2, 0x95, 0x74, 0x17, 0xd7, 0x16, 0x5c, 0xaa, 0xef}, {0x7b, 0xc3, 0x1f, 0x42, 0x61, 0x77, 0x64, 0xa7, 0x23, 0xef, 0x5f, 0x65, 0x25, 0x78, 0x39, 0xda, 0x1f, 0xe7, 0x07, 0xec, 0x6d, 0xb0, 0xed, 0x32, 0xbf, 0xd2, 0x13, 0xf2, 0x93, 0xaf, 0x8b, 0x00}}; static Cpa8U edwards_25519_kp_v[7][32] = { {0x0d, 0xce, 0xde, 0x2a, 0x33, 0xba, 0xb5, 0xc4, 0x4f, 0x1e, 0xe9, 0x65, 0x99, 0x5e, 0x21, 0xdf, 0x5c, 0xfc, 0x67, 0x84, 0x2f, 0x1b, 0x90, 0xe2, 0xc6, 0x9f, 0x9e, 0xa6, 0x59, 0x0a, 0x89, 0x9d}, {0x3b, 0xa1, 0x6a, 0x01, 0x5e, 0x1d, 0xd4, 0x2b, 0x3d, 0x08, 0x8c, 0x7a, 0x68, 0xc3, 0x44, 0xec, 0x47, 0xaa, 0xba, 0x46, 0x3f, 0x67, 0xf4, 0xe9, 0x09, 0x9c, 0x63, 0x4f, 0x64, 0x78, 0x1e, 0x00}, {0x43, 0x82, 0x9f, 0xf4, 0x28, 0x01, 0x33, 0xff, 0x74, 0xd7, 0xd6, 0xcd, 0xa0, 0xef, 0x9a, 0x64, 0x58, 0x28, 0xee, 0xa3, 0x5f, 0xd9, 0x83, 0x5b, 0xff, 0x8b, 0xba, 0xa0, 0x40, 0xc8, 0xe9, 0x65}, {0x04, 0x31, 0xfa, 0xe6, 0x90, 0x32, 0xa8, 0x14, 0xed, 0xc9, 0x50, 0x9f, 0x96, 0xdb, 0xd4, 0xa9, 0x3a, 0x72, 0x08, 0xfb, 0xab, 0x47, 0xc0, 0x5a, 0x9e, 0x79, 0x26, 0x25, 0xbd, 0xe2, 0x60, 0x90}, {0x69, 0x3b, 0xd6, 0x36, 0x1a, 0xad, 0x3a, 0x2d, 0x65, 0x81, 0x9f, 0xbf, 0xf5, 0xac, 0x7e, 0x09, 0x6c, 0x0c, 0xf4, 0xeb, 0x96, 0xb9, 0x26, 0xb5, 0x3c, 0x68, 0xdd, 0xa0, 0xba, 0xb8, 0x5b, 0xc3}, {0x4c, 0xd0, 0x42, 0x86, 0xf7, 0x94, 0x77, 0x7d, 0x66, 0xa1, 0x75, 0x46, 0x5d, 0xcd, 0xb6, 0x72, 0x3c, 0x33, 0xdb, 0xcd, 0xab, 0xf1, 0x64, 0xba, 0x92, 0x10, 0x9d, 0x00, 0x56, 0xe6, 0x3a, 0xa4}, {0x43, 0xd2, 0x04, 0xba, 0xaf, 0x6e, 0x50, 0x5f, 0xe2, 0xdb, 0xfa, 0xd3, 0xf9, 0x5b, 0xb5, 0x39, 0x88, 0x53, 0x99, 0x51, 0xbd, 0xd1, 0x1b, 0x22, 0x4a, 0x08, 0x91, 0x11, 0x2b, 0x7d, 0x8b, 0x94}}; /********************* * Montgomery 448 Kg * *********************/ static Cpa8U montgomery_448_kg_k[9][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x90, 0x92, 0x36, 0xd3, 0xaf, 0x35, 0x96, 0x00, 0xd5, 0x41, 0xe6, 0x05, 0xd8, 0xb7, 0x98, 0x03, 0x35, 0xd1, 0x1a, 0xb4, 0xdc, 0xeb, 0xce, 0x27, 0x30, 0x5d, 0xef, 0x75, 0x01, 0xda, 0x8c, 0xed, 0x72, 0xca, 0xfc, 0xa3, 0x20, 0x59, 0x98, 0x41, 0xde, 0x0c, 0x70, 0x73, 0x9f, 0xd8, 0xad, 0x72, 0xa3, 0xe7, 0x4a, 0x48, 0xb8, 0x09, 0xf2}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xa5, 0x95, 0xcc, 0x30, 0x9e, 0x74, 0x6b, 0xdb, 0xf2, 0x19, 0x34, 0xfa, 0x61, 0xd0, 0x4e, 0x31, 0x51, 0xa5, 0x2a, 0xf0, 0x43, 0xa5, 0xf6, 0xdb, 0xe6, 0x28, 0x04, 0xf5, 0x4d, 0x05, 0x6c, 0xe1, 0x04, 0x29, 0x34, 0xc0, 0xdb, 0xf5, 0x77, 0xbf, 0x89, 0x4a, 0x6c, 0xf2, 0x9e, 0xfa, 0xa8, 0x8c, 0x9f, 0xdd, 0x17, 0x64, 0xf3, 0xc8, 0x75}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xce, 0xe4, 0xdc, 0x79, 0x74, 0x97, 0xf8, 0x58, 0xe5, 0xe1, 0xfd, 0x19, 0x61, 0x0b, 0x93, 0x92, 0x98, 0x9d, 0xe9, 0x09, 0x4c, 0xd8, 0x93, 0x5a, 0xab, 0xce, 0xdb, 0x16, 0xe7, 0x0e, 0x6d, 0xec, 0x3a, 0x1f, 0xa2, 0x84, 0x7b, 0xe2, 0x04, 0x51, 0xfe, 0x60, 0x40, 0xd2, 0xe9, 0x97, 0x18, 0xa6, 0x30, 0x27, 0xe9, 0xe8, 0x22, 0xb0, 0xb4}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x85, 0xfd, 0x2f, 0x9c, 0xa9, 0x9a, 0xe1, 0xbe, 0xc0, 0xeb, 0x1d, 0x01, 0x48, 0x11, 0x68, 0x87, 0xa4, 0xcf, 0xa5, 0x50, 0xa7, 0x60, 0x08, 0x80, 0xaf, 0x63, 0x8e, 0x3b, 0x5d, 0x6c, 0xf1, 0x58, 0xc8, 0x21, 0x0c, 0x88, 0xfd, 0x1e, 0x3f, 0x16, 0xa1, 0x81, 0xd2, 0xac, 0x35, 0xd3, 0xd7, 0xe4, 0xfa, 0x79, 0x1b, 0x65, 0x39, 0x35, 0xc8}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x41, 0x8d, 0x9e, 0x49, 0xd2, 0x35, 0x10, 0xc1, 0x53, 0x01, 0x70, 0x9a, 0x86, 0x93, 0x2f, 0xfb, 0xf8, 0xa5, 0xee, 0x13, 0x6e, 0x06, 0x87, 0x5f, 0x1b, 0xea, 0x57, 0x59, 0x23, 0x73, 0x99, 0x35, 0x8e, 0x1e, 0xdc, 0x16, 0x02, 0x0b, 0x54, 0xeb, 0x7d, 0xf6, 0x84, 0xe5, 0x5c, 0x4d, 0x8f, 0x76, 0xf1, 0xf5, 0x7b, 0xcb, 0x0d, 0x78, 0x8e}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x73, 0x3b, 0xbf, 0x9d, 0xdd, 0x12, 0x40, 0x99, 0x7f, 0xab, 0x0f, 0xb1, 0x74, 0x94, 0xf5, 0x13, 0x8a, 0x22, 0xa6, 0xd4, 0xef, 0xb6, 0x27, 0xde, 0x27, 0x70, 0xc6, 0x3c, 0xc0, 0xe2, 0xc5, 0x4e, 0xff, 0x31, 0xcb, 0x49, 0x7d, 0x17, 0x69, 0xa0, 0xa3, 0x4a, 0xf4, 0xae, 0x9f, 0x54, 0x49, 0x87, 0x6a, 0xb0, 0x57, 0x00, 0xad, 0x74, 0x26}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xef, 0xa7, 0x50, 0xf2, 0x10, 0x33, 0x04, 0xfa, 0xc2, 0xc9, 0x3d, 0x7a, 0x9d, 0xc7, 0x75, 0xfb, 0xe6, 0xa0, 0x50, 0x0c, 0xbd, 0x55, 0x6e, 0x14, 0xcb, 0xed, 0xcf, 0x98, 0xa9, 0xf3, 0xf1, 0x37, 0x8b, 0x7a, 0x2f, 0xe3, 0x52, 0x94, 0xa8, 0xb2, 0x1e, 0xfd, 0xe4, 0x3f, 0x1a, 0x69, 0xfa, 0xb7, 0xbf, 0x81, 0x81, 0x92, 0x84, 0x66, 0xcc}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xca, 0x23, 0xe9, 0xc4, 0x4e, 0xdb, 0x49, 0xae, 0xd6, 0x36, 0x90, 0x21, 0x6c, 0xc2, 0x72, 0x8d, 0xc5, 0x8f, 0x55, 0x23, 0x78, 0xc2, 0x92, 0xab, 0x58, 0x44, 0xf3}}; static Cpa8U montgomery_448_kg_u[9][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5d, 0x6d, 0xdd, 0xdf, 0xe4, 0x40, 0xcc, 0x63, 0xd8, 0xc7, 0x35, 0xc6, 0x8f, 0x70, 0xdd, 0xba, 0x89, 0xc2, 0x88, 0xfd, 0x03, 0xeb, 0x48, 0x7c, 0xc3, 0x8c, 0x85, 0x46, 0xde, 0x9a, 0x9a, 0xc6, 0xa1, 0xa7, 0x78, 0x09, 0xb5, 0x39, 0xe2, 0x9e, 0xb0, 0x62, 0x4b, 0x21, 0xe7, 0xbe, 0x69, 0xc5, 0x3b, 0xba, 0x4d, 0xa4, 0x20, 0xb8, 0xe9}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x61, 0xb9, 0x75, 0x6f, 0xa4, 0x84, 0x07, 0x52, 0x25, 0x6f, 0xee, 0xa1, 0xcd, 0xdc, 0x40, 0xc0, 0x09, 0xe5, 0xfc, 0x3f, 0xad, 0x0d, 0x45, 0xfe, 0x44, 0xdd, 0x26, 0x4e, 0xd0, 0x8d, 0xe7, 0xdb, 0x4a, 0xdb, 0x66, 0xef, 0x65, 0x78, 0x82, 0xa6, 0xd3, 0xcd, 0x74, 0xb7, 0x29, 0xc0, 0x4c, 0x66, 0x9d, 0xdf, 0x77, 0x57, 0x0b, 0xec, 0x6e}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xd7, 0x90, 0xaa, 0x4e, 0x47, 0x75, 0x28, 0xa7, 0x8d, 0xe5, 0x23, 0x8b, 0xaa, 0xe9, 0xd4, 0xcb, 0x51, 0x9f, 0x9d, 0x14, 0x34, 0x76, 0x2f, 0xa2, 0x4b, 0xb1, 0x7f, 0xa3, 0x37, 0x78, 0x74, 0x0b, 0x6d, 0x8f, 0xd9, 0xdb, 0xcc, 0x58, 0x45, 0x9a, 0xfe, 0x40, 0xf0, 0x15, 0x2f, 0x39, 0x6a, 0xde, 0xae, 0x63, 0x6c, 0x35, 0x2f, 0x14, 0xca}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x8e, 0x9b, 0x0e, 0xb3, 0xac, 0xa0, 0xc8, 0xdd, 0x17, 0xa7, 0x34, 0xe6, 0xad, 0x6a, 0x8c, 0xdb, 0xd5, 0x18, 0xbe, 0x3d, 0x30, 0x7c, 0xaf, 0x83, 0xda, 0x76, 0x9a, 0xe1, 0x6b, 0x46, 0x51, 0xfa, 0x40, 0xdd, 0x08, 0xe6, 0x74, 0x99, 0xfb, 0x0b, 0x4a, 0x02, 0x33, 0x9e, 0x51, 0x1e, 0xc1, 0x28, 0x67, 0xe2, 0x16, 0xe2, 0x06, 0xe6, 0xfc}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf7, 0xbb, 0x41, 0x22, 0x6a, 0xc3, 0x6b, 0x4f, 0xda, 0x8f, 0xb8, 0x59, 0x6b, 0x04, 0xef, 0x06, 0x50, 0xa7, 0x7f, 0xf7, 0xf5, 0xad, 0xd5, 0xd0, 0x73, 0x54, 0xd2, 0xd2, 0x09, 0xa8, 0x38, 0x30, 0xb8, 0x31, 0x4f, 0xb4, 0x67, 0x7d, 0xcc, 0xb2, 0x61, 0xfa, 0x5b, 0xbf, 0xc8, 0x65, 0xf4, 0xb4, 0x8f, 0x85, 0x4a, 0x87, 0x9b, 0x21, 0xaf}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x04, 0x1c, 0x2c, 0xdd, 0xd0, 0xef, 0xd7, 0x85, 0x1a, 0x69, 0x2e, 0xd2, 0xb0, 0x8d, 0x1f, 0xab, 0x89, 0x79, 0x69, 0x21, 0xee, 0x2d, 0xb1, 0x15, 0xeb, 0xa7, 0x8b, 0x63, 0xb4, 0x00, 0xa1, 0xc1, 0x28, 0xe3, 0xa9, 0x59, 0x2b, 0x3e, 0xc6, 0xc0, 0x1c, 0x04, 0xee, 0x2c, 0xe7, 0x62, 0x4f, 0x5a, 0xf1, 0xe5, 0x6e, 0x7d, 0xba, 0x16, 0x3f}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xde, 0x8b, 0xc6, 0x4c, 0xd8, 0xaa, 0x53, 0xd8, 0x94, 0xd2, 0xd6, 0x23, 0x70, 0xe4, 0xb0, 0x0a, 0x2b, 0x61, 0xb0, 0x94, 0xc4, 0x3b, 0xc1, 0xec, 0x43, 0xd4, 0x92, 0x95, 0x97, 0xed, 0x82, 0x63, 0x45, 0xf7, 0x2c, 0x68, 0x1d, 0x20, 0x23, 0x52, 0x41, 0x34, 0x11, 0x89, 0xc1, 0xf9, 0xe2, 0x60, 0x3a, 0xa9, 0xcc, 0x60, 0xd3, 0x23, 0x90}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x34, 0xbf, 0xa7, 0x1a, 0xd1, 0xba, 0xc2, 0x91, 0x94, 0x94, 0x33, 0xee, 0x6e, 0x7e, 0xb2, 0xd8, 0x71, 0x9b, 0xcf, 0xb3, 0x5c, 0xa6, 0x2c, 0x05, 0x16, 0xd1, 0x82, 0x3f, 0x85, 0xb0, 0x2a, 0x71, 0x99, 0x3d, 0x58, 0x63, 0xb6, 0x79, 0xe0, 0xb5, 0x73, 0xa8, 0x42, 0x95, 0x81, 0x7b, 0x9c, 0xbd, 0xbe, 0xc8, 0x7f, 0xa1, 0xfd, 0x5b, 0x08}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x34, 0x86, 0x79, 0x0f, 0x19, 0xe6, 0x93, 0x12, 0x81, 0xd5, 0x25, 0x86, 0x6d, 0xe5, 0x4f, 0x3e, 0x80, 0xcb, 0x96, 0xe6, 0x1f, 0x4f, 0x1f, 0x48, 0xa3, 0xc2, 0x54, 0xd8, 0x28, 0xa4, 0x0f, 0xc8, 0xbd, 0xa5, 0x08, 0xf9, 0x79, 0x40, 0x04, 0x56, 0xbb, 0x6d, 0xfa, 0xbc, 0x06, 0x22, 0x16, 0xc2, 0x1b, 0x79, 0x3a, 0x4a, 0x99, 0x8d, 0xa1}}; /*********************** * Montgomery 25519 Kg * ***********************/ static Cpa8U montgomery_25519_kg_k[9][32] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x97, 0x1a, 0xa0, 0x18, 0xaf, 0x39, 0x44, 0xe9, 0x32, 0x62, 0x4c, 0x47, 0xef, 0x47, 0xb3, 0x46, 0x16, 0xd6, 0xee, 0xbb, 0x42, 0x73, 0x83, 0xa6, 0x8f, 0xb4, 0xbd, 0x2f, 0xd7, 0x5f, 0x25, 0x03}, {0x38, 0xab, 0xf0, 0x73, 0xea, 0x9a, 0xc5, 0x45, 0x95, 0x93, 0x60, 0x56, 0x99, 0x64, 0x8c, 0x5f, 0x27, 0x01, 0x21, 0xb4, 0xfb, 0xbd, 0x77, 0xd0, 0xe6, 0xfb, 0xe2, 0xb2, 0x94, 0x75, 0x16, 0xee}, {0xfb, 0x3e, 0x6b, 0x4d, 0x41, 0x03, 0x2b, 0xd8, 0xdf, 0xed, 0x32, 0xb5, 0xc5, 0xb3, 0x5f, 0xea, 0xd4, 0xe2, 0x27, 0x8d, 0x39, 0x58, 0xcf, 0x6f, 0x20, 0xfb, 0x69, 0x6e, 0xfb, 0x75, 0x0d, 0xa1}, {0xa2, 0xbe, 0xd7, 0x4e, 0xfd, 0x78, 0x1f, 0x87, 0xee, 0xe0, 0xa1, 0x19, 0x2c, 0xa2, 0xde, 0xa9, 0x23, 0xe5, 0x5a, 0xcb, 0xcf, 0xb3, 0xbe, 0x15, 0x49, 0x85, 0x85, 0xbf, 0x8a, 0x19, 0x04, 0x15}, {0xb3, 0x48, 0xee, 0xe7, 0x10, 0x98, 0x0b, 0x0d, 0xbb, 0x9c, 0xe9, 0x30, 0x9b, 0x3c, 0x44, 0xb2, 0x4f, 0x28, 0x9a, 0x7d, 0xc4, 0xa4, 0xbd, 0xea, 0xed, 0xea, 0x09, 0x3d, 0x30, 0x8a, 0x49, 0x80}, {0xa3, 0x65, 0xbd, 0xf7, 0xb8, 0xc0, 0xa8, 0x11, 0xdc, 0x48, 0x02, 0x24, 0x8b, 0xc9, 0x5b, 0xab, 0x77, 0x23, 0x9f, 0xa9, 0x38, 0x77, 0xe9, 0xdc, 0xb1, 0x36, 0xad, 0xb5, 0x9f, 0x33, 0x78, 0x76}, {0x23, 0x92, 0x44, 0xab, 0x13, 0x58, 0xb8, 0x23, 0xad, 0x93, 0xec, 0x93, 0xf6, 0x7a, 0x28, 0xd9, 0xb8, 0x09, 0x21, 0xd5, 0xd5, 0xb4, 0x30, 0x9d, 0xbc, 0x59, 0x48, 0xe1, 0xe6, 0xfe, 0x87, 0x94}, {0xe9, 0xd7, 0x8f, 0xd4, 0x15, 0xd5, 0xdd, 0xf2, 0x57, 0x50, 0x74, 0x19, 0x9c, 0x79, 0xcf, 0xc8, 0xb8, 0x56, 0x10, 0x8b, 0xcf, 0x27, 0xbe, 0xd1, 0xd6, 0x60, 0x8a, 0x36, 0x6d, 0xc4, 0x63, 0x34}}; static Cpa8U montgomery_25519_kg_u[9][32] = { {0x74, 0x3b, 0xcb, 0x58, 0x5f, 0x99, 0x90, 0xed, 0xc2, 0xcf, 0xc4, 0xaf, 0x84, 0xf6, 0xff, 0x30, 0x07, 0x29, 0xbb, 0x5f, 0xac, 0xda, 0x28, 0x15, 0x43, 0x62, 0xcd, 0x47, 0xa3, 0x7d, 0xe5, 0x2f}, {0x25, 0x87, 0x67, 0x85, 0x42, 0x0b, 0x87, 0x42, 0x1c, 0xe3, 0x37, 0x80, 0xbc, 0x9a, 0x6f, 0xfa, 0xf5, 0xef, 0x38, 0xbb, 0xea, 0x02, 0x58, 0x43, 0xa6, 0x64, 0xb9, 0x10, 0x81, 0x38, 0xcb, 0x04}, {0x37, 0x2e, 0xfb, 0xd7, 0x27, 0x8a, 0xb5, 0xca, 0x0a, 0x43, 0x4c, 0x5d, 0x82, 0x20, 0x4d, 0x9b, 0x71, 0x60, 0x35, 0xe4, 0xd0, 0xea, 0x8d, 0x30, 0xea, 0x18, 0x59, 0xc2, 0x08, 0x23, 0x8f, 0x34}, {0x03, 0x2b, 0xca, 0xa1, 0x53, 0xd3, 0x55, 0x02, 0x16, 0x54, 0xa9, 0xe7, 0xc1, 0x79, 0x33, 0x65, 0xde, 0x0e, 0xf9, 0x5d, 0x51, 0x2d, 0x6c, 0x44, 0x35, 0xbb, 0x39, 0xc9, 0x2e, 0xdb, 0xb8, 0x1a}, {0x18, 0xf6, 0x26, 0x0c, 0x18, 0x89, 0x9e, 0x57, 0x5f, 0xb9, 0x25, 0x35, 0xd0, 0x96, 0xd2, 0x3b, 0x87, 0x4f, 0x2e, 0x3e, 0xbb, 0xc5, 0x3c, 0x61, 0x48, 0x92, 0xe3, 0xa3, 0x10, 0x7f, 0xf1, 0x6d}, {0x7e, 0x26, 0xe4, 0xe8, 0x22, 0x47, 0xc0, 0xad, 0x79, 0x59, 0xf7, 0xf3, 0x93, 0x57, 0xd8, 0x54, 0xce, 0x50, 0xfa, 0x88, 0xab, 0xda, 0xd3, 0xc4, 0x78, 0x9b, 0xdd, 0x75, 0xca, 0xd9, 0x3a, 0x74}, {0x25, 0x09, 0xa1, 0x5a, 0x65, 0x1f, 0xd2, 0x4f, 0x01, 0xc1, 0xbf, 0x4b, 0xf5, 0xda, 0x59, 0xe1, 0x51, 0xeb, 0xb3, 0x77, 0x1e, 0x98, 0x7a, 0xbb, 0xa6, 0x11, 0x1d, 0x0c, 0xe0, 0xc5, 0x80, 0x17}, {0x20, 0x0c, 0x77, 0xda, 0x28, 0xe9, 0xc7, 0xc6, 0x4a, 0x24, 0x31, 0x4b, 0xa5, 0x4b, 0xff, 0x10, 0x5b, 0x74, 0x49, 0x94, 0x2a, 0x7e, 0x5d, 0xd8, 0x99, 0xaf, 0xe0, 0x24, 0x1e, 0x07, 0x72, 0x2b}, {0x2f, 0x18, 0x45, 0x26, 0x45, 0x3c, 0xfd, 0xcb, 0x1f, 0x16, 0xbf, 0x58, 0x29, 0x9b, 0xac, 0x8a, 0x2b, 0x84, 0xce, 0x7a, 0xeb, 0x9c, 0x4b, 0x61, 0xf7, 0x94, 0x43, 0xf6, 0xe8, 0xb8, 0x90, 0x21}}; /********************* * Montgomery 448 Kp * *********************/ static Cpa8U montgomery_448_kp_x[10][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xA0, 0xF8, 0x4E, 0xFB, 0xA7, 0xA7, 0x8A, 0xA1, 0xAD, 0x94, 0xDB, 0x29, 0x54, 0xFA, 0x83, 0x25, 0xDA, 0xC6, 0x19, 0x8C, 0xC3, 0xBD, 0xDD, 0x31, 0xC0, 0x4D, 0x81, 0xF9, 0x08, 0x0F, 0x02, 0x7F, 0x43, 0x07, 0xBD, 0x4C, 0x33, 0x88, 0xAD, 0x8A, 0x3F, 0x26, 0xD5, 0xF2, 0x6C, 0x5F, 0xDA, 0xBF, 0x87, 0x34, 0xFA, 0x40, 0xE6, 0xFC, 0x06}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDB, 0x57, 0xD1, 0xE8, 0x1C, 0xE7, 0xBD, 0xDF, 0x1C, 0xB9, 0x78, 0x8A, 0xE2, 0x05, 0xE2, 0x2F, 0xE5, 0xBE, 0x70, 0x35, 0x4D, 0x6C, 0xE5, 0x94, 0x58, 0x01, 0x5D, 0x16, 0x1B, 0x20, 0xB6, 0xE9, 0xA1, 0xE9, 0xF8, 0x52, 0xBB, 0x5D, 0xFB, 0xA8, 0xC1, 0xD4, 0x55, 0x9E, 0x7D, 0x0B, 0x5B, 0x30, 0xD3, 0x56, 0xCD, 0x93, 0xF9, 0xC2, 0xBC, 0x0F}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x32, 0x37, 0x76, 0xab, 0x6d, 0x78, 0x01, 0x51, 0x3a, 0xb2, 0xa4, 0x6e, 0x4f, 0x5a, 0xe7, 0x80, 0x78, 0x9f, 0x78, 0x4d, 0x7b, 0x29, 0x90, 0x25, 0x40, 0x61, 0x4c, 0x32, 0x91, 0x07, 0xbf, 0x2d, 0x3a, 0xea, 0x86, 0x6b, 0x30, 0x84, 0x99, 0x22, 0xff, 0x3f, 0x39, 0x3f, 0xab, 0x17, 0x1b, 0x5c, 0x8f, 0x96, 0xa1, 0x72, 0x0f, 0x69, 0x10}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x94, 0x4e, 0x0c, 0x8c, 0x3f, 0xf8, 0x20, 0x4c, 0xdd, 0x97, 0x02, 0x98, 0x86, 0x9d, 0xdf, 0x5a, 0x14, 0x27, 0xd9, 0xce, 0x12, 0xf2, 0xbc, 0xaf, 0xde, 0x9f, 0xb9, 0x0b, 0xba, 0xbd, 0x6e, 0xdf, 0x61, 0xb0, 0x16, 0x76, 0xc2, 0x17, 0x54, 0x6d, 0xf5, 0x1f, 0x79, 0xf8, 0xfa, 0x7a, 0x89, 0x78, 0x12, 0x26, 0xa8, 0x5b, 0xdb, 0xcc, 0xac}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xfc, 0xac, 0xf6, 0xdd, 0xd2, 0x22, 0x1e, 0xad, 0xaf, 0x7f, 0x57, 0x04, 0xec, 0x35, 0x95, 0xe3, 0x84, 0xc1, 0x35, 0x74, 0xec, 0xc9, 0xb2, 0x6c, 0xa8, 0x2b, 0xae, 0x85, 0x2e, 0x24, 0x72, 0x78, 0x1b, 0x52, 0xf3, 0x9a, 0x8c, 0x8b, 0x1a, 0xa0, 0x50, 0x3b, 0x23, 0x8c, 0xd0, 0xc6, 0xb7, 0xcc, 0x19, 0x76, 0x65, 0xa4, 0x4a, 0x0b, 0xd6}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x03, 0x11, 0xfe, 0xe1, 0x27, 0x3e, 0x18, 0x0c, 0xe2, 0x01, 0x96, 0x8f, 0x8f, 0xd7, 0x85, 0x6e, 0x50, 0x9f, 0xb9, 0xd4, 0x42, 0xd2, 0x27, 0x11, 0x49, 0xd4, 0xec, 0xa0, 0x86, 0xd9, 0x6d, 0x98, 0xec, 0x74, 0x23, 0x47, 0x22, 0xdc, 0x79, 0x01, 0x4f, 0x8b, 0x7a, 0x61, 0xc5, 0xf4, 0xb9, 0x55, 0xa7, 0x05, 0x4d, 0x1b, 0x22, 0x00, 0x37}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xae, 0xb9, 0x22, 0xe2, 0xae, 0xc4, 0xcc, 0x39, 0xc8, 0x9f, 0x30, 0xb2, 0xa5, 0x96, 0x44, 0xa7, 0x98, 0x27, 0x98, 0x33, 0x8c, 0x47, 0xbc, 0x2a, 0xe1, 0xe7, 0x59, 0x91, 0xb9, 0xe8, 0x56, 0xd0, 0xb7, 0x97, 0xae, 0x3b, 0xab, 0xaa, 0x81, 0x4d, 0xd0, 0x18, 0xe2, 0x20, 0xbf, 0xfb, 0xd2, 0x94, 0xa7, 0x27, 0xa4, 0x2a, 0x97, 0x86, 0xad}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xfa, 0x66, 0xee, 0xe2, 0xa7, 0x83, 0x69, 0xb6, 0x64, 0x17, 0x7a, 0x6e, 0xbd, 0xe4, 0xe2, 0xcf, 0x9b, 0x02, 0xa0, 0x78, 0x94, 0x25, 0x91, 0x48, 0x06, 0x28, 0xac, 0x5d, 0x9c, 0x06, 0xa7, 0xa4, 0x2e, 0xd7, 0x28, 0x41, 0x6d, 0xba, 0x57, 0x9c, 0xf6, 0xdd, 0x18, 0x94, 0x67, 0x40, 0xe6, 0x34, 0x89, 0xd2, 0xa9, 0x13, 0x22, 0x43, 0x2b}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x8c, 0x5a, 0xb4, 0x60, 0x5a, 0xc7, 0x0f, 0xd3, 0x06, 0x59, 0x14, 0xac, 0x92, 0xdd, 0x30, 0x03, 0x69, 0x68, 0xf3, 0x79, 0x3e, 0x7f, 0x54, 0x3b, 0xc3, 0xcb, 0x87, 0xfd, 0xbb, 0xe4, 0xe9, 0xc5, 0x54, 0x7f, 0x66, 0x47, 0x55, 0x19, 0x35, 0x0d, 0x78, 0x12, 0x15, 0x1e, 0x91, 0x97, 0xd3, 0x27, 0x89, 0x14, 0xdb, 0xca, 0xfc, 0xef, 0xce}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xb6, 0x69, 0x24, 0xb3, 0x01, 0xe7, 0xea, 0x41, 0x1e, 0x2a, 0x97, 0xab, 0x04, 0x2b, 0x33, 0x01, 0x37, 0xf3, 0x09, 0xb7, 0x02, 0xaf, 0xcc, 0x5a, 0x57, 0xd9, 0x23, 0x81, 0x24, 0x99, 0xe9, 0x46, 0xe7, 0x4f, 0x49, 0x16, 0xdc, 0xa5, 0x9c, 0x56, 0x27, 0x93, 0xd5, 0xe4, 0x4b, 0x41, 0xf3, 0x9e, 0x5b, 0x58, 0xc8, 0xa3, 0xc6, 0x70, 0xd6}}; static Cpa8U montgomery_448_kp_k[10][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x0A, 0x60, 0x1C, 0x4F, 0x9A, 0x25, 0x29, 0x4B, 0xF5, 0x68, 0xA3, 0xEB, 0x43, 0x49, 0xF4, 0xBF, 0x8F, 0xD7, 0xCD, 0xF8, 0x24, 0x4C, 0x98, 0x9C, 0x77, 0x0A, 0x70, 0x21, 0xE1, 0xAA, 0xD1, 0xD0, 0x04, 0x51, 0x04, 0xEF, 0xAC, 0x82, 0x88, 0xD2, 0x34, 0x9A, 0xA1, 0xFE, 0x66, 0x52, 0x49, 0x88, 0x8E, 0xEC, 0xF9, 0xDD, 0x2F, 0x26, 0x3D}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x09, 0xE3, 0x5B, 0x8D, 0x2C, 0xDD, 0x82, 0x12, 0x37, 0xB4, 0xA5, 0xE0, 0x44, 0x5C, 0x31, 0xD3, 0x46, 0x5F, 0xE2, 0x06, 0x48, 0x3E, 0x7C, 0xD7, 0x5D, 0x34, 0x38, 0xC5, 0xF8, 0x21, 0xB0, 0x1C, 0x46, 0x0D, 0x8E, 0x90, 0x00, 0xF6, 0xFE, 0xE8, 0x9D, 0x2F, 0xA4, 0xDC, 0x5D, 0x66, 0x52, 0x93, 0x39, 0xB8, 0x28, 0x44, 0x49, 0x3D, 0x20}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x94, 0x4e, 0x0c, 0x8c, 0x3f, 0xf8, 0x20, 0x4c, 0xdd, 0x97, 0x02, 0x98, 0x86, 0x9d, 0xdf, 0x5a, 0x14, 0x27, 0xd9, 0xce, 0x12, 0xf2, 0xbc, 0xaf, 0xde, 0x9f, 0xb9, 0x0b, 0xba, 0xbd, 0x6e, 0xdf, 0x61, 0xb0, 0x16, 0x76, 0xc2, 0x17, 0x54, 0x6d, 0xf5, 0x1f, 0x79, 0xf8, 0xfa, 0x7a, 0x89, 0x78, 0x12, 0x26, 0xa8, 0x5b, 0xdb, 0xcc, 0xac}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xfc, 0xac, 0xf6, 0xdd, 0xd2, 0x22, 0x1e, 0xad, 0xaf, 0x7f, 0x57, 0x04, 0xec, 0x35, 0x95, 0xe3, 0x84, 0xc1, 0x35, 0x74, 0xec, 0xc9, 0xb2, 0x6c, 0xa8, 0x2b, 0xae, 0x85, 0x2e, 0x24, 0x72, 0x78, 0x1b, 0x52, 0xf3, 0x9a, 0x8c, 0x8b, 0x1a, 0xa0, 0x50, 0x3b, 0x23, 0x8c, 0xd0, 0xc6, 0xb7, 0xcc, 0x19, 0x76, 0x65, 0xa4, 0x4a, 0x0b, 0xd6}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x03, 0x11, 0xfe, 0xe1, 0x27, 0x3e, 0x18, 0x0c, 0xe2, 0x01, 0x96, 0x8f, 0x8f, 0xd7, 0x85, 0x6e, 0x50, 0x9f, 0xb9, 0xd4, 0x42, 0xd2, 0x27, 0x11, 0x49, 0xd4, 0xec, 0xa0, 0x86, 0xd9, 0x6d, 0x98, 0xec, 0x74, 0x23, 0x47, 0x22, 0xdc, 0x79, 0x01, 0x4f, 0x8b, 0x7a, 0x61, 0xc5, 0xf4, 0xb9, 0x55, 0xa7, 0x05, 0x4d, 0x1b, 0x22, 0x00, 0x37}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xae, 0xb9, 0x22, 0xe2, 0xae, 0xc4, 0xcc, 0x39, 0xc8, 0x9f, 0x30, 0xb2, 0xa5, 0x96, 0x44, 0xa7, 0x98, 0x27, 0x98, 0x33, 0x8c, 0x47, 0xbc, 0x2a, 0xe1, 0xe7, 0x59, 0x91, 0xb9, 0xe8, 0x56, 0xd0, 0xb7, 0x97, 0xae, 0x3b, 0xab, 0xaa, 0x81, 0x4d, 0xd0, 0x18, 0xe2, 0x20, 0xbf, 0xfb, 0xd2, 0x94, 0xa7, 0x27, 0xa4, 0x2a, 0x97, 0x86, 0xad}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xfa, 0x66, 0xee, 0xe2, 0xa7, 0x83, 0x69, 0xb6, 0x64, 0x17, 0x7a, 0x6e, 0xbd, 0xe4, 0xe2, 0xcf, 0x9b, 0x02, 0xa0, 0x78, 0x94, 0x25, 0x91, 0x48, 0x06, 0x28, 0xac, 0x5d, 0x9c, 0x06, 0xa7, 0xa4, 0x2e, 0xd7, 0x28, 0x41, 0x6d, 0xba, 0x57, 0x9c, 0xf6, 0xdd, 0x18, 0x94, 0x67, 0x40, 0xe6, 0x34, 0x89, 0xd2, 0xa9, 0x13, 0x22, 0x43, 0x2b}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x8c, 0x5a, 0xb4, 0x60, 0x5a, 0xc7, 0x0f, 0xd3, 0x06, 0x59, 0x14, 0xac, 0x92, 0xdd, 0x30, 0x03, 0x69, 0x68, 0xf3, 0x79, 0x3e, 0x7f, 0x54, 0x3b, 0xc3, 0xcb, 0x87, 0xfd, 0xbb, 0xe4, 0xe9, 0xc5, 0x54, 0x7f, 0x66, 0x47, 0x55, 0x19, 0x35, 0x0d, 0x78, 0x12, 0x15, 0x1e, 0x91, 0x97, 0xd3, 0x27, 0x89, 0x14, 0xdb, 0xca, 0xfc, 0xef, 0xce}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xb6, 0x69, 0x24, 0xb3, 0x01, 0xe7, 0xea, 0x41, 0x1e, 0x2a, 0x97, 0xab, 0x04, 0x2b, 0x33, 0x01, 0x37, 0xf3, 0x09, 0xb7, 0x02, 0xaf, 0xcc, 0x5a, 0x57, 0xd9, 0x23, 0x81, 0x24, 0x99, 0xe9, 0x46, 0xe7, 0x4f, 0x49, 0x16, 0xdc, 0xa5, 0x9c, 0x56, 0x27, 0x93, 0xd5, 0xe4, 0x4b, 0x41, 0xf3, 0x9e, 0x5b, 0x58, 0xc8, 0xa3, 0xc6, 0x70, 0xd6}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x29, 0x2b, 0x24, 0xa4, 0xb6, 0xe1, 0x0f, 0x08, 0x77, 0x00, 0xbe, 0x8f, 0x76, 0x38, 0x75, 0xea, 0xf6, 0x53, 0xfa, 0x4a, 0x3d, 0x1e, 0x2d, 0x4f, 0xef, 0x3d, 0xde, 0x1a, 0xc4, 0x9e, 0x7a, 0x2c, 0x0c, 0x99, 0x1a, 0xc9, 0xcb, 0x88, 0x91, 0xb3, 0x97, 0x26, 0x88, 0xc6, 0xab, 0xf5, 0xf7, 0xb8, 0x34, 0xe4, 0xb3, 0x6f, 0x32, 0xf1, 0x11}}; static Cpa8U montgomery_448_kp_u[10][64] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x6B, 0xD9, 0x3D, 0xF7, 0x82, 0x62, 0x76, 0x21, 0x1E, 0x11, 0x61, 0x39, 0x22, 0x98, 0x9D, 0x77, 0xB0, 0x01, 0x6A, 0xC6, 0x5F, 0x44, 0xEB, 0xAD, 0xBA, 0x4F, 0xE1, 0x9F, 0x23, 0x5F, 0x6D, 0x54, 0xD7, 0x12, 0x24, 0x0A, 0xB5, 0x79, 0xDF, 0xFB, 0x6A, 0x5E, 0xD8, 0xB1, 0x1D, 0xDA, 0x97, 0x66, 0xDC, 0x60, 0x5A, 0xF9, 0x4F, 0x3E, 0xCE}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0x17, 0x7C, 0xDA, 0x99, 0x4E, 0x51, 0x54, 0xC9, 0xC1, 0x75, 0xC5, 0x33, 0x36, 0xE6, 0x77, 0x20, 0xD6, 0x21, 0x43, 0xF3, 0x0D, 0x70, 0xA5, 0xE3, 0x3E, 0x1B, 0xAD, 0xA7, 0xC4, 0x63, 0xFE, 0x30, 0x1E, 0x8E, 0x56, 0x13, 0xAC, 0x47, 0x70, 0xF3, 0x9F, 0x6A, 0xDB, 0xB2, 0x63, 0x2F, 0x2F, 0x7A, 0xFF, 0x39, 0x62, 0x57, 0x02, 0x4A, 0x88}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xfc, 0xac, 0xf6, 0xdd, 0xd2, 0x22, 0x1e, 0xad, 0xaf, 0x7f, 0x57, 0x04, 0xec, 0x35, 0x95, 0xe3, 0x84, 0xc1, 0x35, 0x74, 0xec, 0xc9, 0xb2, 0x6c, 0xa8, 0x2b, 0xae, 0x85, 0x2e, 0x24, 0x72, 0x78, 0x1b, 0x52, 0xf3, 0x9a, 0x8c, 0x8b, 0x1a, 0xa0, 0x50, 0x3b, 0x23, 0x8c, 0xd0, 0xc6, 0xb7, 0xcc, 0x19, 0x76, 0x65, 0xa4, 0x4a, 0x0b, 0xd6}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x03, 0x11, 0xfe, 0xe1, 0x27, 0x3e, 0x18, 0x0c, 0xe2, 0x01, 0x96, 0x8f, 0x8f, 0xd7, 0x85, 0x6e, 0x50, 0x9f, 0xb9, 0xd4, 0x42, 0xd2, 0x27, 0x11, 0x49, 0xd4, 0xec, 0xa0, 0x86, 0xd9, 0x6d, 0x98, 0xec, 0x74, 0x23, 0x47, 0x22, 0xdc, 0x79, 0x01, 0x4f, 0x8b, 0x7a, 0x61, 0xc5, 0xf4, 0xb9, 0x55, 0xa7, 0x05, 0x4d, 0x1b, 0x22, 0x00, 0x37}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xae, 0xb9, 0x22, 0xe2, 0xae, 0xc4, 0xcc, 0x39, 0xc8, 0x9f, 0x30, 0xb2, 0xa5, 0x96, 0x44, 0xa7, 0x98, 0x27, 0x98, 0x33, 0x8c, 0x47, 0xbc, 0x2a, 0xe1, 0xe7, 0x59, 0x91, 0xb9, 0xe8, 0x56, 0xd0, 0xb7, 0x97, 0xae, 0x3b, 0xab, 0xaa, 0x81, 0x4d, 0xd0, 0x18, 0xe2, 0x20, 0xbf, 0xfb, 0xd2, 0x94, 0xa7, 0x27, 0xa4, 0x2a, 0x97, 0x86, 0xad}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xfa, 0x66, 0xee, 0xe2, 0xa7, 0x83, 0x69, 0xb6, 0x64, 0x17, 0x7a, 0x6e, 0xbd, 0xe4, 0xe2, 0xcf, 0x9b, 0x02, 0xa0, 0x78, 0x94, 0x25, 0x91, 0x48, 0x06, 0x28, 0xac, 0x5d, 0x9c, 0x06, 0xa7, 0xa4, 0x2e, 0xd7, 0x28, 0x41, 0x6d, 0xba, 0x57, 0x9c, 0xf6, 0xdd, 0x18, 0x94, 0x67, 0x40, 0xe6, 0x34, 0x89, 0xd2, 0xa9, 0x13, 0x22, 0x43, 0x2b}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x8c, 0x5a, 0xb4, 0x60, 0x5a, 0xc7, 0x0f, 0xd3, 0x06, 0x59, 0x14, 0xac, 0x92, 0xdd, 0x30, 0x03, 0x69, 0x68, 0xf3, 0x79, 0x3e, 0x7f, 0x54, 0x3b, 0xc3, 0xcb, 0x87, 0xfd, 0xbb, 0xe4, 0xe9, 0xc5, 0x54, 0x7f, 0x66, 0x47, 0x55, 0x19, 0x35, 0x0d, 0x78, 0x12, 0x15, 0x1e, 0x91, 0x97, 0xd3, 0x27, 0x89, 0x14, 0xdb, 0xca, 0xfc, 0xef, 0xce}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xb6, 0x69, 0x24, 0xb3, 0x01, 0xe7, 0xea, 0x41, 0x1e, 0x2a, 0x97, 0xab, 0x04, 0x2b, 0x33, 0x01, 0x37, 0xf3, 0x09, 0xb7, 0x02, 0xaf, 0xcc, 0x5a, 0x57, 0xd9, 0x23, 0x81, 0x24, 0x99, 0xe9, 0x46, 0xe7, 0x4f, 0x49, 0x16, 0xdc, 0xa5, 0x9c, 0x56, 0x27, 0x93, 0xd5, 0xe4, 0x4b, 0x41, 0xf3, 0x9e, 0x5b, 0x58, 0xc8, 0xa3, 0xc6, 0x70, 0xd6}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x29, 0x2b, 0x24, 0xa4, 0xb6, 0xe1, 0x0f, 0x08, 0x77, 0x00, 0xbe, 0x8f, 0x76, 0x38, 0x75, 0xea, 0xf6, 0x53, 0xfa, 0x4a, 0x3d, 0x1e, 0x2d, 0x4f, 0xef, 0x3d, 0xde, 0x1a, 0xc4, 0x9e, 0x7a, 0x2c, 0x0c, 0x99, 0x1a, 0xc9, 0xcb, 0x88, 0x91, 0xb3, 0x97, 0x26, 0x88, 0xc6, 0xab, 0xf5, 0xf7, 0xb8, 0x34, 0xe4, 0xb3, 0x6f, 0x32, 0xf1, 0x11}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9f, 0x21, 0x6e, 0xa2, 0xfa, 0x54, 0xef, 0x53, 0xc3, 0x3e, 0xea, 0xce, 0x9f, 0xb7, 0xe2, 0x86, 0x82, 0xb8, 0x2d, 0x20, 0x87, 0xd0, 0x10, 0xcf, 0x67, 0x6c, 0xaf, 0xd4, 0x09, 0x5e, 0x97, 0x7b, 0xc1, 0xd5, 0xbd, 0xeb, 0xe3, 0x4c, 0x27, 0x67, 0xc4, 0x26, 0x88, 0x28, 0x00, 0x5b, 0x1e, 0xaf, 0x9d, 0x5b, 0xd5, 0x49, 0x47, 0x3b, 0xaa}}; /*********************** * Montgomery 25519 Kp * ***********************/ static Cpa8U montgomery_25519_kp_x[9][32] = { {0x4C, 0x1C, 0xAB, 0xD0, 0xA6, 0x03, 0xA9, 0x10, 0x3b, 0x35, 0xB3, 0x26, 0xEC, 0x24, 0x66, 0x72, 0x7C, 0x5F, 0xB1, 0x24, 0xA4, 0xC1, 0x94, 0x35, 0xDB, 0x30, 0x30, 0x58, 0x67, 0x68, 0xDB, 0xE6}, {0x93, 0xA4, 0x15, 0xC7, 0x49, 0xD5, 0x4C, 0xFC, 0x3E, 0x3C, 0xC0, 0x6F, 0x10, 0xE7, 0xDB, 0x31, 0x2C, 0xAE, 0x38, 0x05, 0x9D, 0x95, 0xB7, 0xF4, 0xD3, 0x11, 0x68, 0x78, 0x12, 0x0F, 0x21, 0xE5}, {0x62, 0x9d, 0x47, 0x54, 0x8a, 0x31, 0x49, 0xad, 0xa9, 0x6f, 0x66, 0x8e, 0x67, 0x49, 0x3a, 0x2a, 0x9c, 0x1e, 0xe4, 0xf5, 0x90, 0xb1, 0x18, 0xf9, 0xdf, 0x98, 0x01, 0x38, 0x4b, 0x47, 0xe4, 0x05}, {0x36, 0xd3, 0xe1, 0xe0, 0xde, 0x0c, 0x2e, 0x89, 0xaf, 0x97, 0x57, 0x05, 0x78, 0xaf, 0x81, 0xdb, 0x9e, 0xa9, 0x9b, 0xc4, 0xb1, 0xb1, 0x86, 0xfe, 0xa5, 0x7e, 0x16, 0x85, 0x86, 0xe4, 0x45, 0x88}, {0x1a, 0x0f, 0x77, 0x9c, 0xf1, 0xc8, 0x4a, 0x4b, 0x46, 0x23, 0x01, 0x28, 0x04, 0x5f, 0x5e, 0x41, 0x84, 0x29, 0xa7, 0x76, 0xba, 0xd8, 0xfb, 0x84, 0x37, 0x36, 0x4e, 0xc5, 0x18, 0x5d, 0x60, 0xe8}, {0x5e, 0xf9, 0x5f, 0xe7, 0xe6, 0x18, 0xe3, 0x2a, 0x12, 0x4b, 0xb2, 0x4f, 0xee, 0x74, 0xfb, 0x20, 0xf5, 0xbe, 0x3f, 0xbe, 0x98, 0xcf, 0xf2, 0x05, 0x39, 0xff, 0x46, 0xd1, 0x11, 0x68, 0xf3, 0x1d}, {0x3c, 0xb6, 0xce, 0xa6, 0xd3, 0x0d, 0xa9, 0x02, 0x0d, 0x03, 0x31, 0x16, 0x12, 0xfe, 0x79, 0x19, 0x07, 0xa2, 0x2e, 0x5e, 0x7b, 0xd1, 0x46, 0x07, 0x08, 0xe7, 0xd5, 0x70, 0x72, 0x89, 0xd4, 0x49}, {0x27, 0xd2, 0xc1, 0x87, 0xf7, 0xf8, 0x5e, 0x92, 0xde, 0x57, 0x10, 0x51, 0x4c, 0xf9, 0x3b, 0xdb, 0x3e, 0xdd, 0xf9, 0x42, 0x2f, 0x4c, 0xda, 0x54, 0x16, 0xd3, 0x49, 0x86, 0x89, 0xb4, 0x1d, 0x68}, {0x42, 0x68, 0xe3, 0x90, 0xc0, 0xeb, 0x16, 0x5c, 0x07, 0x0b, 0x64, 0x78, 0x8e, 0x8c, 0x31, 0xc3, 0x64, 0x0f, 0xf3, 0xbf, 0xac, 0x96, 0xa6, 0xf0, 0x31, 0xe1, 0xc8, 0x7c, 0x9e, 0x19, 0xb5, 0xae}}; static Cpa8U montgomery_25519_kp_k[9][32] = { {0xC4, 0x9A, 0x44, 0xBA, 0x44, 0x22, 0x6A, 0x50, 0x18, 0x5A, 0xFC, 0xC1, 0x0A, 0x4C, 0x14, 0x62, 0xDD, 0x5E, 0x46, 0x82, 0x4B, 0x15, 0x16, 0x3B, 0x9D, 0x7C, 0x52, 0xF0, 0x6B, 0xE3, 0x46, 0xA5}, {0x0D, 0xBA, 0x18, 0x79, 0x9E, 0x16, 0xA4, 0x2C, 0xD4, 0x01, 0xEA, 0xE0, 0x21, 0x64, 0x1B, 0xC1, 0xF5, 0x6A, 0x7D, 0x95, 0x91, 0x26, 0xD2, 0x5A, 0x3C, 0x67, 0xB4, 0xD1, 0xD4, 0xE9, 0x66, 0x4B}, {0x36, 0xd3, 0xe1, 0xe0, 0xde, 0x0c, 0x2e, 0x89, 0xaf, 0x97, 0x57, 0x05, 0x78, 0xaf, 0x81, 0xdb, 0x9e, 0xa9, 0x9b, 0xc4, 0xb1, 0xb1, 0x86, 0xfe, 0xa5, 0x7e, 0x16, 0x85, 0x86, 0xe4, 0x45, 0x88}, {0x1a, 0x0f, 0x77, 0x9c, 0xf1, 0xc8, 0x4a, 0x4b, 0x46, 0x23, 0x01, 0x28, 0x04, 0x5f, 0x5e, 0x41, 0x84, 0x29, 0xa7, 0x76, 0xba, 0xd8, 0xfb, 0x84, 0x37, 0x36, 0x4e, 0xc5, 0x18, 0x5d, 0x60, 0xe8}, {0x5e, 0xf9, 0x5f, 0xe7, 0xe6, 0x18, 0xe3, 0x2a, 0x12, 0x4b, 0xb2, 0x4f, 0xee, 0x74, 0xfb, 0x20, 0xf5, 0xbe, 0x3f, 0xbe, 0x98, 0xcf, 0xf2, 0x05, 0x39, 0xff, 0x46, 0xd1, 0x11, 0x68, 0xf3, 0x1d}, {0x3c, 0xb6, 0xce, 0xa6, 0xd3, 0x0d, 0xa9, 0x02, 0x0d, 0x03, 0x31, 0x16, 0x12, 0xfe, 0x79, 0x19, 0x07, 0xa2, 0x2e, 0x5e, 0x7b, 0xd1, 0x46, 0x07, 0x08, 0xe7, 0xd5, 0x70, 0x72, 0x89, 0xd4, 0x49}, {0x27, 0xd2, 0xc1, 0x87, 0xf7, 0xf8, 0x5e, 0x92, 0xde, 0x57, 0x10, 0x51, 0x4c, 0xf9, 0x3b, 0xdb, 0x3e, 0xdd, 0xf9, 0x42, 0x2f, 0x4c, 0xda, 0x54, 0x16, 0xd3, 0x49, 0x86, 0x89, 0xb4, 0x1d, 0x68}, {0x42, 0x68, 0xe3, 0x90, 0xc0, 0xeb, 0x16, 0x5c, 0x07, 0x0b, 0x64, 0x78, 0x8e, 0x8c, 0x31, 0xc3, 0x64, 0x0f, 0xf3, 0xbf, 0xac, 0x96, 0xa6, 0xf0, 0x31, 0xe1, 0xc8, 0x7c, 0x9e, 0x19, 0xb5, 0xae}, {0x3b, 0x00, 0x4a, 0xc9, 0xfe, 0x39, 0x73, 0x85, 0x15, 0x1c, 0xa3, 0xf6, 0x7e, 0x5e, 0x1e, 0x89, 0x69, 0xee, 0xc7, 0x81, 0x66, 0x77, 0xf6, 0x64, 0xe2, 0xa9, 0xb6, 0x60, 0x60, 0xeb, 0x5b, 0x0a}}; static Cpa8U montgomery_25519_kp_u[9][32] = { {0x52, 0x85, 0xA2, 0x77, 0x55, 0x07, 0xB4, 0x54, 0xF7, 0x71, 0x1C, 0x49, 0x03, 0xCF, 0xEC, 0x32, 0x4F, 0x08, 0x8D, 0xF2, 0x4D, 0xEA, 0x94, 0x8E, 0x90, 0xC6, 0xE9, 0x9D, 0x37, 0x55, 0xDA, 0xC3}, {0x57, 0x79, 0xAC, 0x7A, 0x64, 0xF7, 0xF8, 0xE6, 0x52, 0xA1, 0x9F, 0x79, 0x68, 0x5A, 0x59, 0x8B, 0xF8, 0x73, 0xB8, 0xB4, 0x5C, 0xE4, 0xAD, 0x7A, 0x7D, 0x90, 0xE8, 0x76, 0x94, 0xDE, 0xCB, 0x95}, {0x1a, 0x0f, 0x77, 0x9c, 0xf1, 0xc8, 0x4a, 0x4b, 0x46, 0x23, 0x01, 0x28, 0x04, 0x5f, 0x5e, 0x41, 0x84, 0x29, 0xa7, 0x76, 0xba, 0xd8, 0xfb, 0x84, 0x37, 0x36, 0x4e, 0xc5, 0x18, 0x5d, 0x60, 0xe8}, {0x5e, 0xf9, 0x5f, 0xe7, 0xe6, 0x18, 0xe3, 0x2a, 0x12, 0x4b, 0xb2, 0x4f, 0xee, 0x74, 0xfb, 0x20, 0xf5, 0xbe, 0x3f, 0xbe, 0x98, 0xcf, 0xf2, 0x05, 0x39, 0xff, 0x46, 0xd1, 0x11, 0x68, 0xf3, 0x1d}, {0x3c, 0xb6, 0xce, 0xa6, 0xd3, 0x0d, 0xa9, 0x02, 0x0d, 0x03, 0x31, 0x16, 0x12, 0xfe, 0x79, 0x19, 0x07, 0xa2, 0x2e, 0x5e, 0x7b, 0xd1, 0x46, 0x07, 0x08, 0xe7, 0xd5, 0x70, 0x72, 0x89, 0xd4, 0x49}, {0x27, 0xd2, 0xc1, 0x87, 0xf7, 0xf8, 0x5e, 0x92, 0xde, 0x57, 0x10, 0x51, 0x4c, 0xf9, 0x3b, 0xdb, 0x3e, 0xdd, 0xf9, 0x42, 0x2f, 0x4c, 0xda, 0x54, 0x16, 0xd3, 0x49, 0x86, 0x89, 0xb4, 0x1d, 0x68}, {0x42, 0x68, 0xe3, 0x90, 0xc0, 0xeb, 0x16, 0x5c, 0x07, 0x0b, 0x64, 0x78, 0x8e, 0x8c, 0x31, 0xc3, 0x64, 0x0f, 0xf3, 0xbf, 0xac, 0x96, 0xa6, 0xf0, 0x31, 0xe1, 0xc8, 0x7c, 0x9e, 0x19, 0xb5, 0xae}, {0x3b, 0x00, 0x4a, 0xc9, 0xfe, 0x39, 0x73, 0x85, 0x15, 0x1c, 0xa3, 0xf6, 0x7e, 0x5e, 0x1e, 0x89, 0x69, 0xee, 0xc7, 0x81, 0x66, 0x77, 0xf6, 0x64, 0xe2, 0xa9, 0xb6, 0x60, 0x60, 0xeb, 0x5b, 0x0a}, {0x18, 0x9a, 0xf6, 0x04, 0x4d, 0xc5, 0x6c, 0xda, 0x6d, 0x08, 0x86, 0xa2, 0xc6, 0x71, 0xdd, 0x05, 0xd4, 0x69, 0x80, 0xe1, 0xe1, 0x88, 0x7d, 0x39, 0x4d, 0x57, 0xe7, 0x30, 0xf2, 0x7d, 0xba, 0xe4}}; /***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This function selects vectors used in ECED performance test * *****************************************************************************/ CpaStatus getEcMontEdwdsTestVectors(CpaBoolean generator, CpaCyEcMontEdwdsCurveType curveType, Cpa32U vector, sample_ec_montedwds_vectors_t *testVectors) { CpaStatus status = CPA_STATUS_SUCCESS; if (generator == CPA_TRUE) { /* KG */ switch (curveType) { case CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE: /* Montgomery 25519 Kg */ testVectors->x = NULL; testVectors->xSize = 0; testVectors->y = NULL; testVectors->ySize = 0; testVectors->k = montgomery_25519_kg_k[vector]; testVectors->kSize = sizeof(montgomery_25519_kg_k[vector]); testVectors->u = montgomery_25519_kg_u[vector]; testVectors->uSize = sizeof(montgomery_25519_kg_u[vector]); testVectors->v = NULL; testVectors->vSize = 0; testVectors->vectorsNum = sizeof(montgomery_25519_kg_k) / sizeof(montgomery_25519_kg_k[0]); break; case CPA_CY_EC_MONTEDWDS_ED25519_TYPE: /* Edwards 25519 Kg */ testVectors->x = edwards_25519_kg_x; testVectors->xSize = sizeof(edwards_25519_kg_x); testVectors->y = edwards_25519_kg_y; testVectors->ySize = sizeof(edwards_25519_kg_y); testVectors->k = edwards_25519_kg_k[vector]; testVectors->kSize = sizeof(edwards_25519_kg_k[vector]); testVectors->u = edwards_25519_kg_u[vector]; testVectors->uSize = sizeof(edwards_25519_kg_u[vector]); testVectors->v = edwards_25519_kg_v[vector]; testVectors->vSize = sizeof(edwards_25519_kg_v[vector]); testVectors->vectorsNum = sizeof(edwards_25519_kg_k) / sizeof(edwards_25519_kg_k[0]); break; case CPA_CY_EC_MONTEDWDS_CURVE448_TYPE: /* Montgomery 448 Kg */ testVectors->x = NULL; testVectors->xSize = 0; testVectors->y = NULL; testVectors->ySize = 0; testVectors->k = montgomery_448_kg_k[vector]; testVectors->kSize = sizeof(montgomery_448_kg_k[vector]); testVectors->u = montgomery_448_kg_u[vector]; testVectors->uSize = sizeof(montgomery_448_kg_u[vector]); testVectors->v = NULL; testVectors->vSize = 0; testVectors->vectorsNum = sizeof(montgomery_448_kg_k) / sizeof(montgomery_448_kg_k[0]); break; case CPA_CY_EC_MONTEDWDS_ED448_TYPE: /* Edwards 448 Kg */ testVectors->x = edwards_448_kg_x; testVectors->xSize = sizeof(edwards_448_kg_x); testVectors->y = edwards_448_kg_y; testVectors->ySize = sizeof(edwards_448_kg_y); testVectors->k = edwards_448_kg_k[vector]; testVectors->kSize = sizeof(edwards_448_kg_k[vector]); testVectors->u = edwards_448_kg_u[vector]; testVectors->uSize = sizeof(edwards_448_kg_u[vector]); testVectors->v = edwards_448_kg_v[vector]; testVectors->vSize = sizeof(edwards_448_kg_v[vector]); testVectors->vectorsNum = sizeof(edwards_448_kg_k) / sizeof(edwards_448_kg_k[0]); break; default: PRINT("Unknown ECED curveType %d\n", curveType); status = CPA_STATUS_FAIL; break; } } else { /* KP */ switch (curveType) { case CPA_CY_EC_MONTEDWDS_CURVE25519_TYPE: /* Montgomery 25519 Kp */ testVectors->x = montgomery_25519_kp_x[vector]; testVectors->xSize = sizeof(montgomery_25519_kp_x[vector]); testVectors->y = NULL; testVectors->ySize = 0; testVectors->k = montgomery_25519_kp_k[vector]; testVectors->kSize = sizeof(montgomery_25519_kp_k[vector]); testVectors->u = montgomery_25519_kp_u[vector]; testVectors->uSize = sizeof(montgomery_25519_kp_u[vector]); testVectors->v = NULL; testVectors->vSize = 0; testVectors->vectorsNum = sizeof(montgomery_25519_kp_k) / sizeof(montgomery_25519_kp_k[0]); break; case CPA_CY_EC_MONTEDWDS_ED25519_TYPE: /* Edwards 25519 Kp */ testVectors->x = edwards_25519_kp_x[vector]; testVectors->xSize = sizeof(edwards_25519_kp_x[vector]); testVectors->y = edwards_25519_kp_y[vector]; testVectors->ySize = sizeof(edwards_25519_kp_y[vector]); testVectors->k = edwards_25519_kp_k[vector]; testVectors->kSize = sizeof(edwards_25519_kp_k[vector]); testVectors->u = edwards_25519_kp_u[vector]; testVectors->uSize = sizeof(edwards_25519_kp_u[vector]); testVectors->v = edwards_25519_kp_v[vector]; testVectors->vSize = sizeof(edwards_25519_kp_v[vector]); testVectors->vectorsNum = sizeof(edwards_25519_kp_k) / sizeof(edwards_25519_kp_k[0]); break; case CPA_CY_EC_MONTEDWDS_CURVE448_TYPE: /* Montgomery 448 Kp */ testVectors->x = montgomery_448_kp_x[vector]; testVectors->xSize = sizeof(montgomery_448_kp_x[vector]); testVectors->y = NULL; testVectors->ySize = 0; testVectors->k = montgomery_448_kp_k[vector]; testVectors->kSize = sizeof(montgomery_448_kp_k[vector]); testVectors->u = montgomery_448_kp_u[vector]; testVectors->uSize = sizeof(montgomery_448_kp_u[vector]); testVectors->v = NULL; testVectors->vSize = 0; testVectors->vectorsNum = sizeof(montgomery_448_kp_k) / sizeof(montgomery_448_kp_k[0]); break; case CPA_CY_EC_MONTEDWDS_ED448_TYPE: /* Edwards 448 Kp */ testVectors->x = edwards_448_kp_x[vector]; testVectors->xSize = sizeof(edwards_448_kp_x[vector]); testVectors->y = edwards_448_kp_y[vector]; testVectors->ySize = sizeof(edwards_448_kp_y[vector]); testVectors->k = edwards_448_kp_k[vector]; testVectors->kSize = sizeof(edwards_448_kp_k[vector]); testVectors->u = edwards_448_kp_u[vector]; testVectors->uSize = sizeof(edwards_448_kp_u[vector]); testVectors->v = edwards_448_kp_v[vector]; testVectors->vSize = sizeof(edwards_448_kp_v[vector]); testVectors->vectorsNum = sizeof(edwards_448_kp_k) / sizeof(edwards_448_kp_k[0]); break; default: PRINT("Unknown ECED curveType %d\n", curveType); status = CPA_STATUS_FAIL; break; } } return status; } EXPORT_SYMBOL(getEcMontEdwdsTestVectors); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ cpa_sample_code_ec_montedwds_vectors.h000066400000000000000000000117531503624047500405040ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/** ***************************************************************************** * * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_eced_vectors.h * * @defgroup ecMontEdwdsThreads * * @ingroup ecMontEdwdsThreads * * @description * This file contains structure declaration for test vectors * and getEcedTestVectors function definition used in ECED test * *****************************************************************************/ #ifndef CPA_SAMPLE_CODE_ECMONTEDWDS_VECTORS_H #define CPA_SAMPLE_CODE_ECMONTEDWDS_VECTORS_H #include "cpa.h" #include "cpa_types.h" #include "cpa_sample_code_crypto_utils.h" #if CY_API_VERSION_AT_LEAST(2, 3) /** ***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This structure contains data relating to test vectors used in ECED * test. * ****************************************************************************/ typedef struct sample_ec_montedwds_vectors_s { /* pointer to x vector */ Cpa8U *x; /* x vector size */ Cpa32U xSize; /* pointer to y vector */ Cpa8U *y; /* y vector size */ Cpa32U ySize; /* pointer to k vector */ Cpa8U *k; /* k vector size */ Cpa32U kSize; /* pointer to u vector - generated x */ Cpa8U *u; /* u vector size */ Cpa32U uSize; /* pointer to v vector - generated y */ Cpa8U *v; /* v vector size */ Cpa32U vSize; /* number of vectors in selected curve type */ Cpa32U vectorsNum; } sample_ec_montedwds_vectors_t; /** ***************************************************************************** * @ingroup ecMontEdwdsThreads * * @description * This functions selects vectors used in ECED test * ****************************************************************************/ CpaStatus getEcMontEdwdsTestVectors(CpaBoolean generator, CpaCyEcMontEdwdsCurveType curveType, Cpa32U vector, sample_ec_montedwds_vectors_t *testVectors); #endif /* CY_API_VERSION_AT_LEAST(2, 3) */ #endif cpa_sample_code_ecdsa_kpt2_perf.c000066400000000000000000000263541503624047500373150ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * **************************************************************************/ /*************************************************************************** * @file cpa_sample_code_ecdsa_kpt2_perf.c * * This file provides some interface for kpt2 ecdsa performance test. * **************************************************************************/ #include "cpa_sample_code_ecdsa_kpt2_perf.h" #if CY_API_VERSION_AT_LEAST(3, 0) void kpt2FreeECDSAOPDataMemory(CpaCyKptEcdsaSignRSOpData *pKPTSignRSOpData, CpaFlatBuffer *pWpkAndAuthTag, CpaFlatBuffer *pPrivateKey) { if (NULL != pKPTSignRSOpData->privateKey.pData) qaeMemFreeNUMA((void **)&pKPTSignRSOpData->privateKey.pData); if (NULL != pKPTSignRSOpData->m.pData) qaeMemFreeNUMA((void **)&pKPTSignRSOpData->m.pData); if (NULL != pWpkAndAuthTag) { if (NULL != pWpkAndAuthTag->pData) qaeMemFree((void **)&pWpkAndAuthTag->pData); qaeMemFree((void **)&pWpkAndAuthTag); } if (NULL != pPrivateKey) { if (NULL != pPrivateKey->pData) qaeMemFree((void **)&pPrivateKey->pData); qaeMemFree((void **)&pPrivateKey); } return; } /*************************************************************************** * @description * * This function is to set Kpt ECDSA SignRSOpData * * @param[in] pSignRSOpData Unwrapped SignRSOpData * @param[in] instanceHandle InstanceHandle * @param[in] pSampleSWK SWK * @param[in] pIv iv * @param[in] pAad Additional Authenticated Data * @param[in] aadLenInBytes the length of aad * @param[out] pKPTSignRSOpData Kpt ECDSA SignRSOpData * * @retval CPA_STATUS_SUCCESS Operation is successful * @retval CPA_STATUS_FAIL Operation is failure ***************************************************************************/ CpaStatus setKPT2EcdsaSignRSOpData(CpaInstanceHandle instanceHandle, CpaCyKptEcdsaSignRSOpData *pKPTSignRSOpData, CpaCyEcdsaSignRSOpData *pSignRSOpData, Cpa8U *pSampleSWK, Cpa8U *pIv, Cpa8U *pAad, Cpa32U aadLenInBytes) { CpaStatus retstatus = CPA_STATUS_SUCCESS; CpaBoolean status = CPA_TRUE; Cpa32U wpkSize = 0; Cpa8U pAuthTag[AUTH_TAG_LEN_IN_BYTES] = {0}; CpaFlatBuffer *pWpkAndAuthTag = NULL; CpaFlatBuffer *pPrivateKey = NULL; pWpkAndAuthTag = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pWpkAndAuthTag) { PRINT_ERR("qaeMemAlloc pWpkAndAuthTag error\n"); return CPA_STATUS_FAIL; } pPrivateKey = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pPrivateKey) { PRINT_ERR("qaeMemAlloc pClearKey error\n"); qaeMemFree((void **)&pWpkAndAuthTag); return CPA_STATUS_FAIL; } if (GFP_P521_SIZE_IN_BYTES == pSignRSOpData->d.dataLenInBytes) { pWpkAndAuthTag->dataLenInBytes = KPT2_ECDSA_P521_WPK_SIZE_IN_BYTES + AUTH_TAG_LEN_IN_BYTES; pPrivateKey->dataLenInBytes = KPT2_ECDSA_P521_WPK_SIZE_IN_BYTES; } else { pWpkAndAuthTag->dataLenInBytes = pSignRSOpData->d.dataLenInBytes + AUTH_TAG_LEN_IN_BYTES; pPrivateKey->dataLenInBytes = pSignRSOpData->d.dataLenInBytes; } pWpkAndAuthTag->pData = qaeMemAlloc(pWpkAndAuthTag->dataLenInBytes); if (NULL == pWpkAndAuthTag->pData) { PRINT_ERR("qaeMemAlloc pWpkAndAuthTag->pData error\n"); qaeMemFree((void **)&pPrivateKey); qaeMemFree((void **)&pWpkAndAuthTag); return CPA_STATUS_FAIL; } pPrivateKey->pData = qaeMemAlloc(pPrivateKey->dataLenInBytes); if (NULL == pPrivateKey->pData) { PRINT_ERR("qaeMemAlloc pClearKey->pData error\n"); qaeMemFree((void **)&pPrivateKey); qaeMemFree((void **)&pWpkAndAuthTag->pData); qaeMemFree((void **)&pWpkAndAuthTag); return CPA_STATUS_FAIL; } memset(pPrivateKey->pData, 0, pPrivateKey->dataLenInBytes); memcpy(pPrivateKey->pData + pPrivateKey->dataLenInBytes - pSignRSOpData->d.dataLenInBytes, pSignRSOpData->d.pData, pSignRSOpData->d.dataLenInBytes); memset(pWpkAndAuthTag->pData, 0, pWpkAndAuthTag->dataLenInBytes); status = encryptPrivateKey(pPrivateKey->pData, pPrivateKey->dataLenInBytes, pSampleSWK, pIv, IV_LEN_IN_BYTES, pWpkAndAuthTag->pData, &wpkSize, pAuthTag, pAad, aadLenInBytes); if (CPA_FALSE == status) { kpt2FreeECDSAOPDataMemory( pKPTSignRSOpData, pWpkAndAuthTag, pPrivateKey); PRINT_ERR("encryptPrivateKey failed!\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == retstatus) { /* Concatenated with AuthTag */ memcpy( pWpkAndAuthTag->pData + wpkSize, pAuthTag, AUTH_TAG_LEN_IN_BYTES); /* Opdata setup */ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pKPTSignRSOpData->privateKey), pWpkAndAuthTag->dataLenInBytes, pWpkAndAuthTag->pData, pWpkAndAuthTag->dataLenInBytes, kpt2FreeECDSAOPDataMemory(pKPTSignRSOpData, pWpkAndAuthTag, pPrivateKey)); ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pKPTSignRSOpData->m), pSignRSOpData->m.dataLenInBytes, pSignRSOpData->m.pData, pSignRSOpData->m.dataLenInBytes, kpt2FreeECDSAOPDataMemory(pKPTSignRSOpData, pWpkAndAuthTag, pPrivateKey)); } if (NULL != pWpkAndAuthTag && NULL != pWpkAndAuthTag->pData) { qaeMemFree((void **)&pWpkAndAuthTag->pData); } if (NULL != pWpkAndAuthTag) { qaeMemFree((void **)&pWpkAndAuthTag); } if (NULL != pPrivateKey && NULL != pPrivateKey->pData) { qaeMemFree((void **)&pPrivateKey->pData); } if (NULL != pPrivateKey) { qaeMemFree((void **)&pPrivateKey); } return retstatus; } /** ***************************************************************************** * @ingroup sampleKPTECDSACode * * @description * Function for setup KPT ECDSA test before calling framework createThreads * functions * *****************************************************************************/ CpaStatus setupKpt2EcdsaTest(Cpa32U nLenInBits, CpaCyEcFieldType fieldType, sync_mode_t syncMode, ecdsa_step_t step, Cpa32U numBuffers, Cpa32U numLoops) { ecdsa_test_params_t *ecdsaSetup = NULL; ecdsaSetup = (ecdsa_test_params_t *)&thread_setup_g[testTypeCount_g][0]; ecdsaSetup->enableKPT = CPA_TRUE; return setupEcdsaTest( nLenInBits, fieldType, syncMode, step, numBuffers, numLoops); } /****************************************************************************** * @ingroup sampleECDSACode * * @description * This function frees all memory related to KPT2 data. * ****************************************************************************/ void kpt2EcdsaFreeDataMemory(CpaCyKptEcdsaSignRSOpData *pKPTSignRSOpData, CpaCyKptUnwrapContext *pKptUnwrapCtx) { if (NULL != pKPTSignRSOpData) { if (NULL != pKPTSignRSOpData->privateKey.pData) { qaeMemFreeNUMA((void **)&pKPTSignRSOpData->privateKey.pData); } if (NULL != pKPTSignRSOpData->m.pData) { qaeMemFreeNUMA((void **)&pKPTSignRSOpData->m.pData); } qaeMemFreeNUMA((void **)&pKPTSignRSOpData); } if (NULL != pKptUnwrapCtx) { qaeMemFreeNUMA((void **)&pKptUnwrapCtx); } return; } EXPORT_SYMBOL(kpt2EcdsaFreeDataMemory); #endif cpa_sample_code_ecdsa_kpt2_perf.h000066400000000000000000000070151503624047500373130ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_ECDSA_KPT2_PERF_H #define CPA_SAMPLE_CODE_ECDSA_KPT2_PERF_H #include "cpa_sample_code_kpt2_common.h" #if CY_API_VERSION_AT_LEAST(3, 0) #define KPT2_ECDSA_P521_WPK_SIZE_IN_BYTES (72) CpaStatus setKPT2EcdsaSignRSOpData(CpaInstanceHandle instanceHandle, CpaCyKptEcdsaSignRSOpData *pKPTSignRSOpData, CpaCyEcdsaSignRSOpData *pSignRSOpData, Cpa8U *pSampleSWK, Cpa8U *pIv, Cpa8U *pAad, Cpa32U aadLenInBytes); #endif #endif cpa_sample_code_ecdsa_perf.c000066400000000000000000002211031503624047500363420ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_ecdsa_perf.c * * @ingroup cryptoThreads * * @description * This file contains the main ecdsa performance code. This code generates * a random private key, then uses Elliptic curves to get a public key. * A User defined number of random messages are generated and signed * using the private key. A User defined number of messages are then * verified repeatedly using the public key to measure performance * *****************************************************************************/ #include "cpa_cy_ec.h" #include "cpa_cy_ecdsa.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_ec_curves.h" #include "cpa_cy_im.h" #ifdef SC_DEV_INFO_ENABLED #include "cpa_dev.h" #endif #ifdef POLL_INLINE #include "icp_sal_poll.h" #endif #include "qat_perf_cycles.h" #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED #include "cpa_sample_code_ecdsa_kpt2_perf.h" #endif #endif #endif extern Cpa32U packageIdCount_g; CpaBoolean msgFlagSym2 = CPA_FALSE; void ecdsaPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus); void ecdsaPointMultiplyPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); void ecdsaSignOnlyPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS); CpaStatus getCurveData(ecdsa_test_params_t *setup); CpaStatus calcEcPoint(ecdsa_test_params_t *setup, CpaFlatBuffer *k, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk); CpaStatus ecdsaSignRSOpDataSetup(ecdsa_test_params_t *setup, CpaFlatBuffer *d, CpaFlatBuffer *r, CpaFlatBuffer *s, CpaFlatBuffer *message, CpaFlatBuffer *z, CpaFlatBuffer *pDigest, perf_data_t *pEcdsaData, CpaCyEcdsaSignRSOpData *pSignRSOpData); CpaStatus ecdsaPerform(ecdsa_test_params_t *setup); void ecdsaPerformance(single_thread_test_data_t *testSetup); void ecdsaPerformRsOnlyMemFree( ecdsa_test_params_t *setup, CpaFlatBuffer *pX, CpaFlatBuffer *pY, CpaFlatBuffer *pR, CpaFlatBuffer *pS, CpaFlatBuffer *msg, CpaFlatBuffer *pZ, CpaFlatBuffer **ppDigests, CpaCyEcdsaSignRSOpData **ppSignRSOpData, CpaCyEcPointMultiplyOpData **ppPointMultiplyOpData, CpaFlatBuffer privateKey); ///* // * *********************************************************************** // * elliptic curve definitions as defined in: // * http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf // * ************************************************************************/ /*************************************************************************** * @ingroup cryptoThreads * * @description * Callback function for ECDSA verify operations ***************************************************************************/ void ecdsaPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus) { processCallback(pCallbackTag); } /*************************************************************************** * @ingroup cryptoThreads * * @description * Callback function for ECDSA Point Multiply operations ***************************************************************************/ void ecdsaPointMultiplyPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("ECDSA Point Multiply callback failed: status = %d\n", status); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } if (CPA_FALSE == multiplyStatus) { PRINT_ERR("ECDSA Point Multiply output failed\n"); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } processCallback(pCallbackTag); } /*************************************************************************** * @ingroup cryptoThreads * * @description * Callback function for ECDSA verify operations ***************************************************************************/ void ecdsaSignOnlyPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("ECDSA Sign RS callback failed: status = %d\n", status); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } if (CPA_FALSE == multiplyStatus) { PRINT_ERR("ECDSA Sign RS multiply output failed\n"); pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } processCallback(pCallbackTag); } #ifdef POLL_INLINE static void processEcdsaCallback(void *pCallbackTag, CpaStatus status) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; /*check perf_data pointer is valid*/ if (pPerfData == NULL) { PRINT_ERR("Invalid data in CallbackTag\n"); return; } if (CPA_STATUS_SUCCESS != status) { pPerfData->threadReturnStatus = CPA_STATUS_FAIL; } /* response has been received */ pPerfData->responses++; } static void calcEcPointCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { processEcdsaCallback(pCallbackTag, status); } static void ecdsaSignRSCb(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean multiplyStatus, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { processEcdsaCallback(pCallbackTag, status); } #endif /*************************************************************************** * @ingroup cryptoThreads * * @description * get the relevant curve data for the test parameters passed in ***************************************************************************/ CpaStatus getCurveData(ecdsa_test_params_t *setup) { Cpa32U i = 0; Cpa32U numCurves = sizeof(curves_g) / sizeof(ec_curves_t); /*loop through the pre-defined curves and match on the nLenInBytes and the * fieldType than pass a pointer to the matched curve into the setup * structure*/ for (i = 0; i < numCurves; i++) { if (curves_g[i].nLenInBytes == setup->nLenInBytes && curves_g[i].fieldType == setup->fieldType) { break; } } if (i == numCurves) { PRINT_ERR("Could not find curve data for the user input supplied\n"); return CPA_STATUS_FAIL; } /*set the setup to the matched curve*/ setup->pCurve = &curves_g[i]; return CPA_STATUS_SUCCESS; } #define CALC_EC_POINT_MEM_FREE \ do \ { \ qaeMemFreeNUMA((void **)&opData.a.pData); \ qaeMemFreeNUMA((void **)&opData.b.pData); \ qaeMemFreeNUMA((void **)&opData.q.pData); \ qaeMemFreeNUMA((void **)&opData.xg.pData); \ qaeMemFreeNUMA((void **)&opData.yg.pData); \ } while (0) /*************************************************************************** * @ingroup cryptoThreads * * @description * Calculate a point on an Elliptic curve, using the curve in the setup * parameter and a given k, and place the calculated point in pXk and * pYk ***************************************************************************/ CpaStatus calcEcPoint(ecdsa_test_params_t *setup, CpaFlatBuffer *k, CpaFlatBuffer *pXk, CpaFlatBuffer *pYk) { CpaStatus status = CPA_STATUS_FAIL; CpaBoolean multiplyStatus = CPA_TRUE; CpaCyEcPointMultiplyOpData opData = {{0}}; Cpa32U retries = 0; perf_data_t *pPerfData = NULL; CpaCyEcPointMultiplyCbFunc cbFunc = NULL; #ifdef POLL_INLINE CpaInstanceInfo2 *instanceInfo2 = NULL; #endif /*allocate the operation data structure and copy in the elliptic curve * data*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pXk, setup->nLenInBytes, NULL, 0, CALC_EC_POINT_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pYk, setup->nLenInBytes, NULL, 0, CALC_EC_POINT_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(opData.a), setup->nLenInBytes, setup->pCurve->a, setup->pCurve->sizeOfa, CALC_EC_POINT_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(opData.b), setup->pCurve->sizeOfb, setup->pCurve->b, setup->pCurve->sizeOfb, CALC_EC_POINT_MEM_FREE); // displayHexArray("opData.b", opData.b.pData, // opData.b.dataLenInBytes); // // PRINT("opData.b.dataLenInBytes length = // %u\n",opData.b.dataLenInBytes); /* We copy p into q, the QA API uses q and NIST calls the same thing p*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(opData.q), setup->nLenInBytes, setup->pCurve->p, setup->pCurve->sizeOfp, CALC_EC_POINT_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(opData.xg), setup->nLenInBytes, setup->pCurve->xg, setup->pCurve->sizeOfxg, CALC_EC_POINT_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(opData.yg), setup->nLenInBytes, setup->pCurve->yg, setup->pCurve->sizeOfyg, CALC_EC_POINT_MEM_FREE); #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { cbFunc = calcEcPointCb; pPerfData = setup->performanceStats; pPerfData->numOperations = SINGLE_OPERATION; pPerfData->responses = 0; status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } } #endif /*make sure the private key is less than the modulus*/ makeParam1SmallerThanParam2( k->pData, opData.q.pData, k->dataLenInBytes, CPA_FALSE); opData.k.pData = k->pData; opData.k.dataLenInBytes = k->dataLenInBytes; /*set h param*/ opData.h.pData = NULL; opData.h.dataLenInBytes = 0; /*set fieldType*/ opData.fieldType = setup->fieldType; /*Calculate the point on the curve*/ do { status = cpaCyEcPointMultiply(setup->cyInstanceHandle, cbFunc, pPerfData, &opData, &multiplyStatus, pXk, pYk); if (CPA_STATUS_RETRY == status) { retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small break */ if (RETRY_LIMIT == (retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to perform cpaCyEcPointMultiply: status: %d\n", status); status = CPA_STATUS_FAIL; goto exit; } else { if (multiplyStatus == CPA_FALSE) { PRINT_ERR("cpaCyEcPointMultiply status is CPA_FALSE\n"); status = CPA_STATUS_FAIL; goto exit; } } exit: /*free the memory in the operation data structure*/ CALC_EC_POINT_MEM_FREE; #ifdef POLL_INLINE qaeMemFree((void **)&instanceInfo2); #endif return status; } EXPORT_SYMBOL(calcEcPoint); /*************************************************************************** * @ingroup cryptoThreads * * @description * Free any memory allocated in the ecdsaSignRS function ***************************************************************************/ #define ECDSA_SIGN_RS_OPDATA_MEM_FREE \ do \ { \ if (NULL != pSignRSOpData->a.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->a.pData); \ if (NULL != pSignRSOpData->b.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->b.pData); \ if (NULL != pSignRSOpData->k.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->k.pData); \ if (NULL != pSignRSOpData->n.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->n.pData); \ if (NULL != pSignRSOpData->q.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->q.pData); \ if (NULL != pSignRSOpData->xg.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->xg.pData); \ if (NULL != pSignRSOpData->yg.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->yg.pData); \ if (NULL != pSignRSOpData->d.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->d.pData); \ if (NULL != pSignRSOpData->m.pData) \ qaeMemFreeNUMA((void **)&pSignRSOpData->m.pData); \ if (NULL != pDigest->pData) \ qaeMemFreeNUMA((void **)&pDigest->pData); \ } while (0) #ifdef USER_SPACE #endif /* USER_SPACE */ CpaStatus ecdsaSignRSOpDataSetup(ecdsa_test_params_t *setup, CpaFlatBuffer *d, CpaFlatBuffer *r, CpaFlatBuffer *s, CpaFlatBuffer *message, CpaFlatBuffer *z, CpaFlatBuffer *pDigest, perf_data_t *pEcdsaData, CpaCyEcdsaSignRSOpData *pSignRSOpData) { CpaStatus status = CPA_STATUS_FAIL; CpaCyCapabilitiesInfo cap = {0}; /*allocate memory for a SHA512 digest*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDigest, SHA512_DIGEST_LENGTH_IN_BYTES, NULL, 0, ECDSA_SIGN_RS_OPDATA_MEM_FREE); /*allocate sign parameters*/ generateRandomData(message->pData, message->dataLenInBytes); /*Calculate the digest of the message*/ status = getCySpecificInstanceCapabilities(setup->cyInstanceHandle, &cap); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("getCyInstanceCapabilities failed with status: %d\n", status); return status; } if (cap.symSupported == CPA_FALSE) { if (msgFlagSym2 == CPA_FALSE) { PRINT( "ECDSA Warning! SYMMETRIC operation is not supported on Instance.\ Using calcSWDigest instead.\n"); msgFlagSym2 = CPA_TRUE; } status = calcSWDigest(message, pDigest, CPA_CY_SYM_HASH_SHA512); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("ECDSA Calc Digest Error hashAlg %u\n", CPA_CY_SYM_HASH_SHA512); } } else { status = calcDigest( setup->cyInstanceHandle, message, pDigest, CPA_CY_SYM_HASH_SHA512); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("ECDSA Calc Digest Error hashAlg %u\n", CPA_CY_SYM_HASH_SHA512); return status; } } /*copy left most Bytes of digest into z parameter, the length should * be equal or less than SHA512_DIGEST_LENGTH_IN_BYTES*/ memcpy(z->pData, pDigest->pData, z->dataLenInBytes); /*set the opData parameters for signing the message*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->a), setup->nLenInBytes, setup->pCurve->a, setup->pCurve->sizeOfa, ECDSA_SIGN_RS_OPDATA_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->b), setup->nLenInBytes, setup->pCurve->b, setup->pCurve->sizeOfb, ECDSA_SIGN_RS_OPDATA_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->k), setup->nLenInBytes, NULL, 0, ECDSA_SIGN_RS_OPDATA_MEM_FREE); generateRandomData(pSignRSOpData->k.pData, pSignRSOpData->k.dataLenInBytes); /*k is a value >0 and < the order of the base point*/ makeParam1SmallerThanParam2(pSignRSOpData->k.pData, setup->pCurve->r, pSignRSOpData->k.dataLenInBytes, CPA_FALSE); /* we copy r into n, the QA API uses the parameter n as the order of the * base point, the NIST definition of the same is r*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->n), setup->nLenInBytes, setup->pCurve->r, setup->pCurve->sizeOfr, ECDSA_SIGN_RS_OPDATA_MEM_FREE); /* We copy p into q, the QA API uses q and NIST calls the same thing p*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->q), setup->nLenInBytes, setup->pCurve->p, setup->pCurve->sizeOfp, ECDSA_SIGN_RS_OPDATA_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->xg), setup->nLenInBytes, setup->pCurve->xg, setup->pCurve->sizeOfxg, ECDSA_SIGN_RS_OPDATA_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->yg), setup->nLenInBytes, setup->pCurve->yg, setup->pCurve->sizeOfyg, ECDSA_SIGN_RS_OPDATA_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->d), d->dataLenInBytes, d->pData, d->dataLenInBytes, ECDSA_SIGN_RS_OPDATA_MEM_FREE); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pSignRSOpData->m), z->dataLenInBytes, z->pData, z->dataLenInBytes, ECDSA_SIGN_RS_OPDATA_MEM_FREE); pSignRSOpData->fieldType = setup->fieldType; return status; } EXPORT_SYMBOL(ecdsaSignRSOpDataSetup); /*************************************************************************** * @ingroup cryptoThreads * * @description * Sign the digest of a random message using elliptic curve data in setup * parameter ***************************************************************************/ static CpaStatus ecdsaSignRS(ecdsa_test_params_t *setup, CpaFlatBuffer *d, CpaFlatBuffer *r, CpaFlatBuffer *s, CpaFlatBuffer *message, CpaFlatBuffer *z, CpaCyEcdsaSignRSCbFunc cbFunc, perf_data_t *pEcdsaData) { CpaStatus status = CPA_STATUS_FAIL; CpaBoolean signStatus = CPA_FALSE; Cpa32U node = 0; CpaCyEcdsaSignRSOpData *pSignRSOpData = NULL; CpaFlatBuffer *pDigest = NULL; Cpa32U retries = 0; perf_data_t *pPerfData = NULL; CpaCyEcdsaSignRSCbFunc signRSCbFunc = NULL; CpaInstanceInfo2 *instanceInfo2 = NULL; #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED CpaCyKptEcdsaSignRSOpData *pKPTSignRSOpData = NULL; CpaCyKptUnwrapContext *pKptUnwrapCtx = NULL; Cpa32U keyProvisionRetryTimes = 0; /*SWK*/ Cpa8U sampleSWK[SWK_LEN_IN_BYTES] = {0}; Cpa8U iv[IV_LEN_IN_BYTES] = {0}; CpaStatus delKeyStatus = CPA_STATUS_SUCCESS; CpaCyKptKeyManagementStatus kpt2Status = CPA_CY_KPT_SUCCESS; Cpa8U kpt2Ecdsa_AAD_P256[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}; Cpa8U kpt2Ecdsa_AAD_P384[] = {0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22}; Cpa8U kpt2Ecdsa_AAD_P521[] = {0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23}; #endif #endif #endif #ifdef POLL_INLINE CpaBoolean isPolled = CPA_FALSE; if (poll_inline_g) { pPerfData = setup->performanceStats; signRSCbFunc = ecdsaSignRSCb; pPerfData->numOperations = SINGLE_OPERATION; pPerfData->responses = 0; } #endif status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return status; } instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } if (instanceInfo2->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo2->physInstId.packageId; } #ifdef POLL_INLINE isPolled = instanceInfo2->isPolled; #endif qaeMemFree((void **)&instanceInfo2); pSignRSOpData = qaeMemAlloc(sizeof(CpaCyEcdsaSignRSOpData)); if (NULL == pSignRSOpData) { PRINT_ERR("Cannot allocate memory for CpaCyEcdsaSignRSOpData\n"); return CPA_STATUS_FAIL; } pDigest = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pDigest) { PRINT_ERR("Cannot allocate memory for CpaCyEcdsaSignRSOpData\n"); qaeMemFree((void **)&pSignRSOpData); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != ecdsaSignRSOpDataSetup( setup, d, r, s, message, z, pDigest, pEcdsaData, pSignRSOpData)) { PRINT_ERR("ecdsaSignRSOpDataSetup error, status: %d\n", status); qaeMemFree((void **)&(pSignRSOpData)); qaeMemFree((void **)&(pDigest)); return CPA_STATUS_FAIL; } /*perform the sign operation*/ do { #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == setup->enableKPT) { generateRandomData(sampleSWK, SWK_LEN_IN_BYTES); generateRandomData(iv, IV_LEN_IN_BYTES); pKPTSignRSOpData = qaeMemAllocNUMA( sizeof(CpaCyKptEcdsaSignRSOpData), node, BYTE_ALIGNMENT_64); if (NULL == pKPTSignRSOpData) { PRINT_ERR("pKPTSignRSOpData qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } pKptUnwrapCtx = qaeMemAllocNUMA( sizeof(CpaCyKptUnwrapContext), node, BYTE_ALIGNMENT_64); if (NULL == pKptUnwrapCtx) { PRINT_ERR("pKptUnwrapCtx qaeMemAlloc error\n"); kpt2EcdsaFreeDataMemory(pKPTSignRSOpData, pKptUnwrapCtx); return CPA_STATUS_FAIL; } status = encryptAndLoadSWK( setup->cyInstanceHandle, &setup->kptKeyHandle, sampleSWK); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("encryptAndLoadSWKs failed!\n"); kpt2EcdsaFreeDataMemory(pKPTSignRSOpData, pKptUnwrapCtx); return status; } pKptUnwrapCtx->kptHandle = setup->kptKeyHandle; memcpy(pKptUnwrapCtx->iv, iv, IV_LEN_IN_BYTES); switch (setup->nLenInBytes) { case GFP_P256_SIZE_IN_BYTES: memcpy(pKptUnwrapCtx->additionalAuthData, kpt2Ecdsa_AAD_P256, sizeof(kpt2Ecdsa_AAD_P256)); pKptUnwrapCtx->aadLenInBytes = sizeof(kpt2Ecdsa_AAD_P256); break; case GFP_P384_SIZE_IN_BYTES: memcpy(pKptUnwrapCtx->additionalAuthData, kpt2Ecdsa_AAD_P384, sizeof(kpt2Ecdsa_AAD_P384)); pKptUnwrapCtx->aadLenInBytes = sizeof(kpt2Ecdsa_AAD_P384); break; case GFP_P521_SIZE_IN_BYTES: memcpy(pKptUnwrapCtx->additionalAuthData, kpt2Ecdsa_AAD_P521, sizeof(kpt2Ecdsa_AAD_P521)); pKptUnwrapCtx->aadLenInBytes = sizeof(kpt2Ecdsa_AAD_P521); break; default: PRINT_ERR("Curve size(%d) not supported by kpt!\n", setup->nLenInBytes); kpt2EcdsaFreeDataMemory(pKPTSignRSOpData, pKptUnwrapCtx); return CPA_STATUS_FAIL; } status = setKPT2EcdsaSignRSOpData(setup->cyInstanceHandle, pKPTSignRSOpData, pSignRSOpData, sampleSWK, iv, pKptUnwrapCtx->additionalAuthData, pKptUnwrapCtx->aadLenInBytes); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("setKPTEcdsaSignRSOpData failed!\n"); kpt2EcdsaFreeDataMemory(pKPTSignRSOpData, pKptUnwrapCtx); return status; } status = cpaCyKptEcdsaSignRS(setup->cyInstanceHandle, signRSCbFunc, pPerfData, pKPTSignRSOpData, &signStatus, r, s, pKptUnwrapCtx); } else { #endif #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #endif status = cpaCyEcdsaSignRS(setup->cyInstanceHandle, signRSCbFunc, pPerfData, pSignRSOpData, &signStatus, r, s); #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED } #endif #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #endif if (CPA_STATUS_RETRY == status) { retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small break */ if (RETRY_LIMIT == (retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to sign message, status: %d\n", status); ECDSA_SIGN_RS_OPDATA_MEM_FREE; qaeMemFree((void **)&pSignRSOpData); qaeMemFree((void **)&(pDigest)); #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED cpaCyKptDeleteKey( setup->cyInstanceHandle, setup->kptKeyHandle, &kpt2Status); kpt2EcdsaFreeDataMemory(pKPTSignRSOpData, pKptUnwrapCtx); #endif #endif #endif return status; } else { /*if(signStatus != CPA_TRUE) { PRINT_ERR("Unable to sign message\n"); ECDSA_SIGN_RS_OPDATA_MEM_FREE; return CPA_STATUS_FAIL; }*/ } /*free the memory for the operation data and the digest...we save the * message for the verification part*/ ECDSA_SIGN_RS_OPDATA_MEM_FREE; qaeMemFree((void **)&pSignRSOpData); qaeMemFree((void **)&(pDigest)); #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == setup->enableKPT) { do { delKeyStatus = cpaCyKptDeleteKey( setup->cyInstanceHandle, setup->kptKeyHandle, &kpt2Status); usleep(KEY_PROVISION_RETRY_DELAY_MS * 1000); keyProvisionRetryTimes++; } while ((CPA_STATUS_RETRY == delKeyStatus) && (keyProvisionRetryTimes <= KEY_PROVISION_RETRY_TIMES_LIMIT)); if (1 < keyProvisionRetryTimes) { PRINT("KPT ECSDA Delete SWK Retry Times : %d\n", keyProvisionRetryTimes - 1); } if ((CPA_STATUS_SUCCESS != delKeyStatus) || (CPA_CY_KPT_SUCCESS != kpt2Status)) { PRINT_ERR("Delete SWK failed with status: %d,kpt2Status: %d.\n", delKeyStatus, kpt2Status); status = CPA_STATUS_FAIL; } kpt2EcdsaFreeDataMemory(pKPTSignRSOpData, pKptUnwrapCtx); } #endif #endif #endif return status; } #define ECDSA_PERFORM_MEM_FREE() \ do \ { \ ecdsaMemFree(setup, pX, pY, pR, pS, msg, pZ, ppOpData, privateKey); \ } while (0) static void ecdsaMemFree(ecdsa_test_params_t *setup, CpaFlatBuffer *pX, CpaFlatBuffer *pY, CpaFlatBuffer *pR, CpaFlatBuffer *pS, CpaFlatBuffer *msg, CpaFlatBuffer *pZ, CpaCyEcdsaVerifyOpData **ppOpData, CpaFlatBuffer privateKey) { Cpa32U k = 0; /*free verify opData*/ if (NULL != ppOpData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != ppOpData[k]) { qaeMemFreeNUMA((void **)&ppOpData[k]->yp.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->xp.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->yg.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->xg.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->s.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->r.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->q.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->n.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->m.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->a.pData); qaeMemFreeNUMA((void **)&ppOpData[k]->b.pData); qaeMemFree((void **)&ppOpData[k]); } qaeMemFreeNUMA((void **)&pR[k].pData); qaeMemFreeNUMA((void **)&pS[k].pData); qaeMemFreeNUMA((void **)&msg[k].pData); qaeMemFreeNUMA((void **)&pZ[k].pData); } } /* free all memory */ if (NULL != pX && NULL != pX->pData) { qaeMemFreeNUMA((void **)&pX->pData); } if (NULL != pY && NULL != pY->pData) { qaeMemFreeNUMA((void **)&pY->pData); } qaeMemFree((void **)&pX); qaeMemFree((void **)&pY); qaeMemFree((void **)&pR); qaeMemFree((void **)&pS); qaeMemFree((void **)&msg); qaeMemFree((void **)&pZ); if (NULL != ppOpData) { qaeMemFree((void **)&ppOpData); } qaeMemFreeNUMA((void **)&privateKey.pData); } #define ECDSA_PERFORM_RS_ONLY_MEM_FREE() \ do \ { \ ecdsaPerformRsOnlyMemFree(setup, \ pX, \ pY, \ pR, \ pS, \ msg, \ pZ, \ ppDigests, \ ppSignRSOpData, \ NULL, \ privateKey); \ } while (0) #define ECDSA_PERFORM_POINT_MULTIPLY_MEM_FREE() \ do \ { \ ecdsaPerformRsOnlyMemFree(setup, \ pX, \ pY, \ pR, \ pS, \ msg, \ pZ, \ ppDigests, \ ppSignRSOpData, \ ppPointMultiplyOpData, \ privateKey); \ } while (0) void ecdsaPerformRsOnlyMemFree( ecdsa_test_params_t *setup, CpaFlatBuffer *pX, CpaFlatBuffer *pY, CpaFlatBuffer *pR, CpaFlatBuffer *pS, CpaFlatBuffer *msg, CpaFlatBuffer *pZ, CpaFlatBuffer **ppDigests, CpaCyEcdsaSignRSOpData **ppSignRSOpData, CpaCyEcPointMultiplyOpData **ppPointMultiplyOpData, CpaFlatBuffer privateKey) { Cpa32U k = 0; for (k = 0; k < setup->numBuffers; k++) { if (NULL != ppDigests && NULL != ppDigests[k]) { if (NULL != ppDigests[k]->pData) { qaeMemFreeNUMA((void **)&ppDigests[k]->pData); } qaeMemFree((void **)&ppDigests[k]); } if (NULL != pX && NULL != pX[k].pData) { qaeMemFreeNUMA((void **)&pX[k].pData); } if (NULL != pY && NULL != pY[k].pData) { qaeMemFreeNUMA((void **)&pY[k].pData); } if (NULL != pR && NULL != pR[k].pData) { qaeMemFreeNUMA((void **)&pR[k].pData); } if (NULL != pS && NULL != pS[k].pData) { qaeMemFreeNUMA((void **)&pS[k].pData); } if (NULL != msg && NULL != msg[k].pData) { qaeMemFreeNUMA((void **)&msg[k].pData); } if (NULL != pZ && NULL != pZ[k].pData) { qaeMemFreeNUMA((void **)&pZ[k].pData); } if (NULL != ppSignRSOpData && NULL != ppSignRSOpData[k]) { if (NULL != ppSignRSOpData[k]->a.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->a.pData); } if (NULL != ppSignRSOpData[k]->b.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->b.pData); } if (NULL != ppSignRSOpData[k]->k.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->k.pData); } if (NULL != ppSignRSOpData[k]->n.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->n.pData); } if (NULL != ppSignRSOpData[k]->q.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->q.pData); } if (NULL != ppSignRSOpData[k]->xg.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->xg.pData); } if (NULL != ppSignRSOpData[k]->yg.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->yg.pData); } if (NULL != ppSignRSOpData[k]->d.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->d.pData); } if (NULL != ppSignRSOpData[k]->m.pData) { qaeMemFreeNUMA((void **)&ppSignRSOpData[k]->m.pData); } qaeMemFree((void **)&ppSignRSOpData[k]); } if (NULL != ppPointMultiplyOpData && NULL != ppPointMultiplyOpData[k]) { if (NULL != ppPointMultiplyOpData[k]->a.pData) { qaeMemFreeNUMA((void **)&ppPointMultiplyOpData[k]->a.pData); } if (NULL != ppPointMultiplyOpData[k]->b.pData) { qaeMemFreeNUMA((void **)&ppPointMultiplyOpData[k]->b.pData); } if (NULL != ppPointMultiplyOpData[k]->q.pData) { qaeMemFreeNUMA((void **)&ppPointMultiplyOpData[k]->q.pData); } if (NULL != ppPointMultiplyOpData[k]->xg.pData) { qaeMemFreeNUMA((void **)&ppPointMultiplyOpData[k]->xg.pData); } if (NULL != ppPointMultiplyOpData[k]->yg.pData) { qaeMemFreeNUMA((void **)&ppPointMultiplyOpData[k]->yg.pData); } qaeMemFree((void **)&ppPointMultiplyOpData[k]); } } if (NULL != pX) { qaeMemFree((void **)&pX); } if (NULL != pY) { qaeMemFree((void **)&pY); } if (NULL != pR) { qaeMemFree((void **)&pR); } if (NULL != pS) { qaeMemFree((void **)&pS); } if (NULL != msg) { qaeMemFree((void **)&msg); } if (NULL != pZ) { qaeMemFree((void **)&pZ); } if (NULL != ppDigests) { qaeMemFree((void **)&ppDigests); } if (NULL != ppSignRSOpData) { qaeMemFree((void(**)) & ppSignRSOpData); } if (NULL != ppPointMultiplyOpData) { qaeMemFree((void(**)) & ppPointMultiplyOpData); } if (NULL != privateKey.pData) { qaeMemFreeNUMA((void **)&privateKey.pData); } } /*************************************************************************** * @ingroup cryptoThreads * * @description * setup a number of buffers to be signed by ECDSA then verified using * EC curve data ***************************************************************************/ CpaStatus ecdsaPerform(ecdsa_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; CpaBoolean verifyStatus; CpaCyEcdsaStats64 ecdsaStats; CpaStatus status = CPA_STATUS_FAIL; /*pointer to Elliptic curve public key points*/ CpaFlatBuffer *pX = NULL; CpaFlatBuffer *pY = NULL; /*array of pointers to Signature R & S of the messages below*/ CpaFlatBuffer *pR = NULL; CpaFlatBuffer *pS = NULL; /*array of pointers to messages to be signed*/ CpaFlatBuffer *msg = NULL; /*array of pointers to store digest of the above messages*/ CpaFlatBuffer *pZ = NULL; /*private key used for all messages and to generate public key*/ CpaFlatBuffer privateKey = {.dataLenInBytes = 0, .pData = NULL}; /*array of pointers to the operation data structure for each verify * operation*/ CpaCyEcdsaVerifyOpData **ppOpData = NULL; /*variable to store what cpu thread is running on*/ Cpa32U node = 0; /*pointer to location to store performance data*/ perf_data_t *pEcdsaData = NULL; CpaInstanceInfo2 *instanceInfo = NULL; CpaCyEcdsaVerifyCbFunc cbFunc = NULL; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_FAIL; perf_data_t *pPerfData = setup->performanceStats; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; #endif #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED CpaCyCapabilitiesInfo pCapInfo = {0}; #endif #endif DECLARE_IA_CYCLE_COUNT_VARIABLES(); instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); goto barrier; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); goto barrier; } #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == setup->enableKPT) { status = cpaCyQueryCapabilities(setup->cyInstanceHandle, &pCapInfo); if ((CPA_STATUS_SUCCESS == status) && !pCapInfo.kptSupported) { PRINT_ERR( "Inst (BDF:%02x:%02d.%d) does not support KPT2!\n", (Cpa8U)(instanceInfo->physInstId.busAddress >> 8), (Cpa8U)((instanceInfo->physInstId.busAddress & 0xFF) >> 3), (Cpa8U)(instanceInfo->physInstId.busAddress & 7)); sampleCodeBarrier(); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_SUCCESS; } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyQueryCapabilities failed!\n"); sampleCodeBarrier(); qaeMemFree((void **)&instanceInfo); return status; } } #endif #endif status = cpaCyEcdsaQueryStats64(setup->cyInstanceHandle, &ecdsaStats); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Could not retrieve stats, error status %d\n", status); } /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); goto barrier; } /*get the curve data based on the test setup*/ status = getCurveData(setup); if (CPA_STATUS_SUCCESS != status) { /*any error is printed in the getCurveData function*/ goto barrier; } /*get memory location to write performance stats to*/ pEcdsaData = setup->performanceStats; /*get the number of operations to be done in this test*/ pEcdsaData->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; pEcdsaData->responses = 0; coo_init(pEcdsaData, pEcdsaData->numOperations); /* Initialize semaphore used in callback */ sampleCodeSemaphoreInit(&pEcdsaData->comp, 0); /*allocate memory to store public key points*/ pX = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pX) { PRINT_ERR("pY mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } memset(pX, 0, sizeof(CpaFlatBuffer)); pY = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pY) { PRINT_ERR("pY mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } memset(pY, 0, sizeof(CpaFlatBuffer)); privateKey.pData = qaeMemAllocNUMA(setup->nLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == privateKey.pData) { PRINT_ERR("privateKey pData mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } privateKey.dataLenInBytes = setup->nLenInBytes; /*generate a random private key*/ generateRandomData(privateKey.pData, privateKey.dataLenInBytes); makeParam1SmallerThanParam2( privateKey.pData, setup->pCurve->r, setup->nLenInBytes, CPA_FALSE); /*allocate memory for array of signatures, messages, digests and opData*/ pR = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == pR) { PRINT_ERR("pR mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } pS = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == pS) { PRINT_ERR("pS mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } msg = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == msg) { PRINT_ERR("msg mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } pZ = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == pZ) { PRINT_ERR("pZ mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } /*calculate the public key p(X,Y) points*/ status = calcEcPoint(setup, &privateKey, pX, pY); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("calcEcPoint fails with status %d\n", status); ECDSA_PERFORM_MEM_FREE(); goto barrier; } /*for each buffer: * generate a random message * calculate the digest * sign the digest of the message with R&S*/ for (i = 0; i < setup->numBuffers; i++) { /*allocate the pointers within the array of pointers*/ /*allocate the pData for each CpaFlatBuffer*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pR[i], setup->nLenInBytes, NULL, 0, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pS[i], setup->nLenInBytes, NULL, 0, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &msg[i], setup->nLenInBytes, NULL, 0, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pZ[i], setup->nLenInBytes, NULL, 0, ECDSA_PERFORM_MEM_FREE()); /*sign the message (the message is populated within the ecdsaSignRS * function with random data*/ status = ecdsaSignRS( setup, &privateKey, &pR[i], &pS[i], &msg[i], &pZ[i], NULL, NULL); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("ecdsaSignRS error %d\n", status); ECDSA_PERFORM_MEM_FREE(); goto barrier; } } /*verify the signatures to the messages*/ status = allocArrayOfVirtPointers((void **)&ppOpData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("ppOpData mem allocation error\n"); ECDSA_PERFORM_MEM_FREE(); goto barrier; } /*allocate and populate all the verifyOpData buffers*/ for (i = 0; i < setup->numBuffers; i++) { ppOpData[i] = qaeMemAlloc(sizeof(CpaCyEcdsaVerifyOpData)); if (NULL == ppOpData[i]) { PRINT_ERR("ppOpData[%u] memory allocation error\n", i); ECDSA_PERFORM_MEM_FREE(); status = CPA_STATUS_FAIL; goto barrier; } memset(ppOpData[i], 0, sizeof(CpaCyEcdsaVerifyOpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->a, setup->nLenInBytes, setup->pCurve->a, setup->pCurve->sizeOfa, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->b, setup->nLenInBytes, setup->pCurve->b, setup->pCurve->sizeOfb, ECDSA_PERFORM_MEM_FREE()); ppOpData[i]->fieldType = setup->fieldType; /*m pZ contains the digest of msg*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->m, setup->nLenInBytes, pZ[i].pData, pZ[i].dataLenInBytes, ECDSA_PERFORM_MEM_FREE()); /*http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf: * Any point of order r can serve as the base point * QA-API uses n value to describe base point*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->n, setup->nLenInBytes, setup->pCurve->r, setup->pCurve->sizeOfr, ECDSA_PERFORM_MEM_FREE()); /*http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf: * use p for either prime modulus for GFP or polynomial for GF2 * QA API uses q for the same*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->q, setup->nLenInBytes, setup->pCurve->p, setup->pCurve->sizeOfp, ECDSA_PERFORM_MEM_FREE()); /*r is part of the RS signature*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->r, setup->nLenInBytes, pR[i].pData, pR[i].dataLenInBytes, ECDSA_PERFORM_MEM_FREE()); /*s is part of the RS signature*/ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->s, setup->nLenInBytes, pS[i].pData, pS[i].dataLenInBytes, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->xg, setup->nLenInBytes, setup->pCurve->xg, setup->pCurve->sizeOfxg, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->yg, setup->nLenInBytes, setup->pCurve->yg, setup->pCurve->sizeOfyg, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->xp, setup->nLenInBytes, pX->pData, pX->dataLenInBytes, ECDSA_PERFORM_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &ppOpData[i]->yp, setup->nLenInBytes, pY->pData, pY->dataLenInBytes, ECDSA_PERFORM_MEM_FREE()); } /*this barrier will wait until all threads get to this point*/ /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = ecdsaPerformCallback; } pEcdsaData->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; pEcdsaData->responses = 0; barrier: sampleCodeBarrier(); /* exiting the function if any failure occurs in previous steps*/ if (CPA_STATUS_SUCCESS != status) { setup->performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&instanceInfo); return status; } /*record the start time, the callback measures the end time when the last * response is received*/ pEcdsaData->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { for (i = 0; i < setup->numBuffers; i++) { do { coo_req_start(pEcdsaData); status = cpaCyEcdsaVerify(setup->cyInstanceHandle, cbFunc, pEcdsaData, ppOpData[i], &verifyStatus); coo_req_stop(pEcdsaData, status); if (CPA_STATUS_RETRY == status) { #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo->isPolled) { sampleCodeAsymPollInstance(setup->cyInstanceHandle, 0); nextPoll = numOps + asymPollingInterval_g; } } #endif pEcdsaData->retries++; /*if the acceleration engine is busy pause for a * moment by making a context switch*/ if (RETRY_LIMIT == (pEcdsaData->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { BUSY_LOOP(); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("ECDSA Verify function failed with status:%d\n", status); ECDSA_PERFORM_MEM_FREE(); qaeMemFree((void **)&instanceInfo); return status; } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy( pEcdsaData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } } #endif if (ASYNC != setup->syncMode) { if (CPA_TRUE != verifyStatus) { PRINT_ERR("ECDSA Verify function verification failed " "but status = %d\n", status); status = CPA_STATUS_FAIL; } /*else { PRINT_ERR("ECDSA Verify function verification " "succeeded\n"); }*/ } } /*end buffers loop */ } /* end of numLoops loop*/ #ifdef POLL_INLINE if (poll_inline_g) { if ((instanceInfo->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pEcdsaData, setup->cyInstanceHandle, pEcdsaData->numOperations); } } #endif if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pEcdsaData, setup->syncMode, setup->numBuffers, setup->numLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Thread %u timeout. ", setup->threadID); } } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { IA_CYCLE_COUNT_CALCULATION(); } coo_average(pEcdsaData); coo_deinit(pEcdsaData); sampleCodeSemaphoreDestroy(&pEcdsaData->comp); /*Free all memory*/ ECDSA_PERFORM_MEM_FREE(); qaeMemFree((void **)&instanceInfo); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } EXPORT_SYMBOL(ecdsaPerform); /*************************************************************************** * @ingroup cryptoThreads * * @description * Print the performance stats of the elliptic curve dsa operations ***************************************************************************/ static CpaStatus ecdsaPrintStats(thread_creation_data_t *data) { ecdsa_test_params_t *params = (ecdsa_test_params_t *)data->setupPtr; if (ECDSA_STEP_SIGNRS == params->step) { #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == params->enableKPT) { PRINT("KPT2 ECDSA SIGNRS\n"); } else { PRINT("ECDSA SIGNRS\n"); } #else PRINT("ECDSA SIGNRS\n"); #endif #else PRINT("ECDSA SIGNRS\n"); #endif } else if (ECDSA_STEP_VERIFY == params->step) { #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == params->enableKPT) { PRINT("KPT2 ECDSA VERIFY\n"); } else { PRINT("ECDSA VERIFY\n"); } #else PRINT("ECDSA VERIFY\n"); #endif #else PRINT("ECDSA VERIFY\n"); #endif } else if (ECDSA_STEP_POINT_MULTIPLY == params->step) { PRINT("ECDSA POINT MULTIPLY\n"); } PRINT("EC Size %23u\n", data->packetSize); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /*************************************************************************** * @ingroup cryptoThreads * * @description * setup an elliptic curve performance thread ***************************************************************************/ void ecdsaPerformance(single_thread_test_data_t *testSetup) { ecdsa_test_params_t ecdsaSetup = {0}; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; ecdsa_test_params_t *params = (ecdsa_test_params_t *)testSetup->setupPtr; CpaInstanceInfo2 *instanceInfo = NULL; #ifdef SC_DEV_INFO_ENABLED CpaDeviceInfo deviceInfo = {0}; #endif testSetup->passCriteria = getPassCriteria(); /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call * startThreads anyway*/ startBarrier(); /* * In case of error scenario, the thread will exit early. * register the print function here itself to properly exit with statistics. */ testSetup->statsPrintFunc = (stats_print_func_t)ecdsaPrintStats; /*give our thread a unique memory location to store performance stats*/ ecdsaSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); ecdsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); ecdsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); ecdsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /* give our thread a logical crypto instance to use * use % to wrap around the max number of instances*/ ecdsaSetup.cyInstanceHandle = cyInstances[(testSetup->logicalQaInstance) % numInstances]; instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); qaeMemFree((void **)&cyInstances); return; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(ecdsaSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); ecdsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } #ifdef SC_DEV_INFO_ENABLED /* check whether asym service enabled or not for the instance */ status = cpaGetDeviceInfo(instanceInfo->physInstId.acceleratorId, &deviceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaGetDeviceInfo failed", __func__, __LINE__); ecdsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } if (CPA_FALSE == deviceInfo.cyAsymEnabled) { PRINT_ERR("%s::%d Error! cyAsymEnabled service not enabled for the " "configured instance\n", __func__, __LINE__); ecdsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } #endif if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } memset(ecdsaSetup.performanceStats, 0, sizeof(perf_data_t)); ecdsaSetup.performanceStats->packageId = instanceInfo->physInstId.packageId; ecdsaSetup.threadID = testSetup->threadID; ecdsaSetup.nLenInBytes = params->nLenInBytes; ecdsaSetup.fieldType = params->fieldType; ecdsaSetup.numBuffers = params->numBuffers; ecdsaSetup.numLoops = params->numLoops; ecdsaSetup.syncMode = params->syncMode; #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED ecdsaSetup.enableKPT = params->enableKPT; #endif #endif /*launch function that does all the work*/ switch (params->step) { case (ECDSA_STEP_VERIFY): status = ecdsaPerform(&ecdsaSetup); break; default: PRINT_ERR("Function not supported for step %d\n", params->step); status = CPA_STATUS_FAIL; break; } if (CPA_STATUS_SUCCESS != status) { #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == params->enableKPT) { PRINT("KPT2 ECDSA Thread %u FAILED\n", testSetup->threadID); } else { #endif #endif PRINT("ECDSA Thread %u FAILED\n", testSetup->threadID); #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED } #endif #endif ecdsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadComplete(testSetup->threadID); } EXPORT_SYMBOL(ecdsaPerformance); /*************************************************************************** * @ingroup cryptoThreads * * @description * This function is used to set the parameters to be used in the elliptic * curve performance thread. It is called before the createThreads * function of the framework. The framework replicates it across many * cores ***************************************************************************/ CpaStatus setupEcdsaTest(Cpa32U nLenInBits, CpaCyEcFieldType fieldType, sync_mode_t syncMode, ecdsa_step_t step, Cpa32U numBuffers, Cpa32U numLoops) { /* testSetupData_g is a multi-dimensional array that stores the setup for * all thread variations in an array of characters. we store our test setup * at the start of the second array ie index 0. There maybe multi thread * types (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure*/ ecdsa_test_params_t *ecdsaSetup = NULL; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } if (iaCycleCount_g) { #ifdef POLL_INLINE enablePollInline(); #endif timeStampTime_g = getTimeStampTime(); PRINT("timeStampTime_g %llu\n", timeStampTime_g); } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } ecdsaSetup = (ecdsa_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)ecdsaPerformance; testSetupData_g[testTypeCount_g].packetSize = nLenInBits; /*if nLenInBits is not an even number of bytes then round up * ecdsaSetup->nLenInBytes*/ ecdsaSetup->nLenInBytes = (nLenInBits + NUM_BITS_IN_BYTE - 1) / NUM_BITS_IN_BYTE; ecdsaSetup->fieldType = fieldType; ecdsaSetup->syncMode = syncMode; ecdsaSetup->numBuffers = numBuffers; ecdsaSetup->numLoops = numLoops; ecdsaSetup->step = step; return CPA_STATUS_SUCCESS; } cpa_sample_code_ike_dsa_perf.c000066400000000000000000002310151503624047500366650ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_ike_dsa_perf.c * * @ingroup cryptoThreads * * @description * This file contains code which chains QA API functions together to * simulate IKE, over all flow of data is as follows: * * 1. Alice & Bob generate public & private DSA keys * we generated a third DSA key set to act as a trusted third party * 2. Alice & Bob agree on a p & g and generate secret random x * 3. Alice & Bob Perform DH Phase1 to produce Public Value - PV = g^x mod p * 4. Bob Perform DH Phase2 to produce Secret Key SK = alicePV^x mod p * 5. Sign Bobs Public Value using peers public key -> DSA decrypt bobsPV * 6. Setup Alices Decrypt and Diffie Hellman Data for performance Loop * 7. IKE main mode Asymmetric steps * 7a Perform DH phase1 for Alice alicePV = g^x mod p * 7b Perform DSA verify of third party: bobsPV = DSA encrypt bobsSig * 7c Perform DSA verify of Bobs signed public values (same as 7b) * 7d Sign all of Alices public value buffers DSA decrypt alicesPV * 7e Perform the DH phase2 operation for Alice * SK = bobsPV(from 7b)^x mod p * *****************************************************************************/ #include "cpa_cy_dsa.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_utils_common.h" /*This is the number of DSA and Diffie Hellman QA APIs chained together in * which performance is measured against*/ #define NUMBER_OF_CHAINED_OPS (5) #define ONE_LOOP (1) #define ONE_BUFFER (1) #define NUMBER_OF_RSA_VERIFIES (2) #define IKEDSA_DEFAULT_H_VALUE (2) extern void dsaGenRandom(CpaFlatBuffer *dsaRand, CpaFlatBuffer *dsaQ); extern CpaStatus dsaGenG(CpaInstanceHandle instanceHandle, CpaCyDsaGParamGenOpData *gOpData, CpaFlatBuffer *dsaG); extern CpaStatus dsaGenY(CpaInstanceHandle instanceHandle, CpaCyDsaYParamGenOpData *yOpData, CpaFlatBuffer *dsaY); extern CpaStatus dsaGenRS(CpaInstanceHandle instanceHandle, CpaCyDsaRSSignOpData *rsOpData, CpaFlatBuffer *dsaR, CpaFlatBuffer *dsaS); CpaStatus dsaGenZ(CpaInstanceHandle instanceHandle, CpaFlatBuffer *msg, CpaCySymHashAlgorithm hashAlg, CpaFlatBuffer *dsaZ); CpaStatus setupIkeDsaTest(Cpa32U pLenInBits, Cpa32U qLenInBits, sync_mode_t syncMode, Cpa32U numBuffs, Cpa32U numLoops); void ikeDsaCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut); void ikeDsaPerformance(single_thread_test_data_t *testSetup); /***************************************************************** * Declare a static 1024/160 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U ikedsa_1024_160_p[] = { 0xEA, 0xE2, 0xE2, 0x08, 0xBC, 0x34, 0x79, 0xAF, 0x6C, 0xD9, 0x90, 0xC8, 0xB6, 0x17, 0x0D, 0x33, 0x31, 0xDF, 0x22, 0xBB, 0x2D, 0x54, 0x64, 0x76, 0x98, 0xD5, 0x5A, 0x53, 0xE1, 0x14, 0xBE, 0x73, 0xDA, 0x89, 0xC6, 0x2D, 0x39, 0x00, 0x69, 0xA5, 0x42, 0x14, 0x90, 0x7E, 0x2F, 0x67, 0x31, 0xF0, 0xC2, 0x4B, 0xAC, 0x7E, 0x4C, 0xCF, 0xE9, 0x48, 0xFD, 0x67, 0xD8, 0x5E, 0x6B, 0x08, 0x65, 0x55, 0x56, 0xE0, 0xB3, 0xDE, 0x62, 0x23, 0xE2, 0xCF, 0x85, 0x9E, 0x6E, 0x4D, 0x07, 0xC2, 0x95, 0xAA, 0x46, 0x1C, 0xE5, 0xE5, 0x97, 0x1F, 0x97, 0x67, 0xAC, 0x6B, 0xAB, 0x39, 0x87, 0x17, 0x66, 0x92, 0x67, 0xC1, 0x97, 0x13, 0x3F, 0xF1, 0xB3, 0x98, 0x1B, 0x73, 0x09, 0x6D, 0x58, 0x25, 0xA5, 0xEF, 0x71, 0x93, 0x99, 0x8F, 0xB0, 0x81, 0x23, 0x48, 0xAF, 0xD9, 0x3A, 0xDB, 0xDB, 0x03, 0x0E, 0xFB}; static Cpa8U ikedsa_1024_160_q[] = {0x9D, 0x6D, 0x96, 0xC4, 0xB8, 0x69, 0x37, 0xC1, 0x60, 0x6D, 0x6E, 0xBA, 0x37, 0x5C, 0x46, 0x25, 0x49, 0x3C, 0x50, 0x33}; /***************************************************************** * Declare a static 2048/224 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U ikedsa_2048_224_p[] = { 0xb9, 0x8f, 0x24, 0x95, 0x41, 0x14, 0x86, 0x5f, 0xc2, 0xaf, 0xf1, 0x80, 0x92, 0x2b, 0x33, 0x46, 0xaa, 0xcf, 0xec, 0x30, 0x90, 0x3c, 0x2b, 0xa8, 0x87, 0xd6, 0x59, 0x15, 0x14, 0xfe, 0xa1, 0xff, 0x00, 0xe6, 0x95, 0xf4, 0x7f, 0x3d, 0xa3, 0x37, 0x9e, 0x41, 0x1c, 0xd4, 0xf4, 0x00, 0x78, 0xb1, 0x68, 0x88, 0x2e, 0x32, 0xa4, 0x8e, 0xc1, 0xb5, 0x05, 0x85, 0x22, 0x4c, 0x83, 0x3a, 0x5e, 0x8e, 0x48, 0x9f, 0x62, 0x24, 0xa6, 0xb6, 0x95, 0xf1, 0xb0, 0xe3, 0xa2, 0x18, 0xc6, 0x72, 0xf3, 0xcb, 0xe1, 0x42, 0x44, 0x16, 0x3d, 0x29, 0x39, 0xb8, 0x7f, 0xf8, 0xe3, 0xe7, 0xb1, 0xd3, 0xc8, 0x06, 0x6f, 0x6f, 0x1c, 0x84, 0x94, 0x90, 0x21, 0x75, 0xe6, 0x10, 0xda, 0x5b, 0x45, 0xdf, 0xc2, 0xa2, 0xc0, 0x41, 0xb7, 0x07, 0xdf, 0x77, 0x37, 0xc5, 0xe2, 0x4b, 0x99, 0x5b, 0x09, 0x37, 0xf5, 0xc5, 0xbc, 0x85, 0x2f, 0xde, 0x6e, 0x71, 0xd6, 0xef, 0xaa, 0xc7, 0x4b, 0xbc, 0xe8, 0x5c, 0xe6, 0xcf, 0x7b, 0x2a, 0x3c, 0x70, 0xd1, 0x67, 0xc2, 0x1d, 0xae, 0xde, 0x7e, 0x6c, 0x9e, 0xfd, 0xf0, 0xee, 0x06, 0xbc, 0x29, 0xde, 0x68, 0xe1, 0xac, 0x52, 0xe5, 0xdd, 0xa5, 0xd2, 0x76, 0x12, 0x62, 0x8a, 0x66, 0x90, 0xbe, 0xc7, 0xc2, 0x42, 0xbc, 0xd0, 0xa6, 0x28, 0x47, 0xe2, 0x37, 0x86, 0xa6, 0x12, 0x7f, 0x24, 0x83, 0x99, 0x51, 0xdf, 0xec, 0x51, 0x95, 0xc9, 0x2c, 0xb2, 0x3e, 0x9c, 0x83, 0xa0, 0xd7, 0x5f, 0x18, 0xb7, 0xd9, 0x31, 0x55, 0xcb, 0x05, 0x2f, 0xb5, 0xa8, 0x6f, 0x13, 0xf3, 0x31, 0x28, 0x5b, 0x55, 0x81, 0x53, 0xc3, 0xdb, 0x06, 0x21, 0x13, 0x93, 0xd9, 0xef, 0x54, 0x36, 0x35, 0x1b, 0x39, 0x0c, 0x94, 0x8f, 0x4f, 0x78, 0x68, 0x8f, 0xbf, 0x99, 0xfd, 0x6c, 0x86, 0x71, 0xf9}; static Cpa8U ikedsa_2048_224_q[] = {0x8a, 0xad, 0x30, 0x8a, 0x52, 0x54, 0x0f, 0x30, 0xf9, 0xe4, 0x8b, 0x0b, 0xe0, 0xfd, 0x3e, 0x8d, 0xa1, 0xba, 0xd8, 0x07, 0x63, 0x8b, 0x40, 0x38, 0x30, 0x25, 0x81, 0x93}; /***************************************************************** * Declare a static 2048/256 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U ikedsa_2048_256_p[] = { 0x92, 0xf2, 0x30, 0x17, 0x69, 0x5c, 0x21, 0x41, 0x61, 0x53, 0xf9, 0x5f, 0xbe, 0x0a, 0x7b, 0x78, 0x5d, 0xec, 0xea, 0x3b, 0x93, 0xd1, 0xf0, 0xd8, 0xe8, 0x16, 0xb9, 0x47, 0x75, 0xca, 0xeb, 0xf6, 0x5a, 0x4a, 0xc9, 0x95, 0x22, 0x80, 0x38, 0x13, 0x6a, 0xd7, 0xe6, 0x21, 0x3a, 0x44, 0xd3, 0x99, 0xc0, 0xc7, 0x70, 0xf6, 0x28, 0xbe, 0x04, 0x99, 0x9b, 0xa1, 0x7d, 0x34, 0x63, 0x70, 0x0e, 0xf2, 0x23, 0xbe, 0x7c, 0xe4, 0x79, 0xe4, 0x23, 0x70, 0xdc, 0x5f, 0xd8, 0x79, 0x0e, 0x6c, 0xbf, 0x03, 0xee, 0xe4, 0x79, 0xd4, 0xce, 0xf1, 0x3d, 0x93, 0xd6, 0xd2, 0xa4, 0x2e, 0xf2, 0x28, 0x3a, 0x82, 0xb8, 0x63, 0xa5, 0xe6, 0x06, 0x99, 0xa1, 0x67, 0xc7, 0x82, 0xa9, 0x0d, 0xfd, 0xbc, 0x67, 0xb5, 0x63, 0xd8, 0xd0, 0xd2, 0xf3, 0x51, 0xe7, 0x1d, 0xfa, 0xb2, 0x9a, 0x62, 0xbf, 0x65, 0x98, 0x72, 0x28, 0x78, 0x0d, 0x3e, 0x40, 0xb6, 0x88, 0x2e, 0x1d, 0x5d, 0xbb, 0x8c, 0x70, 0x79, 0x68, 0x9e, 0x06, 0xda, 0xe9, 0xb0, 0x2f, 0xa1, 0x16, 0x83, 0x14, 0x93, 0xf9, 0x1f, 0xcd, 0x79, 0x41, 0x07, 0x42, 0x56, 0x13, 0x05, 0x29, 0xaa, 0x99, 0x7d, 0x2c, 0xad, 0xa4, 0xa8, 0xf0, 0xfb, 0x58, 0x23, 0x31, 0x89, 0xc0, 0xa0, 0xda, 0x75, 0xb1, 0xe8, 0xcb, 0x4d, 0x18, 0x99, 0xfe, 0x86, 0x3b, 0x9b, 0x2b, 0x64, 0xca, 0x79, 0xc0, 0x97, 0xd3, 0xfc, 0xb4, 0x95, 0xd2, 0x69, 0xe1, 0xb9, 0xb4, 0xbd, 0xd1, 0xfa, 0x32, 0x3d, 0x98, 0x08, 0x87, 0x03, 0x8b, 0x4c, 0x17, 0x78, 0x99, 0x73, 0xe3, 0x3d, 0x2d, 0xef, 0xe1, 0x93, 0x39, 0xda, 0x21, 0xdc, 0x23, 0x1c, 0x98, 0x56, 0x3c, 0x70, 0x60, 0x5d, 0x55, 0x17, 0x7a, 0x23, 0x35, 0x45, 0x42, 0xa6, 0x33, 0x90, 0xeb, 0x19, 0x39, 0x18, 0xd6, 0x7b}; static Cpa8U ikedsa_2048_256_q[] = { 0xa3, 0x4f, 0x3a, 0xaa, 0x84, 0x9b, 0x1e, 0x28, 0xd3, 0x82, 0x3b, 0x89, 0x6f, 0xb6, 0xe2, 0x0f, 0xfe, 0x07, 0xdb, 0xe4, 0x85, 0xa5, 0x81, 0x6c, 0xbb, 0x14, 0x3f, 0x97, 0xf1, 0x47, 0x6a, 0xf9}; /***************************************************************** * Declare a static 3072/256 bit P/Q pair that satisfies FIPS186-3 * ***************************************************************/ static Cpa8U ikedsa_3072_256_p[] = { 0xa3, 0x78, 0x53, 0xcf, 0x35, 0x04, 0x0d, 0xb2, 0x07, 0x24, 0x2b, 0xab, 0x21, 0xd0, 0xa3, 0x9a, 0xb5, 0xa5, 0x25, 0x22, 0xac, 0xb3, 0x06, 0xe4, 0xdc, 0x04, 0x7b, 0xa5, 0xb9, 0xc3, 0xe5, 0x34, 0x4a, 0x23, 0x42, 0xfd, 0x6c, 0x5d, 0x61, 0x28, 0x06, 0x90, 0xe3, 0x9a, 0x4a, 0xab, 0x7b, 0xd7, 0x25, 0x84, 0x0d, 0x95, 0xe2, 0xda, 0x53, 0xb7, 0x49, 0xfc, 0xbf, 0xcf, 0xa2, 0xd6, 0x9b, 0xf9, 0x17, 0x0b, 0x6e, 0xef, 0x65, 0xbf, 0xf7, 0xc2, 0x42, 0x8d, 0x65, 0x9f, 0xe0, 0x0c, 0x47, 0x8c, 0xa1, 0xaf, 0xf4, 0x1b, 0x10, 0x36, 0xe6, 0x8e, 0x95, 0x22, 0xaa, 0xc3, 0xee, 0xb7, 0x85, 0x15, 0xf1, 0xaf, 0x29, 0xff, 0xc1, 0x38, 0xaa, 0x27, 0x48, 0x4e, 0x12, 0xad, 0xf9, 0x2e, 0xec, 0x85, 0x1e, 0x54, 0x8f, 0x19, 0x21, 0x08, 0x14, 0xb3, 0x16, 0x64, 0x06, 0x4c, 0x4d, 0x7e, 0x30, 0xe9, 0x45, 0x49, 0x13, 0x7a, 0x0b, 0x7d, 0x06, 0x14, 0x92, 0xb6, 0xa8, 0x51, 0x7a, 0xe2, 0xed, 0xd9, 0xae, 0x31, 0x06, 0xe3, 0x5b, 0xcf, 0xea, 0x28, 0xb7, 0x3f, 0xec, 0x34, 0x16, 0xff, 0x40, 0x41, 0x65, 0x7e, 0x97, 0xad, 0x4a, 0xcb, 0x78, 0x87, 0xea, 0xf2, 0xb7, 0xa0, 0x2b, 0xcd, 0x8e, 0xe1, 0xb0, 0x5d, 0x99, 0x1e, 0x81, 0xca, 0xe7, 0x7d, 0xf2, 0xd1, 0x57, 0xdb, 0x95, 0x8f, 0xd4, 0x81, 0xc6, 0xed, 0x00, 0x47, 0xe3, 0x84, 0xdf, 0x75, 0xf0, 0x9c, 0xec, 0xca, 0x34, 0x1f, 0xb2, 0xe8, 0x38, 0xc7, 0x19, 0xaf, 0x4d, 0xd1, 0xe4, 0xf1, 0x80, 0x83, 0xbd, 0x31, 0x48, 0x74, 0xd0, 0x97, 0x7c, 0xf6, 0x1b, 0x03, 0xcc, 0xf3, 0x00, 0x2d, 0x90, 0x3f, 0x1d, 0x1f, 0x94, 0x6f, 0x47, 0x46, 0xb3, 0x04, 0x6a, 0x14, 0x4a, 0xb0, 0x75, 0x9c, 0x3f, 0x40, 0x1e, 0x31, 0x52, 0x26, 0xfe, 0x9a, 0x4e, 0x6f, 0xde, 0x00, 0xc4, 0x54, 0xe4, 0xf9, 0x0e, 0x4a, 0x14, 0x87, 0x99, 0x81, 0xd9, 0x8f, 0x6e, 0xdc, 0xa2, 0xdd, 0xab, 0xcf, 0xe0, 0x78, 0x3a, 0xe9, 0xfd, 0x84, 0xd0, 0xf2, 0xb0, 0xcb, 0x74, 0xef, 0xa8, 0x27, 0x6f, 0xbf, 0xe4, 0xa1, 0x52, 0x5d, 0x39, 0xd1, 0x28, 0x09, 0x76, 0x78, 0xa9, 0x32, 0x18, 0x9d, 0x57, 0xe1, 0x97, 0x29, 0x29, 0x5c, 0xf3, 0xb9, 0x70, 0x3b, 0x4b, 0x2a, 0x2d, 0x5e, 0x98, 0x0d, 0x90, 0xcb, 0xa7, 0xd1, 0xd1, 0x9f, 0x28, 0xea, 0xbe, 0x7a, 0x92, 0xfd, 0xc4, 0xe8, 0x00, 0x4d, 0xef, 0x05, 0x45, 0x97, 0xc4, 0x2d, 0x2e, 0x94, 0x80, 0x44, 0x90, 0xf8, 0x5a, 0xbd, 0xd1, 0x86, 0xa1, 0xef, 0x47, 0x93, 0xe9, 0x1b, 0x98, 0x59, 0x1b, 0xbb, 0xb2, 0x66, 0xbd, 0x23, 0x23, 0x60, 0x4d, 0xeb, 0x6f, 0x5a, 0xcd, 0xee, 0x43, 0xab, 0x02, 0x08, 0xa6, 0xc7}; static Cpa8U ikedsa_3072_256_q[] = { 0xc4, 0x06, 0xcd, 0x06, 0x69, 0xd9, 0x82, 0x2f, 0x5e, 0x41, 0x91, 0x3c, 0x9c, 0xb8, 0xa3, 0x06, 0xee, 0x25, 0x68, 0xdc, 0x22, 0x8c, 0x4a, 0x39, 0x96, 0x01, 0xe3, 0x57, 0x93, 0xf4, 0x4e, 0x41}; /* this structure is used to store data required by each client in the ike-dsa * transaction */ typedef struct ike_dsa_client_data_s { CpaFlatBuffer **ppPublicValues; CpaFlatBuffer **ppSecretKeys; CpaCyDhPhase2SecretKeyGenOpData **ppPhase2; CpaCyDhPhase1KeyGenOpData **ppPhase1; CpaCyDsaRSSignOpData **ppRSSignOpData; CpaCyDsaVerifyOpData **ppVerifyOpData; CpaCyDsaVerifyOpData **ppVerifyOpData2; CpaFlatBuffer **ppR; CpaFlatBuffer **ppS; } ike_dsa_client_data_t; /***************************************************************************** * @ingroup IKE_DSA Threads * * @description * Asymmetric callback function: This function is invoked when a * operation has been processed *****************************************************************************/ void ikeDsaCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { processCallback(pCallbackTag); } /****************************************************************************** * @ingroup sampleRSACode * * @description * This function frees all Operation Data memory setup in this file. * The code checks for any unallocated memory before it attempts to free it. ******************************************************************************/ static void dsaFreeDataMemory(dsa_test_params_t *setup, CpaCyDsaRSSignOpData *pSignOpdata[], CpaCyDsaVerifyOpData *pVerifyOpData[], CpaCyDsaVerifyOpData *pVerifyOpData2[], CpaFlatBuffer *pR[], CpaFlatBuffer *pS[]) { Cpa32U bufferCount = 0; if (NULL != pSignOpdata) { if (NULL != pSignOpdata[0]) { qaeMemFreeNUMA((void **)&pSignOpdata[bufferCount]->P.pData); qaeMemFreeNUMA((void **)&pSignOpdata[bufferCount]->Q.pData); qaeMemFreeNUMA((void **)&pSignOpdata[bufferCount]->G.pData); } } for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { if (NULL != pSignOpdata) { if (NULL != pSignOpdata[bufferCount]) { qaeMemFreeNUMA((void **)&pSignOpdata[bufferCount]->X.pData); qaeMemFreeNUMA((void **)&pSignOpdata[bufferCount]->K.pData); qaeMemFreeNUMA((void **)&pSignOpdata[bufferCount]->Z.pData); } } if (NULL != pVerifyOpData) { if (NULL != pVerifyOpData[bufferCount]) { qaeMemFreeNUMA((void **)&pVerifyOpData[bufferCount]->Y.pData); qaeMemFreeNUMA((void **)&pVerifyOpData[bufferCount]->R.pData); qaeMemFreeNUMA((void **)&pVerifyOpData[bufferCount]->S.pData); } } if (NULL != pVerifyOpData2) { if (NULL != pVerifyOpData2[bufferCount]) { qaeMemFreeNUMA((void **)&pVerifyOpData2[bufferCount]->R.pData); qaeMemFreeNUMA((void **)&pVerifyOpData2[bufferCount]->S.pData); } } if (NULL != pR) { if (NULL != pR[bufferCount]) { qaeMemFreeNUMA((void **)&pR[bufferCount]->pData); } } if (NULL != pS) { if (NULL != pS[bufferCount]) { qaeMemFreeNUMA((void **)&pS[bufferCount]->pData); } } } return; } // EXPORT_SYMBOL(rsaFreeDataMemory); /***************************************************************************** * @ingroup IKE_DSA * * @description * This function is free an array of operation data structures for * ikedsa operations, any memory allocation is freed in * ikeDsaPerform ******************************************************************************/ static void ikeDsaMemFreeDsaData(ike_dsa_client_data_t *client) { if (NULL != client) { if (NULL != client->ppRSSignOpData) { qaeMemFreeNUMA((void **)&client->ppRSSignOpData); } if (NULL != client->ppVerifyOpData) { qaeMemFreeNUMA((void **)&client->ppVerifyOpData); } if (NULL != client->ppVerifyOpData2) { qaeMemFreeNUMA((void **)&client->ppVerifyOpData2); } if (NULL != client->ppR) { qaeMemFreeNUMA((void **)&client->ppR); } if (NULL != client->ppS) { qaeMemFreeNUMA((void **)&client->ppS); } } return; } /***************************************************************************** * @ingroup IKE_DSA * * @description * This function allocates the client memory for an IKE-DSA * transaction used in ikeDsaPerform ******************************************************************************/ static CpaStatus allocDsaClientMem(dsa_test_params_t *setup, ike_dsa_client_data_t *client) { if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppRSSignOpData, setup->numBuffers)) { PRINT_ERR("Could not allocate ppRSSignOpData\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppVerifyOpData, setup->numBuffers)) { PRINT_ERR("Could not allocate ppVerifyOpData\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppVerifyOpData2, setup->numBuffers)) { PRINT_ERR("Could not allocate ppVerifyOpData2\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppPhase1, setup->numBuffers)) { PRINT_ERR("Could not allocate ppPhase1\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppPhase2, setup->numBuffers)) { PRINT_ERR("Could not allocate ppPhase2\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppPublicValues, setup->numBuffers)) { PRINT_ERR("Could not allocate ppPublicValues\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppSecretKeys, setup->numBuffers)) { PRINT_ERR("Could not allocate ppSecretKeys\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppR, setup->numBuffers)) { PRINT_ERR("Could not allocate ppR\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppS, setup->numBuffers)) { PRINT_ERR("Could not allocate ppS\n"); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup sampleDSACode * * @description * free all memory used in DSA IKE code in this file * *****************************************************************************/ static void freeIkeDsaMem(dsa_test_params_t *setup, CpaFlatBuffer *dsaX, CpaFlatBuffer *dsaY, CpaFlatBuffer *dsaK, CpaFlatBuffer *dsaP, CpaFlatBuffer *dsaQ, CpaFlatBuffer *dsaG, CpaFlatBuffer *dsaH) { freeArrayFlatBufferNUMA(dsaX, setup->numBuffers); freeArrayFlatBufferNUMA(dsaY, setup->numBuffers); freeArrayFlatBufferNUMA(dsaK, setup->numBuffers); /*free the normal flatBuffer pData */ if (NULL != dsaP) { qaeMemFreeNUMA((void **)dsaP->pData); } if (NULL != dsaQ) { qaeMemFreeNUMA((void **)dsaQ->pData); } if (NULL != dsaG) { qaeMemFreeNUMA((void **)dsaG->pData); } if (NULL != dsaH) { qaeMemFreeNUMA((void **)dsaH->pData); } } /** ***************************************************************************** * @ingroup sampleDSACode * * @description * Macro to free all memory used in DSA IKE code in this file * *****************************************************************************/ #define FREE_ikeDSA_MEM \ freeIkeDsaMem(setup, pDsaX, pDsaY, pDsaK, pDsaP, pDsaQ, pDsaG, pDsaH) /****************************************************************************** * @ingroup sampleDSACode * * @description * this function allocates space and generates arrays of DSA keys, based on the * parameters within the setup * ****************************************************************************/ static CpaStatus genDsaPara(dsa_test_params_t *setup, CpaCyDsaRSSignOpData **ppSignOpData, CpaCyDsaVerifyOpData **ppVerifyOpData, CpaCyDsaVerifyOpData **ppVerifyOpData2, CpaFlatBuffer **ppdsaR, CpaFlatBuffer **ppdsaS) { Cpa32U i = 0; Cpa32U status = 0; /*DSA parameters */ /*DSA P parameter, this shall be populated by the hard coded P at the top * of this file */ CpaFlatBuffer *pDsaP = NULL; /*DSA Q parameter, this shall be populated by the hard coded Q at the top * of this file */ CpaFlatBuffer *pDsaQ = NULL; /* DSA G parameter used to generate Y, the signature R&S, and to verify */ CpaFlatBuffer *pDsaG = NULL; /*H is used to generate G, H is hard coded to DEFAULT_H_VALUE */ CpaFlatBuffer *pDsaH = NULL; /*random number X used to generate Y and Sign R&S */ CpaFlatBuffer *pDsaX = NULL; /*DSA Y parameter is used in the verification stage */ CpaFlatBuffer *pDsaY = NULL; /*K is a random number used in the generation of signature R&S */ CpaFlatBuffer *pDsaK = NULL; CpaFlatBuffer *pDsaR1 = NULL; CpaFlatBuffer *pDsaS1 = NULL; CpaFlatBuffer *pDsaR2 = NULL; CpaFlatBuffer *pDsaS2 = NULL; /*GCC compiler complains without the double {{}} to init the following * structures*/ CpaCyDsaGParamGenOpData gOpData = {{0, NULL}, {0, NULL}, {0, NULL}}; CpaCyDsaYParamGenOpData yOpData = {{0}}; Cpa8U *pDataPtr = NULL; Cpa32U sizeOfp = 0; Cpa8U *qDataPtr = NULL; Cpa32U sizeOfq = 0; Cpa32U node = 0; #ifdef POLL_INLINE CpaInstanceInfo2 *instanceInfo2 = NULL; #endif #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } } qaeMemFree((void **)&instanceInfo2); #endif status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not determine node for memory allocation\n"); return status; } /*check the p and q input len and set the pointers to the data */ if (MODULUS_1024_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_160_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = ikedsa_1024_160_p; qDataPtr = ikedsa_1024_160_q; sizeOfp = sizeof(ikedsa_1024_160_p); sizeOfq = sizeof(ikedsa_1024_160_q); } else if (MODULUS_2048_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_224_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = ikedsa_2048_224_p; qDataPtr = ikedsa_2048_224_q; sizeOfp = sizeof(ikedsa_2048_224_p); sizeOfq = sizeof(ikedsa_2048_224_q); } else if (MODULUS_2048_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_256_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = ikedsa_2048_256_p; qDataPtr = ikedsa_2048_256_q; sizeOfp = sizeof(ikedsa_2048_256_p); sizeOfq = sizeof(ikedsa_2048_256_q); } else if (MODULUS_3072_BIT / NUM_BITS_IN_BYTE == setup->pLenInBytes && EXPONENT_256_BIT / NUM_BITS_IN_BYTE == setup->qLenInBytes) { pDataPtr = ikedsa_3072_256_p; qDataPtr = ikedsa_3072_256_q; sizeOfp = sizeof(ikedsa_3072_256_p); sizeOfq = sizeof(ikedsa_3072_256_q); } else { PRINT_ERR("P & Q len not supported\n"); /*thread status is init to fail so just return fail here*/ return CPA_STATUS_FAIL; } /* Completion used in callback */ /*Allocate all the buffers */ pDsaX = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == pDsaX) { PRINT_ERR("Could not allocate memory\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } pDsaY = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == pDsaY) { PRINT_ERR("Could not allocate memory\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } pDsaK = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == pDsaK) { PRINT_ERR("Could not allocate memory\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } /************************************************************************ * STAGE 1 Setup up the DSA parameters, generate X, G, Y, K, Z, * generate user defined number of messages to be signed * calculate the digest of the messages * sign all the messages * setup the verification data structure **************************************************************************/ /*set P */ pDsaP = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaP) { PRINT_ERR("Could not allocate memory for pDsaP\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaP, setup->pLenInBytes, pDataPtr, sizeOfp, FREE_ikeDSA_MEM); /*set Q */ pDsaQ = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaQ) { PRINT_ERR("Could not allocate memory for pDsaQ\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaQ, setup->qLenInBytes, qDataPtr, sizeOfq, FREE_ikeDSA_MEM); /*generate X for each buffer */ for (i = 0; i < setup->numBuffers; i++) { /*Choose X is generated by random method, where 0 < X < Q */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pDsaX[i], setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); dsaGenRandom(&pDsaX[i], pDsaQ); } /*************************************************************************** * set genG opData and generate G * ************************************************************************/ /*H is required to genG */ pDsaH = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaH) { PRINT_ERR("Could not allocate memory for pDsaH\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaH, setup->pLenInBytes, NULL, 0, FREE_ikeDSA_MEM); memset(pDsaH->pData, 0, pDsaH->dataLenInBytes); pDsaH->pData[setup->pLenInBytes - 1] = IKEDSA_DEFAULT_H_VALUE; /*allocate space for G */ pDsaG = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaG) { PRINT_ERR("Could not allocate memory for pDsaG\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaG, setup->pLenInBytes, NULL, 0, FREE_ikeDSA_MEM); /*set opData to generate G */ gOpData.P.pData = pDsaP->pData; gOpData.P.dataLenInBytes = pDsaP->dataLenInBytes; gOpData.Q.pData = pDsaQ->pData; gOpData.Q.dataLenInBytes = pDsaQ->dataLenInBytes; gOpData.H.pData = pDsaH->pData; gOpData.H.dataLenInBytes = pDsaH->dataLenInBytes; status = dsaGenG(setup->cyInstanceHandle, &gOpData, pDsaG); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to generate IKE DSA parameter G\n"); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } /*generate a Y for each buffer */ for (i = 0; i < setup->numBuffers; i++) { /*set the opData to gen Y */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pDsaY[i], setup->pLenInBytes, NULL, 0, FREE_ikeDSA_MEM); yOpData.P.pData = pDsaP->pData; yOpData.P.dataLenInBytes = pDsaP->dataLenInBytes; yOpData.G.pData = pDsaG->pData; yOpData.G.dataLenInBytes = pDsaG->dataLenInBytes; yOpData.X.pData = pDsaX[i].pData; yOpData.X.dataLenInBytes = pDsaX[i].dataLenInBytes; status = dsaGenY(setup->cyInstanceHandle, &yOpData, &pDsaY[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating Y for buffer %d\n", i); /*free all the pData buffers allocated and Array of pointers * allocated */ FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } /*Generate a random per-message value K, where 0 < K < Q. */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pDsaK[i], setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); dsaGenRandom(&pDsaK[i], pDsaQ); /* Allocate memory for the PublicValue buffer */ ppdsaR[i] = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == ppdsaR[i]) { PRINT("ppdsaR[%d] is NULL \n", i); FREE_ikeDSA_MEM; return CPA_STATUS_FAIL; } ppdsaS[i] = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == ppdsaS[i]) { PRINT("ppdsaS[%d] is NULL \n", i); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, ppdsaR[i], setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, ppdsaS[i], setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); ppSignOpData[i] = qaeMemAllocNUMA( sizeof(CpaCyDsaRSSignOpData), node, BYTE_ALIGNMENT_64); if (NULL == ppSignOpData[i]) { PRINT_ERR("Failed to allocate mem for ppSignOpData input data\n"); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); qaeMemFree((void **)&ppdsaS); return CPA_STATUS_FAIL; } memset(ppSignOpData[i], 0, sizeof(CpaCyDsaRSSignOpData)); /*Gen R & S signature */ ppSignOpData[i]->P.pData = pDsaP->pData; ppSignOpData[i]->P.dataLenInBytes = pDsaP->dataLenInBytes; ppSignOpData[i]->Q.pData = pDsaQ->pData; ppSignOpData[i]->Q.dataLenInBytes = pDsaQ->dataLenInBytes; ppSignOpData[i]->G.pData = pDsaG->pData; ppSignOpData[i]->G.dataLenInBytes = pDsaG->dataLenInBytes; ppSignOpData[i]->X.pData = pDsaX[i].pData; ppSignOpData[i]->X.dataLenInBytes = pDsaX[i].dataLenInBytes; ppSignOpData[i]->K.pData = pDsaK[i].pData; ppSignOpData[i]->K.dataLenInBytes = pDsaK[i].dataLenInBytes; /*Verify signature */ ppVerifyOpData[i] = qaeMemAllocNUMA( sizeof(CpaCyDsaVerifyOpData), node, BYTE_ALIGNMENT_64); if (NULL == ppVerifyOpData[i]) { PRINT_ERR("Failed to allocate mem for ppVerifyOpData input data\n"); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); qaeMemFree((void **)&ppdsaS); qaeMemFree((void **)&ppSignOpData); return CPA_STATUS_FAIL; } memset(ppVerifyOpData[i], 0, sizeof(CpaCyDsaVerifyOpData)); pDsaR1 = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaR1) { PRINT_ERR("Failed to allocate memory for pDsaR1\n"); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); qaeMemFree((void **)&ppdsaS); qaeMemFree((void **)&ppSignOpData); qaeMemFree((void **)&ppVerifyOpData); return CPA_STATUS_FAIL; } pDsaS1 = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaS1) { PRINT_ERR("Failed to allocate memory for pDsaS1\n"); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); qaeMemFree((void **)&ppdsaS); qaeMemFree((void **)&ppSignOpData); qaeMemFree((void **)&ppVerifyOpData); qaeMemFree((void **)&pDsaR1); return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaR1, setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaS1, setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); ppVerifyOpData[i]->P.pData = pDsaP->pData; ppVerifyOpData[i]->P.dataLenInBytes = pDsaP->dataLenInBytes; ppVerifyOpData[i]->Q.pData = pDsaQ->pData; ppVerifyOpData[i]->Q.dataLenInBytes = pDsaQ->dataLenInBytes; ppVerifyOpData[i]->G.pData = pDsaG->pData; ppVerifyOpData[i]->G.dataLenInBytes = pDsaG->dataLenInBytes; ppVerifyOpData[i]->Y.pData = pDsaY[i].pData; ppVerifyOpData[i]->Y.dataLenInBytes = pDsaY[i].dataLenInBytes; ppVerifyOpData[i]->R.pData = pDsaR1->pData; ppVerifyOpData[i]->R.dataLenInBytes = pDsaR1->dataLenInBytes; ppVerifyOpData[i]->S.pData = pDsaS1->pData; ppVerifyOpData[i]->S.dataLenInBytes = pDsaS1->dataLenInBytes; ppVerifyOpData2[i] = qaeMemAllocNUMA( sizeof(CpaCyDsaVerifyOpData), node, BYTE_ALIGNMENT_64); if (NULL == ppVerifyOpData2[i]) { PRINT_ERR("Failed to allocate mem for ppVerifyOpData input data\n"); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); qaeMemFree((void **)&ppdsaS); qaeMemFree((void **)&ppSignOpData); qaeMemFree((void **)&ppVerifyOpData); qaeMemFree((void **)&pDsaR1); qaeMemFree((void **)&pDsaS1); return CPA_STATUS_FAIL; } memset(ppVerifyOpData2[i], 0, sizeof(CpaCyDsaVerifyOpData)); pDsaR2 = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaR2) { PRINT_ERR("Failed to allocate mem for pDsaR2 input data\n"); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); qaeMemFree((void **)&ppdsaS); qaeMemFree((void **)&ppSignOpData); qaeMemFree((void **)&ppVerifyOpData); qaeMemFree((void **)&pDsaR1); qaeMemFree((void **)&pDsaS1); qaeMemFree((void **)&ppVerifyOpData2); return CPA_STATUS_FAIL; } pDsaS2 = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == pDsaS2) { PRINT_ERR("Failed to allocate mem for pDsaS2 input data\n"); FREE_ikeDSA_MEM; qaeMemFree((void **)&ppdsaR); qaeMemFree((void **)&ppdsaS); qaeMemFree((void **)&ppSignOpData); qaeMemFree((void **)&ppVerifyOpData); qaeMemFree((void **)&pDsaR1); qaeMemFree((void **)&pDsaS1); qaeMemFree((void **)&ppVerifyOpData2); qaeMemFree((void **)&pDsaR2); return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaR2, setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDsaS2, setup->qLenInBytes, NULL, 0, FREE_ikeDSA_MEM); ppVerifyOpData2[i]->P.pData = pDsaP->pData; ppVerifyOpData2[i]->P.dataLenInBytes = pDsaP->dataLenInBytes; ppVerifyOpData2[i]->Q.pData = pDsaQ->pData; ppVerifyOpData2[i]->Q.dataLenInBytes = pDsaQ->dataLenInBytes; ppVerifyOpData2[i]->G.pData = pDsaG->pData; ppVerifyOpData2[i]->G.dataLenInBytes = pDsaG->dataLenInBytes; ppVerifyOpData2[i]->Y.pData = pDsaY[i].pData; ppVerifyOpData2[i]->Y.dataLenInBytes = pDsaY[i].dataLenInBytes; ppVerifyOpData2[i]->R.pData = pDsaR2->pData; ppVerifyOpData2[i]->R.dataLenInBytes = pDsaR2->dataLenInBytes; ppVerifyOpData2[i]->S.pData = pDsaS2->pData; ppVerifyOpData2[i]->S.dataLenInBytes = pDsaS2->dataLenInBytes; } return CPA_STATUS_SUCCESS; } /****************************************************************************** * @ingroup sampleDSACode * * @description * this function measures the performance of DSA Encrypt operations * It is assumed all the encrypt data and keys have been been set using * functions defined in this file * ****************************************************************************/ static CpaStatus sampleDsaSign(dsa_test_params_t *setup, CpaCyDsaRSSignOpData *pRSSignOpData[], CpaFlatBuffer *dsaR[], CpaFlatBuffer *dsaS[], Cpa32U numBuffers, Cpa32U numLoops) { Cpa32U outerLoop = 0; Cpa32U i = 0; CpaStatus status = CPA_STATUS_SUCCESS; for (outerLoop = 0; outerLoop < setup->numLoops; outerLoop++) { for (i = 0; i < setup->numBuffers; i++) { status = dsaGenRS( setup->cyInstanceHandle, pRSSignOpData[i], dsaR[i], dsaS[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating R&S for buffer %d\n", i); // FREE_DSA_MEM; return CPA_STATUS_FAIL; } } } return CPA_STATUS_SUCCESS; } /***************************************************************************** * @ingroup IKE_DSA * * @description * This function frees all the dynamically allocated memory used in the * ikeDsaPerform * Each pointer is checked to see if its null and if not it is free'd, * The underlying free function ensures that when freeing the pointer is reset * to NULL ******************************************************************************/ static void ikeDsaMemFree(dsa_test_params_t *setup, ike_dsa_client_data_t *alice, ike_dsa_client_data_t *bob) { dsaFreeDataMemory(setup, alice->ppRSSignOpData, alice->ppVerifyOpData, alice->ppVerifyOpData2, alice->ppR, alice->ppS); dsaFreeDataMemory(setup, bob->ppRSSignOpData, bob->ppVerifyOpData, bob->ppVerifyOpData2, bob->ppR, bob->ppS); /*free the signature pointer arrays because in RSA code this is allocated * as a local variable*/ ikeDsaMemFreeDsaData(alice); ikeDsaMemFreeDsaData(bob); dhMemFreePh1((asym_test_params_t *)setup, alice->ppPhase1, alice->ppPublicValues, bob->ppPhase1, bob->ppPublicValues); qaeMemFree((void **)&alice->ppPublicValues); qaeMemFree((void **)&bob->ppPublicValues); qaeMemFree((void **)&alice->ppPhase1); qaeMemFree((void **)&bob->ppPhase1); dhMemFreePh2((asym_test_params_t *)setup, alice->ppSecretKeys, alice->ppPhase2, bob->ppSecretKeys, bob->ppPhase2); qaeMemFree((void **)&alice->ppSecretKeys); qaeMemFree((void **)&bob->ppSecretKeys); qaeMemFree((void **)&alice->ppPhase2); qaeMemFree((void **)&bob->ppPhase2); return; } #define FREE_dsaSetup_MEM \ do \ { \ qaeMemFreeNUMA((void **)&dsaZ[i].pData); \ qaeMemFree((void **)&dsaZ); \ } while (0) /****************************************************************************** * @ingroup sampleDSACode * * @description * this function sets up the data to be decrypted and allocates space to * store the output * ****************************************************************************/ static CpaStatus dsaZSetup(CpaFlatBuffer **ppPublicValues, CpaCyDsaRSSignOpData **ppSignatureOpData, CpaCyDsaVerifyOpData **ppVerifyOpData, CpaCyDsaVerifyOpData **ppVerifyOpData2, dsa_test_params_t *setup) { Cpa32U i = 0; CpaStatus status = CPA_STATUS_SUCCESS; /*Z is the digest of the message in dsaM */ CpaFlatBuffer *dsaZ = NULL; Cpa32U node = 0; #ifdef POLL_INLINE CpaInstanceInfo2 instanceInfo2 = {0}; #endif #ifdef POLL_INLINE if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, &instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); return CPA_STATUS_FAIL; } } #endif status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not determine node for memory allocation\n"); return status; } dsaZ = qaeMemAlloc(sizeof(CpaFlatBuffer) * setup->numBuffers); if (NULL == dsaZ) { PRINT_ERR("Could not allocate memory\n"); return CPA_STATUS_FAIL; } /*generate a Y for each buffer */ for (i = 0; i < setup->numBuffers; i++) { /*allocate space for digest of message */ ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &dsaZ[i], setup->qLenInBytes, NULL, 0, FREE_dsaSetup_MEM); /*calculate digest of message */ status = dsaGenZ(setup->cyInstanceHandle, ppPublicValues[i], setup->hashAlg, &dsaZ[i]); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error Generating Z for buffer %d\n", i); FREE_dsaSetup_MEM; return CPA_STATUS_FAIL; } (*ppSignatureOpData[i]).Z.pData = dsaZ[i].pData; (*ppSignatureOpData[i]).Z.dataLenInBytes = dsaZ[i].dataLenInBytes; (*ppVerifyOpData[i]).Z.pData = dsaZ[i].pData; (*ppVerifyOpData[i]).Z.dataLenInBytes = dsaZ[i].dataLenInBytes; (*ppVerifyOpData2[i]).Z.pData = dsaZ[i].pData; (*ppVerifyOpData2[i]).Z.dataLenInBytes = dsaZ[i].dataLenInBytes; } qaeMemFree((void **)&dsaZ); return CPA_STATUS_SUCCESS; } /***************************************************************************** * @ingroup IKE_DSA * * @description * This function sets up the QA API asymmetric functions of an IKE * transaction using DSA to sign/verify DH generated keys ******************************************************************************/ static CpaStatus ikeDsaPerform(dsa_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean verifyStatus = CPA_TRUE; Cpa32U i = 0; Cpa32U innerLoop = 0; CpaBoolean dsaSignprotocolStatus = CPA_FALSE; ike_dsa_client_data_t alice = {0}; ike_dsa_client_data_t bob = {0}; Cpa32U node = 0; /*functions called in this code over writes the performanceStats->response, * so we use a local counter to count responses */ Cpa32U responses = 0; Cpa32U packageId = 0; CpaInstanceInfo2 *instanceInfo2 = NULL; instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); qaeMemFree((void **)&instanceInfo2); return status; } packageId = instanceInfo2->physInstId.packageId; qaeMemFree((void **)&instanceInfo2); /************************************************************************/ /* Allocate all the memory for DH and DSA operations */ /************************************************************************/ /*Allocate for Alice*/ if (CPA_STATUS_SUCCESS != allocDsaClientMem(setup, &alice)) { PRINT_ERR("Alice allocClientMem error\n"); ikeDsaMemFree(setup, &alice, &bob); return CPA_STATUS_FAIL; } /*Allocate for Bob*/ if (CPA_STATUS_SUCCESS != allocDsaClientMem(setup, &bob)) { PRINT_ERR("Bob allocClientMem error\n"); ikeDsaMemFree(setup, &alice, &bob); return CPA_STATUS_FAIL; } /************************************************************************** * STEP 1. Alice & Bob generate public & private DSA keys * ************************************************************************/ status = genDsaPara(setup, alice.ppRSSignOpData, alice.ppVerifyOpData, alice.ppVerifyOpData2, alice.ppR, alice.ppS); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error, failed Alice genDsaPara, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } status = genDsaPara(setup, bob.ppRSSignOpData, bob.ppVerifyOpData, bob.ppVerifyOpData2, bob.ppR, bob.ppS); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error, failed Bob genDsaPara, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /************************************************************************** * STEP 2. Alice & Bob agree on a p & g and generate secret random x **************************************************************************/ status = dhPhase1Setup((asym_test_params_t *)setup, alice.ppPhase1, bob.ppPhase1, alice.ppPublicValues, bob.ppPublicValues, NULL); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error, failed dhPhase1Setup, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /************************************************************************** * STEP 3. Alice & Bob Perform DH Phase1 to produce Public Value - * PV = g^x mod p **************************************************************************/ /**************************************************************************/ /*Perform DH phase1 for Alice */ /**************************************************************************/ status = dhPhase1(alice.ppPhase1, alice.ppPublicValues, (asym_test_params_t *)setup, setup->numBuffers, ONE_LOOP); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error, failed to complete dhPhase1 for Alice, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /**************************************************************************/ /*Perform DH phase1 for Bob */ /**************************************************************************/ status = dhPhase1(bob.ppPhase1, bob.ppPublicValues, (asym_test_params_t *)setup, setup->numBuffers, ONE_LOOP); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to complete dhPhase1 for Bob, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /**************************************************************************/ /*Perform Phase2 setup for Bob */ /**************************************************************************/ status = dhPhase2Setup(bob.ppSecretKeys, bob.ppPhase1, bob.ppPhase2, alice.ppPublicValues, (asym_test_params_t *)setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to setup phase2 for Bob, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /**************************************************************************/ /*Calculate Bobs secret keys */ /**************************************************************************/ status = dhPhase2Perform(bob.ppSecretKeys, bob.ppPhase2, (asym_test_params_t *)setup, setup->numBuffers, ONE_LOOP); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to perform phase2 for Bob, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /*************************************************************************** * STEP 5. Sign Bobs Public Value using peers public key -> * Bobs Signature = DSA sign bobsPV *************************************************************************/ status = dsaZSetup(bob.ppPublicValues, bob.ppRSSignOpData, bob.ppVerifyOpData, bob.ppVerifyOpData2, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed rsaDecryptDataSetup for Bob, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } status = dsaZSetup(alice.ppPublicValues, alice.ppRSSignOpData, alice.ppVerifyOpData2, alice.ppVerifyOpData2, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed rsaDecryptDataSetup for Bob, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /**************************************************************************/ /* Sign all of Bobs public value buffers, but loop only once */ /**************************************************************************/ status = sampleDsaSign(setup, bob.ppRSSignOpData, bob.ppR, bob.ppS, setup->numBuffers, ONE_LOOP); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed sampleDsaSign for Bob, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /* Copy the DSA signature output into the verification structure * in the performance loop we verify bobs signature. Bobs signature is * the input the the verification operation*/ for (i = 0; i < setup->numBuffers; i++) { /*check that the signature is the expected length*/ if (bob.ppVerifyOpData[i]->R.dataLenInBytes != bob.ppR[i]->dataLenInBytes) { PRINT_ERR("Verify R data len does not match the signature len\n"); ikeDsaMemFree(setup, &alice, &bob); return status; } memcpy(bob.ppVerifyOpData[i]->R.pData, bob.ppR[i]->pData, bob.ppVerifyOpData[i]->R.dataLenInBytes); if (bob.ppVerifyOpData[i]->S.dataLenInBytes != bob.ppS[i]->dataLenInBytes) { PRINT_ERR("Verify S data len does not match the signature len\n"); ikeDsaMemFree(setup, &alice, &bob); return status; } memcpy(bob.ppVerifyOpData[i]->S.pData, bob.ppS[i]->pData, bob.ppVerifyOpData[i]->S.dataLenInBytes); /*check that the signature is the expected length*/ if (bob.ppVerifyOpData2[i]->R.dataLenInBytes != bob.ppR[i]->dataLenInBytes) { PRINT_ERR("Verify 2 R data len does not match the signature len\n"); ikeDsaMemFree(setup, &alice, &bob); return status; } memcpy(bob.ppVerifyOpData2[i]->R.pData, bob.ppR[i]->pData, bob.ppVerifyOpData2[i]->R.dataLenInBytes); if (bob.ppVerifyOpData2[i]->R.dataLenInBytes != bob.ppS[i]->dataLenInBytes) { PRINT_ERR("Verify 2 S data len does not match the signature len\n"); ikeDsaMemFree(setup, &alice, &bob); return status; } memcpy(bob.ppVerifyOpData2[i]->S.pData, bob.ppS[i]->pData, bob.ppVerifyOpData2[i]->S.dataLenInBytes); } /*************************************************************************** * STEP 6. Setup Alices Decrypt and Diffie Hellman Data for performance *Loop *************************************************************************/ /**************************************************************************/ /* Perform Phase2 setup for Alice */ /**************************************************************************/ status = dhPhase2Setup(alice.ppSecretKeys, alice.ppPhase1, alice.ppPhase2, bob.ppPublicValues, (asym_test_params_t *)setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to setup phase2 for Alice, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /*************************************************************************** * STEP 7 IKE main mode Asymmetric steps **************************************************************************/ /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); memset(setup->performanceStats, 0, sizeof(perf_data_t)); setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); setup->performanceStats->packageId = packageId; /*pre-set the number of ops we plan to submit*/ /*number of responses equals the number of QA APIs we have chained together * multiplied by the number of buffers and how many times we have looped * over the buffers */ setup->performanceStats->numOperations = NUMBER_OF_CHAINED_OPS * (Cpa64U)setup->numBuffers * (Cpa64U)setup->numLoops; setup->performanceStats->averagePacketSizeInBytes = setup->pLenInBytes; setup->performanceStats->responses = 0; /* Completion used in callback */ sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); for (i = 0; i < setup->numLoops; i++) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { /******************************************************************/ /* Step 7a Perform DH phase1 for Alice * This step, performs setup->NumBuffers DH Phase1 * Operations to * Calculate setup->numBuffers Public Values for Alice*/ /******************************************************************/ do { /*****************************************************************/ /* ikeRsaCallback : used in asynchronous mode * performanceStats: Opaque user data * ppPhase1 : Structure containing p, g and x * ppPublicValues : Public value (output) */ /******************************************************************/ status = cpaCyDhKeyGenPhase1(setup->cyInstanceHandle, NULL /*ikeRsaCallback*/, setup->performanceStats, alice.ppPhase1[innerLoop], alice.ppPublicValues[innerLoop]); /*this is a back off mechanism to stop the code * continually submitting requests. Without this the * CPU * can report a soft lockup if it continually loops * on busy*/ if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to complete dhPhase1 for Alice, status: %d\n", status); break; } /******************************************************************/ /* Step 7b Perform RSA verify of third party...normally this is done * on at third party to verify that bob is who he says he * is, but * here we are performing a second RSA encrypt on Bobs * signature to * test the sequence of calls */ /******************************************************************/ do { status = cpaCyDsaVerify(setup->cyInstanceHandle, NULL, setup->performanceStats, bob.ppVerifyOpData[innerLoop], &verifyStatus); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small * break */ if (RETRY_LIMIT == (setup->performanceStats->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed on DSAVerify for Bob using buffer=%d \n ", innerLoop); break; } /*************************************************************** * Step 7c Perform RSA verify of Bobs signed public values. * Bobs Public values and Bobs RSA Signature have been * pre-calculated Bobs signature is in the EncryptOpData * structure, the verified value should match bobsPublic value, * but in this code we don't check if they match **************************************************************/ do { status = cpaCyDsaVerify(setup->cyInstanceHandle, NULL, setup->performanceStats, bob.ppVerifyOpData2[innerLoop], &verifyStatus); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; /*once we get to many retries, perform a context switch * to give the acceleration engine a small * break */ if (RETRY_LIMIT == (setup->performanceStats->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed on DSAVerify for Bob using buffer=%d \n ", innerLoop); break; } /****************************************************************** * Step 7d Sign all of Alices public value buffers, * Alices Public Value is in the Decrypt opData setup, the signature * is placed in alices signature ******************************************************************/ /*status = sampleDsaSign(setup, alice.ppRSSignOpData, alice.ppR, alice.ppS, setup->numBuffers, ONE_LOOP);*/ do { status = cpaCyDsaSignRS(setup->cyInstanceHandle, NULL, setup->performanceStats, alice.ppRSSignOpData[innerLoop], &dsaSignprotocolStatus, alice.ppR[innerLoop], alice.ppS[innerLoop]); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while ((CPA_STATUS_RETRY == status) && ((setup->performanceStats->retries % (RETRY_LIMIT + 1)) <= RETRY_LIMIT)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to complete RsaSign for Alice, status: %d\n", status); ikeDsaMemFree(setup, &alice, &bob); return status; } /******************************************************************/ /* Step 7e Perform the DH phase2 operation for Alice, * using Bobs verified Public values */ do { status = cpaCyDhKeyGenPhase2Secret(setup->cyInstanceHandle, NULL /*ikeRsaCallback*/, setup->performanceStats, alice.ppPhase2[innerLoop], alice.ppSecretKeys[innerLoop]); /*this is a back off mechanism to stop the code * continually calling the Decrypt operation when the * acceleration units are busy. Without this the CPU * can report a soft lockup if it continually loops * on busy*/ if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Diffie Hellman Phase2 for Alice, status: %d\n", status); break; } /*At this point Bob and Alice should have created the same shared * secret key*/ responses++; } /*end innerLoop*/ if (CPA_STATUS_SUCCESS != status) { break; } } /*end numLoops*/ setup->performanceStats->endCyclesTimestamp = sampleCodeTimestamp(); /*if (CPA_STATUS_SUCCESS == status) { if(sampleCodeSemaphoreWait(&setup->performanceStats->comp, SAMPLE_CODE_WAIT_FOREVER) != CPA_STATUS_SUCCESS) { PRINT_ERR("interruption in ike rsa Loop\n"); status = CPA_STATUS_FAIL; } }*/ sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); if (CPA_STATUS_SUCCESS != status) { ikeDsaMemFree(setup, &alice, &bob); return status; } ikeDsaMemFree(setup, &alice, &bob); /*set the total number of responses and requests. */ setup->performanceStats->numOperations = responses * NUMBER_OF_CHAINED_OPS; setup->performanceStats->responses = responses * NUMBER_OF_CHAINED_OPS; return status; } /***************************************************************************** * @ingroup IKE_DSA * * @description * This function prints the IKE-DSA performance stats ******************************************************************************/ static CpaStatus ikeDsaPrintStats(thread_creation_data_t *data) { PRINT("IKE_DSA SIMULATION\n"); PRINT("Modulus Size %17u\n", data->packetSize); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /***************************************************************************** *@ingroup cryptoThreads * * @description * This function sets up an IKE-DSA thread ******************************************************************************/ void ikeDsaPerformance(single_thread_test_data_t *testSetup) { dsa_test_params_t ikeDsaSetup; dsa_test_params_t *setup = (dsa_test_params_t *)testSetup->setupPtr; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; /* This barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*give our thread a unique memory location to store performance stats*/ ikeDsaSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); ikeDsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (cyInstances == NULL) { PRINT_ERR("Error allocating memory for instance handles\n"); ikeDsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); ikeDsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); ikeDsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /*give our thread a unique memory location to store performance stats */ ikeDsaSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; ikeDsaSetup.hashAlg = setup->hashAlg; ikeDsaSetup.pLenInBytes = setup->pLenInBytes; ikeDsaSetup.qLenInBytes = setup->qLenInBytes; ikeDsaSetup.numBuffers = setup->numBuffers; ikeDsaSetup.numLoops = setup->numLoops; ikeDsaSetup.syncMode = setup->syncMode; /*launch function that does all the work*/ status = ikeDsaPerform(&ikeDsaSetup); if (CPA_STATUS_SUCCESS != status) { PRINT("ikeDsa Thread FAILED with status: %d\n", status); ikeDsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)ikeDsaPrintStats; } qaeMemFree((void **)&cyInstances); sampleCodeThreadComplete(testSetup->threadID); } /***************************************************************************** *@ingroup cryptoThreads * * @description * This function needs to be called first to setup an IKE test. * Then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ******************************************************************************/ CpaStatus setupIkeDsaTest(Cpa32U pLenInBits, Cpa32U qLenInBits, sync_mode_t syncMode, Cpa32U numBuffs, Cpa32U numLoops) { /*thread_setup_g is a multi-dimensional array that stores the setup for all * thread variations in an array of characters. we store our test setup at * the start of the second array ie index 0. There maybe multi thread types * (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * asymmetric structure*/ dsa_test_params_t *ikeDsaSetup = NULL; if (MAX_THREAD_VARIATION <= testTypeCount_g) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } if (MAX_SETUP_STRUCT_SIZE_IN_BYTES <= sizeof(dsa_test_params_t)) { PRINT_ERR("Test structure is to big for framework\n"); PRINT_ERR("Size needed: %u, limit %u\n", (Cpa32U)sizeof(dsa_test_params_t), (Cpa32U)MAX_SETUP_STRUCT_SIZE_IN_BYTES); return CPA_STATUS_FAIL; } /*get the pre-allocated memory allocation to store the setup for IKE test*/ ikeDsaSetup = (dsa_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)ikeDsaPerformance; testSetupData_g[testTypeCount_g].packetSize = pLenInBits; /*then we store the test setup in the above location */ if (MODULUS_1024_BIT == pLenInBits && EXPONENT_160_BIT == qLenInBits) { ikeDsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA1; } else if (MODULUS_2048_BIT == pLenInBits && EXPONENT_224_BIT == qLenInBits) { ikeDsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA224; } else if (MODULUS_2048_BIT == pLenInBits && EXPONENT_256_BIT == qLenInBits) { ikeDsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA256; } else if (MODULUS_3072_BIT == pLenInBits && EXPONENT_256_BIT == qLenInBits) { ikeDsaSetup->hashAlg = CPA_CY_SYM_HASH_SHA256; } else { PRINT_ERR("pLen & qLen combination not supported, must be 1024/160 "); PRINT("2048/224, 2048/256 or 3072/256\n"); return CPA_STATUS_FAIL; } ikeDsaSetup->pLenInBytes = pLenInBits / NUM_BITS_IN_BYTE; ikeDsaSetup->qLenInBytes = qLenInBits / NUM_BITS_IN_BYTE; ikeDsaSetup->numBuffers = numBuffs; ikeDsaSetup->numLoops = numLoops; ikeDsaSetup->syncMode = syncMode; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setupIkeDsaTest); cpa_sample_code_ike_rsa_perf.c000066400000000000000000001243541503624047500367120ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_ike_rsa_perf.c * * @ingroup cryptoThreads * * @description * This file contains code which chains QA API functions together to * simulate IKE, over all flow of data is as follows: * * 1. Alice & Bob generate public & private RSA keys * we generated a third RSA key set to act as a trusted third party * 2. Alice & Bob agree on a p & g and generate secret random x * 3. Alice & Bob Perform DH Phase1 to produce Public Value - PV = g^x mod p * 4. Bob Perform DH Phase2 to produce Secret Key SK = alicePV^x mod p * 5. Sign Bobs Public Value using peers public key -> RSA decrypt bobsPV * 6. Setup Alices Decrypt and Diffie Hellman Data for performance Loop * 7. IKE main mode Asymmetric steps * 7a Perform DH phase1 for Alice alicePV = g^x mod p * 7b Perform RSA verify of third party: bobsPV = RSA encrypt bobsSig * 7c Perform RSA verify of Bobs signed public values (same as 7b) * 7d Sign all of Alices public value buffers RSA decrypt alicesPV * 7e Perform the DH phase2 operation for Alice * SK = bobsPV(from 7b)^x mod p * *****************************************************************************/ #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_utils_common.h" /*This is the number of RSA and Diffie Hellman QA APIs chained together in * which performance is measured against*/ #define NUMBER_OF_CHAINED_OPS (5) #define ONE_LOOP (1) #define ONE_BUFFER (1) #define NUMBER_OF_RSA_VERIFIES (2) /* this structure is used to store data required by each client in the ike-rsa * transaction */ typedef struct ike_rsa_client_data_s { CpaFlatBuffer **ppPublicValues; CpaFlatBuffer **ppSecretKeys; CpaCyDhPhase2SecretKeyGenOpData **ppPhase2; CpaCyDhPhase1KeyGenOpData **ppPhase1; CpaCyRsaEncryptOpData **ppEncryptOpData; CpaFlatBuffer **ppPVverifier; CpaCyRsaEncryptOpData **ppEncryptOpData2; CpaFlatBuffer **ppPVverifier2; CpaCyRsaDecryptOpData **ppDecryptOpData; CpaFlatBuffer **ppSignatures; } ike_rsa_client_data_t; void ikeRsaCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut); CpaStatus allocClientMem(asym_test_params_t *setup, ike_rsa_client_data_t *client); /***************************************************************************** * @ingroup IKE_RSA Threads * * @description * Asymmetric callback function: This function is invoked when a * operation has been processed *****************************************************************************/ void ikeRsaCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { processCallback(pCallbackTag); } /***************************************************************************** * @ingroup IKE_RSA * * @description * This function is free an array of operation data structures for * ikersa operations, any memory allocation is freed in * ikeRsaPerform ******************************************************************************/ static void ikeRsaMemFreeRsaData(ike_rsa_client_data_t *client) { if (NULL != client) { if (NULL != client->ppSignatures) { qaeMemFreeNUMA((void **)&client->ppSignatures); } if (NULL != client->ppDecryptOpData) { qaeMemFreeNUMA((void **)&client->ppDecryptOpData); } if (NULL != client->ppEncryptOpData) { qaeMemFreeNUMA((void **)&client->ppEncryptOpData); } if (NULL != client->ppPVverifier) { qaeMemFreeNUMA((void **)&client->ppPVverifier); } if (NULL != client->ppEncryptOpData2) { qaeMemFreeNUMA((void **)&client->ppEncryptOpData2); } if (NULL != client->ppPVverifier2) { qaeMemFreeNUMA((void **)&client->ppPVverifier2); } } } /***************************************************************************** * @ingroup IKE_RSA * * @description * This function frees all the dynamically allocated memory used in the * ikeRsaPerform * Each pointer is checked to see if its null and if not it is free'd, * The underlying free function ensures that when freeing the pointer is reset * to NULL ******************************************************************************/ static void ikeRsaMemFree(asym_test_params_t *setup, ike_rsa_client_data_t *alice, ike_rsa_client_data_t *bob, CpaCyRsaPrivateKey *pPrivateKey[], CpaCyRsaPublicKey *pPublicKey[]) { rsaFreeDataMemory(setup, alice->ppDecryptOpData, alice->ppSignatures, alice->ppEncryptOpData, alice->ppPVverifier); rsaFreeKeyMemory(setup, pPrivateKey, pPublicKey); rsaFreeDataMemory(setup, bob->ppDecryptOpData, bob->ppSignatures, bob->ppEncryptOpData, bob->ppPVverifier); rsaFreeDataMemory( setup, NULL, NULL, bob->ppEncryptOpData2, bob->ppPVverifier2); rsaFreeDataMemory( setup, NULL, NULL, alice->ppEncryptOpData2, alice->ppPVverifier2); /*free the signature pointer arrays because in RSA code this is allocated * as a local variable*/ ikeRsaMemFreeRsaData(alice); ikeRsaMemFreeRsaData(bob); dhMemFreePh1(setup, alice->ppPhase1, alice->ppPublicValues, bob->ppPhase1, bob->ppPublicValues); qaeMemFree((void **)&alice->ppPublicValues); qaeMemFree((void **)&bob->ppPublicValues); qaeMemFree((void **)&alice->ppPhase1); qaeMemFree((void **)&bob->ppPhase1); dhMemFreePh2(setup, alice->ppSecretKeys, alice->ppPhase2, bob->ppSecretKeys, bob->ppPhase2); qaeMemFree((void **)&alice->ppSecretKeys); qaeMemFree((void **)&bob->ppSecretKeys); qaeMemFree((void **)&alice->ppPhase2); qaeMemFree((void **)&bob->ppPhase2); if (NULL != pPrivateKey) { qaeMemFreeNUMA((void **)&pPrivateKey); } if (NULL != pPublicKey) { qaeMemFreeNUMA((void **)&pPublicKey); } } /***************************************************************************** * @ingroup IKE_RSA * * @description * This function allocates the client memory for an IKE-RSA * transaction used in ikeRsaPerform ******************************************************************************/ CpaStatus allocClientMem(asym_test_params_t *setup, ike_rsa_client_data_t *client) { if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppDecryptOpData, setup->numBuffers)) { PRINT_ERR("Could not allocate DecryptOpData\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppEncryptOpData, setup->numBuffers)) { PRINT_ERR("Could not allocate EncryptOpData\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppPVverifier, setup->numBuffers)) { PRINT_ERR("Could not allocate ppPVverifier\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppEncryptOpData2, setup->numBuffers)) { PRINT_ERR("Could not allocate EncryptOpData\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppPVverifier2, setup->numBuffers)) { PRINT_ERR("Could not allocate ppPVverifier\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppPhase1, setup->numBuffers)) { PRINT_ERR("Could not allocate DecryptOpData\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppPhase2, setup->numBuffers)) { PRINT_ERR("Could not allocate DecryptOpData\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppPublicValues, setup->numBuffers)) { PRINT_ERR("Could not allocate ppPublicValues\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfVirtPointers((void **)&client->ppSecretKeys, setup->numBuffers)) { PRINT_ERR("Could not allocate ppSecretKeys\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != allocArrayOfPointers(setup->cyInstanceHandle, (void **)&client->ppSignatures, setup->numBuffers)) { PRINT_ERR("Could not allocate ppSignatures\n"); return CPA_STATUS_FAIL; } /*all allocation was successful if we get to here*/ return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(allocClientMem); /***************************************************************************** * @ingroup IKE_RSA * * @description * This function sets up the QA API asymmetric functions of an IKE * transaction using RSA to sign/verify DH generated keys ******************************************************************************/ static CpaStatus ikeRsaPerform(asym_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; Cpa32U innerLoop = 0; ike_rsa_client_data_t alice = {0}; ike_rsa_client_data_t bob = {0}; CpaCyRsaPrivateKey **pPrivateKey = NULL; CpaCyRsaPublicKey **pPublicKey = NULL; Cpa32U node = 0; Cpa32U packageId = 0; /*functions called in this code over writes the performanceStats->response, * so we use a local counter to count responses */ Cpa32U responses = 0; CpaInstanceInfo2 *instanceInfo2 = NULL; instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } packageId = instanceInfo2->physInstId.packageId; qaeMemFree((void **)&instanceInfo2); status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return status; } /************************************************************************/ /* Allocate all the memory for DH and RSA operations */ /************************************************************************/ /*these macros internally free memory return fail if they fail*/ status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&pPrivateKey, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { return CPA_STATUS_FAIL; } status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&pPublicKey, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { qaeMemFreeNUMA((void **)&pPrivateKey); return CPA_STATUS_FAIL; } /*Allocate for Alice*/ if (CPA_STATUS_SUCCESS != allocClientMem(setup, &alice)) { PRINT_ERR("allocClientMem error\n"); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return CPA_STATUS_FAIL; } /*Allocate for Bob*/ if (CPA_STATUS_SUCCESS != allocClientMem(setup, &bob)) { PRINT_ERR("allocClientMem error\n"); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return CPA_STATUS_FAIL; } /* ************************************************************************* * STEP 1. Alice & Bob generate public & private RSA keys * ************************************************************************/ status = genKeyArray(setup, pPrivateKey, pPublicKey); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error, failed genKeyArray, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /************************************************************************** * STEP 2. Alice & Bob agree on a p & g and generate secret random x **************************************************************************/ status = dhPhase1Setup(setup, alice.ppPhase1, bob.ppPhase1, alice.ppPublicValues, bob.ppPublicValues, pPublicKey); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error, failed dhPhase1Setup, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /************************************************************************** * STEP 3. Alice & Bob Perform DH Phase1 to produce Public Value - * PV = g^x mod p **************************************************************************/ status = dhPhase1(alice.ppPhase1, alice.ppPublicValues, setup, setup->numBuffers, ONE_LOOP); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Error, failed to complete dhPhase1 for Alice, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /**************************************************************************/ /*Perform DH phase1 for Bob */ /**************************************************************************/ status = dhPhase1( bob.ppPhase1, bob.ppPublicValues, setup, setup->numBuffers, ONE_LOOP); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to complete dhPhase1 for Bob, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /**************************************************************************/ /*Perform Phase2 setup for Bob */ /**************************************************************************/ status = dhPhase2Setup(bob.ppSecretKeys, bob.ppPhase1, bob.ppPhase2, alice.ppPublicValues, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to setup phase2 for Bob, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /**************************************************************************/ /*Calculate Bobs secret keys */ /**************************************************************************/ status = dhPhase2Perform( bob.ppSecretKeys, bob.ppPhase2, setup, setup->numBuffers, ONE_LOOP); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to perform phase2 for Bob, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /*************************************************************************** * STEP 5. Sign Bobs Public Value using peers public key -> * Bobs Signature = RSA decrypt bobsPV * ************************************************************************/ /**************************************************************************/ /*Setup the RSA decrypt structure */ /**************************************************************************/ status = rsaDecryptDataSetup( bob.ppPublicValues, bob.ppDecryptOpData, bob.ppSignatures, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed rsaDecryptDataSetup for Bob, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /************************************************************************** * setup encryption, we need an encryptOpData structure, because the * rsaSetOpDataKeys generates a public key and needs to copy it into * an encryptOpData structure **************************************************************************/ status = rsaEncryptDataSetup( bob.ppSignatures, bob.ppEncryptOpData, bob.ppPVverifier, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed rsaEncryptDataSetup for Bob, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } status = rsaEncryptDataSetup( bob.ppSignatures, bob.ppEncryptOpData2, bob.ppPVverifier2, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed rsaEncryptDataSetup for Bob, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /**************************************************************************/ /* Setup decryption opData structure with RSA key */ /**************************************************************************/ rsaSetOpDataKeys(setup, bob.ppDecryptOpData, bob.ppEncryptOpData, pPrivateKey, pPublicKey); rsaSetOpDataKeys(setup, bob.ppDecryptOpData, bob.ppEncryptOpData2, pPrivateKey, pPublicKey); /**************************************************************************/ /* Sign all of Bobs public value buffers, but loop only once */ /**************************************************************************/ status = sampleRsaDecrypt(setup, bob.ppDecryptOpData, bob.ppSignatures, pPrivateKey, pPublicKey, setup->numBuffers, ONE_LOOP); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed sampleRsaDecrypt for Bob, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /* Copy the RSADecrypt output into the Encrypt Op structure * in the performance loop we verify bobs signature. Bobs signature is * the input the the encrypt operation*/ for (i = 0; i < setup->numBuffers; i++) { /*check that the signature is the expected length*/ if (bob.ppEncryptOpData[i]->inputData.dataLenInBytes != bob.ppSignatures[i]->dataLenInBytes) { PRINT_ERR("encrypt data len does not match the signature len\n"); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } memcpy(bob.ppEncryptOpData[i]->inputData.pData, bob.ppSignatures[i]->pData, bob.ppEncryptOpData[i]->inputData.dataLenInBytes); /*check that the signature is the expected length*/ if (bob.ppEncryptOpData2[i]->inputData.dataLenInBytes != bob.ppSignatures[i]->dataLenInBytes) { PRINT_ERR("encrypt data len does not match the signature len\n"); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } memcpy(bob.ppEncryptOpData2[i]->inputData.pData, bob.ppSignatures[i]->pData, bob.ppEncryptOpData2[i]->inputData.dataLenInBytes); } /*************************************************************************** * STEP 6. Setup Alices Decrypt and Diffie Hellman Data for performance Loop * ************************************************************************/ /**************************************************************************/ /* Setup the RSA decrypt structure*/ /**************************************************************************/ status = rsaDecryptDataSetup( alice.ppPublicValues, alice.ppDecryptOpData, alice.ppSignatures, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed rsaDecryptDataSetup for Alice, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return CPA_STATUS_FAIL; } /************************************************************************** * Setup encryption: we need an encryptOpData structure, because the * rsaSetOpDataKeys generates a public key and needs to copy it into * an encryptOpData structure **************************************************************************/ status = rsaEncryptDataSetup( alice.ppSignatures, alice.ppEncryptOpData, alice.ppPVverifier, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed rsaEncryptDataSetup for Alice, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return CPA_STATUS_FAIL; } /**************************************************************************/ /*setup decryption opData structure with RSA key */ /**************************************************************************/ rsaSetOpDataKeys(setup, alice.ppDecryptOpData, alice.ppEncryptOpData, pPrivateKey, pPublicKey); /**************************************************************************/ /* Perform Phase2 setup for Alice */ /**************************************************************************/ status = dhPhase2Setup(alice.ppSecretKeys, alice.ppPhase1, alice.ppPhase2, bob.ppPVverifier, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to setup phase2 for Alice, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /*************************************************************************** * STEP 7 IKE main mode Asymmetric steps **************************************************************************/ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Error, failed to allocate ppPVverifier2, status: %d\n", status); ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); memset(setup->performanceStats, 0, sizeof(perf_data_t)); setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); setup->performanceStats->packageId = packageId; /*pre-set the number of ops we plan to submit*/ /*number of responses equals the number of QA APIs we have chained together * multiplied by the number of buffers and how many times we have looped * over the buffers */ setup->performanceStats->numOperations = (Cpa64U)NUMBER_OF_CHAINED_OPS * setup->numBuffers * setup->numLoops; setup->performanceStats->averagePacketSizeInBytes = setup->modulusSizeInBytes; setup->performanceStats->responses = 0; /* Completion used in callback */ sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); for (i = 0; i < setup->numLoops; i++) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { /******************************************************************/ /* Step 7a Perform DH phase1 for Alice * This step, performs setup->NumBuffers DH Phase1 Operations to * Calculate setup->numBuffers Public Values for Alice*/ /******************************************************************/ do { /*****************************************************************/ /* ikeRsaCallback : used in asynchronous mode * performanceStats: Opaque user data * ppPhase1 : Structure containing p, g and x * ppPublicValues : Public value (output) */ /******************************************************************/ status = cpaCyDhKeyGenPhase1(setup->cyInstanceHandle, NULL /*ikeRsaCallback*/, setup->performanceStats, alice.ppPhase1[innerLoop], alice.ppPublicValues[innerLoop]); /*this is a back off mechanism to stop the code * continually submitting requests. Without this the CPU * can report a soft lockup if it continually loops * on busy*/ if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to complete dhPhase1 for Alice, status: %d\n", status); break; } /******************************************************************/ /* Step 7b Perform RSA verify of third party...normally this is done * on at third party to verify that bob is who he says he is, but * here we are performing a second RSA encrypt on Bobs signature to * test the sequence of calls */ /******************************************************************/ do { status = cpaCyRsaEncrypt(setup->cyInstanceHandle, NULL /*ikeRsaCallback*/, setup->performanceStats, bob.ppEncryptOpData[innerLoop], bob.ppPVverifier[innerLoop]); if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed on RsaVerify for Bob using buffer=%d \n", innerLoop); break; } /*************************************************************** * Step 7c Perform RSA verify of Bobs signed public values. * Bobs Public values and Bobs RSA Signature have been * pre-calculated Bobs signature is in the EncryptOpData * structure, the verifier value should match bobsPublic value, * but in this code we don't check if they match **************************************************************/ do { status = cpaCyRsaEncrypt(setup->cyInstanceHandle, NULL /*ikeRsaCallback*/, setup->performanceStats, bob.ppEncryptOpData2[innerLoop], bob.ppPVverifier2[innerLoop]); if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed on RsaVerify for Bob using buffer=%d \n ", innerLoop); break; } /****************************************************************** * Step 7d Sign all of Alices public value buffers, * Alices Public Value is in the Decrypt opData setup, the signature * is placed in alices signature ******************************************************************/ do { status = cpaCyRsaDecrypt(setup->cyInstanceHandle, NULL /*ikeRsaCallback*/, setup->performanceStats, alice.ppDecryptOpData[innerLoop], alice.ppSignatures[innerLoop]); if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Failed to complete RsaSign for Alice, status: %d\n", innerLoop); break; } /******************************************************************/ /* Step 7e Perform the DH phase2 operation for Alice, * using Bobs verified Public values */ do { status = cpaCyDhKeyGenPhase2Secret(setup->cyInstanceHandle, NULL /*ikeRsaCallback*/, setup->performanceStats, alice.ppPhase2[innerLoop], alice.ppSecretKeys[innerLoop]); /*this is a back off mechanism to stop the code * continually calling the Decrypt operation when the * acceleration units are busy. Without this the CPU * can report a soft lockup if it continually loops * on busy*/ if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Diffie Hellman Phase2 for Alice, status: %d\n", status); break; } /*At this point Bob and Alice should have created the same shared * secret key*/ responses++; } /*end innerLoop*/ if (CPA_STATUS_SUCCESS != status) { break; } } /*end numLoops*/ setup->performanceStats->endCyclesTimestamp = sampleCodeTimestamp(); /*if (CPA_STATUS_SUCCESS == status) { if(sampleCodeSemaphoreWait(&setup->performanceStats->comp, SAMPLE_CODE_WAIT_FOREVER) != CPA_STATUS_SUCCESS) { PRINT_ERR("interruption in ike rsa Loop\n"); status = CPA_STATUS_FAIL; } }*/ sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); if (CPA_STATUS_SUCCESS != status) { ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); return status; } ikeRsaMemFree(setup, &alice, &bob, pPrivateKey, pPublicKey); /*set the total number of responses and requests. */ setup->performanceStats->numOperations = (Cpa64U)responses * NUMBER_OF_CHAINED_OPS; setup->performanceStats->responses = responses * NUMBER_OF_CHAINED_OPS; if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } /***************************************************************************** * @ingroup IKE_RSA * * @description * This function prints the IKE-RSA performance stats ******************************************************************************/ static CpaStatus ikeRsaPrintStats(thread_creation_data_t *data) { PRINT("IKE_RSA SIMULATION\n"); PRINT("Modulus Size %17u\n", data->packetSize); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /***************************************************************************** *@ingroup cryptoThreads * * @description * This function sets up an IKE-RSA thread ******************************************************************************/ static void ikeRsaPerformance(single_thread_test_data_t *testSetup) { asym_test_params_t ikeRsaSetup; asym_test_params_t *setup = (asym_test_params_t *)testSetup->setupPtr; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; /* This barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*give our thread a unique memory location to store performance stats*/ ikeRsaSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); ikeRsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); ikeRsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); ikeRsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); ikeRsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /* give our thread a logical crypto instance to use * use % to wrap around the max number of instances*/ ikeRsaSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; ikeRsaSetup.modulusSizeInBytes = setup->modulusSizeInBytes; ikeRsaSetup.exponentSizeInBytes = setup->exponentSizeInBytes; ikeRsaSetup.numBuffers = setup->numBuffers; ikeRsaSetup.numLoops = setup->numLoops; ikeRsaSetup.rsaKeyRepType = setup->rsaKeyRepType; ikeRsaSetup.syncMode = ASYNC; /*launch function that does all the work*/ status = ikeRsaPerform(&ikeRsaSetup); if (CPA_STATUS_SUCCESS != status) { PRINT("ikeRsa Thread FAILED with status: %d\n", status); ikeRsaSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)ikeRsaPrintStats; } qaeMemFree((void **)&cyInstances); sampleCodeThreadComplete(testSetup->threadID); } /***************************************************************************** *@ingroup cryptoThreads * * @description * This function needs to be called first to setup an IKE test. * Then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ******************************************************************************/ CpaStatus setupIkeRsaTest(Cpa32U modSizeInBits, Cpa32U expSizeInBits, Cpa32U numBuffs, Cpa32U numLoops) { /*thread_setup_g is a multi-dimensional array that stores the setup for all * thread variations in an array of characters. we store our test setup at * the start of the second array ie index 0. There maybe multi thread types * (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * asymmetric structure*/ asym_test_params_t *ikeRsaSetup = NULL; if (MAX_THREAD_VARIATION <= testTypeCount_g) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } if (MAX_SETUP_STRUCT_SIZE_IN_BYTES <= sizeof(asym_test_params_t)) { PRINT_ERR("Test structure is to big for framework\n"); PRINT_ERR("Size needed: %u, limit %u\n", (Cpa32U)sizeof(asym_test_params_t), (Cpa32U)MAX_SETUP_STRUCT_SIZE_IN_BYTES); return CPA_STATUS_FAIL; } /*get the pre-allocated memory allocation to store the setup for IKE test*/ ikeRsaSetup = (asym_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)ikeRsaPerformance; testSetupData_g[testTypeCount_g].packetSize = modSizeInBits; ikeRsaSetup->modulusSizeInBytes = modSizeInBits / NUM_BITS_IN_BYTE; ikeRsaSetup->exponentSizeInBytes = expSizeInBits / NUM_BITS_IN_BYTE; ikeRsaSetup->numBuffers = numBuffs; ikeRsaSetup->numLoops = numLoops; ikeRsaSetup->rsaKeyRepType = CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setupIkeRsaTest); cpa_sample_code_kpt2_common.c000066400000000000000000000476611503624047500365160ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * **************************************************************************/ /*************************************************************************** * @file cpa_sample_code_kpt2_common.c * * This file provides some interface for testing key_protection_technology. * **************************************************************************/ #include "cpa_sample_code_kpt2_common.h" #if CY_API_VERSION_AT_LEAST(3, 0) /*************************************************************************** * @description * * This function is to load encrypted SWKs to QAT * * @param[in] instanceHandle Instance handle * @param[in] encryptedSWK encrypted SWK * @param[out] kptKeyHandle keyhandle * * @detail load 1 SWK, * and expect the results to be successfully * * @retval CPA_STATUS_SUCCESS Load SWK successfully * @retval CPA_STATUS_FAIL Load SWK failed * ***************************************************************************/ CpaStatus kptLoadSWK(CpaInstanceHandle instanceHandle, CpaCyKptHandle *kptKeyHandle, CpaFlatBuffer *encryptedSWK) { CpaStatus status = CPA_STATUS_FAIL; CpaCyKptKeyManagementStatus kptStatus = CPA_CY_KPT_SUCCESS; CpaCyKptLoadKey *pSWKLoadKey = NULL; Cpa32U node = 0; Cpa32U keyProvisionRetryTimes = 0; status = sampleCodeCyGetNode(instanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Get nodeId failed!\n"); return status; } pSWKLoadKey = qaeMemAllocNUMA(sizeof(CpaCyKptLoadKey), node, BYTE_ALIGNMENT_64); if (NULL == pSWKLoadKey) { return CPA_STATUS_FAIL; } pSWKLoadKey->wrappingAlgorithm = CPA_CY_KPT_WRAPPING_KEY_TYPE_AES256_GCM; pSWKLoadKey->eSWK.pData = qaeMemAllocNUMA(encryptedSWK->dataLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pSWKLoadKey->eSWK.pData) { qaeMemFreeNUMA((void **)&pSWKLoadKey); return CPA_STATUS_FAIL; } pSWKLoadKey->eSWK.dataLenInBytes = encryptedSWK->dataLenInBytes; memcpy(pSWKLoadKey->eSWK.pData, encryptedSWK->pData, encryptedSWK->dataLenInBytes); do { status = cpaCyKptLoadKey( instanceHandle, pSWKLoadKey, kptKeyHandle, &kptStatus); usleep(KEY_PROVISION_RETRY_DELAY_MS * 1000); keyProvisionRetryTimes++; } while ((CPA_STATUS_RETRY == status) && (keyProvisionRetryTimes <= KEY_PROVISION_RETRY_TIMES_LIMIT)); if (1 < keyProvisionRetryTimes) { PRINT("KPT Load Key Retry Times : %d\n", keyProvisionRetryTimes - 1); } if (CPA_STATUS_SUCCESS == status) { if (CPA_CY_KPT_SUCCESS != kptStatus) { PRINT_ERR("Check CPA_CY_KPT_SUCCESS failed.\n"); status = CPA_STATUS_FAIL; } } else { PRINT_ERR("cpaCyKptLoadKey failed with status:%d.\n", status); } if (NULL != pSWKLoadKey) { if (NULL != pSWKLoadKey->eSWK.pData) { qaeMemFreeNUMA((void **)&pSWKLoadKey->eSWK.pData); } qaeMemFreeNUMA((void **)&pSWKLoadKey); } return status; } EXPORT_SYMBOL(kptLoadSWK); /*************************************************************************** * @description * * This function is to encrypt SWKs. * * @param[in] instanceHandle Instance Handle * @param[in] sampleSWK SWK * @param[out] encryptedSWK encrypted SWK * * @retval CPA_STATUS_SUCCESS Setup successfully * @retval CPA_STATUS_FAIL Setup failed ***************************************************************************/ CpaStatus kptEncryptSWK(CpaInstanceHandle instanceHandle, Cpa8U *sampleSWK, CpaFlatBuffer **encryptedSWK) { CpaStatus status = CPA_STATUS_FAIL; CpaCyKptValidationKey *pPerPartPublicKeyData = NULL; EVP_PKEY *pPubKey = NULL; EVP_PKEY_CTX *pCtx = NULL; #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) BN_CTX *pBn_ctx = NULL; OSSL_PARAM_BLD *pBld = NULL; BIGNUM *pE_bn = NULL; BIGNUM *pN_bn = NULL; OSSL_PARAM *pParams = NULL; #else #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) CpaBoolean retStatus = CPA_TRUE; RSA *pKey = NULL; #endif #endif int ret = 0; CpaCyKptKeyManagementStatus kptStatus = CPA_CY_KPT_SUCCESS; Cpa32U node = 0; Cpa32U keyProvisionRetryTimes = 0; status = sampleCodeCyGetNode(instanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Get node ID failed!\n"); return status; } pPerPartPublicKeyData = qaeMemAllocNUMA(sizeof(CpaCyKptValidationKey), node, BYTE_ALIGNMENT_64); if (NULL == pPerPartPublicKeyData) { status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { /*get I-PuK*/ pPerPartPublicKeyData->publicKey.modulusN.dataLenInBytes = CPA_CY_RSA3K_SIG_SIZE_INBYTES; pPerPartPublicKeyData->publicKey.publicExponentE.dataLenInBytes = PER_PART_PKEY_E_SIZE; pPerPartPublicKeyData->publicKey.modulusN.pData = qaeMemAllocNUMA(sizeof(Cpa8U) * CPA_CY_RSA3K_SIG_SIZE_INBYTES, node, BYTE_ALIGNMENT_64); pPerPartPublicKeyData->publicKey.publicExponentE.pData = qaeMemAllocNUMA( sizeof(Cpa8U) * PER_PART_PKEY_E_SIZE, node, BYTE_ALIGNMENT_64); if ((NULL == pPerPartPublicKeyData->publicKey.modulusN.pData) || (NULL == pPerPartPublicKeyData->publicKey.publicExponentE.pData)) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { do { status = cpaCyKptQueryDeviceCredentials( instanceHandle, pPerPartPublicKeyData, &kptStatus); usleep(KEY_PROVISION_RETRY_DELAY_MS * 1000); keyProvisionRetryTimes++; } while ((CPA_STATUS_RETRY == status) && (keyProvisionRetryTimes <= KEY_PROVISION_RETRY_TIMES_LIMIT)); if (1 < keyProvisionRetryTimes) { PRINT("KPT Get I-Pu Retry Times : %d\n", keyProvisionRetryTimes - 1); } if (CPA_STATUS_SUCCESS != status || CPA_CY_KPT_SUCCESS != kptStatus) { PRINT_ERR("Get I-Pu failed with status: %d,kptStatus: %d\n", status, kptStatus); status = CPA_STATUS_FAIL; } } #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) if (CPA_STATUS_SUCCESS == status) { pBn_ctx = BN_CTX_new(); pBld = OSSL_PARAM_BLD_new(); if ((NULL == pBn_ctx) || (NULL == pBld)) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { pN_bn = BN_CTX_get(pBn_ctx); pE_bn = BN_CTX_get(pBn_ctx); if ((NULL == pN_bn) || (NULL == pE_bn)) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { BN_bin2bn(pPerPartPublicKeyData->publicKey.modulusN.pData, pPerPartPublicKeyData->publicKey.modulusN.dataLenInBytes, pN_bn); OSSL_PARAM_BLD_push_BN(pBld, "n", pN_bn); BN_bin2bn( pPerPartPublicKeyData->publicKey.publicExponentE.pData, pPerPartPublicKeyData->publicKey.publicExponentE.dataLenInBytes, pE_bn); OSSL_PARAM_BLD_push_BN(pBld, "e", pE_bn); pParams = OSSL_PARAM_BLD_to_param(pBld); if (NULL == pParams) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { pCtx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); if (NULL == pCtx) { PRINT_ERR("Allocates generate key context failed!\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { EVP_PKEY_fromdata_init(pCtx); EVP_PKEY_fromdata(pCtx, &pPubKey, EVP_PKEY_PUBLIC_KEY, pParams); EVP_PKEY_CTX_free(pCtx); pCtx = EVP_PKEY_CTX_new(pPubKey, NULL); if (NULL == pCtx) { PRINT_ERR("Allocates public key algorithm context failed!\n"); status = CPA_STATUS_FAIL; } } #else #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) if (CPA_STATUS_SUCCESS == status) { pKey = RSA_new(); pPubKey = EVP_PKEY_new(); if (NULL == pKey) { status = CPA_STATUS_FAIL; } else if (NULL == pPubKey) { RSA_free(pKey); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /*-----set public key with n and e-----*/ retStatus = RSA_set0_key( pKey, BN_bin2bn(pPerPartPublicKeyData->publicKey.modulusN.pData, pPerPartPublicKeyData->publicKey.modulusN.dataLenInBytes, NULL), BN_bin2bn( pPerPartPublicKeyData->publicKey.publicExponentE.pData, pPerPartPublicKeyData->publicKey.publicExponentE.dataLenInBytes, NULL), NULL); if (CPA_TRUE != retStatus) { PRINT_ERR("RSA_set0_key failed \n"); RSA_free(pKey); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { EVP_PKEY_assign_RSA(pPubKey, pKey); pCtx = EVP_PKEY_CTX_new(pPubKey, NULL); if (NULL == pCtx) { PRINT_ERR("Allocates public key algorithm context failed!\n"); status = CPA_STATUS_FAIL; } } #endif #endif // #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) if (CPA_STATUS_SUCCESS == status) { if (EVP_PKEY_encrypt_init(pCtx) > 0) { EVP_PKEY_CTX_ctrl_str(pCtx, "rsa_padding_mode", "oaep"); EVP_PKEY_CTX_ctrl_str(pCtx, "rsa_oaep_md", "sha256"); EVP_PKEY_CTX_ctrl_str(pCtx, "rsa_mgf1_md", "sha256"); } else { PRINT_ERR("Initializes a public key algorithm context failed!\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { /*encrypt SWK*/ (*encryptedSWK)->pData = qaeMemAlloc( pPerPartPublicKeyData->publicKey.modulusN.dataLenInBytes + pPerPartPublicKeyData->publicKey.publicExponentE.dataLenInBytes); if (NULL == (*encryptedSWK)->pData) { PRINT_ERR("qaeMemAlloc error\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { (*encryptedSWK)->dataLenInBytes = pPerPartPublicKeyData->publicKey.modulusN.dataLenInBytes + pPerPartPublicKeyData->publicKey.publicExponentE.dataLenInBytes; ret = EVP_PKEY_encrypt(pCtx, (*encryptedSWK)->pData, (size_t *)&((*encryptedSWK)->dataLenInBytes), sampleSWK, SWK_LEN_IN_BYTES); if ((ret <= 0) || (0 == (*encryptedSWK)->dataLenInBytes) || ((*encryptedSWK)->dataLenInBytes > (pPerPartPublicKeyData->publicKey.modulusN.dataLenInBytes + pPerPartPublicKeyData->publicKey.publicExponentE.dataLenInBytes))) { PRINT_ERR("Encrypt SWK failed!\n"); qaeMemFree((void **)&((*encryptedSWK)->pData)); status = CPA_STATUS_FAIL; } } #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) if (NULL != pBn_ctx) { BN_CTX_free(pBn_ctx); } if (NULL != pBld) { OSSL_PARAM_BLD_free(pBld); } if (NULL != pParams) { OSSL_PARAM_free(pParams); } #endif if (NULL != pCtx) { EVP_PKEY_CTX_free(pCtx); } if (NULL != pPubKey) { EVP_PKEY_free(pPubKey); } if (NULL != pPerPartPublicKeyData) { if (NULL != pPerPartPublicKeyData->publicKey.modulusN.pData) { qaeMemFreeNUMA( (void **)&pPerPartPublicKeyData->publicKey.modulusN.pData); } if (NULL != pPerPartPublicKeyData->publicKey.publicExponentE.pData) { qaeMemFreeNUMA((void **)&pPerPartPublicKeyData->publicKey .publicExponentE.pData); } qaeMemFreeNUMA((void **)&pPerPartPublicKeyData); } return status; } EXPORT_SYMBOL(kptEncryptSWK); /*************************************************************************** * @description * * This function is to encrypt SWKs and load encrypted SWK to QAT * * @param[in] instanceHandle Instance handle * @param[in] sampleSWK SWK * @param[out] kptKeyHandle key handle * * @detail Encrypt and load 1 SWK, * and expect the results to be SC_LOAD_SWK_SUCCESS * * @retval CPA_STATUS_SUCCESS Load SWK successfully * @retval CPA_STATUS_FAIL Load SWK failed * ***************************************************************************/ CpaStatus encryptAndLoadSWK(CpaInstanceHandle instanceHandle, CpaCyKptHandle *kptKeyHandle, Cpa8U *sampleSWK) { CpaStatus status = CPA_STATUS_SUCCESS; CpaFlatBuffer *encryptedSWK = NULL; /*encrypt SWK*/ encryptedSWK = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == encryptedSWK) { PRINT_ERR("qaeMemAlloc error\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { status = kptEncryptSWK(instanceHandle, sampleSWK, &encryptedSWK); } if (CPA_STATUS_SUCCESS == status) { /*Load SWKs*/ status = kptLoadSWK(instanceHandle, kptKeyHandle, encryptedSWK); } if (NULL != encryptedSWK) { qaeMemFree((void **)&encryptedSWK); } return status; } EXPORT_SYMBOL(encryptAndLoadSWK); /*************************************************************************** * @description * * This function is to encrypt customer private key by AES-256-GCM * * @param[in] pPrivateKey customer private key * @param[in] privateKeyLength customer private key length * @param[in] pSWK SWK * @param[in] pIv iv * @param[in] ivLength iv length * @param[in] pAad Additional Authenticated Data * @param[in] aadLenInBytes the length of aad * @param[out] pWrappedPrivateKey wrapped private key * @param[out] pWPKLenth wrapped private key length * @param[out] pAuthTag Authentication tag (16 Bytes) * * @retval 1 Operation is successful * @retval 0 Operation is failure ***************************************************************************/ CpaBoolean encryptPrivateKey(Cpa8U *pPrivateKey, Cpa32U privateKeyLength, Cpa8U *pSWK, Cpa8U *pIv, Cpa32U ivLength, Cpa8U *pWrappedPrivateKey, Cpa32U *pWPKLenth, Cpa8U *pAuthTag, Cpa8U *pAad, Cpa32U aadLenInBytes) { EVP_CIPHER_CTX *pCtx; Cpa32U outputLength; Cpa32U cipherTestLen; CpaBoolean status = CPA_TRUE; if (!(pCtx = EVP_CIPHER_CTX_new())) { PRINT_ERR("EVP_CIPHER_CTX_new() failed\n"); return CPA_FALSE; } if (EVP_EncryptInit_ex(pCtx, EVP_aes_256_gcm(), NULL, NULL, NULL) == 0) { PRINT_ERR("EVP_EncryptInit_ex() failed\n"); EVP_CIPHER_CTX_free(pCtx); return CPA_FALSE; } if (EVP_CIPHER_CTX_ctrl(pCtx, EVP_CTRL_GCM_SET_IVLEN, ivLength, NULL) == 0) { PRINT_ERR("EVP_CIPHER_CTX_ctrl() failed\n"); EVP_CIPHER_CTX_free(pCtx); return CPA_FALSE; } if (EVP_EncryptInit_ex(pCtx, NULL, NULL, pSWK, pIv) == 0) { PRINT_ERR("EVP_EncryptInit_ex() failed\n"); EVP_CIPHER_CTX_free(pCtx); return CPA_FALSE; } if (EVP_EncryptUpdate( pCtx, NULL, (int *)&outputLength, pAad, aadLenInBytes) == 0) { PRINT_ERR("EVP_EncryptUpdate() failed\n"); EVP_CIPHER_CTX_free(pCtx); return CPA_FALSE; } if (EVP_EncryptUpdate(pCtx, pWrappedPrivateKey, (int *)&outputLength, pPrivateKey, privateKeyLength) == 0) { PRINT_ERR("EVP_EncryptUpdate() failed\n"); EVP_CIPHER_CTX_free(pCtx); return CPA_FALSE; } cipherTestLen = outputLength; if (EVP_EncryptFinal_ex( pCtx, pWrappedPrivateKey + outputLength, (int *)&outputLength) == 0) { PRINT_ERR("EVP_EncryptFinal_ex() failed\n"); EVP_CIPHER_CTX_free(pCtx); return CPA_FALSE; } if (EVP_CIPHER_CTX_ctrl( pCtx, EVP_CTRL_GCM_GET_TAG, AUTH_TAG_LEN_IN_BYTES, pAuthTag) == 0) { PRINT_ERR("EVP_CIPHER_CTX_ctrl() failed\n"); EVP_CIPHER_CTX_free(pCtx); return CPA_FALSE; } EVP_CIPHER_CTX_free(pCtx); cipherTestLen += outputLength; *pWPKLenth = cipherTestLen; return status; } EXPORT_SYMBOL(encryptPrivateKey); #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ cpa_sample_code_kpt2_common.h000066400000000000000000000104201503624047500365020ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_KPT2_COMMON_H #define CPA_SAMPLE_CODE_KPT2_COMMON_H #include #include #include #include #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) #include #endif #include "cpa_cy_kpt.h" #include "cpa_sample_code_crypto_utils.h" #if CY_API_VERSION_AT_LEAST(3, 0) #define AUTH_TAG_LEN_IN_BYTES 16 #define IV_LEN_IN_BYTES 12 #define MAX_SWK_PER_PHYSICAL_DEVICE 128 #define SWK_LEN_IN_BYTES 32 #define NUM_OF_SWK_ONLY_ONE 1 #define PER_PART_PKEY_E_SIZE 8 #define NUM_KEY_PAIRS (2) #define KEY_PROVISION_RETRY_TIMES_LIMIT 20 #define KEY_PROVISION_RETRY_DELAY_MS 300 /* KPT Stolen Key Test */ CpaStatus encryptAndLoadSWK(CpaInstanceHandle instanceHandle, CpaCyKptHandle *kptKeyHandle, Cpa8U *sampleSWK); CpaBoolean encryptPrivateKey(Cpa8U *pPrivateKey, Cpa32U privateKeyLength, Cpa8U *pSWK, Cpa8U *pIv, Cpa32U ivLength, Cpa8U *pWrappedPrivateKey, Cpa32U *pWPKLenth, Cpa8U *pAuthTag, Cpa8U *pAad, Cpa32U aadLenInBytes); #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #endif /* CPA_SAMPLE_CODE_KPT2_COMMON_H */ cpa_sample_code_nrbg_perf.c000066400000000000000000000422031503624047500362150ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_nrbg_sample.c * * @ingroup sampleNrbgFunctional * * @description * This is sample code that implements the NRBG-registered functions. This * also implements the GetEntropy and HealthTest functions using NRGB API. * *****************************************************************************/ #include "cpa_sample_code_nrbg_perf.h" /** ***************************************************************************** * @ingroup sampleNrbgFunctional * NRBG Internal Callback Function * * @description * This is an internal callback function that will be used to signal * the caller that the asynchronous operation is completed. The signal * is performed by calling the client-supplied callback function. * * @see * IcpSalDrbgGetEntropyInputCbFunc * *****************************************************************************/ static void nrbgPerformCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { processCallback(pCallbackTag); } static void nrbgMemFree(nrbg_test_params_t *setup, CpaFlatBuffer *pEntropy, CpaCyNrbgOpData **pOpData) { Cpa32U k = 0; /*free verify opData*/ if (NULL != pOpData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != pEntropy && NULL != pEntropy[k].pData) { qaeMemFreeNUMA((void **)&pEntropy[k].pData); } if (NULL != pOpData[k]) { qaeMemFree((void **)&pOpData[k]); } } } qaeMemFreeNUMA((void **)&pEntropy); qaeMemFreeNUMA((void **)&pOpData); } /** ***************************************************************************** * @ingroup sampleNrbgFunctional * NRBG Get Entropy Function * * @description * This function implements the DRBG implementation-specific * 'Get Entropy Input' function by calling cpaCyNrbgGetEntropy API. * * @see * IcpSalDrbgGetEntropyInputFunc * *****************************************************************************/ static CpaStatus nrbgPerform(nrbg_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; CpaStatus status = CPA_STATUS_FAIL; /*pointer to Entropy Buffer*/ CpaFlatBuffer *pEntropy = NULL; /*array of pointers to the operation data structure for each * operation*/ CpaCyNrbgOpData **opData = NULL; /*variable to store what cpu thread is running on*/ Cpa32U node = 0; /*pointer to location to store performance data*/ perf_data_t *pNrbgData = NULL; CpaCyGenFlatBufCbFunc cbFunc = NULL; /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } if (0 == setup->nLenInBytes) { PRINT_ERR("Invalid parameter -- nLenInBytes\n"); return CPA_STATUS_INVALID_PARAM; } if (0 == setup->numLoops) { PRINT_ERR("Invalid parameter -- numLoops\n"); return CPA_STATUS_INVALID_PARAM; } if (0 == setup->numBuffers) { PRINT_ERR("Invalid parameter -- numBuffers\n"); return CPA_STATUS_INVALID_PARAM; } /*get memory location to write performance stats to*/ pNrbgData = setup->performanceStats; memset(pNrbgData, 0, sizeof(perf_data_t)); /*get the number of operations to be done in this test*/ pNrbgData->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; pNrbgData->responses = 0; /* Initialize semaphore used in callback */ sampleCodeSemaphoreInit(&pNrbgData->comp, 0); /*verify the signatures to the messages*/ status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&opData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("opData mem allocation error\n"); return CPA_STATUS_FAIL; } pEntropy = qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == pEntropy) { PRINT_ERR("pEntropy mem allocation error\n"); nrbgMemFree(setup, NULL, opData); return CPA_STATUS_FAIL; } memset(pEntropy, 0, sizeof(CpaFlatBuffer) * setup->numBuffers); /*allocate and populate all the CpaCyNrbgOpData buffers*/ for (i = 0; i < setup->numBuffers; i++) { opData[i] = qaeMemAlloc(sizeof(CpaCyNrbgOpData)); if (NULL == opData[i]) { PRINT_ERR("opData[%u] memory allocation error\n", i); nrbgMemFree(setup, pEntropy, opData); return status; } memset(opData[i], 0, sizeof(CpaCyNrbgOpData)); pEntropy[i].pData = qaeMemAllocNUMA(setup->nLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pEntropy[i].pData) { PRINT_ERR("pEntropy.pData memory allocation error\n"); qaeMemFreeNUMA((void **)&pEntropy[i].pData); return CPA_STATUS_FAIL; } opData[i]->lengthInBytes = setup->nLenInBytes; pEntropy[i].dataLenInBytes = setup->nLenInBytes; } /*this barrier will wait until all threads get to this point*/ /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = nrbgPerformCallback; } sampleCodeBarrier(); /*record the start time, the callback measures the end time when the last * response is received*/ pNrbgData->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { for (i = 0; i < setup->numBuffers; i++) { pNrbgData->numOperations = 1; pNrbgData->responses = 0; do { status = cpaCyNrbgGetEntropy(setup->cyInstanceHandle, cbFunc, pNrbgData, opData[i], &pEntropy[i]); if (CPA_STATUS_RETRY == status) { pNrbgData->retries++; /*if the acceleration engine is busy pause for a * moment by making a context switch*/ if (RETRY_LIMIT == (pNrbgData->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR(" NRBG function failed with status:%d\n", status); nrbgMemFree(setup, pEntropy, opData); return status; } if (CPA_STATUS_SUCCESS == status) { status = waitForResponses(pNrbgData, setup->syncMode, 1, 1); } } /*end buffers loop */ } /* end of numLoops loop*/ pNrbgData->numOperations = (Cpa64U)setup->numLoops * setup->numBuffers; pNrbgData->responses = pNrbgData->numOperations; sampleCodeSemaphoreDestroy(&pNrbgData->comp); /*Free all memory*/ if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } /*************************************************************************** * @ingroup cryptoThreads * * @description * Print the performance stats of the elliptic curve dsa operations ***************************************************************************/ static CpaStatus nrbgPrintStats(thread_creation_data_t *data) { PRINT("NRBG\n"); PRINT("NRBG Size %23u\n", data->packetSize); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } /*************************************************************************** * @ingroup cryptoThreads * * @description * setup an elliptic curve performance thread ***************************************************************************/ static void nrbgPerformance(single_thread_test_data_t *testSetup) { nrbg_test_params_t nrbgSetup; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaStatus status = CPA_STATUS_FAIL; Cpa32U continousRngTestFailures = 0; nrbg_test_params_t *params = (nrbg_test_params_t *)testSetup->setupPtr; /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call * startThreads anyway*/ startBarrier(); /*give our thread a unique memory location to store performance stats*/ nrbgSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); nrbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); nrbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); nrbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); nrbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /* give our thread a logical crypto instance to use * use % to wrap around the max number of instances*/ nrbgSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; nrbgSetup.nLenInBytes = params->nLenInBytes; nrbgSetup.numBuffers = params->numBuffers; nrbgSetup.numLoops = params->numLoops; nrbgSetup.syncMode = params->syncMode; /*launch function that does all the work*/ status = icp_sal_nrbgHealthTest(nrbgSetup.cyInstanceHandle, &continousRngTestFailures); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("icp_sal_nrbgHealthTest failed. (status = %d)\n", status); nrbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } /* * In this sample code, continousRngTestFailures is printed for * debug purposes only. Refer to icp_sal_nrbgHealthTest API for * more details about this counter. */ /*PRINT("continousRngTestFailures = %d\n", continousRngTestFailures);*/ status = nrbgPerform(&nrbgSetup); if (CPA_STATUS_SUCCESS != status) { PRINT("NRBG Thread %u FAILED\n", testSetup->logicalQaInstance); nrbgSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)nrbgPrintStats; } qaeMemFree((void **)&cyInstances); sampleCodeThreadComplete(testSetup->threadID); } /*************************************************************************** * @ingroup cryptoThreads * * @description * This function is used to set the parameters to be used in the *Non-Deterministic * Random Bit Generation Sample Code performance thread. It is called *before the * createThreads function of the framework. The framework replicates it *across many * cores ***************************************************************************/ CpaStatus setupNrbgTest(Cpa32U nLenInBytes, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops) { /* testSetupData_g is a multi-dimensional array that stores the setup for * all thread variations in an array of characters. we store our test setup * at the start of the second array ie index 0. There maybe multi thread * types (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure*/ nrbg_test_params_t *nrbgSetup = NULL; Cpa8S name[] = {'N', 'R', 'B', '\0'}; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); nrbgSetup = (nrbg_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)nrbgPerformance; testSetupData_g[testTypeCount_g].packetSize = nLenInBytes; nrbgSetup->nLenInBytes = nLenInBytes; nrbgSetup->syncMode = syncMode; nrbgSetup->numBuffers = numBuffers; nrbgSetup->numLoops = numLoops; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setupNrbgTest); cpa_sample_code_nrbg_perf.h000066400000000000000000000110141503624047500362160ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file cpa_sample_code_nrbg_perf.h * * @defgroup sampleNrbgFunctional * * @ingroup sampleCode * * @description * Non-Deterministic Random Bit Generation Performance Sample Code *functions. * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_NRBG_PERF_H #define CPA_SAMPLE_CODE_NRBG_PERF_H #include "cpa_sample_code_crypto_utils.h" #include "cpa_cy_nrbg.h" #include "icp_sal_nrbg_ht.h" #include "cpa.h" /************************************************************************* * @ingroup sampleNrbgFunctional * * @description * This function starts the crypto instance and registers NRBG * functions. * * @param[in] syncMode Sync Mode of the test: async and sync * @param[in] nLenInBytes Data length of Non-Deterministic Random Bit * Generation, unit is byte, must be more than 0. * @param[in] numBuffers The number of buffers List,a minimum * @param[in] numLoops The number of Loops * @context * This functions is called from the user process context * * @assumptions * None * @sideEffects * None * @reentrant * No * @threadSafe * Yes * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * *************************************************************************/ CpaStatus setupNrbgTest(Cpa32U nLenInBytes, sync_mode_t syncMode, Cpa32U numBuffers, Cpa32U numLoops); #endif cpa_sample_code_rsa_kpt2_perf.c000066400000000000000000000606141503624047500370200ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * **************************************************************************/ /*************************************************************************** * @file cpa_sample_code_rsa_kpt2_perf.c * * This file provides some interface for kpt2 RSA performance test. * **************************************************************************/ #include "cpa_sample_code_rsa_kpt2_perf.h" #if CY_API_VERSION_AT_LEAST(3, 0) void kptFreeRSAOPDataMemory(CpaCyKptRsaDecryptOpData *pKPTDecryptOpData, CpaFlatBuffer *pWpkAndAuthTag, CpaFlatBuffer *pPrivateKeyOfType1, CpaFlatBuffer *pPrivateKeyOfType2) { if (NULL != pKPTDecryptOpData->inputData.pData) qaeMemFreeNUMA((void **)&pKPTDecryptOpData->inputData.pData); if (NULL != pKPTDecryptOpData->pRecipientPrivateKey->privateKeyRep1 .privateKey.pData) qaeMemFreeNUMA((void **)&pKPTDecryptOpData->pRecipientPrivateKey ->privateKeyRep1.privateKey.pData); if (NULL != pKPTDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .privateKey.pData) qaeMemFreeNUMA((void **)&pKPTDecryptOpData->pRecipientPrivateKey ->privateKeyRep2.privateKey.pData); qaeMemFreeNUMA((void **)&pKPTDecryptOpData->pRecipientPrivateKey); qaeMemFreeNUMA((void **)&pKPTDecryptOpData); if (NULL != pWpkAndAuthTag) { if (NULL != pWpkAndAuthTag->pData) qaeMemFreeNUMA((void **)&pWpkAndAuthTag->pData); qaeMemFree((void **)&pWpkAndAuthTag); } if (NULL != pPrivateKeyOfType1) { if (NULL != pPrivateKeyOfType1->pData) qaeMemFreeNUMA((void **)&pPrivateKeyOfType1->pData); qaeMemFree((void **)&pPrivateKeyOfType1); } if (NULL != pPrivateKeyOfType2) { if (NULL != pPrivateKeyOfType2->pData) qaeMemFreeNUMA((void **)&pPrivateKeyOfType2->pData); qaeMemFree((void **)&pPrivateKeyOfType2); } return; } EXPORT_SYMBOL(kptFreeRSAOPDataMemory); /*************************************************************************** * @description * * This function is to set Kpt Rsa Decrypt OpData * * @param[in] instanceHandle instanceHandle * @param[in] pDecryptOpData Unwrapped Decrypt OpData * @param[in] pRsaPublicKey RSA public key * @param[in] node node * @param[in] pSampleSWK SWK * @param[in] pIv iv * @param[in] pAad Additional Authenticated Data * @param[in] aadLenInBytes the length of aad * @param[out] pKPTDecryptOpData Kpt Rsa Decrypt OpData * * @retval CPA_STATUS_SUCCESS Operation is successful * @retval CPA_STATUS_FAIL Operation is failure ***************************************************************************/ CpaStatus setKpt2RsaDecryptOpData(CpaInstanceHandle instanceHandle, CpaCyKptRsaDecryptOpData **pKPTDecryptOpData, CpaCyRsaDecryptOpData *pDecryptOpData, CpaCyRsaPublicKey *pRsaPublicKey, Cpa32U node, Cpa8U *pSampleSWK, Cpa8U *pIv, Cpa8U *pAad, Cpa32U aadLenInBytes) { CpaBoolean status = CPA_TRUE; Cpa32U wpkSize = 0; Cpa8U pAuthTag[AUTH_TAG_LEN_IN_BYTES] = {0}; CpaFlatBuffer *pWpkAndAuthTag = NULL; CpaFlatBuffer *pPrivateKeyOfType1 = NULL; CpaFlatBuffer *pPrivateKeyOfType2 = NULL; CpaCyKptRsaDecryptOpData *pKptDecOpdata = NULL; pKptDecOpdata = qaeMemAllocNUMA( sizeof(CpaCyKptRsaDecryptOpData), node, BYTE_ALIGNMENT_64); if (NULL == pKptDecOpdata) { PRINT_ERR("qaeMemAllocNUMA pKptDecOpdata error\n"); return CPA_STATUS_FAIL; } pKptDecOpdata->pRecipientPrivateKey = qaeMemAllocNUMA(sizeof(CpaCyKptRsaPrivateKey), node, BYTE_ALIGNMENT_64); if (NULL == pKptDecOpdata->pRecipientPrivateKey) { PRINT_ERR( "qaeMemAllocNUMA pKPTDecryptOpData->pRecipientPrivateKey error\n"); qaeMemFreeNUMA((void **)&pKptDecOpdata); return CPA_STATUS_FAIL; } pPrivateKeyOfType1 = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pPrivateKeyOfType1) { PRINT_ERR("qaeMemAlloc pPrivateKeyOfType1 error\n"); qaeMemFreeNUMA((void **)&(pKptDecOpdata->pRecipientPrivateKey)); qaeMemFreeNUMA((void **)&pKptDecOpdata); return CPA_STATUS_FAIL; } pPrivateKeyOfType2 = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pPrivateKeyOfType2) { PRINT_ERR("qaeMemAlloc pPrivateKeyOfType2 error\n"); qaeMemFree((void **)&pPrivateKeyOfType1); qaeMemFreeNUMA((void **)&(pKptDecOpdata->pRecipientPrivateKey)); qaeMemFreeNUMA((void **)&pKptDecOpdata); return CPA_STATUS_FAIL; } pWpkAndAuthTag = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pWpkAndAuthTag) { PRINT_ERR("qaeMemAlloc pWpkAndAuthTag error\n"); qaeMemFree((void **)&pPrivateKeyOfType1); qaeMemFree((void **)&pPrivateKeyOfType2); qaeMemFreeNUMA((void **)&(pKptDecOpdata->pRecipientPrivateKey)); qaeMemFreeNUMA((void **)&pKptDecOpdata); return CPA_STATUS_FAIL; } if (CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 == pDecryptOpData->pRecipientPrivateKey->privateKeyRepType) { pPrivateKeyOfType1->dataLenInBytes = pDecryptOpData->pRecipientPrivateKey->privateKeyRep1 .privateExponentD.dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep1.modulusN .dataLenInBytes; pPrivateKeyOfType1->pData = qaeMemAllocNUMA( pPrivateKeyOfType1->dataLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pPrivateKeyOfType1->pData) { PRINT_ERR("qaeMemAlloc pPrivateKeyOfType1->pData error\n"); kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2); return CPA_STATUS_FAIL; } memset( pPrivateKeyOfType1->pData, 0, pPrivateKeyOfType1->dataLenInBytes); memcpy(pPrivateKeyOfType1->pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep1 .privateExponentD.pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep1 .privateExponentD.dataLenInBytes); memcpy( pPrivateKeyOfType1->pData + pDecryptOpData->pRecipientPrivateKey->privateKeyRep1 .privateExponentD.dataLenInBytes, pDecryptOpData->pRecipientPrivateKey->privateKeyRep1.modulusN.pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep1.modulusN .dataLenInBytes); pWpkAndAuthTag->dataLenInBytes = pPrivateKeyOfType1->dataLenInBytes + AUTH_TAG_LEN_IN_BYTES; pWpkAndAuthTag->pData = qaeMemAllocNUMA( pWpkAndAuthTag->dataLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pWpkAndAuthTag->pData) { PRINT_ERR("qaeMemAlloc pWpkAndAuthTag->pData error\n"); kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2); return CPA_STATUS_FAIL; } status = encryptPrivateKey(pPrivateKeyOfType1->pData, pPrivateKeyOfType1->dataLenInBytes, pSampleSWK, pIv, IV_LEN_IN_BYTES, pWpkAndAuthTag->pData, &wpkSize, pAuthTag, pAad, aadLenInBytes); if (CPA_FALSE == status) { PRINT_ERR("encyPrivateKey failed!\n"); kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2); return CPA_STATUS_FAIL; } /* Concatenated with AuthTag */ memcpy( pWpkAndAuthTag->pData + wpkSize, pAuthTag, AUTH_TAG_LEN_IN_BYTES); /* Opdata setup */ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pKptDecOpdata->inputData), pDecryptOpData->inputData.dataLenInBytes, pDecryptOpData->inputData.pData, pDecryptOpData->inputData.dataLenInBytes, kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2)); ALLOC_FLAT_BUFF_DATA( instanceHandle, &(pKptDecOpdata->pRecipientPrivateKey->privateKeyRep1.privateKey), wpkSize + AUTH_TAG_LEN_IN_BYTES, pWpkAndAuthTag->pData, wpkSize + AUTH_TAG_LEN_IN_BYTES, kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2)); pKptDecOpdata->pRecipientPrivateKey->version = pDecryptOpData->pRecipientPrivateKey->version; pKptDecOpdata->pRecipientPrivateKey->privateKeyRepType = pDecryptOpData->pRecipientPrivateKey->privateKeyRepType; } else { pPrivateKeyOfType2->dataLenInBytes = pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.coefficientQInv .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.exponent1Dp .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.exponent2Dq .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q .dataLenInBytes + /* publicExponentE is only 3bytes, so the value of publicExponentE.dataLenInBytes is 3, but the length of publicExponentE required by the driver is twice that of prime1P, so here is twice that of prime1P.dataLenInBytes. */ pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes * NUM_KEY_PAIRS; pPrivateKeyOfType2->pData = qaeMemAllocNUMA( pPrivateKeyOfType2->dataLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pPrivateKeyOfType2->pData) { PRINT_ERR("qaeMemAlloc pPrivateKeyOfType2->pData error\n"); kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2); return CPA_STATUS_FAIL; } memset( pPrivateKeyOfType2->pData, 0, pPrivateKeyOfType2->dataLenInBytes); memcpy( pPrivateKeyOfType2->pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P.pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes); memcpy( pPrivateKeyOfType2->pData + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q.pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q .dataLenInBytes); memcpy(pPrivateKeyOfType2->pData + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q .dataLenInBytes, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.exponent1Dp .pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.exponent1Dp .dataLenInBytes); memcpy(pPrivateKeyOfType2->pData + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .exponent1Dp.dataLenInBytes, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.exponent2Dq .pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.exponent2Dq .dataLenInBytes); memcpy(pPrivateKeyOfType2->pData + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .exponent1Dp.dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .exponent2Dq.dataLenInBytes, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .coefficientQInv.pData, pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .coefficientQInv.dataLenInBytes); memcpy(pPrivateKeyOfType2->pData + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q .dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .exponent1Dp.dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .exponent2Dq.dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2 .coefficientQInv.dataLenInBytes + pDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P .dataLenInBytes * NUM_KEY_PAIRS - pRsaPublicKey->publicExponentE.dataLenInBytes, pRsaPublicKey->publicExponentE.pData, pRsaPublicKey->publicExponentE.dataLenInBytes); pWpkAndAuthTag->dataLenInBytes = pPrivateKeyOfType2->dataLenInBytes + AUTH_TAG_LEN_IN_BYTES; pWpkAndAuthTag->pData = qaeMemAllocNUMA( pWpkAndAuthTag->dataLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pWpkAndAuthTag->pData) { PRINT_ERR("qaeMemAlloc pWpkAndAuthTag->pData error\n"); kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2); return CPA_STATUS_FAIL; } status = encryptPrivateKey(pPrivateKeyOfType2->pData, pPrivateKeyOfType2->dataLenInBytes, pSampleSWK, pIv, IV_LEN_IN_BYTES, pWpkAndAuthTag->pData, &wpkSize, pAuthTag, pAad, aadLenInBytes); if (CPA_FALSE == status) { PRINT_ERR("encyPrivateKey failed!\n"); kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2); return CPA_STATUS_FAIL; } /* Concatenated with AuthTag */ memcpy( pWpkAndAuthTag->pData + wpkSize, pAuthTag, AUTH_TAG_LEN_IN_BYTES); /* Opdata setup */ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pKptDecOpdata->inputData), pDecryptOpData->inputData.dataLenInBytes, pDecryptOpData->inputData.pData, pDecryptOpData->inputData.dataLenInBytes, kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2)); ALLOC_FLAT_BUFF_DATA( instanceHandle, &(pKptDecOpdata->pRecipientPrivateKey->privateKeyRep2.privateKey), wpkSize + AUTH_TAG_LEN_IN_BYTES, pWpkAndAuthTag->pData, wpkSize + AUTH_TAG_LEN_IN_BYTES, kptFreeRSAOPDataMemory(pKptDecOpdata, pWpkAndAuthTag, pPrivateKeyOfType1, pPrivateKeyOfType2)); pKptDecOpdata->pRecipientPrivateKey->version = pDecryptOpData->pRecipientPrivateKey->version; pKptDecOpdata->pRecipientPrivateKey->privateKeyRepType = pDecryptOpData->pRecipientPrivateKey->privateKeyRepType; } *pKPTDecryptOpData = pKptDecOpdata; if (NULL != pPrivateKeyOfType1) { if (NULL != pPrivateKeyOfType1->pData) { qaeMemFreeNUMA((void **)&pPrivateKeyOfType1->pData); } qaeMemFree((void **)&pPrivateKeyOfType1); } if (NULL != pPrivateKeyOfType2) { if (NULL != pPrivateKeyOfType2->pData) { qaeMemFreeNUMA((void **)&pPrivateKeyOfType2->pData); } qaeMemFree((void **)&pPrivateKeyOfType2); } if (NULL != pWpkAndAuthTag) { if (NULL != pWpkAndAuthTag->pData) { qaeMemFreeNUMA((void **)&pWpkAndAuthTag->pData); } qaeMemFree((void **)&pWpkAndAuthTag); } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setKpt2RsaDecryptOpData); /** ***************************************************************************** * @ingroup sampleKPTRSACode * * @description * Function for setup KPT RSA test before calling framework createThreads * functions * *****************************************************************************/ CpaStatus setupKpt2RsaTest(Cpa32U modulusSize, CpaCyRsaPrivateKeyRepType rsaKeyRepType, sync_mode_t syncMode, Cpa32U numBuffs, Cpa32U numLoops) { asym_test_params_t *rsaSetup = NULL; rsaSetup = (asym_test_params_t *)&thread_setup_g[testTypeCount_g][0]; rsaSetup->enableKPT = CPA_TRUE; return setupRsaTest( modulusSize, rsaKeyRepType, syncMode, numBuffs, numLoops); } EXPORT_SYMBOL(setupKpt2RsaTest); /****************************************************************************** * @ingroup sampleKPTRSACode * * @description * This function frees all memory related to KPT2 data. ******************************************************************************/ void kpt2RsaFreeDataMemory(asym_test_params_t *setup, CpaCyKptUnwrapContext **pKptUnwrapCtx, CpaCyKptRsaDecryptOpData **ppKPTDecryptOpData) { Cpa32U bufferCount = 0; for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { if (NULL != ppKPTDecryptOpData) { if (NULL != ppKPTDecryptOpData[bufferCount]) { if (NULL != ppKPTDecryptOpData[bufferCount]->inputData.pData) { qaeMemFreeNUMA((void **)&ppKPTDecryptOpData[bufferCount] ->inputData.pData); } if (NULL != ppKPTDecryptOpData[bufferCount] ->pRecipientPrivateKey->privateKeyRep1.privateKey.pData) { qaeMemFreeNUMA((void **)&ppKPTDecryptOpData[bufferCount] ->pRecipientPrivateKey->privateKeyRep1 .privateKey.pData); } if (NULL != ppKPTDecryptOpData[bufferCount] ->pRecipientPrivateKey->privateKeyRep2.privateKey.pData) { qaeMemFreeNUMA((void **)&ppKPTDecryptOpData[bufferCount] ->pRecipientPrivateKey->privateKeyRep2 .privateKey.pData); } qaeMemFreeNUMA((void **)&ppKPTDecryptOpData[bufferCount] ->pRecipientPrivateKey); qaeMemFreeNUMA((void **)&ppKPTDecryptOpData[bufferCount]); } } if (NULL != pKptUnwrapCtx) { if (NULL != pKptUnwrapCtx[bufferCount]) { qaeMemFreeNUMA((void **)&pKptUnwrapCtx[bufferCount]); } } } return; } EXPORT_SYMBOL(kpt2RsaFreeDataMemory); #endif cpa_sample_code_rsa_kpt2_perf.h000066400000000000000000000071101503624047500370150ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef CPA_SAMPLE_CODE_RSA_KPT2_PERF_H #define CPA_SAMPLE_CODE_RSA_KPT2_PERF_H #include "cpa_sample_code_kpt2_common.h" #if CY_API_VERSION_AT_LEAST(3, 0) CpaStatus setKpt2RsaDecryptOpData(CpaInstanceHandle instanceHandle, CpaCyKptRsaDecryptOpData **pKPTDecryptOpData, CpaCyRsaDecryptOpData *pDecryptOpData, CpaCyRsaPublicKey *pRsaPublicKey, Cpa32U node, Cpa8U *pSampleSWK, Cpa8U *pIv, Cpa8U *pAad, Cpa32U aadLenInBytes); #endif #endif cpa_sample_code_rsa_perf.c000066400000000000000000002447701503624047500360670ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_rsa_perf.c * * @defgroup sampleRSACode RSA 1024, 2048, 4096 bit Decrypt CRT * Performance code * * @ingroup sampleRSACode * * @description * This is a sample code that uses RSA APIs. * Functions contained in this file: * - rsaCallback * - ALLOC_FLAT_BUFF_DATA * - FREE_GENERATE_RSA_KEY_MEM * - generateRSAKey * - FREE_GEN_KEY_ARRAY_MEM * - genKeyArray * - rsaSetOpDataKeys * - FREE_RSA_ENCRYPT_DATA_SETUP_MEM * - rsaEncryptDataSetup * - FREE_RSA_DECRYPT_DATA_SETUP_MEM * - rsaDecryptDataSetup * - rsaFreeDataMemory * - rsaFreeKeyMemory * - sampleRsaEncrypt * - sampleRsaDcrypt * - sampleRsaPerform * - sampleRsaThreadSetup * - printRsaPerfData * - setupRsaTest * * This code preallocates a number of buffers as defined by * setup->numBuffers. The preallocated buffers are then * continuously looped until setup->numLoops is met. * Time stamping is started prior to the first performed RSA Decrypt * Operation and is stopped when all callbacks have returned. * The code is called for each packet size as defined in cpaPerformance * *****************************************************************************/ #include "cpa.h" #include "cpa_cy_common.h" #include "cpa_cy_rsa.h" #include "cpa_sample_code_crypto_utils.h" #include "icp_sal_poll.h" #include "qat_perf_sleeptime.h" #ifdef SC_DEV_INFO_ENABLED #include "cpa_dev.h" #endif #include "qat_perf_cycles.h" #include "cpa_sample_code_framework.h" #include "cpa_dev.h" #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED #include "cpa_sample_code_rsa_kpt2_perf.h" #endif #endif #endif /* ****************************************************************************** * macros ****************************************************************************** */ #define NUM_KEY_PAIRS (2) #define NUM_RSA_KEYGEN_RETRIES (1000) #ifdef POLL_INLINE Cpa32U asymPollingInterval_g = 0; EXPORT_SYMBOL(asymPollingInterval_g); #endif extern int latency_single_buffer_mode; /* set to 1 for single buffer processing */ /*we use public exponent e = 65537. The NIST Special Publication on Computer * Security (SP 800-78 Rev 1 of August 2007) does not allow public exponents e * smaller than 65537. * * This value can be regarded as a compromise between avoiding potential small * exponent attacks and still allowing efficient encryptions * (or signature verification).*/ Cpa8U rsaPublicExponent_g[] = {0x01, 0x00, 0x01}; // Cpa8U rsaPublicExponent_g[] = {0x03}; // Cpa8U rsaPublicExponent_g[] = {0x11}; extern Cpa32U packageIdCount_g; void sampleRsaThreadSetup(single_thread_test_data_t *testSetup); CpaStatus setupRsaBackpressureTest(Cpa32U numLoops); CpaStatus setAsymPollingInterval(Cpa64U pollingInterval); #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED void kpt2RsaCallback(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaFlatBuffer *pOut); #endif #endif /****************************************************************************** * @ingroup sampleRSACode * * @description * Callback for RSA KeyGen operations, we declare function signature as per the * API but we only use the pCallbackTag parameter * ****************************************************************************/ static void rsaKeyGenCallback(void *pCallbackTag, CpaStatus status, void *pKeyGenOpData, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; /*check perf_data pointer is valid*/ if (pPerfData == NULL) { PRINT_ERR("Invalid data in CallbackTag\n"); return; } /* response has been received */ pPerfData->responses++; /*if we have received the pre-set numOperations, then get the clock cycle * as a timestamp and post the Semaphore to release parent thread*/ if (pPerfData->numOperations == pPerfData->responses) { /*let calling thread know that we are done*/ sampleCodeSemaphorePost(&pPerfData->comp); } } /****************************************************************************** * @ingroup sampleRSACode * * @description * Callback for RSA operations, we declare function signature as per the API * but we only use the pCallbackTag parameter * ****************************************************************************/ static void rsaCallback(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaFlatBuffer *pOut) { processCallback(pCallbackTag); } #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED /****************************************************************************** * @ingroup sampleRSACode * * @description * Callback for KPT2 RSA operations * ****************************************************************************/ void kpt2RsaCallback(void *pCallbackTag, CpaStatus status, void *pOpdata, CpaFlatBuffer *pOut) { perf_data_t *pPerfData = (perf_data_t *)pCallbackTag; if (CPA_STATUS_SUCCESS != status) { pPerfData->threadReturnStatus = status; PRINT_ERR("kpt2RsaCallback failed with status %d\n", status); } if (CPA_STATUS_FAIL == status) { PRINT_ERR("KPT RSA Decrypt failed!\n"); } processCallback(pCallbackTag); } EXPORT_SYMBOL(kpt2RsaCallback); #endif #endif #ifdef POLL_INLINE CpaStatus setAsymPollingInterval(Cpa64U pollingInterval) { asymPollingInterval_g = pollingInterval; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setAsymPollingInterval); #endif /****************************************************************************** * @ingroup sampleRSACode * * @description * Frees any memory allocated by the generateRSAKey function * qaeMemFreeNUMA first checks to see if any memory is allocated before * attempting to free ******************************************************************************/ #define FREE_GENERATE_RSA_KEY_MEM() \ do \ { \ qaeMemFreeNUMA((void **)&pPublicKey->modulusN.pData); \ qaeMemFreeNUMA((void **)&pPublicKey->publicExponentE.pData); \ qaeMemFreeNUMA((void **)&pPrivateKey->privateKeyRep1.modulusN.pData); \ qaeMemFreeNUMA( \ (void **)&pPrivateKey->privateKeyRep1.privateExponentD.pData); \ qaeMemFreeNUMA((void **)&pPrivateKey->privateKeyRep2.prime1P.pData); \ qaeMemFreeNUMA((void **)&pPrivateKey->privateKeyRep2.prime2Q.pData); \ qaeMemFreeNUMA( \ (void **)&pPrivateKey->privateKeyRep2.exponent2Dq.pData); \ qaeMemFreeNUMA( \ (void **)&pPrivateKey->privateKeyRep2.exponent1Dp.pData); \ qaeMemFreeNUMA( \ (void **)&pPrivateKey->privateKeyRep2.coefficientQInv.pData); \ } while (0) /****************************************************************************** * @ingroup sampleRSACode * * @description * This function generates RSA keys from a given modulus length ******************************************************************************/ CpaStatus generateRSAKey(CpaInstanceHandle instanceHandle, Cpa32U modulusLenInBytes, CpaCyRsaPrivateKey *pPrivateKey, CpaCyRsaPublicKey *pPublicKey, asym_test_params_t *setup) { CpaStatus status = CPA_STATUS_FAIL; CpaCyRsaKeyGenOpData keyGenOpData; Cpa32U kSize = 0; Cpa32U retry = 0; perf_data_t *pPerfData = setup->performanceStats; CpaCyRsaKeyGenCbFunc rsaKeyGenCb = NULL; #ifdef POLL_INLINE CpaInstanceInfo2 *instanceInfo2 = NULL; #endif if (SYNC == setup->syncMode) { rsaKeyGenCb = NULL; } /*allocate the public key modulus*/ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPublicKey->modulusN), modulusLenInBytes, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); /*allocate and set the public exponent (e)*/ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPublicKey->publicExponentE), sizeof(rsaPublicExponent_g), rsaPublicExponent_g, sizeof(rsaPublicExponent_g), FREE_GENERATE_RSA_KEY_MEM()); /*setup private key data*/ /*if key type is CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1 then kSize is the size of * the modulus, otherwise its half the modulus size */ if (pPrivateKey->privateKeyRepType == CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1) { kSize = modulusLenInBytes; /*allocate space for the key data modulusN*/ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep1.modulusN), kSize, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); /*allocate space for the key data privateExponentD*/ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep1.privateExponentD), kSize, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); } else { /*allocate space for the key data modulusN*/ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep1.modulusN), modulusLenInBytes, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); /*allocate space for the key data privateExponentD*/ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep1.privateExponentD), modulusLenInBytes, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); kSize = modulusLenInBytes / NUM_KEY_PAIRS; /*allocate space for all the type2 key parameters * all allocated memory is freed in sampleRSAperform*/ ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep2.exponent2Dq), kSize, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep2.exponent1Dp), kSize, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep2.coefficientQInv), kSize, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); } ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep2.prime1P), modulusLenInBytes / NUM_KEY_PAIRS, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); if (useStaticPrime == 1) { status = generateHardCodedPrime1P( &(pPrivateKey->privateKeyRep2.prime1P), setup); } else { status = generatePrime( &(pPrivateKey->privateKeyRep2.prime1P), instanceHandle, setup); } if (status != CPA_STATUS_SUCCESS) { PRINT("Error could not generate privateKeyRep2.prime1P"); FREE_GENERATE_RSA_KEY_MEM(); status = CPA_STATUS_FAIL; goto exit; } ALLOC_FLAT_BUFF_DATA(instanceHandle, &(pPrivateKey->privateKeyRep2.prime2Q), modulusLenInBytes / NUM_KEY_PAIRS, NULL, 0, FREE_GENERATE_RSA_KEY_MEM()); if (useStaticPrime == 1) { status = generateHardCodedPrime2Q( &(pPrivateKey->privateKeyRep2.prime2Q), setup); } else { status = generatePrime( &(pPrivateKey->privateKeyRep2.prime2Q), instanceHandle, setup); } if (status != CPA_STATUS_SUCCESS) { PRINT("Error could not generate privateKeyRep2.prime2Q"); FREE_GENERATE_RSA_KEY_MEM(); status = CPA_STATUS_FAIL; goto exit; } /*set the keyGen operation data*/ keyGenOpData.privateKeyRepType = pPrivateKey->privateKeyRepType; keyGenOpData.version = pPrivateKey->version; keyGenOpData.modulusLenInBytes = modulusLenInBytes; keyGenOpData.prime1P = pPrivateKey->privateKeyRep2.prime1P; keyGenOpData.prime2Q = pPrivateKey->privateKeyRep2.prime2Q; keyGenOpData.publicExponentE = pPublicKey->publicExponentE; /*generate the public and private RSA keys*/ pPerfData->responses = 0; pPerfData->numOperations = SINGLE_OPERATION; sampleCodeSemaphoreInit(&pPerfData->comp, 0); #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } rsaKeyGenCb = rsaKeyGenCallback; } #endif for (retry = 0; retry < NUM_RSA_KEYGEN_RETRIES; retry++) { status = cpaCyRsaGenKey(instanceHandle, rsaKeyGenCb, pPerfData, &keyGenOpData, pPrivateKey, pPublicKey); if ((status == CPA_STATUS_SUCCESS) && (0 != memcmp(pPrivateKey->privateKeyRep2.prime1P.pData, pPrivateKey->privateKeyRep2.prime2Q.pData, pPrivateKey->privateKeyRep2.prime1P.dataLenInBytes))) { break; } if (!useStaticPrime) { /*could fail due to invalid e,p,q combination, so re-generate * p,q and try again*/ if (generatePrime(&(pPrivateKey->privateKeyRep2.prime1P), instanceHandle, setup) != CPA_STATUS_SUCCESS) { PRINT("Error could not generate privateKeyRep2.prime1P"); FREE_GENERATE_RSA_KEY_MEM(); sampleCodeSemaphoreDestroy(&pPerfData->comp); status = CPA_STATUS_FAIL; goto exit; } if (generatePrime(&(pPrivateKey->privateKeyRep2.prime2Q), instanceHandle, setup) != CPA_STATUS_SUCCESS) { PRINT("Error could not generate privateKeyRep2.prime2Q"); FREE_GENERATE_RSA_KEY_MEM(); sampleCodeSemaphoreDestroy(&pPerfData->comp); status = CPA_STATUS_FAIL; goto exit; } keyGenOpData.prime1P = pPrivateKey->privateKeyRep2.prime1P; keyGenOpData.prime2Q = pPrivateKey->privateKeyRep2.prime2Q; } } if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to generate RSA key, status: %d\n", status); FREE_GENERATE_RSA_KEY_MEM(); sampleCodeSemaphoreDestroy(&pPerfData->comp); status = CPA_STATUS_FAIL; goto exit; } if (SYNC == setup->syncMode || rsaKeyGenCb == NULL) { rsaKeyGenCallback( pPerfData, status, &keyGenOpData, pPrivateKey, pPublicKey); } #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (CPA_STATUS_SUCCESS == status) { if (sampleCodeSemaphoreWait(&pPerfData->comp, SAMPLE_CODE_WAIT_DEFAULT) != CPA_STATUS_SUCCESS) { PRINT_ERR("timeout or interruption in cpaCyPrimeTest\n"); status = CPA_STATUS_FAIL; } } sampleCodeSemaphoreDestroy(&pPerfData->comp); exit: #ifdef POLL_INLINE qaeMemFree((void **)&instanceInfo2); #endif return status; } EXPORT_SYMBOL(generateRSAKey); /****************************************************************************** * @ingroup sampleRSACode * * @description * Frees any memory allocated by the genKeyArray function * qaeMemFree first checks to see if any memory is allocated before * attempting to free ******************************************************************************/ #define FREE_GEN_KEY_ARRAY_MEM(publicCount, privateCount) \ do \ { \ Cpa32U j = 0; \ for (j = 0; j < privateCount; j++) \ { \ qaeMemFree((void **)&pPrivateKey[j]); \ } \ for (j = 0; j < publicCount; j++) \ { \ qaeMemFree((void **)&pPublicKey[j]); \ } \ } while (0) /****************************************************************************** * @ingroup sampleRSACode * * @description * this function allocates space and generates arrays of RSA keys, based on the * parameters within the setup * ****************************************************************************/ CpaStatus genKeyArray(asym_test_params_t *setup, CpaCyRsaPrivateKey *pPrivateKey[], CpaCyRsaPublicKey *pPublicKey[]) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U bufferCount = 0; Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not get node\n"); return status; } /*for each bufferList create the operation data*/ for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { /*set key pointers to null so that if any memory allocation fails and * we attempt to free it, the free will check if its NULL 1st*/ pPrivateKey[bufferCount] = NULL; pPublicKey[bufferCount] = NULL; } /*for each bufferList create the operation data*/ for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { /*********************/ /* Setup Public Key */ /*********************/ pPublicKey[bufferCount] = (CpaCyRsaPublicKey *)qaeMemAlloc(sizeof(CpaCyRsaPublicKey)); if (NULL == pPublicKey[bufferCount]) { PRINT_ERR("No memory for pTmpPublicKey\n"); FREE_GEN_KEY_ARRAY_MEM(bufferCount, bufferCount); return CPA_STATUS_FAIL; } memset(pPublicKey[bufferCount], 0, sizeof(CpaCyRsaPublicKey)); /* Setup Private Key */ pPrivateKey[bufferCount] = (CpaCyRsaPrivateKey *)qaeMemAlloc(sizeof(CpaCyRsaPrivateKey)); if (NULL == pPrivateKey[bufferCount]) { PRINT_ERR("No memory for pTmpPrivateKey\n"); FREE_GEN_KEY_ARRAY_MEM(bufferCount + 1, bufferCount); return CPA_STATUS_FAIL; } memset(pPrivateKey[bufferCount], 0, sizeof(CpaCyRsaPrivateKey)); /* Setup version and key type */ pPrivateKey[bufferCount]->version = CPA_CY_RSA_VERSION_TWO_PRIME; if (setup->rsaKeyRepType == CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2) { pPrivateKey[bufferCount]->privateKeyRepType = CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2; } else { pPrivateKey[bufferCount]->privateKeyRepType = CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_1; } /*generate the keys*/ status = generateRSAKey(setup->cyInstanceHandle, setup->modulusSizeInBytes, pPrivateKey[bufferCount], pPublicKey[bufferCount], setup); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("RSAKey gen error %d on %d\n", status, bufferCount); FREE_GEN_KEY_ARRAY_MEM(bufferCount + 1, bufferCount + 1); return status; } } return status; } EXPORT_SYMBOL(genKeyArray); /****************************************************************************** * @ingroup sampleRSACode * * @description * this function gets RSA keys and copies them into the RSA decryptOpData or * encryptOpStructures structure, in this function any memory allocation * is freed in sampleRSAPerform function * ****************************************************************************/ void rsaSetOpDataKeys(asym_test_params_t *setup, CpaCyRsaDecryptOpData *pDecryptOpData[], CpaCyRsaEncryptOpData *pEncryptOpData[], CpaCyRsaPrivateKey *pPrivateKey[], CpaCyRsaPublicKey *pPublicKey[]) { Cpa32U bufferCount = 0; for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { /*copy keys into Encrypt or Decrypt operation data structures*/ if (pDecryptOpData != NULL) { if (pDecryptOpData[bufferCount] != NULL && pPrivateKey[bufferCount] != NULL) { pDecryptOpData[bufferCount]->pRecipientPrivateKey = pPrivateKey[bufferCount]; } else { PRINT_ERR("Could not assign RecipientPrivateKey\n"); } } if (pEncryptOpData != NULL) { if (pEncryptOpData[bufferCount] != NULL && pPublicKey[bufferCount] != NULL) { pEncryptOpData[bufferCount]->pPublicKey = pPublicKey[bufferCount]; } else { PRINT_ERR("Could not assign RecipientPrivateKey\n"); } } } } EXPORT_SYMBOL(rsaSetOpDataKeys); /****************************************************************************** * @ingroup sampleRSACode * * @description * Frees any memory allocated by the rsaEncryptDataSetup function * qaeMemFreeNUMA first checks to see if any memory is allocated before * attempting to free ******************************************************************************/ #define FREE_RSA_ENCRYPT_DATA_SETUP_MEM() \ do \ { \ Cpa32U j = 0; \ for (j = 0; j < setup->numBuffers; j++) \ { \ qaeMemFreeNUMA((void **)&pOpdata[j]->inputData.pData); \ qaeMemFree((void **)&pOpdata[j]); \ qaeMemFreeNUMA((void **)&pOutputData[j]->pData); \ qaeMemFree((void **)&pOutputData[j]); \ } \ } while (0) /****************************************************************************** * @ingroup sampleRSACode * * @description * This function setups up an array of operation data structures for * Encryption operations, any memory allocation is freed in * sampleRSAPerform ******************************************************************************/ CpaStatus rsaEncryptDataSetup(CpaFlatBuffer *pEncryptData[], CpaCyRsaEncryptOpData *pOpdata[], CpaFlatBuffer *pOutputData[], asym_test_params_t *setup) { /*status is used inside macros within this function*/ CpaStatus status = CPA_STATUS_FAIL; Cpa32U bufferCount = 0; Cpa32U bufferSize = setup->modulusSizeInBytes; Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not get node\n"); return status; } /*for each bufferList create the operation data*/ for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { /*allocate a flat buffer for the output*/ pOutputData[bufferCount] = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pOutputData[bufferCount]) { PRINT_ERR("Failed to allocate mem for encrypt output data\n"); FREE_RSA_ENCRYPT_DATA_SETUP_MEM(); return CPA_STATUS_FAIL; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pOutputData[bufferCount], bufferSize, NULL, 0, FREE_RSA_ENCRYPT_DATA_SETUP_MEM()); pOpdata[bufferCount] = qaeMemAlloc(sizeof(CpaCyRsaEncryptOpData)); /*allocate the input data and populate with random data*/ if (NULL == pOpdata[bufferCount]) { PRINT_ERR("Failed to allocate mem for encrypt input data\n"); FREE_RSA_ENCRYPT_DATA_SETUP_MEM(); return CPA_STATUS_FAIL; } memset(pOpdata[bufferCount], 0, sizeof(CpaCyRsaEncryptOpData)); /*if there is no encrypt data provided, * generate random data to encrypt*/ if (pEncryptData == NULL) { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pOpdata[bufferCount]->inputData, bufferSize, NULL, 0, FREE_RSA_ENCRYPT_DATA_SETUP_MEM()); generateRandomData(pOpdata[bufferCount]->inputData.pData, bufferSize); } /*else copy the input data into the buffer*/ else { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &pOpdata[bufferCount]->inputData, pEncryptData[bufferCount]->dataLenInBytes, pEncryptData[bufferCount]->pData, 0, FREE_RSA_ENCRYPT_DATA_SETUP_MEM()); } } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(rsaEncryptDataSetup); /****************************************************************************** * @ingroup sampleRSACode * * @description * Frees any memory allocated by the rsaDecryptDataSetup function * qaeMemFreeNUMA first checks to see if any memory is allocated before * attempting to free ******************************************************************************/ #define FREE_RSA_DECRYPT_DATA_SETUP_MEM() \ do \ { \ Cpa32U j = 0; \ for (j = 0; j < setup->numBuffers; j++) \ { \ qaeMemFreeNUMA((void **)&pOpdata[j]->inputData.pData); \ qaeMemFree((void **)&pOpdata[j]); \ qaeMemFreeNUMA((void **)&pOutputData[j]->pData); \ qaeMemFree((void **)&pOutputData[j]); \ } \ } while (0) /****************************************************************************** * @ingroup sampleRSACode * * @description * this function sets up the data to be decrypted and allocates space to * store the output * ****************************************************************************/ CpaStatus rsaDecryptDataSetup(CpaFlatBuffer *pDecryptData[], CpaCyRsaDecryptOpData *pOpdata[], CpaFlatBuffer *pOutputData[], asym_test_params_t *setup) { /*status is used inside macros within this function*/ CpaStatus status = CPA_STATUS_FAIL; Cpa32U bufferCount = 0; Cpa32U bufferSize = setup->modulusSizeInBytes; Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not get node\n"); return status; } /*for each bufferList create the operation data*/ for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { pOpdata[bufferCount] = NULL; pOutputData[bufferCount] = NULL; /*allocate a flat buffer for the output*/ pOutputData[bufferCount] = qaeMemAlloc(sizeof(CpaFlatBuffer)); if (NULL == pOutputData[bufferCount]) { PRINT_ERR("Failed to allocate memory for Decrypt output buffer\n"); FREE_RSA_DECRYPT_DATA_SETUP_MEM(); return CPA_STATUS_FAIL; } memset(pOutputData[bufferCount], 0, sizeof(CpaFlatBuffer)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pOutputData[bufferCount], bufferSize, NULL, 0, FREE_RSA_DECRYPT_DATA_SETUP_MEM()); /*allocate memory for operation data*/ pOpdata[bufferCount] = qaeMemAlloc(sizeof(CpaCyRsaDecryptOpData)); if (NULL == pOpdata[bufferCount]) { PRINT_ERR("Failed to allocate memory for Decrypt opData\n"); FREE_RSA_DECRYPT_DATA_SETUP_MEM(); return CPA_STATUS_FAIL; } memset(pOpdata[bufferCount], 0, sizeof(CpaCyRsaDecryptOpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &(pOpdata[bufferCount]->inputData), bufferSize, NULL, 0, FREE_RSA_DECRYPT_DATA_SETUP_MEM()); /*generate random data to decrypt if there is no input data*/ if (pDecryptData == NULL) { generateRandomData(pOpdata[bufferCount]->inputData.pData, bufferSize); /*make sure it's less than the modulus (MSB = modulusN.pData[0])*/ pOpdata[bufferCount]->inputData.pData[0] = 0; } /*else copy the input data into the buffer*/ else { if (pDecryptData[bufferCount] != NULL) { if (pDecryptData[bufferCount]->pData != NULL) { memcpy(pOpdata[bufferCount]->inputData.pData, pDecryptData[bufferCount]->pData, pDecryptData[bufferCount]->dataLenInBytes); } else { PRINT_ERR("Could not copy decrypt data into buffers\n"); return CPA_STATUS_FAIL; } } else { PRINT_ERR("decrypt flat buffer points to NULL\n"); return CPA_STATUS_FAIL; } } } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(rsaDecryptDataSetup); /****************************************************************************** * @ingroup sampleRSACode * * @description * This function frees all Operation Data memory setup in this file. * The code checks for any unallocated memory before it attempts to free it. ******************************************************************************/ void rsaFreeDataMemory(asym_test_params_t *setup, CpaCyRsaDecryptOpData *pOpdata[], CpaFlatBuffer *pOutputData[], CpaCyRsaEncryptOpData *pEncryptOpdata[], CpaFlatBuffer *pInputData[]) { Cpa32U bufferCount = 0; for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { if (NULL != pOpdata) { if (NULL != pOpdata[bufferCount]) { qaeMemFreeNUMA((void **)&pOpdata[bufferCount]->inputData.pData); qaeMemFree((void **)&pOpdata[bufferCount]); } } if (NULL != pOutputData) { if (NULL != pOutputData[bufferCount]) { qaeMemFreeNUMA((void **)&pOutputData[bufferCount]->pData); qaeMemFree((void **)&pOutputData[bufferCount]); } } if (NULL != pEncryptOpdata) { if (NULL != pEncryptOpdata[bufferCount]) { qaeMemFreeNUMA( (void **)&pEncryptOpdata[bufferCount]->inputData.pData); qaeMemFree((void **)&pEncryptOpdata[bufferCount]); } } if (NULL != pInputData) { if (NULL != pInputData[bufferCount]) { qaeMemFreeNUMA((void **)&pInputData[bufferCount]->pData); qaeMemFree((void **)&pInputData[bufferCount]); } } } return; } EXPORT_SYMBOL(rsaFreeDataMemory); /****************************************************************************** * @ingroup sampleRSACode * * @description * This function frees all memory related to RSA key data. This function must be * called before rsaFreeDataMemory otherwise the pointers to the key data will * be lost and we won't be able to free the memory * ****************************************************************************/ void rsaFreeKeyMemory(asym_test_params_t *setup, CpaCyRsaPrivateKey *pPrivateKey[], CpaCyRsaPublicKey *pPublicKey[]) { Cpa32U bufferCount = 0; if (NULL == pPrivateKey || NULL == pPrivateKey) { PRINT_ERR("Could not free rsaKeys\n"); return; } for (bufferCount = 0; bufferCount < setup->numBuffers; bufferCount++) { /* free public key*/ if (NULL == pPublicKey[bufferCount]) { PRINT_ERR("Could not free pPublicKey[%d]\n", bufferCount); } else { qaeMemFreeNUMA((void **)&pPublicKey[bufferCount]->modulusN.pData); qaeMemFreeNUMA( (void **)&pPublicKey[bufferCount]->publicExponentE.pData); qaeMemFree((void **)&pPublicKey[bufferCount]); } /* free private key*/ if (NULL == pPrivateKey[bufferCount]) { PRINT_ERR("Could not free pPrivateKey[%d]\n", bufferCount); } else { if (pPrivateKey[bufferCount]->privateKeyRepType == CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2) { CpaCyRsaPrivateKeyRep1 *resp1 = &pPrivateKey[bufferCount]->privateKeyRep1; qaeMemFreeNUMA((void **)&resp1->modulusN.pData); qaeMemFreeNUMA((void **)&resp1->privateExponentD.pData); qaeMemFreeNUMA((void **)&pPrivateKey[bufferCount] ->privateKeyRep2.coefficientQInv.pData); qaeMemFreeNUMA((void **)&pPrivateKey[bufferCount] ->privateKeyRep2.exponent2Dq.pData); qaeMemFreeNUMA((void **)&pPrivateKey[bufferCount] ->privateKeyRep2.exponent1Dp.pData); qaeMemFreeNUMA((void **)&pPrivateKey[bufferCount] ->privateKeyRep2.prime2Q.pData); qaeMemFreeNUMA((void **)&pPrivateKey[bufferCount] ->privateKeyRep2.prime1P.pData); qaeMemFree((void **)&pPrivateKey[bufferCount]); } } } return; } EXPORT_SYMBOL(rsaFreeKeyMemory); /****************************************************************************** * * @ingroup sampleRSACode * * @description * this function measures the performance of RSA Encrypt operations * It is assume all the encrypt data and keys have been been set using functions * defined in this file * ****************************************************************************/ CpaStatus sampleRsaEncrypt(asym_test_params_t *setup, CpaCyRsaEncryptOpData **ppEncryptOpData, CpaFlatBuffer **ppOutputData, Cpa32U numBuffers, Cpa32U numLoops) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U insideLoopCount = 0; Cpa32U outsideLoopCount = 0; CpaCyGenFlatBufCbFunc cbFunc = NULL; perf_data_t *pPerfData = setup->performanceStats; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_SUCCESS; CpaInstanceInfo2 *instanceInfo2 = NULL; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; #endif DECLARE_IA_CYCLE_COUNT_VARIABLES(); #ifdef POLL_INLINE instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR( "Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } #endif setup->performanceStats->averagePacketSizeInBytes = setup->modulusSizeInBytes; setup->performanceStats->numOperations = (Cpa64U)numLoops * numBuffers; setup->performanceStats->responses = 0; coo_init(pPerfData, pPerfData->numOperations); /* Semaphore used in callback */ sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = rsaCallback; } if (setup->performEncrypt) { sampleCodeBarrier(); /* Get the clock cycle timestamp and store in Global, collect this only * for the first request, the callback collects it for the last */ setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); } /*loop around number of preallocated buffer lists*/ for (outsideLoopCount = 0; outsideLoopCount < numLoops; outsideLoopCount++) { /*perform on preallocated buffer lists*/ for (insideLoopCount = 0; insideLoopCount < numBuffers; insideLoopCount++) { do { coo_req_start(pPerfData); status = cpaCyRsaEncrypt(setup->cyInstanceHandle, cbFunc, pPerfData, ppEncryptOpData[insideLoopCount], ppOutputData[insideLoopCount]); coo_req_stop(pPerfData, status); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { coo_poll_trad_cy(pPerfData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } #endif if (RETRY_LIMIT == (setup->performanceStats->retries % (RETRY_LIMIT + 1))) { AVOID_SOFTLOCKUP; } } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { BUSY_LOOP(); } if (CPA_STATUS_SUCCESS != status) { break; } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy( pPerfData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } } #endif } /* end of inner loop */ if (CPA_STATUS_SUCCESS != status) { break; } } /* end of outer loop */ if (CPA_STATUS_SUCCESS == status) { if (SYNC == setup->syncMode) { pPerfData->endCyclesTimestamp = sampleCodeTimestamp(); sampleCodeSemaphorePost(&setup->performanceStats->comp); pPerfData->responses = (Cpa64U)setup->numBuffers * setup->numLoops; } /*wait for all submitted encrypt operations to complete*/ if (sampleCodeSemaphoreWait(&setup->performanceStats->comp, SAMPLE_CODE_WAIT_DEFAULT) != CPA_STATUS_SUCCESS) { PRINT_ERR("interruption in cpaCyRsaEncrypt\n"); } } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { IA_CYCLE_COUNT_CALCULATION(); } coo_average(pPerfData); coo_deinit(pPerfData); sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); #ifdef POLL_INLINE qaeMemFree((void **)&instanceInfo2); #endif return status; } /****************************************************************************** * @ingroup sampleRSACode * * @description * This functions performs RSA Encrypt using openssl library * * ****************************************************************************/ /****************************************************************************** * @ingroup sampleRSACode * * @description * this function measures the performance of RSA Encrypt operations * It is assumed all the encrypt data and keys have been been set using * functions defined in this file * ****************************************************************************/ CpaStatus sampleRsaDecrypt(asym_test_params_t *setup, CpaCyRsaDecryptOpData **ppDecryptOpData, CpaFlatBuffer **ppOutputData, CpaCyRsaPrivateKey **pPrivateKey, CpaCyRsaPublicKey **pPublicKey, Cpa32U numBuffers, Cpa32U numLoops) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U insideLoopCount = 0; Cpa32U outsideLoopCount = 0; CpaCyGenFlatBufCbFunc cbFunc = NULL; perf_data_t *pPerfData = setup->performanceStats; CpaInstanceInfo2 *instanceInfo = NULL; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_FAIL; Cpa64U numOps = 0; Cpa64U nextPoll = asymPollingInterval_g; CpaBoolean isPolled = CPA_FALSE; #endif Cpa64U latency_submissions = 0; Cpa32U i = 0; perf_cycles_t *request_submit_start = NULL; perf_cycles_t *request_respnse_time = NULL; const Cpa32U request_mem_sz = sizeof(perf_cycles_t) * MAX_LATENCY_COUNT; #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED /* KPT related */ CpaCyKptKeyManagementStatus kpt2Status = CPA_CY_KPT_SUCCESS; CpaCyKptUnwrapContext **pKptUnwrapCtx = NULL; Cpa32U node = 0; Cpa32U keyProvisionRetryTimes = 0; CpaCyKptRsaDecryptOpData **ppKPTDecryptOpData = NULL; CpaCyCapabilitiesInfo pCapInfo = {0}; CpaStatus delKeyStatus = CPA_STATUS_SUCCESS; Cpa8U rsaAdditionalAuthData[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01}; /*SWK*/ Cpa8U sampleSWK[SWK_LEN_IN_BYTES] = {0}; Cpa8U iv[IV_LEN_IN_BYTES] = {0}; if (CPA_TRUE == setup->enableKPT) { status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed!\n"); return status; } ppKPTDecryptOpData = qaeMemAllocNUMA( sizeof(CpaCyKptRsaDecryptOpData *) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == ppKPTDecryptOpData) { PRINT_ERR("qaeMemAlloc ppKPTDecryptOpData error\n"); return CPA_STATUS_FAIL; } pKptUnwrapCtx = qaeMemAllocNUMA(sizeof(CpaCyKptUnwrapContext *) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == pKptUnwrapCtx) { PRINT_ERR("qaeMemAlloc pKptUnwrapCtx error\n"); qaeMemFreeNUMA((void **)&ppKPTDecryptOpData); return CPA_STATUS_FAIL; } } /* KPT related */ #endif #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ /* KPT Stolen Key Test */ #endif DECLARE_IA_CYCLE_COUNT_VARIABLES(); if (latency_enable) { if (setup->performanceStats->numOperations > LATENCY_SUBMISSION_LIMIT) { PRINT_ERR("Error max submissions for latency must be <= %d\n", LATENCY_SUBMISSION_LIMIT); return CPA_STATUS_FAIL; } request_submit_start = qaeMemAlloc(request_mem_sz); request_respnse_time = qaeMemAlloc(request_mem_sz); if (request_submit_start == NULL || request_respnse_time == NULL) { PRINT_ERR("Failed to allocate memory for submission and" " response times\n"); qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); return CPA_STATUS_FAIL; } memset(request_submit_start, 0, request_mem_sz); memset(request_respnse_time, 0, request_mem_sz); setup->performanceStats->nextCount = (setup->numBuffers * setup->numLoops) / 100; setup->performanceStats->countIncrement = (setup->numBuffers * setup->numLoops) / 100; setup->performanceStats->response_times = request_respnse_time; /* for debug purposes*/ setup->performanceStats->start_times = request_submit_start; } instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); return CPA_STATUS_FAIL; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } setup->performanceStats->packageId = instanceInfo->physInstId.packageId; setup->performanceStats->averagePacketSizeInBytes = setup->modulusSizeInBytes; setup->performanceStats->numOperations = (Cpa64U)numLoops * numBuffers; setup->performanceStats->responses = 0; coo_init(pPerfData, pPerfData->numOperations); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { setup->performanceStats->busyLoopValue = busyLoopCounter_g; setup->performanceStats->busyLoopCount = 0; } /* Semaphore used in callback */ sampleCodeSemaphoreInit(&setup->performanceStats->comp, 0); /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == setup->enableKPT) { cbFunc = kpt2RsaCallback; } else { #endif #endif cbFunc = rsaCallback; #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED } #endif #endif } #ifdef POLL_INLINE if (poll_inline_g) { status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } isPolled = instanceInfo->isPolled; } #endif #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == setup->enableKPT) { status = cpaCyQueryCapabilities(setup->cyInstanceHandle, &pCapInfo); if ((CPA_STATUS_SUCCESS == status) && !pCapInfo.kptSupported) { PRINT_ERR( "Inst (BDF:%02x:%02d.%d) does not support KPT2!\n", (Cpa8U)(instanceInfo->physInstId.busAddress >> 8), (Cpa8U)((instanceInfo->physInstId.busAddress & 0xFF) >> 3), (Cpa8U)(instanceInfo->physInstId.busAddress & 7)); sampleCodeBarrier(); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_SUCCESS; } qaeMemFree((void **)&instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyQueryCapabilities failed!\n"); return status; } generateRandomData(sampleSWK, SWK_LEN_IN_BYTES); generateRandomData(iv, IV_LEN_IN_BYTES); status = encryptAndLoadSWK( setup->cyInstanceHandle, &setup->kptKeyHandle, sampleSWK); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("encryptAndLoadSWKs failed!\n"); kpt2RsaFreeDataMemory(setup, pKptUnwrapCtx, ppKPTDecryptOpData); qaeMemFreeNUMA((void **)&ppKPTDecryptOpData); qaeMemFreeNUMA((void **)&pKptUnwrapCtx); return status; } for (insideLoopCount = 0; insideLoopCount < numBuffers; insideLoopCount++) { pKptUnwrapCtx[insideLoopCount] = qaeMemAllocNUMA( sizeof(CpaCyKptUnwrapContext), node, BYTE_ALIGNMENT_64); status = setKpt2RsaDecryptOpData(setup->cyInstanceHandle, &ppKPTDecryptOpData[insideLoopCount], ppDecryptOpData[insideLoopCount], pPublicKey[insideLoopCount], node, sampleSWK, iv, rsaAdditionalAuthData, sizeof(rsaAdditionalAuthData)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("setKptRsaDecryptOpData failed!\n"); cpaCyKptDeleteKey( setup->cyInstanceHandle, setup->kptKeyHandle, &kpt2Status); kpt2RsaFreeDataMemory(setup, pKptUnwrapCtx, ppKPTDecryptOpData); qaeMemFreeNUMA((void **)&ppKPTDecryptOpData); qaeMemFreeNUMA((void **)&pKptUnwrapCtx); return status; } pKptUnwrapCtx[insideLoopCount]->kptHandle = setup->kptKeyHandle; memcpy(pKptUnwrapCtx[insideLoopCount]->iv, iv, IV_LEN_IN_BYTES); memcpy(pKptUnwrapCtx[insideLoopCount]->additionalAuthData, rsaAdditionalAuthData, sizeof(rsaAdditionalAuthData)); pKptUnwrapCtx[insideLoopCount]->aadLenInBytes = sizeof(rsaAdditionalAuthData); } } #endif #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #endif if (NULL != instanceInfo) { qaeMemFree((void **)&instanceInfo); } /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Get the clock cycle timestamp and store in Global, collect this only * for the first request, the callback collects it for the last */ setup->performanceStats->startCyclesTimestamp = sampleCodeTimestamp(); /*loop around number of pre-allocated buffer lists*/ for (outsideLoopCount = 0; outsideLoopCount < numLoops; outsideLoopCount++) { /*perform on pre-allocated buffer lists*/ for (insideLoopCount = 0; insideLoopCount < numBuffers; insideLoopCount++) { do { if (latency_enable) { if (latency_submissions + 1 == setup->performanceStats->nextCount) { request_submit_start[setup->performanceStats ->latencyCount] = sampleCodeTimestamp(); } } coo_req_start(pPerfData); #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == setup->enableKPT) { status = cpaCyKptRsaDecrypt( setup->cyInstanceHandle, cbFunc, setup->performanceStats, ppKPTDecryptOpData[insideLoopCount], ppOutputData[insideLoopCount], pKptUnwrapCtx[insideLoopCount]); if (CPA_STATUS_FAIL == status) { PRINT_ERR("KPT RSA Decrypt failed!\n"); } } else { #endif #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #endif status = cpaCyRsaDecrypt(setup->cyInstanceHandle, cbFunc, setup->performanceStats, ppDecryptOpData[insideLoopCount], ppOutputData[insideLoopCount]); #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED } #endif #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #endif coo_req_stop(pPerfData, status); if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; #ifdef POLL_INLINE if (poll_inline_g) { if (isPolled) { coo_poll_trad_cy(pPerfData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } #endif AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { BUSY_LOOP(); } if (CPA_STATUS_INVALID_PARAM == status) { /* Reduce number of operations to poll because of invalid * parameters. Keys are invalid because the generation of * them was based on invalid prime. */ pPerfData->numOperations = (outsideLoopCount + 1) * numBuffers - 1; /* Do not continue with outside loop in case of invalid param */ outsideLoopCount = numLoops; } else if (CPA_STATUS_SUCCESS != status) { break; } if (latency_enable) { /* Another buffer has been submitted to the accelerator */ latency_submissions++; /* Have we been requested to process one buffer at a time. This * will result in no retries and so the best latency times. */ if (latency_single_buffer_mode != 0) { /* Must now wait until this buffer is processed by the CPM */ while (pPerfData->responses != latency_submissions) { /* Keep polling until encryption of the buffer * completes * and rsaPerformCallback() increments * pPerfData->responses */ sampleCodeAsymPollInstance(setup->cyInstanceHandle, 0); } } } #ifdef POLL_INLINE if (poll_inline_g) { if (isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy( pPerfData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + asymPollingInterval_g; } } } #endif } /* end of inner loop */ if (CPA_STATUS_SUCCESS != status) { break; } } /* end of outer loop */ #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pPerfData, setup->cyInstanceHandle, pPerfData->numOperations); } } #endif if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pPerfData, setup->syncMode, setup->numBuffers, setup->numLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Thread %u timeout. ", setup->threadID); } } if (latency_enable) { if (latency_debug) { PRINT("%s: Calculating min, max and ave latencies...\n", __FUNCTION__); sampleCodeSleep(1); /* Let all our debug be printed out */ } /* Will be less than this */ setup->performanceStats->minLatency = MAX_LATENCY_LIMIT; /* Will be more than this */ setup->performanceStats->maxLatency = 0; /* Let's accumulate in 'aveLatency' all the individual 'latency' * times. Typically, there should be MAX_LATENCY_COUNT of these. * We also calculate min/max so we can get a sense of the variance. */ for (i = 0; i < setup->performanceStats->latencyCount; i++) { perf_cycles_t latency = setup->performanceStats->response_times[i] - request_submit_start[i]; setup->performanceStats->aveLatency += latency; if (latency < setup->performanceStats->minLatency) setup->performanceStats->minLatency = latency; if (latency > setup->performanceStats->maxLatency) setup->performanceStats->maxLatency = latency; if (latency_debug) PRINT("%d, end[i]:%llu, start[i]:%llu, min:%llu, ave:%llu, " "max:%llu\n", i, setup->performanceStats->response_times[i], request_submit_start[i], setup->performanceStats->minLatency, setup->performanceStats->aveLatency, setup->performanceStats->maxLatency); } if (setup->performanceStats->latencyCount > 0) { /* Then scale down this accumulated value to get the average. * This will be reported by dcPrintStats() at the end of the test */ do_div(setup->performanceStats->aveLatency, setup->performanceStats->latencyCount); } /*we are finished with the response time so set to null before exit*/ setup->performanceStats->response_times = NULL; qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { IA_CYCLE_COUNT_CALCULATION(); } coo_average(pPerfData); coo_deinit(pPerfData); sampleCodeSemaphoreDestroy(&setup->performanceStats->comp); #ifdef USER_SPACE #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == setup->enableKPT) { do { delKeyStatus = cpaCyKptDeleteKey( setup->cyInstanceHandle, setup->kptKeyHandle, &kpt2Status); usleep(KEY_PROVISION_RETRY_DELAY_MS * 1000); keyProvisionRetryTimes++; } while ((CPA_STATUS_RETRY == delKeyStatus) && (keyProvisionRetryTimes <= KEY_PROVISION_RETRY_TIMES_LIMIT)); if (1 < keyProvisionRetryTimes) { PRINT("KPT RSA Delete SWK Retry Times : %d\n", keyProvisionRetryTimes - 1); } if ((CPA_STATUS_SUCCESS != delKeyStatus) || (CPA_CY_KPT_SUCCESS != kpt2Status)) { PRINT_ERR("Delete SWK failed with status: %d,kpt2Status: %d.\n", delKeyStatus, kpt2Status); status = CPA_STATUS_FAIL; } kpt2RsaFreeDataMemory(setup, pKptUnwrapCtx, ppKPTDecryptOpData); qaeMemFreeNUMA((void **)&ppKPTDecryptOpData); qaeMemFreeNUMA((void **)&pKptUnwrapCtx); } #endif #endif /* CY_API_VERSION_AT_LEAST(3, 0) */ #endif return status; } EXPORT_SYMBOL(sampleRsaDecrypt); /****************************************************************************** * @ingroup sampleRSACode * * @description * Main executing function * *****************************************************************************/ CpaStatus sampleRsaPerform(asym_test_params_t *setup) { /* start of local variable declarations */ CpaStatus status = CPA_STATUS_SUCCESS; /* RSA key and opData parameters */ CpaCyRsaPrivateKey **ppPrivateKey = NULL; CpaCyRsaPublicKey **ppPublicKey = NULL; CpaCyRsaDecryptOpData **ppDecryptOpData = NULL; CpaFlatBuffer **ppDecryptOutputData = NULL; /* end of local variable declarations */ ppPrivateKey = qaeMemAlloc(sizeof(CpaCyRsaPrivateKey *) * setup->numBuffers); if (NULL == ppPrivateKey) { PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } ppPublicKey = qaeMemAlloc(sizeof(CpaCyRsaPublicKey *) * setup->numBuffers); if (NULL == ppPublicKey) { qaeMemFree((void **)&ppPrivateKey); PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } ppDecryptOpData = qaeMemAlloc(sizeof(CpaCyRsaDecryptOpData *) * setup->numBuffers); if (NULL == ppDecryptOpData) { qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } ppDecryptOutputData = qaeMemAlloc(sizeof(CpaFlatBuffer *) * setup->numBuffers); if (NULL == ppDecryptOutputData) { qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppDecryptOpData); PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } status = genKeyArray(setup, ppPrivateKey, ppPublicKey); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("genKeyArray error %d\n", status); qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppDecryptOpData); qaeMemFree((void **)&ppDecryptOutputData); return CPA_STATUS_FAIL; } /*setup decrypt operation to decrypt random data*/ status = rsaDecryptDataSetup(NULL, ppDecryptOpData, ppDecryptOutputData, setup); if (status != CPA_STATUS_SUCCESS) { rsaFreeDataMemory( setup, ppDecryptOpData, ppDecryptOutputData, NULL, NULL); qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppDecryptOpData); qaeMemFree((void **)&ppDecryptOutputData); return CPA_STATUS_FAIL; } /*setup decryption opData structure with RSA key*/ rsaSetOpDataKeys(setup, ppDecryptOpData, NULL, ppPrivateKey, ppPublicKey); status = sampleRsaDecrypt(setup, ppDecryptOpData, ppDecryptOutputData, ppPrivateKey, ppPublicKey, setup->numBuffers, setup->numLoops); /*free all the key and operation data memory*/ rsaFreeKeyMemory(setup, ppPrivateKey, ppPublicKey); rsaFreeDataMemory(setup, ppDecryptOpData, ppDecryptOutputData, NULL, NULL); qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppDecryptOpData); qaeMemFree((void **)&ppDecryptOutputData); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } static CpaStatus sampleRsaEncryptPerform(asym_test_params_t *setup) { /* start of local variable declarations */ CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U count = 0; /* RSA key and opData parameters */ CpaCyRsaPrivateKey **ppPrivateKey = NULL; CpaCyRsaPublicKey **ppPublicKey = NULL; CpaCyRsaEncryptOpData **ppEncryptOpData = NULL; CpaFlatBuffer **ppEncryptOutputData = NULL; /* end of local variable declarations */ ppPrivateKey = qaeMemAlloc(sizeof(CpaCyRsaPrivateKey *) * setup->numBuffers); if (NULL == ppPrivateKey) { PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } ppPublicKey = qaeMemAlloc(sizeof(CpaCyRsaPublicKey *) * setup->numBuffers); if (NULL == ppPublicKey) { qaeMemFree((void **)&ppPrivateKey); PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } ppEncryptOpData = qaeMemAlloc(sizeof(CpaCyRsaEncryptOpData *) * setup->numBuffers); if (NULL == ppEncryptOpData) { qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } ppEncryptOutputData = qaeMemAlloc(sizeof(CpaFlatBuffer *) * setup->numBuffers); if (NULL == ppEncryptOutputData) { qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppEncryptOpData); PRINT_ERR("qaeMemAlloc error\n"); return CPA_STATUS_FAIL; } status = genKeyArray(setup, ppPrivateKey, ppPublicKey); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("genKeyArray error %d\n", status); qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppEncryptOpData); qaeMemFree((void **)&ppEncryptOutputData); return CPA_STATUS_FAIL; } /*setup decrypt operation to decrypt random data*/ status = rsaEncryptDataSetup(NULL, ppEncryptOpData, ppEncryptOutputData, setup); if (status != CPA_STATUS_SUCCESS) { rsaFreeDataMemory( setup, NULL, NULL, ppEncryptOpData, ppEncryptOutputData); qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppEncryptOpData); qaeMemFree((void **)&ppEncryptOutputData); return CPA_STATUS_FAIL; } for (count = 0; count < setup->numBuffers; count++) { makeParam1SmallerThanParam2(ppEncryptOpData[count]->inputData.pData, ppPublicKey[count]->modulusN.pData, ppPublicKey[count]->modulusN.dataLenInBytes, CPA_FALSE); } /*setup decryption opData structure with RSA key*/ rsaSetOpDataKeys(setup, NULL, ppEncryptOpData, ppPrivateKey, ppPublicKey); status = sampleRsaEncrypt(setup, ppEncryptOpData, ppEncryptOutputData, setup->numBuffers, setup->numLoops); /*free all the key and operation data memory*/ rsaFreeKeyMemory(setup, ppPrivateKey, ppPublicKey); rsaFreeDataMemory(setup, NULL, NULL, ppEncryptOpData, ppEncryptOutputData); qaeMemFree((void **)&ppPrivateKey); qaeMemFree((void **)&ppPublicKey); qaeMemFree((void **)&ppEncryptOpData); qaeMemFree((void **)&ppEncryptOutputData); return status; } /****************************************************************************** * @ingroup sampleRSACode * * @description * Function for executing relevant algorithm and packet size * *****************************************************************************/ void sampleRsaThreadSetup(single_thread_test_data_t *testSetup) { asym_test_params_t rsaTestSetup = {0}; CpaStatus status = CPA_STATUS_SUCCESS; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; asym_test_params_t *params = (asym_test_params_t *)testSetup->setupPtr; CpaInstanceInfo2 *instanceInfo = NULL; #ifdef SC_DEV_INFO_ENABLED CpaDeviceInfo deviceInfo = {0}; #endif testSetup->passCriteria = getPassCriteria(); /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /* * In case of error scenario, the thread will exit early. * register the print function here itself to properly exit with statistics. */ if (params->rsaKeyRepType == CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2) { testSetup->statsPrintFunc = (stats_print_func_t)printRsaCrtPerfData; } else { testSetup->statsPrintFunc = (stats_print_func_t)printRsaPerfData; } /*give our thread a unique memory location to store performance stats*/ rsaTestSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return; } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); qaeMemFree((void **)&cyInstances); return; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); /* give our thread a logical crypto instance to use. * Use % to wrap around the max number of instances*/ rsaTestSetup.cyInstanceHandle = cyInstances[(testSetup->logicalQaInstance) % numInstances]; status = cpaCyInstanceGetInfo2(rsaTestSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } #ifdef SC_DEV_INFO_ENABLED /* check whether asym service enabled or not for the instance */ status = cpaGetDeviceInfo(instanceInfo->physInstId.acceleratorId, &deviceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaGetDeviceInfo failed", __func__, __LINE__); rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (CPA_FALSE == deviceInfo.cyAsymEnabled) { PRINT_ERR("%s::%d Error! cyAsymEnabled service not enabled for the " "configured instance\n", __func__, __LINE__); rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } #endif if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } rsaTestSetup.modulusSizeInBytes = testSetup->packetSize; rsaTestSetup.rsaKeyRepType = params->rsaKeyRepType; rsaTestSetup.numBuffers = params->numBuffers; rsaTestSetup.numLoops = params->numLoops; rsaTestSetup.syncMode = params->syncMode; rsaTestSetup.performEncrypt = params->performEncrypt; #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED rsaTestSetup.enableKPT = params->enableKPT; #endif #endif /*launch function that does all the work*/ if (params->performEncrypt) { status = sampleRsaEncryptPerform(&rsaTestSetup); } else { status = sampleRsaPerform(&rsaTestSetup); } // status = CPA_STATUS_FAIL; if (CPA_STATUS_SUCCESS != status) { #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == params->enableKPT) { PRINT("KPT2 Rsa Thread %u Failed\n", testSetup->threadID); } else { #endif #endif PRINT("Rsa Thread %u Failed\n", testSetup->threadID); #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED } #endif #endif rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeBarrier(); } else { rsaTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; } exit: qaeMemFree((void **)&instanceInfo); qaeMemFree((void **)&cyInstances); sampleCodeThreadComplete(testSetup->threadID); } EXPORT_SYMBOL(sampleRsaThreadSetup); /** ***************************************************************************** * @ingroup sampleRSACode * * @description * function to print out RSA CRT performance data * *****************************************************************************/ CpaStatus printRsaCrtPerfData(thread_creation_data_t *data) { asym_test_params_t *params = (asym_test_params_t *)data->setupPtr; if (params->performEncrypt) { PRINT("RSA CRT ENCRYPT\n"); } else { #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED if (CPA_TRUE == params->enableKPT) { PRINT("KPT RSA CRT DECRYPT\n"); } else { PRINT("RSA CRT DECRYPT\n"); } #else PRINT("RSA CRT DECRYPT\n"); #endif #else PRINT("RSA CRT DECRYPT\n"); #endif } PRINT("Modulus Size %19u\n", data->packetSize * NUM_BITS_IN_BYTE); return (printAsymStatsAndStopServices(data)); } /** ***************************************************************************** * @ingroup sampleRSACode * * @description * function to print out RSA CRT performance data * *****************************************************************************/ CpaStatus printRsaPerfData(thread_creation_data_t *data) { #if CY_API_VERSION_AT_LEAST(3, 0) #ifdef SC_KPT2_ENABLED asym_test_params_t *params = (asym_test_params_t *)data->setupPtr; if (CPA_TRUE == params->enableKPT) { PRINT("KPT RSA DECRYPT\n"); } else { PRINT("RSA DECRYPT\n"); } #else PRINT("RSA DECRYPT\n"); #endif #else PRINT("RSA DECRYPT\n"); #endif PRINT("Modulus Size %19u\n", data->packetSize * NUM_BITS_IN_BYTE); return (printAsymStatsAndStopServices(data)); } /** ***************************************************************************** * @ingroup sampleRSACode * * @description * Function for setup RSA test before calling framework createThreads * functions * *****************************************************************************/ CpaStatus setupRsaTest(Cpa32U modulusSize, CpaCyRsaPrivateKeyRepType rsaKeyRepType, sync_mode_t syncMode, Cpa32U numBuffs, Cpa32U numLoops) { /*setup is a multi-dimensional array that stores the setup for all thread * variations in an array of characters. we store our test setup at the * start of the second array ie index 0. There maybe multi thread types * (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure*/ asym_test_params_t *rsaSetup = NULL; Cpa8S name[] = {'R', 'S', 'A', '\0'}; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } if (iaCycleCount_g) { #ifdef POLL_INLINE enablePollInline(); #endif timeStampTime_g = getTimeStampTime(); PRINT("timeStampTime_g %llu\n", timeStampTime_g); } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration * file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); rsaSetup = (asym_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)sampleRsaThreadSetup; testSetupData_g[testTypeCount_g].packetSize = modulusSize / NUM_BITS_IN_BYTE; rsaSetup->rsaKeyRepType = rsaKeyRepType; rsaSetup->syncMode = syncMode; rsaSetup->numBuffers = numBuffs; rsaSetup->numLoops = numLoops; return CPA_STATUS_SUCCESS; } cpa_sample_code_sm2_Keyex_P1_P2.c000066400000000000000000000607641503624047500370340ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sm2_perf.c * * @ingroup cryptoThreads * * @description * This file contains the sm2 performance code. * Including Key Exchange P1/P2 * More details about the algorithm is in * http://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 *****************************************************************************/ #include "cpa_sample_code_sm2_perf.h" /** ****************************************************************************** * Callback function * Sm2 Key Exchange Phase 1 Callback function * Performance statistic * ******************************************************************************/ static void sm2KeyexP1Callback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { processCallback(pCallbackTag); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("sm2KeyexP1Callback error status %d\n", status); } } /** ****************************************************************************** * SM2 key exchange phase 2 post processing * SM2 APIs return the results of the point multiplication * In this function, continue to calculate the shared key with KDF && SM3 hash * param input : pIntermediateBuffer,pOut * param output : pSecretKeyBuffer ******************************************************************************/ static CpaStatus sm2KeyExPostProc(sm2_perf_test_t *perf_test, void *ptr) { CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2KeyExOutputData *pKeyexPKEOut = NULL; pKeyexPKEOut = (CpaCyEcsm2KeyExOutputData *)ptr; memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData, pKeyexPKEOut->x.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE, pKeyexPKEOut->y.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData + 2 * GFP_SM2_COORDINATE_SIZE_IN_BYTE, ZA, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData + 3 * GFP_SM2_COORDINATE_SIZE_IN_BYTE, ZB, GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* KDF(Xu||Yu||ZA||ZB,klen) */ status = kdf(perf_test->perf_buffer->pIntermediateBuffer, perf_test->perf_buffer->pC1Buffer); return status; } /** ****************************************************************************** * * Free any memory allocated in the SM2 key exchange phase 1 operation * ******************************************************************************/ void sm2KeyexP1MemFree(sm2_test_params_t *setup, CpaCyEcsm2KeyExPhase1OpData **opData, CpaCyEcsm2KeyExOutputData **outData) { Cpa32U k = 0; if (NULL != opData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != opData[k]) { qaeMemFreeNUMA((void **)&opData[k]->r.pData); qaeMemFreeNUMA((void **)&opData[k]); } } qaeMemFreeNUMA((void **)&opData); } if (NULL != outData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != outData[k]) { qaeMemFreeNUMA((void **)&outData[k]->x.pData); qaeMemFreeNUMA((void **)&outData[k]->y.pData); qaeMemFreeNUMA((void **)&outData[k]); } } qaeMemFreeNUMA((void **)&outData); } } /** ****************************************************************************** * Callback function * Sm2 Key Exchange Phase 2 Callback function * Post processing with KDF && SM3 Hash * Performance statistic * ******************************************************************************/ static void sm2KeyexP2Callback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { post_proc_data_t *postProcData = NULL; sm2_perf_test_t *pPerfTestData = NULL; void *ptr = NULL; perf_data_t *pPerfData = NULL; postProcData = (post_proc_data_t *)pCallbackTag; pPerfTestData = postProcData->sm2_perf_test; ptr = postProcData->ptr; pPerfData = pPerfTestData->setup->performanceStats; sm2KeyExPostProc(pPerfTestData, ptr); processCallback(pPerfData); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("sm2KeyexP2Callback error status %d\n", status); } } /** ****************************************************************************** * * Free any memory allocated in the SM2 key exchange phase 2 operation * ******************************************************************************/ void sm2KeyexP2MemFree(sm2_test_params_t *setup, CpaCyEcsm2KeyExPhase2OpData **opData, CpaCyEcsm2KeyExOutputData **outData, post_proc_data_t **post_proc_data) { Cpa32U k = 0; if (NULL != opData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != opData[k]) { qaeMemFreeNUMA((void **)&opData[k]->r.pData); qaeMemFreeNUMA((void **)&opData[k]->d.pData); qaeMemFreeNUMA((void **)&opData[k]->x1.pData); qaeMemFreeNUMA((void **)&opData[k]->x2.pData); qaeMemFreeNUMA((void **)&opData[k]->y2.pData); qaeMemFreeNUMA((void **)&opData[k]->xP.pData); qaeMemFreeNUMA((void **)&opData[k]->yP.pData); qaeMemFreeNUMA((void **)&opData[k]); } } qaeMemFreeNUMA((void **)&opData); } if (NULL != outData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != outData[k]) { qaeMemFreeNUMA((void **)&outData[k]->x.pData); qaeMemFreeNUMA((void **)&outData[k]->y.pData); qaeMemFreeNUMA((void **)&outData[k]); } } qaeMemFreeNUMA((void **)&outData); } if (NULL != post_proc_data) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != post_proc_data[k]) { qaeMemFreeNUMA((void **)&post_proc_data[k]); } } qaeMemFreeNUMA((void **)&post_proc_data); } } /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 key exchange phase 2 operation * This function is called for key exchange phase 2 performance test. * ******************************************************************************/ CpaStatus sm2KeyexP2Perform(sm2_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; CpaCyEcsm2Stats64 sm2Stats = {0}; CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2KeyExPhase2OpData **opData = NULL; CpaCyEcsm2KeyExOutputData **outData = NULL; /* allocated for every loop */ post_proc_data_t **post_proc_data = NULL; CpaFlatBuffer *pSecretKey = NULL; CpaFlatBuffer *pIntermediateBuffer = NULL; Cpa32U klen = SECRET_KEY_LEN_IN_BYTE; /*variable to store what cpu thread is running on*/ Cpa32U node = 0; /*pointer to location to store performance data*/ perf_data_t *pSm2Data = NULL; sm2_perf_test_t *sm2PerfTest = NULL; sm2_perf_buf_t *sm2PerfBuffer = NULL; CpaCyGenFlatBufCbFunc cbFunc = NULL; status = cpaCyEcsm2QueryStats64(setup->cyInstanceHandle, &sm2Stats); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Could not retrieve stats, error status %d\n", status); return status; } /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } sm2PerfTest = qaeMemAllocNUMA(sizeof(sm2_perf_test_t), node, BYTE_ALIGNMENT_64); if (NULL == sm2PerfTest) { PRINT_ERR("Memory allocation failure for sm2PerfTest\n"); return CPA_STATUS_FAIL; } sm2PerfBuffer = qaeMemAllocNUMA(sizeof(sm2_perf_buf_t), node, BYTE_ALIGNMENT_64); if (NULL == sm2PerfBuffer) { PRINT_ERR("Memory allocation failure for sm2PerfBuffer\n"); goto cleanup; } initSemaphoreAndVariables(pSm2Data, setup); status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&opData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("opData mem allocation error\n"); goto cleanup; } /* allocate memory according to the setup->numBuffers */ status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&post_proc_data, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("post_proc_data mem allocation error\n"); goto cleanup; } status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&outData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("outData mem allocation error\n"); goto cleanup; } /*allocate and populate all the operation data buffers*/ for (i = 0; i < setup->numBuffers; i++) { opData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2KeyExPhase2OpData), node, BYTE_ALIGNMENT_64); if (NULL == opData[i]) { PRINT_ERR("opData[%u] memory allocation error\n", i); goto cleanup; } memset(opData[i], 0, sizeof(CpaCyEcsm2KeyExPhase2OpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->r, setup->nLenInBytes, setup->random[setup->numBuffers - i - 1].pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P2_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->d, setup->nLenInBytes, setup->d2->pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P2_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->x1, setup->nLenInBytes, setup->x2[i].pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P2_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->x2, setup->nLenInBytes, setup->x1[i].pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P2_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->y2, setup->nLenInBytes, setup->y1[i].pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P2_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->xP, setup->nLenInBytes, setup->xP->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P2_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->yP, setup->nLenInBytes, setup->yP->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P2_MEM_FREE()); outData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2KeyExOutputData), node, BYTE_ALIGNMENT_64); if (NULL == outData[i]) { PRINT_ERR("outData[%u] memory allocation error\n", i); goto cleanup; } memset(outData[i], 0, sizeof(CpaCyEcsm2KeyExOutputData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->x, setup->nLenInBytes, NULL, 0, SM2_PERFORM_KEYEX_P2_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->y, setup->nLenInBytes, NULL, 0, SM2_PERFORM_KEYEX_P2_MEM_FREE()); post_proc_data[i] = qaeMemAllocNUMA(sizeof(post_proc_data_t), node, BYTE_ALIGNMENT_64); if (NULL == post_proc_data[i]) { PRINT_ERR("Memory allocation failure for post_proc_data\n"); goto cleanup; } memset(post_proc_data[i], 0, sizeof(post_proc_data_t)); } /* Set the callback function if asynchronous mode is set */ if (ASYNC == setup->syncMode) { cbFunc = (CpaCyGenFlatBufCbFunc)sm2KeyexP2Callback; } pSecretKey = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pSecretKey, klen, NULL, 0, SM2_KEYEX_MSG_MEM_FREE()); pIntermediateBuffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pIntermediateBuffer, 4 * GFP_SM2_SIZE_IN_BYTE + KDF_COUNTER_PADDING, NULL, 0, SM2_KEYEX_MSG_MEM_FREE()); /* Temporary buffers for sm2KeyExPostProc */ sm2PerfBuffer->pC1Buffer = pSecretKey; sm2PerfBuffer->pIntermediateBuffer = pIntermediateBuffer; sm2PerfBuffer->pKeyexPKEOut = outData[0]; /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Record the start time, the callback measures the end time when the last * response is received*/ pSm2Data->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { for (i = 0; i < setup->numBuffers; i++) { do { opData[i]->fieldType = setup->fieldType; sm2PerfTest->setup = setup; sm2PerfTest->perf_buffer = sm2PerfBuffer; post_proc_data[i]->sm2_perf_test = sm2PerfTest; post_proc_data[i]->ptr = (void *)outData[i]; status = cpaCyEcsm2KeyExPhase2(setup->cyInstanceHandle, (CpaCyGenFlatBufCbFunc)cbFunc, (void *)post_proc_data[i], opData[i], outData[i]); waitForAEonRetry(status, pSm2Data); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("SM2 Verify function failed with status:%d\n", status); goto cleanup; } } /*end buffers loop */ } /* end of numLoops loop*/ if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSm2Data, setup->syncMode, setup->numBuffers, setup->numLoops); } sampleCodeSemaphoreDestroy(&pSm2Data->comp); /*Free all memory*/ SM2_KEYEX_MSG_MEM_FREE(); SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; cleanup: SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (pSecretKey != NULL) SM2_KEYEX_MSG_MEM_FREE(); if (sm2PerfBuffer != NULL) SM2_PERFORM_KEYEX_P2_MEM_FREE(); return CPA_STATUS_FAIL; } /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 key exchange phase 1 operation * This function is called for key exchange phase 1 performance test. * ******************************************************************************/ CpaStatus sm2KeyexP1Perform(sm2_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; CpaCyEcsm2Stats64 sm2Stats = {0}; CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2KeyExPhase1OpData **opData = NULL; CpaCyEcsm2KeyExOutputData **outData = NULL; /*variable to store what CPU Node/socket is running on*/ Cpa32U node = 0; /*pointer to location to store performance data*/ perf_data_t *pSm2Data = NULL; CpaCyGenFlatBufCbFunc cbFunc = NULL; status = cpaCyEcsm2QueryStats64(setup->cyInstanceHandle, &sm2Stats); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Could not retrieve stats, error status %d\n", status); return status; } /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } initSemaphoreAndVariables(pSm2Data, setup); status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&opData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("opData mem allocation error\n"); goto cleanup; } status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&outData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("outData mem allocation error\n"); goto cleanup; } /*allocate and populate all the Operation Data buffers*/ for (i = 0; i < setup->numBuffers; i++) { opData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2KeyExPhase1OpData), node, BYTE_ALIGNMENT_64); if (NULL == opData[i]) { PRINT_ERR("opData[%u] memory allocation error\n", i); goto cleanup; } memset(opData[i], 0, sizeof(CpaCyEcsm2KeyExPhase1OpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->r, setup->nLenInBytes, setup->random[i].pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_KEYEX_P1_MEM_FREE()); outData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2KeyExOutputData), node, BYTE_ALIGNMENT_64); if (NULL == outData[i]) { PRINT_ERR("outData[%u] memory allocation error\n", i); goto cleanup; } memset(outData[i], 0, sizeof(CpaCyEcsm2KeyExOutputData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->x, setup->nLenInBytes, NULL, 0, SM2_PERFORM_KEYEX_P1_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->y, setup->nLenInBytes, NULL, 0, SM2_PERFORM_KEYEX_P1_MEM_FREE()); } /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = (CpaCyGenFlatBufCbFunc)sm2KeyexP1Callback; } pSm2Data->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; pSm2Data->responses = 0; /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Record the start time, the callback measures the end time when the last * response is received */ pSm2Data->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { for (i = 0; i < setup->numBuffers; i++) { do { opData[i]->fieldType = setup->fieldType; status = cpaCyEcsm2KeyExPhase1(setup->cyInstanceHandle, (CpaCyGenFlatBufCbFunc)cbFunc, pSm2Data, opData[i], outData[i]); waitForAEonRetry(status, pSm2Data); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("SM2 Verify function failed with status:%d\n", status); goto cleanup; } } /*end buffers loop */ } /* end of numLoops loop*/ if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSm2Data, setup->syncMode, setup->numBuffers, setup->numLoops); } sampleCodeSemaphoreDestroy(&pSm2Data->comp); /*Free all memory*/ SM2_PERFORM_KEYEX_P1_MEM_FREE(); SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; cleanup: SM2_PERFORM_SETUP_FLAT_MEM_FREE(); SM2_PERFORM_KEYEX_P1_MEM_FREE(); return CPA_STATUS_FAIL; } cpa_sample_code_sm2_enc_dec.c000066400000000000000000001261021503624047500364130ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sm2_perf.c * * @ingroup cryptoThreads * * @description * This file contains the sm2 performance code. * Including Encryption, Decryption * More details about the algorithm is in * http://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 *****************************************************************************/ #include "cpa_sample_code_sm2_perf.h" #include "cpa_sample_code_crypto_utils.h" /** ******************************************************************************* * * Free any memory allocated in the SM2 cipher data setup * *******************************************************************************/ void sm2SetupEncMemFree(CpaCyEcsm2EncryptOpData *opData, CpaCyEcsm2EncryptOutputData *outData) { if (NULL != opData) { qaeMemFreeNUMA((void **)&opData->k.pData); qaeMemFreeNUMA((void **)&opData->xP.pData); qaeMemFreeNUMA((void **)&opData->yP.pData); qaeMemFreeNUMA((void **)&opData); } if (NULL != outData) { qaeMemFreeNUMA((void **)&outData->x1.pData); qaeMemFreeNUMA((void **)&outData->y1.pData); qaeMemFreeNUMA((void **)&outData->x2.pData); qaeMemFreeNUMA((void **)&outData->y2.pData); qaeMemFreeNUMA((void **)&outData); } } /** ****************************************************************************** * SM2 encryption function for data setup * This function will be called in sm2PerfDataSetup(), encrypt the * random message, and store the cipher for the decryption perform. * ******************************************************************************/ CpaStatus sm2Enc(sm2_test_params_t *setup) { Cpa32U j = 0; CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2EncryptOpData *opData = NULL; CpaCyEcsm2EncryptOutputData *outData = NULL; CpaFlatBuffer *pC1Buffer = NULL; CpaFlatBuffer *pC2Buffer = NULL; CpaFlatBuffer *pC3Buffer = NULL; CpaFlatBuffer *pIntermediateBuffer = NULL; CpaFlatBuffer *pEncOutputData = NULL; /*variable to store what cpu thread is running on*/ Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /* Allocate memory for the operation data */ opData = qaeMemAllocNUMA( sizeof(CpaCyEcsm2EncryptOpData), node, BYTE_ALIGNMENT_64); if (NULL == opData) { PRINT_ERR("opData memory allocation error\n"); goto cleanup; } memset(opData, 0, sizeof(CpaCyEcsm2EncryptOpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData->k, setup->nLenInBytes, setup->random[0].pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_SETUP_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData->xP, setup->nLenInBytes, setup->xP->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_SETUP_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData->yP, setup->nLenInBytes, setup->yP->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_SETUP_ENC_MEM_FREE()); /* Alloc memory for the output data */ outData = qaeMemAllocNUMA( sizeof(CpaCyEcsm2EncryptOutputData), 0, BYTE_ALIGNMENT_64); if (NULL == outData) { PRINT_ERR("SM2 outData memory allocation error\n"); goto cleanup; } memset(outData, 0, sizeof(CpaCyEcsm2EncryptOutputData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData->x1, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData->y1, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData->x2, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData->y2, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_ENC_MEM_FREE()); /* Alloc memory for the intermediate buffers */ pC1Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC1Buffer, GFP_SM2_POINT_SIZE_IN_BYTE, NULL, 0, SM2_ENC_SETUP_MSG_MEM_FREE()); pC2Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC2Buffer, MESSAGE_LEN, NULL, 0, SM2_ENC_SETUP_MSG_MEM_FREE()); pC3Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC3Buffer, SM3_HASH_SIZE_IN_BYTE, NULL, 0, SM2_ENC_SETUP_MSG_MEM_FREE()); pIntermediateBuffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pIntermediateBuffer, 2 * GFP_SM2_SIZE_IN_BYTE + KDF_COUNTER_PADDING, NULL, 0, SM2_ENC_SETUP_MSG_MEM_FREE()); pEncOutputData = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pEncOutputData, GFP_SM2_POINT_SIZE_IN_BYTE + MESSAGE_LEN + SM3_HASH_SIZE_IN_BYTE, NULL, 0, SM2_ENC_SETUP_MSG_MEM_FREE()); /* Call the driver API to calculate point multiplication, in * synchronous mode */ do { opData->fieldType = setup->fieldType; status = cpaCyEcsm2Encrypt( setup->cyInstanceHandle, NULL, NULL, opData, outData); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("SM2 Enc function failed with status:%d\n", status); goto cleanup; } /* convert point (x1,y1) to byte string, uncompressed */ convertPointToBytes( pC1Buffer->pData, outData->x1.pData, outData->y1.pData, FALSE); /* copy point multiply results, x2 , y2 to x2||y2 */ memcpy(pIntermediateBuffer->pData, outData->x2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(pIntermediateBuffer->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE, outData->y2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* kdf function, input buffer 68bytes x2||y2 + 4byte ct, * output buffer 32bytes */ kdf(pIntermediateBuffer, pC2Buffer); /* msg xor t (output of KDF) */ for (j = 0; j < MESSAGE_LEN; j++) { *(pC2Buffer->pData + j) ^= *(setup->message->pData + j); } /* x2||M||y2 */ memcpy(pEncOutputData->pData, outData->x2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(pEncOutputData->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE, setup->message->pData, MESSAGE_LEN); memcpy(pEncOutputData->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE + MESSAGE_LEN, outData->y2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* hash(x2||M||y2) */ sm3(pEncOutputData->pData, 2 * GFP_SM2_COORDINATE_SIZE_IN_BYTE + MESSAGE_LEN, pC3Buffer->pData); /* C1||C2||C3 */ memcpy(setup->cipher->pData, pC1Buffer->pData, GFP_SM2_POINT_SIZE_IN_BYTE); memcpy(setup->cipher->pData + GFP_SM2_POINT_SIZE_IN_BYTE, pC2Buffer->pData, MESSAGE_LEN); memcpy(setup->cipher->pData + GFP_SM2_POINT_SIZE_IN_BYTE + MESSAGE_LEN, pC3Buffer->pData, GFP_SM2_SIZE_IN_BYTE); /*Free all memory*/ SM2_ENC_SETUP_MSG_MEM_FREE(); return status; cleanup: SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (pC1Buffer != NULL) SM2_ENC_SETUP_MSG_MEM_FREE(); else SM2_PERFORM_SETUP_ENC_MEM_FREE(); return status; } /** ****************************************************************************** * * Free any memory allocated in the SM2 encryption operation * ******************************************************************************/ static void sm2EncMemFree(sm2_test_params_t *setup, CpaCyEcsm2EncryptOpData **opData, CpaCyEcsm2EncryptOutputData **outData, post_proc_data_t **post_proc_data) { Cpa32U k = 0; if (NULL != opData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != opData[k]) { qaeMemFreeNUMA((void **)&opData[k]->k.pData); qaeMemFreeNUMA((void **)&opData[k]->xP.pData); qaeMemFreeNUMA((void **)&opData[k]->yP.pData); qaeMemFreeNUMA((void **)&opData[k]); } } qaeMemFreeNUMA((void **)&opData); } if (NULL != outData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != outData[k]) { qaeMemFreeNUMA((void **)&outData[k]->x1.pData); qaeMemFreeNUMA((void **)&outData[k]->y1.pData); qaeMemFreeNUMA((void **)&outData[k]->x2.pData); qaeMemFreeNUMA((void **)&outData[k]->y2.pData); qaeMemFreeNUMA((void **)&outData[k]); } } qaeMemFreeNUMA((void **)&outData); } if (NULL != post_proc_data) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != post_proc_data[k]) { qaeMemFreeNUMA((void **)&post_proc_data[k]); } } qaeMemFreeNUMA((void **)&post_proc_data); } } /** ****************************************************************************** * * Free any memory allocated in the SM2 decryption operation * ******************************************************************************/ static void sm2DecMemFree(sm2_test_params_t *setup, CpaCyEcsm2DecryptOpData **opData, CpaCyEcsm2DecryptOutputData **outData, post_proc_data_t **post_proc_data) { Cpa32U k = 0; if (NULL != opData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != opData[k]) { qaeMemFreeNUMA((void **)&opData[k]->d.pData); qaeMemFreeNUMA((void **)&opData[k]->x1.pData); qaeMemFreeNUMA((void **)&opData[k]->y1.pData); qaeMemFreeNUMA((void **)&opData[k]); } } qaeMemFreeNUMA((void **)&opData); } if (NULL != outData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != outData[k]) { qaeMemFreeNUMA((void **)&outData[k]->x2.pData); qaeMemFreeNUMA((void **)&outData[k]->y2.pData); qaeMemFreeNUMA((void **)&outData[k]); } } qaeMemFreeNUMA((void **)&outData); } if (NULL != post_proc_data) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != post_proc_data[k]) { qaeMemFreeNUMA((void **)&post_proc_data[k]); } } qaeMemFreeNUMA((void **)&post_proc_data); } } /** ****************************************************************************** * SM2 encryption post processing * SM2 APIs return the results of the point multiplication * In this function, continue to calculate the cipher text with KDF && SM3 hash * param input : pC1Buffer,pC2Buffer,pC3Buffer,pIntermediateBuffer,pEncPKEOut * param output : pEncOutputData ******************************************************************************/ static CpaStatus sm2EncPostProc(sm2_perf_test_t *perf_test, void *ptr) { int j = 0; CpaStatus status = CPA_STATUS_SUCCESS; CpaCyEcsm2EncryptOutputData *pEncPKEOut = NULL; pEncPKEOut = (CpaCyEcsm2EncryptOutputData *)ptr; /* convert point (x1,y1) to byte string, uncompressed */ convertPointToBytes(perf_test->perf_buffer->pC1Buffer->pData, pEncPKEOut->x1.pData, pEncPKEOut->y1.pData, FALSE); /* copy point multiply results, x2 , y2 to x2||y2 */ memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData, pEncPKEOut->x2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE, pEncPKEOut->y2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* kdf function, input buffer 68bytes x2||y2 + 4byte ct, * output buffer 32bytes */ kdf(perf_test->perf_buffer->pIntermediateBuffer, perf_test->perf_buffer->pC2Buffer); /* msg xor t (output of KDF) */ for (j = 0; j < MESSAGE_LEN; j++) { *(perf_test->perf_buffer->pC2Buffer->pData + j) ^= *(perf_test->setup->message->pData + j); } /* x2||M||y2 */ memcpy(perf_test->perf_buffer->pEncOutputData->pData, pEncPKEOut->x2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pEncOutputData->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE, perf_test->setup->message->pData, MESSAGE_LEN); memcpy(perf_test->perf_buffer->pEncOutputData->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE + MESSAGE_LEN, pEncPKEOut->y2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* hash(x2||M||y2) */ sm3(perf_test->perf_buffer->pEncOutputData->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE + MESSAGE_LEN + GFP_SM2_COORDINATE_SIZE_IN_BYTE, perf_test->perf_buffer->pC3Buffer->pData); memset(perf_test->perf_buffer->pEncOutputData->pData, 0, GFP_SM2_POINT_SIZE_IN_BYTE + MESSAGE_LEN + GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* C1||C2||C3 */ memcpy(perf_test->perf_buffer->pEncOutputData->pData, perf_test->perf_buffer->pC1Buffer->pData, GFP_SM2_POINT_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pEncOutputData->pData + GFP_SM2_POINT_SIZE_IN_BYTE, perf_test->perf_buffer->pC2Buffer->pData, MESSAGE_LEN); memcpy(perf_test->perf_buffer->pEncOutputData->pData + GFP_SM2_POINT_SIZE_IN_BYTE + MESSAGE_LEN, perf_test->perf_buffer->pC3Buffer->pData, GFP_SM2_SIZE_IN_BYTE); return status; } /* ****************************************************************************** * SM2 decryption post processing * SM2 APIs return the results of the point multiplication * In this function, continue to calculate the plain text with KDF && SM3 hash * param input : pC1Buffer,pC2Buffer,pC3Buffer,pHashBuffer,pIntermediateBuffer, * pDecPKEOut * param output : pDecOutputData ******************************************************************************/ static CpaStatus sm2DecPostProc(sm2_perf_test_t *perf_test, void *ptr) { int j = 0; CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2DecryptOutputData *pDecPKEOut = NULL; pDecPKEOut = (CpaCyEcsm2DecryptOutputData *)ptr; /* x2||y2 */ memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData, pDecPKEOut->x2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pIntermediateBuffer->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE, pDecPKEOut->y2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* KDF(X2||y2,klen) */ kdf(perf_test->perf_buffer->pIntermediateBuffer, perf_test->perf_buffer->pC1Buffer); /* msg = C2 xor t */ for (j = 0; j < MESSAGE_LEN; j++) { *(perf_test->perf_buffer->pC1Buffer->pData + j) ^= *(perf_test->perf_buffer->pC2Buffer->pData + j); } /* x2||M'||y2 */ memcpy(perf_test->perf_buffer->pDecOutputData->pData, pDecPKEOut->x2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); memcpy(perf_test->perf_buffer->pDecOutputData->pData + GFP_SM2_COORDINATE_SIZE_IN_BYTE, perf_test->perf_buffer->pC1Buffer->pData, MESSAGE_LEN); memcpy(perf_test->perf_buffer->pDecOutputData->pData + CIPHER_LEN - GFP_SM2_POINT_SIZE_IN_BYTE, pDecPKEOut->y2.pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE); /* hash(x2||M'||y2) */ sm3(perf_test->perf_buffer->pDecOutputData->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE + CIPHER_LEN - GFP_SM2_POINT_SIZE_IN_BYTE, perf_test->perf_buffer->pHashBuffer->pData); /* check if hash value is equal to the C3 */ hashCheck(perf_test->perf_buffer->pC3Buffer->pData, perf_test->perf_buffer->pHashBuffer->pData, &status); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("DEC Error \n"); } return status; } /** ****************************************************************************** * Callback function * Sm2 Encryption Callback function * Post processing with KDF && SM3 Hash * Performance statistic * ******************************************************************************/ static void sm2EncCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { post_proc_data_t *postProcData = NULL; sm2_perf_test_t *pPerfTestData = NULL; perf_data_t *pPerfData = NULL; void *ptr = NULL; postProcData = (post_proc_data_t *)pCallbackTag; pPerfTestData = postProcData->sm2_perf_test; ptr = postProcData->ptr; pPerfData = pPerfTestData->setup->performanceStats; sm2EncPostProc(pPerfTestData, ptr); processCallback(pPerfData); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("sm2EncCallback error status %d\n", status); } } /** ****************************************************************************** * Callback function * Sm2 Decryption Callback function * Post processing with KDF && SM3 Hash * Performance statistic * ******************************************************************************/ static void sm2DecCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaFlatBuffer *pOut) { post_proc_data_t *postProcData = NULL; sm2_perf_test_t *pPerfTestData = NULL; perf_data_t *pPerfData = NULL; void *ptr = NULL; postProcData = (post_proc_data_t *)pCallbackTag; pPerfTestData = postProcData->sm2_perf_test; ptr = postProcData->ptr; pPerfData = pPerfTestData->setup->performanceStats; sm2DecPostProc(pPerfTestData, ptr); processCallback(pPerfData); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("sm2DecCallback error status %d\n", status); } } /** ****************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Encryption operation * This function is called for performance test. * ******************************************************************************/ CpaStatus sm2EncPerform(sm2_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; Cpa32U loops = 0; CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2EncryptOpData **opData = NULL; CpaCyEcsm2EncryptOutputData **outData = NULL; /* allocated for every loop */ post_proc_data_t **post_proc_data = NULL; CpaFlatBuffer *pC1Buffer = NULL; CpaFlatBuffer *pC2Buffer = NULL; CpaFlatBuffer *pC3Buffer = NULL; CpaFlatBuffer *pIntermediateBuffer = NULL; CpaFlatBuffer *pEncOutputData = NULL; /* Variable to store what CPU Node/socket is running on*/ Cpa32U node = 0; /* Pointer to location to store performance data*/ perf_data_t *pSm2Data = NULL; sm2_perf_test_t *sm2PerfTest = NULL; sm2_perf_buf_t *sm2PerfBuffer = NULL; CpaCyGenFlatBufCbFunc cbFunc = NULL; /* Get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } sm2PerfTest = qaeMemAllocNUMA(sizeof(sm2_perf_test_t), node, BYTE_ALIGNMENT_64); if (NULL == sm2PerfTest) { PRINT_ERR("Memory allocation failure for sm2PerfTest\n"); return CPA_STATUS_FAIL; } sm2PerfBuffer = qaeMemAllocNUMA(sizeof(sm2_perf_buf_t), node, BYTE_ALIGNMENT_64); if (NULL == sm2PerfBuffer) { PRINT_ERR("Memory allocation failure for sm2PerfBuffer\n"); goto cleanup; } initSemaphoreAndVariables(pSm2Data, setup); status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&opData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("opData mem allocation error\n"); goto cleanup; } /* allocate memory according to the setup->numBuffers */ status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&post_proc_data, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("post_proc_data mem allocation error\n"); goto cleanup; } status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&outData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("outData mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { opData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2EncryptOpData), node, BYTE_ALIGNMENT_64); if (NULL == opData[i]) { PRINT_ERR("opData[%u] memory allocation error\n", i); goto cleanup; } memset(opData[i], 0, sizeof(CpaCyEcsm2EncryptOpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->k, setup->nLenInBytes, setup->random[i].pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->xP, setup->nLenInBytes, setup->xP->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->yP, setup->nLenInBytes, setup->yP->pData, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_ENC_MEM_FREE()); opData[i]->fieldType = setup->fieldType; outData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2EncryptOutputData), node, BYTE_ALIGNMENT_64); if (NULL == outData[i]) { PRINT_ERR("outData[%u] memory allocation error\n", i); goto cleanup; } memset(outData[i], 0, sizeof(CpaCyEcsm2EncryptOutputData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->x1, setup->nLenInBytes, NULL, 0, SM2_PERFORM_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->y1, setup->nLenInBytes, NULL, 0, SM2_PERFORM_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->x2, setup->nLenInBytes, NULL, 0, SM2_PERFORM_ENC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->y2, setup->nLenInBytes, NULL, 0, SM2_PERFORM_ENC_MEM_FREE()); post_proc_data[i] = qaeMemAllocNUMA(sizeof(post_proc_data_t), node, BYTE_ALIGNMENT_64); if (NULL == post_proc_data[i]) { PRINT_ERR("Memory allocation failure for post_proc_data\n"); goto cleanup; } memset(post_proc_data[i], 0, sizeof(post_proc_data_t)); } /* Set the callback function if asynchronous mode is set */ if (ASYNC == setup->syncMode) { cbFunc = (CpaCyGenFlatBufCbFunc)sm2EncCallback; } numLoops = setup->numLoops; pC1Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC1Buffer, GFP_SM2_POINT_SIZE_IN_BYTE, NULL, 0, SM2_ENC_MSG_MEM_FREE()); pC2Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC2Buffer, MESSAGE_LEN, NULL, 0, SM2_ENC_MSG_MEM_FREE()); pC3Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC3Buffer, GFP_SM2_COORDINATE_SIZE_IN_BYTE, NULL, 0, SM2_ENC_MSG_MEM_FREE()); pIntermediateBuffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pIntermediateBuffer, 2 * GFP_SM2_SIZE_IN_BYTE + KDF_COUNTER_PADDING, NULL, 0, SM2_ENC_MSG_MEM_FREE()); pEncOutputData = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pEncOutputData, GFP_SM2_POINT_SIZE_IN_BYTE + MESSAGE_LEN + GFP_SM2_COORDINATE_SIZE_IN_BYTE, NULL, 0, SM2_ENC_MSG_MEM_FREE()); /* Temporary buffers for sm2EncPostProc */ sm2PerfBuffer->pC1Buffer = pC1Buffer; sm2PerfBuffer->pC2Buffer = pC2Buffer; sm2PerfBuffer->pC3Buffer = pC3Buffer; sm2PerfBuffer->pIntermediateBuffer = pIntermediateBuffer; sm2PerfBuffer->pEncOutputData = pEncOutputData; /* record the base address of the output data of API */ sm2PerfBuffer->pDecPKEOut = (CpaCyEcsm2DecryptOutputData *)outData[0]; /* This barrier will wait until all threads get to this point */ sampleCodeBarrier(); /* Record the start time, the callback measures the end time when the last * response is received*/ pSm2Data->startCyclesTimestamp = sampleCodeTimestamp(); for (loops = 0; loops < numLoops; loops++) { for (i = 0; i < setup->numBuffers; i++) { do { opData[i]->fieldType = setup->fieldType; sm2PerfTest->setup = setup; sm2PerfTest->perf_buffer = sm2PerfBuffer; post_proc_data[i]->sm2_perf_test = sm2PerfTest; post_proc_data[i]->ptr = (void *)outData[i]; status = cpaCyEcsm2Encrypt(setup->cyInstanceHandle, (CpaCyGenFlatBufCbFunc)cbFunc, (void *)post_proc_data[i], opData[i], outData[i]); waitForAEonRetry(status, pSm2Data); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("SM2 Enc function failed with status:%d\n", status); goto cleanup; } } /*end buffers loop */ } /* end of numLoops loop*/ if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSm2Data, setup->syncMode, setup->numBuffers, setup->numLoops); } sampleCodeSemaphoreDestroy(&pSm2Data->comp); /*Free all memory*/ SM2_ENC_MSG_MEM_FREE(); SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; cleanup: SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (pC1Buffer != NULL) SM2_ENC_MSG_MEM_FREE(); if (sm2PerfTest != NULL) SM2_PERFORM_ENC_MEM_FREE(); return CPA_STATUS_FAIL; } /* ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Decryption operation * This function is called for performance test. * ******************************************************************************/ CpaStatus sm2DecPerform(sm2_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; Cpa32U loops = 0; CpaCyEcsm2Stats64 sm2Stats = {0}; CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2DecryptOpData **opData = NULL; CpaCyEcsm2DecryptOutputData **outData = NULL; /* allocated for every loop */ post_proc_data_t **post_proc_data = NULL; CpaFlatBuffer *pDecOutputData = NULL; CpaFlatBuffer *pM1Buffer = NULL; CpaFlatBuffer *pC2Buffer = NULL; CpaFlatBuffer *pC3Buffer = NULL; CpaFlatBuffer *pHashBuffer = NULL; CpaFlatBuffer *pIntermediateBuffer = NULL; /*variable to store what cpu thread is running on*/ Cpa32U node = 0; /*pointer to location to store performance data*/ perf_data_t *pSm2Data = NULL; sm2_perf_test_t *sm2PerfTest = NULL; sm2_perf_buf_t *sm2PerfBuffer = NULL; CpaCyGenFlatBufCbFunc cbFunc = NULL; status = cpaCyEcsm2QueryStats64(setup->cyInstanceHandle, &sm2Stats); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Could not retrieve stats, error status %d\n", status); return status; } /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } sm2PerfTest = qaeMemAllocNUMA(sizeof(sm2_perf_test_t), node, BYTE_ALIGNMENT_64); if (NULL == sm2PerfTest) { PRINT_ERR("Memory allocation failure for sm2PerfTest\n"); return CPA_STATUS_FAIL; } sm2PerfBuffer = qaeMemAllocNUMA(sizeof(sm2_perf_buf_t), node, BYTE_ALIGNMENT_64); if (NULL == sm2PerfBuffer) { PRINT_ERR("Memory allocation failure for sm2PerfBuffer\n"); goto cleanup; } initSemaphoreAndVariables(pSm2Data, setup); numLoops = setup->numLoops; status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&opData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("opData mem allocation error\n"); goto cleanup; } /* allocate memory according to the setup->numBuffers */ status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&post_proc_data, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("post_proc_data mem allocation error\n"); goto cleanup; } status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&outData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("outData mem allocation error\n"); goto cleanup; } /* Allocate and populate all the operation data buffers */ for (i = 0; i < setup->numBuffers; i++) { opData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2DecryptOpData), node, BYTE_ALIGNMENT_64); if (NULL == opData[i]) { PRINT_ERR("opData[%u] memory allocation error\n", i); goto cleanup; } memset(opData[i], 0, sizeof(CpaCyEcsm2DecryptOpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->d, setup->nLenInBytes, setup->d->pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_DEC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->x1, setup->nLenInBytes, setup->cipher->pData + 1, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_DEC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->y1, setup->nLenInBytes, setup->cipher->pData + 1 + GFP_SM2_COORDINATE_SIZE_IN_BYTE, GFP_SM2_COORDINATE_SIZE_IN_BYTE, SM2_PERFORM_DEC_MEM_FREE()); outData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2DecryptOutputData), node, BYTE_ALIGNMENT_64); if (NULL == outData[i]) { PRINT_ERR("outData[%u] memory allocation error\n", i); goto cleanup; } memset(outData[i], 0, sizeof(CpaCyEcsm2DecryptOutputData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->x2, setup->nLenInBytes, NULL, 0, SM2_PERFORM_DEC_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->y2, setup->nLenInBytes, NULL, 0, SM2_PERFORM_DEC_MEM_FREE()); post_proc_data[i] = qaeMemAllocNUMA(sizeof(post_proc_data_t), node, BYTE_ALIGNMENT_64); if (NULL == post_proc_data[i]) { PRINT_ERR("Memory allocation failure for post_proc_data\n"); goto cleanup; } memset(post_proc_data[i], 0, sizeof(post_proc_data_t)); } pC2Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC2Buffer, MESSAGE_LEN, setup->cipher->pData + GFP_SM2_POINT_SIZE_IN_BYTE, MESSAGE_LEN, SM2_DEC_MSG_MEM_FREE()); pC3Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pC3Buffer, SM3_HASH_SIZE_IN_BYTE, setup->cipher->pData + GFP_SM2_POINT_SIZE_IN_BYTE + MESSAGE_LEN, SM3_HASH_SIZE_IN_BYTE, SM2_DEC_MSG_MEM_FREE()); pM1Buffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pM1Buffer, MESSAGE_LEN, NULL, 0, SM2_DEC_MSG_MEM_FREE()); pHashBuffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pHashBuffer, SM3_HASH_SIZE_IN_BYTE, NULL, 0, SM2_DEC_MSG_MEM_FREE()); pIntermediateBuffer = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pIntermediateBuffer, 2 * GFP_SM2_SIZE_IN_BYTE + KDF_COUNTER_PADDING, NULL, 0, SM2_DEC_MSG_MEM_FREE()); pDecOutputData = qaeMemAllocNUMA(sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, pDecOutputData, CIPHER_LEN, NULL, 0, SM2_DEC_MSG_MEM_FREE()); /* Set the callback function if asynchronous mode is set */ if (ASYNC == setup->syncMode) { cbFunc = (CpaCyGenFlatBufCbFunc)sm2DecCallback; } /* Temporary buffers for sm2DecPostProc*/ sm2PerfBuffer->pC1Buffer = pM1Buffer; sm2PerfBuffer->pC2Buffer = pC2Buffer; sm2PerfBuffer->pC3Buffer = pC3Buffer; sm2PerfBuffer->pHashBuffer = pHashBuffer; /* 64 bytes + 4 bytes */ sm2PerfBuffer->pIntermediateBuffer = pIntermediateBuffer; /* 1 byte(header,04=uncompression) + 64 bytes(x,y coordinate) + msg_len + * 32 bytes */ sm2PerfBuffer->pDecOutputData = pDecOutputData; /* record the base address of the output data of API */ sm2PerfBuffer->pDecPKEOut = outData[0]; /* This barrier will wait until all threads get to this point */ sampleCodeBarrier(); /* Record the start time, the callback measures the end time when the last * response is received*/ pSm2Data->startCyclesTimestamp = sampleCodeTimestamp(); for (loops = 0; loops < numLoops; loops++) { for (i = 0; i < setup->numBuffers; i++) { do { opData[i]->fieldType = setup->fieldType; sm2PerfTest->setup = setup; sm2PerfTest->perf_buffer = sm2PerfBuffer; post_proc_data[i]->sm2_perf_test = sm2PerfTest; post_proc_data[i]->ptr = (void *)outData[i]; status = cpaCyEcsm2Decrypt(setup->cyInstanceHandle, (CpaCyGenFlatBufCbFunc)cbFunc, (void *)post_proc_data[i], opData[i], outData[i]); waitForAEonRetry(status, pSm2Data); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("SM2 Decryption function failed with status:%d\n", status); goto cleanup; } } /*end buffers loop */ } /* end of numLoops loop*/ if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSm2Data, setup->syncMode, setup->numBuffers, setup->numLoops); } sampleCodeSemaphoreDestroy(&pSm2Data->comp); /* Free all memory */ SM2_DEC_MSG_MEM_FREE(); SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; cleanup: SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (pC2Buffer != NULL) SM2_DEC_MSG_MEM_FREE(); if (opData != NULL) SM2_PERFORM_DEC_MEM_FREE(); return CPA_STATUS_FAIL; } cpa_sample_code_sm2_kdf_hash.c000066400000000000000000000371751503624047500366150ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * This file contains the KDF (key derivation function) and HASH (SM3) utilities * to build up the SM2 sample code. * * More details about the KDF function see * http://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 * * More details about the SM3 hash function see * http://tools.ietf.org/html/draft-shen-sm3-hash-00 * * To complete a full process of the SM2 encryption, decryption, key exchange, * etc, the KDF & SM3 HASH computation are required, this file is just used by * the SM2 sample code to demonstrate how to build up the full SM2 algorithm * flows. * * ***************************************************************************/ #include #include "cpa.h" #include "cpa_types.h" /** ****************************************************************************** * Standard operations according to the Spec. ******************************************************************************/ #define FF0(x, y, z) ((x) ^ (y) ^ (z)) #define FF1(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) #define GG0(x, y, z) ((x) ^ (y) ^ (z)) #define GG1(x, y, z) (((x) & (y)) | ((~(x)) & (z))) #define SHL(x, n) (((x)&0xFFFFFFFF) << n) #define ROTL(x, n) (SHL((x), n) | ((x) >> (32 - n))) #define P0(x) ((x) ^ ROTL((x), 9) ^ ROTL((x), 17)) #define P1(x) ((x) ^ ROTL((x), 15) ^ ROTL((x), 23)) #define SM3_HASH_SIZE_IN_BYTE (32) /** ****************************************************************************** * Convert 4 bytes to unsigned long * Big endian according to the Spec. ******************************************************************************/ #define BYTES_TO_ULONG(l, b, i) \ { \ (l) = ((Cpa32U)(b)[(i)] << 24) | ((Cpa32U)(b)[(i) + 1] << 16) | \ ((Cpa32U)(b)[(i) + 2] << 8) | ((Cpa32U)(b)[(i) + 3]); \ } /** ****************************************************************************** * Convert unsigned long to 4 bytes * Big endian according to the Spec. ******************************************************************************/ #define ULONG_TO_BYTES(l, b, i) \ { \ (b)[(i)] = (Cpa8U)((l) >> 24); \ (b)[(i) + 1] = (Cpa8U)((l) >> 16); \ (b)[(i) + 2] = (Cpa8U)((l) >> 8); \ (b)[(i) + 3] = (Cpa8U)((l)); \ } /* constant data define */ #define BLOCK_BYTE_LEN 64 #define MSG_BYTE_LEN 8 #define W_BYTE_LEN 68 #define W1_BYTE_LEN 64 #define T_BYTE_LEN 64 /** ****************************************************************************** * Assume a message has length l. First add the bit "1" to the end of * this message, then add k bits of "0", such that k is the smallest * non-negative integer satisfyingGBPo * * l+1+k = 448 mod 512 * * Then add a 64 bits string, which is the binary expression of length l. * After padding, the length of the new message m' is a multiple of 512. * Here defines a 64 bytes array, according to the numbers need to be filled * Pad the bytes to the end of the data. ******************************************************************************/ static const Cpa8U sm3PaddingData[BLOCK_BYTE_LEN] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /** ****************************************************************************** * SM3 block data process function * Each block 512bits(64 byte) ******************************************************************************/ static void sm3BlockProcess(Cpa32U *sm3_state, Cpa8U *sm3_buffer) { Cpa32U SS1 = 0, SS2 = 0, TT1 = 0, TT2 = 0, W[W_BYTE_LEN] = {0}, W1[W1_BYTE_LEN] = {0}; Cpa32U A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0; Cpa64U T[T_BYTE_LEN] = { 0 }; Cpa32U Temp1 = 0, Temp2 = 0, Temp3 = 0, Temp4 = 0, Temp5 = 0; Cpa32S j = 0; /* according to the spec, the block processing is divided into * two parts, index from 0 ~ 15 and 16 ~ 63, using different * constants 0x79CC4519, 0x7A879D8A */ for (j = 0; j < 16; j++) /*constant number defined in the spec*/ T[j] = 0x79CC4519; for (j = 16; j < 64; j++) /*constant number defined in the spec*/ T[j] = 0x7A879D8A; /*convert the buffer data to word (big endian) */ BYTES_TO_ULONG(W[0], sm3_buffer, 0); BYTES_TO_ULONG(W[1], sm3_buffer, 4); BYTES_TO_ULONG(W[2], sm3_buffer, 8); BYTES_TO_ULONG(W[3], sm3_buffer, 12); BYTES_TO_ULONG(W[4], sm3_buffer, 16); BYTES_TO_ULONG(W[5], sm3_buffer, 20); BYTES_TO_ULONG(W[6], sm3_buffer, 24); BYTES_TO_ULONG(W[7], sm3_buffer, 28); BYTES_TO_ULONG(W[8], sm3_buffer, 32); BYTES_TO_ULONG(W[9], sm3_buffer, 36); BYTES_TO_ULONG(W[10], sm3_buffer, 40); BYTES_TO_ULONG(W[11], sm3_buffer, 44); BYTES_TO_ULONG(W[12], sm3_buffer, 48); BYTES_TO_ULONG(W[13], sm3_buffer, 52); BYTES_TO_ULONG(W[14], sm3_buffer, 56); BYTES_TO_ULONG(W[15], sm3_buffer, 60); for (j = 16; j < W_BYTE_LEN; j++) { Temp1 = W[j - 16] ^ W[j - 9]; Temp2 = ROTL(W[j - 3], 15); Temp3 = Temp1 ^ Temp2; Temp4 = P1(Temp3); Temp5 = ROTL(W[j - 13], 7) ^ W[j - 6]; W[j] = Temp4 ^ Temp5; } for (j = 0; j < W1_BYTE_LEN; j++) { W1[j] = W[j] ^ W[j + 4]; } A = sm3_state[0]; B = sm3_state[1]; C = sm3_state[2]; D = sm3_state[3]; E = sm3_state[4]; F = sm3_state[5]; G = sm3_state[6]; H = sm3_state[7]; /* according to the spec, the block processing is divided into * two parts, index from 0 ~ 15 and 16 ~ 63, using different * constants T[i] (0x79CC4519, 0x7A879D8A) and different MACRO * FF0/GG0 and FF1/GG1 */ for (j = 0; j < 16; j++) { SS1 = ROTL((ROTL(A, 12) + E + ROTL(T[j], j)), 7); SS2 = SS1 ^ ROTL(A, 12); TT1 = FF0(A, B, C) + D + SS2 + W1[j]; TT2 = GG0(E, F, G) + H + SS1 + W[j]; D = C; C = ROTL(B, 9); B = A; A = TT1; H = G; G = ROTL(F, 19); F = E; E = P0(TT2); } for (j = 16; j < 64; j++) { SS1 = ROTL((ROTL(A, 12) + E + ROTL(T[j], j)), 7); SS2 = SS1 ^ ROTL(A, 12); TT1 = FF1(A, B, C) + D + SS2 + W1[j]; TT2 = GG1(E, F, G) + H + SS1 + W[j]; D = C; C = ROTL(B, 9); B = A; A = TT1; H = G; G = ROTL(F, 19); F = E; E = P0(TT2); } sm3_state[0] ^= A; sm3_state[1] ^= B; sm3_state[2] ^= C; sm3_state[3] ^= D; sm3_state[4] ^= E; sm3_state[5] ^= F; sm3_state[6] ^= G; sm3_state[7] ^= H; } /** ****************************************************************************** * SM3 process function * Padding input data according to ilen * Call sm3BlockProcess for each data block * param: input data; input data length; state register ptr; state buffer ptr * filled; message length buffer ******************************************************************************/ static void sm3Process(Cpa8U *input, Cpa64U ilen, Cpa32U *sm3_state, Cpa8U *sm3_buffer, Cpa32U *pfilled, Cpa8U *message_len) { /* If input length is larger than 64 bytes, process each 64-byte block in a * loop */ if (ilen >= 64) { while (ilen >= 64) { memcpy((void *)(sm3_buffer), (void *)input, BLOCK_BYTE_LEN); sm3BlockProcess(sm3_state, sm3_buffer); input += BLOCK_BYTE_LEN; ilen -= BLOCK_BYTE_LEN; } } /* Process the last block data, which is padded by (1000...message_length) * */ memcpy((void *)(sm3_buffer), (void *)input, ilen); memcpy((void *)(sm3_buffer + ilen), (void *)sm3PaddingData, *pfilled); memcpy((void *)(sm3_buffer + ilen + *pfilled), (void *)message_len, MSG_BYTE_LEN); sm3BlockProcess(sm3_state, sm3_buffer); } /** ****************************************************************************** * SM3 Hash function * param input : input message, input message length * param output : digest output buffer ******************************************************************************/ void sm3(Cpa8U *input, Cpa64U ilen, Cpa8U *output) { /* Sm3 intermediate state */ Cpa32U sm3_state[8] = {0}; /* Data buffer */ Cpa8U sm3_buffer[64] = {0}; /* Assume a message has length l. First add the bit "1" to the end of * this message, then add k bits of "0", such that k is the smallest * non-negative integer satisfyingGBPo * * l+1+k = 448 mod 512 * * Then add a 64 bits string, which is the binary expression of length l. * After padding, the length of the new message m' is a multiple of 512. * * "filled" calculate the number of bytes need to be padding at the end * The last block should be 64 bytes(512 bits) * Then filled = BLOCK_BYTE_LEN - (input length % BLOCK_BYTE_LEN) - * MSG_BYTE_LEN */ Cpa32U filled = 0; /* Message length */ Cpa8U message_len[8] = {0}; Cpa64U ilenbits = ilen * 8; filled = BLOCK_BYTE_LEN - (ilen % BLOCK_BYTE_LEN) - MSG_BYTE_LEN; /* Initial value of the state register, this is defined in the spec*/ sm3_state[0] = 0x7380166F; sm3_state[1] = 0x4914B2B9; sm3_state[2] = 0x172442D7; sm3_state[3] = 0xDA8A0600; sm3_state[4] = 0xA96F30BC; sm3_state[5] = 0x163138AA; sm3_state[6] = 0xE38DEE4D; sm3_state[7] = 0xB0FB0E4E; /* According to the spec, the message length need to be padding to * the end of the data as a bit string. * Convert the length value to a byte array */ ULONG_TO_BYTES((Cpa32U)(ilenbits >> 32), message_len, 0); ULONG_TO_BYTES((Cpa32U)(ilenbits), message_len, 4); /* Sm3 data process function*/ sm3Process(input, ilen, sm3_state, sm3_buffer, &filled, message_len); /* Copy the result in state registers to the output buffer*/ ULONG_TO_BYTES(sm3_state[0], output, 0); ULONG_TO_BYTES(sm3_state[1], output, 4); ULONG_TO_BYTES(sm3_state[2], output, 8); ULONG_TO_BYTES(sm3_state[3], output, 12); ULONG_TO_BYTES(sm3_state[4], output, 16); ULONG_TO_BYTES(sm3_state[5], output, 20); ULONG_TO_BYTES(sm3_state[6], output, 24); ULONG_TO_BYTES(sm3_state[7], output, 28); } /** ****************************************************************************** * KDF function * param input : inbuf, Flatbuf of input message * note : When alloc a piece of memory for the input message buffer * (eg. inbuf->pData) * more 4 bytes should be alloced, for an efficient padding * scheme, while the ilen should be added 4 bytes on the original * input message length (inbuf->dataLenInBytes). * * param output : output buffer ******************************************************************************/ CpaStatus kdf(CpaFlatBuffer *inbuf, CpaFlatBuffer *outbuf) { Cpa32U i = 0; CpaStatus status = CPA_STATUS_FAIL; Cpa32U processed = 0; Cpa8U ctBytes[4] = {0}; /* According to the spec, KDF function will pad a counter at the end of * each block */ Cpa32U ct = 0x00000001; /* Calculate the numbers of the blocks */ Cpa32U numOfBlocks = outbuf->dataLenInBytes / SM3_HASH_SIZE_IN_BYTE; /* Calculate the numbers of bytes of the last output block */ Cpa32U finalBlockBytes = outbuf->dataLenInBytes % SM3_HASH_SIZE_IN_BYTE; /* Temp buffer for hash value of each block */ Cpa8U hashBuffer[SM3_HASH_SIZE_IN_BYTE]; for (i = 0; i < numOfBlocks; i++) { /* Convert the counter to 4 bytes*/ ULONG_TO_BYTES(ct, ctBytes, 0); /* Padding 4 bytes counter for each data block */ memcpy(inbuf->pData + inbuf->dataLenInBytes - 4, ctBytes, 4); /* Calculate the hash value of each data block */ sm3(inbuf->pData, inbuf->dataLenInBytes, hashBuffer); /* Cat the hash value in order */ memcpy(outbuf->pData + processed, hashBuffer, SM3_HASH_SIZE_IN_BYTE); ct++; processed += SM3_HASH_SIZE_IN_BYTE; } /* Process the last data block, according to the spec, KDF function will * output a variable length of message, the last data block will be * truncated. */ ULONG_TO_BYTES(ct, ctBytes, 0); memcpy(inbuf->pData + inbuf->dataLenInBytes - 4, ctBytes, 4); sm3(inbuf->pData, inbuf->dataLenInBytes, hashBuffer); memcpy(outbuf->pData + processed, hashBuffer, finalBlockBytes); return status; } cpa_sample_code_sm2_perf.c000066400000000000000000000743151503624047500357770ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sm2_perf.c * * @ingroup cryptoThreads * * @description * This file contains the sm2 performance code. * This file setup Sign, Verify, Encryption, Decryption, Key Exchange P1/P2 * More details about the algorithm is in * http://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 *****************************************************************************/ #include "cpa_sample_code_sm2_perf.h" extern int latency_single_buffer_mode; /* set to 1 for single buffer processing */ extern Cpa32U packageIdCount_g; /** ****************************************************************************** * SM2 performance test data setup function * This function will be called in sm2Performance() function, before the * performance testing thread started. It setup the random data for the testing * according to the setup->step. * e.g. If run sm2 decryption performance test, this function will generate a * random private key and calculate the public key, then generate random * messages and call sm2Enc() to encrypt the random message to get the data * that decryption needs. * ******************************************************************************/ static CpaStatus sm2PerfDataSetup(sm2_test_params_t *setup) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U node = 0; Cpa32U i = 0; CpaCyEcsm2GeneratorMultiplyOpData privateKey = {{0}}; CpaCyEcsm2SignOpData signOp = {{0}}; CpaCyEcsm2KeyExPhase1OpData keyexOp = {{0}}; CpaCyEcsm2KeyExOutputData keyexOutput = {{0}}; CpaBoolean sm2Status = CPA_FALSE; CpaFlatBuffer signOutput_r = {0}; CpaFlatBuffer signOutput_s = {0}; CpaFlatBuffer pubKey_x = {0}; CpaFlatBuffer pubKey_y = {0}; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /* Allocate memory for common data, * private key(d, d2, d2 is set for key exchange) and public key(xP,yP)*/ setup->d = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); setup->d2 = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); setup->xP = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); setup->yP = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == setup->d || NULL == setup->d2 || NULL == setup->xP || NULL == setup->yP) { PRINT_ERR("key memory allocation error\n"); goto cleanup; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, setup->d, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, setup->d2, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, setup->xP, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, setup->yP, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); /* alloc memory for random message for encryption */ setup->message = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == setup->message) { PRINT_ERR("key memory allocation error\n"); goto cleanup; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, setup->message, MESSAGE_LEN, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); generateRandomData(setup->d->pData, setup->d->dataLenInBytes); /* For parameters being passed to Large Number API, the MSB must be 1 */ setup->d->pData[0] = 0x01; generateRandomData(setup->d2->pData, setup->d2->dataLenInBytes); /* For parameters being passed to Large Number API, the MSB must be 1 */ setup->d2->pData[0] = 0x01; generateRandomData(setup->message->pData, setup->message->dataLenInBytes); /* calculate public key via d */ privateKey.k.dataLenInBytes = setup->d->dataLenInBytes; privateKey.k.pData = setup->d->pData; privateKey.fieldType = setup->fieldType; pubKey_x.dataLenInBytes = setup->xP->dataLenInBytes; pubKey_x.pData = setup->xP->pData; pubKey_y.dataLenInBytes = setup->yP->dataLenInBytes; pubKey_y.pData = setup->yP->pData; /* call the driver API in synchronous mode */ status = cpaCyEcsm2GeneratorMultiply( setup->cyInstanceHandle, NULL, /* Sync mode*/ NULL, &privateKey, /* Generator multiplication request data */ &sm2Status, /* Multiply status */ &pubKey_x, /* Generator multiplication response data */ &pubKey_y); /* Generator multiplication response data */ if (CPA_STATUS_SUCCESS != status) { /* Not a success; could be a retry, a fail, an invalid param or * a resource issue */ PRINT_ERR("Generate public key failed (status = %d)\n", status); goto cleanup; } /* Allocate memory for random digests for signature */ setup->digest = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == setup->digest) { PRINT_ERR("digest mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->digest[i], setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); generateRandomData(setup->digest[i].pData, setup->digest[i].dataLenInBytes); /* For parameters being passed to Large Number API, the MSB must be 1 */ setup->digest[i].pData[0] = 0x01; } /* Allocate memory for random numbers */ setup->random = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == setup->random) { PRINT_ERR("random number mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->random[i], setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); generateRandomData(setup->random[i].pData, setup->random[i].dataLenInBytes); /* For parameters being passed to Large Number API, the MSB must be 1 */ setup->random[i].pData[0] = 0x01; } /* If running SM2 signature verify , we need to generate correct signature * data, using cyEcsm2Sign API to sign random digest, store the result in * the setup->verifOp */ if (setup->step == SM2_STEP_VERIFY) { /* Allocate memory for setup->verifOp */ status = allocArrayOfPointers(setup->cyInstanceHandle, (void **)&setup->verifyOp, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("setup->verifyOp mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { setup->verifyOp[i] = qaeMemAlloc(sizeof(CpaCyEcsm2VerifyOpData)); if (NULL == setup->verifyOp[i]) { PRINT_ERR("setup->verifyOp[%u] memory allocation error\n", i); goto cleanup; } memset(setup->verifyOp[i], 0, sizeof(CpaCyEcsm2VerifyOpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->verifyOp[i]->e, setup->nLenInBytes, setup->digest[i].pData, setup->digest[i].dataLenInBytes, SM2_PERFORM_SETUP_VERIFY_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->verifyOp[i]->xP, setup->nLenInBytes, setup->xP->pData, setup->xP->dataLenInBytes, SM2_PERFORM_SETUP_VERIFY_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->verifyOp[i]->yP, setup->nLenInBytes, setup->yP->pData, setup->yP->dataLenInBytes, SM2_PERFORM_SETUP_VERIFY_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->verifyOp[i]->r, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_VERIFY_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->verifyOp[i]->s, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_VERIFY_MEM_FREE()); /* fill input and output structure */ signOp.k.dataLenInBytes = setup->random[i].dataLenInBytes; signOp.k.pData = setup->random[i].pData; signOp.e.dataLenInBytes = setup->digest[i].dataLenInBytes; signOp.e.pData = setup->digest[i].pData; signOp.d.dataLenInBytes = setup->d->dataLenInBytes; signOp.d.pData = setup->d->pData; signOp.fieldType = setup->fieldType; signOutput_r.dataLenInBytes = setup->verifyOp[i]->r.dataLenInBytes; signOutput_r.pData = setup->verifyOp[i]->r.pData; signOutput_s.dataLenInBytes = setup->verifyOp[i]->s.dataLenInBytes; signOutput_s.pData = setup->verifyOp[i]->s.pData; /* call the driver API to sign the random digest */ do { status = cpaCyEcsm2Sign( setup->cyInstanceHandle, NULL, /* Sync mode*/ NULL, &signOp, /* Structure containing k, d and e */ &sm2Status, /* signStatus indicates if the result is valid */ &signOutput_r, /* Signature r, s (function output) */ &signOutput_s); /* Signature r, s (function output) */ } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { /* Not a success; could be a retry, a fail, an invalid param or * a resource issue */ PRINT_ERR("cpaCyEcsm2Sign() not a success. (status = %d)\n", status); goto cleanup; } } } /* if running SM2 decryption performance test, we need to generate correct * ciphers using cyEcsm2Enc API to encryption the random message , * store the results in setup->cipher */ if (setup->step == SM2_STEP_DEC) { setup->cipher = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer), node, BYTE_ALIGNMENT_64); if (NULL == setup->cipher) { PRINT_ERR("cipher memory allocation error\n"); goto cleanup; } ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, setup->cipher, CIPHER_LEN, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); /* sm2 encryption operation, encrypt the random messages to get the * ciphers that decryption needs */ status = sm2Enc(setup); } /* if running SM2 key exchange phase2 , we need prepare the correct data * that generated by key exchange phase 1 */ if (setup->step == SM2_STEP_KEYEX_P2) { setup->x1 = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == setup->x1) { PRINT_ERR("random number mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->x1[i], setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); } setup->y1 = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == setup->y1) { PRINT_ERR("random number mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->y1[i], setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); } setup->x2 = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == setup->x2) { PRINT_ERR("random number mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->x2[i], setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); } setup->y2 = (CpaFlatBuffer *)qaeMemAllocNUMA( sizeof(CpaFlatBuffer) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == setup->y2) { PRINT_ERR("random number mem allocation error\n"); goto cleanup; } for (i = 0; i < setup->numBuffers; i++) { ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &setup->y2[i], setup->nLenInBytes, NULL, 0, SM2_PERFORM_SETUP_FLAT_MEM_FREE()); } /* key exchange need two sides , both sides generate a SM2 EC point * and exchange it with each other then any side will generate the * secret key using the two points(both generated by key exchange * phase1, one is his own and one is from the other side.) so here we * need to calculate 2 key exchange phase 1, * using different random parameters */ for (i = 0; i < setup->numBuffers; i++) { /* fill the input and output structure for key exchange phase 1*/ keyexOp.r.dataLenInBytes = setup->random[i].dataLenInBytes; keyexOp.r.pData = setup->random[i].pData; keyexOp.fieldType = setup->fieldType; keyexOutput.x.dataLenInBytes = setup->x1[i].dataLenInBytes; keyexOutput.x.pData = setup->x1[i].pData; keyexOutput.y.dataLenInBytes = setup->y1[i].dataLenInBytes; keyexOutput.y.pData = setup->y1[i].pData; do { status = cpaCyEcsm2KeyExPhase1( setup->cyInstanceHandle, NULL, /* Sync mode */ NULL, &keyexOp, /* Key exchange p1 request data */ &keyexOutput /* Key exchange p1 response data */); } while (CPA_STATUS_RETRY == status); /* fill the input and output structure for key exchange phase 1 * using the random value in inverse order */ keyexOp.r.dataLenInBytes = setup->random[setup->numBuffers - i - 1].dataLenInBytes; keyexOp.r.pData = setup->random[setup->numBuffers - i - 1].pData; keyexOp.fieldType = setup->fieldType; keyexOutput.x.dataLenInBytes = setup->x2[i].dataLenInBytes; keyexOutput.x.pData = setup->x2[i].pData; keyexOutput.y.dataLenInBytes = setup->y2[i].dataLenInBytes; keyexOutput.y.pData = setup->y2[i].pData; do { status = cpaCyEcsm2KeyExPhase1( setup->cyInstanceHandle, NULL, /* Sync mode*/ NULL, &keyexOp, /* Key exchange p1 request data */ &keyexOutput /* Key exchange p1 response data */); } while (CPA_STATUS_RETRY == status); } } return status; cleanup: SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (setup->verifyOp != NULL) SM2_PERFORM_SETUP_VERIFY_MEM_FREE(); return CPA_STATUS_FAIL; } #ifndef NEWDISPLAY /** *************************************************************************** * @ingroup cryptoThreads * * @description * Print the performance stats of the SM2 operations according to the step ***************************************************************************/ static CpaStatus sm2PrintStats(thread_creation_data_t *data) { sm2_test_params_t *params = (sm2_test_params_t *)data->setupPtr; switch (params->step) { case (SM2_STEP_SIGN): PRINT("SM2 SIGN \n"); break; case (SM2_STEP_VERIFY): PRINT("SM2 VERIFY\n"); break; case (SM2_STEP_ENC): PRINT("SM2 ENCRYPT\n"); break; case (SM2_STEP_DEC): PRINT("SM2 DECRYPT\n"); break; case (SM2_STEP_KEYEX_P1): PRINT("SM2 KEY EXCHANGE P1\n"); break; case (SM2_STEP_KEYEX_P2): PRINT("SM2 KEY EXCHANGE P2\n"); break; } PRINT("SM2 Size %23u\n", data->packetSize); printAsymStatsAndStopServices(data); return CPA_STATUS_SUCCESS; } #endif /** *************************************************************************** * @ingroup cryptoThreads * * @description * setup a SM2 performance thread **************************************************************************/ void sm2Performance(single_thread_test_data_t *testSetup) { sm2_test_params_t sm2Setup = {0}; CpaStatus status = CPA_STATUS_SUCCESS; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; sm2_test_params_t *params = (sm2_test_params_t *)testSetup->setupPtr; CpaInstanceInfo2 instanceInfo = {0}; CpaDeviceInfo deviceInfo = {0}; CpaCyCapabilitiesInfo capInfo = {0}; testSetup->passCriteria = getPassCriteria(); /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call * startThreads anyway*/ startBarrier(); /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)sm2PrintStats; /*give our thread a unique memory location to store performance stats*/ sm2Setup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (cyInstances == NULL) { PRINT_ERR("Error allocating memory for instance handles\n"); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } /* give our thread a logical crypto instance to use * use % to wrap around the max number of instances*/ sm2Setup.cyInstanceHandle = cyInstances[(testSetup->logicalQaInstance) % numInstances]; status = cpaCyInstanceGetInfo2(sm2Setup.cyInstanceHandle, &instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 failed\n"); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } /* check whether asym service enabled or not for the instance */ status = cpaGetDeviceInfo(instanceInfo.physInstId.acceleratorId, &deviceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetDeviceInfo failed\n"); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (CPA_FALSE == deviceInfo.cyAsymEnabled) { PRINT_ERR("Error! cyAsymEnabled service not enabled for the " "configured instance\n"); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } /* check if SM2 is supported for the instance */ if (CPA_STATUS_SUCCESS != cpaCyQueryCapabilities(sm2Setup.cyInstanceHandle, &capInfo)) { PRINT_ERR("cpaCyQueryCapabilities failed\n"); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (!capInfo.ecSm2Supported) { PRINT_ERR("SM2 is Unsupported on Device\n"); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_UNSUPPORTED; numCreatedThreads_g--; goto exit; } if (instanceInfo.physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo.physInstId.packageId; } sm2Setup.nLenInBytes = params->nLenInBytes; sm2Setup.fieldType = params->fieldType; sm2Setup.numBuffers = params->numBuffers; sm2Setup.numLoops = params->numLoops; sm2Setup.syncMode = params->syncMode; sm2Setup.step = params->step; /* according to the sm2Setup->step, this function will generate the correct * random data for the performance test */ sm2PerfDataSetup(&sm2Setup); /* Launch function that does all the work */ switch (params->step) { case SM2_STEP_SIGN: status = sm2SignPerform(&sm2Setup); break; case SM2_STEP_VERIFY: status = sm2VerifyPerform(&sm2Setup); break; case SM2_STEP_ENC: status = sm2EncPerform(&sm2Setup); break; case SM2_STEP_DEC: status = sm2DecPerform(&sm2Setup); break; case SM2_STEP_KEYEX_P1: status = sm2KeyexP1Perform(&sm2Setup); break; case SM2_STEP_KEYEX_P2: status = sm2KeyexP2Perform(&sm2Setup); break; default: PRINT_ERR("Function not supported for step %d\n", params->step); status = CPA_STATUS_FAIL; break; } if (CPA_STATUS_SUCCESS != status) { PRINT("SM2 Thread %u FAILED\n", testSetup->logicalQaInstance); sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { sm2Setup.performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; } exit: if (cyInstances != NULL) { qaeMemFree((void **)&cyInstances); } sampleCodeThreadComplete(testSetup->threadID); } EXPORT_SYMBOL(sm2Performance); /** *************************************************************************** * @ingroup cryptoThreads * * @description * This function is used to set the parameters to be used in the SM2 * performance thread. It is called before the createThreads * function of the framework. The framework replicates it across many * cores ***************************************************************************/ CpaStatus setupSm2Test(Cpa32U nLenInBits, CpaCyEcFieldType fieldType, sync_mode_t syncMode, sm2_step_t step, Cpa32U numBuffers, Cpa32U numLoops) { /* testSetupData_g is a multi-dimensional array that stores the setup for * all thread variations in an array of characters. we store our test setup * at the start of the second array ie index 0. There maybe multi-thread * types (setups) running as counted by testTypeCount_g*/ /*as setup is a multi-dimensional char array we need to cast it to the * symmetric structure*/ sm2_test_params_t *sm2Setup = NULL; Cpa8S name[] = {'S', 'M', '2', '\0'}; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Error starting Crypto Services\n"); return CPA_STATUS_FAIL; } if (iaCycleCount_g) { #ifdef POLL_INLINE enablePollInline(); #endif timeStampTime_g = getTimeStampTime(); PRINT("timeStampTime_g %llu\n", timeStampTime_g); } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration * file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); sm2Setup = (sm2_test_params_t *)&thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)sm2Performance; /* If nLenInBits is not an even number of bytes then round up * sm2Setup->nLenInBytes*/ sm2Setup->nLenInBytes = (nLenInBits + NUM_BITS_IN_BYTE - 1) / NUM_BITS_IN_BYTE; testSetupData_g[testTypeCount_g].packetSize = sm2Setup->nLenInBytes; sm2Setup->fieldType = fieldType; sm2Setup->syncMode = syncMode; sm2Setup->numBuffers = numBuffers; sm2Setup->numLoops = numLoops; sm2Setup->step = step; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setupSm2Test); cpa_sample_code_sm2_perf.h000066400000000000000000000761041503624047500360020ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sm2_perf.c * * @ingroup cryptoThreads * * @description * This file contains the sm2 performance code. * Including Macros and function declaration * More details about the algorithm is in * http://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 *****************************************************************************/ #ifndef CPA_SAMPLE_CODE_SM2_PERF_H #define CPA_SAMPLE_CODE_SM2_PERF_H #include "cpa_cy_ec.h" #include "cpa_cy_ecsm2.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_utils_common.h" #include "cpa_dev.h" #ifdef NEWDISPLAY #include "cpa_sample_code_NEWDISPLAY_crypto_utils.h" #endif /** ****************************************************************************** * SM2 encryption function for data setup * This function will be called in sm2PerfDataSetup(), encrypt the * random message, and store the cipher for the decryption perform. * ******************************************************************************/ CpaStatus sm2Enc(sm2_test_params_t *setup); /** ****************************************************************************** * SM3 Hash function * param input : input digest, input digest length * param output : digest output buffer ******************************************************************************/ extern void sm3(Cpa8U *input, Cpa64U ilen, Cpa8U *output); /** ****************************************************************************** * Key Derivation Function * param inbuf flatbuffer holding the data * param outbuf kdf output buffer ******************************************************************************/ extern CpaStatus kdf(CpaFlatBuffer *inbuf, CpaFlatBuffer *outbuf); #define TIMEOUT_MS 5000 /* 5 seconds*/ #define MESSAGE_LEN 19 #define CIPHER_LEN \ (SM3_HASH_SIZE_IN_BYTE + GFP_SM2_POINT_SIZE_IN_BYTE + MESSAGE_LEN) /* ID of A for key exchange ,arbitrary data*/ static const Cpa8U ZA[] = { 0xE4, 0xD1, 0xD0, 0xC3, 0xCA, 0x4C, 0x7F, 0x11, 0xBC, 0x8F, 0xF8, 0xCB, 0x3F, 0x4C, 0x02, 0xA7, 0x8F, 0x10, 0x8F, 0xA0, 0x98, 0xE5, 0x1A, 0x66, 0x84, 0x87, 0x24, 0x0F, 0x75, 0xE2, 0x0F, 0x31 }; /* ID of B for key exchange, arbitrary data*/ static const Cpa8U ZB[] = { 0x6B, 0x4B, 0x6D, 0x0E, 0x27, 0x66, 0x91, 0xBD, 0x4A, 0x11, 0xBF, 0x72, 0xF4, 0xFB, 0x50, 0x1A, 0xE3, 0x09, 0xFD, 0xAC, 0xB7, 0x2F, 0xA6, 0xCC, 0x33, 0x6E, 0x66, 0x56, 0x11, 0x9A, 0xBD, 0x67 }; /* This struct is used in the performance test loop, such as encryption, * decryption. * Every loop has its own post processing data struct, using it to pass the * result of API to the callback function for the next hash operations. * It has two members: * sm2_perf_test is a point to the regular performance testing data struct, * including some base pointer. * ptr is general pointer, point to the current API outData struct * */ typedef struct post_proc_data_s { sm2_perf_test_t *sm2_perf_test; void *ptr; } post_proc_data_t; typedef struct Ecsm2SignOutputData { CpaFlatBuffer r; /**< signature output r */ CpaFlatBuffer s; /**< signature output s */ } Ecsm2SignOutputData; /** ****************************************************************************** * wait for AE execution slot on Retry * param input : status * param output : pSm2Data ******************************************************************************/ #define waitForAEonRetry(status, pSm2Data) \ do \ { \ if (CPA_STATUS_RETRY == status) \ { \ pSm2Data->retries++; \ /* If the acceleration engine is busy pause for a moment by \ * making a context switch */ \ if (RETRY_LIMIT == (pSm2Data->retries % (RETRY_LIMIT + 1))) \ { \ AVOID_SOFTLOCKUP; \ } \ } \ } while (0) /** ****************************************************************************** * Initialise the semaphore, performance stat, number of operations * param input : setup * param output : pSm2Data ******************************************************************************/ #define initSemaphoreAndVariables(pSm2Data, setup) \ do \ { \ /* Get memory location to write performance stats to */ \ pSm2Data = setup->performanceStats; \ memset(pSm2Data, 0, sizeof(perf_data_t)); \ \ /*get the number of operations to be done in this test*/ \ pSm2Data->numOperations = (Cpa64U)setup->numBuffers * setup->numLoops; \ pSm2Data->responses = 0; \ \ /* Initialise semaphore used in callback */ \ sampleCodeSemaphoreInit(&pSm2Data->comp, 0); \ \ } while (0) /** ****************************************************************************** * convert point coordinates to byte string * param input : byteString, converted byte string, uncompressed format, PC=04 * param output : x , y , coordinate ******************************************************************************/ #define convertPointToBytes(byteString, x, y, isCompressed) \ do \ { \ *(byteString) = HEADER_UNCOMPRESSION_POINT; \ memcpy((byteString) + 1, (x), GFP_SM2_COORDINATE_SIZE_IN_BYTE); \ memcpy((byteString) + 1 + GFP_SM2_COORDINATE_SIZE_IN_BYTE, \ (y), \ GFP_SM2_COORDINATE_SIZE_IN_BYTE); \ } while (0) /* ****************************************************************************** * Split cipher to C1 C2 C3, according to the spec * param input : Cipher C, length ilen * param output : C1,C2,C3 ******************************************************************************/ #define splitCipherData(C, ilen, C1, C2, C3, isCompressed) \ do \ { \ memcpy((C1), (C), GFP_SM2_POINT_SIZE_IN_BYTE); \ memcpy((C2), \ (C) + GFP_SM2_POINT_SIZE_IN_BYTE, \ (ilen)-GFP_SM2_POINT_SIZE_IN_BYTE - SM3_HASH_SIZE_IN_BYTE); \ memcpy((C3), \ (C) + (ilen)-GFP_SM2_COORDINATE_SIZE_IN_BYTE, \ SM3_HASH_SIZE_IN_BYTE); \ } while (0) /* ****************************************************************************** * Split C1 to point, according to the spec * param input : C1 * param output : x coordinate X1, y coordinate Y1 ******************************************************************************/ #define splitC1toPoint(C1, X1, Y1, isCompressed) \ do \ { \ memcpy((X1), (C1) + 1, GFP_SM2_COORDINATE_SIZE_IN_BYTE); \ memcpy((Y1), \ (C1) + 1 + GFP_SM2_COORDINATE_SIZE_IN_BYTE, \ GFP_SM2_COORDINATE_SIZE_IN_BYTE); \ } while (0) /* ****************************************************************************** * Check hash value * param input : C3,hashValue * param output : status ******************************************************************************/ #define hashCheck(C3, hashValue, status) \ do \ { \ int i; \ *(status) = CPA_STATUS_SUCCESS; \ for (i = 0; i < SM3_HASH_SIZE_IN_BYTE; i++) \ { \ if (*((C3) + i) != *((hashValue) + i)) \ { \ *(status) = CPA_STATUS_FAIL; \ break; \ } \ } \ } while (0) /** ****************************************************************************** * * Free any memory allocated in the SM2 data setup process * ******************************************************************************/ static void sm2SetupFlatMemFree(sm2_test_params_t *setup) { Cpa32U k = 0; if (setup->d != NULL) { if (NULL != setup->d->pData) qaeMemFreeNUMA((void **)&setup->d->pData); qaeMemFreeNUMA((void **)&setup->d); } if (setup->d2 != NULL) { if (NULL != setup->d2->pData) qaeMemFreeNUMA((void **)&setup->d2->pData); qaeMemFreeNUMA((void **)&setup->d2); } if (setup->xP != NULL) { if (NULL != setup->xP->pData) qaeMemFreeNUMA((void **)&setup->xP->pData); qaeMemFreeNUMA((void **)&setup->xP); } if (setup->yP != NULL) { if (NULL != setup->yP->pData) qaeMemFreeNUMA((void **)&setup->yP->pData); qaeMemFreeNUMA((void **)&setup->yP); } if (setup->message != NULL) { if (NULL != setup->message->pData) qaeMemFreeNUMA((void **)&setup->message->pData); qaeMemFreeNUMA((void **)&setup->message); } if (setup->cipher != NULL) { if (NULL != setup->cipher->pData) qaeMemFreeNUMA((void **)&setup->cipher->pData); qaeMemFreeNUMA((void **)&setup->cipher); } if (NULL != setup->digest) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != setup->digest[k].pData) qaeMemFreeNUMA((void **)&setup->digest[k].pData); } qaeMemFreeNUMA((void **)&setup->digest); } if (NULL != setup->random) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != setup->random[k].pData) qaeMemFreeNUMA((void **)&setup->random[k].pData); } qaeMemFreeNUMA((void **)&setup->random); } if (NULL != setup->x1) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != setup->x1[k].pData) qaeMemFreeNUMA((void **)&setup->x1[k].pData); } qaeMemFreeNUMA((void **)&setup->x1); } if (NULL != setup->y1) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != setup->y1[k].pData) qaeMemFreeNUMA((void **)&setup->y1[k].pData); } qaeMemFreeNUMA((void **)&setup->y1); } if (NULL != setup->x2) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != setup->x2[k].pData) qaeMemFreeNUMA((void **)&setup->x2[k].pData); } qaeMemFreeNUMA((void **)&setup->x2); } if (NULL != setup->y2) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != setup->y2[k].pData) qaeMemFreeNUMA((void **)&setup->y2[k].pData); } qaeMemFreeNUMA((void **)&setup->y2); } } /** ****************************************************************************** * * Free any memory allocated in the sm2Perform function * ******************************************************************************/ #define SM2_ENC_SETUP_MSG_MEM_FREE() \ do \ { \ qaeMemFreeNUMA((void **)&pC1Buffer->pData); \ qaeMemFreeNUMA((void **)&pC1Buffer); \ qaeMemFreeNUMA((void **)&pC2Buffer->pData); \ qaeMemFreeNUMA((void **)&pC2Buffer); \ qaeMemFreeNUMA((void **)&pC3Buffer->pData); \ qaeMemFreeNUMA((void **)&pC3Buffer); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer->pData); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer); \ qaeMemFreeNUMA((void **)&pEncOutputData->pData); \ qaeMemFreeNUMA((void **)&pEncOutputData); \ sm2SetupEncMemFree(opData, outData); \ } while (0) #define SM2_ENC_MSG_MEM_FREE() \ do \ { \ qaeMemFreeNUMA((void **)&pC1Buffer->pData); \ qaeMemFreeNUMA((void **)&pC1Buffer); \ qaeMemFreeNUMA((void **)&pC2Buffer->pData); \ qaeMemFreeNUMA((void **)&pC2Buffer); \ qaeMemFreeNUMA((void **)&pC3Buffer->pData); \ qaeMemFreeNUMA((void **)&pC3Buffer); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer->pData); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer); \ qaeMemFreeNUMA((void **)&pEncOutputData->pData); \ qaeMemFreeNUMA((void **)&pEncOutputData); \ sm2EncMemFree(setup, opData, outData, post_proc_data); \ if (NULL != sm2PerfBuffer) \ { \ qaeMemFreeNUMA((void **)&sm2PerfBuffer); \ } \ if (NULL != sm2PerfTest) \ { \ qaeMemFreeNUMA((void **)&sm2PerfTest); \ } \ } while (0) #define SM2_DEC_MSG_MEM_FREE() \ do \ { \ qaeMemFreeNUMA((void **)&pM1Buffer->pData); \ qaeMemFreeNUMA((void **)&pM1Buffer); \ qaeMemFreeNUMA((void **)&pC2Buffer->pData); \ qaeMemFreeNUMA((void **)&pC2Buffer); \ qaeMemFreeNUMA((void **)&pC3Buffer->pData); \ qaeMemFreeNUMA((void **)&pC3Buffer); \ qaeMemFreeNUMA((void **)&pHashBuffer->pData); \ qaeMemFreeNUMA((void **)&pHashBuffer); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer->pData); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer); \ qaeMemFreeNUMA((void **)&pDecOutputData->pData); \ qaeMemFreeNUMA((void **)&pDecOutputData); \ sm2DecMemFree(setup, opData, outData, post_proc_data); \ if (NULL != sm2PerfBuffer) \ { \ qaeMemFreeNUMA((void **)&sm2PerfBuffer); \ } \ if (NULL != sm2PerfTest) \ { \ qaeMemFreeNUMA((void **)&sm2PerfTest); \ } \ } while (0) #define SM2_KEYEX_MSG_MEM_FREE() \ do \ { \ qaeMemFreeNUMA((void **)&pSecretKey->pData); \ qaeMemFreeNUMA((void **)&pSecretKey); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer->pData); \ qaeMemFreeNUMA((void **)&pIntermediateBuffer); \ sm2KeyexP2MemFree(setup, opData, outData, post_proc_data); \ if (NULL != sm2PerfBuffer) \ { \ qaeMemFreeNUMA((void **)&sm2PerfBuffer); \ } \ if (NULL != sm2PerfTest) \ { \ qaeMemFreeNUMA((void **)&sm2PerfTest); \ } \ } while (0) #define SM2_PERFORM_ENC_MEM_FREE() \ do \ { \ sm2EncMemFree(setup, opData, outData, post_proc_data); \ if (NULL != sm2PerfBuffer) \ { \ qaeMemFreeNUMA((void **)&sm2PerfBuffer); \ } \ if (NULL != sm2PerfTest) \ { \ qaeMemFreeNUMA((void **)&sm2PerfTest); \ } \ } while (0) #define SM2_PERFORM_DEC_MEM_FREE() \ do \ { \ sm2DecMemFree(setup, opData, outData, post_proc_data); \ if (NULL != sm2PerfBuffer) \ { \ qaeMemFreeNUMA((void **)&sm2PerfBuffer); \ } \ if (NULL != sm2PerfTest) \ { \ qaeMemFreeNUMA((void **)&sm2PerfTest); \ } \ } while (0) #define SM2_PERFORM_KEYEX_P1_MEM_FREE() \ do \ { \ sm2KeyexP1MemFree(setup, opData, outData); \ } while (0) #define SM2_PERFORM_KEYEX_P2_MEM_FREE() \ do \ { \ sm2KeyexP2MemFree(setup, opData, outData, post_proc_data); \ if (NULL != sm2PerfBuffer) \ { \ qaeMemFreeNUMA((void **)&sm2PerfBuffer); \ } \ if (NULL != sm2PerfTest) \ { \ qaeMemFreeNUMA((void **)&sm2PerfTest); \ } \ } while (0) #define SM2_PERFORM_SIGN_MEM_FREE() \ do \ { \ sm2SignMemFree(setup, opData, outData); \ } while (0) #define SM2_PERFORM_VERIFY_MEM_FREE() \ do \ { \ sm2VerifyMemFree(setup, vOpData); \ } while (0) #define SM2_PERFORM_SETUP_VERIFY_MEM_FREE() \ do \ { \ sm2VerifyMemFree(setup, setup->verifyOp); \ } while (0) #define SM2_PERFORM_SETUP_FLAT_MEM_FREE() \ do \ { \ sm2SetupFlatMemFree(setup); \ } while (0) #define SM2_PERFORM_SETUP_ENC_MEM_FREE() \ do \ { \ sm2SetupEncMemFree(opData, outData); \ } while (0) /** ******************************************************************************* * * Free any memory allocated in the SM2 cipher data setup * *******************************************************************************/ void sm2SetupEncMemFree(CpaCyEcsm2EncryptOpData *opData, CpaCyEcsm2EncryptOutputData *outData); /** ****************************************************************************** * * Free any memory allocated in the SM2 signature verification operation * ******************************************************************************/ void sm2VerifyMemFree(sm2_test_params_t *setup, CpaCyEcsm2VerifyOpData **vOpData); /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Signature operation * This function is called for signature performance test. * ******************************************************************************/ CpaStatus sm2SignPerform(sm2_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Signature verify operation * This function is called for signatrue verify performance test. * ******************************************************************************/ CpaStatus sm2VerifyPerform(sm2_test_params_t *setup); /** ****************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Encryption operation * This function is called for performance test. * ******************************************************************************/ CpaStatus sm2EncPerform(sm2_test_params_t *setup); /* ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Decryption operation * This function is called for performance test. * ******************************************************************************/ CpaStatus sm2DecPerform(sm2_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 key exchange phase 1 operation * This function is called for key exchange phase 1 performance test. * ******************************************************************************/ CpaStatus sm2KeyexP1Perform(sm2_test_params_t *setup); /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 key exchange phase 2 operation * This function is called for key exchange phase 2 performance test. * ******************************************************************************/ CpaStatus sm2KeyexP2Perform(sm2_test_params_t *setup); /** ****************************************************************************** * * Free any memory allocated in the SM2 key exchange phase 2 operation * ******************************************************************************/ void sm2KeyexP2MemFree(sm2_test_params_t *setup, CpaCyEcsm2KeyExPhase2OpData **opData, CpaCyEcsm2KeyExOutputData **outData, post_proc_data_t **post_proc_data); /** ****************************************************************************** * * Free any memory allocated in the SM2 key exchange phase 1 operation * ******************************************************************************/ void sm2KeyexP1MemFree(sm2_test_params_t *setup, CpaCyEcsm2KeyExPhase1OpData **opData, CpaCyEcsm2KeyExOutputData **outData); #endif cpa_sample_code_sm2_sign_verify.c000066400000000000000000000407241503624047500373640ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sm2_perf.c * * @ingroup cryptoThreads * * @description * This file contains the sm2 performance code. * Including Sign, Verify * More details about the algorithm is in * http://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 *****************************************************************************/ #include "cpa_sample_code_sm2_perf.h" /** ****************************************************************************** * * Free any memory allocated in the SM2 signature operation * ******************************************************************************/ static void sm2SignMemFree(sm2_test_params_t *setup, CpaCyEcsm2SignOpData **opData, Ecsm2SignOutputData **outData) { Cpa32U k = 0; if (NULL != opData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != opData[k]) { qaeMemFreeNUMA((void **)&opData[k]->k.pData); qaeMemFreeNUMA((void **)&opData[k]->e.pData); qaeMemFreeNUMA((void **)&opData[k]->d.pData); qaeMemFreeNUMA((void **)&opData[k]); } } qaeMemFreeNUMA((void **)&opData); } if (NULL != outData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != outData[k]) { qaeMemFreeNUMA((void **)&outData[k]->r.pData); qaeMemFreeNUMA((void **)&outData[k]->s.pData); qaeMemFreeNUMA((void **)&outData[k]); } } qaeMemFreeNUMA((void **)&outData); } } /** ****************************************************************************** * * Free any memory allocated in the SM2 signature verification operation * ******************************************************************************/ void sm2VerifyMemFree(sm2_test_params_t *setup, CpaCyEcsm2VerifyOpData **vOpData) { Cpa32U k = 0; if (NULL != vOpData) { for (k = 0; k < setup->numBuffers; k++) { if (NULL != vOpData[k]) { qaeMemFreeNUMA((void **)&vOpData[k]->e.pData); qaeMemFreeNUMA((void **)&vOpData[k]->r.pData); qaeMemFreeNUMA((void **)&vOpData[k]->s.pData); qaeMemFreeNUMA((void **)&vOpData[k]->yP.pData); qaeMemFreeNUMA((void **)&vOpData[k]->xP.pData); qaeMemFree((void **)&vOpData[k]); } } qaeMemFreeNUMA((void **)&vOpData); } } /** ****************************************************************************** * Callback function * Sm2 Signature Callback function * Performance statistic * ******************************************************************************/ static void sm2SignCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean pass, CpaFlatBuffer *pR, CpaFlatBuffer *pS) { if (CPA_TRUE != pass) { PRINT_ERR("SM2 Signature point operation failed!\n"); } processCallback(pCallbackTag); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("sm2SignCallback error status %d\n", status); } } /** ****************************************************************************** * Callback function * Sm2 Signature Verification Callback function * Performance statistic * ******************************************************************************/ static void sm2VerifyCallback(void *pCallbackTag, CpaStatus status, void *pOpData, CpaBoolean verifyStatus) { if (CPA_TRUE != verifyStatus) { PRINT_ERR("SM2 Signature Verify failed!\n"); } processCallback(pCallbackTag); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("sm2VerifyCallback error status %d\n", status); } } /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Signature operation * This function is called for signature performance test. * ******************************************************************************/ CpaStatus sm2SignPerform(sm2_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; CpaCyEcsm2Stats64 sm2Stats = {0}; CpaStatus status = CPA_STATUS_FAIL; CpaBoolean pStatus = CPA_FALSE; CpaCyEcsm2SignOpData **opData = NULL; Ecsm2SignOutputData **outData = NULL; /* variable to store what CPU Node/socket the thread is running on*/ Cpa32U node = 0; /*pointer to location to store performance data*/ perf_data_t *pSm2Data = NULL; CpaCyEcsm2SignCbFunc cbFunc = NULL; status = cpaCyEcsm2QueryStats64(setup->cyInstanceHandle, &sm2Stats); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Could not retrieve stats, error status %d\n", status); return status; } /* Get the node we are running on for local memory allocation */ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } initSemaphoreAndVariables(pSm2Data, setup); status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&opData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("opData mem allocation error\n"); goto cleanup; } status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&outData, setup->numBuffers); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("outData mem allocation error\n"); goto cleanup; } /*allocate and populate all the operation data buffers*/ for (i = 0; i < setup->numBuffers; i++) { opData[i] = qaeMemAllocNUMA( sizeof(CpaCyEcsm2SignOpData), node, BYTE_ALIGNMENT_64); if (NULL == opData[i]) { PRINT_ERR("opData[%u] memory allocation error\n", i); goto cleanup; } memset(opData[i], 0, sizeof(CpaCyEcsm2SignOpData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->e, setup->nLenInBytes, setup->digest[i].pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_SIGN_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->k, setup->nLenInBytes, setup->random[i].pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_SIGN_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &opData[i]->d, setup->nLenInBytes, setup->d->pData, GFP_SM2_SIZE_IN_BYTE, SM2_PERFORM_SIGN_MEM_FREE()); outData[i] = qaeMemAllocNUMA( sizeof(Ecsm2SignOutputData), node, BYTE_ALIGNMENT_64); if (NULL == outData[i]) { PRINT_ERR("outData[%u] memory allocation error\n", i); goto cleanup; } memset(outData[i], 0, sizeof(Ecsm2SignOutputData)); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->r, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SIGN_MEM_FREE()); ALLOC_FLAT_BUFF_DATA(setup->cyInstanceHandle, &outData[i]->s, setup->nLenInBytes, NULL, 0, SM2_PERFORM_SIGN_MEM_FREE()); } /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = (CpaCyEcsm2SignCbFunc)sm2SignCallback; } /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Record the start time, the callback measures the end time when the last * response is received */ pSm2Data->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { for (i = 0; i < setup->numBuffers; i++) { do { opData[i]->fieldType = setup->fieldType; status = cpaCyEcsm2Sign(setup->cyInstanceHandle, (CpaCyEcsm2SignCbFunc)cbFunc, pSm2Data, opData[i], &pStatus, &outData[i]->r, &outData[i]->s); waitForAEonRetry(status, pSm2Data); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("SM2 Verify function failed with status:%d\n", status); goto cleanup; } } /*end buffers loop */ } /* end of numLoops loop*/ if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSm2Data, setup->syncMode, setup->numBuffers, setup->numLoops); } sampleCodeSemaphoreDestroy(&pSm2Data->comp); /*Free all memory*/ SM2_PERFORM_SETUP_FLAT_MEM_FREE(); SM2_PERFORM_SIGN_MEM_FREE(); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; cleanup: SM2_PERFORM_SETUP_FLAT_MEM_FREE(); SM2_PERFORM_SIGN_MEM_FREE(); return CPA_STATUS_FAIL; } /** ***************************************************************************** * @ingroup cryptoThreads * * @description * Perform Ecsm2 Signature verify operation * This function is called for signatrue verify performance test. * ******************************************************************************/ CpaStatus sm2VerifyPerform(sm2_test_params_t *setup) { Cpa32U i = 0; Cpa32U numLoops = 0; CpaBoolean verifyStatus = CPA_FALSE; CpaCyEcsm2Stats64 sm2Stats = {0}; CpaStatus status = CPA_STATUS_FAIL; CpaCyEcsm2VerifyOpData **vOpData = setup->verifyOp; /*variable to store what cpu thread is running on*/ Cpa32U node = 0; /*pointer to location to store performance data*/ perf_data_t *pSm2Data = NULL; CpaCyEcsm2VerifyCbFunc cbFunc = NULL; status = cpaCyEcsm2QueryStats64(setup->cyInstanceHandle, &sm2Stats); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Could not retrieve stats, error status %d\n", status); return status; } /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } initSemaphoreAndVariables(pSm2Data, setup); /*set the callback function if asynchronous mode is set*/ if (ASYNC == setup->syncMode) { cbFunc = (CpaCyEcsm2VerifyCbFunc)sm2VerifyCallback; } /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /*record the start time, the callback measures the end time when the last * response is received*/ pSm2Data->startCyclesTimestamp = sampleCodeTimestamp(); for (numLoops = 0; numLoops < setup->numLoops; numLoops++) { for (i = 0; i < setup->numBuffers; i++) { vOpData[i]->fieldType = setup->fieldType; do { status = cpaCyEcsm2Verify(setup->cyInstanceHandle, (CpaCyEcsm2VerifyCbFunc)cbFunc, pSm2Data, vOpData[i], &verifyStatus); waitForAEonRetry(status, pSm2Data); } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("SM2 Verify function failed with status:%d\n", status); SM2_PERFORM_VERIFY_MEM_FREE(); return status; } if (ASYNC != setup->syncMode) { if (CPA_TRUE != verifyStatus) { PRINT_ERR("SM2 Verify function verification failed " "but status = %d\n", status); } else { PRINT_ERR("SM2 Verify function verification " "succeeded\n"); } } } /*end buffers loop */ } /* end of numLoops loop*/ if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSm2Data, setup->syncMode, setup->numBuffers, setup->numLoops); } sampleCodeSemaphoreDestroy(&pSm2Data->comp); /*Free all memory*/ SM2_PERFORM_VERIFY_MEM_FREE(); SM2_PERFORM_SETUP_FLAT_MEM_FREE(); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } cpa_sample_code_sym_perf.c000066400000000000000000002422511503624047500361020ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sym_perf.c * * @defgroup sampleSymmetricPerf Symmetric Performance code * * @ingroup sampleSymmetricPerf * * @description * This file contains the main symmetric performance sample code. It is * capable of performing all ciphers, all hashes, authenticated hashes * and algorithm chaining. Nested Hashes are not supported * * This code pre-allocates a number of bufferLists as defined by * setup->numBuffLists, each bufferlist includes several flat buffers which * its size is equal to buffer size. The pre-allocated buffers are then * continuously looped until the numLoops is met. * Time stamping is started prior to the * Operation and is stopped when all callbacks have returned. * The packet size and algorithm to be tested is setup using the * setupSymmetricTest function. The framework is used to create the threads * which calls functions here to execute symmetric performance * *****************************************************************************/ #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_framework.h" #include "icp_sal_poll.h" #define EVEN_NUMBER (2) extern int signOfLife; extern volatile CpaBoolean digestAppended_g; extern int verboseOutput; extern Cpa32U symPollingInterval_g; #include "busy_loop.h" #include "qat_perf_cycles.h" #define ADF_MAX_DEVICES 32 Cpa16U busAddressId[ADF_MAX_DEVICES] = {0}; extern Cpa32U packageIdCount_g; extern int latency_single_buffer_mode; /* set to 1 for single buffer processing */ extern CpaInstanceHandle *cyInstances_g; /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * Callback function for result of perform operation * *****************************************************************************/ void symPerformCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult) { /*we declare the callback as per the API requirements, but we only use * the pCallbackTag parameter*/ processCallback(pCallbackTag); } /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * calculate the pointer of digest result in the buffer list * digest result should be located in the end of Plaintext and * digest result should be align with block size of cipher. * Please see example as the following: @verbatim +--------+----------------------------------------------------+--------+----+ | | Ciphertext | Digest |Pad + +--------+----------------------------------------------------+--------+----+ <-FlatBuffer[0]-><-FlatBuffer[1]-><-FlatBuffer[2]-><-FlatBuffer[3]-> <- Buffer List -> @endverbatim * @param[in] packetSize Data packet size * @param[in] blockSizeInBytes block length of the cipher * @param[in] bufferSizeInByte buffer size in the flatbuffer of bufferlist * @param[in] pBufferList the pointer of Buffer list which store data and * comprised of flatbuffers. * *****************************************************************************/ static Cpa8U *symCalDigestAddress(Cpa32U packetSize, Cpa32U blockSizeInBytes, Cpa32U bufferSizeInByte, CpaBufferList *pBufferList) { Cpa8U *pDigestResult = 0; Cpa32U numBuffers = pBufferList->numBuffers; Cpa32U packsetSizePad = 0; Cpa32U digestOffset = 0; Cpa32U indexBuffer = 0; #ifdef DEBUF_CODE PRINT("flatBufferSize %d\n", bufferSizeInByte); #endif /* check if packetSize is 0 */ if (bufferSizeInByte == 0) { pDigestResult = pBufferList->pBuffers[0].pData + packetSize; } else if (packetSize % bufferSizeInByte == 0) { pDigestResult = pBufferList->pBuffers[numBuffers - 1].pData + bufferSizeInByte; } else { /* since Digest address (pDigestResult) need to align with * blockSizeInBytes, we will check if packetSize is align with * blockSizeInBytes, * if not, padding will added after message */ if (packetSize % blockSizeInBytes != 0) { packsetSizePad = blockSizeInBytes - (packetSize % blockSizeInBytes); } /* calculate actual offset of digest result in flatbuffer*/ digestOffset = (packetSize + packsetSizePad) % bufferSizeInByte; /* calculate the which flat buffer store pDigestResult * pDigestResult will appended in the end of pData */ indexBuffer = (packetSize + packsetSizePad) / bufferSizeInByte; pDigestResult = pBufferList->pBuffers[indexBuffer].pData + digestOffset; } return pDigestResult; } #ifdef SYM_SET_SETDIGESTBUFFER /* Not used API sampleSymmetricPerf */ /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * initialize the digest within pBufferList by value. * * @param[in] messageLenToCipherInBytes Cipher Message Length * @param[in] digestLengthInBytes Digest Length * @param[in] value Initial value for Digest Buffer * @param[in] pBufferList the pointer of Buffer list which store * data and comprised of flatbuffers. *****************************************************************************/ static void symSetDigestBuffer(Cpa32U messageLenToCipherInBytes, Cpa32U digestLengthInBytes, Cpa8U value, CpaBufferList *pBufferList) { Cpa8U *pDigestResult = 0; Cpa32U indexBuffer = 0; Cpa32U i = 0; /* all the rest of data including padding will initialized , * so ivLenInBytes is 1.*/ pDigestResult = symCalDigestAddress(messageLenToCipherInBytes, 1, pBufferList->pBuffers[0].dataLenInBytes, pBufferList); indexBuffer = messageLenToCipherInBytes / pBufferList->pBuffers[0].dataLenInBytes; /* reset the digest memory to 0 */ memset( pDigestResult, value, (pBufferList->pBuffers[0].dataLenInBytes - messageLenToCipherInBytes % pBufferList->pBuffers[0].dataLenInBytes)); indexBuffer++; for (i = indexBuffer; i < pBufferList->numBuffers; i++) { memset(pBufferList->pBuffers[i].pData, value, pBufferList->pBuffers[i].dataLenInBytes); } } #endif /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * Create a symmetric session */ static CpaStatus symmetricSetupSession(CpaCySymCbFunc pSymCb, Cpa8U *pCipherKey, Cpa8U *pAuthKey, CpaCySymSessionCtx *pSession, symmetric_test_params_t *setup ) { Cpa32U sessionCtxSizeInBytes = 0; #if CPA_CY_API_VERSION_NUM_MINOR >= 8 Cpa32U sessionCtxDynamicSizeInBytes = 0; #endif CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymSessionCtx pLocalSession = NULL; Cpa32U cipherKeyLen = 0; Cpa32U authKeyLen = 0; Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /*set the cipher and authentication key len*/ cipherKeyLen = setup->setupData.cipherSetupData.cipherKeyLenInBytes; authKeyLen = setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes; /*generate a random cipher and authentication key*/ generateRandomData(pCipherKey, cipherKeyLen); generateRandomData(pAuthKey, authKeyLen); /*cipher setup only needs to be set for alg chaining, cipher, AES-GCM * and AES-CCM*/ setup->setupData.cipherSetupData.pCipherKey = pCipherKey; /*hash setup only needs to be set for hash, AES-GCM * and AES-CCM*/ setup->setupData.hashSetupData.authModeSetupData.authKey = pAuthKey; if (CPA_CY_SYM_HASH_AES_GMAC == setup->setupData.hashSetupData.hashAlgorithm) { setup->setupData.hashSetupData.authModeSetupData.authKey = NULL; setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes = 0; } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == setup->setupData.hashSetupData.hashAlgorithm #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || ((CPA_CY_SYM_HASH_ZUC_EIA3 == setup->setupData.hashSetupData.hashAlgorithm) && (KEY_SIZE_128_IN_BYTES == setup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes)) #endif ) { setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes = KEY_SIZE_128_IN_BYTES; } else { setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes = 0; } /* will not verify digest by default*/ setup->setupData.verifyDigest = CPA_FALSE; /*this is the original API to get the required context size, we show the * function used here, but we only use the size for the older version of the * API get size for memory allocation*/ status = cpaCySymSessionCtxGetSize( setup->cyInstanceHandle, &setup->setupData, &sessionCtxSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetSize error, status: %d", status); return status; } #if CPA_CY_API_VERSION_NUM_MINOR >= 8 /*get dynamic context size*/ status = cpaCySymSessionCtxGetDynamicSize(setup->cyInstanceHandle, &setup->setupData, &sessionCtxDynamicSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetDynamicSize error, status: %d", status); return status; } /* * allocate session memory using dynamic context size */ sessionCtxSizeInBytes = sessionCtxDynamicSizeInBytes; #endif pLocalSession = qaeMemAllocNUMA(sessionCtxSizeInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pLocalSession) { PRINT_ERR("Could not allocate pLocalSession memory\n"); return CPA_STATUS_FAIL; } /*zero session memory*/ memset(pLocalSession, 0, sessionCtxSizeInBytes); /* * init session with asynchronous callback- pLocalSession will contain * the session context */ status = cpaCySymInitSession( setup->cyInstanceHandle, pSymCb, &setup->setupData, pLocalSession); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymInitSession error, status: %d\n", status); qaeMemFreeNUMA((void **)&pLocalSession); return status; } *pSession = pLocalSession; #if CPA_CY_API_VERSION_NUM_MINOR >= 8 #endif return status; } /***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * Free memory allocated in the symmetricPerformOpDataSetup function * ****************************************************************************/ static void opDataMemFree(CpaCySymOpData *pOpdata[], Cpa32U numBuffers, CpaBoolean digestAppend) { Cpa32U k = 0; for (k = 0; k < numBuffers; k++) { if (NULL != pOpdata[k]) { qaeMemFreeNUMA((void **)&pOpdata[k]->pIv); if (NULL != pOpdata[k]->pAdditionalAuthData) { qaeMemFreeNUMA((void **)&pOpdata[k]->pAdditionalAuthData); } qaeMemFree((void **)&pOpdata[k]); } } } /***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * Setup symmetric operation data * ****************************************************************************/ static CpaStatus symmetricPerformOpDataSetup(CpaCySymSessionCtx pSessionCtx, Cpa32U *pPacketSize, CpaCySymOpData *pOpdata[], symmetric_test_params_t *setup, CpaBufferList *pBuffListArray[]) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U createCount = 0; Cpa32U node = 0; /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /*for each bufferList set the symmetric operation data*/ for (createCount = 0; createCount < setup->numBuffLists; createCount++) { pOpdata[createCount] = qaeMemAlloc(sizeof(CpaCySymOpData)); if (NULL == pOpdata[createCount]) { PRINT_ERR("Could not allocate Opdata memory at index %u\n", createCount); opDataMemFree(pOpdata, setup->numBuffLists, CPA_FALSE); return CPA_STATUS_FAIL; } memset(pOpdata[createCount], 0, sizeof(CpaCySymOpData)); pOpdata[createCount]->sessionCtx = pSessionCtx; pOpdata[createCount]->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; /*these only need to be set for cipher and alg chaining */ pOpdata[createCount]->cryptoStartSrcOffsetInBytes = setup->cryptoSrcOffset; /* messageLenToCipherInBytes and messageLenToHashInBytes do not have * to be the same. In this code we want to either hash the entire buffer * or encrypt the entire buffer, depending on the SymOperation. * For Alg Chaining, depending on the chain order, for HashThenCipher, * the digest will be the hash of the unencrypted buffer and then we * cipher the buffer. OR for CipherThenHash, we cipher the buffer, then * the perform the hash on the encrypted buffer, so that the digest is * the digest of the encrypted data*/ pOpdata[createCount]->messageLenToCipherInBytes = pPacketSize[createCount] - setup->cryptoSrcOffset; /*these only need to be set for hash and alg chaining*/ pOpdata[createCount]->hashStartSrcOffsetInBytes = HASH_OFFSET_BYTES; pOpdata[createCount]->messageLenToHashInBytes = pPacketSize[createCount]; pOpdata[createCount]->pAdditionalAuthData = NULL; /* In GMAC mode, there is no message to Cipher */ if (CPA_CY_SYM_HASH_AES_GMAC == setup->setupData.hashSetupData.hashAlgorithm) { pOpdata[createCount]->cryptoStartSrcOffsetInBytes = 0; pOpdata[createCount]->messageLenToCipherInBytes = 0; } if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == setup->setupData.hashSetupData.hashAlgorithm #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || ((CPA_CY_SYM_HASH_ZUC_EIA3 == setup->setupData.hashSetupData.hashAlgorithm) && (KEY_SIZE_128_IN_BYTES == setup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes)) #endif ) { pOpdata[createCount]->pAdditionalAuthData = qaeMemAllocNUMA(KEY_SIZE_128_IN_BYTES, node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[createCount]->pAdditionalAuthData) { PRINT_ERR("Could not allocate additional auth data index %u\n", createCount); opDataMemFree(pOpdata, setup->numBuffLists, CPA_FALSE); return CPA_STATUS_FAIL; } memset(pOpdata[createCount]->pAdditionalAuthData, 0xAA, KEY_SIZE_128_IN_BYTES); } else if (((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) || (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM)) && (setup->setupData.hashSetupData.hashAlgorithm != CPA_CY_SYM_HASH_AES_GMAC)) { /*must allocate to the nearest block size required (above 18 bytes)*/ pOpdata[createCount]->pAdditionalAuthData = qaeMemAllocNUMA( AES_CCM_MIN_AAD_ALLOC_LENGTH, node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[createCount]->pAdditionalAuthData) { PRINT_ERR("Could not allocate additional auth data index %u\n", createCount); opDataMemFree(pOpdata, setup->numBuffLists, CPA_FALSE); return CPA_STATUS_FAIL; } memset(pOpdata[createCount]->pAdditionalAuthData, 0, AES_CCM_MIN_AAD_ALLOC_LENGTH); } /*set IV len depending on what we are testing*/ switch (setup->setupData.cipherSetupData.cipherAlgorithm) { case CPA_CY_SYM_CIPHER_AES_CBC: case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_AES_CCM: case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: case CPA_CY_SYM_CIPHER_AES_F8: case CPA_CY_SYM_CIPHER_AES_XTS: #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 case CPA_CY_SYM_CIPHER_ZUC_EEA3: #endif case CPA_CY_SYM_CIPHER_SM4_ECB: case CPA_CY_SYM_CIPHER_SM4_CBC: case CPA_CY_SYM_CIPHER_SM4_CTR: if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_ZUC_EEA3 && setup->setupData.cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_256_IN_BYTES) { pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_24_BYTE_BLOCK_CIPHER; } else { pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_16_BYTE_BLOCK_CIPHER; } /* If 0 use default else use value passed. */ if (0 != setup->ivLength) { pOpdata[createCount]->ivLenInBytes = setup->ivLength; } break; case CPA_CY_SYM_CIPHER_CHACHA: pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_12_BYTE_CHACHA; /* If 0 use default else use value passed. */ if (0 != setup->ivLength) { pOpdata[createCount]->ivLenInBytes = setup->ivLength; } break; case CPA_CY_SYM_CIPHER_DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CTR: case CPA_CY_SYM_CIPHER_KASUMI_F8: pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_8_BYTE_BLOCK_CIPHER; /* If 0 use default else use value passed. */ if (0 != setup->ivLength) { pOpdata[createCount]->ivLenInBytes = setup->ivLength; } break; case CPA_CY_SYM_CIPHER_AES_GCM: pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_16_BYTE_GCM; /* If 0 use default else use value passed. */ if (0 != setup->ivLength) { pOpdata[createCount]->ivLenInBytes = setup->ivLength; } break; default: pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_8_BYTE_BLOCK_CIPHER; break; } /*allocate NUMA aware aligned memory for IV*/ pOpdata[createCount]->pIv = qaeMemAllocNUMA( pOpdata[createCount]->ivLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[createCount]->pIv) { PRINT_ERR("IV is null\n"); opDataMemFree(pOpdata, setup->numBuffLists, CPA_FALSE); return CPA_STATUS_FAIL; } memset( pOpdata[createCount]->pIv, 0, pOpdata[createCount]->ivLenInBytes); if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { /*Although the IV data length for CCM must be 16 bytes, The nonce length must be between 7 and 13 inclusive*/ pOpdata[createCount]->ivLenInBytes = AES_CCM_DEFAULT_NONCE_LENGTH; } /*if we are testing HASH or Alg Chaining, set the location to place * the digest result, this space was allocated in sampleSymmetricPerform * function*/ if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { /* calculate digest offset */ pOpdata[createCount]->pDigestResult = symCalDigestAddress(pPacketSize[createCount], IV_LEN_FOR_16_BYTE_BLOCK_CIPHER, setup->flatBufferSizeInBytes, pBuffListArray[createCount]); } if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { /*generate a random IV*/ generateRandomData(&(pOpdata[createCount]->pIv[1]), pOpdata[createCount]->ivLenInBytes); memcpy(&(pOpdata[createCount]->pAdditionalAuthData[1]), &(pOpdata[createCount]->pIv[1]), pOpdata[createCount]->ivLenInBytes); } else { /*generate a random IV*/ generateRandomData(pOpdata[createCount]->pIv, pOpdata[createCount]->ivLenInBytes); } } return CPA_STATUS_SUCCESS; } /***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * measures the performance of symmetric encryption operations * ****************************************************************************/ static CpaStatus symPerform(symmetric_test_params_t *setup, perf_data_t *pSymData, Cpa32U numOfLoops, CpaCySymOpData **ppOpData, CpaBufferList **ppSrcBuffListArray, CpaCySymCipherDirection cipherDirection) { CpaBoolean verifyResult = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U outsideLoopCount = 0; Cpa32U insideLoopCount = 0; CpaInstanceInfo2 *instanceInfo2 = NULL; #ifdef POLL_INLINE CpaStatus pollStatus = CPA_STATUS_SUCCESS; Cpa64U numOps = 0; Cpa64U nextPoll = symPollingInterval_g; #endif /* Counts the number of buffers submitted for encryption. Only * MAX_LATENCY_COUNT of these will be 'latency buffers' whose * times are measured */ Cpa32U submissions = 0; /* set when the latency buffer is sent to accelerator */ perf_cycles_t *request_submit_start = NULL; /* set in completion service routine dcPerformCallback() */ perf_cycles_t *request_respnse_time = NULL; const Cpa32U request_mem_sz = sizeof(perf_cycles_t) * MAX_LATENCY_COUNT; /* Capture busy loop before memset of performanceStats */ Cpa32U busyLoopValue = pSymData->busyLoopValue; Cpa32U staticAssign = 0, busyLoopCount = 0, numBusyLoops = 0; perf_cycles_t startBusyLoop = 0, endBusyLoop = 0, totalBusyLoopCycles = 0; instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); saveClearRestorePerfStats(pSymData); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } pSymData->packageId = instanceInfo2->physInstId.packageId; if (latency_enable) { if (pSymData->numOperations > LATENCY_SUBMISSION_LIMIT) { PRINT_ERR("Error max submissions for latency must be <= %d\n", LATENCY_SUBMISSION_LIMIT); qaeMemFree((void **)&instanceInfo2); return CPA_STATUS_FAIL; } request_submit_start = qaeMemAlloc(request_mem_sz); request_respnse_time = qaeMemAlloc(request_mem_sz); if (request_submit_start == NULL || request_respnse_time == NULL) { PRINT_ERR("Failed to allocate memory for submission and response " "times\n"); qaeMemFree((void **)&instanceInfo2); qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); return CPA_STATUS_FAIL; } memset(request_submit_start, 0, request_mem_sz); memset(request_respnse_time, 0, request_mem_sz); /* Calculate how many buffer submissions between latency measurements.. */ pSymData->nextCount = (setup->numBuffLists * setup->numLoops) / MAX_LATENCY_COUNT; /* .. and set the next trigger count to this */ pSymData->countIncrement = pSymData->nextCount; /* How many latency measurements of the MAX_LATENCY_COUNT have been * taken so far */ pSymData->latencyCount = 0; /* Completion routine sets end times in the array indirectly */ pSymData->response_times = request_respnse_time; pSymData->start_times = request_submit_start; if (latency_debug) PRINT("%s: LATENCY_CODE: Initial nextCount %u, countIncrement %u\n", __FUNCTION__, pSymData->nextCount, pSymData->countIncrement); } /*preset the number of ops we plan to submit*/ pSymData->numOperations = (Cpa64U)setup->numBuffLists * setup->numLoops; coo_init(pSymData, pSymData->numOperations); pSymData->retries = 0; /* Init the semaphore used in the callback */ sampleCodeSemaphoreInit(&pSymData->comp, 0); /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Get the time, collect this only for the first * request, the callback collects it for the last */ pSymData->startCyclesTimestamp = sampleCodeTimestamp(); /* The outside for-loop will loop around the preallocated buffer list * array the number of times necessary to satisfy: * NUM_OPERATIONS / setup->numBuffLists*/ for (outsideLoopCount = 0; outsideLoopCount < numOfLoops; outsideLoopCount++) { /* This inner for-loop loops around the number of Buffer Lists * that have been preallocated. Once the array has completed- * exit to the outer loop to move on the next iteration of the * preallocated loop. */ for (insideLoopCount = 0; insideLoopCount < setup->numBuffLists; insideLoopCount++) { /* When the callback returns it will increment the responses * counter and test if its equal to NUM_OPERATIONS, in that * case all responses have been successfully received. */ do { if (latency_enable) { if (pSymData->latencyCount < MAX_LATENCY_COUNT) { if (submissions + 1 == pSymData->nextCount) { request_submit_start[pSymData->latencyCount] = sampleCodeTimestamp(); } } } coo_req_start(pSymData); status = cpaCySymPerformOp(setup->cyInstanceHandle, pSymData, ppOpData[insideLoopCount], ppSrcBuffListArray[insideLoopCount], ppSrcBuffListArray[insideLoopCount], /*in-place operation*/ &verifyResult); coo_req_stop(pSymData, status); if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { sampleCodeSymPollInstance(setup->cyInstanceHandle, 0); nextPoll = numOps + symPollingInterval_g; } } #endif AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { busyLoop(busyLoopValue, &staticAssign); busyLoopCount++; } if (CPA_STATUS_SUCCESS != status) { break; } if (latency_enable) { /* Another buffer has been submitted to the accelerator */ submissions++; /* Have we been requested to process one buffer at a time. This * will result in no retries and so the best latency times. */ if (latency_single_buffer_mode != 0) { /* Must now wait until this buffer is processed by the CPM */ while (pSymData->responses != submissions) { /* Keep polling until compression of the buffer * completes * and symPerformCallback() increments * pSymData->responses */ icp_sal_CyPollInstance(setup->cyInstanceHandle, 0); } } } #ifdef POLL_INLINE if (poll_inline_g) { if (instanceInfo2->isPolled) { ++numOps; if (numOps == nextPoll) { coo_poll_trad_cy( pSymData, setup->cyInstanceHandle, &pollStatus); nextPoll = numOps + symPollingInterval_g; } } } #endif } /*end of inner loop */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp Error %d\n", status); break; } } /* end of outer loop */ #ifdef POLL_INLINE if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2->isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pSymData, setup->cyInstanceHandle, pSymData->numOperations); } } #endif /* Checking the response count and initiating the sem_wait in waitForResponses function to complete the operations */ if (pSymData->responses != pSymData->numOperations) { if (CPA_STATUS_SUCCESS == status) { status = waitForResponses( pSymData, setup->syncMode, setup->numBuffLists, numOfLoops); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Thread %u timeout. ", setup->threadID); } } } if (latency_enable) { int i; if (latency_debug) { PRINT("%s: Calculating min, max and ave latencies...\n", __FUNCTION__); sampleCodeSleep(1); /* Let all our debug be printed out */ } pSymData->minLatency = MAX_LATENCY_LIMIT; /* Will be less than this */ pSymData->maxLatency = 0; /* Will be more than this */ /* Let's accumulate in 'aveLatency' all the individual 'latency' * times. Typically, there should be MAX_LATENCY_COUNT of these. * We also calculate min/max so we can get a sense of the variance. */ for (i = 0; i < pSymData->latencyCount; i++) { perf_cycles_t latency = pSymData->response_times[i] - request_submit_start[i]; pSymData->aveLatency += latency; if (latency < pSymData->minLatency) pSymData->minLatency = latency; if (latency > pSymData->maxLatency) pSymData->maxLatency = latency; if (latency_debug) PRINT("%d, end[i]:%llu, start[i]:%llu, min:%llu, ave:%llu, " "max:%llu\n", i, pSymData->response_times[i], request_submit_start[i], pSymData->minLatency, pSymData->aveLatency, pSymData->maxLatency); } if (pSymData->latencyCount > 0) { /* Then scale down this accumulated value to get the average. * This will be reported by dcPrintStats() at the end of the test */ do_div(pSymData->aveLatency, pSymData->latencyCount); } /*we are finished with the response time so set to null before exit*/ pSymData->response_times = NULL; qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { pSymData->busyLoopValue = busyLoopValue; pSymData->busyLoopCount = busyLoopCount; pSymData->totalBusyLoopCycles = totalBusyLoopCycles; busyLoopTimeStamp(); startBusyLoop = busyLoopTimeStamp(); for (numBusyLoops = 0; numBusyLoops < busyLoopCount; numBusyLoops++) { busyLoop(busyLoopValue, &staticAssign); } endBusyLoop = busyLoopTimeStamp(); setup->performanceStats->totalBusyLoopCycles = endBusyLoop - startBusyLoop; setup->performanceStats->offloadCycles = (setup->performanceStats->endCyclesTimestamp - setup->performanceStats->startCyclesTimestamp) - setup->performanceStats->totalBusyLoopCycles; do_div(setup->performanceStats->offloadCycles, setup->performanceStats->responses); } coo_average(pSymData); coo_deinit(pSymData); /*clean up the callback semaphore*/ sampleCodeSemaphoreDestroy(&pSymData->comp); qaeMemFree((void **)&instanceInfo2); return status; } /***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * Free memory allocated in the sampleSymmetricPerform function * ****************************************************************************/ static void symPerformMemFree(symmetric_test_params_t *setup, CpaFlatBuffer **ppSrcBuffPtrArray, CpaBufferList **ppSrcBuffListArray, CpaCySymOpData **ppOpData, CpaCySymSessionCtx *pSessionCtx) { /*free bufferLists, flatBuffers and data*/ sampleFreeBuffers(ppSrcBuffPtrArray, ppSrcBuffListArray, setup); if (NULL != ppOpData) { opDataMemFree(ppOpData, setup->numBuffLists, setup->digestAppend); qaeMemFree((void **)&ppOpData); } /* free the session memory - calling code is responsible for * removing the session first*/ if (NULL != *pSessionCtx) { qaeMemFreeNUMA((void **)pSessionCtx); } if (NULL != ppSrcBuffPtrArray) { qaeMemFree((void **)&ppSrcBuffPtrArray); } if (NULL != ppSrcBuffListArray) { qaeMemFree((void **)&ppSrcBuffListArray); } } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Used for profiling IA offload cost. * * Phase One:Iterates over the main perform function, increasing the number * of busy loop cycles(BUSY_LOOP_INCREMENT) on each iteration until no retries * occur. * * Phase Two: Continues to iterate over the main perform function, increasing * the number of busy loop cycles on each iteration until performance is * affected then steps back to the last increment value, i.e. the last * increment step(BUSY_LOOP_INCREMENT) before performance was affected. *****************************************************************************/ static CpaStatus performOffloadCalculation( symmetric_test_params_t *setup, perf_data_t *pSymData, Cpa32U numOfLoops, CpaCySymOpData **ppOpData, CpaBufferList **ppSrcBuffListArray, CpaCySymCipherDirection cipherDirection) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32S baseThroughput = 0, currentThroughput = 0; Cpa32U packetSize = 0, lowerBound = 0, upperBound = 0; perf_data_t *pPerfData = setup->performanceStats; pPerfData->busyLoopValue = 1; packetSize = setup->packetSizeInBytesArray[0]; baseThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* Find the lower bound(retries) and upper bound(no retries) for subsequent * binary search. */ while (CPA_STATUS_SUCCESS == status && pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue; pPerfData->busyLoopValue = pPerfData->busyLoopValue << 1; /* PERFORM OP */ status = symPerform(setup, pSymData, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); } upperBound = pPerfData->busyLoopValue; /* Binary Search for no retries while maintaining throughput */ while (CPA_STATUS_SUCCESS == status && lowerBound <= upperBound) { pPerfData->busyLoopValue = (upperBound + lowerBound) / 2; /* PERFORM OP */ status = symPerform(setup, pSymData, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); currentThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* If no retries and we're within ERROR_MARGIN (0.1%) of base throughput */ if (pPerfData->retries == 0 && (withinMargin(baseThroughput, currentThroughput, ERROR_MARGIN) == 1)) { break; } /* If we see retries */ else if (pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue + 1; } /* Else retries are zero, but throughput has been affected. */ else { upperBound = pPerfData->busyLoopValue - 1; } } return status; } /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * Main executing function ******************************************************************************/ CpaStatus sampleSymmetricPerform(symmetric_test_params_t *setup) { /* start of local variable declarations */ CpaCySymSessionCtx pEncryptSessionCtx = NULL; CpaCySymOpData **ppOpData = NULL; CpaFlatBuffer **ppSrcBuffPtrArray = NULL; CpaBufferList **ppSrcBuffListArray = NULL; Cpa32U *totalSizeInBytes = NULL; perf_data_t *pSymPerfData = NULL; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numOfLoops = setup->numLoops; Cpa32U insideLoopCount = 0; Cpa8U *cipherKey = NULL; Cpa8U *authKey = NULL; CpaCySymCbFunc pSymCb = NULL; Cpa32U node = 0; CpaCySymCipherDirection cipherDirection = cipherDirection_g; /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return CPA_STATUS_FAIL; } totalSizeInBytes = qaeMemAlloc(setup->numBuffLists * sizeof(Cpa32U)); if (NULL == totalSizeInBytes) { PRINT_ERR("sampleCodeCyGetNode memory allocation error\n"); return CPA_STATUS_FAIL; } /* Initialize local variables */ cipherKey = qaeMemAlloc( setup->setupData.cipherSetupData.cipherKeyLenInBytes * sizeof(Cpa8U)); if (NULL == cipherKey) { PRINT_ERR("cipherKey memory allocation error\n"); goto exit; } authKey = qaeMemAlloc( setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes * sizeof(Cpa8U)); if (NULL == authKey) { PRINT_ERR("authKey memory allocation error\n"); goto exit; } /*allocate memory for an array of bufferList pointers, flatBuffer pointers * and operation data, the bufferLists and Flat buffers are created in * sampleCreateBuffers of cpa_sample_code_crypto_utils.c*/ status = allocArrayOfVirtPointers((void **)&ppOpData, setup->numBuffLists); if (CPA_STATUS_SUCCESS != status) { goto exit; } status = allocArrayOfVirtPointers((void **)&ppSrcBuffPtrArray, setup->numBuffLists); if (CPA_STATUS_SUCCESS != status) { goto exit; } status = allocArrayOfVirtPointers((void **)&ppSrcBuffListArray, setup->numBuffLists); if (CPA_STATUS_SUCCESS != status) { goto exit; } /*use the preallocated performance stats to store performance data, this * points to an element in perfStats array in the framework, each thread * points to a unique element of perfStats array*/ pSymPerfData = setup->performanceStats; if (NULL == pSymPerfData) { PRINT_ERR("perf data pointer is NULL\n"); status = CPA_STATUS_FAIL; goto exit; } if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH && (setup->setupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SNOW3G_UIA2 || setup->setupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_KASUMI_F9)) { setup->setupData.hashSetupData.digestResultLenInBytes = DIGEST_RESULT_4BYTES; } /*if we are testing hash or alg chain, get the hash size that needs to be * allocated for the digest result. sampleCreateBuffers uses the hash size * to allocate the appropriate memory*/ for (insideLoopCount = 0; insideLoopCount < setup->numBuffLists; insideLoopCount++) { /* need to be allocate space for the digest result. */ totalSizeInBytes[insideLoopCount] = setup->packetSizeInBytesArray[insideLoopCount] + setup->setupData.hashSetupData.digestResultLenInBytes; } /*init the symmetric session*/ /*if the mode is asynchronous then set the callback function*/ if (ASYNC == setup->syncMode) { pSymCb = symPerformCallback; } status = symmetricSetupSession(pSymCb, cipherKey, authKey, &pEncryptSessionCtx, setup ); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("symmetricSetupSession error, status %d\n", status); goto exit; } /* we create sample buffers with space for digest result if testing hash or * alg chain , otherwise we just create sample buffers * based on the bufferSize we are testing*/ status = sampleCreateBuffers(setup->cyInstanceHandle, totalSizeInBytes, ppSrcBuffPtrArray, ppSrcBuffListArray, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCreateBuffers error, status %d\n", status); goto exit; } /*setup the symmetric operation data*/ status = symmetricPerformOpDataSetup(pEncryptSessionCtx, setup->packetSizeInBytesArray, ppOpData, setup, ppSrcBuffListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("symmetricPerformOpDataSetup error, status %d\n", status); goto exit; } status = symPerform(setup, pSymPerfData, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { status = performOffloadCalculation(setup, pSymPerfData, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); } if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("symPerform error, status %d\n", status); goto exit; } status = removeSymSession(setup->cyInstanceHandle, pEncryptSessionCtx); exit: symPerformMemFree(setup, ppSrcBuffPtrArray, ppSrcBuffListArray, ppOpData, &pEncryptSessionCtx); if (NULL != authKey) { qaeMemFree((void **)&authKey); } if (NULL != cipherKey) { qaeMemFree((void **)&cipherKey); } if (NULL != totalSizeInBytes) { qaeMemFree((void **)&totalSizeInBytes); } if (NULL != setup->performanceStats) { if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } } return status; } /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * Setup a symmetric crypto thread for a given packet size or mix ******************************************************************************/ void sampleSymmetricPerformance(single_thread_test_data_t *testSetup) { symmetric_test_params_t symTestSetup; symmetric_test_params_t *pSetup = ((symmetric_test_params_t *)testSetup->setupPtr); Cpa32U loopIteration = 0; CpaStatus status = CPA_STATUS_SUCCESS; /*define the distribution of the packet mix * here we defined 2 lots of 10 sizes * later it is replicated into 100 buffers*/ Cpa32U packetMix[NUM_PACKETS_IMIX] = { BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_8992, BUFFER_SIZE_64, BUFFER_SIZE_1504}; Cpa32U *pPacketSize = NULL; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaInstanceInfo2 *instanceInfo = NULL; #if defined(SC_WITH_QAT22) CpaCyCapabilitiesInfo pCapInfo = {0}; #endif testSetup->passCriteria = getPassCriteria(); memset(&symTestSetup, 0, sizeof(symmetric_test_params_t)); /*cast the setup to a known structure so that we can populate our local * test setup*/ symTestSetup.setupData = pSetup->setupData; /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*give our thread a unique memory location to store performance stats*/ symTestSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return; } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } #if defined(SC_WITH_QAT22) while (testSetup->logicalQaInstance < numInstances) { cpaCyQueryCapabilities(cyInstances[testSetup->logicalQaInstance], &pCapInfo); if (CPA_TRUE != pCapInfo.symSupported) testSetup->logicalQaInstance++; else break; } if (testSetup->logicalQaInstance >= numInstances) { PRINT_ERR("Warning! SYMMETRIC operation is not supported on Instance\n"); testSetup->logicalQaInstance = 0; } #endif instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; status = cpaCyInstanceGetInfo2(symTestSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } pPacketSize = qaeMemAlloc(sizeof(Cpa32U) * pSetup->numBuffLists); if (NULL == pPacketSize) { PRINT_ERR("Could not allocate memory for pPacketSize\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (testSetup->packetSize == PACKET_IMIX) { /*we are testing IMIX so we copy buffer sizes from preallocated * array into symTestSetup.numBuffLists*/ Cpa32U indexer = sizeof(packetMix) / sizeof(Cpa32U); for (loopIteration = 0; loopIteration < pSetup->numBuffLists; loopIteration++) { pPacketSize[loopIteration] = packetMix[loopIteration % indexer]; } } else { /*we are testing a uniform bufferSize, so we set the bufferSize array * accordingly*/ if (useUnalignedBuffer != 0) { for (loopIteration = 0; loopIteration < pSetup->numBuffLists; loopIteration++) { pPacketSize[loopIteration] = testSetup->packetSize + 1; } } else { for (loopIteration = 0; loopIteration < pSetup->numBuffLists; loopIteration++) { pPacketSize[loopIteration] = testSetup->packetSize; } } } /*initialize digestIsAppended with input parameter */ symTestSetup.setupData.digestIsAppended = pSetup->digestAppend; symTestSetup.numBuffLists = pSetup->numBuffLists; symTestSetup.flatBufferSizeInBytes = pSetup->flatBufferSizeInBytes; symTestSetup.enableRoundOffPkt = pSetup->enableRoundOffPkt; symTestSetup.numLoops = pSetup->numLoops; /*reset the stats print function to NULL, we set it to the proper function * if the test passes at the end of this function*/ testSetup->statsPrintFunc = NULL; /*assign the array of buffer sizes we are testing to the symmetric test * setup*/ symTestSetup.packetSizeInBytesArray = pPacketSize; /*assign our thread a unique memory location to store performance stats*/ symTestSetup.performanceStats = testSetup->performanceStats; memset(symTestSetup.performanceStats, 0, sizeof(perf_data_t)); symTestSetup.performanceStats->packageId = instanceInfo->physInstId.packageId; symTestSetup.performanceStats->averagePacketSizeInBytes = testSetup->packetSize == PACKET_IMIX ? BUFFER_SIZE_1152 : testSetup->packetSize; /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; symTestSetup.syncMode = pSetup->syncMode; /*store core affinity, this assumes logical cpu core number is the same * logicalQaInstace */ symTestSetup.performanceStats->logicalCoreAffinity = testSetup->logicalQaInstance; symTestSetup.threadID = testSetup->threadID; symTestSetup.isDpApi = pSetup->isDpApi; symTestSetup.cryptoSrcOffset = pSetup->cryptoSrcOffset; symTestSetup.digestAppend = pSetup->digestAppend; symTestSetup.ivLength = pSetup->ivLength; if (CPA_TRUE != checkCapability(cyInstances[testSetup->logicalQaInstance], &symTestSetup)) { PRINT("\nThread %u Invalid test.Capability check failed for the " "requested algorithm on the configured instance\n", testSetup->threadID); testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_UNSUPPORTED; error_flag_g = CPA_FALSE; sampleCodeBarrier(); goto exit; } /*launch function that does all the work*/ status = sampleSymmetricPerform(&symTestSetup); if (CPA_STATUS_SUCCESS != status) { printSymTestType(&symTestSetup); PRINT("Test %u FAILED\n", testSetup->threadID); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; } if ((CPA_STATUS_SUCCESS != status) || (symTestSetup.performanceStats->threadReturnStatus == CPA_STATUS_FAIL)) { /* Stop Cy Service function should be called after all threads * complete their execution. This function will be called from * WaitForThreadCompletion().*/ testSetup->statsPrintFunc = (stats_print_func_t)stopCyServicesFromCallback; } exit: /*free memory and exit*/ if (pPacketSize != NULL) { qaeMemFree((void **)&pPacketSize); } qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); #if defined(SC_WITH_QAT22) testSetup->logicalQaInstance = 0; #endif sampleCodeThreadComplete(testSetup->threadID); return; } EXPORT_SYMBOL(sampleSymmetricPerformance); /****************************************************************************** * @ingroup sampleSymmetricTest * * @description * setup a symmetric test * This function needs to be called from main to setup a symmetric test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ******************************************************************************/ CpaStatus setupSymmetricTest(CpaCySymOp opType, CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCyPriority priority, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, nested_hash_test_setup_t *nestedModeSetupDataPtr, Cpa32U packetSize, Cpa32U bufferSizeInBytes, Cpa32U numBuffLists, Cpa32U numLoops, Cpa32U digestAppend) { /*thread_setup_g is a multidimensional global array that stores the setup * for all thread variations in an array of characters. We store our test * setup at the start of the second array ie index 0. There maybe multiple * thread types(setups) running as counted by testTypeCount_g*/ symmetric_test_params_t *symmetricSetup = NULL; Cpa8S name[] = {'S', 'Y', 'M', '\0'}; CpaCySymCapabilitiesInfo capInfo = {{0}}; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /* Return an error if the number of packets is not modulus zero of the * number of packets to cover IMIX packet mix. */ if (packetSize == PACKET_IMIX && (numBuffLists % NUM_PACKETS_IMIX) != 0) { PRINT_ERR("To ensure that the weighting of IMIX packets is correct " ", the number of buffers (%d) should be a multiple of %d\n", numBuffLists, NUM_PACKETS_IMIX); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Failed to start Crypto services\n"); return CPA_STATUS_FAIL; } if (iaCycleCount_g) { #ifdef POLL_INLINE enablePollInline(); #endif } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } /*as setup is a multidimensional char array we need to cast it to the * symmetric structure*/ memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); symmetricSetup = (symmetric_test_params_t *)&thread_setup_g[testTypeCount_g][0]; memset(symmetricSetup, 0, sizeof(symmetric_test_params_t)); testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)sampleSymmetricPerformance; { testSetupData_g[testTypeCount_g].packetSize = packetSize; symmetricSetup->setupData.partialsNotRequired = CPA_TRUE; } /*then we store the test setup in the above location*/ // symmetricSetup->setupData.sessionPriority=CPA_CY_PRIORITY_HIGH; symmetricSetup->setupData.sessionPriority = priority; symmetricSetup->setupData.symOperation = opType; symmetricSetup->setupData.cipherSetupData.cipherAlgorithm = cipherAlg; symmetricSetup->setupData.cipherSetupData.cipherDirection = cipherDirection_g; symmetricSetup->setupData.cipherSetupData.cipherKeyLenInBytes = cipherKeyLengthInBytes; symmetricSetup->setupData.hashSetupData.hashAlgorithm = hashAlg; symmetricSetup->setupData.hashSetupData.hashMode = hashMode; symmetricSetup->isDpApi = CPA_FALSE; symmetricSetup->cryptoSrcOffset = cipherOffset; /* in this code we limit the digest result len to be the same as the the * authentication key len*/ symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = authKeyLengthInBytes; /* GCM hash works only on 8,12 and 16 bytes, default to 16 if others */ if (CPA_CY_SYM_HASH_AES_GCM == hashAlg && (authKeyLengthInBytes != 8 && authKeyLengthInBytes != 12 && authKeyLengthInBytes != 16)) { PRINT("CPA_CY_SYM_HASH_AES_GCM digest length %u unsupported , " "defaulting to 16 \n", authKeyLengthInBytes); symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = 16; } #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 #endif if (CPA_STATUS_SUCCESS == cpaCySymQueryCapabilities(cyInstances_g[0], &capInfo)) { if (CPA_BITMAP_BIT_TEST(capInfo.ciphers, CPA_CY_SYM_CIPHER_CHACHA)) { /* Always run AES-GCM/GMAC algchain with single pass mode */ if ((CPA_CY_SYM_CIPHER_AES_GCM == cipherAlg) && (CPA_CY_SYM_HASH_AES_GCM == hashAlg || CPA_CY_SYM_HASH_AES_GMAC == hashAlg) && CPA_CY_SYM_OP_ALGORITHM_CHAINING == opType) { symmetricSetup->ivLength = CPA_CIPHER_SPC_IV_SIZE; } } } // check which kind of hash mode is selected if (CPA_CY_SYM_HASH_MODE_NESTED == hashMode) { // nested mode if (NULL == nestedModeSetupDataPtr) { PRINT_ERR("Doesn't support nested mode, " "nestedModeSetupDataPtr is NULL\n"); return CPA_STATUS_FAIL; } // set the struct for nested hash mode /* If random numbers need to be generated */ if (CPA_TRUE == nestedModeSetupDataPtr->generateRandom) { symmetricSetup->setupData.hashSetupData.nestedModeSetupData .innerPrefixLenInBytes = SHA512_DIGEST_LENGTH_IN_BYTES; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .pInnerPrefixData = symmetricSetup->nestedHashInnerPrefix; generateRandomData(symmetricSetup->setupData.hashSetupData .nestedModeSetupData.pInnerPrefixData, SHA512_DIGEST_LENGTH_IN_BYTES); symmetricSetup->setupData.hashSetupData.nestedModeSetupData .outerHashAlgorithm = CPA_CY_SYM_HASH_SHA512; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .pOuterPrefixData = symmetricSetup->nestedHashOuterPrefix; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .outerPrefixLenInBytes = SHA512_DIGEST_LENGTH_IN_BYTES; generateRandomData(symmetricSetup->setupData.hashSetupData .nestedModeSetupData.pOuterPrefixData, SHA512_DIGEST_LENGTH_IN_BYTES); } /* Support for old code */ else { symmetricSetup->setupData.hashSetupData.nestedModeSetupData = nestedModeSetupDataPtr->nestedSetupData; } } if ((CPA_CY_SYM_HASH_AES_XCBC == hashAlg) && (AES_XCBC_DIGEST_LENGTH_IN_BYTES != authKeyLengthInBytes)) { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = AES_XCBC_DIGEST_LENGTH_IN_BYTES; } else if ((CPA_CY_SYM_HASH_KASUMI_F9 == hashAlg) || (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlg)) { /* * KASUMI_F9 and SNOW3G_UIA2 supports authKeyLen=128bits * and digestResultLen=32bits */ symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = KASUMI_F9_OR_SNOW3G_UIA2_KEY_SIZE_128_IN_BYTES; symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = setHashDigestLen(hashAlg); } #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 // ZUC-EIA3 supports authKeyLen=128bits and digestResultLen=32bits else if (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlg && authKeyLengthInBytes < KEY_SIZE_256_IN_BYTES) { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = KEY_SIZE_128_IN_BYTES; symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = setHashDigestLen(hashAlg); } #endif else { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = authKeyLengthInBytes; } symmetricSetup->setupData.algChainOrder = chainOrder; symmetricSetup->syncMode = syncMode; symmetricSetup->flatBufferSizeInBytes = bufferSizeInBytes; symmetricSetup->numLoops = numLoops; symmetricSetup->numBuffLists = numBuffLists; if (((bufferSizeInBytes != 0) && (packetSize == PACKET_IMIX)) || (bufferSizeInBytes % IV_LEN_FOR_16_BYTE_BLOCK_CIPHER != 0)) { PRINT_ERR("Doesn't support PACKET_IMIX " "when the flat buffer size is not 0 or " " it's not align with block size (%d): ", bufferSizeInBytes); return CPA_STATUS_FAIL; } symmetricSetup->digestAppend = digestAppend; return CPA_STATUS_SUCCESS; } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a cipher test * This function needs to be called from main to setup a cipher test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ******************************************************************************/ CpaStatus setupCipherTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U bufferSizeInBytes, Cpa32U numLists, Cpa32U numLoops) { return setupSymmetricTest( CPA_CY_SYM_OP_CIPHER, cipherAlg, cipherKeyLengthInBytes, NOT_USED, priority, NOT_USED /* hash alg not needed in cipher test*/, NOT_USED /* hash mode not needed in cipher test*/, NOT_USED /* auth key len not needed in cipher test*/, NOT_USED /* chain mode not needed in cipher test*/, syncMode, NULL, /* nested hash data not needed in cipher test*/ packetSize, bufferSizeInBytes, numLists, numLoops, digestAppended_g); } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a hash test * This function needs to be called from main to setup a hash test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ******************************************************************************/ CpaStatus setupHashTest(CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops) { return setupSymmetricTest( CPA_CY_SYM_OP_HASH, NOT_USED /* cipher alg not needed in cipher test*/, NOT_USED /* cipher key len not needed in cipher test*/, NOT_USED, priority, hashAlg, hashMode, authKeyLengthInBytes, NOT_USED /* chain mode not needed in cipher test*/, syncMode, NULL, /* nested hash data not needed in cipher test*/ packetSize, BUFFER_SIZE_0, numBufferLists, numLoops, digestAppended_g); } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test (default High Priority) * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupAlgChainTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U bufferSizeInBytes, Cpa32U numBufferLists, Cpa32U numLoops) { return setupSymmetricTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlg, cipherKeyLengthInBytes, NOT_USED, priority, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, syncMode, NULL, packetSize, bufferSizeInBytes, numBufferLists, numLoops, digestAppended_g); } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup an IPsec scenario where payload = IP packet, the IP header is not * encrypted thus requires an offset into the buffer to test. * * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupIpSecTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops) { return setupSymmetricTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlg, cipherKeyLengthInBytes, cipherOffset, CPA_CY_PRIORITY_HIGH, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, ASYNC, NULL, packetSize, BUFFER_SIZE_0, numBufferLists, numLoops, digestAppended_g); } EXPORT_SYMBOL(setupIpSecTest); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test with High Priority * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupAlgChainTestHP(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops) { return setupAlgChainTest(cipherAlg, cipherKeyLengthInBytes, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, CPA_CY_PRIORITY_HIGH, syncMode, packetSize, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, numBufferLists, numLoops); } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test with Normal Priority * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupAlgChainTestNP(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops) { return setupAlgChainTest(cipherAlg, cipherKeyLengthInBytes, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, CPA_CY_PRIORITY_NORMAL, syncMode, packetSize, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, numBufferLists, numLoops); } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test fixing High priority and async mode * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupAlgChainTestHPAsync(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops) { return setupAlgChainTest(cipherAlg, cipherKeyLengthInBytes, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, CPA_CY_PRIORITY_HIGH, ASYNC, packetSize, DEFAULT_CPA_FLAT_BUFFERS_PER_LIST, numBufferLists, numLoops); } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a alg chain test * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupAlgChainTestNestedMode( CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, nested_hash_test_setup_t *nestedModeSetupData, Cpa32U packetSize, Cpa32U numBufferLists, Cpa32U numLoops) { return setupSymmetricTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlg, cipherKeyLengthInBytes, NOT_USED, priority, hashAlg, CPA_CY_SYM_HASH_MODE_NESTED, authKeyLengthInBytes, chainOrder, syncMode, nestedModeSetupData, packetSize, BUFFER_SIZE_0, numBufferLists, numLoops, digestAppended_g); } cpa_sample_code_sym_perf_dp.c000066400000000000000000003461321503624047500365700ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /***************************************************************************** * @file cpa_sample_code_sym_perf_dp.c * * @defgroup sampleSymmetricDpPerf Symmetric Data Plane Performance code * * @ingroup sampleSymmetricDpPerf * * @description * This file contains the main symmetric Data Plane performance sample * code. * It is capable of performing all ciphers, all hashes, authenticated * hashes and algorithm chaining. Nested Hashes are not supported * * setup->numBuffLists, each bufferlist includes several flat buffers which * its size is equal to buffer size. The pre-allocated buffers are then * continuously looped until the numLoops is met. * Time stamping is started prior to the * Operation and is stopped when all callbacks have returned. * The packet size and algorithm to be tested is setup using the * setupSymmetricDpTest function. The framework is used to create the * threads which calls functions here to execute symmetric data plane * performance. *****************************************************************************/ #include "cpa_sample_code_sym_perf_dp.h" #include "qat_perf_utils.h" #include "icp_sal_poll.h" #include "busy_loop.h" #include "qat_perf_cycles.h" #include "qat_perf_sleeptime.h" #include "qat_perf_buffer_utils.h" #define REL_LOOP_MULTIPLIER (2) #define SYM_OPERATIONS_DEFAULT_POLLING_INTERVAL (16) Cpa32U symPollingInterval_g = SYM_OPERATIONS_DEFAULT_POLLING_INTERVAL; EXPORT_SYMBOL(symPollingInterval_g); /* define the distribution of the packet mix here we defined * 2 lots of 10 sizes later it is replicated into 100 buffers*/ static const Cpa32U packetMix[NUM_PACKETS_IMIX] = { BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_8992, BUFFER_SIZE_64, BUFFER_SIZE_1504}; extern volatile CpaBoolean digestAppended_g; extern int signOfLife; extern Cpa32U packageIdCount_g; extern int latency_single_buffer_mode; /* set to 1 for single buffer processing */ extern char *cpaStatusToString(CpaStatus status); /* for more readable debug */ extern CpaCySymCipherDirection getCipherDirection(void); /* For Backoff timer implementation for symmetric DataPlain */ extern volatile CpaBoolean backoff_timer_g; extern volatile CpaBoolean backoff_dynamic_g; extern uint32_t backoff_static_timer_g; extern CpaInstanceHandle *cyInstances_g; CpaStatus setSymPollingInterval(Cpa64U pollingInterval); CpaStatus printDigestAppend(CpaBoolean flag); CpaStatus printSymPollingInterval(void); void sampleSymmetricDpPerformance(single_thread_test_data_t *testSetup); /***************************************************************************** * * Internal Function Interfaces * *****************************************************************************/ /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Set the polling interval. The Polling interval is the number of successful * submissions before the driver is polled for responses * ***************************************************************************/ CpaStatus setSymPollingInterval(Cpa64U pollingInterval) { symPollingInterval_g = pollingInterval; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setSymPollingInterval); /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * print the digestAppend flag state * ***************************************************************************/ CpaStatus printDigestAppend(CpaBoolean flag) { PRINT("digestAppended_g %d\n", digestAppended_g); return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(printDigestAppend); /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Print the polling interval. The Polling interval is the number * of successful submissions before the driver is polled for responses * ***************************************************************************/ CpaStatus printSymPollingInterval(void) { PRINT("Symmetric Polling Interval: %u\n", symPollingInterval_g); return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(printSymPollingInterval); /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Poll the number of DP operations * ***************************************************************************/ static CpaStatus cyDpPollNumOperations(perf_data_t *pPerfData, CpaInstanceHandle instanceHandle, Cpa64U numOperations) { CpaStatus status = CPA_STATUS_FAIL; perf_cycles_t startCycles = 0, totalCycles = 0; CpaInstanceInfo2 info2 = { 0 }; Cpa32U freq = sampleCodeGetCpuFreq(); startCycles = sampleCodeTimestamp(); status = cpaCyInstanceGetInfo2(instanceHandle, &info2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 failed. (status = %d)\n", status); return CPA_STATUS_FAIL; } while (pPerfData->responses != numOperations) { if (CPA_TRUE == info2.isPolled) { coo_poll_dp_cy(pPerfData, instanceHandle, &status); if (CPA_STATUS_FAIL == status) { PRINT_ERR("Error polling instance\n"); return CPA_STATUS_FAIL; } } if (CPA_STATUS_RETRY == status) { AVOID_SOFTLOCKUP; } totalCycles = (sampleCodeTimestamp() - startCycles); if (totalCycles > 0) { do_div(totalCycles, freq); } if (totalCycles > SAMPLE_CODE_WAIT_DEFAULT) { PRINT_ERR("Timeout on polling remaining Operations\n"); return status; } } return CPA_STATUS_SUCCESS; } /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * calculate the pointer of digest result in the buffer list * digest result should be located in the end of Plaintext and * digest result should be align with block size of cipher. * Please see example as the following: @verbatim +--------+----------------------------------------------------+--------+----+ | | Ciphertext | Digest |Pad + +--------+----------------------------------------------------+--------+----+ <-FlatBuffer[0]-><-FlatBuffer[1]-><-FlatBuffer[2]-><-FlatBuffer[3]-> <- Buffer List -> @endverbatim * @param[in] packetSize Data packet size * @param[in] bufferSizeInByte buffer size in the flatbuffer of bufferlist * @param[in] blockSizeInBytes min block length of the cipher, Digest need to * align with it. * @param[in] pBufferList the pointer of Buffer list which store data and * comprised of flatbuffers. * *****************************************************************************/ static CpaPhysicalAddr symDpCalDigestAddress(Cpa32U packetSize, Cpa32U bufferSizeInByte, Cpa32U blockSizeInBytes, CpaPhysBufferList *pBufferList) { Cpa32U packsetSizePad = 0; Cpa32U digestOffset = 0; CpaPhysicalAddr pDigestResult = 0; Cpa32U indexBuffer = 0; Cpa32U numBuffers = pBufferList->numBuffers; /* check if packetSize is 0 */ if (bufferSizeInByte == 0) { pDigestResult = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)( pBufferList->flatBuffers[0].bufferPhysAddr + packetSize); } else if (packetSize % bufferSizeInByte == 0) { pDigestResult = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)( pBufferList->flatBuffers[numBuffers - 1].bufferPhysAddr + bufferSizeInByte); } else { /* since Digest address (pDigestResult) need to align with * blockSizeInBytes, we will check if packetSize is align with * blockSizeInBytes, * if not, padding will added after message */ if (packetSize % blockSizeInBytes != 0) { packsetSizePad = blockSizeInBytes - (packetSize % blockSizeInBytes); } /* calculate actual offset of digest result in flatbuffer*/ digestOffset = (packetSize + packsetSizePad) % bufferSizeInByte; /* calculate the which flat buffer store pDigestResult * pDigestResult will appended in the end of pData */ indexBuffer = (packetSize + packsetSizePad) / bufferSizeInByte; pDigestResult = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)( pBufferList->flatBuffers[indexBuffer].bufferPhysAddr + digestOffset); } return pDigestResult; } /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * calculate the pointer of TLS digest result in the buffer list * digest result should be located in the end of Plaintext and * digest result should be align with block size of cipher. *****************************************************************************/ static CpaPhysicalAddr symDpCalTLSDigestAddress(Cpa32U packetSize, Cpa32U headerSizeInByte, Cpa32U blockSizeInBytes, CpaPhysBufferList *pBufferList) { CpaPhysicalAddr pDigestResult = 0; Cpa32U numBuffers = pBufferList->numBuffers; /* In case of single flat buffer in the list, Digest * Address is Header + Cipher data Length */ pDigestResult = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)( pBufferList->flatBuffers[numBuffers - 1].bufferPhysAddr + packetSize + headerSizeInByte); return pDigestResult; } /** ***************************************************************************** * @ingroup sampleSymmetricPerf * * @description * initialize the digest buffer * *****************************************************************************/ static void symDpSetDigestBuffer(Cpa32U messageLenToCipherInBytes, Cpa32U digestLengthInBytes, Cpa8U value, CpaBufferList *pBufferList) { Cpa8U *pDigestResult = 0; Cpa32U indexBuffer = 0; Cpa32U i = 0; Cpa32U bufferSizeInByte = pBufferList->pBuffers[0].dataLenInBytes; /* all the rest of data including padding will initialized , * so ivLenInBytes is 1.*/ if (bufferSizeInByte == 0) { pDigestResult = (Cpa8U *)(pBufferList->pBuffers[0].pData + messageLenToCipherInBytes); /* reset the digest memory to 0 */ memset((void *)pDigestResult, value, digestLengthInBytes); } else { /* calculate the which flat buffer store pDigestResult * pDigestResult will appended in the end of pData */ indexBuffer = messageLenToCipherInBytes / bufferSizeInByte; pDigestResult = (Cpa8U *)(pBufferList->pBuffers[indexBuffer].pData + (messageLenToCipherInBytes % bufferSizeInByte)); /* reset the digest memory to 0 */ memset((void *)pDigestResult, value, (pBufferList->pBuffers[0].dataLenInBytes - messageLenToCipherInBytes % pBufferList->pBuffers[0].dataLenInBytes)); indexBuffer++; for (i = indexBuffer; i < pBufferList->numBuffers; i++) { memset((void *)(uintptr_t)pBufferList->pBuffers[i].pData, value, pBufferList->pBuffers[i].dataLenInBytes); } } } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Free memory allocated in the symmetricPerformOpDataSetup function * ***************************************************************************/ static void dpOpDataMemFree(CpaCySymDpOpData *pOpdata[], Cpa32U numBuffers) { Cpa32U k = 0; for (k = 0; k < numBuffers; k++) { if (NULL != pOpdata[k]) { if (NULL != pOpdata[k]->pIv) { qaeMemFreeNUMA((void **)&pOpdata[k]->pIv); } if (NULL != pOpdata[k]->pAdditionalAuthData) { qaeMemFreeNUMA((void **)&pOpdata[k]->pAdditionalAuthData); } qaeMemFreeNUMA((void **)&pOpdata[k]); } /*end of if(NULL != pOpdata[k]) */ } /* End of main loop */ } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Free memory allocated in the sampleSymmetricDpPerform function * ***************************************************************************/ static void symDpPerformMemFree(symmetric_test_params_t *setup, CpaBufferList **ppSrcBuffListArray, CpaPhysBufferList **ppSrcPyhsBuffListArray, CpaCySymDpOpData **ppOpData, CpaCySymDpSessionCtx *pSessionCtx, Cpa8U *authKey, Cpa8U *cipherKey, Cpa32U *packetSize) { Cpa32U m = 0; /*free bufferLists, flatBuffers and data*/ if (NULL != ppOpData) { dpOpDataMemFree(ppOpData, setup->numBuffLists); qaeMemFreeNUMA((void **)&ppOpData); } /* free session memory - calling code is responsible for * removing the sessions */ if (NULL != pSessionCtx) { if (reliability_g) { if (NULL != *pSessionCtx) { for (m = 0; m < setup->numSessions; m++) { qaeMemFreeNUMA((void **)&pSessionCtx[m]); } } } qaeMemFree((void **)&pSessionCtx); } /* Free session array , Operation Data, buffer List array*/ if (NULL != cipherKey) { qaeMemFree((void **)&cipherKey); } if (NULL != authKey) { qaeMemFree((void **)&authKey); } if (NULL != packetSize) { qaeMemFree((void **)&packetSize); } if ((NULL != ppSrcBuffListArray) && (NULL != *ppSrcBuffListArray)) { dpSampleFreeBuffers(ppSrcBuffListArray, ppSrcPyhsBuffListArray, setup->numBuffLists, ppSrcBuffListArray[0]->numBuffers); qaeMemFreeNUMA((void **)&ppSrcBuffListArray); } if (NULL != ppSrcPyhsBuffListArray) { qaeMemFreeNUMA((void **)&ppSrcPyhsBuffListArray); } } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Callback function for symmetric perform operation. * Response will increased 1 after each symmetric operation finished. * When the number of response is equal to the number of operations, * it will release one semaphore for async operation. *****************************************************************************/ static void symDpPerformCallback(CpaCySymDpOpData *pOpData, CpaStatus status, CpaBoolean verifyResult) { /* pCallbacktag in the pOpData structure is used to store * index of to the perf_data_t associated the thread * */ perf_data_t *pPerfData = pOpData->pCallbackTag; pPerfData->responses++; if (latency_enable) { /* Did we setup the array pointer? */ if (NULL == pPerfData->response_times) { PRINT_ERR("pPerfData response_times is null\n"); return; } /* Have we sampled too many buffer operations? */ if (pPerfData->latencyCount > MAX_LATENCY_COUNT) { PRINT_ERR("pPerfData latencyCount > MAX_LATENCY_COUNT\n"); return; } /* Is this the buffer we calculate latency on? * And have we calculated too many for array? */ if (pPerfData->responses == pPerfData->nextCount) { int i = pPerfData->latencyCount; /* Now get the end timestamp - before any print outs */ pPerfData->response_times[i] = sampleCodeTimestamp(); pPerfData->nextCount += pPerfData->countIncrement; if (latency_debug) PRINT("%s: responses=%u, latencyCount=%d, end[i]:%llu, " "start[i]:%llu, nextCount=%u\n", __FUNCTION__, (unsigned int)pPerfData->responses, i, pPerfData->response_times[i], pPerfData->start_times[i], pPerfData->nextCount); pPerfData->latencyCount++; } } /*if we have received the pre-set numOperations, then get the clock cycle * as a timestamp and post the Semaphore to release parent thread*/ if (pPerfData->numOperations == pPerfData->responses) { pPerfData->endCyclesTimestamp = sampleCodeTimestamp(); } } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Wait for in-flight request and removes symmetric session * *****************************************************************************/ static CpaStatus symmetricDpRemoveSession(CpaInstanceHandle instanceHandle, CpaCySymDpSessionCtx pSessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; #if CY_API_VERSION_AT_LEAST(2, 2) /* In ASYNC mode we need to wait for * all pending request to be finished. */ { CpaBoolean sessionInUse = CPA_FALSE; do { cpaCySymSessionInUse(pSessionCtx, &sessionInUse); if (sessionInUse == CPA_TRUE) { sleepNano(REMOVE_SESSION_WAIT * 1000); } else { break; } } while (1); } #endif /* Free up resources allocated */ status = cpaCySymDpRemoveSession(instanceHandle, pSessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Removal of session failed with status %d\n", status); status = CPA_STATUS_FAIL; } return status; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Create a symmetric session * *****************************************************************************/ static CpaStatus symmetricDpSetupSession(CpaCySymDpCbFunc pSymCb, Cpa8U *pCipherKey, Cpa8U *pAuthKey, CpaCySymDpSessionCtx *pSession, CpaBoolean digestVerify, CpaBoolean digestIsEncrypted, symmetric_test_params_t *setup ) { Cpa32U sessionCtxSizeInBytes = 0; #if CPA_CY_API_VERSION_NUM_MINOR >= 8 Cpa32U sessionCtxDynamicSizeInBytes = 0; #endif CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymDpSessionCtx pLocalSession = NULL; Cpa32U cipherKeyLen = 0; Cpa32U authKeyLen = 0; Cpa32U node = 0; status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /*set the cipher and authentication key len*/ cipherKeyLen = setup->setupData.cipherSetupData.cipherKeyLenInBytes; authKeyLen = setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes; /*generate a random cipher and authentication key*/ generateRandomData(pCipherKey, cipherKeyLen); generateRandomData(pAuthKey, authKeyLen); /*cipher setup only needs to be set for alg chaining, cipher, AES-GCM * and AES-CCM*/ setup->setupData.cipherSetupData.pCipherKey = pCipherKey; /*hash setup only needs to be set for hash, AES-GCM * and AES-CCM*/ setup->setupData.hashSetupData.authModeSetupData.authKey = pAuthKey; /*hash algorithm initialization*/ if (CPA_CY_SYM_HASH_AES_GMAC == setup->setupData.hashSetupData.hashAlgorithm) { setup->setupData.hashSetupData.authModeSetupData.authKey = NULL; setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes = 0; } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == setup->setupData.hashSetupData.hashAlgorithm #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || ((CPA_CY_SYM_HASH_ZUC_EIA3 == setup->setupData.hashSetupData.hashAlgorithm) && (KEY_SIZE_128_IN_BYTES == setup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes)) #endif ) { setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes = KEY_SIZE_128_IN_BYTES; } else { /* For AES-CCM, AAD(additional auth data) is optional.*/ setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes = 0; } #if CY_API_VERSION_AT_LEAST(3, 0) /* Set verifyDigest for performance cases. */ if (!reliability_g && setup->setupData.cipherSetupData.cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT && setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { setup->setupData.verifyDigest = CPA_TRUE; } else #endif { setup->setupData.verifyDigest = CPA_FALSE; } /*this is the original API to get the required context size, we show the * function used here, but we only use the size for the older version of the * API get size for memory allocation*/ status = cpaCySymDpSessionCtxGetSize( setup->cyInstanceHandle, &setup->setupData, &sessionCtxSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetSize error, status: %d", status); return status; } #if CPA_CY_API_VERSION_NUM_MINOR >= 8 /*get dynamic context size*/ status = cpaCySymDpSessionCtxGetDynamicSize(setup->cyInstanceHandle, &setup->setupData, &sessionCtxDynamicSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetDynamicSize error, status: %d", status); return status; } /* * allocate session memory using dynamic context size */ sessionCtxSizeInBytes = sessionCtxDynamicSizeInBytes; #endif pLocalSession = qaeMemAllocNUMA(sessionCtxSizeInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pLocalSession) { PRINT_ERR("Could not allocate pLocalSession memory\n"); return CPA_STATUS_FAIL; } /*zero session memory*/ memset(pLocalSession, 0, sessionCtxSizeInBytes); /* * init session - pLocalSession will contain the session context */ status = cpaCySymDpInitSession( setup->cyInstanceHandle, &setup->setupData, pLocalSession); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymInitSession error, status: %d\n", status); qaeMemFreeNUMA((void **)&pLocalSession); return status; } *pSession = pLocalSession; #if CPA_CY_API_VERSION_NUM_MINOR >= 8 #endif /* Register asynchronous callback with instance handle*/ status = cpaCySymDpRegCbFunc(setup->cyInstanceHandle, pSymCb); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpRegCbFunc error, status: %d\n", status); qaeMemFreeNUMA((void **)&pLocalSession); return status; } return status; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Setup symmetric operation data * ***************************************************************************/ static CpaStatus symmetricDpPerformOpDataSetup( CpaCySymDpSessionCtx *pSessionCtx, Cpa32U *pPacketSize, CpaCySymDpOpData *pOpdata[], symmetric_test_params_t *setup, CpaPhysBufferList *ppSrcBuffListArray[], CpaPhysBufferList *ppDestBuffListArray[]) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U createCount = 0; Cpa32U node = 0; /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return status; } /*for each bufferList set the symmetric operation data*/ for (createCount = 0; createCount < setup->numBuffLists; createCount++) { /* allocate op data structure for each entry*/ pOpdata[createCount] = qaeMemAllocNUMA(sizeof(CpaCySymDpOpData), node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[createCount]) { PRINT_ERR("Could not allocate Opdata memory at index %u\n", createCount); dpOpDataMemFree(pOpdata, createCount); return CPA_STATUS_FAIL; } /* Zero initialize Op data structure*/ memset(pOpdata[createCount], 0, sizeof(CpaCySymDpOpData)); /* * Initialize Op data structure with different sessions : * multiple session */ pOpdata[createCount]->sessionCtx = pSessionCtx[createCount % setup->numSessions]; /* Starting point for cipher processing */ pOpdata[createCount]->cryptoStartSrcOffsetInBytes = setup->cryptoSrcOffset; /* This should be passed in as 13 bytes in practice for a standard TLS packet using 2 flatbuffers in a bufferList. */ /* messageLenToCipherInBytes and messageLenToHashInBytes do not have * to be the same. In this code we want to either hash the entire buffer * or encrypt the entire buffer, depending on the SymOperation. * For Alg Chaining, depending on the chain order, for HashThenCipher, * the digest will be the hash of the unencrypted buffer and then we * cipher the buffer. OR for CipherThenHash, we cipher the buffer, then * the perform the hash on the encrypted buffer, so that the digest is * the digest of the encrypted data*/ if (setup->isTLS) { /* messageLenToCipherInBytes and messageLenToHashInBytes do not have * to be the same.*/ pOpdata[createCount]->messageLenToCipherInBytes = setup->flatBufferSizeInBytes - setup->cryptoSrcOffset; pOpdata[createCount]->messageLenToHashInBytes = setup->cryptoSrcOffset + pPacketSize[createCount]; } else { pOpdata[createCount]->messageLenToCipherInBytes = pPacketSize[createCount] - setup->cryptoSrcOffset; pOpdata[createCount]->messageLenToHashInBytes = pPacketSize[createCount]; } /* Starting point for hash processing */ pOpdata[createCount]->hashStartSrcOffsetInBytes = HASH_OFFSET_BYTES; pOpdata[createCount]->pAdditionalAuthData = NULL; /* In GMAC mode, there is no message to Cipher */ if (CPA_CY_SYM_HASH_AES_GMAC == setup->setupData.hashSetupData.hashAlgorithm) { pOpdata[createCount]->cryptoStartSrcOffsetInBytes = 0; pOpdata[createCount]->messageLenToCipherInBytes = 0; } /*these only need to be set for HASH_SNOW3G_UIA2*/ if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == setup->setupData.hashSetupData.hashAlgorithm #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || ((CPA_CY_SYM_HASH_ZUC_EIA3 == setup->setupData.hashSetupData.hashAlgorithm) && (KEY_SIZE_128_IN_BYTES == setup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes)) #endif ) { pOpdata[createCount]->pAdditionalAuthData = qaeMemAllocNUMA(KEY_SIZE_128_IN_BYTES, node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[createCount]->pAdditionalAuthData) { PRINT_ERR("Could not allocate additional auth data index %d\n", createCount); dpOpDataMemFree(pOpdata, createCount); return CPA_STATUS_FAIL; } memset(pOpdata[createCount]->pAdditionalAuthData, SYM_AUTH_INIT_VALUE, KEY_SIZE_128_IN_BYTES); } /*End of if(CPA_CY_SYM_HASH_SNOW3G_UIA2 == ... */ else if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { /*must allocate to the nearest block size required (above 18 bytes)*/ pOpdata[createCount]->pAdditionalAuthData = qaeMemAllocNUMA( AES_CCM_MIN_AAD_ALLOC_LENGTH, node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[createCount]->pAdditionalAuthData) { PRINT_ERR("Could not allocate additional auth data index %u\n", createCount); dpOpDataMemFree(pOpdata, createCount); return CPA_STATUS_FAIL; } memset(pOpdata[createCount]->pAdditionalAuthData, 0, AES_CCM_MIN_AAD_ALLOC_LENGTH); } /* End of else if(setup->setupData.cipherSetupData.cipherAlgorithm .*/ /* in this code we always allocate the IV, but it is not always used * this reduces the if/else logic when trying to cater for as many * symmetric crypto options as possible*/ pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_8_BYTE_BLOCK_CIPHER; /*set IV len depending on what we are testing*/ if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CBC || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CTR || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_SNOW3G_UEA2 || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_F8 || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_XTS #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_ZUC_EEA3 #endif || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_SM4_CBC || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_SM4_CTR) { if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_ZUC_EEA3 && setup->setupData.cipherSetupData.cipherKeyLenInBytes == KEY_SIZE_256_IN_BYTES) { pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_24_BYTE_BLOCK_CIPHER; } else { pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_16_BYTE_BLOCK_CIPHER; } /* If 0 use default else use value passed. */ if (0 != setup->ivLength) { pOpdata[createCount]->ivLenInBytes = setup->ivLength; } } else if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) { pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_16_BYTE_GCM; /* If 0 use default else use value passed. */ if (0 != setup->ivLength) { pOpdata[createCount]->ivLenInBytes = setup->ivLength; } } else if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_CHACHA) { pOpdata[createCount]->ivLenInBytes = IV_LEN_FOR_12_BYTE_CHACHA; /* If 0 use default else use value passed. */ if (0 != setup->ivLength) { pOpdata[createCount]->ivLenInBytes = setup->ivLength; } } /*allocate NUMA aware aligned memory for IV*/ pOpdata[createCount]->pIv = qaeMemAllocNUMA( pOpdata[createCount]->ivLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[createCount]->pIv) { PRINT_ERR("IV is null\n"); dpOpDataMemFree(pOpdata, createCount); return CPA_STATUS_FAIL; } memset( pOpdata[createCount]->pIv, 0, pOpdata[createCount]->ivLenInBytes); if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { /*Although the IV data length for CCM must be 16 bytes, The nonce length must be between 7 and 13 inclusive*/ pOpdata[createCount]->ivLenInBytes = AES_CCM_DEFAULT_NONCE_LENGTH; } /*if we are testing HASH or Alg Chaining, set the location to place * the digest result, this space was allocated in * sampleSymmetricDpPerform function*/ if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { if (setup->isTLS) { pOpdata[createCount]->digestResult = symDpCalTLSDigestAddress(pPacketSize[createCount], setup->cryptoSrcOffset, IV_LEN_FOR_16_BYTE_BLOCK_CIPHER, ppSrcBuffListArray[createCount]); } else { pOpdata[createCount]->digestResult = symDpCalDigestAddress(pPacketSize[createCount], setup->flatBufferSizeInBytes, IV_LEN_FOR_16_BYTE_BLOCK_CIPHER, ppSrcBuffListArray[createCount]); } } if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { /*digestAppend is always true for CCM*/ pOpdata[createCount]->digestResult = (CpaPhysicalAddr)CPA_TRUE; /*generate a random IV*/ generateRandomData( &(pOpdata[createCount]->pIv[SYM_DP_LV_OFFSET_CCM]), pOpdata[createCount]->ivLenInBytes); /*API requires copying of the nonce to the first byte of the AAD*/ memcpy(&(pOpdata[createCount] ->pAdditionalAuthData[SYM_DP_LV_OFFSET_CCM]), &(pOpdata[createCount]->pIv[SYM_DP_LV_OFFSET_CCM]), pOpdata[createCount]->ivLenInBytes); } else { /*generate a random IV*/ generateRandomData(pOpdata[createCount]->pIv, pOpdata[createCount]->ivLenInBytes); } /* initialize iv structure */ if (0 != pOpdata[createCount]->ivLenInBytes) { pOpdata[createCount]->iv = (CpaPhysicalAddr)( SAMPLE_CODE_UINT)virtAddrToDevAddr(pOpdata[createCount]->pIv, setup->cyInstanceHandle, CPA_ACC_SVC_TYPE_CRYPTO); } else { pOpdata[createCount]->iv = (CpaPhysicalAddr)(uintptr_t)NULL; } /* the physical address of additionalAuthData */ if (NULL != pOpdata[createCount]->pAdditionalAuthData) { pOpdata[createCount]->additionalAuthData = (CpaPhysicalAddr)(SAMPLE_CODE_UINT)virtAddrToDevAddr( pOpdata[createCount]->pAdditionalAuthData, setup->cyInstanceHandle, CPA_ACC_SVC_TYPE_CRYPTO); } else { pOpdata[createCount]->additionalAuthData = (CpaPhysicalAddr)(uintptr_t)NULL; } /* if No buffer size specified, default value is flat buffers * (no buffer chaining) */ if (0 == setup->flatBufferSizeInBytes) { /* Set physical address for srcbuffer */ pOpdata[createCount]->srcBuffer = ppSrcBuffListArray[createCount]->flatBuffers->bufferPhysAddr; /* Set length of srcbuffer */ pOpdata[createCount]->srcBufferLen = ppSrcBuffListArray[createCount]->flatBuffers->dataLenInBytes; /* Set physical address for dstBuffer */ pOpdata[createCount]->dstBuffer = ppDestBuffListArray[createCount]->flatBuffers->bufferPhysAddr; /* Set length of dstBuffer */ pOpdata[createCount]->dstBufferLen = ppDestBuffListArray[createCount]->flatBuffers->dataLenInBytes; if (setup->setupData.digestIsAppended == CPA_FALSE) { if (setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { pOpdata[createCount]->srcBufferLen -= setup->setupData.hashSetupData.digestResultLenInBytes; pOpdata[createCount]->dstBufferLen -= setup->setupData.hashSetupData.digestResultLenInBytes; } } } else { /* Set physical address for srcbuffer */ pOpdata[createCount]->srcBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( (SAMPLE_CODE_UINT *)(uintptr_t) ppSrcBuffListArray[createCount], setup->cyInstanceHandle, CPA_ACC_SVC_TYPE_CRYPTO); /* Set length of srcbuffer */ pOpdata[createCount]->srcBufferLen = CPA_DP_BUFLIST; /* Set physical address for dstBuffer */ pOpdata[createCount]->dstBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( (SAMPLE_CODE_UINT *)(uintptr_t) ppDestBuffListArray[createCount], setup->cyInstanceHandle, CPA_ACC_SVC_TYPE_CRYPTO); /* Set length of dstBuffer */ pOpdata[createCount]->dstBufferLen = CPA_DP_BUFLIST; } /* Instance handle */ pOpdata[createCount]->instanceHandle = setup->cyInstanceHandle; /* the physical address of this structure */ pOpdata[createCount]->thisPhys = (CpaPhysicalAddr)virtAddrToDevAddr(pOpdata[createCount], setup->cyInstanceHandle, CPA_ACC_SVC_TYPE_CRYPTO); /* Set response : initialize pCallbackTag with perf_data_t to * callback operation */ pOpdata[createCount]->pCallbackTag = setup->performanceStats; } /* End of for main loop*/ return CPA_STATUS_SUCCESS; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * symmetric encryption operations enqueued to be performed later * The request is submitted to be performed by invoking the function * @ref cpaCySymDpPerformOpNow. * ***************************************************************************/ static CpaStatus symDpPerformEnqueueOp(symmetric_test_params_t *setup, Cpa32U numOfLoops, CpaCySymDpOpData **ppOpData, CpaBufferList **ppSrcBuffListArray, CpaCySymCipherDirection cipherDirection) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U outsideLoopCount = 0; Cpa32U insideLoopCount = 0; Cpa32U maxRequestNum = 0; perf_data_t *pSymData = NULL; Cpa64U numOps = 0; Cpa64U nextPoll = symPollingInterval_g; CpaBoolean performNowFlag = CPA_TRUE; CpaInstanceInfo2 *instanceInfo = NULL; /* backoff timer parameters initialization */ Cpa32U k = 0; Cpa32U backoff = 0; Cpa32U submissions = 0; Cpa32U i = 0; perf_cycles_t *request_submit_start = NULL; perf_cycles_t *request_respnse_time = NULL; const Cpa32U request_mem_sz = sizeof(perf_cycles_t) * MAX_LATENCY_COUNT; Cpa32U busyLoopValue = 0; Cpa32U staticAssign = 0, busyLoopCount = 0, j = 0; perf_cycles_t startBusyLoop = 0, endBusyLoop = 0, totalBusyLoopCycles = 0; CpaStatus pollStatus = CPA_STATUS_SUCCESS; /* Check if setup is NULL */ if (NULL == setup) { PRINT_ERR("parameter setup is NULL\n"); status = CPA_STATUS_FAIL; return status; } /* Capture busy loop before memset of performanceStats */ busyLoopValue = setup->performanceStats->busyLoopValue; /* Initialize perform data structure with setup->performanceStats*/ pSymData = setup->performanceStats; /* Zero initialize pSymData*/ saveClearRestorePerfStats(pSymData); instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); return CPA_STATUS_FAIL; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } pSymData->packageId = instanceInfo->physInstId.packageId; /*preset the number of ops we plan to submit*/ pSymData->numOperations = (Cpa64U)setup->numBuffLists * numOfLoops; coo_init(pSymData, pSymData->numOperations); /* reset number of response to 0, sync sym operations within outside loop*/ pSymData->responses = 0; pSymData->retries = 0; if (latency_enable) { if (pSymData->numOperations > LATENCY_SUBMISSION_LIMIT) { PRINT_ERR("Error max submissions for latency must be <= %d\n", LATENCY_SUBMISSION_LIMIT); return CPA_STATUS_FAIL; } request_submit_start = qaeMemAlloc(request_mem_sz); request_respnse_time = qaeMemAlloc(request_mem_sz); if (request_submit_start == NULL || request_respnse_time == NULL) { PRINT_ERR("Failed to allocate memory for submission and response " "times\n"); qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); return CPA_STATUS_FAIL; } memset(request_submit_start, 0, request_mem_sz); memset(request_respnse_time, 0, request_mem_sz); /* Calculate how many buffer submissions between latency measurements.. */ pSymData->countIncrement = (Cpa32U)pSymData->numOperations / MAX_LATENCY_COUNT; /* .. and set the next trigger count to this */ pSymData->nextCount = pSymData->countIncrement; /* How many latency measurements of the MAX_LATENCY_COUNT have been * taken so far */ pSymData->latencyCount = 0; /* Completion routine sets end times in the array indirectly */ pSymData->response_times = request_respnse_time; pSymData->start_times = request_submit_start; /* for debug */ if (latency_debug) PRINT("LATENCY_CODE: Initial nextCount %u, countIncrement %u\n", pSymData->nextCount, pSymData->countIncrement); } /* Check if numRequests: * the number of requests should no more than numbuffer*/ if (setup->numRequests > setup->numBuffLists) { maxRequestNum = setup->numBuffLists; PRINT_ERR("parameter numRequests is error %d\n", setup->numRequests); } else { maxRequestNum = setup->numRequests; } /* CCM algorithm, initialize digest buffer to 0 for encryption */ if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { for (outsideLoopCount = 0; outsideLoopCount < setup->numBuffLists; outsideLoopCount++) { if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT != cipherDirection) { /* Initialize digest buffer to 0 */ symDpSetDigestBuffer( ppOpData[outsideLoopCount]->messageLenToCipherInBytes, AES_CCM_DIGEST_LENGTH_IN_BYTES, 0, ppSrcBuffListArray[outsideLoopCount]); } } /* End of outsideLoopCount */ } /* End of if which cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CCM */ /* this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Get the time, collect this only for the first * request, the callback collects it for the last */ pSymData->startCyclesTimestamp = sampleCodeTimestamp(); /* The outside for-loop will loop around the preallocated * buffer list array*/ for (outsideLoopCount = 0; outsideLoopCount < numOfLoops; outsideLoopCount++) { /* This inner for-loop loops around the number of Buffer Lists * that have been preallocated. Once the array has completed * exit to the outer loop to move on the next iteration of the * preallocated loop. */ for (insideLoopCount = 0; insideLoopCount < setup->numBuffLists; insideLoopCount++) { /* Check the submitted request is equal to max request number or * if we are submitting the last packet * Then perform queued requests with PerformOpNowFlag is CPA_TRUE */ if ((insideLoopCount % maxRequestNum == 0) || ((insideLoopCount == setup->numBuffLists - 1) && (outsideLoopCount == numOfLoops - 1))) { performNowFlag = CPA_TRUE; } else { performNowFlag = CPA_FALSE; } do { if (latency_enable) { // Ensures we get a callback for each submissions performNowFlag = CPA_TRUE; if (submissions + 1 == pSymData->nextCount) { int i = pSymData->latencyCount; /* When this buffer has been processed the 'submissions' * count will be incremented and checked in the * symDpPerformCallback() * routine. So we grab it's start time now. */ if (latency_debug) PRINT("%s: status=%s submissions=%u, nextCount=%u, " "latencyCount=%d\n", __FUNCTION__, cpaStatusToString(status), submissions, pSymData->nextCount, i); /* Must do this after any print outs */ /* NOTE: Will be overwritten if CPA_STATUS_RETRY */ request_submit_start[pSymData->latencyCount] = sampleCodeTimestamp(); } } coo_req_start(pSymData); /* Enqueue a single symmetric crypto request, perform later*/ status = cpaCySymDpEnqueueOp(ppOpData[insideLoopCount], performNowFlag); coo_req_stop(pSymData, status); /* When cpaCySymDpEnqueueOp return CPA_STATUS_RETRY, perform * cpaCySymDpPerformOpNow to clear those requests in the queue, * and pSymData->retries will increase 1 * also re-schedule thread and wait for finishing operation. */ if (CPA_STATUS_RETRY == status) { pSymData->retries++; if (backoff_timer_g && backoff_dynamic_g) { /* * Backoff a bit if submission was unsuccessful */ for (k = 1; k <= backoff; k++) { /* * do nothing */ __asm__ volatile("nop"); } /* * increase the backoff interval after the unsuccessful * submission. * if the backoff is too big, set it 0 (this is done for * the large packets * as they keep device busy and backoff could became * unnecessary long) */ if (backoff < SYM_BACKOFF_TIMER_MAX) { backoff += SYM_BACKOFF_STEP_FORWARD; } else { backoff = 0; } } else { /* if requested just to wait certain number of busy * loop cycles (static timer) */ if (backoff_timer_g) { for (k = 1; k <= backoff_static_timer_g; k++) { /* * do nothing */ __asm__ volatile("nop"); } } } if (CPA_TRUE == instanceInfo->isPolled) { coo_poll_dp_cy( pSymData, setup->cyInstanceHandle, &pollStatus); } nextPoll = numOps + symPollingInterval_g; AVOID_SOFTLOCKUP; } else { if (backoff_timer_g && backoff_dynamic_g) { /* decrease the backoff value after the successful * submission */ if (backoff > SYM_BACKOFF_STEP_BACK) { backoff -= SYM_BACKOFF_STEP_BACK; } } } } while (CPA_STATUS_RETRY == status); if (performNowFlag && CPA_CC_BUSY_LOOPS == iaCycleCount_g) { busyLoop(busyLoopValue, &staticAssign); busyLoopCount++; } /* if cpaCySymDpEnqueueOp operation return non-success, * break the inside loop directly */ if (CPA_STATUS_SUCCESS != status) { break; } if (latency_enable) { /* Another buffer has been submitted to the accelerator */ submissions++; /* Have we been requested to process one buffer at a time. This * will result in no retries and so the best latency times. */ if (latency_single_buffer_mode != 0) { /* Must now wait until this buffer is processed by the CPM */ while (pSymData->responses != submissions) { if (CPA_TRUE == instanceInfo->isPolled) { /* Keep polling until compression of the buffer * completes * and dcPerformCallback() increments * perfData->responses */ icp_sal_CyPollDpInstance(setup->cyInstanceHandle, 0); } AVOID_SOFTLOCKUP; } } } /*If reach the limitation, * system will poll all requests in the queue*/ ++numOps; if (numOps == nextPoll) { if (CPA_TRUE == instanceInfo->isPolled) { coo_poll_dp_cy( pSymData, setup->cyInstanceHandle, &pollStatus); } nextPoll = numOps + symPollingInterval_g; } } /* End of inside Loop */ /* if status != CPA_STATUS_SUCCESS, break the out loop directly */ if (CPA_STATUS_SUCCESS != status) { break; } } /* End of outside Loop */ /* When the callback returns it will increment the responses * counter and test if its equal to numBuffLists, in that * case all responses have been successfully received. */ if (CPA_STATUS_SUCCESS == status) { /* ** Now need to wait for all the in-flight Requests. */ status = cyDpPollNumOperations( pSymData, setup->cyInstanceHandle, pSymData->numOperations); } if (latency_enable) { if (latency_debug) PRINT("%s: Calculating min, max and ave latencies...\n", __FUNCTION__); pSymData->minLatency = MAX_LATENCY_LIMIT; /* Will be less than this */ pSymData->maxLatency = 0; /* Will be more than this */ /* Let's accumulate in 'aveLatency' all the individual 'latency' * times. Typically, there should be MAX_LATENCY_COUNT of these. * We also calculate min/max so we can get a sense of the variance. */ for (i = 0; i < pSymData->latencyCount; i++) { perf_cycles_t latency = pSymData->response_times[i] - request_submit_start[i]; pSymData->aveLatency += latency; if (latency < pSymData->minLatency) pSymData->minLatency = latency; if (latency > pSymData->maxLatency) pSymData->maxLatency = latency; if (latency_debug) PRINT("%d, end[i]:%llu, start[i]:%llu, min:%llu, ave:%llu, " "max:%llu\n", i, pSymData->response_times[i], request_submit_start[i], pSymData->minLatency, pSymData->aveLatency, pSymData->maxLatency); } if (pSymData->latencyCount > 0) { /* Then scale down this accumulated value to get the average. * This will be reported by dcPrintStats() at the end of the test */ do_div(pSymData->aveLatency, pSymData->latencyCount); } qaeMemFree((void **)&request_respnse_time); qaeMemFree((void **)&request_submit_start); } if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { pSymData->busyLoopValue = busyLoopValue; pSymData->busyLoopCount = busyLoopCount; pSymData->totalBusyLoopCycles = totalBusyLoopCycles; busyLoopTimeStamp(); startBusyLoop = busyLoopTimeStamp(); for (j = 0; j < busyLoopCount; j++) { busyLoop(busyLoopValue, &staticAssign); } endBusyLoop = busyLoopTimeStamp(); setup->performanceStats->totalBusyLoopCycles = endBusyLoop - startBusyLoop; setup->performanceStats->offloadCycles = (setup->performanceStats->endCyclesTimestamp - setup->performanceStats->startCyclesTimestamp) - setup->performanceStats->totalBusyLoopCycles; if (setup->performanceStats->responses == 0) { PRINT_ERR("The response count is 0\n"); } else { do_div(setup->performanceStats->offloadCycles, setup->performanceStats->responses); } } coo_average(pSymData); coo_deinit(pSymData); qaeMemFree((void **)&instanceInfo); return status; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Enqueue multiple requests with one operation, perform later * ***************************************************************************/ static CpaStatus symDpPerformEnqueueOpBatch( symmetric_test_params_t *setup, Cpa32U numOfLoops, CpaCySymDpOpData **ppOpData, CpaBufferList **ppSrcBuffListArray, CpaCySymCipherDirection cipherDirection) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U outsideLoopCount = 0; Cpa32U insideLoopCount = 0; Cpa32U batchCount = 0; Cpa32U maxBatchNum = 0; Cpa32U maxRequestNum = 0; Cpa32U queueRequestNum = 0; CpaBoolean performNow = CPA_FALSE; perf_data_t *pSymData = NULL; Cpa32U numOps = 0; CpaInstanceInfo2 *instanceInfo = NULL; /* Check if setup is NULL */ if (NULL == setup) { PRINT_ERR("parameter setup is NULL\n"); status = CPA_STATUS_FAIL; return status; } /* Initialize perform data structure with setup->performanceStats*/ pSymData = setup->performanceStats; saveClearRestorePerfStats(pSymData); instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); return CPA_STATUS_FAIL; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&instanceInfo); return CPA_STATUS_FAIL; } pSymData->packageId = instanceInfo->physInstId.packageId; /*preset the number of ops we plan to submit*/ pSymData->numOperations = (Cpa64U)setup->numBuffLists * numOfLoops; /* reset number of response to 0, sync sym operations within outside * loop*/ pSymData->responses = 0; pSymData->retries = 0; /* Check if numRequests: number of requests should no more than numbuffer*/ if (setup->numRequests > setup->numBuffLists) { maxRequestNum = setup->numBuffLists; PRINT_ERR("parameter numRequests is error %d\n", setup->numRequests); } else { maxRequestNum = setup->numRequests; } /* Check if numOpDpBatch:number of Batch Op should no more than numbuffer*/ if (setup->numOpDpBatch > setup->numBuffLists) { maxBatchNum = setup->numBuffLists; PRINT_ERR("parameter numOpDpBatch is error %d\n", setup->numOpDpBatch); } else { maxBatchNum = setup->numOpDpBatch; } /* Check if numOpDpBatch: numOpDpBatch should no more than numRequests*/ if (maxBatchNum > maxRequestNum) { maxBatchNum = maxRequestNum; PRINT_ERR("parameter numOpDpBatch %d is more than numRequests %d\n", setup->numOpDpBatch, setup->numRequests); } /* CCM algorithm, initialize digest buffer to 0 when encrypt */ if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { for (outsideLoopCount = 0; outsideLoopCount < setup->numBuffLists; outsideLoopCount++) { if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT != cipherDirection) { symDpSetDigestBuffer( ppOpData[outsideLoopCount]->messageLenToCipherInBytes, AES_CCM_DIGEST_LENGTH_IN_BYTES, 0, ppSrcBuffListArray[outsideLoopCount]); } } /* End of outsideLoopCount */ } /* End of if which cipherAlgorithm = CPA_CY_SYM_CIPHER_AES_CCM */ /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Get the time, collect this only for the first * request, the callback collects it for the last */ pSymData->startCyclesTimestamp = sampleCodeTimestamp(); /*The outside for-loop will loop around the preallocated buffer list array*/ for (outsideLoopCount = 0; outsideLoopCount < numOfLoops; outsideLoopCount++) { /* This inner for-loop loops around the number of Buffer Lists * that have been preallocated. Once the array has completed- * exit to the outer loop to move on the next iteration of the * preallocated loop. */ insideLoopCount = 0; queueRequestNum = 0; while (insideLoopCount < setup->numBuffLists) { /* Calculate the number of request for batch operation */ if ((insideLoopCount + maxBatchNum) >= setup->numBuffLists) { batchCount = setup->numBuffLists - insideLoopCount; /* since it's last batch op in the inside loop, * all batch operation need to perform directly */ performNow = CPA_TRUE; } else { batchCount = maxBatchNum; performNow = CPA_FALSE; } /* make sure that queued requests is no more than maxRequestNum*/ if ((queueRequestNum + batchCount) >= maxRequestNum) { batchCount = maxRequestNum - queueRequestNum; /* current queued requests is more than request number * which allowed to be queued, * all batch operations need to perform directly */ performNow = CPA_TRUE; queueRequestNum = 0; } else { /* update request number in the queue */ queueRequestNum += batchCount; } /* Perform cpaCySymDpEnqueueOpBatch */ do { status = cpaCySymDpEnqueueOpBatch( batchCount, &ppOpData[insideLoopCount], performNow); /* When cpaCySymDpEnqueueOp return CPA_STATUS_RETRY, * perform cpaCySymDpPerformOpNow to clear those requests * in the queue,and pSymData->retries will increase 1 * also re-schedule thread and wait for finishing operation. */ if (CPA_STATUS_RETRY == status) { setup->performanceStats->retries++; AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); /* if status isn't CPA_STATUS_SUCCESS, * break the inside loop directly */ if (CPA_STATUS_SUCCESS != status) { break; } /* update insideLoopCount */ insideLoopCount += batchCount; numOps += batchCount; if ((numOps >= symPollingInterval_g)) { if (CPA_TRUE == instanceInfo->isPolled) { icp_sal_CyPollDpInstance(setup->cyInstanceHandle, 0); } numOps = 0; } } /* End of inside Loop while*/ /* if status != CPA_STATUS_SUCCESS, break the out loop directly */ if (CPA_STATUS_SUCCESS != status) { break; } } /* End of outside Loop */ /* When the callback returns it will increment the responses * counter and test if its equal to numBuffLists, in that * case all responses have been successfully received. */ if (CPA_STATUS_SUCCESS == status) { /* ** Now need to wait for all the in-flight Requests. */ status = cyDpPollNumOperations( pSymData, setup->cyInstanceHandle, pSymData->numOperations); } qaeMemFree((void **)&instanceInfo); return status; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Used for profiling IA offload cost. * * Phase One:Iterates over the main perform function, increasing the number * of busy loop cycles(BUSY_LOOP_INCREMENT) on each iteration until no retries * occur. * * Phase Two: Continues to iterate over the main perform function, increasing * the number of busy loop cycles on each iteration until performance is * affected then steps back to the last increment value, i.e. the last * increment step(BUSY_LOOP_INCREMENT) before performance was affected. *****************************************************************************/ static CpaStatus performOffloadCalculation( symmetric_test_params_t *setup, Cpa32U numOfLoops, CpaCySymDpOpData **ppOpData, CpaBufferList **ppSrcBuffListArray, CpaCySymCipherDirection cipherDirection) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32S baseThroughput = 0, currentThroughput = 0; Cpa32U packetSize = 0, lowerBound = 0, upperBound = 0; perf_data_t *pPerfData = setup->performanceStats; pPerfData->busyLoopValue = 1; packetSize = setup->packetSizeInBytesArray[0]; baseThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* Find the lower bound(retries) and upper bound(no retries) for subsequent * binary search. */ while (CPA_STATUS_SUCCESS == status && pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue; pPerfData->busyLoopValue = pPerfData->busyLoopValue << 1; /* PERFORM OP */ if (SYM_DP_ENQUEUEING == setup->numOpDpBatch) { status = symDpPerformEnqueueOp(setup, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); } else { status = symDpPerformEnqueueOpBatch(setup, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); } } upperBound = pPerfData->busyLoopValue; while (CPA_STATUS_SUCCESS == status && lowerBound <= upperBound) { pPerfData->busyLoopValue = (upperBound + lowerBound) / 2; /* PERFORM OP */ if (SYM_DP_ENQUEUEING == setup->numOpDpBatch) { status = symDpPerformEnqueueOp(setup, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); } else { status = symDpPerformEnqueueOpBatch(setup, numOfLoops, ppOpData, ppSrcBuffListArray, cipherDirection); } currentThroughput = getThroughput(pPerfData->responses, packetSize, pPerfData->endCyclesTimestamp - pPerfData->startCyclesTimestamp); /* If no retries and we're within ERROR_MARGIN (0.1%) of base throughput */ if (pPerfData->retries == 0 && (withinMargin(baseThroughput, currentThroughput, ERROR_MARGIN) == 1)) { break; } /* If we see retries */ else if (pPerfData->retries != 0) { lowerBound = pPerfData->busyLoopValue + 1; } /* Else retries are zero, but throughput has been affected. */ else { upperBound = pPerfData->busyLoopValue - 1; } } return status; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Main executing function *****************************************************************************/ static CpaStatus sampleSymmetricDpPerform(symmetric_test_params_t *setup) { /* start of local variable declarations */ CpaCySymDpSessionCtx *pEncryptSessionCtx = NULL; CpaCySymDpOpData **ppOpData = NULL; CpaPhysBufferList **ppSrcPhysBuffListArray = NULL; CpaBufferList **ppSrcBuffListArray = NULL; Cpa32U i = 0; Cpa32U *totalSizeInBytes = NULL; perf_data_t *pSymPerfData = NULL; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U numOfLoops = 0; Cpa32U insideLoopCount = 0; Cpa32U numOfOperations = 0; Cpa8U *cipherKey = NULL; Cpa8U *authKey = NULL; CpaCySymDpCbFunc pSymCb = NULL; Cpa32U node = 0; /* Check if setup is null */ if (NULL == setup) { PRINT_ERR("parameter setup is error \n"); return CPA_STATUS_FAIL; } /*get the node we are running on for local memory allocation*/ status = sampleCodeCyGetNode(setup->cyInstanceHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode error, status: %d\n", status); return CPA_STATUS_FAIL; } /* Initialize local variables */ numOfLoops = setup->numLoops; cipherKey = qaeMemAlloc( setup->setupData.cipherSetupData.cipherKeyLenInBytes * sizeof(Cpa8U)); if (NULL == cipherKey) { PRINT_ERR("cipherKey memory allocation error\n"); return CPA_STATUS_FAIL; } authKey = qaeMemAlloc( setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes * sizeof(Cpa8U)); if (NULL == authKey) { PRINT_ERR("authKey memory allocation error\n"); qaeMemFree((void **)&cipherKey); return CPA_STATUS_FAIL; } totalSizeInBytes = qaeMemAlloc(setup->numBuffLists * sizeof(Cpa32U)); if (NULL == totalSizeInBytes) { PRINT_ERR("totalSizeInBytes memory allocation error\n"); qaeMemFree((void **)&authKey); qaeMemFree((void **)&cipherKey); return CPA_STATUS_FAIL; } pEncryptSessionCtx = qaeMemAlloc(sizeof(CpaCySymDpSessionCtx) * setup->numSessions); if (NULL == pEncryptSessionCtx) { PRINT_ERR("Encrypto Session Array memory allocation error\n"); qaeMemFree((void **)&authKey); qaeMemFree((void **)&cipherKey); qaeMemFree((void **)&totalSizeInBytes); return CPA_STATUS_FAIL; } /*allocate memory for an array of bufferList pointers, flatBuffer pointers * and operation data, the bufferLists and Flat buffers are created in * dpSampleCreateBuffers of cpa_sample_code_crypto_utils.c*/ status = allocArrayOfPointers( setup->cyInstanceHandle, (void **)&ppOpData, setup->numBuffLists); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate opData Array\n"); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return CPA_STATUS_FAIL; } status = allocArrayOfPointers(setup->cyInstanceHandle, (void **)&ppSrcBuffListArray, setup->numBuffLists); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate ppSrcBuffListArray\n"); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return CPA_STATUS_FAIL; } status = allocArrayOfPointers(setup->cyInstanceHandle, (void **)&ppSrcPhysBuffListArray, setup->numBuffLists); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate ppSrcPhysBuffListArray\n"); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return CPA_STATUS_FAIL; } /*use the preallocated performance stats to store performance data, this * points to an element in perfStats array in the framework, each thread * points to a unique element of perfStats array */ pSymPerfData = setup->performanceStats; if (NULL == pSymPerfData) { PRINT_ERR("perf data pointer is NULL\n"); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return CPA_STATUS_FAIL; } /* End of if(NULL == pSymPerfData) */ saveClearRestorePerfStats(pSymPerfData); if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH && (setup->setupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_SNOW3G_UIA2 || setup->setupData.hashSetupData.hashAlgorithm == CPA_CY_SYM_HASH_KASUMI_F9)) { setup->setupData.hashSetupData.digestResultLenInBytes = DIGEST_RESULT_4BYTES; } /*if we are testing hash or alg chain, get the hash size that needs to be * allocated for the digest result. sampleCreateBuffers uses the hash size * to allocate the appropriate memory*/ for (insideLoopCount = 0; insideLoopCount < setup->numBuffLists; insideLoopCount++) { if (setup->isTLS) { /* Calculate totalSizeInBytes: * It should equal packetSizeInBytes + digestResultLenInBytes. * + padding. */ totalSizeInBytes[insideLoopCount] = setup->flatBufferSizeInBytes; } else { /* Calculate totalSizeInBytes: * It should no more than packetSizeInBytes + * digestResultLenInBytes. In cipher algorithm, * digestResultLenInBytes should be 0. */ totalSizeInBytes[insideLoopCount] = setup->packetSizeInBytesArray[insideLoopCount] + setup->setupData.hashSetupData.digestResultLenInBytes; } } /*init the symmetric session*/ /*if the mode is asynchronous then set the callback function*/ if (ASYNC == setup->syncMode) { pSymCb = (CpaCySymDpCbFunc)symDpPerformCallback; } /* Setup session array with cipher key and authKey*/ for (i = 0; i < setup->numSessions; i++) { status = symmetricDpSetupSession(pSymCb, cipherKey, authKey, &pEncryptSessionCtx[i], CPA_FALSE, CPA_FALSE, setup ); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("symmetricDpSetupSession error, status %d\n", status); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return CPA_STATUS_FAIL; } /* End of if (CPA_STATUS_SUCCESS != status) */ } /* End of session loop */ /*if we are testing hash or alg chain, will create sample buffers with * space for digest result, otherwise we just create sample physical buffer * list and physical flat buffers based on the bufferSize we are testing. */ status = dpSampleCreateBuffers(setup->cyInstanceHandle, totalSizeInBytes, ppSrcBuffListArray, ppSrcPhysBuffListArray, setup); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("dpSampleCreateBuffers error, status %d\n", status); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return CPA_STATUS_FAIL; } /*End of if which symOperation == CPA_CY_SYM_OP_HASH */ /* setup the encrypt operation data with session array, packet size array * the pointer of operation data structure, the pointer of setup parameter * the pointer of source buffer list array and the pointer of destination * buffer list */ status = symmetricDpPerformOpDataSetup(pEncryptSessionCtx, setup->packetSizeInBytesArray, ppOpData, setup, ppSrcPhysBuffListArray, ppSrcPhysBuffListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("symmetricDpPerformOpDataSetup error, status %d\n", status); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return status; } /*Perform different symmetric Data Plane Operations with four functions *numOpDpBatch : numRequests : Functions *SYM_DP_ENQUEUEING : >SYM_DP_PERFORM_NOW_FLAG : symDpPerformEnqueueOp *Description: enqueue a single symmetric request, perform later *SYM_DP_ENQUEUEING : SYM_DP_PERFORM_NOW_FLAG : symDpPerformEnqueueOpNow *Description: perform a single symmetric request immediately *!=SYM_DP_ENQUEUEING : >SYM_DP_PERFORM_NOW_FLAG : *symDpPerformEnqueueOpBatch Description: enqueue multiple requests with one *operation, perform later *!=SYM_DP_ENQUEUEING : SYM_DP_PERFORM_NOW_FLAG *:symDpPerformEnqueueOpBatchNow *Description: perform multiple requests with one operation immediately */ if (SYM_DP_ENQUEUEING == setup->numOpDpBatch) { status = symDpPerformEnqueueOp( setup, numOfLoops, ppOpData, ppSrcBuffListArray, setup->setupData.cipherSetupData.cipherDirection); } else { status = symDpPerformEnqueueOpBatch( setup, numOfLoops, ppOpData, ppSrcBuffListArray, setup->setupData.cipherSetupData.cipherDirection); } /* End of if(SYM_DP_ENQUEUEING == setup->numOpDpBatch) */ if (CPA_CC_BUSY_LOOPS == iaCycleCount_g) { status = performOffloadCalculation( setup, numOfLoops, ppOpData, ppSrcBuffListArray, setup->setupData.cipherSetupData.cipherDirection); } numOfOperations += pSymPerfData->numOperations; if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("symPerform error, status %d, \n", status); symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); return status; } /* we must set again the number of operations and responses * after perform sym operation */ pSymPerfData->numOperations = numOfOperations; pSymPerfData->responses = pSymPerfData->numOperations; /* Free up resources allocated */ for (i = 0; i < setup->numSessions; i++) { if (CPA_STATUS_SUCCESS != symmetricDpRemoveSession(setup->cyInstanceHandle, pEncryptSessionCtx[i])) { PRINT_ERR("Deregister session failed\n"); status = CPA_STATUS_FAIL; } } /* for(i=0; inumSessions;i++) */ symDpPerformMemFree(setup, ppSrcBuffListArray, ppSrcPhysBuffListArray, ppOpData, pEncryptSessionCtx, authKey, cipherKey, totalSizeInBytes); if (CPA_STATUS_SUCCESS != setup->performanceStats->threadReturnStatus) { status = CPA_STATUS_FAIL; } return status; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * Setup a symmetric crypto thread for a given packet size or mix *****************************************************************************/ void sampleSymmetricDpPerformance(single_thread_test_data_t *testSetup) { symmetric_test_params_t symTestSetup; symmetric_test_params_t *pSetup = ((symmetric_test_params_t *)testSetup->setupPtr); Cpa32U loopIteration = 0; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U *pPacketSize = NULL; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaInstanceInfo2 *instanceInfo = NULL; #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) int fd = -1; #endif testSetup->passCriteria = getPassCriteria(); memset(&symTestSetup, 0, sizeof(symmetric_test_params_t)); /*cast the setup to a known structure so that we can populate our local * test setup*/ symTestSetup.setupData = pSetup->setupData; /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*give our thread a unique memory location to store performance stats*/ symTestSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; return; } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); status = cpaCyInstanceGetInfo2(symTestSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } symTestSetup.performanceStats->packageId = instanceInfo->physInstId.packageId; if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } #if !defined(SC_BSD_UPSTREAM) if (instanceInfo->isPolled == CPA_FALSE) { PRINT("Data-Plane operations not supported on non-polled instances\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } #endif #if defined(USER_SPACE) && !defined(SC_EPOLL_DISABLED) status = icp_sal_CyGetFileDescriptor(symTestSetup.cyInstanceHandle, &fd); if (CPA_STATUS_SUCCESS == status) { PRINT("Data-Plane operations not supported on Epoll instances\n"); qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); icp_sal_CyPutFileDescriptor(symTestSetup.cyInstanceHandle, fd); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_UNSUPPORTED; /* Stop Cy Service function should be called after all threads * complete their execution. This function will be called from * WaitForThreadCompletion().*/ testSetup->statsPrintFunc = (stats_print_func_t)stopCyServicesFromCallback; sampleCodeThreadExit(); } #endif /* Assign the unique thread id to the symTestSetup structure */ symTestSetup.threadID = testSetup->threadID; pPacketSize = qaeMemAlloc(sizeof(Cpa32U) * pSetup->numBuffLists); if (NULL == pPacketSize) { PRINT_ERR("Could not allocate memory for pPacketSize\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; goto exit; } if (testSetup->packetSize == PACKET_IMIX) { /*we are testing IMIX so we copy buffer sizes from preallocated * array into symTestSetup.numBuffLists*/ Cpa32U indexer = sizeof(packetMix) / sizeof(Cpa32U); symTestSetup.performanceStats->averagePacketSizeInBytes = BUFFER_SIZE_1152; for (loopIteration = 0; loopIteration < pSetup->numBuffLists; loopIteration++) { pPacketSize[loopIteration] = packetMix[loopIteration % indexer]; } } else { symTestSetup.performanceStats->averagePacketSizeInBytes = testSetup->packetSize; /*we are testing a uniform bufferSize, so we set the bufferSize array * accordingly*/ for (loopIteration = 0; loopIteration < pSetup->numBuffLists; loopIteration++) { pPacketSize[loopIteration] = testSetup->packetSize; } } symTestSetup.numOpDpBatch = pSetup->numOpDpBatch; symTestSetup.numRequests = pSetup->numRequests; symTestSetup.numSessions = pSetup->numSessions; symTestSetup.flatBufferSizeInBytes = pSetup->flatBufferSizeInBytes; symTestSetup.enableRoundOffPkt = pSetup->enableRoundOffPkt; symTestSetup.numBuffLists = pSetup->numBuffLists; symTestSetup.numLoops = pSetup->numLoops; /*reset the stats print function to NULL, we set it to the proper function * if the test passes at the end of this function*/ testSetup->statsPrintFunc = NULL; /*assign the array of buffer sizes we are testing to the symmetric test * setup*/ symTestSetup.packetSizeInBytesArray = pPacketSize; /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; symTestSetup.syncMode = pSetup->syncMode; /*store core affinity, this assumes logical cpu core number is the same * logicalQaInstace */ symTestSetup.performanceStats->logicalCoreAffinity = testSetup->logicalQaInstance; symTestSetup.isDpApi = pSetup->isDpApi; symTestSetup.cryptoSrcOffset = pSetup->cryptoSrcOffset; symTestSetup.digestAppend = pSetup->digestAppend; symTestSetup.ivLength = pSetup->ivLength; symTestSetup.isTLS = pSetup->isTLS; /*launch function that does all the work*/ if (CPA_TRUE != checkCapability(cyInstances[testSetup->logicalQaInstance], &symTestSetup)) { PRINT("\nThread %u Invalid test.Capability check failed for the " "requested algorithm on the configured instance\n", testSetup->threadID); testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_UNSUPPORTED; error_flag_g = CPA_FALSE; sampleCodeBarrier(); symTestSetup.packetSizeInBytesArray = NULL; goto exit; } status = sampleSymmetricDpPerform(&symTestSetup); if (CPA_STATUS_SUCCESS != status) { printSymTestType(&symTestSetup); PRINT("Symmetric thread %u FAILED\n", testSetup->threadID); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; } if ((CPA_STATUS_SUCCESS != status) || (symTestSetup.performanceStats->threadReturnStatus == CPA_STATUS_FAIL)) { /* Stop Cy Service function should be called after all threads * complete their execution. This function will be called from * WaitForThreadCompletion().*/ testSetup->statsPrintFunc = (stats_print_func_t)stopCyServicesFromCallback; } exit: /*free memory and exit*/ if (pPacketSize != NULL) { qaeMemFree((void **)&pPacketSize); } qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadComplete(testSetup->threadID); } EXPORT_SYMBOL(sampleSymmetricDpPerformance); /***************************************************************************** * * External Function Interfaces * ****************************************************************************/ /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * setup a symmetric test * This function needs to be called from main to setup a symmetric test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances ****************************************************************************/ CpaStatus setupSymmetricDpTest( CpaCySymOp opType, CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCyPriority priority, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, CpaCySymHashNestedModeSetupData *nestedModeSetupDataPtr, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U bufferSizeInBytes, Cpa32U numBuffLists, Cpa32U numLoops, Cpa32U digestAppend, CpaBoolean isTLS) { symmetric_test_params_t *symmetricSetup = NULL; Cpa8S name[] = {'D', 'P', '_', 'S', 'Y', 'M', '\0'}; Cpa32U padding = 0; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /* Return an error if the number of packets is not modulus zero of the * number of packets to cover IMIX packet mix. */ if (packetSize == PACKET_IMIX && (numBuffLists % NUM_PACKETS_IMIX) != 0) { PRINT_ERR("To ensure that the weighting of IMIX packets is correct " ", the number of buffers (%d) should be a multiple of %d\n", numBuffLists, NUM_PACKETS_IMIX); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Failed to start Crypto services\n"); return CPA_STATUS_FAIL; } /*as setup is a multidimensional char array we need to cast it to the * symmetric structure*/ memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); symmetricSetup = (symmetric_test_params_t *)&thread_setup_g[testTypeCount_g][0]; memset(symmetricSetup, 0, sizeof(symmetric_test_params_t)); testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)sampleSymmetricDpPerformance; testSetupData_g[testTypeCount_g].packetSize = packetSize; /*then we store the test setup in the above location*/ symmetricSetup->setupData.sessionPriority = priority; symmetricSetup->setupData.symOperation = opType; symmetricSetup->setupData.cipherSetupData.cipherAlgorithm = cipherAlg; symmetricSetup->setupData.cipherSetupData.cipherDirection = cipherDirection_g; symmetricSetup->setupData.cipherSetupData.cipherDirection = getCipherDirection(); symmetricSetup->setupData.cipherSetupData.cipherKeyLenInBytes = cipherKeyLengthInBytes; symmetricSetup->setupData.hashSetupData.hashAlgorithm = hashAlg; symmetricSetup->setupData.hashSetupData.hashMode = hashMode; symmetricSetup->setupData.digestIsAppended = digestAppend; /* The flag to denote whether the setup done for SymmetricDpTest * is TLS or SSL */ symmetricSetup->isTLS = isTLS; if ((symmetricSetup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) && (symmetricSetup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM)) { symmetricSetup->setupData.digestIsAppended = CPA_TRUE; } symmetricSetup->isDpApi = CPA_TRUE; symmetricSetup->cryptoSrcOffset = cipherOffset; /* Partial not supported in DP case */ symmetricSetup->setupData.partialsNotRequired = CPA_TRUE; /* in this code we limit the digest result len to be the same as the the * authentication key len*/ symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = authKeyLengthInBytes; if ((CPA_CY_SYM_HASH_AES_GCM == hashAlg || CPA_CY_SYM_HASH_AES_CCM == hashAlg) && (authKeyLengthInBytes != 8 && authKeyLengthInBytes != 12 && authKeyLengthInBytes != 16)) { PRINT("For CPA_CY_SYM_HASH_AES_GCM and CPA_CY_SYM_HASH_AES_CCM, digest " "length %u unsupported " "defaulting to 16 \n", authKeyLengthInBytes); symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = 16; } if (CPA_STATUS_SUCCESS == checkForChachapolySupport()) { /* Always run AES-GCM/GMAC algchain with single pass mode */ if ((CPA_CY_SYM_CIPHER_AES_GCM == cipherAlg) && (CPA_CY_SYM_HASH_AES_GCM == hashAlg || CPA_CY_SYM_HASH_AES_GMAC == hashAlg) && CPA_CY_SYM_OP_ALGORITHM_CHAINING == opType) { symmetricSetup->ivLength = CPA_CIPHER_SPC_IV_SIZE; } } if (((hashAlg == CPA_CY_SYM_HASH_KASUMI_F9) || (hashAlg == CPA_CY_SYM_HASH_SNOW3G_UIA2)) && (authKeyLengthInBytes != 4)) { PRINT("CPA_CY_SYM_HASH_SNOW3G_UIA2/CPA_CY_SYM_HASH_KASUMI_F9" " digest length %u unsupported " "defaulting to 4 \n", authKeyLengthInBytes); symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = 4; } #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 #endif /* check which kind of hash mode is selected */ /*nested mode */ if (CPA_CY_SYM_HASH_MODE_NESTED == hashMode) { /*set the struct for nested hash mode */ if (NULL == nestedModeSetupDataPtr) { /* set a default nested mode setup data */ symmetricSetup->setupData.hashSetupData.nestedModeSetupData .outerHashAlgorithm = hashAlg; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .pInnerPrefixData = NULL; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .innerPrefixLenInBytes = 0; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .pOuterPrefixData = NULL; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .outerPrefixLenInBytes = 0; } else { symmetricSetup->setupData.hashSetupData.nestedModeSetupData = *nestedModeSetupDataPtr; } } if ((CPA_CY_SYM_HASH_AES_XCBC == hashAlg) && (AES_XCBC_DIGEST_LENGTH_IN_BYTES != authKeyLengthInBytes)) { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = AES_XCBC_DIGEST_LENGTH_IN_BYTES; } #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 // ZUC-EIA3 supports authKeyLen=128bits and digestResultLen=32bits else if (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlg && authKeyLengthInBytes < KEY_SIZE_256_IN_BYTES) { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = KEY_SIZE_128_IN_BYTES; symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = setHashDigestLen(hashAlg); } #endif else { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = authKeyLengthInBytes; } if (isTLS) { if (((CPA_CY_SYM_CIPHER_AES_CBC == symmetricSetup->setupData.cipherSetupData.cipherAlgorithm) && (CPA_CY_SYM_HASH_SHA1 == hashAlg)) || ((CPA_CY_SYM_CIPHER_AES_CBC == symmetricSetup->setupData.cipherSetupData.cipherAlgorithm) && (CPA_CY_SYM_HASH_SHA256 == hashAlg))) { symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = setHashDigestLen(hashAlg); } else { PRINT_ERR("Invalid Cipher Hash combination\n"); return CPA_STATUS_FAIL; } symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = authKeyLengthInBytes; /* flat Buffer Size is Header + Cipher data + Hash digest */ symmetricSetup->flatBufferSizeInBytes = symmetricSetup->cryptoSrcOffset + packetSize + symmetricSetup->setupData.hashSetupData.digestResultLenInBytes; /* Exclude the header for padding calculation */ padding = IV_LEN_FOR_16_BYTE_BLOCK_CIPHER - ((symmetricSetup->flatBufferSizeInBytes - symmetricSetup->cryptoSrcOffset) % IV_LEN_FOR_16_BYTE_BLOCK_CIPHER); symmetricSetup->flatBufferSizeInBytes += padding; } else { symmetricSetup->flatBufferSizeInBytes = bufferSizeInBytes; } symmetricSetup->setupData.algChainOrder = chainOrder; symmetricSetup->syncMode = syncMode; symmetricSetup->numOpDpBatch = numDpBatchOp; symmetricSetup->numRequests = numRequests; symmetricSetup->numSessions = numSessions; symmetricSetup->numBuffLists = numBuffLists; symmetricSetup->numLoops = numLoops; if (((bufferSizeInBytes != 0) && (packetSize == PACKET_IMIX)) || (bufferSizeInBytes % IV_LEN_FOR_16_BYTE_BLOCK_CIPHER != 0)) { PRINT_ERR("Doesn't support PACKET_IMIX " "when the flat buffer size is not 0 or " " it's not align with block size (%d): ", bufferSizeInBytes); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * setup a cipher test * This function needs to be called from main to setup a cipher test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances *****************************************************************************/ CpaStatus setupCipherDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U flatBufferSize, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops) { return setupSymmetricDpTest( CPA_CY_SYM_OP_CIPHER, cipherAlg, cipherKeyLengthInBytes, NOT_USED, priority, NOT_USED /* hash alg not needed in cipher test*/, NOT_USED /* hash mode not needed in cipher test*/, NOT_USED /* auth key len not needed in cipher test*/, NOT_USED /* chain mode not needed in cipher test*/, syncMode, NULL, /* nested hash data not needed in cipher test*/ packetSize, numDpBatchOp, numRequests, numSessions, flatBufferSize, numBuffLists, numLoops, digestAppended_g, CPA_FALSE); } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * setup a hash test * This function needs to be called from main to setup a hash test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances *****************************************************************************/ CpaStatus setupHashDpTest(CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops) { return setupSymmetricDpTest( CPA_CY_SYM_OP_HASH, NOT_USED /* cipher alg not needed in cipher test*/, NOT_USED /* cipher key len not needed in cipher test*/, NOT_USED, priority, hashAlg, hashMode, authKeyLengthInBytes, NOT_USED /* chain mode not needed in cipher test*/, syncMode, NULL, /* nested hash data not needed in cipher test*/ packetSize, numDpBatchOp, numRequests, numSessions, BUFFER_SIZE_0, numBuffLists, numLoops, digestAppended_g, CPA_FALSE); } /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * setup a alg chain test. * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances *****************************************************************************/ CpaStatus setupAlgChainDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U flatBufferSize, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops) { return setupSymmetricDpTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlg, cipherKeyLengthInBytes, NOT_USED, priority, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, syncMode, NULL, packetSize, numDpBatchOp, numRequests, numSessions, flatBufferSize, numBuffLists, numLoops, digestAppended_g, CPA_FALSE); } /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup an IPsec scenario where payload = IP packet, the IP header is not * encrypted thus requires an offset into the buffer to test. * * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupIpSecDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops) { return setupSymmetricDpTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlg, cipherKeyLengthInBytes, cipherOffset, CPA_CY_PRIORITY_HIGH, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, ASYNC, NULL, packetSize, numDpBatchOp, numRequests, numSessions, BUFFER_SIZE_0, numBuffLists, numLoops, digestAppended_g, CPA_FALSE); } EXPORT_SYMBOL(setupIpSecDpTest); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a TLS scenario where TBD * * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupTLSDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U payloadSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops) { return setupSymmetricDpTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlg, cipherKeyLengthInBytes, cipherOffset, CPA_CY_PRIORITY_HIGH, hashAlg, hashMode, authKeyLengthInBytes, chainOrder, ASYNC, NULL, payloadSize, numDpBatchOp, numRequests, numSessions, BUFFER_SIZE_0, numBuffLists, numLoops, digestAppended_g, CPA_TRUE); } EXPORT_SYMBOL(setupTLSDpTest); /***************************************************************************** * @ingroup sampleSymmetricDpPerf * * @description * setup a alg chain test * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances *****************************************************************************/ CpaStatus setupAlgChainTestDpNestedMode( CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, CpaCySymHashNestedModeSetupData *nestedModeSetupData, Cpa32U packetSize, Cpa32U numDpOpBatch, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops) { return setupSymmetricDpTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlg, cipherKeyLengthInBytes, NOT_USED, priority, hashAlg, CPA_CY_SYM_HASH_MODE_NESTED, authKeyLengthInBytes, chainOrder, syncMode, nestedModeSetupData, packetSize, numDpOpBatch, numRequests, numSessions, BUFFER_SIZE_0, numBuffLists, numLoops, digestAppended_g, CPA_FALSE); } cpa_sample_code_sym_perf_dp.h000066400000000000000000000613601503624047500365720ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sym_perf_dp.h * * @defgroup sampleSymmetricDpPerf Symmetric Data Plane Performance code * * @ingroup sampleSymmetricDpPerf * * @description * This file contains function prototype and macro definition * for symmetric Data Plane performance sample code. * *****************************************************************************/ #ifndef CPA_SAMPLE_CODE_SYM_PERF_DP_H_ #define CPA_SAMPLE_CODE_SYM_PERF_DP_H_ #include "cpa_sample_code_crypto_utils.h" #include "cpa_cy_sym_dp.h" /** Macro definition **/ /* Symmetric DP operation Type * SYM_DP_ENQUEUEING: Enqueue operation will submit one operation * into the queue list at one time */ #define SYM_DP_ENQUEUEING (0) /* Symmetric DP operation perform flag * if setup->numRequests is equal to SYM_DP_PERFORM_NOW_FLAG, * the operation should be performed immediately (performOpNow is CPA_TRUE), * otherwise enqueued to be performed later (performOpNow = CPA_FALSE). */ #define SYM_DP_PERFORM_NOW_FLAG (1) /* init value for AdditionalAuthData when Snow3g */ #define SYM_AUTH_INIT_VALUE (0XAA) /* Symmetric DP min num loop */ #define SYM_DP_MIN_NUM_LOOP (1) /* lv field offset for CPA_CY_SYM_CIPHER_AES_CCM */ #define SYM_DP_LV_OFFSET_CCM (1) #define SYM_DP_SINGLE_SESSION (1) #define SYM_DP_NUM_BUFFERS (5000) /* step back for the dynamic algorithm */ #define SYM_BACKOFF_STEP_BACK 20 /* step forward for the dynamic algorithm */ #define SYM_BACKOFF_STEP_FORWARD 10 * SYM_BACKOFF_STEP_BACK /* maximum value of the dynamic backoff delay */ #define SYM_BACKOFF_TIMER_MAX 10000 /** Function Declaration**/ /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * setup a symmetric test * * @description * This function needs to be called from main to setup a symmetric test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances. * * @param[in] opType operation type * @param[in] cipherAlg Indicates cipher algorithms and modes * @param[in] cipherKeyLengthInBytes The length of cipher key in bytes * @param[in] priority The level of priority * @param[in] hashAlg Indicates hash algorithm * @param[in] hashMode Mode of Hash algorithm * @param[in] authKeyLengthInBytes The length of Authentication key in * bytes. * @param[in] chainOrder If this opType is an chaining algorithm * then this parameter determines the order * in which the operations are chained. * If this opType isn't chaining algorithm * then this parameter will be ignored. * @param[in] syncMode Sync Mode of the test: async and sync * @param[in] nestedModeSetupDataPtr The pointer of Hash Mode Nested Setup * Data * @param[in] packetSize Data packet size of array * @param[in] numDpOpBatch How many Op at one time. if * numOpDpBatch >0, enqueue multiple * requests with one operation. * Otherwise, perform a single symmetric * request * @param[in] numRequests How many requests will be submitted * at one time: * numRequests = 1: enqueue a single * request and perform symmetric operation * immediately. * otherwise : enqueue numRequests before * calling API to perform the operations. * @param[in] numSessions The number Of session per test thread. * @param[in] bufferSizeInBytes The Length Of flat buffer per buffer * list. If bufferSizeInBytes is 0, * it will only provide physical address * to srcbuffer/destbuffer in OpData. * @param[in] numBuffLists The number of buffers List,a minimum * of 1024 buffers should be used in the * sample code to ensure that both RX/TX * rings are full during performance * operations. This also ensures that * in-flight requests are not being * resubmitted before being returned by the * driver. * @param[in] numLoops The number of Loops * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. * *****************************************************************************/ CpaStatus setupSymmetricDpTest( CpaCySymOp opType, CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCyPriority priority, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, CpaCySymHashNestedModeSetupData *nestedModeSetupDataPtr, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffers, Cpa32U numBuffLists, Cpa32U numLoops, Cpa32U digestAppend, CpaBoolean isTLS); /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * setup a cipher test * * @description * This function needs to be called from main to setup a cipher test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances. * * @param[in] cipherAlg Indicates cipher algorithms and modes * @param[in] cipherKeyLengthInBytes The length of cipher key in bytes * @param[in] priority The level of priority * @param[in] syncMode Sync Mode of the test: async and sync * @param[in] packetSize Data packet size of array * @param[in] numDpOpBatch How many Op at one time. if * numOpDpBatch >0, enqueue multiple * requests with one operation. * Otherwise, perform a single symmetric * request * @param[in] numRequests How many requests will be submitted * at one time: * numRequests = 1: enqueue a single * request and perform symmetric operation * immediately. * otherwise : enqueue numRequests before * calling API to perform the operations. * @param[in] numSessions The number Of session per test thread. * @param[in] numBuffLists The number of buffers List,a minimum * of 1024 buffers should be used in the * sample code to ensure that both RX/TX * rings are full during performance * operations. This also ensures that * in-flight requests are not being * resubmitted before being returned by the * driver. * @param[in] numLoops The number of Loops * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. *****************************************************************************/ CpaStatus setupCipherDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U flatBufferSize, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops); /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * setup a hash test * * @description * This function needs to be called from main to setup a hash test. * then the framework createThreads function is used to propagate this setup * across cores using different crypto logical instances. * * @param[in] hashAlg Indicates hash algorithm * @param[in] hashMode Mode of Hash algorithm * @param[in] authKeyLengthInBytes The length of Authentication key in * bytes. * @param[in] priority The level of priority * @param[in] syncMode Sync Mode of the test: async and sync * @param[in] packetSize Data packet size of array * @param[in] numDpOpBatch How many Op at one time. if * numOpDpBatch >0, enqueue multiple * requests with one operation. * Otherwise, perform a single symmetric * request * @param[in] numRequests How many requests will be submitted * at one time: * numRequests = 1: enqueue a single * request and perform symmetric operation * immediately. * otherwise : enqueue numRequests before * calling API to perform the operations. * @param[in] numSessions The number Of session per test thread. * @param[in] numBuffLists The number of buffers List,a minimum * of 1024 buffers should be used in the * sample code to ensure that both RX/TX * rings are full during performance * operations. This also ensures that * in-flight requests are not being * resubmitted before being returned by the * driver. * @param[in] numLoops The number of Loops * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. *****************************************************************************/ CpaStatus setupHashDpTest(CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops); /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * setup a alg chain test (default High Priority) * * @description * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances * * @param[in] cipherAlg Indicates cipher algorithms and modes * @param[in] cipherKeyLengthInBytes The length of cipher key in bytes * @param[in] hashAlg Indicates hash algorithm * @param[in] hashMode Mode of Hash algorithm * @param[in] authKeyLengthInBytes the length of Authentication key in * bytes * @param[in] chainOrder If this opType is an chaining algorithm * then this parameter determines the order * in which the operations are chained. * If this opType isn't chaining algorithm * then this parameter will be ignored. * @param[in] syncMode Sync Mode of the test: async and sync * @param[in] packetSize Data packet size of array * @param[in] numDpOpBatch How many Op at one time. if * numOpDpBatch >0, enqueue multiple * requests with one operation. * Otherwise, perform a single symmetric * request * @param[in] numRequests How many requests will be submitted * at one time: * numRequests = 1: enqueue a single * request and perform symmetric operation * immediately. * otherwise : enqueue numRequests before * calling API to perform the operations. * @param[in] numSessions The number Of session per test thread. * @param[in] numBuffLists The number of buffers List,a minimum * of 1024 buffers should be used in the * sample code to ensure that both RX/TX * rings are full during performance * operations. This also ensures that * in-flight requests are not being * resubmitted before being returned by the * driver. * @param[in] numLoops The number of Loops * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. *****************************************************************************/ CpaStatus setupAlgChainDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U flatBufferSize, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup an IPsec scenario where payload = IP packet, the IP header is not * encrypted thus requires an offset into the buffer to test. * * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupIpSecDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops); /****************************************************************************** * @ingroup sampleSymmetricPerf * * @description * setup a TLS scenario where packet size passed in represents the size of * the payload data. Seq num, header, MAC and padding will get added to packet * so it will be bigger. * * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this setup * across IA cores using different crypto logical instances ******************************************************************************/ CpaStatus setupTLSDpTest(CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, Cpa32U packetSize, Cpa32U numDpBatchOp, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops); /** ***************************************************************************** * @ingroup sampleSymmetricDpPerf * setup a alg chain nested mode test for data plane API. * * @description * This function needs to be called from main to setup an alg chain test. * then the framework createThreads function is used to propagate this * setup across IA cores using different crypto logical instances. * * @param[in] cipherAlg Indicates cipher algorithms and modes * @param[in] cipherKeyLengthInBytes The length of cipher key in bytes * @param[in] hashAlg Indicates hash algorithms * @param[in] authKeyLengthInBytes the length of Authentication key in * bytes * @param[in] chainOrder If this opType is an chaining algorithm * then this parameter determines the order * in which the operations are chained. * If this opType isn't chaining algorithm * then this parameter will be ignored. * @param[in] priority The level of priority * @param[in] syncMode Sync Mode of the test: async and sync * @param[in] nestedModeSetupData Hash Mode Nested Setup Data * @param[in] packetSize Data packet size of array * @param[in] numDpOpBatch How many Op at one time. if * numOpDpBatch >0, enqueue multiple * requests with one operation. * Otherwise, perform a single symmetric * request * @param[in] numRequests How many requests will be submitted * at one time: * numRequests = 1: enqueue a single * request and perform symmetric operation * immediately. * otherwise : enqueue numRequests before * calling API to perform the operations. * @param[in] numSessions The number Of session per test thread. * @param[in] numBuffLists The number of buffers List,a minimum * of 1024 buffers should be used in the * sample code to ensure that both RX/TX * rings are full during performance * operations. This also ensures that * in-flight requests are not being * resubmitted before being returned by the * driver. * @param[in] numLoops The number of Loops * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. *****************************************************************************/ CpaStatus setupAlgChainTestDpNestedMode( CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, CpaCySymHashAlgorithm hashAlg, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, CpaCySymHashNestedModeSetupData *nestedModeSetupData, Cpa32U packetSize, Cpa32U numDpOpBatch, Cpa32U numRequests, Cpa32U numSessions, Cpa32U numBuffLists, Cpa32U numLoops); #endif /* CPA_SAMPLE_CODE_SYM_PERF_DP_H_ */ cpa_sample_code_sym_update.c000066400000000000000000002041521503624047500364260ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sym_update.c * * @defgroup sampleSymmetricPerf Symmetric Performance code * * @ingroup sampleSymmetricPerf * * @description * This file contains the main symmetric session update performance * sample code. It is capable of performing all ciphers, all hashes, * authenticated hashes and algorithm chaining with session update * operation. * *****************************************************************************/ #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_framework.h" #include "icp_sal_poll.h" #include "cpa_cy_sym.h" #include "cpa_sample_code_framework.h" #include "cpa_sample_code_utils.h" #include "cpa_sample_code_utils_common.h" #include "cpa.h" #include "cpa_cy_common.h" #include "cpa_cy_sym.h" #include "cpa_sample_code_sym_update_common.h" #if CY_API_VERSION_AT_LEAST(2, 2) // Perform static CpaStatus performOpAndVerify(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, symmetric_test_params_t *setup, CpaCySymSessionUpdateData *pSessionUpdate, Cpa32U node, perf_data_t *pSymData, CpaBufferList **pSrcBufferList, CpaBufferList **pDstBufferList, CpaCySymOpData **pOpData, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U innerLoop = 0; Cpa32U failCount = 0; CpaBoolean sessionInUse = CPA_TRUE; CpaBoolean verifyResult = CPA_TRUE; setup->performanceStats->numOperations += setup->numBuffers; // Perform for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { do { status = cpaCySymPerformOp(cyInstHandle, pSymData, pOpData[innerLoop], pSrcBufferList[innerLoop], pDstBufferList[innerLoop], &verifyResult); if (CPA_STATUS_RETRY == status) { pSymData->retries++; AVOID_SOFTLOCKUP; } } while (status == CPA_STATUS_RETRY); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp failed - status %d\n", status); failCount++; } } // Wait for completion do { status = cpaCySymSessionInUse(sessionCtx, &sessionInUse); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionInUse: failed - status: %d\n", status); break; } AVOID_SOFTLOCKUP; } while (sessionInUse == CPA_TRUE); if (failCount > 0) { status = CPA_STATUS_FAIL; } return status; } // Perform for cipher session static CpaStatus updatePerformCipher(symmetric_test_params_t *setup, CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pSessionUpdate, CpaInstanceHandle cyInstHandle, Cpa32U node, perf_data_t *pSymData, CpaCySymOpData **pOpData, CpaBufferList **pSrcBufferList, CpaBufferList **pDstBufferList, CpaBoolean *verifyResult, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus updateStatus = CPA_STATUS_SUCCESS; status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData(sessionCtx, pSessionUpdate, NULL, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pCipherKey, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS != updateStatus) { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } return status; } // Perform for hash session static CpaStatus updatePerformHash(symmetric_test_params_t *setup, CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pSessionUpdate, CpaInstanceHandle cyInstHandle, Cpa32U node, perf_data_t *pSymData, CpaCySymOpData **pOpData, CpaBufferList **pSrcBufferList, CpaBufferList **pDstBufferList, CpaBoolean *verifyResult, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus updateStatus = CPA_STATUS_SUCCESS; status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pUpdateAuthKey, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS != status) { setupUpdateData(sessionCtx, pSessionUpdate, NULL, &pAuthKey, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS != updateStatus) { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } return status; } // Perform for alg chain session static CpaStatus updatePerformAlgChain( symmetric_test_params_t *setup, CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pSessionUpdate, CpaInstanceHandle cyInstHandle, Cpa32U node, perf_data_t *pSymData, CpaCySymOpData **pOpData, CpaBufferList **pSrcBufferList, CpaBufferList **pDstBufferList, CpaBoolean *verifyResult, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus updateStatus = CPA_STATUS_SUCCESS; status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pUpdateAuthKey, CPA_FALSE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { updateStatus = CPA_STATUS_UNSUPPORTED; } else { // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pAuthKey, CPA_FALSE); } else { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData(sessionCtx, pSessionUpdate, NULL, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pCipherKey, &pAuthKey, CPA_FALSE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { // Update session updateStatus = CPA_STATUS_UNSUPPORTED; } else { updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData(sessionCtx, pSessionUpdate, &pUpdateCipherKey, &pUpdateAuthKey, CPA_FALSE); } else { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pUpdateAuthKey, CPA_TRUE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { // Update session updateStatus = CPA_STATUS_UNSUPPORTED; } else { updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pAuthKey, CPA_TRUE); } else { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerify(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBufferList, pDstBufferList, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pCipherKey, &pAuthKey, CPA_TRUE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { updateStatus = CPA_STATUS_UNSUPPORTED; } else { // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData(sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_TRUE); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } return status; } static CpaStatus updatePerform(symmetric_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus sessionStatus = CPA_STATUS_SUCCESS; Cpa32U node = 0; CpaInstanceInfo2 *instanceInfo2 = NULL; CpaInstanceHandle cyInstHandle = setup->cyInstanceHandle; Cpa8U *pIvBuffer = NULL; Cpa32U ivBufferLen = setup->ivLength; Cpa8U **pSrcBuffer = NULL; CpaBufferList **pSrcBufferList = NULL; Cpa8U **pDstBuffer = NULL; CpaBufferList **pDstBufferList = NULL; Cpa32U srcBufferLen = setup->flatBufferSizeInBytes; Cpa32U dstBufferLen = setup->flatBufferSizeInBytes; CpaCySymOpData **pOpData = NULL; Cpa32U sessionCtxSize = 0; CpaCySymSessionCtx sessionCtx = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; CpaBoolean verifyResult = CPA_TRUE; perf_data_t *pSymData = NULL; CpaCySymCbFunc pSymCb = NULL; Cpa8U *pCipherKey = NULL; Cpa8U *pUpdateCipherKey = NULL; Cpa8U *pAuthKey = NULL; Cpa8U *pUpdateAuthKey = NULL; Cpa8U *pAdditionalAuthData = NULL; Cpa32U innerLoop = 0; Cpa32U outerLoop = 0; Cpa32U failCount = 0; CpaCySymSessionUpdateData sessionUpdate = {0}; CpaCySymCapabilitiesInfo capInfo; Cpa32U srcBufferCnt = 0; Cpa32U srcBufferListCnt = 0; Cpa32U dstBufferCnt = 0; Cpa32U dstBufferListCnt = 0; Cpa32U opDataCnt = 0; sampleCodeBarrier(); cpaCySymQueryCapabilities(cyInstHandle, &capInfo); if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { /* For cipher, check if cipher algorithm is correct */ if (!CPA_BITMAP_BIT_TEST( capInfo.ciphers, setup->setupData.cipherSetupData.cipherAlgorithm)) { PRINT("Cipher "); printCipherAlg(setup->setupData.cipherSetupData); PRINT(" is not supported on device. Marking as SUCCESS\n"); return CPA_STATUS_SUCCESS; } } if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { /* For cipher, check if hash algorithm is correct */ if (!CPA_BITMAP_BIT_TEST(capInfo.hashes, setup->setupData.hashSetupData.hashAlgorithm)) { PRINT("Hash "); printHashAlg(setup->setupData.hashSetupData); PRINT(" is not supported on device. Marking as SUCCESS\n"); return CPA_STATUS_SUCCESS; } } instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); // Get instance info status = cpaCyInstanceGetInfo2(cyInstHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return status; } qaeMemFree((void **)&instanceInfo2); // Get node status = sampleCodeCyGetNode(cyInstHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return status; } // Alloc IV if (CPA_STATUS_SUCCESS == status) { if (ivBufferLen > 0) { if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { /* Although the IV data length for CCM must be 16 bytes, * the nonce length must be between 7 and 13 inclusive */ ivBufferLen = AES_CCM_DEFAULT_NONCE_LENGTH; setup->ivLength = AES_CCM_DEFAULT_NONCE_LENGTH; pIvBuffer = qaeMemAllocNUMA(ivBufferLen, node, BYTE_ALIGNMENT_64); if (NULL == pIvBuffer) { PRINT_ERR("Alloc iv failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { memset(pIvBuffer, 0, ivBufferLen); /*generate a random IV*/ generateRandomData(&pIvBuffer[1], ivBufferLen); } } else { status = allocAndFillRandom(&pIvBuffer, ivBufferLen, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc iv failed with status %u\n", status); } } } else { PRINT_ERR("Invalid iv buffer length\n"); status = CPA_STATUS_FAIL; } } // Alloc src if (CPA_STATUS_SUCCESS == status) { pSrcBuffer = qaeMemAllocNUMA( (sizeof(Cpa8U *) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (NULL == pSrcBuffer) { PRINT_ERR("Alloc Src buffer failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { pSrcBufferList = qaeMemAllocNUMA( (sizeof(Cpa8U *) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (NULL == pSrcBufferList) { PRINT_ERR("Alloc Src buffer list failed\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { // Alloc src buffer pSrcBuffer[innerLoop] = qaeMemAllocNUMA( srcBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pSrcBuffer[innerLoop]) { PRINT_ERR("Alloc Src buffer failed\n"); status = CPA_STATUS_FAIL; break; } else { generateRandomData(pSrcBuffer[innerLoop], srcBufferLen); } srcBufferCnt++; // Alloc src buffer list status = setupBufferList( &pSrcBuffer[innerLoop], 1, srcBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes, &pSrcBufferList[innerLoop], node); if (pSrcBufferList[innerLoop] == NULL) { PRINT_ERR("Alloc Src buffer list failed\n"); status = CPA_STATUS_FAIL; break; } srcBufferListCnt++; } } } // Alloc dst buffer list if (CPA_STATUS_SUCCESS == status) { pDstBuffer = qaeMemAllocNUMA( (sizeof(Cpa8U *) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (NULL == pDstBuffer) { PRINT_ERR("Alloc Dst buffer failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { pDstBufferList = qaeMemAllocNUMA( (sizeof(Cpa8U *) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (NULL == pDstBufferList) { PRINT_ERR("Alloc Dst buffer failed\n"); status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { // Alloc dst buffer pDstBuffer[innerLoop] = qaeMemAllocNUMA( dstBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pDstBuffer[innerLoop]) { PRINT_ERR("Alloc Dst buffer failed\n"); status = CPA_STATUS_FAIL; break; } dstBufferCnt++; // Alloc dst buffer list status = setupBufferList( &pDstBuffer[innerLoop], 1, dstBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes, &pDstBufferList[innerLoop], node); if (pDstBufferList[innerLoop] == NULL) { PRINT_ERR("Alloc Dst buffer list failed\n"); status = CPA_STATUS_FAIL; break; } dstBufferListCnt++; } } } if (CPA_STATUS_SUCCESS == status) { // Alloc cipherkey & update cipherkey if (setup->setupData.cipherSetupData.cipherKeyLenInBytes > 0) { status = allocAndFillRandom( &pCipherKey, setup->setupData.cipherSetupData.cipherKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc and fill random failed for cipherKey\n"); } else { status = allocAndFillRandom( &pUpdateCipherKey, setup->setupData.cipherSetupData.cipherKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "Alloc and fill random failed for update cipherKey\n"); } } } } // Alloc authkey & update authkey if (CPA_STATUS_SUCCESS == status) { if (setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes > 0) { status = allocAndFillRandom(&pAuthKey, setup->setupData.hashSetupData .authModeSetupData.authKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc and fill random failed for authKey\n"); } if (CPA_STATUS_SUCCESS == status) { status = allocAndFillRandom(&pUpdateAuthKey, setup->setupData.hashSetupData .authModeSetupData.authKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "Alloc and fill random failed for update authKey\n"); } } } } // Alloc additional auth data if (CPA_STATUS_SUCCESS == status) { if (setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes > 0) { if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) && (setup->setupData.hashSetupData.hashAlgorithm != CPA_CY_SYM_HASH_AES_GMAC)) { pAdditionalAuthData = qaeMemAllocNUMA(setup->setupData.hashSetupData .authModeSetupData.aadLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pAdditionalAuthData) { PRINT_ERR("Alloc and fill random failed for additional " "auth data\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { memset(pAdditionalAuthData, 0, setup->setupData.hashSetupData.authModeSetupData .aadLenInBytes); memcpy(&pAdditionalAuthData[1], &pIvBuffer[1], ivBufferLen); } } else { status = allocAndFillRandom(&pAdditionalAuthData, setup->setupData.hashSetupData .authModeSetupData.aadLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc and fill random failed for additional" "auth data\n"); } } } } // Session setup if (CPA_STATUS_SUCCESS == status) { sessionSetupData.symOperation = setup->setupData.symOperation; sessionSetupData.sessionPriority = setup->setupData.sessionPriority; sessionSetupData.partialsNotRequired = setup->setupData.partialsNotRequired; if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { sessionSetupData.cipherSetupData.cipherAlgorithm = setup->setupData.cipherSetupData.cipherAlgorithm; sessionSetupData.cipherSetupData.pCipherKey = pCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = setup->setupData.cipherSetupData.cipherKeyLenInBytes; sessionSetupData.cipherSetupData.cipherDirection = setup->setupData.cipherSetupData.cipherDirection; } if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { sessionSetupData.hashSetupData.hashAlgorithm = setup->setupData.hashSetupData.hashAlgorithm; sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH; sessionSetupData.hashSetupData.digestResultLenInBytes = setup->setupData.hashSetupData.digestResultLenInBytes; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = setup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes; sessionSetupData.digestIsAppended = CPA_TRUE; sessionSetupData.verifyDigest = CPA_FALSE; sessionSetupData.hashSetupData.authModeSetupData.authKey = pAuthKey; } if (setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { sessionSetupData.algChainOrder = setup->setupData.algChainOrder; } } // Get sessionCtx size if (CPA_STATUS_SUCCESS == status) { status = cpaCySymSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymSessionCtxGetSize failed with status: %d\n", status); } } // Alloc session ctx if (CPA_STATUS_SUCCESS == status) { sessionCtx = qaeMemAllocNUMA(sessionCtxSize, node, BYTE_ALIGNMENT_64); if (NULL == sessionCtx) { PRINT_ERR("Could not allocate pLocalSession memory\n"); status = CPA_STATUS_FAIL; } else { memset(sessionCtx, 0, sessionCtxSize); } } // Set sync mode if (CPA_STATUS_SUCCESS == status) { if (ASYNC == setup->syncMode) { pSymCb = symPerformCallback; } } // Init session if (CPA_STATUS_SUCCESS == status) { status = cpaCySymInitSession( cyInstHandle, pSymCb, &sessionSetupData, sessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymInitSession failed with status: %d\n", status); } } // Alloc pOpData if (CPA_STATUS_SUCCESS == status) { pOpData = qaeMemAllocNUMA((sizeof(CpaCySymOpData *) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (pOpData == NULL) { PRINT_ERR("Alloc pOpData buffer failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { pOpData[innerLoop] = qaeMemAllocNUMA( sizeof(CpaCySymOpData), node, BYTE_ALIGNMENT_64); if (NULL == pOpData[innerLoop]) { PRINT_ERR("Alloc pOpData buffer failed\n"); status = CPA_STATUS_FAIL; break; } opDataCnt++; } } } // Setup opData if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { pOpData[innerLoop]->sessionCtx = sessionCtx; pOpData[innerLoop]->packetType = CPA_CY_SYM_PACKET_TYPE_FULL; pOpData[innerLoop]->pIv = pIvBuffer; pOpData[innerLoop]->ivLenInBytes = ivBufferLen; pOpData[innerLoop]->cryptoStartSrcOffsetInBytes = 0; pOpData[innerLoop]->hashStartSrcOffsetInBytes = 0; pOpData[innerLoop]->messageLenToHashInBytes = srcBufferLen; pOpData[innerLoop]->messageLenToCipherInBytes = srcBufferLen; if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { pOpData[innerLoop]->pAdditionalAuthData = pAdditionalAuthData; } } } pSymData = setup->performanceStats; memset(pSymData, 0, sizeof(perf_data_t)); /* Init the semaphore used in the callback */ sampleCodeSemaphoreInit(&pSymData->comp, 0); // Perform op if (CPA_STATUS_SUCCESS == status) { /* Get the time, collect this only for the first * request, the callback collects it for the last */ pSymData->startCyclesTimestamp = sampleCodeTimestamp(); for (outerLoop = 0; outerLoop < setup->numLoops; outerLoop++) { if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER) { status = updatePerformCipher(setup, sessionCtx, &sessionUpdate, cyInstHandle, node, pSymData, pOpData, pSrcBufferList, pDstBufferList, &verifyResult, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("updatePerformCipher failed\n"); failCount++; } } else if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH) { status = updatePerformHash(setup, sessionCtx, &sessionUpdate, cyInstHandle, node, pSymData, pOpData, pSrcBufferList, pDstBufferList, &verifyResult, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("updatePerformHash failed\n"); failCount++; } } else if (setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { status = updatePerformAlgChain(setup, sessionCtx, &sessionUpdate, cyInstHandle, node, pSymData, pOpData, pSrcBufferList, pDstBufferList, &verifyResult, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("updatePerformAlgChain failed\n"); failCount++; } } } } /*clean up the callback semaphore*/ sampleCodeSemaphoreDestroy(&pSymData->comp); if (failCount > 0) { status = CPA_STATUS_FAIL; } // Remove session sessionStatus = removeSymSession(cyInstHandle, sessionCtx); if (sessionStatus != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymRemoveSession failed with status: %d\n", sessionStatus); } if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } // Free memory for (innerLoop = 0; innerLoop < srcBufferCnt; innerLoop++) { freeUpdateMem((void **)&pSrcBuffer[innerLoop]); } for (innerLoop = 0; innerLoop < srcBufferListCnt; innerLoop++) { freeUpdateMem((void **)&pSrcBufferList[innerLoop]); } for (innerLoop = 0; innerLoop < dstBufferCnt; innerLoop++) { freeUpdateMem((void **)&pDstBuffer[innerLoop]); } for (innerLoop = 0; innerLoop < dstBufferListCnt; innerLoop++) { freeUpdateMem((void **)&pDstBufferList[innerLoop]); } for (innerLoop = 0; innerLoop < opDataCnt; innerLoop++) { freeUpdateMem((void **)&pOpData[innerLoop]); } freeUpdateMem((void **)&pSrcBuffer); freeUpdateMem((void **)&pSrcBufferList); freeUpdateMem((void **)&pDstBuffer); freeUpdateMem((void **)&pDstBufferList); freeUpdateMem((void **)&pOpData); freeUpdateMem((void **)&pIvBuffer); freeUpdateMem((void **)&pCipherKey); freeUpdateMem((void **)&pUpdateCipherKey); freeUpdateMem((void **)&pAuthKey); freeUpdateMem((void **)&pUpdateAuthKey); freeUpdateMem((void **)&pAdditionalAuthData); freeUpdateMem((void **)&sessionCtx); return status; } static void sampleSymmetricUpdatePerformance( single_thread_test_data_t *testSetup) { symmetric_test_params_t updateTestSetup; symmetric_test_params_t *pSetup = ((symmetric_test_params_t *)testSetup->setupPtr); CpaStatus status = CPA_STATUS_SUCCESS; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; memset(&updateTestSetup, 0, sizeof(symmetric_test_params_t)); updateTestSetup.setupData = pSetup->setupData; updateTestSetup.performanceStats = testSetup->performanceStats; status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } updateTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; updateTestSetup.syncMode = pSetup->syncMode; updateTestSetup.flatBufferSizeInBytes = pSetup->flatBufferSizeInBytes; updateTestSetup.numBuffers = pSetup->numBuffers; updateTestSetup.numLoops = pSetup->numLoops; updateTestSetup.ivLength = pSetup->ivLength; PRINT("Thread %u, LI %u, ", testSetup->threadID, testSetup->logicalQaInstance); if (updateTestSetup.setupData.symOperation == CPA_CY_SYM_OP_CIPHER) { PRINT("Cipher "); printCipherAlg(updateTestSetup.setupData.cipherSetupData); } else if (updateTestSetup.setupData.symOperation == CPA_CY_SYM_OP_HASH) { PRINT("Hash "); printHashAlg(updateTestSetup.setupData.hashSetupData); } else if (updateTestSetup.setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { PRINT("AlgChain "); printCipherAlg(updateTestSetup.setupData.cipherSetupData); PRINT(" "); printHashAlg(updateTestSetup.setupData.hashSetupData); } PRINT("\n"); startBarrier(); status = updatePerform(&updateTestSetup); if (CPA_STATUS_SUCCESS != status) { updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; } qaeMemFree((void **)&cyInstances); sampleCodeThreadComplete(testSetup->threadID); } #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ CpaStatus setupSessionUpdateCipher(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops) { #if CY_API_VERSION_AT_LEAST(2, 2) return symSetupSessionUpdateTest(CPA_CY_SYM_OP_CIPHER, cipherAlgorithm, cipherKeyLen, 0, 0, 0, 0, 0, priority, syncMode, packetSize, numOfPacketsInBuffer, numBuffers, numLoops, CPA_FALSE, sampleSymmetricUpdatePerformance); #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } EXPORT_SYMBOL(setupSessionUpdateCipher); CpaStatus setupSessionUpdateHash(CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops) { #if CY_API_VERSION_AT_LEAST(2, 2) return symSetupSessionUpdateTest(CPA_CY_SYM_OP_HASH, 0, 0, hashAlgorithm, authKeyLen, hashMode, digestResultLenInBytes, 0, priority, syncMode, packetSize, numOfPacketsInBuffer, numBuffers, numLoops, CPA_FALSE, sampleSymmetricUpdatePerformance); #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } EXPORT_SYMBOL(setupSessionUpdateHash); CpaStatus setupSessionUpdateAlgChain(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops) { #if CY_API_VERSION_AT_LEAST(2, 2) return symSetupSessionUpdateTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlgorithm, cipherKeyLen, hashAlgorithm, authKeyLen, hashMode, digestResultLenInBytes, chainOrder, priority, syncMode, packetSize, numOfPacketsInBuffer, numBuffers, numLoops, CPA_FALSE, sampleSymmetricUpdatePerformance); #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } EXPORT_SYMBOL(setupSessionUpdateAlgChain); CpaStatus sessionUpdateTest(Cpa32U numLoops, Cpa32U numBuffers) { #if CY_API_VERSION_AT_LEAST(2, 2) CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U failCount = 0; Cpa32U cipher = 0; Cpa32U hash = 0; Cpa32U *coreMask = NULL; extern const Cpa32U algChainAlgs[][ALGCHAIN_HASH_NUM]; extern const testSetupCipher_t cipherSetup[ALGCHAIN_CIPHER_NUM]; extern const testSetupHash_t hashSetup[ALGCHAIN_HASH_NUM]; extern const Cpa32U cipherAlgs[CIPHER_ALG_NUM]; extern const Cpa32U hashAlgs[HASH_ALG_NUM]; // Run cipher tests for (cipher = 0; cipher < CIPHER_ALG_NUM; cipher++) { status = setupSessionUpdateCipher( cipherSetup[cipherAlgs[cipher]].cipherAlgorithm, cipherSetup[cipherAlgs[cipher]].cipherKeyLen, CPA_CY_PRIORITY_NORMAL, ASYNC, SIZE_BIT_IN_BYTES(768), 100, numBuffers, numLoops); if (CPA_STATUS_SUCCESS == status) { if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } coreMask = cyInstMap_g; status = createPerfomanceThreads(numInst_g, coreMask, numInst_g, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads\n"); return status; } status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT("Error starting threads\n"); return status; } status = waitForThreadCompletion(); if (CPA_STATUS_SUCCESS != status) { PRINT("Performance thread(s) failed\n"); failCount++; continue; } } else { PRINT("Error setup session"); failCount++; } } // Run hash tests for (hash = 0; hash < HASH_ALG_NUM; hash++) { status = setupSessionUpdateHash( hashSetup[hashAlgs[hash]].hashAlgorithm, hashSetup[hashAlgs[hash]].authKeyLen, CPA_CY_SYM_HASH_MODE_AUTH, hashSetup[hashAlgs[hash]].digestResultLenInBytes, CPA_CY_PRIORITY_NORMAL, ASYNC, SIZE_BIT_IN_BYTES(768), 100, numBuffers, numLoops); if (CPA_STATUS_SUCCESS == status) { if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } coreMask = cyInstMap_g; status = createPerfomanceThreads(numInst_g, coreMask, numInst_g, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads\n"); return status; } status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT("Error starting threads\n"); return status; } status = waitForThreadCompletion(); if (CPA_STATUS_SUCCESS != status) { PRINT("Performance thread(s) failed\n"); failCount++; continue; } } else { PRINT("Error setup session"); failCount++; } } // Run algchain tests for (cipher = 0; cipher < ALGCHAIN_CIPHER_NUM; cipher++) { for (hash = 0; hash < ALGCHAIN_HASH_NUM; hash++) { if (algChainAlgs[cipher][hash]) { status = setupSessionUpdateAlgChain( cipherSetup[cipher].cipherAlgorithm, cipherSetup[cipher].cipherKeyLen, hashSetup[hash].hashAlgorithm, hashSetup[hash].authKeyLen, CPA_CY_SYM_HASH_MODE_AUTH, hashSetup[hash].digestResultLenInBytes, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, SIZE_BIT_IN_BYTES(768), 100, numBuffers, numLoops); if (CPA_STATUS_SUCCESS == status) { if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } coreMask = cyInstMap_g; status = createPerfomanceThreads( numInst_g, coreMask, numInst_g, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads\n"); return status; } status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT("Error starting threads\n"); return status; } status = waitForThreadCompletion(); if (CPA_STATUS_SUCCESS != status) { PRINT("Performance thread(s) failed\n"); failCount++; continue; } } else { PRINT("Error setup session"); failCount++; } } } } if (failCount > 0) { status = CPA_STATUS_FAIL; } return status; #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } EXPORT_SYMBOL(sessionUpdateTest); cpa_sample_code_sym_update_common.c000066400000000000000000000433621503624047500400020ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sym_update.c * * @defgroup sampleSymmetricPerf Symmetric Performance code * * @ingroup sampleSymmetricPerf * * @description * This file contains the main symmetric session update performance * sample code. It is capable of performing all ciphers, all hashes, * authenticated hashes and algorithm chaining with session update * operation. * *****************************************************************************/ #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_framework.h" #include "icp_sal_poll.h" #include "cpa_cy_sym.h" #include "cpa_sample_code_framework.h" #include "cpa_sample_code_utils.h" #include "cpa_sample_code_utils_common.h" #include "cpa_sample_code_sym_update_common.h" #include "cpa.h" #include "cpa_cy_common.h" #include "cpa_cy_sym.h" #include "cpa_cy_sym_dp.h" #if CY_API_VERSION_AT_LEAST(2, 2) #ifdef SC_SYM_UPDATE_DISABLED CpaStatus cpaCySymUpdateSession( CpaCySymSessionCtx sessionCtx, const CpaCySymSessionUpdateData *pSessionUpdateData) { return CPA_STATUS_UNSUPPORTED; } #endif #ifdef SC_SYM_SESSION_INUSE_DISABLED CpaStatus cpaCySymSessionInUse(CpaCySymSessionCtx sessionCtx, CpaBoolean *pSessionInUse) { return CPA_STATUS_UNSUPPORTED; } #endif #endif #if CY_API_VERSION_AT_LEAST(2, 2) // Init variables #define CIPHER_ALGORITHM_LIST \ { { 0, 0 }, \ { CPA_CY_SYM_CIPHER_NULL, SIZE_BIT_IN_BYTES(128) }, \ { CPA_CY_SYM_CIPHER_ARC4, SIZE_BIT_IN_BYTES(128) }, \ { CPA_CY_SYM_CIPHER_AES_ECB, SIZE_BIT_IN_BYTES(192) }, \ { CPA_CY_SYM_CIPHER_AES_CBC, SIZE_BIT_IN_BYTES(256) }, \ { CPA_CY_SYM_CIPHER_AES_CTR, SIZE_BIT_IN_BYTES(128) }, \ { CPA_CY_SYM_CIPHER_AES_CCM, SIZE_BIT_IN_BYTES(128) }, \ { CPA_CY_SYM_CIPHER_AES_GCM, SIZE_BIT_IN_BYTES(128) }, \ { CPA_CY_SYM_CIPHER_DES_ECB, SIZE_BIT_IN_BYTES(64) }, \ { CPA_CY_SYM_CIPHER_DES_CBC, SIZE_BIT_IN_BYTES(64) }, \ { CPA_CY_SYM_CIPHER_3DES_ECB, SIZE_BIT_IN_BYTES(192) }, \ { CPA_CY_SYM_CIPHER_3DES_CBC, SIZE_BIT_IN_BYTES(192) }, \ { CPA_CY_SYM_CIPHER_3DES_CTR, SIZE_BIT_IN_BYTES(192) }, \ { CPA_CY_SYM_CIPHER_KASUMI_F8, SIZE_BIT_IN_BYTES(128) }, \ { CPA_CY_SYM_CIPHER_SNOW3G_UEA2, SIZE_BIT_IN_BYTES(128) }, \ { CPA_CY_SYM_CIPHER_AES_F8, SIZE_BIT_IN_BYTES(256) }, \ { CPA_CY_SYM_CIPHER_AES_XTS, SIZE_BIT_IN_BYTES(256) }, \ { CPA_CY_SYM_CIPHER_ZUC_EEA3, SIZE_BIT_IN_BYTES(128) } }; #define HASH_ALGORITHM_LIST \ { { CPA_CY_SYM_HASH_NONE, SIZE_BIT_IN_BYTES(512), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_MD5, SIZE_BIT_IN_BYTES(192), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_SHA1, SIZE_BIT_IN_BYTES(128), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_SHA224, SIZE_BIT_IN_BYTES(224), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_SHA256, SIZE_BIT_IN_BYTES(256), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_SHA384, SIZE_BIT_IN_BYTES(384), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_SHA512, SIZE_BIT_IN_BYTES(512), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_AES_XCBC, SIZE_BIT_IN_BYTES(128), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_AES_CCM, SIZE_BIT_IN_BYTES(512), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_AES_GCM, SIZE_BIT_IN_BYTES(512), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_KASUMI_F9, SIZE_BIT_IN_BYTES(128), DIGEST_LENGTH_4 }, \ { CPA_CY_SYM_HASH_SNOW3G_UIA2, \ SIZE_BIT_IN_BYTES(128), \ DIGEST_LENGTH_4 }, \ { CPA_CY_SYM_HASH_AES_CMAC, SIZE_BIT_IN_BYTES(128), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_AES_GMAC, SIZE_BIT_IN_BYTES(512), DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_AES_CBC_MAC, \ SIZE_BIT_IN_BYTES(128), \ DIGEST_LENGTH_16 }, \ { CPA_CY_SYM_HASH_ZUC_EIA3, SIZE_BIT_IN_BYTES(128), DIGEST_LENGTH_4 }, \ { CPA_CY_SYM_HASH_SHA3_256, \ SIZE_BIT_IN_BYTES(128), \ DIGEST_LENGTH_16 } }; #define ALGORITHM_CHAIN_BIT_MASK \ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, \ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, \ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, \ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 } }; #define CIPHER_ALGORITHM_NUM \ { 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; #define HASH_ALGORITHM_NUM { 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, 15, 16 }; const testSetupCipher_t cipherSetup[ALGCHAIN_CIPHER_NUM] = CIPHER_ALGORITHM_LIST; const testSetupHash_t hashSetup[ALGCHAIN_HASH_NUM] = HASH_ALGORITHM_LIST; const Cpa32U algChainAlgs[][ALGCHAIN_HASH_NUM] = ALGORITHM_CHAIN_BIT_MASK; const Cpa32U cipherAlgs[CIPHER_ALG_NUM] = CIPHER_ALGORITHM_NUM; const Cpa32U hashAlgs[HASH_ALG_NUM] = HASH_ALGORITHM_NUM; extern CpaStatus getCryptoInstanceMapping(void); extern Cpa16U numInstances_g; extern Cpa32U *cyInstMap_g; extern Cpa32U *dcInstMap_g; extern Cpa32U instMap_g; extern Cpa16U numInst_g; extern CpaBoolean usePartial_g; // Configure session update data void setupUpdateData(CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pUpdateData, Cpa8U **pUpdateCipherKey, Cpa8U **pUpdateHashKey, CpaBoolean updateCipherDirection) { pUpdateData->flags = 0; if (pUpdateCipherKey != NULL) { pUpdateData->flags |= CPA_CY_SYM_SESUPD_CIPHER_KEY; pUpdateData->pCipherKey = *pUpdateCipherKey; } if (pUpdateHashKey != NULL) { pUpdateData->flags |= CPA_CY_SYM_SESUPD_AUTH_KEY; pUpdateData->authKey = *pUpdateHashKey; } if (updateCipherDirection) { pUpdateData->flags |= CPA_CY_SYM_SESUPD_CIPHER_DIR; if (pUpdateData->cipherDirection != CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT) { pUpdateData->cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; } else { pUpdateData->cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; } } } CpaStatus allocAndFillRandom(Cpa8U **pBuff, Cpa32U len, Cpa32U node) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa8U *pBufferTemp = NULL; pBufferTemp = qaeMemAllocNUMA(len, node, BYTE_ALIGNMENT_64); if (NULL == pBufferTemp) { PRINT("Error allocating memory\n"); status = CPA_STATUS_FAIL; } else { generateRandomData(pBufferTemp, len); } *pBuff = pBufferTemp; return status; } void freeUpdateMem(void **mem) { if (NULL != mem && NULL != *mem) { qaeMemFreeNUMA(mem); } } // Setup buffer list function CpaStatus setupBufferList(Cpa8U **pBuff, Cpa32U numBuff, Cpa32U bufferSize, CpaBufferList **pSrcBuffer, Cpa32U node) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U bufferMetaSize = 0; Cpa32U bufferListSize = 0; Cpa32U bufferDescTotalSize = 0; Cpa8U *pBufferMem = NULL; CpaInstanceHandle cyInstHandle = CPA_INSTANCE_HANDLE_SINGLE; Cpa32U i = 0; status = cpaCyBufferListGetMetaSize(cyInstHandle, 1, &bufferMetaSize); if (CPA_STATUS_SUCCESS == status) { bufferListSize = sizeof(CpaBufferList) + (numBuff * sizeof(CpaFlatBuffer)); bufferDescTotalSize = bufferMetaSize + bufferListSize; pBufferMem = qaeMemAllocNUMA(bufferDescTotalSize, node, BYTE_ALIGNMENT_64); if (NULL == pBufferMem) { status = CPA_STATUS_FAIL; } } if (CPA_STATUS_SUCCESS == status) { CpaBufferList *pTmpBufList = (CpaBufferList *)pBufferMem; pTmpBufList->numBuffers = numBuff; pTmpBufList->pPrivateMetaData = pBufferMem + bufferListSize; pTmpBufList->pBuffers = (CpaFlatBuffer *)(pBufferMem + sizeof(CpaBufferList)); for (i = 0; i < numBuff; i++) { pTmpBufList->pBuffers[i].pData = pBuff[i]; pTmpBufList->pBuffers[i].dataLenInBytes = bufferSize; } *pSrcBuffer = pTmpBufList; } return status; } CpaStatus symSetupSessionUpdateTest(CpaCySymOp symOperation, CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCySymAlgChainOrder algChainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops, CpaBoolean isDpApi, void *samplePerformanceFunction) { symmetric_test_params_t *updateSetup = NULL; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Failed to start Crypto services\n"); return CPA_STATUS_FAIL; } if (!poll_inline_g && !isDpApi) { /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } if ((symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING || symOperation == CPA_CY_SYM_OP_HASH) && hashMode != CPA_CY_SYM_HASH_MODE_AUTH) { PRINT_ERR("Unsupported hash mode\n"); return CPA_STATUS_FAIL; } updateSetup = (symmetric_test_params_t *)&thread_setup_g[testTypeCount_g][0]; memset(updateSetup, 0, sizeof(symmetric_test_params_t)); testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)samplePerformanceFunction; updateSetup->setupData.sessionPriority = priority; updateSetup->setupData.symOperation = symOperation; updateSetup->setupData.algChainOrder = algChainOrder; updateSetup->setupData.cipherSetupData.cipherAlgorithm = cipherAlgorithm; updateSetup->setupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; updateSetup->setupData.cipherSetupData.cipherKeyLenInBytes = cipherKeyLen; updateSetup->setupData.hashSetupData.hashAlgorithm = hashAlgorithm; updateSetup->setupData.hashSetupData.hashMode = hashMode; updateSetup->setupData.hashSetupData.digestResultLenInBytes = digestResultLenInBytes; updateSetup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes = authKeyLen; updateSetup->flatBufferSizeInBytes = packetSize; updateSetup->numBuffers = numBuffers; updateSetup->numLoops = numLoops; updateSetup->syncMode = syncMode; updateSetup->isDpApi = isDpApi; /* Set partialsNotRequired to TRUE for default case */ updateSetup->setupData.partialsNotRequired = CPA_TRUE; if (cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CTR || cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CBC || cipherAlgorithm == CPA_CY_SYM_CIPHER_SNOW3G_UEA2 || cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_F8 || cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_XTS || cipherAlgorithm == CPA_CY_SYM_CIPHER_ZUC_EEA3) { updateSetup->ivLength = IV_LEN_FOR_16_BYTE_BLOCK_CIPHER; } else if (cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) { updateSetup->ivLength = IV_LEN_FOR_16_BYTE_GCM; } else { updateSetup->ivLength = IV_LEN_FOR_8_BYTE_BLOCK_CIPHER; } if (hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3 || hashAlgorithm == CPA_CY_SYM_HASH_SNOW3G_UIA2) { updateSetup->setupData.hashSetupData.authModeSetupData.aadLenInBytes = KEY_SIZE_128_IN_BYTES; } else if (hashAlgorithm == CPA_CY_SYM_HASH_AES_GCM || hashAlgorithm == CPA_CY_SYM_HASH_AES_CCM) { updateSetup->setupData.hashSetupData.authModeSetupData.aadLenInBytes = AES_CCM_MIN_AAD_ALLOC_LENGTH; } else { updateSetup->setupData.hashSetupData.authModeSetupData.aadLenInBytes = 0; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(symSetupSessionUpdateTest); #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ cpa_sample_code_sym_update_common.h000066400000000000000000000153531503624047500400060ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sym_update.c * * @defgroup sampleSymmetricPerf Symmetric Performance code * * @ingroup sampleSymmetricPerf * * @description * This file contains the main symmetric session update performance * sample code. It is capable of performing all ciphers, all hashes, * authenticated hashes and algorithm chaining with session update * operation. * *****************************************************************************/ #ifndef CPA_SAMPLE_CODE_SYM_UPDATE_COMMON_H_ #define CPA_SAMPLE_CODE_SYM_UPDATE_COMMON_H_ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_cy_sym_dp.h" #include "icp_sal_poll.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_framework.h" #include "cpa_sample_code_framework.h" #include "cpa_sample_code_utils.h" #include "cpa_sample_code_utils_common.h" #include "cpa_cy_common.h" #define CIPHER_ALG_NUM (15) #define HASH_ALG_NUM (13) #define ALGCHAIN_CIPHER_NUM (18) #define ALGCHAIN_HASH_NUM (17) #define SIZE_BIT_IN_BYTES(bits) ((bits + 7) / 8) #define DIGEST_LENGTH_16 (16) #define DIGEST_LENGTH_4 (4) #define DIGEST_LENGTH_8 (8) #if CY_API_VERSION_AT_LEAST(2, 2) // Test config struct typedef struct testSetupCipher_s { CpaCySymCipherAlgorithm cipherAlgorithm; Cpa32U cipherKeyLen; } testSetupCipher_t; typedef struct testSetupHash_s { CpaCySymHashAlgorithm hashAlgorithm; Cpa32U authKeyLen; Cpa32U digestResultLenInBytes; } testSetupHash_t; extern CpaStatus getCryptoInstanceMapping(void); extern Cpa16U numInstances_g; extern Cpa32U *cyInstMap_g; extern Cpa32U *dcInstMap_g; extern Cpa32U instMap_g; extern Cpa16U numInst_g; extern CpaBoolean usePartial_g; void symUpdateCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult); void symDpUpdateCallback(CpaCySymDpOpData *pOpData, CpaStatus status, CpaBoolean verifyResult); void sessionUpdatePrintStatsDp(thread_creation_data_t *data); CpaStatus allocAndFillRandom(Cpa8U **pBuff, Cpa32U len, Cpa32U node); void freeUpdateMem(void **mem); CpaStatus setupBufferList(Cpa8U **pBuff, Cpa32U numBuff, Cpa32U bufferSize, CpaBufferList **pSrcBuffer, Cpa32U node); void setupUpdateData(CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pUpdateData, Cpa8U **pUpdateCipherKey, Cpa8U **pUpdateHashKey, CpaBoolean updateCipherDirection); CpaStatus symSetupSessionUpdateTest(CpaCySymOp symOperation, CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCySymAlgChainOrder algChainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops, CpaBoolean isDpApi, void *samplePerformanceFunction); #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ #endif /* CPA_SAMPLE_CODE_SYM_UPDATE_COMMON_H_ */ cpa_sample_code_sym_update_dp.c000066400000000000000000002102621503624047500371100ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_sym_update_sp.c * * @defgroup sampleSymmetricDpPerf Symmetric Data Plane Performance code * * @ingroup sampleSymmetricDpPerf * * @description * This file contains the main symmetric Data Plane session update * performance sample code. It is capable of performing all ciphers, * all hashes, authenticated hashes and algorithm chaining with session * update operation. * *****************************************************************************/ #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_cy_sym_dp.h" #include "icp_sal_poll.h" #include "cpa_sample_code_crypto_utils.h" #include "cpa_sample_code_framework.h" #include "cpa_sample_code_framework.h" #include "cpa_sample_code_utils.h" #include "cpa_sample_code_utils_common.h" #include "cpa_cy_common.h" #include "cpa_sample_code_sym_update_common.h" #include "qat_perf_buffer_utils.h" #define SYM_DP_OPS_DEFAULT_POLLING_INTERVAL (16) Cpa32U symDpPollingInterval_g = SYM_DP_OPS_DEFAULT_POLLING_INTERVAL; #if CY_API_VERSION_AT_LEAST(2, 2) static void symDpPerformUpdateCallback(CpaCySymDpOpData *pOpData, CpaStatus status, CpaBoolean verifyResult) { /* pCallbacktag in the pOpData structure is used to store * index of to the perf_data_t associated the thread */ perf_data_t *pPerfData = pOpData->pCallbackTag; pPerfData->responses++; /*if we have received the pre-set numOperations, then get the clock cycle * as a timestamp and post the Semaphore to release parent thread */ if (pPerfData->numOperations == pPerfData->responses) { pPerfData->endCyclesTimestamp = sampleCodeTimestamp(); } } // Perform verify static CpaStatus performOpAndVerifyDp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, symmetric_test_params_t *setup, CpaCySymSessionUpdateData *pSessionUpdate, Cpa32U node, perf_data_t *pSymData, Cpa8U **pSrcBuffer, Cpa8U **pDstBuffer, CpaCySymDpOpData **pOpData, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U failCount = 0; Cpa32U innerLoop = 0; CpaBoolean sessionInUse = CPA_FALSE; CpaBoolean performNow = CPA_FALSE; Cpa64U numOps = 0; Cpa64U nextPoll = symDpPollingInterval_g; CpaInstanceInfo2 *instanceInfo2 = NULL; instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); // Get instance info status = cpaCyInstanceGetInfo2(cyInstHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return status; } // Perform setup->performanceStats->numOperations += setup->numBuffers; for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { if (innerLoop == setup->numBuffers - 1) { performNow = CPA_TRUE; } else { performNow = CPA_FALSE; } do { status = cpaCySymDpEnqueueOp(pOpData[innerLoop], performNow); if (CPA_STATUS_RETRY == status) { pSymData->retries++; pSymData->pollCount++; if (CPA_TRUE == instanceInfo2->isPolled) { icp_sal_CyPollDpInstance(setup->cyInstanceHandle, 0); } nextPoll = numOps + symDpPollingInterval_g; AVOID_SOFTLOCKUP; } } while (status == CPA_STATUS_RETRY); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpPerformOp failed\n"); failCount++; } ++numOps; if (numOps == nextPoll) { if (CPA_TRUE == instanceInfo2->isPolled) { icp_sal_CyPollDpInstance(setup->cyInstanceHandle, 0); } nextPoll = numOps + symDpPollingInterval_g; } } // Wait for completion if (CPA_STATUS_SUCCESS == status) { status = cyDpPollRemainingOperations(setup->performanceStats, cyInstHandle); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cyDpPollRemainingOperations: failed\n"); } } do { status = cpaCySymSessionInUse(sessionCtx, &sessionInUse); if (status == CPA_STATUS_FAIL) { PRINT_ERR("cpaCySymSessionInUse: failed\n"); break; } AVOID_SOFTLOCKUP; } while (sessionInUse == CPA_TRUE); if (failCount > 0) { status = CPA_STATUS_FAIL; } return status; } // Perform for cipher session static CpaStatus updatePerformCipherDp( symmetric_test_params_t *setup, CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pSessionUpdate, CpaInstanceHandle cyInstHandle, Cpa32U node, perf_data_t *pSymData, CpaCySymDpOpData **pOpData, Cpa8U **pSrcBuffer, Cpa8U **pDstBuffer, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus updateStatus = CPA_STATUS_SUCCESS; status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData(sessionCtx, pSessionUpdate, NULL, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pCipherKey, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS != updateStatus) { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } return status; } // Perform for hash session static CpaStatus updatePerformHashDp(symmetric_test_params_t *setup, CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pSessionUpdate, CpaInstanceHandle cyInstHandle, Cpa32U node, perf_data_t *pSymData, CpaCySymDpOpData **pOpData, Cpa8U **pSrcBuffer, Cpa8U **pDstBuffer, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus updateStatus = CPA_STATUS_SUCCESS; status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pUpdateAuthKey, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS != status) { setupUpdateData(sessionCtx, pSessionUpdate, NULL, &pAuthKey, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS != updateStatus) { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } return status; } // Perform for alg chain session static CpaStatus updatePerformAlgChainDp( symmetric_test_params_t *setup, CpaCySymSessionCtx sessionCtx, CpaCySymSessionUpdateData *pSessionUpdate, CpaInstanceHandle cyInstHandle, Cpa32U node, perf_data_t *pSymData, CpaCySymDpOpData **pOpData, Cpa8U **pSrcBuffer, Cpa8U **pDstBuffer, Cpa8U *pCipherKey, Cpa8U *pUpdateCipherKey, Cpa8U *pAuthKey, Cpa8U *pUpdateAuthKey, Cpa8U *pAdditionalAuthData, Cpa8U *pIvBuffer) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus updateStatus = CPA_STATUS_SUCCESS; status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_FALSE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pUpdateAuthKey, CPA_FALSE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { updateStatus = CPA_STATUS_UNSUPPORTED; } else { // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pAuthKey, CPA_FALSE); } else { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData(sessionCtx, pSessionUpdate, NULL, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pCipherKey, &pAuthKey, CPA_FALSE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { updateStatus = CPA_STATUS_UNSUPPORTED; } else { updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData(sessionCtx, pSessionUpdate, &pUpdateCipherKey, &pUpdateAuthKey, CPA_FALSE); } else { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pUpdateAuthKey, CPA_TRUE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { updateStatus = CPA_STATUS_UNSUPPORTED; } else { updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData( sessionCtx, pSessionUpdate, NULL, &pAuthKey, CPA_TRUE); } else { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_TRUE); // Update session updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); if (CPA_STATUS_SUCCESS == updateStatus) { status = performOpAndVerifyDp(cyInstHandle, sessionCtx, setup, pSessionUpdate, node, pSymData, pSrcBuffer, pDstBuffer, pOpData, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("performOpAndVerify failed\n"); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } // Setup update data if (CPA_STATUS_SUCCESS == status) { setupUpdateData( sessionCtx, pSessionUpdate, &pCipherKey, &pAuthKey, CPA_TRUE); /* Skip invalid case with auth key update on AES_CCM AES_GCM algchain * algorithm */ if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM || setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_GCM) && (pSessionUpdate->flags & CPA_CY_SYM_SESUPD_AUTH_KEY)) { updateStatus = CPA_STATUS_UNSUPPORTED; } else { updateStatus = cpaCySymUpdateSession(sessionCtx, pSessionUpdate); } if (CPA_STATUS_UNSUPPORTED == updateStatus || CPA_STATUS_SUCCESS == updateStatus) { if (CPA_STATUS_UNSUPPORTED == updateStatus) { setupUpdateData(sessionCtx, pSessionUpdate, &pUpdateCipherKey, NULL, CPA_TRUE); } } else { PRINT_ERR("Update session failed\n"); status = CPA_STATUS_FAIL; } } return status; } static CpaStatus updatePerformDp(symmetric_test_params_t *setup) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus sessionStatus = CPA_STATUS_SUCCESS; Cpa32U node = 0; CpaInstanceInfo2 *instanceInfo2 = NULL; CpaInstanceHandle cyInstHandle = setup->cyInstanceHandle; Cpa8U *pIvBuffer = NULL; Cpa32U ivBufferLen = setup->ivLength; Cpa8U **pSrcBuffer = NULL; Cpa8U **pDstBuffer = NULL; Cpa32U srcBufferLen = setup->flatBufferSizeInBytes; Cpa32U dstBufferLen = setup->flatBufferSizeInBytes; CpaCySymDpOpData **pOpData = NULL; Cpa32U sessionCtxSize = 0; CpaCySymSessionCtx sessionCtx = NULL; CpaCySymSessionSetupData sessionSetupData = {0}; perf_data_t *pSymData = NULL; Cpa8U *pCipherKey = NULL; Cpa8U *pUpdateCipherKey = NULL; Cpa8U *pAuthKey = NULL; Cpa8U *pUpdateAuthKey = NULL; Cpa8U *pAdditionalAuthData = NULL; Cpa32U innerLoop = 0; Cpa32U outerLoop = 0; Cpa32U failCount = 0; CpaCySymSessionUpdateData sessionUpdate = {0}; CpaCySymCapabilitiesInfo capInfo; Cpa32U srcBufferCnt = 0; Cpa32U dstBufferCnt = 0; Cpa32U opDataCnt = 0; sampleCodeBarrier(); cpaCySymQueryCapabilities(cyInstHandle, &capInfo); if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { /* For cipher, check if cipher algorithm is correct */ if (!CPA_BITMAP_BIT_TEST( capInfo.ciphers, setup->setupData.cipherSetupData.cipherAlgorithm)) { PRINT("Cipher "); printCipherAlg(setup->setupData.cipherSetupData); PRINT(" is not supported on device. Marking as SUCCESS\n"); return CPA_STATUS_SUCCESS; } } if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { /* For cipher, check if hash algorithm is correct */ if (!CPA_BITMAP_BIT_TEST(capInfo.hashes, setup->setupData.hashSetupData.hashAlgorithm)) { PRINT("Hash "); printHashAlg(setup->setupData.hashSetupData); PRINT(" is not supported on device. Marking as SUCCESS\n"); return CPA_STATUS_SUCCESS; } } instanceInfo2 = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo2 == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo2"); return CPA_STATUS_FAIL; } memset(instanceInfo2, 0, sizeof(CpaInstanceInfo2)); // Get instance info status = cpaCyInstanceGetInfo2(cyInstHandle, instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); qaeMemFree((void **)&instanceInfo2); return status; } qaeMemFree((void **)&instanceInfo2); // Get node status = sampleCodeCyGetNode(cyInstHandle, &node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("sampleCodeCyGetNode failed with status %u\n", status); return status; } // Alloc src if (CPA_STATUS_SUCCESS == status) { pSrcBuffer = qaeMemAllocNUMA( (sizeof(Cpa8U *) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (NULL == pSrcBuffer) { PRINT_ERR("Alloc Src buffer failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { // Alloc src buffer pSrcBuffer[innerLoop] = qaeMemAllocNUMA( srcBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes, node, BYTE_ALIGNMENT_64); if (pSrcBuffer[innerLoop] == NULL) { PRINT_ERR("Alloc Src buffer failed\n"); status = CPA_STATUS_FAIL; break; } else { generateRandomData(pSrcBuffer[innerLoop], srcBufferLen); } srcBufferCnt++; } } } // Alloc dst buffer list if (CPA_STATUS_SUCCESS == status) { pDstBuffer = qaeMemAllocNUMA( sizeof(Cpa8U *) * setup->numBuffers, node, BYTE_ALIGNMENT_64); if (NULL == pDstBuffer) { PRINT_ERR("Alloc Dst buffer failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { // Alloc dst buffer pDstBuffer[innerLoop] = qaeMemAllocNUMA( dstBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pDstBuffer[innerLoop]) { PRINT_ERR("Alloc Dst buffer failed\n"); status = CPA_STATUS_FAIL; break; } dstBufferCnt++; } } } if (CPA_STATUS_SUCCESS == status) { // Alloc cipherkey & update cipherkey if (setup->setupData.cipherSetupData.cipherKeyLenInBytes > 0) { status = allocAndFillRandom( &pCipherKey, setup->setupData.cipherSetupData.cipherKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc and fill random failed for cipherKey\n"); } else { status = allocAndFillRandom( &pUpdateCipherKey, setup->setupData.cipherSetupData.cipherKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "Alloc and fill random failed for update cipherKey\n"); } } } } // Alloc IV if (CPA_STATUS_SUCCESS == status) { if (ivBufferLen > 0) { if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { /* Although the IV data length for CCM must be 16 bytes, * the nonce length must be between 7 and 13 inclusive */ ivBufferLen = AES_CCM_DEFAULT_NONCE_LENGTH; setup->ivLength = AES_CCM_DEFAULT_NONCE_LENGTH; pIvBuffer = qaeMemAllocNUMA(ivBufferLen, node, BYTE_ALIGNMENT_64); if (NULL == pIvBuffer) { PRINT_ERR("Alloc iv failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { memset(pIvBuffer, 0, ivBufferLen); /*generate a random IV*/ generateRandomData(&pIvBuffer[1], ivBufferLen); } } else { status = allocAndFillRandom(&pIvBuffer, ivBufferLen, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc iv failed with status %u\n", status); } } } else { PRINT_ERR("Invalid iv buffer length\n"); status = CPA_STATUS_FAIL; } } // Alloc authkey & update authkey if (CPA_STATUS_SUCCESS == status) { if (setup->setupData.hashSetupData.authModeSetupData.authKeyLenInBytes > 0) { status = allocAndFillRandom(&pAuthKey, setup->setupData.hashSetupData .authModeSetupData.authKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc and fill random failed for authKey\n"); } if (CPA_STATUS_SUCCESS == status) { status = allocAndFillRandom(&pUpdateAuthKey, setup->setupData.hashSetupData .authModeSetupData.authKeyLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "Alloc and fill random failed for update authKey\n"); } } } } // Alloc additional auth data if (CPA_STATUS_SUCCESS == status) { if (setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes > 0) { if ((setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) && (setup->setupData.hashSetupData.hashAlgorithm != CPA_CY_SYM_HASH_AES_GMAC)) { pAdditionalAuthData = qaeMemAllocNUMA(setup->setupData.hashSetupData .authModeSetupData.aadLenInBytes, node, BYTE_ALIGNMENT_64); if (NULL == pAdditionalAuthData) { PRINT_ERR("Alloc and fill random failed for additional " "auth data\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { memset(pAdditionalAuthData, 0, setup->setupData.hashSetupData.authModeSetupData .aadLenInBytes); memcpy(&pAdditionalAuthData[1], &pIvBuffer[1], ivBufferLen); } } else { status = allocAndFillRandom(&pAdditionalAuthData, setup->setupData.hashSetupData .authModeSetupData.aadLenInBytes, node); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Alloc and fill random failed for additional" "auth data\n"); } } } } // Session setup if (CPA_STATUS_SUCCESS == status) { sessionSetupData.symOperation = setup->setupData.symOperation; sessionSetupData.sessionPriority = setup->setupData.sessionPriority; sessionSetupData.partialsNotRequired = setup->setupData.partialsNotRequired; if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { sessionSetupData.cipherSetupData.cipherAlgorithm = setup->setupData.cipherSetupData.cipherAlgorithm; sessionSetupData.cipherSetupData.pCipherKey = pCipherKey; sessionSetupData.cipherSetupData.cipherKeyLenInBytes = setup->setupData.cipherSetupData.cipherKeyLenInBytes; sessionSetupData.cipherSetupData.cipherDirection = setup->setupData.cipherSetupData.cipherDirection; } if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { sessionSetupData.hashSetupData.hashAlgorithm = setup->setupData.hashSetupData.hashAlgorithm; sessionSetupData.hashSetupData.hashMode = setup->setupData.hashSetupData.hashMode; sessionSetupData.hashSetupData.digestResultLenInBytes = setup->setupData.hashSetupData.digestResultLenInBytes; sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = setup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes; sessionSetupData.hashSetupData.authModeSetupData.aadLenInBytes = setup->setupData.hashSetupData.authModeSetupData.aadLenInBytes; sessionSetupData.digestIsAppended = CPA_FALSE; sessionSetupData.verifyDigest = CPA_FALSE; sessionSetupData.hashSetupData.authModeSetupData.authKey = pAuthKey; } if (setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { sessionSetupData.algChainOrder = setup->setupData.algChainOrder; } if ((setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) && (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM)) { sessionSetupData.digestIsAppended = CPA_TRUE; } } // Get sessionCtx size if (CPA_STATUS_SUCCESS == status) { status = cpaCySymDpSessionCtxGetSize( cyInstHandle, &sessionSetupData, &sessionCtxSize); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpSessionCtxGetSize failed with status: %d\n", status); } } // Alloc session ctx if (CPA_STATUS_SUCCESS == status) { sessionCtx = qaeMemAllocNUMA(sessionCtxSize, node, BYTE_ALIGNMENT_64); if (NULL == sessionCtx) { PRINT_ERR("Could not allocate pLocalSession memory\n"); status = CPA_STATUS_FAIL; } else { memset(sessionCtx, 0, sessionCtxSize); } } // Init session if (CPA_STATUS_SUCCESS == status) { status = cpaCySymDpInitSession(cyInstHandle, &sessionSetupData, sessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpInitSession failed with status: %d\n", status); } } // Alloc pOpData if (CPA_STATUS_SUCCESS == status) { pOpData = qaeMemAllocNUMA((sizeof(CpaCySymDpOpData *) * setup->numBuffers), node, BYTE_ALIGNMENT_64); if (NULL == pOpData) { PRINT_ERR("Alloc pOpData buffer failed\n"); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { pOpData[innerLoop] = qaeMemAllocNUMA( sizeof(CpaCySymDpOpData), node, BYTE_ALIGNMENT_64); if (NULL == pOpData[innerLoop]) { PRINT_ERR("Alloc pOpData buffer failed\n"); status = CPA_STATUS_FAIL; break; } /* Zero initialize Op data structure*/ memset(pOpData[innerLoop], 0, sizeof(CpaCySymDpOpData)); opDataCnt++; } } } // Setup opData if (CPA_STATUS_SUCCESS == status) { for (innerLoop = 0; innerLoop < setup->numBuffers; innerLoop++) { pOpData[innerLoop]->thisPhys = (CpaPhysicalAddr)virtAddrToDevAddr( pOpData[innerLoop], cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData[innerLoop]->instanceHandle = cyInstHandle; pOpData[innerLoop]->sessionCtx = sessionCtx; pOpData[innerLoop]->pCallbackTag = setup->performanceStats; pOpData[innerLoop]->cryptoStartSrcOffsetInBytes = 0; pOpData[innerLoop]->hashStartSrcOffsetInBytes = 0; pOpData[innerLoop]->messageLenToHashInBytes = srcBufferLen; pOpData[innerLoop]->messageLenToCipherInBytes = srcBufferLen; pOpData[innerLoop]->srcBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( pSrcBuffer[innerLoop], cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData[innerLoop]->srcBufferLen = srcBufferLen; pOpData[innerLoop]->dstBuffer = (CpaPhysicalAddr)virtAddrToDevAddr( pDstBuffer[innerLoop], cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData[innerLoop]->dstBufferLen = dstBufferLen; if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { pOpData[innerLoop]->iv = (CpaPhysicalAddr)virtAddrToDevAddr( pIvBuffer, cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData[innerLoop]->pIv = pIvBuffer; pOpData[innerLoop]->ivLenInBytes = ivBufferLen; } if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH || setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { if (NULL != pAdditionalAuthData) { pOpData[innerLoop]->additionalAuthData = (CpaPhysicalAddr)virtAddrToDevAddr( pAdditionalAuthData, cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO); pOpData[innerLoop]->pAdditionalAuthData = pAdditionalAuthData; } else { pOpData[innerLoop]->additionalAuthData = (CpaPhysicalAddr)(uintptr_t)NULL; pOpData[innerLoop]->pAdditionalAuthData = NULL; } pOpData[innerLoop]->digestResult = (CpaPhysicalAddr)virtAddrToDevAddr( pDstBuffer[innerLoop], cyInstHandle, CPA_ACC_SVC_TYPE_CRYPTO) + dstBufferLen; pOpData[innerLoop]->srcBufferLen = srcBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes; pOpData[innerLoop]->dstBufferLen = dstBufferLen + setup->setupData.hashSetupData.digestResultLenInBytes; } if (setup->setupData.cipherSetupData.cipherAlgorithm == CPA_CY_SYM_CIPHER_AES_CCM) { pOpData[innerLoop]->digestResult = (CpaPhysicalAddr)CPA_TRUE; } } } // Register Callback if (CPA_STATUS_SUCCESS == status) { if (setup->syncMode == ASYNC) { status = cpaCySymDpRegCbFunc( cyInstHandle, (CpaCySymDpCbFunc)symDpPerformUpdateCallback); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymDpRegCbFunc failed with status %u\n", status); } } } // Perform op if (CPA_STATUS_SUCCESS == status) { pSymData = setup->performanceStats; memset(pSymData, 0, sizeof(perf_data_t)); /* Get the time, collect this only for the first * request, the callback collects it for the last */ pSymData->startCyclesTimestamp = sampleCodeTimestamp(); for (outerLoop = 0; outerLoop < setup->numLoops; outerLoop++) { if (setup->setupData.symOperation == CPA_CY_SYM_OP_CIPHER) { status = updatePerformCipherDp(setup, sessionCtx, &sessionUpdate, cyInstHandle, node, pSymData, pOpData, pSrcBuffer, pDstBuffer, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("updatePerformCipherDp failed\n"); failCount++; } } else if (setup->setupData.symOperation == CPA_CY_SYM_OP_HASH) { status = updatePerformHashDp(setup, sessionCtx, &sessionUpdate, cyInstHandle, node, pSymData, pOpData, pSrcBuffer, pDstBuffer, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("updatePerformHashDp failed\n"); failCount++; } } else if (setup->setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { status = updatePerformAlgChainDp(setup, sessionCtx, &sessionUpdate, cyInstHandle, node, pSymData, pOpData, pSrcBuffer, pDstBuffer, pCipherKey, pUpdateCipherKey, pAuthKey, pUpdateAuthKey, pAdditionalAuthData, pIvBuffer); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("updatePerformAlgChainDp failed\n"); failCount++; } } } } if (failCount > 0) { status = CPA_STATUS_FAIL; } // Remove session sessionStatus = removeSymSession(cyInstHandle, sessionCtx); if (sessionStatus != CPA_STATUS_SUCCESS) { PRINT_ERR("removeSymSession failed with status: %d\n", sessionStatus); } if (CPA_STATUS_SUCCESS == status) { status = sessionStatus; } for (innerLoop = 0; innerLoop < srcBufferCnt; innerLoop++) { freeUpdateMem((void **)&pSrcBuffer[innerLoop]); } for (innerLoop = 0; innerLoop < dstBufferCnt; innerLoop++) { freeUpdateMem((void **)&pDstBuffer[innerLoop]); } for (innerLoop = 0; innerLoop < opDataCnt; innerLoop++) { freeUpdateMem((void **)&pOpData[innerLoop]); } freeUpdateMem((void **)&pSrcBuffer); freeUpdateMem((void **)&pDstBuffer); freeUpdateMem((void **)&pOpData); freeUpdateMem((void **)&pIvBuffer); freeUpdateMem((void **)&pCipherKey); freeUpdateMem((void **)&pUpdateCipherKey); freeUpdateMem((void **)&pAuthKey); freeUpdateMem((void **)&pUpdateAuthKey); freeUpdateMem((void **)&pAdditionalAuthData); freeUpdateMem((void **)&sessionCtx); return status; } static void sampleSymmetricDpUpdatePerformance( single_thread_test_data_t *testSetup) { symmetric_test_params_t updateTestSetup; symmetric_test_params_t *pSetup = ((symmetric_test_params_t *)testSetup->setupPtr); CpaStatus status = CPA_STATUS_SUCCESS; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; memset(&updateTestSetup, 0, sizeof(symmetric_test_params_t)); updateTestSetup.setupData = pSetup->setupData; updateTestSetup.performanceStats = testSetup->performanceStats; status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } updateTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; updateTestSetup.ivLength = pSetup->ivLength; updateTestSetup.syncMode = pSetup->syncMode; updateTestSetup.flatBufferSizeInBytes = pSetup->flatBufferSizeInBytes; updateTestSetup.numBuffers = pSetup->numBuffers; updateTestSetup.numLoops = pSetup->numLoops; PRINT("Thread %u, LI %u, ", testSetup->threadID, testSetup->logicalQaInstance); if (updateTestSetup.setupData.symOperation == CPA_CY_SYM_OP_CIPHER) { PRINT("CipherDP "); printCipherAlg(updateTestSetup.setupData.cipherSetupData); } else if (updateTestSetup.setupData.symOperation == CPA_CY_SYM_OP_HASH) { PRINT("HashDP "); printHashAlg(updateTestSetup.setupData.hashSetupData); } else if (updateTestSetup.setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { PRINT("AlgChainDP "); printCipherAlg(updateTestSetup.setupData.cipherSetupData); PRINT(" "); printHashAlg(updateTestSetup.setupData.hashSetupData); } PRINT("\n"); startBarrier(); status = updatePerformDp(&updateTestSetup); if (CPA_STATUS_SUCCESS != status) { updateTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; } qaeMemFree((void **)&cyInstances); sampleCodeThreadComplete(testSetup->threadID); } #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ CpaStatus setupSessionUpdateCipherDp(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops) { #if CY_API_VERSION_AT_LEAST(2, 2) return symSetupSessionUpdateTest(CPA_CY_SYM_OP_CIPHER, cipherAlgorithm, cipherKeyLen, 0, 0, 0, 0, 0, priority, syncMode, packetSize, numOfPacketsInBuffer, numBuffers, numLoops, CPA_TRUE, sampleSymmetricDpUpdatePerformance); #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } CpaStatus setupSessionUpdateHashDp(CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops) { #if CY_API_VERSION_AT_LEAST(2, 2) return symSetupSessionUpdateTest(CPA_CY_SYM_OP_HASH, 0, 0, hashAlgorithm, authKeyLen, hashMode, digestResultLenInBytes, 0, priority, syncMode, packetSize, numOfPacketsInBuffer, numBuffers, numLoops, CPA_TRUE, sampleSymmetricDpUpdatePerformance); #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } CpaStatus setupSessionUpdateAlgChainDp(CpaCySymCipherAlgorithm cipherAlgorithm, Cpa32U cipherKeyLen, CpaCySymHashAlgorithm hashAlgorithm, Cpa32U authKeyLen, CpaCySymHashMode hashMode, Cpa32U digestResultLenInBytes, CpaCySymAlgChainOrder chainOrder, CpaCyPriority priority, sync_mode_t syncMode, Cpa32U packetSize, Cpa32U numOfPacketsInBuffer, Cpa32U numBuffers, Cpa32U numLoops) { #if CY_API_VERSION_AT_LEAST(2, 2) return symSetupSessionUpdateTest(CPA_CY_SYM_OP_ALGORITHM_CHAINING, cipherAlgorithm, cipherKeyLen, hashAlgorithm, authKeyLen, hashMode, digestResultLenInBytes, chainOrder, priority, syncMode, packetSize, numOfPacketsInBuffer, numBuffers, numLoops, CPA_TRUE, sampleSymmetricDpUpdatePerformance); #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } CpaStatus sessionUpdateTestDp(Cpa32U numLoops, Cpa32U numBuffers) { #if CY_API_VERSION_AT_LEAST(2, 2) CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U failCount = 0; Cpa32U cipher = 0; Cpa32U hash = 0; Cpa32U *coreMask = NULL; extern const Cpa32U algChainAlgs[][ALGCHAIN_HASH_NUM]; extern const testSetupCipher_t cipherSetup[ALGCHAIN_CIPHER_NUM]; extern const testSetupHash_t hashSetup[ALGCHAIN_HASH_NUM]; extern const Cpa32U cipherAlgs[CIPHER_ALG_NUM]; extern const Cpa32U hashAlgs[HASH_ALG_NUM]; // Run cipher tests for (cipher = 0; cipher < CIPHER_ALG_NUM; cipher++) { status = setupSessionUpdateCipherDp( cipherSetup[cipherAlgs[cipher]].cipherAlgorithm, cipherSetup[cipherAlgs[cipher]].cipherKeyLen, CPA_CY_PRIORITY_NORMAL, ASYNC, SIZE_BIT_IN_BYTES(768), 10, numBuffers, numLoops); if (CPA_STATUS_SUCCESS == status) { if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } coreMask = cyInstMap_g; status = createPerfomanceThreads(numInst_g, coreMask, numInst_g, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads\n"); return status; } status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT("Error starting threads\n"); return status; } status = waitForThreadCompletion(); if (CPA_STATUS_SUCCESS != status) { PRINT("Performance thread(s) failed\n"); failCount++; continue; } } else { PRINT("Error setup session"); failCount++; } } // Run hash tests for (hash = 0; hash < HASH_ALG_NUM; hash++) { status = setupSessionUpdateHashDp( hashSetup[hashAlgs[hash]].hashAlgorithm, hashSetup[hashAlgs[hash]].authKeyLen, CPA_CY_SYM_HASH_MODE_AUTH, hashSetup[hashAlgs[hash]].digestResultLenInBytes, CPA_CY_PRIORITY_NORMAL, ASYNC, SIZE_BIT_IN_BYTES(768), 10, numBuffers, numLoops); if (CPA_STATUS_SUCCESS == status) { if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } coreMask = cyInstMap_g; status = createPerfomanceThreads(numInst_g, coreMask, numInst_g, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads\n"); return status; } status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT("Error starting threads\n"); return status; } status = waitForThreadCompletion(); if (CPA_STATUS_SUCCESS != status) { PRINT("Performance thread(s) failed\n"); failCount++; continue; } } else { PRINT("Error setup session"); failCount++; } } // Run algchain tests for (cipher = 0; cipher < ALGCHAIN_CIPHER_NUM; cipher++) { for (hash = 0; hash < ALGCHAIN_HASH_NUM; hash++) { if (algChainAlgs[cipher][hash]) { status = setupSessionUpdateAlgChainDp( cipherSetup[cipher].cipherAlgorithm, cipherSetup[cipher].cipherKeyLen, hashSetup[hash].hashAlgorithm, hashSetup[hash].authKeyLen, CPA_CY_SYM_HASH_MODE_AUTH, hashSetup[hash].digestResultLenInBytes, CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH, CPA_CY_PRIORITY_NORMAL, ASYNC, SIZE_BIT_IN_BYTES(768), 10, numBuffers, numLoops); if (CPA_STATUS_SUCCESS == status) { if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } coreMask = cyInstMap_g; status = createPerfomanceThreads( numInst_g, coreMask, numInst_g, 0); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads\n"); return status; } status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT("Error starting threads\n"); return status; } status = waitForThreadCompletion(); if (CPA_STATUS_SUCCESS != status) { PRINT("Performance thread(s) failed\n"); failCount++; continue; } } else { PRINT("Error setup session"); failCount++; } } } } if (failCount > 0) { status = CPA_STATUS_FAIL; } return status; #else PRINT_ERR("The Session Reuse is not supported in this release\n"); return CPA_STATUS_UNSUPPORTED; #endif /* CY_API_VERSION_AT_LEAST(2, 2) */ } EXPORT_SYMBOL(sessionUpdateTestDp); qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_main.c000066400000000000000000000736101503624047500336410ustar00rootroot00000000000000 /*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "cpa_dc.h" #include "cpa_sample_code_crypto_utils.h" #include "qat_compression_main.h" #include "icp_sal_poll.h" #include "qat_perf_latency.h" #include "qat_sym_utils.h" extern volatile CpaBoolean reliability_g; extern Cpa32U packageIdCount_g; extern volatile CpaBoolean digestAppended_g; extern CpaStatus createStartandWaitForCompletion(Cpa32U instType); extern void symPerformCallback(void *pCallbackTag, CpaStatus status, const CpaCySymOp operationType, void *pOpData, CpaBufferList *pDstBuffer, CpaBoolean verifyResult); CpaStatus cipherNewPerformanceTest(CpaBoolean mode, Cpa32U mask, Cpa32U bufferSize, Cpa32U numBuffers, Cpa32U numLoops); void qatSymmetricPerformance(single_thread_test_data_t *testSetup); /*allocates buffers store a file for compression. The buffers are sent to * hardware, performance is recorded and stored in the setup parameter * the sample code framework prints out results after the thread completes*/ static CpaStatus scSymPoc(symmetric_test_params_t *setup_sym) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U *testBufferSize = setup_sym->packetSizeInBytesArray; Cpa32U digestSizeInBytes = setup_sym->setupData.hashSetupData.digestResultLenInBytes; Cpa32U numberOfBuffersPerList = 1; CpaBufferList *srcBufferListArray = NULL; CpaBufferList *copyBufferListArray = NULL; CpaCySymOpData *encryptOpData = NULL; CpaCySymOpData *decryptOpData = NULL; CpaCySymSessionCtx encryptSessionCtx = NULL; CpaCySymSessionCtx decryptSessionCtx = NULL; CpaCySymCbFunc cySymCbFn = symPerformCallback; Cpa32U numLoops = 0; Cpa32U i = 0; /* Allocate memory for source & destination bufferLists and results */ status = qatAllocateSymLists(setup_sym, &srcBufferListArray, ©BufferListArray, &encryptOpData, &decryptOpData); /* Allocate the CpaFlatBuffers in each list */ if (CPA_STATUS_SUCCESS == status) { status = qatAllocateSymFlatBuffers(setup_sym, srcBufferListArray, numberOfBuffersPerList, testBufferSize, digestSizeInBytes, copyBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate all flat buffers for symmetric\n"); } } /* Copy corpus data into allocated buffers */ if (CPA_STATUS_SUCCESS == status) { status = PopulateBuffers(srcBufferListArray, setup_sym->numBuffLists, NULL, 0, testBufferSize); } if (CPA_STATUS_SUCCESS == status) { status = copyBuffers( srcBufferListArray, copyBufferListArray, setup_sym->numBuffLists); } /* Initialize the compression session to use */ if (CPA_STATUS_SUCCESS == status) { status = qatSymSessionInit( setup_sym, &encryptSessionCtx, &decryptSessionCtx, cySymCbFn); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("qatSymSessionInit returned status %d\n", status); } } /* Initialize encrypt opData */ if (CPA_STATUS_SUCCESS == status) { status = qatSymOpDataSetup(setup_sym, encryptSessionCtx, /* testBufferSize, */ setup_sym->packetSizeInBytesArray, encryptOpData, srcBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "qatSymPerformOpDataSetup for encrypt returned status %d\n", status); } } /* Initialize decrypt opData */ if (CPA_STATUS_SUCCESS == status) { status = qatSymOpDataSetup(setup_sym, decryptSessionCtx, /* testBufferSize, */ setup_sym->packetSizeInBytesArray, encryptOpData, srcBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "qatSymPerformOpDataSetup for decrypt returned status %d\n", status); } } // encrypt or decrypt the data if (CPA_STATUS_SUCCESS == status) { if (setup_sym->setupData.cipherSetupData.cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT && reliability_g == CPA_FALSE) { status = qatSymPerform(setup_sym, encryptOpData, srcBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "qatSymPerform for encryptOpData returned status %d\n", status); } } else if (setup_sym->setupData.cipherSetupData.cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT && reliability_g == CPA_FALSE) { /*copy numLoops, set setup->numLoops to 1 to compress data, then * restore setup->numLoops to measure decompress performance*/ numLoops = setup_sym->numLoops; setup_sym->numLoops = 1; status = qatSymPerform(setup_sym, encryptOpData, srcBufferListArray); if (CPA_STATUS_SUCCESS == status) { /*restore setup->NumLoops*/ setup_sym->numLoops = numLoops; status = qatSymPerform(setup_sym, decryptOpData, srcBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR( "qatSymPerform for decryptOpData returned status %d\n", status); } } } else if (setup_sym->setupData.cipherSetupData.cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT && reliability_g == CPA_TRUE) { /*copy numLoops, set setup->numLoops to 1 to do repeated * compress-swdecompress for numLoops times*/ numLoops = setup_sym->numLoops; setup_sym->numLoops = 1; for (i = 0; i < numLoops; i++) { status = qatSymPerform(setup_sym, encryptOpData, srcBufferListArray); // now i need to decrypt if (CPA_STATUS_SUCCESS == status) { status = qatSymPerform( setup_sym, decryptOpData, srcBufferListArray); if (CPA_STATUS_SUCCESS == status) { /*3rd param is compression setup struct, need to resolve status = qatCmpBuffers(srcBufferListArray, copyBufferListArray, setup_sym);*/ } } if (CPA_STATUS_SUCCESS != status) { break; } } } } // SYMMETRIC if (CPA_STATUS_SUCCESS != qatSymFreeOpData(setup_sym, encryptOpData)) { PRINT_ERR("could not free pIv and auth memory in encryptOpData "); status = CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS != qatSymFreeOpData(setup_sym, decryptOpData)) { PRINT_ERR("could not free pIv and auth memory in decryptOpData "); status = CPA_STATUS_FAIL; } /* Remove the session free the handle */ if (CPA_STATUS_SUCCESS != qatSymSessionTeardown(setup_sym, &encryptSessionCtx, &decryptSessionCtx)) { PRINT_ERR("qatSymSessionTeardown error\n"); status = CPA_STATUS_FAIL; } /* Free CpaFlatBuffers and privateMetaData in CpaBufferLists */ if (CPA_STATUS_SUCCESS != qatFreeSymFlatBuffers(setup_sym, srcBufferListArray, copyBufferListArray)) { PRINT_ERR("qatFreeSymFlatBuffers error\n"); status = CPA_STATUS_FAIL; } /* Free CpaBufferLists and encrypt/decrypt OpData */ if (CPA_STATUS_SUCCESS != qatFreeSymLists(&srcBufferListArray, ©BufferListArray, &encryptOpData, &decryptOpData)) { PRINT_ERR("qatFreeSymLists error\n"); status = CPA_STATUS_FAIL; } return status; } void qatSymmetricPerformance(single_thread_test_data_t *testSetup) { symmetric_test_params_t symTestSetup; symmetric_test_params_t *pSetup = ((symmetric_test_params_t *)testSetup->setupPtr); Cpa32U loopIteration = 0; CpaStatus status = CPA_STATUS_SUCCESS; /*define the distribution of the packet mix * here we defined 2 lots of 10 sizes * later it is replicated into 100 buffers*/ Cpa32U packetMix[NUM_PACKETS_IMIX] = { BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_752, BUFFER_SIZE_64, BUFFER_SIZE_1504, BUFFER_SIZE_1504, BUFFER_SIZE_64, BUFFER_SIZE_8992, BUFFER_SIZE_64, BUFFER_SIZE_1504}; Cpa32U *pPacketSize; Cpa16U numInstances = 0; CpaInstanceHandle *cyInstances = NULL; CpaInstanceInfo2 *instanceInfo = NULL; memset(&symTestSetup, 0, sizeof(symmetric_test_params_t)); /*cast the setup to a known structure so that we can populate our local * test setup*/ symTestSetup.setupData = pSetup->setupData; if (reliability_g) { PRINT("\nThread %u, LI %u, ", testSetup->threadID, testSetup->logicalQaInstance); if (symTestSetup.setupData.symOperation == CPA_CY_SYM_OP_CIPHER) { PRINT("Cipher "); printCipherAlg(symTestSetup.setupData.cipherSetupData); } else if (symTestSetup.setupData.symOperation == CPA_CY_SYM_OP_HASH) { PRINT("Hash "); printHashAlg(symTestSetup.setupData.hashSetupData); } else if (symTestSetup.setupData.symOperation == CPA_CY_SYM_OP_ALGORITHM_CHAINING) { PRINT("AlgChain "); printCipherAlg(symTestSetup.setupData.cipherSetupData); PRINT(" "); printHashAlg(symTestSetup.setupData.hashSetupData); } PRINT(" in Reliability mode\n"); } /*this barrier is to halt this thread when run in user space context, the * startThreads function releases this barrier, in kernel space it does * nothing, but kernel space threads do not start until we call startThreads * anyway*/ startBarrier(); /*give our thread a unique memory location to store performance stats*/ symTestSetup.performanceStats = testSetup->performanceStats; /*get the instance handles so that we can start our thread on the selected * instance*/ status = cpaCyGetNumInstances(&numInstances); if (CPA_STATUS_SUCCESS != status || numInstances == 0) { PRINT_ERR("cpaCyGetNumInstances error, status:%d, numInstanaces:%d\n", status, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } cyInstances = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInstances); if (NULL == cyInstances) { PRINT_ERR("Error allocating memory for instance handles\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (cpaCyGetInstances(numInstances, cyInstances) != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to get instances\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } if (testSetup->logicalQaInstance > numInstances) { PRINT_ERR("%u is Invalid Logical QA Instance, max is: %u\n", testSetup->logicalQaInstance, numInstances); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); sampleCodeThreadExit(); } instanceInfo = qaeMemAlloc(sizeof(CpaInstanceInfo2)); if (instanceInfo == NULL) { PRINT_ERR("Failed to allocate memory for instanceInfo"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); return; } memset(instanceInfo, 0, sizeof(CpaInstanceInfo2)); /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; status = cpaCyInstanceGetInfo2(symTestSetup.cyInstanceHandle, instanceInfo); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("%s::%d cpaCyInstanceGetInfo2 failed", __func__, __LINE__); qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; sampleCodeThreadExit(); } if (instanceInfo->physInstId.packageId > packageIdCount_g) { packageIdCount_g = instanceInfo->physInstId.packageId; } pPacketSize = qaeMemAlloc(sizeof(Cpa32U) * pSetup->numBuffLists); if (NULL == pPacketSize) { PRINT_ERR("Could not allocate memory for pPacketSize\n"); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadExit(); } if (testSetup->packetSize == PACKET_IMIX) { /*we are testing IMIX so we copy buffer sizes from preallocated * array into symTestSetup.numBuffLists*/ Cpa32U indexer = sizeof(packetMix) / sizeof(Cpa32U); for (loopIteration = 0; loopIteration < pSetup->numBuffLists; loopIteration++) { pPacketSize[loopIteration] = packetMix[loopIteration % indexer]; } } else { /*we are testing a uniform bufferSize, so we set the bufferSize array * accordingly*/ for (loopIteration = 0; loopIteration < pSetup->numBuffLists; loopIteration++) { pPacketSize[loopIteration] = testSetup->packetSize; } } /*initialize digestIsAppended with input parameter */ symTestSetup.setupData.digestIsAppended = pSetup->digestAppend; symTestSetup.numBuffLists = pSetup->numBuffLists; symTestSetup.flatBufferSizeInBytes = pSetup->flatBufferSizeInBytes; symTestSetup.numLoops = pSetup->numLoops; /*reset the stats print function to NULL, we set it to the proper function * if the test passes at the end of this function*/ testSetup->statsPrintFunc = NULL; /*assign the array of buffer sizes we are testing to the symmetric test * setup*/ symTestSetup.packetSizeInBytesArray = pPacketSize; /*assign our thread a unique memory location to store performance stats*/ symTestSetup.performanceStats = testSetup->performanceStats; symTestSetup.performanceStats->packageId = instanceInfo->physInstId.packageId; symTestSetup.performanceStats->averagePacketSizeInBytes = testSetup->packetSize; /* give our thread a logical crypto instance to use*/ symTestSetup.cyInstanceHandle = cyInstances[testSetup->logicalQaInstance]; symTestSetup.syncMode = pSetup->syncMode; /*store core affinity, this assumes logical cpu core number is the same * logicalQaInstace */ symTestSetup.performanceStats->logicalCoreAffinity = testSetup->logicalQaInstance; symTestSetup.threadID = testSetup->threadID; symTestSetup.isDpApi = pSetup->isDpApi; symTestSetup.cryptoSrcOffset = pSetup->cryptoSrcOffset; symTestSetup.digestAppend = pSetup->digestAppend; /*launch function that does all the work*/ if (CPA_TRUE != checkCapability(cyInstances[testSetup->logicalQaInstance], &symTestSetup)) { PRINT("\nThread %u Invalid test\n", testSetup->threadID); testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_SUCCESS; sampleCodeBarrier(); qaeMemFree((void **)&pPacketSize); qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadComplete(testSetup->threadID); } status = scSymPoc(&symTestSetup); if (CPA_STATUS_SUCCESS != status) { printSymTestType(&symTestSetup); PRINT("Test %u FAILED\n", testSetup->threadID); symTestSetup.performanceStats->threadReturnStatus = CPA_STATUS_FAIL; } else { if (reliability_g) { PRINT("Symmetric thread %u complete\n", testSetup->threadID); } /*set the print function that can be used to print stats at the end of * the test*/ testSetup->statsPrintFunc = (stats_print_func_t)printSymmetricPerfDataAndStopCyService; } if ((CPA_STATUS_SUCCESS != status) || (symTestSetup.performanceStats->threadReturnStatus == CPA_STATUS_FAIL)) { /* Stop Cy Service function should be called after all threads * complete their execution. This function will be called from * WaitForThreadCompletion().*/ testSetup->statsPrintFunc = (stats_print_func_t)stopCyServicesFromCallback; } /*free memory and exit*/ qaeMemFree((void **)&pPacketSize); qaeMemFree((void **)&cyInstances); qaeMemFree((void **)&instanceInfo); sampleCodeThreadComplete(testSetup->threadID); } static CpaStatus setupNewSymmetricTest( CpaCySymOp opType, CpaCySymCipherAlgorithm cipherAlg, Cpa32U cipherKeyLengthInBytes, Cpa32U cipherOffset, CpaCyPriority priority, CpaCySymHashAlgorithm hashAlg, CpaCySymHashMode hashMode, Cpa32U authKeyLengthInBytes, CpaCySymAlgChainOrder chainOrder, sync_mode_t syncMode, CpaCySymHashNestedModeSetupData *nestedModeSetupDataPtr, Cpa32U packetSize, Cpa32U bufferSizeInBytes, Cpa32U numBuffLists, Cpa32U numLoops, Cpa32U digestAppend) { /*thread_setup_g is a multidimensional global array that stores the setup * for all thread variations in an array of characters. We store our test * setup at the start of the second array ie index 0. There maybe multiple * thread types(setups) running as counted by testTypeCount_g*/ symmetric_test_params_t *symmetricSetup = NULL; Cpa8S name[] = {'S', 'Y', 'M', '\0'}; if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Supported Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } /* Return an error if the number of packets is not modulus zero of the * number of packets to cover IMIX packet mix. */ if (packetSize == PACKET_IMIX && (numBuffLists % NUM_PACKETS_IMIX) != 0) { PRINT_ERR("To ensure that the weighting of IMIX packets is correct " ", the number of buffers (%d) should be a multiple of %d\n", numBuffLists, NUM_PACKETS_IMIX); return CPA_STATUS_FAIL; } /*start crypto service if not already started*/ if (CPA_STATUS_SUCCESS != startCyServices()) { PRINT_ERR("Failed to start Crypto services\n"); return CPA_STATUS_FAIL; } if (!poll_inline_g) { /* start polling threads if polling is enabled in the configuration file */ if (CPA_STATUS_SUCCESS != cyCreatePollingThreadsIfPollingIsEnabled()) { PRINT_ERR("Error creating polling threads\n"); return CPA_STATUS_FAIL; } } /*as setup is a multidimensional char array we need to cast it to the * symmetric structure*/ memcpy(&thread_name_g[testTypeCount_g][0], name, THREAD_NAME_LEN); symmetricSetup = (symmetric_test_params_t *)&thread_setup_g[testTypeCount_g][0]; memset(symmetricSetup, 0, sizeof(symmetric_test_params_t)); testSetupData_g[testTypeCount_g].performance_function = (performance_func_t)sampleSymmetricPerformance; testSetupData_g[testTypeCount_g].packetSize = packetSize; /*then we store the test setup in the above location*/ // symmetricSetup->setupData.sessionPriority=CPA_CY_PRIORITY_HIGH; symmetricSetup->setupData.sessionPriority = priority; symmetricSetup->setupData.symOperation = opType; symmetricSetup->setupData.cipherSetupData.cipherAlgorithm = cipherAlg; symmetricSetup->setupData.cipherSetupData.cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; symmetricSetup->setupData.cipherSetupData.cipherKeyLenInBytes = cipherKeyLengthInBytes; symmetricSetup->setupData.hashSetupData.hashAlgorithm = hashAlg; symmetricSetup->setupData.hashSetupData.hashMode = hashMode; symmetricSetup->isDpApi = CPA_FALSE; symmetricSetup->cryptoSrcOffset = cipherOffset; /* in this code we limit the digest result len to be the same as the the * authentication key len*/ symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = authKeyLengthInBytes; /* GCM hash works only on 8,12 and 16 bytes, default to 16 if others */ if (CPA_CY_SYM_HASH_AES_GCM == hashAlg && (authKeyLengthInBytes != 8 && authKeyLengthInBytes != 12 && authKeyLengthInBytes != 16)) { PRINT("CPA_CY_SYM_HASH_AES_GCM digest length %u unsupported , " "defaulting to 16 \n", authKeyLengthInBytes); symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = 16; } #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 // for SH3 keylength == blocklength. And keylength might be > = digestlen if (CPA_CY_SYM_HASH_SHA3_256 == hashAlg) { symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = setHashDigestLen(hashAlg); } #endif // check which kind of hash mode is selected if (CPA_CY_SYM_HASH_MODE_NESTED == hashMode) { // nested mode // set the struct for nested hash mode if (NULL == nestedModeSetupDataPtr) { // set a default nested mode setup data symmetricSetup->setupData.hashSetupData.nestedModeSetupData .outerHashAlgorithm = hashAlg; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .pInnerPrefixData = NULL; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .innerPrefixLenInBytes = 0; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .pOuterPrefixData = NULL; symmetricSetup->setupData.hashSetupData.nestedModeSetupData .outerPrefixLenInBytes = 0; } else { symmetricSetup->setupData.hashSetupData.nestedModeSetupData = *nestedModeSetupDataPtr; } } if ((CPA_CY_SYM_HASH_AES_XCBC == hashAlg) && (AES_XCBC_DIGEST_LENGTH_IN_BYTES != authKeyLengthInBytes)) { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = AES_XCBC_DIGEST_LENGTH_IN_BYTES; } else if ((CPA_CY_SYM_HASH_KASUMI_F9 == hashAlg) || (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlg)) { /* * KASUMI_F9 and SNOW3G_UIA2 supports authKeyLen=128bits * and digestResultLen=32bits */ symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = KASUMI_F9_OR_SNOW3G_UIA2_KEY_SIZE_128_IN_BYTES; symmetricSetup->setupData.hashSetupData.digestResultLenInBytes = setHashDigestLen(hashAlg); } #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 // ZUC-EIA3 supports authKeyLen=128bits and digestResultLen=32bits else if (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlg) { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = KEY_SIZE_128_IN_BYTES; } #endif else { symmetricSetup->setupData.hashSetupData.authModeSetupData .authKeyLenInBytes = authKeyLengthInBytes; } symmetricSetup->setupData.algChainOrder = chainOrder; symmetricSetup->syncMode = syncMode; symmetricSetup->flatBufferSizeInBytes = bufferSizeInBytes; symmetricSetup->numLoops = numLoops; symmetricSetup->numBuffLists = numBuffLists; if (((bufferSizeInBytes != 0) && (packetSize == PACKET_IMIX)) || (bufferSizeInBytes % IV_LEN_FOR_16_BYTE_BLOCK_CIPHER != 0)) { PRINT_ERR("Doesn't support PACKET_IMIX " "when the flat buffer size is not 0 or " " it's not align with block size (%d): ", bufferSizeInBytes); return CPA_STATUS_FAIL; } symmetricSetup->digestAppend = digestAppend; return CPA_STATUS_SUCCESS; } CpaStatus cipherNewPerformanceTest(CpaBoolean mode, Cpa32U mask, Cpa32U bufferSize, Cpa32U numBuffers, Cpa32U numLoops) { CpaStatus retStatus = CPA_STATUS_SUCCESS; if (CPA_STATUS_SUCCESS != setupNewSymmetricTest( CPA_CY_SYM_OP_CIPHER, CPA_CY_SYM_CIPHER_AES_CBC, KEY_SIZE_128_IN_BYTES, NOT_USED, CPA_CY_PRIORITY_HIGH, NOT_USED /* hash alg not needed in cipher test*/, NOT_USED /* hash mode not needed in cipher test*/, NOT_USED /* auth key len not needed in cipher test*/, NOT_USED /* chain mode not needed in cipher test*/, 1, NULL, /* nested hash data not needed in cipher test*/ bufferSize, 0, numBuffers, numLoops, digestAppended_g)) { PRINT_ERR("Error setting up Cipher Test\n"); retStatus = CPA_STATUS_FAIL; } else { if (CPA_STATUS_SUCCESS != createStartandWaitForCompletionCrypto(SYM)) { retStatus = CPA_STATUS_FAIL; /*set status to fail, * but continue with rest of testing*/ } } return retStatus; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_utils.c000066400000000000000000000755711503624047500340650ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #include "qat_sym_utils.h" #include "cpa_dc.h" #include "../common/qat_perf_buffer_utils.h" #include "qat_compression_main.h" #define EVEN_NUMBER (2) extern CpaBoolean usePartial_g; extern Cpa32U symPollingInterval_g; CpaStatus qatFreeSymLists(CpaBufferList **srcBufferListArray, CpaBufferList **copyBufferListArray, CpaCySymOpData **encryptOpData, CpaCySymOpData **decryptOpData) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus retStatus = CPA_STATUS_SUCCESS; status = FreeArrayOfStructures((void **)srcBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free srcBufferListArray"); retStatus = CPA_STATUS_FAIL; } status = FreeArrayOfStructures((void **)copyBufferListArray); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free copyBufferListArray"); retStatus = CPA_STATUS_FAIL; } status = FreeArrayOfStructures((void **)encryptOpData); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free encryptOpData"); retStatus = CPA_STATUS_FAIL; } status = FreeArrayOfStructures((void **)decryptOpData); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not free decryptOpData"); retStatus = CPA_STATUS_FAIL; } return retStatus; } CpaStatus qatAllocateSymLists(symmetric_test_params_t *setup, CpaBufferList **srcBufferListArray, CpaBufferList **copyBufferListArray, CpaCySymOpData **encryptOpData, CpaCySymOpData **decryptOpData) { CpaStatus status = CPA_STATUS_SUCCESS; status = AllocArrayOfStructures((void **)srcBufferListArray, setup->numBuffLists, sizeof(CpaBufferList)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate memory for srcBufferListArray\n"); } if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures((void **)copyBufferListArray, setup->numBuffers, sizeof(CpaBufferList)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate copyBufferListArray\n"); } } if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures((void **)encryptOpData, setup->numBuffLists, sizeof(CpaCySymOpData)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate encryptOpData\n"); } } if (CPA_STATUS_SUCCESS == status) { status = AllocArrayOfStructures((void **)decryptOpData, setup->numBuffLists, sizeof(CpaCySymOpData)); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not allocate decryptOpData\n"); } } if (CPA_STATUS_SUCCESS != status) { /*something went wrong so attempt to free allocated structures * Don't capture the status here as we want to return non success anyway */ qatFreeSymLists(srcBufferListArray, copyBufferListArray, encryptOpData, decryptOpData); } return status; } CpaStatus qatFreeSymFlatBuffers(symmetric_test_params_t *setup, CpaBufferList *srcBufferListArray, CpaBufferList *copyBufferListArray) { CpaStatus status = CPA_STATUS_SUCCESS; if (CPA_STATUS_SUCCESS != freeBuffersInLists(srcBufferListArray, setup->numBuffLists)) { PRINT_ERR("freeBuffersInLists (src) error\n"); status = CPA_STATUS_FAIL; } // keep trying to free destListArray if (CPA_STATUS_SUCCESS != freeBuffersInLists(copyBufferListArray, setup->numBuffLists)) { status = CPA_STATUS_FAIL; PRINT_ERR("copyBuffersInLists (dest) error\n"); } return status; } CpaStatus qatAllocateSymFlatBuffers( symmetric_test_params_t *setup, CpaBufferList *srcBufferListArray, Cpa32U numBuffersInSrcList, /*affects the metaSize of CpaBufferList*/ Cpa32U *sizeOfBuffersInSrcList, /*size of CpaFlatBuffers to allocate*/ Cpa32U digestSize, CpaBufferList *copyBufferListArray) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U metaSize = 0; if (CPA_STATUS_SUCCESS == status) { // getDcMetaSize required for the src list status = cpaCyBufferListGetMetaSize( setup->cyInstanceHandle, numBuffersInSrcList, &metaSize); } if (CPA_STATUS_SUCCESS == status) { status = AllocateBuffersInLists(srcBufferListArray, setup->numBuffLists, numBuffersInSrcList, sizeOfBuffersInSrcList, digestSize, metaSize, setup->node, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS == status) { status = AllocateBuffersInLists(copyBufferListArray, setup->numBuffLists, numBuffersInSrcList, sizeOfBuffersInSrcList, digestSize, metaSize, setup->node, BYTE_ALIGNMENT_64); } if (CPA_STATUS_SUCCESS != status) { // an error has occurred allocating memory so we need to free qatFreeSymFlatBuffers(setup, srcBufferListArray, copyBufferListArray); } return status; } CpaStatus qatSymSessionInit(symmetric_test_params_t *setup, CpaCySymSessionCtx *encryptSessionCtx, CpaCySymSessionCtx *decryptSessionCtx, CpaCySymCbFunc pSymCb) { Cpa32U sessionCtxSizeInBytes = 0; #if CPA_CY_API_VERSION_NUM_MINOR >= 8 Cpa32U sessionCtxDynamicSizeInBytes = 0; #endif CpaStatus status = CPA_STATUS_SUCCESS; CpaCySymCipherSetupData *cipherSetupData = NULL; CpaCySymHashAuthModeSetupData *authModeSetupData = NULL; CpaCySymHashAlgorithm hashAlgorithm = CPA_CY_SYM_HASH_NONE; /* Shorten dereference path for more code readability */ cipherSetupData = &(setup->setupData.cipherSetupData); authModeSetupData = &(setup->setupData.hashSetupData.authModeSetupData); hashAlgorithm = setup->setupData.hashSetupData.hashAlgorithm; /*generate a random cipher and authentication key*/ /*cipher setup only needs to be set for alg chaining, cipher, AES-GCM * and AES-CCM*/ cipherSetupData->pCipherKey = (Cpa8U *)qaeMemAlloc(cipherSetupData->cipherKeyLenInBytes); if (NULL == cipherSetupData->pCipherKey) { PRINT_ERR("Could not allocate pCipherKey\n"); qatSymSessionTeardown(setup, encryptSessionCtx, decryptSessionCtx); return status; } generateRandomData(cipherSetupData->pCipherKey, cipherSetupData->cipherKeyLenInBytes); /*hash setup only needs to be set for hash, AES-GCM and AES-CCM*/ if (CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { authModeSetupData->authKey = NULL; authModeSetupData->authKeyLenInBytes = 0; } else { authModeSetupData->authKey = (Cpa8U *)qaeMemAlloc(authModeSetupData->authKeyLenInBytes); if (NULL == authModeSetupData->authKey) { PRINT_ERR("Could not allocate authKey\n"); qatSymSessionTeardown(setup, encryptSessionCtx, decryptSessionCtx); return status; } generateRandomData(authModeSetupData->authKey, authModeSetupData->authKeyLenInBytes); } if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm #endif ) { authModeSetupData->aadLenInBytes = KEY_SIZE_128_IN_BYTES; } else { authModeSetupData->aadLenInBytes = 0; } /* will not verify digest by default*/ setup->setupData.verifyDigest = CPA_FALSE; /*this is the original API to get the required context size, we show the * function used here, but we only use the size for the older version of the * API get size for memory allocation*/ status = cpaCySymSessionCtxGetSize( setup->cyInstanceHandle, &setup->setupData, &sessionCtxSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetSize error, status: %d", status); return status; } #if CPA_CY_API_VERSION_NUM_MINOR >= 8 /*get dynamic context size*/ status = cpaCySymSessionCtxGetDynamicSize(setup->cyInstanceHandle, &setup->setupData, &sessionCtxDynamicSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetDynamicSize error, status: %d", status); return status; } /* compare dynamic context size to normal context size*/ if (sessionCtxDynamicSizeInBytes > sessionCtxSizeInBytes) { PRINT_ERR("Dynamic size should not be larger than max size\n"); return CPA_STATUS_FAIL; } /* * allocate session memory using dynamic context size */ sessionCtxSizeInBytes = sessionCtxDynamicSizeInBytes; #endif *encryptSessionCtx = qaeMemAllocNUMA(sessionCtxSizeInBytes, setup->node, BYTE_ALIGNMENT_64); if (NULL == *encryptSessionCtx) { PRINT_ERR("Could not allocate pLocalSession memory\n"); return CPA_STATUS_FAIL; } /*zero session memory*/ memset(*encryptSessionCtx, 0, sessionCtxSizeInBytes); /* * init session with asynchronous callback- pLocalSession will contain * the session context */ status = cpaCySymInitSession( setup->cyInstanceHandle, pSymCb, &setup->setupData, *encryptSessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymInitSession error, status: %d\n", status); qatSymSessionTeardown(setup, encryptSessionCtx, decryptSessionCtx); return status; } /*init a second session for the decrypt*/ cipherSetupData->cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; if (setup->setupData.algChainOrder == CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH) { setup->setupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; } else { setup->setupData.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; } setup->setupData.verifyDigest = CPA_TRUE; /*get size for mem allocation*/ status = cpaCySymSessionCtxGetSize( setup->cyInstanceHandle, &setup->setupData, &sessionCtxSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetSize error, status: %d", status); return status; } #if CPA_CY_API_VERSION_NUM_MINOR >= 8 /*get dynamic context size*/ status = cpaCySymSessionCtxGetDynamicSize(setup->cyInstanceHandle, &setup->setupData, &sessionCtxDynamicSizeInBytes); if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("cpaCySymSessionCtxGetDynamicSize error, status: %d", status); return status; } /* compare dynamic context size to normal context size*/ if (sessionCtxDynamicSizeInBytes > sessionCtxSizeInBytes) { PRINT_ERR("Dynamic size should not be larger than max size\n"); return CPA_STATUS_FAIL; } /* * allocate session memory using dynamic context size */ sessionCtxSizeInBytes = sessionCtxDynamicSizeInBytes; #endif *decryptSessionCtx = qaeMemAllocNUMA(sessionCtxSizeInBytes, setup->node, BYTE_ALIGNMENT_64); if (NULL == *decryptSessionCtx) { PRINT_ERR("Could not allocate decryptSessionCtx memory\n"); qatSymSessionTeardown(setup, encryptSessionCtx, decryptSessionCtx); return CPA_STATUS_FAIL; } memset(*decryptSessionCtx, 0, sessionCtxSizeInBytes); status = cpaCySymInitSession( setup->cyInstanceHandle, pSymCb, &setup->setupData, *decryptSessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymInitSession error, status: %d\n", status); qatSymSessionTeardown(setup, encryptSessionCtx, *decryptSessionCtx); return status; } return status; } CpaStatus qatSymSessionTeardown(symmetric_test_params_t *setup, CpaCySymSessionCtx *encryptSessionCtx, CpaCySymSessionCtx *decryptSessionCtx) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus returnStatus = CPA_STATUS_SUCCESS; status = removeSymSession(setup->cyInstanceHandle, *encryptSessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not remove encrypt session context"); returnStatus = CPA_STATUS_FAIL; } status = removeSymSession(setup->cyInstanceHandle, *decryptSessionCtx); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not remove decrypt session context"); returnStatus = CPA_STATUS_FAIL; } qaeMemFree( (void **)&(setup->setupData.hashSetupData.authModeSetupData.authKey)); if (NULL != setup->setupData.hashSetupData.authModeSetupData.authKey) { PRINT_ERR("could not free authentication key"); returnStatus = CPA_STATUS_FAIL; } qaeMemFree((void **)&(setup->setupData.cipherSetupData.pCipherKey)); if (NULL != setup->setupData.cipherSetupData.pCipherKey) { PRINT_ERR("could not free cipher key"); returnStatus = CPA_STATUS_FAIL; } qaeMemFreeNUMA((void **)encryptSessionCtx); if (NULL != *encryptSessionCtx) { PRINT_ERR("could not free encrypt session context"); returnStatus = CPA_STATUS_FAIL; } qaeMemFreeNUMA((void **)decryptSessionCtx); if (NULL != *decryptSessionCtx) { PRINT_ERR("could not free decrypt session context"); returnStatus = CPA_STATUS_FAIL; } return returnStatus; } CpaStatus qatSymFreeOpData(symmetric_test_params_t *const pSetup, CpaCySymOpData *const pOpdata) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U idx = 0; if (NULL == pOpdata) { PRINT_ERR("pOpdata is NULL\n"); return CPA_STATUS_FAIL; } for (idx = 0; idx < pSetup->numBuffLists; idx++) { if (NULL != pOpdata[idx].pIv) { qaeMemFreeNUMA((void **)&(pOpdata[idx].pIv)); } if (NULL != pOpdata[idx].pAdditionalAuthData) { qaeMemFreeNUMA((void **)&(pOpdata[idx].pAdditionalAuthData)); } if ((NULL != pOpdata[idx].pIv) || (NULL != pOpdata[idx].pAdditionalAuthData)) { PRINT_ERR("Failed to free pIv or pAdditionalAuthData\n"); status = CPA_STATUS_FAIL; } } return status; } CpaStatus qatSymOpDataSetup(symmetric_test_params_t *pSetup, CpaCySymSessionCtx sessionCtx, Cpa32U *pPacketSize, CpaCySymOpData *pOpdata, CpaBufferList *pBuffListArray) { CpaCySymCipherAlgorithm cipherAlgorithm = CPA_CY_SYM_CIPHER_NULL; CpaCySymHashAlgorithm hashAlgorithm = CPA_CY_SYM_HASH_NONE; Cpa32U numOfBuffers = 0; Cpa32U idx = 0; /* Shortens dereference path for more code readability */ cipherAlgorithm = pSetup->setupData.cipherSetupData.cipherAlgorithm; hashAlgorithm = pSetup->setupData.hashSetupData.hashAlgorithm; /* For each bufferList set the symmetric operation data */ for (idx = 0; idx < pSetup->numBuffLists; idx++) { memset(&pOpdata[idx], 0, sizeof(CpaCySymOpData)); pOpdata[idx].sessionCtx = sessionCtx; pOpdata[idx].packetType = CPA_CY_SYM_PACKET_TYPE_FULL; if (usePartial_g && ((idx % EVEN_NUMBER) == 0)) { pOpdata[idx].packetType = CPA_CY_SYM_PACKET_TYPE_PARTIAL; } else if (usePartial_g) { pOpdata[idx].packetType = CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL; } /* These only need to be set for cipher and alg chaining */ pOpdata[idx].cryptoStartSrcOffsetInBytes = pSetup->cryptoSrcOffset; /* messageLenToCipherInBytes and messageLenToHashInBytes do not have * to be the same. In this code we want to either hash the entire buffer * or encrypt the entire buffer, depending on the SymOperation. * For Alg Chaining, depending on the chain order, for HashThenCipher, * the digest will be the hash of the unencrypted buffer and then we * cipher the buffer. OR for CipherThenHash, we cipher the buffer, then * the perform the hash on the encrypted buffer, so that the digest is * the digest of the encrypted data */ pOpdata[idx].messageLenToCipherInBytes = pPacketSize[idx] - pSetup->cryptoSrcOffset; /* These only need to be set for hash and alg chaining*/ pOpdata[idx].hashStartSrcOffsetInBytes = HASH_OFFSET_BYTES; pOpdata[idx].messageLenToHashInBytes = pPacketSize[idx]; pOpdata[idx].pAdditionalAuthData = NULL; /* In GMAC mode, there is no message to Cipher */ if (CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { pOpdata[idx].cryptoStartSrcOffsetInBytes = 0; pOpdata[idx].messageLenToCipherInBytes = 0; } if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 || CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm #endif ) { pOpdata[idx].pAdditionalAuthData = qaeMemAllocNUMA( KEY_SIZE_128_IN_BYTES, pSetup->node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[idx].pAdditionalAuthData) { qatSymFreeOpData(pSetup, pOpdata); PRINT_ERR("Could not allocate additional auth data index %u\n", idx); return CPA_STATUS_FAIL; } memset( pOpdata[idx].pAdditionalAuthData, 0xAA, KEY_SIZE_128_IN_BYTES); } else if (((CPA_CY_SYM_CIPHER_AES_CCM == cipherAlgorithm) || (CPA_CY_SYM_CIPHER_AES_GCM == cipherAlgorithm)) && (CPA_CY_SYM_HASH_AES_GMAC != hashAlgorithm)) { /* must allocate to the nearest block size required * (above 18 bytes) */ pOpdata[idx].pAdditionalAuthData = qaeMemAllocNUMA( AES_CCM_MIN_AAD_ALLOC_LENGTH, pSetup->node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[idx].pAdditionalAuthData) { PRINT_ERR("Could not allocate additional auth data index %u\n", idx); qatSymFreeOpData(pSetup, pOpdata); return CPA_STATUS_FAIL; } memset(pOpdata[idx].pAdditionalAuthData, 0, AES_CCM_MIN_AAD_ALLOC_LENGTH); } /* set IV len depending on what we are testing */ switch (cipherAlgorithm) { case CPA_CY_SYM_CIPHER_AES_CBC: case CPA_CY_SYM_CIPHER_AES_CTR: case CPA_CY_SYM_CIPHER_AES_CCM: case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: case CPA_CY_SYM_CIPHER_AES_F8: case CPA_CY_SYM_CIPHER_AES_XTS: #if CPA_CY_API_VERSION_NUM_MAJOR >= 2 case CPA_CY_SYM_CIPHER_ZUC_EEA3: #endif pOpdata[idx].ivLenInBytes = IV_LEN_FOR_16_BYTE_BLOCK_CIPHER; break; case CPA_CY_SYM_CIPHER_DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CBC: case CPA_CY_SYM_CIPHER_3DES_CTR: case CPA_CY_SYM_CIPHER_KASUMI_F8: pOpdata[idx].ivLenInBytes = IV_LEN_FOR_8_BYTE_BLOCK_CIPHER; break; case CPA_CY_SYM_CIPHER_AES_GCM: pOpdata[idx].ivLenInBytes = IV_LEN_FOR_12_BYTE_GCM; break; default: pOpdata[idx].ivLenInBytes = IV_LEN_FOR_8_BYTE_BLOCK_CIPHER; break; } /*allocate NUMA aware aligned memory for IV*/ pOpdata[idx].pIv = qaeMemAllocNUMA( pOpdata[idx].ivLenInBytes, pSetup->node, BYTE_ALIGNMENT_64); if (NULL == pOpdata[idx].pIv) { qatSymFreeOpData(pSetup, pOpdata); PRINT_ERR("IV is null\n"); return CPA_STATUS_FAIL; } memset(pOpdata[idx].pIv, 0, pOpdata[idx].ivLenInBytes); if (CPA_CY_SYM_CIPHER_AES_CCM == cipherAlgorithm) { /*Although the IV data length for CCM must be 16 bytes, The nonce length must be between 7 and 13 inclusive*/ pOpdata[idx].ivLenInBytes = AES_CCM_DEFAULT_NONCE_LENGTH; } /*if we are testing HASH or Alg Chaining, set the location to place * the digest result, this space was allocated in sampleSymmetricPerform * function*/ if ((CPA_CY_SYM_OP_HASH == pSetup->setupData.symOperation) || (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSetup->setupData.symOperation)) { /* calculate digest offset */ numOfBuffers = pBuffListArray[idx].numBuffers; pOpdata[idx].pDigestResult = pBuffListArray[idx].pBuffers[numOfBuffers - 1].pData + pSetup->packetSizeInBytesArray[idx]; } if ((CPA_CY_SYM_CIPHER_AES_CCM == cipherAlgorithm) && (CPA_CY_SYM_HASH_AES_GMAC != hashAlgorithm)) { /*generate a random IV*/ generateRandomData(&(pOpdata[idx].pIv[1]), pOpdata[idx].ivLenInBytes); memcpy(&(pOpdata[idx].pAdditionalAuthData[1]), &(pOpdata[idx].pIv[1]), pOpdata[idx].ivLenInBytes); } else { /*generate a random IV*/ generateRandomData(pOpdata[idx].pIv, pOpdata[idx].ivLenInBytes); } } return CPA_STATUS_SUCCESS; } CpaStatus qatSymPerform(symmetric_test_params_t *setup, CpaCySymOpData *ppOpData, CpaBufferList *ppSrcBuffListArray) { CpaBoolean verifyResult = CPA_FALSE; CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U outsideLoopCount = 0; Cpa32U insideLoopCount = 0; CpaInstanceInfo2 instanceInfo2 = {0}; Cpa64U numOps = 0; Cpa64U nextPoll = symPollingInterval_g; perf_data_t *pSymData = setup->performanceStats; memset(pSymData, 0, sizeof(perf_data_t)); status = cpaCyInstanceGetInfo2(setup->cyInstanceHandle, &instanceInfo2); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyInstanceGetInfo2 error, status: %d\n", status); return CPA_STATUS_FAIL; } pSymData->packageId = instanceInfo2.physInstId.packageId; qatInitLatency( setup->performanceStats, setup->numBuffLists, setup->numLoops); /*preset the number of ops we plan to submit*/ pSymData->numOperations = (Cpa64U)setup->numBuffLists * setup->numLoops; /* Init the semaphore used in the callback */ sampleCodeSemaphoreInit(&pSymData->comp, 0); /*this barrier will wait until all threads get to this point*/ sampleCodeBarrier(); /* Get the time, collect this only for the first * request, the callback collects it for the last */ pSymData->startCyclesTimestamp = sampleCodeTimestamp(); /* The outside for-loop will loop around the preallocated buffer list * array the number of times necessary to satisfy: * NUM_OPERATIONS / setup->numBuffLists*/ for (outsideLoopCount = 0; outsideLoopCount < setup->numLoops; outsideLoopCount++) { checkStopTestExitFlag(pSymData, &(setup->numLoops), &(setup->numBuffLists), outsideLoopCount); /* This inner for-loop loops around the number of Buffer Lists * that have been preallocated. Once the array has completed- * exit to the outer loop to move on the next iteration of the * preallocated loop. */ for (insideLoopCount = 0; insideLoopCount < setup->numBuffLists; insideLoopCount++) { /* When the callback returns it will increment the responses * counter and test if its equal to NUM_OPERATIONS, in that * case all responses have been successfully received. */ do { qatStartLatencyMeasurement(setup->performanceStats, setup->submissions); status = cpaCySymPerformOp(setup->cyInstanceHandle, pSymData, &ppOpData[insideLoopCount], &ppSrcBuffListArray[insideLoopCount], &ppSrcBuffListArray[insideLoopCount], /*in-place operation*/ &verifyResult); if (status == CPA_STATUS_RETRY) { setup->performanceStats->retries++; if (poll_inline_g) { if (instanceInfo2.isPolled) { icp_sal_CyPollInstance(setup->cyInstanceHandle, 0); nextPoll = numOps + symPollingInterval_g; } } AVOID_SOFTLOCKUP; } } while (CPA_STATUS_RETRY == status); if (CPA_STATUS_SUCCESS != status) { break; } setup->submissions++; qatLatencyPollForResponses(setup->performanceStats, setup->submissions, setup->cyInstanceHandle, CPA_TRUE, CPA_FALSE); if (poll_inline_g) { if (instanceInfo2.isPolled) { ++numOps; if (numOps == nextPoll) { icp_sal_CyPollInstance(setup->cyInstanceHandle, 0); pSymData->pollCount++; nextPoll = numOps + symPollingInterval_g; } } } } /*end of inner loop */ if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCySymPerformOp Error %d\n", status); break; } } /* end of outer loop */ if (poll_inline_g) { if ((CPA_STATUS_SUCCESS == status) && (instanceInfo2.isPolled)) { /* ** Now need to wait for all the in-flight Requests. */ status = cyPollNumOperations( pSymData, setup->cyInstanceHandle, pSymData->numOperations); } } /* Checking the response count and initiating the sem_wait in waitForResponses function to complete the operations */ if (pSymData->responses != pSymData->numOperations) { if (CPA_STATUS_SUCCESS == status) { status = waitForResponses(pSymData, setup->syncMode, setup->numBuffLists, setup->numLoops); } } qatSummariseLatencyMeasurements(setup->performanceStats); /*clean up the callback semaphore*/ sampleCodeSemaphoreDestroy(&pSymData->comp); return status; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/crypto/qat_sym_utils.h000066400000000000000000000121661503624047500340610ustar00rootroot00000000000000/**************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ #ifndef QAT_SYM_UTILS_H #define QAT_SYM_UTILS_H #include "cpa.h" #include "cpa_cy_sym.h" #include "cpa_sample_code_crypto_utils.h" CpaStatus qatFreeSymLists(CpaBufferList **srcBufferListArray, CpaBufferList **copyBufferListArray, CpaCySymOpData **encryptOpData, CpaCySymOpData **decryptOpData); CpaStatus qatAllocateSymLists(symmetric_test_params_t *setup, CpaBufferList **srcBufferListArray, CpaBufferList **copyBufferListArray, CpaCySymOpData **encryptOpData, CpaCySymOpData **decryptOpData); CpaStatus qatFreeSymFlatBuffers(symmetric_test_params_t *setup, CpaBufferList *srcBufferListArray, CpaBufferList *copyBufferListArray); CpaStatus qatAllocateSymFlatBuffers( symmetric_test_params_t *setup, CpaBufferList *srcBufferListArray, Cpa32U numBuffersInSrcList, /* affects the metaSize of CpaBufferList */ Cpa32U *sizeOfBuffersInSrcList, /* size of CpaFlatBuffers to allocate */ Cpa32U digestSize, CpaBufferList *copyBufferListArray); CpaStatus qatSymSessionInit(symmetric_test_params_t *setup, CpaCySymSessionCtx *encryptSessionCtx, CpaCySymSessionCtx *decryptSessionCtx, CpaCySymCbFunc pSymCb); CpaStatus qatSymSessionTeardown(symmetric_test_params_t *setup, CpaCySymSessionCtx *encryptSessionCtx, CpaCySymSessionCtx *decryptSessionCtx); CpaStatus qatSymFreeOpData(symmetric_test_params_t *const pSetup, CpaCySymOpData *const pOpdata); CpaStatus qatSymOpDataSetup(symmetric_test_params_t *pSetup, CpaCySymSessionCtx sessionCtx, Cpa32U *pPacketSize, CpaCySymOpData *pOpdata, CpaBufferList *pBuffListArray); CpaStatus qatSymPerform(symmetric_test_params_t *setup, CpaCySymOpData *ppOpData, CpaBufferList *ppSrcBuffListArray); #endif /* QAT_SYM_UTILS_H */ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/000077500000000000000000000000001503624047500314625ustar00rootroot00000000000000cpa_sample_code_framework.c000066400000000000000000002016151503624047500367270ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * Doxygen group definitions ****************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_framework.c * * @defgroup perfCodeFramework performance sample code framework * * @ingroup perfCodeFramework * * @description * This file contains the test creation functions of the performance sample * code framework. * Functions contained in this file: * - startThreads * - waitForThreadCompletion * - createPerformanceThreads * - killCreatedThreads * - clearPerfStats * * functions within allow to create and run multiple threads. * * The user defines the test setup(s) and function(s) to run and uses * functions implemented here to create, start and wait for the threads to * complete * * the setup and functions called are defined elsewhere, but they must fit * within the thread_creation_data_t and single_thread_test_data_t * structures. Examples of how these are set can be seen in the crypto * folder cpa_sample_code_crypto_utils.c ->setupSymetricTest *****************************************************************************/ #include "cpa_sample_code_framework.h" #include "cpa_sample_code_crypto_utils.h" /****************************************************************************** * GLOBAL VARIABLES * These variables are used in the framework to provide setup information, a * location to write performance stats, count the number of threads and types of * threads, and to control the start of user space threads. THEY ARE NOT THREAD * SAFE. The only variable that the user should need to use is the * thread_setup_g array * The user will be required to write some setup data to this array. * * testTypeCount_g is used to control where the user writes there setup * data in thread_setup_g array * * The framework code ensures that writing to these variables is only done * before threads start and after they all complete. The only exception to this * is performance stats, where each thread as a unique location to store stats * ******************************************************************************/ #ifdef USER_SPACE /*store the threadId, this only used for thread setup and after threads are * complete, so it not required to be atomic*/ sample_code_thread_t *threads_g; /*this array stores the setup and performance data of all threads created. * there is duplication between this and testSetupData_g, * however this makes it easier for collation of stats when there are * multiple creations of one type of thread. * There is no sharing data between threads*/ single_thread_test_data_t *singleThreadData_g; /*this array stores the setup and performance data of ONE_TYPE_OF_THREAD. This * is updated on thread setup and read and clear once all threads are complete*/ thread_creation_data_t *testSetupData_g; /*declare space to store setup structures in. This stores all the setup of each * thread, there is no sharing between threads, so each section of the array * is autonomous to 1 thread*/ Cpa8U (*thread_setup_g)[MAX_SETUP_STRUCT_SIZE_IN_BYTES]; Cpa8U (*thread_name_g)[THREAD_NAME_LEN]; #else sample_code_thread_t threads_g[MAX_THREADS]; single_thread_test_data_t singleThreadData_g[MAX_THREADS] = {{0}}; thread_creation_data_t testSetupData_g[MAX_THREAD_VARIATION] = {{0}}; Cpa8U thread_setup_g[MAX_THREAD_VARIATION][MAX_SETUP_STRUCT_SIZE_IN_BYTES]; Cpa8U thread_name_g[MAX_THREAD_VARIATION][THREAD_NAME_LEN]; #endif /*declare array of perf_stats pointers. Each thread is provided is own * perf_stats */ perf_data_t *perfStats_g[MAX_THREAD_VARIATION]; /*global flag to track if the perfStats_g array is initialized*/ CpaBoolean perfStatsInit_g = CPA_FALSE; int useStaticPrime = 1; int useUnalignedBuffer = 0; volatile CpaBoolean isChangingThreadQaInstanceRequired_g = CPA_FALSE; EXPORT_SYMBOL(isChangingThreadQaInstanceRequired_g); /*global variables -note syntax is to use _g for all global variables*/ /*this is used to count the total number of threads created, this is * incremented during the thread creation phase once threads are started it * is read only and set to zero when all threads are finished*/ volatile Cpa32U numCreatedThreads_g = 0; int numThreadsToCreate_g = 0; /** * Boolean flag used to indicate if any error occurred in submit, * polling threads or callback function */ volatile CpaBoolean error_flag_g = CPA_FALSE; /*this is used to count the total number of threads reached to start barrier, * this is incremented during the thread reach to start barrier phase and * set to zero when all threads are executed */ volatile Cpa32U numThreadsAtBarrier_g = 0; /*this is used to count the number of different thread variations created, * it is incremented during thread setup and is read only once threads are * started. It is set to zero one all threads are complete*/ Cpa32U testTypeCount_g = 0; Cpa32U packageIdCount_g = 0; EXPORT_SYMBOL(packageIdCount_g); CpaBoolean devicesCounted_g = CPA_FALSE; /*this is used to limit the maximum number of cores uses in the thread * creation*/ Cpa32U coreLimit_g = 0; /*this is used to stop user space threads from executing to the main barrier * before all threads are created*/ /*this is a shared mutex between user space threads, if one thread locks this * all other threads wait until its released, which is done by calling the * cpa_sample_code_mutex_unlock or cpa_sample_code_barrier_wait function*/ sample_code_thread_mutex_t threadControlMutex_g; /*this is the conditional variable that user space threads wait on to start, the * conditional variable is broadcast on call of startThreads, sends a broadcast * to all user space threads waiting at cpa_sample_code_barrier, each thread * attempts to lock the mutex above, restart its code, then release the mutex*/ sample_code_thread_cond_t threadConditionControl_g; /* this is used to stop user space threads from executing once registered with * the framework. * This mutex is initialized by startBarrierInit() and the locking/unlocking * mechanism is supported in startBarrier(). */ sample_code_thread_mutex_t startThreadControlMutex_g; /*this is the conditional variable that user space threads wait on to start, the * conditional variable is broadcast on call of startThreads, sends a broadcast * to all user space threads waiting at cpa_sample_code_barrier, each thread * attempts to lock the mutex above, restart its code, then release the mutex*/ sample_code_thread_cond_t startThreadConditionControl_g; /*this is local to this file and it only used once thread setup to indicate * whether threadControlMutex_g and threadConditionControl_g have been * initialized. It is reset to false once all threads are complete*/ CpaBoolean threadControlInitilised_g = CPA_FALSE; /* Threads other then the performance threads may like the know if the * barrier has been lifted and the performance threads have started to load * the QAT. SampleCodeBarrierLifted is set to CPA_TRUE when barrier is * lifted. */ CpaBoolean SampleCodeBarrierLifted = CPA_FALSE; /*this is used to check if all the threads have * been started, before that waitForCompletion function will hang forever * waiting for threads to end their work.*/ volatile thread_state_e threadState_g = THREAD_NOT_STARTED; volatile CpaBoolean reliability_g = CPA_FALSE; volatile CpaBoolean cnverr_g = CPA_FALSE; volatile CpaBoolean cnvnrerr_g = CPA_FALSE; volatile CpaBoolean dataIntegrity_g = CPA_FALSE; volatile CpaBoolean dataIntegrityVerify_g = CPA_FALSE; volatile CpaBoolean hwVerify_g = CPA_FALSE; volatile CpaBoolean keyCorrupt_g = CPA_FALSE; volatile CpaBoolean enableReadInstance_g = CPA_FALSE; /* DC chaining specific variable to enable S/W write chaining operation */ volatile CpaBoolean swWrite_g = CPA_FALSE; volatile CpaBoolean isNsRequest_g = CPA_FALSE; int verboseOutput = 1; CpaStatus setHwVerify(CpaBoolean val); CpaStatus setSwWrite(CpaBoolean val); CpaStatus setKeyCorrupt(CpaBoolean val); CpaStatus enableReadInstance(CpaBoolean val); CpaStatus setDcNsFlag(CpaBoolean val) { if (val != 0) { isNsRequest_g = CPA_TRUE; } else { isNsRequest_g = CPA_FALSE; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(isNsRequest_g); EXPORT_SYMBOL(setDcNsFlag); CpaStatus setDataIntegrity(CpaBoolean val) { dataIntegrity_g = val; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(dataIntegrity_g); EXPORT_SYMBOL(setDataIntegrity); CpaStatus setDataIntegrityVerify(CpaBoolean val) { dataIntegrity_g = val; dataIntegrityVerify_g = val; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(dataIntegrityVerify_g); EXPORT_SYMBOL(setDataIntegrityVerify); CpaStatus setReliability(CpaBoolean val) { if (val != 0) { reliability_g = CPA_TRUE; } else { reliability_g = CPA_FALSE; } return CPA_STATUS_SUCCESS; } CpaStatus setUnalignedBuffer(CpaBoolean val) { if (val != 0) { useUnalignedBuffer = CPA_TRUE; } else { useUnalignedBuffer = CPA_FALSE; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(useUnalignedBuffer); CpaStatus setUseStaticPrime(int val) { if (val != 0) { useStaticPrime = 1; } else { useStaticPrime = 0; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(useStaticPrime); CpaStatus printReliability(void) { if (CPA_TRUE == reliability_g) { PRINT("reliability_g = %s", "CPA_TRUE\n"); } else { PRINT("reliability_g = %s", "CPA_FALSE\n"); } return CPA_STATUS_SUCCESS; } CpaStatus setHwVerify(CpaBoolean val) { if (val != 0) { hwVerify_g = CPA_TRUE; } else { hwVerify_g = CPA_FALSE; } return CPA_STATUS_SUCCESS; } CpaStatus setSwWrite(CpaBoolean val) { if (val != 0) { swWrite_g = CPA_TRUE; } else { swWrite_g = CPA_FALSE; } return CPA_STATUS_SUCCESS; } CpaStatus setKeyCorrupt(CpaBoolean val) { if (val != 0) { keyCorrupt_g = CPA_TRUE; } else { keyCorrupt_g = CPA_FALSE; } return CPA_STATUS_SUCCESS; } CpaStatus enableReadInstance(CpaBoolean val) { if (val != 0) { enableReadInstance_g = CPA_TRUE; } else { enableReadInstance_g = CPA_FALSE; } return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(reliability_g); EXPORT_SYMBOL(setReliability); EXPORT_SYMBOL(setUnalignedBuffer); EXPORT_SYMBOL(setUseStaticPrime); EXPORT_SYMBOL(printReliability); EXPORT_SYMBOL(hwVerify_g); EXPORT_SYMBOL(swWrite_g); EXPORT_SYMBOL(setHwVerify); EXPORT_SYMBOL(setSwWrite); EXPORT_SYMBOL(setKeyCorrupt); EXPORT_SYMBOL(keyCorrupt_g); EXPORT_SYMBOL(enableReadInstance); EXPORT_SYMBOL(enableReadInstance_g); /*Global flag to enable sleep function that is used to slow down pulling for *request on thread RETRY e.g. concurrent performance measurements*/ CpaBoolean sleepTime_enable = CPA_FALSE; CpaStatus enableSleeptime(void) { sleepTime_enable = CPA_TRUE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(enableSleeptime); CpaStatus disableSleeptime(void) { sleepTime_enable = CPA_FALSE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(disableSleeptime); /*Global flag to enable adjustable sleep value*/ CpaBoolean adjust_sleepTime_enable_g = CPA_FALSE; CpaStatus enableAdjustSleepTime(void) { adjust_sleepTime_enable_g = CPA_TRUE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(enableAdjustSleepTime); CpaStatus disableAdjustSleepTime(void) { adjust_sleepTime_enable_g = CPA_FALSE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(disableAdjustSleepTime); /*Global sleep values for DC/SYM/RSA must be set for sleeptime functionality*/ Cpa32U dc_slv_g; Cpa32U cy_slv_g; Cpa32U rsa_slv_g; Cpa32U dc_bufferCount_g = DEFAULT_NUM_OF_BUFF_PER_LIST; CpaStatus set_dc_slv(Cpa32U arg) { dc_slv_g = arg; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(set_dc_slv); CpaStatus set_cy_slv(Cpa32U arg) { cy_slv_g = arg; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(set_cy_slv); CpaStatus set_rsa_slv(Cpa32U arg) { rsa_slv_g = arg; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(set_rsa_slv); CpaStatus set_buffer_count(Cpa32U arg) { dc_bufferCount_g = arg; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(set_buffer_count); EXPORT_SYMBOL(dc_bufferCount_g); volatile CpaBoolean fineTune_g = CPA_FALSE; volatile Cpa16U iaCycleCount_g = CPA_CC_DISABLE; /* Global Gbps rate for compression requests */ volatile Cpa32U cprRate_g = 0xFFFFFFFE; /* Setter function for lobal Gbps rate for compression requests */ CpaStatus setCprRate(Cpa32U rate) { cprRate_g = rate; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(setCprRate); CpaStatus setFineTune(CpaBoolean val) { fineTune_g = val; return CPA_STATUS_SUCCESS; } CpaStatus printFineTune(void) { if (CPA_TRUE == fineTune_g) { PRINT("fineTune_g = %s", "CPA_TRUE\n"); } else { PRINT("fineTune_g = %s", "CPA_FALSE\n"); } return CPA_STATUS_SUCCESS; } CpaStatus enableCycleCount(void) { iaCycleCount_g = CPA_CC_REQ_POLL_STAMP; #ifdef SC_BSD_UPSTREAM singleInstRequired_g = CPA_TRUE; #endif return CPA_STATUS_SUCCESS; } CpaStatus disableCycleCount(void) { iaCycleCount_g = CPA_CC_DISABLE; #ifdef SC_BSD_UPSTREAM singleInstRequired_g = CPA_FALSE; #endif return CPA_STATUS_SUCCESS; } CpaStatus setCycleCountMode(int mode) { iaCycleCount_g = mode; #ifdef SC_BSD_UPSTREAM if (mode != CPA_CC_DISABLE) singleInstRequired_g = CPA_TRUE; else singleInstRequired_g = CPA_FALSE; #endif return CPA_STATUS_SUCCESS; } /*this function enables extra output from sample code such as: per thread and * per device performance.*/ int getVerboseOutput(void) { return verboseOutput; } /*this function disables extra output from sample code such as: per thread and * per device performance.*/ CpaStatus setVerboseOutput(int a) { verboseOutput = a; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(iaCycleCount_g); EXPORT_SYMBOL(getVerboseOutput); EXPORT_SYMBOL(setVerboseOutput); EXPORT_SYMBOL(enableCycleCount); EXPORT_SYMBOL(disableCycleCount); EXPORT_SYMBOL(setFineTune); EXPORT_SYMBOL(printFineTune); volatile CpaBoolean poll_inline_g = CPA_FALSE; volatile CpaBoolean xltOverflow_g = CPA_FALSE; volatile CpaBoolean exitLoopFlag_g = CPA_FALSE; volatile CpaBoolean stopTestsIsEnabled_g = CPA_FALSE; /* This is function is used to save and restore members * of perf stats that should persist after clearing all * others. */ void saveClearRestorePerfStats(perf_data_t *perf) { memset(perf, 0, sizeof(perf_data_t)); } sample_code_thread_t stress_test_threads_g; stress_test_threads_params_t stress_test_threads_params_g = {0}; CpaStatus getTestReturn(void) { CpaStatus status = CPA_STATUS_SUCCESS; sampleCodeThreadJoin(&stress_test_threads_g); if (error_flag_g == CPA_TRUE) { stress_test_threads_params_g.threadReturnStatus = CPA_STATUS_FAIL; error_flag_g = CPA_FALSE; } status = stress_test_threads_params_g.threadReturnStatus; stress_test_threads_params_g.threadReturnStatus = CPA_STATUS_SUCCESS; return status; } EXPORT_SYMBOL(getTestReturn); #ifdef POLL_INLINE CpaStatus enablePollInline(void) { poll_inline_g = CPA_TRUE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(enablePollInline); CpaStatus disablePollInline(void) { poll_inline_g = CPA_FALSE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(disablePollInline); #endif CpaStatus enableStopTests(void) { stopTestsIsEnabled_g = CPA_TRUE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(enableStopTests); EXPORT_SYMBOL(stopTestsIsEnabled_g); CpaStatus disableStopTests(void) { stopTestsIsEnabled_g = CPA_FALSE; return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(disableStopTests); CpaStatus setExitLoopFlag(Cpa32U value) { switch (value) { case EXIT_OFF: exitLoopFlag_g = CPA_FALSE; return CPA_STATUS_SUCCESS; case EXIT_IMMEDIATELY: /*setExitLoop flag to complete thread in their current loop*/ exitLoopFlag_g = CPA_TRUE; break; case EXIT_WHEN_THREADS_COMPLETE: /*wait for thread control flag to be set to false in * waitForThreadCompletion. Break if error flag was set*/ while (threadState_g != THREAD_COMPLETED && error_flag_g == CPA_FALSE) { /*wait for all threads to complete*/ sampleCodeSleepMilliSec(SLEEP_ONE_HUNDRED_MILLISEC); } break; default: PRINT_ERR("Invalid input to %s\n", __func__); return CPA_STATUS_FAIL; } return getTestReturn(); } /*exit loop mechanism to leave early if numLoops is large * note that this might not work if the we get stuck in the * do-while loop below*/ /** ***************************************************************************** * @file cpa_sample_code_framework.c * * @defgroup perfCodeFramework performance sample code framework * * @ingroup perfCodeFramework * * @description * Exit loop mechanism to leave early if the exitLoopFlag is set * as it will change the value of numLoops in the setup structure to the * current index value of the loop + EXIT_OFFSET * numLoops is indicating how many time program will loop over the files. * * @param[in] performanceStats Pointer to perf_data_t structure * @param[in] numLoops Pointer to numLoops element in the setup * structure * @param[in] numLists Pointer to numLists element in the setup * structure * @param[in] localNumLoops current value of iteration over numLoops * numLoops from the structure will be * allocated to this value + OFFSET * *****************************************************************************/ void checkStopTestExitFlag(perf_data_t *performanceStats, Cpa32U *numLoops, Cpa32U *numLists, Cpa32U localNumLoops) { if (CPA_TRUE == stopTestsIsEnabled_g) { /* Check if terminated by global flag. * If yes, update numOperations and numLoops completed */ if (CPA_TRUE == exitLoopFlag_g) { *numLoops = localNumLoops + OFFSET_LOOP_EXIT; performanceStats->numOperations = (Cpa64U)(*numLoops) * (*numLists); performanceStats->numLoops = (*numLoops); } } } CpaStatus enableXltOverflow(Cpa32U value) { if (0 == value) { xltOverflow_g = CPA_FALSE; } else { xltOverflow_g = CPA_TRUE; } return CPA_STATUS_SUCCESS; } /* * The default values for the backoff timer */ volatile CpaBoolean backoff_timer_g = CPA_TRUE; volatile CpaBoolean backoff_dynamic_g = CPA_TRUE; uint32_t backoff_static_timer_g = 10; EXPORT_SYMBOL(backoff_timer_g); EXPORT_SYMBOL(backoff_dynamic_g); EXPORT_SYMBOL(backoff_static_timer_g); CpaStatus enableBackoffTimer() { backoff_timer_g = CPA_TRUE; return CPA_STATUS_SUCCESS; } CpaStatus disableBackoffTimer() { backoff_timer_g = CPA_FALSE; return CPA_STATUS_SUCCESS; } CpaStatus enableBackoffDynamic() { backoff_dynamic_g = CPA_TRUE; enableBackoffTimer(); return CPA_STATUS_SUCCESS; } CpaStatus enableBackoffStatic(uint32_t numBusyLoops) { backoff_static_timer_g = numBusyLoops; backoff_dynamic_g = CPA_FALSE; enableBackoffTimer(); return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(enableBackoffStatic); /*************************************************************************** * FUNCTION IMPLEMENTATIONS * *************************************************************************/ /* This function calls the OS to start all the created threads*/ CpaStatus startThreads(void) { Cpa32U threadId = 0; Cpa32U i = 0; FUNC_ENTRY(); /* Wait for all the threads arrived to start barrier state and then * send broadcast message to all threads for execution */ sample_code_wait_threads_arrived(SLEEP_ONE_SEC, MAX_RETRY); /* broadcast to user space threads that they can start, this does nothing * in kernel space*/ sample_code_thread_mutex_lock(&startThreadControlMutex_g); sample_code_thread_cond_broadcast(&startThreadConditionControl_g); sample_code_thread_mutex_unlock(&startThreadControlMutex_g); /*start all threads*/ for (threadId = 0; threadId < numCreatedThreads_g; threadId++) { if (sampleCodeThreadStart(&threads_g[threadId]) != CPA_STATUS_SUCCESS) { /* if we can't start one thread we kill all created threads * and return fail*/ for (threadId = 0; threadId < numCreatedThreads_g; threadId++) { if (numCreatedThreads_g > 0) { sampleCodeThreadKill(&threads_g[numCreatedThreads_g - 1]); numCreatedThreads_g--; } } for (i = 0; i < testTypeCount_g; i++) { if (NULL != perfStats_g[i]) { qaeMemFree((void **)&perfStats_g[i]); } } PRINT_ERR("can't start threads\n"); return CPA_STATUS_FAIL; } } /* after that each thread has started, set the flag that indicate * startThreads has been called*/ threadState_g = THREAD_STARTED; /* Reset the flag, when all threads are executed */ sample_code_thread_mutex_lock(&startThreadControlMutex_g); numThreadsAtBarrier_g = 0; sample_code_thread_mutex_unlock(&startThreadControlMutex_g); FUNC_EXIT(); return CPA_STATUS_SUCCESS; } /*This functions waits for all threads to complete including all perform * operations. It is required to wait for all threads to complete so that * performance stats can be collated*/ CpaStatus waitForThreadCompletion(void) { CpaStatus status = CPA_STATUS_SUCCESS; CpaStatus statusPrintFunc = CPA_STATUS_SUCCESS; Cpa32U i = 0; stats_print_func_t statsPrintFunc; FUNC_ENTRY(); /* Check if starThread has been called*/ if (threadState_g == THREAD_STARTED) { /* Wait for all threads_g to complete */ for (i = 0; i < numCreatedThreads_g; i++) { if (CPA_STATUS_SUCCESS != sampleCodeThreadCollect(&threads_g[i], i)) { PRINT_ERR("sampleCodeThreadCollect failed\n"); status = CPA_STATUS_FAIL; } /* If user supplied specific pass criteria, * determine test status using it. */ if (singleThreadData_g[i].passCriteria != NULL) { if (CPA_STATUS_SUCCESS != singleThreadData_g[i].passCriteria( (void *)(&singleThreadData_g[i]))) status = CPA_STATUS_FAIL; } else { if ((CPA_STATUS_FAIL == singleThreadData_g[i] .performanceStats->threadReturnStatus) || (error_flag_g == CPA_TRUE)) { status = CPA_STATUS_FAIL; } } if (CPA_TRUE == singleThreadData_g[i].isUsedByMega) { if (CPA_STATUS_UNSUPPORTED == singleThreadData_g[i].performanceStats->threadReturnStatus) { status = CPA_STATUS_UNSUPPORTED; } if (CPA_STATUS_FAIL == status) { PRINT_ERR("Mega Thread using row %d failed\n", singleThreadData_g[i].megaRowId); } else if (CPA_STATUS_UNSUPPORTED == status) { PRINT("Mega Thread using row %d unsupported\n", singleThreadData_g[i].megaRowId); } else { PRINT("Mega Thread using row %d passed\n", singleThreadData_g[i].megaRowId); } } } /*print out collated stats for all types of threads*/ #ifndef NEWDISLAY PRINT("---------------------------------------\n"); #endif for (i = 0; i < testTypeCount_g; i++) { if ((CPA_STATUS_UNSUPPORTED == status) ||(CPA_STATUS_UNSUPPORTED == singleThreadData_g[i].performanceStats->threadReturnStatus)) { continue; } statsPrintFunc = *(testSetupData_g[i].statsPrintFunc); if (statsPrintFunc != NULL) { statusPrintFunc = statsPrintFunc(&testSetupData_g[i]); } else { PRINT_ERR("Unable to print stats for thread variation %d\n", i); status = CPA_STATUS_FAIL; } if (NULL != perfStats_g[i]) { qaeMemFree((void **)&perfStats_g[i]); } if (i < testTypeCount_g - 1) { PRINT("---------------------------------------\n\n"); } } if (statusPrintFunc == CPA_STATUS_FAIL) { status = CPA_STATUS_FAIL; } #ifndef NEWDISLAY PRINT("---------------------------------------\n\n"); #endif /* Clean up and exit */ error_flag_g = CPA_FALSE; threadControlInitilised_g = CPA_FALSE; threadState_g = THREAD_COMPLETED; numCreatedThreads_g = 0; testTypeCount_g = 0; packageIdCount_g = 0; devicesCounted_g = CPA_FALSE; sampleCodeBarrierDestroy(); } else { PRINT_ERR("startThreads() has not been called\n"); } FUNC_EXIT(); return status; } /*this function reset the thread related variables and release memory on error * exit */ void threadExitCleanup(void) { Cpa32U i = 0; for (i = 0; i < testTypeCount_g; i++) { if (NULL != perfStats_g[i]) { qaeMemFree((void **)&perfStats_g[i]); } } threadControlInitilised_g = CPA_FALSE; threadState_g = THREAD_COMPLETED; testTypeCount_g = 0; packageIdCount_g = 0; devicesCounted_g = CPA_FALSE; } /*this function limits the number of cores to be used in the create threads * function*/ CpaStatus setCoreLimit(Cpa32U limit) { Cpa32U nProcessorsOnline = sampleCodeGetNumberOfCpus(); if (limit > nProcessorsOnline) { PRINT_ERR("exceeds number of cores (%u) on system\n", nProcessorsOnline); return CPA_STATUS_FAIL; } coreLimit_g = limit; return CPA_STATUS_SUCCESS; } /*Init perfStats_g for all thread types to NULL*/ CpaStatus initPerfStats(Cpa32U testTypeIndex, Cpa32U numberOfThreads) { CpaStatus status = CPA_STATUS_SUCCESS; Cpa32U i = 0; if (perfStatsInit_g == CPA_FALSE) { for (i = 0; i < MAX_THREAD_VARIATION; i++) { perfStats_g[i] = NULL; } perfStatsInit_g = CPA_TRUE; } /*free if not already free, this should not happen, so print a warning * in the event that it needed to be free'd*/ if (NULL != perfStats_g[testTypeIndex]) { PRINT("Warning perfStats not free'd from previous use\n"); qaeMemFree((void **)&perfStats_g[testTypeIndex]); } /*allocate memory to store perfStats for each thread created*/ perfStats_g[testTypeIndex] = qaeMemAlloc(sizeof(perf_data_t) * numberOfThreads); if (NULL == perfStats_g[testTypeIndex]) { PRINT_ERR("Could not allocate memory for perfStats_g[%u]\n", testTypeIndex); status = CPA_STATUS_FAIL; } return status; } /*This function creates threads based on the pre-condition that the user has * called a setup function that has populated the oneTypeOfThreadData. This * function creates threads based on what is in the oneTypeOfThreadData at the * current threadVariationCount (which is an index into the oneTypeOfThreadData * array. * This function replicates threads across cores*/ CpaStatus createPerfomanceThreads(Cpa32U numLogicalIaCoresToUse, Cpa32U *logicalIaCore, Cpa32U numberLogicalInstancesToUse, Cpa32U startingQaLogicalInstanceOffset) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U i = 0; Cpa32U qaLogicalInstance = startingQaLogicalInstanceOffset; Cpa32U totalNumberOfThreads = 0; Cpa32U numOfInsToUse = 1; /*this is the total number of threads to create of the current setup and * depends on either how many cores are on the SUT or how many the user * wants to use*/ performance_func_t functionPtr = NULL; Cpa32U nProcessorsOnline = 0; sample_code_thread_attr_t *threadAttr = NULL; if (enableReadInstance_g) numOfInsToUse = 2; /*1st we check that we still have room to store details of the threads to * be created*/ if (testTypeCount_g >= MAX_THREAD_VARIATION) { PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); return CPA_STATUS_FAIL; } if (testSetupData_g[testTypeCount_g].performance_function == NULL) { PRINT_ERR("No thread function has been set\n"); return CPA_STATUS_FAIL; } /*initialize thread control for user space, in kernel space this code * does nothing, we only do this once*/ if (threadControlInitilised_g == CPA_FALSE) { sampleCodeBarrierInit(); startBarrierInit(); threadControlInitilised_g = CPA_TRUE; } /*get the number of cores on the system*/ nProcessorsOnline = sampleCodeGetNumberOfCpus(); /*calculate the number of threads to be setup*/ if (numLogicalIaCoresToUse != USE_ALL_CORES) { totalNumberOfThreads = numLogicalIaCoresToUse / numOfInsToUse; } else { if (coreLimit_g > 0) { totalNumberOfThreads = coreLimit_g; } else { totalNumberOfThreads = nProcessorsOnline; } } /*populate the threadData we area creating*/ /*&thread_setup_g[testTypeCount_g][0] is a pointer to an area of memory * that contains the setup, so get the base address of this memory location * */ testSetupData_g[testTypeCount_g].setupPtr = &thread_setup_g[testTypeCount_g][0]; testSetupData_g[testTypeCount_g].numberOfThreads = totalNumberOfThreads; functionPtr = testSetupData_g[testTypeCount_g].performance_function; /* Set numThreadsToCreate so that if any thread rushes to doing its actual * processing, * it's stopped by sampleCodeBarrier until number of threads reaching * barrier becomes * equal to this variable */ numThreadsToCreate_g = totalNumberOfThreads; status = initPerfStats(testTypeCount_g, numThreadsToCreate_g); if (CPA_STATUS_SUCCESS != status) { return status; } /*populate threadData with performance stats, * setupData and sessions etc...*/ for (i = 0; i < totalNumberOfThreads; i++) { /*wrap around core to use if we have exceed max number of cores*/ if (logicalIaCore[i] >= nProcessorsOnline) { PRINT("Warning we have reached core limit "); PRINT("resetting core to 0\n"); logicalIaCore[i] = 0; } /*check that we have not reached allocated memory limit to store * thread data*/ if (numCreatedThreads_g >= MAX_THREADS) { PRINT_ERR("Maximum Support Thread has been reached\n"); PRINT_ERR("Number of Threads created: %d ", numCreatedThreads_g); PRINT_ERR("Max is %d\n", MAX_THREADS); /*kill any threads we have created in this current function * context*/ killCreatedThreads(i); if (NULL != perfStats_g[testTypeCount_g]) { qaeMemFree((void **)&perfStats_g[testTypeCount_g]); } return CPA_STATUS_FAIL; } if ((testTypeCount_g < MAX_THREAD_VARIATION)) { clearPerfStats(&perfStats_g[testTypeCount_g][i]); testSetupData_g[testTypeCount_g].performanceStats[i] = &perfStats_g[testTypeCount_g][i]; testSetupData_g[testTypeCount_g].statsPrintFunc = &singleThreadData_g[numCreatedThreads_g].statsPrintFunc; /*&thread_setup_g[testTypeCount_g][0] is a pointer to an area of * memory that contains the setup, so get the base address of this * memory location, the thread that we call is expected to be able * to cast this memory location into the structure that it expects*/ singleThreadData_g[numCreatedThreads_g].setupPtr = &thread_setup_g[testTypeCount_g][0]; singleThreadData_g[numCreatedThreads_g].performanceStats = &perfStats_g[testTypeCount_g][i]; singleThreadData_g[numCreatedThreads_g].packetSize = testSetupData_g[testTypeCount_g].packetSize; singleThreadData_g[numCreatedThreads_g].logicalQaInstance = qaLogicalInstance; if (enableReadInstance_g) { singleThreadData_g[numCreatedThreads_g].logicalQaReadInstance = qaLogicalInstance + 1; } singleThreadData_g[numCreatedThreads_g].threadID = numCreatedThreads_g; singleThreadData_g[numCreatedThreads_g].passCriteria = NULL; singleThreadData_g[numCreatedThreads_g].megaRowId = testSetupData_g[testTypeCount_g].megaRowId; singleThreadData_g[numCreatedThreads_g].isUsedByMega = testSetupData_g[testTypeCount_g].isUsedByMega; /*Initialize completion structure for kernel space thread * management.*/ sampleCodeCompletionInit(numCreatedThreads_g); /*we need to increment numCreatedThreads_g here otherwise if it * is used in the new thread there could be timing issue*/ numCreatedThreads_g++; status = sampleCodeThreadCreate( &threads_g[numCreatedThreads_g - 1], threadAttr, functionPtr, &singleThreadData_g[numCreatedThreads_g - 1]); } else { PRINT_ERR("testTypeCount_g or thread variations hit max limit"); status = CPA_STATUS_FAIL; } if (status != CPA_STATUS_SUCCESS) { PRINT_ERR("Failed to create thread: %d", i); /*we can safely kill all threads in kernel space because * they have not started...in user space, dynamically * allocated memory is assumed to be freed by the OS*/ numCreatedThreads_g--; killCreatedThreads(i); if (NULL != perfStats_g[testTypeCount_g]) { qaeMemFree((void **)&perfStats_g[testTypeCount_g]); } return CPA_STATUS_FAIL; } else { /*tie a create thread to a specific core */ #if defined(_WIN64) || defined(WIN32) singleThreadData_g[numCreatedThreads_g - 1] .performanceStats->logicalCoreAffinity = logicalIaCore[i]; #endif if (CPA_STATUS_SUCCESS != sampleCodeThreadBind(&threads_g[numCreatedThreads_g - 1], logicalIaCore[i])) { PRINT_ERR("Failed to bind thread: %d", i); killCreatedThreads(i); if (NULL != perfStats_g[testTypeCount_g]) { qaeMemFree((void **)&perfStats_g[testTypeCount_g]); } return CPA_STATUS_FAIL; } } qaLogicalInstance = qaLogicalInstance + numOfInsToUse; /*wrap around qaLogicalInstance if we have used all that was intended * to use * WARNING this framework is not aware of the number of QA instances * in the system it assumes the user will pass in the right * information*/ if (qaLogicalInstance - startingQaLogicalInstanceOffset == numberLogicalInstancesToUse) { qaLogicalInstance = startingQaLogicalInstanceOffset; } } testTypeCount_g++; return CPA_STATUS_SUCCESS; } /* This function reprocesses the threads setting the logicalQaCoreIndex * correctly within each already created Crypto Thread * Input Arguments: * threadoffset : The thread number to start with reprocessing. * cyIaCore : The Crypto Instances array that includes both sym * and asym instances. * symOrasymIaCore : The Symmetric or Asymmetric Crypto array. * numCyInstances : size of cyIaCore array. */ void qatModifyCyThreadLogicalQaInstance(Cpa8U threadOffset, CpaInstanceHandle *cyIaCore, CpaInstanceHandle *symOrAsymIaCore, Cpa8U numCyInstances) { Cpa32U i = 0; Cpa8U j = 0; for (i = threadOffset; i < numCreatedThreads_g; i++) { for (j = 0; j < numCyInstances; j++) { if (symOrAsymIaCore[singleThreadData_g[i].logicalQaInstance] == cyIaCore[j]) { singleThreadData_g[i].logicalQaInstance = j; break; } } } } CpaBoolean isSampleCodeBarrierLifted(void) { return SampleCodeBarrierLifted; } EXPORT_SYMBOL(isSampleCodeBarrierLifted); void killCreatedThreads(Cpa32U numThreadsToKill) { Cpa32U j = 0; /*kill any create threads*/ if (numThreadsToKill > numCreatedThreads_g) { numThreadsToKill = numCreatedThreads_g; } for (j = 0; j < numThreadsToKill; j++) { if (numCreatedThreads_g > 0) { sampleCodeThreadKill(&threads_g[numCreatedThreads_g - 1]); numCreatedThreads_g--; } } } void clearPerfStats(perf_data_t *stats) { memset(stats, 0, sizeof(perf_data_t)); } void getLongestCycleCount(perf_data_t *dest, perf_data_t *src[], Cpa32U count) { Cpa32U i = 0; for (i = 0; i < count; i++) { if (src[i]->threadReturnStatus == CPA_STATUS_SUCCESS) break; } if (NULL != dest && NULL != src && NULL != src[i]) { dest->startCyclesTimestamp = src[i]->startCyclesTimestamp; dest->endCyclesTimestamp = src[i]->endCyclesTimestamp; } else { PRINT_ERR("Cannot get cycle counts," " performance data points to NULL\n"); return; } for (i = 1; i < count; i++) { if (src[i]->threadReturnStatus == CPA_STATUS_SUCCESS) { /*get the lowest start time*/ if ((src[i]->startCyclesTimestamp < dest->startCyclesTimestamp)) { dest->startCyclesTimestamp = src[i]->startCyclesTimestamp; } /*get the high finish time*/ if ((src[i]->endCyclesTimestamp > dest->endCyclesTimestamp)) { dest->endCyclesTimestamp = src[i]->endCyclesTimestamp; } } } } void getLongestCycleCount2(perf_data_t *dest, perf_data_t *src[], Cpa32U count, Cpa32U *perfDataDeviceOffsets, Cpa32U *threadCountPerDevice) { Cpa32U i = 0; Cpa32U j = 0; /*zero out perfDataDeviceOffsets*/ for (i = 0; i < (packageIdCount_g + 1); i++) { threadCountPerDevice[i] = 0; perfDataDeviceOffsets[i] = 0; } /* Count the threadPerDevice value based on * package Id of first thread */ j = src[0]->packageId; threadCountPerDevice[j] = 1; for (i = 1; i < count; i++) { if (src[i]->packageId > src[i - 1]->packageId) { j++; perfDataDeviceOffsets[j] = i; } if (j < (packageIdCount_g + 1)) { threadCountPerDevice[j]++; } } for (i = 0; i < (packageIdCount_g + 1); i++) { getLongestCycleCount( &dest[i], &src[perfDataDeviceOffsets[i]], threadCountPerDevice[i]); } } /* get the core affinity of a given instance handle */ CpaStatus getCoreAffinity(CpaInstanceHandle instance, Cpa32U *coreAffinity, Cpa32U instType) { CpaInstanceInfo2 info = {0}; Cpa32U i = 0; CpaStatus status = CPA_STATUS_FAIL; switch (instType) { #ifdef DO_CRYPTO case CRYPTO: { status = cpaCyInstanceGetInfo2(instance, &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); return status; } } break; #endif /* DO_CRYPTO */ #ifdef INCLUDE_COMPRESSION case COMPRESSION: { status = cpaDcInstanceGetInfo2(instance, &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); return status; } } break; #endif /*INCLUDE_COMPRESSION*/ default: { PRINT_ERR("Unknown Instance type\n"); return CPA_STATUS_FAIL; } break; } /* End Switch */ /*loop of the instanceInfo coreAffinity bitmask to find the core affinity*/ for (i = 0; i < CPA_MAX_CORES; i++) { if (CPA_BITMAP_BIT_TEST(info.coreAffinity, i)) { *coreAffinity = i; return CPA_STATUS_SUCCESS; } } PRINT_ERR("Could not find core affinity\n"); return CPA_STATUS_FAIL; } void freeInstanceMapping(void) { if (NULL != cyInst_g) { qaeMemFree((void **)&cyInst_g); } if (NULL != symCyInst_g) { qaeMemFree((void **)&symCyInst_g); } if (NULL != asymCyInst_g) { qaeMemFree((void **)&asymCyInst_g); } if (NULL != dcInst_g) { qaeMemFree((void **)&dcInst_g); } if (NULL != cyInstMap_g) { qaeMemFree((void **)&cyInstMap_g); } if (NULL != symCyInstMap_g) { qaeMemFree((void **)&symCyInstMap_g); } if (NULL != asymCyInstMap_g) { qaeMemFree((void **)&asymCyInstMap_g); } if (NULL != dcInstMap_g) { qaeMemFree((void **)&dcInstMap_g); } numInst_g = 0; } EXPORT_SYMBOL(freeInstanceMapping); CpaStatus getCryptoInstanceMapping(void) { CpaStatus status = CPA_STATUS_FAIL; #ifdef DO_CRYPTO /* Called from within this file */ Cpa32U i = 0; Cpa32U coreAffinity = 0; CpaInstanceInfo2 info = {0}; /*get the number of crypto instances*/ status = cpaCyGetNumInstances(&numInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetNumInstances failed with status: %d\n", status); freeInstanceMapping(); return CPA_STATUS_FAIL; } if (numInst_g > 0) { /* use single instance for latency and COO */ if (singleInstRequired_g) { numInst_g = 1; } /*allocate memory to store the instance handles*/ cyInst_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInst_g); if (cyInst_g == NULL) { PRINT_ERR("Failed to allocate memory for instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } /*get the instances handles and place in allocated memory*/ status = cpaCyGetInstances(numInst_g, cyInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaCyGetInstances failed with status: %d\n", status); freeInstanceMapping(); return status; } /*allocate memory for the instance core mapping*/ cyInstMap_g = qaeMemAlloc(sizeof(Cpa32U) * numInst_g); if (cyInstMap_g == NULL) { PRINT_ERR("Failed to allocate memory for instance mapping\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } for (i = 0; i < numInst_g; i++) { status = cpaCyInstanceGetInfo2(cyInst_g[i], &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); freeInstanceMapping(); return status; } if (CPA_STATUS_SUCCESS == getCoreAffinity(cyInst_g[i], &coreAffinity, CRYPTO)) { if ((packageIdCount_g < info.physInstId.packageId) && (info.operState == CPA_OPER_STATE_UP) && (CPA_FALSE == devicesCounted_g)) { packageIdCount_g = info.physInstId.packageId; } if (verboseOutput) { PRINT("Inst %u, Affin: %u, Dev: %u, Accel %u, " "BDF %02X:%02X:%02X\n", i, coreAffinity, info.physInstId.packageId, info.physInstId.acceleratorId, (Cpa8U)((info.physInstId.busAddress) >> 8), (Cpa8U)((info.physInstId.busAddress) & 0xFF) >> 3, (Cpa8U)((info.physInstId.busAddress) & 7)); } if (info.isPolled) cyInstMap_g[i] = coreAffinity; else cyInstMap_g[i] = coreAffinity + 1; } else { freeInstanceMapping(); return CPA_STATUS_FAIL; } } devicesCounted_g = CPA_TRUE; } else { PRINT("There are no crypto instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } #endif /* DO_CRYPTO*/ return status; } EXPORT_SYMBOL(getCryptoInstanceMapping); #if CY_API_VERSION_AT_LEAST(3, 0) CpaStatus getSymInstanceMapping(Cpa16U *numSymInstances) { CpaStatus status = CPA_STATUS_FAIL; #ifdef DO_CRYPTO /* Called from within this file */ Cpa32U i = 0; Cpa32U coreAffinity = 0; CpaInstanceInfo2 info = {0}; /*get the number of Sym crypto instances*/ status = cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO_SYM, numSymInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetNumInstances failed with status: %d\n", status); freeInstanceMapping(); return CPA_STATUS_FAIL; } if (*numSymInstances > 0) { /*allocate memory to store the instance handles*/ /* use single instance for latency and COO */ if (singleInstRequired_g) { *numSymInstances = 1; } symCyInst_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * (*numSymInstances)); if (symCyInst_g == NULL) { PRINT_ERR("Failed to allocate memory for instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } /*get the instances handles and place in allocated memory*/ status = cpaGetInstances( CPA_ACC_SVC_TYPE_CRYPTO_SYM, *numSymInstances, symCyInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetInstances failed with status: %d\n", status); freeInstanceMapping(); return status; } /*allocate memory for the instance core mapping*/ symCyInstMap_g = qaeMemAlloc(sizeof(Cpa32U) * (*numSymInstances)); if (symCyInstMap_g == NULL) { PRINT_ERR("Failed to allocate memory for instance mapping\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } for (i = 0; i < *numSymInstances; i++) { status = cpaCyInstanceGetInfo2(symCyInst_g[i], &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); freeInstanceMapping(); return status; } if (CPA_STATUS_SUCCESS == getCoreAffinity(symCyInst_g[i], &coreAffinity, CRYPTO)) { if ((packageIdCount_g < info.physInstId.packageId) && (info.operState == CPA_OPER_STATE_UP) && (CPA_FALSE == devicesCounted_g)) { packageIdCount_g = info.physInstId.packageId; } if (info.isPolled) symCyInstMap_g[i] = coreAffinity; else symCyInstMap_g[i] = coreAffinity + 1; } else { freeInstanceMapping(); return CPA_STATUS_FAIL; } } devicesCounted_g = CPA_TRUE; } else { PRINT("There are no Sym crypto instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } #endif /* DO_CRYPTO*/ return status; } EXPORT_SYMBOL(getSymInstanceMapping); CpaStatus getAsymInstanceMapping(Cpa16U *numAsymInstances) { CpaStatus status = CPA_STATUS_FAIL; #ifdef DO_CRYPTO /* Called from within this file */ Cpa32U i = 0; Cpa32U coreAffinity = 0; CpaInstanceInfo2 info = {0}; /*get the number of Asym crypto instances*/ status = cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO_ASYM, numAsymInstances); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetNumInstances failed with status: %d\n", status); freeInstanceMapping(); return CPA_STATUS_FAIL; } if (*numAsymInstances > 0) { /*allocate memory to store the instance handles*/ /* use single instance for latency and COO */ if (singleInstRequired_g) { *numAsymInstances = 1; } asymCyInst_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * (*numAsymInstances)); if (asymCyInst_g == NULL) { PRINT_ERR("Failed to allocate memory for instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } /*get the instances handles and place in allocated memory*/ status = cpaGetInstances( CPA_ACC_SVC_TYPE_CRYPTO_ASYM, *numAsymInstances, asymCyInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaGetInstances failed with status: %d\n", status); freeInstanceMapping(); return status; } /*allocate memory for the instance core mapping*/ asymCyInstMap_g = qaeMemAlloc(sizeof(Cpa32U) * (*numAsymInstances)); if (asymCyInstMap_g == NULL) { PRINT_ERR("Failed to allocate memory for instance mapping\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } for (i = 0; i < *numAsymInstances; i++) { status = cpaCyInstanceGetInfo2(asymCyInst_g[i], &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); freeInstanceMapping(); return status; } if (CPA_STATUS_SUCCESS == getCoreAffinity(asymCyInst_g[i], &coreAffinity, CRYPTO)) { if ((packageIdCount_g < info.physInstId.packageId) && (info.operState == CPA_OPER_STATE_UP) && (CPA_FALSE == devicesCounted_g)) { packageIdCount_g = info.physInstId.packageId; } if (info.isPolled) asymCyInstMap_g[i] = coreAffinity; else asymCyInstMap_g[i] = coreAffinity + 1; } else { freeInstanceMapping(); return CPA_STATUS_FAIL; } } devicesCounted_g = CPA_TRUE; } else { PRINT("There are no Asym crypto instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } #endif /* DO_CRYPTO*/ return status; } EXPORT_SYMBOL(getAsymInstanceMapping); #endif #ifdef INCLUDE_COMPRESSION /*get the instance to core affinity mapping of the compression instances and * populate the InstMap structure*/ CpaStatus getCompressionInstanceMapping(void) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U i = 0; Cpa32U coreAffinity = 0; CpaInstanceInfo2 info = {0}; /*get the number of compression instances*/ status = cpaDcGetNumInstances(&numInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetNumInstances failed with status: %d\n", status); freeInstanceMapping(); return CPA_STATUS_FAIL; } if (numInst_g > 0) { /* use single instance for latency and COO */ if (singleInstRequired_g) { numInst_g = 1; } /*allocate memory to store the instance handles*/ dcInst_g = qaeMemAlloc(sizeof(CpaInstanceHandle) * numInst_g); if (dcInst_g == NULL) { PRINT_ERR("Failed to allocate memory for instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } /*get the instances handles and place in allocated memory*/ status = cpaDcGetInstances(numInst_g, dcInst_g); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("cpaDcGetInstances failed with status: %d\n", status); freeInstanceMapping(); return status; } /*allocate memory for the instance core mapping*/ dcInstMap_g = qaeMemAlloc(sizeof(Cpa32U) * numInst_g); if (dcInstMap_g == NULL) { PRINT_ERR("Failed to allocate memory for instance mapping\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } for (i = 0; i < numInst_g; i++) { status = cpaDcInstanceGetInfo2(dcInst_g[i], &info); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("could not get instance info\n"); freeInstanceMapping(); return status; } if (CPA_STATUS_SUCCESS == getCoreAffinity(dcInst_g[i], &coreAffinity, COMPRESSION)) { if ((packageIdCount_g < info.physInstId.packageId) && (info.operState == CPA_OPER_STATE_UP) && CPA_FALSE == devicesCounted_g) { packageIdCount_g = info.physInstId.packageId; } if (verboseOutput) { PRINT("Inst %u, Affin: %u, Dev: %u, Accel %u, " "BDF %02X:%02X:%02X\n", i, coreAffinity, info.physInstId.packageId, info.physInstId.acceleratorId, (Cpa8U)((info.physInstId.busAddress) >> 8), (Cpa8U)((info.physInstId.busAddress) & 0xFF) >> 3, (Cpa8U)((info.physInstId.busAddress) & 7)); } if (info.isPolled) dcInstMap_g[i] = coreAffinity; else dcInstMap_g[i] = coreAffinity + 1; } else { freeInstanceMapping(); return CPA_STATUS_FAIL; } } devicesCounted_g = CPA_TRUE; } else { PRINT("There are no compression instances\n"); freeInstanceMapping(); return CPA_STATUS_FAIL; } return status; } EXPORT_SYMBOL(getCompressionInstanceMapping); #endif CpaStatus createStartandWaitForCompletionCrypto(Cpa32U instType) { CpaStatus status = CPA_STATUS_FAIL; #if CY_API_VERSION_AT_LEAST(3, 0) status = createStartandWaitForCompletion(instType); #endif #if !CY_API_VERSION_AT_LEAST(3, 0) status = createStartandWaitForCompletion(CRYPTO); #endif return status; } /*this function can only be called after the last setup function has been * called, it creates the threads for the last setup function called, then * starts all threads and waits for all threads to complete. */ CpaStatus createStartandWaitForCompletion(Cpa32U instType) { CpaStatus status = CPA_STATUS_FAIL; Cpa32U *instMap = NULL; Cpa16U numInst = 0; #if CY_API_VERSION_AT_LEAST(3, 0) CpaBoolean isSymAsymConf = CPA_FALSE; CpaInstanceHandle *sym_asymInst = NULL; Cpa16U nSymInstances = 0; Cpa16U nAsymInstances = 0; if ((instType != COMPRESSION) ) { cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO_SYM, &nSymInstances); cpaGetNumInstances(CPA_ACC_SVC_TYPE_CRYPTO_ASYM, &nAsymInstances); if ((nSymInstances > 0) && (nAsymInstances > 0)) { isSymAsymConf = CPA_TRUE; } } #endif switch (instType) { #ifdef DO_CRYPTO #if CY_API_VERSION_AT_LEAST(3, 0) case SYM: if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } instMap = cyInstMap_g; numInst = numInst_g; if (isSymAsymConf == CPA_TRUE) { if (CPA_STATUS_SUCCESS != getSymInstanceMapping(&nSymInstances)) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } numInst = nSymInstances; instMap = symCyInstMap_g; sym_asymInst = symCyInst_g; } break; case ASYM: if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } instMap = cyInstMap_g; numInst = numInst_g; if (isSymAsymConf == CPA_TRUE) { if (CPA_STATUS_SUCCESS != getAsymInstanceMapping(&nAsymInstances)) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } numInst = nAsymInstances; instMap = asymCyInstMap_g; sym_asymInst = asymCyInst_g; } break; #endif case CRYPTO: { if (CPA_STATUS_SUCCESS != getCryptoInstanceMapping()) { PRINT_ERR("Could not get Crypto Instance mapping\n"); return CPA_STATUS_FAIL; } instMap = cyInstMap_g; numInst = numInst_g; } break; #endif /* DO_CRYPTO */ #ifdef INCLUDE_COMPRESSION case COMPRESSION: { if (CPA_STATUS_SUCCESS != getCompressionInstanceMapping()) { PRINT_ERR("Could not get Compression Instance mapping\n"); return CPA_STATUS_FAIL; } instMap = dcInstMap_g; numInst = numInst_g; } break; #endif default: { PRINT_ERR("Invalid instance type\n"); return CPA_STATUS_FAIL; } break; } /* End Switch */ #if CY_API_VERSION_AT_LEAST(3, 0) if ((isSymAsymConf == CPA_TRUE) && (instType == SYM || instType == ASYM)) { isChangingThreadQaInstanceRequired_g = CPA_TRUE; } #endif status = createPerfomanceThreads(numInst, instMap, USE_ALL_QA_LOGICAL_INSTANCES, DEFAULT_LOGICAL_INST_INSTANCE_OFFSET); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not create threads, status: %d\n", status); return status; } #if CY_API_VERSION_AT_LEAST(3, 0) if ((isSymAsymConf == CPA_TRUE) && (instType == SYM || instType == ASYM)) { qatModifyCyThreadLogicalQaInstance( 0, cyInst_g, sym_asymInst, numInst_g); isChangingThreadQaInstanceRequired_g = CPA_FALSE; } #endif status = startThreads(); if (CPA_STATUS_SUCCESS != status) { PRINT_ERR("Could not start threads, status: %d\n", status); return status; } /*wait for threads_g to finished and print out stats*/ status = waitForThreadCompletion(); freeInstanceMapping(); return status; } CpaStatus allocThreadMem() { #ifdef USER_SPACE testSetupData_g = qaeMemAlloc(sizeof(thread_creation_data_t) * MAX_THREAD_VARIATION); if(testSetupData_g == NULL) { PRINT_ERR("Failed to allocate memory for testSetupData\n"); return CPA_STATUS_FAIL; } singleThreadData_g = qaeMemAlloc(sizeof(single_thread_test_data_t) * MAX_THREADS); if(singleThreadData_g ==NULL) { PRINT_ERR("Failed to allocate memory for singleThreadData\n"); return CPA_STATUS_FAIL; } threads_g = qaeMemAlloc(sizeof(sample_code_thread_t) * MAX_THREADS); if(threads_g ==NULL) { PRINT_ERR("Failed to allocate memory for thread\n"); return CPA_STATUS_FAIL; } thread_setup_g = qaeMemAlloc(sizeof(*thread_setup_g) * MAX_THREAD_VARIATION); if (*thread_setup_g == NULL) { PRINT_ERR("Failed to allocate memory for thread_setup_g\n"); return CPA_STATUS_FAIL; } thread_name_g = qaeMemAlloc(sizeof(*thread_name_g) * MAX_THREAD_VARIATION); if (*thread_name_g == NULL) { PRINT_ERR("Failed to allocate memory for thread_name_g\n"); return CPA_STATUS_FAIL; } #endif return CPA_STATUS_SUCCESS; } EXPORT_SYMBOL(allocThreadMem); void freeThreadMem() { #ifdef USER_SPACE if(testSetupData_g != NULL) { qaeMemFree((void **)&testSetupData_g); } if(singleThreadData_g != NULL) { qaeMemFree((void **)&singleThreadData_g); } if(threads_g!= NULL) { qaeMemFree((void **)&threads_g); } if((*thread_setup_g) != NULL) { qaeMemFree((void **)&(thread_setup_g)); } if((*thread_name_g) != NULL) { qaeMemFree((void **)&(thread_name_g)); } #endif } EXPORT_SYMBOL(freeThreadMem); int latency_debug = 0; /* set to 1 for debug PRINT() */ EXPORT_SYMBOL(latency_debug); int latency_enable = 0; /* set to 1 for enable latency testing */ EXPORT_SYMBOL(latency_enable); cpa_sample_code_framework.h000066400000000000000000000645331503624047500367420ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_framework.h * * This file provides prototypes, macros and structures required in the sample * code framework * *****************************************************************************/ #ifndef _SAMPLECODEFRAMEWORK_H__ #define _SAMPLECODEFRAMEWORK_H__ #include "busy_loop.h" #include "cpa.h" #include "cpa_cy_common.h" #include "cpa_sample_code_utils_common.h" #include "cpa_dc.h" /* after terminate the loop, we need adjust loop offset */ #define OFFSET_LOOP_EXIT 1 #define EXIT_OFF 0 #define EXIT_IMMEDIATELY 1 #define EXIT_WHEN_THREADS_COMPLETE 2 /* The global variable dc_bufferCount_g should be initialized by * * DEFAULT_NUM_OF_BUFF_PER_LIST */ #define DEFAULT_NUM_OF_BUFF_PER_LIST 1 /* this is used to allocate space for all types test setups, this is unknown to * the framework. * the size of this is based on the assumption that the CpaCySymSessionSetupData * is the largest setup structure in the QA API's so we set our size to be 2 * times the size of CpaCySymSessionSetupData ~90bytes to allow enough room for * all setup types*/ #ifdef USER_SPACE #define MAX_SETUP_STRUCT_SIZE_IN_BYTES (800) #else #define MAX_SETUP_STRUCT_SIZE_IN_BYTES (700) #endif /*the following macros are defined for default cores to be used in tests, * */ /*some functions, such as symmetric crypto have multi purpose (hash, cipher) * this means that some parameters passed to functions are not used, we define * and use this macro in the code where this an input parameter is not used*/ #define NOT_USED (0) /*flag to indicate to createThreads function to create and bind a thread on all * Available cores or just one core*/ #define USE_ALL_CORES (0) #define USE_ONE_CORE (1) /*flag to indicate to createThreads function start creating threads for this * core id and upwards*/ #define DEFAULT_CORE_OFFSET (0) /*flag to the createThread function to attempt to use as many qa logical * instances as possible, however as the framework applies 1 thread per core * and each threads uses its own qaInstance, and there is generally more * qaInstances available then cores means that use of all qaLogicalInstances * is normally not possible*/ #define USE_ALL_QA_LOGICAL_INSTANCES (0) #define USE_ONE_QA_LOGICAL_INSTANCE (1) /*this defines the 1st qaLogicalInstance to be used with the 1st create thread * the each threads uses and incremental instance from this offset*/ #define DEFAULT_LOGICAL_INST_INSTANCE_OFFSET (0) #define DEFAULT_MAP (0x1) #define CRYPTO (1) #define COMPRESSION (2) #define SYM (3) #define ASYM (4) #define MAX_RETRY (10) #define SLEEP_ONE_SEC (1) #define SLEEP_ONE_HUNDRED_MILLISEC (100) /* Common macro definitions */ #ifndef DC_API_VERSION_AT_LEAST #define DC_API_VERSION_AT_LEAST(major, minor) \ (CPA_DC_API_VERSION_NUM_MAJOR > major || \ (CPA_DC_API_VERSION_NUM_MAJOR == major && \ CPA_DC_API_VERSION_NUM_MINOR >= minor)) #endif typedef CpaStatus (*compute_test_result_func_t)(void *); /** ***************************************************************************** * @ingroup perfCodeFramework * Thread Creation Setup Data. * @description * This structure contains data relating to setting and replicating a * thread across cores * ****************************************************************************/ typedef struct thread_creation_data_s { performance_func_t performance_function; /*function to launch as a thread to measure performance */ void *setupPtr; /*pointer to setup data specific to the performance Test type*/ Cpa32U numberOfThreads; /*stores the number of threads to be created with the data store in * setupPtr*/ perf_data_t *performanceStats[MAX_THREADS]; /*stores performance stats for all threads of same test_type and same * setup*/ Cpa32U packetSize; /*flat buffer size to be tested*/ stats_print_func_t *statsPrintFunc; /*pointer to function capable of printing our stat related to specific * test variation*/ Cpa32U megaRowId; /* mega row id reference */ CpaBoolean isUsedByMega; /* indicates if this thread is created by mega api */ } thread_creation_data_t; /** ***************************************************************************** * @ingroup perfCodeFramework * Thread Creation Setup Data. * @description * This structure contains data relating to a single thread * ****************************************************************************/ typedef struct single_thread_test_data_s { void *setupPtr; /*pointer to setup data specific to the performance Test type*/ Cpa32U numberOfThreads; perf_data_t *performanceStats; /*performance stats points to one of the performanceStats of * thread_creation_data*/ Cpa32U packetSize; /*flat buffer size to be tested*/ Cpa32U logicalQaInstance; Cpa32U logicalQaReadInstance; /*the logicalQaInstance for the thread to use*/ stats_print_func_t statsPrintFunc; /*pointer to function capable of printing our status related to specific * test variation*/ Cpa32U threadID; /* Unique Thread ID based on the order in which the thread is created */ compute_test_result_func_t passCriteria; /* policy function that is called after the results have been collected * to determine pass criteria. Users can populate this pointer to add * specific pass criteria for the tests on per thread basis. */ Cpa32U megaRowId; /* mega row id reference */ CpaBoolean isUsedByMega; /* indicates if this thread is created by mega api */ } single_thread_test_data_t; extern int useStaticPrime; extern int useUnalignedBuffer; extern volatile CpaBoolean reliability_g; extern volatile CpaBoolean cnverr_g; extern volatile CpaBoolean cnvnrerr_g; extern volatile CpaBoolean error_flag_g; extern volatile CpaBoolean dataIntegrity_g; extern volatile CpaBoolean dataIntegrityVerify_g; extern volatile CpaBoolean hwVerify_g; extern volatile CpaBoolean swWrite_g; extern volatile CpaBoolean keyCorrupt_g; extern volatile CpaBoolean enableReadInstance_g; CpaStatus setReliability(CpaBoolean val); CpaStatus setUnalignedBuffer(CpaBoolean val); CpaStatus setUseStaticPrime(int val); CpaStatus setDcNsFlag(CpaBoolean val); extern volatile CpaBoolean isNsRequest_g; CpaStatus setDataIntegrity(CpaBoolean val); CpaStatus setDataIntegrityVerify(CpaBoolean val); CpaStatus printReliability(void); extern volatile CpaBoolean fineTune_g; extern volatile Cpa16U iaCycleCount_g; CpaStatus setFineTune(CpaBoolean val); CpaStatus set_cy_slv(Cpa32U arg); CpaStatus set_dc_slv(Cpa32U arg); CpaStatus set_rsa_slv(Cpa32U arg); CpaStatus set_buffer_count(Cpa32U arg); CpaStatus setVerboseOutput(int a); int getVerboseOutput(void); CpaStatus initPerfStats(Cpa32U testTypeIndex, Cpa32U numberOfThreads); CpaStatus printPerfStats(Cpa32U testTypeNumber, Cpa32U threadNumber); CpaStatus printFineTune(void); CpaStatus enableSleeptime(void); CpaStatus disableSleeptime(void); CpaStatus enableAdjustSleepTime(void); CpaStatus disableAdjustSleepTime(void); /* Defines a global value for Trad API CPR rate */ extern volatile Cpa32U cprRate_g; /* Controls cprRate_g via API */ CpaStatus setCprRate(Cpa32U rate); /* Defines value iaCycleCount_g - disabled */ #define CPA_CC_DISABLE 0 /* Defines value iaCycleCount_g - enabled in timestamp mode */ #define CPA_CC_REQ_POLL_STAMP 1 /* Defines value iaCycleCount_g - enabled in busy loop mode */ #define CPA_CC_BUSY_LOOPS 2 /* Function for enabling cycle count in default mode */ CpaStatus enableCycleCount(void); /* Function for disabling cycle count */ CpaStatus disableCycleCount(void); /* Function used to set cycle count mode */ CpaStatus setCycleCountMode(int mode); #include "cpa_dc.h" /* after terminate the loop, we need adjust loop offset */ #define OFFSET_LOOP_EXIT 1 /*this global variable is used to terminate the stress cases from the loop * operation. * When it's set to CPA_TRUE, stress case will be terminated from the current * loop operation, * return successful. */ typedef struct stress_test_threads_params_s { Cpa32U numBuffers; /*number of buffers */ Cpa32U numDpBatchOp; /*number of Dp Batch Operation */ Cpa32U numRequests; /*number of Dp requests */ Cpa32U numSessions; /*number of Dp Session */ Cpa32U numLoops; /*number of loop operation */ Cpa32U numDcLoops; /*number of DC loop operation */ Cpa32U modSizeInBits; Cpa32U expSizeInBits; CpaStatus threadReturnStatus; Cpa32U corpus; /*corpus for compression test */ Cpa32U mask; /*bitmask */ Cpa32U testType; /* Compression Test Type */ CpaBoolean isStaticAndDynamic; /* Test both static and dynamic in a single function call */ CpaDcCompType algorithm; /* Compression Algorithm to run */ CpaDcSessionDir direction; /* Compression Direction */ CpaDcHuffType huffmanType; /* Static or Dynamic Huffman trees */ CpaDcSessionState state; /* Stateful or Stateless Compression */ Cpa16U numSymInstances; /* Number of Sym instances required */ Cpa16U numPkeInstances; /* Number of Pke instances required */ Cpa16U numDcInstances; /* Number of Dc instances required */ Cpa32U numDcStatefulThreads; /* Number of threads to create for Stateful compression tests */ Cpa32U numPfsThreads; /* Number of threads to create for PFS tests */ Cpa32U numCipherThreads; /* Number of threads to create for Cipher tests */ Cpa32U numAlgChainThreads; /* Number of threads to create for Alg Chain tests */ Cpa32U numHashThreads; /* Number of threads to create for Hash tests */ Cpa32U numChainingThreads; /* Number of threads to create for Chaining tests */ } stress_test_threads_params_t; extern sample_code_thread_t stress_test_threads_g; extern stress_test_threads_params_t stress_test_threads_params_g; typedef enum { THREAD_NOT_STARTED = 0, THREAD_STARTED, THREAD_COMPLETED, } thread_state_e; extern volatile thread_state_e threadState_g; extern volatile Cpa32U numCreatedThreads_g; extern volatile CpaBoolean exitLoopFlag_g; extern volatile CpaBoolean stopTestsIsEnabled_g; extern int verboseOutput; CpaStatus enableStopTests(void); CpaStatus disableStopTests(void); extern CpaStatus setExitLoopFlag(Cpa32U value); void checkStopTestExitFlag(perf_data_t *performanceStats, Cpa32U *numLoops, Cpa32U *numLists, Cpa32U localNumLoops); extern CpaStatus getTestReturn(void); extern volatile CpaBoolean xltOverflow_g; extern CpaStatus enableXltOverflow(Cpa32U value); extern volatile CpaBoolean poll_inline_g; extern CpaBoolean sleepTime_enable; extern CpaBoolean adjust_sleepTime_enable_g; extern Cpa32U dc_slv_g; extern Cpa32U cy_slv_g; extern Cpa32U rsa_slv_g; extern Cpa32U dc_bufferCount_g; #ifdef POLL_INLINE CpaStatus enablePollInline(void); CpaStatus disablePollInline(void); #endif #define CHECK_TEST_TYPE_COUNT() \ if (testTypeCount_g >= MAX_THREAD_VARIATION) \ { \ PRINT_ERR("Maximum Support Thread Variation has been exceeded\n"); \ PRINT_ERR("Number of Thread Variations created: %d", testTypeCount_g); \ PRINT_ERR(" Max is %d\n", MAX_THREAD_VARIATION); \ return CPA_STATUS_FAIL; \ } /** * ***************************************************************************** * * these variables are used to keep status of the backoff timer settings * * CpaBoolean backoff_timer_g - indicates if backoff timer is enabled * * true - enabled * * false - disabled * * backoff_dynamic_g - indicates if dynamic algorithm is enabled * * true - enabled (determine backoff delay dynamically) * * false - disabled (use static backoff delay) * * backoff_static_timer_g - number of busy loop cycles for the static * * backoff timer * *****************************************************************************/ extern volatile CpaBoolean backoff_timer_g; extern volatile CpaBoolean backoff_dynamic_g; extern uint32_t backoff_static_timer_g; extern Cpa32U testTypeCount_g; /** ***************************************************************************** * @ingroup sampleCode * enableBackoffTimer * * @description * enables backoff timer; * * @param[in] none * * @retval status of execution * * @pre * none * @post * the backoff timer is enabled * *****************************************************************************/ CpaStatus enableBackoffTimer(void); /** ***************************************************************************** * @ingroup sampleCode * disableBackoffTimer * * @description * disables backoff timer; * * @param[in] none * * @retval status of execution * * @pre * none * @post * the backoff timer is disabled * *****************************************************************************/ CpaStatus disableBackoffTimer(void); /** ***************************************************************************** * @ingroup sampleCode * e nableBackoffDynamic * * @description * enables the dynamic algorithm for the backoff timer. * The function also calls enableBackoffTimer(); * * @param[in] none * * @retval status of execution * * @pre * none * @post * the dynamic backoff timer is switched on * *****************************************************************************/ CpaStatus enableBackoffDynamic(void); /** ***************************************************************************** * @ingroup sampleCode * enableBackoffStatic * * @description * enables the static delay for the backoff timer. The delay value is to * be passed as a parameter. The delay value will be used as a number * of cycles for the busy_loop. * * @param[in] number of busy loop cycles * * @retval status of execution * * @pre * none * @post * the static backoff timer is switched on. The delay value is set. * *****************************************************************************/ CpaStatus enableBackoffStatic(uint32_t numBusyLoops); /* ***************************************************************************** * FUNCTION PROTOTYPES * ****************************************************************************/ /** ***************************************************************************** * @ingroup perfCodeFramework * setCoreLimit * * @description * this function limits the number of cores to be used in the create * threads function * * @threadSafe * No * * * * @param[in] limit the number of cores to create threads on * * * @retval This function returns * CPA_STATUS_SUCCESS when the limit is less than the number of cores on the * system * CPA_STATUS_FAIL when limit is > number of cores on the system * * @pre * none * @post * threads will be created on the limited number or cores * *****************************************************************************/ CpaStatus setCoreLimit(Cpa32U limit); /* ***************************************************************************** * FUNCTION PROTOTYPES * ****************************************************************************/ /** ***************************************************************************** * @ingroup perfCodeFramework * createPerfomanceThreads * * @description * This function creates threads. The threads are created across cores * and to use separate qaLogicalInstances * * @threadSafe * No * * * * @param[in] numLogicalIaCoresToUse the number of cores to create * threads on * * @param[in] logicalIaCore - array containing cores to bind threads to * * @param[in] numberLogicalInstancesToUse the number of qaLogicalInstancs to * use, note the implementation will create the number of threads * bases on the lower of numberOfIaCores to use or * numberLogicalInstancesToUse * * @param[in] startingLogicalInstanceOffset qaLogicalInstance to be used in * 1st threads, each subsequent thread increments this value * * @retval This function returns * CPA_STATUS_SUCCESS when all threads were created * CPA_STATUS_FAIL when some thing went wrong, an error should be printed to * STDOUT in this case * * @pre * user defined setup has been called which populates thread_setup_g with * all the * parameters and the function required to start the thread * @post * Threads are created (but not started in the case of kernel threads, user * threads have a barrier at the start to stop them until all threads * have been created * *****************************************************************************/ CpaStatus createPerfomanceThreads(Cpa32U numLogicalIaCoresToUse, Cpa32U *logicalIaCore, Cpa32U numberLogicalInstancesToUse, Cpa32U startingLogicalInstanceOffset); /** ***************************************************************************** * @ingroup perfCodeFramework * qatModifyCyThreadLogicalQaInstance * * @description * This function creates threads. The threads are created across cores * and to use separate qaLogicalInstances * * * @param[in] threadoffset : The thread number to start with reprocessing. * * @param[in] cyIaCore : The Crypto Instances array that includes both sym * and asym instances. * * @param[in] symOrasymIaCore : The Symmetric or Asymmetric Crypto array. * and asym instances. * @param[in] numCyInstances : size of cyIaCore array. * */ void qatModifyCyThreadLogicalQaInstance(Cpa8U threadOffset, CpaInstanceHandle *cyIaCore, CpaInstanceHandle *symOrAsymIaCore, Cpa8U numCyInstances); /** ***************************************************************************** * @ingroup perfCodeFramework * waitForThreadCompletion * * @description * This function waits for all created threads to complete, then print all * stats to STDOUT * * @threadSafe * No * * @retval This function returns the success of the performance threads * * @pre * threads have been started * @post * threads are complete and stats printed to STDOUT * *****************************************************************************/ CpaStatus waitForThreadCompletion(void); /** ***************************************************************************** * @ingroup perfCodeFramework * Memory and thread Data cleanup. * @description * This function reset the thread related variable and release memory * on error exit * ****************************************************************************/ void threadExitCleanup(void); /** ***************************************************************************** * @ingroup perfCodeFramework * startThreads * * @description * This function starts all the created threads, or in the case of user * threads frees the barrier to let them continue * * @threadSafe * No * * @retval This function returns * CPA_STATUS_SUCCESS when all threads were started * CPA_STATUS_FAIL when some thing went wrong, an error should be printed to * STDOUT in this case * * @pre * threads have been started * @post * threads are complete and stats printed to STDOUT * *****************************************************************************/ CpaStatus startThreads(void); /** ***************************************************************************** * @ingroup perfCodeFramework * killCreatedThreads * * @description * This function kills the the last "numThreadsToKill" created threads * * * @threadSafe * No * * @param[in] numThreadsToKill this defines how many threads from the last one * created to be killed * * @retval This function returns void * * @pre * threads have been started * @post * threads are complete and stats printed to STDOUT * *****************************************************************************/ void killCreatedThreads(Cpa32U numThreadsToKill); CpaStatus createStartandWaitForCompletion(Cpa32U instType); CpaStatus createStartandWaitForCompletionCrypto(Cpa32U instType); CpaStatus allocThreadMem(void); void freeThreadMem(void); /** ***************************************************************************** * @ingroup perfCodeFramework * clearPerfStats * * @description * clears (zeros) an instance of perf_data_t * * * @threadSafe * No * * @param[in] *stats pointer to perf_data_t structure to be cleared * * @retval This function returns void * * @pre * none * @post * perf_data_t structure pointed to contains all 0's * *****************************************************************************/ void clearPerfStats(perf_data_t *stats); /** ***************************************************************************** * @ingroup cryptoThreads * getLongestCycleCount * * @description * get the smallest starting cycle and the largest end cycle from a list * of perf_data_t structures. This function should be used on a collection * of threads all testing the same thread Variation. the src data is set to * zero once read. *****************************************************************************/ void getLongestCycleCount(perf_data_t *dest, perf_data_t *src[], Cpa32U count); void getLongestCycleCount2(perf_data_t *dest, perf_data_t *src[], Cpa32U count, Cpa32U *perfDataDeviceOffsets, Cpa32U *threadCountPerDevice); /** ***************************************************************************** * The variables needed to control latency measurement at runtime ***************************************************************************** */ extern int latency_debug; /* set to 1 for debug PRINT() */ extern int latency_enable; /* set to 1 for enable latency testing */ extern CpaInstanceHandle *cyInst_g; extern CpaInstanceHandle *symCyInst_g; extern CpaInstanceHandle *asymCyInst_g; extern CpaInstanceHandle *dcInst_g; extern Cpa32U *cyInstMap_g; extern Cpa32U *symCyInstMap_g; extern Cpa32U *asymCyInstMap_g; extern Cpa32U *dcInstMap_g; extern Cpa32U instMap_g; extern Cpa16U numInst_g; extern Cpa8U singleInstRequired_g; CpaStatus createStartandWaitForCompletion(Cpa32U instType); CpaBoolean isSampleCodeBarrierLifted(void); void freeInstanceMapping(void); CpaStatus getCryptoInstanceMapping(void); CpaStatus getSymInstanceMapping(Cpa16U *numSymInstances); CpaStatus getAsymInstanceMapping(Cpa16U *numAsymInstances); CpaStatus getCompressionInstanceMapping(void); CpaStatus getCoreAffinity(CpaInstanceHandle instance, Cpa32U *coreAffinity, Cpa32U instType); compute_test_result_func_t getPassCriteria(void); void setPassCriteria(compute_test_result_func_t pfunc); void saveClearRestorePerfStats(perf_data_t *perf); #endif /*_SAMPLECODEFRAMEWORK_H__*/ cpa_sample_code_utils_common.h000066400000000000000000001104161503624047500374450ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_utils_common.h * * This file provides linux kernel os abstraction functions * *****************************************************************************/ #ifndef _COMMON_SAMPLECODEUTILS_H__ #define _COMMON_SAMPLECODEUTILS_H__ #include "cpa_sample_code_utils.h" #include "cpa.h" #ifdef USER_SPACE #include "qae_mem.h" #else #include "qae_mem_utils.h" #endif #if defined(SC_WITH_QAT20_UPSTREAM) #define SC_WITH_GEN4 #endif #ifndef SAMPLE_CODE_CORPUS_PATH #define SAMPLE_CODE_CORPUS_PATH "/lib/firmware/" #endif #ifndef CACHE_LINE_SIZE #define CACHE_LINE_SIZE (64) #endif #define ALL_BITS_SET64U (0xFFFFFFFFFFFFFFFFL) #define __cpa_cache_aligned __attribute__((__aligned__(CACHE_LINE_SIZE))) /* ***************************************************************************** * Types & Structures * ****************************************************************************/ typedef enum { CAT_CIPHER = 0, CAT_HASH, CAT_ALG_CHAIN, CAT_NESTED, CAT_PKE, CAT_COMP, CAT_CNV } algo_category_e; #define MAX_ALGO_CATEGORY (8) /*This is used to define a pointer to a function*/ typedef void (*performance_func_t)(void *); typedef CpaStatus (*stats_print_func_t)(void *); /*this type def is used to count the clock cycles taken to perform quick * assist operations*/ typedef unsigned long long perf_cycles_t; extern volatile Cpa32U numArrivedThreads_g; extern CpaBoolean SampleCodeBarrierLifted; /** ***************************************************************************** * @ingroup perfCodeFramework * time structure * @description * used to store thread execution time ****************************************************************************/ typedef struct sample_code_time_s { long secs; /**< seconds */ long nsecs; /**< nanoseconds */ } sample_code_time_t; /** ***************************************************************************** * @ingroup perfCodeFramework * thread attribute structure * @description * used to store thread attributes ****************************************************************************/ typedef struct sample_code_thread_attr_s { char *name; /**< name */ Cpa32U stackSize; /**< stack size */ Cpa32U priority; /**< priority */ Cpa32S policy; /**< policy */ } sample_code_thread_attr_t; /** ***************************************************************************** * @ingroup perfCodeFramework * Performance Data Structure * @description * used to store performance data on a per thread basis ****************************************************************************/ typedef struct perf_data_s { /* used to correlate requests and responses so that last request */ /* can be figured out in the callback to get timestamp */ volatile Cpa64U responses; /*store number of submissions*/ Cpa32U submissions; volatile CpaBoolean readDone; Cpa64U retries; Cpa32U pollRetries; Cpa32S currentThroughput; Cpa64U nextPoll; perf_cycles_t startCyclesTimestamp; /* start TS before perform */ perf_cycles_t midCyclesTimestamp; /* start TS before perform */ perf_cycles_t endCyclesTimestamp; /* end TS for last perform captured in CB */ /*rate variables*/ Cpa32U sleepTime; Cpa32U compRate; sample_code_semaphore_t comp; Cpa64U numOperations; /*flag to indicate rings were full at least once during session*/ Cpa32U averagePacketSizeInBytes; Cpa32U numBuffers; sample_code_thread_mutex_t mutex; CpaStatus threadReturnStatus; /* Collect additional status from the result data * structure reported by the compression/decompression * operation to indicate the exact reason for failure. */ CpaStatus additionalStatus; /*logical core affinity of test*/ Cpa32U logicalCoreAffinity; /*device used by thread*/ Cpa32U packageId; #if defined(_WIN64) || defined(WIN32) Cpa32U cpuCoreUtilPercentage; Cpa32U cpuOverallUtilPercentage; #endif perf_cycles_t req_temp; perf_cycles_t cost_temp; Cpa64U req_count; Cpa64U req_cost_count; Cpa64U poll_cost_count; perf_cycles_t req_sum_cycles; perf_cycles_t req_cost_sum_cycles; perf_cycles_t poll_sum_cycles; perf_cycles_t poll_cost_sum_cycles; Cpa32U bytesConsumedPerLoop; Cpa32U bytesProducedPerLoop; Cpa32U numLoops; Cpa32U pollCount; Cpa32U overflow; Cpa32U busyLoopValue; Cpa32U cyclesPerBusyLoop; Cpa32U busyLoopCount; perf_cycles_t offloadCycles; perf_cycles_t totalBusyLoopCycles; Cpa64U busyLoopResponses; CpaBoolean isIACycleCountProfiled; Cpa32U latencyCount; Cpa32U nextCount; Cpa32U countIncrement; perf_cycles_t response_process_time; perf_cycles_t *start_times; perf_cycles_t *response_times; perf_cycles_t minLatency; perf_cycles_t aveLatency; perf_cycles_t maxLatency; CpaFlatBuffer *expectedResults; Cpa64U preTestRecoveryCount; Cpa64U postTestRecoveryCount; } perf_data_t; /* ***************************************************************************** * MACROS * ****************************************************************************/ #define SEMAPHORE_MAX_COUNT 100 #define POST_PRIORITY_INCREMENT 0 #define POST_COUNT_INCREMENT 1 #define NUM_NANOSEC_IN_SEC (1000000000) #define NUM_MICROSEC_IN_SEC (1000000) #define NUM_MILLISEC_IN_SEC (1000) #define NUM_NANOSEC_IN_MILLISEC (1000000) #define SAMPLE_CODE_WAIT_FOREVER (-1) #ifdef ICP_DELAYED_RESPONSE #define SAMPLE_CODE_WAIT_DEFAULT (90000) #else #define SAMPLE_CODE_WAIT_DEFAULT (30000) #endif #define SAMPLE_CODE_WAIT_PRIMES (90000) #define SAMPLE_CODE_WAIT_NONE (0) #define DEFAULT_THREAD_PRIORITY (15) #define THREAD_PRIORITY_SCHED_OTHER (0) #define MAX_PRIORITY_VALUE (39) #define NICE_VAL_DIFFERENCE (20) #define SAMPLE_CODE_THOUSAND (1000) #define MAX_CORPUS_FILE_PATH_LEN (100) /*the limit of the number of different types of threads to be created*/ #ifdef KERNEL_SPACE #ifndef MAX_KERNEL_THREAD_VARIATION #define MAX_THREAD_VARIATION (300) #else #define MAX_THREAD_VARIATION (MAX_KERNEL_THREAD_VARIATION) #endif #else #define MAX_THREAD_VARIATION (600) #endif #define THREAD_NAME_LEN (4) #define CORE_MASK_MSB (0x10000000) /*the limit of the number of one type of thread, should be at least the number * of cores on the system we want to test*/ #define MAX_NUM_OF_ONE_TYPE_OF_THREAD (512) /*total number of threads that the framework will support*/ #define MAX_THREADS MAX_THREAD_VARIATION *MAX_NUM_OF_ONE_TYPE_OF_THREAD #define MAX_LATENCY_LIMIT (__LONG_LONG_MAX__ - 1UL) /* Must have this many buffers being submitted before * latency statistics can be calculated */ #define LATENCY_SUBMISSION_LIMIT (1000000000) /* Total number of latency measurements being made. Spread * over total buffer count */ #define MAX_LATENCY_COUNT (100) #define ZLIB_HEADER_SIZE (2) /* Define types which need to vary between 32 and 64 bit OS and 32bit * application * on 64bit OS. * */ #define SAMPLE_CODE_UINT Cpa64U #define SAMPLE_CODE_INT Cpa64S /*add 2 sampe_code_time_t structs together*/ #define SAMPLE_CODE_TIME_ADD(tvA, tvB) \ (tvA).secs += (tvB).secs; \ (tvA).nsecs += (tvB).nsecs; \ if ((tvA).nsecs >= NUM_NANOSEC_IN_SEC) \ { \ (tvA).secs++; \ (tvA).nsecs -= NUM_NANOSEC_IN_SEC; \ } /*convert sample_code_time_t to milliseconds*/ #define SAMPLE_CODE_TIMEVAL_TO_MS(milliseconds, pTv) \ ((sample_code_time_t *)pTv)->secs = milliseconds / 1000; \ ((sample_code_time_t *)pTv)->nsecs = (milliseconds % 1000) * 1000000 /*print the function name, line number and user defined message, print *macros for Windows are defined in platform-specific header files*/ #if !defined(_WIN64) && !defined(WIN32) #define PRINT_ERR(args...) \ do \ { \ PRINT("%s, %s():%d ", __FILE__, __func__, __LINE__); \ PRINT(args); \ } while (0) #endif #define FUNC_ENTRY() #define FUNC_EXIT() /* Check if the value returned by a function was ICP_STATUS_SUCCESS print * and error if not successful */ #define CHECK_FOR_SUCCESS(value) \ if (value != CPA_STATUS_SUCCESS) \ { \ PRINT("%s():%d ", __func__, __LINE__); \ PRINT("ERROR value: %d\n", value); \ } /* Check if the value returned by a function was ICP_STATUS_SUCCESS print * an error and return ICP_STATUS_FAIL if not successful */ #define CHECK_STATUS_AND_RETURN_FAIL_IF_NOT_SUCCESS(value) \ if (value != CPA_STATUS_SUCCESS) \ do \ { \ PRINT("%s():%d ", __func__, __LINE__); \ PRINT("ERROR value: %d\n", value); \ return CPA_STATUS_FAIL; \ } while (0) /* Check if pointer is null, print an error and return if pointer is null */ #define CHECK_POINTER_AND_RETURN_IF_NULL(ptr) \ if (ptr == NULL) \ { \ PRINT_ERR( \ "%s():%d NULL pointer error: [" #ptr "]", __func__, __LINE__); \ return; \ } /* Check if pointer is null, print an error and return ICP_STATUS_FAIL if * pointer is NULL */ #define CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(ptr) \ if (ptr == NULL) \ { \ PRINT_ERR( \ "%s():%d NULL pointer error: [" #ptr "]", __func__, __LINE__); \ return CPA_STATUS_FAIL; \ } /* Check if pointer is null, print an error and return NULL if pointer is null */ #define CHECK_POINTER_AND_RETURN_NULL_IF_NULL(ptr) \ if (ptr == NULL) \ { \ PRINT_ERR( \ "%s():%d NULL pointer error: [" #ptr "]", __func__, __LINE__); \ return NULL; \ } /* Check if expression evaluates to CPA_TRUE. If not, then print error message * whose format and arguments are passed. */ #define CHECK_EXPRESSION_AND_LOG_FAIL(exp, errMsgfmt, ...) \ { \ if (!(exp)) \ { \ PRINT_ERR(errMsgfmt, __VA_ARGS__); \ } \ } /* Check if expression evaluates to CPA_TRUE. If not, then print error message * whose format and arguments are passed and return failure. */ #define CHECK_EXPRESSION_AND_RETURN_FAIL(exp, errMsgfmt, ...) \ { \ if (!(exp)) \ { \ PRINT_ERR(errMsgfmt, __VA_ARGS__); \ return CPA_STATUS_FAIL; \ } \ } /* Check if expression evaluates to CPA_TRUE. If not, then print error message * whose format and arguments are passed and return error code specified. */ #define CHECK_EXPRESSION_AND_RETURN_CODE(exp, errCode, errMsgfmt, ...) \ { \ if (!(exp)) \ { \ PRINT_ERR(errMsgfmt, __VA_ARGS__); \ return errCode; \ } \ } /* Check if expression evaluates to CPA_TRUE. If not, then print error message * whose format and arguments are passed and goto Exit */ #define CHECK_EXPRESSION_AND_GOTO_EXIT(exp, errMsgfmt, ...) \ { \ if (!(exp)) \ { \ PRINT_ERR(errMsgfmt, __VA_ARGS__); \ goto Exit; \ } \ } /* Check if expression evaluates to CPA_TRUE. If not, then print error message * whose format and arguments are passed, failVariable to CPA_STATUS_FAIL, * and goto Exit */ #define CHECK_EXPRESSION_AND_GOTO_EXIT_WITH_FAILURE_SET( \ exp, failVariable, errMsgfmt, ...) \ { \ if (!(exp)) \ { \ PRINT_ERR(errMsgfmt, __VA_ARGS__); \ failVariable = CPA_STATUS_FAIL; \ goto Exit; \ } \ } /* Check if a parameter is within a specified range */ #define CHECK_PARAM_RANGE(param, min, max) \ do \ { \ if (param > max || param < min) \ { \ PRINT_ERR("%s(): param out of range: [" #param "]\n", __func__); \ return CPA_STATUS_FAIL; \ } \ } while (0) /* ***************************************************************************** * FUNCTION PROTOTYPES * ****************************************************************************/ perf_cycles_t sampleCodeTimestamp(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeGetCpuFreq * * @description * This function returns the frequency of the IA core * * * @retval This function returns the frequency of the IA core * * @pre * none * @post * None * *****************************************************************************/ Cpa32U sampleCodeGetCpuFreq(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeSleep * * @description * This function will forces the executing code to sleep for the specified * number of seconds * * * @param[in] seconds the number of seconds to sleep * * * @retval This function returns void * * @pre * none * @post * None * *****************************************************************************/ void sampleCodeSleep(Cpa32U seconds); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeSleep * * @description * This function will forces the executing code to sleep for the specified * number of milliseconds * * * @param[in] seconds the number of seconds to sleep * * * @retval This function returns void * * @pre * none * @post * None * *****************************************************************************/ void sampleCodeSleepMilliSec(Cpa32U milliseconds); /** * Function used to create delay in nanoseconds */ void sleepNano(Cpa32U nanoseconds); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeGetNumberOfCpus * * @description * This function will gets the number of logical CPU's on the system. * note: A hyper threaded enabled core will return 2 logical CPUs * * * @param[in] none * * @retval The number of logical CPU's on the system * * @pre * none * @post * None * *****************************************************************************/ Cpa32U sampleCodeGetNumberOfCpus(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeGetCpu * * @description * This function gets the logical CPU that the executing code is running * on * * * @param[in] none * * @retval The number of logical CPU's on the system, that the executing code is * running on * * @pre * none * @post * None * *****************************************************************************/ Cpa32S sampleCodeGetCpu(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeGetNode * * @description * This function gets the physical node that the executing code is * running on * * * @param[in] none * * @retval The node, that the executing code is running on * * @pre * none * @post * None * *****************************************************************************/ /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeGetCpu * * @description * This function gets the logical CPU that the executing code is running on * * * @param[in] none * * @retval The number of logical CPU's on the system, that the executing code is * running on * * @pre * none * @post * None * *****************************************************************************/ Cpa32S sampleCodeGetCpu(void); ; /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeGetNode * * @description * This function gets the node that the executing code is running * on * * * @param[in] none * * @retval The node that the executing code is * running on * * @pre * none * @post * None * *****************************************************************************/ Cpa32S sampleCodeGetNode(void); /** ***************************************************************************** * @ingroup perfCodeFramework * generateRandomData * * @description * This function generates random data for CpaFlatBuffers * * * @param[in] pWriteRandData pointer to CpaFlatBuffer pData * @param[in] lengthOfRand CpaFlatBuffer Data length specified in bytes * * @retval none * * @pre * none * @post * None * *****************************************************************************/ void generateRandomData(Cpa8U *pWriteRandData, Cpa32U lengthOfRand); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadCreate * * @description * This function creates a thread to run the specified function as set by * the function pointer param which takes an argument specified by the * params pointer * * * @param[out] *thread pointer to sample_code_thread_t which is populated * by the function * @param[in] *threadAttr pointer to sample_code_thread_attr_t which defines the * attributes of the thread * @param[in] function pointer to the function to be executed in thread context * @param[in] params pointer to a structure containing the parameters to be * passed to the function * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * * @pre * none * @post * thread is created * *****************************************************************************/ CpaStatus sampleCodeThreadCreate(sample_code_thread_t *thread, sample_code_thread_attr_t *threadAttr, performance_func_t function, void *params); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadBind * * @description * This function forces a thread to run on a specified logical IA core * * * @param[in] *thread pointer which identifies the thread to be tied to a core * @param[in] logicalCore in which the thread will run on * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * * @pre * thread is created * @post * thread is bound to run on a specific IA core * *****************************************************************************/ CpaStatus sampleCodeThreadBind(sample_code_thread_t *thread, Cpa32U logicalCore); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadStart * * @description * This function executes the specified function * * * @param[in] *thread pointer which identifies the thread to be started * * @retval CPA_STATUS_SUCCESS Function executed successfully. * @retval CPA_STATUS_FAIL Function failed. * * @pre * thread is created * @post * function pointed to is started in thread context * *****************************************************************************/ CpaStatus sampleCodeThreadStart(sample_code_thread_t *thread); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadKill * * @description * This function is kills a created thread * * * @param[in] *thread pointer which identifies the thread to be killed * * @retval none * * @pre * thread is created * @post * threads is closed * *****************************************************************************/ CpaStatus sampleCodeThreadKill(sample_code_thread_t *thread); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadPrioritySet * * @description * This function sets the priority of the thread * * * @param[in] *thread pointer which identifies the thread to prioritized * * @retval none * * @pre * thread is created * @post * thread priority is set * *****************************************************************************/ CpaStatus sampleCodeThreadPrioritySet(sample_code_thread_t *thread, Cpa32U priority); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadPrioritySet * * @description * This function sets the policy and priority of user space threads_g, in * kernel space this function does nothing * * * @param[in] *thread pointer which identifies the thread to prioritized * * @retval none * * @pre * thread is created * @post * thread priority is set * *****************************************************************************/ CpaStatus sampleCodeThreadSetPolicyAndPriority(sample_code_thread_t *thread, Cpa32U policy, Cpa32U priority); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadJoin * * @description * Blocks and Waits for a thread as set by thread id to exit * * * @param[in] *thread pointer which identifies the thread to wait on * * @retval none * * @pre * thread is created * @post * thread waited on has completed * *****************************************************************************/ CpaStatus sampleCodeThreadJoin(sample_code_thread_t *thread); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadTimedJoin * * @description * Blocks and Waits for a thread as set by thread id to exit * * * @param[in] *thread pointer which identifies the thread to wait on * *pTimeOutInMs pointer which identifies time to wait * * @retval none * * @pre * thread is created * @post * thread waited on has completed or timeout * *****************************************************************************/ CpaStatus sampleCodeThreadTimedJoin(sample_code_thread_t *thread, Cpa64U *pTimeOutInMs); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeTimeTGet * * @description * populates a time_t structure * * * @param[out] *pTime, time_t structure that is populated * * @retval none * * @pre * none * @post * pTime contains current time_t * *****************************************************************************/ CpaStatus sampleCodeTimeTGet(sample_code_time_t *pTime); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeSemaphoreInit * * @description * initialises a semaphore type with start value * * * @param[out] *semPtr, is the semaphore to be initialized * @param[in] start_value, is the value to init the semaphore to 0 = free * >0 is not free * * @retval none * * @pre * none * @post * none * *****************************************************************************/ CpaStatus sampleCodeSemaphoreInit(sample_code_semaphore_t *semPtr, Cpa32U start_value); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeSemaphorePost * * @description * increments the semaphore count. In this code the * sampleCodeSemaphoreWaitInterruptible is called and if count is 0, * then it decrements the count to -1, blocks * and waits for this function increment the count back to zero to free it * * * @param[out] *semPtr, is the semaphore to be initialized * * @retval none * * @pre * semaphore is initialized * @post * semaphore count is incremented * *****************************************************************************/ CpaStatus sampleCodeSemaphorePost(sample_code_semaphore_t *semPtr); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeSemaphoreDestroy * * @description * free and memory internal allocated by the semaphore * * * @param[out] *semPtr, is the semaphore to be initialized * * @retval none * * @pre * semaphore is initialized * @post * semaphore is destroyed * *****************************************************************************/ CpaStatus sampleCodeSemaphoreDestroy(sample_code_semaphore_t *semPtr); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeSemaphoreWaitInterruptible * * @description * This function decrements the usage count of the semaphore. * If the new value is less than zero, the calling process is added to the * wait queue and blocked. If the new value is zero or greater, * the process obtains the semaphore * * * @param[out] *semPtr, is the semaphore to be initialized * * @retval none * * @pre * semaphore is initialized * @post * semaphore is decremented * *****************************************************************************/ CpaStatus sampleCodeSemaphoreWait(sample_code_semaphore_t *semPtr, Cpa32S timeout); /** ***************************************************************************** * @ingroup perfCodeFramework * startBarrier * * @description * this function is provided specifically to pause user space threads * from executing. until signaled to do so * * * @param[out] *semPtr, is the semaphore to be initialized * * @retval none * * @pre * sample_code_thread_mutex_t threadControlMutex_g and * sample_code_thread_cond_t threadConditionControl_g are initialized * @post * calling function is blocked until the a broadcast is sent to the * threadConditionControl_g conditional variable * *****************************************************************************/ void startBarrier(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeBarrier * * @description * pauses a thread from executing until a proscribed number have all * reached the barrier. This is only used to stop threads_g from * starting there main work function until all threads_g are ready * to start work * * @param[out] *semPtr, is the semaphore to be initialized * * @retval none * * @pre * semaphore is initialized * @post * semaphore is decremented * *****************************************************************************/ void sampleCodeBarrier(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeBarrierInit * * @description * Initialized the barrier for threads_g to stop at * * * * @retval none * * @pre * barrier is initialized * @post * barrier is decremented * *****************************************************************************/ void sampleCodeBarrierInit(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeBarrierDestroy * * @description * Destroys the barrier and all dependent resources * * * * @retval none * * @pre * barrier is initialized * @post * barrier is destroyed * *****************************************************************************/ void sampleCodeBarrierDestroy(void); /** ***************************************************************************** * @ingroup perfCodeFramework * startBarrierInit * * @description * Initialized the barrier for threads_g to stop at * * * * @retval none * * @pre * barrier is initialized * @post * barrier is decremented * *****************************************************************************/ void startBarrierInit(void); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeDcEventPoll * * @description * Perform an event based poll for Compression Instances * * * * @retval none * * *****************************************************************************/ void sampleCodeDcEventPoll(CpaInstanceHandle instanceHandle); /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeCyEventPoll * * @description * Perform an event based poll for Crypto Instances * * * * @retval none * * *****************************************************************************/ void sampleCodeCyEventPoll(CpaInstanceHandle instanceHandle); void sampleCodeCompletionInit(Cpa32U threadId); CpaStatus sampleCodeThreadCollect(sample_code_thread_t *thread, Cpa32U threadId); void sampleCodeThreadComplete(Cpa32U threadId); Cpa32U getCPUSpeed(void); Cpa32U updateCPUSpeed(void); #endif /*_COMMON_SAMPLECODEUTILS_H__*/ qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/000077500000000000000000000000001503624047500326215ustar00rootroot00000000000000user_space/000077500000000000000000000000001503624047500346735ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/linuxcpa_sample_code_utils.c000066400000000000000000001075121503624047500413630ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/user_space /****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_utils.c * * This file provides linux kernel os abstraction functions * *****************************************************************************/ #include "cpa_sample_code_utils.h" #include "cpa_sample_code_utils_common.h" #include "icp_sal_poll.h" #include #include #include #include #include #include #include #include #include #include #include #include #include // check GLIBC version used. #define GLIBC_VERSION_AT_LEAST(major, minor) \ (__GLIBC__ > major || (__GLIBC__ == major && __GLIBC_MINOR__ >= minor)) #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) && \ (GLIBC_VERSION_AT_LEAST(2, 25))) #include #endif #define EPOLL_MAX_EVENTS 1 #define _4K_PAGE_SIZE (4 * 1024) #if UINT_MAX == 0xFFFFFFFF typedef unsigned uint32_t; #endif volatile Cpa32U numArrivedThreads_g; extern volatile Cpa32U numCreatedThreads_g; extern int verboseOutput; extern sample_code_thread_mutex_t threadControlMutex_g; extern sample_code_thread_cond_t threadConditionControl_g; extern sample_code_thread_mutex_t startThreadControlMutex_g; extern sample_code_thread_cond_t startThreadConditionControl_g; extern CpaBoolean dc_service_started_g; extern CpaBoolean cy_service_started_g; extern volatile Cpa32U numThreadsAtBarrier_g; Cpa32U cpu_freq_g = 0; extern volatile CpaBoolean isChangingThreadQaInstanceRequired_g; static char *firmwarePath = SAMPLE_CODE_CORPUS_PATH; sample_code_thread_barrier_t barr; extern CpaStatus getCorpusFile(Cpa8U **ppSrcBuff, char *filename, Cpa32U *size); extern CpaStatus getCompressedFile(Cpa8U **ppSrcBuff, char *filename, Cpa32U *size); extern CpaStatus calcSWDigest(CpaFlatBuffer *msg, CpaFlatBuffer *digest, CpaCySymHashAlgorithm hashAlg); #define UPPER_HALF_OF_REGISTER (32) #if ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) || \ (!GLIBC_VERSION_AT_LEAST(2, 25))) static __inline__ Cpa64U sampleCoderdtsc(void) { volatile unsigned long a, d; asm volatile("rdtsc" : "=a"(a), "=d"(d)); return (((Cpa64U)a) | (((Cpa64U)d) << UPPER_HALF_OF_REGISTER)); } #endif ChipRec_u64 getCPUTick() { //================================================== = // Use RDTSC To Read CPU Time Stamp Counter //================================================== = ChipRec_u64 u64Ret; __asm__ __volatile__("rdtsc" : "=A"(u64Ret) :); return u64Ret; } #define __CPUID(in, a, b, c, d) \ asm volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(in)); static __inline__ void sampleCodeCpuid(void) { unsigned int a = 0x00, b = 0x00, c = 0x00, d = 0x00; __CPUID(0x00, a, b, c, d); } static __inline__ Cpa64U sampleCodeRdtscp(void) { Cpa64U returnval = 0; #ifdef __x86_64__ volatile unsigned long a = 0, d = 0; sampleCodeCpuid(); asm volatile("rdtsc" : "=a"(a), "=d"(d)); returnval = (((Cpa64U)d) << UPPER_HALF_OF_REGISTER); returnval |= ((Cpa64U)a); #else asm volatile("rdtsc" : "=A"(returnval)); #endif return returnval; } perf_cycles_t sampleCodeTimestamp(void) { /*get time stamp twice, because we need to prime the timestamp counter*/ sampleCodeRdtscp(); return (perf_cycles_t)sampleCodeRdtscp(); } void sampleCodeSleep(Cpa32U seconds) { sleep(seconds); } static void sampleCodeSleepUsingNanoSleep(Cpa32U milliseconds, Cpa32U nanoseconds) { struct timespec reqTime; struct timespec tmleft; int ret; reqTime.tv_sec = milliseconds / NUM_MILLISEC_IN_SEC; reqTime.tv_nsec = nanoseconds + ((milliseconds % NUM_MILLISEC_IN_SEC) * NUM_NANOSEC_IN_MILLISEC); do { ret = nanosleep(&reqTime, &tmleft); reqTime = tmleft; } while (ret != 0 && errno == EINTR); if (ret != 0) { PRINT_ERR("Failed to Sleep! errno:%d\n", errno); } return; } void sampleCodeSleepMilliSec(Cpa32U milliseconds) { sampleCodeSleepUsingNanoSleep(milliseconds, 0); } void sleepNano(Cpa32U nanoseconds) { sampleCodeSleepUsingNanoSleep(0, nanoseconds); } Cpa32U sampleCodeGetNumberOfCpus(void) { int numCpus = 0; numCpus = sysconf(_SC_NPROCESSORS_ONLN); if (numCpus < 0) { PRINT_ERR("Failed to get online processors count %d\n", errno); numCpus = 0; } return numCpus; } #include ChipRec_u32 timeGetTime(void) { //================================================== = // Using Linux Time Functions To Determine Time //================================================== = struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec * 1000 + tv.tv_usec / 1000; } Cpa32U getCPUSpeed() { ChipRec_s64 startTick, endTick; static Cpa32U cpuSpeed = 0; if (cpuSpeed == 0) { /*get the number of ticks in 1 second*/ startTick = getCPUTick(); sampleCodeSleep(1); endTick = getCPUTick(); cpuSpeed = endTick - startTick; } cpu_freq_g = cpuSpeed / 1000; //================================================== = // Return The Processors Speed In Hertz //================================================== = return cpuSpeed; } Cpa32U updateCPUSpeed() { ChipRec_s64 startTick, endTick; Cpa32U cpuSpeed = 0; /*get the number of ticks in 1 second*/ startTick = getCPUTick(); sampleCodeSleep(1); endTick = getCPUTick(); cpuSpeed = endTick - startTick; cpu_freq_g = cpuSpeed / 1000; return cpuSpeed; } Cpa32U sampleCodeGetCpuFreq() { return cpu_freq_g; } void generateRandomData(Cpa8U *pWriteRandData, Cpa32U lengthOfRand) { Cpa32U i = 0; #if ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) || \ (!GLIBC_VERSION_AT_LEAST(2, 25))) srand(sampleCoderdtsc()); #endif for (i = 0; i < lengthOfRand; i++) { #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) && \ (GLIBC_VERSION_AT_LEAST(2, 25))) ssize_t status = getrandom(&pWriteRandData[i], sizeof(Cpa8U), GRND_NONBLOCK); if (status == -1) { PRINT_ERR("generateRandomData failed, Error Code: %d - %s\n", errno, strerror(errno)); } #else pWriteRandData[i] = (Cpa8U)rand(); #endif } } CpaStatus sampleCodeThreadCreate(sample_code_thread_t *thread, sample_code_thread_attr_t *threadAttr, performance_func_t function, void *params) { // CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(thread); // CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(function); int status = 1; pthread_attr_t attr; struct sched_param param; Cpa32U pmin = 0; Cpa32U pmax = 0; status = pthread_attr_init(&attr); if (status != 0) { PRINT_ERR("%d\n", errno); return CPA_STATUS_FAIL; } /* Setting scheduling parameter will fail for non root user, * as the default value of inheritsched is PTHREAD_EXPLICIT_SCHED in * POSIX. It is not required to set it explicitly before setting the * scheduling policy */ if (threadAttr == NULL) { status = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); if (status != 0) { pthread_attr_destroy(&attr); PRINT_ERR("%d\n", errno); return CPA_STATUS_FAIL; } status = pthread_attr_setschedpolicy(&attr, THREAD_DEFAULT_SCHED_POLICY); if (status != 0) { pthread_attr_destroy(&attr); PRINT_ERR("%d\n", errno); return CPA_STATUS_FAIL; } /* Set priority based on value in threadAttr */ memset(¶m, 0, sizeof(param)); param.sched_priority = THREAD_PRIORITY_SCHED_OTHER; status = pthread_attr_setschedparam(&attr, ¶m); if (status != 0) { pthread_attr_destroy(&attr); PRINT_ERR("%d\n", errno); return CPA_STATUS_FAIL; } } else { /* Set scheduling policy based on value in threadAttr */ if ((threadAttr->policy != SCHED_RR) && (threadAttr->policy != SCHED_FIFO) && (threadAttr->policy != SCHED_OTHER)) { threadAttr->policy = THREAD_DEFAULT_SCHED_POLICY; } status = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); if (status != 0) { PRINT_ERR("%d\n", errno); pthread_attr_destroy(&attr); return CPA_STATUS_FAIL; } status = pthread_attr_setschedpolicy(&attr, threadAttr->policy); if (status != 0) { PRINT_ERR("%d\n", errno); pthread_attr_destroy(&attr); return CPA_STATUS_FAIL; } /* Set priority based on value in threadAttr */ memset(¶m, 0, sizeof(param)); pmin = sched_get_priority_min(threadAttr->policy); pmax = sched_get_priority_max(threadAttr->policy); if (threadAttr->priority > pmax) { threadAttr->priority = pmax; } if (threadAttr->priority < pmin) { threadAttr->priority = pmin; } param.sched_priority = threadAttr->priority; if (threadAttr->policy != SCHED_OTHER) { status = pthread_attr_setschedparam(&attr, ¶m); if (status != 0) { PRINT_ERR("%d\n", errno); pthread_attr_destroy(&attr); return CPA_STATUS_FAIL; } } } status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); if (status != 0) { PRINT_ERR("%d\n", errno); pthread_attr_destroy(&attr); return CPA_STATUS_FAIL; } status = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); if (status != 0) { PRINT_ERR("%d\n", errno); pthread_attr_destroy(&attr); return CPA_STATUS_FAIL; } /*pthread_create expects "void *(*start_routine)(void*)" as the 3rd argument * but we are calling functions with return void instead of void*, normally * the return value of the start_routine contains the exit status, in this * sample code we track any internal errors in the start_routine, to allow * this to compile we need to cast "function" parameter, this is the same * as calling it as void *(*function)(void*)*/ status = pthread_create(thread, &attr, (void *(*)(void *))function, params); if (status != 0) { PRINT_ERR("%d\n", errno); pthread_attr_destroy(&attr); return CPA_STATUS_FAIL; } /*destroy the thread attributes as they are no longer required, this does * not affect the created thread*/ pthread_attr_destroy(&attr); return CPA_STATUS_SUCCESS; } CpaStatus sampleCodeThreadBind(sample_code_thread_t *thread, Cpa32U logicalCore) { int status = 1; cpu_set_t cpuset; CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(thread); CPU_ZERO(&cpuset); CPU_SET(logicalCore, &cpuset); status = pthread_setaffinity_np(*thread, sizeof(cpu_set_t), &cpuset); if (status != 0) { return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus sampleCodeThreadStart(sample_code_thread_t *thread) { CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(thread); return CPA_STATUS_SUCCESS; } void sampleCodeThreadExit(void) { pthread_exit(NULL); } CpaStatus sampleCodeThreadKill(sample_code_thread_t *thread) { Cpa32U status = 0; CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(thread); /* To avoid the deadlock, before killing all * createdThreads confirm that barrier condition is not * waiting for any thread arrival. */ if ((numArrivedThreads_g) && (numArrivedThreads_g >= numCreatedThreads_g)) { sample_code_thread_mutex_lock(&threadControlMutex_g); sample_code_thread_cond_broadcast(&threadConditionControl_g); sample_code_thread_mutex_unlock(&threadControlMutex_g); } if (*thread != 0x00) { status = pthread_cancel(*thread); } else { PRINT_ERR("sampleCodeThreadKill: Thread not exist\n"); } if (status) { PRINT_ERR("sampleCodeThreadKill: Failed to cancel the thread!\n"); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus sampleCodeThreadPrioritySet(sample_code_thread_t *thread, Cpa32U priority) { Cpa32S status; struct sched_param param1; int policy1; Cpa32U minPrio; Cpa32U maxPrio; CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(thread); status = pthread_getschedparam(*thread, &policy1, ¶m1); if (status != 0) { PRINT_ERR("pthread_getschedparam, failed with status %d\n", status); return CPA_STATUS_FAIL; } minPrio = sched_get_priority_min(policy1); maxPrio = sched_get_priority_max(policy1); if ((priority < minPrio) || (priority > maxPrio)) { PRINT_ERR("priority outside valid range\n"); return CPA_STATUS_FAIL; } status = pthread_setschedprio(*thread, priority); if (status != 0) { PRINT_ERR("pthread_setschedprio, failed with status %d\n", status); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus sampleCodeThreadSetPolicyAndPriority(sample_code_thread_t *thread, Cpa32U policy, Cpa32U priority) { CpaStatus status = CPA_STATUS_FAIL; struct sched_param param; int policy1; Cpa32U minPrio, maxPrio; CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(thread); /* check for a valid value for 'policy' */ if ((policy != SCHED_RR) && (policy != SCHED_FIFO) && (policy != SCHED_OTHER)) { PRINT_ERR("policy error\n"); return CPA_STATUS_FAIL; } memset(¶m, 0, sizeof(param)); status = pthread_getschedparam(*thread, &policy1, ¶m); if (status != 0) { PRINT_ERR("%d\n", errno); return CPA_STATUS_FAIL; } minPrio = sched_get_priority_min(policy); maxPrio = sched_get_priority_max(policy); if ((priority < minPrio) || (priority > maxPrio)) { return CPA_STATUS_FAIL; } param.sched_priority = priority; status = pthread_setschedparam(*thread, policy, ¶m); if (status != 0) { PRINT_ERR("%d\n", errno); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus sampleCodeThreadJoin(sample_code_thread_t *thread) { Cpa32S status = 0; status = pthread_join(*thread, NULL); if (status != 0) { PRINT_ERR("pthread_join failed, Error Code: %d - %s\n", status, strerror(status)); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } CpaStatus sampleCodeThreadTimedJoin(sample_code_thread_t *thread, Cpa64U *pTimeOutInMs) { struct timespec ts = {0}; Cpa32S status = 0; #if GLIBC_VERSION_AT_LEAST(2, 17) status = clock_gettime(CLOCK_REALTIME, &ts); if (status != 0) { PRINT_ERR("clock_gettime failed, Error Code: %d - %s\n", errno, strerror(errno)); return CPA_STATUS_FAIL; } #else struct timeval tv = {0}; status = gettimeofday(&tv, NULL); if (status != 0) { PRINT_ERR("gettimeofday failed, Error Code: %d - %s\n", status, strerror(status)); return CPA_STATUS_FAIL; } // converting results from msec to nanonseconds TIMEVAL_TO_TIMESPEC(&tv, &ts); #endif ts.tv_sec += *pTimeOutInMs / 1000; ts.tv_nsec += (*pTimeOutInMs % 1000) * 1000000; status = pthread_timedjoin_np(*thread, NULL, &ts); if (status != 0) { PRINT_ERR("pthread_timedjoin_np failed, Error Code: %d - %s\n", status, strerror(status)); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } /********************************************** * Time module **********************************************/ /* * Retrieve current system time. */ CpaStatus sampleCodeTimeTGet(sample_code_time_t *ptime) { struct timeval tval; if (gettimeofday(&tval, NULL) == -1) { PRINT_ERR("sampleCodeTimeTGet(): gettimeofday system call failed \n"); return CPA_STATUS_FAIL; } ptime->secs = tval.tv_sec; /* * gettimeofday returns in terms of sec and uSec. * Convert it into sec and nanoseconds into sample_code_time_t type */ ptime->nsecs = tval.tv_usec * 1000; return CPA_STATUS_SUCCESS; } /******************************************************** * Semaphore Functions implemented using POSIX interfaces. ********************************************************/ /* * Initializes a semaphore object */ CpaStatus sampleCodeSemaphoreInit(sample_code_semaphore_t *semPtr, Cpa32U start_value) { CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(semPtr); /* * Allocate memory for the semaphore object. */ *semPtr = qaeMemAlloc(sizeof(sem_t)); if (!(*semPtr)) { PRINT_ERR("failed to allocate for semaphore \n"); return CPA_STATUS_FAIL; } /* * Initialize the semaphore object. */ if (sem_init(*semPtr, SAMPLECODE_POSIX_SHARED_SEMAPHORE, start_value) == -1) { PRINT_ERR("sample_code_semaphoreInit Failed to initialize semaphore\n"); qaeMemFree((void **)&*semPtr); *semPtr = NULL; return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } /* * Decrements a semaphore, blocking if the semaphore is unavailable (value is 0) */ CpaStatus sampleCodeSemaphoreWait(sample_code_semaphore_t *semPtr, Cpa32S timeout) { Cpa32S status; sample_code_time_t timeoutVal, currTime; CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(semPtr); CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(*semPtr); /* * Guard against illegal timeout values * WAIT_FORVER = -1 */ if (timeout < SAMPLE_CODE_WAIT_FOREVER) { PRINT_ERR("sample_code_semaphoreWait(): illegal timeout value \n"); return CPA_STATUS_FAIL; } if (timeout == SAMPLE_CODE_WAIT_FOREVER) { status = sem_wait(*semPtr); } else if (timeout == SAMPLE_CODE_WAIT_NONE) { status = sem_trywait(*semPtr); } else { /* * Convert the inputted time into appropriate timespec struct. * Since timespec and sample_code_time_t timeval are of the the same * type. * Reuse the timeval to timespec macros. */ SAMPLE_CODE_TIMEVAL_TO_MS(timeout, &timeoutVal); /* Get current time */ if (CPA_STATUS_SUCCESS != sampleCodeTimeTGet(&currTime)) { return CPA_STATUS_FAIL; } /* Add this to the timeout so that it gives absolute timeout value */ SAMPLE_CODE_TIME_ADD(timeoutVal, currTime); /*this loop waits until the timeout, when timeout occurs sem_timedwait * returns -1 with errno = ETIMEDOUT, EINTR means that some signal * caused a premature exit of sem_timedwait and it loops again for the * specified timeout*/ do { status = sem_timedwait(*semPtr, (const struct timespec *)&timeoutVal); } while ((status == -1) && (errno == EINTR)); } if (status < 0) { PRINT_ERR("sample_code_semaphoreWait(): errno: %d \n", errno); return CPA_STATUS_FAIL; } else { return CPA_STATUS_SUCCESS; } } /* * Increments a semaphore object */ CpaStatus sampleCodeSemaphorePost(sample_code_semaphore_t *semPtr) { Cpa32S status; CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(semPtr); CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(*semPtr); /* * Increment the semaphore object. */ status = sem_post(*semPtr); if (status < 0) { PRINT_ERR("errno: %d\n", errno); return CPA_STATUS_FAIL; } else { return CPA_STATUS_SUCCESS; } } /* * Destroys the semaphore object */ CpaStatus sampleCodeSemaphoreDestroy(sample_code_semaphore_t *semPtr) { Cpa32S Status; CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(semPtr); /* * Destroy the semaphore object. */ Status = sem_destroy(*semPtr); if (Status != 0) { PRINT_ERR("sample_code_semaphoreDestroy() : \ Semaphore Destroy failed\n"); return CPA_STATUS_FAIL; } /* * Free space allocated for the semaphore object. */ qaeMemFree((void **)&*semPtr); *semPtr = NULL; return CPA_STATUS_SUCCESS; } void sampleCodeBarrierInit(void) { sample_code_thread_mutex_init(&threadControlMutex_g); sample_code_thread_cond_init(&threadConditionControl_g); numArrivedThreads_g = 0; SampleCodeBarrierLifted = CPA_FALSE; getCPUSpeed(); } void sampleCodeBarrierDestroy(void) { sample_code_thread_mutex_destroy(&threadControlMutex_g); sample_code_thread_cond_destroy(&threadConditionControl_g); sample_code_thread_mutex_destroy(&startThreadControlMutex_g); sample_code_thread_cond_destroy(&startThreadConditionControl_g); SampleCodeBarrierLifted = CPA_FALSE; numArrivedThreads_g = 0; } /*This is a barrier function that all performance threads_g need to call after * setting up sessions and population of bufferList, but prior to the "Do Work" * functions, this allows all threads_g to be ready and start "Work" all at the * same time*/ void sampleCodeBarrier(void) { sample_code_thread_mutex_lock(&threadControlMutex_g); numArrivedThreads_g++; if (numArrivedThreads_g < numCreatedThreads_g) { sample_code_thread_cond_wait(&threadConditionControl_g, &threadControlMutex_g); } else { sample_code_thread_cond_broadcast(&threadConditionControl_g); SampleCodeBarrierLifted = CPA_TRUE; } sample_code_thread_mutex_unlock(&threadControlMutex_g); } void startBarrierInit(void) { sample_code_thread_mutex_init(&startThreadControlMutex_g); sample_code_thread_cond_init(&startThreadConditionControl_g); } void startBarrier(void) { sample_code_thread_mutex_lock(&startThreadControlMutex_g); /* Count the number of threads reached to barrier for unblock * the below condition */ numThreadsAtBarrier_g++; if ((numThreadsAtBarrier_g < numCreatedThreads_g) || (isChangingThreadQaInstanceRequired_g == CPA_TRUE)) { sample_code_thread_cond_wait(&startThreadConditionControl_g, &startThreadControlMutex_g); } else { sample_code_thread_cond_broadcast(&startThreadConditionControl_g); } sample_code_thread_mutex_unlock(&startThreadControlMutex_g); } CpaStatus getCorpusFile(Cpa8U **ppSrcBuff, char *filename, Cpa32U *size) { FILE *corpusFilePtr = NULL; long lSize; char fullpath[MAX_CORPUS_FILE_PATH_LEN]; Cpa32S strSize = 0; strSize = snprintf(fullpath, sizeof(fullpath), "%s%s", firmwarePath, filename); CHECK_PARAM_RANGE(strSize, 1, sizeof(fullpath)); corpusFilePtr = fopen(fullpath, "rb"); if (corpusFilePtr == NULL) { PRINT("Could not open corpus file: %s\n", fullpath); return CPA_STATUS_FAIL; } fseek(corpusFilePtr, 0, SEEK_END); lSize = ftell(corpusFilePtr); if (lSize < 0) { PRINT("Error getting file position\n"); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } if (fseek(corpusFilePtr, 0, SEEK_SET) != 0) { PRINT("Could not move to beginning of file\n"); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } /* To avoid negative values */ if (lSize >= 0) { *ppSrcBuff = qaeMemAlloc(lSize); } if (*ppSrcBuff == NULL) { PRINT("%s:: Can't Allocate Memory for srcBuff!\n", __FUNCTION__); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } *size = fread(*ppSrcBuff, 1, lSize, corpusFilePtr); if (*size != lSize) { PRINT_ERR("%s Input Error! size(%ul) != lSize(%ld)\n", fullpath, *size, lSize); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } fclose(corpusFilePtr); return CPA_STATUS_SUCCESS; } CpaStatus calcSWDigest(CpaFlatBuffer *msg, CpaFlatBuffer *digest, CpaCySymHashAlgorithm hashAlg) { CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(msg); CHECK_POINTER_AND_RETURN_FAIL_IF_NULL(digest); switch (hashAlg) { case CPA_CY_SYM_HASH_SHA1: return (SHA1(msg->pData, msg->dataLenInBytes, digest->pData) == NULL) ? CPA_STATUS_FAIL : CPA_STATUS_SUCCESS; case CPA_CY_SYM_HASH_SHA224: return (SHA224(msg->pData, msg->dataLenInBytes, digest->pData) == NULL) ? CPA_STATUS_FAIL : CPA_STATUS_SUCCESS; case CPA_CY_SYM_HASH_SHA256: return (SHA256(msg->pData, msg->dataLenInBytes, digest->pData) == NULL) ? CPA_STATUS_FAIL : CPA_STATUS_SUCCESS; case CPA_CY_SYM_HASH_SHA512: return (SHA512(msg->pData, msg->dataLenInBytes, digest->pData) == NULL) ? CPA_STATUS_FAIL : CPA_STATUS_SUCCESS; default: PRINT_ERR("Unsupported algorithm %d\n", hashAlg); return CPA_STATUS_UNSUPPORTED; } } CpaStatus getCompressedFile(Cpa8U **ppSrcBuff, char *filename, Cpa32U *size) { FILE *corpusFilePtr = NULL; long lSize; char fullpath[MAX_CORPUS_FILE_PATH_LEN]; Cpa32S strSize = 0; strSize = snprintf(fullpath, sizeof(fullpath), "%s%s", firmwarePath, filename); CHECK_PARAM_RANGE(strSize, 1, sizeof(fullpath)); corpusFilePtr = fopen(fullpath, "rb"); if (corpusFilePtr == NULL) { PRINT("Could not open file\n"); return CPA_STATUS_FAIL; } fseek(corpusFilePtr, 0, SEEK_END); lSize = ftell(corpusFilePtr); if (lSize < 0) { PRINT("Error getting file position\n"); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } if (fseek(corpusFilePtr, 0, SEEK_SET) != 0) { PRINT("Could not move to beginning of file\n"); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } if (lSize >= 0) { *ppSrcBuff = qaeMemAlloc(lSize); } if (*ppSrcBuff == NULL) { PRINT("%s:: Can't Allocate Memory for srcBuff!\n", __FUNCTION__); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } *size = fread(*ppSrcBuff, 1, lSize, corpusFilePtr); if (*size != lSize) { PRINT_ERR("Error Input Error!"); fclose(corpusFilePtr); return CPA_STATUS_FAIL; } fclose(corpusFilePtr); return CPA_STATUS_SUCCESS; } int parseArg(int argc, char **argv, option_t *optArray, int numOpt) { int indexArgv = 1; int indexOpt = 0; int value = 0; char name[CLI_OPT_LEN]; CpaBoolean matchFound = CPA_FALSE; if (NULL == optArray) return 1; while (indexArgv < argc) { if (NULL != argv[indexArgv]) { memset((void *)name, 0, sizeof(name)); if (strlen(argv[indexArgv]) > CLI_OPT_LEN) { PRINT_ERR("input argument %d, exceeds permitted length\n", indexArgv); return -1; } sscanf(argv[indexArgv], "%24[^'=']=%d", name, &value); for (indexOpt = 0; indexOpt < numOpt; indexOpt++) { if (0 == strncmp(name, optArray[indexOpt].optName, sizeof(name))) { optArray[indexOpt].optValue = value; matchFound = CPA_TRUE; } } if (matchFound == CPA_FALSE) { PRINT_ERR("%s not recognized\n", name); return -1; } } indexArgv++; matchFound = CPA_FALSE; } return 0; } static int sampleCodeEventPoll(CpaInstanceHandle instanceHandle, CpaAccelerationServiceType accelServieType) { #ifndef SC_EPOLL_DISABLED int fd = 0; int i = 0; int n = 0; int efd = 0; struct epoll_event event; struct epoll_event *events; CpaStatus status = CPA_STATUS_FAIL; CpaBoolean volatile *pServiceStarted = NULL; typedef CpaStatus (*ptr2_icp_sal_GetFileDescriptor)(CpaInstanceHandle, int *); typedef CpaStatus (*ptr2_icp_sal_PutFileDescriptor)(CpaInstanceHandle, int); typedef CpaStatus (*ptr2_icp_sal_PollInstance)(CpaInstanceHandle, Cpa32U); ptr2_icp_sal_GetFileDescriptor getFileDescriptorFn = NULL; ptr2_icp_sal_PollInstance pollInstanceFn = NULL; ptr2_icp_sal_PutFileDescriptor putFileDescriptorFn = NULL; #ifdef DO_CRYPTO if (accelServieType == CPA_ACC_SVC_TYPE_CRYPTO) { getFileDescriptorFn = icp_sal_CyGetFileDescriptor; pollInstanceFn = icp_sal_CyPollInstance; putFileDescriptorFn = icp_sal_CyPutFileDescriptor; pServiceStarted = &cy_service_started_g; } #endif if (accelServieType == CPA_ACC_SVC_TYPE_DATA_COMPRESSION) { getFileDescriptorFn = icp_sal_DcGetFileDescriptor; pollInstanceFn = icp_sal_DcPollInstance; putFileDescriptorFn = icp_sal_DcPutFileDescriptor; pServiceStarted = &dc_service_started_g; } if (getFileDescriptorFn == NULL || pollInstanceFn == NULL || putFileDescriptorFn == NULL) { PRINT_ERR("Error initializing event polling mechanism for service %d\n", accelServieType); return -1; } if (CPA_STATUS_SUCCESS != getFileDescriptorFn(instanceHandle, &fd)) { PRINT_ERR("Error getting CY file descriptor for epoll instance\n"); return -1; } efd = epoll_create1(0); if (-1 == efd) { PRINT_ERR("Error creating epoll fd for instance\n"); return -1; } event.data.fd = fd; event.events = EPOLLIN | EPOLLET; if (-1 == epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event)) { PRINT_ERR("Error adding fd to epoll: %d\n", errno); return -1; } events = qaeMemAlloc(EPOLL_MAX_EVENTS * sizeof(event)); if (NULL == events) { PRINT_ERR("Error allocating memory for epoll events\n"); return -1; } while (*pServiceStarted == CPA_TRUE) { n = epoll_wait(efd, events, EPOLL_MAX_EVENTS, 100); for (i = 0; i < n; i++) { if (fd == events[i].data.fd && (events[i].events & EPOLLIN)) { status = pollInstanceFn(instanceHandle, 0); if ((CPA_STATUS_SUCCESS != status) && (CPA_STATUS_RETRY != status)) { PRINT_ERR("Error:poll instance returned status %d\n", status); } } } } if (-1 == epoll_ctl(efd, EPOLL_CTL_DEL, fd, &event)) { PRINT_ERR("Error removing fd from epoll\n"); } qaeMemFree((void **)&events); putFileDescriptorFn(instanceHandle, fd); close(efd); return 0; #else PRINT_ERR("Event based polling not enabled during compile\n"); return -1; #endif } void sampleCodeDcEventPoll(CpaInstanceHandle instanceHandle) { if (0 != sampleCodeEventPoll(instanceHandle, CPA_ACC_SVC_TYPE_DATA_COMPRESSION)) { PRINT_ERR("Error enabling sample code event poll\n"); } } void sampleCodeCyEventPoll(CpaInstanceHandle instanceHandle) { if (0 != sampleCodeEventPoll(instanceHandle, CPA_ACC_SVC_TYPE_CRYPTO)) { PRINT_ERR("Error enabling sample code event poll\n"); } } void sample_code_wait_threads_arrived(Cpa32U sleepTimeout, Cpa32U maxRetries) { Cpa32U retryValue = 0; do { sampleCodeSleep(sleepTimeout); if (maxRetries == retryValue) { PRINT("startThreads: MAX RETRY reached and all threads are not " "reached to barrier \n"); break; } retryValue++; } while (numThreadsAtBarrier_g < numCreatedThreads_g); } /* The three functions below are needed to sync performance threads in * kernel space in the user space they don't do much */ void sampleCodeCompletionInit(Cpa32U threadId) { return; } CpaStatus sampleCodeThreadCollect(sample_code_thread_t *thread, Cpa32U threadId) { return sampleCodeThreadJoin(thread); } void sampleCodeThreadComplete(Cpa32U threadId) { sampleCodeThreadExit(); } cpa_sample_code_utils.h000066400000000000000000000326131503624047500413670ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/framework/linux/user_space /****************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ /** ***************************************************************************** * @file cpa_sample_code_utils.h * * This file provides linux kernel os abstraction functions * *****************************************************************************/ #ifndef _USER_SPACE_SAMPLECODEUTILS_H__ #define _USER_SPACE_SAMPLECODEUTILS_H__ #include "cpa.h" #include #include #include #include #include #include #include #include #include #include #include #include "openssl/sha.h" /** ***************************************************************************** * these variables are used to keep status of the backoff timer settings * CpaBoolean backoff_timer_g - indicates if backoff timer is enabled * true - enabled * false - disabled * backoff_dynamic_g - indicates if dynamic algorithm is enabled * true - enabled (determine backoff delay dynamically) * false - disabled (use static backoff delay) * backoff_static_timer_g - number of busy loop cycles for the static * backoff timer *****************************************************************************/ extern volatile CpaBoolean backoff_timer_g; extern volatile CpaBoolean backoff_dynamic_g; extern uint32_t backoff_static_timer_g; /** *****************************************************************************/ typedef long ChipRec_s32; ///< 32 bit signed integer typedef long long ChipRec_s64; ///< 64 bit signed integer typedef unsigned long ChipRec_u32; ///< 32 bit unsigned integer typedef unsigned long long ChipRec_u64; ///< 64 bit unsigned integer #define sample_code_thread_t pthread_t typedef sem_t *sample_code_semaphore_t; #define EXPORT_SYMBOL(doNothing) #define SAMPLECODE_POSIX_SHARED_SEMAPHORE (1) /* A minimum of 512 buffers should be used in the sample code to ensure that * both RX/TX rings are full during performance operations. This also ensures * that in-flight requests are not being resubmitted before being returned by * the driver. */ #define CY_SYM_DP_NUM_BUFFERS (1000) #define CY_SYM_DP_NUM_LOOPS (100) #define CLI_OPT_LEN (25) #define RUN_ALL_TESTS (127) #define DEFAULT_SIGN_OF_LIFE (0) #define USE_V1_CONFIG_FILE (1) #define USE_V2_CONFIG_FILE (2) #define MAX_NUMOPT (16) typedef struct option_s { const char optName[CLI_OPT_LEN]; int optValue; } option_t; extern int parseArg(int argc, char **argv, option_t *optArray, int numOpt); #define THREAD_DEFAULT_SCHED_POLICY SCHED_OTHER #define sample_code_thread_mutex_t pthread_mutex_t #define sample_code_thread_cond_t pthread_cond_t #define sample_code_thread_barrier_t pthread_barrier_t #define PTHREAD_CHECK_RETURN_VALUE(fn) \ do \ { \ int ret = (fn); \ if (ret != 0) \ { \ PRINT_ERR("pthread function failed with error:%d\n", ret); \ } \ } while (0) #define sample_code_thread_mutex_init(mutex_ptr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_mutex_init(mutex_ptr, NULL)) #define sample_code_thread_mutex_lock(mutex_ptr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_mutex_lock(mutex_ptr)) #define sample_code_thread_mutex_unlock(mutex_ptr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_mutex_unlock(mutex_ptr)) #define sample_code_thread_mutex_destroy(mutex_ptr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_mutex_destroy(mutex_ptr)) #define sample_code_thread_cond_init(condPtr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_cond_init(condPtr, NULL)) #define sample_code_thread_cond_wait(condPtr, mutex_ptr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_cond_wait(condPtr, mutex_ptr)) #define sample_code_thread_cond_broadcast(condPtr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_cond_broadcast(condPtr)) #define sample_code_thread_cond_destroy(cPtr) \ PTHREAD_CHECK_RETURN_VALUE(pthread_cond_destroy(cPtr)) #define PRINT(args...) \ do \ { \ printf(args); \ } while (0) #define do_div(n, base) (n = n / base) #include #include #include #include /** ***************************************************************************** * @ingroup perfCodeFramework * sampleCodeThreadExit * * @description * This function is called by threads_g on exit, for user space it cleans * up pthreads_g, for kernel space it does nothing and is provided to allow * an application to be compiled to run in user or kernel * * * @param[in] none, this function is called within the thread context * * @retval none * * @pre * thread is executing * @post * thread is closed * *****************************************************************************/ void sampleCodeThreadExit(void); #ifdef BLOCKOUT typedef unsigned long long ticks_t; /* cpuid for intel e gnu compiler */ #if defined(__INTEL_COMPILER) #define __CPUID(a, b) __cpuid((a), (b)) #else /* #if defined (__INTEL_COMPILER) */ #define __CPUID(in, a, b, c, d) \ asm volatile("cpuid" \ : "=a"(a), "=b"(b), "=c"(c), "=d"(d) \ : "a"(in) \ : "ebx"); #endif /* #if defined (__INTEL_COMPILER) */ static void __inline__ cpuid(void) { #if defined(__INTEL_COMPILER) int CPUInfo[4] = {-1}; __CPUID(CPUInfo, 1); #else /* #if defined (__INTEL_COMPILER) */ unsigned int a = 0x00, b = 0x00, c = 0x00, d = 0x00; __CPUID(0x00, a, b, c, d); #endif /* #if defined (__INTEL_COMPILER) */ } static __inline__ ticks_t rdtsc(void) { unsigned long a, d; asm volatile("rdtsc" : "=a"(a), "=d"(d)); return (((ticks_t)a) | (((ticks_t)d) << 32)); } /* Serialized version of the rdtsc instruction to properly count cycles need to remove the cpuid overhead ticks_t cpuid_cycles = get_cpuid_cycles(); ticks_t s1 = rdtscp(); { code_to_benchmark(); } ticks_t s2 = rdtscp(); ticks_t measured_time = s2 - s1 - cpuid_cycles; */ static __inline__ ticks_t rdtscp(void) { volatile unsigned long a = 0, d = 0; ticks_t returnval = 0; cpuid(); asm volatile("rdtsc" : "=a"(a), "=d"(d)); returnval = (((ticks_t)d) << 32); returnval |= ((ticks_t)a); return returnval; } /* This function estimates the number of clock cycles for the cpuid instruction Needs to be run at least 3 times to "warm-up" and report a stable number */ static __inline__ ticks_t rdtscll() { volatile ticks_t cpuid_cycles = 0; volatile ticks_t s1; cpuid(); s1 = rdtsc(); cpuid(); cpuid_cycles = rdtsc(); cpuid_cycles -= s1; // printf("cpuid_cycles: %llu \n", cpuid_cycles); cpuid(); s1 = rdtsc(); cpuid(); cpuid_cycles = rdtsc(); cpuid_cycles -= s1; // printf("cpuid_cycles: %llu \n", cpuid_cycles); cpuid(); s1 = rdtsc(); cpuid(); cpuid_cycles = rdtsc(); cpuid_cycles -= s1; // printf("cpuid_cycles: %llu \n", cpuid_cycles); return cpuid_cycles; } #endif /** ***************************************************************************** * @ingroup sampleCode * enableBackoffTimer * * @description * enables backoff timer; * * @param[in] none * * @retval status of execution * * @pre * none * @post * the backoff timer is enabled * *****************************************************************************/ CpaStatus enableBackoffTimer(); /** ***************************************************************************** * @ingroup sampleCode * disableBackoffTimer * * @description * disables backoff timer; * * @param[in] none * * @retval status of execution * * @pre * none * @post * the backoff timer is disabled * *****************************************************************************/ CpaStatus disableBackoffTimer(); /** ***************************************************************************** * @ingroup sampleCode * e nableBackoffDynamic * * @description * enables the dynamic algorithm for the backoff timer. * The function also calls enableBackoffTimer(); * * @param[in] none * * @retval status of execution * * @pre * none * @post * the dynamic backoff timer is switched on * *****************************************************************************/ CpaStatus enableBackoffDynamic(); /** ***************************************************************************** * @ingroup sampleCode * enableBackoffStatic * * @description * enables the static delay for the backoff timer. The delay value is to * be passed as a parameter. The delay value will be used as a number * of cycles for the busy_loop. * * @param[in] number of busy loop cycles * * @retval status of execution * * @pre * none * @post * the static backoff timer is switched on. The delay value is set. * *****************************************************************************/ CpaStatus enableBackoffStatic(uint32_t numBusyLoops); /** ***************************************************************************** * @ingroup sampleCode * sample_code_wait_threads_arrived * * @description * Checks if all the threads arrived and prints error is they are not after . * * @param[in] sleepTimeout - sleep between reties * maxRetries - maximum number of retries * * @retval * none * * @pre * none * @post * none * *****************************************************************************/ void sample_code_wait_threads_arrived(Cpa32U sleepTimeout, Cpa32U maxRetries); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/000077500000000000000000000000001503624047500302335ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/linux/000077500000000000000000000000001503624047500313725ustar00rootroot00000000000000kernel_space/000077500000000000000000000000001503624047500337465ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/linuxqae_mem_utils.c000066400000000000000000000162551503624047500367470ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/linux/kernel_space/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qae_mem_utils.c * * This file provides linux kernel memory allocation for quick assist API * *****************************************************************************/ #include "qae_mem_utils.h" #ifdef SAL_IOMMU_CODE #include #endif #include #include #include #include #include /* Maximum memory can be allocated by kmalloc*/ #define QAE_MEM_SIZE_LIMIT (1024 * 4096) /* return amount of padding based on padSize a and alignment b*/ #define MEM_PADDING(a, b) ((b - (a % b)) % b) #define IS_VMALLOC_ADDR(addr) \ (((QAE_UINT)(addr) >= VMALLOC_START) && ((QAE_UINT)(addr) < VMALLOC_END)) Cpa32U numaAllocations_g = 0; Cpa32U normalAllocations_g = 0; /************************************** * Memory functions *************************************/ void *qaeMemAlloc(Cpa32U memsize) { if (memsize > QAE_MEM_SIZE_LIMIT) { return (vmalloc(memsize)); } normalAllocations_g++; return (kmalloc(memsize, GFP_KERNEL)); } void *qaeMemAllocNUMA(Cpa32U size, Cpa32U node, Cpa32U alignment) { void *ptr = NULL; uint64_t phys_ptr = 0; void *pRet = NULL; Cpa32U alignment_offset = 0; qae_mem_alloc_info_t memInfo = {0}; if (size == 0 || alignment < 1) { printk(" size or alignment are zero \n"); return NULL; } /*alignment should be 1,2,4,8....*/ if (alignment & (alignment - 1)) { printk("Expecting alignment of a power of \ two but did not get one\n"); return NULL; } // add the alignment and the struct size to the buffer size memInfo.mSize = size + alignment + sizeof(qae_mem_alloc_info_t); #ifdef SAL_IOMMU_CODE memInfo.mSize = icp_sal_iommu_get_remap_size(memInfo.mSize); #endif /*allocate contiguous memory*/ ptr = kmalloc_node(memInfo.mSize, GFP_KERNEL, node); if (ptr == NULL) { printk("failed to allocate memory\n"); return NULL; } // store the base address into the struct memInfo.mAllocMemPtr = ptr; phys_ptr = virt_to_phys(ptr); #ifdef SAL_IOMMU_CODE if (icp_sal_iommu_map(phys_ptr, phys_ptr, memInfo.mSize)) { printk("failed to iommu remap\n"); kfree(ptr); return NULL; } #endif // add the size of the struct to the return pointer pRet = (char *)memInfo.mAllocMemPtr + sizeof(qae_mem_alloc_info_t); // compute the offset from the lignement alignment_offset = (QAE_UINT)pRet % alignment; // in order to obtain the pointer to the buffer add the alignment and // subtract the offset, now we have the return pointer aligned pRet = (char *)pRet + (alignment - alignment_offset); // copy the struct immediately before the buffer pointer memcpy((void *)((char *)pRet - sizeof(qae_mem_alloc_info_t)), (void *)(&memInfo), sizeof(qae_mem_alloc_info_t)); // increment the NUMA allocations counter numaAllocations_g++; return pRet; } void qaeMemFreeNUMA(void **ptr) { qae_mem_alloc_info_t *memInfo = NULL; if (ptr == NULL || *ptr == NULL) { return; } memInfo = (qae_mem_alloc_info_t *)((Cpa8S *)*ptr - sizeof(qae_mem_alloc_info_t)); if (memInfo->mSize == 0 || memInfo->mAllocMemPtr == NULL) { printk("Detected the corrupted data: memory leak!\n"); printk("Size: %d, memPtr: %p\n", memInfo->mSize, memInfo->mAllocMemPtr); return; } #ifdef SAL_IOMMU_CODE if (icp_sal_iommu_unmap(virt_to_phys(memInfo->mAllocMemPtr), memInfo->mSize)) { printk("failed to iommu unmap\n"); } #endif kfree(memInfo->mAllocMemPtr); numaAllocations_g--; *ptr = NULL; } void qaeMemFree(void **ptr) { if (ptr == NULL || *ptr == NULL) { return; } if (IS_VMALLOC_ADDR(*ptr)) { vfree(*ptr); return; } kfree(*ptr); normalAllocations_g--; *ptr = NULL; } QAE_PHYS_ADDR qaeVirtToPhysNUMA(void *ptr) { return (QAE_PHYS_ADDR)(QAE_UINT)virt_to_phys(ptr); } void printMemAllocations() { printk("NUMA Allocations %d\n", numaAllocations_g); printk("Normal Allocations %d\n", normalAllocations_g); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/linux/user_space/000077500000000000000000000000001503624047500335235ustar00rootroot00000000000000qae_mem_utils.c000066400000000000000000000323761503624047500364470ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/linux/user_space/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qae_mem_utils.c * * This file provides provide for Linux user space memory allocation. It uses * a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the quick assist sample code * *****************************************************************************/ #include "qae_mem.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef SAL_IOMMU_CODE #include #endif #define QAE_MEM "/dev/usdm_drv" #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE - 1)) #define USER_MEM_128BYTE_OFFSET (128) #define MAGIC_NUM 0xABCD12345678ECDFUL static pthread_mutex_t mutex_g = PTHREAD_MUTEX_INITIALIZER; static qae_dev_mem_info_t *pUserMemList = NULL; static qae_dev_mem_info_t *pUserMemListHead = NULL; static int fd = 0; /************************************** * Memory functions *************************************/ CpaStatus qaeMemInit(void) { fd = open(QAE_MEM, O_RDWR); if (fd < 0) { printf("unable to open %s %d\n", QAE_MEM, fd); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } void qaeMemDestroy(void) { close(fd); } void *qaeMemAlloc(Cpa32U memsize) { QAE_UINT *memPtr = NULL; memPtr = malloc(memsize); return memPtr; } static CpaStatus userMemListAdd(qae_dev_mem_info_t *pMemInfo) { int ret = 0; ret = pthread_mutex_lock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex lock\n", ret); return CPA_STATUS_FAIL; } ADD_ELEMENT_TO_END_OF_LIST(pMemInfo, pUserMemList, pUserMemListHead); ret = pthread_mutex_unlock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex unlock\n", ret); return CPA_STATUS_FAIL; } return CPA_STATUS_SUCCESS; } static void userMemListFree(qae_dev_mem_info_t *pMemInfo) { qae_dev_mem_info_t *pCurr = NULL; for (pCurr = pUserMemListHead; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr == pMemInfo) { REMOVE_ELEMENT_FROM_LIST(pCurr, pUserMemList, pUserMemListHead); break; } } } static qae_dev_mem_info_t *userMemLookupBySize(Cpa32U size) { qae_dev_mem_info_t *pCurr = NULL; for (pCurr = pUserMemListHead; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr->available_size >= size) { return pCurr; } } return NULL; } static qae_dev_mem_info_t *userMemLookupByVirtAddr(void *virt_addr) { qae_dev_mem_info_t *pCurr = NULL; for (pCurr = pUserMemListHead; pCurr != NULL; pCurr = pCurr->pNext) { if ((QAE_UINT)pCurr->virt_addr <= (QAE_UINT)virt_addr && ((QAE_UINT)pCurr->virt_addr + pCurr->size) > (QAE_UINT)virt_addr) { return pCurr; } } return NULL; } void *qaeMemAllocNUMA(Cpa32U size, Cpa32U node, Cpa32U alignment) { int ret = 0; qae_dev_mem_info_t *pMemInfo = NULL; void *pVirtAddress = NULL; void *pOriginalAddress = NULL; QAE_UINT padding = 0; QAE_UINT aligned_address = 0; uint64_t magic = MAGIC_NUM; if (size == 0 || alignment == 0) { printf("Invalid size or alignment parameter\n"); return NULL; } if (fd < 0) { printf("Memory file handle is not ready\n"); return NULL; } ret = pthread_mutex_lock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex lock\n", ret); return NULL; } if ((pMemInfo = userMemLookupBySize(size + alignment)) != NULL) { pOriginalAddress = (void *)((QAE_UINT)pMemInfo->virt_addr + (QAE_UINT)(pMemInfo->size - pMemInfo->available_size)); padding = (QAE_UINT)pOriginalAddress % alignment; aligned_address = ((QAE_UINT)pOriginalAddress) - padding + alignment; pMemInfo->available_size -= (size + (aligned_address - (QAE_UINT)pOriginalAddress)); pMemInfo->allocations += 1; ret = pthread_mutex_unlock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex lock\n", ret); return NULL; } return (void *)aligned_address; } pMemInfo = malloc(sizeof(qae_dev_mem_info_t)); if (NULL == pMemInfo) { printf("unable to allocate pMemInfo buffer\n"); pthread_mutex_unlock(&mutex_g); return NULL; } pMemInfo->allocations = 0; pMemInfo->size = USER_MEM_128BYTE_OFFSET + size; pMemInfo->size = pMemInfo->size % PAGE_SIZE ? ((pMemInfo->size / PAGE_SIZE) + 1) * PAGE_SIZE : pMemInfo->size; #ifdef SAL_IOMMU_CODE pMemInfo->size = icp_sal_iommu_get_remap_size(pMemInfo->size); #endif pMemInfo->nodeId = node; ret = ioctl(fd, DEV_MEM_IOC_MEMALLOC, pMemInfo); if (ret != 0) { printf("ioctl call failed, ret = %d\n", ret); free(pMemInfo); pthread_mutex_unlock(&mutex_g); return NULL; } pMemInfo->virt_addr = mmap((caddr_t)0, pMemInfo->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (pMemInfo->id * getpagesize())); if (pMemInfo->virt_addr == (caddr_t)MAP_FAILED) { printf("mmap failed\n"); ret = ioctl(fd, DEV_MEM_IOC_MEMFREE, pMemInfo); if (ret != 0) { printf("ioctl call failed, ret = %d\n", ret); } free(pMemInfo); pthread_mutex_unlock(&mutex_g); return NULL; } pMemInfo->available_size = pMemInfo->size - size - USER_MEM_128BYTE_OFFSET; pMemInfo->allocations = 1; memcpy(pMemInfo->virt_addr, pMemInfo, sizeof(qae_dev_mem_info_t)); memcpy(pMemInfo->virt_addr, &magic, sizeof(uint64_t)); pVirtAddress = (void *)((QAE_UINT)pMemInfo->virt_addr + USER_MEM_128BYTE_OFFSET); /* Free mutex as lock is re-acquired in userMemListAdd */ pthread_mutex_unlock(&mutex_g); if (CPA_STATUS_SUCCESS != userMemListAdd(pMemInfo)) { printf("Error on mem list add\n"); return NULL; } return pVirtAddress; } void qaeMemFreeNUMA(void **ptr) { int ret = 0; qae_dev_mem_info_t *pMemInfo = NULL; void *pVirtAddress = NULL; if (NULL == ptr) { printf("Invalid virtual address\n"); return; } pVirtAddress = *ptr; if (pVirtAddress == NULL) { printf("Invalid virtual address\n"); return; } ret = pthread_mutex_lock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex lock\n", ret); return; } if ((pMemInfo = userMemLookupByVirtAddr(pVirtAddress)) != NULL) { pMemInfo->allocations -= 1; if (pMemInfo->allocations != 0) { *ptr = NULL; ret = pthread_mutex_unlock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex unlock\n", ret); return; } return; } } else { printf("userMemLookupByVirtAddr failed\n"); ret = pthread_mutex_unlock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex unlock\n", ret); return; } return; } ret = munmap(pMemInfo->virt_addr, pMemInfo->size); if (ret != 0) { printf("munmap failed, ret = %d\n", ret); } ret = ioctl(fd, DEV_MEM_IOC_MEMFREE, pMemInfo); if (ret != 0) { printf("ioctl call failed, ret = %d\n", ret); } userMemListFree(pMemInfo); free(pMemInfo); *ptr = NULL; ret = pthread_mutex_unlock(&mutex_g); if (0 != ret) { printf("Error(%d) on thread mutex lock\n", ret); return; } return; } void qaeMemFree(void **ptr) { if (NULL == ptr || NULL == *ptr) { printf("ERROR, Trying to Free NULL Pointer\n"); return; } free(*ptr); *ptr = NULL; } /* NEW_1_4_CODE_WITH_MAGIC causes a * performance penalty. The #else code can cause * instability if used for a prolonged period. * * If you want stability with less performance then comment in the * NEW_1_4_CODE_WITH_MAGIC*/ #define NEW_1_4_CODE_WITH_MAGIC #ifdef NEW_1_4_CODE_WITH_MAGIC /*run less performance more stable virt2Phys function*/ QAE_PHYS_ADDR qaeVirtToPhysNUMA(void *pVirtAddress) { qae_dev_mem_info_t *pMemInfo = NULL; void *pVirtPageAddress = NULL; QAE_UINT offset = 0; uint64_t *magic; if (pVirtAddress == NULL) { printf("qaeVirtToPhysNUMA(): Null virtual address pointer\n"); return (QAE_PHYS_ADDR)0; } pVirtPageAddress = ((int *)((((QAE_UINT)pVirtAddress)) & (PAGE_MASK))); offset = (QAE_UINT)pVirtAddress - (QAE_UINT)pVirtPageAddress; do { pMemInfo = (qae_dev_mem_info_t *)pVirtPageAddress; magic = (uint64_t *)pMemInfo; if ((MAGIC_NUM == *magic) && (pMemInfo->virt_addr == pVirtPageAddress)) { break; } pVirtPageAddress = (void *)((QAE_UINT)pVirtPageAddress - PAGE_SIZE); offset += PAGE_SIZE; } while (pMemInfo->virt_addr != pVirtPageAddress); return (QAE_PHYS_ADDR)(pMemInfo->phy_addr + offset); } #else /*run higher performance vitr2Phys function, also could cause memory * corruption*/ QAE_PHYS_ADDR qaeVirtToPhysNUMA(void *pVirtAddress) { qae_dev_mem_info_t *pMemInfo = NULL; void *pVirtPageAddress = NULL; QAE_UINT offset = 0; if (pVirtAddress == NULL) { printf("qaeVirtToPhysNUMA(): Null virtual address pointer\n"); return (QAE_PHYS_ADDR)0; } pVirtPageAddress = ((int *)((((QAE_UINT)pVirtAddress)) & (PAGE_MASK))); offset = (QAE_UINT)pVirtAddress - (QAE_UINT)pVirtPageAddress; do { pMemInfo = (qae_dev_mem_info_t *)pVirtPageAddress; if (pMemInfo->virt_addr == pVirtPageAddress) { break; } pVirtPageAddress = (void *)((QAE_UINT)pVirtPageAddress - PAGE_SIZE); offset += PAGE_SIZE; } while (pMemInfo->virt_addr != pVirtPageAddress); return (QAE_PHYS_ADDR)(pMemInfo->phy_addr + offset); } #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/qae_mem.h000066400000000000000000000353601503624047500320170ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qae_mem.h * * This file provides linux kernel memory allocation for quick assist API * *****************************************************************************/ #ifndef QAE_MEM_H_ #define QAE_MEM_H_ #include "cpa.h" /*define types which need to vary between 32 and 64 bit*/ #ifdef __x86_64__ #define QAE_UINT Cpa64U #define QAE_INT Cpa64S #else #define QAE_UINT Cpa32U #define QAE_INT Cpa32S #endif #define QAE_PHYS_ADDR CpaPhysicalAddr /** ***************************************************************************** * @ingroup perfCodeFramework * Framework aligned memory structure. * @description * This structure is used to assist the framework in allocating aligned * memory ****************************************************************************/ typedef struct qae_mem_alloc_info_s { void *mAllocMemPtr; /* memory addr returned by the kernel */ Cpa32U mSize; /* allocated size */ } qae_mem_alloc_info_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory info. * @description * This structure is used to store info on aligned user space memory * memory ****************************************************************************/ #pragma pack(push) #pragma pack(1) typedef struct qae_dev_mem_info_s { union { struct qae_dev_mem_info_s *pPrev; uint64_t padding_pPrev; }; union { struct qae_dev_mem_info_s *pNext; uint64_t padding_pNext; }; uint32_t id; /* Id of this block */ uint32_t nodeId; /* Node id for NUMA */ uint32_t size; /* Size of this block (bytes) */ uint32_t available_size; /* Available size remained on the page */ uint16_t allocations; /* Counter keeping track of number of allocations */ union { void *kmalloc_ptr; uint64_t padding_kmalloc_ptr; }; /* Pointer to mem originally returned by kmalloc */ union { int32_t *kmalloc_area; uint64_t padding_kamalloc_area; }; /* Pointer to kmalloc'd area rounded up to a page boundary */ uint64_t phy_addr; /* Physical address of the kmalloced area */ union { void *virt_addr; uint64_t padding_virt_addr; }; /* Base address in user space - i.e. virtual address */ } qae_dev_mem_info_t; #pragma pack(pop) /** ***************************************************************************** * @ingroup qaeMemUtils * array structure * @description * This structure is used to copy chunks of data read from files * from user to kernel space ****************************************************************************/ typedef struct dev_mem_file_s { unsigned char data[2048]; unsigned int size; } dev_mem_file_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory list pointer structure. * @description * This structure is used to assist in allocating aligned * memory ****************************************************************************/ typedef struct user_proc_mem_list_s { unsigned int pid; unsigned int allocs_nr; unsigned int max_id; qae_dev_mem_info_t *freed_head; qae_dev_mem_info_t *freed_tail; qae_dev_mem_info_t *head; qae_dev_mem_info_t *tail; struct user_proc_mem_list_s *pPrev; struct user_proc_mem_list_s *pNext; } user_proc_mem_list_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory list pointer structure. * @description * This structure is used to assist in allocating aligned * memory ****************************************************************************/ typedef struct user_mem_dev_s { user_proc_mem_list_t *head; user_proc_mem_list_t *tail; } user_mem_dev_t; #define ENSURE_NOT_NULL(ptr, str, status) \ do \ { \ if (ptr == NULL) \ { \ printk("%s\n", str); \ return status; \ } \ } while (0); #define ADD_ELEMENT_TO_END_OF_LIST(elementtoadd, currentptr, headptr) \ do \ { \ if (NULL == currentptr) \ { \ currentptr = elementtoadd; \ elementtoadd->pNext = NULL; \ elementtoadd->pPrev = NULL; \ headptr = currentptr; \ } \ else \ { \ elementtoadd->pPrev = currentptr; \ currentptr->pNext = elementtoadd; \ elementtoadd->pNext = NULL; \ currentptr = elementtoadd; \ } \ } while (0); #define REMOVE_ELEMENT_FROM_LIST(elementtoremove, currentptr, headptr) \ do \ { \ /*If the previous pointer is not NULL*/ \ if (NULL != elementtoremove->pPrev) \ { \ elementtoremove->pPrev->pNext = elementtoremove->pNext; \ if (elementtoremove->pNext) \ { \ elementtoremove->pNext->pPrev = elementtoremove->pPrev; \ } \ else \ { \ currentptr = elementtoremove->pPrev; \ } \ } \ else if (NULL != elementtoremove->pNext) \ { \ elementtoremove->pNext->pPrev = NULL; \ headptr = elementtoremove->pNext; \ } \ else \ { \ currentptr = NULL; \ headptr = NULL; \ } \ } while (0) /* IOCTL number for use between the kernel and the user space application */ #define DEV_MEM_MAGIC 'q' #define DEV_MEM_CMD_MEMALLOC (0) #define DEV_MEM_CMD_MEMFREE (1) #define DEV_MEM_CMD_CORPUS (2) /* IOCTL commands for requesting kernel memory */ #define DEV_MEM_IOC_MEMALLOC \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMALLOC, qae_dev_mem_info_t) #define DEV_MEM_IOC_MEMFREE \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMFREE, qae_dev_mem_info_t) #define DEV_MEM_IOC_CORPUS \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_CORPUS, dev_mem_file_t) #ifdef BLOCKOUT qae_dev_mem_info_t *userMemAlloc(user_mem_dev_t *dev, Cpa32U sizeInBytes, Cpa32U node, Cpa32U pid); qae_dev_mem_info_t *userMemGetInfo(user_mem_dev_t *dev, Cpa32U id, Cpa32U pid); void userMemFree(user_mem_dev_t *dev, Cpa32U id, Cpa32U pid); void userMemFreeAllPid(user_mem_dev_t *dev, Cpa32U pid); void userMemFreeAll(user_mem_dev_t *dev); #endif /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemAlloc * * @description * allocates memsize bytes of memory * * * @param[in] memsize, the amount of memory in bytes to be allocated * * @retval pointer to the allocated memory * * @pre * none * @post * memory is allocated * *****************************************************************************/ void *qaeMemAlloc(Cpa32U memsize); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemAllocNUMA * * @description * allocates contiguous memory local to the cpu(node) of memsize bytes * * * @param[in] memsize, the amount of memory in bytes to be allocated * * @retval pointer to the allocated memory * * @pre * none * @post * memory is allocated * *****************************************************************************/ void *qaeMemAllocNUMA(Cpa32U size, Cpa32U node, Cpa32U alignment); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeVirtToPhysNUMA * * @description * Converts a virtual address to a physical one * * * @param[in] pVirtAddr pointer to the virtual address * * @retval pointer to the physical address * * @pre * none * @post * memory is allocated * *****************************************************************************/ QAE_PHYS_ADDR qaeVirtToPhysNUMA(void *pVirtAddr); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemFreeNUMA * * @description * frees memory allocated by the qaeMemAllocNUMA function * * * @param[in] pointer to the memory to be freed * * @retval none * * @pre * none * @post * memory is freed * *****************************************************************************/ void qaeMemFreeNUMA(void **ptr); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemFree * * @description * frees memory allocated by the qaeMemAlloc function * * * @param[in] pointer to the memory to be freed * * @retval none * * @pre * none * @post * memory is freed * *****************************************************************************/ void qaeMemFree(void **ptr); void printMemAllocations(void); int register_mem_device_driver(void); void unregister_mem_device_driver(void); int qae_mem_init(void); void qae_mem_exit(void); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/sample_code/performance/qae/qae_mem_utils.h000066400000000000000000000366021503624047500332370ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qae_mem_utils.h * * This file provides linux kernel memory allocation for quick assist API * *****************************************************************************/ #ifndef QAE_MEM_UTILS_H_ #define QAE_MEM_UTILS_H_ #include "cpa.h" /*define types which need to vary between 32 and 64 bit*/ #ifdef __x86_64__ #define QAE_UINT Cpa64U #define QAE_INT Cpa64S #else #define QAE_UINT Cpa32U #define QAE_INT Cpa32S #endif #define QAE_PHYS_ADDR CpaPhysicalAddr /** ***************************************************************************** * @ingroup perfCodeFramework * Framework aligned memory structure. * @description * This structure is used to assist the framework in allocating aligned * memory ****************************************************************************/ typedef struct qae_mem_alloc_info_s { void *mAllocMemPtr; /* memory addr returned by the kernel */ Cpa32U mSize; /* allocated size */ } qae_mem_alloc_info_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory info. * @description * This structure is used to store info on aligned user space memory * memory ****************************************************************************/ #pragma pack(push) #pragma pack(1) typedef struct dev_mem_info_s { union { struct dev_mem_info_s *pPrev; uint64_t padding_pPrev; }; union { struct dev_mem_info_s *pNext; uint64_t padding_pNext; }; uint32_t id; /* Id of this block */ uint32_t nodeId; /* Node id for NUMA */ uint32_t size; /* Size of this block (bytes) */ uint32_t available_size; /* Available size remained on the page */ uint16_t allocations; /* Counter keeping track of number of allocations */ union { void *kmalloc_ptr; uint64_t padding_kmalloc_ptr; }; /* Pointer to mem originally returned by kmalloc */ union { int32_t *kmalloc_area; uint64_t padding_kamalloc_area; }; /* Pointer to kmalloc'd area rounded up to a page boundary */ uint64_t phy_addr; /* Physical address of the kmalloced area */ union { void *virt_addr; uint64_t padding_virt_addr; }; /* Base address in user space - i.e. virtual address */ } dev_mem_info_t; #pragma pack(pop) /** ***************************************************************************** * @ingroup qaeMemUtils * array structure * @description * This structure is used to copy chunks of data read from files * from user to kernel space ****************************************************************************/ typedef struct dev_mem_file_s { unsigned char data[2048]; unsigned int size; } dev_mem_file_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory list pointer structure. * @description * This structure is used to assist in allocating aligned * memory ****************************************************************************/ typedef struct user_proc_mem_list_s { unsigned int pid; unsigned int allocs_nr; unsigned int max_id; dev_mem_info_t *freed_head; dev_mem_info_t *freed_tail; dev_mem_info_t *head; dev_mem_info_t *tail; struct user_proc_mem_list_s *pPrev; struct user_proc_mem_list_s *pNext; } user_proc_mem_list_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory list pointer structure. * @description * This structure is used to assist in allocating aligned * memory ****************************************************************************/ typedef struct user_mem_dev_s { user_proc_mem_list_t *head; user_proc_mem_list_t *tail; } user_mem_dev_t; #define ENSURE_NOT_NULL(ptr, str, status) \ \ do \ { \ if (ptr == NULL) \ { \ printk("%s\n", str); \ return status; \ } \ \ } while (0); #define ENSURE_NOT_NULL_RETURN_VOID(ptr, str) \ do \ { \ if (ptr == NULL) \ { \ printk("%s\n", str); \ return; \ } \ } while (0); #define ADD_ELEMENT_TO_END_OF_LIST(elementtoadd, currentptr, headptr) \ do \ { \ if (NULL == currentptr) \ { \ currentptr = elementtoadd; \ elementtoadd->pNext = NULL; \ elementtoadd->pPrev = NULL; \ headptr = currentptr; \ } \ else \ { \ elementtoadd->pPrev = currentptr; \ currentptr->pNext = elementtoadd; \ elementtoadd->pNext = NULL; \ currentptr = elementtoadd; \ } \ } while (0); #define REMOVE_ELEMENT_FROM_LIST(elementtoremove, currentptr, headptr) \ do \ { \ /*If the previous pointer is not NULL*/ \ if (NULL != elementtoremove->pPrev) \ { \ elementtoremove->pPrev->pNext = elementtoremove->pNext; \ if (elementtoremove->pNext) \ { \ elementtoremove->pNext->pPrev = elementtoremove->pPrev; \ } \ else \ { \ currentptr = elementtoremove->pPrev; \ } \ } \ else if (NULL != elementtoremove->pNext) \ { \ elementtoremove->pNext->pPrev = NULL; \ headptr = elementtoremove->pNext; \ } \ else \ { \ currentptr = NULL; \ headptr = NULL; \ } \ } while (0) /* IOCTL number for use between the kernel and the user space application */ #define DEV_MEM_MAGIC 'q' #define DEV_MEM_CMD_MEMALLOC (0) #define DEV_MEM_CMD_MEMFREE (1) #define DEV_MEM_CMD_CORPUS (2) /* IOCTL commands for requesting kernel memory */ #define DEV_MEM_IOC_MEMALLOC \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMALLOC, dev_mem_info_t) #define DEV_MEM_IOC_MEMFREE \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMFREE, dev_mem_info_t) #define DEV_MEM_IOC_CORPUS \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_CORPUS, dev_mem_file_t) #ifdef BLOCKOUT dev_mem_info_t *userMemAlloc(user_mem_dev_t *dev, Cpa32U sizeInBytes, Cpa32U node, Cpa32U pid); dev_mem_info_t *userMemGetInfo(user_mem_dev_t *dev, Cpa32U id, Cpa32U pid); void userMemFree(user_mem_dev_t *dev, Cpa32U id, Cpa32U pid); void userMemFreeAllPid(user_mem_dev_t *dev, Cpa32U pid); void userMemFreeAll(user_mem_dev_t *dev); #endif /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemAlloc * * @description * allocates memsize bytes of memory * * * @param[in] memsize, the amount of memory in bytes to be allocated * * @retval pointer to the allocated memory * * @pre * none * @post * memory is allocated * *****************************************************************************/ void *qaeMemAlloc(Cpa32U memsize); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemAllocNUMA * * @description * allocates contiguous memory local to the cpu(node) of memsize bytes * * * @param[in] memsize, the amount of memory in bytes to be allocated * * @retval pointer to the allocated memory * * @pre * none * @post * memory is allocated * *****************************************************************************/ void *qaeMemAllocNUMA(Cpa32U size, Cpa32U node, Cpa32U alignment); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeVirtToPhysNUMA * * @description * Converts a virtual address to a physical one * * * @param[in] pVirtAddr pointer to the virtual address * * @retval pointer to the physical address * * @pre * none * @post * memory is allocated * *****************************************************************************/ QAE_PHYS_ADDR qaeVirtToPhysNUMA(void *pVirtAddr); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemFreeNUMA * * @description * frees memory allocated by the qaeMemAllocNUMA function * * * @param[in] pointer to the memory to be freed * * @retval none * * @pre * none * @post * memory is freed * *****************************************************************************/ void qaeMemFreeNUMA(void **ptr); /** ***************************************************************************** * @ingroup quicksssistExtension_MemoryManagement * qaeMemFree * * @description * frees memory allocated by the qaeMemAlloc function * * * @param[in] pointer to the memory to be freed * * @retval none * * @pre * none * @post * memory is freed * *****************************************************************************/ void qaeMemFree(void **ptr); void printMemAllocations(void); #endif qatlib-25.08.0/quickassist/lookaside/access_layer/src/user/000077500000000000000000000000001503624047500236675ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/access_layer/src/user/sal_user.c000066400000000000000000000253111503624047500256520ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_user.c * * @defgroup SalUser * * @description * This file contains implementation of functions to start/stop user process * *****************************************************************************/ /* QAT-API includes */ #include "cpa.h" #include "cpa_dc.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_accel_devices.h" #include "icp_adf_accel_mgr.h" #include "icp_adf_user_proxy.h" #include "icp_adf_transport.h" #include "icp_adf_cfg.h" #include "icp_adf_debug.h" /* FW includes */ #include "icp_qat_fw_la.h" /* SAL includes */ #include "icp_sal_user.h" #include "lac_log.h" #include "lac_mem.h" #include "lac_mem_pools.h" #include "lac_list.h" #ifndef ICP_DC_ONLY #include "lac_sal_types_crypto.h" #endif #include "sal_types_compression.h" #include "lac_sal.h" #include "lac_sal_ctrl.h" #include "dc_session.h" #include "dc_ns_datapath.h" STATIC OsalMutex sync_lock; #define START_REF_COUNT_MAX 64 CpaStatus icp_adf_resetUserProxy(void); /* Start reference count to keep track of multiple calls to * icp_sal_userStartMulti() and icp_sal_userStop() from the same application. * Only the first call to start will map the instances and * the last call to stop will free them. * This is added to support co-existence scenario (two libraries using * QAT in same application). */ STATIC int start_ref_count = 0; STATIC pid_t start_ref_pid = -1; static CpaStatus do_userReset() { CpaStatus status = CPA_STATUS_SUCCESS; /* there is no option to reset the mutex, hence destroying * it and re-initializing. */ if (sync_lock) osalMutexDestroy(&sync_lock); if (CPA_STATUS_SUCCESS != LAC_INIT_MUTEX(&sync_lock)) { LAC_LOG_ERROR("Mutex init failed for sync_lock\n"); status = CPA_STATUS_RESOURCE; } else { start_ref_count = 0; if (CPA_STATUS_SUCCESS == icp_adf_resetUserProxy()) { status = icp_adf_resetSubsystemTable(); } else { LAC_LOG_ERROR("Error resetting user proxy\n"); status = CPA_STATUS_FAIL; } } return status; } static CpaStatus do_userStart(const char *process_name) { CpaStatus status = CPA_STATUS_SUCCESS; status = icpSetProcessName(process_name); LAC_CHECK_STATUS(status); status = SalCtrl_AdfServicesRegister(); LAC_CHECK_STATUS(status); status = icp_adf_userProxyInit(process_name); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to initialize proxy\n"); SalCtrl_AdfServicesUnregister(); return status; } status = SalCtrl_AdfServicesStartedCheck(); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to start services\n"); SalCtrl_AdfServicesUnregister(); } return status; } CpaStatus icp_sal_userStart(const char *process_name) { char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES + 1] = {0}; CpaStatus status = CPA_STATUS_SUCCESS; pid_t pid = getpid(); if (start_ref_pid != pid) { status = do_userReset(); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("do_userReset failed\n"); return CPA_STATUS_FAIL; } } if (osalMutexLock(&sync_lock, OSAL_WAIT_FOREVER)) { LAC_LOG_ERROR("Mutex lock failed\n"); osalMutexDestroy(&sync_lock); return CPA_STATUS_FAIL; } if (0 == start_ref_count) { status = icp_adf_userProcessToStart(process_name, name); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_DEBUG("icp_adf_userProcessToStart failed\n"); if (osalMutexUnlock(&sync_lock)) LAC_LOG_ERROR("Mutex unlock failed\n"); else osalMutexDestroy(&sync_lock); return CPA_STATUS_FAIL; } status = do_userStart(name); } if (CPA_STATUS_SUCCESS == status) { /* To handle overflow case */ if (start_ref_count >= START_REF_COUNT_MAX) { LAC_LOG_ERROR("start_ref_count overflow!\n"); if (osalMutexUnlock(&sync_lock)) LAC_LOG_ERROR("Mutex unlock failed\n"); else osalMutexDestroy(&sync_lock); return CPA_STATUS_FAIL; } else { start_ref_count += 1; } } if (osalMutexUnlock(&sync_lock)) { LAC_LOG_ERROR("Mutex unlock failed\n"); return CPA_STATUS_FAIL; } if (CPA_STATUS_SUCCESS == status) { start_ref_pid = pid; } return status; } CpaStatus icp_sal_userStartMultiProcess(const char *pProcessName, CpaBoolean limitDevAccess) { return icp_sal_userStart(pProcessName); } static CpaStatus do_userStop() { CpaStatus status = SalCtrl_AdfServicesUnregister(); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to unregister\n"); return status; } status = icp_adf_userProxyShutdown(); if (CPA_STATUS_SUCCESS != status) { LAC_LOG_ERROR("Failed to shutdown proxy\n"); return status; } icp_adf_userProcessStop(); return status; } CpaStatus icp_sal_userStop() { CpaStatus status = CPA_STATUS_SUCCESS; pid_t pid = getpid(); if (!sync_lock) { LAC_LOG_DEBUG("Mutex lock not initialized\n"); return CPA_STATUS_FAIL; } if (osalMutexLock(&sync_lock, OSAL_WAIT_FOREVER)) { LAC_LOG_ERROR("Mutex lock failed\n"); osalMutexDestroy(&sync_lock); return CPA_STATUS_FAIL; } if (start_ref_pid != pid) { LAC_LOG_DEBUG("Process id mismatch\n"); if (osalMutexUnlock(&sync_lock)) LAC_LOG_ERROR("Mutex unlock failed\n"); return CPA_STATUS_FAIL; } if (1 == start_ref_count) { status = do_userStop(); } if (0 < start_ref_count) { start_ref_count -= 1; } if (0 == start_ref_count) { start_ref_pid = -1; } if (osalMutexUnlock(&sync_lock)) { LAC_LOG_ERROR("Mutex unlock failed\n"); return CPA_STATUS_FAIL; } if (0 == start_ref_count) { osalMutexDestroy(&sync_lock); } return status; } CpaStatus icp_sal_find_new_devices(void) { return icp_adf_userFindNewDevices(); } CpaStatus icp_sal_poll_device_events(void) { return icp_adf_pollDeviceEvents(); } CpaStatus icp_sal_check_device(Cpa32U packageId) { return icp_adf_userCheckDevice(packageId); } CpaStatus icp_sal_check_all_devices(void) { return icp_adf_userCheckAllDevices(); } CpaStatus icp_sal_heartbeat_simulate_failure(Cpa32U packageId) { #ifdef ICP_HB_FAIL_SIM return icp_adf_heartbeatSimulateFailure(packageId); #else return CPA_STATUS_UNSUPPORTED; #endif } CpaStatus icp_sal_get_num_pfs(Cpa16U *pNumPFs) { return icp_adf_userGetNumPfs(pNumPFs); } CpaStatus icp_sal_get_pf_info(CpaPfInfo *pPf_info) { return icp_adf_userGetPfInfo((icp_accel_pf_info_t *)pPf_info); } CpaStatus icp_sal_reset_device(Cpa32U accelId) { return icp_adf_resetDevice(accelId); } CpaStatus icp_sal_cnv_simulate_error(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle) { #ifdef ICP_DC_ERROR_SIMULATION return dcSetCnvError(dcInstance, pSessionHandle); #else return CPA_STATUS_UNSUPPORTED; #endif } CpaStatus icp_sal_ns_cnv_simulate_error(CpaInstanceHandle dcInstance) { #ifdef ICP_DC_ERROR_SIMULATION return dcNsSetCnvErrorInj(dcInstance, CPA_TRUE); #else return CPA_STATUS_UNSUPPORTED; #endif } CpaStatus icp_sal_ns_cnv_reset_error(CpaInstanceHandle dcInstance) { #ifdef ICP_DC_ERROR_SIMULATION return dcNsSetCnvErrorInj(dcInstance, CPA_FALSE); #else return CPA_STATUS_UNSUPPORTED; #endif } CpaBoolean icp_sal_userIsQatAvailable(void) { return icp_adf_isDeviceAvailable(); } qatlib-25.08.0/quickassist/lookaside/access_layer/src/user/sal_user_congestion_mgmt.c000066400000000000000000000160601503624047500311270ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /* ***************************************************************************** * @file sal_user_congestion_mgmt.c * * @defgroup SalUserCongsMgmt * * @description * This file contains Congestion Management API implementations *****************************************************************************/ /* QAT-API includes */ #include "cpa.h" /* ADF includes */ #include "icp_adf_init.h" #include "icp_adf_transport.h" #include "icp_adf_transport_dp.h" /* SAL includes */ #include "icp_sal_congestion_mgmt.h" #include "lac_sal_types_crypto.h" #include "lac_sal.h" #include "sal_service_state.h" /* ***************************************************************************** * @ingroup SalCongsMgmt * Symmetric get in-flight requests * * @description * This function is used to fetch in-flight and max in-flight request * counts for the given symmetric instance handle. * * @param[in] instanceHandle Symmetric instance handle * @param[out] maxInflightRequests Max in-flight request count * @param[out] numInflightRequests Current in-flight request count * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed * @retval CPA_STATUS_INVALID_PARAM Invalid parameter * *****************************************************************************/ CpaStatus icp_sal_SymGetInflightRequests(CpaInstanceHandle instanceHandle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests) { sal_crypto_service_t *crypto_handle = NULL; crypto_handle = (sal_crypto_service_t *)instanceHandle; LAC_CHECK_NULL_PARAM(crypto_handle); LAC_CHECK_NULL_PARAM(maxInflightRequests); LAC_CHECK_NULL_PARAM(numInflightRequests); SAL_RUNNING_CHECK(crypto_handle); return icp_adf_getInflightRequests(crypto_handle->trans_handle_sym_tx, maxInflightRequests, numInflightRequests); } CpaStatus icp_sal_AsymGetInflightRequests(CpaInstanceHandle instanceHandle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests) { sal_crypto_service_t *crypto_handle = NULL; crypto_handle = (sal_crypto_service_t *)instanceHandle; LAC_CHECK_NULL_PARAM(crypto_handle); LAC_CHECK_NULL_PARAM(maxInflightRequests); LAC_CHECK_NULL_PARAM(numInflightRequests); SAL_RUNNING_CHECK(crypto_handle); return icp_adf_getInflightRequests(crypto_handle->trans_handle_asym_tx, maxInflightRequests, numInflightRequests); } /* ***************************************************************************** * @ingroup SalCongsMgmt * Symmetric data plane get in-flight requests * * @description * Data plane API to fetch in-flight and max in-flight request counts * for the given symmetric instance handle. * * @param[in] instanceHandle Symmetric instance handle * @param[out] maxInflightRequests Max in-flight request count * @param[out] numInflightRequests Current in-flight request count * * @retval CPA_STATUS_SUCCESS Function executed successfully * @retval CPA_STATUS_FAIL Function failed * @retval CPA_STATUS_INVALID_PARAM Invalid parameter * *****************************************************************************/ CpaStatus icp_sal_dp_SymGetInflightRequests(CpaInstanceHandle instanceHandle, Cpa32U *maxInflightRequests, Cpa32U *numInflightRequests) { sal_crypto_service_t *crypto_handle = NULL; crypto_handle = (sal_crypto_service_t *)instanceHandle; LAC_CHECK_NULL_PARAM(crypto_handle); LAC_CHECK_NULL_PARAM(maxInflightRequests); LAC_CHECK_NULL_PARAM(numInflightRequests); SAL_RUNNING_CHECK(crypto_handle); icp_adf_getDpInflightRequests(crypto_handle->trans_handle_sym_tx, maxInflightRequests, numInflightRequests); return CPA_STATUS_SUCCESS; } qatlib-25.08.0/quickassist/lookaside/access_layer/src/user/sal_user_dyn_instance.c000066400000000000000000000126351503624047500304150ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file sal_user_dyn_instance.c * * @defgroup SalUser * * @description * This file contains implementation of functions * to allocate/free dynamic crypto/compression instances * These APIs have been deprecated. * *****************************************************************************/ /* QAT-API includes */ #include "cpa.h" #ifndef ICP_DC_ONLY CpaStatus icp_sal_userCyGetAvailableNumDynInstances(Cpa32U *pNumCyInstances) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userCyGetAvailableNumDynInstancesByDevPkg( Cpa32U *pNumCyInstances, Cpa32U devPkgID) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userCyGetAvailableNumDynInstancesByPkgAccel( Cpa32U *pNumCyInstances, Cpa32U devPkgID, Cpa32U accelerator_number) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userCyInstancesAlloc(Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userCyInstancesAllocByDevPkg(Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances, Cpa32U devPkgID) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userCyFreeInstances(Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userCyInstancesAllocByPkgAccel( Cpa32U numCyInstances, CpaInstanceHandle *pCyInstances, Cpa32U devPkgID, Cpa32U accelerator_number) { return CPA_STATUS_UNSUPPORTED; } #endif CpaStatus icp_sal_userDcGetAvailableNumDynInstances(Cpa32U *pNumDcInstances) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userDcGetAvailableNumDynInstancesByDevPkg( Cpa32U *pNumDcInstances, Cpa32U devPkgID) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userDcInstancesAlloc(Cpa32U numDcInstances, CpaInstanceHandle *pDcInstances) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userDcInstancesAllocByDevPkg(Cpa32U numDcInstances, CpaInstanceHandle *pDcInstances, Cpa32U devPkgID) { return CPA_STATUS_UNSUPPORTED; } CpaStatus icp_sal_userDcFreeInstances(Cpa32U numDcInstances, CpaInstanceHandle *pDcInstances) { return CPA_STATUS_UNSUPPORTED; } qatlib-25.08.0/quickassist/lookaside/firmware/000077500000000000000000000000001503624047500213015ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/firmware/include/000077500000000000000000000000001503624047500227245ustar00rootroot00000000000000qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw.h000066400000000000000000001603661503624047500252250ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** ***************************************************************************** * @file icp_qat_fw.h * @defgroup icp_qat_fw_comn ICP QAT FW Common Processing Definitions * @ingroup icp_qat_fw * * @description * This file documents the common interfaces that the QAT FW running on * the QAT AE exports. This common layer is used by a number of services * to export content processing services. * *****************************************************************************/ #ifndef _ICP_QAT_FW_H_ #define _ICP_QAT_FW_H_ /* * ============================== * General Notes on the Interface */ /* * * ============================== * * Introduction * * Data movement and slice chaining * * Endianness * - Unless otherwise stated, all structures are defined in LITTLE ENDIAN * MODE * * Alignment * - In general all data structures provided to a request should be aligned * on the 64 byte boundary so as to allow optimal memory transfers. At the * minimum they must be aligned to the 8 byte boundary * * Sizes * Quad words = 8 bytes * * Terminology * * ============================== */ /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ #include "icp_qat_hw.h" /* Big assumptions that both bitpos and mask are constants */ #define QAT_FIELD_SET(flags, val, bitpos, mask) \ (flags) = \ (((flags) & (~((mask) << (bitpos)))) | (((val) & (mask)) << (bitpos))) #define QAT_FIELD_GET(flags, bitpos, mask) (((flags) >> (bitpos)) & (mask)) #define QAT_FLAG_SET(flags, bitpos) (flags) = ((flags) | (1 << (bitpos))) #define QAT_FLAG_CLEAR(flags, bitpos) (flags) = ((flags) & (~(1 << (bitpos)))) #define QAT_FLAG_GET(flags, bitpos) (((flags) >> (bitpos)) & 1) /**< @ingroup icp_qat_fw_comn * Default request and response ring size in bytes */ #define ICP_QAT_FW_REQ_DEFAULT_SZ 128 #define ICP_QAT_FW_RESP_DEFAULT_SZ 32 #define ICP_QAT_FW_COMN_ONE_BYTE_SHIFT 8 #define ICP_QAT_FW_COMN_SINGLE_BYTE_MASK 0xFF /**< @ingroup icp_qat_fw_comn * Common Request - Block sizes definitions in multiples of individual long * words */ #define ICP_QAT_FW_NUM_LONGWORDS_1 1 #define ICP_QAT_FW_NUM_LONGWORDS_2 2 #define ICP_QAT_FW_NUM_LONGWORDS_3 3 #define ICP_QAT_FW_NUM_LONGWORDS_4 4 #define ICP_QAT_FW_NUM_LONGWORDS_5 5 #define ICP_QAT_FW_NUM_LONGWORDS_6 6 #define ICP_QAT_FW_NUM_LONGWORDS_7 7 #define ICP_QAT_FW_NUM_LONGWORDS_10 10 #define ICP_QAT_FW_NUM_LONGWORDS_13 13 /**< @ingroup icp_qat_fw_comn * Definition of the associated service Id for NULL service type. * Note: the response is expected to use ICP_QAT_FW_COMN_RESP_SERV_CPM_FW */ #define ICP_QAT_FW_NULL_REQ_SERV_ID 1 /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the firmware interface service users, for * responses. * @description * Enumeration which is used to indicate the ids of the services * for responses using the external firmware interfaces. * *****************************************************************************/ typedef enum { ICP_QAT_FW_COMN_RESP_SERV_NULL, /**< NULL service id type */ ICP_QAT_FW_COMN_RESP_SERV_CPM_FW, /**< CPM FW Service ID */ ICP_QAT_FW_COMN_RESP_SERV_DELIMITER /**< Delimiter service id type */ } icp_qat_fw_comn_resp_serv_id_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the request types * @description * Enumeration which is used to indicate the ids of the request * types used in each of the external firmware interfaces * *****************************************************************************/ typedef enum { ICP_QAT_FW_COMN_REQ_NULL = 0, /**< NULL request type */ ICP_QAT_FW_COMN_REQ_CPM_FW_PKE = 3, /**< CPM FW PKE Request */ ICP_QAT_FW_COMN_REQ_CPM_FW_LA = 4, /**< CPM FW Lookaside Request */ ICP_QAT_FW_COMN_REQ_CPM_FW_DMA = 7, /**< CPM FW DMA Request */ ICP_QAT_FW_COMN_REQ_CPM_FW_COMP = 9, /**< CPM FW Compression Request */ ICP_QAT_FW_COMN_REQ_CPM_FW_COMP_CHAIN = 0xB, /**< CPM FW dc_chain Request */ ICP_QAT_FW_COMN_REQ_DELIMITER /**< End delimiter */ } icp_qat_fw_comn_request_id_t; /* ========================================================================= */ /* QAT FW REQUEST STRUCTURES */ /* ========================================================================= */ /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Common request flags type * * @description * Definition of the common request flags. * *****************************************************************************/ typedef uint8_t icp_qat_fw_comn_flags; /** ***************************************************************************** * @ingroup icp_qat_fw_comn_pke * Common request flags type for PKE * * @description * Definition of the common request flags. * *****************************************************************************/ typedef uint16_t icp_qat_fw_comn_flags_pke; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Common request - Service specific flags type * * @description * Definition of the common request service specific flags. * *****************************************************************************/ typedef uint16_t icp_qat_fw_serv_specif_flags; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Common request - Extended service specific flags type * * @description * Definition of the common request extended service specific flags. * *****************************************************************************/ typedef uint8_t icp_qat_fw_ext_serv_specif_flags; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common QAT FW request content descriptor field - * points to the content descriptor parameters or itself contains service- * specific data. Also specifies content descriptor parameter size. * Contains reserved fields. * @description * Common section of the request used across all of the services exposed * by the QAT FW. Each of the services inherit these common fields * *****************************************************************************/ typedef union icp_qat_fw_comn_req_hdr_cd_pars_s { /**< LWs 2-5 */ struct { uint64_t content_desc_addr; /**< Address of the content descriptor */ uint16_t content_desc_resrvd1; /**< Content descriptor reserved field */ uint8_t content_desc_params_sz; /**< Size of the content descriptor parameters in quad words. These * parameters describe the session setup configuration info for the * slices that this request relies upon i.e. the configuration word and * cipher key needed by the cipher slice if there is a request for * cipher processing. */ uint8_t content_desc_hdr_resrvd2; /**< Content descriptor reserved field */ uint32_t content_desc_resrvd3; /**< Content descriptor reserved field */ } s; struct { uint32_t serv_specif_fields[ICP_QAT_FW_NUM_LONGWORDS_4]; } s1; } icp_qat_fw_comn_req_hdr_cd_pars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common QAT FW request middle block. * @description * Common section of the request used across all of the services exposed * by the QAT FW. Each of the services inherit these common fields * *****************************************************************************/ typedef struct icp_qat_fw_comn_req_mid_s { /**< LWs 6-13 */ uint64_t opaque_data; /**< Opaque data passed unmodified from the request to response messages by * firmware (fw) */ uint64_t src_data_addr; /**< Generic definition of the source data supplied to the QAT AE. The * common flags are used to further describe the attributes of this * field */ uint64_t dest_data_addr; /**< Generic definition of the destination data supplied to the QAT AE. The * common flags are used to further describe the attributes of this * field */ uint32_t src_length; /** < Length of source flat buffer in case src buffer * type is flat */ uint32_t dst_length; /** < Length of source flat buffer in case dst buffer * type is flat */ } icp_qat_fw_comn_req_mid_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common QAT FW request content descriptor control * block. * * @description * Service specific section of the request used across all of the services * exposed by the QAT FW. Each of the services populates this block * uniquely. Refer to the service-specific header structures e.g. * 'icp_qat_fw_cipher_hdr_s' (for Cipher) etc. * *****************************************************************************/ typedef struct icp_qat_fw_comn_req_cd_ctrl_s { /**< LWs 27-31 */ uint32_t content_desc_ctrl_lw[ICP_QAT_FW_NUM_LONGWORDS_5]; } icp_qat_fw_comn_req_cd_ctrl_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common QAT FW request header. * @description * Common section of the request used across all of the services exposed * by the QAT FW. Each of the services inherit these common fields. The * reserved field of 7 bits and the service command Id field are all * service-specific fields, along with the service specific flags. * *****************************************************************************/ typedef struct icp_qat_fw_comn_req_hdr_s { /**< LW0 */ uint8_t resrvd1; /**< reserved field */ uint8_t service_cmd_id; /**< Service Command Id - this field is service-specific * Please use service-specific command Id here e.g.Crypto Command Id * or Compression Command Id etc. */ uint8_t service_type; /**< Service type */ uint8_t hdr_flags; /**< This represents a flags field for the Service Request. * The most significant bit is the 'valid' flag and the only * one used. All remaining bit positions are unused and * are therefore reserved and need to be set to 0. */ /**< LW1 */ icp_qat_fw_serv_specif_flags serv_specif_flags; /**< Common Request service-specific flags * e.g. Symmetric Crypto Command Flags */ icp_qat_fw_comn_flags comn_req_flags; /**< Common Request Flags consisting of * - 6 reserved bits, * - 1 Content Descriptor field type bit and * - 1 Source/destination pointer type bit */ icp_qat_fw_ext_serv_specif_flags extended_serv_specif_flags; /**< An extension of serv_specif_flags */ } icp_qat_fw_comn_req_hdr_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common QAT FW request parameter field. * * @description * Service specific section of the request used across all of the services * exposed by the QAT FW. Each of the services populates this block * uniquely. Refer to service-specific header structures e.g. * 'icp_qat_fw_comn_req_cipher_rqpars_s' (for Cipher) etc. * *****************************************************************************/ typedef struct icp_qat_fw_comn_req_rqpars_s { /**< LWs 14-26 */ uint32_t serv_specif_rqpars_lw[ICP_QAT_FW_NUM_LONGWORDS_13]; } icp_qat_fw_comn_req_rqpars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common request structure with service specific * fields * @description * This is a definition of the full qat request structure used by all * services. Each service is free to use the service fields in its own * way. This struct is useful as a message passing argument before the * service contained within the request is determined. * *****************************************************************************/ typedef struct icp_qat_fw_comn_req_s { /**< LWs 0-1 */ icp_qat_fw_comn_req_hdr_t comn_hdr; /**< Common request header */ /**< LWs 2-5 */ icp_qat_fw_comn_req_hdr_cd_pars_t cd_pars; /**< Common Request content descriptor field which points either to a * content descriptor * parameter block or contains the service-specific data itself. */ /**< LWs 6-13 */ icp_qat_fw_comn_req_mid_t comn_mid; /**< Common request middle section */ /**< LWs 14-26 */ icp_qat_fw_comn_req_rqpars_t serv_specif_rqpars; /**< Common request service-specific parameter field */ /**< LWs 27-31 */ icp_qat_fw_comn_req_cd_ctrl_t cd_ctrl; /**< Common request content descriptor control block - * this field is service-specific */ } icp_qat_fw_comn_req_t; /* ========================================================================= */ /* QAT FW RESPONSE STRUCTURES */ /* ========================================================================= */ /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Error code field * * @description * Overloaded field with 8 bit common error field or two * 8 bit compression error fields for compression and translator slices * *****************************************************************************/ typedef union icp_qat_fw_comn_error_s { struct { uint8_t resrvd; /**< 8 bit reserved field */ uint8_t comn_err_code; /**< 8 bit common error code */ } s; /**< Structure which is used for non-compression responses */ struct { uint8_t xlat_err_code; /**< 8 bit translator error field */ uint8_t cmp_err_code; /**< 8 bit compression error field */ } s1; /** Structure which is used for compression responses */ } icp_qat_fw_comn_error_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common QAT FW response header. * @description * This section of the response is common across all of the services * that generate a firmware interface response * *****************************************************************************/ typedef struct icp_qat_fw_comn_resp_hdr_s { /**< LW0 */ uint8_t resrvd1; /**< Reserved field - this field is service-specific - * Note: The Response Destination Id has been removed * from first QWord */ uint8_t service_id; /**< Service Id returned by service block */ uint8_t response_type; /**< Response type - copied from the request to * the response message */ uint8_t hdr_flags; /**< This represents a flags field for the Response. * Bit<7> = 'valid' flag * Bit<6> = 'CNV' flag indicating that CNV was executed * on the current request * Bit<5> = 'CNVNR' flag indicating that a recovery happened * on the current request following a CNV error * Bit<4> = 'Stored Block' flag indicating that whether * stored blocks are returned (when ASB is on). * All remaining bits are unused and are therefore reserved. * They must to be set to 0. */ /**< LW 1 */ icp_qat_fw_comn_error_t comn_error; /**< This field is overloaded to allow for one 8 bit common error field * or two 8 bit error fields from compression and translator */ uint8_t comn_status; /**< Status field which specifies which slice(s) report an error */ uint8_t cmd_id; /**< Command Id - passed from the request to the response message */ } icp_qat_fw_comn_resp_hdr_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Definition of the common response structure with service specific * fields * @description * This is a definition of the full qat response structure used by all * services. * *****************************************************************************/ typedef struct icp_qat_fw_comn_resp_s { /**< LWs 0-1 */ icp_qat_fw_comn_resp_hdr_t comn_hdr; /**< Common header fields */ /**< LWs 2-3 */ uint64_t opaque_data; /**< Opaque data passed from the request to the response message */ /**< LWs 4-7 */ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4]; /**< Reserved */ } icp_qat_fw_comn_resp_t; /* ========================================================================= */ /* MACRO DEFINITIONS */ /* ========================================================================= */ /* Common QAT FW request header - structure of LW0 * + ===== + ---- + ----------- + ----------- + ----------- + ----------- + * | Bit | 31 | 30 - 24 | 21 - 16 | 15 - 8 | 7 - 0 | * + ===== + ---- + ----------- + ----------- + ----------- + ----------- + * | Flags | V | Reserved | Serv Type | Serv Cmd Id | Reserved | * + ===== + ---- + ----------- + ----------- + ----------- + ----------- + */ /**< @ingroup icp_qat_fw_comn * Definition of the setting of the header's valid flag */ #define ICP_QAT_FW_COMN_REQ_FLAG_SET 1 /**< @ingroup icp_qat_fw_comn * Definition of the setting of the header's valid flag */ #define ICP_QAT_FW_COMN_REQ_FLAG_CLR 0 /**< @ingroup icp_qat_fw_comn * Macros defining the bit position and mask of the 'valid' flag, within the * hdr_flags field of LW0 (service request and response) */ #define ICP_QAT_FW_COMN_VALID_FLAG_BITPOS 7 #define ICP_QAT_FW_COMN_VALID_FLAG_MASK 0x1 #define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK 0x3F /*Common QAT FW response header - structure of LW0 *+ ===== + -- + --- + ----- + ----- + ---- + --------- + ----------- +------+ *| Bit | 31 | 30 | 29 | 28 | 27-24| 21 - 16 | 15 - 8 | 7-0 | *+ ===== + -- + --- + ----- + ----- + ---- + --------- + ----------- + -----+ *| Flags | V | CNV | CNVNR |Stored | Rsvd | Serv Type | Serv Cmd Id | Rsvd | *| | | | | block | | | | | *+ ===== + -- + --- + ----- + ----- + ---- + --------- + ----------- +------+ */ /**< @ingroup icp_qat_fw_comn * Macros defining the bit position and mask of 'CNV' flag * within the hdr_flags field of LW0 (service response only) */ #define ICP_QAT_FW_COMN_CNV_FLAG_BITPOS 6 #define ICP_QAT_FW_COMN_CNV_FLAG_MASK 0x1 /**< @ingroup icp_qat_fw_comn * Macros defining the bit position and mask of CNVNR flag * within the hdr_flags field of LW0 (service response only) */ #define ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS 5 #define ICP_QAT_FW_COMN_CNVNR_FLAG_MASK 0x1 /**< @ingroup icp_qat_fw_comn * Macros defining the bit position and mask of Stored Blocks flag * within the hdr_flags field of LW0 (service response only) */ #define ICP_QAT_FW_COMN_ST_BLK_FLAG_BITPOS 4 #define ICP_QAT_FW_COMN_ST_BLK_FLAG_MASK 0x1 /**< @ingroup icp_qat_fw_comn * Macros defining the bit position and mask of E2E_DCPR flag * within the hdr_flags field of LW0 (service response only) */ #define ICP_QAT_FW_COMN_E2E_DCPR_FLAG_BITPOS 3 #define ICP_QAT_FW_COMN_E2E_DCPR_FLAG_MASK 0x1 /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of Service Type Field * * @param icp_qat_fw_comn_req_hdr_t Structure 'icp_qat_fw_comn_req_hdr_t' * to extract the Service Type Field * *****************************************************************************/ #define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \ icp_qat_fw_comn_req_hdr_t.service_type /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for setting of Service Type Field * * @param 'icp_qat_fw_comn_req_hdr_t' structure to set the Service * Type Field * @param val Value of the Service Type Field * *****************************************************************************/ #define ICP_QAT_FW_COMN_OV_SRV_TYPE_SET(icp_qat_fw_comn_req_hdr_t, val) \ icp_qat_fw_comn_req_hdr_t.service_type = val /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of Service Command Id Field * * @param icp_qat_fw_comn_req_hdr_t Structure 'icp_qat_fw_comn_req_hdr_t' * to extract the Service Command Id Field * *****************************************************************************/ #define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_GET(icp_qat_fw_comn_req_hdr_t) \ icp_qat_fw_comn_req_hdr_t.service_cmd_id /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for setting of Service Command Id Field * * @param 'icp_qat_fw_comn_req_hdr_t' structure to set the * Service Command Id Field * @param val Value of the Service Command Id Field * *****************************************************************************/ #define ICP_QAT_FW_COMN_OV_SRV_CMD_ID_SET(icp_qat_fw_comn_req_hdr_t, val) \ icp_qat_fw_comn_req_hdr_t.service_cmd_id = val /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Extract the valid flag from the request or response's header flags. * * @param hdr_t Request or Response 'hdr_t' structure to extract the valid bit * from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_VALID_FLAG_GET(hdr_t) \ ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_t.hdr_flags) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Extract the CNVNR flag from the header flags in the response only. * * @param hdr_t Response 'hdr_t' structure to extract the CNVNR bit * from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdr_flags) \ QAT_FIELD_GET(hdr_flags, \ ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS, \ ICP_QAT_FW_COMN_CNVNR_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Set the CNVNR bit in the response's header flags. * * @param hdr_t Response 'hdr_t' structure to set the CNVNR bit * @param val Value of the CNVNR bit flag. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_SET(hdr_t, val) \ QAT_FIELD_SET((hdr_t.hdr_flags), \ (val), \ ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS, \ ICP_QAT_FW_COMN_CNVNR_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Extract the CNV flag from the header flags in the response only. * * @param hdr_t Response 'hdr_t' structure to extract the CNV bit * from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdr_flags) \ QAT_FIELD_GET(hdr_flags, \ ICP_QAT_FW_COMN_CNV_FLAG_BITPOS, \ ICP_QAT_FW_COMN_CNV_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Extract the E2E_DCPR flag from the header flags in the response only. * * @param hdr_t Response 'hdr_t' structure to extract the E2E_DCPR bit * from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_E2E_DCPR_FLAG_GET(hdr_flags) \ QAT_FIELD_GET(hdr_flags, \ ICP_QAT_FW_COMN_E2E_DCPR_FLAG_BITPOS, \ ICP_QAT_FW_COMN_E2E_DCPR_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Set the valid bit in the request's header flags. * * @param hdr_t Request or Response 'hdr_t' structure to set the valid bit * @param val Value of the valid bit flag. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_VALID_FLAG_SET(hdr_t, val) \ ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Extract the Stored Block flag from the header flags in the * response only. * * @param hdr_flags Response 'hdr' structure to extract the * Stored Block bit from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_ST_BLK_FLAG_GET(hdr_flags) \ QAT_FIELD_GET(hdr_flags, \ ICP_QAT_FW_COMN_ST_BLK_FLAG_BITPOS, \ ICP_QAT_FW_COMN_ST_BLK_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Set the Stored Block bit in the response's header flags. * * @param hdr_t Response 'hdr_t' structure to set the ST_BLK bit * @param val Value of the ST_BLK bit flag. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_ST_BLK_FLAG_SET(hdr_t, val) \ QAT_FIELD_SET((hdr_t.hdr_flags), \ (val), \ ICP_QAT_FW_COMN_ST_BLK_FLAG_BITPOS, \ ICP_QAT_FW_COMN_ST_BLK_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Common macro to extract the valid flag from the header flags field * within the header structure (request or response). * * @param hdr_t Structure (request or response) to extract the * valid bit from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_COMN_VALID_FLAG_GET(hdr_flags) \ QAT_FIELD_GET(hdr_flags, \ ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \ ICP_QAT_FW_COMN_VALID_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Common macro to extract the remaining reserved flags from the header flags field within the header structure (request or response). * * @param hdr_t Structure (request or response) to extract the * remaining bits from the 'hdr_flags' field (excluding the * valid flag). * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_GET(hdr_flags) \ ((hdr_flags)&ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Common macro to set the reserved bits of the header * flags field within the header structure (request or response). * * @param hdr_flags Response 'hdr' structure to extract the * Stored Block Returned bit from the 'hdr_flags' field. * @param val Value of the reserved bits * *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_RESRVD_FLD_SET(hdr_flags, val) \ (hdr_flags) = \ (((hdr_flags) & ~(ICP_QAT_FW_COMN_HDR_RESRVD_FLD_MASK)) | (val)) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Common macro to set the valid bit in the header flags field within * the header structure (request or response). * * @param hdr_t Structure (request or response) containing the header * flags field, to allow the valid bit to be set. * @param val Value of the valid bit flag. * *****************************************************************************/ #define ICP_QAT_FW_COMN_VALID_FLAG_SET(hdr_t, val) \ QAT_FIELD_SET((hdr_t.hdr_flags), \ (val), \ ICP_QAT_FW_COMN_VALID_FLAG_BITPOS, \ ICP_QAT_FW_COMN_VALID_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro that must be used when building the common header flags. * Note that all bits reserved field bits 0-6 (LW0) need to be forced to 0. * * @param ptr Value of the valid flag *****************************************************************************/ #define ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(valid) \ (((valid)&ICP_QAT_FW_COMN_VALID_FLAG_MASK) \ << ICP_QAT_FW_COMN_VALID_FLAG_BITPOS) /* * < @ingroup icp_qat_fw_comn * Common Request Flags Definition * The bit offsets below are within the flags field. These are NOT relative to * the memory word. Unused fields e.g. reserved bits, must be zeroed. * * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + * | Bits [15:8] | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + * | Flags[15:8] | Rsv | Rsv | Rsv | Rsv | Rsv | Rsv | Rsv | Rsv | * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + * | Bits [7:0] | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + * | Flags [7:0] | Rsv | Rsv | Rsv | Rsv | Rsv | Rsv | Cdt | Ptr | * + ===== + ------ + --- + --- + --- + --- + --- + --- + --- + --- + */ #define QAT_COMN_PTR_TYPE_BITPOS 0 /**< @ingroup icp_qat_fw_comn * Common Request Flags - Starting bit position indicating * Src&Dst Buffer Pointer type */ #define QAT_COMN_PTR_TYPE_MASK 0x1 /**< @ingroup icp_qat_fw_comn * Common Request Flags - One bit mask used to determine * Src&Dst Buffer Pointer type */ #define QAT_COMN_CD_FLD_TYPE_BITPOS 1 /**< @ingroup icp_qat_fw_comn * Common Request Flags - Starting bit position indicating * CD Field type */ #define QAT_COMN_CD_FLD_TYPE_MASK 0x1 /**< @ingroup icp_qat_fw_comn * Common Request Flags - One bit mask used to determine * CD Field type */ /* ========================================================================= */ /* Pointer Type Flag definitions */ /* ========================================================================= */ #define QAT_COMN_PTR_TYPE_FLAT 0x0 /**< @ingroup icp_qat_fw_comn * Constant value indicating Src&Dst Buffer Pointer type is flat * If Batch and Pack mode is enabled, only applies to Destination buffer.*/ #define QAT_COMN_PTR_TYPE_SGL 0x1 /**< @ingroup icp_qat_fw_comn * Constant value indicating Src&Dst Buffer Pointer type is SGL type * If Batch and Pack mode is enabled, only applies to Destination buffer.*/ #define QAT_COMN_PTR_TYPE_BATCH 0x2 /**< @ingroup icp_qat_fw_comn * Constant value indicating Src is a batch request * and Dst Buffer Pointer type is SGL type */ /* ========================================================================= */ /* CD Field Flag definitions */ /* ========================================================================= */ #define QAT_COMN_CD_FLD_TYPE_64BIT_ADR 0x0 /**< @ingroup icp_qat_fw_comn * Constant value indicating CD Field contains 64-bit address */ #define QAT_COMN_CD_FLD_TYPE_16BYTE_DATA 0x1 /**< @ingroup icp_qat_fw_comn * Constant value indicating CD Field contains 16 bytes of setup data */ /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro that must be used when building the common request flags. * Note that all bits reserved field bits 2-15 (LW1) need to be forced to 0. * * @param ptr Value of the pointer type flag * @param cdt Value of the cd field type flag *****************************************************************************/ #define ICP_QAT_FW_COMN_FLAGS_BUILD(cdt, ptr) \ ((((cdt)&QAT_COMN_CD_FLD_TYPE_MASK) << QAT_COMN_CD_FLD_TYPE_BITPOS) | \ (((ptr)&QAT_COMN_PTR_TYPE_MASK) << QAT_COMN_PTR_TYPE_BITPOS)) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the pointer type bit from the common flags * * @param flags Flags to extract the pointer type bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_PTR_TYPE_GET(flags) \ QAT_FIELD_GET(flags, QAT_COMN_PTR_TYPE_BITPOS, QAT_COMN_PTR_TYPE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the cd field type bit from the common flags * * @param flags Flags to extract the cd field type type bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_CD_FLD_TYPE_GET(flags) \ QAT_FIELD_GET(flags, QAT_COMN_CD_FLD_TYPE_BITPOS, QAT_COMN_CD_FLD_TYPE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for setting the pointer type bit in the common flags * * @param flags Flags in which Pointer Type bit will be set * @param val Value of the bit to be set in flags * *****************************************************************************/ #define ICP_QAT_FW_COMN_PTR_TYPE_SET(flags, val) \ QAT_FIELD_SET(flags, val, QAT_COMN_PTR_TYPE_BITPOS, QAT_COMN_PTR_TYPE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for setting the cd field type bit in the common flags * * @param flags Flags in which Cd Field Type bit will be set * @param val Value of the bit to be set in flags * *****************************************************************************/ #define ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_COMN_CD_FLD_TYPE_BITPOS, QAT_COMN_CD_FLD_TYPE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macros using the bit position and mask to set/extract the next * and current id nibbles within the next_curr_id field of the * content descriptor header block. Note that these are defined * in the common header file, as they are used by compression, cipher * and authentication. * * @param cd_ctrl_hdr_t Content descriptor control block header pointer. * @param val Value of the field being set. * *****************************************************************************/ #define ICP_QAT_FW_COMN_NEXT_ID_BITPOS 4 #define ICP_QAT_FW_COMN_NEXT_ID_MASK 0xF0 #define ICP_QAT_FW_COMN_CURR_ID_BITPOS 0 #define ICP_QAT_FW_COMN_CURR_ID_MASK 0x0F #define ICP_QAT_FW_COMN_NEXT_ID_GET(cd_ctrl_hdr_t) \ ((((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_NEXT_ID_MASK) >> \ (ICP_QAT_FW_COMN_NEXT_ID_BITPOS)) #define ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl_hdr_t, val) \ ((cd_ctrl_hdr_t)->next_curr_id) = \ ((((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_CURR_ID_MASK) | \ ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) & \ ICP_QAT_FW_COMN_NEXT_ID_MASK)) #define ICP_QAT_FW_COMN_CURR_ID_GET(cd_ctrl_hdr_t) \ (((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_CURR_ID_MASK) #define ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl_hdr_t, val) \ ((cd_ctrl_hdr_t)->next_curr_id) = \ ((((cd_ctrl_hdr_t)->next_curr_id) & ICP_QAT_FW_COMN_NEXT_ID_MASK) | \ ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK)) /* * < @ingroup icp_qat_fw_comn * Common Status Field Definition The bit offsets below are within the COMMON * RESPONSE status field, assumed to be 8 bits wide. In the case of the PKE * response (which follows the CPM 1.5 message format), the status field is 16 * bits wide. * The status flags are contained within the most significant byte and align * with the diagram below. Please therefore refer to the service-specific PKE * header file for the appropriate macro definition to extract the PKE status * flag from the PKE response, which assumes that a word is passed to the * macro. * + ===== + ------ + --- + --- + ---- + ---- + -------- + ---- + ---------- + * | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * + ===== + ------ + --- + --- + ---- + ---- + -------- + ---- + ---------- + * | Flags | Crypto | Pke | Cmp | Xlat | EOLB | UnSupReq | Rsvd | XltWaApply | * + ===== + ------ + --- + --- + ---- + ---- + -------- + ---- + ---------- + * Note: * For the service specific status bit definitions refer to service header files * Eg. Crypto Status bit refers to Symmetric Crypto, Key Generation, and NRBG * Requests' Status. Unused bits e.g. reserved bits need to have been forced to * 0. */ #define QAT_COMN_RESP_CRYPTO_STATUS_BITPOS 7 /**< @ingroup icp_qat_fw_comn * Starting bit position indicating Response for Crypto service Flag */ #define QAT_COMN_RESP_CRYPTO_STATUS_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask used to determine Crypto status mask */ #define QAT_COMN_RESP_PKE_STATUS_BITPOS 6 /**< @ingroup icp_qat_fw_comn * Starting bit position indicating Response for PKE service Flag */ #define QAT_COMN_RESP_PKE_STATUS_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask used to determine PKE status mask */ #define QAT_COMN_RESP_CMP_STATUS_BITPOS 5 /**< @ingroup icp_qat_fw_comn * Starting bit position indicating Response for Compression service Flag */ #define QAT_COMN_RESP_CMP_STATUS_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask used to determine Compression status mask */ #define QAT_COMN_RESP_XLAT_STATUS_BITPOS 4 /**< @ingroup icp_qat_fw_comn * Starting bit position indicating Response for Xlat service Flag */ #define QAT_COMN_RESP_XLAT_STATUS_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask used to determine Translator status mask */ #define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS 3 /**< @ingroup icp_qat_fw_comn * Starting bit position indicating the last block in a deflate stream for the compression service Flag */ #define QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask used to determine the last block in a deflate stream status mask */ #define QAT_COMN_RESP_UNSUPPORTED_REQUEST_BITPOS 2 /**< @ingroup icp_qat_fw_comn * Starting bit position indicating when an unsupported service request Flag */ #define QAT_COMN_RESP_UNSUPPORTED_REQUEST_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask used to determine the unsupported service request status mask */ #define QAT_COMN_RESP_INVALID_PARAMETER_BITPOS 1 /**< @ingroup icp_qat_fw_comn * Starting bit position indicating invalid parameter of the request */ #define QAT_COMN_RESP_INVALID_PARAMETER_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask used to determine the setting of invalid parameter flag */ #define QAT_COMN_RESP_XLT_APPLIED_BITPOS 0 /**< @ingroup icp_qat_fw_comn * Bit position indicating that firmware applied a weight adjustment to * the translation frequency counters */ #define QAT_COMN_RESP_XLT_APPLIED_MASK 0x1 /**< @ingroup icp_qat_fw_comn * One bit mask */ /** ****************************************************************************** * @description * Macro that must be used when building the status * for the common response * * @param crypto Value of the Crypto Service status flag * @param comp Value of the Compression Service Status flag * @param xlat Value of the Xlator Status flag * @param eolb Value of the Compression End of Last Block Status flag * @param unsupp Value of the Unsupported Request flag * @param xlt Value of the Translation marker flag *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_STATUS_BUILD( \ crypto, pke, comp, xlat, eolb, unsupp, xlt) \ ((((crypto)&QAT_COMN_RESP_CRYPTO_STATUS_MASK) \ << QAT_COMN_RESP_CRYPTO_STATUS_BITPOS) | \ (((pke)&QAT_COMN_RESP_PKE_STATUS_MASK) \ << QAT_COMN_RESP_PKE_STATUS_BITPOS) | \ (((xlt)&QAT_COMN_RESP_XLT_APPLIED_MASK) \ << QAT_COMN_RESP_XLT_APPLIED_BITPOS) | \ (((comp)&QAT_COMN_RESP_CMP_STATUS_MASK) \ << QAT_COMN_RESP_CMP_STATUS_BITPOS) | \ (((xlat)&QAT_COMN_RESP_XLAT_STATUS_MASK) \ << QAT_COMN_RESP_XLAT_STATUS_BITPOS) | \ (((eolb)&QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) \ << QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS) | \ (((unsupp)&QAT_COMN_RESP_UNSUPPORTED_REQUEST_MASK) \ << QAT_COMN_RESP_UNSUPPORTED_REQUEST_BITPOS)) /* ========================================================================= */ /* GETTERS */ /* ========================================================================= */ /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the Crypto bit from the status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_CRYPTO_STATUS_BITPOS, \ QAT_COMN_RESP_CRYPTO_STATUS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the PKE bit from the status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_PKE_STAT_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_PKE_STATUS_BITPOS, \ QAT_COMN_RESP_PKE_STATUS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the Compression bit from the status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_CMP_STATUS_BITPOS, \ QAT_COMN_RESP_CMP_STATUS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the Translator bit from the status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_XLAT_STATUS_BITPOS, \ QAT_COMN_RESP_XLAT_STATUS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the translation Weight Adjustment Applied bit * from the status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_XLT_APPLIED_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_XLT_APPLIED_BITPOS, \ QAT_COMN_RESP_XLT_APPLIED_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the end of compression block bit from the * status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_CMP_END_OF_LAST_BLK_BITPOS, \ QAT_COMN_RESP_CMP_END_OF_LAST_BLK_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the Unsupported request from the status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_UNSUPPORTED_REQUEST_BITPOS, \ QAT_COMN_RESP_UNSUPPORTED_REQUEST_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Macro for extraction of the Invalid Parameter flag from the status * * @param status * Status to extract the status bit from * *****************************************************************************/ #define ICP_QAT_FW_COMN_RESP_INVALID_PARAMETER_GET(status) \ QAT_FIELD_GET(status, \ QAT_COMN_RESP_INVALID_PARAMETER_BITPOS, \ QAT_COMN_RESP_INVALID_PARAMETER_MASK) /* ========================================================================= */ /* Status Flag definitions */ /* ========================================================================= */ #define ICP_QAT_FW_COMN_STATUS_FLAG_OK 0 /**< @ingroup icp_qat_fw_comn * Definition of successful processing of a request */ #define ICP_QAT_FW_COMN_STATUS_FLAG_ERROR 1 /**< @ingroup icp_qat_fw_comn * Definition of erroneous processing of a request */ #define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_CLR 0 /**< @ingroup icp_qat_fw_comn * Final Deflate block of a compression request not completed */ #define ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET 1 /**< @ingroup icp_qat_fw_comn * Final Deflate block of a compression request completed */ #define ERR_CODE_NO_ERROR 0 /**< Error Code constant value for no error */ #define ERR_CODE_INVALID_BLOCK_TYPE -1 /**< Invalid block type (type == 3)*/ #define ERR_CODE_NO_MATCH_ONES_COMP -2 /**< Stored block length does not match one's complement */ #define ERR_CODE_TOO_MANY_LEN_OR_DIS -3 /**< Too many length or distance codes */ #define ERR_CODE_INCOMPLETE_LEN -4 /**< Code lengths codes incomplete */ #define ERR_CODE_RPT_LEN_NO_FIRST_LEN -5 /**< Repeat lengths with no first length */ #define ERR_CODE_RPT_GT_SPEC_LEN -6 /**< Repeat more than specified lengths */ #define ERR_CODE_INV_LIT_LEN_CODE_LEN -7 /**< Invalid lit/len code lengths */ #define ERR_CODE_INV_DIS_CODE_LEN -8 /**< Invalid distance code lengths */ #define ERR_CODE_INV_LIT_LEN_DIS_IN_BLK -9 /**< Invalid lit/len or distance code in fixed/dynamic block */ #define ERR_CODE_DIS_TOO_FAR_BACK -10 /**< Distance too far back in fixed or dynamic block */ /**< Common Error code definitions */ #define ERR_CODE_OVERFLOW_ERROR -11 /**< Error Code constant value for overflow error */ #define ERR_CODE_SOFT_ERROR -12 /**< Error Code constant value for soft error */ #define ERR_CODE_FATAL_ERROR -13 /**< Error Code constant value for hard/fatal error */ #define ERR_CODE_COMP_OUTPUT_CORRUPTION -14 /**< Error Code constant for compression output corruption */ #define ERR_CODE_HW_INCOMPLETE_FILE -15 /**< Error Code constant value for incomplete file hardware error */ #define ERR_CODE_SSM_ERROR -16 /**< Error Code constant value for error detected by SSM e.g. slice hang */ #define ERR_CODE_ENDPOINT_ERROR -17 /**< Error Code constant value for error detected by PCIe Endpoint, e.g. push * data error */ #define ERR_CODE_CNV_ERROR -18 /**< Error Code constant value for cnv failure */ #define ERR_CODE_EMPTY_DYM_BLOCK -19 /**< Error Code constant value for submission of empty dynamic stored block to * slice */ #define ERR_CODE_DICT_OVERFLOW -22 /**< Error returned when compressed dictionary is inflated to more than 32KB */ #define ERR_CODE_DICT_DECOMP_ERR -23 /**< Error returned when compressed dictionary cannot be inflated due to soft * error */ #define ERR_CODE_SSM_PARITY_ERROR -27 /**< Error Code constant value for error detected by SSM errors in the absence * of a WDT expiry */ #define ERR_CODE_DICT_DECOMP_BUFF_CONSTR_ERROR -28 /**< Error returned when decomp dict buffer with non-16B aligned address or * non-16B multiplied size */ #define ERR_CODE_LZ4_MULTIBLOCK_WITHOUT_HEADER -29 /**< Error returned in LZ4 CRC over block mode if multi-LZ4(#block>1) blocks are * generated */ #define ERR_CODE_MISC_ERROR -50 /**< Error Code constant for error detected but the source * of error is not recognized */ /** ***************************************************************************** * @ingroup icp_qat_fw_comn * Slice types for building of the processing chain within the content * descriptor * * @description * Enumeration used to indicate the ids of the slice types through which * data will pass. * * A logical slice is not a hardware slice but is a software FSM * performing the actions of a slice * *****************************************************************************/ typedef enum { ICP_QAT_FW_SLICE_NULL = 0, /**< NULL slice type */ ICP_QAT_FW_SLICE_CIPHER = 1, /**< CIPHER slice type */ ICP_QAT_FW_SLICE_AUTH = 2, /**< AUTH slice type */ ICP_QAT_FW_SLICE_DRAM_RD = 3, /**< DRAM_RD Logical slice type */ ICP_QAT_FW_SLICE_DRAM_WR = 4, /**< DRAM_WR Logical slice type */ ICP_QAT_FW_SLICE_COMP = 5, /**< Compression slice type */ ICP_QAT_FW_SLICE_XLAT = 6, /**< Translator slice type */ ICP_QAT_FW_SLICE_DELIMITER /**< End delimiter */ } icp_qat_fw_slice_t; #endif /* _ICP_QAT_FW_H_ */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw_comp.h000066400000000000000000001476351503624047500262470ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** ***************************************************************************** * @file icp_qat_fw_comp.h * @defgroup icp_qat_fw_comp ICP QAT FW Compression Service * Interface Definitions * @ingroup icp_qat_fw * @description * This file documents structs used to provide the interface to the * Compression QAT FW service * *****************************************************************************/ #ifndef _ICP_QAT_FW_COMP_H_ #define _ICP_QAT_FW_COMP_H_ /* ****************************************************************************** * Include local header files ****************************************************************************** */ #include "icp_qat_fw.h" /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the Compression command types * @description * Enumeration which is used to indicate the ids of functions * that are exposed by the Compression QAT FW service * *****************************************************************************/ typedef enum { ICP_QAT_FW_COMP_CMD_STATIC = 0, /*!< Static Compress Request */ ICP_QAT_FW_COMP_CMD_DYNAMIC = 1, /*!< Dynamic Compress Request */ ICP_QAT_FW_COMP_CMD_DECOMPRESS = 2, /*!< Decompress Request */ ICP_QAT_FW_COMP_CMD_DELIMITER /**< Delimiter type */ } icp_qat_fw_comp_cmd_id_t; /* * REQUEST FLAGS IN COMMON COMPRESSION * In common message it is named as SERVICE SPECIFIC FLAGS. * * + ===== + ------ + ------ + --- + ----- + ----- + ----- + -- + ---- + --- + * | Bit | 15 - 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * + ===== + ------ + ----- + --- + ----- + ----- + ----- + -- + ---- + --- + * | Flags | Rsvd | Dis. |Resvd| Dis. | Enh. |Auto |Sess| Rsvd | Rsvd| * | | Bits | secure | =0 | Type0 | ASB |Select |Type| = 0 | = 0 | * | | = 0 |RAM use | | Header | |Best | | | | * | | |as intmd| | | | | | | | * | | | buf | | | | | | | | * + ===== + ------ + ----- + --- + ------ + ----- + ----- + -- + ---- + --- + * Note: For QAT 2.0 Disable Secure Ram, DisType0 Header and Enhanced ASB bits * are don't care. i.e., these features are removed from QAT 2.0. */ /**< Flag usage */ #define ICP_QAT_FW_COMP_STATELESS_SESSION 0 /**< @ingroup icp_qat_fw_comp * Flag representing that session is stateless */ #define ICP_QAT_FW_COMP_STATEFUL_SESSION 1 /**< @ingroup icp_qat_fw_comp * Flag representing that session is stateful */ #define ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST 0 /**< @ingroup icp_qat_fw_comp * Flag representing that autoselectbest is NOT used */ #define ICP_QAT_FW_COMP_AUTO_SELECT_BEST 1 /**< @ingroup icp_qat_fw_comp * Flag representing that autoselectbest is used */ #define ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST 0 /**< @ingroup icp_qat_fw_comp * Flag representing that enhanced autoselectbest is NOT used */ #define ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST 1 /**< @ingroup icp_qat_fw_comp * Flag representing that enhanced autoselectbest is used */ #define ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST 0 /**< @ingroup icp_qat_fw_comp * Flag representing that enhanced autoselectbest is NOT used */ #define ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST 1 /**< @ingroup icp_qat_fw_comp * Flag representing that enhanced autoselectbest is used */ #define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF 1 /**< @ingroup icp_qat_fw_comp * Flag representing secure RAM from being used as * an intermediate buffer is DISABLED. */ #define ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF 0 /**< @ingroup icp_qat_fw_comp * Flag representing secure RAM from being used as * an intermediate buffer is ENABLED. */ /**< Flag mask & bit position */ #define ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS 2 /**< @ingroup icp_qat_fw_comp * Starting bit position for the session type */ #define ICP_QAT_FW_COMP_SESSION_TYPE_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine the session type */ #define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS 3 /**< @ingroup icp_qat_fw_comp * Starting bit position for auto select best */ #define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for auto select best */ #define ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS 4 /**< @ingroup icp_qat_fw_comp * Starting bit position for enhanced auto select best */ #define ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for enhanced auto select best */ #define ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS 5 /**< @ingroup icp_qat_fw_comp * Starting bit position for disabling type zero header write back when Enhanced autoselect best is enabled. If set firmware does not return type0 store block header, only copies src to dest. (if best output is Type0) */ #define ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for auto select best */ #define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS 7 /**< @ingroup icp_qat_fw_comp * Starting bit position for flag used to disable secure ram from * being used as an intermediate buffer. */ #define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for disable secure ram for use as an intermediate buffer. */ #define ICP_QAT_FW_COMP_DICTIONARY_TYPE_BITPOS 24 /**< @ingroup icp_qat_fw_comp * Starting bit position for the dictionary type in the dictionary parameters received in the compression request parameters. */ #define ICP_QAT_FW_COMP_DICTIONARY_TYPE_MASK 0xFF /**< @ingroup icp_qat_fw_comp * One Most Significant Byte mask for the dictionary type in the dictionary parameters received in the compression request parameters. */ #define ICP_QAT_FW_COMP_DICTIONARY_LENGTH_BITPOS 0 /**< @ingroup icp_qat_fw_comp * Starting bit position for the dictionary length in the dictionary parameters received in the compression request parameters. */ #define ICP_QAT_FW_COMP_DICTIONARY_LENGTH_MASK 0xFFFFFF /**< @ingroup icp_qat_fw_comp * Three Least Significant Bytes mask for the dictionary length in the dictionary parameters received in the compression request parameters. */ /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro used for the generation of the command flags for Compression Request. * This should always be used for the generation of the flags. No direct sets or * masks should be performed on the flags data * * @param sesstype Session Type * @param autoselect AutoSelectBest * @enhanced_asb Enhanced AutoSelectBest * @ret_uncomp RetUnCompressed * @secure_ram Secure Ram usage * ******************************************************************************/ #define ICP_QAT_FW_COMP_FLAGS_BUILD( \ sesstype, autoselect, enhanced_asb, ret_uncomp, secure_ram) \ (((sesstype & ICP_QAT_FW_COMP_SESSION_TYPE_MASK) \ << ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS) | \ ((autoselect & ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK) \ << ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS) | \ ((enhanced_asb & ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK) \ << ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS) | \ ((ret_uncomp & ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK) \ << ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS) | \ ((secure_ram & ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK) \ << ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS)) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro used for the generation of the command flags for Compression Request. * This should always be used for the generation of the flags. No direct sets or * masks should be performed on the flags data * * @param sesstype Session Type * @param autoselect AutoSelectBest * Selects between compressed and uncompressed output. * No distinction made between static and dynamic * compressed data. * *********************************************************************************/ #define ICP_QAT_FW_COMP_20_FLAGS_BUILD(sesstype, autoselect) \ (((sesstype & ICP_QAT_FW_COMP_SESSION_TYPE_MASK) \ << ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS) | \ ((autoselect & ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK) \ << ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS)) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the session type bit * * @param flags Flags to extract the session type bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_SESSION_TYPE_GET(flags) \ QAT_FIELD_GET(flags, \ ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS, \ ICP_QAT_FW_COMP_SESSION_TYPE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the autoSelectBest bit * * @param flags Flags to extract the autoSelectBest bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_GET(flags) \ QAT_FIELD_GET(flags, \ ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS, \ ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the enhanced asb bit * * @param flags Flags to extract the enhanced asb bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_EN_ASB_GET(flags) \ QAT_FIELD_GET(flags, \ ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS, \ ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the RetUncomp bit * * @param flags Flags to extract the Ret Uncomp bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_RET_UNCOMP_GET(flags) \ QAT_FIELD_GET(flags, \ ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS, \ ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the Secure Ram usage bit * * @param flags Flags to extract the Secure Ram usage from * *****************************************************************************/ #define ICP_QAT_FW_COMP_SECURE_RAM_USE_GET(flags) \ QAT_FIELD_GET(flags, \ ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS, \ ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the dictionary type byte * * @param dict_params LW parameter to extract the dictionary type byte from * *****************************************************************************/ #define ICP_QAT_FW_COMP_DICTIONARY_TYPE_GET(dict_params) \ QAT_FIELD_GET(dict_params, \ ICP_QAT_FW_COMP_DICTIONARY_TYPE_BITPOS, \ ICP_QAT_FW_COMP_DICTIONARY_TYPE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the dictionary length byte * * @param dict_params LW parameter to extract the dictionary type byte from * *****************************************************************************/ #define ICP_QAT_FW_COMP_DICTIONARY_LEN_GET(dict_params) \ QAT_FIELD_GET(dict_params, \ ICP_QAT_FW_COMP_DICTIONARY_LENGTH_BITPOS, \ ICP_QAT_FW_COMP_DICTIONARY_LENGTH_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro used for the generation of the dictionary parameters for compression * request. * * @param dict_type Dictionary type to be encoded into dictionary * parameters * @param dict_len Dictionary length to be encoded into dictionary * parameters * *****************************************************************************/ #define ICP_QAT_FW_COMP_DICTIONARY_PARAMS_BUILD(dict_type, dict_len) \ (((dict_type & ICP_QAT_FW_COMP_DICTIONARY_TYPE_MASK) \ << ICP_QAT_FW_COMP_DICTIONARY_TYPE_BITPOS) | \ ((dict_len & ICP_QAT_FW_COMP_DICTIONARY_LENGTH_MASK) \ << ICP_QAT_FW_COMP_DICTIONARY_LENGTH_BITPOS)) /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the compression header cd pars block * @description * Definition of the compression processing cd pars block. * The structure is a service-specific implementation of the common * structure. *****************************************************************************/ typedef union icp_qat_fw_comp_req_hdr_cd_pars_s { /**< LWs 2-5 */ struct { uint64_t content_desc_addr; /**< Address of the content descriptor */ uint16_t content_desc_resrvd1; /**< Content descriptor reserved field */ uint8_t content_desc_params_sz; /**< Size of the content descriptor parameters in quad words. These * parameters describe the session setup configuration info for the * slices that this request relies upon i.e. the configuration word and * cipher key needed by the cipher slice if there is a request for * cipher processing. */ uint8_t content_desc_hdr_resrvd2; /**< Content descriptor reserved field */ uint32_t content_desc_resrvd3; /**< Content descriptor reserved field */ } s; struct { uint32_t comp_slice_cfg_word[ICP_QAT_FW_NUM_LONGWORDS_2]; /* Compression Slice Config Word */ uint32_t content_desc_resrvd4; /**< Content descriptor reserved field */ } sl; } icp_qat_fw_comp_req_hdr_cd_pars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the compression request parameters block * @description * Definition of the compression processing request parameters block. * The structure below forms part of the Compression + Translation * Parameters block spanning LWs 14-23, thus differing from the common * base Parameters block structure. Unused fields must be set to 0. * *****************************************************************************/ typedef struct icp_qat_fw_comp_req_params_s { /**< LW 14 */ uint32_t comp_len; /**< Size of input to process in bytes Note: Only EOP requests can be odd * for decompression. IA must set LSB to zero for odd sized intermediate * inputs */ /**< LW 15 */ uint32_t out_buffer_sz; /**< Size of output buffer in bytes */ /**< LW 16 */ union { struct { /** LW 16 */ uint32_t initial_crc32; /**< CRC for processed bytes (input byte count) */ /** LW 17 */ uint32_t initial_adler; /**< Adler for processed bytes (input byte count) */ } legacy; /** LW 16-17 */ uint64_t crc_data_addr; /**< CRC data structure pointer */ } crc; /**< LW 18 */ uint32_t req_par_flags; /**< LW 19 */ uint32_t dictionary_params; } icp_qat_fw_comp_req_params_t; /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro used for the generation of the request parameter flags. * This should always be used for the generation of the flags. No direct sets or * masks should be performed on the flags data * * @param sop SOP Flag, 0 restore, 1 don't restore * @param eop EOP Flag, 0 restore, 1 don't restore * @param bfinal Set bfinal in this block or not * @param cnv Whether internal CNV check is to be performed * * ICP_QAT_FW_COMP_NO_CNV * * ICP_QAT_FW_COMP_CNV * @param cnvnr Whether internal CNV recovery is to be performed * * ICP_QAT_FW_COMP_NO_CNV_RECOVERY * * ICP_QAT_FW_COMP_CNV_RECOVERY * @param cnvdfx Whether CNV error injection is to be performed * * ICP_QAT_FW_COMP_NO_CNV_DFX * * ICP_QAT_FW_COMP_CNV_DFX * @param crc CRC Mode Flag - 0 legacy, 1 crc data struct * @param xxhash_acc xxHash accumulate flag * * ICP_QAT_FW_COMP_NO_XXHASH_ACC - xxHash32 is not * accumulated across requests * * ICP_QAT_FW_COMP_XXHASH_ACC - xxhash32 is * accumulated across requests * @param cnv_error_type CnV error type to inject * * ICP_QAT_FW_COMP_CNV_ERROR_CHECKSUM * checksum mismatch * * ICP_QAT_FW_COMP_CNV_ERROR_DCPR_OBC_DIFF * DCPR produced length difference * * ICP_QAT_FW_COMP_CNV_ERROR_DCPR * DCPR error * * ICP_QAT_FW_COMP_CNV_ERROR_XLT * Translator error * * ICP_QAT_FW_COMP_CNV_ERROR_DCPR_IBC_DIFF * DCPR consumed length difference * @param append_crc Append CRC flag * @param drop_data Drop the result data * @param partial_decomp Return only part of the decompressed data *****************************************************************************/ #define ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(sop, \ eop, \ bfinal, \ cnv, \ cnvnr, \ cnvdfx, \ crc, \ xxhash_acc, \ cnv_error_type, \ append_crc, \ drop_data, \ partial_decomp) \ (((sop & ICP_QAT_FW_COMP_SOP_MASK) << ICP_QAT_FW_COMP_SOP_BITPOS) | \ ((eop & ICP_QAT_FW_COMP_EOP_MASK) << ICP_QAT_FW_COMP_EOP_BITPOS) | \ ((bfinal & ICP_QAT_FW_COMP_BFINAL_MASK) \ << ICP_QAT_FW_COMP_BFINAL_BITPOS) | \ ((cnv & ICP_QAT_FW_COMP_CNV_MASK) << ICP_QAT_FW_COMP_CNV_BITPOS) | \ ((cnvnr & ICP_QAT_FW_COMP_CNVNR_MASK) << ICP_QAT_FW_COMP_CNVNR_BITPOS) | \ ((cnvdfx & ICP_QAT_FW_COMP_CNV_DFX_MASK) \ << ICP_QAT_FW_COMP_CNV_DFX_BITPOS) | \ ((crc & ICP_QAT_FW_COMP_CRC_MODE_MASK) \ << ICP_QAT_FW_COMP_CRC_MODE_BITPOS) | \ ((xxhash_acc & ICP_QAT_FW_COMP_XXHASH_ACC_MODE_MASK) \ << ICP_QAT_FW_COMP_XXHASH_ACC_MODE_BITPOS) | \ ((cnv_error_type & ICP_QAT_FW_COMP_CNV_ERROR_MASK) \ << ICP_QAT_FW_COMP_CNV_ERROR_BITPOS) | \ ((append_crc & ICP_QAT_FW_COMP_APPEND_CRC_MASK) \ << ICP_QAT_FW_COMP_APPEND_CRC_BITPOS) | \ ((drop_data & ICP_QAT_FW_COMP_DROP_DATA_MASK) \ << ICP_QAT_FW_COMP_DROP_DATA_BITPOS) | \ ((partial_decomp & ICP_QAT_FW_COMP_PARTIAL_DECOMP_MASK) \ << ICP_QAT_FW_COMP_PARTIAL_DECOMP_BITPOS)) /* * REQUEST FLAGS IN REQUEST PARAMETERS COMPRESSION * * +=====+-----+----- + --- + --- +-----+ --- + ----- + --- + ---- + -- + -- + * | Bit |31-24| 20 | 19 | 18 | 17 | 16 | 15-7 | 6 | 5-2 | 1 | 0 | * +=====+-----+----- + --- + ----+-----+ --- + ----- + --- + ---- + -- + -- + * |Flags|Resvd|xxHash| CRC | CNV |CNVNR| CNV | Resvd |BFin | Resvd|EOP |SOP | * | |=0 |acc | MODE| DFX | | | =0 | | =0 | | | * | | | | | | | | | | | | | * +=====+-----+----- + --- + ----+-----+ --- + ----- + --- + ---- + -- + -- + */ /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the additional QAT2.0 Compression command types * @description * Enumeration which is used to indicate the ids of functions * that are exposed by the Compression QAT FW service * *****************************************************************************/ typedef enum { ICP_QAT_FW_COMP_20_CMD_LZ4_COMPRESS = 3, /*!< LZ4 Compress Request */ ICP_QAT_FW_COMP_20_CMD_LZ4_DECOMPRESS = 4, /*!< LZ4 Decompress Request */ ICP_QAT_FW_COMP_20_CMD_LZ4S_COMPRESS = 5, /*!< LZ4S Compress Request */ ICP_QAT_FW_COMP_20_CMD_LZ4S_DECOMPRESS = 6, /*!< LZ4S Decompress Request */ ICP_QAT_FW_COMP_20_CMD_RESERVED_1 = 7, /*!< Placeholder */ ICP_QAT_FW_COMP_20_CMD_RESERVED_2 = 8, /*!< Placeholder */ ICP_QAT_FW_COMP_20_CMD_DELIMITER /**< Delimiter type */ } icp_qat_fw_comp_20_cmd_id_t; /* * REQUEST FLAGS IN REQUEST PARAMETERS COMPRESSION * * + ===== + ----- + --- +-----+-------+ --- + ---------+ --- + ---- + --- + --- + * | Bit | 31-20 | 19 | 18 | 17 | 16 | 15 - 7 | 6 | 5-2 | 1 | 0 | * + ===== + ----- + --- +-----+-------+ --- + ---------+ --- | ---- + --- + --- + * | Flags | Resvd | CRC | CNV | CNVNR | CNV |Resvd Bits|BFin |Resvd | EOP | SOP | * | | =0 | Mode| DFX | | | =0 | | =0 | | | * | | | | | | | | | | | | * + ===== + ----- + --- +-----+-------+ --- + ---------+ --- | ---- + --- + --- + */ #define ICP_QAT_FW_COMP_NOT_SOP 0 /**< @ingroup icp_qat_fw_comp * Flag representing that a request is NOT Start of Packet */ #define ICP_QAT_FW_COMP_SOP 1 /**< @ingroup icp_qat_fw_comp * * Flag representing that a request IS Start of Packet */ #define ICP_QAT_FW_COMP_NOT_EOP 0 /**< @ingroup icp_qat_fw_comp * Flag representing that a request is NOT Start of Packet */ #define ICP_QAT_FW_COMP_EOP 1 /**< @ingroup icp_qat_fw_comp * Flag representing that a request IS End of Packet */ #define ICP_QAT_FW_COMP_NOT_BFINAL 0 /**< @ingroup icp_qat_fw_comp * Flag representing to indicate firmware this is not the last block */ #define ICP_QAT_FW_COMP_BFINAL 1 /**< @ingroup icp_qat_fw_comp * Flag representing to indicate firmware this is the last block */ #define ICP_QAT_FW_COMP_NO_CNV 0 /**< @ingroup icp_qat_fw_comp * Flag indicating that NO cnv check is to be performed on the request */ #define ICP_QAT_FW_COMP_CNV 1 /**< @ingroup icp_qat_fw_comp * Flag indicating that a cnv check IS to be performed on the request */ #define ICP_QAT_FW_COMP_NO_CNV_RECOVERY 0 /**< @ingroup icp_qat_fw_comp * Flag indicating that NO cnv recovery is to be performed on the request */ #define ICP_QAT_FW_COMP_CNV_RECOVERY 1 /**< @ingroup icp_qat_fw_comp * Flag indicating that a cnv recovery is to be performed on the request */ #define ICP_QAT_FW_COMP_NO_CNV_DFX 0 /**< @ingroup icp_qat_fw_comp * Flag indicating that NO CNV inject error is to be performed on the request */ #define ICP_QAT_FW_COMP_CNV_DFX 1 /**< @ingroup icp_qat_fw_comp * Flag indicating that CNV inject error is to be performed on the request */ #define ICP_QAT_FW_COMP_CRC_MODE_LEGACY 0 /**< @ingroup icp_qat_fw_comp * Flag representing to use the legacy CRC mode */ #define ICP_QAT_FW_COMP_CRC_MODE_E2E 1 /**< @ingroup icp_qat_fw_comp * Flag representing to use the external CRC data struct */ #define ICP_QAT_FW_COMP_NO_XXHASH_ACC 0 /**< @ingroup icp_qat_fw_comp * * Flag indicating that xxHash will NOT be accumulated across requests */ #define ICP_QAT_FW_COMP_XXHASH_ACC 1 /**< @ingroup icp_qat_fw_comp * * Flag indicating that xxHash WILL be accumulated across requests */ #define ICP_QAT_FW_COMP_APPEND_CRC 1 /**< @ingroup icp_qat_fw_comp * Flag indicating to append CRC to the compressed data * or extract the appended CRC for decompression */ #define ICP_QAT_FW_COMP_NO_APPEND_CRC 0 /**< @ingroup icp_qat_fw_comp * Flag indicating to not append CRC to the compressed data */ #define ICP_QAT_FW_COMP_DROP_DATA 1 /**< @ingroup icp_qat_fw_comp * Flag representing to drop the data. The decompressed data * is not returned */ #define ICP_QAT_FW_COMP_NO_DROP_DATA 0 /**< @ingroup icp_qat_fw_comp * Flag representing to not drop the data. The decompressed data * is returned */ #define ICP_QAT_FW_COMP_NO_PARTIAL_DECOMPRESS 0 /**< @ingroup icp_qat_fw_comp * Flag representing to not do partial decompression. * The entire decompressed data is returned */ #define ICP_QAT_FW_COMP_PARTIAL_DECOMPRESS 1 /**< @ingroup icp_qat_fw_comp * Flag representing to do partial decompression. The decompressed * data returned is defined by the offset and length in request */ #define ICP_QAT_FW_COMP_SOP_BITPOS 0 /**< @ingroup icp_qat_fw_comp * Starting bit position for SOP */ #define ICP_QAT_FW_COMP_SOP_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine SOP */ #define ICP_QAT_FW_COMP_EOP_BITPOS 1 /**< @ingroup icp_qat_fw_comp * Starting bit position for EOP */ #define ICP_QAT_FW_COMP_EOP_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine EOP */ #define ICP_QAT_FW_COMP_BFINAL_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for the bfinal bit */ #define ICP_QAT_FW_COMP_BFINAL_BITPOS 6 /**< @ingroup icp_qat_fw_comp * Starting bit position for the bfinal bit */ #define ICP_QAT_FW_COMP_CNV_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for the CNV bit */ #define ICP_QAT_FW_COMP_CNV_BITPOS 16 /**< @ingroup icp_qat_fw_comp * Starting bit position for the CNV bit */ #define ICP_QAT_FW_COMP_CNVNR_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for the CNV Recovery bit */ #define ICP_QAT_FW_COMP_CNVNR_BITPOS 17 /**< @ingroup icp_qat_fw_comp * Starting bit position for the CNV Recovery bit */ #define ICP_QAT_FW_COMP_CNV_DFX_BITPOS 18 /**< @ingroup icp_qat_fw_comp * Starting bit position for the CNV DFX bit */ #define ICP_QAT_FW_COMP_CNV_DFX_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask for the CNV DFX bit */ #define ICP_QAT_FW_COMP_CRC_MODE_BITPOS 19 /**< @ingroup icp_qat_fw_comp * Starting bit position for CRC mode */ #define ICP_QAT_FW_COMP_CRC_MODE_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine CRC mode */ #define ICP_QAT_FW_COMP_XXHASH_ACC_MODE_BITPOS 20 /**< @ingroup icp_qat_fw_comp * Starting bit position for xxHash accumulate mode */ #define ICP_QAT_FW_COMP_XXHASH_ACC_MODE_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine xxHash accumulate mode */ #define ICP_QAT_FW_COMP_CNV_ERROR_BITPOS 21 /**< @ingroup icp_qat_fw_comp * Starting bit position for CnV error type */ #define ICP_QAT_FW_COMP_CNV_ERROR_MASK 0b111 /**< @ingroup icp_qat_fw_comp * Three bit mask used to determine CnV error type */ #define ICP_QAT_FW_COMP_CNV_ERROR_NONE 0b000 /**< @ingroup icp_qat_fw_comp * The CnV error type for no error */ #define ICP_QAT_FW_COMP_CNV_ERROR_CHECKSUM 0b001 /**< @ingroup icp_qat_fw_comp * The CnV error type for checksum mismatch */ #define ICP_QAT_FW_COMP_CNV_ERROR_DCPR_OBC_DIFF 0b010 /**< @ingroup icp_qat_fw_comp * The CnV error type for DCPR produced length difference */ #define ICP_QAT_FW_COMP_CNV_ERROR_DCPR 0b011 /**< @ingroup icp_qat_fw_comp * The CnV error type for DCPR error */ #define ICP_QAT_FW_COMP_CNV_ERROR_XLT 0b100 /**< @ingroup icp_qat_fw_comp * The CnV error type for translator error */ #define ICP_QAT_FW_COMP_CNV_ERROR_DCPR_IBC_DIFF 0b101 /**< @ingroup icp_qat_fw_comp * The CnV error type for DCPR consumed length difference */ #define ICP_QAT_FW_COMP_APPEND_CRC_BITPOS 24 /**< @ingroup icp_qat_fw_comp * Starting bit position for append CRC flag */ #define ICP_QAT_FW_COMP_APPEND_CRC_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine if append CRC is enabled */ #define ICP_QAT_FW_COMP_DROP_DATA_BITPOS 25 /**< @ingroup icp_qat_fw_comp * Starting bit position to indicate dropping the return data */ #define ICP_QAT_FW_COMP_DROP_DATA_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine if data should be returned */ #define ICP_QAT_FW_COMP_PARTIAL_DECOMP_BITPOS 27 /**< @ingroup icp_qat_fw_comp * Starting bit position to indicate partial decompression */ #define ICP_QAT_FW_COMP_PARTIAL_DECOMP_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine if data should be partially decompressed */ #define ICP_QAT_FW_COMP_LZ4_OUTPUT_CRC_MODE_BITPOS 28 /**< @ingroup icp_qat_fw_comp * Starting bit position for LZ4 CRC output mode */ #define ICP_QAT_FW_COMP_LZ4_OUTPUT_CRC_MODE_MASK 0x1 /**< @ingroup icp_qat_fw_comp * One bit mask used to determine LZ4 CRC output mode */ /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the SOP bit * * @param flags Flags to extract the SOP bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_SOP_GET(flags) \ QAT_FIELD_GET(flags, ICP_QAT_FW_COMP_SOP_BITPOS, ICP_QAT_FW_COMP_SOP_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the EOP bit * * @param flags Flags to extract the EOP bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_EOP_GET(flags) \ QAT_FIELD_GET(flags, ICP_QAT_FW_COMP_EOP_BITPOS, ICP_QAT_FW_COMP_EOP_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the bfinal bit * * @param flags Flags to extract the bfinal bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_BFINAL_GET(flags) \ QAT_FIELD_GET( \ flags, ICP_QAT_FW_COMP_BFINAL_BITPOS, ICP_QAT_FW_COMP_BFINAL_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the CNV bit * * @param flags Flag set containing the CNV flag * *****************************************************************************/ #define ICP_QAT_FW_COMP_CNV_GET(flags) \ QAT_FIELD_GET(flags, ICP_QAT_FW_COMP_CNV_BITPOS, ICP_QAT_FW_COMP_CNV_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the crc mode bit * * @param flags Flags to extract the crc mode bit from * ******************************************************************************/ #define ICP_QAT_FW_COMP_CRC_MODE_GET(flags) \ QAT_FIELD_GET( \ flags, ICP_QAT_FW_COMP_CRC_MODE_BITPOS, ICP_QAT_FW_COMP_CRC_MODE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for extraction of the xxHash accumulate mode bit * * @param flags Flags to extract the xxHash accumulate mode bit from * *****************************************************************************/ #define ICP_QAT_FW_COMP_XXHASH_ACC_MODE_GET(flags) \ QAT_FIELD_GET(flags, \ ICP_QAT_FW_COMP_XXHASH_ACC_MODE_BITPOS, \ ICP_QAT_FW_COMP_XXHASH_ACC_MODE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for setting of the xxHash accumulate mode bit * * @param flags Flags to set the xxHash accumulate mode bit to * @param val xxHash accumulate mode to set * *****************************************************************************/ #define ICP_QAT_FW_COMP_XXHASH_ACC_MODE_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ ICP_QAT_FW_COMP_XXHASH_ACC_MODE_BITPOS, \ ICP_QAT_FW_COMP_XXHASH_ACC_MODE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Macro for setting of the LZ4 output crc mode bit * * @param flags Flags to set the LZ4 output crc mode bit to * @param val LZ4 output crc mode to set * *****************************************************************************/ #define ICP_QAT_FW_COMP_LZ4_OUTPUT_CRC_MODE_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ ICP_QAT_FW_COMP_LZ4_OUTPUT_CRC_MODE_BITPOS, \ ICP_QAT_FW_COMP_LZ4_OUTPUT_CRC_MODE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the translator request parameters block * @description * Definition of the translator processing request parameters block * The structure below forms part of the Compression + Translation * Parameters block spanning LWs 14-23, thus differing from the common * base Parameters block structure. Unused fields must be set to 0. * *****************************************************************************/ typedef struct icp_qat_fw_xlt_req_params_s { /**< LWs 20-21 */ uint64_t inter_buff_ptr; /**< This field specifies the physical address of an intermediate * buffer SGL array. The array contains a pair of 64-bit * intermediate buffer pointers to SGL buffer descriptors, one pair * per CPM. Please refer to the CPM1.6 Firmware Interface HLD * specification for more details. */ } icp_qat_fw_xlt_req_params_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Compression header of the content descriptor block * @description * Definition of the service-specific compression control block header * structure. The compression parameters are defined per algorithm * and are located in the icp_qat_hw.h file. This compression * cd block spans LWs 24-29, forming part of the compression + translation * cd block, thus differing from the common base content descriptor * structure. * *****************************************************************************/ typedef struct icp_qat_fw_comp_cd_hdr_s { /**< LW 24 */ uint16_t ram_bank_flags; /**< Flags to show which ram banks to access */ uint8_t comp_cfg_offset; /**< Quad word offset from the content descriptor parameters address to the * parameters for the compression processing */ uint8_t next_curr_id; /**< This field combines the next and current id (each four bits) - * the next id is the most significant nibble. * Next Id: Set to the next slice to pass the compressed data through. * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through * anymore slices after compression * Current Id: Initialised with the compression slice type */ /**< LW 25 */ uint32_t resrvd; /**< LWs 26-27 */ uint64_t comp_state_addr; /**< Pointer to compression state */ /**< LWs 28-29 */ uint64_t ram_banks_addr; /**< Pointer to banks */ } icp_qat_fw_comp_cd_hdr_t; #define COMP_CPR_INITIAL_CRC 0 #define COMP_CPR_INITIAL_ADLER 1 /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Translator content descriptor header block * @description * Definition of the structure used to describe the translation processing * to perform on data. The translator parameters are defined per algorithm * and are located in the icp_qat_hw.h file. This translation cd block * spans LWs 30-31, forming part of the compression + translation cd block, * thus differing from the common base content descriptor structure. * *****************************************************************************/ typedef struct icp_qat_fw_xlt_cd_hdr_s { /**< LW 30 */ uint16_t resrvd1; /**< Reserved field and assumed set to 0 */ uint8_t resrvd2; /**< Reserved field and assumed set to 0 */ uint8_t next_curr_id; /**< This field combines the next and current id (each four bits) - * the next id is the most significant nibble. * Next Id: Set to the next slice to pass the translated data through. * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through * any more slices after compression * Current Id: Initialised with the translation slice type */ /**< LW 31 */ uint32_t resrvd3; /**< Reserved and should be set to zero, needed for quadword alignment */ } icp_qat_fw_xlt_cd_hdr_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the common Compression QAT FW request * @description * This is a definition of the full request structure for * compression and translation. * *****************************************************************************/ typedef struct icp_qat_fw_comp_req_s { /**< LWs 0-1 */ icp_qat_fw_comn_req_hdr_t comn_hdr; /**< Common request header - for Service Command Id, * use service-specific Compression Command Id. * Service Specific Flags - use Compression Command Flags */ /**< LWs 2-5 */ icp_qat_fw_comp_req_hdr_cd_pars_t cd_pars; /**< Compression service-specific content descriptor field which points * either to a content descriptor parameter block or contains the * compression slice config word. */ /**< LWs 6-13 */ icp_qat_fw_comn_req_mid_t comn_mid; /**< Common request middle section */ /**< LWs 14-19 */ icp_qat_fw_comp_req_params_t comp_pars; /**< Compression request Parameters block */ /**< LWs 20-21 */ union { icp_qat_fw_xlt_req_params_t xlt_pars; /**< Translation request Parameters block */ uint32_t resrvd1[ICP_QAT_FW_NUM_LONGWORDS_2]; /**< Reserved if not used for translation */ struct { uint32_t partial_decompress_length; /**< LW 20 \n Length of the decompressed data to return */ uint32_t partial_decompress_offset; /**< LW 21 \n Offset of the decompressed data at which to return */ } partial_decompress; } u1; /**< LWs 22-23 */ union { uint32_t resrvd2[ICP_QAT_FW_NUM_LONGWORDS_2]; /**< Reserved - not used if Batch and Pack is disabled.*/ uint64_t resrvd3; /**< Reserved - not used if Batch and Pack is disabled.*/ } u3; /**< LWs 24-29 */ icp_qat_fw_comp_cd_hdr_t comp_cd_ctrl; /**< Compression request content descriptor control * block header */ /**< LWs 30-31 */ union { icp_qat_fw_xlt_cd_hdr_t xlt_cd_ctrl; /**< Translation request content descriptor * control block header */ uint32_t resrvd3[ICP_QAT_FW_NUM_LONGWORDS_2]; /**< Reserved if not used for translation */ } u2; } icp_qat_fw_comp_req_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the compression QAT FW response descriptor parameters * @description * This part of the response is specific to the compression response. * *****************************************************************************/ typedef struct icp_qat_fw_resp_comp_pars_s { /**< LW 4 */ uint32_t input_byte_counter; /**< Input byte counter */ /**< LW 5 */ uint32_t output_byte_counter; /**< Output byte counter */ /** LW 6-7 */ union { struct { /** LW 6 */ uint32_t curr_crc32; /**< Current CRC32 */ /** LW 7 */ uint32_t curr_adler_32; /**< Current Adler32 */ } legacy; uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_2]; /**< Reserved if not in legacy mode */ } crc; } icp_qat_fw_resp_comp_pars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the Compression Eagle Tail Response * @description * This is the response delivered to the ET rings by the Compression * QAT FW service for all commands * *****************************************************************************/ typedef struct icp_qat_fw_comp_resp_s { /**< LWs 0-1 */ icp_qat_fw_comn_resp_hdr_t comn_resp; /**< Common interface response format see icp_qat_fw.h */ /**< LWs 2-3 */ uint64_t opaque_data; /**< Opaque data passed from the request to the response message */ /**< LWs 4-7 */ icp_qat_fw_resp_comp_pars_t comp_resp_pars; /**< Common response params (checksums and byte counts) */ } icp_qat_fw_comp_resp_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the compression dictionary types * @description * Enumeration which is used to indicate the type of the dictionary * received for the compression service * *****************************************************************************/ typedef enum { ICP_QAT_FW_COMP_DICT_TYPE_NONE = 0, /*!< No Dictionary Mode */ ICP_QAT_FW_COMP_DICT_TYPE_UNCOMPRESSED = 1, /*!< Uncompressed Dictionary */ ICP_QAT_FW_COMP_DICT_TYPE_COMPRESSED = 2, /*!< Compressed Dictionary */ ICP_QAT_FW_COMP_DICT_TYPE_DELIMITER /**< Delimiter type */ } icp_qat_fw_comp_dict_type_t; /* RAM Bank defines */ #define QAT_FW_COMP_BANK_FLAG_MASK 0x1 #define QAT_FW_COMP_BANK_I_BITPOS 8 #define QAT_FW_COMP_BANK_H_BITPOS 7 #define QAT_FW_COMP_BANK_G_BITPOS 6 #define QAT_FW_COMP_BANK_F_BITPOS 5 #define QAT_FW_COMP_BANK_E_BITPOS 4 #define QAT_FW_COMP_BANK_D_BITPOS 3 #define QAT_FW_COMP_BANK_C_BITPOS 2 #define QAT_FW_COMP_BANK_B_BITPOS 1 #define QAT_FW_COMP_BANK_A_BITPOS 0 /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the ram bank enabled values * @description * Enumeration used to define whether a ram bank is enabled or not * *****************************************************************************/ typedef enum { ICP_QAT_FW_COMP_BANK_DISABLED = 0, /*!< BANK DISABLED */ ICP_QAT_FW_COMP_BANK_ENABLED = 1, /*!< BANK ENABLED */ ICP_QAT_FW_COMP_BANK_DELIMITER = 2 /**< Delimiter type */ } icp_qat_fw_comp_bank_enabled_t; /** ****************************************************************************** * @ingroup icp_qat_fw_comp * * @description * Build the ram bank flags in the compression content descriptor * which specify which banks are used to save history * * @param bank_i_enable * @param bank_h_enable * @param bank_g_enable * @param bank_f_enable * @param bank_e_enable * @param bank_d_enable * @param bank_c_enable * @param bank_b_enable * @param bank_a_enable *****************************************************************************/ #define ICP_QAT_FW_COMP_RAM_FLAGS_BUILD(bank_i_enable, \ bank_h_enable, \ bank_g_enable, \ bank_f_enable, \ bank_e_enable, \ bank_d_enable, \ bank_c_enable, \ bank_b_enable, \ bank_a_enable) \ ((((bank_i_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_I_BITPOS) | \ (((bank_h_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_H_BITPOS) | \ (((bank_g_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_G_BITPOS) | \ (((bank_f_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_F_BITPOS) | \ (((bank_e_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_E_BITPOS) | \ (((bank_d_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_D_BITPOS) | \ (((bank_c_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_C_BITPOS) | \ (((bank_b_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_B_BITPOS) | \ (((bank_a_enable)&QAT_FW_COMP_BANK_FLAG_MASK) \ << QAT_FW_COMP_BANK_A_BITPOS)) /** ***************************************************************************** * @ingroup icp_qat_fw_comp * Definition of the xxhash32 acc state buffer * @description * This is data structure used in stateful lite for xxhash32 * *****************************************************************************/ typedef struct xxhash_acc_state_buff_s { /**< LW 0 */ uint32_t in_counter; /**< Accumulated (total) consumed bytes. As oppose to the per request IBC in * the response.*/ /**< LW 1 */ uint32_t out_counter; /**< OBC as in the response.*/ /**< LW 2-5 */ uint32_t xxhash_state[4]; /**< Initial value is set by IA to the values stated in HAS.*/ /**< LW 6-9 */ uint32_t clear_txt[4]; /**< Set to 0 for the first request.*/ } xxhash_acc_state_buff_t; #endif /* _ICP_QAT_FW_COMP_H_ */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw_dc_chain.h000066400000000000000000000272021503624047500270240ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** * @file icp_qat_fw_dc_chain.h * @defgroup icp_qat_fw_dc_chain ICP QAT FW CHAIN Processing Definitions * @ingroup icp_qat_fw * $Revision: 0.1 $ * @brief * This file documents the external interfaces that the QAT FW running * on the QAT Acceleration Engine provides to clients wanting to * accelerate chaining applications */ #include "lac_common.h" #ifndef __ICP_QAT_FW_DC_CHAIN_H__ #define __ICP_QAT_FW_DC_CHAIN_H__ #define ICP_QAT_FW_COMP_CHAIN_REQ_FLAGS_BUILD( \ append_crc, verify, derive_key, crc_ctx)\ (((append_crc & ICP_QAT_FW_COMP_CHAIN_APPEND_CRC_MASK) \ << ICP_QAT_FW_COMP_CHAIN_APPEND_CRC_BITPOS) | \ ((verify & ICP_QAT_FW_COMP_CHAIN_VERIFY_MASK) \ << ICP_QAT_FW_COMP_CHAIN_VERIFY_BITPOS) | \ ((derive_key & ICP_QAT_FW_COMP_CHAIN_DERIVE_KEY_MASK) \ << ICP_QAT_FW_COMP_CHAIN_DERIVE_KEY_BITPOS) | \ ((crc_ctx & ICP_QAT_FW_COMP_CHAIN_CRC64_CTX_MASK) \ << ICP_QAT_FW_COMP_CHAIN_CRC64_CTX_BITPOS)) #define ICP_QAT_FW_COMP_CHAIN_APPEND_CRC 1 #define ICP_QAT_FW_COMP_CHAIN_NO_APPEND_CRC 0 #define ICP_QAT_FW_COMP_CHAIN_VERIFY 1 #define ICP_QAT_FW_COMP_CHAIN_NO_VERIFY 0 #define ICP_QAT_FW_COMP_CHAIN_DERIVE_KEY 1 #define ICP_QAT_FW_COMP_CHAIN_NO_DERIVE_KEY 0 #define ICP_QAT_FW_COMP_CHAIN_CRC64_CTX 1 #define ICP_QAT_FW_COMP_CHAIN_NO_CRC64_CTX 0 #define ICP_QAT_FW_COMP_CHAIN_APPEND_CRC_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_APPEND_CRC_BITPOS 0 #define ICP_QAT_FW_COMP_CHAIN_VERIFY_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_VERIFY_BITPOS 1 #define ICP_QAT_FW_COMP_CHAIN_DERIVE_KEY_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_DERIVE_KEY_BITPOS 2 #define ICP_QAT_FW_COMP_CHAIN_CRC64_CTX_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_CRC64_CTX_BITPOS 3 #define ICP_QAT_FW_COMP_CHAIN_REQ_EXTEND_FLAGS_BUILD( \ cnv, asb, cbc, xts, ccm, cnvnr) \ (((cnv & ICP_QAT_FW_COMP_CHAIN_CNV_MASK) \ << ICP_QAT_FW_COMP_CHAIN_CNV_BITPOS) | \ ((asb & ICP_QAT_FW_COMP_CHAIN_ASB_MASK) \ << ICP_QAT_FW_COMP_CHAIN_ASB_BITPOS) | \ ((cbc & ICP_QAT_FW_COMP_CHAIN_CBC_MASK) \ << ICP_QAT_FW_COMP_CHAIN_CBC_BITPOS) | \ ((xts & ICP_QAT_FW_COMP_CHAIN_XTS_MASK) \ << ICP_QAT_FW_COMP_CHAIN_XTS_BITPOS) | \ ((ccm & ICP_QAT_FW_COMP_CHAIN_CCM_MASK) \ << ICP_QAT_FW_COMP_CHAIN_CCM_BITPOS) | \ ((cnvnr & ICP_QAT_FW_COMP_CHAIN_CNV_RECOVERY_MASK) \ << ICP_QAT_FW_COMP_CHAIN_CNV_RECOVERY_BITPOS)) #define ICP_QAT_FW_COMP_CHAIN_NO_CNV 0 #define ICP_QAT_FW_COMP_CHAIN_CNV 1 #define ICP_QAT_FW_COMP_CHAIN_NO_CNV_RECOVERY 0 #define ICP_QAT_FW_COMP_CHAIN_CNV_RECOVERY 1 #define ICP_QAT_FW_COMP_CHAIN_NO_ASB 0 #define ICP_QAT_FW_COMP_CHAIN_ASB 1 #define ICP_QAT_FW_COMP_CHAIN_NO_CBC 0 #define ICP_QAT_FW_COMP_CHAIN_CBC 1 #define ICP_QAT_FW_COMP_CHAIN_NO_XTS 0 #define ICP_QAT_FW_COMP_CHAIN_XTS 1 #define ICP_QAT_FW_COMP_CHAIN_NO_CCM 0 #define ICP_QAT_FW_COMP_CHAIN_CCM 1 #define ICP_QAT_FW_COMP_CHAIN_CNV_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_CNV_BITPOS 0 #define ICP_QAT_FW_COMP_CHAIN_ASB_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_ASB_BITPOS 4 #define ICP_QAT_FW_COMP_CHAIN_CBC_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_CBC_BITPOS 6 #define ICP_QAT_FW_COMP_CHAIN_XTS_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_XTS_BITPOS 10 #define ICP_QAT_FW_COMP_CHAIN_CCM_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_CCM_BITPOS 8 #define ICP_QAT_FW_COMP_CHAIN_CNV_RECOVERY_MASK 0x1 #define ICP_QAT_FW_COMP_CHAIN_CNV_RECOVERY_BITPOS 12 #define DC_CHAIN_MAX_LINK 0x3 typedef enum { ICP_QAT_FW_NO_CHAINING = 0, ICP_QAT_FW_CHAINING_CMD_DECRYPT_DECOMPRESS = 1, ICP_QAT_FW_CHAINING_CMD_DYNAMIC_COMP_ENCRYT = 2, ICP_QAT_FW_CHAINING_CMD_HASH_STATIC_COMP = 3, ICP_QAT_FW_CHAINING_CMD_HASH_DYNAMIC_COMP = 4 } icp_qat_comp_chain_cmd_id_t; typedef enum { ICP_QAT_FW_NO_CHAINING_20 = 0, ICP_QAT_FW_CHAINING_20_CMD_DECRYPT_DECOMPRESS = 1, ICP_QAT_FW_CHAINING_20_CMD_COMPRESS_ENCRYPT = 2, ICP_QAT_FW_CHAINING_20_CMD_HASH_COMPRESS = 3 } icp_qat_comp_chain_20_cmd_id_t; /** ***************************************************************************** * @ingroup icp_qat_fw_dc_chain * * @description * Define the chaining request descriptor header * *****************************************************************************/ typedef struct icp_qat_comp_chain_req_hdr_s { /* LW0 */ Cpa8U resrvd1; /* Reserved field */ Cpa8U service_cmd_id; /* Service Command Id - this field is service-specific * valid value are in enum icp_qat_comp_chain_cmd_id_t * except ICP_QAT_FW_NO_CHAINING */ Cpa8U service_type; /* Service type */ Cpa8U hdr_flags; /* This represents a flags field for the Service Request. * The most significant bit is the 'valid' flag and the only * one used. All remaining bit positions are unused and * are therefore reserved and need to be set to 0. */ /* LW1 */ Cpa16U numLinks; /* Number of links for chaining request */ } icp_qat_comp_chain_req_hdr_t; /** *************************************************************************** * @ingroup icp_qat_fw_dc_chain * Request data for chaining QAT messages * * @description * This structure defines the request data for chaining QAT messages. This * is used to store data which is known when the message is sent and which we * wish to retrieve when the response message is processed. **************************************************************************/ typedef struct icp_qat_fw_comp_chain_req_s { icp_qat_comp_chain_req_hdr_t hdr; /* Chaining request header */ Cpa16U extendFlags; /* Extend flags for CBC, CNV, ASB */ Cpa32U resrvd1[4]; Cpa64U opaque_data; /* Chaining cookie pointer */ Cpa32U resrvd2[8]; Cpa64U compReqAddr; /* Physical address for compression request */ Cpa64U compRespAddr; /* Physical address for compression response */ Cpa64U symCryptoReqAddr; /* Physical address for symmetric crypto request */ Cpa64U symCryptoRespAddr; /* Physical address for symmetric crypto response */ Cpa32U resrvd3[8]; } icp_qat_fw_comp_chain_req_t; /** *************************************************************************** * @ingroup icp_qat_fw_dc_chain * Request data for chaining Stor2 QAT messages * * @description * This structure defines the request data for chaining QAT messages. This * is used to store data which is known when the message is sent and which we * wish to retrieve when the response message is processed. **************************************************************************/ typedef struct icp_qat_fw_chain_stor2_req_s { /**< LWs 0-1 */ icp_qat_fw_comn_req_hdr_t comn_hdr; /**< Common request header - for Service Command Id, * use service-specific Chain Command Id. * Service Specific Flags - use Chain Command Flags */ /**< LWs 2-5 */ icp_qat_fw_comn_req_hdr_cd_pars_t cd_pars; /**< Common Request content descriptor field which points either to a * content descriptor * parameter block or contains the service-specific data itself. */ /**< LWs 6-13 */ icp_qat_fw_comn_req_mid_t comn_mid; /**< Common request middle section */ /**< LWs 14-15 */ Cpa32U resrvd3[2]; /**< LWs 16-23 */ Cpa64U compReqAddr; /* Physical address for compression request */ Cpa64U compRespAddr; /* Physical address for compression response */ Cpa64U symCryptoReqAddr; /* Physical address for symmetric crypto request */ Cpa64U symCryptoRespAddr; /* Physical address for symmetric crypto response */ /**< LWs 24-31 */ Cpa32U resrvd4[8]; } icp_qat_fw_chain_stor2_req_t; /** ***************************************************************************** * @ingroup icp_qat_fw_dc_chain * * @description * Define the chaining response format * *****************************************************************************/ typedef struct icp_qat_fw_comp_chain_resp_s { Cpa8U resrvd0; Cpa8U cmdID; /* Chaining Command id */ Cpa8U serviceType; /* Chaining service type */ Cpa8U valid; Cpa16U resrvd1; Cpa8U rspStatus; /* Response status */ Cpa8U chainCmdID; /* Chaining Command id */ Cpa64U opaque_data; /* * Opaque data pointer, it's a copy of the callback data * passed when the request was created */ Cpa32U numLinks; /* Number of links in chain */ Cpa32U resrvd2[3]; } icp_qat_fw_comp_chain_resp_t; #endif qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw_init_admin.h000066400000000000000000000474341503624047500274200ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** ***************************************************************************** * @file icp_qat_fw_init_admin.h * @defgroup icp_qat_fw_init_admin ICP QAT FW Initialisation/Admin Interface * Definitions * @ingroup icp_qat_fw * * @description * This file documents structs used at init time in the configuration of * the QAT FW, as well as for Admin requests and responses. * *****************************************************************************/ #ifndef _ICP_QAT_FW_INIT_ADMIN_H_ #define _ICP_QAT_FW_INIT_ADMIN_H_ /* ****************************************************************************** * Include local header files ****************************************************************************** */ #include "icp_qat_fw.h" #define ICP_QAT_NUM_THREADS 8 /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * Definition of the init time and admin command types * @description * Enumeration which is used to indicate the ids of Init/Admin commands * *****************************************************************************/ typedef enum { ICP_QAT_FW_INIT_ME = 0, /**< ME Initialisation command type */ ICP_QAT_FW_TRNG_ENABLE = 1, /**< TRNG Enable command type */ ICP_QAT_FW_TRNG_DISABLE = 2, /**< TRNG Disable command type */ ICP_QAT_FW_CONSTANTS_CFG = 3, /**< Constants configuration command type */ ICP_QAT_FW_STATUS_GET = 4, /**< Admin: Status Get command type */ ICP_QAT_FW_COUNTERS_GET = 5, /**< Admin: Counters Get command type */ ICP_QAT_FW_LOOPBACK = 6, /**< Admin: Loopback command type */ ICP_QAT_FW_HEARTBEAT_SYNC = 7, /**< Admin: Heartbeat Sync command type */ ICP_QAT_FW_HEARTBEAT_GET = 8, /**< Admin: Heartbeat Get command type */ ICP_QAT_FW_COMP_CAPABILITY_GET = 9, /**< Admin: Compression Capability Get command type */ ICP_QAT_FW_CRYPTO_CAPABILITY_GET = 10, /**< Admin: Compression Crypto Get command type */ ICP_QAT_FW_HEARTBEAT_CONFIG_WR = 13, /**< Admin: Heartbeat Config Update command type */ } icp_qat_fw_init_admin_cmd_id_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * Definition of Init/Admin Response status * @description * Enumeration which is used to indicate the possible values of the status * field within an Init/Admin Response message. * *****************************************************************************/ typedef enum { ICP_QAT_FW_INIT_RESP_STATUS_SUCCESS = 0, /**< ME Initialisation/Admin response indication successful status */ ICP_QAT_FW_INIT_RESP_STATUS_FAIL = 1, /**< ME Initialisation/Admin response indication failure status */ ICP_QAT_FW_INIT_RESP_STATUS_UNSUPPORTED = 4 /**< ME Initialisation/Admin response indication failure status */ } icp_qat_fw_init_admin_resp_status_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * QAT FW Init/Admin request message * @description * This struct contains data needed to generate a init/admin request * *****************************************************************************/ typedef struct icp_qat_fw_init_admin_req_s { /**< LW0 */ uint16_t init_cfg_sz; /**< Initialisation config size */ uint8_t resrvd1; /**< Reserved field */ uint8_t init_admin_cmd_id; /**< Init/Admin time command that is described in the request */ /**< LW1 */ uint32_t resrvd2; /**< Reserved field -to keep 64-bit ptr alignment */ /**< LWs 2-3 */ uint64_t opaque_data; /**< LWs 4-5 */ uint64_t init_cfg_ptr; /**< Pointer to configuration data */ /**< LW 6 */ uint16_t ibuf_size_in_kb; /**< Size in KB of internal buffers used to optimize dynamic * compression, or 0 to select the default */ uint16_t resrvd3; /**< Reserved */ /**< LW 7 */ uint32_t resrvd4; /**< Reserved */ } icp_qat_fw_init_admin_req_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * QAT FW Init/Admin response header * @description * Structure containing the data for the Initialisation/Admin Response * message header. * *****************************************************************************/ typedef struct icp_qat_fw_init_admin_resp_hdr_s { /**< LW0 */ uint8_t flags; /**< Flags field */ uint8_t resrvd1; /**< Reserved field */ uint8_t status; /**< Status field */ uint8_t init_admin_cmd_id; /**< Init/Admin time command that is described in the request */ } icp_qat_fw_init_admin_resp_hdr_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * QAT FW Init/Admin response header for fw capability * @description * Structure containing the data for the Initialisation/Admin Response * message header. * *****************************************************************************/ typedef struct icp_qat_fw_init_admin_fw_capability_resp_hdr_s { /**< LW0 */ uint16_t reserved; /**< Reserved */ uint8_t status; /**< Status field */ uint8_t init_admin_cmd_id; /**< Init/Admin time command that is described in the request */ } icp_qat_fw_init_admin_fw_capability_resp_hdr_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * QAT FW Init/Admin response for fw capability compression and crypto * @description * This struct contains data needed to generate a init/admin response * *****************************************************************************/ typedef struct icp_qat_fw_init_admin_capability_resp_s { /**< LW0 */ icp_qat_fw_init_admin_fw_capability_resp_hdr_t init_resp_hdr; /**< Initialisation/Admin response header */ /**< LW1 */ uint32_t extended_features; /**< Extended feature field */ /**< LWs 2-3 */ uint64_t opaque_data; /**< LWs 4-7 */ union { /**< Specific to a compression capability response only */ struct { uint16_t compression_algos; /**< QAT FW supported Compression algorithms */ uint16_t checksum_algos; /**< QAT FW supported Checksum algorithms */ uint32_t deflate_capabilities; /**< QAT FW supported Deflate capabilities */ uint16_t lz4_capabilities; /**< QAT FW supported LZ4 capabilities */ uint16_t resrvd1; /**< Reserved capabilities */ uint16_t lz4s_capabilities; /**< QAT FW supported LZ4S capabilities */ uint16_t resrvd2; /**< Reserved field for future expansion */ } compression; /**< Specific to a crypto capability response only */ struct { uint32_t cipher_algos; /**< QAT FW supported Cipher algorithms */ uint32_t hash_algos; /**< QAT FW supported Hash algorithms */ uint16_t keygen_algos; /**< QAT FW supported Key Generation algorithms */ uint16_t other; /**< QAT FW other capabilities */ uint16_t public_key_algos; /**< QAT FW supported Public Key algorithms */ uint16_t prime_algos; /**< QAT FW supported Prime algorithms */ } crypto; }; } icp_qat_fw_init_admin_capability_resp_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * QAT FW Init/Admin response Parameters * @description * Structure containing the data for the Initialisation/Admin Response * message Parameters field. * *****************************************************************************/ typedef struct icp_qat_fw_init_admin_resp_pars_s { /**< LWs 4-7 */ union { uint32_t resrvd1[ICP_QAT_FW_NUM_LONGWORDS_4]; /**< Reserved fields - unused by all init admin common responses */ /**< Specific to an Admin Status Get Response only */ struct { uint32_t version_patch_num; /**< QAT FW build patch number */ uint8_t context_id; /**< Context id of the context that serviced the status request */ uint8_t ae_id; /**< id of the acceleration engine that serviced the status request */ uint16_t resrvd1; /**< Reserved field */ uint64_t resrvd2; /**< Now a reserved field */ } s1; /**< Specific to an Admin Counters Get Response only */ struct { uint64_t req_rec_count; /**< Request received count */ uint64_t resp_sent_count; /**< Response sent count */ } s2; } u; } icp_qat_fw_init_admin_resp_pars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * QAT FW Init/Admin response for heartbeat counter response * @description * This struct contains data needed to generate a init/admin response * *****************************************************************************/ typedef struct icp_qat_fw_init_admin_hb_cnt_s { uint16_t resp_heartbeat_cnt; /**< Heartbeat response count */ uint16_t req_heartbeat_cnt; /**< Heartbeat request count */ } icp_qat_fw_init_admin_hb_cnt_t; typedef struct icp_qat_fw_init_admin_hb_stats_s { icp_qat_fw_init_admin_hb_cnt_t stats[ICP_QAT_NUM_THREADS]; } icp_qat_fw_init_admin_hb_stats_t; /** ***************************************************************************** * @ingroup icp_qat_fw_init_admin * QAT FW Init/Admin response * @description * This struct contains data needed to generate a init/admin response * *****************************************************************************/ typedef struct icp_qat_fw_init_admin_resp_s { /**< LW0 */ icp_qat_fw_init_admin_resp_hdr_t init_resp_hdr; /**< Initialisation/Admin response header */ /**< LW1 */ union { uint32_t resrvd2; /**< Reserved field - to keep 64-bit ptr alignment * - specific to all init common responses */ /**< Specific to an Admin Status Get response only */ struct { uint16_t version_minor_num; /**< QAT FW minor build number */ uint16_t version_major_num; /**< QAT FW major build number */ } s; } u; /**< LWs 2-3 */ uint64_t opaque_data; /**< LWs 4-7 */ icp_qat_fw_init_admin_resp_pars_t init_resp_pars; /**< Initialisation/Admin response parameters */ } icp_qat_fw_init_admin_resp_t; /* ========================================================================= */ /* HEARTBEAT MACROS */ /* ========================================================================= */ /**< @ingroup icp_qat_fw_init_admin * Definition of the setting of the Init-Admin response heartbeat flag to OK */ #define ICP_QAT_FW_COMN_HEARTBEAT_OK 0 /**< @ingroup icp_qat_fw_init_admin * Definition of the setting of the Init-Admin response heartbeat flag to BLOCKED */ #define ICP_QAT_FW_COMN_HEARTBEAT_BLOCKED 1 /**< @ingroup icp_qat_fw_init_admin * Macros defining the bit position and mask of the Init-Admin response heartbeat flag within the flags field */ #define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS 0 #define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK 0x1 #define ICP_QAT_FW_COMN_STATUS_RESRVD_FLD_MASK 0xFE /** ****************************************************************************** * @ingroup icp_qat_fw_init_admin * * @description * Extract the heartbeat flag from the Init-Admin response header * structure. * * @param hdr_t Response header structure 'icp_qat_fw_init_admin_resp_hdr_t'. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_GET(hdr_t) \ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(hdr_t.flags) /** ****************************************************************************** * @ingroup icp_qat_fw_init_admin * * @description * Extract the heartbeat flag from the Init-Admin response header * structure. * * @param hdr_t Response header structure 'icp_qat_fw_init_admin_resp_hdr_t'. * Value of the heartbeat flag. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_SET(hdr_t, val) \ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_SET(hdr_t, val) /** ****************************************************************************** * @ingroup icp_qat_fw_init_admin * * @description * Extract the heartbeat flag from the Init-Admin response header structure * status field. * * @param hdr_t Status flags field. * *****************************************************************************/ #define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(flags) \ QAT_FIELD_GET(flags, \ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS, \ ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK) /* ========================================================================= */ /* FW CAPABILITY DEFINES */ /* ========================================================================= */ /* Compression */ #define ICP_QAT_FW_CAP_COMP_EXT_CNV_BITPOS 0 #define ICP_QAT_FW_CAP_COMP_COMPRESSION_DEFLATE_BITPOS 0 #define ICP_QAT_FW_CAP_COMP_CHECKSUM_CRC32_BITPOS 0 #define ICP_QAT_FW_CAP_COMP_CHECKSUM_ADLER_BITPOS 1 #define ICP_QAT_FW_CAP_COMP_DEFLATE_COMPRESS_BITPOS 0 #define ICP_QAT_FW_CAP_COMP_DEFLATE_DECOMPRESS_BITPOS 1 #define ICP_QAT_FW_CAP_COMP_DEFLATE_STATEFUL_BITPOS 2 #define ICP_QAT_FW_CAP_COMP_DEFLATE_STATELESS_BITPOS 3 #define ICP_QAT_FW_CAP_COMP_DEFLATE_DYNAMIC_HUFFMAN_BITPOS 8 #define ICP_QAT_FW_CAP_COMP_DEFLATE_PRECOMP_HUFFMAN_BITPOS 9 #define ICP_QAT_FW_CAP_COMP_DEFLATE_DYN_HUFFMAN_BUFFER_BITPOS 10 #define ICP_QAT_FW_CAP_COMP_DEFLATE_AUTO_SELECT_BEST_BITPOS 11 #define ICP_QAT_FW_CAP_COMP_DEFLATE_END_OF_LAST_BLOCK_BITPOS 12 /* Cryptography */ #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_NULL_BITPOS 0 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_ARC4_BITPOS 1 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_AES_ECB_BITPOS 2 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_AES_CBC_BITPOS 3 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_AES_CTR_BITPOS 4 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_AES_CCM_BITPOS 5 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_AES_GCM_BITPOS 6 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_DES_ECB_BITPOS 7 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_DES_CBC_BITPOS 8 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_3DES_ECB_BITPOS 9 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_3DES_CBC_BITPOS 10 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_3DES_CTR_BITPOS 11 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_KASUMI_F8_BITPOS 12 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_SNOW3G_UEA2_BITPOS 13 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_AES_F8_BITPOS 14 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_AES_XTS_BITPOS 15 #define ICP_QAT_FW_CAP_CRYPTO_CIPHER_ZUC_EEA3_BITPOS 16 #define ICP_QAT_FW_CAP_CRYPTO_HASH_MD5_BITPOS 0 #define ICP_QAT_FW_CAP_CRYPTO_HASH_SHA1_BITPOS 1 #define ICP_QAT_FW_CAP_CRYPTO_HASH_SHA224_BITPOS 2 #define ICP_QAT_FW_CAP_CRYPTO_HASH_SHA256_BITPOS 3 #define ICP_QAT_FW_CAP_CRYPTO_HASH_SHA384_BITPOS 4 #define ICP_QAT_FW_CAP_CRYPTO_HASH_SHA512_BITPOS 5 #define ICP_QAT_FW_CAP_CRYPTO_HASH_AES_XCBC_BITPOS 6 #define ICP_QAT_FW_CAP_CRYPTO_HASH_AES_CCM_BITPOS 7 #define ICP_QAT_FW_CAP_CRYPTO_HASH_AES_GCM_BITPOS 8 #define ICP_QAT_FW_CAP_CRYPTO_HASH_KASUMI_F9_BITPOS 9 #define ICP_QAT_FW_CAP_CRYPTO_HASH_SNOW3G_UIA2_BITPOS 10 #define ICP_QAT_FW_CAP_CRYPTO_HASH_AES_CMAC_BITPOS 11 #define ICP_QAT_FW_CAP_CRYPTO_HASH_AES_GMAC_BITPOS 12 #define ICP_QAT_FW_CAP_CRYPTO_HASH_AES_CBCMAC_BITPOS 13 #define ICP_QAT_FW_CAP_CRYPTO_HASH_ZUC_EIA3_BITPOS 14 #define ICP_QAT_FW_CAP_CRYPTO_HASH_SHA3_256_BITPOS 15 #define ICP_QAT_FW_CAP_CRYPTO_KEYGEN_MGF1_BITPOS 0 #define ICP_QAT_FW_CAP_CRYPTO_KEYGEN_SSL_PRF_BITPOS 1 #define ICP_QAT_FW_CAP_CRYPTO_KEYGEN_TLS10_PRF_BITPOS 2 #define ICP_QAT_FW_CAP_CRYPTO_KEYGEN_TLS12_PRF_BITPOS 3 #define ICP_QAT_FW_CAP_CRYPTO_OTHER_STATEFUL_BITPOS 0 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_RSA_BITPOS 0 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_DH_BITPOS 1 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_DSA_BITPOS 2 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_LN_BITPOS 3 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_ECDH_BITPOS 4 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_ECDSA_BITPOS 5 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_EC_BITPOS 6 #define ICP_QAT_FW_CAP_CRYPTO_PUBLIC_KEY_ECSM2_BITPOS 7 #define ICP_QAT_FW_CAP_CRYPTO_PRIME_GDC_BITPOS 0 #define ICP_QAT_FW_CAP_CRYPTO_PRIME_FERMAT_BITPOS 1 #define ICP_QAT_FW_CAP_CRYPTO_PRIME_MILLERRABIN_BITPOS 2 #define ICP_QAT_FW_CAP_CRYPTO_PRIME_LUCAS_BITPOS 3 #endif /* _ICP_QAT_FW_INIT_ADMIN_H_ */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw_la.h000066400000000000000000002671711503624047500257030ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** ***************************************************************************** * @file icp_qat_fw_la.h * @defgroup icp_qat_fw_la ICP QAT FW Lookaside Service Interface Definitions * @ingroup icp_qat_fw * @description * This file documents structs used to provided the interface to the * LookAside (LA) QAT FW service * *****************************************************************************/ #ifndef _ICP_QAT_FW_LA_H_ #define _ICP_QAT_FW_LA_H_ /* ****************************************************************************** * Include local header files ****************************************************************************** */ #include "icp_qat_fw.h" /* ========================================================================= */ /* QAT FW REQUEST STRUCTURES */ /* ========================================================================= */ /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the LookAside (LA) command types * @description * Enumeration which is used to indicate the ids of functions * that are exposed by the LA QAT FW service * *****************************************************************************/ typedef enum { ICP_QAT_FW_LA_CMD_CIPHER = 0, /*!< Cipher Request */ ICP_QAT_FW_LA_CMD_AUTH = 1, /*!< Auth Request */ ICP_QAT_FW_LA_CMD_CIPHER_HASH = 2, /*!< Cipher-Hash Request */ ICP_QAT_FW_LA_CMD_HASH_CIPHER = 3, /*!< Hash-Cipher Request */ ICP_QAT_FW_LA_CMD_TRNG_GET_RANDOM = 4, /*!< TRNG Get Random Request */ ICP_QAT_FW_LA_CMD_TRNG_TEST = 5, /*!< TRNG Test Request */ ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE = 6, /*!< SSL3 Key Derivation Request */ ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE = 7, /*!< TLS Key Derivation Request */ ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE = 8, /*!< TLS Key Derivation Request */ ICP_QAT_FW_LA_CMD_MGF1 = 9, /*!< MGF1 Request */ ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP = 10, /*!< Auth Pre-Compute Request */ ICP_QAT_FW_LA_CMD_CIPHER_PRE_COMP = 11, /*!< Auth Pre-Compute Request */ ICP_QAT_FW_LA_CMD_HKDF_EXTRACT = 12, /*!< HKDF Extract Request */ ICP_QAT_FW_LA_CMD_HKDF_EXPAND = 13, /*!< HKDF Expand Request */ ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND = 14, /*!< HKDF Extract and Expand Request */ ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL = 15, /*!< HKDF Expand Label Request */ ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL = 16, /*!< HKDF Extract and Expand Label Request */ ICP_QAT_FW_LA_CMD_DELIMITER = 17 /**< Delimiter type */ } icp_qat_fw_la_cmd_id_t; /* For the definitions of the bits in the status field of the common * response, refer to icp_qat_fw.h. * The return values specific to Lookaside service are given below. */ #define ICP_QAT_FW_LA_ICV_VER_STATUS_PASS ICP_QAT_FW_COMN_STATUS_FLAG_OK /**< @ingroup icp_qat_fw_la * Status flag indicating that the ICV verification passed */ #define ICP_QAT_FW_LA_ICV_VER_STATUS_FAIL ICP_QAT_FW_COMN_STATUS_FLAG_ERROR /**< @ingroup icp_qat_fw_la * Status flag indicating that the ICV verification failed */ #define ICP_QAT_FW_LA_TRNG_STATUS_PASS ICP_QAT_FW_COMN_STATUS_FLAG_OK /**< @ingroup icp_qat_fw_la * Status flag indicating that the TRNG returned valid entropy data */ #define ICP_QAT_FW_LA_TRNG_STATUS_FAIL ICP_QAT_FW_COMN_STATUS_FLAG_ERROR /**< @ingroup icp_qat_fw_la * Status flag indicating that the TRNG Command Failed. */ /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the common LA QAT FW bulk request * @description * Definition of the full bulk processing request structure. * Used for hash, cipher, hash-cipher and authentication-encryption * requests etc. * *****************************************************************************/ typedef struct icp_qat_fw_la_bulk_req_s { /**< LWs 0-1 */ icp_qat_fw_comn_req_hdr_t comn_hdr; /**< Common request header - for Service Command Id, * use service-specific Crypto Command Id. * Service Specific Flags - use Symmetric Crypto Command Flags * (all of cipher, auth, SSL3, TLS and MGF, * excluding TRNG - field unused) */ /**< LWs 2-5 */ icp_qat_fw_comn_req_hdr_cd_pars_t cd_pars; /**< Common Request content descriptor field which points either to a * content descriptor * parameter block or contains the service-specific data itself. */ /**< LWs 6-13 */ icp_qat_fw_comn_req_mid_t comn_mid; /**< Common request middle section */ /**< LWs 14-26 */ icp_qat_fw_comn_req_rqpars_t serv_specif_rqpars; /**< Common request service-specific parameter field */ /**< LWs 27-31 */ icp_qat_fw_comn_req_cd_ctrl_t cd_ctrl; /**< Common request content descriptor control block - * this field is service-specific */ } icp_qat_fw_la_bulk_req_t; /* * LA BULK (SYMMETRIC CRYPTO) COMMAND FLAGS * In common message it is named as SERVICE SPECIFIC FLAGS. * * + ===== + ---------- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + * | Bit | [15:13] | 12 | 11 | 10 | 7-9 | 6 | 5 | 4 | 3 | 2 | 1-0 | * + ===== + ---------- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------+ ----- + * | Flags | Resvd Bits | ZUC | GcmIV |Digest | Prot | Cmp | Rtn | Upd | Ciph/ | CiphIV| Part- | * | | =0 | Prot | Len | In Buf| flgs | Auth | Auth | State | Auth | Field | ial | * + ===== + ---------- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ----- + ------+ ----- + */ /* Private defines */ /* bits 15:14 */ #define ICP_QAT_FW_LA_USE_WIRELESS_SLICE_TYPE 2 /**< @ingroup icp_qat_fw_la * FW Selects Wireless Cipher Slice * Cipher Algorithms: AES-{F8}, Snow3G, ZUC * Auth Algorithms : Snow3G, ZUC */ #define ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE 1 /**< @ingroup icp_qat_fw_la * FW Selects UCS Cipher Slice * Cipher Algorithms: AES-{CTR/XTS}, Single Pass AES-GCM * Auth Algorithms : SHA1/ SHA{2/3}-{224/256/384/512} */ #define ICP_QAT_FW_LA_USE_LEGACY_SLICE_TYPE 0 /**< @ingroup icp_qat_fw_la * FW Selects Legacy Cipher/Auth Slice * Cipher Algorithms: AES-{CBC/ECB}, SM4, Single Pass AES-CCM * Auth Algorithms : SHA1/ SHA{2/3}-{224/256/384/512} */ #define QAT_LA_SLICE_TYPE_BITPOS 14 /**< @ingroup icp_qat_fw_la * Starting bit position for the slice type selection. * Refer to HAS for Slice type assignment details on QAT2.0 */ #define QAT_LA_SLICE_TYPE_MASK 0x3 /**< @ingroup icp_qat_fw_la * Two bit mask used to determine the Slice type */ /* bit 11 */ #define ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS 1 /**< @ingroup icp_qat_fw_la * Indicates the IV Length for GCM protocol is 96 Bits (12 Octets) * If set FW does the padding to compute CTR0 */ #define ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS 0 /**< @ingroup icp_qat_fw_la * Indicates the IV Length for GCM protocol is not 96 Bits (12 Octets) * If IA computes CTR0 */ #define QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS 12 /**< @ingroup icp_cpm_fw_la * Bit position defining ZUC processing for a encrypt command */ #define ICP_QAT_FW_LA_ZUC_3G_PROTO 1 /**< @ingroup icp_cpm_fw_la * Value indicating ZUC processing for a encrypt command */ #define QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the ZUC 3G protocol bit. * Must be set for Cipher-only, Cipher + Auth and Auth-only */ #define QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_BITPOS 13 /**< @ingroup icp_cpm_fw_la * Bit position defining SINGLE PASS processing for a encrypt command */ #define ICP_QAT_FW_LA_SINGLE_PASS_PROTO 1 /**< @ingroup icp_cpm_fw_la * Value indicating SINGLE PASS processing for a encrypt command */ #define QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the SINGLE PASS protocol bit. * Must be set for Cipher-only */ #define QAT_LA_GCM_IV_LEN_FLAG_BITPOS 11 /**< @ingroup icp_qat_fw_la * Starting bit position for GCM IV Length indication. If set * the IV Length is 96 Bits, clear for other IV lengths */ #define QAT_LA_GCM_IV_LEN_FLAG_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the GCM IV Length indication bit. * If set the IV Length is 96 Bits, clear for other IV lengths */ /* bit 10 */ #define ICP_QAT_FW_LA_DIGEST_IN_BUFFER 1 /**< @ingroup icp_qat_fw_la * Flag representing that authentication digest is stored or is extracted * from the source buffer. Auth Result Pointer will be ignored in this case. */ #define ICP_QAT_FW_LA_NO_DIGEST_IN_BUFFER 0 /**< @ingroup icp_qat_fw_la * Flag representing that authentication digest is NOT stored or is NOT * extracted from the source buffer. Auth result will get stored or extracted * from the Auth Result Pointer. Please not that in this case digest CANNOT be * encrypted. */ #define QAT_LA_DIGEST_IN_BUFFER_BITPOS 10 /**< @ingroup icp_qat_fw_la * Starting bit position for Digest in Buffer flag */ #define QAT_LA_DIGEST_IN_BUFFER_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the Digest in Buffer flag */ /* bits 7-9 */ #define ICP_QAT_FW_LA_SNOW_3G_PROTO 4 /**< @ingroup icp_cpm_fw_la * Indicates SNOW_3G processing for a encrypt command */ #define ICP_QAT_FW_LA_GCM_PROTO 2 /**< @ingroup icp_qat_fw_la * Indicates GCM processing for a auth_encrypt command */ #define ICP_QAT_FW_LA_CCM_PROTO 1 /**< @ingroup icp_qat_fw_la * Indicates CCM processing for a auth_encrypt command */ #define ICP_QAT_FW_LA_NO_PROTO 0 /**< @ingroup icp_qat_fw_la * Indicates no specific protocol processing for the command */ #define QAT_LA_PROTO_BITPOS 7 /**< @ingroup icp_qat_fw_la * Starting bit position for the Lookaside Protocols */ #define QAT_LA_PROTO_MASK 0x7 /**< @ingroup icp_qat_fw_la * Three bit mask used to determine the Lookaside Protocol */ /* bit 6 */ #define ICP_QAT_FW_LA_CMP_AUTH_RES 1 /**< @ingroup icp_qat_fw_la * Flag representing the need to compare the auth result data to the expected * value in DRAM at the auth_address. */ #define ICP_QAT_FW_LA_NO_CMP_AUTH_RES 0 /**< @ingroup icp_qat_fw_la * Flag representing that there is no need to do a compare of the auth data * to the expected value */ #define QAT_LA_CMP_AUTH_RES_BITPOS 6 /**< @ingroup icp_qat_fw_la * Starting bit position for Auth compare digest result */ #define QAT_LA_CMP_AUTH_RES_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the Auth compare digest result */ /* bit 5 */ #define ICP_QAT_FW_LA_RET_AUTH_RES 1 /**< @ingroup icp_qat_fw_la * Flag representing the need to return the auth result data to dram after the * request processing is complete */ #define ICP_QAT_FW_LA_NO_RET_AUTH_RES 0 /**< @ingroup icp_qat_fw_la * Flag representing that there is no need to return the auth result data */ #define QAT_LA_RET_AUTH_RES_BITPOS 5 /**< @ingroup icp_qat_fw_la * Starting bit position for Auth return digest result */ #define QAT_LA_RET_AUTH_RES_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the Auth return digest result */ /* bit 4 */ #define ICP_QAT_FW_LA_UPDATE_STATE 1 /**< @ingroup icp_qat_fw_la * Flag representing the need to update the state data in dram after the * request processing is complete */ #define ICP_QAT_FW_LA_NO_UPDATE_STATE 0 /**< @ingroup icp_qat_fw_la * Flag representing that there is no need to update the state data */ #define QAT_LA_UPDATE_STATE_BITPOS 4 /**< @ingroup icp_qat_fw_la * Starting bit position for Update State. */ #define QAT_LA_UPDATE_STATE_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the Update State */ /* bit 3 */ #define ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_CD_SETUP 0 /**< @ingroup icp_qat_fw_la * Flag representing Cipher/Auth Config Offset Type, where the offset * is contained in CD Setup. When the SHRAM constants page * is not used for cipher/auth configuration, then the Content Descriptor * pointer field must be a pointer (as opposed to a 16-byte key), since * the block pointed to must contain both the slice config and the key */ #define ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_SHRAM_CP 1 /**< @ingroup icp_qat_fw_la * Flag representing Cipher/Auth Config Offset Type, where the offset * is contained in SHRAM constants page. */ #define QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS 3 /**< @ingroup icp_qat_fw_la * Starting bit position indicating Cipher/Auth Config * offset type */ #define QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine Cipher/Auth Config * offset type */ /* bit 2 */ #define ICP_QAT_FW_CIPH_IV_64BIT_PTR 0 /**< @ingroup icp_qat_fw_la * Flag representing Cipher IV field contents via 64-bit pointer */ #define ICP_QAT_FW_CIPH_IV_16BYTE_DATA 1 /**< @ingroup icp_qat_fw_la * Flag representing Cipher IV field contents as 16-byte data array */ #define QAT_LA_CIPH_IV_FLD_BITPOS 2 /**< @ingroup icp_qat_fw_la * Starting bit position indicating Cipher IV field * contents */ #define QAT_LA_CIPH_IV_FLD_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the Cipher IV field * contents */ /* bits 0-1 */ #define ICP_QAT_FW_LA_PARTIAL_NONE 0 /**< @ingroup icp_qat_fw_la * Flag representing no need for partial processing condition i.e. * entire packet processed in the current command */ #define ICP_QAT_FW_LA_PARTIAL_START 1 /**< @ingroup icp_qat_fw_la * Flag representing the first chunk of the partial packet */ #define ICP_QAT_FW_LA_PARTIAL_MID 3 /**< @ingroup icp_qat_fw_la * Flag representing a middle chunk of the partial packet */ #define ICP_QAT_FW_LA_PARTIAL_END 2 /**< @ingroup icp_qat_fw_la * Flag representing the final/end chunk of the partial packet */ #define QAT_LA_PARTIAL_BITPOS 0 /**< @ingroup icp_qat_fw_la * Starting bit position indicating partial state */ #define QAT_LA_PARTIAL_MASK 0x3 /**< @ingroup icp_qat_fw_la * Two bit mask used to determine the partial state */ /* * LA BULK (SYMMETRIC CRYPTO) EXTENDED COMMAND FLAGS * * + ===== + --- + --- + --- + --- + --- + --- + --- + ---- + * | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * + ===== + --- + --- + --- + --- + --- + --- + --- + ---- + * | Flags | Rsv | Rsv | Rsv | Rsv | WAT | WCP | Rsv | Ext | * | | | | | | | | | Prot | * | | | | | | | | | Flags| * + ===== + --- + --- + --- + --- + --- + --- + --- + ---- + */ /* Private defines */ #define QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS_BITPOS 0 /**< @ingroup icp_cpm_fw_la * Bit position defining the Extended Protocol Flags mode */ #define QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS 1 /**< @ingroup icp_cpm_fw_la * Value indicating the use of Extended Protocol Flags */ #define QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the use of Extended Protocol Flags. */ #define QAT_LA_USE_WCP_SLICE_BITPOS 2 /**< @ingroup icp_cpm_fw_la * Bit position defining the Wireless Cipher (WCP) slice flag */ #define QAT_LA_USE_WCP_SLICE 1 /**< @ingroup icp_cpm_fw_la * Value indicating the use of the Wireless Cipher (WCP) slice */ #define QAT_LA_USE_WCP_SLICE_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the use of the Wireless Cipher (WCP) slice */ #define QAT_LA_USE_WAT_SLICE_BITPOS 3 /**< @ingroup icp_cpm_fw_la * Bit position defining the Wireless Authentication (WAT) slice flag */ #define QAT_LA_USE_WAT_SLICE 1 /**< @ingroup icp_cpm_fw_la * Value indicating the use of the Wireless Authentication (WAT) slice */ #define QAT_LA_USE_WAT_SLICE_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the use of the Wireless Authentication (WAT) * slice */ /* The table below defines the meaning of the prefix_addr & hash_state_sz in * the case of partial processing. See the HLD for further details * * + ====== + ------------------------- + ----------------------- + * | Partial| Prefix Addr | Hash State Sz | * | State | | | * + ====== + ------------------------- + ----------------------- + * | FULL | Points to the prefix data | Prefix size as below. | * | | | No update of state | * + ====== + ------------------------- + ----------------------- + * | SOP | Points to the prefix | = inner prefix rounded | * | | data. State is updated | to qwrds + outer prefix | * | | at prefix_addr - state_sz | rounded to qwrds. The | * | | - 8 (counter size) | writeback state sz | * | | | comes from the CD | * + ====== + ------------------------- + ----------------------- + * | MOP | Points to the state data | State size rounded to | * | | Updated state written to | num qwrds + 8 (for the | * | | same location | counter) + inner prefix | * | | | rounded to qwrds + | * | | | outer prefix rounded to | * | | | qwrds. | * + ====== + ------------------------- + ----------------------- + * | EOP | Points to the state data | State size rounded to | * | | | num qwrds + 8 (for the | * | | | counter) + inner prefix | * | | | rounded to qwrds + | * | | | outer prefix rounded to | * | | | qwrds. | * + ====== + ------------------------- + ----------------------- + * * Notes: * * - If the EOP is set it is assumed that no state update is to be performed. * However it is the clients responsibility to set the update_state flag * correctly i.e. not set for EOP or Full packet cases. Only set for SOP and * MOP with no EOP flag * - The SOP take precedence over the MOP and EOP i.e. in the calculation of * the address to writeback the state. * - The prefix address must be on at least the 8 byte boundary */ /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro used for the generation of the Lookaside flags for a request. This * should always be used for the generation of the flags field. No direct sets * or masks should be performed on the flags data * * @param gcm_iv_len GCM IV Length indication bit * @param auth_rslt Authentication result - Digest is stored/extracted * in/from the source buffer * straight after the authenticated region * @param proto Protocol handled by a command * @param cmp_auth Compare auth result with the expected value * @param ret_auth Return auth result to the client via DRAM * @param update_state Indicate update of the crypto state information * is required * @param ciphIV Cipher IV field contents * @param ciphcfg Cipher/Auth Config offset type * @param partial Indicate if the packet is a partial part * *****************************************************************************/ #define ICP_QAT_FW_LA_FLAGS_BUILD(zuc_proto, \ gcm_iv_len, \ auth_rslt, \ proto, \ cmp_auth, \ ret_auth, \ update_state, \ ciphIV, \ ciphcfg, \ partial) \ (((zuc_proto & QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK) \ << QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS) | \ ((gcm_iv_len & QAT_LA_GCM_IV_LEN_FLAG_MASK) \ << QAT_LA_GCM_IV_LEN_FLAG_BITPOS) | \ ((auth_rslt & QAT_LA_DIGEST_IN_BUFFER_MASK) \ << QAT_LA_DIGEST_IN_BUFFER_BITPOS) | \ ((proto & QAT_LA_PROTO_MASK) << QAT_LA_PROTO_BITPOS) | \ ((cmp_auth & QAT_LA_CMP_AUTH_RES_MASK) << QAT_LA_CMP_AUTH_RES_BITPOS) | \ ((ret_auth & QAT_LA_RET_AUTH_RES_MASK) << QAT_LA_RET_AUTH_RES_BITPOS) | \ ((update_state & QAT_LA_UPDATE_STATE_MASK) \ << QAT_LA_UPDATE_STATE_BITPOS) | \ ((ciphIV & QAT_LA_CIPH_IV_FLD_MASK) << QAT_LA_CIPH_IV_FLD_BITPOS) | \ ((ciphcfg & QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK) \ << QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS) | \ ((partial & QAT_LA_PARTIAL_MASK) << QAT_LA_PARTIAL_BITPOS)) /* Macros for extracting field bits */ /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the Cipher IV field contents (bit 2) * * @param flags Flags to extract the Cipher IV field contents * *****************************************************************************/ #define ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_GET(flags) \ QAT_FIELD_GET(flags, QAT_LA_CIPH_IV_FLD_BITPOS, QAT_LA_CIPH_IV_FLD_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the Cipher/Auth Config * offset type (bit 3) * * @param flags Flags to extract the Cipher/Auth Config * offset type * *****************************************************************************/ #define ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_GET(flags) \ QAT_FIELD_GET(flags, \ QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS, \ QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the ZUC protocol bit * information (bit 11) * * @param flags Flags to extract the ZUC protocol bit * *****************************************************************************/ #define ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_GET(flags) \ QAT_FIELD_GET(flags, \ QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS, \ QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the GCM IV Len is 12 Octets / 96 Bits * information (bit 11) * * @param flags Flags to extract the GCM IV length * *****************************************************************************/ #define ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_GET(flags) \ QAT_FIELD_GET( \ flags, QAT_LA_GCM_IV_LEN_FLAG_BITPOS, QAT_LA_GCM_IV_LEN_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the LA protocol state (bits 9-7) * * @param flags Flags to extract the protocol state * *****************************************************************************/ #define ICP_QAT_FW_LA_PROTO_GET(flags) \ QAT_FIELD_GET(flags, QAT_LA_PROTO_BITPOS, QAT_LA_PROTO_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "compare auth" state (bit 6) * * @param flags Flags to extract the compare auth result state * *****************************************************************************/ #define ICP_QAT_FW_LA_CMP_AUTH_GET(flags) \ QAT_FIELD_GET(flags, QAT_LA_CMP_AUTH_RES_BITPOS, QAT_LA_CMP_AUTH_RES_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "return auth" state (bit 5) * * @param flags Flags to extract the return auth result state * *****************************************************************************/ #define ICP_QAT_FW_LA_RET_AUTH_GET(flags) \ QAT_FIELD_GET(flags, QAT_LA_RET_AUTH_RES_BITPOS, QAT_LA_RET_AUTH_RES_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "digest in buffer" state (bit 10) * * @param flags Flags to extract the digest in buffer state * *****************************************************************************/ #define ICP_QAT_FW_LA_DIGEST_IN_BUFFER_GET(flags) \ QAT_FIELD_GET( \ flags, QAT_LA_DIGEST_IN_BUFFER_BITPOS, QAT_LA_DIGEST_IN_BUFFER_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the update content state value. (bit 4) * * @param flags Flags to extract the update content state bit * *****************************************************************************/ #define ICP_QAT_FW_LA_UPDATE_STATE_GET(flags) \ QAT_FIELD_GET(flags, QAT_LA_UPDATE_STATE_BITPOS, QAT_LA_UPDATE_STATE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "partial" packet state (bits 1-0) * * @param flags Flags to extract the partial state * *****************************************************************************/ #define ICP_QAT_FW_LA_PARTIAL_GET(flags) \ QAT_FIELD_GET(flags, QAT_LA_PARTIAL_BITPOS, QAT_LA_PARTIAL_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "Use Extended Protocol Flags" value * * @param flags Extended Command Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_GET(flags) \ QAT_FIELD_GET(flags, \ QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS_BITPOS, \ QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the slice type information from the flags. * * @param flags Flags to extract the protocol state * *****************************************************************************/ #define ICP_QAT_FW_LA_SLICE_TYPE_GET(flags) \ QAT_FIELD_GET(flags, QAT_LA_SLICE_TYPE_BITPOS, QAT_LA_SLICE_TYPE_MASK) /* Macros for setting field bits */ /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the Cipher IV field contents * * @param flags Flags to set with the Cipher IV field contents * @param val Field contents indicator value * *****************************************************************************/ #define ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_LA_CIPH_IV_FLD_BITPOS, QAT_LA_CIPH_IV_FLD_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the Cipher/Auth Config * offset type * * @param flags Flags to set the Cipher/Auth Config offset type * @param val Offset type value * *****************************************************************************/ #define ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ QAT_LA_CIPH_AUTH_CFG_OFFSET_BITPOS, \ QAT_LA_CIPH_AUTH_CFG_OFFSET_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the ZUC protocol flag * * @param flags Flags to set the ZUC protocol flag * @param val Protocol value * *****************************************************************************/ #define ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ QAT_FW_LA_ZUC_3G_PROTO_FLAG_BITPOS, \ QAT_FW_LA_ZUC_3G_PROTO_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the SINGLE PASSprotocol flag * * @param flags Flags to set the SINGLE PASS protocol flag * @param val Protocol value * *****************************************************************************/ #define ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_BITPOS, \ QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the GCM IV length flag state * * @param flags Flags to set the GCM IV length flag state * @param val Protocol value * *****************************************************************************/ #define ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ QAT_LA_GCM_IV_LEN_FLAG_BITPOS, \ QAT_LA_GCM_IV_LEN_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the LA protocol flag state * * @param flags Flags to set the protocol state * @param val Protocol value * *****************************************************************************/ #define ICP_QAT_FW_LA_PROTO_SET(flags, val) \ QAT_FIELD_SET(flags, val, QAT_LA_PROTO_BITPOS, QAT_LA_PROTO_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "compare auth" flag state * * @param flags Flags to set the compare auth result state * @param val Compare Auth value * *****************************************************************************/ #define ICP_QAT_FW_LA_CMP_AUTH_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_LA_CMP_AUTH_RES_BITPOS, QAT_LA_CMP_AUTH_RES_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "return auth" flag state * * @param flags Flags to set the return auth result state * @param val Return Auth value * *****************************************************************************/ #define ICP_QAT_FW_LA_RET_AUTH_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_LA_RET_AUTH_RES_BITPOS, QAT_LA_RET_AUTH_RES_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "digest in buffer" flag state * * @param flags Flags to set the digest in buffer state * @param val Digest in buffer value * *****************************************************************************/ #define ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ QAT_LA_DIGEST_IN_BUFFER_BITPOS, \ QAT_LA_DIGEST_IN_BUFFER_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "update state" flag value * * @param flags Flags to set the update content state * @param val Update Content State flag value * *****************************************************************************/ #define ICP_QAT_FW_LA_UPDATE_STATE_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_LA_UPDATE_STATE_BITPOS, QAT_LA_UPDATE_STATE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "partial" packet flag state * * @param flags Flags to set the partial state * @param val Partial state value * *****************************************************************************/ #define ICP_QAT_FW_LA_PARTIAL_SET(flags, val) \ QAT_FIELD_SET(flags, val, QAT_LA_PARTIAL_BITPOS, QAT_LA_PARTIAL_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "Use Extended Protocol Flags" value * * @param flags Extended Command Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_USE_EXTENDED_PROTOCOL_FLAGS_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS_BITPOS, \ QAT_LA_USE_EXTENDED_PROTOCOL_FLAGS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "slice type" field in la flags * * @param flags Flags to set the slice type * @param val Value of the slice type to be set. * *****************************************************************************/ #define ICP_QAT_FW_LA_SLICE_TYPE_SET(flags, val) \ QAT_FIELD_SET(flags, val, QAT_LA_SLICE_TYPE_BITPOS, QAT_LA_SLICE_TYPE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the Wireless Cipher (WCP) slice flag to enable * extended crypto capabilities on supported platforms * * @param flags Extended Command Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_USE_WCP_SLICE_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_LA_USE_WCP_SLICE_BITPOS, QAT_LA_USE_WCP_SLICE_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the Wireless Authentication (WAT) slice flag to * enable extended crypto capabilities on supported platforms * * @param flags Extended Command Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_USE_WAT_SLICE_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_LA_USE_WAT_SLICE_BITPOS, QAT_LA_USE_WAT_SLICE_MASK) /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Cipher header Content Descriptor pars block * @description * Definition of the cipher processing header cd pars block. * The structure is a service-specific implementation of the common * 'icp_qat_fw_comn_req_hdr_cd_pars_s' structure. *****************************************************************************/ typedef union icp_qat_fw_cipher_req_hdr_cd_pars_s { /**< LWs 2-5 */ struct { uint64_t content_desc_addr; /**< Address of the content descriptor */ uint16_t content_desc_resrvd1; /**< Content descriptor reserved field */ uint8_t content_desc_params_sz; /**< Size of the content descriptor parameters in quad words. These * parameters describe the session setup configuration info for the * slices that this request relies upon i.e. the configuration word and * cipher key needed by the cipher slice if there is a request for * cipher processing. */ uint8_t content_desc_hdr_resrvd2; /**< Content descriptor reserved field */ uint32_t content_desc_resrvd3; /**< Content descriptor reserved field */ } s; struct { uint32_t cipher_key_array[ICP_QAT_FW_NUM_LONGWORDS_4]; /* Cipher Key Array */ } s1; } icp_qat_fw_cipher_req_hdr_cd_pars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Authentication header Content Descriptor pars block * @description * Definition of the authentication processing header cd pars block. *****************************************************************************/ /* Note: Authentication uses the common 'icp_qat_fw_comn_req_hdr_cd_pars_s' * structure - similarly, it is also used by SSL3, TLS and MGF. Only cipher * and cipher + authentication require service-specific implementations of * the structure */ /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Cipher + Auth header Content Descriptor pars block * @description * Definition of the cipher + auth processing header cd pars block. * The structure is a service-specific implementation of the common * 'icp_qat_fw_comn_req_hdr_cd_pars_s' structure. *****************************************************************************/ typedef union icp_qat_fw_cipher_auth_req_hdr_cd_pars_s { /**< LWs 2-5 */ struct { uint64_t content_desc_addr; /**< Address of the content descriptor */ uint16_t content_desc_resrvd1; /**< Content descriptor reserved field */ uint8_t content_desc_params_sz; /**< Size of the content descriptor parameters in quad words. These * parameters describe the session setup configuration info for the * slices that this request relies upon i.e. the configuration word and * cipher key needed by the cipher slice if there is a request for * cipher processing. */ uint8_t content_desc_hdr_resrvd2; /**< Content descriptor reserved field */ uint32_t content_desc_resrvd3; /**< Content descriptor reserved field */ } s; struct { uint32_t cipher_key_array[ICP_QAT_FW_NUM_LONGWORDS_4]; /* Cipher Key Array */ } sl; } icp_qat_fw_cipher_auth_req_hdr_cd_pars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Cipher content descriptor control block (header) * @description * Definition of the service-specific cipher control block header * structure. This header forms part of the content descriptor * block incorporating LWs 27-31, as defined by the common base * parameters structure. * *****************************************************************************/ typedef struct icp_qat_fw_cipher_cd_ctrl_hdr_s { /**< LW 27 */ uint8_t cipher_state_sz; /**< State size in quad words of the cipher algorithm used in this session. * Set to zero if the algorithm doesn't provide any state */ uint8_t cipher_key_sz; /**< Key size in quad words of the cipher algorithm used in this session */ uint8_t cipher_cfg_offset; /**< Quad word offset from the content descriptor parameters address i.e. * (content_address + (cd_hdr_sz << 3)) to the parameters for the cipher * processing */ uint8_t next_curr_id; /**< This field combines the next and current id (each four bits) - * the next id is the most significant nibble. * Next Id: Set to the next slice to pass the ciphered data through. * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through * any more slices after cipher. * Current Id: Initialised with the cipher slice type */ /**< LW 28 */ uint8_t cipher_padding_sz; /**< State padding size in quad words. Set to 0 if no padding is required. */ uint8_t resrvd1; uint16_t resrvd2; /**< Reserved bytes to bring the struct to the word boundary, used by * authentication. MUST be set to 0 */ /**< LWs 29-31 */ uint32_t resrvd3[ICP_QAT_FW_NUM_LONGWORDS_3]; /**< Reserved bytes used by authentication. MUST be set to 0 */ } icp_qat_fw_cipher_cd_ctrl_hdr_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Authentication content descriptor control block (header) * @description * Definition of the service-specific authentication control block * header structure. This header forms part of the content descriptor * block incorporating LWs 27-31, as defined by the common base * parameters structure, the first portion of which is reserved for * cipher. * *****************************************************************************/ typedef struct icp_qat_fw_auth_cd_ctrl_hdr_s { /**< LW 27 */ uint32_t resrvd1; /**< Reserved bytes, used by cipher only. MUST be set to 0 */ /**< LW 28 */ uint8_t resrvd2; /**< Reserved byte, used by cipher only. MUST be set to 0 */ uint8_t hash_flags; /**< General flags defining the processing to perform. 0 is normal * processing * and 1 means there is a nested hash processing loop to go through */ uint8_t hash_cfg_offset; /**< Quad word offset from the content descriptor parameters address to the * parameters for the auth processing */ uint8_t next_curr_id; /**< This field combines the next and current id (each four bits) - * the next id is the most significant nibble. * Next Id: Set to the next slice to pass the authentication data through. * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through * any more slices after authentication. * Current Id: Initialised with the authentication slice type */ /**< LW 29 */ uint8_t resrvd3; /**< Now a reserved field. MUST be set to 0 */ uint8_t outer_prefix_sz; /**< Size in bytes of outer prefix data */ uint8_t final_sz; /**< Size in bytes of digest to be returned to the client if requested */ uint8_t inner_res_sz; /**< Size in bytes of the digest from the inner hash algorithm */ /**< LW 30 */ uint8_t resrvd4; /**< Now a reserved field. MUST be set to zero. */ uint8_t inner_state1_sz; /**< Size in bytes of inner hash state1 data. Must be a qword multiple */ uint8_t inner_state2_offset; /**< Quad word offset from the content descriptor parameters pointer to the * inner state2 value */ uint8_t inner_state2_sz; /**< Size in bytes of inner hash state2 data. Must be a qword multiple */ /**< LW 31 */ uint8_t outer_config_offset; /**< Quad word offset from the content descriptor parameters pointer to the * outer configuration information */ uint8_t outer_state1_sz; /**< Size in bytes of the outer state1 value */ uint8_t outer_res_sz; /**< Size in bytes of digest from the outer auth algorithm */ uint8_t outer_prefix_offset; /**< Quad word offset from the start of the inner prefix data to the outer * prefix information. Should equal the rounded inner prefix size, converted * to qwords */ } icp_qat_fw_auth_cd_ctrl_hdr_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Cipher + Authentication content descriptor control block header * @description * Definition of both service-specific cipher + authentication control * block header structures. This header forms part of the content * descriptor block incorporating LWs 27-31, as defined by the common * base parameters structure. * *****************************************************************************/ typedef struct icp_qat_fw_cipher_auth_cd_ctrl_hdr_s { /**< LW 27 */ uint8_t cipher_state_sz; /**< State size in quad words of the cipher algorithm used in this session. * Set to zero if the algorithm doesn't provide any state */ uint8_t cipher_key_sz; /**< Key size in quad words of the cipher algorithm used in this session */ uint8_t cipher_cfg_offset; /**< Quad word offset from the content descriptor parameters address i.e. * (content_address + (cd_hdr_sz << 3)) to the parameters for the cipher * processing */ uint8_t next_curr_id_cipher; /**< This field combines the next and current id (each four bits) - * the next id is the most significant nibble. * Next Id: Set to the next slice to pass the ciphered data through. * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through * any more slices after cipher. * Current Id: Initialised with the cipher slice type */ /**< LW 28 */ uint8_t cipher_padding_sz; /**< State padding size in quad words. Set to 0 if no padding is required. */ uint8_t hash_flags; /**< General flags defining the processing to perform. 0 is normal * processing * and 1 means there is a nested hash processing loop to go through */ uint8_t hash_cfg_offset; /**< Quad word offset from the content descriptor parameters address to the * parameters for the auth processing */ uint8_t next_curr_id_auth; /**< This field combines the next and current id (each four bits) - * the next id is the most significant nibble. * Next Id: Set to the next slice to pass the authentication data through. * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through * any more slices after authentication. * Current Id: Initialised with the authentication slice type */ /**< LW 29 */ uint8_t resrvd1; /**< Reserved field. MUST be set to 0 */ uint8_t outer_prefix_sz; /**< Size in bytes of outer prefix data */ uint8_t final_sz; /**< Size in bytes of digest to be returned to the client if requested */ uint8_t inner_res_sz; /**< Size in bytes of the digest from the inner hash algorithm */ /**< LW 30 */ uint8_t resrvd2; /**< Now a reserved field. MUST be set to zero. */ uint8_t inner_state1_sz; /**< Size in bytes of inner hash state1 data. Must be a qword multiple */ uint8_t inner_state2_offset; /**< Quad word offset from the content descriptor parameters pointer to the * inner state2 value */ uint8_t inner_state2_sz; /**< Size in bytes of inner hash state2 data. Must be a qword multiple */ /**< LW 31 */ uint8_t outer_config_offset; /**< Quad word offset from the content descriptor parameters pointer to the * outer configuration information */ uint8_t outer_state1_sz; /**< Size in bytes of the outer state1 value */ uint8_t outer_res_sz; /**< Size in bytes of digest from the outer auth algorithm */ uint8_t outer_prefix_offset; /**< Quad word offset from the start of the inner prefix data to the outer * prefix information. Should equal the rounded inner prefix size, converted * to qwords */ } icp_qat_fw_cipher_auth_cd_ctrl_hdr_t; /* * HASH FLAGS * * + ===== + --- + --- + --- + --- + --- + --- + --- + ---- + * | Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * + ===== + --- + --- + --- + --- + --- + --- + --- + ---- + * | Flags | Rsv | Rsv |MODE2| ZUC |SNOW | Rsv | Rsv |NESTED| * | | | | |EIA3 | 3G | | | | * | | | | | |UIA2 | | | | * + ===== + --- + --- + --- + --- + --- + --- + --- + ---- + */ /* Bit 0 */ #define QAT_FW_LA_AUTH_HDR_NESTED_BITPOS 0 /**< @ingroup icp_qat_fw_comn * Bit position of the hash_flags bit to indicate the request * requires nested hashing */ #define ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED 1 /**< @ingroup icp_qat_fw_comn * Definition of the hash_flags bit of the auth_hdr to indicate the request * requires nested hashing */ #define ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED 0 /**< @ingroup icp_qat_fw_comn * Definition of the hash_flags bit of the auth_hdr for no nested hashing * required */ #define QAT_FW_LA_AUTH_HDR_NESTED_MASK 0x1 /**< @ingroup icp_qat_fw_comn * Bit mask of the hash_flags bit to indicate the request * requires nested hashing */ /* Bit 3 */ #define QAT_FW_LA_SNOW3G_UIA2_BITPOS 3 /**< @ingroup icp_cpm_fw_la * Bit position defining hash algorithm Snow3g-UIA2 */ #define QAT_FW_LA_SNOW3G_UIA2 1 /**< @ingroup icp_cpm_fw_la * Value indicating the use of hash algorithm Snow3g-UIA2 */ #define QAT_FW_LA_SNOW3G_UIA2_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the use of hash algorithm Snow3g-UIA2 */ /* Bit 4 */ #define QAT_FW_LA_ZUC_EIA3_BITPOS 4 /**< @ingroup icp_cpm_fw_la * Bit position defining hash algorithm ZUC-EIA3 */ #define QAT_FW_LA_ZUC_EIA3 1 /**< @ingroup icp_cpm_fw_la * Value indicating the use of hash algorithm ZUC-EIA3 */ #define QAT_FW_LA_ZUC_EIA3_MASK 0x1 /**< @ingroup icp_qat_fw_la * One bit mask used to determine the use of hash algorithm ZUC-EIA3 */ /* Bit 5 */ #define QAT_FW_LA_MODE2_BITPOS 5 /**< @ingroup icp_qat_fw_comn * Bit position of the Mode 2 bit */ #define QAT_FW_LA_MODE2 1 /**< @ingroup icp_qat_fw_comn * Value indicating the Mode 2*/ #define QAT_FW_LA_NO_MODE2 0 /**< @ingroup icp_qat_fw_comn * Value indicating the no Mode 2*/ #define QAT_FW_LA_MODE2_MASK 0x1 /**< @ingroup icp_qat_fw_comn * Bit mask of Mode 2 */ /* Macros for extracting hash flags */ /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "Nested" hash flag * * @param flags Hash Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_GET(flags) \ QAT_FIELD_GET(flags, \ QAT_FW_LA_AUTH_HDR_NESTED_BITPOS, \ QAT_FW_LA_AUTH_HDR_NESTED_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "Snow3g-UIA2" hash flag * * @param flags Hash Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_SNOW3G_UIA2_GET(flags) \ QAT_FIELD_GET( \ flags, QAT_FW_LA_SNOW3G_UIA2_BITPOS, QAT_FW_LA_SNOW3G_UIA2_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "ZUC-EIA3" hash flag * * @param flags Hash Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_ZUC_EIA3_GET(flags) \ QAT_FIELD_GET(flags, QAT_FW_LA_ZUC_EIA3_BITPOS, QAT_FW_LA_ZUC_EIA3_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the "Mode 2" hash flag * * @param flags Hash Flags * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_MODE2_GET(flags) \ QAT_FIELD_GET(flags, QAT_FW_LA_MODE2_BITPOS, QAT_FW_LA_MODE2_MASK) /* Macros for setting hash flags */ /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "Nested" hash flag * * @param flags Hash Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET(flags, val) \ QAT_FIELD_SET(flags, \ val, \ QAT_FW_LA_AUTH_HDR_NESTED_BITPOS, \ QAT_FW_LA_AUTH_HDR_NESTED_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "Snow3g-UIA2" hash flag * * @param flags Hash Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_SNOW3G_UIA2_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_FW_LA_SNOW3G_UIA2_BITPOS, QAT_FW_LA_SNOW3G_UIA2_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "ZUC-EIA3" hash flag * * @param flags Hash Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_ZUC_EIA3_SET(flags, val) \ QAT_FIELD_SET( \ flags, val, QAT_FW_LA_ZUC_EIA3_BITPOS, QAT_FW_LA_ZUC_EIA3_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for setting the "ZUC-EIA3" hash flag * * @param flags Hash Flags * @param val Value of the flag * *****************************************************************************/ #define ICP_QAT_FW_HASH_FLAG_MODE2_SET(flags, val) \ QAT_FIELD_SET(flags, val, QAT_FW_LA_MODE2_BITPOS, QAT_FW_LA_MODE2_MASK) #define ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX 240 #define ICP_QAT_FW_SPC_AAD_SZ_MAX 0x3FFF /**< @ingroup icp_qat_fw_comn * Maximum size of AAD data allowed for CCM or GCM processing. AAD data size90 - * is stored in 8-bit field and must be multiple of hash block size. 240 is * largest value which satisfy both requirements.AAD_SZ_MAX is in byte units */ /* * request parameter #defines */ #define ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET (24) /**< @ingroup icp_qat_fw_comn * Offset in bytes from the start of the request parameters block to the hash * (auth) request parameters */ #define ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET (0) /**< @ingroup icp_qat_fw_comn * Offset in bytes from the start of the request parameters block to the cipher * request parameters */ /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the cipher request parameters block * * @description * Definition of the cipher processing request parameters block * structure, which forms part of the block incorporating LWs 14-26, * as defined by the common base parameters structure. * Unused fields must be set to 0. * *****************************************************************************/ /**< Pack compiler directive added to prevent the * compiler from padding this structure to a 64-bit boundary */ #pragma pack(push, 1) typedef struct icp_qat_fw_la_cipher_req_params_s { /**< LW 14 */ uint32_t cipher_offset; /**< Cipher offset long word. */ /**< LW 15 */ uint32_t cipher_length; /**< Cipher length long word. */ /**< LWs 16-19 */ union { uint32_t cipher_IV_array[ICP_QAT_FW_NUM_LONGWORDS_4]; /**< Cipher IV array */ struct { uint64_t cipher_IV_ptr; /**< Cipher IV pointer or Partial State Pointer */ uint64_t resrvd1; /**< reserved */ } s; } u; /* LW 20 - 21 */ uint64_t spc_aad_addr; /**< Address of the AAD info in DRAM */ /* LW 22 - 23 */ uint64_t spc_auth_res_addr; /**< Address of the authentication result information to validate or * the location to which the digest information can be written back to */ /* LW 24 */ uint16_t spc_aad_sz; /**< Size in bytes of AAD data to prefix to the packet * for ChaChaPoly or GCM processing */ uint8_t reserved; /**< reserved */ uint8_t spc_auth_res_sz; /**< Size in bytes of the authentication result */ } icp_qat_fw_la_cipher_req_params_t; #pragma pack(pop) /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the cipher request parameters block for Gen4 * * @description * Definition of the cipher processing request parameters block * structure, which forms part of the block incorporating LWs 14-26, * as defined by the common base parameters structure. * Unused fields must be set to 0. * *****************************************************************************/ typedef struct icp_qat_fw_la_cipher_20_req_params_s { /**< LW 14 */ uint32_t cipher_offset; /**< Cipher offset long word. */ /**< LW 15 */ uint32_t cipher_length; /**< Cipher length long word. */ /**< LWs 16-19 */ union { uint32_t cipher_IV_array[ICP_QAT_FW_NUM_LONGWORDS_4]; /**< Cipher IV array */ struct { uint64_t cipher_IV_ptr; /**< Cipher IV pointer or Partial State Pointer */ uint64_t resrvd1; /**< reserved */ } s; } u; /**< LW 20 */ uint32_t spc_aad_offset; /**< LW 21 */ uint32_t spc_aad_sz; /**< LW 22 - 23 */ uint64_t spc_aad_addr; /**< LW 24 - 25 */ uint64_t spc_auth_res_addr; /**< LW 26 */ uint8_t reserved[3]; uint8_t spc_auth_res_sz; } icp_qat_fw_la_cipher_20_req_params_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the auth request parameters block * @description * Definition of the authentication processing request parameters block * structure, which forms part of the block incorporating LWs 14-26, * as defined by the common base parameters structure. Note: * This structure is used by TLS only. * *****************************************************************************/ /**< Pack compiler directive added to prevent the * compiler from padding this structure to a 64-bit boundary */ #pragma pack(push, 1) typedef struct icp_qat_fw_la_auth_req_params_s { /**< LW 20 */ uint32_t auth_off; /**< Byte offset from the start of packet to the auth data region */ /**< LW 21 */ uint32_t auth_len; /**< Byte length of the auth data region */ /**< LWs 22-23 */ union { uint64_t auth_partial_st_prefix; /**< Address of the authentication partial state prefix * information */ uint64_t aad_adr; /**< Address of the AAD info in DRAM. Used for the CCM and GCM * protocols */ } u1; /**< LWs 24-25 */ uint64_t auth_res_addr; /**< Address of the authentication result information to validate or * the location to which the digest information can be written back to */ /**< LW 26 */ union { uint8_t inner_prefix_sz; /**< Size in bytes of the inner prefix data */ uint8_t aad_sz; /**< Size in bytes of padded AAD data to prefix to the packet for CCM * or GCM processing */ } u2; uint8_t resrvd1; /**< reserved */ uint8_t hash_state_sz; /**< Number of quad words of inner and outer hash prefix data to process * Maximum size is 240 */ uint8_t auth_res_sz; /**< Size in bytes of the authentication result */ } icp_qat_fw_la_auth_req_params_t; #pragma pack(pop) /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the auth request parameters block * @description * Definition of the authentication processing request parameters block * structure, which forms part of the block incorporating LWs 14-26, * as defined by the common base parameters structure. Note: * This structure is used by SSL3 and MGF1 only. All fields other than * inner prefix/ AAD size are unused and therefore reserved. * *****************************************************************************/ typedef struct icp_qat_fw_la_auth_req_params_resrvd_flds_s { /**< LWs 20-25 */ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_6]; /**< LW 26 */ union { uint8_t inner_prefix_sz; /**< Size in bytes of the inner prefix data */ uint8_t aad_sz; /**< Size in bytes of padded AAD data to prefix to the packet for CCM * or GCM processing */ } u2; uint8_t resrvd1; /**< reserved */ uint16_t resrvd2; /**< reserved */ } icp_qat_fw_la_auth_req_params_resrvd_flds_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the shared fields within the parameter block * containing SSL, TLS or MGF information. * @description * This structure defines the shared fields for SSL, TLS or MGF * within the parameter block incorporating LWs 14-26, as defined * by the common base parameters structure. * Unused fields must be set to 0. * *****************************************************************************/ typedef struct icp_qat_fw_la_key_gen_common_s { /**< LW 14 */ union { /**< SSL3 */ uint16_t secret_lgth_ssl; /**< Length of Secret information for SSL. In the case of TLS the * secret is supplied in the content descriptor */ /**< MGF */ uint16_t mask_length; /**< Size in bytes of the desired output mask for MGF1*/ /**< TLS */ uint16_t secret_lgth_tls; /**< TLS Secret length */ } u; union { /**< SSL3 */ struct { uint8_t output_lgth_ssl; /**< Output length */ uint8_t label_lgth_ssl; /**< Label length */ } s1; /**< MGF */ struct { uint8_t hash_length; /**< Hash length */ uint8_t seed_length; /**< Seed length */ } s2; /**< TLS */ struct { uint8_t output_lgth_tls; /**< Output length */ uint8_t label_lgth_tls; /**< Label length */ } s3; /**< HKDF */ struct { uint8_t rsrvd1; /**< Unused */ uint8_t info_length; /**< Info length. This is plain data, not wrapped in an * icp_qat_fw_hkdf_label structure. */ } hkdf; /**< HKDF Expand Label */ struct { uint8_t rsrvd1; /**< Unused */ uint8_t num_labels; /**< Number of labels */ } hkdf_label; } u1; /**< LW 15 */ union { /**< SSL3 */ uint8_t iter_count; /**< Iteration count used by the SSL key gen request */ /**< TLS */ uint8_t tls_seed_length; /**< TLS Seed length */ /**< HKDF */ uint8_t hkdf_ikm_length; /**< Input keying material (IKM) length */ uint8_t resrvd1; /**< Reserved field set to 0 for MGF1 */ } u2; union { /**< HKDF */ uint8_t hkdf_num_sublabels; /**< Number of subLabels in subLabel buffer, 0-4 */ uint8_t resrvd2; /**< Reserved space - unused */ } u3; uint16_t resrvd3; /**< Reserved space - unused */ } icp_qat_fw_la_key_gen_common_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the SSL3 request parameters block * @description * This structure contains the the SSL3 processing request parameters * incorporating LWs 14-26, as defined by the common base * parameters structure. Unused fields must be set to 0. * *****************************************************************************/ typedef struct icp_qat_fw_la_ssl3_req_params_s { /**< LWs 14-15 */ icp_qat_fw_la_key_gen_common_t keygen_comn; /**< For other key gen processing these field holds ssl, tls or mgf * parameters */ /**< LW 16-25 */ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_10]; /**< Reserved */ /**< LW 26 */ union { uint8_t inner_prefix_sz; /**< Size in bytes of the inner prefix data */ uint8_t aad_sz; /**< Size in bytes of padded AAD data to prefix to the packet for CCM * or GCM processing */ } u2; uint8_t resrvd1; /**< reserved */ uint16_t resrvd2; /**< reserved */ } icp_qat_fw_la_ssl3_req_params_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the MGF request parameters block * @description * This structure contains the the MGF processing request parameters * incorporating LWs 14-26, as defined by the common base parameters * structure. Unused fields must be set to 0. * *****************************************************************************/ typedef struct icp_qat_fw_la_mgf_req_params_s { /**< LWs 14-15 */ icp_qat_fw_la_key_gen_common_t keygen_comn; /**< For other key gen processing these field holds ssl or mgf * parameters */ /**< LW 16-25 */ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_10]; /**< Reserved */ /**< LW 26 */ union { uint8_t inner_prefix_sz; /**< Size in bytes of the inner prefix data */ uint8_t aad_sz; /**< Size in bytes of padded AAD data to prefix to the packet for CCM * or GCM processing */ } u2; uint8_t resrvd1; /**< reserved */ uint16_t resrvd2; /**< reserved */ } icp_qat_fw_la_mgf_req_params_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the TLS request parameters block * @description * This structure contains the the TLS processing request parameters * incorporating LWs 14-26, as defined by the common base parameters * structure. Unused fields must be set to 0. * *****************************************************************************/ typedef struct icp_qat_fw_la_tls_req_params_s { /**< LWs 14-15 */ icp_qat_fw_la_key_gen_common_t keygen_comn; /**< For other key gen processing these field holds ssl, tls or mgf * parameters */ /**< LW 16-19 */ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4]; /**< Reserved */ } icp_qat_fw_la_tls_req_params_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the common QAT FW request middle block for TRNG. * @description * Common section of the request used across all of the services exposed * by the QAT FW. Each of the services inherit these common fields. TRNG * requires a specific implementation. * *****************************************************************************/ typedef struct icp_qat_fw_la_trng_req_mid_s { /**< LWs 6-13 */ uint64_t opaque_data; /**< Opaque data passed unmodified from the request to response messages by * firmware (fw) */ uint64_t resrvd1; /**< Reserved, unused for TRNG */ uint64_t dest_data_addr; /**< Generic definition of the destination data supplied to the QAT AE. The * common flags are used to further describe the attributes of this * field */ uint32_t resrvd2; /** < Reserved, unused for TRNG */ uint32_t entropy_length; /**< Size of the data in bytes to process. Used by the get_random * command. Set to 0 for commands that dont need a length parameter */ } icp_qat_fw_la_trng_req_mid_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the common LA QAT FW TRNG request * @description * Definition of the TRNG processing request type * *****************************************************************************/ typedef struct icp_qat_fw_la_trng_req_s { /**< LWs 0-1 */ icp_qat_fw_comn_req_hdr_t comn_hdr; /**< Common request header */ /**< LWs 2-5 */ icp_qat_fw_comn_req_hdr_cd_pars_t cd_pars; /**< Common Request content descriptor field which points either to a * content descriptor * parameter block or contains the service-specific data itself. */ /**< LWs 6-13 */ icp_qat_fw_la_trng_req_mid_t comn_mid; /**< TRNG request middle section - differs from the common mid-section */ /**< LWs 14-26 */ uint32_t resrvd1[ICP_QAT_FW_NUM_LONGWORDS_13]; /**< LWs 27-31 */ uint32_t resrvd2[ICP_QAT_FW_NUM_LONGWORDS_5]; } icp_qat_fw_la_trng_req_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Lookaside Eagle Tail Response * @description * This is the response delivered to the ET rings by the Lookaside * QAT FW service for all commands * *****************************************************************************/ typedef struct icp_qat_fw_la_resp_s { /**< LWs 0-1 */ icp_qat_fw_comn_resp_hdr_t comn_resp; /**< Common interface response format see icp_qat_fw.h */ /**< LWs 2-3 */ uint64_t opaque_data; /**< Opaque data passed from the request to the response message */ /**< LWs 4-7 */ uint32_t resrvd[ICP_QAT_FW_NUM_LONGWORDS_4]; /**< Reserved */ } icp_qat_fw_la_resp_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Lookaside TRNG Test Status Structure * @description * As an addition to ICP_QAT_FW_LA_TRNG_STATUS Pass or Fail information * in common response fields, as a response to TRNG_TEST request, Test * status, Counter for failed tests and 4 entropy counter values are * sent * Status of test status and the fail counts. * * *****************************************************************************/ typedef struct icp_qat_fw_la_trng_test_result_s { uint32_t test_status_info; /**< TRNG comparator health test status& Validity information see Test Status Bit Fields below. */ uint32_t test_status_fail_count; /**< TRNG comparator health test status, 32bit fail counter */ uint64_t r_ent_ones_cnt; /**< Raw Entropy ones counter */ uint64_t r_ent_zeros_cnt; /**< Raw Entropy zeros counter */ uint64_t c_ent_ones_cnt; /**< Conditioned Entropy ones counter */ uint64_t c_ent_zeros_cnt; /**< Conditioned Entropy zeros counter */ uint64_t resrvd; /**< Reserved field must be set to zero */ } icp_qat_fw_la_trng_test_result_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Lookaside SSL Key Material Input * @description * This struct defines the layout of input parameters for the * SSL3 key generation (source flat buffer format) * *****************************************************************************/ typedef struct icp_qat_fw_la_ssl_key_material_input_s { uint64_t seed_addr; /**< Pointer to seed */ uint64_t label_addr; /**< Pointer to label(s) */ uint64_t secret_addr; /**< Pointer to secret */ } icp_qat_fw_la_ssl_key_material_input_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Lookaside TLS Key Material Input * @description * This struct defines the layout of input parameters for the * TLS key generation (source flat buffer format) * @note * Secret state value (S split into S1 and S2 parts) is supplied via * Content Descriptor. S1 is placed in an outer prefix buffer, and S2 * inside the inner prefix buffer. * *****************************************************************************/ typedef struct icp_qat_fw_la_tls_key_material_input_s { uint64_t seed_addr; /**< Pointer to seed */ uint64_t label_addr; /**< Pointer to label(s) */ } icp_qat_fw_la_tls_key_material_input_t; /** ***************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Lookaside HKDF (TLS 1.3) Key Material Input * @description * This structure defines the source buffer for HKDF operations, which * must be provided in flat buffer format. * * The result will be returned in the destination buffer (flat format). * All generated key materials will be returned in a packed layout. Where * sublabel flags are specified, the result of the child expands will * immediately follow their parent. * * @note * TLS 1.3 / HKDF operations require only one key (either the Extract Salt * or the Expand PSK) which is placed in the inner prefix buffer. * *****************************************************************************/ typedef struct icp_qat_fw_la_hkdf_key_material_input_s { uint64_t ikm_addr; /**< Pointer to IKM (input keying material) */ uint64_t labels_addr; /**< Pointer to labels buffer. * For HKDF Expand (without Label) this buffer contains the Info. * * For TLS 1.3 / HKDF Expand-Label this buffer contains up to 4 * icp_qat_fw_hkdf_label structures, which will result in a * corresponding number of first level Expand-Label operations. * * For each of these operations, the result may become an input to child * Expand-Label operations as specified by the sublabel flags, where bit * 0 indicates a child Expand using label 0 from the sublabels buffer, * bit 1 indicates sublabel 1, and so on. In this way, up to 20 * Expand-Label operations may be performed in one request. */ uint64_t sublabels_addr; /**< Pointer to 0-4 sublabels for TLS 1.3, following the format * described for label_addr above. The buffer will typically contain * all 4 of the supported sublabels. * The sublabel flags defined for this context are as follows: * - QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS * - QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS * - QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS */ } icp_qat_fw_la_hkdf_key_material_input_t; /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macros using the bit position and mask to set/extract the next * and current id nibbles within the next_curr_id field of the * content descriptor header block, ONLY FOR CIPHER + AUTH COMBINED. * Note that for cipher only or authentication only, the common macros * need to be used. These are defined in the 'icp_qat_fw.h' common header * file, as they are used by compression, cipher and authentication. * * @param cd_ctrl_hdr_t Content descriptor control block header. * @param val Value of the field being set. * *****************************************************************************/ /** Cipher fields within Cipher + Authentication structure */ #define ICP_QAT_FW_CIPHER_NEXT_ID_GET(cd_ctrl_hdr_t) \ ((((cd_ctrl_hdr_t)->next_curr_id_cipher) & \ ICP_QAT_FW_COMN_NEXT_ID_MASK) >> \ (ICP_QAT_FW_COMN_NEXT_ID_BITPOS)) #define ICP_QAT_FW_CIPHER_NEXT_ID_SET(cd_ctrl_hdr_t, val) \ (cd_ctrl_hdr_t)->next_curr_id_cipher = \ ((((cd_ctrl_hdr_t)->next_curr_id_cipher) & \ ICP_QAT_FW_COMN_CURR_ID_MASK) | \ ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) & \ ICP_QAT_FW_COMN_NEXT_ID_MASK)) #define ICP_QAT_FW_CIPHER_CURR_ID_GET(cd_ctrl_hdr_t) \ (((cd_ctrl_hdr_t)->next_curr_id_cipher) & ICP_QAT_FW_COMN_CURR_ID_MASK) #define ICP_QAT_FW_CIPHER_CURR_ID_SET(cd_ctrl_hdr_t, val) \ (cd_ctrl_hdr_t)->next_curr_id_cipher = \ ((((cd_ctrl_hdr_t)->next_curr_id_cipher) & \ ICP_QAT_FW_COMN_NEXT_ID_MASK) | \ ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK)) /** Authentication fields within Cipher + Authentication structure */ #define ICP_QAT_FW_AUTH_NEXT_ID_GET(cd_ctrl_hdr_t) \ ((((cd_ctrl_hdr_t)->next_curr_id_auth) & ICP_QAT_FW_COMN_NEXT_ID_MASK) >> \ (ICP_QAT_FW_COMN_NEXT_ID_BITPOS)) #define ICP_QAT_FW_AUTH_NEXT_ID_SET(cd_ctrl_hdr_t, val) \ (cd_ctrl_hdr_t)->next_curr_id_auth = \ ((((cd_ctrl_hdr_t)->next_curr_id_auth) & \ ICP_QAT_FW_COMN_CURR_ID_MASK) | \ ((val << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) & \ ICP_QAT_FW_COMN_NEXT_ID_MASK)) #define ICP_QAT_FW_AUTH_CURR_ID_GET(cd_ctrl_hdr_t) \ (((cd_ctrl_hdr_t)->next_curr_id_auth) & ICP_QAT_FW_COMN_CURR_ID_MASK) #define ICP_QAT_FW_AUTH_CURR_ID_SET(cd_ctrl_hdr_t, val) \ (cd_ctrl_hdr_t)->next_curr_id_auth = \ ((((cd_ctrl_hdr_t)->next_curr_id_auth) & \ ICP_QAT_FW_COMN_NEXT_ID_MASK) | \ ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK)) /* Definitions of the bits in the test_status_info of the TRNG_TEST response. * The values returned by the Lookaside service are given below * The Test result and Test Fail Count values are only valid if the Test * Results Valid (Tv) is set. * * TRNG Test Status Info * + ===== + ------------------------------------------------ + --- + --- + * | Bit | 31 - 2 | 1 | 0 | * + ===== + ------------------------------------------------ + --- + --- + * | Flags | RESERVED = 0 | Tv | Ts | * + ===== + ------------------------------------------------------------ + */ /****************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Lookaside TRNG Test Status Information received as * a part of icp_qat_fw_la_trng_test_result_t * *****************************************************************************/ #define QAT_FW_LA_TRNG_TEST_STATUS_TS_BITPOS 0 /**< @ingroup icp_qat_fw_la * TRNG Test Result t_status field bit pos definition.*/ #define QAT_FW_LA_TRNG_TEST_STATUS_TS_MASK 0x1 /**< @ingroup icp_qat_fw_la * TRNG Test Result t_status field mask definition.*/ #define QAT_FW_LA_TRNG_TEST_STATUS_TV_BITPOS 1 /**< @ingroup icp_qat_fw_la * TRNG Test Result test results valid field bit pos definition.*/ #define QAT_FW_LA_TRNG_TEST_STATUS_TV_MASK 0x1 /**< @ingroup icp_qat_fw_la * TRNG Test Result test results valid field mask definition.*/ /****************************************************************************** * @ingroup icp_qat_fw_la * Definition of the Lookaside TRNG test_status values. * * *****************************************************************************/ #define QAT_FW_LA_TRNG_TEST_STATUS_TV_VALID 1 /**< @ingroup icp_qat_fw_la * TRNG TEST Response Test Results Valid Value.*/ #define QAT_FW_LA_TRNG_TEST_STATUS_TV_NOT_VALID 0 /**< @ingroup icp_qat_fw_la * TRNG TEST Response Test Results are NOT Valid Value.*/ #define QAT_FW_LA_TRNG_TEST_STATUS_TS_NO_FAILS 1 /**< @ingroup icp_qat_fw_la * Value for TRNG Test status tests have NO FAILs Value.*/ #define QAT_FW_LA_TRNG_TEST_STATUS_TS_HAS_FAILS 0 /**< @ingroup icp_qat_fw_la * Value for TRNG Test status tests have one or more FAILS Value.*/ /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the Test Status Field returned in the response * to TRNG TEST command. * * @param test_status 8 bit test_status value to extract the status bit * *****************************************************************************/ #define ICP_QAT_FW_LA_TRNG_TEST_STATUS_TS_FLD_GET(test_status) \ QAT_FIELD_GET(test_status, \ QAT_FW_LA_TRNG_TEST_STATUS_TS_BITPOS, \ QAT_FW_LA_TRNG_TEST_STATUS_TS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_la * * @description * Macro for extraction of the Test Results Valid Field returned in the * response to TRNG TEST command. * * @param test_status 8 bit test_status value to extract the Tests * Results valid bit * *****************************************************************************/ #define ICP_QAT_FW_LA_TRNG_TEST_STATUS_TV_FLD_GET(test_status) \ QAT_FIELD_GET(test_status, \ QAT_FW_LA_TRNG_TEST_STATUS_TV_BITPOS, \ QAT_FW_LA_TRNG_TEST_STATUS_TV_MASK) /* ****************************************************************************** * MGF Max supported input parameters ****************************************************************************** */ #define ICP_QAT_FW_LA_MGF_SEED_LEN_MAX 255 /**< @ingroup icp_qat_fw_la * Maximum seed length for MGF1 request in bytes * Typical values may be 48, 64, 128 bytes (or any).*/ #define ICP_QAT_FW_LA_MGF_MASK_LEN_MAX 65528 /**< @ingroup icp_qat_fw_la * Maximum mask length for MGF1 request in bytes * Typical values may be 8 (64-bit), 16 (128-bit). MUST be quad word multiple */ /* ****************************************************************************** * SSL Max supported input parameters ****************************************************************************** */ #define ICP_QAT_FW_LA_SSL_SECRET_LEN_MAX 512 /**< @ingroup icp_qat_fw_la * Maximum secret length for SSL3 Key Gen request (bytes) */ #define ICP_QAT_FW_LA_SSL_ITERATES_LEN_MAX 16 /**< @ingroup icp_qat_fw_la * Maximum iterations for SSL3 Key Gen request (integer) */ #define ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX 136 /**< @ingroup icp_qat_fw_la * Maximum label length for SSL3 Key Gen request (bytes) */ #define ICP_QAT_FW_LA_SSL_SEED_LEN_MAX 64 /**< @ingroup icp_qat_fw_la * Maximum seed length for SSL3 Key Gen request (bytes) */ #define ICP_QAT_FW_LA_SSL_OUTPUT_LEN_MAX 248 /**< @ingroup icp_qat_fw_la * Maximum output length for SSL3 Key Gen request (bytes) */ /* ****************************************************************************** * TLS Max supported input parameters ****************************************************************************** */ #define ICP_QAT_FW_LA_TLS_SECRET_LEN_MAX 128 /**< @ingroup icp_qat_fw_la * Maximum secret length for TLS Key Gen request (bytes) */ #define ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX 128 /**< @ingroup icp_qat_fw_la * Maximum secret length for TLS Key Gen request (bytes) */ #define ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX 64 /**< @ingroup icp_qat_fw_la * Maximum secret length for TLS Key Gen request (bytes) */ #define ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX 255 /**< @ingroup icp_qat_fw_la * Maximum label length for TLS Key Gen request (bytes) */ #define ICP_QAT_FW_LA_TLS_SEED_LEN_MAX 64 /**< @ingroup icp_qat_fw_la * Maximum seed length for TLS Key Gen request (bytes) */ #define ICP_QAT_FW_LA_TLS_OUTPUT_LEN_MAX 248 /**< @ingroup icp_qat_fw_la * Maximum output length for TLS Key Gen request (bytes) */ /* ****************************************************************************** * HKDF input parameters ****************************************************************************** */ #define QAT_FW_HKDF_LABEL_BUFFER_SZ 78 #define QAT_FW_HKDF_LABEL_LEN_SZ 1 #define QAT_FW_HKDF_LABEL_FLAGS_SZ 1 #define QAT_FW_HKDF_LABEL_STRUCT_SZ \ (QAT_FW_HKDF_LABEL_BUFFER_SZ + QAT_FW_HKDF_LABEL_LEN_SZ + \ QAT_FW_HKDF_LABEL_FLAGS_SZ) /** ***************************************************************************** * @ingroup icp_qat_fw_la * * @description * Wraps an RFC 8446 HkdfLabel with metadata for use in HKDF Expand-Label * operations. * *****************************************************************************/ struct icp_qat_fw_hkdf_label { uint8_t label[QAT_FW_HKDF_LABEL_BUFFER_SZ]; /**< Buffer containing an HkdfLabel as specified in RFC 8446 */ uint8_t label_length; /**< The size of the HkdfLabel */ union { uint8_t label_flags; /**< For first-level labels: each bit in [0..3] will trigger a child * Expand-Label operation on the corresponding sublabel. Bits [4..7] * are reserved. */ uint8_t sublabel_flags; /**< For sublabels the following flags are defined: * - QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS * - QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS * - QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS */ } u; }; #define ICP_QAT_FW_LA_HKDF_SECRET_LEN_MAX 64 /**< Maximum secret length for HKDF request (bytes) */ #define ICP_QAT_FW_LA_HKDF_IKM_LEN_MAX 64 /**< Maximum IKM length for HKDF request (bytes) */ #define QAT_FW_HKDF_MAX_LABELS 4 /**< Maximum number of label structures allowed in the labels buffer */ #define QAT_FW_HKDF_MAX_SUBLABELS 4 /**< Maximum number of label structures allowed in the sublabels buffer */ /* ****************************************************************************** * HKDF inner sublabel flags ****************************************************************************** */ #define QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS 0 /**< Limit sublabel expand output to 12 bytes -- used with the "iv" sublabel */ #define QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS 1 /**< Limit sublabel expand output to 16 bytes -- used with SHA-256 "key" */ #define QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS 2 /**< Limit sublabel expand output to 32 bytes -- used with SHA-384 "key" */ #endif /* _ICP_QAT_FW_LA_H_ */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw_mmp.h000066400000000000000000007263161503624047500261010ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /* --- (Automatically generated (build v. 2.7), do not modify manually) --- */ /** * @file icp_qat_fw_mmp.h * @defgroup icp_qat_fw_mmp ICP QAT FW MMP Processing Definitions * @ingroup icp_qat_fw * $Revision: 0.1 $ * @brief * This file documents the external interfaces that the QAT FW running * on the QAT Acceleration Engine provides to clients wanting to * accelerate crypto asymmetric applications */ #ifndef __ICP_QAT_FW_MMP__ #define __ICP_QAT_FW_MMP__ /************************************************************************** * Include local header files ************************************************************************** */ #include "icp_qat_fw.h" /************************************************************************** * Local constants ************************************************************************** */ #define ICP_QAT_FW_PKE_INPUT_COUNT_MAX 7 /**< @ingroup icp_qat_fw_pke * Maximum number of input parameters in all PKE request */ #define ICP_QAT_FW_PKE_OUTPUT_COUNT_MAX 5 /**< @ingroup icp_qat_fw_pke * Maximum number of output parameters in all PKE request */ /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC P384 Variable Point Multiplication [k]P, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_EC_POINT_MULTIPLICATION_P384. */ typedef struct icp_qat_fw_mmp_ec_point_multiplication_p384_input_s { uint64_t xp; /**< xP = affine coordinate X of point P (6 qwords)*/ uint64_t yp; /**< yP = affine coordinate Y of point P (6 qwords)*/ uint64_t k; /**< k = scalar (6 qwords)*/ } icp_qat_fw_mmp_ec_point_multiplication_p384_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC P384 Generator Point Multiplication [k]G, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_EC_GENERATOR_MULTIPLICATION_P384. */ typedef struct icp_qat_fw_mmp_ec_generator_multiplication_p384_input_s { uint64_t k; /**< k = scalar (6 qwords)*/ } icp_qat_fw_mmp_ec_generator_multiplication_p384_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC P384 ECDSA Sign RS, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_SIGN_RS_P384. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_p384_input_s { uint64_t k; /**< k = random value, > 0 and < n (order of G for P384) (6 qwords)*/ uint64_t e; /**< (6 qwords)*/ uint64_t d; /**< (6 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_p384_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC P256 Variable Point Multiplication [k]P, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_EC_POINT_MULTIPLICATION_P256. */ typedef struct icp_qat_fw_mmp_ec_point_multiplication_p256_input_s { uint64_t xp; /**< xP = affine coordinate X of point P (4 qwords)*/ uint64_t yp; /**< yP = affine coordinate Y of point P (4 qwords)*/ uint64_t k; /**< k = scalar (4 qwords)*/ } icp_qat_fw_mmp_ec_point_multiplication_p256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC P256 Generator Point Multiplication [k]G, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_EC_GENERATOR_MULTIPLICATION_P256. */ typedef struct icp_qat_fw_mmp_ec_generator_multiplication_p256_input_s { uint64_t k; /**< k = scalar (4 qwords)*/ } icp_qat_fw_mmp_ec_generator_multiplication_p256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC P256 ECDSA Sign RS, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_SIGN_RS_P256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_p256_input_s { uint64_t k; /**< k = random value, > 0 and < n (order of G for P256) (4 qwords)*/ uint64_t e; /**< (4 qwords)*/ uint64_t d; /**< (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_p256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 point multiply [k]G , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_GENERATOR_MULTIPLICATION. */ typedef struct icp_qat_fw_mmp_ecsm2_generator_multiplication_input_s { uint64_t k; /**< k = multiplicand (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_generator_multiplication_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 point multiply [k]P , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_POINT_MULTIPLICATION. */ typedef struct icp_qat_fw_mmp_ecsm2_point_multiplication_input_s { uint64_t k; /**< k = input number (4 qwords)*/ uint64_t x; /**< x = affine coordinate X of input point (4 qwords)*/ uint64_t y; /**< y = affine coordinate Y of input point (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_point_multiplication_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 point verify , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_POINT_VERIFY. */ typedef struct icp_qat_fw_mmp_ecsm2_point_verify_input_s { uint64_t x; /**< x = affine coordinate X of input point (4 qwords)*/ uint64_t y; /**< y = affine coordinate Y of input point (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_point_verify_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 Sign RS , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_SIGN_RS. */ typedef struct icp_qat_fw_mmp_ecsm2_sign_rs_input_s { uint64_t k; /**< k = random value (4 qwords)*/ uint64_t e; /**< e = digest of the message to be signed (4 qwords)*/ uint64_t d; /**< d = private key (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_sign_rs_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 Signature Verify , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_VERIFY. */ typedef struct icp_qat_fw_mmp_ecsm2_verify_input_s { uint64_t e; /**< e = digest of the message to be signed (4 qwords)*/ uint64_t r; /**< r = signature (4 qwords)*/ uint64_t s; /**< s = signature (4 qwords)*/ uint64_t xp; /**< xP = affine coordinate X of point P=[d]G (4 qwords)*/ uint64_t yp; /**< yP = affine coordinate Y of point P=[d]G (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_verify_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 encryption , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_ENCRYPTION. */ typedef struct icp_qat_fw_mmp_ecsm2_encryption_input_s { uint64_t k; /**< k = random value (4 qwords)*/ uint64_t xp; /**< xP = affine coordinate X of point P=[d]G (4 qwords)*/ uint64_t yp; /**< yP = affine coordinate Y of point P=[d]G (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_encryption_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 decryption , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_DECRYPTION. */ typedef struct icp_qat_fw_mmp_ecsm2_decryption_input_s { uint64_t d; /**< d = private key (4 qwords)*/ uint64_t xpb; /**< xPb = affine coordinate X of point C1 (4 qwords)*/ uint64_t ypb; /**< yPb = affine coordinate Y of point C1 (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_decryption_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 key exchange phase1 , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_KEYEX_P1. */ typedef struct icp_qat_fw_mmp_ecsm2_keyex_p1_input_s { uint64_t k; /**< k = random value (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_keyex_p1_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC SM2 key exchange phase2 , * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECSM2_KEYEX_P2. */ typedef struct icp_qat_fw_mmp_ecsm2_keyex_p2_input_s { uint64_t r; /**< r = random value (4 qwords)*/ uint64_t d; /**< d = private key (4 qwords)*/ uint64_t x1; /**< x1 = affine coordinate X of point RA (4 qwords)*/ uint64_t x2; /**< x2 = affine coordinate X of point RB (4 qwords)*/ uint64_t y2; /**< y2 = affine coordinate X of point RB (4 qwords)*/ uint64_t xp; /**< xP = affine coordinate X of public key PB (4 qwords)*/ uint64_t yp; /**< yP = affine coordinate X of public key PB (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_keyex_p2_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Initialisation sequence, * to be used when icp_qat_fw_pke_request_s::functionalityId is #PKE_INIT. */ typedef struct icp_qat_fw_mmp_init_input_s { uint64_t z; /**< zeroed quadword (1 qwords)*/ } icp_qat_fw_mmp_init_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for * 768-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_G2_768. */ typedef struct icp_qat_fw_mmp_dh_g2_768_input_s { uint64_t e; /**< exponent > 0 and < 2^768 (12 qwords)*/ uint64_t m; /**< modulus ≥ 2^767 and < 2^768 (12 qwords)*/ } icp_qat_fw_mmp_dh_g2_768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation for 768-bit * numbers, to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_DH_768. */ typedef struct icp_qat_fw_mmp_dh_768_input_s { uint64_t g; /**< base ≥ 0 and < 2^768 (12 qwords)*/ uint64_t e; /**< exponent > 0 and < 2^768 (12 qwords)*/ uint64_t m; /**< modulus ≥ 2^767 and < 2^768 (12 qwords)*/ } icp_qat_fw_mmp_dh_768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for * 1024-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_G2_1024. */ typedef struct icp_qat_fw_mmp_dh_g2_1024_input_s { uint64_t e; /**< exponent > 0 and < 2^1024 (16 qwords)*/ uint64_t m; /**< modulus ≥ 2^1023 and < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_dh_g2_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation for * 1024-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_1024. */ typedef struct icp_qat_fw_mmp_dh_1024_input_s { uint64_t g; /**< base ≥ 0 and < 2^1024 (16 qwords)*/ uint64_t e; /**< exponent > 0 and < 2^1024 (16 qwords)*/ uint64_t m; /**< modulus ≥ 2^1023 and < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_dh_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for * 1536-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_G2_1536. */ typedef struct icp_qat_fw_mmp_dh_g2_1536_input_s { uint64_t e; /**< exponent > 0 and < 2^1536 (24 qwords)*/ uint64_t m; /**< modulus ≥ 2^1535 and < 2^1536 (24 qwords)*/ } icp_qat_fw_mmp_dh_g2_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation for * 1536-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_1536. */ typedef struct icp_qat_fw_mmp_dh_1536_input_s { uint64_t g; /**< base ≥ 0 and < 2^1536 (24 qwords)*/ uint64_t e; /**< exponent > 0 and < 2^1536 (24 qwords)*/ uint64_t m; /**< modulus ≥ 2^1535 and < 2^1536 (24 qwords)*/ } icp_qat_fw_mmp_dh_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for * 2048-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_G2_2048. */ typedef struct icp_qat_fw_mmp_dh_g2_2048_input_s { uint64_t e; /**< exponent > 0 and < 2^2048 (32 qwords)*/ uint64_t m; /**< modulus ≥ 2^2047 and < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_dh_g2_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation for * 2048-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_2048. */ typedef struct icp_qat_fw_mmp_dh_2048_input_s { uint64_t g; /**< base ≥ 0 and < 2^2048 (32 qwords)*/ uint64_t e; /**< exponent > 0 and < 2^2048 (32 qwords)*/ uint64_t m; /**< modulus ≥ 2^2047 and < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_dh_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for * 3072-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_G2_3072. */ typedef struct icp_qat_fw_mmp_dh_g2_3072_input_s { uint64_t e; /**< exponent > 0 and < 2^3072 (48 qwords)*/ uint64_t m; /**< modulus ≥ 2^3071 and < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_dh_g2_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation for * 3072-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_3072. */ typedef struct icp_qat_fw_mmp_dh_3072_input_s { uint64_t g; /**< base ≥ 0 and < 2^3072 (48 qwords)*/ uint64_t e; /**< exponent > 0 and < 2^3072 (48 qwords)*/ uint64_t m; /**< modulus ≥ 2^3071 and < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_dh_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for * 4096-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_G2_4096. */ typedef struct icp_qat_fw_mmp_dh_g2_4096_input_s { uint64_t e; /**< exponent > 0 and < 2^4096 (64 qwords)*/ uint64_t m; /**< modulus ≥ 2^4095 and < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_dh_g2_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation for * 4096-bit numbers, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DH_4096. */ typedef struct icp_qat_fw_mmp_dh_4096_input_s { uint64_t g; /**< base ≥ 0 and < 2^4096 (64 qwords)*/ uint64_t e; /**< exponent > 0 and < 2^4096 (64 qwords)*/ uint64_t m; /**< modulus ≥ 2^4095 and < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_dh_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation base 2 for * 8192-bit numbers, to be used when icp_qat_fw_pke_request_s::functionalityId * is #PKE_DH_G2_8192. */ typedef struct icp_qat_fw_mmp_dh_g2_8192_input_s { uint64_t e; /**< exponent > 0 and < 2^8192 (128 qwords)*/ uint64_t m; /**< modulus ≥ 2^8191 and < 2^8192 (128 qwords)*/ } icp_qat_fw_mmp_dh_g2_8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Diffie-Hellman Modular exponentiation for * 8192-bit numbers, to be used when icp_qat_fw_pke_request_s::functionalityId * is #PKE_DH_8192. */ typedef struct icp_qat_fw_mmp_dh_8192_input_s { uint64_t g; /**< base ≥ 0 and < 2^8192 (128 qwords)*/ uint64_t e; /**< exponent > 0 and < 2^8192 (128 qwords)*/ uint64_t m; /**< modulus ≥ 2^8191 and < 2^8192 (128 qwords)*/ } icp_qat_fw_mmp_dh_8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 512 key generation first form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP1_512. */ typedef struct icp_qat_fw_mmp_rsa_kp1_512_input_s { uint64_t p; /**< RSA parameter, prime,  2 < p < 2^256 (4 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2 < q < 2^256 (4 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (8 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 512 key generation second form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP2_512. */ typedef struct icp_qat_fw_mmp_rsa_kp2_512_input_s { uint64_t p; /**< RSA parameter, prime,  2^255 < p < 2^256 (4 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^255 < q < 2^256 (4 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (8 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 512 Encryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_EP_512. */ typedef struct icp_qat_fw_mmp_rsa_ep_512_input_s { uint64_t m; /**< message representative, < n (8 qwords)*/ uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (8 qwords)*/ uint64_t n; /**< RSA key, > 0 and < 2^256 (8 qwords)*/ } icp_qat_fw_mmp_rsa_ep_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 512 Decryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP1_512. */ typedef struct icp_qat_fw_mmp_rsa_dp1_512_input_s { uint64_t c; /**< cipher text representative, < n (8 qwords)*/ uint64_t d; /**< RSA private key (RSADP first form) (8 qwords)*/ uint64_t n; /**< RSA key > 0 and < 2^256 (8 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1024 Decryption with CRT, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP2_512. */ typedef struct icp_qat_fw_mmp_rsa_dp2_512_input_s { uint64_t c; /**< cipher text representative, < (p*q) (8 qwords)*/ uint64_t p; /**< RSA parameter, prime,  2^255 < p < 2^256 (4 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^255 < q < 2^256 (4 qwords)*/ uint64_t dp; /**< RSA private key, 0 < dp < p-1 (4 qwords)*/ uint64_t dq; /**< RSA private key 0 < dq < q-1 (4 qwords)*/ uint64_t qinv; /**< RSA private key 0 < qInv < p (4 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1024 key generation first form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP1_1024. */ typedef struct icp_qat_fw_mmp_rsa_kp1_1024_input_s { uint64_t p; /**< RSA parameter, prime,  2 < p < 2^512 (8 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2 < q < 2^512 (8 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (16 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1024 key generation second form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP2_1024. */ typedef struct icp_qat_fw_mmp_rsa_kp2_1024_input_s { uint64_t p; /**< RSA parameter, prime,  2^511 < p < 2^512 (8 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^511 < q < 2^512 (8 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (16 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1024 Encryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_EP_1024. */ typedef struct icp_qat_fw_mmp_rsa_ep_1024_input_s { uint64_t m; /**< message representative, < n (16 qwords)*/ uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (16 qwords)*/ uint64_t n; /**< RSA key, > 0 and < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_rsa_ep_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1024 Decryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP1_1024. */ typedef struct icp_qat_fw_mmp_rsa_dp1_1024_input_s { uint64_t c; /**< cipher text representative, < n (16 qwords)*/ uint64_t d; /**< RSA private key (RSADP first form) (16 qwords)*/ uint64_t n; /**< RSA key > 0 and < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1024 Decryption with CRT, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP2_1024. */ typedef struct icp_qat_fw_mmp_rsa_dp2_1024_input_s { uint64_t c; /**< cipher text representative, < (p*q) (16 qwords)*/ uint64_t p; /**< RSA parameter, prime,  2^511 < p < 2^512 (8 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^511 < q < 2^512 (8 qwords)*/ uint64_t dp; /**< RSA private key, 0 < dp < p-1 (8 qwords)*/ uint64_t dq; /**< RSA private key 0 < dq < q-1 (8 qwords)*/ uint64_t qinv; /**< RSA private key 0 < qInv < p (8 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1536 key generation first form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP1_1536. */ typedef struct icp_qat_fw_mmp_rsa_kp1_1536_input_s { uint64_t p; /**< RSA parameter, prime,  2 < p < 2^768 (12 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2 < q < 2^768 (12 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (24 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1536 key generation second form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP2_1536. */ typedef struct icp_qat_fw_mmp_rsa_kp2_1536_input_s { uint64_t p; /**< RSA parameter, prime,  2^767 < p < 2^768 (12 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^767 < q < 2^768 (12 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (24 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1536 Encryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_EP_1536. */ typedef struct icp_qat_fw_mmp_rsa_ep_1536_input_s { uint64_t m; /**< message representative, < n (24 qwords)*/ uint64_t e; /**< RSA public key, ≥ 3 and ≤ (p*q)-1 (24 qwords)*/ uint64_t n; /**< RSA key > 0 and < 2^1536 (24 qwords)*/ } icp_qat_fw_mmp_rsa_ep_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1536 Decryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP1_1536. */ typedef struct icp_qat_fw_mmp_rsa_dp1_1536_input_s { uint64_t c; /**< cipher text representative, < n (24 qwords)*/ uint64_t d; /**< RSA private key (24 qwords)*/ uint64_t n; /**< RSA key, > 0 and < 2^1536 (24 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 1536 Decryption with CRT, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP2_1536. */ typedef struct icp_qat_fw_mmp_rsa_dp2_1536_input_s { uint64_t c; /**< cipher text representative, < (p*q) (24 qwords)*/ uint64_t p; /**< RSA parameter, prime,  2^767 < p < 2^768 (12 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^767 < p < 2^768 (12 qwords)*/ uint64_t dp; /**< RSA private key, 0 < dp < p-1 (12 qwords)*/ uint64_t dq; /**< RSA private key, 0 < dq < q-1 (12 qwords)*/ uint64_t qinv; /**< RSA private key, 0 < qInv < p (12 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 2048 key generation first form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP1_2048. */ typedef struct icp_qat_fw_mmp_rsa_kp1_2048_input_s { uint64_t p; /**< RSA parameter, prime,  2 < p < 2^1024 (16 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2 < q < 2^1024 (16 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (32 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 2048 key generation second form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP2_2048. */ typedef struct icp_qat_fw_mmp_rsa_kp2_2048_input_s { uint64_t p; /**< RSA parameter, prime,  2^1023 < p < 2^1024 (16 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^1023 < q < 2^1024 (16 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (32 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 2048 Encryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_EP_2048. */ typedef struct icp_qat_fw_mmp_rsa_ep_2048_input_s { uint64_t m; /**< message representative, < n (32 qwords)*/ uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (32 qwords)*/ uint64_t n; /**< RSA key > 0 and < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_rsa_ep_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 2048 Decryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP1_2048. */ typedef struct icp_qat_fw_mmp_rsa_dp1_2048_input_s { uint64_t c; /**< cipher text representative, < n (32 qwords)*/ uint64_t d; /**< RSA private key (32 qwords)*/ uint64_t n; /**< RSA key > 0 and < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 2048 Decryption with CRT, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP2_2048. */ typedef struct icp_qat_fw_mmp_rsa_dp2_2048_input_s { uint64_t c; /**< cipher text representative, < (p*q) (32 qwords)*/ uint64_t p; /**< RSA parameter, prime,  2^1023 < p < 2^1024 (16 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^1023 < q < 2^1024 (16 qwords)*/ uint64_t dp; /**< RSA private key, 0 < dp < p-1 (16 qwords)*/ uint64_t dq; /**< RSA private key, 0 < dq < q-1 (16 qwords)*/ uint64_t qinv; /**< RSA private key, 0 < qInv < p (16 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 3072 key generation first form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP1_3072. */ typedef struct icp_qat_fw_mmp_rsa_kp1_3072_input_s { uint64_t p; /**< RSA parameter, prime,  2 < p < 2^1536 (24 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2 < q < 2^1536 (24 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (48 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 3072 key generation second form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP2_3072. */ typedef struct icp_qat_fw_mmp_rsa_kp2_3072_input_s { uint64_t p; /**< RSA parameter, prime,  2^1535 < p < 2^1536 (24 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^1535 < q < 2^1536 (24 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (48 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 3072 Encryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_EP_3072. */ typedef struct icp_qat_fw_mmp_rsa_ep_3072_input_s { uint64_t m; /**< message representative, < n (48 qwords)*/ uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (48 qwords)*/ uint64_t n; /**< RSA key > 0 and < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_rsa_ep_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 3072 Decryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP1_3072. */ typedef struct icp_qat_fw_mmp_rsa_dp1_3072_input_s { uint64_t c; /**< cipher text representative, < n (48 qwords)*/ uint64_t d; /**< RSA private key (48 qwords)*/ uint64_t n; /**< RSA key > 0 and < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 3072 Decryption with CRT, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP2_3072. */ typedef struct icp_qat_fw_mmp_rsa_dp2_3072_input_s { uint64_t c; /**< cipher text representative, < (p*q) (48 qwords)*/ uint64_t p; /**< RSA parameter, prime,  2^1535 < p < 2^1536 (24 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^1535 < q < 2^1536 (24 qwords)*/ uint64_t dp; /**< RSA private key, 0 < dp < p-1 (24 qwords)*/ uint64_t dq; /**< RSA private key, 0 < dq < q-1 (24 qwords)*/ uint64_t qinv; /**< RSA private key, 0 < qInv < p (24 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 4096 key generation first form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP1_4096. */ typedef struct icp_qat_fw_mmp_rsa_kp1_4096_input_s { uint64_t p; /**< RSA parameter, prime,  2 < p < 2^2048 (32 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2 < q < 2^2048 (32 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (64 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 4096 key generation second form, to be used * when icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_KP2_4096. */ typedef struct icp_qat_fw_mmp_rsa_kp2_4096_input_s { uint64_t p; /**< RSA parameter, prime,  2^2047 < p < 2^2048 (32 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^2047 < q < 2^2048 (32 qwords)*/ uint64_t e; /**< RSA public key, must be odd, ≥ 3 and ≤ (p*q)-1,  with GCD(e, p-1, q-1) = 1 (64 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 4096 Encryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_EP_4096. */ typedef struct icp_qat_fw_mmp_rsa_ep_4096_input_s { uint64_t m; /**< message representative, < n (64 qwords)*/ uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (64 qwords)*/ uint64_t n; /**< RSA key, > 0 and < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_rsa_ep_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 4096 Decryption, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP1_4096. */ typedef struct icp_qat_fw_mmp_rsa_dp1_4096_input_s { uint64_t c; /**< cipher text representative, < n (64 qwords)*/ uint64_t d; /**< RSA private key (64 qwords)*/ uint64_t n; /**< RSA key, > 0 and < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 4096 Decryption with CRT, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_RSA_DP2_4096. */ typedef struct icp_qat_fw_mmp_rsa_dp2_4096_input_s { uint64_t c; /**< cipher text representative, < (p*q) (64 qwords)*/ uint64_t p; /**< RSA parameter, prime,  2^2047 < p < 2^2048 (32 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^2047 < q < 2^2048 (32 qwords)*/ uint64_t dp; /**< RSA private key, 0 < dp < p-1 (32 qwords)*/ uint64_t dq; /**< RSA private key, 0 < dq < q-1 (32 qwords)*/ uint64_t qinv; /**< RSA private key, 0 < qInv < p (32 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 8192 Encryption, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_RSA_EP_8192. */ typedef struct icp_qat_fw_mmp_rsa_ep_8192_input_s { uint64_t m; /**< message representative, < n (128 qwords)*/ uint64_t e; /**< RSA public key, ≥ 3 and ≤ n-1 (128 qwords)*/ uint64_t n; /**< RSA key, > 0 and < 2^8192 (128 qwords)*/ } icp_qat_fw_mmp_rsa_ep_8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 8192 Decryption, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_RSA_DP1_8192. */ typedef struct icp_qat_fw_mmp_rsa_dp1_8192_input_s { uint64_t c; /**< cipher text representative, < n (128 qwords)*/ uint64_t d; /**< RSA private key (128 qwords)*/ uint64_t n; /**< RSA key, > 0 and < 2^8192 (128 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for RSA 8192 Decryption with CRT, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_RSA_DP2_8192. */ typedef struct icp_qat_fw_mmp_rsa_dp2_8192_input_s { uint64_t c; /**< cipher text representative, < (p*q) (128 qwords)*/ uint64_t p; /**< RSA parameter, prime,  2^4095 < p < 2^4096 (64 qwords)*/ uint64_t q; /**< RSA parameter, prime,  2^4095 < q < 2^4096 (64 qwords)*/ uint64_t dp; /**< RSA private key, 0 < dp < p-1 (64 qwords)*/ uint64_t dq; /**< RSA private key, 0 < dq < q-1 (64 qwords)*/ uint64_t qinv; /**< RSA private key, 0 < qInv < p (64 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 192-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_192. */ typedef struct icp_qat_fw_mmp_gcd_pt_192_input_s { uint64_t m; /**< prime candidate > 1 and < 2^192 (3 qwords)*/ } icp_qat_fw_mmp_gcd_pt_192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 256-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_256. */ typedef struct icp_qat_fw_mmp_gcd_pt_256_input_s { uint64_t m; /**< prime candidate > 1 and < 2^256 (4 qwords)*/ } icp_qat_fw_mmp_gcd_pt_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 384-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_384. */ typedef struct icp_qat_fw_mmp_gcd_pt_384_input_s { uint64_t m; /**< prime candidate > 1 and < 2^384 (6 qwords)*/ } icp_qat_fw_mmp_gcd_pt_384_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 512-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_512. */ typedef struct icp_qat_fw_mmp_gcd_pt_512_input_s { uint64_t m; /**< prime candidate > 1 and < 2^512 (8 qwords)*/ } icp_qat_fw_mmp_gcd_pt_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 768-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_768. */ typedef struct icp_qat_fw_mmp_gcd_pt_768_input_s { uint64_t m; /**< prime candidate > 1 and < 2^768 (12 qwords)*/ } icp_qat_fw_mmp_gcd_pt_768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 1024-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_1024. */ typedef struct icp_qat_fw_mmp_gcd_pt_1024_input_s { uint64_t m; /**< prime candidate > 1 and < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_gcd_pt_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 1536-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_1536. */ typedef struct icp_qat_fw_mmp_gcd_pt_1536_input_s { uint64_t m; /**< (24 qwords)*/ } icp_qat_fw_mmp_gcd_pt_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 2048-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_2048. */ typedef struct icp_qat_fw_mmp_gcd_pt_2048_input_s { uint64_t m; /**< prime candidate > 1 and < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_gcd_pt_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 3072-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_3072. */ typedef struct icp_qat_fw_mmp_gcd_pt_3072_input_s { uint64_t m; /**< prime candidate > 1 and < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_gcd_pt_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for GCD primality test for 4096-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_GCD_PT_4096. */ typedef struct icp_qat_fw_mmp_gcd_pt_4096_input_s { uint64_t m; /**< prime candidate > 1 and < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_gcd_pt_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 160-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_FERMAT_PT_160. */ typedef struct icp_qat_fw_mmp_fermat_pt_160_input_s { uint64_t m; /**< prime candidate, 2^159 < m < 2^160 (3 qwords)*/ } icp_qat_fw_mmp_fermat_pt_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 512-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_FERMAT_PT_512. */ typedef struct icp_qat_fw_mmp_fermat_pt_512_input_s { uint64_t m; /**< prime candidate, 2^511 < m < 2^512 (8 qwords)*/ } icp_qat_fw_mmp_fermat_pt_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for <e; 512-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_FERMAT_PT_L512. */ typedef struct icp_qat_fw_mmp_fermat_pt_l512_input_s { uint64_t m; /**< prime candidate, 5 < m < 2^512 (8 qwords)*/ } icp_qat_fw_mmp_fermat_pt_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 768-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_FERMAT_PT_768. */ typedef struct icp_qat_fw_mmp_fermat_pt_768_input_s { uint64_t m; /**< prime candidate, 2^767 < m < 2^768 (12 qwords)*/ } icp_qat_fw_mmp_fermat_pt_768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 1024-bit numbers, to * be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_FERMAT_PT_1024. */ typedef struct icp_qat_fw_mmp_fermat_pt_1024_input_s { uint64_t m; /**< prime candidate, 2^1023 < m < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_fermat_pt_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 1536-bit numbers, to * be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_FERMAT_PT_1536. */ typedef struct icp_qat_fw_mmp_fermat_pt_1536_input_s { uint64_t m; /**< prime candidate, 2^1535 < m < 2^1536 (24 qwords)*/ } icp_qat_fw_mmp_fermat_pt_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 2048-bit numbers, to * be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_FERMAT_PT_2048. */ typedef struct icp_qat_fw_mmp_fermat_pt_2048_input_s { uint64_t m; /**< prime candidate, 2^2047 < m < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_fermat_pt_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 3072-bit numbers, to * be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_FERMAT_PT_3072. */ typedef struct icp_qat_fw_mmp_fermat_pt_3072_input_s { uint64_t m; /**< prime candidate, 2^3071 < m < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_fermat_pt_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Fermat primality test for 4096-bit numbers, to * be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_FERMAT_PT_4096. */ typedef struct icp_qat_fw_mmp_fermat_pt_4096_input_s { uint64_t m; /**< prime candidate, 2^4095 < m < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_fermat_pt_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 160-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_160. */ typedef struct icp_qat_fw_mmp_mr_pt_160_input_s { uint64_t x; /**< randomness > 1 and < m-1 (3 qwords)*/ uint64_t m; /**< prime candidate > 2^159 and < 2^160 (3 qwords)*/ } icp_qat_fw_mmp_mr_pt_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 512-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_512. */ typedef struct icp_qat_fw_mmp_mr_pt_512_input_s { uint64_t x; /**< randomness > 1 and < m-1 (8 qwords)*/ uint64_t m; /**< prime candidate > 2^511 and < 2^512 (8 qwords)*/ } icp_qat_fw_mmp_mr_pt_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 768-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_768. */ typedef struct icp_qat_fw_mmp_mr_pt_768_input_s { uint64_t x; /**< randomness > 1 and < m-1 (12 qwords)*/ uint64_t m; /**< prime candidate > 2^767 and < 2^768 (12 qwords)*/ } icp_qat_fw_mmp_mr_pt_768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 1024-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_1024. */ typedef struct icp_qat_fw_mmp_mr_pt_1024_input_s { uint64_t x; /**< randomness > 1 and < m-1 (16 qwords)*/ uint64_t m; /**< prime candidate > 2^1023 and < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_mr_pt_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 1536-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_1536. */ typedef struct icp_qat_fw_mmp_mr_pt_1536_input_s { uint64_t x; /**< randomness > 1 and < m-1 (24 qwords)*/ uint64_t m; /**< prime candidate > 2^1535 and < 2^1536 (24 qwords)*/ } icp_qat_fw_mmp_mr_pt_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 2048-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_2048. */ typedef struct icp_qat_fw_mmp_mr_pt_2048_input_s { uint64_t x; /**< randomness > 1 and <m-1 (32 qwords)*/ uint64_t m; /**< prime candidate > 2^2047 and < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_mr_pt_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 3072-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_3072. */ typedef struct icp_qat_fw_mmp_mr_pt_3072_input_s { uint64_t x; /**< randomness > 1 and < m-1 (48 qwords)*/ uint64_t m; /**< prime candidate > 2^3071 and < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_mr_pt_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 4096-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_4096. */ typedef struct icp_qat_fw_mmp_mr_pt_4096_input_s { uint64_t x; /**< randomness > 1 and < m-1 (64 qwords)*/ uint64_t m; /**< prime candidate > 2^4095 and < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_mr_pt_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Miller-Rabin primality test for 512-bit numbers, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_MR_PT_L512. */ typedef struct icp_qat_fw_mmp_mr_pt_l512_input_s { uint64_t x; /**< randomness > 1 and < m-1 (8 qwords)*/ uint64_t m; /**< prime candidate > 1 and < 2^512 (8 qwords)*/ } icp_qat_fw_mmp_mr_pt_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 160-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_160. */ typedef struct icp_qat_fw_mmp_lucas_pt_160_input_s { uint64_t m; /**< odd prime candidate > 2^159 and < 2^160 (3 qwords)*/ } icp_qat_fw_mmp_lucas_pt_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 512-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_512. */ typedef struct icp_qat_fw_mmp_lucas_pt_512_input_s { uint64_t m; /**< odd prime candidate > 2^511 and < 2^512 (8 qwords)*/ } icp_qat_fw_mmp_lucas_pt_512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 768-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_768. */ typedef struct icp_qat_fw_mmp_lucas_pt_768_input_s { uint64_t m; /**< odd prime candidate > 2^767 and < 2^768 (12 qwords)*/ } icp_qat_fw_mmp_lucas_pt_768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 1024-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_1024. */ typedef struct icp_qat_fw_mmp_lucas_pt_1024_input_s { uint64_t m; /**< odd prime candidate > 2^1023 and < 2^1024 (16 qwords)*/ } icp_qat_fw_mmp_lucas_pt_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 1536-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_1536. */ typedef struct icp_qat_fw_mmp_lucas_pt_1536_input_s { uint64_t m; /**< odd prime candidate > 2^1535 and < 2^1536 (24 qwords)*/ } icp_qat_fw_mmp_lucas_pt_1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 2048-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_2048. */ typedef struct icp_qat_fw_mmp_lucas_pt_2048_input_s { uint64_t m; /**< odd prime candidate > 2^2047 and < 2^2048 (32 qwords)*/ } icp_qat_fw_mmp_lucas_pt_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 3072-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_3072. */ typedef struct icp_qat_fw_mmp_lucas_pt_3072_input_s { uint64_t m; /**< odd prime candidate > 2^3071 and < 2^3072 (48 qwords)*/ } icp_qat_fw_mmp_lucas_pt_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for 4096-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_4096. */ typedef struct icp_qat_fw_mmp_lucas_pt_4096_input_s { uint64_t m; /**< odd prime candidate > 2^4096 and < 2^4096 (64 qwords)*/ } icp_qat_fw_mmp_lucas_pt_4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Lucas primality test for L512-bit numbers, to be * used when icp_qat_fw_pke_request_s::functionalityId is #PKE_LUCAS_PT_L512. */ typedef struct icp_qat_fw_mmp_lucas_pt_l512_input_s { uint64_t m; /**< odd prime candidate > 5 and < 2^512 (8 qwords)*/ } icp_qat_fw_mmp_lucas_pt_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 512-bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L512. */ typedef struct icp_qat_fw_maths_modexp_l512_input_s { uint64_t g; /**< base ≥ 0 and < 2^512 (8 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^512 (8 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^512 (8 qwords)*/ } icp_qat_fw_maths_modexp_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 1024-bit, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L1024. */ typedef struct icp_qat_fw_maths_modexp_l1024_input_s { uint64_t g; /**< base ≥ 0 and < 2^1024 (16 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^1024 (16 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^1024 (16 qwords)*/ } icp_qat_fw_maths_modexp_l1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 1536-bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L1536. */ typedef struct icp_qat_fw_maths_modexp_l1536_input_s { uint64_t g; /**< base ≥ 0 and < 2^1536 (24 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^1536 (24 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^1536 (24 qwords)*/ } icp_qat_fw_maths_modexp_l1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 2048-bit, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L2048. */ typedef struct icp_qat_fw_maths_modexp_l2048_input_s { uint64_t g; /**< base ≥ 0 and < 2^2048 (32 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^2048 (32 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^2048 (32 qwords)*/ } icp_qat_fw_maths_modexp_l2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 2560-bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L2560. */ typedef struct icp_qat_fw_maths_modexp_l2560_input_s { uint64_t g; /**< base ≥ 0 and < 2^2560 (40 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^2560 (40 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^2560 (40 qwords)*/ } icp_qat_fw_maths_modexp_l2560_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 3072-bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L3072. */ typedef struct icp_qat_fw_maths_modexp_l3072_input_s { uint64_t g; /**< base ≥ 0 and < 2^3072 (48 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^3072 (48 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^3072 (48 qwords)*/ } icp_qat_fw_maths_modexp_l3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 3584-bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L3584. */ typedef struct icp_qat_fw_maths_modexp_l3584_input_s { uint64_t g; /**< base ≥ 0 and < 2^3584 (56 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^3584 (56 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^3584 (56 qwords)*/ } icp_qat_fw_maths_modexp_l3584_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers less than * 4096-bit, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L4096. */ typedef struct icp_qat_fw_maths_modexp_l4096_input_s { uint64_t g; /**< base ≥ 0 and < 2^4096 (64 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^4096 (64 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^4096 (64 qwords)*/ } icp_qat_fw_maths_modexp_l4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular exponentiation for numbers up to 8192 * bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODEXP_L8192. */ typedef struct icp_qat_fw_maths_modexp_l8192_input_s { uint64_t g; /**< base ≥ 0 and < 2^8192 (128 qwords)*/ uint64_t e; /**< exponent ≥ 0 and < 2^8192 (128 qwords)*/ uint64_t m; /**< modulus > 0 and < 2^8192 (128 qwords)*/ } icp_qat_fw_maths_modexp_l8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 128 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L128. */ typedef struct icp_qat_fw_maths_modinv_odd_l128_input_s { uint64_t a; /**< number > 0 and < 2^128 (2 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^128, coprime to a (2 qwords)*/ } icp_qat_fw_maths_modinv_odd_l128_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 192 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L192. */ typedef struct icp_qat_fw_maths_modinv_odd_l192_input_s { uint64_t a; /**< number > 0 and < 2^192 (3 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^192, coprime to a (3 qwords)*/ } icp_qat_fw_maths_modinv_odd_l192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 256 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L256. */ typedef struct icp_qat_fw_maths_modinv_odd_l256_input_s { uint64_t a; /**< number > 0 and < 2^256 (4 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^256, coprime to a (4 qwords)*/ } icp_qat_fw_maths_modinv_odd_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 384 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L384. */ typedef struct icp_qat_fw_maths_modinv_odd_l384_input_s { uint64_t a; /**< number > 0 and < 2^384 (6 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^384, coprime to a (6 qwords)*/ } icp_qat_fw_maths_modinv_odd_l384_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 512 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L512. */ typedef struct icp_qat_fw_maths_modinv_odd_l512_input_s { uint64_t a; /**< number > 0 and < 2^512 (8 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^512, coprime to a (8 qwords)*/ } icp_qat_fw_maths_modinv_odd_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 768 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L768. */ typedef struct icp_qat_fw_maths_modinv_odd_l768_input_s { uint64_t a; /**< number > 0 and < 2^768 (12 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^768,coprime to a (12 qwords)*/ } icp_qat_fw_maths_modinv_odd_l768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 1024 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L1024. */ typedef struct icp_qat_fw_maths_modinv_odd_l1024_input_s { uint64_t a; /**< number > 0 and < 2^1024 (16 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^1024, coprime to a (16 qwords)*/ } icp_qat_fw_maths_modinv_odd_l1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 1536 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L1536. */ typedef struct icp_qat_fw_maths_modinv_odd_l1536_input_s { uint64_t a; /**< number > 0 and < 2^1536 (24 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^1536, coprime to a (24 qwords)*/ } icp_qat_fw_maths_modinv_odd_l1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 2048 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L2048. */ typedef struct icp_qat_fw_maths_modinv_odd_l2048_input_s { uint64_t a; /**< number > 0 and < 2^2048 (32 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^2048, coprime to a (32 qwords)*/ } icp_qat_fw_maths_modinv_odd_l2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 3072 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L3072. */ typedef struct icp_qat_fw_maths_modinv_odd_l3072_input_s { uint64_t a; /**< number > 0 and < 2^3072 (48 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^3072, coprime to a (48 qwords)*/ } icp_qat_fw_maths_modinv_odd_l3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 4096 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_ODD_L4096. */ typedef struct icp_qat_fw_maths_modinv_odd_l4096_input_s { uint64_t a; /**< number > 0 and < 2^4096 (64 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^4096, coprime to a (64 qwords)*/ } icp_qat_fw_maths_modinv_odd_l4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers up to * 8192 bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODINV_ODD_L8192. */ typedef struct icp_qat_fw_maths_modinv_odd_l8192_input_s { uint64_t a; /**< number > 0 and < 2^8192 (128 qwords)*/ uint64_t b; /**< odd modulus > 0 and < 2^8192, coprime to a (128 qwords)*/ } icp_qat_fw_maths_modinv_odd_l8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 128 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L128. */ typedef struct icp_qat_fw_maths_modinv_even_l128_input_s { uint64_t a; /**< odd number > 0 and < 2^128 (2 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^128, coprime with a (2 qwords)*/ } icp_qat_fw_maths_modinv_even_l128_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 192 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L192. */ typedef struct icp_qat_fw_maths_modinv_even_l192_input_s { uint64_t a; /**< odd number > 0 and < 2^192 (3 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^192, coprime with a (3 qwords)*/ } icp_qat_fw_maths_modinv_even_l192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 256 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L256. */ typedef struct icp_qat_fw_maths_modinv_even_l256_input_s { uint64_t a; /**< odd number > 0 and < 2^256 (4 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^256, coprime with a (4 qwords)*/ } icp_qat_fw_maths_modinv_even_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 384 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L384. */ typedef struct icp_qat_fw_maths_modinv_even_l384_input_s { uint64_t a; /**< odd number > 0 and < 2^384 (6 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^384, coprime with a (6 qwords)*/ } icp_qat_fw_maths_modinv_even_l384_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 512 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L512. */ typedef struct icp_qat_fw_maths_modinv_even_l512_input_s { uint64_t a; /**< odd number > 0 and < 2^512 (8 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^512, coprime with a (8 qwords)*/ } icp_qat_fw_maths_modinv_even_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 768 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L768. */ typedef struct icp_qat_fw_maths_modinv_even_l768_input_s { uint64_t a; /**< odd number > 0 and < 2^768 (12 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^768, coprime with a (12 qwords)*/ } icp_qat_fw_maths_modinv_even_l768_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 1024 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L1024. */ typedef struct icp_qat_fw_maths_modinv_even_l1024_input_s { uint64_t a; /**< odd number > 0 and < 2^1024 (16 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^1024, coprime with a (16 qwords)*/ } icp_qat_fw_maths_modinv_even_l1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 1536 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L1536. */ typedef struct icp_qat_fw_maths_modinv_even_l1536_input_s { uint64_t a; /**< odd number > 0 and < 2^1536 (24 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^1536, coprime with a (24 qwords)*/ } icp_qat_fw_maths_modinv_even_l1536_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 2048 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L2048. */ typedef struct icp_qat_fw_maths_modinv_even_l2048_input_s { uint64_t a; /**< odd number > 0 and < 2^2048 (32 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^2048, coprime with a (32 qwords)*/ } icp_qat_fw_maths_modinv_even_l2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 3072 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L3072. */ typedef struct icp_qat_fw_maths_modinv_even_l3072_input_s { uint64_t a; /**< odd number > 0 and < 2^3072 (48 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^3072, coprime with a (48 qwords)*/ } icp_qat_fw_maths_modinv_even_l3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers less * than 4096 bits, to be used when icp_qat_fw_pke_request_s::functionalityId * is #MATHS_MODINV_EVEN_L4096. */ typedef struct icp_qat_fw_maths_modinv_even_l4096_input_s { uint64_t a; /**< odd number > 0 and < 2^4096 (64 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^4096, coprime with a (64 qwords)*/ } icp_qat_fw_maths_modinv_even_l4096_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for Modular multiplicative inverse for numbers up to * 8192 bits, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_MODINV_EVEN_L8192. */ typedef struct icp_qat_fw_maths_modinv_even_l8192_input_s { uint64_t a; /**< odd number > 0 and < 2^8192 (128 qwords)*/ uint64_t b; /**< even modulus > 0 and < 2^8192, coprime with a (128 qwords)*/ } icp_qat_fw_maths_modinv_even_l8192_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_P_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_1024_160_input_s { uint64_t x; /**< DSA 1024-bit randomness (16 qwords)*/ uint64_t q; /**< DSA 160-bit parameter (3 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA key generation G, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_G_1024. */ typedef struct icp_qat_fw_mmp_dsa_gen_g_1024_input_s { uint64_t p; /**< DSA 1024-bit parameter (16 qwords)*/ uint64_t q; /**< DSA 160-bit parameter (3 qwords)*/ uint64_t h; /**< DSA 1024-bit parameter (16 qwords)*/ } icp_qat_fw_mmp_dsa_gen_g_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA key generation Y, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_Y_1024. */ typedef struct icp_qat_fw_mmp_dsa_gen_y_1024_input_s { uint64_t p; /**< DSA 1024-bit parameter (16 qwords)*/ uint64_t g; /**< DSA parameter (16 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (160 bits), (3 qwords)*/ } icp_qat_fw_mmp_dsa_gen_y_1024_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s { uint64_t k; /**< randomly generated DSA parameter (3 qwords)*/ uint64_t p; /**< DSA parameter, (16 qwords)*/ uint64_t q; /**< DSA parameter (3 qwords)*/ uint64_t g; /**< DSA parameter (16 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_S_160. */ typedef struct icp_qat_fw_mmp_dsa_sign_s_160_input_s { uint64_t m; /**< digest message to be signed (3 qwords)*/ uint64_t k; /**< randomly generated DSA parameter (3 qwords)*/ uint64_t q; /**< DSA parameter (3 qwords)*/ uint64_t r; /**< DSA parameter (3 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (3 qwords)*/ } icp_qat_fw_mmp_dsa_sign_s_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_S_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s { uint64_t m; /**< digest of the message to be signed (3 qwords)*/ uint64_t k; /**< randomly generated DSA parameter (3 qwords)*/ uint64_t p; /**< DSA parameter (16 qwords)*/ uint64_t q; /**< DSA parameter (3 qwords)*/ uint64_t g; /**< DSA parameter (16 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (3 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_VERIFY_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_verify_1024_160_input_s { uint64_t r; /**< DSA 160-bits signature (3 qwords)*/ uint64_t s; /**< DSA 160-bits signature (3 qwords)*/ uint64_t m; /**< digest of the message (3 qwords)*/ uint64_t p; /**< DSA parameter (16 qwords)*/ uint64_t q; /**< DSA parameter (3 qwords)*/ uint64_t g; /**< DSA parameter (16 qwords)*/ uint64_t y; /**< DSA parameter (16 qwords)*/ } icp_qat_fw_mmp_dsa_verify_1024_160_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_P_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_224_input_s { uint64_t x; /**< DSA 2048-bit randomness (32 qwords)*/ uint64_t q; /**< DSA 224-bit parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_2048_224_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA key generation Y, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_Y_2048. */ typedef struct icp_qat_fw_mmp_dsa_gen_y_2048_input_s { uint64_t p; /**< DSA 2048-bit parameter (32 qwords)*/ uint64_t g; /**< DSA parameter (32 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (224/256 bits), (4 qwords)*/ } icp_qat_fw_mmp_dsa_gen_y_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s { uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t p; /**< DSA parameter, (32 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (32 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_S_224. */ typedef struct icp_qat_fw_mmp_dsa_sign_s_224_input_s { uint64_t m; /**< digest message to be signed (4 qwords)*/ uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t r; /**< DSA parameter (4 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_s_224_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_S_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s { uint64_t m; /**< digest of the message to be signed (4 qwords)*/ uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t p; /**< DSA parameter (32 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (32 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_VERIFY_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_verify_2048_224_input_s { uint64_t r; /**< DSA 224-bits signature (4 qwords)*/ uint64_t s; /**< DSA 224-bits signature (4 qwords)*/ uint64_t m; /**< digest of the message (4 qwords)*/ uint64_t p; /**< DSA parameter (32 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (32 qwords)*/ uint64_t y; /**< DSA parameter (32 qwords)*/ } icp_qat_fw_mmp_dsa_verify_2048_224_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_P_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_256_input_s { uint64_t x; /**< DSA 2048-bit randomness (32 qwords)*/ uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_2048_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA key generation G, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_G_2048. */ typedef struct icp_qat_fw_mmp_dsa_gen_g_2048_input_s { uint64_t p; /**< DSA 2048-bit parameter (32 qwords)*/ uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ uint64_t h; /**< DSA 2048-bit parameter (32 qwords)*/ } icp_qat_fw_mmp_dsa_gen_g_2048_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s { uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t p; /**< DSA parameter, (32 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (32 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_S_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_s_256_input_s { uint64_t m; /**< digest message to be signed (4 qwords)*/ uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t r; /**< DSA parameter (4 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_s_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_S_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s { uint64_t m; /**< digest of the message to be signed (4 qwords)*/ uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t p; /**< DSA parameter (32 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (32 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_VERIFY_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_verify_2048_256_input_s { uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ uint64_t m; /**< digest of the message (4 qwords)*/ uint64_t p; /**< DSA parameter (32 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (32 qwords)*/ uint64_t y; /**< DSA parameter (32 qwords)*/ } icp_qat_fw_mmp_dsa_verify_2048_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_P_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_3072_256_input_s { uint64_t x; /**< DSA 3072-bit randomness (48 qwords)*/ uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_3072_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA key generation G, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_G_3072. */ typedef struct icp_qat_fw_mmp_dsa_gen_g_3072_input_s { uint64_t p; /**< DSA 3072-bit parameter (48 qwords)*/ uint64_t q; /**< DSA 256-bit parameter (4 qwords)*/ uint64_t h; /**< DSA 3072-bit parameter (48 qwords)*/ } icp_qat_fw_mmp_dsa_gen_g_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA key generation Y, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_GEN_Y_3072. */ typedef struct icp_qat_fw_mmp_dsa_gen_y_3072_input_s { uint64_t p; /**< DSA 3072-bit parameter (48 qwords)*/ uint64_t g; /**< DSA parameter (48 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (3072 bits), (4 qwords)*/ } icp_qat_fw_mmp_dsa_gen_y_3072_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s { uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t p; /**< DSA parameter, (48 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (48 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_SIGN_R_S_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s { uint64_t m; /**< digest of the message to be signed (4 qwords)*/ uint64_t k; /**< randomly generated DSA parameter (4 qwords)*/ uint64_t p; /**< DSA parameter (48 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (48 qwords)*/ uint64_t x; /**< randomly generated DSA parameter (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for DSA Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_DSA_VERIFY_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_verify_3072_256_input_s { uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ uint64_t m; /**< digest of the message (4 qwords)*/ uint64_t p; /**< DSA parameter (48 qwords)*/ uint64_t q; /**< DSA parameter (4 qwords)*/ uint64_t g; /**< DSA parameter (48 qwords)*/ uint64_t y; /**< DSA parameter (48 qwords)*/ } icp_qat_fw_mmp_dsa_verify_3072_256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA Sign RS for curves B/K-163 and B/K-233, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_SIGN_RS_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_s { uint64_t in; /**< concatenated input parameters (G, n, q, a, b, k, e, d) (36 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA Sign R for curves B/K-163 and B/K-233, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_SIGN_R_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s { uint64_t xg; /**< x coordinate of base point G of B/K-163 of B/K-233 (4 qwords)*/ uint64_t yg; /**< y coordinate of base point G of B/K-163 or B/K-233 (4 qwords)*/ uint64_t n; /**< order of the base point of B/K-163 or B/K-233 (4 qwords)*/ uint64_t q; /**< field polynomial of B/K-163 or B/K-233 (4 qwords)*/ uint64_t a; /**< a equation coefficient of B/K-163 of B/K-233 (4 qwords)*/ uint64_t b; /**< b equation coefficient of B/K-163 or B/K-233 (4 qwords)*/ uint64_t k; /**< random value > 0 and < n (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA Sign S for curves with n < 2^256, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_SIGN_S_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s { uint64_t e; /**< hash of message (0 < e < 2^256) (4 qwords)*/ uint64_t d; /**< private key (>0 and < n) (4 qwords)*/ uint64_t r; /**< ECDSA r signature value (>0 and < n) (4 qwords)*/ uint64_t k; /**< random value > 0 and < n (4 qwords)*/ uint64_t n; /**< order of the base point G (2 < n < 2^256) (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA Verify for curves B/K-163 and B/K-233, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_VERIFY_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_s { uint64_t in; /**< concatenated curve parameter (e,s,r,n,G,Q,a,b,q) (44 qwords)*/ } icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA Sign RS, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_RS_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_s { uint64_t in; /**< concatenated input parameters (G, n, q, a, b, k, e, d) (72 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GF2 Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_R_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s { uint64_t xg; /**< x coordinate of verified base point (> 0 and degree(x(G)) < degree(q)) (8 qwords)*/ uint64_t yg; /**< y coordinate of verified base point (> 0 and degree(y(G)) < degree(q)) (8 qwords)*/ uint64_t n; /**< order of the base point G, which must be prime and a divisor of #E and < 2^512) (8 qwords)*/ uint64_t q; /**< field polynomial of degree > 2 and < 512 (8 qwords)*/ uint64_t a; /**< a equation coefficient (degree(a) < degree(q)) (8 qwords)*/ uint64_t b; /**< b equation coefficient (degree(b) < degree(q)) (8 qwords)*/ uint64_t k; /**< random value > 0 and < n (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GF2 Sign S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_S_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s { uint64_t e; /**< hash of message (0 < e < 2^512) (8 qwords)*/ uint64_t d; /**< private key (>0 and < n) (8 qwords)*/ uint64_t r; /**< ECDSA r signature value (>0 and < n) (8 qwords)*/ uint64_t k; /**< random value > 0 and < n (8 qwords)*/ uint64_t n; /**< order of the base point G, which must be prime and a divisor of #E and < 2^512) (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GF2 Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_VERIFY_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_s { uint64_t in; /**< concatenated curve parameters (e, s, r, n, xG, yG, xQ, yQ, a, b, q) (88 qwords)*/ } icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GF2 Sign RS for curves B-571/K-571, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_SIGN_RS_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_s { uint64_t in; /**< concatenated input parameters (x(G), y(G), n, q, a, b, k, e, d) (81 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GF2 Sign S for curves with deg(q) < 576, * to be used when icp_qat_fw_pke_request_s::functionalityId is * #PKE_ECDSA_SIGN_S_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s { uint64_t e; /**< hash of message < 2^576 (9 qwords)*/ uint64_t d; /**< private key (> 0 and < n) (9 qwords)*/ uint64_t r; /**< ECDSA r signature value (> 0 and < n) (9 qwords)*/ uint64_t k; /**< random value (> 0 and < n) (9 qwords)*/ uint64_t n; /**< order of the base point of the curve (n < 2^576) (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GF2 Sign R for degree 571, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_R_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s { uint64_t xg; /**< x coordinate of verified base point belonging to B/K-571 (9 qwords)*/ uint64_t yg; /**< y coordinate of verified base point belonging to B/K-571 (9 qwords)*/ uint64_t n; /**< order of the base point G (9 qwords)*/ uint64_t q; /**< irreducible field polynomial of B/K-571 (9 qwords)*/ uint64_t a; /**< a coefficient of curve B/K-571 (degree(a) < degree(q)) (9 qwords)*/ uint64_t b; /**< b coefficient of curve B/K-571 (degree(b) < degree(q)) (9 qwords)*/ uint64_t k; /**< random value > 0 and < n (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GF2 Verify for degree 571, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_VERIFY_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_s { uint64_t in; /**< concatenated input (e, s, r, n, G, Q, a, b, q) (99 qwords)*/ } icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for MATHS GF2 Point Multiplication, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GF2_L256. */ typedef struct icp_qat_fw_maths_point_multiplication_gf2_l256_input_s { uint64_t k; /**< scalar multiplier > 0 and < 2^256 (4 qwords)*/ uint64_t xg; /**< x coordinate of curve point (degree(xG) < 256) (4 qwords)*/ uint64_t yg; /**< y coordinate of curve point (degree(yG) < 256) (4 qwords)*/ uint64_t a; /**< a equation coefficient of B/K-163 or B/K-233 (4 qwords)*/ uint64_t b; /**< b equation coefficient of B/K-163 or B/K-233 (4 qwords)*/ uint64_t q; /**< field polynomial of B/K-163 or B/K-233 (4 qwords)*/ uint64_t h; /**< cofactor of B/K-163 or B/K-233 (4 qwords)*/ } icp_qat_fw_maths_point_multiplication_gf2_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for MATHS GF2 Point Verification, to be used when * icp_qat_fw_pke_request_s::functionalityId is #MATHS_POINT_VERIFY_GF2_L256. */ typedef struct icp_qat_fw_maths_point_verify_gf2_l256_input_s { uint64_t xq; /**< x coordinate of input point (4 qwords)*/ uint64_t yq; /**< y coordinate of input point (4 qwords)*/ uint64_t q; /**< field polynomial of curve, degree(q) < 256 (4 qwords)*/ uint64_t a; /**< a equation coefficient of curve, degree(a) < 256 (4 qwords)*/ uint64_t b; /**< b equation coefficient of curve, degree(b) < 256 (4 qwords)*/ } icp_qat_fw_maths_point_verify_gf2_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for MATHS GF2 Point Multiplication, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GF2_L512. */ typedef struct icp_qat_fw_maths_point_multiplication_gf2_l512_input_s { uint64_t k; /**< scalar multiplier > 0 and < 2^512 (8 qwords)*/ uint64_t xg; /**< x coordinate of curve point (degree(xG) < 512) (8 qwords)*/ uint64_t yg; /**< y coordinate of curve point (degree(yG) < 512) (8 qwords)*/ uint64_t a; /**< a equation coefficient (degree(a) < 512) (8 qwords)*/ uint64_t b; /**< b equation coefficient (degree(b) < 512) (8 qwords)*/ uint64_t q; /**< field polynomial of degree > 2 and < 512 (8 qwords)*/ uint64_t h; /**< cofactor (< 2^512) (8 qwords)*/ } icp_qat_fw_maths_point_multiplication_gf2_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for MATHS GF2 Point Verification, to be used when * icp_qat_fw_pke_request_s::functionalityId is #MATHS_POINT_VERIFY_GF2_L512. */ typedef struct icp_qat_fw_maths_point_verify_gf2_l512_input_s { uint64_t xq; /**< x coordinate of input point (8 qwords)*/ uint64_t yq; /**< y coordinate of input point (8 qwords)*/ uint64_t q; /**< field polynomial of degree > 2 and < 512 (8 qwords)*/ uint64_t a; /**< a equation coefficient (degree(a) < 512) (8 qwords)*/ uint64_t b; /**< b equation coefficient (degree(a) < 512) (8 qwords)*/ } icp_qat_fw_maths_point_verify_gf2_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GF2 Point Multiplication for curves * B-571/K-571, to be used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GF2_571. */ typedef struct icp_qat_fw_maths_point_multiplication_gf2_571_input_s { uint64_t k; /**< scalar value > 0 and < 2^576 (9 qwords)*/ uint64_t xg; /**< x coordinate of curve point (degree(xG) < degree(q)) (9 qwords)*/ uint64_t yg; /**< y coordinate of curve point (degree(xG) < degree(q)) (9 qwords)*/ uint64_t a; /**< a equation coefficient for B/K-571 (9 qwords)*/ uint64_t b; /**< b equation coefficient for B/K-571 (9 qwords)*/ uint64_t q; /**< field polynomial of B/K-571 (9 qwords)*/ uint64_t h; /**< cofactor for B/K-571 (1 qwords)*/ } icp_qat_fw_maths_point_multiplication_gf2_571_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GF2 Point Verification for degree 571, to be * used when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_VERIFY_GF2_571. */ typedef struct icp_qat_fw_maths_point_verify_gf2_571_input_s { uint64_t xq; /**< x coordinate of candidate public key (9 qwords)*/ uint64_t yq; /**< y coordinate of candidate public key (9 qwords)*/ uint64_t q; /**< field polynomial of B/K-571 (9 qwords)*/ uint64_t a; /**< a equation coefficient of B/K-571 (9 qwords)*/ uint64_t b; /**< b equation coefficient of B/K-571 (9 qwords)*/ } icp_qat_fw_maths_point_verify_gf2_571_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_R_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s { uint64_t xg; /**< x coordinate of base point G, (4 qwords)*/ uint64_t yg; /**< y coordinate of base point G, (4 qwords)*/ uint64_t n; /**< order of the base point G, which shall be prime (4 qwords)*/ uint64_t q; /**< modulus (4 qwords)*/ uint64_t a; /**< a equation coefficient (4 qwords)*/ uint64_t b; /**< b equation coefficient (4 qwords)*/ uint64_t k; /**< random value (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_S_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s { uint64_t e; /**< digest of the message to be signed (4 qwords)*/ uint64_t d; /**< private key (4 qwords)*/ uint64_t r; /**< DSA r signature value (4 qwords)*/ uint64_t k; /**< random value (4 qwords)*/ uint64_t n; /**< order of the base point G, which shall be prime (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign RS, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_RS_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_s { uint64_t in; /**< {xG, yG, n, q, a, b, k, e, d} concatenated (36 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_VERIFY_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_s { uint64_t in; /**< in = {e, s, r, n, xG, yG, xQ, yQ, a, b,q} concatenated (44 qwords)*/ } icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_R_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s { uint64_t xg; /**< x coordinate of base point G, (8 qwords)*/ uint64_t yg; /**< y coordinate of base point G, (8 qwords)*/ uint64_t n; /**< order of the base point G, which shall be prime (8 qwords)*/ uint64_t q; /**< modulus (8 qwords)*/ uint64_t a; /**< a equation coefficient (8 qwords)*/ uint64_t b; /**< b equation coefficient (8 qwords)*/ uint64_t k; /**< random value (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_S_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s { uint64_t e; /**< digest of the message to be signed (8 qwords)*/ uint64_t d; /**< private key (8 qwords)*/ uint64_t r; /**< DSA r signature value (8 qwords)*/ uint64_t k; /**< random value (8 qwords)*/ uint64_t n; /**< order of the base point G, which shall be prime (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign RS, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_RS_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_s { uint64_t in; /**< {xG, yG, n, q, a, b, k, e, d} concatenated (72 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_VERIFY_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_s { uint64_t in; /**< in = {e, s, r, n, xG, yG, xQ, yQ, a, b,q} concatenated (88 qwords)*/ } icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign R, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_R_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s { uint64_t xg; /**< x coordinate of base point G, (9 qwords)*/ uint64_t yg; /**< y coordinate of base point G, (9 qwords)*/ uint64_t n; /**< order of the base point G, which shall be prime (9 qwords)*/ uint64_t q; /**< modulus (9 qwords)*/ uint64_t a; /**< a equation coefficient (9 qwords)*/ uint64_t b; /**< b equation coefficient (9 qwords)*/ uint64_t k; /**< random value (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign S, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_S_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s { uint64_t e; /**< digest of the message to be signed (9 qwords)*/ uint64_t d; /**< private key (9 qwords)*/ uint64_t r; /**< DSA r signature value (9 qwords)*/ uint64_t k; /**< random value (9 qwords)*/ uint64_t n; /**< order of the base point G, which shall be prime (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Sign RS, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_SIGN_RS_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_s { uint64_t in; /**< {xG, yG, n, q, a, b, k, e, d} concatenated (81 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECDSA GFP Verify, to be used when * icp_qat_fw_pke_request_s::functionalityId is #PKE_ECDSA_VERIFY_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_s { uint64_t in; /**< in = {e, s, r, n, xG, yG, xQ, yQ, a, b,q} concatenated (99 qwords)*/ } icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GFP Point Multiplication, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GFP_L256. */ typedef struct icp_qat_fw_maths_point_multiplication_gfp_l256_input_s { uint64_t k; /**< scalar multiplier (4 qwords)*/ uint64_t xg; /**< x coordinate of curve point (4 qwords)*/ uint64_t yg; /**< y coordinate of curve point (4 qwords)*/ uint64_t a; /**< a equation coefficient (4 qwords)*/ uint64_t b; /**< b equation coefficient (4 qwords)*/ uint64_t q; /**< modulus (4 qwords)*/ uint64_t h; /**< cofactor (4 qwords)*/ } icp_qat_fw_maths_point_multiplication_gfp_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GFP Partial Point Verification, to be used * when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_VERIFY_GFP_L256. */ typedef struct icp_qat_fw_maths_point_verify_gfp_l256_input_s { uint64_t xq; /**< x coordinate of candidate point (4 qwords)*/ uint64_t yq; /**< y coordinate of candidate point (4 qwords)*/ uint64_t q; /**< modulus (4 qwords)*/ uint64_t a; /**< a equation coefficient (4 qwords)*/ uint64_t b; /**< b equation coefficient (4 qwords)*/ } icp_qat_fw_maths_point_verify_gfp_l256_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GFP Point Multiplication, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GFP_L512. */ typedef struct icp_qat_fw_maths_point_multiplication_gfp_l512_input_s { uint64_t k; /**< scalar multiplier (8 qwords)*/ uint64_t xg; /**< x coordinate of curve point (8 qwords)*/ uint64_t yg; /**< y coordinate of curve point (8 qwords)*/ uint64_t a; /**< a equation coefficient (8 qwords)*/ uint64_t b; /**< b equation coefficient (8 qwords)*/ uint64_t q; /**< modulus (8 qwords)*/ uint64_t h; /**< cofactor (8 qwords)*/ } icp_qat_fw_maths_point_multiplication_gfp_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GFP Partial Point, to be used when * icp_qat_fw_pke_request_s::functionalityId is #MATHS_POINT_VERIFY_GFP_L512. */ typedef struct icp_qat_fw_maths_point_verify_gfp_l512_input_s { uint64_t xq; /**< x coordinate of candidate point (8 qwords)*/ uint64_t yq; /**< y coordinate of candidate point (8 qwords)*/ uint64_t q; /**< modulus (8 qwords)*/ uint64_t a; /**< a equation coefficient (8 qwords)*/ uint64_t b; /**< b equation coefficient (8 qwords)*/ } icp_qat_fw_maths_point_verify_gfp_l512_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GFP Point Multiplication, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GFP_521. */ typedef struct icp_qat_fw_maths_point_multiplication_gfp_521_input_s { uint64_t k; /**< scalar multiplier (9 qwords)*/ uint64_t xg; /**< x coordinate of curve point (9 qwords)*/ uint64_t yg; /**< y coordinate of curve point (9 qwords)*/ uint64_t a; /**< a equation coefficient (9 qwords)*/ uint64_t b; /**< b equation coefficient (9 qwords)*/ uint64_t q; /**< modulus (9 qwords)*/ uint64_t h; /**< cofactor (1 qwords)*/ } icp_qat_fw_maths_point_multiplication_gfp_521_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC GFP Partial Point Verification, to be used * when icp_qat_fw_pke_request_s::functionalityId is * #MATHS_POINT_VERIFY_GFP_521. */ typedef struct icp_qat_fw_maths_point_verify_gfp_521_input_s { uint64_t xq; /**< x coordinate of candidate point (9 qwords)*/ uint64_t yq; /**< y coordinate of candidate point (9 qwords)*/ uint64_t q; /**< modulus (9 qwords)*/ uint64_t a; /**< a equation coefficient (9 qwords)*/ uint64_t b; /**< b equation coefficient (9 qwords)*/ } icp_qat_fw_maths_point_verify_gfp_521_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC curve25519 Variable Point Multiplication * [k]P(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_request_s::functionalityId is #POINT_MULTIPLICATION_C25519. */ typedef struct icp_qat_fw_point_multiplication_c25519_input_s { uint64_t xp; /**< xP=Montgomery affine coordinate X of point P(4 qwords)*/ uint64_t k; /**< k = scalar (4 qwords)*/ } icp_qat_fw_point_multiplication_c25519_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC curve25519 Generator Point Multiplication * [k]G(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #GENERATOR_MULTIPLICATION_C25519. */ typedef struct icp_qat_fw_generator_multiplication_c25519_input_s { uint64_t k; /**< k = scalar (4 qwords)*/ } icp_qat_fw_generator_multiplication_c25519_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC edwards25519 Variable Point Multiplication * [k]P, as specified in RFC8032, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #POINT_MULTIPLICATION_ED25519. */ typedef struct icp_qat_fw_point_multiplication_ed25519_input_s { uint64_t xp; /**< xP = Twisted Edwards affine coordinate X of point P (4 qwords)*/ uint64_t yp; /**< yP = Twisted Edwards affine coordinate Y of point P (4 qwords)*/ uint64_t k; /**< k = scalar (4 qwords)*/ } icp_qat_fw_point_multiplication_ed25519_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC edwards25519 Generator Point Multiplication * [k]G, as specified in RFC8032, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #GENERATOR_MULTIPLICATION_ED25519. */ typedef struct icp_qat_fw_generator_multiplication_ed25519_input_s { uint64_t k; /**< k = scalar (4 qwords)*/ } icp_qat_fw_generator_multiplication_ed25519_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC curve448 Variable Point Multiplication * [k]P(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_request_s::functionalityId is #POINT_MULTIPLICATION_C448. */ typedef struct icp_qat_fw_point_multiplication_c448_input_s { uint64_t xp; /**< xP = Montgomery affine coordinate X of point P (8 qwords)*/ uint64_t k; /**< k = scalar (8 qwords)*/ } icp_qat_fw_point_multiplication_c448_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC curve448 Generator Point Multiplication * [k]G(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #GENERATOR_MULTIPLICATION_C448. */ typedef struct icp_qat_fw_generator_multiplication_c448_input_s { uint64_t k; /**< k = scalar (8 qwords)*/ } icp_qat_fw_generator_multiplication_c448_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC edwards448 Variable Point Multiplication * [k]P, as specified in RFC8032, to be used when * icp_qat_fw_pke_request_s::functionalityId is #POINT_MULTIPLICATION_ED448. */ typedef struct icp_qat_fw_point_multiplication_ed448_input_s { uint64_t xp; /**< xP = Edwards affine coordinate X of point P (8 qwords)*/ uint64_t yp; /**< yP = Edwards affine coordinate Y of point P (8 qwords)*/ uint64_t k; /**< k = scalar (8 qwords)*/ } icp_qat_fw_point_multiplication_ed448_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * Input parameter list for ECC edwards448 Generator Point Multiplication * [k]P, as specified in RFC8032, to be used when * icp_qat_fw_pke_request_s::functionalityId is * #GENERATOR_MULTIPLICATION_ED448. */ typedef struct icp_qat_fw_generator_multiplication_ed448_input_s { uint64_t k; /**< k = scalar (8 qwords)*/ } icp_qat_fw_generator_multiplication_ed448_input_t; /** * @ingroup icp_qat_fw_mmp * @brief * MMP input parameters */ typedef union icp_qat_fw_mmp_input_param_u { /** Generic parameter structure : All members of this wrapper structure * are pointers to large integers. */ uint64_t flat_array[ICP_QAT_FW_PKE_INPUT_COUNT_MAX]; /** ECC SM2 point multiply [k]G */ icp_qat_fw_mmp_ecsm2_generator_multiplication_input_t mmp_ecsm2_generator_multiplication; /** ECC SM2 point multiply [k]P */ icp_qat_fw_mmp_ecsm2_point_multiplication_input_t mmp_ecsm2_point_multiplication; /** ECC SM2 point verify */ icp_qat_fw_mmp_ecsm2_point_verify_input_t mmp_ecsm2_point_verify; /** ECC SM2 Sign RS */ icp_qat_fw_mmp_ecsm2_sign_rs_input_t mmp_ecsm2_sign_rs; /** ECC SM2 Signature Verify */ icp_qat_fw_mmp_ecsm2_verify_input_t mmp_ecsm2_verify; /** ECC SM2 encryption */ icp_qat_fw_mmp_ecsm2_encryption_input_t mmp_ecsm2_encryption; /** ECC SM2 decryption */ icp_qat_fw_mmp_ecsm2_decryption_input_t mmp_ecsm2_decryption; /** ECC SM2 key exchange phase1 */ icp_qat_fw_mmp_ecsm2_keyex_p1_input_t mmp_ecsm2_keyex_p1; /** ECC SM2 key exchange phase2 */ icp_qat_fw_mmp_ecsm2_keyex_p2_input_t mmp_ecsm2_keyex_p2; /** Initialisation sequence */ icp_qat_fw_mmp_init_input_t mmp_init; /** ECC P384 Variable Point Multiplication [k]P */ icp_qat_fw_mmp_ec_point_multiplication_p384_input_t mmp_ec_point_multiplication_p384; /** ECC P384 Generator Point Multiplication [k]G */ icp_qat_fw_mmp_ec_generator_multiplication_p384_input_t mmp_ec_generator_multiplication_p384; /** ECC P384 ECDSA Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_p384_input_t mmp_ecdsa_sign_rs_p384; /** ECC P256 Variable Point Multiplication [k]P */ icp_qat_fw_mmp_ec_point_multiplication_p256_input_t mmp_ec_point_multiplication_p256; /** ECC P256 Generator Point Multiplication [k]G */ icp_qat_fw_mmp_ec_generator_multiplication_p256_input_t mmp_ec_generator_multiplication_p256; /** ECC P256 ECDSA Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_p256_input_t mmp_ecdsa_sign_rs_p256; /** Diffie-Hellman Modular exponentiation base 2 for 768-bit numbers */ icp_qat_fw_mmp_dh_g2_768_input_t mmp_dh_g2_768; /** Diffie-Hellman Modular exponentiation for 768-bit numbers */ icp_qat_fw_mmp_dh_768_input_t mmp_dh_768; /** Diffie-Hellman Modular exponentiation base 2 for 1024-bit numbers */ icp_qat_fw_mmp_dh_g2_1024_input_t mmp_dh_g2_1024; /** Diffie-Hellman Modular exponentiation for 1024-bit numbers */ icp_qat_fw_mmp_dh_1024_input_t mmp_dh_1024; /** Diffie-Hellman Modular exponentiation base 2 for 1536-bit numbers */ icp_qat_fw_mmp_dh_g2_1536_input_t mmp_dh_g2_1536; /** Diffie-Hellman Modular exponentiation for 1536-bit numbers */ icp_qat_fw_mmp_dh_1536_input_t mmp_dh_1536; /** Diffie-Hellman Modular exponentiation base 2 for 2048-bit numbers */ icp_qat_fw_mmp_dh_g2_2048_input_t mmp_dh_g2_2048; /** Diffie-Hellman Modular exponentiation for 2048-bit numbers */ icp_qat_fw_mmp_dh_2048_input_t mmp_dh_2048; /** Diffie-Hellman Modular exponentiation base 2 for 3072-bit numbers */ icp_qat_fw_mmp_dh_g2_3072_input_t mmp_dh_g2_3072; /** Diffie-Hellman Modular exponentiation for 3072-bit numbers */ icp_qat_fw_mmp_dh_3072_input_t mmp_dh_3072; /** Diffie-Hellman Modular exponentiation base 2 for 4096-bit numbers */ icp_qat_fw_mmp_dh_g2_4096_input_t mmp_dh_g2_4096; /** Diffie-Hellman Modular exponentiation for 4096-bit numbers */ icp_qat_fw_mmp_dh_4096_input_t mmp_dh_4096; /** Diffie-Hellman Modular exponentiation base 2 for 8192-bit numbers */ icp_qat_fw_mmp_dh_g2_8192_input_t mmp_dh_g2_8192; /** Diffie-Hellman Modular exponentiation for 8192-bit numbers */ icp_qat_fw_mmp_dh_8192_input_t mmp_dh_8192; /** RSA 512 key generation first form */ icp_qat_fw_mmp_rsa_kp1_512_input_t mmp_rsa_kp1_512; /** RSA 512 key generation second form */ icp_qat_fw_mmp_rsa_kp2_512_input_t mmp_rsa_kp2_512; /** RSA 512 Encryption */ icp_qat_fw_mmp_rsa_ep_512_input_t mmp_rsa_ep_512; /** RSA 512 Decryption */ icp_qat_fw_mmp_rsa_dp1_512_input_t mmp_rsa_dp1_512; /** RSA 1024 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_512_input_t mmp_rsa_dp2_512; /** RSA 1024 key generation first form */ icp_qat_fw_mmp_rsa_kp1_1024_input_t mmp_rsa_kp1_1024; /** RSA 1024 key generation second form */ icp_qat_fw_mmp_rsa_kp2_1024_input_t mmp_rsa_kp2_1024; /** RSA 1024 Encryption */ icp_qat_fw_mmp_rsa_ep_1024_input_t mmp_rsa_ep_1024; /** RSA 1024 Decryption */ icp_qat_fw_mmp_rsa_dp1_1024_input_t mmp_rsa_dp1_1024; /** RSA 1024 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_1024_input_t mmp_rsa_dp2_1024; /** RSA 1536 key generation first form */ icp_qat_fw_mmp_rsa_kp1_1536_input_t mmp_rsa_kp1_1536; /** RSA 1536 key generation second form */ icp_qat_fw_mmp_rsa_kp2_1536_input_t mmp_rsa_kp2_1536; /** RSA 1536 Encryption */ icp_qat_fw_mmp_rsa_ep_1536_input_t mmp_rsa_ep_1536; /** RSA 1536 Decryption */ icp_qat_fw_mmp_rsa_dp1_1536_input_t mmp_rsa_dp1_1536; /** RSA 1536 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_1536_input_t mmp_rsa_dp2_1536; /** RSA 2048 key generation first form */ icp_qat_fw_mmp_rsa_kp1_2048_input_t mmp_rsa_kp1_2048; /** RSA 2048 key generation second form */ icp_qat_fw_mmp_rsa_kp2_2048_input_t mmp_rsa_kp2_2048; /** RSA 2048 Encryption */ icp_qat_fw_mmp_rsa_ep_2048_input_t mmp_rsa_ep_2048; /** RSA 2048 Decryption */ icp_qat_fw_mmp_rsa_dp1_2048_input_t mmp_rsa_dp1_2048; /** RSA 2048 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_2048_input_t mmp_rsa_dp2_2048; /** RSA 3072 key generation first form */ icp_qat_fw_mmp_rsa_kp1_3072_input_t mmp_rsa_kp1_3072; /** RSA 3072 key generation second form */ icp_qat_fw_mmp_rsa_kp2_3072_input_t mmp_rsa_kp2_3072; /** RSA 3072 Encryption */ icp_qat_fw_mmp_rsa_ep_3072_input_t mmp_rsa_ep_3072; /** RSA 3072 Decryption */ icp_qat_fw_mmp_rsa_dp1_3072_input_t mmp_rsa_dp1_3072; /** RSA 3072 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_3072_input_t mmp_rsa_dp2_3072; /** RSA 4096 key generation first form */ icp_qat_fw_mmp_rsa_kp1_4096_input_t mmp_rsa_kp1_4096; /** RSA 4096 key generation second form */ icp_qat_fw_mmp_rsa_kp2_4096_input_t mmp_rsa_kp2_4096; /** RSA 4096 Encryption */ icp_qat_fw_mmp_rsa_ep_4096_input_t mmp_rsa_ep_4096; /** RSA 4096 Decryption */ icp_qat_fw_mmp_rsa_dp1_4096_input_t mmp_rsa_dp1_4096; /** RSA 4096 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_4096_input_t mmp_rsa_dp2_4096; /** RSA 8192 Encryption */ icp_qat_fw_mmp_rsa_ep_8192_input_t mmp_rsa_ep_8192; /** RSA 8192 Decryption */ icp_qat_fw_mmp_rsa_dp1_8192_input_t mmp_rsa_dp1_8192; /** RSA 8192 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_8192_input_t mmp_rsa_dp2_8192; /** GCD primality test for 192-bit numbers */ icp_qat_fw_mmp_gcd_pt_192_input_t mmp_gcd_pt_192; /** GCD primality test for 256-bit numbers */ icp_qat_fw_mmp_gcd_pt_256_input_t mmp_gcd_pt_256; /** GCD primality test for 384-bit numbers */ icp_qat_fw_mmp_gcd_pt_384_input_t mmp_gcd_pt_384; /** GCD primality test for 512-bit numbers */ icp_qat_fw_mmp_gcd_pt_512_input_t mmp_gcd_pt_512; /** GCD primality test for 768-bit numbers */ icp_qat_fw_mmp_gcd_pt_768_input_t mmp_gcd_pt_768; /** GCD primality test for 1024-bit numbers */ icp_qat_fw_mmp_gcd_pt_1024_input_t mmp_gcd_pt_1024; /** GCD primality test for 1536-bit numbers */ icp_qat_fw_mmp_gcd_pt_1536_input_t mmp_gcd_pt_1536; /** GCD primality test for 2048-bit numbers */ icp_qat_fw_mmp_gcd_pt_2048_input_t mmp_gcd_pt_2048; /** GCD primality test for 3072-bit numbers */ icp_qat_fw_mmp_gcd_pt_3072_input_t mmp_gcd_pt_3072; /** GCD primality test for 4096-bit numbers */ icp_qat_fw_mmp_gcd_pt_4096_input_t mmp_gcd_pt_4096; /** Fermat primality test for 160-bit numbers */ icp_qat_fw_mmp_fermat_pt_160_input_t mmp_fermat_pt_160; /** Fermat primality test for 512-bit numbers */ icp_qat_fw_mmp_fermat_pt_512_input_t mmp_fermat_pt_512; /** Fermat primality test for <e; 512-bit numbers */ icp_qat_fw_mmp_fermat_pt_l512_input_t mmp_fermat_pt_l512; /** Fermat primality test for 768-bit numbers */ icp_qat_fw_mmp_fermat_pt_768_input_t mmp_fermat_pt_768; /** Fermat primality test for 1024-bit numbers */ icp_qat_fw_mmp_fermat_pt_1024_input_t mmp_fermat_pt_1024; /** Fermat primality test for 1536-bit numbers */ icp_qat_fw_mmp_fermat_pt_1536_input_t mmp_fermat_pt_1536; /** Fermat primality test for 2048-bit numbers */ icp_qat_fw_mmp_fermat_pt_2048_input_t mmp_fermat_pt_2048; /** Fermat primality test for 3072-bit numbers */ icp_qat_fw_mmp_fermat_pt_3072_input_t mmp_fermat_pt_3072; /** Fermat primality test for 4096-bit numbers */ icp_qat_fw_mmp_fermat_pt_4096_input_t mmp_fermat_pt_4096; /** Miller-Rabin primality test for 160-bit numbers */ icp_qat_fw_mmp_mr_pt_160_input_t mmp_mr_pt_160; /** Miller-Rabin primality test for 512-bit numbers */ icp_qat_fw_mmp_mr_pt_512_input_t mmp_mr_pt_512; /** Miller-Rabin primality test for 768-bit numbers */ icp_qat_fw_mmp_mr_pt_768_input_t mmp_mr_pt_768; /** Miller-Rabin primality test for 1024-bit numbers */ icp_qat_fw_mmp_mr_pt_1024_input_t mmp_mr_pt_1024; /** Miller-Rabin primality test for 1536-bit numbers */ icp_qat_fw_mmp_mr_pt_1536_input_t mmp_mr_pt_1536; /** Miller-Rabin primality test for 2048-bit numbers */ icp_qat_fw_mmp_mr_pt_2048_input_t mmp_mr_pt_2048; /** Miller-Rabin primality test for 3072-bit numbers */ icp_qat_fw_mmp_mr_pt_3072_input_t mmp_mr_pt_3072; /** Miller-Rabin primality test for 4096-bit numbers */ icp_qat_fw_mmp_mr_pt_4096_input_t mmp_mr_pt_4096; /** Miller-Rabin primality test for 512-bit numbers */ icp_qat_fw_mmp_mr_pt_l512_input_t mmp_mr_pt_l512; /** Lucas primality test for 160-bit numbers */ icp_qat_fw_mmp_lucas_pt_160_input_t mmp_lucas_pt_160; /** Lucas primality test for 512-bit numbers */ icp_qat_fw_mmp_lucas_pt_512_input_t mmp_lucas_pt_512; /** Lucas primality test for 768-bit numbers */ icp_qat_fw_mmp_lucas_pt_768_input_t mmp_lucas_pt_768; /** Lucas primality test for 1024-bit numbers */ icp_qat_fw_mmp_lucas_pt_1024_input_t mmp_lucas_pt_1024; /** Lucas primality test for 1536-bit numbers */ icp_qat_fw_mmp_lucas_pt_1536_input_t mmp_lucas_pt_1536; /** Lucas primality test for 2048-bit numbers */ icp_qat_fw_mmp_lucas_pt_2048_input_t mmp_lucas_pt_2048; /** Lucas primality test for 3072-bit numbers */ icp_qat_fw_mmp_lucas_pt_3072_input_t mmp_lucas_pt_3072; /** Lucas primality test for 4096-bit numbers */ icp_qat_fw_mmp_lucas_pt_4096_input_t mmp_lucas_pt_4096; /** Lucas primality test for L512-bit numbers */ icp_qat_fw_mmp_lucas_pt_l512_input_t mmp_lucas_pt_l512; /** Modular exponentiation for numbers less than 512-bits */ icp_qat_fw_maths_modexp_l512_input_t maths_modexp_l512; /** Modular exponentiation for numbers less than 1024-bit */ icp_qat_fw_maths_modexp_l1024_input_t maths_modexp_l1024; /** Modular exponentiation for numbers less than 1536-bits */ icp_qat_fw_maths_modexp_l1536_input_t maths_modexp_l1536; /** Modular exponentiation for numbers less than 2048-bit */ icp_qat_fw_maths_modexp_l2048_input_t maths_modexp_l2048; /** Modular exponentiation for numbers less than 2560-bits */ icp_qat_fw_maths_modexp_l2560_input_t maths_modexp_l2560; /** Modular exponentiation for numbers less than 3072-bits */ icp_qat_fw_maths_modexp_l3072_input_t maths_modexp_l3072; /** Modular exponentiation for numbers less than 3584-bits */ icp_qat_fw_maths_modexp_l3584_input_t maths_modexp_l3584; /** Modular exponentiation for numbers less than 4096-bit */ icp_qat_fw_maths_modexp_l4096_input_t maths_modexp_l4096; /** Modular exponentiation for numbers up to 8192 bits */ icp_qat_fw_maths_modexp_l8192_input_t maths_modexp_l8192; /** Modular multiplicative inverse for numbers less than 128 bits */ icp_qat_fw_maths_modinv_odd_l128_input_t maths_modinv_odd_l128; /** Modular multiplicative inverse for numbers less than 192 bits */ icp_qat_fw_maths_modinv_odd_l192_input_t maths_modinv_odd_l192; /** Modular multiplicative inverse for numbers less than 256 bits */ icp_qat_fw_maths_modinv_odd_l256_input_t maths_modinv_odd_l256; /** Modular multiplicative inverse for numbers less than 384 bits */ icp_qat_fw_maths_modinv_odd_l384_input_t maths_modinv_odd_l384; /** Modular multiplicative inverse for numbers less than 512 bits */ icp_qat_fw_maths_modinv_odd_l512_input_t maths_modinv_odd_l512; /** Modular multiplicative inverse for numbers less than 768 bits */ icp_qat_fw_maths_modinv_odd_l768_input_t maths_modinv_odd_l768; /** Modular multiplicative inverse for numbers less than 1024 bits */ icp_qat_fw_maths_modinv_odd_l1024_input_t maths_modinv_odd_l1024; /** Modular multiplicative inverse for numbers less than 1536 bits */ icp_qat_fw_maths_modinv_odd_l1536_input_t maths_modinv_odd_l1536; /** Modular multiplicative inverse for numbers less than 2048 bits */ icp_qat_fw_maths_modinv_odd_l2048_input_t maths_modinv_odd_l2048; /** Modular multiplicative inverse for numbers less than 3072 bits */ icp_qat_fw_maths_modinv_odd_l3072_input_t maths_modinv_odd_l3072; /** Modular multiplicative inverse for numbers less than 4096 bits */ icp_qat_fw_maths_modinv_odd_l4096_input_t maths_modinv_odd_l4096; /** Modular multiplicative inverse for numbers up to 8192 bits */ icp_qat_fw_maths_modinv_odd_l8192_input_t maths_modinv_odd_l8192; /** Modular multiplicative inverse for numbers less than 128 bits */ icp_qat_fw_maths_modinv_even_l128_input_t maths_modinv_even_l128; /** Modular multiplicative inverse for numbers less than 192 bits */ icp_qat_fw_maths_modinv_even_l192_input_t maths_modinv_even_l192; /** Modular multiplicative inverse for numbers less than 256 bits */ icp_qat_fw_maths_modinv_even_l256_input_t maths_modinv_even_l256; /** Modular multiplicative inverse for numbers less than 384 bits */ icp_qat_fw_maths_modinv_even_l384_input_t maths_modinv_even_l384; /** Modular multiplicative inverse for numbers less than 512 bits */ icp_qat_fw_maths_modinv_even_l512_input_t maths_modinv_even_l512; /** Modular multiplicative inverse for numbers less than 768 bits */ icp_qat_fw_maths_modinv_even_l768_input_t maths_modinv_even_l768; /** Modular multiplicative inverse for numbers less than 1024 bits */ icp_qat_fw_maths_modinv_even_l1024_input_t maths_modinv_even_l1024; /** Modular multiplicative inverse for numbers less than 1536 bits */ icp_qat_fw_maths_modinv_even_l1536_input_t maths_modinv_even_l1536; /** Modular multiplicative inverse for numbers less than 2048 bits */ icp_qat_fw_maths_modinv_even_l2048_input_t maths_modinv_even_l2048; /** Modular multiplicative inverse for numbers less than 3072 bits */ icp_qat_fw_maths_modinv_even_l3072_input_t maths_modinv_even_l3072; /** Modular multiplicative inverse for numbers less than 4096 bits */ icp_qat_fw_maths_modinv_even_l4096_input_t maths_modinv_even_l4096; /** Modular multiplicative inverse for numbers up to 8192 bits */ icp_qat_fw_maths_modinv_even_l8192_input_t maths_modinv_even_l8192; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_1024_160_input_t mmp_dsa_gen_p_1024_160; /** DSA key generation G */ icp_qat_fw_mmp_dsa_gen_g_1024_input_t mmp_dsa_gen_g_1024; /** DSA key generation Y */ icp_qat_fw_mmp_dsa_gen_y_1024_input_t mmp_dsa_gen_y_1024; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_1024_160_input_t mmp_dsa_sign_r_1024_160; /** DSA Sign S */ icp_qat_fw_mmp_dsa_sign_s_160_input_t mmp_dsa_sign_s_160; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_t mmp_dsa_sign_r_s_1024_160; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_1024_160_input_t mmp_dsa_verify_1024_160; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_2048_224_input_t mmp_dsa_gen_p_2048_224; /** DSA key generation Y */ icp_qat_fw_mmp_dsa_gen_y_2048_input_t mmp_dsa_gen_y_2048; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_2048_224_input_t mmp_dsa_sign_r_2048_224; /** DSA Sign S */ icp_qat_fw_mmp_dsa_sign_s_224_input_t mmp_dsa_sign_s_224; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_t mmp_dsa_sign_r_s_2048_224; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_2048_224_input_t mmp_dsa_verify_2048_224; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_2048_256_input_t mmp_dsa_gen_p_2048_256; /** DSA key generation G */ icp_qat_fw_mmp_dsa_gen_g_2048_input_t mmp_dsa_gen_g_2048; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_2048_256_input_t mmp_dsa_sign_r_2048_256; /** DSA Sign S */ icp_qat_fw_mmp_dsa_sign_s_256_input_t mmp_dsa_sign_s_256; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_t mmp_dsa_sign_r_s_2048_256; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_2048_256_input_t mmp_dsa_verify_2048_256; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_3072_256_input_t mmp_dsa_gen_p_3072_256; /** DSA key generation G */ icp_qat_fw_mmp_dsa_gen_g_3072_input_t mmp_dsa_gen_g_3072; /** DSA key generation Y */ icp_qat_fw_mmp_dsa_gen_y_3072_input_t mmp_dsa_gen_y_3072; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_3072_256_input_t mmp_dsa_sign_r_3072_256; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_t mmp_dsa_sign_r_s_3072_256; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_3072_256_input_t mmp_dsa_verify_3072_256; /** ECDSA Sign RS for curves B/K-163 and B/K-233 */ icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_t mmp_ecdsa_sign_rs_gf2_l256; /** ECDSA Sign R for curves B/K-163 and B/K-233 */ icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_t mmp_ecdsa_sign_r_gf2_l256; /** ECDSA Sign S for curves with n < 2^256 */ icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_t mmp_ecdsa_sign_s_gf2_l256; /** ECDSA Verify for curves B/K-163 and B/K-233 */ icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_t mmp_ecdsa_verify_gf2_l256; /** ECDSA Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_t mmp_ecdsa_sign_rs_gf2_l512; /** ECDSA GF2 Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_t mmp_ecdsa_sign_r_gf2_l512; /** ECDSA GF2 Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_t mmp_ecdsa_sign_s_gf2_l512; /** ECDSA GF2 Verify */ icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_t mmp_ecdsa_verify_gf2_l512; /** ECDSA GF2 Sign RS for curves B-571/K-571 */ icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_t mmp_ecdsa_sign_rs_gf2_571; /** ECDSA GF2 Sign S for curves with deg(q) < 576 */ icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_t mmp_ecdsa_sign_s_gf2_571; /** ECDSA GF2 Sign R for degree 571 */ icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_t mmp_ecdsa_sign_r_gf2_571; /** ECDSA GF2 Verify for degree 571 */ icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_t mmp_ecdsa_verify_gf2_571; /** MATHS GF2 Point Multiplication */ icp_qat_fw_maths_point_multiplication_gf2_l256_input_t maths_point_multiplication_gf2_l256; /** MATHS GF2 Point Verification */ icp_qat_fw_maths_point_verify_gf2_l256_input_t maths_point_verify_gf2_l256; /** MATHS GF2 Point Multiplication */ icp_qat_fw_maths_point_multiplication_gf2_l512_input_t maths_point_multiplication_gf2_l512; /** MATHS GF2 Point Verification */ icp_qat_fw_maths_point_verify_gf2_l512_input_t maths_point_verify_gf2_l512; /** ECC GF2 Point Multiplication for curves B-571/K-571 */ icp_qat_fw_maths_point_multiplication_gf2_571_input_t maths_point_multiplication_gf2_571; /** ECC GF2 Point Verification for degree 571 */ icp_qat_fw_maths_point_verify_gf2_571_input_t maths_point_verify_gf2_571; /** ECDSA GFP Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_t mmp_ecdsa_sign_r_gfp_l256; /** ECDSA GFP Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_t mmp_ecdsa_sign_s_gfp_l256; /** ECDSA GFP Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_t mmp_ecdsa_sign_rs_gfp_l256; /** ECDSA GFP Verify */ icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_t mmp_ecdsa_verify_gfp_l256; /** ECDSA GFP Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_t mmp_ecdsa_sign_r_gfp_l512; /** ECDSA GFP Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_t mmp_ecdsa_sign_s_gfp_l512; /** ECDSA GFP Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_t mmp_ecdsa_sign_rs_gfp_l512; /** ECDSA GFP Verify */ icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_t mmp_ecdsa_verify_gfp_l512; /** ECDSA GFP Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_t mmp_ecdsa_sign_r_gfp_521; /** ECDSA GFP Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_t mmp_ecdsa_sign_s_gfp_521; /** ECDSA GFP Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_t mmp_ecdsa_sign_rs_gfp_521; /** ECDSA GFP Verify */ icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_t mmp_ecdsa_verify_gfp_521; /** ECC GFP Point Multiplication */ icp_qat_fw_maths_point_multiplication_gfp_l256_input_t maths_point_multiplication_gfp_l256; /** ECC GFP Partial Point Verification */ icp_qat_fw_maths_point_verify_gfp_l256_input_t maths_point_verify_gfp_l256; /** ECC GFP Point Multiplication */ icp_qat_fw_maths_point_multiplication_gfp_l512_input_t maths_point_multiplication_gfp_l512; /** ECC GFP Partial Point */ icp_qat_fw_maths_point_verify_gfp_l512_input_t maths_point_verify_gfp_l512; /** ECC GFP Point Multiplication */ icp_qat_fw_maths_point_multiplication_gfp_521_input_t maths_point_multiplication_gfp_521; /** ECC GFP Partial Point Verification */ icp_qat_fw_maths_point_verify_gfp_521_input_t maths_point_verify_gfp_521; /** ECC curve25519 Variable Point Multiplication [k]P(x), as specified in * RFC7748 */ icp_qat_fw_point_multiplication_c25519_input_t point_multiplication_c25519; /** ECC curve25519 Generator Point Multiplication [k]G(x), as specified in * RFC7748 */ icp_qat_fw_generator_multiplication_c25519_input_t generator_multiplication_c25519; /** ECC edwards25519 Variable Point Multiplication [k]P, as specified in * RFC8032 */ icp_qat_fw_point_multiplication_ed25519_input_t point_multiplication_ed25519; /** ECC edwards25519 Generator Point Multiplication [k]G, as specified in * RFC8032 */ icp_qat_fw_generator_multiplication_ed25519_input_t generator_multiplication_ed25519; /** ECC curve448 Variable Point Multiplication [k]P(x), as specified in * RFC7748 */ icp_qat_fw_point_multiplication_c448_input_t point_multiplication_c448; /** ECC curve448 Generator Point Multiplication [k]G(x), as specified in * RFC7748 */ icp_qat_fw_generator_multiplication_c448_input_t generator_multiplication_c448; /** ECC edwards448 Variable Point Multiplication [k]P, as specified in * RFC8032 */ icp_qat_fw_point_multiplication_ed448_input_t point_multiplication_ed448; /** ECC edwards448 Generator Point Multiplication [k]P, as specified in * RFC8032 */ icp_qat_fw_generator_multiplication_ed448_input_t generator_multiplication_ed448; } icp_qat_fw_mmp_input_param_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC P384 Variable Point Multiplication [k]P, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_EC_POINT_MULTIPLICATION_P384. */ typedef struct icp_qat_fw_mmp_ec_point_multiplication_p384_output_s { uint64_t xr; /**< xR = affine coordinate X of point [k]P (6 qwords)*/ uint64_t yr; /**< yR = affine coordinate Y of point [k]P (6 qwords)*/ } icp_qat_fw_mmp_ec_point_multiplication_p384_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC P384 Generator Point Multiplication [k]G, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_EC_GENERATOR_MULTIPLICATION_P384. */ typedef struct icp_qat_fw_mmp_ec_generator_multiplication_p384_output_s { uint64_t xr; /**< xR = affine coordinate X of point [k]G (6 qwords)*/ uint64_t yr; /**< yR = affine coordinate Y of point [k]G (6 qwords)*/ } icp_qat_fw_mmp_ec_generator_multiplication_p384_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC P384 ECDSA Sign RS, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_RS_P384. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_p384_output_s { uint64_t r; /**< ECDSA signature r (6 qwords)*/ uint64_t s; /**< ECDSA signature s (6 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_p384_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC P256 Variable Point Multiplication [k]P, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_EC_POINT_MULTIPLICATION_P256. */ typedef struct icp_qat_fw_mmp_ec_point_multiplication_p256_output_s { uint64_t xr; /**< xR = affine coordinate X of point [k]P (4 qwords)*/ uint64_t yr; /**< yR = affine coordinate Y of point [k]P (4 qwords)*/ } icp_qat_fw_mmp_ec_point_multiplication_p256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC P256 Generator Point Multiplication [k]G, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_EC_GENERATOR_MULTIPLICATION_P256. */ typedef struct icp_qat_fw_mmp_ec_generator_multiplication_p256_output_s { uint64_t xr; /**< xR = affine coordinate X of point [k]G (4 qwords)*/ uint64_t yr; /**< yR = affine coordinate Y of point [k]G (4 qwords)*/ } icp_qat_fw_mmp_ec_generator_multiplication_p256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC P256 ECDSA Sign RS, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_RS_P256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_p256_output_s { uint64_t r; /**< ECDSA signature r (4 qwords)*/ uint64_t s; /**< ECDSA signature s (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_p256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 point multiply [k]G , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_GENERATOR_MULTIPLICATION. */ typedef struct icp_qat_fw_mmp_ecsm2_generator_multiplication_output_s { uint64_t xd; /**< xD = affine coordinate X of point [k]G (4 qwords)*/ uint64_t yd; /**< yD = affine coordinate Y of point [k]G (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_generator_multiplication_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 point multiply [k]P , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_POINT_MULTIPLICATION. */ typedef struct icp_qat_fw_mmp_ecsm2_point_multiplication_output_s { uint64_t xd; /**< xD = affine coordinate X of point [k](x,y) (4 qwords)*/ uint64_t yd; /**< yD = affine coordinate Y of point [k](x,y) (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_point_multiplication_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 point verify , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_POINT_VERIFY. */ typedef struct icp_qat_fw_mmp_ecsm2_point_verify_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecsm2_point_verify_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 Sign RS , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_SIGN_RS. */ typedef struct icp_qat_fw_mmp_ecsm2_sign_rs_output_s { uint64_t r; /**< ECSM2 signature r (4 qwords)*/ uint64_t s; /**< ECSM2 signature s (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_sign_rs_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 Signature Verify , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_VERIFY. */ typedef struct icp_qat_fw_mmp_ecsm2_verify_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecsm2_verify_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 encryption , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_ENCRYPTION. */ typedef struct icp_qat_fw_mmp_ecsm2_encryption_output_s { uint64_t xc; /**< xC = affine coordinate X of point C1=[k]G (4 qwords)*/ uint64_t yc; /**< yC = affine coordinate Y of point C1=[k]G (4 qwords)*/ uint64_t xpb; /**< xPb = affine coordinate X of point [k](xP,yP) (4 qwords)*/ uint64_t ypb; /**< yPb = affine coordinate Y of point [k](xP,yP) (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_encryption_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 decryption , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_DECRYPTION. */ typedef struct icp_qat_fw_mmp_ecsm2_decryption_output_s { uint64_t xd; /**< xD = affine coordinate X of point [d]C1 (4 qwords)*/ uint64_t yd; /**< yD = affine coordinate Y of point [d]C1 (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_decryption_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 key exchange phase1 , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_KEYEX_P1. */ typedef struct icp_qat_fw_mmp_ecsm2_keyex_p1_output_s { uint64_t xd; /**< xD = affine coordinate X of point [k]G (4 qwords)*/ uint64_t yd; /**< yD = affine coordinate X of point [k]G (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_keyex_p1_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC SM2 key exchange phase2 , * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECSM2_KEYEX_P2. */ typedef struct icp_qat_fw_mmp_ecsm2_keyex_p2_output_s { uint64_t xus; /**< xus = affine coordinate X of point (xU,yU) (4 qwords)*/ uint64_t yus; /**< yus = affine coordinate X of point (xU,yU) (4 qwords)*/ } icp_qat_fw_mmp_ecsm2_keyex_p2_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Initialisation sequence, * to be used when icp_qat_fw_pke_response_s::functionalityId is #PKE_INIT. */ typedef struct icp_qat_fw_mmp_init_output_s { uint64_t zz; /**< 1'd quadword (1 qwords)*/ } icp_qat_fw_mmp_init_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for * 768-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_G2_768. */ typedef struct icp_qat_fw_mmp_dh_g2_768_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (12 qwords)*/ } icp_qat_fw_mmp_dh_g2_768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation for * 768-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_768. */ typedef struct icp_qat_fw_mmp_dh_768_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (12 qwords)*/ } icp_qat_fw_mmp_dh_768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for * 1024-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_G2_1024. */ typedef struct icp_qat_fw_mmp_dh_g2_1024_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (16 qwords)*/ } icp_qat_fw_mmp_dh_g2_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation for * 1024-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_1024. */ typedef struct icp_qat_fw_mmp_dh_1024_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (16 qwords)*/ } icp_qat_fw_mmp_dh_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for * 1536-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_G2_1536. */ typedef struct icp_qat_fw_mmp_dh_g2_1536_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (24 qwords)*/ } icp_qat_fw_mmp_dh_g2_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation for * 1536-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_1536. */ typedef struct icp_qat_fw_mmp_dh_1536_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (24 qwords)*/ } icp_qat_fw_mmp_dh_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for * 2048-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_G2_2048. */ typedef struct icp_qat_fw_mmp_dh_g2_2048_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (32 qwords)*/ } icp_qat_fw_mmp_dh_g2_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation for * 2048-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_2048. */ typedef struct icp_qat_fw_mmp_dh_2048_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (32 qwords)*/ } icp_qat_fw_mmp_dh_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for * 3072-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_G2_3072. */ typedef struct icp_qat_fw_mmp_dh_g2_3072_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (48 qwords)*/ } icp_qat_fw_mmp_dh_g2_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation for * 3072-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_3072. */ typedef struct icp_qat_fw_mmp_dh_3072_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (48 qwords)*/ } icp_qat_fw_mmp_dh_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for * 4096-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_G2_4096. */ typedef struct icp_qat_fw_mmp_dh_g2_4096_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (64 qwords)*/ } icp_qat_fw_mmp_dh_g2_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation for * 4096-bit numbers, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DH_4096. */ typedef struct icp_qat_fw_mmp_dh_4096_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (64 qwords)*/ } icp_qat_fw_mmp_dh_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation base 2 for * 8192-bit numbers, to be used when icp_qat_fw_pke_response_s::functionalityId * is #PKE_DH_G2_8192. */ typedef struct icp_qat_fw_mmp_dh_g2_8192_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (128 qwords)*/ } icp_qat_fw_mmp_dh_g2_8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Diffie-Hellman Modular exponentiation for * 8192-bit numbers, to be used when icp_qat_fw_pke_response_s::functionalityId * is #PKE_DH_8192. */ typedef struct icp_qat_fw_mmp_dh_8192_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (128 qwords)*/ } icp_qat_fw_mmp_dh_8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 512 key generation first form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP1_512. */ typedef struct icp_qat_fw_mmp_rsa_kp1_512_output_s { uint64_t n; /**< RSA key (8 qwords)*/ uint64_t d; /**< RSA private key (first form) (8 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 512 key generation second form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP2_512. */ typedef struct icp_qat_fw_mmp_rsa_kp2_512_output_s { uint64_t n; /**< RSA key (8 qwords)*/ uint64_t d; /**< RSA private key (second form) (8 qwords)*/ uint64_t dp; /**< RSA private key (second form) (4 qwords)*/ uint64_t dq; /**< RSA private key (second form) (4 qwords)*/ uint64_t qinv; /**< RSA private key (second form) (4 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 512 Encryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_EP_512. */ typedef struct icp_qat_fw_mmp_rsa_ep_512_output_s { uint64_t c; /**< cipher text representative, < n (8 qwords)*/ } icp_qat_fw_mmp_rsa_ep_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 512 Decryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP1_512. */ typedef struct icp_qat_fw_mmp_rsa_dp1_512_output_s { uint64_t m; /**< message representative, < n (8 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1024 Decryption with CRT, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP2_512. */ typedef struct icp_qat_fw_mmp_rsa_dp2_512_output_s { uint64_t m; /**< message representative, < (p*q) (8 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1024 key generation first form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP1_1024. */ typedef struct icp_qat_fw_mmp_rsa_kp1_1024_output_s { uint64_t n; /**< RSA key (16 qwords)*/ uint64_t d; /**< RSA private key (first form) (16 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1024 key generation second form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP2_1024. */ typedef struct icp_qat_fw_mmp_rsa_kp2_1024_output_s { uint64_t n; /**< RSA key (16 qwords)*/ uint64_t d; /**< RSA private key (second form) (16 qwords)*/ uint64_t dp; /**< RSA private key (second form) (8 qwords)*/ uint64_t dq; /**< RSA private key (second form) (8 qwords)*/ uint64_t qinv; /**< RSA private key (second form) (8 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1024 Encryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_EP_1024. */ typedef struct icp_qat_fw_mmp_rsa_ep_1024_output_s { uint64_t c; /**< cipher text representative, < n (16 qwords)*/ } icp_qat_fw_mmp_rsa_ep_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1024 Decryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP1_1024. */ typedef struct icp_qat_fw_mmp_rsa_dp1_1024_output_s { uint64_t m; /**< message representative, < n (16 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1024 Decryption with CRT, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP2_1024. */ typedef struct icp_qat_fw_mmp_rsa_dp2_1024_output_s { uint64_t m; /**< message representative, < (p*q) (16 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1536 key generation first form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP1_1536. */ typedef struct icp_qat_fw_mmp_rsa_kp1_1536_output_s { uint64_t n; /**< RSA key (24 qwords)*/ uint64_t d; /**< RSA private key (24 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1536 key generation second form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP2_1536. */ typedef struct icp_qat_fw_mmp_rsa_kp2_1536_output_s { uint64_t n; /**< RSA key (24 qwords)*/ uint64_t d; /**< RSA private key (24 qwords)*/ uint64_t dp; /**< RSA private key (12 qwords)*/ uint64_t dq; /**< RSA private key (12 qwords)*/ uint64_t qinv; /**< RSA private key (12 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1536 Encryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_EP_1536. */ typedef struct icp_qat_fw_mmp_rsa_ep_1536_output_s { uint64_t c; /**< cipher text representative, < n (24 qwords)*/ } icp_qat_fw_mmp_rsa_ep_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1536 Decryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP1_1536. */ typedef struct icp_qat_fw_mmp_rsa_dp1_1536_output_s { uint64_t m; /**< message representative, < n (24 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 1536 Decryption with CRT, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP2_1536. */ typedef struct icp_qat_fw_mmp_rsa_dp2_1536_output_s { uint64_t m; /**< message representative, < (p*q) (24 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 2048 key generation first form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP1_2048. */ typedef struct icp_qat_fw_mmp_rsa_kp1_2048_output_s { uint64_t n; /**< RSA key (32 qwords)*/ uint64_t d; /**< RSA private key (32 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 2048 key generation second form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP2_2048. */ typedef struct icp_qat_fw_mmp_rsa_kp2_2048_output_s { uint64_t n; /**< RSA key (32 qwords)*/ uint64_t d; /**< RSA private key (32 qwords)*/ uint64_t dp; /**< RSA private key (16 qwords)*/ uint64_t dq; /**< RSA private key (16 qwords)*/ uint64_t qinv; /**< RSA private key (16 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 2048 Encryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_EP_2048. */ typedef struct icp_qat_fw_mmp_rsa_ep_2048_output_s { uint64_t c; /**< cipher text representative, < n (32 qwords)*/ } icp_qat_fw_mmp_rsa_ep_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 2048 Decryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP1_2048. */ typedef struct icp_qat_fw_mmp_rsa_dp1_2048_output_s { uint64_t m; /**< message representative, < n (32 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 2048 Decryption with CRT, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP2_2048. */ typedef struct icp_qat_fw_mmp_rsa_dp2_2048_output_s { uint64_t m; /**< message representative, < (p*q) (32 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 3072 key generation first form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP1_3072. */ typedef struct icp_qat_fw_mmp_rsa_kp1_3072_output_s { uint64_t n; /**< RSA key (48 qwords)*/ uint64_t d; /**< RSA private key (48 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 3072 key generation second form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP2_3072. */ typedef struct icp_qat_fw_mmp_rsa_kp2_3072_output_s { uint64_t n; /**< RSA key (48 qwords)*/ uint64_t d; /**< RSA private key (48 qwords)*/ uint64_t dp; /**< RSA private key (24 qwords)*/ uint64_t dq; /**< RSA private key (24 qwords)*/ uint64_t qinv; /**< RSA private key (24 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 3072 Encryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_EP_3072. */ typedef struct icp_qat_fw_mmp_rsa_ep_3072_output_s { uint64_t c; /**< cipher text representative, < n (48 qwords)*/ } icp_qat_fw_mmp_rsa_ep_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 3072 Decryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP1_3072. */ typedef struct icp_qat_fw_mmp_rsa_dp1_3072_output_s { uint64_t m; /**< message representative, < n (48 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 3072 Decryption with CRT, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP2_3072. */ typedef struct icp_qat_fw_mmp_rsa_dp2_3072_output_s { uint64_t m; /**< message representative, < (p*q) (48 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 4096 key generation first form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP1_4096. */ typedef struct icp_qat_fw_mmp_rsa_kp1_4096_output_s { uint64_t n; /**< RSA key (64 qwords)*/ uint64_t d; /**< RSA private key (64 qwords)*/ } icp_qat_fw_mmp_rsa_kp1_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 4096 key generation second form, to be used * when icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_KP2_4096. */ typedef struct icp_qat_fw_mmp_rsa_kp2_4096_output_s { uint64_t n; /**< RSA key (64 qwords)*/ uint64_t d; /**< RSA private key (64 qwords)*/ uint64_t dp; /**< RSA private key (32 qwords)*/ uint64_t dq; /**< RSA private key (32 qwords)*/ uint64_t qinv; /**< RSA private key (32 qwords)*/ } icp_qat_fw_mmp_rsa_kp2_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 4096 Encryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_EP_4096. */ typedef struct icp_qat_fw_mmp_rsa_ep_4096_output_s { uint64_t c; /**< cipher text representative, < n (64 qwords)*/ } icp_qat_fw_mmp_rsa_ep_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 4096 Decryption, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP1_4096. */ typedef struct icp_qat_fw_mmp_rsa_dp1_4096_output_s { uint64_t m; /**< message representative, < n (64 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 4096 Decryption with CRT, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_RSA_DP2_4096. */ typedef struct icp_qat_fw_mmp_rsa_dp2_4096_output_s { uint64_t m; /**< message representative, < (p*q) (64 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 8192 Encryption, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_RSA_EP_8192. */ typedef struct icp_qat_fw_mmp_rsa_ep_8192_output_s { uint64_t c; /**< cipher text representative, < n (128 qwords)*/ } icp_qat_fw_mmp_rsa_ep_8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 8192 Decryption, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_RSA_DP1_8192. */ typedef struct icp_qat_fw_mmp_rsa_dp1_8192_output_s { uint64_t m; /**< message representative, < n (128 qwords)*/ } icp_qat_fw_mmp_rsa_dp1_8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for RSA 8192 Decryption with CRT, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_RSA_DP2_8192. */ typedef struct icp_qat_fw_mmp_rsa_dp2_8192_output_s { uint64_t m; /**< message representative, < (p*q) (128 qwords)*/ } icp_qat_fw_mmp_rsa_dp2_8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 192-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_192. */ typedef struct icp_qat_fw_mmp_gcd_pt_192_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 256-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_256. */ typedef struct icp_qat_fw_mmp_gcd_pt_256_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 384-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_384. */ typedef struct icp_qat_fw_mmp_gcd_pt_384_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_384_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 512-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_512. */ typedef struct icp_qat_fw_mmp_gcd_pt_512_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 768-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_768. */ typedef struct icp_qat_fw_mmp_gcd_pt_768_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 1024-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_1024. */ typedef struct icp_qat_fw_mmp_gcd_pt_1024_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 1536-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_1536. */ typedef struct icp_qat_fw_mmp_gcd_pt_1536_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 2048-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_2048. */ typedef struct icp_qat_fw_mmp_gcd_pt_2048_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 3072-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_3072. */ typedef struct icp_qat_fw_mmp_gcd_pt_3072_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for GCD primality test for 4096-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_GCD_PT_4096. */ typedef struct icp_qat_fw_mmp_gcd_pt_4096_output_s { /* no output parameters */ } icp_qat_fw_mmp_gcd_pt_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 160-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_160. */ typedef struct icp_qat_fw_mmp_fermat_pt_160_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 512-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_512. */ typedef struct icp_qat_fw_mmp_fermat_pt_512_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for <e; 512-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_L512. */ typedef struct icp_qat_fw_mmp_fermat_pt_l512_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 768-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_768. */ typedef struct icp_qat_fw_mmp_fermat_pt_768_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 1024-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_1024. */ typedef struct icp_qat_fw_mmp_fermat_pt_1024_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 1536-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_1536. */ typedef struct icp_qat_fw_mmp_fermat_pt_1536_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 2048-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_2048. */ typedef struct icp_qat_fw_mmp_fermat_pt_2048_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 3072-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_3072. */ typedef struct icp_qat_fw_mmp_fermat_pt_3072_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Fermat primality test for 4096-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_FERMAT_PT_4096. */ typedef struct icp_qat_fw_mmp_fermat_pt_4096_output_s { /* no output parameters */ } icp_qat_fw_mmp_fermat_pt_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 160-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_160. */ typedef struct icp_qat_fw_mmp_mr_pt_160_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 512-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_512. */ typedef struct icp_qat_fw_mmp_mr_pt_512_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 768-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_768. */ typedef struct icp_qat_fw_mmp_mr_pt_768_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 1024-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_1024. */ typedef struct icp_qat_fw_mmp_mr_pt_1024_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 1536-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_1536. */ typedef struct icp_qat_fw_mmp_mr_pt_1536_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 2048-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_2048. */ typedef struct icp_qat_fw_mmp_mr_pt_2048_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 3072-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_3072. */ typedef struct icp_qat_fw_mmp_mr_pt_3072_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 4096-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_4096. */ typedef struct icp_qat_fw_mmp_mr_pt_4096_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Miller-Rabin primality test for 512-bit * numbers, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_MR_PT_L512. */ typedef struct icp_qat_fw_mmp_mr_pt_l512_output_s { /* no output parameters */ } icp_qat_fw_mmp_mr_pt_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 160-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_LUCAS_PT_160. */ typedef struct icp_qat_fw_mmp_lucas_pt_160_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 512-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_LUCAS_PT_512. */ typedef struct icp_qat_fw_mmp_lucas_pt_512_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 768-bit numbers, to be * used when icp_qat_fw_pke_response_s::functionalityId is #PKE_LUCAS_PT_768. */ typedef struct icp_qat_fw_mmp_lucas_pt_768_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 1024-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_LUCAS_PT_1024. */ typedef struct icp_qat_fw_mmp_lucas_pt_1024_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 1536-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_LUCAS_PT_1536. */ typedef struct icp_qat_fw_mmp_lucas_pt_1536_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 2048-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_LUCAS_PT_2048. */ typedef struct icp_qat_fw_mmp_lucas_pt_2048_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 3072-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_LUCAS_PT_3072. */ typedef struct icp_qat_fw_mmp_lucas_pt_3072_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for 4096-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_LUCAS_PT_4096. */ typedef struct icp_qat_fw_mmp_lucas_pt_4096_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Lucas primality test for L512-bit numbers, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_LUCAS_PT_L512. */ typedef struct icp_qat_fw_mmp_lucas_pt_l512_output_s { /* no output parameters */ } icp_qat_fw_mmp_lucas_pt_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 512-bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L512. */ typedef struct icp_qat_fw_maths_modexp_l512_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (8 qwords)*/ } icp_qat_fw_maths_modexp_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 1024-bit, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L1024. */ typedef struct icp_qat_fw_maths_modexp_l1024_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (16 qwords)*/ } icp_qat_fw_maths_modexp_l1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 1536-bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L1536. */ typedef struct icp_qat_fw_maths_modexp_l1536_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (24 qwords)*/ } icp_qat_fw_maths_modexp_l1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 2048-bit, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L2048. */ typedef struct icp_qat_fw_maths_modexp_l2048_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (32 qwords)*/ } icp_qat_fw_maths_modexp_l2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 2560-bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L2560. */ typedef struct icp_qat_fw_maths_modexp_l2560_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (40 qwords)*/ } icp_qat_fw_maths_modexp_l2560_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 3072-bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L3072. */ typedef struct icp_qat_fw_maths_modexp_l3072_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (48 qwords)*/ } icp_qat_fw_maths_modexp_l3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 3584-bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L3584. */ typedef struct icp_qat_fw_maths_modexp_l3584_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (56 qwords)*/ } icp_qat_fw_maths_modexp_l3584_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers less than * 4096-bit, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L4096. */ typedef struct icp_qat_fw_maths_modexp_l4096_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (64 qwords)*/ } icp_qat_fw_maths_modexp_l4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular exponentiation for numbers up to 8192 * bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODEXP_L8192. */ typedef struct icp_qat_fw_maths_modexp_l8192_output_s { uint64_t r; /**< modular exponentiation result ≥ 0 and < m (128 qwords)*/ } icp_qat_fw_maths_modexp_l8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 128 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_ODD_L128. */ typedef struct icp_qat_fw_maths_modinv_odd_l128_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (2 qwords)*/ } icp_qat_fw_maths_modinv_odd_l128_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 192 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_ODD_L192. */ typedef struct icp_qat_fw_maths_modinv_odd_l192_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (3 qwords)*/ } icp_qat_fw_maths_modinv_odd_l192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 256 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_ODD_L256. */ typedef struct icp_qat_fw_maths_modinv_odd_l256_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (4 qwords)*/ } icp_qat_fw_maths_modinv_odd_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 384 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_ODD_L384. */ typedef struct icp_qat_fw_maths_modinv_odd_l384_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (6 qwords)*/ } icp_qat_fw_maths_modinv_odd_l384_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 512 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_ODD_L512. */ typedef struct icp_qat_fw_maths_modinv_odd_l512_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (8 qwords)*/ } icp_qat_fw_maths_modinv_odd_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 768 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_ODD_L768. */ typedef struct icp_qat_fw_maths_modinv_odd_l768_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (12 qwords)*/ } icp_qat_fw_maths_modinv_odd_l768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 1024 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_ODD_L1024. */ typedef struct icp_qat_fw_maths_modinv_odd_l1024_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (16 qwords)*/ } icp_qat_fw_maths_modinv_odd_l1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 1536 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_ODD_L1536. */ typedef struct icp_qat_fw_maths_modinv_odd_l1536_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (24 qwords)*/ } icp_qat_fw_maths_modinv_odd_l1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 2048 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_ODD_L2048. */ typedef struct icp_qat_fw_maths_modinv_odd_l2048_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (32 qwords)*/ } icp_qat_fw_maths_modinv_odd_l2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 3072 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_ODD_L3072. */ typedef struct icp_qat_fw_maths_modinv_odd_l3072_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (48 qwords)*/ } icp_qat_fw_maths_modinv_odd_l3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 4096 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_ODD_L4096. */ typedef struct icp_qat_fw_maths_modinv_odd_l4096_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (64 qwords)*/ } icp_qat_fw_maths_modinv_odd_l4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers up to * 8192 bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODINV_ODD_L8192. */ typedef struct icp_qat_fw_maths_modinv_odd_l8192_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (128 qwords)*/ } icp_qat_fw_maths_modinv_odd_l8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 128 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_EVEN_L128. */ typedef struct icp_qat_fw_maths_modinv_even_l128_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (2 qwords)*/ } icp_qat_fw_maths_modinv_even_l128_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 192 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_EVEN_L192. */ typedef struct icp_qat_fw_maths_modinv_even_l192_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (3 qwords)*/ } icp_qat_fw_maths_modinv_even_l192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 256 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_EVEN_L256. */ typedef struct icp_qat_fw_maths_modinv_even_l256_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (4 qwords)*/ } icp_qat_fw_maths_modinv_even_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 384 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_EVEN_L384. */ typedef struct icp_qat_fw_maths_modinv_even_l384_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (6 qwords)*/ } icp_qat_fw_maths_modinv_even_l384_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 512 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_EVEN_L512. */ typedef struct icp_qat_fw_maths_modinv_even_l512_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (8 qwords)*/ } icp_qat_fw_maths_modinv_even_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 768 bits, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_MODINV_EVEN_L768. */ typedef struct icp_qat_fw_maths_modinv_even_l768_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (12 qwords)*/ } icp_qat_fw_maths_modinv_even_l768_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 1024 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_EVEN_L1024. */ typedef struct icp_qat_fw_maths_modinv_even_l1024_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (16 qwords)*/ } icp_qat_fw_maths_modinv_even_l1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 1536 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_EVEN_L1536. */ typedef struct icp_qat_fw_maths_modinv_even_l1536_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (24 qwords)*/ } icp_qat_fw_maths_modinv_even_l1536_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 2048 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_EVEN_L2048. */ typedef struct icp_qat_fw_maths_modinv_even_l2048_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (32 qwords)*/ } icp_qat_fw_maths_modinv_even_l2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 3072 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_EVEN_L3072. */ typedef struct icp_qat_fw_maths_modinv_even_l3072_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (48 qwords)*/ } icp_qat_fw_maths_modinv_even_l3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers less * than 4096 bits, to be used when * icp_qat_fw_pke_response_s::functionalityId is #MATHS_MODINV_EVEN_L4096. */ typedef struct icp_qat_fw_maths_modinv_even_l4096_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (64 qwords)*/ } icp_qat_fw_maths_modinv_even_l4096_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for Modular multiplicative inverse for numbers up to * 8192 bits, to be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_MODINV_EVEN_L8192. */ typedef struct icp_qat_fw_maths_modinv_even_l8192_output_s { uint64_t c; /**< modular multiplicative inverse of a, > 0 and < b (128 qwords)*/ } icp_qat_fw_maths_modinv_even_l8192_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_P_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_1024_160_output_s { uint64_t p; /**< candidate for DSA parameter p (16 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_1024_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA key generation G, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_G_1024. */ typedef struct icp_qat_fw_mmp_dsa_gen_g_1024_output_s { uint64_t g; /**< DSA parameter (16 qwords)*/ } icp_qat_fw_mmp_dsa_gen_g_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA key generation Y, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_Y_1024. */ typedef struct icp_qat_fw_mmp_dsa_gen_y_1024_output_s { uint64_t y; /**< DSA parameter (16 qwords)*/ } icp_qat_fw_mmp_dsa_gen_y_1024_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_1024_160_output_s { uint64_t r; /**< DSA 160-bits signature (3 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_1024_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_S_160. */ typedef struct icp_qat_fw_mmp_dsa_sign_s_160_output_s { uint64_t s; /**< s DSA 160-bits signature (3 qwords)*/ } icp_qat_fw_mmp_dsa_sign_s_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_S_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_s { uint64_t r; /**< DSA 160-bits signature (3 qwords)*/ uint64_t s; /**< DSA 160-bits signature (3 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_VERIFY_1024_160. */ typedef struct icp_qat_fw_mmp_dsa_verify_1024_160_output_s { /* no output parameters */ } icp_qat_fw_mmp_dsa_verify_1024_160_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_P_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_224_output_s { uint64_t p; /**< candidate for DSA parameter p (32 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_2048_224_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA key generation Y, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_Y_2048. */ typedef struct icp_qat_fw_mmp_dsa_gen_y_2048_output_s { uint64_t y; /**< DSA parameter (32 qwords)*/ } icp_qat_fw_mmp_dsa_gen_y_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_224_output_s { uint64_t r; /**< DSA 224-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_2048_224_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_S_224. */ typedef struct icp_qat_fw_mmp_dsa_sign_s_224_output_s { uint64_t s; /**< s DSA 224-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_s_224_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_S_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_s { uint64_t r; /**< DSA 224-bits signature (4 qwords)*/ uint64_t s; /**< DSA 224-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_VERIFY_2048_224. */ typedef struct icp_qat_fw_mmp_dsa_verify_2048_224_output_s { /* no output parameters */ } icp_qat_fw_mmp_dsa_verify_2048_224_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_P_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_2048_256_output_s { uint64_t p; /**< candidate for DSA parameter p (32 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_2048_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA key generation G, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_G_2048. */ typedef struct icp_qat_fw_mmp_dsa_gen_g_2048_output_s { uint64_t g; /**< DSA parameter (32 qwords)*/ } icp_qat_fw_mmp_dsa_gen_g_2048_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_2048_256_output_s { uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_2048_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_S_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_s_256_output_s { uint64_t s; /**< s DSA 256-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_s_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_S_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_s { uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_VERIFY_2048_256. */ typedef struct icp_qat_fw_mmp_dsa_verify_2048_256_output_s { /* no output parameters */ } icp_qat_fw_mmp_dsa_verify_2048_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA parameter generation P, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_P_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_gen_p_3072_256_output_s { uint64_t p; /**< candidate for DSA parameter p (48 qwords)*/ } icp_qat_fw_mmp_dsa_gen_p_3072_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA key generation G, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_G_3072. */ typedef struct icp_qat_fw_mmp_dsa_gen_g_3072_output_s { uint64_t g; /**< DSA parameter (48 qwords)*/ } icp_qat_fw_mmp_dsa_gen_g_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA key generation Y, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_GEN_Y_3072. */ typedef struct icp_qat_fw_mmp_dsa_gen_y_3072_output_s { uint64_t y; /**< DSA parameter (48 qwords)*/ } icp_qat_fw_mmp_dsa_gen_y_3072_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_3072_256_output_s { uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_3072_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Sign R S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_SIGN_R_S_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_s { uint64_t r; /**< DSA 256-bits signature (4 qwords)*/ uint64_t s; /**< DSA 256-bits signature (4 qwords)*/ } icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for DSA Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_DSA_VERIFY_3072_256. */ typedef struct icp_qat_fw_mmp_dsa_verify_3072_256_output_s { /* no output parameters */ } icp_qat_fw_mmp_dsa_verify_3072_256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA Sign RS for curves B/K-163 and B/K-233, * to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_RS_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_s { uint64_t r; /**< ECDSA signature r > 0 and < n (4 qwords)*/ uint64_t s; /**< ECDSA signature s > 0 and < n (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA Sign R for curves B/K-163 and B/K-233, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_R_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_s { uint64_t r; /**< ECDSA signature r > 0 and < n (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA Sign S for curves with n < 2^256, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_S_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_s { uint64_t s; /**< ECDSA signature s > 0 and < n (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA Verify for curves B/K-163 and B/K-233, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_VERIFY_GF2_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l256_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecdsa_verify_gf2_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA Sign RS, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_RS_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_s { uint64_t r; /**< (8 qwords)*/ uint64_t s; /**< ECDSA signature r > 0 and < n ECDSA signature s > 0 and < n (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GF2 Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_R_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_s { uint64_t r; /**< ECDSA signature r > 0 and < n (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GF2 Sign S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_S_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_s { uint64_t s; /**< ECDSA signature s > 0 and < n (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GF2 Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_VERIFY_GF2_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_l512_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecdsa_verify_gf2_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GF2 Sign RS for curves B-571/K-571, to be * used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_RS_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_s { uint64_t r; /**< (9 qwords)*/ uint64_t s; /**< ECDSA signature r > 0 and < n ECDSA signature s > 0 and < n (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GF2 Sign S for curves with deg(q) < * 576, to be used when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_S_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_s { uint64_t s; /**< ECDSA signature s > 0 and < n (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GF2 Sign R for degree 571, to be used * when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_SIGN_R_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_s { uint64_t r; /**< ECDSA signature r > 0 and < n (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GF2 Verify for degree 571, to be used * when icp_qat_fw_pke_response_s::functionalityId is * #PKE_ECDSA_VERIFY_GF2_571. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gf2_571_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecdsa_verify_gf2_571_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for MATHS GF2 Point Multiplication, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GF2_L256. */ typedef struct icp_qat_fw_maths_point_multiplication_gf2_l256_output_s { uint64_t xk; /**< x coordinate of resultant point (< degree(q)) (4 qwords)*/ uint64_t yk; /**< y coordinate of resultant point (< degree(q)) (4 qwords)*/ } icp_qat_fw_maths_point_multiplication_gf2_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for MATHS GF2 Point Verification, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_VERIFY_GF2_L256. */ typedef struct icp_qat_fw_maths_point_verify_gf2_l256_output_s { /* no output parameters */ } icp_qat_fw_maths_point_verify_gf2_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for MATHS GF2 Point Multiplication, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GF2_L512. */ typedef struct icp_qat_fw_maths_point_multiplication_gf2_l512_output_s { uint64_t xk; /**< x coordinate of resultant point (< q) (8 qwords)*/ uint64_t yk; /**< y coordinate of resultant point (< q) (8 qwords)*/ } icp_qat_fw_maths_point_multiplication_gf2_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for MATHS GF2 Point Verification, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_VERIFY_GF2_L512. */ typedef struct icp_qat_fw_maths_point_verify_gf2_l512_output_s { /* no output parameters */ } icp_qat_fw_maths_point_verify_gf2_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GF2 Point Multiplication for curves * B-571/K-571, to be used when icp_qat_fw_pke_response_s::functionalityId * is #MATHS_POINT_MULTIPLICATION_GF2_571. */ typedef struct icp_qat_fw_maths_point_multiplication_gf2_571_output_s { uint64_t xk; /**< x coordinate of resultant point (degree < degree(q)) (9 qwords)*/ uint64_t yk; /**< y coordinate of resultant point (degree < degree(q)) (9 qwords)*/ } icp_qat_fw_maths_point_multiplication_gf2_571_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GF2 Point Verification for degree 571, to * be used when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_VERIFY_GF2_571. */ typedef struct icp_qat_fw_maths_point_verify_gf2_571_output_s { /* no output parameters */ } icp_qat_fw_maths_point_verify_gf2_571_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_R_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_s { uint64_t r; /**< ECDSA signature (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_S_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_s { uint64_t s; /**< ECDSA signature s (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign RS, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_RS_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_s { uint64_t r; /**< ECDSA signature r (4 qwords)*/ uint64_t s; /**< ECDSA signature s (4 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_VERIFY_GFP_L256. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l256_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecdsa_verify_gfp_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_R_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_s { uint64_t r; /**< ECDSA signature (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_S_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_s { uint64_t s; /**< ECDSA signature s (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign RS, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_RS_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_s { uint64_t r; /**< ECDSA signature r (8 qwords)*/ uint64_t s; /**< ECDSA signature s (8 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_VERIFY_GFP_L512. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_l512_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecdsa_verify_gfp_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign R, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_R_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_s { uint64_t r; /**< ECDSA signature (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign S, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_S_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_s { uint64_t s; /**< ECDSA signature s (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Sign RS, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_SIGN_RS_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_s { uint64_t r; /**< ECDSA signature r (9 qwords)*/ uint64_t s; /**< ECDSA signature s (9 qwords)*/ } icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECDSA GFP Verify, to be used when * icp_qat_fw_pke_response_s::functionalityId is #PKE_ECDSA_VERIFY_GFP_521. */ typedef struct icp_qat_fw_mmp_ecdsa_verify_gfp_521_output_s { /* no output parameters */ } icp_qat_fw_mmp_ecdsa_verify_gfp_521_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GFP Point Multiplication, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GFP_L256. */ typedef struct icp_qat_fw_maths_point_multiplication_gfp_l256_output_s { uint64_t xk; /**< x coordinate of resultant EC point (4 qwords)*/ uint64_t yk; /**< y coordinate of resultant EC point (4 qwords)*/ } icp_qat_fw_maths_point_multiplication_gfp_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GFP Partial Point Verification, to be used * when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_VERIFY_GFP_L256. */ typedef struct icp_qat_fw_maths_point_verify_gfp_l256_output_s { /* no output parameters */ } icp_qat_fw_maths_point_verify_gfp_l256_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GFP Point Multiplication, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GFP_L512. */ typedef struct icp_qat_fw_maths_point_multiplication_gfp_l512_output_s { uint64_t xk; /**< x coordinate of resultant EC point (8 qwords)*/ uint64_t yk; /**< y coordinate of resultant EC point (8 qwords)*/ } icp_qat_fw_maths_point_multiplication_gfp_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GFP Partial Point, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_VERIFY_GFP_L512. */ typedef struct icp_qat_fw_maths_point_verify_gfp_l512_output_s { /* no output parameters */ } icp_qat_fw_maths_point_verify_gfp_l512_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GFP Point Multiplication, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_MULTIPLICATION_GFP_521. */ typedef struct icp_qat_fw_maths_point_multiplication_gfp_521_output_s { uint64_t xk; /**< x coordinate of resultant EC point (9 qwords)*/ uint64_t yk; /**< y coordinate of resultant EC point (9 qwords)*/ } icp_qat_fw_maths_point_multiplication_gfp_521_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC GFP Partial Point Verification, to be used * when icp_qat_fw_pke_response_s::functionalityId is * #MATHS_POINT_VERIFY_GFP_521. */ typedef struct icp_qat_fw_maths_point_verify_gfp_521_output_s { /* no output parameters */ } icp_qat_fw_maths_point_verify_gfp_521_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC curve25519 Variable Point Multiplication * [k]P(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #POINT_MULTIPLICATION_C25519. */ typedef struct icp_qat_fw_point_multiplication_c25519_output_s { uint64_t xr; /**< xR = Montgomery affine coordinate X of point [k]P (4 qwords)*/ } icp_qat_fw_point_multiplication_c25519_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC curve25519 Generator Point Multiplication * [k]G(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #GENERATOR_MULTIPLICATION_C25519. */ typedef struct icp_qat_fw_generator_multiplication_c25519_output_s { uint64_t xr; /**< xR = Montgomery affine coordinate X of point [k]G (4 qwords)*/ } icp_qat_fw_generator_multiplication_c25519_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC edwards25519 Variable Point Multiplication * [k]P, as specified in RFC8032, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #POINT_MULTIPLICATION_ED25519. */ typedef struct icp_qat_fw_point_multiplication_ed25519_output_s { uint64_t xr; /**< xR = Twisted Edwards affine coordinate X of point [k]P (4 qwords)*/ uint64_t yr; /**< yR = Twisted Edwards affine coordinate Y of point [k]P (4 qwords)*/ } icp_qat_fw_point_multiplication_ed25519_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC edwards25519 Generator Point Multiplication * [k]G, as specified in RFC8032, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #GENERATOR_MULTIPLICATION_ED25519. */ typedef struct icp_qat_fw_generator_multiplication_ed25519_output_s { uint64_t xr; /**< xR = Twisted Edwards affine coordinate X of point [k]G (4 qwords)*/ uint64_t yr; /**< yR = Twisted Edwards affine coordinate Y of point [k]G (4 qwords)*/ } icp_qat_fw_generator_multiplication_ed25519_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC curve448 Variable Point Multiplication * [k]P(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #POINT_MULTIPLICATION_C448. */ typedef struct icp_qat_fw_point_multiplication_c448_output_s { uint64_t xr; /**< xR = Montgomery affine coordinate X of point [k]P (8 qwords)*/ } icp_qat_fw_point_multiplication_c448_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC curve448 Generator Point Multiplication * [k]G(x), as specified in RFC7748, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #GENERATOR_MULTIPLICATION_C448. */ typedef struct icp_qat_fw_generator_multiplication_c448_output_s { uint64_t xr; /**< xR = Montgomery affine coordinate X of point [k]G (8 qwords)*/ } icp_qat_fw_generator_multiplication_c448_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC edwards448 Variable Point Multiplication * [k]P, as specified in RFC8032, to be used when * icp_qat_fw_pke_response_s::functionalityId is #POINT_MULTIPLICATION_ED448. */ typedef struct icp_qat_fw_point_multiplication_ed448_output_s { uint64_t xr; /**< xR = Edwards affine coordinate X of point [k]P (8 qwords)*/ uint64_t yr; /**< yR = Edwards affine coordinate Y of point [k]P (8 qwords)*/ } icp_qat_fw_point_multiplication_ed448_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * Output parameter list for ECC edwards448 Generator Point Multiplication * [k]P, as specified in RFC8032, to be used when * icp_qat_fw_pke_response_s::functionalityId is * #GENERATOR_MULTIPLICATION_ED448. */ typedef struct icp_qat_fw_generator_multiplication_ed448_output_s { uint64_t xr; /**< xR = Edwards affine coordinate X of point [k]G (8 qwords)*/ uint64_t yr; /**< yR = Edwards affine coordinate Y of point [k]G (8 qwords)*/ } icp_qat_fw_generator_multiplication_ed448_output_t; /** * @ingroup icp_qat_fw_mmp * @brief * MMP output parameters */ typedef union icp_qat_fw_mmp_output_param_u { /** Generic parameter structure : All members of this wrapper structure * are pointers to large integers. */ uint64_t flat_array[ICP_QAT_FW_PKE_OUTPUT_COUNT_MAX]; /** ECC SM2 point multiply [k]G */ icp_qat_fw_mmp_ecsm2_generator_multiplication_output_t mmp_ecsm2_generator_multiplication; /** ECC SM2 point multiply [k]P */ icp_qat_fw_mmp_ecsm2_point_multiplication_output_t mmp_ecsm2_point_multiplication; /** ECC SM2 point verify */ icp_qat_fw_mmp_ecsm2_point_verify_output_t mmp_ecsm2_point_verify; /** ECC SM2 Sign RS */ icp_qat_fw_mmp_ecsm2_sign_rs_output_t mmp_ecsm2_sign_rs; /** ECC SM2 Signature Verify */ icp_qat_fw_mmp_ecsm2_verify_output_t mmp_ecsm2_verify; /** ECC SM2 encryption */ icp_qat_fw_mmp_ecsm2_encryption_output_t mmp_ecsm2_encryption; /** ECC SM2 decryption */ icp_qat_fw_mmp_ecsm2_decryption_output_t mmp_ecsm2_decryption; /** ECC SM2 key exchange phase1 */ icp_qat_fw_mmp_ecsm2_keyex_p1_output_t mmp_ecsm2_keyex_p1; /** ECC SM2 key exchange phase2 */ icp_qat_fw_mmp_ecsm2_keyex_p2_output_t mmp_ecsm2_keyex_p2; /** Initialisation sequence */ icp_qat_fw_mmp_init_output_t mmp_init; /** ECC P384 Variable Point Multiplication [k]P */ icp_qat_fw_mmp_ec_point_multiplication_p384_output_t mmp_ec_point_multiplication_p384; /** ECC P384 Generator Point Multiplication [k]G */ icp_qat_fw_mmp_ec_generator_multiplication_p384_output_t mmp_ec_generator_multiplication_p384; /** ECC P384 ECDSA Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_p384_output_t mmp_ecdsa_sign_rs_p384; /** ECC P256 Variable Point Multiplication [k]P */ icp_qat_fw_mmp_ec_point_multiplication_p256_output_t mmp_ec_point_multiplication_p256; /** ECC P256 Generator Point Multiplication [k]G */ icp_qat_fw_mmp_ec_generator_multiplication_p256_output_t mmp_ec_generator_multiplication_p256; /** ECC P256 ECDSA Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_p256_output_t mmp_ecdsa_sign_rs_p256; /** Diffie-Hellman Modular exponentiation base 2 for 768-bit numbers */ icp_qat_fw_mmp_dh_g2_768_output_t mmp_dh_g2_768; /** Diffie-Hellman Modular exponentiation for 768-bit numbers */ icp_qat_fw_mmp_dh_768_output_t mmp_dh_768; /** Diffie-Hellman Modular exponentiation base 2 for 1024-bit numbers */ icp_qat_fw_mmp_dh_g2_1024_output_t mmp_dh_g2_1024; /** Diffie-Hellman Modular exponentiation for 1024-bit numbers */ icp_qat_fw_mmp_dh_1024_output_t mmp_dh_1024; /** Diffie-Hellman Modular exponentiation base 2 for 1536-bit numbers */ icp_qat_fw_mmp_dh_g2_1536_output_t mmp_dh_g2_1536; /** Diffie-Hellman Modular exponentiation for 1536-bit numbers */ icp_qat_fw_mmp_dh_1536_output_t mmp_dh_1536; /** Diffie-Hellman Modular exponentiation base 2 for 2048-bit numbers */ icp_qat_fw_mmp_dh_g2_2048_output_t mmp_dh_g2_2048; /** Diffie-Hellman Modular exponentiation for 2048-bit numbers */ icp_qat_fw_mmp_dh_2048_output_t mmp_dh_2048; /** Diffie-Hellman Modular exponentiation base 2 for 3072-bit numbers */ icp_qat_fw_mmp_dh_g2_3072_output_t mmp_dh_g2_3072; /** Diffie-Hellman Modular exponentiation for 3072-bit numbers */ icp_qat_fw_mmp_dh_3072_output_t mmp_dh_3072; /** Diffie-Hellman Modular exponentiation base 2 for 4096-bit numbers */ icp_qat_fw_mmp_dh_g2_4096_output_t mmp_dh_g2_4096; /** Diffie-Hellman Modular exponentiation for 4096-bit numbers */ icp_qat_fw_mmp_dh_4096_output_t mmp_dh_4096; /** Diffie-Hellman Modular exponentiation base 2 for 8192-bit numbers */ icp_qat_fw_mmp_dh_g2_8192_output_t mmp_dh_g2_8192; /** Diffie-Hellman Modular exponentiation for 8192-bit numbers */ icp_qat_fw_mmp_dh_8192_output_t mmp_dh_8192; /** RSA 512 key generation first form */ icp_qat_fw_mmp_rsa_kp1_512_output_t mmp_rsa_kp1_512; /** RSA 512 key generation second form */ icp_qat_fw_mmp_rsa_kp2_512_output_t mmp_rsa_kp2_512; /** RSA 512 Encryption */ icp_qat_fw_mmp_rsa_ep_512_output_t mmp_rsa_ep_512; /** RSA 512 Decryption */ icp_qat_fw_mmp_rsa_dp1_512_output_t mmp_rsa_dp1_512; /** RSA 1024 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_512_output_t mmp_rsa_dp2_512; /** RSA 1024 key generation first form */ icp_qat_fw_mmp_rsa_kp1_1024_output_t mmp_rsa_kp1_1024; /** RSA 1024 key generation second form */ icp_qat_fw_mmp_rsa_kp2_1024_output_t mmp_rsa_kp2_1024; /** RSA 1024 Encryption */ icp_qat_fw_mmp_rsa_ep_1024_output_t mmp_rsa_ep_1024; /** RSA 1024 Decryption */ icp_qat_fw_mmp_rsa_dp1_1024_output_t mmp_rsa_dp1_1024; /** RSA 1024 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_1024_output_t mmp_rsa_dp2_1024; /** RSA 1536 key generation first form */ icp_qat_fw_mmp_rsa_kp1_1536_output_t mmp_rsa_kp1_1536; /** RSA 1536 key generation second form */ icp_qat_fw_mmp_rsa_kp2_1536_output_t mmp_rsa_kp2_1536; /** RSA 1536 Encryption */ icp_qat_fw_mmp_rsa_ep_1536_output_t mmp_rsa_ep_1536; /** RSA 1536 Decryption */ icp_qat_fw_mmp_rsa_dp1_1536_output_t mmp_rsa_dp1_1536; /** RSA 1536 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_1536_output_t mmp_rsa_dp2_1536; /** RSA 2048 key generation first form */ icp_qat_fw_mmp_rsa_kp1_2048_output_t mmp_rsa_kp1_2048; /** RSA 2048 key generation second form */ icp_qat_fw_mmp_rsa_kp2_2048_output_t mmp_rsa_kp2_2048; /** RSA 2048 Encryption */ icp_qat_fw_mmp_rsa_ep_2048_output_t mmp_rsa_ep_2048; /** RSA 2048 Decryption */ icp_qat_fw_mmp_rsa_dp1_2048_output_t mmp_rsa_dp1_2048; /** RSA 2048 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_2048_output_t mmp_rsa_dp2_2048; /** RSA 3072 key generation first form */ icp_qat_fw_mmp_rsa_kp1_3072_output_t mmp_rsa_kp1_3072; /** RSA 3072 key generation second form */ icp_qat_fw_mmp_rsa_kp2_3072_output_t mmp_rsa_kp2_3072; /** RSA 3072 Encryption */ icp_qat_fw_mmp_rsa_ep_3072_output_t mmp_rsa_ep_3072; /** RSA 3072 Decryption */ icp_qat_fw_mmp_rsa_dp1_3072_output_t mmp_rsa_dp1_3072; /** RSA 3072 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_3072_output_t mmp_rsa_dp2_3072; /** RSA 4096 key generation first form */ icp_qat_fw_mmp_rsa_kp1_4096_output_t mmp_rsa_kp1_4096; /** RSA 4096 key generation second form */ icp_qat_fw_mmp_rsa_kp2_4096_output_t mmp_rsa_kp2_4096; /** RSA 4096 Encryption */ icp_qat_fw_mmp_rsa_ep_4096_output_t mmp_rsa_ep_4096; /** RSA 4096 Decryption */ icp_qat_fw_mmp_rsa_dp1_4096_output_t mmp_rsa_dp1_4096; /** RSA 4096 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_4096_output_t mmp_rsa_dp2_4096; /** RSA 8192 Encryption */ icp_qat_fw_mmp_rsa_ep_8192_output_t mmp_rsa_ep_8192; /** RSA 8192 Decryption */ icp_qat_fw_mmp_rsa_dp1_8192_output_t mmp_rsa_dp1_8192; /** RSA 8192 Decryption with CRT */ icp_qat_fw_mmp_rsa_dp2_8192_output_t mmp_rsa_dp2_8192; /** GCD primality test for 192-bit numbers */ icp_qat_fw_mmp_gcd_pt_192_output_t mmp_gcd_pt_192; /** GCD primality test for 256-bit numbers */ icp_qat_fw_mmp_gcd_pt_256_output_t mmp_gcd_pt_256; /** GCD primality test for 384-bit numbers */ icp_qat_fw_mmp_gcd_pt_384_output_t mmp_gcd_pt_384; /** GCD primality test for 512-bit numbers */ icp_qat_fw_mmp_gcd_pt_512_output_t mmp_gcd_pt_512; /** GCD primality test for 768-bit numbers */ icp_qat_fw_mmp_gcd_pt_768_output_t mmp_gcd_pt_768; /** GCD primality test for 1024-bit numbers */ icp_qat_fw_mmp_gcd_pt_1024_output_t mmp_gcd_pt_1024; /** GCD primality test for 1536-bit numbers */ icp_qat_fw_mmp_gcd_pt_1536_output_t mmp_gcd_pt_1536; /** GCD primality test for 2048-bit numbers */ icp_qat_fw_mmp_gcd_pt_2048_output_t mmp_gcd_pt_2048; /** GCD primality test for 3072-bit numbers */ icp_qat_fw_mmp_gcd_pt_3072_output_t mmp_gcd_pt_3072; /** GCD primality test for 4096-bit numbers */ icp_qat_fw_mmp_gcd_pt_4096_output_t mmp_gcd_pt_4096; /** Fermat primality test for 160-bit numbers */ icp_qat_fw_mmp_fermat_pt_160_output_t mmp_fermat_pt_160; /** Fermat primality test for 512-bit numbers */ icp_qat_fw_mmp_fermat_pt_512_output_t mmp_fermat_pt_512; /** Fermat primality test for <e; 512-bit numbers */ icp_qat_fw_mmp_fermat_pt_l512_output_t mmp_fermat_pt_l512; /** Fermat primality test for 768-bit numbers */ icp_qat_fw_mmp_fermat_pt_768_output_t mmp_fermat_pt_768; /** Fermat primality test for 1024-bit numbers */ icp_qat_fw_mmp_fermat_pt_1024_output_t mmp_fermat_pt_1024; /** Fermat primality test for 1536-bit numbers */ icp_qat_fw_mmp_fermat_pt_1536_output_t mmp_fermat_pt_1536; /** Fermat primality test for 2048-bit numbers */ icp_qat_fw_mmp_fermat_pt_2048_output_t mmp_fermat_pt_2048; /** Fermat primality test for 3072-bit numbers */ icp_qat_fw_mmp_fermat_pt_3072_output_t mmp_fermat_pt_3072; /** Fermat primality test for 4096-bit numbers */ icp_qat_fw_mmp_fermat_pt_4096_output_t mmp_fermat_pt_4096; /** Miller-Rabin primality test for 160-bit numbers */ icp_qat_fw_mmp_mr_pt_160_output_t mmp_mr_pt_160; /** Miller-Rabin primality test for 512-bit numbers */ icp_qat_fw_mmp_mr_pt_512_output_t mmp_mr_pt_512; /** Miller-Rabin primality test for 768-bit numbers */ icp_qat_fw_mmp_mr_pt_768_output_t mmp_mr_pt_768; /** Miller-Rabin primality test for 1024-bit numbers */ icp_qat_fw_mmp_mr_pt_1024_output_t mmp_mr_pt_1024; /** Miller-Rabin primality test for 1536-bit numbers */ icp_qat_fw_mmp_mr_pt_1536_output_t mmp_mr_pt_1536; /** Miller-Rabin primality test for 2048-bit numbers */ icp_qat_fw_mmp_mr_pt_2048_output_t mmp_mr_pt_2048; /** Miller-Rabin primality test for 3072-bit numbers */ icp_qat_fw_mmp_mr_pt_3072_output_t mmp_mr_pt_3072; /** Miller-Rabin primality test for 4096-bit numbers */ icp_qat_fw_mmp_mr_pt_4096_output_t mmp_mr_pt_4096; /** Miller-Rabin primality test for 512-bit numbers */ icp_qat_fw_mmp_mr_pt_l512_output_t mmp_mr_pt_l512; /** Lucas primality test for 160-bit numbers */ icp_qat_fw_mmp_lucas_pt_160_output_t mmp_lucas_pt_160; /** Lucas primality test for 512-bit numbers */ icp_qat_fw_mmp_lucas_pt_512_output_t mmp_lucas_pt_512; /** Lucas primality test for 768-bit numbers */ icp_qat_fw_mmp_lucas_pt_768_output_t mmp_lucas_pt_768; /** Lucas primality test for 1024-bit numbers */ icp_qat_fw_mmp_lucas_pt_1024_output_t mmp_lucas_pt_1024; /** Lucas primality test for 1536-bit numbers */ icp_qat_fw_mmp_lucas_pt_1536_output_t mmp_lucas_pt_1536; /** Lucas primality test for 2048-bit numbers */ icp_qat_fw_mmp_lucas_pt_2048_output_t mmp_lucas_pt_2048; /** Lucas primality test for 3072-bit numbers */ icp_qat_fw_mmp_lucas_pt_3072_output_t mmp_lucas_pt_3072; /** Lucas primality test for 4096-bit numbers */ icp_qat_fw_mmp_lucas_pt_4096_output_t mmp_lucas_pt_4096; /** Lucas primality test for L512-bit numbers */ icp_qat_fw_mmp_lucas_pt_l512_output_t mmp_lucas_pt_l512; /** Modular exponentiation for numbers less than 512-bits */ icp_qat_fw_maths_modexp_l512_output_t maths_modexp_l512; /** Modular exponentiation for numbers less than 1024-bit */ icp_qat_fw_maths_modexp_l1024_output_t maths_modexp_l1024; /** Modular exponentiation for numbers less than 1536-bits */ icp_qat_fw_maths_modexp_l1536_output_t maths_modexp_l1536; /** Modular exponentiation for numbers less than 2048-bit */ icp_qat_fw_maths_modexp_l2048_output_t maths_modexp_l2048; /** Modular exponentiation for numbers less than 2560-bits */ icp_qat_fw_maths_modexp_l2560_output_t maths_modexp_l2560; /** Modular exponentiation for numbers less than 3072-bits */ icp_qat_fw_maths_modexp_l3072_output_t maths_modexp_l3072; /** Modular exponentiation for numbers less than 3584-bits */ icp_qat_fw_maths_modexp_l3584_output_t maths_modexp_l3584; /** Modular exponentiation for numbers less than 4096-bit */ icp_qat_fw_maths_modexp_l4096_output_t maths_modexp_l4096; /** Modular exponentiation for numbers up to 8192 bits */ icp_qat_fw_maths_modexp_l8192_output_t maths_modexp_l8192; /** Modular multiplicative inverse for numbers less than 128 bits */ icp_qat_fw_maths_modinv_odd_l128_output_t maths_modinv_odd_l128; /** Modular multiplicative inverse for numbers less than 192 bits */ icp_qat_fw_maths_modinv_odd_l192_output_t maths_modinv_odd_l192; /** Modular multiplicative inverse for numbers less than 256 bits */ icp_qat_fw_maths_modinv_odd_l256_output_t maths_modinv_odd_l256; /** Modular multiplicative inverse for numbers less than 384 bits */ icp_qat_fw_maths_modinv_odd_l384_output_t maths_modinv_odd_l384; /** Modular multiplicative inverse for numbers less than 512 bits */ icp_qat_fw_maths_modinv_odd_l512_output_t maths_modinv_odd_l512; /** Modular multiplicative inverse for numbers less than 768 bits */ icp_qat_fw_maths_modinv_odd_l768_output_t maths_modinv_odd_l768; /** Modular multiplicative inverse for numbers less than 1024 bits */ icp_qat_fw_maths_modinv_odd_l1024_output_t maths_modinv_odd_l1024; /** Modular multiplicative inverse for numbers less than 1536 bits */ icp_qat_fw_maths_modinv_odd_l1536_output_t maths_modinv_odd_l1536; /** Modular multiplicative inverse for numbers less than 2048 bits */ icp_qat_fw_maths_modinv_odd_l2048_output_t maths_modinv_odd_l2048; /** Modular multiplicative inverse for numbers less than 3072 bits */ icp_qat_fw_maths_modinv_odd_l3072_output_t maths_modinv_odd_l3072; /** Modular multiplicative inverse for numbers less than 4096 bits */ icp_qat_fw_maths_modinv_odd_l4096_output_t maths_modinv_odd_l4096; /** Modular multiplicative inverse for numbers up to 8192 bits */ icp_qat_fw_maths_modinv_odd_l8192_output_t maths_modinv_odd_l8192; /** Modular multiplicative inverse for numbers less than 128 bits */ icp_qat_fw_maths_modinv_even_l128_output_t maths_modinv_even_l128; /** Modular multiplicative inverse for numbers less than 192 bits */ icp_qat_fw_maths_modinv_even_l192_output_t maths_modinv_even_l192; /** Modular multiplicative inverse for numbers less than 256 bits */ icp_qat_fw_maths_modinv_even_l256_output_t maths_modinv_even_l256; /** Modular multiplicative inverse for numbers less than 384 bits */ icp_qat_fw_maths_modinv_even_l384_output_t maths_modinv_even_l384; /** Modular multiplicative inverse for numbers less than 512 bits */ icp_qat_fw_maths_modinv_even_l512_output_t maths_modinv_even_l512; /** Modular multiplicative inverse for numbers less than 768 bits */ icp_qat_fw_maths_modinv_even_l768_output_t maths_modinv_even_l768; /** Modular multiplicative inverse for numbers less than 1024 bits */ icp_qat_fw_maths_modinv_even_l1024_output_t maths_modinv_even_l1024; /** Modular multiplicative inverse for numbers less than 1536 bits */ icp_qat_fw_maths_modinv_even_l1536_output_t maths_modinv_even_l1536; /** Modular multiplicative inverse for numbers less than 2048 bits */ icp_qat_fw_maths_modinv_even_l2048_output_t maths_modinv_even_l2048; /** Modular multiplicative inverse for numbers less than 3072 bits */ icp_qat_fw_maths_modinv_even_l3072_output_t maths_modinv_even_l3072; /** Modular multiplicative inverse for numbers less than 4096 bits */ icp_qat_fw_maths_modinv_even_l4096_output_t maths_modinv_even_l4096; /** Modular multiplicative inverse for numbers up to 8192 bits */ icp_qat_fw_maths_modinv_even_l8192_output_t maths_modinv_even_l8192; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_1024_160_output_t mmp_dsa_gen_p_1024_160; /** DSA key generation G */ icp_qat_fw_mmp_dsa_gen_g_1024_output_t mmp_dsa_gen_g_1024; /** DSA key generation Y */ icp_qat_fw_mmp_dsa_gen_y_1024_output_t mmp_dsa_gen_y_1024; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_1024_160_output_t mmp_dsa_sign_r_1024_160; /** DSA Sign S */ icp_qat_fw_mmp_dsa_sign_s_160_output_t mmp_dsa_sign_s_160; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_t mmp_dsa_sign_r_s_1024_160; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_1024_160_output_t mmp_dsa_verify_1024_160; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_2048_224_output_t mmp_dsa_gen_p_2048_224; /** DSA key generation Y */ icp_qat_fw_mmp_dsa_gen_y_2048_output_t mmp_dsa_gen_y_2048; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_2048_224_output_t mmp_dsa_sign_r_2048_224; /** DSA Sign S */ icp_qat_fw_mmp_dsa_sign_s_224_output_t mmp_dsa_sign_s_224; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_t mmp_dsa_sign_r_s_2048_224; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_2048_224_output_t mmp_dsa_verify_2048_224; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_2048_256_output_t mmp_dsa_gen_p_2048_256; /** DSA key generation G */ icp_qat_fw_mmp_dsa_gen_g_2048_output_t mmp_dsa_gen_g_2048; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_2048_256_output_t mmp_dsa_sign_r_2048_256; /** DSA Sign S */ icp_qat_fw_mmp_dsa_sign_s_256_output_t mmp_dsa_sign_s_256; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_t mmp_dsa_sign_r_s_2048_256; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_2048_256_output_t mmp_dsa_verify_2048_256; /** DSA parameter generation P */ icp_qat_fw_mmp_dsa_gen_p_3072_256_output_t mmp_dsa_gen_p_3072_256; /** DSA key generation G */ icp_qat_fw_mmp_dsa_gen_g_3072_output_t mmp_dsa_gen_g_3072; /** DSA key generation Y */ icp_qat_fw_mmp_dsa_gen_y_3072_output_t mmp_dsa_gen_y_3072; /** DSA Sign R */ icp_qat_fw_mmp_dsa_sign_r_3072_256_output_t mmp_dsa_sign_r_3072_256; /** DSA Sign R S */ icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_t mmp_dsa_sign_r_s_3072_256; /** DSA Verify */ icp_qat_fw_mmp_dsa_verify_3072_256_output_t mmp_dsa_verify_3072_256; /** ECDSA Sign RS for curves B/K-163 and B/K-233 */ icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_t mmp_ecdsa_sign_rs_gf2_l256; /** ECDSA Sign R for curves B/K-163 and B/K-233 */ icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_t mmp_ecdsa_sign_r_gf2_l256; /** ECDSA Sign S for curves with n < 2^256 */ icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_t mmp_ecdsa_sign_s_gf2_l256; /** ECDSA Verify for curves B/K-163 and B/K-233 */ icp_qat_fw_mmp_ecdsa_verify_gf2_l256_output_t mmp_ecdsa_verify_gf2_l256; /** ECDSA Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_t mmp_ecdsa_sign_rs_gf2_l512; /** ECDSA GF2 Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_t mmp_ecdsa_sign_r_gf2_l512; /** ECDSA GF2 Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_t mmp_ecdsa_sign_s_gf2_l512; /** ECDSA GF2 Verify */ icp_qat_fw_mmp_ecdsa_verify_gf2_l512_output_t mmp_ecdsa_verify_gf2_l512; /** ECDSA GF2 Sign RS for curves B-571/K-571 */ icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_t mmp_ecdsa_sign_rs_gf2_571; /** ECDSA GF2 Sign S for curves with deg(q) < 576 */ icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_t mmp_ecdsa_sign_s_gf2_571; /** ECDSA GF2 Sign R for degree 571 */ icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_t mmp_ecdsa_sign_r_gf2_571; /** ECDSA GF2 Verify for degree 571 */ icp_qat_fw_mmp_ecdsa_verify_gf2_571_output_t mmp_ecdsa_verify_gf2_571; /** MATHS GF2 Point Multiplication */ icp_qat_fw_maths_point_multiplication_gf2_l256_output_t maths_point_multiplication_gf2_l256; /** MATHS GF2 Point Verification */ icp_qat_fw_maths_point_verify_gf2_l256_output_t maths_point_verify_gf2_l256; /** MATHS GF2 Point Multiplication */ icp_qat_fw_maths_point_multiplication_gf2_l512_output_t maths_point_multiplication_gf2_l512; /** MATHS GF2 Point Verification */ icp_qat_fw_maths_point_verify_gf2_l512_output_t maths_point_verify_gf2_l512; /** ECC GF2 Point Multiplication for curves B-571/K-571 */ icp_qat_fw_maths_point_multiplication_gf2_571_output_t maths_point_multiplication_gf2_571; /** ECC GF2 Point Verification for degree 571 */ icp_qat_fw_maths_point_verify_gf2_571_output_t maths_point_verify_gf2_571; /** ECDSA GFP Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_t mmp_ecdsa_sign_r_gfp_l256; /** ECDSA GFP Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_t mmp_ecdsa_sign_s_gfp_l256; /** ECDSA GFP Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_t mmp_ecdsa_sign_rs_gfp_l256; /** ECDSA GFP Verify */ icp_qat_fw_mmp_ecdsa_verify_gfp_l256_output_t mmp_ecdsa_verify_gfp_l256; /** ECDSA GFP Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_t mmp_ecdsa_sign_r_gfp_l512; /** ECDSA GFP Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_t mmp_ecdsa_sign_s_gfp_l512; /** ECDSA GFP Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_t mmp_ecdsa_sign_rs_gfp_l512; /** ECDSA GFP Verify */ icp_qat_fw_mmp_ecdsa_verify_gfp_l512_output_t mmp_ecdsa_verify_gfp_l512; /** ECDSA GFP Sign R */ icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_t mmp_ecdsa_sign_r_gfp_521; /** ECDSA GFP Sign S */ icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_t mmp_ecdsa_sign_s_gfp_521; /** ECDSA GFP Sign RS */ icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_t mmp_ecdsa_sign_rs_gfp_521; /** ECDSA GFP Verify */ icp_qat_fw_mmp_ecdsa_verify_gfp_521_output_t mmp_ecdsa_verify_gfp_521; /** ECC GFP Point Multiplication */ icp_qat_fw_maths_point_multiplication_gfp_l256_output_t maths_point_multiplication_gfp_l256; /** ECC GFP Partial Point Verification */ icp_qat_fw_maths_point_verify_gfp_l256_output_t maths_point_verify_gfp_l256; /** ECC GFP Point Multiplication */ icp_qat_fw_maths_point_multiplication_gfp_l512_output_t maths_point_multiplication_gfp_l512; /** ECC GFP Partial Point */ icp_qat_fw_maths_point_verify_gfp_l512_output_t maths_point_verify_gfp_l512; /** ECC GFP Point Multiplication */ icp_qat_fw_maths_point_multiplication_gfp_521_output_t maths_point_multiplication_gfp_521; /** ECC GFP Partial Point Verification */ icp_qat_fw_maths_point_verify_gfp_521_output_t maths_point_verify_gfp_521; /** ECC curve25519 Variable Point Multiplication [k]P(x), as specified in * RFC7748 */ icp_qat_fw_point_multiplication_c25519_output_t point_multiplication_c25519; /** ECC curve25519 Generator Point Multiplication [k]G(x), as specified in * RFC7748 */ icp_qat_fw_generator_multiplication_c25519_output_t generator_multiplication_c25519; /** ECC edwards25519 Variable Point Multiplication [k]P, as specified in * RFC8032 */ icp_qat_fw_point_multiplication_ed25519_output_t point_multiplication_ed25519; /** ECC edwards25519 Generator Point Multiplication [k]G, as specified in * RFC8032 */ icp_qat_fw_generator_multiplication_ed25519_output_t generator_multiplication_ed25519; /** ECC curve448 Variable Point Multiplication [k]P(x), as specified in * RFC7748 */ icp_qat_fw_point_multiplication_c448_output_t point_multiplication_c448; /** ECC curve448 Generator Point Multiplication [k]G(x), as specified in * RFC7748 */ icp_qat_fw_generator_multiplication_c448_output_t generator_multiplication_c448; /** ECC edwards448 Variable Point Multiplication [k]P, as specified in * RFC8032 */ icp_qat_fw_point_multiplication_ed448_output_t point_multiplication_ed448; /** ECC edwards448 Generator Point Multiplication [k]P, as specified in * RFC8032 */ icp_qat_fw_generator_multiplication_ed448_output_t generator_multiplication_ed448; } icp_qat_fw_mmp_output_param_t; #endif /* __ICP_QAT_FW_MMP__ */ /* --- (Automatically generated (build v. 2.7), do not modify manually) --- */ /* --- end of file --- */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw_mmp_ids.h000066400000000000000000002664151503624047500267370ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /* --- (Automatically generated (relocation v. 1.5), do not modify manually) --- */ /** * @file icp_qat_fw_mmp_ids.h * @ingroup icp_qat_fw_mmp * $Revision: 0.1 $ * @brief * This file documents the external interfaces that the QAT FW running * on the QAT Acceleration Engine provides to clients wanting to * accelerate crypto asymmetric applications */ #ifndef __ICP_QAT_FW_MMP_IDS__ #define __ICP_QAT_FW_MMP_IDS__ #define PKE_INIT 0x0806169f /**< Functionality ID for Initialisation sequence * @li 1 input parameters : * @link icp_qat_fw_mmp_init_input_s::z z @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_init_output_s::zz zz @endlink */ #define PKE_DH_G2_768 0x1c0b1a10 /**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for * 768-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_dh_g2_768_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_g2_768_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_g2_768_output_s::r r @endlink */ #define PKE_DH_768 0x210c1a1b /**< Functionality ID for Diffie-Hellman Modular exponentiation for 768-bit * numbers * @li 3 input parameters : * @link icp_qat_fw_mmp_dh_768_input_s::g g @endlink * @link icp_qat_fw_mmp_dh_768_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_768_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_768_output_s::r r @endlink */ #define PKE_DH_G2_1024 0x220b1a27 /**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for * 1024-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_dh_g2_1024_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_g2_1024_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_g2_1024_output_s::r r @endlink */ #define PKE_DH_1024 0x290c1a32 /**< Functionality ID for Diffie-Hellman Modular exponentiation for 1024-bit * numbers * @li 3 input parameters : * @link icp_qat_fw_mmp_dh_1024_input_s::g g @endlink * @link icp_qat_fw_mmp_dh_1024_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_1024_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_1024_output_s::r r @endlink */ #define PKE_DH_G2_1536 0x2e0b1a3e /**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for * 1536-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_dh_g2_1536_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_g2_1536_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_g2_1536_output_s::r r @endlink */ #define PKE_DH_1536 0x390c1a49 /**< Functionality ID for Diffie-Hellman Modular exponentiation for 1536-bit * numbers * @li 3 input parameters : * @link icp_qat_fw_mmp_dh_1536_input_s::g g @endlink * @link icp_qat_fw_mmp_dh_1536_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_1536_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_1536_output_s::r r @endlink */ #define PKE_DH_G2_2048 0x3e0b1a55 /**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for * 2048-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_dh_g2_2048_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_g2_2048_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_g2_2048_output_s::r r @endlink */ #define PKE_DH_2048 0x4d0c1a60 /**< Functionality ID for Diffie-Hellman Modular exponentiation for 2048-bit * numbers * @li 3 input parameters : * @link icp_qat_fw_mmp_dh_2048_input_s::g g @endlink * @link icp_qat_fw_mmp_dh_2048_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_2048_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_2048_output_s::r r @endlink */ #define PKE_DH_G2_3072 0x3a0b1a6c /**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for * 3072-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_dh_g2_3072_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_g2_3072_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_g2_3072_output_s::r r @endlink */ #define PKE_DH_3072 0x510c1a77 /**< Functionality ID for Diffie-Hellman Modular exponentiation for 3072-bit * numbers * @li 3 input parameters : * @link icp_qat_fw_mmp_dh_3072_input_s::g g @endlink * @link icp_qat_fw_mmp_dh_3072_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_3072_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_3072_output_s::r r @endlink */ #define PKE_DH_G2_4096 0x4a0b1a83 /**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for * 4096-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_dh_g2_4096_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_g2_4096_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_g2_4096_output_s::r r @endlink */ #define PKE_DH_4096 0x690c1a8e /**< Functionality ID for Diffie-Hellman Modular exponentiation for 4096-bit * numbers * @li 3 input parameters : * @link icp_qat_fw_mmp_dh_4096_input_s::g g @endlink * @link icp_qat_fw_mmp_dh_4096_input_s::e e @endlink * @link icp_qat_fw_mmp_dh_4096_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dh_4096_output_s::r r @endlink */ #define PKE_DH_G2_8192 0x8d0b3626 /**< Functionality ID for Diffie-Hellman Modular exponentiation base 2 for * 8192-bit numbers * @li 2 input parameters : @link icp_qat_fw_mmp_dh_g2_8192_input_s::e e * @endlink @link icp_qat_fw_mmp_dh_g2_8192_input_s::m m @endlink * @li 1 output parameters : @link icp_qat_fw_mmp_dh_g2_8192_output_s::r r * @endlink */ #define PKE_DH_8192 0xcd0d3636 /**< Functionality ID for Diffie-Hellman Modular exponentiation for 8192-bit * numbers * @li 3 input parameters : @link icp_qat_fw_mmp_dh_8192_input_s::g g @endlink * @link icp_qat_fw_mmp_dh_8192_input_s::e e @endlink @link * icp_qat_fw_mmp_dh_8192_input_s::m m @endlink * @li 1 output parameters : @link icp_qat_fw_mmp_dh_8192_output_s::r r @endlink */ #define PKE_RSA_KP1_512 0x191d1a9a /**< Functionality ID for RSA 512 key generation first form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp1_512_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp1_512_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp1_512_input_s::e e @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_rsa_kp1_512_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp1_512_output_s::d d @endlink */ #define PKE_RSA_KP2_512 0x19401acc /**< Functionality ID for RSA 512 key generation second form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp2_512_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp2_512_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp2_512_input_s::e e @endlink * @li 5 output parameters : * @link icp_qat_fw_mmp_rsa_kp2_512_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp2_512_output_s::d d @endlink * @link icp_qat_fw_mmp_rsa_kp2_512_output_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_kp2_512_output_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_kp2_512_output_s::qinv qinv @endlink */ #define PKE_RSA_EP_512 0x1c161b21 /**< Functionality ID for RSA 512 Encryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_ep_512_input_s::m m @endlink * @link icp_qat_fw_mmp_rsa_ep_512_input_s::e e @endlink * @link icp_qat_fw_mmp_rsa_ep_512_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_ep_512_output_s::c c @endlink */ #define PKE_RSA_DP1_512 0x1c161b3c /**< Functionality ID for RSA 512 Decryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_dp1_512_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp1_512_input_s::d d @endlink * @link icp_qat_fw_mmp_rsa_dp1_512_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp1_512_output_s::m m @endlink */ #define PKE_RSA_DP2_512 0x1c131b57 /**< Functionality ID for RSA 1024 Decryption with CRT * @li 6 input parameters : * @link icp_qat_fw_mmp_rsa_dp2_512_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp2_512_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_dp2_512_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_dp2_512_input_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_dp2_512_input_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_dp2_512_input_s::qinv qinv @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp2_512_output_s::m m @endlink */ #define PKE_RSA_KP1_1024 0x36181b71 /**< Functionality ID for RSA 1024 key generation first form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp1_1024_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp1_1024_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp1_1024_input_s::e e @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_rsa_kp1_1024_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp1_1024_output_s::d d @endlink */ #define PKE_RSA_KP2_1024 0x40451b9e /**< Functionality ID for RSA 1024 key generation second form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp2_1024_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp2_1024_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp2_1024_input_s::e e @endlink * @li 5 output parameters : * @link icp_qat_fw_mmp_rsa_kp2_1024_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp2_1024_output_s::d d @endlink * @link icp_qat_fw_mmp_rsa_kp2_1024_output_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_kp2_1024_output_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_kp2_1024_output_s::qinv qinv @endlink */ #define PKE_RSA_EP_1024 0x35111bf7 /**< Functionality ID for RSA 1024 Encryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_ep_1024_input_s::m m @endlink * @link icp_qat_fw_mmp_rsa_ep_1024_input_s::e e @endlink * @link icp_qat_fw_mmp_rsa_ep_1024_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_ep_1024_output_s::c c @endlink */ #define PKE_RSA_DP1_1024 0x35111c12 /**< Functionality ID for RSA 1024 Decryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_dp1_1024_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp1_1024_input_s::d d @endlink * @link icp_qat_fw_mmp_rsa_dp1_1024_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp1_1024_output_s::m m @endlink */ #define PKE_RSA_DP2_1024 0x26131c2d /**< Functionality ID for RSA 1024 Decryption with CRT * @li 6 input parameters : * @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_dp2_1024_input_s::qinv qinv @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp2_1024_output_s::m m @endlink */ #define PKE_RSA_KP1_1536 0x531d1c46 /**< Functionality ID for RSA 1536 key generation first form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp1_1536_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp1_1536_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp1_1536_input_s::e e @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_rsa_kp1_1536_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp1_1536_output_s::d d @endlink */ #define PKE_RSA_KP2_1536 0x32391c78 /**< Functionality ID for RSA 1536 key generation second form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp2_1536_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp2_1536_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp2_1536_input_s::e e @endlink * @li 5 output parameters : * @link icp_qat_fw_mmp_rsa_kp2_1536_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp2_1536_output_s::d d @endlink * @link icp_qat_fw_mmp_rsa_kp2_1536_output_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_kp2_1536_output_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_kp2_1536_output_s::qinv qinv @endlink */ #define PKE_RSA_EP_1536 0x4d111cdc /**< Functionality ID for RSA 1536 Encryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_ep_1536_input_s::m m @endlink * @link icp_qat_fw_mmp_rsa_ep_1536_input_s::e e @endlink * @link icp_qat_fw_mmp_rsa_ep_1536_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_ep_1536_output_s::c c @endlink */ #define PKE_RSA_DP1_1536 0x4d111cf7 /**< Functionality ID for RSA 1536 Decryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_dp1_1536_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp1_1536_input_s::d d @endlink * @link icp_qat_fw_mmp_rsa_dp1_1536_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp1_1536_output_s::m m @endlink */ #define PKE_RSA_DP2_1536 0x45111d12 /**< Functionality ID for RSA 1536 Decryption with CRT * @li 6 input parameters : * @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_dp2_1536_input_s::qinv qinv @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp2_1536_output_s::m m @endlink */ #define PKE_RSA_KP1_2048 0x72181d2e /**< Functionality ID for RSA 2048 key generation first form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp1_2048_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp1_2048_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp1_2048_input_s::e e @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_rsa_kp1_2048_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp1_2048_output_s::d d @endlink */ #define PKE_RSA_KP2_2048 0x42341d5b /**< Functionality ID for RSA 2048 key generation second form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp2_2048_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp2_2048_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp2_2048_input_s::e e @endlink * @li 5 output parameters : * @link icp_qat_fw_mmp_rsa_kp2_2048_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp2_2048_output_s::d d @endlink * @link icp_qat_fw_mmp_rsa_kp2_2048_output_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_kp2_2048_output_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_kp2_2048_output_s::qinv qinv @endlink */ #define PKE_RSA_EP_2048 0x6e111dba /**< Functionality ID for RSA 2048 Encryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_ep_2048_input_s::m m @endlink * @link icp_qat_fw_mmp_rsa_ep_2048_input_s::e e @endlink * @link icp_qat_fw_mmp_rsa_ep_2048_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_ep_2048_output_s::c c @endlink */ #define PKE_RSA_DP1_2048 0x6e111dda /**< Functionality ID for RSA 2048 Decryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_dp1_2048_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp1_2048_input_s::d d @endlink * @link icp_qat_fw_mmp_rsa_dp1_2048_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp1_2048_output_s::m m @endlink */ #define PKE_RSA_DP2_2048 0x59121dfa /**< Functionality ID for RSA 2048 Decryption with CRT * @li 6 input parameters : * @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_dp2_2048_input_s::qinv qinv @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp2_2048_output_s::m m @endlink */ #define PKE_RSA_KP1_3072 0x60191e16 /**< Functionality ID for RSA 3072 key generation first form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp1_3072_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp1_3072_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp1_3072_input_s::e e @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_rsa_kp1_3072_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp1_3072_output_s::d d @endlink */ #define PKE_RSA_KP2_3072 0x68331e45 /**< Functionality ID for RSA 3072 key generation second form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp2_3072_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp2_3072_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp2_3072_input_s::e e @endlink * @li 5 output parameters : * @link icp_qat_fw_mmp_rsa_kp2_3072_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp2_3072_output_s::d d @endlink * @link icp_qat_fw_mmp_rsa_kp2_3072_output_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_kp2_3072_output_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_kp2_3072_output_s::qinv qinv @endlink */ #define PKE_RSA_EP_3072 0x7d111ea3 /**< Functionality ID for RSA 3072 Encryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_ep_3072_input_s::m m @endlink * @link icp_qat_fw_mmp_rsa_ep_3072_input_s::e e @endlink * @link icp_qat_fw_mmp_rsa_ep_3072_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_ep_3072_output_s::c c @endlink */ #define PKE_RSA_DP1_3072 0x7d111ebe /**< Functionality ID for RSA 3072 Decryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_dp1_3072_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp1_3072_input_s::d d @endlink * @link icp_qat_fw_mmp_rsa_dp1_3072_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp1_3072_output_s::m m @endlink */ #define PKE_RSA_DP2_3072 0x81121ed9 /**< Functionality ID for RSA 3072 Decryption with CRT * @li 6 input parameters : * @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_dp2_3072_input_s::qinv qinv @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp2_3072_output_s::m m @endlink */ #define PKE_RSA_KP1_4096 0x7d1f1ef6 /**< Functionality ID for RSA 4096 key generation first form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp1_4096_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp1_4096_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp1_4096_input_s::e e @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_rsa_kp1_4096_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp1_4096_output_s::d d @endlink */ #define PKE_RSA_KP2_4096 0x91251f27 /**< Functionality ID for RSA 4096 key generation second form * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_kp2_4096_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_kp2_4096_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_kp2_4096_input_s::e e @endlink * @li 5 output parameters : * @link icp_qat_fw_mmp_rsa_kp2_4096_output_s::n n @endlink * @link icp_qat_fw_mmp_rsa_kp2_4096_output_s::d d @endlink * @link icp_qat_fw_mmp_rsa_kp2_4096_output_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_kp2_4096_output_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_kp2_4096_output_s::qinv qinv @endlink */ #define PKE_RSA_EP_4096 0xa5101f7e /**< Functionality ID for RSA 4096 Encryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_ep_4096_input_s::m m @endlink * @link icp_qat_fw_mmp_rsa_ep_4096_input_s::e e @endlink * @link icp_qat_fw_mmp_rsa_ep_4096_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_ep_4096_output_s::c c @endlink */ #define PKE_RSA_DP1_4096 0xa5101f98 /**< Functionality ID for RSA 4096 Decryption * @li 3 input parameters : * @link icp_qat_fw_mmp_rsa_dp1_4096_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp1_4096_input_s::d d @endlink * @link icp_qat_fw_mmp_rsa_dp1_4096_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp1_4096_output_s::m m @endlink */ #define PKE_RSA_DP2_4096 0xb1111fb2 /**< Functionality ID for RSA 4096 Decryption with CRT * @li 6 input parameters : * @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::c c @endlink * @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::p p @endlink * @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::q q @endlink * @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::dp dp @endlink * @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::dq dq @endlink * @link icp_qat_fw_mmp_rsa_dp2_4096_input_s::qinv qinv @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_rsa_dp2_4096_output_s::m m @endlink */ #define PKE_RSA_EP_8192 0xc31335c6 /**< Functionality ID for RSA 8192 Encryption * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_ep_8192_input_s::m m * @endlink @link icp_qat_fw_mmp_rsa_ep_8192_input_s::e e @endlink @link * icp_qat_fw_mmp_rsa_ep_8192_input_s::n n @endlink * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_ep_8192_output_s::c c * @endlink */ #define PKE_RSA_DP1_8192 0xc31335e6 /**< Functionality ID for RSA 8192 Decryption * @li 3 input parameters : @link icp_qat_fw_mmp_rsa_dp1_8192_input_s::c c * @endlink @link icp_qat_fw_mmp_rsa_dp1_8192_input_s::d d @endlink @link * icp_qat_fw_mmp_rsa_dp1_8192_input_s::n n @endlink * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp1_8192_output_s::m m * @endlink */ #define PKE_RSA_DP2_8192 0xc9133606 /**< Functionality ID for RSA 8192 Decryption with CRT * @li 6 input parameters : @link icp_qat_fw_mmp_rsa_dp2_8192_input_s::c c * @endlink @link icp_qat_fw_mmp_rsa_dp2_8192_input_s::p p @endlink @link * icp_qat_fw_mmp_rsa_dp2_8192_input_s::q q @endlink @link * icp_qat_fw_mmp_rsa_dp2_8192_input_s::dp dp @endlink @link * icp_qat_fw_mmp_rsa_dp2_8192_input_s::dq dq @endlink @link * icp_qat_fw_mmp_rsa_dp2_8192_input_s::qinv qinv @endlink * @li 1 output parameters : @link icp_qat_fw_mmp_rsa_dp2_8192_output_s::m m * @endlink */ #define PKE_GCD_PT_192 0x19201fcd /**< Functionality ID for GCD primality test for 192-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_192_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_256 0x19201ff7 /**< Functionality ID for GCD primality test for 256-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_256_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_384 0x19202021 /**< Functionality ID for GCD primality test for 384-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_384_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_512 0x1b1b204b /**< Functionality ID for GCD primality test for 512-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_512_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_768 0x170c2070 /**< Functionality ID for GCD primality test for 768-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_768_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_1024 0x130f2085 /**< Functionality ID for GCD primality test for 1024-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_1024_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_1536 0x1d0c2094 /**< Functionality ID for GCD primality test for 1536-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_1536_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_2048 0x210c20a5 /**< Functionality ID for GCD primality test for 2048-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_2048_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_3072 0x290c20b6 /**< Functionality ID for GCD primality test for 3072-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_3072_input_s::m m @endlink * @li no output parameters */ #define PKE_GCD_PT_4096 0x310c20c7 /**< Functionality ID for GCD primality test for 4096-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_gcd_pt_4096_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_160 0x0e1120d8 /**< Functionality ID for Fermat primality test for 160-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_160_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_512 0x121120ee /**< Functionality ID for Fermat primality test for 512-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_512_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_L512 0x19162104 /**< Functionality ID for Fermat primality test for <e; 512-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_l512_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_768 0x19112124 /**< Functionality ID for Fermat primality test for 768-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_768_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_1024 0x1f11213a /**< Functionality ID for Fermat primality test for 1024-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_1024_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_1536 0x2b112150 /**< Functionality ID for Fermat primality test for 1536-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_1536_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_2048 0x3b112166 /**< Functionality ID for Fermat primality test for 2048-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_2048_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_3072 0x3a11217c /**< Functionality ID for Fermat primality test for 3072-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_3072_input_s::m m @endlink * @li no output parameters */ #define PKE_FERMAT_PT_4096 0x4a112192 /**< Functionality ID for Fermat primality test for 4096-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_fermat_pt_4096_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_160 0x0e1221a8 /**< Functionality ID for Miller-Rabin primality test for 160-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_160_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_160_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_512 0x111221bf /**< Functionality ID for Miller-Rabin primality test for 512-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_512_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_512_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_768 0x1d0d21d6 /**< Functionality ID for Miller-Rabin primality test for 768-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_768_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_768_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_1024 0x250d21ed /**< Functionality ID for Miller-Rabin primality test for 1024-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_1024_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_1024_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_1536 0x350d2204 /**< Functionality ID for Miller-Rabin primality test for 1536-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_1536_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_1536_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_2048 0x490d221b /**< Functionality ID for Miller-Rabin primality test for 2048-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_2048_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_2048_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_3072 0x4d0d2232 /**< Functionality ID for Miller-Rabin primality test for 3072-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_3072_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_3072_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_4096 0x650d2249 /**< Functionality ID for Miller-Rabin primality test for 4096-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_4096_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_4096_input_s::m m @endlink * @li no output parameters */ #define PKE_MR_PT_L512 0x18182260 /**< Functionality ID for Miller-Rabin primality test for 512-bit numbers * @li 2 input parameters : * @link icp_qat_fw_mmp_mr_pt_l512_input_s::x x @endlink * @link icp_qat_fw_mmp_mr_pt_l512_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_160 0x0e0c227e /**< Functionality ID for Lucas primality test for 160-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_160_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_512 0x110c228f /**< Functionality ID for Lucas primality test for 512-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_512_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_768 0x130c22a0 /**< Functionality ID for Lucas primality test for 768-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_768_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_1024 0x150c22b1 /**< Functionality ID for Lucas primality test for 1024-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_1024_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_1536 0x190c22c2 /**< Functionality ID for Lucas primality test for 1536-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_1536_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_2048 0x1d0c22d3 /**< Functionality ID for Lucas primality test for 2048-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_2048_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_3072 0x250c22e4 /**< Functionality ID for Lucas primality test for 3072-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_3072_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_4096 0x661522f5 /**< Functionality ID for Lucas primality test for 4096-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_4096_input_s::m m @endlink * @li no output parameters */ #define PKE_LUCAS_PT_L512 0x1617230a /**< Functionality ID for Lucas primality test for L512-bit numbers * @li 1 input parameters : * @link icp_qat_fw_mmp_lucas_pt_l512_input_s::m m @endlink * @li no output parameters */ #define MATHS_MODEXP_L512 0x150c2327 /**< Functionality ID for Modular exponentiation for numbers less than 512-bits * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l512_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l512_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l512_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l512_output_s::r r @endlink */ #define MATHS_MODEXP_L1024 0x2d0c233e /**< Functionality ID for Modular exponentiation for numbers less than 1024-bit * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l1024_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l1024_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l1024_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l1024_output_s::r r @endlink */ #define MATHS_MODEXP_L1536 0x410c2355 /**< Functionality ID for Modular exponentiation for numbers less than 1536-bits * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l1536_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l1536_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l1536_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l1536_output_s::r r @endlink */ #define MATHS_MODEXP_L2048 0x5e12236c /**< Functionality ID for Modular exponentiation for numbers less than 2048-bit * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l2048_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l2048_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l2048_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l2048_output_s::r r @endlink */ #define MATHS_MODEXP_L2560 0x60162388 /**< Functionality ID for Modular exponentiation for numbers less than 2560-bits * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l2560_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l2560_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l2560_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l2560_output_s::r r @endlink */ #define MATHS_MODEXP_L3072 0x650c23a9 /**< Functionality ID for Modular exponentiation for numbers less than 3072-bits * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l3072_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l3072_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l3072_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l3072_output_s::r r @endlink */ #define MATHS_MODEXP_L3584 0x801623c0 /**< Functionality ID for Modular exponentiation for numbers less than 3584-bits * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l3584_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l3584_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l3584_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l3584_output_s::r r @endlink */ #define MATHS_MODEXP_L4096 0x850c23e1 /**< Functionality ID for Modular exponentiation for numbers less than 4096-bit * @li 3 input parameters : * @link icp_qat_fw_maths_modexp_l4096_input_s::g g @endlink * @link icp_qat_fw_maths_modexp_l4096_input_s::e e @endlink * @link icp_qat_fw_maths_modexp_l4096_input_s::m m @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modexp_l4096_output_s::r r @endlink */ #define MATHS_MODEXP_L8192 0xc50c3646 /**< Functionality ID for Modular exponentiation for numbers up to 8192 bits * @li 3 input parameters : @link icp_qat_fw_maths_modexp_l8192_input_s::g g * @endlink @link icp_qat_fw_maths_modexp_l8192_input_s::e e @endlink @link * icp_qat_fw_maths_modexp_l8192_input_s::m m @endlink * @li 1 output parameters : @link icp_qat_fw_maths_modexp_l8192_output_s::r r * @endlink */ #define MATHS_MODINV_ODD_L128 0x090623f8 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 128 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l128_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l128_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l128_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L192 0x0a0623fe /**< Functionality ID for Modular multiplicative inverse for numbers less than * 192 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l192_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l192_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l192_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L256 0x0a062404 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 256 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l256_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l256_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l256_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L384 0x0b06240a /**< Functionality ID for Modular multiplicative inverse for numbers less than * 384 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l384_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l384_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l384_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L512 0x0c062410 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 512 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l512_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l512_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l512_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L768 0x0e062416 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 768 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l768_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l768_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l768_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L1024 0x1006241c /**< Functionality ID for Modular multiplicative inverse for numbers less than * 1024 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l1024_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l1024_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l1024_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L1536 0x18062422 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 1536 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l1536_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l1536_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l1536_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L2048 0x20062428 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 2048 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l2048_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l2048_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l2048_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L3072 0x3006242e /**< Functionality ID for Modular multiplicative inverse for numbers less than * 3072 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l3072_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l3072_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l3072_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L4096 0x40062434 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 4096 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_odd_l4096_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_odd_l4096_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_odd_l4096_output_s::c c @endlink */ #define MATHS_MODINV_ODD_L8192 0x88073656 /**< Functionality ID for Modular multiplicative inverse for numbers up to 8192 * bits * @li 2 input parameters : @link icp_qat_fw_maths_modinv_odd_l8192_input_s::a a * @endlink @link icp_qat_fw_maths_modinv_odd_l8192_input_s::b b @endlink * @li 1 output parameters : @link icp_qat_fw_maths_modinv_odd_l8192_output_s::c * c @endlink */ #define MATHS_MODINV_EVEN_L128 0x0906243a /**< Functionality ID for Modular multiplicative inverse for numbers less than * 128 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l128_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l128_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l128_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L192 0x0a062440 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 192 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l192_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l192_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l192_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L256 0x0a062446 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 256 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l256_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l256_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l256_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L384 0x0e0b244c /**< Functionality ID for Modular multiplicative inverse for numbers less than * 384 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l384_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l384_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l384_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L512 0x110b2457 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 512 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l512_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l512_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l512_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L768 0x170b2462 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 768 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l768_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l768_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l768_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L1024 0x1d0b246d /**< Functionality ID for Modular multiplicative inverse for numbers less than * 1024 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l1024_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l1024_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l1024_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L1536 0x290b2478 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 1536 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l1536_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l1536_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l1536_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L2048 0x350b2483 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 2048 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l2048_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l2048_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l2048_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L3072 0x4d0b248e /**< Functionality ID for Modular multiplicative inverse for numbers less than * 3072 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l3072_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l3072_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l3072_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L4096 0x650b2499 /**< Functionality ID for Modular multiplicative inverse for numbers less than * 4096 bits * @li 2 input parameters : * @link icp_qat_fw_maths_modinv_even_l4096_input_s::a a @endlink * @link icp_qat_fw_maths_modinv_even_l4096_input_s::b b @endlink * @li 1 output parameters : * @link icp_qat_fw_maths_modinv_even_l4096_output_s::c c @endlink */ #define MATHS_MODINV_EVEN_L8192 0xc80d3666 /**< Functionality ID for Modular multiplicative inverse for numbers up to 8192 * bits * @li 2 input parameters : @link icp_qat_fw_maths_modinv_even_l8192_input_s::a * a @endlink @link icp_qat_fw_maths_modinv_even_l8192_input_s::b b @endlink * @li 1 output parameters : @link * icp_qat_fw_maths_modinv_even_l8192_output_s::c c @endlink */ #define PKE_DSA_GEN_P_1024_160 0x381824a4 /**< Functionality ID for DSA parameter generation P * @li 2 input parameters : * @link icp_qat_fw_mmp_dsa_gen_p_1024_160_input_s::x x @endlink * @link icp_qat_fw_mmp_dsa_gen_p_1024_160_input_s::q q @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_p_1024_160_output_s::p p @endlink */ #define PKE_DSA_GEN_G_1024 0x261424d4 /**< Functionality ID for DSA key generation G * @li 3 input parameters : * @link icp_qat_fw_mmp_dsa_gen_g_1024_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_gen_g_1024_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_gen_g_1024_input_s::h h @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_g_1024_output_s::g g @endlink */ #define PKE_DSA_GEN_Y_1024 0x291224ed /**< Functionality ID for DSA key generation Y * @li 3 input parameters : * @link icp_qat_fw_mmp_dsa_gen_y_1024_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_gen_y_1024_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_gen_y_1024_input_s::x x @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_y_1024_output_s::y y @endlink */ #define PKE_DSA_SIGN_R_1024_160 0x2c1c2504 /**< Functionality ID for DSA Sign R * @li 4 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_1024_160_input_s::g g @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_1024_160_output_s::r r @endlink */ #define PKE_DSA_SIGN_S_160 0x12142526 /**< Functionality ID for DSA Sign S * @li 5 input parameters : * @link icp_qat_fw_mmp_dsa_sign_s_160_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_sign_s_160_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_s_160_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_s_160_input_s::r r @endlink * @link icp_qat_fw_mmp_dsa_sign_s_160_input_s::x x @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_sign_s_160_output_s::s s @endlink */ #define PKE_DSA_SIGN_R_S_1024_160 0x301e2540 /**< Functionality ID for DSA Sign R S * @li 6 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_input_s::x x @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_s::r r @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_1024_160_output_s::s s @endlink */ #define PKE_DSA_VERIFY_1024_160 0x323a2570 /**< Functionality ID for DSA Verify * @li 7 input parameters : * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::r r @endlink * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::s s @endlink * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_verify_1024_160_input_s::y y @endlink * @li no output parameters */ #define PKE_DSA_GEN_P_2048_224 0x341d25be /**< Functionality ID for DSA parameter generation P * @li 2 input parameters : * @link icp_qat_fw_mmp_dsa_gen_p_2048_224_input_s::x x @endlink * @link icp_qat_fw_mmp_dsa_gen_p_2048_224_input_s::q q @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_p_2048_224_output_s::p p @endlink */ #define PKE_DSA_GEN_Y_2048 0x4d1225ea /**< Functionality ID for DSA key generation Y * @li 3 input parameters : * @link icp_qat_fw_mmp_dsa_gen_y_2048_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_gen_y_2048_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_gen_y_2048_input_s::x x @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_y_2048_output_s::y y @endlink */ #define PKE_DSA_SIGN_R_2048_224 0x511c2601 /**< Functionality ID for DSA Sign R * @li 4 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_2048_224_input_s::g g @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_2048_224_output_s::r r @endlink */ #define PKE_DSA_SIGN_S_224 0x15142623 /**< Functionality ID for DSA Sign S * @li 5 input parameters : * @link icp_qat_fw_mmp_dsa_sign_s_224_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_sign_s_224_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_s_224_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_s_224_input_s::r r @endlink * @link icp_qat_fw_mmp_dsa_sign_s_224_input_s::x x @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_sign_s_224_output_s::s s @endlink */ #define PKE_DSA_SIGN_R_S_2048_224 0x571e263d /**< Functionality ID for DSA Sign R S * @li 6 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_input_s::x x @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_s::r r @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_224_output_s::s s @endlink */ #define PKE_DSA_VERIFY_2048_224 0x6930266d /**< Functionality ID for DSA Verify * @li 7 input parameters : * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::r r @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::s s @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_224_input_s::y y @endlink * @li no output parameters */ #define PKE_DSA_GEN_P_2048_256 0x431126b7 /**< Functionality ID for DSA parameter generation P * @li 2 input parameters : * @link icp_qat_fw_mmp_dsa_gen_p_2048_256_input_s::x x @endlink * @link icp_qat_fw_mmp_dsa_gen_p_2048_256_input_s::q q @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_p_2048_256_output_s::p p @endlink */ #define PKE_DSA_GEN_G_2048 0x4b1426ed /**< Functionality ID for DSA key generation G * @li 3 input parameters : * @link icp_qat_fw_mmp_dsa_gen_g_2048_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_gen_g_2048_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_gen_g_2048_input_s::h h @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_g_2048_output_s::g g @endlink */ #define PKE_DSA_SIGN_R_2048_256 0x5b182706 /**< Functionality ID for DSA Sign R * @li 4 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_2048_256_input_s::g g @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_2048_256_output_s::r r @endlink */ #define PKE_DSA_SIGN_S_256 0x15142733 /**< Functionality ID for DSA Sign S * @li 5 input parameters : * @link icp_qat_fw_mmp_dsa_sign_s_256_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_sign_s_256_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_s_256_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_s_256_input_s::r r @endlink * @link icp_qat_fw_mmp_dsa_sign_s_256_input_s::x x @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_sign_s_256_output_s::s s @endlink */ #define PKE_DSA_SIGN_R_S_2048_256 0x5a2a274d /**< Functionality ID for DSA Sign R S * @li 6 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_input_s::x x @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_s::r r @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_2048_256_output_s::s s @endlink */ #define PKE_DSA_VERIFY_2048_256 0x723a2789 /**< Functionality ID for DSA Verify * @li 7 input parameters : * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::r r @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::s s @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_verify_2048_256_input_s::y y @endlink * @li no output parameters */ #define PKE_DSA_GEN_P_3072_256 0x4b1127e0 /**< Functionality ID for DSA parameter generation P * @li 2 input parameters : * @link icp_qat_fw_mmp_dsa_gen_p_3072_256_input_s::x x @endlink * @link icp_qat_fw_mmp_dsa_gen_p_3072_256_input_s::q q @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_p_3072_256_output_s::p p @endlink */ #define PKE_DSA_GEN_G_3072 0x4f142816 /**< Functionality ID for DSA key generation G * @li 3 input parameters : * @link icp_qat_fw_mmp_dsa_gen_g_3072_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_gen_g_3072_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_gen_g_3072_input_s::h h @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_g_3072_output_s::g g @endlink */ #define PKE_DSA_GEN_Y_3072 0x5112282f /**< Functionality ID for DSA key generation Y * @li 3 input parameters : * @link icp_qat_fw_mmp_dsa_gen_y_3072_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_gen_y_3072_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_gen_y_3072_input_s::x x @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_gen_y_3072_output_s::y y @endlink */ #define PKE_DSA_SIGN_R_3072_256 0x59282846 /**< Functionality ID for DSA Sign R * @li 4 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_3072_256_input_s::g g @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_3072_256_output_s::r r @endlink */ #define PKE_DSA_SIGN_R_S_3072_256 0x61292874 /**< Functionality ID for DSA Sign R S * @li 6 input parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::k k @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_input_s::x x @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_s::r r @endlink * @link icp_qat_fw_mmp_dsa_sign_r_s_3072_256_output_s::s s @endlink */ #define PKE_DSA_VERIFY_3072_256 0x7f4328ae /**< Functionality ID for DSA Verify * @li 7 input parameters : * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::r r @endlink * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::s s @endlink * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::m m @endlink * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::p p @endlink * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::q q @endlink * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::g g @endlink * @link icp_qat_fw_mmp_dsa_verify_3072_256_input_s::y y @endlink * @li no output parameters */ #define PKE_ECDSA_SIGN_RS_GF2_L256 0x46512907 /**< Functionality ID for ECDSA Sign RS for curves B/K-163 and B/K-233 * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_input_s::in in @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l256_output_s::s s @endlink */ #define PKE_ECDSA_SIGN_R_GF2_L256 0x323a298f /**< Functionality ID for ECDSA Sign R for curves B/K-163 and B/K-233 * @li 7 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::xg xg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::yg yg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::n n @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::q q @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::a a @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::b b @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l256_output_s::r r @endlink */ #define PKE_ECDSA_SIGN_S_GF2_L256 0x2b2229e6 /**< Functionality ID for ECDSA Sign S for curves with n < 2^256 * @li 5 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::e e @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::d d @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::k k @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l256_output_s::s s @endlink */ #define PKE_ECDSA_VERIFY_GF2_L256 0x337e2a27 /**< Functionality ID for ECDSA Verify for curves B/K-163 and B/K-233 * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_verify_gf2_l256_input_s::in in @endlink * @li no output parameters */ #define PKE_ECDSA_SIGN_RS_GF2_L512 0x5e5f2ad7 /**< Functionality ID for ECDSA Sign RS * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_input_s::in in @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_l512_output_s::s s @endlink */ #define PKE_ECDSA_SIGN_R_GF2_L512 0x84312b6a /**< Functionality ID for ECDSA GF2 Sign R * @li 7 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::xg xg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::yg yg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::n n @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::q q @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::a a @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::b b @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_l512_output_s::r r @endlink */ #define PKE_ECDSA_SIGN_S_GF2_L512 0x26182bbe /**< Functionality ID for ECDSA GF2 Sign S * @li 5 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::e e @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::d d @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::k k @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_l512_output_s::s s @endlink */ #define PKE_ECDSA_VERIFY_GF2_L512 0x58892bea /**< Functionality ID for ECDSA GF2 Verify * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_verify_gf2_l512_input_s::in in @endlink * @li no output parameters */ #define PKE_ECDSA_SIGN_RS_GF2_571 0x554a2c93 /**< Functionality ID for ECDSA GF2 Sign RS for curves B-571/K-571 * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_input_s::in in @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_rs_gf2_571_output_s::s s @endlink */ #define PKE_ECDSA_SIGN_S_GF2_571 0x52332d09 /**< Functionality ID for ECDSA GF2 Sign S for curves with deg(q) < 576 * @li 5 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::e e @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::d d @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::k k @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gf2_571_output_s::s s @endlink */ #define PKE_ECDSA_SIGN_R_GF2_571 0x731a2d51 /**< Functionality ID for ECDSA GF2 Sign R for degree 571 * @li 7 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::xg xg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::yg yg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::n n @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::q q @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::a a @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::b b @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gf2_571_output_s::r r @endlink */ #define PKE_ECDSA_VERIFY_GF2_571 0x4f6c2d91 /**< Functionality ID for ECDSA GF2 Verify for degree 571 * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_verify_gf2_571_input_s::in in @endlink * @li no output parameters */ #define MATHS_POINT_MULTIPLICATION_GF2_L256 0x3b242e38 /**< Functionality ID for MATHS GF2 Point Multiplication * @li 7 input parameters : * @link icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::k k * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::xg xg * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::yg yg * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::a a * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::b b * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::q q * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l256_input_s::h h * @endlink * @li 2 output parameters : * @link icp_qat_fw_maths_point_multiplication_gf2_l256_output_s::xk xk * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l256_output_s::yk yk * @endlink */ #define MATHS_POINT_VERIFY_GF2_L256 0x231a2e7c /**< Functionality ID for MATHS GF2 Point Verification * @li 5 input parameters : * @link icp_qat_fw_maths_point_verify_gf2_l256_input_s::xq xq @endlink * @link icp_qat_fw_maths_point_verify_gf2_l256_input_s::yq yq @endlink * @link icp_qat_fw_maths_point_verify_gf2_l256_input_s::q q @endlink * @link icp_qat_fw_maths_point_verify_gf2_l256_input_s::a a @endlink * @link icp_qat_fw_maths_point_verify_gf2_l256_input_s::b b @endlink * @li no output parameters */ #define MATHS_POINT_MULTIPLICATION_GF2_L512 0x722c2e96 /**< Functionality ID for MATHS GF2 Point Multiplication * @li 7 input parameters : * @link icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::k k * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::xg xg * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::yg yg * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::a a * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::b b * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::q q * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l512_input_s::h h * @endlink * @li 2 output parameters : * @link icp_qat_fw_maths_point_multiplication_gf2_l512_output_s::xk xk * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_l512_output_s::yk yk * @endlink */ #define MATHS_POINT_VERIFY_GF2_L512 0x25132ee2 /**< Functionality ID for MATHS GF2 Point Verification * @li 5 input parameters : * @link icp_qat_fw_maths_point_verify_gf2_l512_input_s::xq xq @endlink * @link icp_qat_fw_maths_point_verify_gf2_l512_input_s::yq yq @endlink * @link icp_qat_fw_maths_point_verify_gf2_l512_input_s::q q @endlink * @link icp_qat_fw_maths_point_verify_gf2_l512_input_s::a a @endlink * @link icp_qat_fw_maths_point_verify_gf2_l512_input_s::b b @endlink * @li no output parameters */ #define MATHS_POINT_MULTIPLICATION_GF2_571 0x44152ef5 /**< Functionality ID for ECC GF2 Point Multiplication for curves B-571/K-571 * @li 7 input parameters : * @link icp_qat_fw_maths_point_multiplication_gf2_571_input_s::k k @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_571_input_s::xg xg * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_571_input_s::yg yg * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_571_input_s::a a @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_571_input_s::b b @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_571_input_s::q q @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_571_input_s::h h @endlink * @li 2 output parameters : * @link icp_qat_fw_maths_point_multiplication_gf2_571_output_s::xk xk * @endlink * @link icp_qat_fw_maths_point_multiplication_gf2_571_output_s::yk yk * @endlink */ #define MATHS_POINT_VERIFY_GF2_571 0x12072f1b /**< Functionality ID for ECC GF2 Point Verification for degree 571 * @li 5 input parameters : * @link icp_qat_fw_maths_point_verify_gf2_571_input_s::xq xq @endlink * @link icp_qat_fw_maths_point_verify_gf2_571_input_s::yq yq @endlink * @link icp_qat_fw_maths_point_verify_gf2_571_input_s::q q @endlink * @link icp_qat_fw_maths_point_verify_gf2_571_input_s::a a @endlink * @link icp_qat_fw_maths_point_verify_gf2_571_input_s::b b @endlink * @li no output parameters */ #define PKE_ECDSA_SIGN_R_GFP_L256 0x431b2f22 /**< Functionality ID for ECDSA GFP Sign R * @li 7 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::xg xg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::yg yg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::n n @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::q q @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::a a @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::b b @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l256_output_s::r r @endlink */ #define PKE_ECDSA_SIGN_S_GFP_L256 0x2b252f6d /**< Functionality ID for ECDSA GFP Sign S * @li 5 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::e e @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::d d @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::k k @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l256_output_s::s s @endlink */ #define PKE_ECDSA_SIGN_RS_GFP_L256 0x6a3c2fa6 /**< Functionality ID for ECDSA GFP Sign RS * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_input_s::in in @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l256_output_s::s s @endlink */ #define PKE_ECDSA_VERIFY_GFP_L256 0x325b3023 /**< Functionality ID for ECDSA GFP Verify * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_verify_gfp_l256_input_s::in in @endlink * @li no output parameters */ #define PKE_ECDSA_SIGN_R_GFP_L512 0x4e2530b3 /**< Functionality ID for ECDSA GFP Sign R * @li 7 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::xg xg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::yg yg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::n n @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::q q @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::a a @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::b b @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_l512_output_s::r r @endlink */ #define PKE_ECDSA_SIGN_S_GFP_L512 0x251830fa /**< Functionality ID for ECDSA GFP Sign S * @li 5 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::e e @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::d d @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::k k @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_l512_output_s::s s @endlink */ #define PKE_ECDSA_SIGN_RS_GFP_L512 0x5a2b3127 /**< Functionality ID for ECDSA GFP Sign RS * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_input_s::in in @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_l512_output_s::s s @endlink */ #define PKE_ECDSA_VERIFY_GFP_L512 0x3553318a /**< Functionality ID for ECDSA GFP Verify * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_verify_gfp_l512_input_s::in in @endlink * @li no output parameters */ #define PKE_ECDSA_SIGN_R_GFP_521 0x772c31fe /**< Functionality ID for ECDSA GFP Sign R * @li 7 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::xg xg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::yg yg @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::n n @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::q q @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::a a @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::b b @endlink * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_r_gfp_521_output_s::r r @endlink */ #define PKE_ECDSA_SIGN_S_GFP_521 0x52343251 /**< Functionality ID for ECDSA GFP Sign S * @li 5 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::e e @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::d d @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::k k @endlink * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_input_s::n n @endlink * @li 1 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_s_gfp_521_output_s::s s @endlink */ #define PKE_ECDSA_SIGN_RS_GFP_521 0x494a329b /**< Functionality ID for ECDSA GFP Sign RS * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_input_s::in in @endlink * @li 2 output parameters : * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_s::r r @endlink * @link icp_qat_fw_mmp_ecdsa_sign_rs_gfp_521_output_s::s s @endlink */ #define PKE_ECDSA_VERIFY_GFP_521 0x554c331f /**< Functionality ID for ECDSA GFP Verify * @li 1 input parameters : * @link icp_qat_fw_mmp_ecdsa_verify_gfp_521_input_s::in in @endlink * @li no output parameters */ #define MATHS_POINT_MULTIPLICATION_GFP_L256 0x432033a6 /**< Functionality ID for ECC GFP Point Multiplication * @li 7 input parameters : * @link icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::k k * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::xg xg * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::yg yg * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::a a * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::b b * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::q q * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l256_input_s::h h * @endlink * @li 2 output parameters : * @link icp_qat_fw_maths_point_multiplication_gfp_l256_output_s::xk xk * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l256_output_s::yk yk * @endlink */ #define MATHS_POINT_VERIFY_GFP_L256 0x1f0c33fc /**< Functionality ID for ECC GFP Partial Point Verification * @li 5 input parameters : * @link icp_qat_fw_maths_point_verify_gfp_l256_input_s::xq xq @endlink * @link icp_qat_fw_maths_point_verify_gfp_l256_input_s::yq yq @endlink * @link icp_qat_fw_maths_point_verify_gfp_l256_input_s::q q @endlink * @link icp_qat_fw_maths_point_verify_gfp_l256_input_s::a a @endlink * @link icp_qat_fw_maths_point_verify_gfp_l256_input_s::b b @endlink * @li no output parameters */ #define MATHS_POINT_MULTIPLICATION_GFP_L512 0x41253419 /**< Functionality ID for ECC GFP Point Multiplication * @li 7 input parameters : * @link icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::k k * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::xg xg * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::yg yg * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::a a * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::b b * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::q q * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l512_input_s::h h * @endlink * @li 2 output parameters : * @link icp_qat_fw_maths_point_multiplication_gfp_l512_output_s::xk xk * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_l512_output_s::yk yk * @endlink */ #define MATHS_POINT_VERIFY_GFP_L512 0x2612345c /**< Functionality ID for ECC GFP Partial Point * @li 5 input parameters : * @link icp_qat_fw_maths_point_verify_gfp_l512_input_s::xq xq @endlink * @link icp_qat_fw_maths_point_verify_gfp_l512_input_s::yq yq @endlink * @link icp_qat_fw_maths_point_verify_gfp_l512_input_s::q q @endlink * @link icp_qat_fw_maths_point_verify_gfp_l512_input_s::a a @endlink * @link icp_qat_fw_maths_point_verify_gfp_l512_input_s::b b @endlink * @li no output parameters */ #define MATHS_POINT_MULTIPLICATION_GFP_521 0x5511346e /**< Functionality ID for ECC GFP Point Multiplication * @li 7 input parameters : * @link icp_qat_fw_maths_point_multiplication_gfp_521_input_s::k k @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_521_input_s::xg xg * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_521_input_s::yg yg * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_521_input_s::a a @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_521_input_s::b b @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_521_input_s::q q @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_521_input_s::h h @endlink * @li 2 output parameters : * @link icp_qat_fw_maths_point_multiplication_gfp_521_output_s::xk xk * @endlink * @link icp_qat_fw_maths_point_multiplication_gfp_521_output_s::yk yk * @endlink */ #define MATHS_POINT_VERIFY_GFP_521 0x0e0734be /**< Functionality ID for ECC GFP Partial Point Verification * @li 5 input parameters : * @link icp_qat_fw_maths_point_verify_gfp_521_input_s::xq xq @endlink * @link icp_qat_fw_maths_point_verify_gfp_521_input_s::yq yq @endlink * @link icp_qat_fw_maths_point_verify_gfp_521_input_s::q q @endlink * @link icp_qat_fw_maths_point_verify_gfp_521_input_s::a a @endlink * @link icp_qat_fw_maths_point_verify_gfp_521_input_s::b b @endlink * @li no output parameters */ #define POINT_MULTIPLICATION_C25519 0x0a0634c6 /**< Functionality ID for ECC curve25519 Variable Point Multiplication [k]P(x), * as specified in RFC7748 * @li 2 input parameters : * @link icp_qat_fw_point_multiplication_c25519_input_s::xp xp @endlink * @link icp_qat_fw_point_multiplication_c25519_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_point_multiplication_c25519_output_s::xr xr @endlink */ #define GENERATOR_MULTIPLICATION_C25519 0x0a0634d6 /**< Functionality ID for ECC curve25519 Generator Point Multiplication [k]G(x), * as specified in RFC7748 * @li 1 input parameters : * @link icp_qat_fw_generator_multiplication_c25519_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_generator_multiplication_c25519_output_s::xr xr @endlink */ #define POINT_MULTIPLICATION_ED25519 0x100b34e6 /**< Functionality ID for ECC edwards25519 Variable Point Multiplication [k]P, * as specified in RFC8032 * @li 3 input parameters : * @link icp_qat_fw_point_multiplication_ed25519_input_s::xp xp @endlink * @link icp_qat_fw_point_multiplication_ed25519_input_s::yp yp @endlink * @link icp_qat_fw_point_multiplication_ed25519_input_s::k k @endlink * @li 2 output parameters : * @link icp_qat_fw_point_multiplication_ed25519_output_s::xr xr @endlink * @link icp_qat_fw_point_multiplication_ed25519_output_s::yr yr @endlink */ #define GENERATOR_MULTIPLICATION_ED25519 0x100a34f6 /**< Functionality ID for ECC edwards25519 Generator Point Multiplication [k]G, * as specified in RFC8032 * @li 1 input parameters : * @link icp_qat_fw_generator_multiplication_ed25519_input_s::k k @endlink * @li 2 output parameters : * @link icp_qat_fw_generator_multiplication_ed25519_output_s::xr xr * @endlink * @link icp_qat_fw_generator_multiplication_ed25519_output_s::yr yr * @endlink */ #define POINT_MULTIPLICATION_C448 0x0c063506 /**< Functionality ID for ECC curve448 Variable Point Multiplication [k]P(x), as * specified in RFC7748 * @li 2 input parameters : * @link icp_qat_fw_point_multiplication_c448_input_s::xp xp @endlink * @link icp_qat_fw_point_multiplication_c448_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_point_multiplication_c448_output_s::xr xr @endlink */ #define GENERATOR_MULTIPLICATION_C448 0x0c063516 /**< Functionality ID for ECC curve448 Generator Point Multiplication [k]G(x), * as specified in RFC7748 * @li 1 input parameters : * @link icp_qat_fw_generator_multiplication_c448_input_s::k k @endlink * @li 1 output parameters : * @link icp_qat_fw_generator_multiplication_c448_output_s::xr xr @endlink */ #define POINT_MULTIPLICATION_ED448 0x1a0b3526 /**< Functionality ID for ECC edwards448 Variable Point Multiplication [k]P, as * specified in RFC8032 * @li 3 input parameters : * @link icp_qat_fw_point_multiplication_ed448_input_s::xp xp @endlink * @link icp_qat_fw_point_multiplication_ed448_input_s::yp yp @endlink * @link icp_qat_fw_point_multiplication_ed448_input_s::k k @endlink * @li 2 output parameters : * @link icp_qat_fw_point_multiplication_ed448_output_s::xr xr @endlink * @link icp_qat_fw_point_multiplication_ed448_output_s::yr yr @endlink */ #define GENERATOR_MULTIPLICATION_ED448 0x1a0a3536 /**< Functionality ID for ECC edwards448 Generator Point Multiplication [k]P, as * specified in RFC8032 * @li 1 input parameters : * @link icp_qat_fw_generator_multiplication_ed448_input_s::k k @endlink * @li 2 output parameters : * @link icp_qat_fw_generator_multiplication_ed448_output_s::xr xr @endlink * @link icp_qat_fw_generator_multiplication_ed448_output_s::yr yr @endlink */ #define PKE_EC_POINT_MULTIPLICATION_P256 0x0a083546 /**< Functionality ID for ECC P256 Variable Point Multiplication [k]P(x) * @li 3 input parameters : @link * icp_qat_fw_mmp_ec_p256_point_multiplication_input_s::xp xp @endlink @link * icp_qat_fw_mmp_ec_p256_point_multiplication_input_s::yp yp @endlink @link * icp_qat_fw_mmp_ec_p256_point_multiplication_input_s::k k @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ec_p256_point_multiplication_output_s::xr xr @endlink @link * icp_qat_fw_mmp_ec_p256_point_multiplication_output_s::yr yr @endlink */ #define PKE_EC_POINT_MULTIPLICATION_P256 0x0a083546 /**< Functionality ID for ECC P256 Variable Point Multiplication [k]P(x) * @li 3 input parameters : @link * icp_qat_fw_mmp_ec_p256_point_multiplication_input_s::xp xp @endlink @link * icp_qat_fw_mmp_ec_p256_point_multiplication_input_s::yp yp @endlink @link * icp_qat_fw_mmp_ec_p256_point_multiplication_input_s::k k @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ec_p256_point_multiplication_output_s::xr xr @endlink @link * icp_qat_fw_mmp_ec_p256_point_multiplication_output_s::yr yr @endlink */ #define PKE_EC_GENERATOR_MULTIPLICATION_P256 0x12073556 /**< Functionality ID for ECC P256 Generator Point Multiplication [k]G(x) * @li 1 input parameters : @link * icp_qat_fw_mmp_ec_p256_generator_multiplication_input_s::k k @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ec_p256_generator_multiplication_output_s::xr xr @endlink * @link icp_qat_fw_mmp_ec_p256_generator_multiplication_output_s::yr yr * @endlink */ #define PKE_ECDSA_SIGN_RS_P256 0x18133566 /**< Functionality ID for ECC P256 ECDSA Sign RS * @li 3 input parameters : @link * icp_qat_fw_mmp_ecdsa_sign_rs_p256_input_s::k k @endlink @link * icp_qat_fw_mmp_ecdsa_sign_rs_p256_input_s::e e @endlink @link * icp_qat_fw_mmp_ecdsa_sign_rs_p256_input_s::d d @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ecdsa_sign_rs_p256_output_s::r r @endlink @link * icp_qat_fw_mmp_ecdsa_sign_rs_p256_output_s::s s @endlink */ #define PKE_EC_POINT_MULTIPLICATION_P384 0x0b083586 /**< Functionality ID for ECC P384 Variable Point Multiplication [k]P(x) * @li 3 input parameters : @link * icp_qat_fw_mmp_ec_p384_point_multiplication_input_s::xp xp @endlink @link * icp_qat_fw_mmp_ec_p384_point_multiplication_input_s::yp yp @endlink @link * icp_qat_fw_mmp_ec_p384_point_multiplication_input_s::k k @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ec_p384_point_multiplication_output_s::xr xr @endlink @link * icp_qat_fw_mmp_ec_p384_point_multiplication_output_s::yr yr @endlink */ #define PKE_EC_GENERATOR_MULTIPLICATION_P384 0x0b073596 /**< Functionality ID for ECC P384 Generator Point Multiplication [k]G(x) * @li 1 input parameters : @link * icp_qat_fw_mmp_ec_p384_generator_multiplication_input_s::k k @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ec_p384_generator_multiplication_output_s::xr xr @endlink * @link icp_qat_fw_mmp_ec_p384_generator_multiplication_output_s::yr yr * @endlink */ #define PKE_ECDSA_SIGN_RS_P384 0x1a1335a6 /**< Functionality ID for ECC P384 ECDSA Sign RS * @li 3 input parameters : @link * icp_qat_fw_mmp_ecdsa_sign_rs_p384_input_s::k k @endlink @link * icp_qat_fw_mmp_ecdsa_sign_rs_p384_input_s::e e @endlink @link * icp_qat_fw_mmp_ecdsa_sign_rs_p384_input_s::d d @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ecdsa_sign_rs_p384_output_s::r r @endlink @link * icp_qat_fw_mmp_ecdsa_sign_rs_p384_output_s::s s @endlink */ #define PKE_ECSM2_GENERATOR_MULTIPLICATION 0x220f16ae /**< Functionality ID for ECC SM2 point multiply [k]G * @li 1 input parameters : @link * icp_qat_fw_mmp_ecsm2_generator_multiplication_input_s::k k @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ecsm2_generator_multiplication_output_s::xd xd @endlink @link * icp_qat_fw_mmp_ecsm2_generator_multiplication_output_s::yd yd @endlink */ #define PKE_ECSM2_POINT_MULTIPLICATION 0x211716ce /**< Functionality ID for ECC SM2 point multiply [k]P * @li 3 input parameters : @link * icp_qat_fw_mmp_ecsm2_point_multiplication_input_s::k k @endlink @link * icp_qat_fw_mmp_ecsm2_point_multiplication_input_s::x x @endlink @link * icp_qat_fw_mmp_ecsm2_point_multiplication_input_s::y y @endlink * @li 2 output parameters : @link * icp_qat_fw_mmp_ecsm2_point_multiplication_output_s::xd xd @endlink @link * icp_qat_fw_mmp_ecsm2_point_multiplication_output_s::yd yd @endlink */ #define PKE_ECSM2_POINT_VERIFY 0x1b0716a6 /**< Functionality ID for ECC SM2 point verify * @li 2 input parameters : @link icp_qat_fw_mmp_ecsm2_point_verify_input_s::x x * @endlink @link icp_qat_fw_mmp_ecsm2_point_verify_input_s::y y @endlink * @li no output parameters */ #define PKE_ECSM2_SIGN_RS 0x222116fe /**< Functionality ID for ECC SM2 Sign RS * @li 3 input parameters : @link icp_qat_fw_mmp_ecsm2_sign_rs_input_s::k k * @endlink @link icp_qat_fw_mmp_ecsm2_sign_rs_input_s::e e @endlink @link * icp_qat_fw_mmp_ecsm2_sign_rs_input_s::d d @endlink * @li 2 output parameters : @link icp_qat_fw_mmp_ecsm2_sign_rs_output_s::r r * @endlink @link icp_qat_fw_mmp_ecsm2_sign_rs_output_s::s s @endlink */ #define PKE_ECSM2_VERIFY 0x29241743 /**< Functionality ID for ECC SM2 Signature Verify * @li 5 input parameters : @link icp_qat_fw_mmp_ecsm2_verify_input_s::e e * @endlink @link icp_qat_fw_mmp_ecsm2_verify_input_s::r r @endlink @link * icp_qat_fw_mmp_ecsm2_verify_input_s::s s @endlink @link * icp_qat_fw_mmp_ecsm2_verify_input_s::xp xp @endlink @link * icp_qat_fw_mmp_ecsm2_verify_input_s::yp yp @endlink * @li no output parameters */ #define PKE_ECSM2_ENCRYPTION 0x25221720 /**< Functionality ID for ECC SM2 encryption * @li 3 input parameters : @link icp_qat_fw_mmp_ecsm2_encryption_input_s::k k * @endlink @link icp_qat_fw_mmp_ecsm2_encryption_input_s::xp xp @endlink @link * icp_qat_fw_mmp_ecsm2_encryption_input_s::yp yp @endlink * @li 4 output parameters : @link icp_qat_fw_mmp_ecsm2_encryption_output_s::xc * xc @endlink @link icp_qat_fw_mmp_ecsm2_encryption_output_s::yc yc @endlink * @link icp_qat_fw_mmp_ecsm2_encryption_output_s::xpb xpb @endlink @link * icp_qat_fw_mmp_ecsm2_encryption_output_s::ypb ypb @endlink */ #define PKE_ECSM2_DECRYPTION 0x201716e6 /**< Functionality ID for ECC SM2 decryption * @li 3 input parameters : @link icp_qat_fw_mmp_ecsm2_decryption_input_s::d d * @endlink @link icp_qat_fw_mmp_ecsm2_decryption_input_s::xpb xpb @endlink * @link icp_qat_fw_mmp_ecsm2_decryption_input_s::ypb ypb @endlink * @li 2 output parameters : @link icp_qat_fw_mmp_ecsm2_decryption_output_s::xd * xd @endlink @link icp_qat_fw_mmp_ecsm2_decryption_output_s::yd yd @endlink */ #define PKE_ECSM2_KEYEX_P1 0x220f16be /**< Functionality ID for ECC SM2 key exchange phase1 * @li 1 input parameters : @link icp_qat_fw_mmp_ecsm2_keyex_p1_input_s::k k * @endlink * @li 2 output parameters : @link icp_qat_fw_mmp_ecsm2_keyex_p1_output_s::xd xd * @endlink @link icp_qat_fw_mmp_ecsm2_keyex_p1_output_s::yd yd @endlink */ #define PKE_ECSM2_KEYEX_P2 0x22361768 /**< Functionality ID for ECC SM2 key exchange phase2 * @li 7 input parameters : @link icp_qat_fw_mmp_ecsm2_keyex_p2_input_s::r r * @endlink @link icp_qat_fw_mmp_ecsm2_keyex_p2_input_s::d d @endlink @link * icp_qat_fw_mmp_ecsm2_keyex_p2_input_s::x1 x1 @endlink @link * icp_qat_fw_mmp_ecsm2_keyex_p2_input_s::x2 x2 @endlink @link * icp_qat_fw_mmp_ecsm2_keyex_p2_input_s::y2 y2 @endlink @link * icp_qat_fw_mmp_ecsm2_keyex_p2_input_s::xp xp @endlink @link * icp_qat_fw_mmp_ecsm2_keyex_p2_input_s::yp yp @endlink * @li 2 output parameters : @link icp_qat_fw_mmp_ecsm2_keyex_p2_output_s::xus * xus @endlink @link icp_qat_fw_mmp_ecsm2_keyex_p2_output_s::yus yus @endlink */ #define PKE_LIVENESS 0x00000001 /**< Functionality ID for PKE_LIVENESS * @li 0 input parameter(s) * @li 1 output parameter(s) (8 qwords) */ #define PKE_INTERFACE_SIGNATURE 0x972ded54 /**< Encoded signature of the interface specifications */ #define PKE_INVALID_FUNC_ID 0xffffffff #endif /* __ICP_QAT_FW_MMP_IDS__ */ /* --- (Automatically generated (relocation v. 1.5), do not modify manually) --- */ /* --- end of file --- */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_fw_pke.h000066400000000000000000000430231503624047500260520ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** * @file icp_qat_fw_pke.h * @defgroup icp_qat_fw_pke ICP QAT FW PKE Processing Definitions * @ingroup icp_qat_fw * $Revision: 0.1 $ * @brief * This file documents the external interfaces that the QAT FW running * on the QAT Acceleration Engine provides to clients wanting to * accelerate crypto asymmetric applications */ #ifndef _ICP_QAT_FW_PKE_ #define _ICP_QAT_FW_PKE_ /* **************************************************************************** * Include local header files **************************************************************************** */ #include "icp_qat_fw.h" /** ***************************************************************************** * * @ingroup icp_qat_fw_pke * * @brief * PKE response status field structure contained * within LW1, comprising the common error codes and * the response flags. * *****************************************************************************/ typedef struct icp_qat_fw_pke_resp_status_s { uint8_t comn_err_code; /**< 8 bit common error code */ uint8_t pke_resp_flags; /**< 8-bit PKE response flags */ } icp_qat_fw_pke_resp_status_t; /** ***************************************************************************** * @ingroup icp_qat_fw_pke * Definition of the QAT FW PKE request header pars field. * Structure differs from the DH895xxCC common base header structure, hence * redefined here. * @description * PKE request message header pars structure * *****************************************************************************/ typedef struct icp_qat_fw_req_hdr_pke_cd_pars_s { /**< LWs 2-3 */ uint64_t content_desc_addr; /**< Content descriptor pointer */ /**< LW 4 */ uint32_t content_desc_resrvd; /**< Content descriptor reserved field */ /**< LW 5 */ uint32_t func_id; /**< MMP functionality Id */ } icp_qat_fw_req_hdr_pke_cd_pars_t; /** ***************************************************************************** * @ingroup icp_qat_fw_pke * Definition of the QAT FW PKE request header mid section. * Structure differs from the DH895xxCC common base header structure, * instead following the DH89xxCC format, hence redefined here. * @description * PKE request message header middle structure * *****************************************************************************/ typedef struct icp_qat_fw_req_pke_mid_s { /**< LWs 6-11 */ uint64_t opaque_data; /**< Opaque data passed unmodified from the request to response messages by * firmware (fw) */ uint64_t src_data_addr; /**< Generic definition of the source data supplied to the QAT AE. The * common flags are used to further describe the attributes of this * field */ uint64_t dest_data_addr; /**< Generic definition of the destination data supplied to the QAT AE. The * common flags are used to further describe the attributes of this * field */ /**< Following DH89xxCC structure format - footer is excluded */ } icp_qat_fw_req_pke_mid_t; /** ***************************************************************************** * @ingroup icp_qat_fw_pke * Definition of the QAT FW PKE request header. * Structure differs from the DH895xxCC common base header structure, * instead following the DH89xxCC format, hence redefined here. * @description * PKE request message header structure * *****************************************************************************/ typedef struct icp_qat_fw_req_pke_hdr_s { /**< LW0 */ uint8_t resrvd1; /**< reserved field */ uint8_t resrvd2; /**< reserved field */ uint8_t service_type; /**< Service type */ uint8_t hdr_flags; /**< This represents a flags field for the Service Request. * The most significant bit is the 'valid' flag and the only * one used. All remaining bit positions are unused and * are therefore reserved and need to be set to 0. */ /**< LW1 */ icp_qat_fw_comn_flags_pke comn_req_flags; /**< Common Request flags must indicate flat buffer (as per DH89xxCC) * Common Request flags - PKE slice flags no longer used - slice * allocated to a threadstrand.*/ icp_qat_fw_comn_flags comn_req_flags_ext; /**< Extended Common Request flags */ icp_qat_fw_ext_serv_specif_flags extended_serv_specif_flags; /**< PKE service extension field */ /**< LWs 2-5 */ icp_qat_fw_req_hdr_pke_cd_pars_t cd_pars; /**< PKE request message header pars structure - this differs * from the DH895xxCC common base structure */ } icp_qat_fw_req_pke_hdr_t; /** *************************************************************************** * * @ingroup icp_qat_fw_pke * * @brief * PKE request message structure (64 bytes) * *****************************************************************************/ typedef struct icp_qat_fw_pke_request_s { /**< LWs 0-5 */ icp_qat_fw_req_pke_hdr_t pke_hdr; /**< Request header for PKE - CD Header/Param size * must be zero */ /**< LWs 6-11 (same as DH89xxCC) */ icp_qat_fw_req_pke_mid_t pke_mid; /**< Request middle section for PKE */ /**< LW 12 */ uint8_t output_param_count; /**< Number of output large integers * for request */ uint8_t input_param_count; /**< Number of input large integers * for request */ uint16_t resrvd1; /** Reserved **/ /**< LW 13 */ uint32_t resrvd2; /**< Reserved */ /**< LWs 14-15 */ uint64_t next_req_adr; /** < PKE - next request address */ } icp_qat_fw_pke_request_t; /** ***************************************************************************** * * @ingroup icp_qat_fw_pke * * @brief * PKE response message header structure * *****************************************************************************/ typedef struct icp_qat_fw_resp_pke_hdr_s { /**< LW0 */ uint8_t resrvd1; /**< The Response Destination Id has been removed * from first QWord */ uint8_t resrvd2; /**< Response Pipe Id field is unused (reserved) * - Functionality within DH895xxCC uses arbiter instead */ uint8_t response_type; /**< Response type - copied from the request to * the response message */ uint8_t hdr_flags; /**< This represents a flags field for the Response. * The most significant bit is the 'valid' flag and the only * one used. All remaining bit positions are unused and * are therefore reserved */ /**< LW1 */ icp_qat_fw_pke_resp_status_t resp_status; uint16_t resrvd4; /**< (DH89xxCC) CD Header Size and CD Params Size fields unused. * Set to zero. */ } icp_qat_fw_resp_pke_hdr_t; /** ***************************************************************************** * * @ingroup icp_qat_fw_pke * * @brief * PKE response message structure (32 bytes) * *****************************************************************************/ typedef struct icp_qat_fw_pke_resp_s { /**< LWs 0-1 */ icp_qat_fw_resp_pke_hdr_t pke_resp_hdr; /**< Response header for PKE */ /**< LWs 2-3 */ uint64_t opaque_data; /**< Opaque data passed from the request to the response message */ /**< LWs 4-5 */ uint64_t src_data_addr; /**< Generic definition of the source data supplied to the QAT AE. The * common flags are used to further describe the attributes of this * field */ /**< LWs 6-7 */ uint64_t dest_data_addr; /**< Generic definition of the destination data supplied to the QAT AE. The * common flags are used to further describe the attributes of this * field */ } icp_qat_fw_pke_resp_t; /* ========================================================================= */ /* MACRO DEFINITIONS */ /* ========================================================================= */ /**< @ingroup icp_qat_fw_pke * Macro defining the bit position and mask of the 'valid' flag, within the * hdr_flags field of LW0 (service request and response) of the PKE request */ #define ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS 7 #define ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK 0x1 /**< @ingroup icp_qat_fw_pke * Macro defining the bit position and mask of the PKE status flag, within the * status field LW1 of a PKE response message */ #define QAT_COMN_RESP_PKE_STATUS_BITPOS 6 /**< @ingroup icp_qat_fw_pke * Starting bit position indicating the PKE status flag within the PKE response * pke_resp_flags byte. */ #define QAT_COMN_RESP_PKE_STATUS_MASK 0x1 /**< @ingroup icp_qat_fw_pke * One bit mask used to determine PKE status mask */ /* * < @ingroup icp_qat_fw_pke * *** PKE Response Status Field Definition *** * The PKE response follows the CPM 1.5 message format. The status field is 16 * bits wide, where the status flags are contained within the most significant * byte of the icp_qat_fw_pke_resp_status_t structure. The lower 8 bits of this * word now contain the common error codes, which are defined in the common * header file(*). */ /* + ===== + ----- + ---- + ----- + ----- + ----- + ----- + ----- + ----- + ----------------------- + * | Bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | [7....0] | * + ===== + ----- + ---- + ----- + ----- + ----- + ----- + ----- + ----- + ----------------------- + * | Flags | Rsrvd | Pke | Rsrvd | Rsrvd | Rsrvd | Rsrvd | Rsrvd | Rsrvd | Common error codes(*) | * + ===== + ----- + ---- + ----- + ----- + ----- + ----- + ----- + ----- + ----------------------- + */ /** ****************************************************************************** * @ingroup icp_qat_fw_pke * * @description * Macro for extraction of the PKE bit from the 16-bit status field * particular to a PKE response. The status flags are contained within * the most significant byte of the word. The lower 8 bits of this status * word now contain the common error codes, which are defined in the common * header file. The appropriate macro definition to extract the PKE status * flag from the PKE response assumes that a single byte i.e. * pke_resp_flags is passed to the macro. * * @param status * Status to extract the PKE status bit * *****************************************************************************/ #define ICP_QAT_FW_PKE_RESP_PKE_STAT_GET(flags) \ QAT_FIELD_GET((flags), \ QAT_COMN_RESP_PKE_STATUS_BITPOS, \ QAT_COMN_RESP_PKE_STATUS_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_pke * * @description * Extract the valid flag from the PKE Request's header flags. Note that * this invokes the common macro which may be used by either the request * or the response. * * @param icp_qat_fw_req_pke_hdr_t Structure passed to extract the valid bit * from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_PKE_RQ_VALID_FLAG_GET(icp_qat_fw_req_pke_hdr_t) \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_GET(icp_qat_fw_req_pke_hdr_t) /** ****************************************************************************** * @ingroup icp_qat_fw_pke * * @description * Set the valid bit in the PKE Request's header flags. Note that * this invokes the common macro which may be used by either the request * or the response. * * @param icp_qat_fw_req_pke_hdr_t Structure passed to set the valid bit. * @param val Value of the valid bit flag. * *****************************************************************************/ #define ICP_QAT_FW_PKE_RQ_VALID_FLAG_SET(icp_qat_fw_req_pke_hdr_t, val) \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(icp_qat_fw_req_pke_hdr_t, val) /** ****************************************************************************** * @ingroup icp_qat_fw_pke * * @description * Extract the valid flag from the PKE Response's header flags. Note that * invokes the common macro which may be used by either the request * or the response. * * @param icp_qat_fw_resp_pke_hdr_t Structure to extract the valid bit * from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_PKE_RESP_VALID_FLAG_GET(icp_qat_fw_resp_pke_hdr_t) \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_GET(icp_qat_fw_resp_pke_hdr_t) /** ****************************************************************************** * @ingroup icp_qat_fw_pke * * @description * Set the valid bit in the PKE Response's header flags. Note that * this invokes the common macro which may be used by either the * request or the response. * * @param icp_qat_fw_resp_pke_hdr_t Structure to set the valid bit * @param val Value of the valid bit flag. * *****************************************************************************/ #define ICP_QAT_FW_PKE_RESP_VALID_FLAG_SET(icp_qat_fw_resp_pke_hdr_t, val) \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(icp_qat_fw_resp_pke_hdr_t, val) /** ****************************************************************************** * @ingroup icp_qat_fw_pke * * @description * Common macro to extract the valid flag from the header flags field * within the header structure (request or response). * * @param hdr_t Structure (request or response) to extract the * valid bit from the 'hdr_flags' field. * *****************************************************************************/ #define ICP_QAT_FW_PKE_HDR_VALID_FLAG_GET(hdr_t) \ QAT_FIELD_GET(hdr_t.hdr_flags, \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS, \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_fw_pke * * @description * Common macro to set the valid bit in the header flags field within * the header structure (request or response). * * @param hdr_t Structure (request or response) containing the header * flags field, to allow the valid bit to be set. * @param val Value of the valid bit flag. * *****************************************************************************/ #define ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(hdr_t, val) \ QAT_FIELD_SET((hdr_t.hdr_flags), \ (val), \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_BITPOS, \ ICP_QAT_FW_PKE_HDR_VALID_FLAG_MASK) #endif /* _ICP_QAT_FW_PKE_ */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_hw.h000066400000000000000000002025131503624047500252160ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** ***************************************************************************** * @file icp_qat_hw.h * @defgroup icp_qat_hw_defs ICP QAT HW definitions * @ingroup icp_qat_hw * @description * This file documents definitions for the QAT HW * *****************************************************************************/ #ifndef _ICP_QAT_HW_H_ #define _ICP_QAT_HW_H_ /* ****************************************************************************** * Include public/global header files ****************************************************************************** */ /* ========================================================================= */ /* AccelerationEngine */ /* ========================================================================= */ typedef enum { ICP_QAT_HW_AE_0 = 0, /*!< ID of AE0 */ ICP_QAT_HW_AE_1 = 1, /*!< ID of AE1 */ ICP_QAT_HW_AE_2 = 2, /*!< ID of AE2 */ ICP_QAT_HW_AE_3 = 3, /*!< ID of AE3 */ ICP_QAT_HW_AE_4 = 4, /*!< ID of AE4 */ ICP_QAT_HW_AE_5 = 5, /*!< ID of AE5 */ ICP_QAT_HW_AE_6 = 6, /*!< ID of AE6 */ ICP_QAT_HW_AE_7 = 7, /*!< ID of AE7 */ ICP_QAT_HW_AE_8 = 8, /*!< ID of AE8 */ ICP_QAT_HW_AE_9 = 9, /*!< ID of AE9 */ ICP_QAT_HW_AE_10 = 10, /*!< ID of AE10 */ ICP_QAT_HW_AE_11 = 11, /*!< ID of AE11 */ ICP_QAT_HW_AE_DELIMITER = 12 /**< Delimiter type */ } icp_qat_hw_ae_id_t; /* ========================================================================= */ /* QAT */ /* ========================================================================= */ typedef enum { ICP_QAT_HW_QAT_0 = 0, /*!< ID of QAT0 */ ICP_QAT_HW_QAT_1 = 1, /*!< ID of QAT1 */ ICP_QAT_HW_QAT_2 = 2, /*!< ID of QAT2 */ ICP_QAT_HW_QAT_3 = 3, /*!< ID of QAT3 */ ICP_QAT_HW_QAT_4 = 4, /*!< ID of QAT4 */ ICP_QAT_HW_QAT_5 = 5, /*!< ID of QAT5 */ ICP_QAT_HW_QAT_DELIMITER = 6 /**< Delimiter type */ } icp_qat_hw_qat_id_t; /* ========================================================================= */ /* AUTH SLICE */ /* ========================================================================= */ /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Supported Authentication Algorithm types * @description * Enumeration which is used to define the authenticate algorithms * *****************************************************************************/ typedef enum { ICP_QAT_HW_AUTH_ALGO_NULL = 0, /*!< Null hashing */ ICP_QAT_HW_AUTH_ALGO_SHA1 = 1, /*!< SHA1 hashing */ ICP_QAT_HW_AUTH_ALGO_MD5 = 2, /*!< MD5 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA224 = 3, /*!< SHA-224 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA256 = 4, /*!< SHA-256 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA384 = 5, /*!< SHA-384 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA512 = 6, /*!< SHA-512 hashing */ ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC = 7, /*!< AES-XCBC-MAC hashing */ ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC = 8, /*!< AES-CBC-MAC hashing */ ICP_QAT_HW_AUTH_ALGO_AES_F9 = 9, /*!< AES F9 hashing */ ICP_QAT_HW_AUTH_ALGO_GALOIS_128 = 10, /*!< Galois 128 bit hashing */ ICP_QAT_HW_AUTH_ALGO_GALOIS_64 = 11, /*!< Galois 64 hashing */ ICP_QAT_HW_AUTH_ALGO_KASUMI_F9 = 12, /*!< Kasumi F9 hashing */ ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2 = 13, /*!< UIA2/SNOW_3G F9 hashing */ ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3 = 14, /*!< 128_EIA3/ZUC_3G hashing */ ICP_QAT_HW_AUTH_ALGO_SM3 = 15, /*!< SM3 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA3_224 = 16, /*!< SHA3-224 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA3_256 = 17, /*!< SHA3-256 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA3_384 = 18, /*!< SHA3-384 hashing */ ICP_QAT_HW_AUTH_ALGO_SHA3_512 = 19, /*!< SHA3-512 hashing */ ICP_QAT_HW_AUTH_RESERVED_4 = 20, /*!< Reserved */ ICP_QAT_HW_AUTH_RESERVED_5 = 21, /*!< Reserved */ ICP_QAT_HW_AUTH_ALGO_AES_128_CMAC = 22, /*!< AES-128 CMAC */ ICP_QAT_HW_AUTH_ALGO_AES_192_CMAC = 23, /*!< AES-192 CMAC */ ICP_QAT_HW_AUTH_ALGO_AES_256_CMAC = 24, /*!< AES-256 CMAC */ ICP_QAT_HW_AUTH_ALGO_ZUC_256_MAC_32 = 25, /*!< ZUC-256 MAC-32 hashing */ ICP_QAT_HW_AUTH_ALGO_ZUC_256_MAC_64 = 26, /*!< ZUC-256 MAC-64 hashing */ ICP_QAT_HW_AUTH_ALGO_ZUC_256_MAC_128 = 27, /*!< ZUC-256 MAC-128 hashing */ ICP_QAT_HW_AUTH_ALGO_NIAX = 28, /*!< NIAx (SNOW5G, AES-256, ZUC-256) */ ICP_QAT_HW_AUTH_ALGO_POLY = 29, /*!< POLY hashing */ /* POLY hash standalone algorithm is not supported. * This enum is used only in driver and not used for hardware * configuration.Always keep ICP_QAT_HW_AUTH_ALGO_POLY before * ICP_QAT_HW_AUTH_ALGO_DELIMITER. */ ICP_QAT_HW_AUTH_ALGO_DELIMITER = 30 /**< Delimiter type */ } icp_qat_hw_auth_algo_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported Authentication modes * @description * Enumeration which is used to define the authentication slice modes. * The concept of modes is very specific to the QAT implementation. Its * main use is differentiate how the algorithms are used i.e. mode0 SHA1 * will configure the QAT Auth Slice to do plain SHA1 hashing while mode1 * configures it to do SHA1 HMAC with precomputes and mode2 sets up the * slice to do SHA1 HMAC with no precomputes (uses key directly) * * @Note * Only some algorithms are valid in some of the modes. If you dont know * what you are doing then refer back to the HW documentation * *****************************************************************************/ typedef enum { ICP_QAT_HW_AUTH_MODE0 = 0, /*!< QAT Auth Mode0 configuration */ ICP_QAT_HW_AUTH_MODE1 = 1, /*!< QAT Auth Mode1 configuration */ ICP_QAT_HW_AUTH_MODE2 = 2, /*!< QAT AuthMode2 configuration */ ICP_QAT_HW_AUTH_MODE_DELIMITER = 3 /**< Delimiter type */ } icp_qat_hw_auth_mode_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Auth configuration structure * * @description * Definition of the format of the authentication slice configuration * *****************************************************************************/ typedef struct icp_qat_hw_auth_config_s { uint32_t config; /**< Configuration used for setting up the slice */ uint32_t reserved; /**< Reserved */ } icp_qat_hw_auth_config_t; /* Private defines */ /* Note: Bit positions have been defined for little endian ordering */ /* * AUTH CONFIG WORD BITMAP * + ===== + ------ + ------ + ------- + ------ + ------ + ----- + ----- + ------ + ------ + ---- + ----- + ----- + ----- + * | Bit | 63:56 | 55:52 | 51:48 | 47:32 | 31:24 | 23:22 | 21:18 | 17 | 16 | 15 | 14:8 | 7:4 | 3:0 | * + ===== + ------ + ------ + ------- + ------ + ------ + ----- + ----- + ------ + ------ + ---- + ----- + ------+ ----- + * | Usage | Prog | Resvd | Prog | Resvd | Resvd | Algo | Rsvrd | SHA3 | SHA3 |Rsvrd | Cmp | Mode | Algo | * | |padding | Bits=0 | padding | Bits=0 | Bits=0 | SHA3 | |Padding |Padding | | | | | * | | SHA3 | | SHA3 | | | | |Override|Disable | | | | | * | |(prefix)| |(postfix)| | | | | | | | | | | * + ===== + ------ + ------ + ------- + ------ + ------ + ----- + ----- + ------ + ------ + ---- + ----- + ----- + ------+ */ /**< Flag mask & bit position */ #define QAT_AUTH_MODE_BITPOS 4 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the Auth mode */ #define QAT_AUTH_MODE_MASK 0xF /**< @ingroup icp_qat_hw_defs * Four bit mask used for determining the Auth mode */ #define QAT_AUTH_ALGO_BITPOS 0 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the Auth Algo */ #define QAT_AUTH_ALGO_MASK 0xF /**< @ingroup icp_qat_hw_defs * Four bit mask used for determining the Auth algo */ #define QAT_AUTH_CMP_BITPOS 8 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the Auth Compare */ #define QAT_AUTH_CMP_MASK 0x7F /**< @ingroup icp_qat_hw_defs * Seven bit mask used to determine the Auth Compare */ #define QAT_AUTH_SHA3_PADDING_DISABLE_BITPOS 16 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the Auth h/w * padding disable for SHA3. * Flag set to 0 => h/w is required to pad (default) * Flag set to 1 => No padding in h/w */ #define QAT_AUTH_SHA3_PADDING_DISABLE_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Single bit mask used to determine the Auth h/w * padding disable for SHA3. */ #define QAT_AUTH_SHA3_PADDING_OVERRIDE_BITPOS 17 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the Auth h/w * padding override for SHA3. * Flag set to 0 => default padding behaviour * implemented in SHA3-256 slice will take effect * (default hardware setting upon h/w reset) * Flag set to 1 => SHA3-core will not use the padding * sequence built into the SHA3 core. Instead, the * padding sequence specified in bits 48-51 and 56-63 * of the 64-bit auth config word will apply * (corresponds with EAS bits 32-43). */ #define QAT_AUTH_SHA3_PADDING_OVERRIDE_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Single bit mask used to determine the Auth h/w * padding override for SHA3. */ #define QAT_AUTH_ALGO_SHA3_BITPOS 22 /**< @ingroup icp_qat_hw_defs * Starting bit position for indicating the * SHA3 Auth Algo */ #define QAT_AUTH_ALGO_SHA3_MASK 0x3 /**< @ingroup icp_qat_hw_defs * Two bit mask used for determining the * SHA3 Auth algo */ /**< Flag mask & bit position */ #define QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_BITPOS 16 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the SHA3 * flexible programmable padding postfix. * Note that these bits are set using macro * ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER and are * defined relative to the 32-bit value that * this macro returns. In effect, therefore, this * defines starting bit position 48 within the * 64-bit auth config word. */ #define QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_MASK 0xF /**< @ingroup icp_qat_hw_defs * Four-bit mask used to determine the SHA3 * flexible programmable padding postfix */ #define QAT_AUTH_SHA3_PROG_PADDING_PREFIX_BITPOS 24 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the SHA3 * flexible programmable padding prefix * Note that these bits are set using macro * ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER and are * defined relative to the 32-bit value that * this macro returns. In effect, therefore, this * defines starting bit position 56 within the * 64-bit auth config word. */ #define QAT_AUTH_SHA3_PROG_PADDING_PREFIX_MASK 0xFF /**< @ingroup icp_qat_hw_defs * Eight-bit mask used to determine the SHA3 * flexible programmable padding prefix */ /**< Flag usage - see additional notes @description for * ICP_QAT_HW_AUTH_CONFIG_BUILD and * ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER macros. */ #define QAT_AUTH_SHA3_HW_PADDING_ENABLE 0 /**< @ingroup icp_qat_hw_defs * This setting enables h/w padding for SHA3. */ #define QAT_AUTH_SHA3_HW_PADDING_DISABLE 1 /**< @ingroup icp_qat_hw_defs * This setting disables h/w padding for SHA3. */ #define QAT_AUTH_SHA3_PADDING_DISABLE_USE_DEFAULT 0 /**< @ingroup icp_qat_hw_defs * Default value for the Auth h/w padding disable. * If set to 0 for SHA3-256, h/w padding is enabled. * Padding_Disable is undefined for all non-SHA3-256 * algos and is consequently set to the default of 0. */ #define QAT_AUTH_SHA3_PADDING_OVERRIDE_USE_DEFAULT 0 /**< @ingroup icp_qat_hw_defs * Value for the Auth h/w padding override for SHA3. * Flag set to 0 => default padding behaviour * implemented in SHA3-256 slice will take effect * (default hardware setting upon h/w reset) * For this setting of the override flag, all the * bits of the padding sequence specified * in bits 48-51 and 56-63 of the 64-bit * auth config word are set to 0 (reserved). */ #define QAT_AUTH_SHA3_PADDING_OVERRIDE_PROGRAMMABLE 1 /**< @ingroup icp_qat_hw_defs * Value for the Auth h/w padding override for SHA3. * Flag set to 1 => SHA3-core will not use the padding * sequence built into the SHA3 core. Instead, the * padding sequence specified in bits 48-51 and 56-63 * of the 64-bit auth config word will apply * (corresponds with EAS bits 32-43). */ #define QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_RESERVED 0 /**< @ingroup icp_qat_hw_defs * All the bits of the padding sequence specified in * bits 48-51 of the 64-bit auth config word are set * to 0 (reserved) if the padding override bit is set * to 0, indicating default padding. */ #define QAT_AUTH_SHA3_PROG_PADDING_PREFIX_RESERVED 0 /**< @ingroup icp_qat_hw_defs * All the bits of the padding sequence specified in * bits 56-63 of the 64-bit auth config word are set * to 0 (reserved) if the padding override bit is set * to 0, indicating default padding. */ /** ******************************************************************************* * @ingroup icp_qat_hw_defs * * @description * The derived configuration word for the auth slice is based on the inputs * of mode, algorithm type and compare length. The total size of the auth * config word in the setup block is 64 bits however the size of the value * returned by this macro is assumed to be only 32 bits (for now) and sets * the lower 32 bits of the auth config word. Unfortunately, changing the * size of the returned value to 64 bits will also require changes to the * shared RAM constants table so the macro size will remain at 32 bits. * This means that the padding sequence bits specified in bits 48-51 and * 56-63 of the 64-bit auth config word are NOT included in the * ICP_QAT_HW_AUTH_CONFIG_BUILD macro and are defined in a * separate macro, namely, ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER. * * For the digest generation case the compare length is a don't care value. * Furthermore, if the client will be doing the digest validation, the * compare_length will not be used. * The padding and padding override bits for SHA3 are set internally * by the macro. * Padding_Disable is set it to 0 for SHA3-256 algo only i.e. we want to * enable this to provide the ability to test with h/w padding enabled. * Padding_Disable has no meaning for all non-SHA3-256 algos and is * consequently set the default of 0. * Padding Override is set to 0, implying that the padding behaviour * implemented in the SHA3-256 slice will take effect (default hardware * setting upon h/w reset). * This flag has no meaning for other algos, so is also set to the default * for non-SHA3-256 algos. * * @param mode Authentication mode to use * @param algo Auth Algorithm to use * @param cmp_len The length of the digest if the QAT is to the check * ******************************************************************************/ #define ICP_QAT_HW_AUTH_CONFIG_BUILD(mode, algo, cmp_len) \ ((((mode)&QAT_AUTH_MODE_MASK) << QAT_AUTH_MODE_BITPOS) | \ (((algo)&QAT_AUTH_ALGO_MASK) << QAT_AUTH_ALGO_BITPOS) | \ (((algo >> 4) & QAT_AUTH_ALGO_SHA3_MASK) << QAT_AUTH_ALGO_SHA3_BITPOS) | \ (((QAT_AUTH_SHA3_PADDING_DISABLE_USE_DEFAULT) & \ (QAT_AUTH_SHA3_PADDING_DISABLE_MASK)) \ << QAT_AUTH_SHA3_PADDING_DISABLE_BITPOS) | \ (((QAT_AUTH_SHA3_PADDING_OVERRIDE_USE_DEFAULT) & \ (QAT_AUTH_SHA3_PADDING_OVERRIDE_MASK)) \ << QAT_AUTH_SHA3_PADDING_OVERRIDE_BITPOS) | \ (((cmp_len)&QAT_AUTH_CMP_MASK) << QAT_AUTH_CMP_BITPOS)) /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * This macro sets the upper 32 bits of the 64-bit auth config word. * The sequence bits specified in bits 48-51 and 56-63 of the 64-bit auth * config word are included in this macro, which is therefore assumed to * return a 32-bit value. * Note that the Padding Override bit is set in macro * ICP_QAT_HW_AUTH_CONFIG_BUILD. * Since the Padding Override is set to 0 regardless, for now, all the bits * of the padding sequence specified in bits 48-51 and 56-63 of the 64-bit * auth config word are set to 0 (reserved). Note that the bit positions of * the padding sequence bits are defined relative to the 32-bit value that * this macro returns. * ******************************************************************************/ #define ICP_QAT_HW_AUTH_CONFIG_BUILD_UPPER \ ((((QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_RESERVED) & \ (QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_MASK)) \ << QAT_AUTH_SHA3_PROG_PADDING_POSTFIX_BITPOS) | \ (((QAT_AUTH_SHA3_PROG_PADDING_PREFIX_RESERVED) & \ (QAT_AUTH_SHA3_PROG_PADDING_PREFIX_MASK)) \ << QAT_AUTH_SHA3_PROG_PADDING_PREFIX_BITPOS)) /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Auth Counter structure * * @description * 32 bit counter that tracks the number of data bytes passed through * the slice. This is used by the padding logic for some algorithms. Note * only the upper 32 bits are set. * *****************************************************************************/ typedef struct icp_qat_hw_auth_counter_s { uint32_t counter; /**< Counter value */ uint32_t reserved; /**< Reserved */ } icp_qat_hw_auth_counter_t; /* Private defines */ #define QAT_AUTH_COUNT_MASK 0xFFFFFFFF /**< @ingroup icp_qat_hw_defs * Thirty two bit mask used for determining the Auth count */ #define QAT_AUTH_COUNT_BITPOS 0 /**< @ingroup icp_qat_hw_defs * Starting bit position indicating the Auth count. */ /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Macro to build the auth counter quad word * * @param val Counter value to set * *****************************************************************************/ #define ICP_QAT_HW_AUTH_COUNT_BUILD(val) \ (((val)&QAT_AUTH_COUNT_MASK) << QAT_AUTH_COUNT_BITPOS) /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the common auth parameters * @description * This part of the configuration is constant for each service * *****************************************************************************/ typedef struct icp_qat_hw_auth_setup_s { icp_qat_hw_auth_config_t auth_config; /**< Configuration word for the auth slice */ icp_qat_hw_auth_counter_t auth_counter; /**< Auth counter value for this request */ } icp_qat_hw_auth_setup_t; /* ************************************************************************* */ /* ************************************************************************* */ #define QAT_HW_DEFAULT_ALIGNMENT 8 #define QAT_HW_ROUND_UP(val, n) (((val) + ((n)-1)) & (~(n - 1))) /* State1 */ #define ICP_QAT_HW_NULL_STATE1_SZ 32 /**< @ingroup icp_qat_hw_defs * State1 block size for NULL hashing */ #define ICP_QAT_HW_MD5_STATE1_SZ 16 /**< @ingroup icp_qat_hw_defs * State1 block size for MD5 */ #define ICP_QAT_HW_SHA1_STATE1_SZ 20 /**< @ingroup icp_qat_hw_defs * Define the state1 block size for SHA1 - Note that for the QAT HW the state * is rounded to the nearest 8 byte multiple */ #define ICP_QAT_HW_SHA224_STATE1_SZ 32 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA24 */ #define ICP_QAT_HW_SHA3_224_STATE1_SZ 28 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA3_224 */ #define ICP_QAT_HW_SHA256_STATE1_SZ 32 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA256 */ #define ICP_QAT_HW_SHA3_256_STATE1_SZ 32 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA3_256 */ #define ICP_QAT_HW_SHA384_STATE1_SZ 64 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA384 */ #define ICP_QAT_HW_SHA3_384_STATE1_SZ 48 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA3_384 */ #define ICP_QAT_HW_SHA512_STATE1_SZ 64 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA512 */ #define ICP_QAT_HW_SHA3_512_STATE1_SZ 64 /**< @ingroup icp_qat_hw_defs * State1 block size for SHA3_512 */ #define ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ 16 /**< @ingroup icp_qat_hw_defs * State1 block size for XCBC */ #define ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ 16 /**< @ingroup icp_qat_hw_defs * State1 block size for CBC */ #define ICP_QAT_HW_AES_F9_STATE1_SZ 32 /**< @ingroup icp_qat_hw_defs * State1 block size for AES F9 */ #define ICP_QAT_HW_KASUMI_F9_STATE1_SZ 16 /**< @ingroup icp_qat_hw_defs * State1 block size for Kasumi F9 */ #define ICP_QAT_HW_GALOIS_128_STATE1_SZ 16 /**< @ingroup icp_qat_hw_defs * State1 block size for Galois128 */ #define ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ 8 /**< @ingroup icp_cpm_hw_defs * State1 block size for UIA2 */ #define ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ 8 /**< @ingroup icp_cpm_hw_defs * State1 block size for EIA3 */ #define ICP_QAT_HW_SM3_STATE1_SZ 32 /**< @ingroup icp_cpm_hw_defs * State1 block size for SM3 */ #define ICP_QAT_HW_SHA3_STATEFUL_STATE1_SZ 200 /** <@ingroup icp_cpm_hw_defs * State1 block size for stateful SHA3 processing*/ #define ICP_QAT_HW_ZUC_256_MAC_32_STATE1_SZ 16 /**< @ingroup icp_cpm_hw_defs * State1 block size for ZUC-256 with 32-bit MAC */ #define ICP_QAT_HW_ZUC_256_MAC_64_STATE1_SZ 16 /**< @ingroup icp_cpm_hw_defs * State1 block size for ZUC-256 with 64-bit MAC */ #define ICP_QAT_HW_ZUC_256_MAC_128_STATE1_SZ 16 /**< @ingroup icp_cpm_hw_defs * State1 block size for ZUC-256 with 128-bit MAC */ #define ICP_QAT_HW_AES_CMAC_STATE1_SZ 16 /**< @ingroup icp_cpm_hw_defs * State1 block size for AES-128/192/256 CMAC */ #define ICP_QAT_HW_NIAX_STATE1_SZ 16 /**< @ingroup icp_qat_hw_defs * State1 block size for NIAx (SNOW5G, AES-256, ZUC-256) * Note: State1 is not actually used in Gen6, defined this * to align with legacy AES-256 and ZUC-256. */ /* State2 */ #define ICP_QAT_HW_NULL_STATE2_SZ 32 /**< @ingroup icp_qat_hw_defs * State2 block size for NULL hashing */ #define ICP_QAT_HW_MD5_STATE2_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for MD5 */ #define ICP_QAT_HW_SHA1_STATE2_SZ 20 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA1 - Note that for the QAT HW the state is rounded * to the nearest 8 byte multiple */ #define ICP_QAT_HW_SHA224_STATE2_SZ 32 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA224 */ #define ICP_QAT_HW_SHA3_224_STATE2_SZ 0 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA3_224 */ #define ICP_QAT_HW_SHA256_STATE2_SZ 32 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA256 */ #define ICP_QAT_HW_SHA3_256_STATE2_SZ 0 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA3_256 */ #define ICP_QAT_HW_SHA384_STATE2_SZ 64 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA384 */ #define ICP_QAT_HW_SHA3_384_STATE2_SZ 0 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA3_384 */ #define ICP_QAT_HW_SHA512_STATE2_SZ 64 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA512 */ #define ICP_QAT_HW_SHA3_512_STATE2_SZ 0 /**< @ingroup icp_qat_hw_defs * State2 block size for SHA3_512 */ #define ICP_QAT_HW_AES_XCBC_MAC_KEY_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for XCBC */ #define ICP_QAT_HW_AES_CBC_MAC_KEY_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for CBC */ #define ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for AES Encrypted Counter 0 */ #define ICP_QAT_HW_F9_IK_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for F9 IK */ #define ICP_QAT_HW_F9_FK_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for F9 FK */ #define ICP_QAT_HW_KASUMI_F9_STATE2_SZ \ (ICP_QAT_HW_F9_IK_SZ + ICP_QAT_HW_F9_FK_SZ) /**< @ingroup icp_qat_hw_defs * State2 complete size for Kasumi F9 */ #define ICP_QAT_HW_AES_F9_STATE2_SZ ICP_QAT_HW_KASUMI_F9_STATE2_SZ /**< @ingroup icp_qat_hw_defs * State2 complete size for AES F9 */ #define ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ 24 /**< @ingroup icp_cpm_hw_defs * State2 block size for UIA2 */ #define ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ 32 /**< @ingroup icp_cpm_hw_defs * State2 block size for EIA3 */ #define ICP_QAT_HW_GALOIS_H_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for Galois Multiplier H */ #define ICP_QAT_HW_GALOIS_LEN_A_SZ 8 /**< @ingroup icp_qat_hw_defs * State2 block size for Galois AAD length */ #define ICP_QAT_HW_GALOIS_E_CTR0_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for Galois Encrypted Counter 0 */ #define ICP_QAT_HW_SM3_STATE2_SZ 32 /**< @ingroup icp_qat_hw_defs * State2 block size for SM3 */ #define ICP_QAT_HW_ZUC_256_STATE2_SZ 56 /**< @ingroup icp_qat_hw_defs * State2 block size for ZUC-256 with 32/64/128 bit MAC */ #define ICP_QAT_HW_AES_128_CMAC_STATE2_SZ 16 /**< @ingroup icp_qat_hw_defs * State2 block size for AES-128 CMAC */ #define ICP_QAT_HW_AES_192_CMAC_STATE2_SZ 24 /**< @ingroup icp_qat_hw_defs * State2 block size for AES-192 CMAC */ #define ICP_QAT_HW_AES_256_CMAC_STATE2_SZ 32 /**< @ingroup icp_qat_hw_defs * State2 block size for AES-256 CMAC */ #define ICP_QAT_HW_NIAX_STATE2_SZ 48 /**< @ingroup icp_cpm_hw_defs * State2 block size for NIAx (SNOW5G, AES-256, ZUC-256) */ #define ICP_QAT_HW_ZUC_256_UPDATE_STATE2_SZ 48 /**< @ingroup icp_cpm_hw_defs * State2 block size for updated ZUC-256 MAC-32/64/128 (Gen6) */ /* ************************************************************************* */ /* ************************************************************************* */ /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of SHA512 auth algorithm processing struct * @description * This structs described the parameters to pass to the slice for * configuring it for SHA512 processing. * *****************************************************************************/ typedef struct icp_qat_hw_auth_sha512_s { icp_qat_hw_auth_setup_t inner_setup; /**< Inner loop configuration word for the slice */ uint8_t state1[ICP_QAT_HW_SHA512_STATE1_SZ]; /**< Slice state1 variable */ icp_qat_hw_auth_setup_t outer_setup; /**< Outer configuration word for the slice */ uint8_t state2[ICP_QAT_HW_SHA512_STATE2_SZ]; /**< Slice state2 variable */ } icp_qat_hw_auth_sha512_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of SHA3_512 auth algorithm processing struct * @description * This structs described the parameters to pass to the slice for * configuring it for SHA3_512 processing. * *****************************************************************************/ typedef struct icp_qat_hw_auth_sha3_512_s { icp_qat_hw_auth_setup_t inner_setup; /**< Inner loop configuration word for the slice */ uint8_t state1[ICP_QAT_HW_SHA3_512_STATE1_SZ]; /**< Slice state1 variable */ icp_qat_hw_auth_setup_t outer_setup; /**< Outer configuration word for the slice */ } icp_qat_hw_auth_sha3_512_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of stateful SHA3 auth algorithm processing struct * @description * This structs described the parameters to pass to the slice for * configuring it for stateful SHA3 processing. This is the largest * possible setup block for authentication * *****************************************************************************/ typedef struct icp_qat_hw_auth_sha3_stateful_s { icp_qat_hw_auth_setup_t inner_setup; /**< Inner loop configuration word for the slice */ uint8_t inner_state1[ICP_QAT_HW_SHA3_STATEFUL_STATE1_SZ]; /**< Inner hash block */ icp_qat_hw_auth_setup_t outer_setup; /**< Outer configuration word for the slice */ uint8_t outer_state1[ICP_QAT_HW_SHA3_STATEFUL_STATE1_SZ]; /**< Outer hash block */ } icp_qat_hw_auth_sha3_stateful_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Supported hardware authentication algorithms * @description * Common grouping of the auth algorithm types supported by the QAT * *****************************************************************************/ typedef union icp_qat_hw_auth_algo_blk_u { icp_qat_hw_auth_sha512_t sha512; /**< SHA512 Hashing */ icp_qat_hw_auth_sha3_stateful_t sha3_stateful; /**< Stateful SHA3 Hashing */ } icp_qat_hw_auth_algo_blk_t; #define ICP_QAT_HW_GALOIS_LEN_A_BITPOS 0 /**< @ingroup icp_qat_hw_defs * Bit position of the 32 bit A value in the 64 bit A configuration sent to * the QAT */ #define ICP_QAT_HW_GALOIS_LEN_A_MASK 0xFFFFFFFF /**< @ingroup icp_qat_hw_defs * Mask value for A value */ /* ========================================================================= */ /* CIPHER SLICE */ /* ========================================================================= */ /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported Cipher Algorithm types * @description * Enumeration used to define the cipher algorithms * *****************************************************************************/ typedef enum { ICP_QAT_HW_CIPHER_ALGO_NULL = 0, /*!< Null ciphering */ ICP_QAT_HW_CIPHER_ALGO_DES = 1, /*!< DES ciphering */ ICP_QAT_HW_CIPHER_ALGO_3DES = 2, /*!< 3DES ciphering */ ICP_QAT_HW_CIPHER_ALGO_AES128 = 3, /*!< AES-128 ciphering */ ICP_QAT_HW_CIPHER_ALGO_AES192 = 4, /*!< AES-192 ciphering */ ICP_QAT_HW_CIPHER_ALGO_AES256 = 5, /*!< AES-256 ciphering */ ICP_QAT_HW_CIPHER_ALGO_ARC4 = 6, /*!< ARC4 ciphering */ ICP_QAT_HW_CIPHER_ALGO_KASUMI = 7, /*!< Kasumi */ ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2 = 8, /*!< Snow_3G */ ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3 = 9, /*!< ZUC_3G */ ICP_QAT_HW_CIPHER_ALGO_SM4 = 10, /*!< SM4 ciphering */ ICP_QAT_HW_CIPHER_ALGO_CHACHA20_POLY1305 = 11, /*!< CHACHA POLY SPC AEAD */ ICP_QAT_HW_CIPHER_ALGO_ZUC_256 = 12, /*!< ZUC-256 */ ICP_QAT_HW_CIPHER_ALGO_SNOW_5G = 13, /*!< Snow_5G */ ICP_QAT_HW_CIPHER_DELIMITER = 14 /**< Delimiter type */ } icp_qat_hw_cipher_algo_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported cipher modes of operation * @description * Enumeration used to define the cipher slice modes. * * @Note * Only some algorithms are valid in some of the modes. If you dont know * what you are doing then refer back to the EAS * *****************************************************************************/ typedef enum { ICP_QAT_HW_CIPHER_ECB_MODE = 0, /*!< ECB mode */ ICP_QAT_HW_CIPHER_CBC_MODE = 1, /*!< CBC more */ ICP_QAT_HW_CIPHER_CTR_MODE = 2, /*!< CTR mode */ ICP_QAT_HW_CIPHER_F8_MODE = 3, /*!< F8 mode */ ICP_QAT_HW_CIPHER_GCM_MODE = 4, /*!< AES-GCM single pass AEAD mode */ ICP_QAT_HW_CIPHER_CCM_MODE = 5, /*!< AES-CCM single pass AEAD mode */ ICP_QAT_HW_CIPHER_XTS_MODE = 6, /*!< XTS mode */ ICP_QAT_HW_CIPHER_NCA_MODE = 7, /*!< NCA mode */ ICP_QAT_HW_CIPHER_MODE_DELIMITER = 8 /**< Delimiter type */ } icp_qat_hw_cipher_mode_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Cipher Configuration Struct * * @description * Configuration data used for setting up the QAT Cipher Slice * *****************************************************************************/ typedef struct icp_qat_hw_cipher_config_s { uint32_t val; /**< Cipher slice configuration */ uint32_t reserved; /**< Reserved */ } icp_qat_hw_cipher_config_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Cipher Configuration Struct * * @description * Configuration data used for setting up the QAT UCS Cipher Slice * *****************************************************************************/ typedef struct icp_qat_hw_ucs_cipher_config_s { uint32_t val; /**< Cipher slice configuration */ uint32_t reserved[3]; /**< Reserved */ } icp_qat_hw_ucs_cipher_config_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the cipher direction * @description * Enumeration which is used to define the cipher direction to apply * *****************************************************************************/ typedef enum { /*!< Flag to indicate that encryption is required */ ICP_QAT_HW_CIPHER_ENCRYPT = 0, /*!< Flag to indicate that decryption is required */ ICP_QAT_HW_CIPHER_DECRYPT = 1, } icp_qat_hw_cipher_dir_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the cipher key conversion modes * @description * Enumeration which is used to define if cipher key conversion is needed * *****************************************************************************/ typedef enum { /*!< Flag to indicate that no key convert is required */ ICP_QAT_HW_CIPHER_NO_CONVERT = 0, /*!< Flag to indicate that key conversion is required */ ICP_QAT_HW_CIPHER_KEY_CONVERT = 1, } icp_qat_hw_cipher_convert_t; /* Private defines */ /* Note: Bit positions have been arranged for little endian ordering */ #define QAT_CIPHER_MODE_BITPOS 4 /**< @ingroup icp_qat_hw_defs * Define for the cipher mode bit position */ #define QAT_CIPHER_MODE_MASK 0xF /**< @ingroup icp_qat_hw_defs * Define for the cipher mode mask (four bits) */ #define QAT_CIPHER_ALGO_BITPOS 0 /**< @ingroup icp_qat_hw_defs * Define for the cipher algo bit position */ #define QAT_CIPHER_ALGO_MASK 0xF /**< @ingroup icp_qat_hw_defs * Define for the cipher algo mask (four bits) */ #define QAT_CIPHER_CONVERT_BITPOS 9 /**< @ingroup icp_qat_hw_defs * Define the cipher convert key bit position */ #define QAT_CIPHER_CONVERT_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Define for the cipher convert key mask (one bit)*/ #define QAT_CIPHER_DIR_BITPOS 8 /**< @ingroup icp_qat_hw_defs * Define for the cipher direction bit position */ #define QAT_CIPHER_DIR_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Define for the cipher direction mask (one bit) */ #define QAT_CIPHER_AEAD_HASH_CMP_LEN_MASK 0x1F /**< @ingroup icp_qat_hw_defs * Define for the cipher AEAD Hash compare length mask (5 bits)*/ #define QAT_CIPHER_AEAD_HASH_CMP_LEN_BITPOS 10 /**< @ingroup icp_qat_hw_defs * Define for the cipher AEAD Hash compare length (5 bits)*/ #define QAT_CIPHER_AEAD_AAD_SIZE_LOWER_MASK 0xFF /**< @ingroup icp_qat_hw_defs * Define for the cipher AEAD AAD size lower byte mask */ #define QAT_CIPHER_AEAD_AAD_SIZE_UPPER_MASK 0x3F /**< @ingroup icp_qat_hw_defs * Define for the cipher AEAD AAD size upper 6 bits mask */ #define QAT_CIPHER_AEAD_AAD_UPPER_SHIFT 8 /**< @ingroup icp_qat_hw_defs * Define for the cipher AEAD AAD size Upper byte shift */ #define QAT_CIPHER_AEAD_AAD_LOWER_SHIFT 24 /**< @ingroup icp_qat_hw_defs * Define for the cipher AEAD AAD size Lower byte shift */ #define QAT_CIPHER_AEAD_AAD_SIZE_BITPOS 16 /**< @ingroup icp_qat_hw_defs * Define for the cipher AEAD AAD size (14 bits)*/ #define QAT_CIPHER_MODE_F8_KEY_SZ_MULT 2 /**< @ingroup icp_qat_hw_defs * Define for the cipher mode F8 key size */ #define QAT_CIPHER_MODE_XTS_KEY_SZ_MULT 2 /**< @ingroup icp_qat_hw_defs * Define for the cipher XTS mode key size */ #define QAT_CIPHER_MODE_UCS_XTS_KEY_SZ_MULT 1 /**< @ingroup icp_qat_hw_defs * Define for the UCS cipher XTS mode key size */ /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Build the cipher configuration field * * @param mode Cipher Mode to use * @param algo Cipher Algorithm to use * @param convert Specify if the key is to be converted * @param dir Specify the cipher direction either encrypt or decrypt * *****************************************************************************/ #define ICP_QAT_HW_CIPHER_CONFIG_BUILD( \ mode, algo, convert, dir, aead_hash_cmp_len) \ ((((mode)&QAT_CIPHER_MODE_MASK) << QAT_CIPHER_MODE_BITPOS) | \ (((algo)&QAT_CIPHER_ALGO_MASK) << QAT_CIPHER_ALGO_BITPOS) | \ (((convert)&QAT_CIPHER_CONVERT_MASK) << QAT_CIPHER_CONVERT_BITPOS) | \ (((dir)&QAT_CIPHER_DIR_MASK) << QAT_CIPHER_DIR_BITPOS) | \ (((aead_hash_cmp_len)&QAT_CIPHER_AEAD_HASH_CMP_LEN_MASK) \ << QAT_CIPHER_AEAD_HASH_CMP_LEN_BITPOS)) /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Build the second QW of cipher slice config * * @param aad_size Specify the size of associated authentication data * for AEAD processing * ******************************************************************************/ #define ICP_QAT_HW_CIPHER_CONFIG_BUILD_UPPER(aad_size) \ (((((aad_size) >> QAT_CIPHER_AEAD_AAD_UPPER_SHIFT) & \ QAT_CIPHER_AEAD_AAD_SIZE_UPPER_MASK) \ << QAT_CIPHER_AEAD_AAD_SIZE_BITPOS) | \ (((aad_size)&QAT_CIPHER_AEAD_AAD_SIZE_LOWER_MASK) \ << QAT_CIPHER_AEAD_AAD_LOWER_SHIFT)) #define ICP_QAT_HW_DES_BLK_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the block size for DES. * This used as either the size of the IV or CTR input value */ #define ICP_QAT_HW_3DES_BLK_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the processing block size for 3DES */ #define ICP_QAT_HW_NULL_BLK_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the processing block size for NULL */ #define ICP_QAT_HW_AES_BLK_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the processing block size for AES 128, 192 and 256 */ #define ICP_QAT_HW_KASUMI_BLK_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the processing block size for KASUMI */ #define ICP_QAT_HW_SNOW_3G_BLK_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the processing block size for SNOW_3G */ #define ICP_QAT_HW_ZUC_3G_BLK_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the processing block size for ZUC_3G */ #define ICP_QAT_HW_ZUC_256_BLK_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the processing block size for ZUC-256 */ #define ICP_QAT_HW_NULL_KEY_SZ 256 /**< @ingroup icp_qat_hw_defs * Define the key size for NULL */ #define ICP_QAT_HW_DES_KEY_SZ 8 /**< @ingroup icp_qat_hw_defs * Define the key size for DES */ #define ICP_QAT_HW_3DES_KEY_SZ 24 /**< @ingroup icp_qat_hw_defs * Define the key size for 3DES */ #define ICP_QAT_HW_AES_128_KEY_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the key size for AES128 */ #define ICP_QAT_HW_AES_192_KEY_SZ 24 /**< @ingroup icp_qat_hw_defs * Define the key size for AES192 */ #define ICP_QAT_HW_AES_256_KEY_SZ 32 /**< @ingroup icp_qat_hw_defs * Define the key size for AES256 */ /* AES UCS */ #define ICP_QAT_HW_UCS_AES_128_KEY_SZ ICP_QAT_HW_AES_128_KEY_SZ /**< @ingroup icp_qat_hw_defs * Define the key size for AES128 for UCS slice*/ #define ICP_QAT_HW_UCS_AES_192_KEY_SZ 32 /**< @ingroup icp_qat_hw_defs * Define the key size for AES192 for UCS slice*/ #define ICP_QAT_HW_UCS_AES_256_KEY_SZ ICP_QAT_HW_AES_256_KEY_SZ /**< @ingroup icp_qat_hw_defs * Define the key size for AES256 for UCS slice*/ #define ICP_QAT_HW_AES_128_F8_KEY_SZ \ (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for AES128 F8 */ #define ICP_QAT_HW_AES_192_F8_KEY_SZ \ (ICP_QAT_HW_AES_192_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for AES192 F8 */ #define ICP_QAT_HW_AES_256_F8_KEY_SZ \ (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for AES256 F8 */ #define ICP_QAT_HW_AES_128_XTS_KEY_SZ \ (ICP_QAT_HW_AES_128_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for AES128 XTS */ #define ICP_QAT_HW_AES_256_XTS_KEY_SZ \ (ICP_QAT_HW_AES_256_KEY_SZ * QAT_CIPHER_MODE_XTS_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for AES256 XTS */ #define ICP_QAT_HW_UCS_AES_128_XTS_KEY_SZ \ (ICP_QAT_HW_UCS_AES_128_KEY_SZ * QAT_CIPHER_MODE_UCS_XTS_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for AES128 XTS for the UCS Slice*/ #define ICP_QAT_HW_UCS_AES_256_XTS_KEY_SZ \ (ICP_QAT_HW_UCS_AES_256_KEY_SZ * QAT_CIPHER_MODE_UCS_XTS_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for AES256 XTS for the UCS Slice*/ #define ICP_QAT_HW_KASUMI_KEY_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the key size for Kasumi */ #define ICP_QAT_HW_KASUMI_F8_KEY_SZ \ (ICP_QAT_HW_KASUMI_KEY_SZ * QAT_CIPHER_MODE_F8_KEY_SZ_MULT) /**< @ingroup icp_qat_hw_defs * Define the key size for Kasumi F8 */ /**< @ingroup icp_qat_hw_defs * Define the key size for AES256 XTS */ #define ICP_QAT_HW_ARC4_KEY_SZ 256 /**< @ingroup icp_qat_hw_defs * Define the key size for ARC4 */ #define ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ 16 /**< @ingroup icp_cpm_hw_defs * Define the key size for SNOW_3G_UEA2 */ #define ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ 16 /**< @ingroup icp_cpm_hw_defs * Define the iv size for SNOW_3G_UEA2 */ #define ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ 16 /**< @ingroup icp_cpm_hw_defs * Define the key size for ZUC_3G_EEA3 */ #define ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ 16 /**< @ingroup icp_cpm_hw_defs * Define the iv size for ZUC_3G_EEA3 */ #define ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR 2 /**< @ingroup icp_cpm_hw_defs * Number of the HW register to clear in F8 mode */ #define ICP_QAT_HW_SM4_BLK_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the processing block size for SM4 */ #define ICP_QAT_HW_SM4_KEY_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the key size for SM4 */ #define ICP_QAT_HW_SM4_IV_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the IV size for SM4 */ /**< @ingroup icp_qat_hw_defs * Define the State/ Initialization Vector size for CHACHAPOLY */ #define ICP_QAT_HW_CHACHAPOLY_KEY_SZ 32 /**< @ingroup icp_qat_hw_defs * Define the key size for CHACHA20-Poly1305*/ #define ICP_QAT_HW_CHACHAPOLY_IV_SZ 12 /**< @ingroup icp_qat_hw_defs * Define the block size for CHACHA20-Poly1305*/ #define ICP_QAT_HW_CHACHAPOLY_BLK_SZ 64 /**< @ingroup icp_qat_hw_defs * Define the State/ Initialization Vector size for CHACHA20-Poly1305 */ #define ICP_QAT_HW_CHACHAPOLY_CTR_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the key size for CHACHA20-Poly1305*/ #define ICP_QAT_HW_SPC_CTR_SZ 16 /**< @ingroup icp_qat_hw_defs * Define the Single Pass tag size*/ #define ICP_QAT_HW_CHACHAPOLY_ICV__SZ 16 /**< @ingroup icp_qat_hw_defs * Define the key size for CHACHA20-Poly1305*/ #define ICP_QAT_HW_CHACHAPOLY_AAD_MAX_LOG 14 /**< @ingroup icp_qat_hw_defs * Define the key size for CHACHA20-Poly1305*/ #define ICP_QAT_HW_ZUC_256_KEY_SZ 32 /**< @ingroup icp_cpm_hw_defs * Define the key size for ZUC-256 */ #define ICP_QAT_HW_ZUC_256_IV_SZ 24 /**< @ingroup icp_cpm_hw_defs * Define the iv size for ZUC-256 */ /* SNOW5G */ #define ICP_QAT_HW_SNOW_5G_KEY_SZ 32 /**< @ingroup icp_cpm_hw_defs * Define the key size for SNOW_5G */ #define ICP_QAT_HW_SNOW_5G_IV_SZ 16 /**< @ingroup icp_cpm_hw_defs * Define the iv size for SNOW_5G */ #define ICP_QAT_HW_ZUC_256_UPDATE_IV_SZ 16 /**< @ingroup icp_cpm_hw_defs * Define the iv size for updated ZUC-256 (Gen6) */ /* * SHRAM constants definitions */ #define INIT_SHRAM_CONSTANTS_TABLE_SZ (1024) #define SHRAM_CONSTANTS_TABLE_SIZE_QWS (INIT_SHRAM_CONSTANTS_TABLE_SZ / 4 / 2) /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of AES-256 F8 cipher algorithm processing struct * @description * This structs described the parameters to pass to the slice for * configuring it for AES-256 F8 processing * *****************************************************************************/ typedef struct icp_qat_hw_cipher_aes256_f8_s { icp_qat_hw_cipher_config_t cipher_config; /**< Cipher configuration word for the slice set to * AES-256 and the F8 mode */ uint8_t key[ICP_QAT_HW_AES_256_F8_KEY_SZ]; /**< Cipher key */ } icp_qat_hw_cipher_aes256_f8_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Supported hardware cipher algorithms * @description * Common grouping of the cipher algorithm types supported by the QAT. * This is the largest possible cipher setup block size * *****************************************************************************/ typedef union icp_qat_hw_cipher_algo_blk_u { icp_qat_hw_cipher_aes256_f8_t aes256_f8; /**< AES-256 F8 Cipher */ } icp_qat_hw_cipher_algo_blk_t; /* ========================================================================= */ /* TRNG SLICE */ /* ========================================================================= */ /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported TRNG configuration modes * @description * Enumeration used to define the TRNG modes. Used by clients when * configuring the TRNG for use * *****************************************************************************/ typedef enum { ICP_QAT_HW_TRNG_DBL = 0, /*!< TRNG Disabled mode */ ICP_QAT_HW_TRNG_NHT = 1, /*!< TRNG Normal Health Test mode */ ICP_QAT_HW_TRNG_KAT = 4, /*!< TRNG Known Answer Test mode */ ICP_QAT_HW_TRNG_DELIMITER = 8 /**< Delimiter type */ } icp_qat_hw_trng_cfg_mode_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported TRNG KAT (known answer test) modes * @description * Enumeration which is used to define the TRNG KAT modes. Used by clients * when configuring the TRNG for testing * *****************************************************************************/ typedef enum { ICP_QAT_HW_TRNG_NEG_0 = 0, /*!< TRNG Neg Zero Test */ ICP_QAT_HW_TRNG_NEG_1 = 1, /*!< TRNG Neg One Test */ ICP_QAT_HW_TRNG_POS = 2, /*!< TRNG POS Test */ ICP_QAT_HW_TRNG_POS_VNC = 3, /*!< TRNG POS VNC Test */ ICP_QAT_HW_TRNG_KAT_DELIMITER = 4 /**< Delimiter type */ } icp_qat_hw_trng_kat_mode_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * TRNG mode configuration structure. * * @description * Definition of the format of the TRNG slice configuration. Used * internally by the QAT FW for configuration of the KAT unit or the * TRNG depending on the slice command i.e. either a set_slice_config or * slice_wr_KAT_type * *****************************************************************************/ typedef struct icp_qat_hw_trng_config_s { uint32_t val; /**< Configuration used for setting up the TRNG slice */ uint32_t reserved; /**< Reserved */ } icp_qat_hw_trng_config_t; /* Private Defines */ /* Note: Bit positions have been arranged for little endian ordering */ #define QAT_TRNG_CONFIG_MODE_MASK 0x7 /**< @ingroup icp_qat_hw_defs * Mask for the TRNG configuration mode. (Three bits) */ #define QAT_TRNG_CONFIG_MODE_BITPOS 5 /**< @ingroup icp_qat_hw_defs * TRNG configuration mode bit positions start */ #define QAT_TRNG_KAT_MODE_MASK 0x3 /**< @ingroup icp_qat_hw_defs * Mask of two bits for the TRNG known answer test mode */ #define QAT_TRNG_KAT_MODE_BITPOS 6 /**< @ingroup icp_qat_hw_defs * TRNG known answer test mode bit positions start */ /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Build the configuration byte for the TRNG slice based on the mode * * @param mode Configuration mode parameter * *****************************************************************************/ #define ICP_QAT_HW_TRNG_CONFIG_MODE_BUILD(mode) \ (((mode)&QAT_TRNG_CONFIG_MODE_MASK) << QAT_TRNG_CONFIG_MODE_BITPOS) /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Build the configuration byte for the TRNG KAT based on the mode * * @param mode Configuration mode parameter * *****************************************************************************/ #define ICP_QAT_HW_TRNG_KAT_MODE_BUILD(mode) \ ((((mode)&QAT_TRNG_KAT_MODE_MASK) << QAT_TRNG_KAT_MODE_BITPOS)) /** ***************************************************************************** * @ingroup icp_qat_hw_defs * TRNG test status structure. * * @description * Definition of the format of the TRNG slice test status structure. Used * internally by the QAT FW. * *****************************************************************************/ typedef struct icp_qat_hw_trng_test_status_s { uint32_t status; /**< Status used for setting up the TRNG slice */ uint32_t fail_count; /**< Comparator fail count */ } icp_qat_hw_trng_test_status_t; #define ICP_QAT_HW_TRNG_TEST_NO_FAILURES 1 /**< @ingroup icp_qat_hw_defs * Flag to indicate that there were no Test Failures */ #define ICP_QAT_HW_TRNG_TEST_FAILURES_FOUND 0 /**< @ingroup icp_qat_hw_defs * Flag to indicate that there were Test Failures */ #define ICP_QAT_HW_TRNG_TEST_STATUS_VALID 1 /**< @ingroup icp_qat_hw_defs * Flag to indicate that there is no valid Test output */ #define ICP_QAT_HW_TRNG_TEST_STATUS_INVALID 0 /**< @ingroup icp_qat_hw_defs * Flag to indicate that the Test output is still invalid */ /* Private defines */ #define QAT_TRNG_TEST_FAILURE_FLAG_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Mask of one bit used to determine the TRNG Test pass/fail */ #define QAT_TRNG_TEST_FAILURE_FLAG_BITPOS 4 /**< @ingroup icp_qat_hw_defs * Flag position to indicate that the TRNG Test status is pass of fail */ #define QAT_TRNG_TEST_STATUS_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Mask of one bit used to determine the TRNG Test status */ #define QAT_TRNG_TEST_STATUS_BITPOS 1 /**< @ingroup icp_qat_hw_defs * Flag position to indicate the TRNG Test status */ /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Extract the fail bit for the TRNG slice * * @param status TRNG status value * *****************************************************************************/ #define ICP_QAT_HW_TRNG_FAIL_FLAG_GET(status) \ (((status) >> QAT_TRNG_TEST_FAILURE_FLAG_BITPOS) & \ QAT_TRNG_TEST_FAILURE_FLAG_MASK) /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Extract the status valid bit for the TRNG slice * * @param status TRNG status value * *****************************************************************************/ #define ICP_QAT_HW_TRNG_STATUS_VALID_GET(status) \ (((status) >> QAT_TRNG_TEST_STATUS_BITPOS) & QAT_TRNG_TEST_STATUS_MASK) /** ***************************************************************************** * @ingroup icp_qat_hw_defs * TRNG entropy counters * * @description * Definition of the format of the TRNG entropy counters. Used internally * by the QAT FW. * *****************************************************************************/ typedef struct icp_qat_hw_trng_entropy_counts_s { uint64_t raw_ones_count; /**< Count of raw ones of entropy */ uint64_t raw_zeros_count; /**< Count of raw zeros of entropy */ uint64_t cond_ones_count; /**< Count of conditioned ones entropy */ uint64_t cond_zeros_count; /**< Count of conditioned zeros entropy */ } icp_qat_hw_trng_entropy_counts_t; /* Private defines */ #define QAT_HW_TRNG_ENTROPY_STS_RSVD_SZ 4 /**< @ingroup icp_qat_hw_defs * TRNG entropy status reserved size in bytes */ /** ***************************************************************************** * @ingroup icp_qat_hw_defs * TRNG entropy available status. * * @description * Definition of the format of the TRNG slice entropy status available. * struct. Used internally by the QAT FW. * *****************************************************************************/ typedef struct icp_qat_hw_trng_entropy_status_s { uint32_t status; /**< Entropy status in the TRNG */ uint8_t reserved[QAT_HW_TRNG_ENTROPY_STS_RSVD_SZ]; /**< Reserved */ } icp_qat_hw_trng_entropy_status_t; #define ICP_QAT_HW_TRNG_ENTROPY_AVAIL 1 /**< @ingroup icp_qat_hw_defs * Flag indicating that entropy data is available in the QAT TRNG slice */ #define ICP_QAT_HW_TRNG_ENTROPY_NOT_AVAIL 0 /**< @ingroup icp_qat_hw_defs * Flag indicating that no entropy data is available in the QAT TRNG slice */ /* Private defines */ #define QAT_TRNG_ENTROPY_STATUS_MASK 1 /**< @ingroup icp_qat_hw_defs * Mask of one bit used to determine the TRNG Entropy status */ #define QAT_TRNG_ENTROPY_STATUS_BITPOS 0 /**< @ingroup icp_qat_hw_defs * Starting bit position for TRNG Entropy status. */ /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Extract the entropy available status bit * * @param status TRNG status value * *****************************************************************************/ #define ICP_QAT_HW_TRNG_ENTROPY_STATUS_GET(status) \ (((status) >> QAT_TRNG_ENTROPY_STATUS_BITPOS) & \ QAT_TRNG_ENTROPY_STATUS_MASK) /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Entropy seed data * * @description * This type is used for the definition of the entropy generated by a read * of the TRNG slice * *****************************************************************************/ typedef uint64_t icp_qat_hw_trng_entropy; /* ========================================================================= */ /* COMPRESSION SLICE */ /* ========================================================================= */ /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported compression directions * @description * Enumeration used to define the compression directions * *****************************************************************************/ typedef enum { ICP_QAT_HW_COMPRESSION_DIR_COMPRESS = 0, /*!< Compression */ ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS = 1, /*!< Decompression */ ICP_QAT_HW_COMPRESSION_DIR_DELIMITER = 2 /**< Delimiter type */ } icp_qat_hw_compression_direction_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported delayed match modes * @description * Enumeration used to define whether delayed match is enabled * *****************************************************************************/ typedef enum { ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED = 0, /*!< Delayed match disabled */ ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED = 1, /*!< Delayed match enabled Note: This is the only valid mode - refer to CPM1.6 SAS */ ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DELIMITER = 2 /**< Delimiter type */ } icp_qat_hw_compression_delayed_match_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported compression algorithms * @description * Enumeration used to define the compression algorithms * *****************************************************************************/ typedef enum { ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE = 0, /*!< Deflate compression */ ICP_QAT_HW_COMPRESSION_DEPRECATED = 1, /*!< Deprecated */ ICP_QAT_HW_COMPRESSION_ALGO_DELIMITER = 2 /**< Delimiter type */ } icp_qat_hw_compression_algo_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported compression depths * @description * Enumeration used to define the compression slice depths. * *****************************************************************************/ typedef enum { ICP_QAT_HW_COMPRESSION_DEPTH_1 = 0, /*!< Search depth 1 (Fastest least exhaustive) */ ICP_QAT_HW_COMPRESSION_DEPTH_4 = 1, /*!< Search depth 4 */ ICP_QAT_HW_COMPRESSION_DEPTH_8 = 2, /*!< Search depth 8 */ ICP_QAT_HW_COMPRESSION_DEPTH_16 = 3, /*!< Search depth 16 */ ICP_QAT_HW_COMPRESSION_DEPTH_128 = 4, /*!< Search depth 128 (Slowest, most exhaustive) */ ICP_QAT_HW_COMPRESSION_DEPTH_DELIMITER = 5 /**< Delimiter type */ } icp_qat_hw_compression_depth_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Definition of the supported file types * @description * Enumeration used to define the compression file types. * *****************************************************************************/ typedef enum { ICP_QAT_HW_COMPRESSION_FILE_TYPE_0 = 0, /*!< Use Static Trees */ ICP_QAT_HW_COMPRESSION_FILE_TYPE_1 = 1, /*!< Use Semi-Dynamic Trees at offset 0 */ ICP_QAT_HW_COMPRESSION_FILE_TYPE_2 = 2, /*!< Use Semi-Dynamic Trees at offset 320 */ ICP_QAT_HW_COMPRESSION_FILE_TYPE_3 = 3, /*!< Use Semi-Dynamic Trees at offset 640 */ ICP_QAT_HW_COMPRESSION_FILE_TYPE_4 = 4, /*!< Use Semi-Dynamic Trees at offset 960 */ ICP_QAT_HW_COMPRESSION_FILE_TYPE_DELIMITER = 5 /**< Delimiter type */ } icp_qat_hw_compression_file_type_t; /** ***************************************************************************** * @ingroup icp_qat_hw_defs * Compression Configuration Struct * * @description * Configuration data used for setting up the QAT Compression Slice * *****************************************************************************/ typedef struct icp_qat_hw_compression_config_s { uint32_t lower_val; /**< Compression slice configuration lower LW */ uint32_t upper_val; /**< Compression slice configuration upper LW */ } icp_qat_hw_compression_config_t; /* Private defines */ #define QAT_COMPRESSION_DIR_BITPOS 4 /**< @ingroup icp_qat_hw_defs * Define for the compression direction bit position */ #define QAT_COMPRESSION_DIR_MASK 0x7 /**< @ingroup icp_qat_hw_defs * Define for the compression direction mask (three bits) */ #define QAT_COMPRESSION_DELAYED_MATCH_BITPOS 16 /**< @ingroup icp_qat_hw_defs * Define for the compression delayed match bit position */ #define QAT_COMPRESSION_DELAYED_MATCH_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Define for the delayed match mask (one bit) */ #define QAT_COMPRESSION_ALGO_BITPOS 31 /**< @ingroup icp_qat_hw_defs * Define for the compression algorithm bit position */ #define QAT_COMPRESSION_ALGO_MASK 0x1 /**< @ingroup icp_qat_hw_defs * Define for the compression algorithm mask (one bit) */ #define QAT_COMPRESSION_DEPTH_BITPOS 28 /**< @ingroup icp_qat_hw_defs * Define for the compression depth bit position */ #define QAT_COMPRESSION_DEPTH_MASK 0x7 /**< @ingroup icp_qat_hw_defs * Define for the compression depth mask (three bits) */ #define QAT_COMPRESSION_FILE_TYPE_BITPOS 24 /**< @ingroup icp_qat_hw_defs * Define for the compression file type bit position */ #define QAT_COMPRESSION_FILE_TYPE_MASK 0xF /**< @ingroup icp_qat_hw_defs * Define for the compression file type mask (four bits) */ /** ****************************************************************************** * @ingroup icp_qat_hw_defs * * @description * Build the compression slice configuration field * * @param dir Compression Direction to use, compress or decompress * @param delayed Specify if delayed match should be enabled * @param algo Compression algorithm to use * @param depth Compression search depth to use * @param filetype Compression file type to use, static or semi dynamic trees * *****************************************************************************/ #define ICP_QAT_HW_COMPRESSION_CONFIG_BUILD( \ dir, delayed, algo, depth, filetype) \ ((((dir)&QAT_COMPRESSION_DIR_MASK) << QAT_COMPRESSION_DIR_BITPOS) | \ (((delayed)&QAT_COMPRESSION_DELAYED_MATCH_MASK) \ << QAT_COMPRESSION_DELAYED_MATCH_BITPOS) | \ (((algo)&QAT_COMPRESSION_ALGO_MASK) << QAT_COMPRESSION_ALGO_BITPOS) | \ (((depth)&QAT_COMPRESSION_DEPTH_MASK) << QAT_COMPRESSION_DEPTH_BITPOS) | \ (((filetype)&QAT_COMPRESSION_FILE_TYPE_MASK) \ << QAT_COMPRESSION_FILE_TYPE_BITPOS)) /* ========================================================================= */ /* TRANSLATOR SLICE */ /* ========================================================================= */ /**< Translator slice configuration is set internally by the firmware */ #endif /* _ICP_QAT_HW_H_ */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_hw_20_comp.h000066400000000000000000000331761503624047500265440ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /** ***************************************************************************** * @file icp_qat_hw_2x_comp.h * @defgroup ICP QAT HW accessors for using the for 2.x Compression Slice * definitions * @ingroup icp_qat_hw_2x_comp * @description * This file documents definitions for the QAT HW COMP SLICE * *****************************************************************************/ #ifndef _ICP_QAT_HW_20_COMP_H_ #define _ICP_QAT_HW_20_COMP_H_ #include "icp_qat_hw_20_comp_defs.h" /* For HW definitions */ #include "icp_qat_fw.h" /* For Set Field Macros. */ #define BYTE_SWAP_32 __builtin_bswap32 /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Definition of the hw config csr. This representation has to be further * processed by the corresponding config build function. * *****************************************************************************/ typedef struct icp_qat_hw_comp_20_config_csr_lower_s { /* Fields programmable directly by the SW. */ icp_qat_hw_comp_20_extended_delay_match_mode_t edmm; icp_qat_hw_comp_20_hw_comp_format_t algo; icp_qat_hw_comp_20_search_depth_t sd; icp_qat_hw_comp_20_hbs_control_t hbs; /* Fields programmable directly by the FW. */ /* Block Drop enable. (Set by FW) */ icp_qat_hw_comp_20_abd_t abd; icp_qat_hw_comp_20_lllbd_ctrl_t lllbd; /* Advanced HW control (Set to default vals) */ icp_qat_hw_comp_20_min_match_control_t mmctrl; icp_qat_hw_comp_20_skip_hash_collision_t hash_col; icp_qat_hw_comp_20_skip_hash_update_t hash_update; icp_qat_hw_comp_20_byte_skip_t skip_ctrl; } icp_qat_hw_comp_20_config_csr_lower_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Build the longword as expected by the HW * *****************************************************************************/ static inline uint32_t ICP_QAT_FW_COMP_20_BUILD_CONFIG_LOWER( icp_qat_hw_comp_20_config_csr_lower_t csr) { uint32_t val32 = 0; /* Programmable values */ QAT_FIELD_SET(val32, csr.algo, ICP_QAT_HW_COMP_20_CONFIG_CSR_HW_COMP_FORMAT_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_HW_COMP_FORMAT_MASK); QAT_FIELD_SET(val32, csr.sd, ICP_QAT_HW_COMP_20_CONFIG_CSR_SEARCH_DEPTH_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SEARCH_DEPTH_MASK); QAT_FIELD_SET( val32, csr.edmm, ICP_QAT_HW_COMP_20_CONFIG_CSR_EXTENDED_DELAY_MATCH_MODE_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_EXTENDED_DELAY_MATCH_MODE_MASK); QAT_FIELD_SET(val32, csr.hbs, ICP_QAT_HW_COMP_20_CONFIG_CSR_HBS_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_HBS_CONTROL_MASK); QAT_FIELD_SET(val32, csr.mmctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_MASK); QAT_FIELD_SET(val32, csr.hash_col, ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_COLLISION_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_COLLISION_MASK); QAT_FIELD_SET(val32, csr.hash_update, ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_UPDATE_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_UPDATE_MASK); QAT_FIELD_SET(val32, csr.skip_ctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_BYTE_SKIP_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_BYTE_SKIP_MASK); /* Default values. */ QAT_FIELD_SET(val32, csr.abd, ICP_QAT_HW_COMP_20_CONFIG_CSR_ABD_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_ABD_MASK); QAT_FIELD_SET(val32, csr.lllbd, ICP_QAT_HW_COMP_20_CONFIG_CSR_LLLBD_CTRL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_LLLBD_CTRL_MASK); return BYTE_SWAP_32(val32); } /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Definition of the hw config csr. This representation has to be further * processed by the corresponding config build function. * *****************************************************************************/ typedef struct icp_qat_hw_comp_20_config_csr_upper_s { icp_qat_hw_comp_20_scb_control_t scb_ctrl; icp_qat_hw_comp_20_rmb_control_t rmb_ctrl; icp_qat_hw_comp_20_som_control_t som_ctrl; icp_qat_hw_comp_20_skip_hash_rd_control_t skip_hash_ctrl; icp_qat_hw_comp_20_scb_unload_control_t scb_unload_ctrl; icp_qat_hw_comp_20_disable_token_fusion_control_t disable_token_fusion_ctrl; icp_qat_hw_comp_20_lbms_t lbms; icp_qat_hw_comp_20_scb_mode_reset_mask_t scb_mode_reset; uint16_t lazy; uint16_t nice; } icp_qat_hw_comp_20_config_csr_upper_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Build the longword as expected by the HW * *****************************************************************************/ static inline uint32_t ICP_QAT_FW_COMP_20_BUILD_CONFIG_UPPER( icp_qat_hw_comp_20_config_csr_upper_t csr) { uint32_t val32 = 0; QAT_FIELD_SET(val32, csr.scb_ctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_CONTROL_MASK); QAT_FIELD_SET(val32, csr.rmb_ctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_RMB_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_RMB_CONTROL_MASK); QAT_FIELD_SET(val32, csr.som_ctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_SOM_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SOM_CONTROL_MASK); QAT_FIELD_SET(val32, csr.skip_hash_ctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_RD_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_RD_CONTROL_MASK); QAT_FIELD_SET(val32, csr.scb_unload_ctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_UNLOAD_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_UNLOAD_CONTROL_MASK); QAT_FIELD_SET( val32, csr.disable_token_fusion_ctrl, ICP_QAT_HW_COMP_20_CONFIG_CSR_DISABLE_TOKEN_FUSION_CONTROL_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_DISABLE_TOKEN_FUSION_CONTROL_MASK); QAT_FIELD_SET(val32, csr.lbms, ICP_QAT_HW_COMP_20_CONFIG_CSR_LBMS_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_LBMS_MASK); QAT_FIELD_SET(val32, csr.scb_mode_reset, ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_MODE_RESET_MASK_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_MODE_RESET_MASK_MASK); QAT_FIELD_SET(val32, csr.lazy, ICP_QAT_HW_COMP_20_CONFIG_CSR_LAZY_PARAM_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_LAZY_PARAM_MASK); QAT_FIELD_SET(val32, csr.nice, ICP_QAT_HW_COMP_20_CONFIG_CSR_NICE_PARAM_BITPOS, ICP_QAT_HW_COMP_20_CONFIG_CSR_NICE_PARAM_MASK); return BYTE_SWAP_32(val32); } /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Definition of the hw config csr. This representation has to be further * processed by the corresponding config build function. * *****************************************************************************/ typedef struct icp_qat_hw_decomp_20_config_csr_lower_s { /* Fields programmable directly by the SW. */ icp_qat_hw_decomp_20_hbs_control_t hbs; icp_qat_hw_decomp_20_lbms_t lbms; /* Advanced HW control (Set to default vals) */ icp_qat_hw_decomp_20_hw_comp_format_t algo; icp_qat_hw_decomp_20_min_match_control_t mmctrl; icp_qat_hw_decomp_20_lz4_block_checksum_present_t lbc; } icp_qat_hw_decomp_20_config_csr_lower_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Build the longword as expected by the HW * *****************************************************************************/ static inline uint32_t ICP_QAT_FW_DECOMP_20_BUILD_CONFIG_LOWER( icp_qat_hw_decomp_20_config_csr_lower_t csr) { uint32_t val32 = 0; QAT_FIELD_SET(val32, csr.hbs, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HBS_CONTROL_BITPOS, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HBS_CONTROL_MASK); QAT_FIELD_SET(val32, csr.lbms, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LBMS_BITPOS, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LBMS_MASK); QAT_FIELD_SET(val32, csr.algo, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HW_DECOMP_FORMAT_BITPOS, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HW_DECOMP_FORMAT_MASK); QAT_FIELD_SET(val32, csr.mmctrl, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_BITPOS, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_MASK); QAT_FIELD_SET( val32, csr.lbc, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LZ4_BLOCK_CHECKSUM_PRESENT_BITPOS, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LZ4_BLOCK_CHECKSUM_PRESENT_MASK); return BYTE_SWAP_32(val32); } /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Definition of the hw config csr. This representation has to be further * processed by the corresponding config build function. * *****************************************************************************/ typedef struct icp_qat_hw_decomp_20_config_csr_upper_s { /* Advanced HW control (Set to default vals) */ icp_qat_hw_decomp_20_speculative_decoder_control_t sdc; icp_qat_hw_decomp_20_reserved4_control_t res4; } icp_qat_hw_decomp_20_config_csr_upper_t; /** ***************************************************************************** * @ingroup icp_qat_fw_comn * * @description * Build the longword as expected by the HW * *****************************************************************************/ static inline uint32_t ICP_QAT_FW_DECOMP_20_BUILD_CONFIG_UPPER( icp_qat_hw_decomp_20_config_csr_upper_t csr) { uint32_t val32 = 0; QAT_FIELD_SET( val32, csr.sdc, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_SPECULATIVE_DECODER_CONTROL_BITPOS, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_SPECULATIVE_DECODER_CONTROL_MASK); QAT_FIELD_SET(val32, csr.res4, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_RESERVED4_CONTROL_BITPOS, ICP_QAT_HW_DECOMP_20_CONFIG_CSR_RESERVED4_CONTROL_MASK); return BYTE_SWAP_32(val32); } #endif /* ICP_QAT_HW__2X_COMP_H_ */ qatlib-25.08.0/quickassist/lookaside/firmware/include/icp_qat_hw_20_comp_defs.h000066400000000000000000000673621503624047500275510ustar00rootroot00000000000000/* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ /* **************************************************************************** * @file icp_qat_hw_20_comp_defs.h, (autogenerated at 04-19-18 16:06) * @defgroup icp_qat_hw_comp_20 * @ingroup icp_qat_hw_comp_20 * @description * This file represents the HW configuration CSR definitions **************************************************************************** */ #ifndef _ICP_QAT_HW_20_COMP_DEFS_H #define _ICP_QAT_HW_20_COMP_DEFS_H /*****************************************************************************/ /* SCB Disabled - Set by FW, located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_CONTROL_BITPOS 31 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SCB_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SCB_CONTROL_ENABLE = 0x0, /* Normal Mode using SCB (Default) */ ICP_QAT_HW_COMP_20_SCB_CONTROL_DISABLE = 0x1, /* Legacy CPM1.x Mode with SCB disabled. */ } icp_qat_hw_comp_20_scb_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SCB_CONTROL_DISABLE /*****************************************************************************/ /* Reset Bit Mask Disabled - Set by FW , located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_RMB_CONTROL_BITPOS 30 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_RMB_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible RMB_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_RMB_CONTROL_RESET_ALL = 0x0, /* Reset all data structures with a set_config command. (Set by FW) */ ICP_QAT_HW_COMP_20_RMB_CONTROL_RESET_FC_ONLY = 0x1, /* Reset only the Frequency Counters (LFCT) with a set_config command. */ } icp_qat_hw_comp_20_rmb_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_RMB_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_RMB_CONTROL_RESET_ALL /*****************************************************************************/ /* Slice Operation Mode (SOM) - Set By FW, located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SOM_CONTROL_BITPOS 28 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SOM_CONTROL_MASK 0x3 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SOM_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SOM_CONTROL_NORMAL_MODE = 0x0, /* Normal mode. */ ICP_QAT_HW_COMP_20_SOM_CONTROL_REPLAY_MODE = 0x1, /* Replay mode */ ICP_QAT_HW_COMP_20_SOM_CONTROL_INPUT_CRC = 0x2, /* Input CRC Mode */ ICP_QAT_HW_COMP_20_SOM_CONTROL_RESERVED_MODE = 0x3, /* Reserved. */ } icp_qat_hw_comp_20_som_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SOM_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SOM_CONTROL_NORMAL_MODE /*****************************************************************************/ /* Skip Hash Read (Set By FW) , located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_RD_CONTROL_BITPOS 27 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_RD_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SKIP_HASH_RD_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SKIP_HASH_RD_CONTROL_NO_SKIP = 0x0, /* When set to 0, hash reads are not skipped. */ ICP_QAT_HW_COMP_20_SKIP_HASH_RD_CONTROL_SKIP_HASH_READS = 0x1, /* Hash reads are skipped. */ } icp_qat_hw_comp_20_skip_hash_rd_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_RD_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SKIP_HASH_RD_CONTROL_NO_SKIP /*****************************************************************************/ /* SCB Unload Disable, located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_UNLOAD_CONTROL_BITPOS 26 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_UNLOAD_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SCB_UNLOAD_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SCB_UNLOAD_CONTROL_UNLOAD = 0x0, /* Unloads the LFCT and flushes the State Registers. */ ICP_QAT_HW_COMP_20_SCB_UNLOAD_CONTROL_NO_UNLOAD = 0x1, /* Does not unload the LFCT, but flushes the State Registers. */ } icp_qat_hw_comp_20_scb_unload_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_UNLOAD_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SCB_UNLOAD_CONTROL_UNLOAD /*****************************************************************************/ /* Disable token fusion, located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_DISABLE_TOKEN_FUSION_CONTROL_BITPOS 21 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_DISABLE_TOKEN_FUSION_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible DISABLE_TOKEN_FUSION_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_DISABLE_TOKEN_FUSION_CONTROL_ENABLE = 0x0, /* Enables token fusion. */ ICP_QAT_HW_COMP_20_DISABLE_TOKEN_FUSION_CONTROL_DISABLE = 0x1, /* Disables token fusion. */ } icp_qat_hw_comp_20_disable_token_fusion_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_DISABLE_TOKEN_FUSION_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_DISABLE_TOKEN_FUSION_CONTROL_ENABLE /*****************************************************************************/ /* LZ4 Block Maximum Size (LBMS). Set by FW , located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LBMS_BITPOS 19 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LBMS_MASK 0x3 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible LBMS field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_LBMS_LBMS_64KB = 0x0, /* LZ4 Block Maximum Size (LBMS) == 64 KB */ ICP_QAT_HW_COMP_20_LBMS_LBMS_256KB = 0x1, /* LZ4 Block Maximum Size (LBMS) == 256 KB */ ICP_QAT_HW_COMP_20_LBMS_LBMS_1MB = 0x2, /* LZ4 Block Maximum Size (LBMS) == 1 MB */ ICP_QAT_HW_COMP_20_LBMS_LBMS_4MB = 0x3, /* LZ4 Block Maximum Size (LBMS) == 4 MB */ } icp_qat_hw_comp_20_lbms_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LBMS_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_LBMS_LBMS_64KB /*****************************************************************************/ /* SCB Mode Reset Mask (Set By FW) , located in upper 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_MODE_RESET_MASK_BITPOS 18 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_MODE_RESET_MASK_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SCB_MODE_RESET_MASK field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SCB_MODE_RESET_MASK_RESET_COUNTERS = 0x0, /* LZ4 mode: Reset LIBC, LOBC, In iLZ77 mode: Reset LFCT, OBC */ ICP_QAT_HW_COMP_20_SCB_MODE_RESET_MASK_RESET_COUNTERS_AND_HISTORY = 0x1, /* LZ4 mode: Reset LIBC, LOBC, HB, HT, In iLZ77 mode: Reset LFCT, OBC, HB, HT */ } icp_qat_hw_comp_20_scb_mode_reset_mask_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SCB_MODE_RESET_MASK_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SCB_MODE_RESET_MASK_RESET_COUNTERS /*****************************************************************************/ /* Lazy - For iLZ77, LZ4, and Static DEFLATE, Lazy = 102h , located in upper * 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LAZY_PARAM_BITPOS 9 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LAZY_PARAM_MASK 0x1ff #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LAZY_PARAM_DEFAULT_VAL 258 /*****************************************************************************/ /* Nice - For iLZ77, LZ4, and Static DEFLATE, Nice = 103h , located in upper * 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_NICE_PARAM_BITPOS 0 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_NICE_PARAM_MASK 0x1ff #define ICP_QAT_HW_COMP_20_CONFIG_CSR_NICE_PARAM_DEFAULT_VAL 259 /*****************************************************************************/ /* History Buffer Size (Set By the Driver/ Application), located in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_HBS_CONTROL_BITPOS 14 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_HBS_CONTROL_MASK 0x7 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible HBS_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_HBS_CONTROL_HBS_IS_32KB = 0x0, /* 000b - 32KB */ } icp_qat_hw_comp_20_hbs_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_HBS_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_HBS_CONTROL_HBS_IS_32KB /*****************************************************************************/ /* Adaptive Block Drop (Set By FW if Dynamic), located in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_ABD_BITPOS 13 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_ABD_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible ABD field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_ABD_ABD_ENABLED = 0x0, /* 0b - Feature enabled. */ ICP_QAT_HW_COMP_20_ABD_ABD_DISABLED = 0x1, /* 1b - Feature disabled. */ } icp_qat_hw_comp_20_abd_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_ABD_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_ABD_ABD_ENABLED /*****************************************************************************/ /* Literal+Length Limit Block Drop Block Drop, (Set By FW if Dynamic) , located * in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LLLBD_CTRL_BITPOS 12 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LLLBD_CTRL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible LLLBD_CTRL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_ENABLED = 0x0, /* 0b - Feature enabled. */ ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_DISABLED = 0x1, /* 1b - Feature disabled. */ } icp_qat_hw_comp_20_lllbd_ctrl_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_LLLBD_CTRL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_ENABLED /*****************************************************************************/ /* Search Depth (SD) (Set By Driver/Application), located in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SEARCH_DEPTH_BITPOS 8 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SEARCH_DEPTH_MASK 0xf /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SEARCH_DEPTH field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_1 = 0x1, /* 0001b - Level 1 (search depth = 2^1 = 2) */ ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_6 = 0x3, /* 0001b - Level 6 (search depth = 2^3 = 8) */ ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_9 = 0x4, /* 0001b - Level 9 (search depth = 2^4 = 16) */ ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_9P = 0x12, /* 0001b - Level 9P (search depth = 2^12 = 4096) */ } icp_qat_hw_comp_20_search_depth_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SEARCH_DEPTH_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_1 /*****************************************************************************/ /* Compression Format (Set By Driver/Application. Also See CMD ID), located in * lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_HW_COMP_FORMAT_BITPOS 5 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_HW_COMP_FORMAT_MASK 0x7 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible HW_COMP_FORMAT field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_ILZ77 = 0x0, /* 000 - iLZ77. (Must set Min_Match = 3 bytes and HB size = 32KB.) */ ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_DEFLATE = 0x1, /* 001 - Static DEFLATE. (Must set Min_Match = 3 bytes and HB size = 32KB.) */ ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_LZ4 = 0x2, /* 010 - LZ4. (Must set Min Match = 4 bytes and HB size = 64KB.) */ ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_LZ4S = 0x3, /* 011 - LZ4s. (Min_Match and HBSize must be set accordingly.) */ } icp_qat_hw_comp_20_hw_comp_format_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_HW_COMP_FORMAT_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_DEFLATE /*****************************************************************************/ /* Min Match (Set By FW to default value), located in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_BITPOS 4 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible MIN_MATCH_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_MIN_MATCH_CONTROL_MATCH_3B = 0x0, /* 0 - Match 3 B */ ICP_QAT_HW_COMP_20_MIN_MATCH_CONTROL_MATCH_4B = 0x1, /* 1 - Match 4 B */ } icp_qat_hw_comp_20_min_match_control_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_MIN_MATCH_CONTROL_MATCH_3B /*****************************************************************************/ /* Skip Hash Collision (Set By FW to default value), located in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_COLLISION_BITPOS 3 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_COLLISION_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SKIP_HASH_COLLISION field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SKIP_HASH_COLLISION_ALLOW = 0x0, /* When set to 0, hash collisions are allowed. */ ICP_QAT_HW_COMP_20_SKIP_HASH_COLLISION_DONT_ALLOW = 0x1, /* When set to 0, hash collisions are allowed. */ } icp_qat_hw_comp_20_skip_hash_collision_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_COLLISION_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SKIP_HASH_COLLISION_ALLOW /*****************************************************************************/ /* Skip Hash Update (Set By FW to default value) , located in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_UPDATE_BITPOS 2 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_UPDATE_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SKIP_HASH_UPDATE field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_SKIP_HASH_UPDATE_ALLOW = 0x0, /* 0 - hash updates are not skipped. */ ICP_QAT_HW_COMP_20_SKIP_HASH_UPDATE_DONT_ALLOW = 0x1, /* 1 - hash updates are skipped. */ } icp_qat_hw_comp_20_skip_hash_update_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_SKIP_HASH_UPDATE_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_SKIP_HASH_UPDATE_ALLOW /*****************************************************************************/ /* 3-Byte Match Skip (Set By FW to default value), located in lower 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_BYTE_SKIP_BITPOS 1 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_BYTE_SKIP_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible BYTE_SKIP field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_BYTE_SKIP_3BYTE_TOKEN = 0x0, /* 0 - Use 3-byte token */ ICP_QAT_HW_COMP_20_BYTE_SKIP_3BYTE_LITERAL = 0x1, /* 0 - Use 3-byte literal */ } icp_qat_hw_comp_20_byte_skip_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_BYTE_SKIP_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_BYTE_SKIP_3BYTE_TOKEN /*****************************************************************************/ /* Extended Delayed Match Mode enabled (Set By the Driver), located in lower * 32bit */ #define ICP_QAT_HW_COMP_20_CONFIG_CSR_EXTENDED_DELAY_MATCH_MODE_BITPOS 0 #define ICP_QAT_HW_COMP_20_CONFIG_CSR_EXTENDED_DELAY_MATCH_MODE_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible EXTENDED_DELAY_MATCH_MODE field values *****************************************************************************/ typedef enum { ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_DISABLED = 0x0, /* 0 - EXTENDED_DELAY_MATCH_MODE disabled */ ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_ENABLED = 0x1, /* 1 - EXTENDED_DELAY_MATCH_MODE enabled */ } icp_qat_hw_comp_20_extended_delay_match_mode_t; #define ICP_QAT_HW_COMP_20_CONFIG_CSR_EXTENDED_DELAY_MATCH_MODE_DEFAULT_VAL \ ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_DISABLED /*****************************************************************************/ /* Speculative Decoder Disable (Set By the Driver/ Application), located in * upper 32bit */ #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_SPECULATIVE_DECODER_CONTROL_BITPOS 31 #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_SPECULATIVE_DECODER_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible SPECULATIVE_DECODER_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_DECOMP_20_SPECULATIVE_DECODER_CONTROL_ENABLE = 0x0, /* 0b - Enabled */ ICP_QAT_HW_DECOMP_20_SPECULATIVE_DECODER_CONTROL_DISABLE = 0x1, /* 1b - Disabled */ } icp_qat_hw_decomp_20_speculative_decoder_control_t; #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_SPECULATIVE_DECODER_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_DECOMP_20_SPECULATIVE_DECODER_CONTROL_ENABLE /*****************************************************************************/ /* Mini CAM Disable (Set By the Driver/ Application), located in upper 32bit */ #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_RESERVED4_CONTROL_BITPOS 30 #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_RESERVED4_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible RESERVED4 field values *****************************************************************************/ typedef enum { ICP_QAT_HW_DECOMP_20_RESERVED4_CONTROL_ENABLE = 0x0, /* 0b - Enabled */ ICP_QAT_HW_DECOMP_20_RESERVED4_CONTROL_DISABLE = 0x1, /* 1b - Disabled */ } icp_qat_hw_decomp_20_reserved4_control_t; #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_RESERVED4_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_DECOMP_20_RESERVED4_CONTROL_ENABLE /*****************************************************************************/ /* History Buffer Size (Set By the Driver/ Application), located in lower 32bit */ #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HBS_CONTROL_BITPOS 14 #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HBS_CONTROL_MASK 0x7 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible HBS_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_DECOMP_20_HBS_CONTROL_HBS_IS_32KB = 0x0, /* 000b - 32KB */ } icp_qat_hw_decomp_20_hbs_control_t; #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HBS_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_DECOMP_20_HBS_CONTROL_HBS_IS_32KB /*****************************************************************************/ /* LZ4 Block Maximum Size (LBMS). Set by FW , located in lower 32bit */ #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LBMS_BITPOS 8 #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LBMS_MASK 0x3 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible LBMS field values *****************************************************************************/ typedef enum { ICP_QAT_HW_DECOMP_20_LBMS_LBMS_64KB = 0x0, /* LZ4 Block Maximum Size (LBMS) == 64 KB */ ICP_QAT_HW_DECOMP_20_LBMS_LBMS_256KB = 0x1, /* LZ4 Block Maximum Size (LBMS) == 256 KB */ ICP_QAT_HW_DECOMP_20_LBMS_LBMS_1MB = 0x2, /* LZ4 Block Maximum Size (LBMS) == 1 MB */ ICP_QAT_HW_DECOMP_20_LBMS_LBMS_4MB = 0x3, /* LZ4 Block Maximum Size (LBMS) == 4 MB */ } icp_qat_hw_decomp_20_lbms_t; #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LBMS_DEFAULT_VAL \ ICP_QAT_HW_DECOMP_20_LBMS_LBMS_64KB /*****************************************************************************/ /* Decompression Format (Set By Driver/Application. Also See CMD ID), located in * lower 32bit */ #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HW_DECOMP_FORMAT_BITPOS 5 #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HW_DECOMP_FORMAT_MASK 0x7 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible HW_DECOMP_FORMAT field values *****************************************************************************/ typedef enum { ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_DEFLATE = 0x1, /* 001 - Static DEFLATE. (Must set Min_Match = 3 bytes and HB size = 32KB.) */ ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_LZ4 = 0x2, /* 010 - LZ4. (Must set Min Match = 4 bytes and HB size = 32KB.) */ ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_LZ4S = 0x3, /* 011 - LZ4s. (Min_Match and HBSize must be set accordingly.) */ } icp_qat_hw_decomp_20_hw_comp_format_t; #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_HW_DECOMP_FORMAT_DEFAULT_VAL \ ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_DEFLATE /*****************************************************************************/ /* Decompression Format (Set By Driver/Application. Also See CMD ID), located in * lower 32bit */ #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_BITPOS 4 #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible MIN_MATCH_CONTROL field values *****************************************************************************/ typedef enum { ICP_QAT_HW_DECOMP_20_MIN_MATCH_CONTROL_MATCH_3B = 0x0, /* 0 - Match 3 B */ ICP_QAT_HW_DECOMP_20_MIN_MATCH_CONTROL_MATCH_4B = 0x1, /* 1 - Match 4 B */ } icp_qat_hw_decomp_20_min_match_control_t; #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_MIN_MATCH_CONTROL_DEFAULT_VAL \ ICP_QAT_HW_DECOMP_20_MIN_MATCH_CONTROL_MATCH_3B /*****************************************************************************/ /* LZ4 Block Checksum Present, located in lower 32bit */ #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LZ4_BLOCK_CHECKSUM_PRESENT_BITPOS 3 #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LZ4_BLOCK_CHECKSUM_PRESENT_MASK 0x1 /* **************************************************************************** * @ingroup icp_qat_hw_defs * @description * Enumeration of possible LZ4_CHECKSUM_PRESENT field values *****************************************************************************/ typedef enum { ICP_QAT_HW_DECOMP_20_LZ4_BLOCK_CHKSUM_ABSENT = 0x0, /* the LZ4 Block does not contain the 4-byte checksum */ ICP_QAT_HW_DECOMP_20_LZ4_BLOCK_CHKSUM_PRESENT = 0x1, /* LZ4 Block contains a 4-byte checksum. */ } icp_qat_hw_decomp_20_lz4_block_checksum_present_t; #define ICP_QAT_HW_DECOMP_20_CONFIG_CSR_LZ4_BLOCK_CHECKSUM_PRESENT_DEFAULT_VAL \ ICP_QAT_HW_DECOMP_20_LZ4_BLOCK_CHKSUM_ABSENT #endif /* _ICP_QAT_HW_20_COMP_DEFS_H */ qatlib-25.08.0/quickassist/utilities/000077500000000000000000000000001503624047500175265ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/libusdm_drv/000077500000000000000000000000001503624047500220405ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/libusdm_drv/include/000077500000000000000000000000001503624047500234635ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/libusdm_drv/include/qae_mem_utils.h000066400000000000000000000735021503624047500264670ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** ***************************************************************************** * @file qae_mem_utils.h * * This file provides linux kernel memory allocation for quick assist API * *****************************************************************************/ #ifndef QAE_MEM_UTILS_H_ #define QAE_MEM_UTILS_H_ #if defined(__KERNEL__) #include #include #include #include #include #if (KERNEL_VERSION(2, 6, 38) >= LINUX_VERSION_CODE) #define kstrtoll strict_strtoll #endif /* KERNEL_VERSION */ #endif /* __KERNEL__ */ #define USDM_MOD "usdm_drv: " #define mm_err(...) pr_err(USDM_MOD __VA_ARGS__) #define mm_info(...) pr_info(USDM_MOD __VA_ARGS__) #define mm_warning(...) pr_warn(USDM_MOD __VA_ARGS__) /*define types which need to vary between 32 and 64 bit*/ #define QAE_PAGE_SHIFT 12 #define QAE_PAGE_SIZE (1UL << QAE_PAGE_SHIFT) /* QAE_NUM_PAGES_PER_ALLOC can be defined as 32 pages when library is built, default is 512 */ #ifndef QAE_NUM_PAGES_PER_ALLOC #define QAE_NUM_PAGES_PER_ALLOC 512 #endif #define STATIC static #define UNUSED(x) (void)(x) #define QAE_PHYS_ADDR uint64_t #define QAE_MEM_ZALLOC_GEN(size) kzalloc(size, GFP_KERNEL) #define QAE_MEM_FREE(ptr) \ do \ { \ if (ptr) \ { \ kfree(ptr); \ ptr = NULL; \ } \ } while (0) /* Defining Max Size limit to be used, to allocate using kmalloc as 4MB */ #define QAE_MEM_SIZE_LIMIT (1024 * 4096) /** ***************************************************************************** * @ingroup perfCodeFramework * Framework aligned memory structure. * @description * This structure is used to assist the framework in allocating aligned * memory ****************************************************************************/ typedef struct qae_mem_alloc_info_s { void *mAllocMemPtr; /* memory addr returned by the kernel */ size_t mSize; /* allocated size */ } qae_mem_alloc_info_t; enum slabType { SMALL = 0, LARGE = 1, HUGE_PAGE = 2, }; /* User space memory information structure. */ typedef struct dev_mem_info_s { int64_t nodeId; /* shared b/w user/kernel */ /* Node id for NUMA */ uint64_t size; /* shared b/w user/kernel */ /* Size of this block (bytes) */ enum slabType type; /* Slab for normal memory or large memory */ uint32_t allocations; /* user space only */ /* Huge page file descriptor */ int64_t hpg_fd; /* user space only */ /* The huge page file descriptor of each slab */ uint64_t phy_addr; /* shared b/w user/kernel */ /* Physical address of the kmalloced area */ union { void *virt_addr; /* user space only */ uint64_t padding_virt; }; /* Base address in user space - i.e. virtual address */ union { struct dev_mem_info_s *pPrev_user; /* user space only */ uint64_t padding_prevu; }; union { struct dev_mem_info_s *pNext_user; /* user space only */ uint64_t padding_nextu; }; union { struct dev_mem_info_s *pPrev_user_hash; /* user space only */ uint64_t padding_prevuh; }; union { struct dev_mem_info_s *pNext_user_hash; /* user space only */ uint64_t padding_nextuh; }; #ifdef ICP_THREAD_SPECIFIC_USDM /* These pointers are required for adding and deleting slabs * to/from TMP list. We cannot rely on existing pointers * because those are actually being filled with relevant * addresses given the slab was added to another lists. * Please see ADD_ELEMENT_TO_END_LIST, ADD_ELEMENT_TO_END_LIST * in usdm/include/qae_mem_utils.h */ union { struct dev_mem_info_s *pPrev_user_vfiotmp; /* user space only */ uint64_t padding_prevuvfio; }; union { struct dev_mem_info_s *pNext_user_vfiotmp; /* user space only */ uint64_t padding_nextuvfio; }; uint32_t flag_pinned; /* required while using TMP list */ #endif /* ICP_THREAD_SPECIFIC_USDM */ } dev_mem_info_t; typedef struct user_page_info_s { /* Use 64-bit unsigned to support 32bit application on * a 64-bit kernel */ uint64_t virt_addr; /* physical address shared b/w user/kernel */ uint64_t phy_addr; uint64_t size; } user_page_info_t; /* size of allocation unit */ #define UNIT_SIZE 1024 #define QAE_KBYTE 1024 #define QWORD_WIDTH (8 * sizeof(uint64_t)) #define QWORD_ALL_ONE 0xFFFFFFFFFFFFFFFFULL /* Bitmap is used to keep track the allocation of each block Each 1k block is represented by one bit allocated(1)/free(0) BITMAP_LEN is a macro the represents the number of 64-bit quad words that make up the bitmap with 512 pages of 4k page and 1k units this value is 32 */ #define CHUNK_SIZE (UNIT_SIZE * QWORD_WIDTH) #define BITMAP_LEN (QAE_NUM_PAGES_PER_ALLOC * QAE_PAGE_SIZE / CHUNK_SIZE) #define BLOCK_SIZES (BITMAP_LEN * QWORD_WIDTH) /*block control structure */ typedef struct block_ctrl_s { dev_mem_info_t mem_info; /* memory device info type */ /* adding an extra element at the end to make a barrier */ uint64_t bitmap[BITMAP_LEN + 1]; /* bitmap each bit represents a 1k block */ uint16_t sizes[BLOCK_SIZES]; /* Holds the size of each allocated block */ } block_ctrl_t; /** ***************************************************************************** * @ingroup qaeMemUtils * array structure * @description * This structure is used to copy chunks of data read from files * from user to kernel space ****************************************************************************/ typedef struct dev_mem_file_s { unsigned char data[2048]; unsigned int size; } dev_mem_file_t; #ifdef __KERNEL__ /* Kernel space memory information structure. */ typedef struct kdev_mem_info_s { void *kmalloc_ptr; /* kernel space only (small slab) */ /* Pointer to mem originally returned by kmalloc */ void *huge_mem_ctrl; uint64_t size; /* Slab size */ atomic_t mmap_ref; /* Mapped pages counter */ uint64_t phy_addr; /* shared b/w user/kernel */ /* Physical address of the kmalloc'ed area */ struct kdev_mem_info_s *pPrev_kernel; struct kdev_mem_info_s *pNext_kernel; struct kdev_mem_info_s *pPrev_kernel_hash; struct kdev_mem_info_s *pNext_kernel_hash; } kdev_mem_info_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory list pointer structure. * @description * This structure is used to assist in allocating aligned * memory ****************************************************************************/ typedef struct user_proc_mem_list_s { int pid; uint64_t allocs_nr; uint64_t hugepages_nr; kdev_mem_info_t *head; kdev_mem_info_t *tail; kdev_mem_info_t *hugepage_head; kdev_mem_info_t *hugepage_tail; struct user_proc_mem_list_s *pPrev_user; struct user_proc_mem_list_s *pNext_user; } user_proc_mem_list_t; /** ***************************************************************************** * @ingroup qaeMemUtils * user space memory list pointer structure. * @description * This structure is used to assist in allocating aligned * memory ****************************************************************************/ typedef struct user_mem_dev_s { user_proc_mem_list_t *head; user_proc_mem_list_t *tail; } user_mem_dev_t; #endif /* __KERNEL__ */ /* ****************************************************************************** * @ingroup ADD_ELEMENT_TO_HEAD_LIST * insert element at the head of a linked list * @description * inserts a new element at the head of a * double linked list in user or kernel mode * depending on mode parameter * elementToAdd - ptr to the new element * headPtr - ptr to the first element in list * tailPtr - ptr to the last element int the list * mode - _kernel or _user ******************************************************************************/ #define ADD_ELEMENT_TO_HEAD_LIST(elementToAdd, headPtr, tailPtr, mode) \ do \ { \ elementToAdd->pPrev##mode = NULL; \ if (NULL == headPtr) \ { \ tailPtr = elementToAdd; \ elementToAdd->pNext##mode = NULL; \ } \ else \ { \ elementToAdd->pNext##mode = headPtr; \ headPtr->pPrev##mode = elementToAdd; \ } \ headPtr = elementToAdd; \ } while (0) /* ****************************************************************************** * @ingroup ADD_ELEMENT_TO_END_LIST * insert element at the end of a linked list * @description * inserts a new element at the head of a * double linked list in user or kernel mode * depending on mode parameter * elementToAdd - ptr to the new element * headPtr - ptr to the first element in list * tailPtr - ptr to the last element int the list * mode - _kernel or _user ******************************************************************************/ #define ADD_ELEMENT_TO_END_LIST(elementToAdd, headPtr, tailPtr, mode) \ do \ { \ elementToAdd->pNext##mode = NULL; \ if (NULL == tailPtr) \ { \ headPtr = elementToAdd; \ elementToAdd->pPrev##mode = NULL; \ } \ else \ { \ elementToAdd->pPrev##mode = tailPtr; \ tailPtr->pNext##mode = elementToAdd; \ } \ tailPtr = elementToAdd; \ } while (0) /* ****************************************************************************** * @ingroup REMOVE_ELEMENT_FROM_LIST * remove element at the end of a linked list * @description * removes an element from a * double linked list in user or kernel mode * depending on mode parameter * elementToREmove - ptr to the new element * headPtr - ptr to the first element in list * tailPtr - ptr to the last element int the list * mode - _kernel or _user ******************************************************************************/ #define REMOVE_ELEMENT_FROM_LIST(elementToRemove, headPtr, tailPtr, mode) \ do \ { \ if (NULL != elementToRemove->pPrev##mode) \ { \ elementToRemove->pPrev##mode->pNext##mode = \ elementToRemove->pNext##mode; \ if (NULL != elementToRemove->pNext##mode) \ { \ elementToRemove->pNext##mode->pPrev##mode = \ elementToRemove->pPrev##mode; \ } \ else \ { \ tailPtr = elementToRemove->pPrev##mode; \ } \ } \ else \ { \ if (NULL != elementToRemove->pNext##mode) \ { \ elementToRemove->pNext##mode->pPrev##mode = NULL; \ headPtr = elementToRemove->pNext##mode; \ } \ else \ { \ headPtr = NULL; \ tailPtr = NULL; \ } \ } \ } while (0) /* IOCTL number for use between the kernel and the user space application */ #define DEV_MEM_MAGIC 'q' #define DEV_MEM_CMD_MEMALLOC (0) #define DEV_MEM_CMD_MEMFREE (1) #define DEV_MEM_CMD_RELEASE (2) #define DEV_MEM_CMD_UNREGISTER (3) #define DEV_MEM_CMD_GET_NUM_HPT (4) #define DEV_MEM_CMD_GET_USER_PAGE (5) #define DEV_MEM_CMD_HUGEPAGE_IOMMU_UNMAP (6) /* IOCTL commands for requesting kernel memory */ #define DEV_MEM_IOC_MEMALLOC \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMALLOC, dev_mem_info_t) #define DEV_MEM_IOC_MEMFREE \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMFREE, dev_mem_info_t) #define DEV_MEM_IOC_RELEASE _IO(DEV_MEM_MAGIC, DEV_MEM_CMD_RELEASE) #define DEV_MEM_IOC_UNREGISTER \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_UNREGISTER, dev_mem_info_t) #define DEV_MEM_IOC_GET_NUM_HPT \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_GET_NUM_HPT, uint32_t) #define DEV_MEM_IOC_GET_USER_PAGE \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_GET_USER_PAGE, user_page_info_t) #define DEV_MEM_IOC_HUGEPAGE_IOMMU_UNMAP \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_HUGEPAGE_IOMMU_UNMAP, user_page_info_t) /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeMemInit * * @description * Initialize the user-space allocator, opening the device driver * used to communicate with the kernel-space. * * @param[in] path - path to the specific device * * @retval 0 if the open of the device was successful and * non-zero otherwise * @pre * none * @post * Allocator is initialized * ****************************************************************************/ int32_t qaeMemInit(void); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeMemDestroy * * @description * Release the user-space allocator. It closes the file descriptor * associated with the device driver * * @param[in] none * * @retval none * * @pre * The user space allocator is initialized using qaeMemInit * @post * The user-space allocator is released * ****************************************************************************/ void qaeMemDestroy(void); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUInit * * @description * Function creates iommu domain. Applicable when IOMMU is enabled * * @param[in] none * * @retval 0 - if successful. * non-zero - otherwise * * @pre * IOMMU is enabled. * @post * iommu domain created * ****************************************************************************/ int32_t qaeIOMMUInit(void); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUExit * * @description * Function removes iommu domain. Applicable when IOMMU is enabled * * @param[in] none * * @retval none * * @pre * IOMMU is enabled and an iommu domain is created using qaeIOMMUInit * @post * iommu domain removed * ****************************************************************************/ void qaeIOMMUExit(void); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUgetRemappingSize * * @description * Function calculates size for remapping when IOMMU is enabled. * Before calling any of the qaeMemAlloc functions, this function can be * used to calculate the actual size of memory to be allocated. * The remapping size is at least PAGE_SIZE. * * @param[in] size - Actual size of the memory to be allocated * * @retval Remapping size * * @pre * IOMMU is enabled and an iommu domain is created using qaeIOMMUInit. * @post * Remapping size provided. * ****************************************************************************/ size_t qaeIOMMUgetRemappingSize(size_t size); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUMap * * @description * Function adds mapping from io virtual address to a physical address. * Applicable when IOMMU is enabled * * @param[in] phaddr - Host physical address. * @param[in] iova - IO virtual address. * @param[in] size - Memory size to be remapped obtained from * qaeIOMMUgetRemappingSize() function. * * @retval CPA_STATUS_SUCCESS - if successful. * CPA_STATUS_UNSUPPORTED - if not supported * CPA_STATUS_FAIL - otherwise * * @pre * An iommu domain is created using qaeIOMMUInit. iova points to * previously allocated memory. phaddr is already obtained using * iova using virt_to_phys or similar functions. size is calculated * using qaeIOMMUgetRemappingSize function. * @post * IO virtual address mapped ****************************************************************************/ int32_t qaeIOMMUMap(uint64_t phaddr, uint64_t iova, size_t size); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUUnmap * * @description * Function removes mapping from io virtual address to a physical * address. Applicable when IOMMU is enabled * * @param[in] iova - IO virtual address. * @param[in] size - Memory size to be unmapped * * @retval CPA_STATUS_SUCCESS - if successful. * CPA_STATUS_UNSUPPORTED - if not supported * CPA_STATUS_FAIL - otherwise * * @pre * An iommu domain is created using qaeIOMMUInit. iova points to * previously allocated memory. * @post * IO virtual address unmapped ****************************************************************************/ int32_t qaeIOMMUUnmap(uint64_t iova, size_t size); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUVirtToPhys * * @description * Function translates io virtual address to a physical address. * Applicable when IOMMU is enabled. * * @param[in] iova, IO virtual address * * @retval host physical address - if successful * NULL Otherwise * * @pre * An iommu domain is created using qaeIOMMUInit. iova points to * previously allocated memory. * @post * virtual address is translated to physical address * ****************************************************************************/ uint64_t qaeIOMMUVirtToPhys(uint64_t iova); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUAttachDev * * @description * This function attaches a pci dev (VF) to an iommu domain. * Applicable when IOMMU/SRIOV are enabled and after the driver bringup * in Host is successful. * * @param[in] dev, Device to be attached * * @retval CPA_STATUS_SUCCESS - if successful * CPA_STATUS_UNSUPPORTED - if not supported * CPA_STATUS_FAIL - otherwise * * @pre * An iommu domain is created using qaeIOMMUInit. Driver bringup * in Host is successful. * @post * device is attached * ****************************************************************************/ int32_t qaeIOMMUAttachDev(void *dev); /***************************************************************************** * * @ingroup CommonMemoryDriver * qaeIOMMUDetachDev * * @description * Function detaches pci dev to iommu domain * * @param[in] dev, Device to be detached * * @retval none * * @pre * An iommu domain is created using qaeIOMMUInit, Driver bringup * in Host is successful and dev is already * attached using qaeIOMMUAttachDev * @post * Device is detached * ****************************************************************************/ void qaeIOMMUDetachDev(void *dev); /** ***************************************************************************** * @ingroup CommonMemoryDriver * printMemAllocations * * @description * Prints only the overall count of NUMA and non-NUMA memory allocations * performed. This doesn't provide other details like the allocation * sizes, pointers etc. * * @retval none * * @pre * The user space allocator is initialized using qaeMemInit * @post * memory allocation count printed * ****************************************************************************/ void printMemAllocations(void); #ifndef __KERNEL__ #ifdef ICP_WITHOUT_THREAD #define mem_mutex_lock(x) (0) #define mem_mutex_unlock(x) (0) #else #define mem_mutex_lock(x) pthread_mutex_lock(x) #define mem_mutex_unlock(x) pthread_mutex_unlock(x) #endif #define mem_ioctl(fd, cmd, pMemInfo) ioctl(fd, cmd, pMemInfo) #define qae_open(file, options) open(file, options) #define qae_close(fd) close(fd) #define qae_lseek(fd, offset, whence) lseek(fd, offset, whence) #define qae_read(fd, buf, nbytes) read(fd, buf, nbytes) #define qae_mmap(addr, length, prot, flags, fd, offset) \ mmap(addr, length, prot, flags, fd, offset) #define qae_munmap(addr, length) munmap(addr, length) #define qae_madvise(addr, len, advice) madvise(addr, len, advice) #define qae_fopen(filename, operation) fopen(filename, operation) #define qae_fgets(str, n, stream) fgets(str, n, stream) #define qae_opendir(dirname) opendir(dirname) #define qae_mkstemp(template) mkstemp(template) #endif #if defined(__KERNEL__) int handle_other_ioctls(uint32_t cmd); #if defined(ICP_ADF_IOMMU) int icp_adf_iommu_map(void *iova, void *phaddr, size_t size); int icp_adf_iommu_unmap(void *iova, size_t size); size_t icp_adf_iommu_get_remapping_size(size_t size); static inline int icp_iommu_map(void **iova, void *vaddr, size_t size) { void *phaddr = (void *)virt_to_phys(vaddr); *iova = phaddr; return icp_adf_iommu_map(*iova, phaddr, size); } static inline int icp_iommu_unmap(void *iova, size_t size) { return icp_adf_iommu_unmap(iova, size); } static inline size_t icp_iommu_get_remapping_size(size_t size) { return icp_adf_iommu_get_remapping_size(size); } #elif defined(ICP_OSAL_IOMMU) int osalIOMMUMap(uint64_t iova, uint64_t phaddr, size_t size); static inline int icp_iommu_map(void **iova, void *vaddr, size_t size) { void *phaddr = (void *)virt_to_phys(vaddr); *iova = phaddr; return osalIOMMUMap((uintptr_t)*iova, phaddr, size); } int osalIOMMUUnmap(uint64_t iova, size_t size); static inline int icp_iommu_unmap(void *iova, size_t size) { return osalIOMMUUnmap((uintptr_t)iova, size); } uint64_t osalIOMMUVirtToPhys(uint64_t iova); static inline uint64_t icp_iommu_virt_to_phys(void *iova) { return osalIOMMUVirtToPhys((uintptr_t)iova); } size_t osalIOMMUgetRemappingSize(size_t size); static inline size_t icp_iommu_get_remapping_size(size_t size) { return osalIOMMUgetRemappingSize(size); } #elif defined(ICP_QDM_IOMMU) int qdm_iommu_map(void **iova, void *vaddr, size_t size); int qdm_iommu_unmap(void *iova, size_t size); int qdm_hugepage_iommu_map(void **iova, void *va_page, size_t size); static inline int icp_iommu_map(void **iova, void *vaddr, size_t size) { return qdm_iommu_map(iova, vaddr, size); } static inline int icp_iommu_unmap(void *iova, size_t size) { return qdm_iommu_unmap(iova, size); } static inline int icp_hugepage_iommu_map(void **iova, void *va_page, size_t size) { return qdm_hugepage_iommu_map(iova, va_page, size); } static inline int icp_hugepage_iommu_unmap(void *iova, size_t size) { return qdm_iommu_unmap(iova, size); } static inline size_t icp_iommu_get_remapping_size(size_t size) { return (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); } #else #define ICP_IOMMU_DISABLED static inline int icp_iommu_map(void **iova, void *vaddr, size_t size) { *iova = (void *)(uintptr_t)virt_to_phys(vaddr); return 0; } static inline int icp_iommu_unmap(void *iova, size_t size) { return 0; } static inline int icp_hugepage_iommu_map(void **iova, void *va_page, size_t size) { *iova = (void *)(uintptr_t)page_to_phys((struct page *)va_page); return 0; } static inline int icp_hugepage_iommu_unmap(void *iova, size_t size) { return 0; } static inline size_t icp_iommu_get_remapping_size(size_t size) { return (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); } #endif #endif #endif qatlib-25.08.0/quickassist/utilities/libusdm_drv/qae_mem.h000066400000000000000000000236141503624047500236230ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** *************************************************************************** * @file qae_mem.h * * This file provides linux/FreeBSD memory allocation for quick assist API * ****************************************************************************/ #ifndef QAE_MEM_H_ #define QAE_MEM_H_ #ifdef __cplusplus extern "C" { #endif #ifdef __KERNEL__ #include #else #include #include #endif /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeMemAlloc * * @brief * When used in user space, allocates memsize bytes of virtual memory. * When used in kernel space, allocates memsize bytes of contiguous and * pinned memory. * * @param[in] memsize - the amount of memory in bytes to be allocated * * @retval pointer to the allocated memory or NULL if the allocation failed * * @pre * none * @post * memory is allocated and the pointer to the allocated memory location * is returned * ****************************************************************************/ void *qaeMemAlloc(size_t memsize); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeMemFree * * @brief * Frees memory allocated by the qaeMemAlloc function. * Applicable for both user and kernel spaces. * * @param[in] ptr - Address of the pointer to the memory to be freed * * @retval none * * @pre * *ptr points to memory previously allocated by qaeMemAlloc * @post * memory is freed and pointer value is set to NULL * ****************************************************************************/ void qaeMemFree(void **ptr); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeMemAllocNUMA * * @brief * Allocates and returns virtual memory mapped to pinned, contiguous * physical memory aligned to phys_alignment_byte. This API enables * user to choose a CPU node nearest to QAT device. This API is applicable * for both user and kernel spaces. Based on the address space used, * memory mapped from corresponding virtual address space will be returned. * * @param[in] size - A non-zero value representing the amount of memory in * bytes to be allocated. It cannot exceed QAE_MAX_ALLOC_SIZE. * @param[in] node - NUMA node * @param[in] phys_alignment_byte - A non-zero value representing memory * boundary alignment in bytes. It must * be in powers of 2 not exceeding 4MB. * * @retval pointer to the allocated memory or NULL if the allocation failed * * @pre * none * @post * memory is allocated and pointer to the allocated memory is returned * ****************************************************************************/ void *qaeMemAllocNUMA(size_t size, int node, size_t phys_alignment_byte); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeMemFreeNUMA * * @brief * Frees memory allocated by the qaeMemAllocNUMA function. * Applicable for both user and kernel spaces. * * @param[in] ptr - Address of pointer to the memory to be freed * * @retval none * * @pre * *ptr points to memory previously allocated by qaeMemAllocNUMA * @post * memory is freed and the pointer value is set to NULL * ****************************************************************************/ void qaeMemFreeNUMA(void **ptr); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeMemFreeNonZeroNUMA * * @brief * Frees memory allocated by qaeMemAllocNUMA function. * Does not clear the memory region before freeing unlike other API. * Applicable for user space only. * * @param[in] ptr - Address of pointer to the memory to be freed * * @retval none * * @pre * *ptr points to memory previously allocated by qaeMemAllocNUMA * @post * memory is freed and the pointer value is set to NULL * ****************************************************************************/ void qaeMemFreeNonZeroNUMA(void **ptr); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeVirtToPhysNUMA * * @brief * Converts a virtual address provided by qaeMemAllocNUMA to a * physical one. Applicable for both user and kernel spaces. * * @param[in] pVirtAddr - pointer to the virtual address * * @retval pointer to the physical address or 0(NULL) on error * * @pre * pVirtAddr points to memory previously allocated by qaeMemAllocNUMA * @post * Appropriate physical address is provided * ****************************************************************************/ uint64_t qaeVirtToPhysNUMA(void *pVirtAddr); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaePhysToVirtNUMA * * @brief * Translates a physical address to a virtual one of a memory allocated * by qaeMemAllocNUMA() function. Applicable for user space. * * @param[in] physAddress - physical address * * @retval pointer to the virtual address or 0 (NULL) on error * * @pre * physAddress points to memory previously allocated by qaeMemAllocNUMA * @post * Appropriate virtual address is provided * ****************************************************************************/ void *qaePhysToVirtNUMA(uint64_t physAddress); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeRegisterDevice * * @brief * Registers a vfio device file descriptor * * @param[in] fd - file descriptor * * @retval 0 on success * * @pre * none * * @post * ****************************************************************************/ int qaeRegisterDevice(int fd); /** ***************************************************************************** * @ingroup CommonMemoryDriver * qaeUnregisterDevice * * @brief * Unregisters a vfio device file descriptor * * @param[in] fd - file descriptor * * @retval 0 on success * * @pre * none * * @post * ****************************************************************************/ int qaeUnregisterDevice(int fd); #ifndef __KERNEL__ /*! Define a constant for user space to select any available NUMA node */ #define NUMA_ANY_NODE (-1) /** *************************************************************************** * @ingroup CommonMemoryDriver * qaeAtFork * * @brief * Must be called when child process is forked to adjust the kernel * memory map page. * * @param[in] - none * * @retval none * ****************************************************************************/ void qaeAtFork(void); #endif #ifdef __cplusplus } /* close the extern "C" { */ #endif #endif /* #ifndef QAE_MEM_H_ */ qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/000077500000000000000000000000001503624047500241715ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_common.c000066400000000000000000000460241503624047500273170ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_common.c * * This file provides for Linux user space memory allocation. It uses * a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the quick assist sample code * ***************************************************************************/ #include "qae_mem_lib_utils.h" #include "qae_mem_utils_common.h" /* Maximum supported alignment is 4M. */ #define QAE_MAX_PHYS_ALIGN (0x400000ULL) /* Current cached memory size. */ size_t g_cache_size = 0; /* Maximum cached memory size, 8 Mb by default */ size_t g_max_cache = MAX_CACHE_DEPTH_MB; /* The maximum number we allow to search for available size */ size_t g_max_lookup_num = 10; /* User space page table for fast virtual to physical address translation */ page_table_t g_page_table = { { { 0 } } }; /* User space hash for fast slab searching */ slab_list_t g_slab_list[PAGE_SIZE] = { { 0 } }; #ifndef ICP_WITHOUT_THREAD pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif API_LOCAL dev_mem_info_t *__qae_pUserCacheHead = NULL; API_LOCAL dev_mem_info_t *__qae_pUserCacheTail = NULL; API_LOCAL dev_mem_info_t *__qae_pUserMemListHead = NULL; API_LOCAL dev_mem_info_t *__qae_pUserMemListTail = NULL; API_LOCAL dev_mem_info_t *__qae_pUserLargeMemListHead = NULL; API_LOCAL dev_mem_info_t *__qae_pUserLargeMemListTail = NULL; free_page_table_fptr_t free_page_table_fptr = free_page_table; load_key_fptr_t load_key_fptr = load_key; API_LOCAL dev_mem_info_t *__qae_userMemLookupBySize(size_t size, int node, void **block, const size_t align) { dev_mem_info_t *pCurr = NULL; size_t link_num = 0; for (pCurr = __qae_pUserMemListHead; pCurr != NULL; pCurr = pCurr->pNext_user) { if (g_strict_node && (pCurr->nodeId != node)) { continue; } *block = __qae_mem_alloc((block_ctrl_t *)pCurr, size, align); if (NULL != *block) { return pCurr; } /* Prevent from visiting whole chain, because after the first * several node, the chance to get one is very small. * Another consideration is to prevent new allocation from old * link, so that the old link could be released */ link_num++; if (link_num >= g_max_lookup_num) { break; } } return NULL; } /* translate a physical address to a virtual address */ void *qaePhysToVirtNUMA(uint64_t physAddress) { int status; dev_mem_info_t *slab; uintptr_t offset; void *ret = NULL; status = mem_mutex_lock(&mutex); if (status) { CMD_ERROR("%s:%d Error on thread mutex lock %s\n", __func__, __LINE__, strerror(status)); return NULL; } /* find slab from physical address without using hash lookup */ for (slab = __qae_pUserMemListHead; slab != NULL; slab = slab->pNext_user) { offset = (uintptr_t)physAddress - (uintptr_t)slab->phy_addr; if (offset < slab->size) { ret = (void *)((uintptr_t)slab->virt_addr + offset); break; } } status = mem_mutex_unlock(&mutex); if (status) { CMD_ERROR("%s:%d Error on thread mutex unlock %s\n", __func__, __LINE__, strerror(status)); return NULL; } return ret; } static int32_t memoryRemap(dev_mem_info_t *head) { // NOT SUPPORTED if (NULL != head) { CMD_ERROR("%s:%d not supported \n", __func__, __LINE__); return -EIO; } return 0; } void qaeAtFork() { int ret = 0; int32_t status0 = 0; int32_t status1 = 0; int32_t status2 = 0; ret = mem_mutex_lock(&mutex); if (unlikely(ret)) { CMD_ERROR( "%s:%d Error(%d) on thread mutex lock \n", __func__, __LINE__, ret); return; } status0 = memoryRemap(__qae_pUserCacheHead); status1 = memoryRemap(__qae_pUserMemListHead); status2 = memoryRemap(__qae_pUserLargeMemListHead); ret = mem_mutex_unlock(&mutex); if (unlikely(ret)) { CMD_ERROR("%s:%d Error on thread mutex unlock %s\n", __func__, __LINE__, strerror(ret)); goto fork_exit; } fork_exit: if (unlikely(status0)) { CMD_ERROR( "%s:%d Failed to remap memory allocations \n", __func__, __LINE__); } if (unlikely(status1)) { CMD_ERROR( "%s:%d Failed to remap memory allocations \n", __func__, __LINE__); } if (unlikely(status2)) { CMD_ERROR("%s:%d Failed to remap large memory allocations \n", __func__, __LINE__); } return; } API_LOCAL void __qae_free_slab(const int fd, dev_mem_info_t *slab) { dev_mem_info_t memInfo; int ret = 0; del_slab_from_hash(slab); memcpy(&memInfo, slab, sizeof(dev_mem_info_t)); /* Need to disconnect from original chain */ ret = qae_munmap(memInfo.virt_addr, memInfo.size); if (ret) { CMD_ERROR("%s:%d munmap failed, ret = %d\n", __func__, __LINE__, ret); } if (LARGE == memInfo.type) { ret = qae_munmap(slab, getpagesize()); if (ret) { CMD_ERROR( "%s:%d munmap failed, ret = %d\n", __func__, __LINE__, ret); } } __qae_finish_free_slab(fd, &memInfo); } API_LOCAL dev_mem_info_t *__qae_find_slab(const int fd, const size_t size, const int node, void **addr, const size_t align) { dev_mem_info_t *slab = __qae_userMemLookupBySize(size, node, addr, align); if (NULL == slab) { slab = pop_slab(node); if (NULL != slab) { *addr = init_slab_and_alloc((block_ctrl_t *)slab, size, align); if (NULL == *addr) { CMD_ERROR("%s:%d Memory allocation failed Virtual address: %p " " Size: %zu \n", __func__, __LINE__, slab, size); __qae_free_slab(fd, slab); return NULL; } } } return slab; } API_LOCAL void __qae_ResetControl(void) { /* Reset all control structures. */ free_page_table_fptr(&g_page_table); memset(&g_page_table, 0, sizeof(g_page_table)); memset(&g_slab_list, 0, sizeof(g_slab_list)); g_cache_size = 0; __qae_pUserCacheHead = NULL; __qae_pUserCacheTail = NULL; __qae_pUserMemListHead = NULL; __qae_pUserMemListTail = NULL; __qae_pUserLargeMemListHead = NULL; __qae_pUserLargeMemListTail = NULL; } int32_t qaeMemInit() { int32_t fd_status = 0; int32_t status = 0; status = mem_mutex_lock(&mutex); if (status) { CMD_ERROR("%s:%d Error on thread mutex lock %s\n", __func__, __LINE__, strerror(status)); return -EIO; } fd_status = __qae_open(); status = mem_mutex_unlock(&mutex); if (status) { CMD_ERROR("%s:%d Error on thread mutex unlock %s\n", __func__, __LINE__, strerror(status)); return -EIO; } return fd_status; } API_LOCAL void __qae_destroyList(const int fd, dev_mem_info_t *pList) { dev_mem_info_t *pCurr = pList; while (pCurr) { dev_mem_info_t *next = pCurr->pNext_user; __qae_free_slab(fd, pCurr); pCurr = next; } } API_LOCAL void __qae_reset_cache(const int fd) { dev_mem_info_t *slab = NULL; do { slab = pop_slab(NUMA_ANY_NODE); if (NULL != slab) __qae_free_slab(fd, slab); } while (slab != NULL); } void qaeMemDestroy(void) { int ret = 0; /* Free all of the chains */ ret = mem_mutex_lock(&mutex); if (unlikely(ret)) { CMD_ERROR( "%s:%d Error(%d) on thread mutex lock \n", __func__, __LINE__, ret); return; } /* release all control buffers */ free_page_table_fptr(&g_page_table); __qae_reset_cache(g_fd); __qae_destroyList(g_fd, __qae_pUserMemListHead); __qae_destroyList(g_fd, __qae_pUserLargeMemListHead); __qae_pUserCacheHead = NULL; __qae_pUserCacheTail = NULL; __qae_pUserMemListHead = NULL; __qae_pUserMemListTail = NULL; __qae_pUserLargeMemListHead = NULL; __qae_pUserLargeMemListTail = NULL; __qae_free_special(); ret = mem_mutex_unlock(&mutex); if (unlikely(ret)) { CMD_ERROR("%s:%d Error(%d) on thread mutex unlock\n", __func__, __LINE__, ret); } } API_LOCAL void *__qae_alloc_addr(size_t size, const int node, const size_t phys_alignment_byte) { dev_mem_info_t *p_ctrl_blk = NULL; void *pVirtAddress = NULL; size_t allocate_pages = 0; enum slabType mem_type = SMALL; const size_t phys_align_unit = phys_alignment_byte / UNIT_SIZE; const size_t reserved = div_round_up(sizeof(block_ctrl_t), UNIT_SIZE); /* calculate units needed */ const size_t requested_pages = div_round_up(size, UNIT_SIZE) + reserved; if (0 != __qae_open()) return NULL; if (requested_pages > QAE_NUM_PAGES_PER_ALLOC * QAE_PAGE_SIZE / UNIT_SIZE || phys_alignment_byte >= QAE_NUM_PAGES_PER_ALLOC * QAE_PAGE_SIZE) { mem_type = LARGE; /* Huge page and Large memory are mutually exclusive * Since Large slabs are NOT 2 MB aligned, but huge * pages are always 2 MB aligned. */ if (__qae_hugepage_enabled()) return NULL; size = MAX(size, phys_alignment_byte); allocate_pages = div_round_up(size, UNIT_SIZE); } else { allocate_pages = QAE_NUM_PAGES_PER_ALLOC * QAE_PAGE_SIZE / UNIT_SIZE; if (__qae_hugepage_enabled()) mem_type = HUGE_PAGE; p_ctrl_blk = __qae_find_slab(g_fd, size, node, &pVirtAddress, phys_align_unit); if (p_ctrl_blk) { p_ctrl_blk->allocations += 1; return pVirtAddress; } } /* Try to allocate memory as much as possible */ p_ctrl_blk = __qae_alloc_slab( g_fd, allocate_pages * UNIT_SIZE, phys_alignment_byte, node, mem_type); if (NULL == p_ctrl_blk) return NULL; store_mmap_range(&g_page_table, p_ctrl_blk->virt_addr, p_ctrl_blk->phy_addr, p_ctrl_blk->size, __qae_hugepage_enabled()); if (LARGE == mem_type) { p_ctrl_blk->allocations = 1; ADD_ELEMENT_TO_HEAD_LIST(p_ctrl_blk, __qae_pUserLargeMemListHead, __qae_pUserLargeMemListTail, _user); pVirtAddress = p_ctrl_blk->virt_addr; } else { p_ctrl_blk->allocations = 1; if ((uintptr_t)p_ctrl_blk->virt_addr % QAE_PAGE_SIZE) { CMD_ERROR("%s:%d Bad virtual address alignment %lux %x %lux\n", __func__, __LINE__, (uintptr_t)p_ctrl_blk->virt_addr, QAE_NUM_PAGES_PER_ALLOC, QAE_PAGE_SIZE); __qae_free_slab(g_fd, p_ctrl_blk); return NULL; } pVirtAddress = init_slab_and_alloc( (block_ctrl_t *)p_ctrl_blk, size, phys_align_unit); if (NULL == pVirtAddress) { CMD_ERROR("%s:%d Memory allocation failed Virtual address: %p " " Size: %zu \n", __func__, __LINE__, p_ctrl_blk, size); __qae_free_slab(g_fd, p_ctrl_blk); return NULL; } } return pVirtAddress; } void *qaeMemAllocNUMA(size_t size, int node, size_t phys_alignment_byte) { void *pVirtAddress = NULL; int ret = 0; if (!size) { CMD_ERROR("%s:%d Size cannot be zero \n", __func__, __LINE__); return NULL; } if (size > QAE_MAX_ALLOC_SIZE) { CMD_ERROR( "%s:%d Size cannot exceed 64M for vfio\n", __func__, __LINE__); return NULL; } if (!phys_alignment_byte || phys_alignment_byte > QAE_MAX_PHYS_ALIGN || (phys_alignment_byte & (phys_alignment_byte - 1))) { CMD_ERROR("%s:%d Invalid alignment parameter %zu. It must be non zero, " "not more than %llu and multiple of 2 \n", __func__, __LINE__, phys_alignment_byte, QAE_MAX_PHYS_ALIGN); return NULL; } ret = mem_mutex_lock(&mutex); if (unlikely(ret)) { CMD_ERROR("%s:%d Error on thread mutex lock %s\n", __func__, __LINE__, strerror(ret)); return NULL; } pVirtAddress = __qae_alloc_addr(size, node, phys_alignment_byte); ret = mem_mutex_unlock(&mutex); if (unlikely(ret)) { CMD_ERROR("%s:%d Error on thread mutex unlock %s\n", __func__, __LINE__, strerror(ret)); return NULL; } return pVirtAddress; } API_LOCAL void __qae_free_addr(void **p_va, bool secure_free) { dev_mem_info_t *p_ctrl_blk = NULL; if (0 != __qae_open()) return; if ((p_ctrl_blk = find_slab_in_hash(*p_va)) == NULL) { CMD_ERROR("%s:%d Unable to free as lookup failed on address (%p) " "provided \n", __func__, __LINE__, *p_va); return; } if (SMALL == p_ctrl_blk->type || HUGE_PAGE == p_ctrl_blk->type) { if (__qae_mem_free((block_ctrl_t *)p_ctrl_blk, *p_va, secure_free)) { p_ctrl_blk->allocations -= 1; } else { /*Skip push_slab(p_ctrl_blk)) and return when mem_free fails */ CMD_ERROR("%s:%d mem_free returned false (%p) " "provided \n", __func__, __LINE__, *p_va); *p_va = NULL; return; } if (p_ctrl_blk->allocations) { *p_va = NULL; return; } REMOVE_ELEMENT_FROM_LIST( p_ctrl_blk, __qae_pUserMemListHead, __qae_pUserMemListTail, _user); if (0 != push_slab(p_ctrl_blk)) __qae_free_slab(g_fd, p_ctrl_blk); } else { REMOVE_ELEMENT_FROM_LIST(p_ctrl_blk, __qae_pUserLargeMemListHead, __qae_pUserLargeMemListTail, _user); __qae_free_slab(g_fd, p_ctrl_blk); } *p_va = NULL; } /* __qae_memFreeNUMA function * Frees memory pointed by ptr. * ptr refers to memory allocated by qaeMemAllocNUMA function. * secure_free is a boolean to perform memory free secured or not. */ API_LOCAL void __qae_memFreeNUMA(void **ptr, bool secure_free) { int ret = 0; if (NULL == ptr) { CMD_ERROR( "%s:%d Input parameter cannot be NULL \n", __func__, __LINE__); return; } if (NULL == *ptr) { CMD_ERROR( "%s:%d Address to be freed cannot be NULL \n", __func__, __LINE__); return; } ret = mem_mutex_lock(&mutex); if (ret) { CMD_ERROR("%s:%d Error on thread mutex lock %s\n", __func__, __LINE__, strerror(ret)); return; } __qae_free_addr(ptr, secure_free); ret = mem_mutex_unlock(&mutex); if (ret) { CMD_ERROR("%s:%d Error on thread mutex unlock %s\n", __func__, __LINE__, strerror(ret)); } return; } qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_hugepage_utils.h000066400000000000000000000107531503624047500310410ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_hugepage_utils.h * * This file provides API for utilities of Linux/FreeBSD user space memory * allocation with huge page enabled. * ***************************************************************************/ #ifndef QAE_MEM_HUGEPAGE_UTILS_H #define QAE_MEM_HUGEPAGE_UTILS_H #include "qae_mem_utils.h" #include "qae_mem_user_utils.h" API_LOCAL uint64_t __qae_hugepage_virt2phy(const int fd, const void *virtaddr, const size_t size); API_LOCAL void *__qae_hugepage_mmap_phy_addr(const size_t len); API_LOCAL int __qae_hugepage_iommu_unmap(const int fd, const dev_mem_info_t *memInfo); API_LOCAL dev_mem_info_t *__qae_hugepage_alloc_slab(const int fd, const size_t size, const int node, enum slabType type); API_LOCAL dev_mem_info_t *__qae_vfio_hugepage_alloc_slab(const int fd, const size_t size, const int node, enum slabType type, const uint32_t alignment); API_LOCAL void __qae_hugepage_free_slab(const dev_mem_info_t *memInfo); API_LOCAL void __qae_vfio_hugepage_free_slab(dev_mem_info_t *memInfo); API_LOCAL int __qae_init_hugepages(const int fd); API_LOCAL int __qae_vfio_init_hugepages(void); API_LOCAL int __qae_hugepage_enabled(void); #endif qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_lib_utils.h000066400000000000000000000176711503624047500300300ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_lib_utils.h * * This file provides for Linux user space memory allocation. It uses * a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the quick assist sample code * ***************************************************************************/ #ifndef QAE_MEM_COMMON_H #define QAE_MEM_COMMON_H #include #include #include #include #include #include #include #include #include #include #include #ifndef ICP_WITHOUT_THREAD #include #endif #include #include #include #include #include "qae_mem.h" #include "qae_mem_utils.h" #include "qae_mem_user_utils.h" #include "qae_page_table_common.h" #include "qae_mem_hugepage_utils.h" #include "qae_mem_utils_common.h" extern int g_strict_node; /* Current cached memory size. */ extern size_t g_cache_size; /* Maximum cached memory size, 8 Mb by default */ extern size_t g_max_cache; /* User space hash for fast slab searching */ extern slab_list_t g_slab_list[PAGE_SIZE]; extern dev_mem_info_t *__qae_pUserCacheHead; extern dev_mem_info_t *__qae_pUserCacheTail; extern dev_mem_info_t *__qae_pUserMemListHead; extern dev_mem_info_t *__qae_pUserMemListTail; extern dev_mem_info_t *__qae_pUserLargeMemListHead; extern dev_mem_info_t *__qae_pUserLargeMemListTail; extern uint32_t numaAllocations_g; API_LOCAL void __qae_ResetControl(void); API_LOCAL dev_mem_info_t *__qae_userMemLookupBySize(size_t size, int node, void **block, const size_t align); API_LOCAL void __qae_free_slab(const int fd, dev_mem_info_t *slab); API_LOCAL dev_mem_info_t *__qae_find_slab(const int fd, const size_t size, const int node, void **addr, const size_t align); API_LOCAL int __qae_open(void); API_LOCAL void __qae_destroyList(const int fd, dev_mem_info_t *pList); API_LOCAL void __qae_reset_cache(const int fd); API_LOCAL int __qae_free_special(void); API_LOCAL dev_mem_info_t *__qae_alloc_slab(const int fd, const size_t size, const uint32_t alignment, const int node, enum slabType type); static inline void add_slab_to_hash(dev_mem_info_t *slab) { const size_t key = get_key(slab->phy_addr); ADD_ELEMENT_TO_HEAD_LIST( slab, g_slab_list[key].head, g_slab_list[key].tail, _user_hash); } static inline void del_slab_from_hash(dev_mem_info_t *slab) { const size_t key = get_key(slab->phy_addr); REMOVE_ELEMENT_FROM_LIST( slab, g_slab_list[key].head, g_slab_list[key].tail, _user_hash); } static inline dev_mem_info_t *find_slab_in_hash(void *virt_addr) { const size_t key = load_key_fptr(&g_page_table, virt_addr); dev_mem_info_t *slab = g_slab_list[key].head; while (slab) { uintptr_t offs = (uintptr_t)virt_addr - (uintptr_t)slab->virt_addr; if (offs < slab->size) return slab; slab = slab->pNext_user_hash; } return NULL; } static inline void *init_slab_and_alloc(block_ctrl_t *slab, const size_t size, const size_t phys_align_unit) { const size_t last = slab->mem_info.size / CHUNK_SIZE; dev_mem_info_t *p_ctrl_blk = &slab->mem_info; const size_t reserved = div_round_up(sizeof(block_ctrl_t), UNIT_SIZE); void *virt_addr = NULL; /* initialise the bitmap to 1 for reserved blocks */ set_bitmap(slab->bitmap, 0, reserved); /* make a barrier to stop search at the end of the bitmap */ slab->bitmap[last] = QWORD_ALL_ONE; virt_addr = __qae_mem_alloc(slab, size, phys_align_unit); if (NULL != virt_addr) { ADD_ELEMENT_TO_HEAD_LIST( p_ctrl_blk, __qae_pUserMemListHead, __qae_pUserMemListTail, _user); } return virt_addr; } static inline int push_slab(dev_mem_info_t *slab) { if (g_cache_size + slab->size <= g_max_cache) { g_cache_size += slab->size; ADD_ELEMENT_TO_HEAD_LIST( slab, __qae_pUserCacheHead, __qae_pUserCacheTail, _user); return 0; } return -ENOMEM; } static inline dev_mem_info_t *pop_slab(const int node) { dev_mem_info_t *slab = NULL; for (slab = __qae_pUserCacheHead; slab != NULL; slab = slab->pNext_user) { if (node != NUMA_ANY_NODE) if (g_strict_node && (node != slab->nodeId)) continue; g_cache_size -= slab->size; REMOVE_ELEMENT_FROM_LIST( slab, __qae_pUserCacheHead, __qae_pUserCacheTail, _user); return slab; } return NULL; } #endif /* QAE_MEM_COMMON_H */ qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_multi_thread.h000066400000000000000000000227541503624047500305210ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_utils_common.h * * This file provides for Linux user space memory allocation. It uses * a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the quick assist sample code * ***************************************************************************/ #ifndef QAE_MEM_MULTI_THREAD_H #define QAE_MEM_MULTI_THREAD_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qae_mem.h" #include "qae_mem_utils.h" #include "qae_mem_user_utils.h" #include "qae_page_table_common.h" #include "qae_mem_hugepage_utils.h" #include "qae_mem_utils_common.h" #ifdef ICP_THREAD_SPECIFIC_USDM #define PINNED 1 #define NOT_PINNED 0 typedef struct { dev_mem_info_t *pUserCacheHead; dev_mem_info_t *pUserCacheTail; dev_mem_info_t *pUserMemListHead; dev_mem_info_t *pUserMemListTail; dev_mem_info_t *pUserLargeMemListHead; dev_mem_info_t *pUserLargeMemListTail; size_t g_cache_size; size_t g_max_cache; size_t g_max_lookup_num; slab_list_t g_slab_list[PAGE_SIZE]; int g_strict_node; uint32_t numaAllocations_g; uint32_t thd_process_id; } qae_mem_info_t; extern slab_list_t g_slab_tmp_list; extern pthread_mutex_t mutex_tmp_list; extern pthread_key_t qae_key; extern pthread_once_t qae_key_once; extern __thread int qae_mem_inited; API_LOCAL dev_mem_info_t *__qae_userMemLookupBySize(size_t size, int node, void **block, const size_t align, qae_mem_info_t *tls_ptr); API_LOCAL int __qae_free_special(void); API_LOCAL void __qae_free_slab(const int fd, dev_mem_info_t *slab, qae_mem_info_t *tls_ptr); API_LOCAL dev_mem_info_t *__qae_find_slab(const int fd, const size_t size, const int node, void **addr, const size_t align, qae_mem_info_t *tls_ptr); API_LOCAL void __qae_destroyList(const int fd, dev_mem_info_t *pList, void *thread_key); API_LOCAL void __qae_reset_cache(const int fd, void *thread_key); API_LOCAL dev_mem_info_t *__qae_alloc_slab(const int fd, const size_t size, const uint32_t alignment, const int node, enum slabType type, qae_mem_info_t *tls_ptr); /* These *_tmp_list() functions are for managing the TMP list in thread * specific implementation. */ static inline void save_slab_to_tmp_list(dev_mem_info_t *slab) { mem_mutex_lock(&mutex_tmp_list); ADD_ELEMENT_TO_HEAD_LIST( slab, g_slab_tmp_list.head, g_slab_tmp_list.tail, _user_vfiotmp); mem_mutex_unlock(&mutex_tmp_list); } static inline void remove_slab_from_tmp_list(dev_mem_info_t *slab) { mem_mutex_lock(&mutex_tmp_list); REMOVE_ELEMENT_FROM_LIST( slab, g_slab_tmp_list.head, g_slab_tmp_list.tail, _user_vfiotmp); mem_mutex_unlock(&mutex_tmp_list); } static inline void add_slab_to_hash(dev_mem_info_t *slab, qae_mem_info_t *tls_ptr) { const size_t key = get_key(slab->phy_addr); ADD_ELEMENT_TO_HEAD_LIST(slab, tls_ptr->g_slab_list[key].head, tls_ptr->g_slab_list[key].tail, _user_hash); } static inline void del_slab_from_hash(dev_mem_info_t *slab, qae_mem_info_t *tls_ptr) { const size_t key = get_key(slab->phy_addr); REMOVE_ELEMENT_FROM_LIST(slab, tls_ptr->g_slab_list[key].head, tls_ptr->g_slab_list[key].tail, _user_hash); } static inline dev_mem_info_t *find_slab_in_hash(void *virt_addr, qae_mem_info_t *tls_ptr) { const size_t key = load_key_fptr(&g_page_table, virt_addr); dev_mem_info_t *slab = tls_ptr->g_slab_list[key].head; while (slab) { uintptr_t offs = (uintptr_t)virt_addr - (uintptr_t)slab->virt_addr; if (offs < slab->size) return slab; slab = slab->pNext_user_hash; } return NULL; } static inline void *init_slab_and_alloc(block_ctrl_t *slab, const size_t size, const size_t phys_align_unit, qae_mem_info_t *tls_ptr) { const size_t last = slab->mem_info.size / CHUNK_SIZE; dev_mem_info_t *p_ctrl_blk = &slab->mem_info; const size_t reserved = div_round_up(sizeof(block_ctrl_t), UNIT_SIZE); void *virt_addr = NULL; /* initialise the bitmap to 1 for reserved blocks */ set_bitmap(slab->bitmap, 0, reserved); /* make a barrier to stop search at the end of the bitmap */ slab->bitmap[last] = QWORD_ALL_ONE; virt_addr = __qae_mem_alloc(slab, size, phys_align_unit); if (NULL != virt_addr) { ADD_ELEMENT_TO_HEAD_LIST(p_ctrl_blk, tls_ptr->pUserMemListHead, tls_ptr->pUserMemListTail, _user); } return virt_addr; } static inline int push_slab(dev_mem_info_t *slab, qae_mem_info_t *tls_ptr) { if (tls_ptr->g_cache_size + slab->size <= tls_ptr->g_max_cache) { tls_ptr->g_cache_size += slab->size; ADD_ELEMENT_TO_HEAD_LIST( slab, tls_ptr->pUserCacheHead, tls_ptr->pUserCacheTail, _user); return 0; } return -ENOMEM; } static inline dev_mem_info_t *pop_slab(const int node, qae_mem_info_t *tls_ptr) { dev_mem_info_t *slab = NULL; for (slab = tls_ptr->pUserCacheHead; slab != NULL; slab = slab->pNext_user) { if (node != NUMA_ANY_NODE) if (tls_ptr->g_strict_node && (node != slab->nodeId)) continue; tls_ptr->g_cache_size -= slab->size; REMOVE_ELEMENT_FROM_LIST( slab, tls_ptr->pUserCacheHead, tls_ptr->pUserCacheTail, _user); return slab; } return NULL; } #endif #endif /* QAE_MEM_THREAD_H */ qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_multi_thread_utils.c000066400000000000000000000440301503624047500317230ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_multi_thread_utils.c * * This file provides for thread specific Linux user space memory allocation. * It uses a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the quick assist sample code * * Each thread handles its own memory allocator information. Thread local * storage is used to hold all slab memory allocator information for each * thread. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #ifndef ICP_WITHOUT_THREAD #include #endif #include #include #include #include #include "qae_mem.h" #include "qae_mem_utils.h" #include "qae_mem_user_utils.h" #include "qae_page_table_common.h" #include "qae_mem_utils_common.h" #include "qae_mem_multi_thread.h" #include "qae_mem_hugepage_utils.h" #include /************************************************************************** macro **************************************************************************/ /* User space page table for fast virtual to physical address translation */ page_table_t g_page_table = { { { 0 } } }; slab_list_t g_slab_tmp_list = { 0 }; pthread_mutex_t mutex_tmp_list = PTHREAD_MUTEX_INITIALIZER; pthread_key_t qae_key; pthread_once_t qae_key_once = PTHREAD_ONCE_INIT; __thread int qae_mem_inited = 0; free_page_table_fptr_t free_page_table_fptr = free_page_table; load_key_fptr_t load_key_fptr = load_key; void qae_mem_destroy_t(void *thread_key); static void qae_make_key() { pthread_key_create(&qae_key, qae_mem_destroy_t); } API_LOCAL dev_mem_info_t *__qae_userMemLookupBySize(size_t size, int node, void **block, const size_t align, qae_mem_info_t *tls_ptr) { dev_mem_info_t *pCurr = NULL; size_t link_num = 0; for (pCurr = tls_ptr->pUserMemListHead; pCurr != NULL; pCurr = pCurr->pNext_user) { if (tls_ptr->g_strict_node && (pCurr->nodeId != node)) { continue; } *block = __qae_mem_alloc((block_ctrl_t *)pCurr, size, align); if (NULL != *block) { return pCurr; } /* Prevent from visiting whole chain, because after the first * several node, the chance to get one is very small. * Another consideration is to prevent new allocation from old * link, so that the old link could be released */ link_num++; if (link_num >= tls_ptr->g_max_lookup_num) { break; } } return NULL; } /* translate a physical address to a virtual address */ void *qaePhysToVirtNUMA(uint64_t physAddress) { dev_mem_info_t *slab; uintptr_t offset; void *ret = NULL; qae_mem_info_t *tls_ptr; tls_ptr = (qae_mem_info_t *)pthread_getspecific(qae_key); /* find slab from physical address without using hash lookup */ for (slab = tls_ptr->pUserMemListHead; slab != NULL; slab = slab->pNext_user) { offset = (uintptr_t)physAddress - (uintptr_t)slab->phy_addr; if (offset < slab->size) { ret = (void *)((uintptr_t)slab->virt_addr + offset); break; } } return ret; } void qaeAtFork() { return; } API_LOCAL void __qae_free_slab(const int fd, dev_mem_info_t *slab, qae_mem_info_t *tls_ptr) { dev_mem_info_t memInfo; int ret = 0; del_slab_from_hash(slab, tls_ptr); /* Remove the slab from TMP list as well */ remove_slab_from_tmp_list(slab); memcpy(&memInfo, slab, sizeof(dev_mem_info_t)); /* Need to disconnect from original chain */ ret = qae_munmap(memInfo.virt_addr, memInfo.size); if (ret) { CMD_ERROR("%s:%d munmap failed, ret = %d\n", __func__, __LINE__, ret); } if (LARGE == memInfo.type) { ret = qae_munmap(slab, getpagesize()); if (ret) { CMD_ERROR( "%s:%d munmap failed, ret = %d\n", __func__, __LINE__, ret); } } __qae_finish_free_slab(fd, &memInfo); } API_LOCAL dev_mem_info_t *__qae_find_slab(const int fd, const size_t size, const int node, void **addr, const size_t align, qae_mem_info_t *tls_ptr) { dev_mem_info_t *slab = __qae_userMemLookupBySize(size, node, addr, align, tls_ptr); if (NULL == slab) { slab = pop_slab(node, tls_ptr); if (NULL != slab) { *addr = init_slab_and_alloc((block_ctrl_t *)slab, size, align, tls_ptr); if (NULL == *addr) { CMD_ERROR("%s:%d Memory allocation failed Virtual address: %p " " Size: %zu \n", __func__, __LINE__, slab, size); __qae_free_slab(fd, slab, tls_ptr); return NULL; } } } return slab; } static void qae_mem_init_t(void) { qae_mem_info_t *tls_ptr; pthread_once(&qae_key_once, qae_make_key); if ((tls_ptr = (qae_mem_info_t *)pthread_getspecific(qae_key)) == NULL) { tls_ptr = malloc(sizeof(qae_mem_info_t)); /* Reset all control structures. */ memset(tls_ptr, 0, sizeof(qae_mem_info_t)); pthread_setspecific(qae_key, (void *)tls_ptr); } /* Set this to 0, because mmap doesn't provide NUMA aware memory */ tls_ptr->g_strict_node = 0; tls_ptr->g_max_lookup_num = 10; /* MAX cache size per thread */ tls_ptr->g_max_cache = MAX_CACHE_DEPTH_MB; tls_ptr->thd_process_id = syscall(__NR_gettid); qae_mem_inited = 1; } int32_t qaeMemInit() { int32_t fd_status = 0; int32_t status = 0; if (!is_new_process()) { /* Return if it is an existing process. */ return status; } qae_key = 0; qae_mem_inited = 0; qae_key_once = PTHREAD_ONCE_INIT; fd_status = __qae_open(); return fd_status; } API_LOCAL void __qae_destroyList(const int fd, dev_mem_info_t *pList, void *thread_key) { dev_mem_info_t *pCurr = pList; while (pCurr) { dev_mem_info_t *next = pCurr->pNext_user; __qae_free_slab(fd, pCurr, (qae_mem_info_t *)thread_key); pCurr = next; } } API_LOCAL void __qae_reset_cache(const int fd, void *thread_key) { dev_mem_info_t *slab = NULL; do { slab = pop_slab(NUMA_ANY_NODE, (qae_mem_info_t *)thread_key); if (NULL != slab) __qae_free_slab(fd, slab, (qae_mem_info_t *)thread_key); } while (slab != NULL); } void qaeMemDestroy(void) { qae_mem_info_t *tls_ptr = NULL; free_page_table_fptr(&g_page_table); tls_ptr = (qae_mem_info_t *)pthread_getspecific(qae_key); if (tls_ptr && qae_mem_inited) { __qae_reset_cache(g_fd, (void *)tls_ptr); __qae_destroyList(g_fd, tls_ptr->pUserMemListHead, (void *)tls_ptr); __qae_destroyList( g_fd, tls_ptr->pUserLargeMemListHead, (void *)tls_ptr); free(tls_ptr); pthread_setspecific(qae_key, NULL); } __qae_free_special(); qae_mem_inited = 0; pthread_key_delete(qae_key); } void qae_mem_destroy_t(void *thread_key) { qae_mem_info_t *tls_ptr; tls_ptr = (qae_mem_info_t *)thread_key; /* release all control buffers */ __qae_reset_cache(g_fd, thread_key); __qae_destroyList(g_fd, tls_ptr->pUserMemListHead, thread_key); __qae_destroyList(g_fd, tls_ptr->pUserLargeMemListHead, thread_key); free(thread_key); qae_mem_inited = 0; } API_LOCAL void *__qae_alloc_addr(size_t size, const int node, const size_t phys_alignment_byte) { dev_mem_info_t *p_ctrl_blk = NULL; void *pVirtAddress = NULL; size_t allocate_pages = 0; enum slabType mem_type = SMALL; qae_mem_info_t *tls_ptr; tls_ptr = (qae_mem_info_t *)pthread_getspecific(qae_key); const size_t phys_align_unit = phys_alignment_byte / UNIT_SIZE; const size_t reserved = div_round_up(sizeof(block_ctrl_t), UNIT_SIZE); /* calculate units needed */ const size_t requested_pages = div_round_up(size, UNIT_SIZE) + reserved; if (tls_ptr == NULL) { CMD_ERROR("error, unable to initialise slab allocator\n"); return NULL; } if (requested_pages > QAE_NUM_PAGES_PER_ALLOC * QAE_PAGE_SIZE / UNIT_SIZE || phys_alignment_byte >= QAE_NUM_PAGES_PER_ALLOC * QAE_PAGE_SIZE) { mem_type = LARGE; /* Huge page and Large memory are mutually exclusive * Since Large slabs are NOT 2 MB aligned, but huge * pages are always 2 MB aligned. */ if (__qae_hugepage_enabled()) return NULL; size = MAX(size, phys_alignment_byte); allocate_pages = div_round_up(size, UNIT_SIZE); } else { allocate_pages = QAE_NUM_PAGES_PER_ALLOC * QAE_PAGE_SIZE / UNIT_SIZE; if (__qae_hugepage_enabled()) mem_type = HUGE_PAGE; p_ctrl_blk = __qae_find_slab( g_fd, size, node, &pVirtAddress, phys_align_unit, tls_ptr); if (p_ctrl_blk) { p_ctrl_blk->allocations += 1; return pVirtAddress; } } /* Try to allocate memory as much as possible */ p_ctrl_blk = __qae_alloc_slab(g_fd, allocate_pages * UNIT_SIZE, phys_alignment_byte, node, mem_type, tls_ptr); if (NULL == p_ctrl_blk) return NULL; store_mmap_range(&g_page_table, p_ctrl_blk->virt_addr, p_ctrl_blk->phy_addr, p_ctrl_blk->size, __qae_hugepage_enabled()); if (LARGE == mem_type) { p_ctrl_blk->allocations = 1; ADD_ELEMENT_TO_HEAD_LIST(p_ctrl_blk, tls_ptr->pUserLargeMemListHead, tls_ptr->pUserLargeMemListTail, _user); pVirtAddress = p_ctrl_blk->virt_addr; } else { p_ctrl_blk->allocations = 1; if ((uintptr_t)p_ctrl_blk->virt_addr % QAE_PAGE_SIZE) { CMD_ERROR("%s:%d Bad virtual address alignment %lux %x %lux\n", __func__, __LINE__, (uintptr_t)p_ctrl_blk->virt_addr, QAE_NUM_PAGES_PER_ALLOC, QAE_PAGE_SIZE); __qae_free_slab(g_fd, p_ctrl_blk, tls_ptr); return NULL; } pVirtAddress = init_slab_and_alloc( (block_ctrl_t *)p_ctrl_blk, size, phys_align_unit, tls_ptr); if (NULL == pVirtAddress) { CMD_ERROR("%s:%d Memory allocation failed Virtual address: %p " " Size: %zu \n", __func__, __LINE__, p_ctrl_blk, size); __qae_free_slab(g_fd, p_ctrl_blk, tls_ptr); return NULL; } } return pVirtAddress; } void *qaeMemAllocNUMA(size_t size, int node, size_t phys_alignment_byte) { void *pVirtAddress = NULL; if (!size) { CMD_ERROR("%s:%d Size cannot be zero \n", __func__, __LINE__); return NULL; } if (size > QAE_MAX_ALLOC_SIZE) { CMD_ERROR( "%s:%d Size cannot exceed 64M for vfio\n", __func__, __LINE__); return NULL; } if (!phys_alignment_byte || phys_alignment_byte > QAE_MAX_PHYS_ALIGN || (phys_alignment_byte & (phys_alignment_byte - 1))) { CMD_ERROR("%s:%d Invalid alignment parameter %zu. It must be non zero, " "not more than %llu and multiple of 2 \n", __func__, __LINE__, phys_alignment_byte, QAE_MAX_PHYS_ALIGN); return NULL; } if (0 != qaeMemInit()) return NULL; if (!qae_mem_inited) { qae_mem_init_t(); } pVirtAddress = __qae_alloc_addr(size, node, phys_alignment_byte); return pVirtAddress; } API_LOCAL void __qae_free_addr(void **p_va, bool secure_free) { dev_mem_info_t *p_ctrl_blk = NULL; qae_mem_info_t *tls_ptr; tls_ptr = (qae_mem_info_t *)pthread_getspecific(qae_key); if (!tls_ptr) { CMD_ERROR("%s:%d No memory alloc info found \n", __func__, __LINE__); return; } if ((p_ctrl_blk = find_slab_in_hash(*p_va, tls_ptr)) == NULL) { CMD_ERROR("%s:%d Unable to free as lookup failed on address (%p) " "provided \n", __func__, __LINE__, *p_va); return; } if (SMALL == p_ctrl_blk->type || HUGE_PAGE == p_ctrl_blk->type) { if (__qae_mem_free((block_ctrl_t *)p_ctrl_blk, *p_va, secure_free)) { p_ctrl_blk->allocations -= 1; } else { /*Skip push_slab(p_ctrl_blk)) and return when mem_free fails */ CMD_ERROR("%s:%d mem_free returned false (%p) " "provided \n", __func__, __LINE__, *p_va); *p_va = NULL; return; } if (p_ctrl_blk->allocations) { *p_va = NULL; return; } REMOVE_ELEMENT_FROM_LIST(p_ctrl_blk, tls_ptr->pUserMemListHead, tls_ptr->pUserMemListTail, _user); if (0 != push_slab(p_ctrl_blk, tls_ptr)) __qae_free_slab(g_fd, p_ctrl_blk, tls_ptr); } else { REMOVE_ELEMENT_FROM_LIST(p_ctrl_blk, tls_ptr->pUserLargeMemListHead, tls_ptr->pUserLargeMemListTail, _user); __qae_free_slab(g_fd, p_ctrl_blk, tls_ptr); } *p_va = NULL; } /* __qae_memFreeNUMA function * Frees memory pointed by ptr. * ptr refers to memory allocated by qaeMemAllocNUMA function. * secure_free is a boolean to perform memory free secured or not. */ API_LOCAL void __qae_memFreeNUMA(void **ptr, bool secure_free) { if (NULL == ptr) { CMD_ERROR( "%s:%d Input parameter cannot be NULL \n", __func__, __LINE__); return; } if (NULL == *ptr) { CMD_ERROR( "%s:%d Address to be freed cannot be NULL \n", __func__, __LINE__); return; } __qae_free_addr(ptr, secure_free); return; } qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_user_utils.h000066400000000000000000000076211503624047500302320ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_user_utils.h * * This file provides for API of Linux user space memory allocation * ***************************************************************************/ #ifndef QAE_MEM_USER_UTILS_H #define QAE_MEM_USER_UTILS_H #include #include #ifndef SKIP_BUILTIN_FUNC #define unlikely(x) __builtin_expect((x), 0) #else #define unlikely(x) (0 == (x)) #endif #if __GNUC__ >= 4 #define API_PUBLIC __attribute__((visibility("default"))) #define API_LOCAL __attribute__((visibility("hidden"))) #else #define API_PUBLIC #define API_LOCAL #endif #ifdef ICP_DEBUG static inline void CMD_DEBUG(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stdout, format, args); va_end(args); } #else #define CMD_DEBUG(...) #endif static inline void CMD_ERROR(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); } #endif qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_utils_common.c000066400000000000000000000327531503624047500305430ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_utils_common.c * * This file provides for Linux user space memory allocation. It uses * a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the quick assist sample code * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qae_mem.h" #include "qae_mem_utils.h" #include "qae_mem_user_utils.h" #include "qae_mem_utils_common.h" load_addr_fptr_t load_addr_fptr = load_addr; const uint64_t __qae_bitmask[65] = { 0x0000000000000000ULL, 0x0000000000000001ULL, 0x0000000000000003ULL, 0x0000000000000007ULL, 0x000000000000000fULL, 0x000000000000001fULL, 0x000000000000003fULL, 0x000000000000007fULL, 0x00000000000000ffULL, 0x00000000000001ffULL, 0x00000000000003ffULL, 0x00000000000007ffULL, 0x0000000000000fffULL, 0x0000000000001fffULL, 0x0000000000003fffULL, 0x0000000000007fffULL, 0x000000000000ffffULL, 0x000000000001ffffULL, 0x000000000003ffffULL, 0x000000000007ffffULL, 0x00000000000fffffULL, 0x00000000001fffffULL, 0x00000000003fffffULL, 0x00000000007fffffULL, 0x0000000000ffffffULL, 0x0000000001ffffffULL, 0x0000000003ffffffULL, 0x0000000007ffffffULL, 0x000000000fffffffULL, 0x000000001fffffffULL, 0x000000003fffffffULL, 0x000000007fffffffULL, 0x00000000ffffffffULL, 0x00000001ffffffffULL, 0x00000003ffffffffULL, 0x00000007ffffffffULL, 0x0000000fffffffffULL, 0x0000001fffffffffULL, 0x0000003fffffffffULL, 0x0000007fffffffffULL, 0x000000ffffffffffULL, 0x000001ffffffffffULL, 0x000003ffffffffffULL, 0x000007ffffffffffULL, 0x00000fffffffffffULL, 0x00001fffffffffffULL, 0x00003fffffffffffULL, 0x00007fffffffffffULL, 0x0000ffffffffffffULL, 0x0001ffffffffffffULL, 0x0003ffffffffffffULL, 0x0007ffffffffffffULL, 0x000fffffffffffffULL, 0x001fffffffffffffULL, 0x003fffffffffffffULL, 0x007fffffffffffffULL, 0x00ffffffffffffffULL, 0x01ffffffffffffffULL, 0x03ffffffffffffffULL, 0x07ffffffffffffffULL, 0x0fffffffffffffffULL, 0x1fffffffffffffffULL, 0x3fffffffffffffffULL, 0x7fffffffffffffffULL, 0xffffffffffffffffULL, }; /* bitmap_read function * reads a 64-bit window from a BITMAP_LENx64-bit bitmap * starting from window_pos (0 <-> BITMAP_LENx64 -1) * map points to the BITMAP_LENx64 bit map area * returns the 64-bit window from the BITMAP_LENx64 bitmap. * Each bit represents a 1k block in the 2 Meg buffer */ STATIC uint64_t bitmap_read(uint64_t *map, size_t window_pos) { uint64_t quad_word_window = 0ULL; uint64_t next_quad_word = 0ULL; size_t quad_word_pos = 0; size_t bit_pos = 0; quad_word_pos = window_pos / QWORD_WIDTH; if (quad_word_pos >= BITMAP_LEN) { return QWORD_ALL_ONE; } bit_pos = window_pos % QWORD_WIDTH; quad_word_window = map[quad_word_pos]; if (0 == bit_pos) { return quad_word_window; } /* it is safe to read the next quad word because * there is always a barrier at the end */ next_quad_word = map[quad_word_pos + 1]; quad_word_window >>= bit_pos; next_quad_word <<= QWORD_WIDTH - bit_pos; quad_word_window |= next_quad_word; return quad_word_window; } /* mem_alloc function * mem_alloc allocates memory with min. size = UNIT_SIZE * block_ctrl points to a block_ctrl_t structure with virtual address * size is the requested number of bytes * minimum allocation size is UNIT_SIZE * returns a pointer to the newly allocated block * input: block_ctrl - pointer to the memory control block * size - size requested in bytes * output: pointer to the allocated area */ API_LOCAL void *__qae_mem_alloc(block_ctrl_t *block_ctrl, size_t size, size_t align) { uint64_t *bitmap = NULL; size_t window_pos = 0; void *retval = NULL; size_t blocks_found = 0; uint64_t bitmap_window = 0ULL; size_t blocks_required = 0ULL; size_t first_block = 0; size_t width = 0; size_t width_ones = 0; if (NULL == block_ctrl || 0 == size) { CMD_ERROR(" %s:%d invalid control block or size provided " "block_ctrl = %p and size = %zu \n", __func__, __LINE__, block_ctrl, size); return retval; } bitmap = block_ctrl->bitmap; blocks_required = div_round_up(size, UNIT_SIZE); window_pos = 0; first_block = window_pos; do { /* read 64-bit bitmap window from window_pos (0-BITMAP_LEN*64) */ bitmap_window = bitmap_read(bitmap, window_pos); /* find number of contiguous 0s from right */ width = mem_ctzll(bitmap_window); /* increment number of blocks found with number of contig. 0s in bitmap window */ blocks_found += width; /* check if a fit is found */ if (blocks_found >= blocks_required) { /* calculate return address from virtual address and first block number */ retval = (uint8_t *)(block_ctrl) + first_block * UNIT_SIZE; if (first_block + blocks_required > BITMAP_LEN * QWORD_WIDTH) { CMD_ERROR("%s:%d Allocation error - Required blocks exceeds " "bitmap window. Block index = %zu, Blocks required" " = %zu and Bitmap window = %ld \n", __func__, __LINE__, first_block, blocks_required, (BITMAP_LEN * QWORD_WIDTH)); return NULL; } /* save length in the reserved area right after the bitmap */ block_ctrl->sizes[first_block] = (uint16_t)blocks_required; /* set bit maps from bit position (0<->BITMAP_LEN*64 -1) = * first_block(0<->BITMAP_LEN*64-1) * with blocks_required length in bitmap */ set_bitmap(bitmap, first_block, blocks_required); break; } else { /* Did not find fit. Check if bitmap_window has at least a 1*/ if (bitmap_window) { /* This field of contiguous 0s is not big enough, so need * to jump past those 0s and the adjacent 1s and * restart the search at next 0. */ /* move past the zeros to where the 1s start */ bitmap_window >>= width; /* count the 1s */ width_ones = mem_ctzll(~bitmap_window); /* Set position from which to read next window */ window_pos += width + width_ones; /* Align position if necessary*/ if (align && window_pos % align) { window_pos += align - window_pos % align; } /* Reset previous search results */ first_block = window_pos; blocks_found = 0; } else { /* bit field of 0s is contiguous, but fit not found yet * move window_pos an search more 0s */ window_pos += width; } } } while (window_pos < BITMAP_LEN * QWORD_WIDTH); return retval; } /* * deallocates previously allocated blocks * block_ctrl is a pointer to block_ctrl_t structure * block is a result from a previous mem_alloc call * secure_free is a boolean to perform memory free secured or not */ API_LOCAL bool __qae_mem_free(block_ctrl_t *block_ctrl, void *block, bool secure_free) { size_t first_block = 0; uint32_t length = 0; uint8_t *start_of_block = block; uint64_t *bitmap = NULL; if (NULL == block_ctrl || NULL == block) { CMD_ERROR("%s:%d One of the parameters is NULL. block_ctrl = %p " "block = %p\n", __func__, __LINE__, block_ctrl, block); return false; } if ((uintptr_t)block % UNIT_SIZE) { CMD_ERROR("%s:%d Block address(%p) must be multiple of Unit size(%d)\n", __func__, __LINE__, block, UNIT_SIZE); return false; } bitmap = block_ctrl->bitmap; /* find start of block in block numbers using the address of start of * buffer and block retrieve first_block and length of block from integer * at the start of block */ first_block = ((uintptr_t)start_of_block - (uintptr_t)block_ctrl) / UNIT_SIZE; length = block_ctrl->sizes[first_block]; if (!length) { CMD_ERROR("%s:%d Invalid block address provided - " "Block index = %zu. " "Possibly double free.\n", __func__, __LINE__, first_block); return false; } if (length + first_block > BITMAP_LEN * QWORD_WIDTH) { CMD_ERROR("%s:%d Invalid block address provided - " "block length exceeds bitmap window. block index = %zu " "and block length: %d\n", __func__, __LINE__, first_block, length); return false; } block_ctrl->sizes[first_block] = 0; /* clear bitmap from bitmap position (0<->BITMAP_LEN*64 - 1) for length*/ clear_bitmap(bitmap, first_block, length); if (secure_free) { #ifndef ICP_DISABLE_SECURE_MEM_FREE qae_memzero_explicit(block, length * UNIT_SIZE); #endif } return true; } /************************************** * Memory functions *************************************/ void *qaeMemAlloc(size_t memsize) { void *memPtr = NULL; memPtr = calloc(memsize, sizeof(uint8_t)); return memPtr; } void qaeMemFree(void **ptr) { if ((!ptr) || !(*ptr)) { CMD_ERROR("%s:%d Trying to Free NULL Pointer\n", __func__, __LINE__); return; } free(*ptr); *ptr = NULL; } /*translate a virtual address to a physical address */ uint64_t qaeVirtToPhysNUMA(void *pVirtAddress) { return load_addr_fptr(&g_page_table, pVirtAddress); } void qaeMemFreeNUMA(void **ptr) { __qae_memFreeNUMA(ptr, true); return; } void qaeMemFreeNonZeroNUMA(void **ptr) { __qae_memFreeNUMA(ptr, false); return; } qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_mem_utils_common.h000066400000000000000000000232401503624047500305370ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_utils_common.h * * This file provides for Linux user space memory allocation. It uses * a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the quick assist sample code * ***************************************************************************/ #ifndef QAE_MEM_UTILS_COMMON_H #define QAE_MEM_UTILS_COMMON_H #include #include #include #include #include #include #include #include #include #include #include #ifndef ICP_WITHOUT_THREAD #include #endif #include #include #include #include #include "qae_mem.h" #include "qae_mem_utils.h" #include "qae_mem_user_utils.h" #include "qae_page_table_common.h" #include "qae_mem_hugepage_utils.h" /* Maximum cached memory size, 8 Mb by default */ #define MAX_CACHE_DEPTH_MB (0x800000) /* Maximum supported alignment is 4M. */ #define QAE_MAX_PHYS_ALIGN (0x400000ULL) /* Maximum supported allocation is 64M for vfio. */ #define QAE_MAX_ALLOC_SIZE (0x4000000ULL) #ifdef MADV_WIPEONFORK #define CACHE_PID #endif #ifdef CACHE_PID extern void *cache_pid; #endif typedef struct { dev_mem_info_t *head; dev_mem_info_t *tail; } slab_list_t; /* User space page table for fast virtual to physical address translation */ extern page_table_t g_page_table; extern const uint64_t __qae_bitmask[65]; extern int g_fd; extern uint32_t normalAllocations_g; extern free_page_table_fptr_t free_page_table_fptr; extern load_addr_fptr_t load_addr_fptr; extern load_key_fptr_t load_key_fptr; API_LOCAL int __qae_open(void); API_LOCAL void *__qae_mem_alloc(block_ctrl_t *block_ctrl, size_t size, size_t align); API_LOCAL bool __qae_mem_free(block_ctrl_t *block_ctrl, void *block, bool secure_free); API_LOCAL void __qae_finish_free_slab(const int fd, dev_mem_info_t *slab); API_LOCAL void *__qae_alloc_addr(size_t size, const int node, const size_t phys_alignment_byte); API_LOCAL void __qae_free_addr(void **p_va, bool secure_free); API_LOCAL uint64_t allocate_iova(const uint32_t size, uint32_t alignment); API_LOCAL void iova_release(uint64_t iova, uint32_t size); API_LOCAL int dma_map_slab(const void *virt, const uint64_t iova, const size_t size); API_LOCAL int dma_unmap_slab(const uint64_t iova, const size_t size); API_LOCAL void __qae_memFreeNUMA(void **ptr, bool secure_free); static inline size_t div_round_up(const size_t n, const size_t d) { return (n + d - 1) / d; } static inline size_t round_up(const size_t n, const size_t s) { return ((n + s - 1) / s) * s; } /* mem_ctzll function * input: a 64-bit bitmap window * output: number of contiguous 0s from least significant bit position * __GNUC__ predefined macro and __builtin_ctz() are supported by Intel C */ static inline int32_t mem_ctzll(uint64_t bitmap_window) { if (bitmap_window) { #ifdef __GNUC__ return __builtin_ctzll(bitmap_window); #else #error "Undefined built-in function" #endif } return QWORD_WIDTH; } /* clear_bitmap function * clear the BITMAP_LENx64-bit bitmap from pos * for len length * input : map - pointer to the bitmap * pos - bit position * len - number of contiguous bits */ static inline void clear_bitmap(uint64_t *bitmap, const size_t index, size_t len) { size_t qword = index / QWORD_WIDTH; const size_t offset = index % QWORD_WIDTH; size_t num; if (offset > 0) { const size_t width = MIN(len, QWORD_WIDTH - offset); const uint64_t mask = __qae_bitmask[width] << offset; /* Clear required bits */ bitmap[qword] &= ~mask; len -= width; qword += 1; } num = len / QWORD_WIDTH; len %= QWORD_WIDTH; while (num--) { bitmap[qword++] = 0; } /* Clear remaining bits */ bitmap[qword] &= ~__qae_bitmask[len]; } /* set_bitmap function * set the BITMAP_LENx64-bit bitmap from pos * for len length * input : map - pointer to the bitmap * pos - bit position * len - number of contiguous bits */ static inline void set_bitmap(uint64_t *bitmap, const size_t index, size_t len) { size_t qword = index / QWORD_WIDTH; const size_t offset = index % QWORD_WIDTH; size_t num; if (offset > 0) { const size_t width = MIN(len, QWORD_WIDTH - offset); const uint64_t mask = __qae_bitmask[width] << offset; /* Set required bits */ bitmap[qword] |= mask; len -= width; qword += 1; } num = len / QWORD_WIDTH; len %= QWORD_WIDTH; while (num--) { bitmap[qword++] = ~0ULL; } /* Set remaining bits */ bitmap[qword] |= __qae_bitmask[len]; } #ifdef CACHE_PID static inline void uncache_process_id(void) { int ret = 0; if (cache_pid != NULL) { ret = qae_munmap(cache_pid, getpagesize()); if (ret) { CMD_ERROR("%s:%d munmap call for cache failed, ret = %d\n", __func__, __LINE__, ret); } cache_pid = NULL; } } static inline int cache_process_id(void) { if (!cache_pid) { int page_size = getpagesize(); cache_pid = qae_mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (cache_pid == NULL) { CMD_ERROR( "%s:%d Unable to mmap aligned memory \n", __func__, __LINE__); return -ENOMEM; } if (qae_madvise(cache_pid, page_size, MADV_WIPEONFORK)) { CMD_ERROR( "%s:%d Unable to update page properties\n", __func__, __LINE__); qae_munmap(cache_pid, page_size); close(g_fd); g_fd = -1; cache_pid = NULL; return -ENOMEM; } } *((pid_t *)cache_pid) = getpid(); return 0; } #endif /* CACHE_PID */ #ifndef CACHE_PID static inline int check_pid(void) { static pid_t pid = 0; if (pid != getpid()) { pid = getpid(); return 1; } return 0; } #endif /* !CACHE_PID */ static inline int is_new_process() { /* Check if it is a new process or child. */ #ifdef CACHE_PID const int is_new_pid = cache_pid == NULL || (cache_pid != NULL && *((pid_t *)cache_pid) == 0); #else const int is_new_pid = check_pid(); #endif return is_new_pid; } #endif /* QAE_MEM_UTILS_COMMON_H */ qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_page_table_common.h000066400000000000000000000251731503624047500306330ustar00rootroot00000000000000/******************************************************************************* * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * @file qae_page_table_common.h * * This file provides user-space page tables (similar to Intel x86/x64 * page tables) for fast virtual to physical address translation. Essentially, * this is an implementation of the trie data structure optimized for the x86 HW * constraints. * Memory required: * - 8 Mb to cover 4 Gb address space. * I.e. if only 1 Gb is used it will require additional 2 Mb. * ******************************************************************************/ #ifndef QAE_PAGE_TABLE_COMMON_H #define QAE_PAGE_TABLE_COMMON_H #include #include "qae_page_table_defs.h" #include #include "qae_mem_user_utils.h" API_LOCAL void __qae_set_free_page_table_fptr(free_page_table_fptr_t fp); API_LOCAL void __qae_set_loadaddr_fptr(load_addr_fptr_t fp); API_LOCAL void __qae_set_loadkey_fptr(load_key_fptr_t fp); static inline void *qae_memzero(void *const ptr, const size_t count) { uint32_t lim = 0; volatile unsigned char *volatile dstPtr = ptr; while (lim < count) { dstPtr[lim++] = '\0'; } return (void *)dstPtr; } /* * Fills a memory zone with 0, * returns pointer to the memory zone. */ static inline void *qae_memzero_explicit(void *const ptr, const size_t count) { if (!ptr) { return NULL; } #ifdef __STDC_LIB_EXT1__ errno_t result = memset_s(ptr, sizeof(ptr), 0, count); /* Supported on C11 standard */ if (result != 0) { return NULL; } return ptr; #endif /* __STDC_LIB_EXT1__ */ return qae_memzero(ptr, count); /* Platform-independent secure memset */ } static inline void *next_level(page_table_t *volatile *ptr) { page_table_t *old_ptr = *ptr; page_table_t *new_ptr; if (NULL != old_ptr) return old_ptr; new_ptr = mmap(NULL, sizeof(page_table_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if ((void *)-1 == new_ptr) return NULL; if (!__sync_bool_compare_and_swap(ptr, NULL, new_ptr)) munmap(new_ptr, sizeof(page_table_t)); return *ptr; } static inline void free_page_level(page_table_t *const level, const size_t iter) { size_t i = 0; if (0 == iter) return; for (i = 0; i < LEVEL_SIZE; ++i) { page_table_t *pt = level->next[i].pt; if (NULL != pt) { free_page_level(pt, iter - 1); munmap(pt, sizeof(page_table_t)); } } } static inline void free_page_table(page_table_t *const table) { /* There are 1+4 levels in 64-bit page table for 4KB pages. */ free_page_level(table, 4); /* Reset global root table. */ memset(table, 0, sizeof(page_table_t)); } static inline void store_addr(page_table_t *level, uintptr_t virt, uint64_t phys) { page_index_t id; id.addr = virt; level = next_level(&level->next[id.pg_entry.idxl4].pt); if (NULL == level) return; level = next_level(&level->next[id.pg_entry.idxl3].pt); if (NULL == level) return; level = next_level(&level->next[id.pg_entry.idxl2].pt); if (NULL == level) return; level = next_level(&level->next[id.pg_entry.idxl1].pt); if (NULL == level) return; level->next[id.pg_entry.idxl0].pa = phys; } static inline void store_addr_hpg(page_table_t *level, uintptr_t virt, uint64_t phys) { page_index_t id; id.addr = virt; level = next_level(&level->next[id.hpg_entry.idxl4].pt); if (NULL == level) return; level = next_level(&level->next[id.hpg_entry.idxl3].pt); if (NULL == level) return; level = next_level(&level->next[id.hpg_entry.idxl2].pt); if (NULL == level) return; level->next[id.hpg_entry.idxl1].pa = phys; } static inline uint64_t get_key(const uint64_t phys) { /* For 4KB page: use bits 20-31 of a physical address as a hash key. * It provides a good distribution for 1Mb/2Mb slabs and a moderate * distribution for 128Kb/256Kb/512Kbslabs. */ return (phys >> 20) & ~QAE_PAGE_MASK; } static inline void store_mmap_range(page_table_t *p_level, void *p_virt, uint64_t p_phys, size_t p_size, int hp_en) { size_t offset; size_t page_size = PAGE_SIZE; uint64_t page_mask = QAE_PAGE_MASK; store_addr_fptr_t store_addr_ptr = store_addr; const uintptr_t virt = (uintptr_t)p_virt; if (hp_en) { page_size = HUGEPAGE_SIZE; page_mask = HUGEPAGE_MASK; store_addr_ptr = store_addr_hpg; } /* Store the key into the physical address itself, * for 4KB pages: 12 lower bits are always 0 (physical page addresses * are 4KB-aligned). * for 2MB pages: 21 lower bits are always 0 (physical page addresses * are 2MB-aligned) */ p_phys = (p_phys & page_mask) | get_key(p_phys); for (offset = 0; offset < p_size; offset += page_size) { store_addr_ptr(p_level, virt + offset, p_phys + offset); } } static inline uint64_t load_addr(page_table_t *level, void *virt) { page_index_t id; uint64_t phy_addr; id.addr = (uintptr_t)virt; level = level->next[id.pg_entry.idxl4].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl3].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl2].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl1].pt; if (NULL == level) return 0; phy_addr = level->next[id.pg_entry.idxl0].pa; if (0 == phy_addr) return 0; return (phy_addr & QAE_PAGE_MASK) | id.pg_entry.offset; } static inline uint64_t load_addr_hpg(page_table_t *level, void *virt) { page_index_t id; uint64_t phy_addr; id.addr = (uintptr_t)virt; level = level->next[id.hpg_entry.idxl4].pt; if (NULL == level) return 0; level = level->next[id.hpg_entry.idxl3].pt; if (NULL == level) return 0; level = level->next[id.hpg_entry.idxl2].pt; if (NULL == level) return 0; phy_addr = level->next[id.hpg_entry.idxl1].pa; if (0 == phy_addr) return 0; return (phy_addr & HUGEPAGE_MASK) | id.hpg_entry.offset; } static inline uint64_t load_key(page_table_t *level, void *virt) { page_index_t id; uint64_t phy_addr; id.addr = (uintptr_t)virt; level = level->next[id.pg_entry.idxl4].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl3].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl2].pt; if (NULL == level) return 0; level = level->next[id.pg_entry.idxl1].pt; if (NULL == level) return 0; phy_addr = level->next[id.pg_entry.idxl0].pa; return phy_addr & ~QAE_PAGE_MASK; } static inline uint64_t load_key_hpg(page_table_t *level, void *virt) { page_index_t id; uint64_t phy_addr; id.addr = (uintptr_t)virt; level = level->next[id.hpg_entry.idxl4].pt; if (NULL == level) return 0; level = level->next[id.hpg_entry.idxl3].pt; if (NULL == level) return 0; level = level->next[id.hpg_entry.idxl2].pt; if (NULL == level) return 0; phy_addr = level->next[id.hpg_entry.idxl1].pa; /* The hash key is of 4KB long for both normal page and huge page */ return phy_addr & ~QAE_PAGE_MASK; } static inline void free_page_table_hpg(page_table_t *const table) { /* There are 1+3 levels in 64-bit page table for 2MB hugepages. */ free_page_level(table, 3); /* Reset global root table. */ memset(table, 0, sizeof(page_table_t)); } #endif /* QAE_PAGE_TABLE_COMMON_H */ qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/qae_page_table_defs.h000066400000000000000000000105131503624047500302540ustar00rootroot00000000000000/******************************************************************************* * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * @file qae_page_table_defs.h * * This file provides user-space page tables definitions. * ******************************************************************************/ #ifndef QAE_PAGE_TABLE_DEFS_H #define QAE_PAGE_TABLE_DEFS_H #define __STDC_WANT_LIB_EXT1__ 1 #include #include #include #include #ifdef PAGE_SIZE #undef PAGE_SIZE #endif #define PAGE_SIZE (0x1000) #define PAGE_SHIFT (12) #include #define QAE_PAGE_MASK (~(PAGE_SIZE - 1)) #define LEVEL_SIZE (PAGE_SIZE / sizeof(uint64_t)) #define HUGEPAGE_SIZE (0x200000) #define HUGEPAGE_SHIFT (21) #define HUGEPAGE_MASK (~(HUGEPAGE_SIZE - 1)) typedef struct { uint64_t offset : 12; uint64_t idxl0 : 9; uint64_t idxl1 : 9; uint64_t idxl2 : 9; uint64_t idxl3 : 9; uint64_t idxl4 : 9; } page_entry_t; typedef struct { uint64_t offset : 21; uint64_t idxl1 : 9; uint64_t idxl2 : 9; uint64_t idxl3 : 9; uint64_t idxl4 : 9; } hugepage_entry_t; typedef union { uint64_t addr; page_entry_t pg_entry; hugepage_entry_t hpg_entry; } page_index_t; typedef struct page_table_t { union { uint64_t pa; struct page_table_t *pt; } next[LEVEL_SIZE]; } page_table_t; typedef void (*free_page_table_fptr_t)(page_table_t *const table); typedef void (*store_addr_fptr_t)(page_table_t *, uintptr_t, uint64_t); typedef uint64_t (*load_addr_fptr_t)(page_table_t *, void *); typedef uint64_t (*load_key_fptr_t)(page_table_t *, void *); #endif /* QAE_PAGE_TABLE_DEFS_H */ qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/vfio/000077500000000000000000000000001503624047500251345ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/vfio/qae_mem_hugepage_utils_vfio.c000066400000000000000000000323311503624047500330160ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_hugepage_utils_vfio.c * * This file provides dummy huge page utilities for Linux user space memory * allocation with huge page not supported for vfio. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qae_mem_hugepage_utils.h" #include "qae_mem_user_utils.h" #include "qae_mem_utils_common.h" #include "qae_mem_utils.h" #include "qae_page_table_common.h" #ifdef ICP_THREAD_SPECIFIC_USDM #include "qae_mem_multi_thread.h" #endif static bool g_hugepages_enabled = false; static size_t g_num_hugepages = 0; static const char sys_dir_path[] = "/sys/kernel/mm/hugepages"; extern int vfio_container_fd; extern int g_noiommu_enabled; #define HUGEPAGE_FILE_DIR "/dev/hugepages/qat-usdm.XXXXXX" #define HUGEPAGE_FILE_LEN (sizeof(HUGEPAGE_FILE_DIR)) #define HUGEPAGE_SYS_NODE "hugepages-2048kB" #define HUGEPAGE_SOCKET_PATH_SIZE 50 #define HUGEPAGE_SYSFS_PATH_SIZE HUGEPAGE_SOCKET_PATH_SIZE + 32 /* The pfn (page frame number) are bits 0-54 of page. */ #define PFN_MASK 0x7fffffffffffffULL #define PAGEMAP_FILE "/proc/self/pagemap" /* Parse a sysfs (or other) file containing one integer value */ static int parse_sysfs_value(const char *filename, unsigned long *val) { FILE *f; char buf[BUFSIZ]; char *end = NULL; if ((f = qae_fopen(filename, "r")) == NULL) { CMD_ERROR("%s(): qae_fopen failed for %s\n", __func__, filename); return -1; } if (qae_fgets(buf, sizeof(buf), f) == NULL) { CMD_ERROR( "%s(): qae_fgets failed for sysfs value %s\n", __func__, filename); fclose(f); return -1; } *val = strtoul(buf, &end, 0); if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) { CMD_ERROR("%s(): cannot parse sysfs value %s\n", __func__, filename); fclose(f); return -1; } fclose(f); return 0; } static int get_num_hugepages_per_system(const char *subdir) { char path[HUGEPAGE_SYSFS_PATH_SIZE] = { '\0' }; char socketpath[HUGEPAGE_SOCKET_PATH_SIZE] = { '\0' }; DIR *socketdir; unsigned long num_pages = 0; const char nr_hp_file[] = "nr_hugepages"; snprintf(socketpath, sizeof(socketpath), "%s/%s", sys_dir_path, subdir); socketdir = qae_opendir(socketpath); if (socketdir) { closedir(socketdir); } else { if (g_hugepages_enabled) return -EIO; /* * HUGETLBFS is not configured in kernel. * Number of hugepages should be 0 */ g_num_hugepages = 0; return 0; } snprintf(path, sizeof(path), "%s/%s", socketpath, nr_hp_file); if (parse_sysfs_value(path, &num_pages) < 0) return -EIO; g_num_hugepages = num_pages; return 0; } /* * Use linux system page map file (proc/self/pagemap) to get the physical * address. Called in the vfio noiommu mode for virtual to physical address * translation. */ STATIC int mem_virt2phy(const void *virtaddr, uint64_t *physaddr_ptr) { int fd, retval; uint64_t page; unsigned long virt_pfn; int page_size; off_t offset; *physaddr_ptr = 0; /* standard page size */ page_size = getpagesize(); fd = qae_open(PAGEMAP_FILE, O_RDONLY); if (fd < 0) { CMD_ERROR("%s(): could not open %s: %s\n", __func__, PAGEMAP_FILE, strerror(errno)); return -EPERM; } virt_pfn = (unsigned long)virtaddr / page_size; offset = sizeof(uint64_t) * virt_pfn; if (qae_lseek(fd, offset, SEEK_SET) == (off_t) -1) { CMD_ERROR( "%s(): seek failure in %s: %d\n", __func__, PAGEMAP_FILE, errno); close(fd); return -EINVAL; } retval = qae_read(fd, &page, sizeof(page)); if (retval < 0) { CMD_ERROR( "%s(): could not read %s: %d\n", __func__, PAGEMAP_FILE, errno); return retval; } else if (retval != sizeof(page)) { CMD_ERROR("%s(): read %d bytes from %s " "but expected %zu:\n", __func__, retval, PAGEMAP_FILE, sizeof(page)); return -EINVAL; } if (qae_close(fd)) { CMD_ERROR("%s(): closing %s failed: %s\n", __func__, PAGEMAP_FILE, strerror(errno)); } if ((page & PFN_MASK) == 0) return -EINVAL; *physaddr_ptr = ((page & PFN_MASK) * page_size) + ((unsigned long)virtaddr % page_size); return 0; } API_LOCAL int __qae_vfio_init_hugepages() { int ret = 0; if (get_num_hugepages_per_system(HUGEPAGE_SYS_NODE)) return -EIO; if (g_num_hugepages > 0) { g_hugepages_enabled = true; __qae_set_free_page_table_fptr(free_page_table_hpg); __qae_set_loadaddr_fptr(load_addr_hpg); __qae_set_loadkey_fptr(load_key_hpg); } else { g_hugepages_enabled = false; __qae_set_free_page_table_fptr(free_page_table); __qae_set_loadaddr_fptr(load_addr); __qae_set_loadkey_fptr(load_key); } return ret; } API_LOCAL int __qae_hugepage_enabled() { return g_hugepages_enabled; } STATIC void *__qae_vfio_hugepage_mmap_addr(const size_t size) { void *addr = NULL; int ret = 0; int hpg_fd; char hpg_fname[HUGEPAGE_FILE_LEN]; /* * for every mapped huge page there will be a separate file descriptor * created from a temporary file, we should NOT close fd explicitly, it * will be reclaimed by the OS when the process gets terminated, and * meanwhile the huge page binding to the fd will be released, this could * guarantee the memory cleanup order between user buffers and ETR. */ snprintf(hpg_fname, sizeof(HUGEPAGE_FILE_DIR), "%s", HUGEPAGE_FILE_DIR); hpg_fd = qae_mkstemp(hpg_fname); if (hpg_fd < 0) { CMD_ERROR("%s:%d mkstemp(%s) for hpg_fd failed\n", __func__, __LINE__, hpg_fname); return NULL; } unlink(hpg_fname); addr = qae_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_HUGETLB, hpg_fd, 0); if (MAP_FAILED == addr) { CMD_ERROR("%s:%d qae_mmap(%s) for hpg_fd failed\n", __func__, __LINE__, hpg_fname); close(hpg_fd); return NULL; } ret = qae_madvise(addr, size, MADV_DONTFORK); if (0 != ret) { qae_munmap(addr, size); CMD_ERROR("%s:%d qae_madvise(%s) for hpg_fd failed\n", __func__, __LINE__, hpg_fname); close(hpg_fd); return NULL; } ((dev_mem_info_t *)addr)->hpg_fd = hpg_fd; return addr; } API_LOCAL dev_mem_info_t *__qae_vfio_hugepage_alloc_slab(const int fd, const size_t size, const int node, enum slabType type, const uint32_t alignment) { dev_mem_info_t *slab = NULL; int ret = 0; UNUSED(fd); if (get_num_hugepages_per_system(HUGEPAGE_SYS_NODE)) return NULL; if (!g_num_hugepages) { CMD_ERROR("%s:%d mmap: exceeded max huge pages allocations for this " "process.\n", __func__, __LINE__); return NULL; } slab = __qae_vfio_hugepage_mmap_addr(size); if (!slab) { CMD_ERROR("%s:%d mmap on huge page memory allocation failed\n", __func__, __LINE__); return NULL; } slab->nodeId = node; slab->size = size; slab->type = type; slab->virt_addr = slab; if (!g_noiommu_enabled) slab->phy_addr = allocate_iova(size, alignment); else ret = mem_virt2phy(slab->virt_addr, &slab->phy_addr); if (ret || !slab->phy_addr) { CMD_ERROR("%s:%d cannot map 0x%p to iova, ret:%d, noiommu_enabled:%d\n", __func__, __LINE__, slab->virt_addr, ret, g_noiommu_enabled); goto error; } /* Defer IOMMU map until container is registered. */ if (vfio_container_fd < 0) { #ifdef ICP_THREAD_SPECIFIC_USDM /* Save the slab in a TMP list for the deferred pinning. */ slab->flag_pinned = NOT_PINNED; save_slab_to_tmp_list(slab); #endif /* This is required for adding into hash table.*/ return slab; } #ifdef ICP_THREAD_SPECIFIC_USDM /* In the case of thread specific implementation, the slabs that are * allocated from different threads should be kept in a global array * for getting the slab information at the time of pinning and * un-pinning which is done in qaeRegisterDevice()/qaeUnregisterDevice() * functions. * NOTE: A new variable 'flag_pinned' is introduced. As the TMP list is * being employed to keep all the slabs, we need a marker to later * identify among the slabs in the TMP list that are already pinned! * The pinning will take place for the slab in * __qae_vfio_hugepage_alloc_slab itself if there is a vfio_container_fd * active). This flag is required to skip those slabs while doing deferred * pinning at the qaeRegisterDevice() time. */ save_slab_to_tmp_list(slab); #endif if (dma_map_slab(slab->virt_addr, slab->phy_addr, slab->size)) goto error; #ifdef ICP_THREAD_SPECIFIC_USDM slab->flag_pinned = PINNED; #endif return slab; error: if (!g_noiommu_enabled) iova_release(slab->phy_addr, slab->size); qae_munmap(slab, size); return NULL; } API_LOCAL void __qae_vfio_hugepage_free_slab(dev_mem_info_t *memInfo) { close(memInfo->hpg_fd); iova_release(memInfo->phy_addr, memInfo->size); if (vfio_container_fd < 0) return; dma_unmap_slab(memInfo->phy_addr, memInfo->size); #ifdef ICP_THREAD_SPECIFIC_USDM memInfo->flag_pinned = NOT_PINNED; #endif } qatlib-25.08.0/quickassist/utilities/libusdm_drv/user_space/vfio/qae_mem_utils_vfio.c000066400000000000000000000673151503624047500311630ustar00rootroot00000000000000/*************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * ***************************************************************************/ /** **************************************************************************** * @file qae_mem_utils_vfio.c * * This file provides for Linux user space memory allocation. It uses * a driver that allocates the memory in kernel memory space (to ensure * physically contiguous memory) and maps it to * user space for use by the QuickAssist libraries and their users * ***************************************************************************/ #include #include "qae_mem_utils_common.h" #ifdef ICP_THREAD_SPECIFIC_USDM #include "qae_mem_multi_thread.h" #else #include "qae_mem_lib_utils.h" #endif #ifdef CACHE_PID void *cache_pid = NULL; #endif /************************************************************************** macro **************************************************************************/ #ifdef __x86_64__ #define IOVA_BITS 39 #else #define IOVA_BITS 32 #endif #define SLAB_BITS 21 #define IOVA_IDX(iova) \ ((iova >> SLAB_BITS) & ((1 << (IOVA_BITS - SLAB_BITS)) - 1)) #define IOVA_SLAB_SIZE (1 << SLAB_BITS) /* Don't use null IOVA */ #define FIRST_IOVA IOVA_SLAB_SIZE #define NUM_IOVA_SLABS (1 << (IOVA_BITS - SLAB_BITS)) #define MAX_IOVA ((1ll << IOVA_BITS) - IOVA_SLAB_SIZE) #ifdef ICP_THREAD_SPECIFIC_USDM /* Needed to protect iova allocation for GEN2 devices */ pthread_mutex_t iova_mutex = PTHREAD_MUTEX_INITIALIZER; #endif /* ICP_THREAD_SPECIFIC_USDM */ #define E_NOIOMMU_MODE "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode" /************************************************************************** static variable **************************************************************************/ int g_fd = 0; int g_strict_node = 0; int vfio_container_fd = -1; int g_noiommu_enabled = 0; STATIC pid_t vfio_pid = 0; static int vfio_container_ref = 0; API_LOCAL void __qae_set_free_page_table_fptr(free_page_table_fptr_t fp) { free_page_table_fptr = fp; } API_LOCAL void __qae_set_loadaddr_fptr(load_addr_fptr_t fp) { load_addr_fptr = fp; } API_LOCAL void __qae_set_loadkey_fptr(load_key_fptr_t fp) { load_key_fptr = fp; } /* * Each IOVA_SLAB represents a set of memory pages of size 2MB that * are contiguous from the viewpoint of the IO device. * The iova_used bitmap identifies the IOVA slabs that have been used. */ static uint32_t iova_used[NUM_IOVA_SLABS / (CHAR_BIT * sizeof(uint32_t))] = {0}; static uint64_t next_iova = FIRST_IOVA; /************************************************************************** function **************************************************************************/ static unsigned int bit_is_set(uint32_t used[], unsigned index) { const int bits = CHAR_BIT * sizeof(uint32_t); return used[index / bits] & (1 << (index % bits)); } static void set_bit(uint32_t used[], unsigned index) { const int bits = CHAR_BIT * sizeof(uint32_t); used[index / bits] |= (1 << (index % bits)); } static void clear_bit(uint32_t used[], unsigned index) { const int bits = CHAR_BIT * sizeof(uint32_t); used[index / bits] &= ~(1 << (index % bits)); } static int iova_reserve(uint64_t iova, uint32_t size) { unsigned slab = IOVA_IDX(iova); int count; int num_slabs = div_round_up(size, IOVA_SLAB_SIZE); if (iova + size - IOVA_SLAB_SIZE > MAX_IOVA) return 1; /* Reserve a range of IOVA */ for (count = 0; count < num_slabs; count++, slab++) { if (bit_is_set(iova_used, slab)) break; set_bit(iova_used, slab); } if (count < num_slabs) { /* If the complete range couldn't be reserved, revert */ while (count-- > 0) { slab--; clear_bit(iova_used, slab); } return 1; } return 0; } void iova_release(uint64_t iova, uint32_t size) { unsigned slab = 0; int count; int num_slabs = 0; #ifdef ICP_THREAD_SPECIFIC_USDM if (unlikely(mem_mutex_lock(&iova_mutex))) { CMD_ERROR( "%s:%d Error on thread iova_mutex lock\n", __func__, __LINE__); return; } #endif slab = IOVA_IDX(iova); num_slabs = (size + (1 << SLAB_BITS) - 1) >> SLAB_BITS; for (count = 0; count < num_slabs; count++, slab++) clear_bit(iova_used, slab); #ifdef ICP_THREAD_SPECIFIC_USDM if (unlikely(mem_mutex_unlock(&iova_mutex))) { CMD_ERROR( "%s:%d Error on thread iova_mutex unlock\n", __func__, __LINE__); } #endif } static int vfio_noiommu_enabled(void) { int fd, cnt; char enabled; fd = qae_open(E_NOIOMMU_MODE, O_RDONLY); if (fd < 0) { CMD_ERROR( "%s():%d could not open %s\n", __func__, __LINE__, E_NOIOMMU_MODE); return 0; } cnt = qae_read(fd, &enabled, 1); if (cnt == 1 && enabled == 'Y') return 1; if (qae_close(fd)) { CMD_ERROR( "%s():%d could not close %s\n", __func__, __LINE__, E_NOIOMMU_MODE); } return 0; } inline int dma_map_slab(const void *virt, const uint64_t iova, const size_t size) { int ret = 0; struct vfio_iommu_type1_dma_map dma_map = {.argsz = sizeof(dma_map), .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, .vaddr = (uintptr_t)virt, .iova = (uintptr_t)iova, .size = size}; if (g_noiommu_enabled) return ret; if (mem_ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map) && errno != EEXIST) { CMD_ERROR("%s:%d VFIO_IOMMU_MAP_DMA failed va=%llx iova=%llx size=%lx " "-- errno=%d\n", __func__, __LINE__, dma_map.vaddr, dma_map.iova, dma_map.size, errno); ret = 1; } return ret; } inline int dma_unmap_slab(const uint64_t iova, const size_t size) { int ret = 0; struct vfio_iommu_type1_dma_unmap dma_umap = { .argsz = sizeof(dma_umap), .iova = (uintptr_t)iova, .size = size}; if (g_noiommu_enabled) return ret; ret = mem_ioctl(vfio_container_fd, VFIO_IOMMU_UNMAP_DMA, &dma_umap); if (ret) CMD_ERROR( "%s:%d VFIO_IOMMU_UNMAP_DMA failed iova=%llx size%lx -- errno=%d\n", __func__, __LINE__, dma_umap.iova, dma_umap.size, errno); return ret; } static inline void ioctl_free_slab(const int fd, dev_mem_info_t *memInfo) { UNUSED(fd); iova_release(memInfo->phy_addr, memInfo->size); if (vfio_container_fd < 0) return; dma_unmap_slab(memInfo->phy_addr, memInfo->size); #ifdef ICP_THREAD_SPECIFIC_USDM memInfo->flag_pinned = NOT_PINNED; #endif } API_LOCAL void __qae_finish_free_slab(const int fd, dev_mem_info_t *slab) { if (HUGE_PAGE == slab->type) { __qae_vfio_hugepage_free_slab(slab); } else { ioctl_free_slab(fd, slab); } } /************************************** * Memory functions *************************************/ static inline int qaeInitProcess(void) { if (is_new_process()) { #ifndef ICP_THREAD_SPECIFIC_USDM __qae_ResetControl(); #else free_page_table_fptr(&g_page_table); memset(&g_page_table, 0, sizeof(g_page_table)); qae_key = 0; qae_mem_inited = 0; qae_key_once = PTHREAD_ONCE_INIT; g_slab_tmp_list.head = NULL; g_slab_tmp_list.tail = NULL; #endif memset(&iova_used, 0, sizeof(iova_used)); next_iova = FIRST_IOVA; #ifdef CACHE_PID cache_process_id(); #endif /* CACHE_PID */ if (__qae_vfio_init_hugepages()) return -EIO; } return 0; } API_LOCAL int __qae_open() { return qaeInitProcess(); } API_LOCAL int __qae_free_special(void) { #ifdef CACHE_PID uncache_process_id(); #endif return 0; } uint64_t allocate_iova(const uint32_t size, uint32_t alignment) { uint64_t iova; unsigned tryCount; #ifdef ICP_THREAD_SPECIFIC_USDM if (unlikely(mem_mutex_lock(&iova_mutex))) { CMD_ERROR( "%s:%d Error on thread iova_mutex lock %s\n", __func__, __LINE__); return 0; } #endif /* IOVA alignment must be minimum of IOVA_SLAB_SIZE but may be greater */ alignment = round_up(alignment, IOVA_SLAB_SIZE); iova = round_up(next_iova, alignment); for (tryCount = 0; tryCount < MAX_IOVA / alignment; tryCount++) { if (iova_reserve(iova, size)) { /* Couldn't reserve at that iova */ iova += alignment; if (iova > MAX_IOVA) iova = round_up(FIRST_IOVA, alignment); } else { next_iova = iova + round_up(size, IOVA_SLAB_SIZE); if (next_iova > MAX_IOVA) next_iova = FIRST_IOVA; #ifdef ICP_THREAD_SPECIFIC_USDM if (unlikely(mem_mutex_unlock(&iova_mutex))) { CMD_ERROR("%s:%d Error on thread iova_mutex unlock %s\n", __func__, __LINE__); return 0; } #endif return iova; } } #ifdef ICP_THREAD_SPECIFIC_USDM if (unlikely(mem_mutex_unlock(&iova_mutex))) { CMD_ERROR( "%s:%d Error on thread iova_mutex unlock %s\n", __func__, __LINE__); } #endif return 0; } static inline void *mmap_alloc(const size_t size) { int flags = MAP_ANONYMOUS | MAP_PRIVATE; void *ptr = NULL; ptr = qae_mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0); if (ptr != MAP_FAILED) { if (qae_madvise(ptr, size, MADV_DONTFORK)) { munmap(ptr, size); ptr = MAP_FAILED; } } return (ptr == MAP_FAILED) ? NULL : ptr; } static inline dev_mem_info_t *ioctl_alloc_slab(const int fd, const size_t size_r, const uint32_t alignment, const int node, enum slabType type) { dev_mem_info_t *slab = NULL; size_t size = round_up(size_r, PAGE_SIZE); UNUSED(node); UNUSED(fd); if (g_noiommu_enabled) { /* * Report error here. This function is called for non-hugepage case. * Hugepages are required for noiommu mode. */ CMD_ERROR("%s:%d Hugepages are needed for vfio-noiommu mode\n", __func__, __LINE__); return NULL; } if (SMALL == type) slab = mmap_alloc(size); else slab = mmap_alloc(getpagesize()); if (NULL == slab) { CMD_ERROR("%s:%d mmap memory failed\n", __func__, __LINE__); return NULL; } if (SMALL == type) slab->virt_addr = slab; else { slab->virt_addr = mmap_alloc(size); if (NULL == slab->virt_addr) { CMD_ERROR("%s:%d mmap failed for large memory allocation\n", __func__, __LINE__); qae_munmap(slab, getpagesize()); return NULL; } } slab->size = size; slab->phy_addr = allocate_iova(size, alignment); if (!slab->phy_addr) { CMD_ERROR("%s:%d cannot map 0x%p to iova\n", __func__, __LINE__, slab->virt_addr); goto error; } slab->type = type; /* Defer IOMMU map until container is registered. * This is a use-case where qaeMemAllocNUMA() is invoked before * process start up. * NOTE: Regardless of when it is invoked, the * qaeRegisterDevice()/qaeUnregsiterDevice() would get invoked * as many number of times as the number of devices found in the * QAT hardware. However, the pinning and un-pinning occur only * once based on the value of vfio_container_fd. */ if (vfio_container_fd < 0) { #ifdef ICP_THREAD_SPECIFIC_USDM /* Save the slab in a TMP list for the deferred pinning. */ slab->flag_pinned = NOT_PINNED; save_slab_to_tmp_list(slab); #endif /* This is required for adding into hash table.*/ return slab; } #ifdef ICP_THREAD_SPECIFIC_USDM /* In the case of thread specific implementation, the slabs that are * allocated from different threads should be kept in a global array * for getting the slab information at the time of pinning and * un-pinning which is done in qaeRegisterDevice()/qaeUnregisterDevice() * functions. * NOTE: A new variable 'flag_pinned' is introduced. As the TMP list is * being employed to keep all the slabs, we need a marker to later * identify among the slabs in the TMP list that are already pinned! * The pinning will take place for the slab in this ioctl_alloc_slab() * itself if there is a vfio_container_fd active). This flag is required * to skip those slabs while doing deferred pinning at the * qaeRegisterDevice() time. */ save_slab_to_tmp_list(slab); #endif if (dma_map_slab(slab->virt_addr, slab->phy_addr, slab->size)) goto error; #ifdef ICP_THREAD_SPECIFIC_USDM slab->flag_pinned = PINNED; #endif return slab; error: iova_release(slab->phy_addr, slab->size); if (SMALL == type) { qae_munmap(slab, slab->size); } else { qae_munmap(slab->virt_addr, slab->size); qae_munmap(slab, getpagesize()); } return NULL; } #ifndef ICP_THREAD_SPECIFIC_USDM API_LOCAL dev_mem_info_t *__qae_alloc_slab(const int fd, const size_t size, const uint32_t alignment, const int node, enum slabType type) { dev_mem_info_t *slab = NULL; if (HUGE_PAGE == type) { slab = __qae_vfio_hugepage_alloc_slab(fd, size, node, type, alignment); } else { slab = ioctl_alloc_slab(fd, size, alignment, node, type); } /* Store a slab into the hash table for a fast lookup. * NOTE: this is not the free list. This hash table is used * for finding the slab info from virt address quickly * at the time of qaeMemFreeNUMA code flow. The free list * is accessed by push_slab()/pop_slab() functions (uses * tls_ptr->pUserCacheHead/Tail). */ if (slab) add_slab_to_hash(slab); return slab; } #else /* ICP_THREAD_SPECIFIC_USDM */ API_LOCAL dev_mem_info_t *__qae_alloc_slab(const int fd, const size_t size, const uint32_t alignment, const int node, enum slabType type, qae_mem_info_t *tls_ptr) { dev_mem_info_t *slab = NULL; if (HUGE_PAGE == type) { slab = __qae_vfio_hugepage_alloc_slab(fd, size, node, type, alignment); } else { slab = ioctl_alloc_slab(fd, size, alignment, node, type); } /* Store a slab into the hash table for a fast lookup. * NOTE: this is not the free list. This hash table is used * for finding the slab info from virt address quickly * at the time of qaeMemFreeNUMA code flow. The free list * is accessed by push_slab()/pop_slab() functions (uses * tls_ptr->pUserCacheHead/Tail). */ if (slab) add_slab_to_hash(slab, tls_ptr); return slab; } #endif /* ICP_THREAD_SPECIFIC_USDM */ static int dma_map_slabs(dev_mem_info_t *pList) { dev_mem_info_t *slab; for (slab = pList; slab != NULL;) { #ifdef ICP_THREAD_SPECIFIC_USDM /* Do the deferred pinning only on slabs in the TMP list that * are NOT pinned at ioctl_alloc_slab() */ if (slab->flag_pinned == NOT_PINNED) { if (dma_map_slab(slab->virt_addr, slab->phy_addr, slab->size)) return 1; /* now that slab has been PINNED, mark it */ slab->flag_pinned = PINNED; } slab = slab->pNext_user_vfiotmp; #else if (dma_map_slab(slab->virt_addr, slab->phy_addr, slab->size)) return 1; slab = slab->pNext_user; #endif } return 0; } static int dma_unmap_slabs(dev_mem_info_t *pList) { dev_mem_info_t *slab; for (slab = pList; slab != NULL;) { #ifdef ICP_THREAD_SPECIFIC_USDM if (slab->flag_pinned == PINNED) { if (dma_unmap_slab(slab->phy_addr, slab->size)) return 1; slab->flag_pinned = NOT_PINNED; } slab = slab->pNext_user_vfiotmp; #else if (dma_unmap_slab(slab->phy_addr, slab->size)) return 1; slab = slab->pNext_user; #endif } return 0; } #ifdef VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE static void filter_range( uint64_t *next_start, struct vfio_iommu_type1_info_cap_iova_range *iova_range) { unsigned i; uint64_t next = *next_start; if (iova_range) { for (i = 0; i < iova_range->nr_iovas; i++) { /* Exclude any IOVA from the previous end to this start */ while (next < MIN(iova_range->iova_ranges[i].start, MAX_IOVA)) { set_bit(iova_used, IOVA_IDX(next)); next += IOVA_SLAB_SIZE; } if (iova_range->iova_ranges[i].end >= MAX_IOVA) break; next = (iova_range->iova_ranges[i].end + 1) & ~(IOVA_SLAB_SIZE - 1); } *next_start = next; } } #endif #ifdef VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE static int filter_dma_ranges(int fd) { uint64_t next_start = 0; struct vfio_iommu_type1_info *iommu_info; struct vfio_info_cap_header *cap_header; struct vfio_iommu_type1_info_cap_iova_range *iova_range = NULL; #define INFO_SIZE 0x1000 iommu_info = calloc(1, INFO_SIZE); if (!iommu_info) { CMD_ERROR( "%s:%d Allocation failed for iommu_info\n", __func__, __LINE__); return -1; } iommu_info->argsz = INFO_SIZE; if (mem_ioctl(fd, VFIO_IOMMU_GET_INFO, iommu_info)) { CMD_ERROR("%s:%d VFIO_IOMMU_GET_INFO ioctl failed %d\n", __func__, __LINE__, errno); free(iommu_info); return -1; } if (iommu_info->flags & VFIO_IOMMU_INFO_CAPS) { if (!iommu_info->cap_offset) { CMD_ERROR("%s:%d Not enough space to return IOMMU capabilities. " "Increase INFO_SIZE\n", __func__, __LINE__); free(iommu_info); return -1; } cap_header = (typeof(cap_header))((char *)iommu_info + iommu_info->cap_offset); while (cap_header) { if (cap_header->id == VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE) { if (iova_range) { CMD_DEBUG("%s:%d Unexpected second INFO_CAP_IOVA_RANGE\n", __func__, __LINE__); } iova_range = (struct vfio_iommu_type1_info_cap_iova_range *)cap_header; filter_range(&next_start, iova_range); } if (cap_header->next) cap_header = (typeof(cap_header))((char *)iommu_info + cap_header->next); else cap_header = NULL; } } free(iommu_info); return 0; } #else static int filter_dma_ranges(int fd) { UNUSED(fd); return 0; } #endif #ifndef ICP_THREAD_SPECIFIC_USDM int qaeRegisterDevice(int fd) { int ret = 0; pid_t pid = getpid(); g_noiommu_enabled = vfio_noiommu_enabled(); if(!g_noiommu_enabled) { if (filter_dma_ranges(fd)) return -1; } if (qaeInitProcess()) { CMD_ERROR("Failed to init qae process\n"); return -1; } /* When a new process is spawned then that means that * a new container is brought up, so we need to do * necessary actions, like, pinning memory of that process * to IOMMU (associate memory to the new container). */ if (pid != vfio_pid) { vfio_pid = pid; vfio_container_fd = -1; vfio_container_ref = 0; } if (vfio_container_fd < 0) { vfio_container_fd = fd; /* Map any slabs that were allocated before qaeRegisterDevice. */ if (dma_map_slabs(__qae_pUserMemListHead)) ret = 1; if (dma_map_slabs(__qae_pUserLargeMemListHead)) ret = 1; if (dma_map_slabs(__qae_pUserCacheHead)) ret = 1; if (ret) { vfio_container_fd = -1; return 1; } } if (fd == vfio_container_fd) { vfio_container_ref++; } else { CMD_ERROR("%s:%d Invalid container fd %d != %d\n", __func__, __LINE__, fd, vfio_container_fd); ret = 1; } return ret; } int qaeUnregisterDevice(int fd) { int ret = 0; pid_t pid = getpid(); if (vfio_container_ref <= 0 || vfio_container_fd != fd) return 1; if (pid != vfio_pid) return 0; if (--vfio_container_ref == 0) { if (dma_unmap_slabs(__qae_pUserMemListHead)) ret = 1; if (dma_unmap_slabs(__qae_pUserLargeMemListHead)) ret = 1; if (dma_unmap_slabs(__qae_pUserCacheHead)) ret = 1; vfio_container_fd = -1; } return ret; } #else /* ICP_THREAD_SPECIFIC_USDM */ /* The memory pinning operation is usually performed at the memory allocation * time itself but there are use cases where the application may allocate * memory before it has registered with USDM. In such cases, the pinning * will be deferred until a container_fd is active (the fd argument * to the qaeRegisterDevice() is exactly that). The expectation is that the * allocated memory is then pinned within qaeRegisterDevice() so that it * can be used for DMA. */ int qaeRegisterDevice(int fd) { int ret = 0; dev_mem_info_t *slab; pid_t pid = getpid(); g_noiommu_enabled = vfio_noiommu_enabled(); if(!g_noiommu_enabled) { if (filter_dma_ranges(fd)) return -1; } if (qaeInitProcess()) { CMD_ERROR("Failed to init qae process\n"); return -1; } /* When a new process is spawned then that means that * a new container is brought up, so we need to do * necessary actions, like, pinning memory of that process * to IOMMU (associate memory to the new container). */ if (pid != vfio_pid) { vfio_pid = pid; vfio_container_fd = -1; vfio_container_ref = 0; } if (vfio_container_fd < 0) { vfio_container_fd = fd; /* Do the memory pinning by referring to the TMP list */ if (unlikely(mem_mutex_lock(&mutex_tmp_list))) { CMD_ERROR("%s:%d Error on temp mutex lock\n", __func__, __LINE__); return -EIO; } slab = g_slab_tmp_list.head; if (slab != NULL) { if (dma_map_slabs(slab)) { vfio_container_fd = -1; ret = 1; } } if (unlikely(mem_mutex_unlock(&mutex_tmp_list))) { CMD_ERROR( "%s:%d Error on temp mutex unlock %s\n", __func__, __LINE__); return -EIO; } if (ret) return 1; } if (fd == vfio_container_fd) { vfio_container_ref++; } else { CMD_ERROR("%s:%d Invalid container fd %d != %d\n", __func__, __LINE__, fd, vfio_container_fd); ret = 1; } return ret; } int qaeUnregisterDevice(int fd) { int ret = 0; dev_mem_info_t *slab; pid_t pid = getpid(); if (vfio_container_ref <= 0 || vfio_container_fd != fd) return 1; if (pid != vfio_pid) return 0; if (--vfio_container_ref == 0) { /* Do the memory un-pinning by referring to the TMP list */ if (unlikely(mem_mutex_lock(&mutex_tmp_list))) { CMD_ERROR("%s:%d Error on temp mutex lock\n", __func__, __LINE__); return -EIO; } slab = g_slab_tmp_list.head; if (slab != NULL) { if (dma_unmap_slabs(slab)) ret = 1; } if (unlikely(mem_mutex_unlock(&mutex_tmp_list))) { CMD_ERROR( "%s:%d Error on temp mutex unlock %s\n", __func__, __LINE__); return -EIO; } vfio_container_fd = -1; } return ret; } #endif /* ICP_THREAD_SPECIFIC_USDM */ qatlib-25.08.0/quickassist/utilities/osal/000077500000000000000000000000001503624047500204645ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/osal/include/000077500000000000000000000000001503624047500221075ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/osal/include/Osal.h000066400000000000000000001414501503624047500231630ustar00rootroot00000000000000/** * @file Osal.h * * @brief Top include file for OSAL * * @par * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ #ifndef OSAL_H #define OSAL_H #ifdef __cplusplus extern "C" { #endif #include "OsalOsTypes.h" #include "OsalTypes.h" #ifndef DISABLE_NUMA_ALLOCATION #include "OsalDevDrvCommon.h" #endif #define OSAL_HOST_TO_NW_16(uData) OSAL_OS_HOST_TO_NW_16(uData) #define OSAL_HOST_TO_NW_32(uData) OSAL_OS_HOST_TO_NW_32(uData) #define OSAL_HOST_TO_NW_64(uData) OSAL_OS_HOST_TO_NW_64(uData) #define OSAL_NW_TO_HOST_16(uData) OSAL_OS_NW_TO_HOST_16(uData) #define OSAL_NW_TO_HOST_32(uData) OSAL_OS_NW_TO_HOST_32(uData) #define OSAL_NW_TO_HOST_64(uData) OSAL_OS_NW_TO_HOST_64(uData) #define OSAL_UDIV64_32(dividend, divisor) OSAL_OS_UDIV64_32(dividend, divisor) #define OSAL_UMOD64_32(dividend, divisor) OSAL_OS_UMOD64_32(dividend, divisor) /** * @ingroup Osal * * @brief Interrupt-safe logging function * * @param level - identifier prefix for the message * @param device - output device * @param format - message format, in a printf format * @param va_list - takes a variable list * * IRQ-safe logging function, similar to printf. Accepts up to 6 arguments * to print (excluding the level, device and the format). This function will * actually display the message only if the level is lower than the current * verbosity level or if the OSAL_LOG_LVL_USER level is used. An output device * must be specified (see OsalTypes.h). * * @li Reentrant: yes * @li IRQ safe: yes * * @return - BepSide the exceptions documented in the note below, the returned * value is the number of printed characters, or -1 if the parameters are * incorrect (NULL format, unknown output device) * * @note The exceptions to the return value are: * VxWorks*: The return value is 32 if the specified level is 1 and 64 * if the specified level is greater than 1 and less or equal than 9. * WinCE*: If compiled for EBOOT then the return value is always 0. * * @note The given print format should take into account the specified * output device. OSAL_STDOUT supports all the usual print formats, * however a custom hex display specified by OSAL_HEX would support * only a fixed number of hexadecimal digits. */ OSAL_PUBLIC INT32 osalLog(OsalLogLevel level, OsalLogDevice device, char *format, ...); /** * @ingroup Osal * * @brief Setting the module name * * @param moduleName - the string to be prepended with OSAL log message * * A facility provided to the user to prepend module name with OSAL * log messages. Example usage of this API to help the user to separate * messages from other modules. After the API called the subsequent calls to * osalLog or osalStdLog API's shall log the module name followed with * regular OSAL log message. To disable module name prepend users need to * invoke this API as osalLogSetPrefix(""); * * @li Reentrant: yes * @li IRQ safe: yes * * @return - None. * */ OSAL_PUBLIC void osalLogSetPrefix(CHAR *moduleName); /** * @ingroup Osal * * @brief simple logging function * * @param arg_pFmtString - message format, in printf format * @param ... - variable arguments * * Logging function, similar to printf. This provides a barebones logging * mechanism for users without differing verbosity levels. This interface * is not guaranteed to be IRQ safe. * * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalStdLog(const char *arg_pFmtString, ...); /** * @ingroup Osal * * @brief sets the current logging verbosity level * * @param level - new log verbosity level * * Sets the log verbosity level. The default value is OSAL_LOG_ERROR. * * @li Reentrant: yes * @li IRQ safe: yes * * @return - Old log verbosity level */ OSAL_PUBLIC UINT32 osalLogLevelSet(UINT32 level); OSAL_PUBLIC void osalLogModuleSet(const char *name); OSAL_PUBLIC void osalLogOutputSet(UINT32 output); /** * @ingroup Osal * * @brief Atomically read the value of atomic variable * * @param pAtomicVar IN - atomic variable * * Atomically reads the value of pAtomicVar to the outValue * * @li Reentrant: yes * @li IRQ safe: yes * * @return pAtomicVar value */ OSAL_PUBLIC INT64 osalAtomicGet(OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief Atomically set the value of atomic variable * * @param inValue IN - atomic variable to be set equal to inValue * * @param pAtomicVar OUT - atomic variable * * Atomically sets the value of pAtomicVar to the value given * * @li Reentrant: yes * @li IRQ safe: yes * * @return none */ OSAL_PUBLIC void osalAtomicSet(INT64 inValue, OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief Atomically set the value of atomic variable * * @param inValue (in) - atomic variable to be set equal to inValue * * @param pAtomicVar (in & out) - atomic variable * * Atomically sets the value of pAtomicVar to the inValue given * This function calls an atomic builtin which is not a full barrier, * but rather an acquire barrier to lock the variable. * * @li Reentrant: yes * @li IRQ safe: yes * * @return previous value of pAtomicVar value */ OSAL_PUBLIC INT64 osalAtomicTestAndSet(INT64 inValue, OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief Reset the value of atomic variable * * @param pAtomicVar (in) - atomic variable * * Writes the constant 0 to *pAtomicVar * This function calls an atomic builtin which releases the lock * acquired by osalAtomicTestAndSet function. * * @li Reentrant: yes * @li IRQ safe: yes * * @return none */ OSAL_PUBLIC void osalAtomicRelease(OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief add the value to atomic variable * * @param inValue (in) - value to be added to the atomic variable * * @param pAtomicVar (in & out) - atomic variable * * Atomically adds the value of inValue to the pAtomicVar * * @li Reentrant: yes * @li IRQ safe: yes * * @return pAtomicVar value after the addition */ OSAL_PUBLIC INT64 osalAtomicAdd(INT64 inValue, OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief subtract the value from atomic variable * * @param inValue IN - atomic variable value to be subtracted by value * * @param pAtomicVar IN/OUT - atomic variable * * Atomically subtracts the value of pAtomicVar by inValue * * @li Reentrant: yes * @li IRQ safe: yes * * @return pAtomicVar value after the subtraction */ OSAL_PUBLIC INT64 osalAtomicSub(INT64 inValue, OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief increment value of atomic variable by 1 * * @param pAtomicVar IN/OUT - atomic variable * * Atomically increments the value of pAtomicVar by 1. * * @li Reentrant: yes * @li IRQ safe: yes * * @return pAtomicVar value after the increment */ OSAL_PUBLIC INT64 osalAtomicInc(OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief decrement value of atomic variable by 1 * * @param pAtomicVar IN/OUT - atomic variable * * Atomically decrements the value of pAtomicVar by 1. * * @li Reentrant: yes * @li IRQ safe: yes * * @return pAtomic value after the decrement */ OSAL_PUBLIC INT64 osalAtomicDec(OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief decrement atomic variable value by 1 and test result * * @param pAtomicVar (IN/OUT) - atomic variable * * Atomically decrements the value of pAtomicVar by 1 and test * result for zero. * * @li Reentrant: yes * @li IRQ safe: yes * * @return OSAL_FAIL if the result is zero or OSAL_SUCCESS otherwise */ OSAL_PUBLIC OSAL_STATUS osalAtomicDecAndTest(OsalAtomic *pAtomicVar); /** * @ingroup Osal * * @brief Yielding sleep for a number of milliseconds * * @param milliseconds - number of milliseconds to sleep * * The calling thread will sleep for the specified number of milliseconds. * This sleep is yielding, hence other tasks will be scheduled by the * operating system during the sleep period. Calling this function with an * argument of 0 will place the thread at the end of the current scheduling * loop. * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalSleep(UINT32 milliseconds); /** * @ingroup Osal * * @brief Yields execution of current thread * * Yields the execution of the current thread * * @li Reentrant: yes * @li IRQ safe: no * * @return - none */ OSAL_PUBLIC void osalYield(void); /************************************** * Memory functions *************************************/ /** * @ingroup Osal * * @brief Initialize the user-space allocator * * @param path - path to the specific device * * Initialize the user-space allocator opening the device driver used * to communicate with the kernel-space. * * @li Reentrant: yes * @li IRQ safe: no * * @return OSAL_SUCCESS if the open of the device was successful and * OSAL_FAIL otherwise */ OSAL_STATUS osalMemInitialize(char *path); /** * @ingroup Osal * * @brief Finalize the user-space allocator * * It closes the file descriptor associated with the device driver * * @li Reentrant: yes * @li IRQ safe: no * */ void osalMemDestroy(void); /** * @ingroup Osal * * @brief Allocates memory * * @param size - memory size to allocate, in bytes * * Allocates a memory zone of the specified size. * * @li Reentrant: yes * @li IRQ safe: no * * @return Pointer to the allocated zone or NULL if the allocation failed */ void *osalMemAlloc(UINT32 size); /** * @ingroup Osal * * @brief Allocates memory atomically * * @param size - memory size to allocate, in bytes * * Allocates a memory zone of a given size, and in kernel space * the allocation is high priority. * * @li Reentrant: yes * @li IRQ safe: no * * @return Pointer to the allocated zone or NULL if the allocation failed */ void *osalMemAllocAtomic(UINT32 size); /** * @ingroup Osal * * @brief NUMA aware memory allocation; available on Linux OS only. * * @param size - memory size to allocate, in bytes * @param node - node * @param alignment - memory boundary alignment (alignment can not be 0) * * Allocates a memory zone of a given size on the specified node * The returned memory is guaraunteed to be physically contiguous if the * given size is less than 128KB and belonging to the node specified * * @li Reentrant: yes * @li IRQ safe: no * * @return Pointer to the allocated zone or NULL if the allocation failed */ void *osalMemAllocContiguousNUMA(UINT32 size, UINT32 node, UINT32 alignment); /** * @ingroup Osal * * @brief Frees memory allocated by OsalMemAllocNUMA; available on Linux OS * only. * * @param ptr - pointer to the memory zone * @param size - size of the pointer previously allocated * * Frees a previously allocated memory zone * * @li Reentrant: yes * @li IRQ safe: no * * @return - none */ void osalMemFreeNUMA(void *ptr); /** * @ingroup Osal * * @brief Frees memory allocated by OsalMemAlloc * * @param ptr - pointer to the memory zone * * Frees a previously allocated memory zone * * @li Reentrant: yes * @li IRQ safe: no * * @return - none */ void osalMemFree(void *ptr); /** * @ingroup Osal * * @brief Converts a virtual address to a physical one * * @param pVirtAddr - pointer to the memory zone * * Converts a virtual address to a physical one. It's implementation * works only for user-space. * * @li Reentrant: yes * @li IRQ safe: no * * @return - physical address in a form of UINT64 */ UINT64 osalVirtToPhysNUMA(void *pVirtAddr); /** * @ingroup Osal * * @brief Allocation of a page of memory from a specific * NUMA node and return physical address. * * @param node - NUMA node to allocate from * @param physAddr - The physical address of the allocated page. * * Allocates memory of a given size on the specified node. * The size of the PAGE is OS dependent. * * @li Reentrant: yes * @li IRQ safe: no * * @return Pointer to the allocated memory or NULL if the allocation failed */ void *osalMemAllocPage(UINT32 node, UINT64 *physAddr); /** * @ingroup Osal * * @brief Frees memory allocated by osalMemAllocPage * * @param ptr - pointer to the memory * * Frees a previously allocated memory * * @li Reentrant: yes * @li IRQ safe: no * * @return - none */ void osalMemFreePage(void *ptr); /* * Using the intrinsic OS memcpy/memset * yields greater performance */ /** * @ingroup Osal * * @brief Copies data bytes from pSrc memory zone to pDest memory zone * * @param pDest - pDestination memory zone * @param pSrc - source memory zone * @param count - number of bytes to copy * * Copies count bytes from the source memory zone pointed by pSrc into the * memory zone pointed by pDest. * * @li Reentrant: yes * @li IRQ safe: yes * * @return Pointer to the pDestination memory zone */ void *osalMemCopy(void *pDest, const void *pSrc, UINT32 count); /** * @ingroup Osal * * @brief Fills a memory zone * * @ ptr - pointer to the memory zone * @param filler - byte to fill the memory zone with * @param count - number of bytes to fill * * Fills a memory zone with a given constant byte * * @li Reentrant: yes * @li IRQ safe: yes * * @return Pointer to the memory zone */ void *osalMemSet(void *ptr, UINT8 filler, UINT32 count); /** * @ingroup Osal * * @brief Fills a memory zone * * @ ptr - pointer to the memory zone * @param count - number of bytes to fill * * Function for unoptimized calls * Fills a memory zone with 0 * * @li Reentrant: yes * @li IRQ safe: yes * * @return Pointer to the memory zone */ void *osalMemZeroExplicit(void *ptr, UINT32 count); /***************************** * Time *****************************/ /* Retrieve current system time * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalTimeGet(OsalTimeval *pTime); /** * @ingroup Osal * * @brief Allocates aligned memory * * @param space - (Unused right now ) kernel_space or user_space * @param size - malloc memory size required to be allocated * @param alignment - alignment required in bytes * * Allocate an aligned memory zone * * @li Reentrant: yes * @li IRQ safe: no * * @return - void pointer to malloced memory */ OSAL_PUBLIC VOID *osalMemAllocAligned(UINT32 space, UINT32 size, UINT32 alignment); /** * @ingroup Osal * * @brief Frees memory allocated by OsalMemAllocAligned * * @param ptr - pointer to contiguous aligned memory zone * * Frees a previously allocated Aligned memory zone * * @li Reentrant: yes * @li IRQ safe: no * * @return - none */ OSAL_PUBLIC void osalMemAlignedFree(void *ptr); /** * @ingroup Osal * * @brief Converts milliseconds to OsalTimeval * * @param milliseconds - number of milliseconds to convert * @param pTv - pointer to the pDestination structure * * Converts a millisecond value into an OsalTimeval structure * * @li Reentrant: yes * @li IRQ safe: yes * * @return - Corresponding OsalTimeval structure * Note: This function is OS-independent. Implemented by core. */ #define OSAL_MS_TO_TIMEVAL(milliseconds, pTv) \ ((OsalTimeval *)pTv)->secs = milliseconds / 1000; \ ((OsalTimeval *)pTv)->nsecs = (milliseconds % 1000) * 1000000 /** * @ingroup Osal * * @brief "add" operator for OsalTimeval * * @param tvA, tvB - OsalTimeval structures to add * * Adds the second OsalTimevalStruct to the first one (equivalent to * tvA += tvB) * * @li Reentrant: yes * @li IRQ safe: yes * * @return - none * Note: This function is OS-independent. */ #define OSAL_TIME_ADD(tvA, tvB) \ (tvA).secs += (tvB).secs; \ (tvA).nsecs += (tvB).nsecs; \ if ((tvA).nsecs >= OSAL_BILLION) \ { \ (tvA).secs++; \ (tvA).nsecs -= OSAL_BILLION; \ } /** * @ingroup Osal * * @brief "subtract" operator for OsalTimeval * * @param tvA, tvB - OsalTimeval structures to subtract * * Subtracts the second OsalTimevalStruct from the first one (equivalent * to tvA -= tvB) * * @li Reentrant: yes * @li IRQ safe: yes * * @return - none * Note: This function is OS-independent. Implemented by core. */ #define OSAL_TIME_SUB(tvA, tvB) \ if ((tvA).nsecs >= (tvB).nsecs) \ { \ (tvA).secs -= (tvB).secs; \ (tvA).nsecs -= (tvB).nsecs; \ } \ else \ { \ (tvA).secs -= ((tvB).secs + 1); \ (tvA).nsecs += OSAL_BILLION - (tvB).nsecs; \ } /** * @ingroup Osal * * @brief Converts OsalTimeVal to milliseconds * * @param tv - OsalTimeval structure to convert * * Converts an OsalTimeval structure into milliseconds * * @li Reentrant: yes * @li IRQ safe: yes * * @return - Corresponding number of milliseconds * Note: This function is OS-independent. Implemented by core. */ #define OSAL_TIMEVAL_TO_MS(tv) ((tv.secs * 1000) + (tv.nsecs / OSAL_MILLION)) #define OSAL_OEM_TIMESTAMP_RESOLUTION_GET (846596000) /**< 846.596 MHz */ #define OSAL_OEM_OS_NAME_GET(name, limit) OsalPosixOsNameGet(name, limit) #define OSAL_OEM_OS_VERSION_GET(version, limit) \ OsalPosixOsVersionGet(version, limit) /** * @ingroup IxOsal * * @brief virtual to physical address translation * * @param virtAddr - virtual address * * Converts a virtual address into its equivalent MMU-mapped physical address * * @li Reentrant: yes * @li IRQ safe: yes * * @return Corresponding physical address, as UINT32 */ #define OSAL_MMU_VIRT_TO_PHYS(virtAddr) OSAL_OS_MMU_VIRT_TO_PHYS(virtAddr) /** * @ingroup IxOsal * * @brief physical to virtual address translation * * @param physAddr - physical address * * Converts a physical address into its equivalent MMU-mapped virtual address * * @li Reentrant: yes * @li IRQ safe: yes * * @return Corresponding virtual address, as UINT32 */ #define OSAL_MMU_PHYS_TO_VIRT(physAddr) OSAL_OS_MMU_PHYS_TO_VIRT(physAddr) /** * @ingroup Osal * * @brief Converts ticks into OsalToTimeval * * @param ticks - number of ticks * @param pTv - pointer to the destination structure * * Internal function to convert the specified number of ticks into * an OsalTimeval structure * * @li Reentrant: yes * @li IRQ safe: yes * * @return - Corresponding OsalTimeval structure * Note: This function is OS-independent and internal to OSAL */ OSAL_PUBLIC void osalTicksToTimeval(UINT64 ticks, OsalTimeval *pTv); /** * @ingroup Osal * * @brief Converts OsalTimeVal into ticks * * @param tv - an OsalTimeval structure * * Internal function to convert an OsalTimeval structure into OS ticks * * @li Reentrant: yes * @li IRQ safe: yes * * @return - Corresponding number of ticks * * Note: This function is OS-independent and internal to OSAL. */ OSAL_PUBLIC UINT32 osalTimevalToTicks(OsalTimeval tv); /** * @ingroup Osal * * @brief Retrieves the current timestamp * * @li Reentrant: yes * @li IRQ safe: yes * * @return - The current timestamp * * @note The implementation of this function is platform-specific. Not * all the platforms provide a high-resolution timestamp counter. */ OSAL_PUBLIC UINT64 osalTimestampGet(void); /** * @ingroup Osal * * @brief Retrieves the current timestamp in nanoseconds units * * @li Reentrant: yes * @li IRQ safe: yes * * @return - The current timestamp in nanoseconds units * * @note The implementation of this function is platform-specific. Not * all the platforms provide a nanosecond resolution timestamp but the * lower resolutions ones will be converted to the nanoseconds units. */ OSAL_PUBLIC UINT64 osalTimestampGetNs(void); /** * @ingroup Osal * * @brief System clock rate, in ticks * * Retrieves the resolution (number of ticks per second) of the system clock * * @li Reentrant: yes * @li IRQ safe: yes * * @return - The system clock rate * * @note The implementation of this function is platform and OS-specific. * The system clock rate is not always available - */ OSAL_PUBLIC UINT32 osalSysClockRateGet(void); /** *********************************************************** * @param: pLock - IN - pointer to a spinlock_t type * * @return: OSAL_STATUS - OSAL_SUCCESS or OSAL_FAIL * * @brief: Initialize the SpinLock *********************************************************** */ /** * @ingroup Osal * * @brief Initializes the SpinLock object * * @param pLock - Spinlock handle * @param pLockType - Spinlock type * * Initializes the SpinLock object and its type. * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalLockInit(OsalLock *pLock, OsalLockType pLockType); /** * @ingroup Osal * * @brief Acquires a spin lock * * @param pLock - Spinlock handle * * This routine acquires a spin lock so the * caller can synchronize access to shared data in a * multiprocessor-safe way by raising IRQL. * * @li Reentrant: yes * @li IRQ safe: yes * * @return - Returns OSAL_SUCCESS if the spinlock is acquired. Returns OSAL_FAIL * if * spinlock handle is NULL. If spinlock is already acquired by any * other thread of execution then it tries in busy loop/spins till it * gets spinlock. */ OSAL_PUBLIC OSAL_STATUS osalLock(OsalLock *pLock); /** * @ingroup Osal * * @brief Releases the spin lock * * @param pLock - Spinlock handle * * This routine releases the spin lock which the thread had acquired * * @li Reentrant: yes * @li IRQ safe: yes * * @return - return OSAL_SUCCESS if the spinlock is released. Returns OSAL_FAIL * if * spinlockhandle passed is NULL. */ OSAL_PUBLIC OSAL_STATUS osalUnlock(OsalLock *pLock); /** * @ingroup Osal * * @brief Destroy the spin lock object * * @param pLock - Spinlock handle * * @li Reentrant: yes * @li IRQ safe: yes * * @return - returns OSAL_SUCCESS if plock is destroyed. * returns OSAL_FAIL if plock is NULL. * returns OSAL_UNSUPPORTED if current operating system does not * support this operation. */ OSAL_PUBLIC OSAL_STATUS osalLockDestroy(OsalLock *pLock); /** * @ingroup Osal * * @brief Acquires a spinlock; kernel-space only. * * @param pLock - Spinlock handle * @param flags - local irqs saved in flags * * @usage This API can be used when critical section is shared between * irq routines * * This routine saves local irqs in flags & then acquires a spinlock * * @li Reentrant: yes * @li IRQ safe: yes * * @return - returns OSAL_SUCCESS if spinlock acquired. If the spinlock is not * available then it busy loops/spins till pLock available. * If the spinlock handle passed is NULL then returns OSAL_FAIL. */ OSAL_PUBLIC OSAL_STATUS osalLockIrqSave(OsalLock *pLock, unsigned long *flags); /** * @ingroup Osal * * @brief Releases the spin lock; kernel-space only. * * @param pLock - Spinlock handle * @param flags - local irqs saved in flags * * @usage This API can be used when critical section is shared between * irq routines * * This routine releases the acquired spin lock & restores irqs in flags * * @li Reentrant: yes * @li IRQ safe: yes * * @return - returns OSAL_SUCCESS if pLock is unlocked. Returns OSAL_FAIL if the * pLock is NULL. */ OSAL_PUBLIC OSAL_STATUS osalUnlockIrqRestore(OsalLock *pLock, unsigned long *flags); /** * @ingroup Osal * * @brief Acquires a spinlock * * @param slock - Spinlock handle * * This routine disables bottom half & then acquires a slock * * @li Reentrant: yes * @li IRQ safe: yes * * @usage This API can be used in user context when critical section is * shared between user context & bottom half handler * * @return - returns OSAL_SUCCESS if spinlock is acquired. If spinlock is * not available then it busy loops/spins till slock is * available. * returns OSAL_FAIL if spinlock handle passed is NULL. * returns OSAL_UNSUPPORTED if current operating system does not * support this operation. */ OSAL_PUBLIC OSAL_STATUS osalLockBh(OsalLock *slock); /** * @ingroup Osal * * @brief Releases the spin lock * * @param slock - Spinlock handle * * This routine releases the acquired spinlock & enables the * bottom half handler * * @li Reentrant: yes * @li IRQ safe: no * * @usage This API can be used in user context when critical section is * shared between user context & bottom half handler * * @return - returns OSAL_SUCCESS if slock is released or unlocked. * returns OSAL_FAIL if slock is NULL. * returns OSAL_UNSUPPORTED if current operating system does not * support this operation. */ OSAL_PUBLIC OSAL_STATUS osalUnlockBh(OsalLock *slock); /** * @ingroup Osal * * @brief Initializes a semaphore * * @param pSid - semaphore handle * @param start_value - initial semaphore value * * Initializes a semaphore object * Note: Semaphore initialization OsalSemaphoreInit API must be called * first before using any OSAL Semaphore APIs * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreInit(OsalSemaphore *pSid, UINT32 start_value); /** * @ingroup Osal * * @brief Destroys a semaphore object * * @param pSid - semaphore handle * * Destroys a semaphore object; the caller should ensure that no thread is * blocked on this semaphore. If call made when thread blocked on semaphore the * behaviour is unpredictable * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreDestroy(OsalSemaphore *pSid); /** * @ingroup Osal * * @brief Waits on (decrements) a semaphore for specified time; available for * kernel-space * on Linux OS. * * @param pSid - semaphore handle * @param timeout - timeout, in ms; OSAL_WAIT_FOREVER (-1) if the thread * is to block indefinitely or OSAL_WAIT_NONE (0) if the thread is to * return immediately even if the call fails * * Decrements a semaphore, blocking for specified time if the semaphore is * unavailable (value is 0).The current thread or process can be interrupted * by a signal. * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreWaitInterruptible(OsalSemaphore *pSid, INT32 timeout); /** * @ingroup Osal * * @brief Wakes up thread blocked on semapohore. Increments a semaphore if * the value leass than one and wakes up threads waiting on wait queue; * available * for kernel-space on Linux OS. * * @param pSid - semaphore handle * * increments a semaphore if the value less than one and wakes up the thread * which is waiting for the semaphore. * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalSemaphorePostWakeup(OsalSemaphore *pSid); /** * @ingroup Osal * * @brief Waits on (decrements) a semaphore * * @param pSid - semaphore handle * @param timeout - timeout, in ms; OSAL_WAIT_FOREVER (-1) if the thread * is to block indefinitely or OSAL_WAIT_NONE (0) if the thread is to * return immediately even if the call fails * * Decrements a semaphore, blocking if the semaphore is * unavailable (value is 0). * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreWait(OsalSemaphore *pSid, INT32 timeout); /** * @ingroup IxOsal * * @brief Non-blocking wait on semaphore * * @param semaphore - semaphore handle * * Decrements a semaphore, not blocking the calling thread if the semaphore * is unavailable * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreTryWait(OsalSemaphore *semaphore); /** * @ingroup Osal * * @brief Posts to (increments) a semaphore * * @param pSid - semaphore handle * * Increments a semaphore object * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalSemaphorePost(OsalSemaphore *pSid); /** * @ingroup Osal * * @brief Gets semaphore value * * @param sid - semaphore handle * @param value - location to store the semaphore value * * Retrieves the current value of a semaphore object * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreGetValue(OsalSemaphore *sid, UINT32 *value); /** * @ingroup Osal * * @brief initializes a pMutex * * @param pMutex - pMutex handle * * Initializes a pMutex object * @note Mutex initialization OsalMutexInit API must be called * first before using any OSAL Mutex APIs * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalMutexInit(OsalMutex *pMutex); /** * @ingroup Osal * * @brief locks a pMutex * * @param pMutex - pMutex handle * @param timeout - timeout in ms; OSAL_WAIT_FOREVER (-1) to wait forever * or OSAL_WAIT_NONE to return immediately * * Locks a pMutex object * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalMutexLock(OsalMutex *pMutex, INT32 timeout); /** * @ingroup Osal * * @brief Unlocks a pMutex * * @param pMutex - pMutex handle * * Unlocks a pMutex object * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalMutexUnlock(OsalMutex *pMutex); /** * @ingroup Osal * * @brief Destroys a pMutex object * * @param pMutex - pMutex handle * * Destroys a pMutex object; the caller should ensure that no thread is * blocked on this pMutex. If call made when thread blocked on pMutex the * behaviour is unpredictable * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalMutexDestroy(OsalMutex *pMutex); /** * @ingroup Osal * * @brief Non-blocking attempt to lock a pMutex * * @param pMutex - pMutex handle * * Attempts to lock a pMutex object, returning immediately with OSAL_SUCCESS if * the lock was successful or OSAL_FAIL if the lock failed * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_PUBLIC OSAL_STATUS osalMutexTryLock(OsalMutex *pMutex); /** * @ingroup Osal * * @brief Creates a new thread * * @param pTid - handle of the thread to be created * @param threadAttr - pointer to a thread attribute object * @param entryPoint - thread entry point * @param arg - argument to be passed to the startRoutine * * Creates a thread given a thread handle and a thread attribute object. The * same thread attribute object can be used to create separate threads. "NULL" * can be specified as the attribute, in which case the default values will * be used. The thread needs to be explicitly started using osalThreadStart(). * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL * * @note In certain operating systems, this API function will both create and * start a thread in the same call. */ OSAL_PUBLIC OSAL_STATUS osalThreadCreate(OsalThread *pTid, OsalThreadAttr *threadAttr, OsalVoidFnVoidPtr entryPoint, void *arg); /** * @ingroup Osal * * @brief Sticks the thread to a specific CPU * * @param pTid - handle of the thread to be binded * @param cpu - the number of the CPU * * @li Reentrant: yes * @li IRQ safe: no * * @return - None */ OSAL_PUBLIC void osalThreadBind(OsalThread *pTid, UINT32 cpu); /** * @ingroup Osal * * @brief Starts a newly created thread * * @param pTid - handle of the thread to be started * * Starts a thread given its thread handle. This function is to be called * only once, following the thread initialization. * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalThreadStart(OsalThread *pTid); /** * @ingroup Osal * * @brief Sets the priority of a thread * * @param pTid - handle of the thread * @param priority - new priority, between 0 and 255 (0 being the highest) * * Sets the thread priority * * @li Reentrant: yes * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalThreadPrioritySet(OsalThread *pTid, UINT32 priority); OSAL_PUBLIC OSAL_STATUS osalThreadSetPolicyAndPriority(OsalThread *thread, UINT32 policy, UINT32 priority); /** * @ingroup Osal * * @brief Terminates a thread execution * * @param pTid - handle of the thread to be terminated * * Kills a thread given its thread handle. * * @li Reentrant: yes * @li IRQ safe: no * * @note This function does not guarantee to kill the thread immediately. * * @return - OSAL_SUCCESS/OSAL_FAIL/OSAL_UNSUPPORTED depending on implementation */ OSAL_PUBLIC OSAL_STATUS osalThreadKill(OsalThread *pTid); /** * @ingroup Osal * * @brief Exits a running thread * * Terminates the calling thread * * @li Reentrant: yes * @li IRQ safe: no * * @return - This function never returns */ OSAL_PUBLIC void osalThreadExit(void); /** * @ingroup Osal * * @brief map physical memory into virtual address space * * @param physAddr - physical address to map * @param size - size of the memory to map * * @return start address of the virtual memory zone. * */ OSAL_PUBLIC UARCH_INT osalIoRemap(UINT64 physAddr, UINT32 size); /** * @ingroup Osal * * @brief unmap virtual address space which was mapped using osalIoRemap * * @param virtAddr - virtual address * * Return value: void * */ OSAL_PUBLIC void osalIoUnmap(UARCH_INT virtAddr, UINT32 size); /** * @ingroup Osal * * @brief Calculate MD5 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least md5 block size long as defined in * rfc1321 (64 bytes) * out - output pointer for state data after single md5 transform * operation. * The buffer needs to be at least md5 state size long as defined in * rfc1321 (16 bytes) * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashMD5(UINT8 *in, UINT8 *out); /** * @ingroup Osal * * @brief Calculate MD5 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least md5 block size long as defined in * rfc1321 (64 bytes) * out - output pointer for state data after single md5 transform * operation. * The buffer needs to be at least md5 state size long as defined in * rfc1321 (16 bytes) * len - Length on the input to be processed. * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashMD5Full(UINT8 *in, UINT8 *out, UINT32 len); /** * @ingroup Osal * * @brief Calculate SHA1 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least sha1 block size long as defined in * rfc3174 (64 bytes) * out - output pointer for state data after single sha1 transform * operation. * The buffer needs to be at least sha1 state size long as defined in * rfc3174 (20 bytes) * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA1(UINT8 *in, UINT8 *out); /** * @ingroup Osal * * @brief Calculate SHA1 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least sha1 block size long as defined in * rfc3174 (64 bytes) * out - output pointer for state data after single sha1 transform * operation. * The buffer needs to be at least sha1 state size long as defined in * rfc3174 (20 bytes) * len - Length on the input to be processed. * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA1Full(UINT8 *in, UINT8 *out, UINT32 len); /** * @ingroup Osal * * @brief Calculate SHA224 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least sha224 block size long as defined in * rfc3874 and rfc4868 (64 bytes) * out - output pointer for state data after single sha224 transform * operation. * The buffer needs to be at least sha224 state size long as defined in * rfc3874 and rfc4868 (32 bytes) * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA224(UINT8 *in, UINT8 *out); /** * @ingroup Osal * * @brief Calculate SHA256 transform operation * * * @param in - pointer to data to be processed. * The buffer needs to be at least sha256 block size long as defined in * rfc4868 (64 bytes) * out - output pointer for state data after single sha256 transform * operation. * The buffer needs to be at least sha256 state size long as defined in * rfc4868 (32 bytes) * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA256(UINT8 *in, UINT8 *out); /** * @ingroup Osal * * @brief Calculate SHA256 transform operation * * * @param in - pointer to data to be processed. * The buffer needs to be at least sha256 block size long as defined in * rfc4868 (64 bytes) * out - output pointer for state data after single sha256 transform * operation. * The buffer needs to be at least sha256 state size long as defined in * rfc4868 (32 bytes) * len - Length on the input to be processed. * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA256Full(UINT8 *in, UINT8 *out, UINT32 len); /** * @ingroup Osal * * @brief Calculate SHA384 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least sha384 block size long as defined in * rfc4868 (128 bytes) * out - output pointer for state data after single sha384 transform * operation. * The buffer needs to be at least sha384 state size long as defined in * rfc4868 (64 bytes) * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA384(UINT8 *in, UINT8 *out); /** * @ingroup Osal * * @brief Calculate SHA384 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least sha384 block size long as defined in * rfc4868 (128 bytes) * out - output pointer for state data after single sha384 transform * operation. * The buffer needs to be at least sha384 state size long as defined in * rfc4868 (64 bytes) * len - Length on the input to be processed. * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA384Full(UINT8 *in, UINT8 *out, UINT32 len); /** * @ingroup Osal * * @brief Calculate SHA512 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least sha512 block size long as defined in * rfc4868 (128 bytes) * out - output pointer for state data after single sha512 transform * operation. * The buffer needs to be at least sha512 state size long as defined in * rfc4868 (64 bytes) * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA512(UINT8 *in, UINT8 *out); /** * @ingroup Osal * * @brief Calculate SHA512 transform operation * * @param in - pointer to data to be processed. * The buffer needs to be at least sha512 block size long as defined in * rfc4868 (128 bytes) * out - output pointer for state data after single sha512 transform * operation. * The buffer needs to be at least sha512 state size long as defined in * rfc4868 (64 bytes) * len - Length on the input to be processed. * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalHashSHA512Full(UINT8 *in, UINT8 *out, UINT32 len); /** * @ingroup Osal * * @brief Single block AES encrypt * * @param key - pointer to symmetric key. * keyLenInBytes - key length * in - pointer to data to encrypt * out - pointer to output buffer for encrypted text * The in and out buffers need to be at least AES block size long * as defined in rfc3686 (16 bytes) * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalAESEncrypt(UINT8 *key, UINT32 keyLenInBytes, UINT8 *in, UINT8 *out); /** * @ingroup Osal * * @brief Converts AES forward key to reverse key * * @param key - pointer to symmetric key. * keyLenInBytes - key length * out - pointer to output buffer for reversed key * The in and out buffers need to be at least AES block size long * as defined in rfc3686 (16 bytes) * * @li Reentrant: yes * @li IRQ safe: yes * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalAESKeyExpansionForward(UINT8 *key, UINT32 keyLenInBytes, UINT32 *out); /** * @ingroup Osal * * @brief Crypto interface init function * * @param void * * @li Reentrant: no * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL * */ OSAL_STATUS osalCryptoInterfaceInit(void); /** * @ingroup Osal * * @brief Crypto interface exit function * * @param void * * @li Reentrant: no * @li IRQ safe: no * * @return - void * */ void osalCryptoInterfaceExit(void); /** * @ingroup Osal * * @brief Function adds mapping from io virtual address * to a physical address. * * @param in - Host physical address. * in - IO virtual address. * in - Memory size to be remapped obtained from * osalIOMMUgetRemappingSize() function. * * @li Reentrant: no * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ int osalIOMMUMap(UINT64 phaddr, UINT64 iova, size_t size); /** * @ingroup Osal * * @brief Function removes mapping from io virtual * address to a physical address. * * @param in - IO virtual address. * in - Memory size to be remapped obtained from * osalIOMMUgetRemappingSize() function. * * @li Reentrant: no * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ int osalIOMMUUnmap(UINT64 iova, size_t size); /** * @ingroup Osal * * @brief Function translates io virtual address * to a physical address. * * @param in - IO virtual address. * * @li Reentrant: no * @li IRQ safe: no * * @return - host physical address */ UINT64 osalIOMMUVirtToPhys(UINT64 iova); /** * @ingroup Osal * * @brief Function attaches pci dev to iommu domain. * * @param in - Device to be attached. * * @li Reentrant: no * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ int osalIOMMUAttachDev(void *dev); /** * @ingroup Osal * * @brief Function detaches pci dev to iommu domain. * * @param in - Device to be detached. * * @li Reentrant: no * @li IRQ safe: no * * @return - void */ void osalIOMMUDetachDev(void *dev); /** * @ingroup Osal * * @brief Function calculates size for remapping. * * @param in - size. * * @li Reentrant: no * @li IRQ safe: no * * @return - Remapping size. */ size_t osalIOMMUgetRemappingSize(size_t size); /** * @ingroup Osal * * @brief Function creates iommu domain. * * @param none * * @li Reentrant: no * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ int osalIOMMUInit(void); /** * @ingroup Osal * * @brief Function removes iommu domain. * * @param none * * @li Reentrant: no * @li IRQ safe: no * * @return - void */ void osalIOMMUExit(void); /** * @ingroup Osal * * @brief Function saves pci configuration. * * @param in - pci device with configuration data to be saved * in - node number * out - pointer to the pointer of saved data * * @li Reentrant: no * @li IRQ safe: no * * @return - pointer to memory on heap with saved data or NULL */ void *osalPCIStateStore(void *dev, UINT32 node); /** * @ingroup Osal * * @brief Function restores pci configuration. * * @param in - pci device with configuration to be restored * in - pointer to the saved data * * @li Reentrant: no * @li IRQ safe: no * * @return - OSAL_SUCCESS/OSAL_FAIL */ OSAL_STATUS osalPCIStateRestore(void *dev, void *state); /** * @ingroup Osal * * @brief Function sets PCIe Capabilities Offset * * Set PCIe Capabilities Offset * * @param in - dev pci device * * @li Reentrant: no * @li IRQ safe: no * * @return - none */ void osalSetPCICapabilitiesOffset(void *dev); #ifdef __cplusplus } #endif #endif qatlib-25.08.0/quickassist/utilities/osal/include/OsalDevDrvCommon.h000066400000000000000000000350501503624047500254450ustar00rootroot00000000000000/** * @file OsalDevDrvCommon.h * * @brief Common device driver and macro types * * * @par * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * */ #ifndef OSAL_DEV_DRV_COMMON_H #define OSAL_DEV_DRV_COMMON_H #ifdef __cplusplus extern "C" { #endif #include "OsalOsTypes.h" #pragma pack(push) /* Push the current alignment on the stack */ #pragma pack(1) /* Force alignment on 1 byte to support 32 \ bits user space on 64 bits kernels */ /* Number of allocated pages for memory managements * For kernel which can allocate 4M, then value can be 512 * So that the performance can be improved * For legacy old kernel, the value can be 32, that is 128k */ #ifndef ICP_NUM_PAGES_PER_ALLOC #ifndef ICP_SRIOV #define NUM_PAGES_PER_ALLOC 512 #else #define NUM_PAGES_PER_ALLOC 256 #endif #else #define NUM_PAGES_PER_ALLOC 32 #endif #define DOUBLE_NUM_PAGES_PER_ALLOC (0x2 * NUM_PAGES_PER_ALLOC) /* magic used to identify double length * Need to bigger than 2 of ICP_NUM_PAGES_PER_ALLOC * The reason is that we will mmap 2*ICP_NUM_PAGES_PER_ALLOC * to achieve page alignment, and this macro is used when * user really wants to mmap 2*ICP_NUM_PAGES_PER_ALLOC pages */ #define ICP_MMAP_DOUBLE_NUM_PAGES 2048 typedef struct dev_mem_info_s { uint32_t id; /* Id of this block */ uint32_t nodeId; /* Node id for NUMA */ uint32_t size; /* Size of this block (bytes) */ uint32_t mmap_size; /* Size used to call mmap (bytes) */ uint32_t available_size; /* Available size remained on the page */ uint16_t allocations; /* Counter keeping track of number of allocations */ union { void *kmalloc_ptr; uint64_t padding_kmalloc_ptr; }; /* Pointer to mem originally returned by kmalloc */ union { int32_t *kmalloc_area; uint64_t padding_kmalloc_area; }; /* Pointer to kmalloc'd area rounded up to a page boundary */ UINT64 phy_addr; /* Physical address of the kmalloced area */ union { void *virt_addr; uint64_t padding_virt_addr; }; /* Base address in user space - i.e. virtual address */ union { void *fvirt_addr; uint64_t padding_fvirt_addr; }; /* virtual address return from mmap, and it is saved for munmap*/ /* Please be noted that padding should be used to make the same structure size for both 32 bit and 64 bit */ union { struct dev_mem_info_s *pPrev; uint64_t padding_pPrev; }; union { struct dev_mem_info_s *pNext; uint64_t padding_pNext; }; } dev_mem_info_t; typedef struct dev_iommu_info_s { uint64_t phaddr; uint64_t iova; uint64_t size; } dev_iommu_info_t; #pragma pack(pop) /* Restore Previous alignment */ typedef struct user_proc_mem_list_s { uint32_t pid; uint32_t allocs_nr; uint32_t max_id; dev_mem_info_t *freed_head; dev_mem_info_t *freed_tail; dev_mem_info_t *head; dev_mem_info_t *tail; struct user_proc_mem_list_s *pPrev; struct user_proc_mem_list_s *pNext; } user_proc_mem_list_t; typedef struct user_mem_dev_s { user_proc_mem_list_t *head; user_proc_mem_list_t *tail; } user_mem_dev_t; #define ADD_ELEMENT_TO_HEAD_OF_LIST(elementtoadd, currentptr, headptr) \ do \ { \ if (NULL == currentptr) \ { \ currentptr = elementtoadd; \ elementtoadd->pNext = NULL; \ elementtoadd->pPrev = NULL; \ } \ else \ { \ elementtoadd->pNext = headptr; \ elementtoadd->pPrev = NULL; \ headptr->pPrev = elementtoadd; \ } \ headptr = elementtoadd; \ } while (0); #define ADD_ELEMENT_TO_END_OF_LIST(elementtoadd, currentptr, headptr) \ do \ { \ if (NULL == currentptr) \ { \ currentptr = elementtoadd; \ elementtoadd->pNext = NULL; \ elementtoadd->pPrev = NULL; \ headptr = currentptr; \ } \ else \ { \ elementtoadd->pPrev = currentptr; \ currentptr->pNext = elementtoadd; \ elementtoadd->pNext = NULL; \ currentptr = elementtoadd; \ } \ } while (0); #define REMOVE_ELEMENT_FROM_LIST(elementtoremove, currentptr, headptr) \ do \ { \ /*If the previous pointer is not NULL*/ \ if (NULL != elementtoremove->pPrev) \ { \ elementtoremove->pPrev->pNext = elementtoremove->pNext; \ if (elementtoremove->pNext) \ { \ elementtoremove->pNext->pPrev = elementtoremove->pPrev; \ } \ else \ { \ currentptr = elementtoremove->pPrev; \ } \ } \ else if (NULL != elementtoremove->pNext) \ { \ elementtoremove->pNext->pPrev = NULL; \ headptr = elementtoremove->pNext; \ } \ else \ { \ currentptr = NULL; \ headptr = NULL; \ } \ } while (0) /* IOCTL number for use between the kernel and the user space application */ #define DEV_MEM_MAGIC 'm' #define DEV_MEM_CMD_MEMALLOC (0) #define DEV_MEM_CMD_MEMFREE (1) #define DEV_MEM_CMD_IOMMUMAP (2) #define DEV_MEM_CMD_IOMMUUNMAP (3) #define DEV_MEM_CMD_IOMMUVTOP (4) /* IOCTL commands for requesting kernel memory */ #define DEV_MEM_IOC_MEMALLOC \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMALLOC, dev_mem_info_t) #define DEV_MEM_IOC_MEMFREE \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_MEMFREE, dev_mem_info_t) #define DEV_MEM_IOC_IOMMUMAP \ _IOR(DEV_MEM_MAGIC, DEV_MEM_CMD_IOMMUMAP, dev_iommu_info_t) #define DEV_MEM_IOC_IOMMUUNMAP \ _IOR(DEV_MEM_MAGIC, DEV_MEM_CMD_IOMMUUNMAP, dev_iommu_info_t) #define DEV_MEM_IOC_IOMMUVTOP \ _IOWR(DEV_MEM_MAGIC, DEV_MEM_CMD_IOMMUVTOP, dev_iommu_info_t) /* IOCTL number for use between the kernel and the user space application */ #define DEV_MEM_MAGIC_PAGE 'p' #define DEV_MEM_CMD_MEMALLOCPAGE (0) #define DEV_MEM_CMD_MEMFREEPAGE (1) /* IOCTL commands for requesting kernel memory */ #define DEV_MEM_IOC_MEMALLOCPAGE \ _IOWR(DEV_MEM_MAGIC_PAGE, DEV_MEM_CMD_MEMALLOCPAGE, dev_mem_info_t) #define DEV_MEM_IOC_MEMFREEPAGE \ _IOWR(DEV_MEM_MAGIC_PAGE, DEV_MEM_CMD_MEMFREEPAGE, dev_mem_info_t) #define DEV_PATH_SIZE 60 #define DEV_NAME_SIZE 20 #define OS_DEV_DIRECTORY "/dev/" #define DEV_MEM_NAME "icp_dev_mem" #define DEV_MEM_NAME_PAGE "icp_dev_mem_page" #define DEV_MEM_PATH "/dev/icp_dev_mem" #define DEV_MEM_PAGE_PATH "/dev/icp_dev_mem_page" /** ******************************************************************************* * @ingroup Osal * * @brief This macro checks if a parameter is within a specified range * * @param[in] param Parameter * @param[in] min Parameter must be greater than OR equal to * min * @param[in] max Parameter must be less than max * * @return OSAL_FAIL Parameter is outside range * @return void Parameter is within range ******************************************************************************/ #define OSAL_CHECK_PARAM_RANGE(param, min, max) \ do \ { \ if (((param) < (min)) || ((param) >= (max))) \ { \ osalLog(OSAL_LOG_LVL_WARNING, \ OSAL_LOG_DEV_STDOUT, \ "param is outside valid range\n"); \ return OSAL_FAIL; \ } \ } while (0) dev_mem_info_t *userMemAlloc(user_mem_dev_t *dev, UINT32 sizeInBytes, UINT32 node, UINT32 pid); dev_mem_info_t *userMemGetInfo(user_mem_dev_t *dev, UINT32 id, UINT32 pid); void userMemFree(user_mem_dev_t *dev, UINT32 id, UINT32 pid); dev_mem_info_t *userMemAllocPage(user_mem_dev_t *dev, UINT32 node, UINT32 pid); dev_mem_info_t *userMemGetInfoPage(user_mem_dev_t *dev, UINT32 id, UINT32 pid); void userMemFreePage(user_mem_dev_t *dev, UINT32 id, UINT32 pid); void userMemFreeAllPid(user_mem_dev_t *dev, UINT32 pid); void userMemFreeAll(user_mem_dev_t *dev); void userMemFreeAllPagePid(user_mem_dev_t *dev, UINT32 pid); void userMemFreeAllPage(user_mem_dev_t *dev); #ifdef __cplusplus } #endif #endif qatlib-25.08.0/quickassist/utilities/osal/include/OsalTypes.h000066400000000000000000000472621503624047500242160ustar00rootroot00000000000000/** * @file OsalTypes.h * * @brief Define OSAL basic data types. * * This file contains fundamental data types used by OSAL. * * @par * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ #ifndef OSAL_TYPES_H #define OSAL_TYPES_H #ifdef __cplusplus extern "C" { #endif /* * Include the OS-specific type definitions */ #include "OsalOsTypes.h" /** * @defgroup OsalTypes Osal basic data types. * * @brief Basic data types for Osal * * @{ */ /** * @typedef OSAL_STATUS * @brief OSAL status * * @note Possible OSAL return status include OSAL_SUCCESS, OSAL_FAIL, * OSAL_RETRY, OSAL_RESOURCE, OSAL_INVALID_PARAM, OSAL_FATAL * and OSAL_UNSUPPORTED. */ typedef INT32 OSAL_STATUS; /** * @brief VUINT32 * * @note volatile UINT32 */ typedef volatile UINT32 VUINT32; /** * @brief VINT32 * * @note volatile INT32 */ typedef volatile INT32 VINT32; /** * @ingroup Osal * * @def NUMELEMS * * @brief Calculate number of elements */ #ifndef NUMELEMS #define NUMELEMS(x) (sizeof(x) / sizeof((x)[0])) #endif /** * @ingroup Osal * * @def OSAL_BILLION * * @brief Alias for 1,000,000,000 * */ #define OSAL_BILLION (1000000000) /** * @ingroup Osal * * @def OSAL_MILLION * * @brief Alias for 1,000,000 * */ #define OSAL_MILLION (1000000) /** * @ingroup Osal * * @def OSAL_THOUSAND * * @brief Alias for 1,000 * */ #define OSAL_THOUSAND (1000) /** * @ingroup Osal * * @def OSAL_HUNDRED * * @brief Alias for 100 * */ #define OSAL_HUNDRED (100) #if defined(__x86_64__) || defined(__aarch64__) #define ARCH_INT INT64 #else #define ARCH_INT INT32 #endif #if defined(__x86_64__) || defined(__aarch64__) #define UARCH_INT UINT64 #else #define UARCH_INT UINT32 #endif /** * @ingroup Osal * * @def NULL * * @brief Define for Null */ #ifndef NULL #define NULL 0L #endif /** * @ingroup Osal * * @def OSAL_SUCCESS * * @brief Success status */ #ifndef OSAL_SUCCESS #define OSAL_SUCCESS (0) /**< #defined as 0 */ #define OSAL_STATUS_SUCCESS (0) /**< #defined as 0 */ #endif /** * @ingroup Osal * * @def OSAL_FAIL * * @brief Failure status */ #ifndef OSAL_FAIL #define OSAL_FAIL (-1) /**< #defined as -1 */ #define OSAL_STATUS_FAIL (-1) /**< #defined as -1 */ #endif /** * @ingroup Osal * * @def OSAL_RETRY * * @brief Retry status */ #ifndef OSAL_RETRY #define OSAL_RETRY (-2) /**< #defined as -2 */ #define OSAL_STATUS_RETRY (-2) /**< #defined as -2 */ #endif /** * @ingroup Osal * * @def OSAL_RESOURCE * * @brief The resource that has been requested is unavailable. * Refer to the relevant sections of the API for specifics * on what the suggested course of action is. */ #ifndef OSAL_RESOURCE #define OSAL_RESOURCE (-3) /**< #defined as -3 */ #define OSAL_STATUS_RESOURCE (-3) /**< #defined as -3 */ #endif /** * @ingroup Osal * * @def OSAL_INVALID_PARAM * * @brief Invalid parameter has been passed in. */ #ifndef OSAL_INVALID_PARAM #define OSAL_INVALID_PARAM (-4) /**< #defined as -4 */ #define OSAL_STATUS_INVALID_PARAM (-4) /**< #defined as -4 */ #endif /** * @ingroup Osal * * @def OSAL_FATAL * * @brief A serious error has occurred. */ #ifndef OSAL_FATAL #define OSAL_FATAL (-5) /**< #defined as -5 */ #define OSAL_STATUS_FATAL (-5) /**< #defined as -5 */ #endif /** * @ingroup Osal * * @def OSAL_UNSUPPORTED * * @brief Function is not supported/implemented. */ #ifndef OSAL_UNSUPPORTED #define OSAL_UNSUPPORTED (-6) /**< #defined as -6 */ #define OSAL_STATUS_UNSUPPORTED (-6) /**< #defined as -6 */ #endif /** * @ingroup Osal * * @def OSAL_PRIVATE * * @brief Private define */ #ifndef OSAL_PRIVATE #ifdef OSAL_PRIVATE_OFF #define OSAL_PRIVATE /* nothing */ #else #define OSAL_PRIVATE \ static /**< #defined as static, except for debug builds \ */ #endif /* OSAL_PRIVATE_OFF */ #endif /* OSAL_PRIVATE */ /* * Placeholder for future use */ #ifndef OSAL_RESTRICTED #define OSAL_RESTRICTED #endif /* OSAL_RESTRICTED */ /** * @ingroup Osal * * @def OSAL_INLINE * * @brief Alias for __inline * */ #ifndef _DIAB_TOOL #ifndef OSAL_INLINE #define OSAL_INLINE __inline #endif /* OSAL_INLINE */ /** * @ingroup Osal * * @def __inline__ * * @brief Alias for __inline */ #ifndef __inline__ #define __inline__ OSAL_INLINE #endif #else /** * @ingroup Osal * * @def OSAL_INLINE * * @brief Alias for __inline */ #ifndef OSAL_INLINE #define OSAL_INLINE \ __inline__ /* Diab Compiler uses __inline__ (compiler di \ rective) */ #endif /* OSAL_INLINE */ #endif /*_DIAB_TOOL*/ /* Each OS can define its own OSAL_PUBLIC, otherwise it will be empty. */ #ifndef OSAL_PUBLIC #define OSAL_PUBLIC #endif /* OSAL_PUBLIC */ /** * @ingroup Osal * * @def OSAL_INLINE_EXTERN * * @brief Alias for __inline extern * */ #ifndef OSAL_INLINE_EXTERN #define OSAL_INLINE_EXTERN OSAL_INLINE extern #endif /** * @ingroup Osal * * @def OSAL_USES_ATTRIBUTE_PACKED * * @brief Defining packed attribute type in compiler/OS that supports it. * */ #ifndef OSAL_USES_ATTRIBUTE_PACKED #define OSAL_USES_ATTRIBUTE_PACKED TRUE #endif /** * @ingroup Osal * * @def OSAL_MAX_ALIGNMENT * * @brief Defining maximum alignment supported for aligned memory allocation. * */ #define OSAL_MAX_ALIGNMENT 256 #ifndef MILLISEC_TO_SEC_FACTOR #define MILLISEC_TO_SEC_FACTOR 1000 #endif /* MILLISEC_TO_SEC_FACTOR */ /** * @ingroup Osal * @enum OsalLogDevice * @brief This is an emum for OSAL log devices. */ typedef enum { OSAL_LOG_OUTPUT_NONE = 0, /**= 40700 return __atomic_load_n(atomicVar, __ATOMIC_ACQUIRE); #else return __sync_fetch_and_and(atomicVar, (INT64)0xFFFFFFFFFFFFFFFFULL); #endif } OSAL_PUBLIC OSAL_INLINE void osalAtomicSet(INT64 inValue, OsalAtomic *atomicVar) { __sync_lock_test_and_set(atomicVar, inValue); } OSAL_PUBLIC OSAL_INLINE INT64 osalAtomicTestAndSet(INT64 inValue, OsalAtomic *pAtomicVar) { return __sync_lock_test_and_set(pAtomicVar, inValue); } OSAL_PUBLIC OSAL_INLINE void osalAtomicRelease(OsalAtomic *pAtomicVar) { __sync_lock_release(pAtomicVar); } OSAL_PUBLIC OSAL_INLINE INT64 osalAtomicAdd(INT64 inValue, OsalAtomic *atomicVar) { return __sync_add_and_fetch(atomicVar, inValue); } OSAL_PUBLIC OSAL_INLINE INT64 osalAtomicSub(INT64 inValue, OsalAtomic *atomicVar) { return __sync_sub_and_fetch(atomicVar, inValue); } OSAL_PUBLIC OSAL_INLINE INT64 osalAtomicInc(OsalAtomic *atomicVar) { return __sync_add_and_fetch(atomicVar, 1); } OSAL_PUBLIC OSAL_INLINE INT64 osalAtomicDec(OsalAtomic *atomicVar) { return __sync_sub_and_fetch(atomicVar, 1); } OSAL_PUBLIC OSAL_INLINE OSAL_STATUS osalAtomicDecAndTest(OsalAtomic *atomicVar) { return (OSAL_STATUS)(__sync_sub_and_fetch(atomicVar, 1) == 0); } qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/OsalCryptoInterface.c000066400000000000000000000212331503624047500306300ustar00rootroot00000000000000/** * @file OsalCryptoInterface.c (linux user space) * * @brief Osal interface to openssl crypto library. * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "Osal.h" #include #include #include /* Required for MIN macro */ #include #define INIT(TYPE) TYPE##_Init #define TRANSFORM(TYPE) TYPE##_Transform #define UPDATE(TYPE) TYPE##_Update #define FINAL(TYPE) TYPE##_Final #ifndef OSAL_AES_SET_ENCRYPT #define OSAL_AES_SET_ENCRYPT AES_set_encrypt_key #endif #define OSAL_AES_ENCRYPT AES_encrypt #define BYTE_TO_BITS_SHIFT 3 #define AES_128_KEY_LEN_BYTES 16 #define AES_192_KEY_LEN_BYTES 24 #define AES_256_KEY_LEN_BYTES 32 OSAL_STATUS osalHashMD5(UINT8 *in, UINT8 *out) { MD5_CTX ctx; if (!INIT(MD5)(&ctx)) { return OSAL_FAIL; } TRANSFORM(MD5)(&ctx, in); memcpy(out, &ctx, MD5_DIGEST_LENGTH); return OSAL_SUCCESS; } OSAL_STATUS osalHashMD5Full(UINT8 *in, UINT8 *out, UINT32 len) { MD5_CTX ctx; if (!INIT(MD5)(&ctx)) { return OSAL_FAIL; } UPDATE(MD5)(&ctx, in, len); FINAL(MD5)(out, &ctx); memcpy(out, &ctx, MD5_DIGEST_LENGTH); return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA1(UINT8 *in, UINT8 *out) { SHA_CTX ctx; if (!INIT(SHA1)(&ctx)) { return OSAL_FAIL; } TRANSFORM(SHA1)(&ctx, in); memcpy(out, &ctx, SHA_DIGEST_LENGTH); return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA1Full(UINT8 *in, UINT8 *out, UINT32 len) { SHA_CTX ctx; UINT8 i = 0; if (!INIT(SHA1)(&ctx)) { return OSAL_FAIL; } UPDATE(SHA1)(&ctx, in, len); FINAL(SHA1)(out, &ctx); memcpy(out, &ctx, SHA_DIGEST_LENGTH); /* Change output endianness for SHA1 algorithm */ for (i = 0; i < (SHA_DIGEST_LENGTH >> 2); i++) { ((UINT32 *)(out))[i] = OSAL_HOST_TO_NW_32(((UINT32 *)(out))[i]); } return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA224(UINT8 *in, UINT8 *out) { SHA256_CTX ctx; if (!INIT(SHA224)(&ctx)) { return OSAL_FAIL; } TRANSFORM(SHA256)(&ctx, in); memcpy(out, &ctx, SHA256_DIGEST_LENGTH); return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA256(UINT8 *in, UINT8 *out) { SHA256_CTX ctx; if (!INIT(SHA256)(&ctx)) { return OSAL_FAIL; } TRANSFORM(SHA256)(&ctx, in); memcpy(out, &ctx, SHA256_DIGEST_LENGTH); return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA256Full(UINT8 *in, UINT8 *out, UINT32 len) { SHA256_CTX ctx; UINT8 i = 0; if (!INIT(SHA256)(&ctx)) { return OSAL_FAIL; } UPDATE(SHA256)(&ctx, in, len); FINAL(SHA256)(out, &ctx); memcpy(out, &ctx, SHA256_DIGEST_LENGTH); /* Change output endianness for SHA256 algorithm */ for (i = 0; i < (SHA256_DIGEST_LENGTH >> 2); i++) { ((UINT32 *)(out))[i] = OSAL_HOST_TO_NW_32(((UINT32 *)(out))[i]); } return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA384(UINT8 *in, UINT8 *out) { SHA512_CTX ctx; if (!INIT(SHA384)(&ctx)) { return OSAL_FAIL; } TRANSFORM(SHA512)(&ctx, in); memcpy(out, &ctx, SHA512_DIGEST_LENGTH); return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA384Full(UINT8 *in, UINT8 *out, UINT32 len) { /* We must use SHA512 for 384 context */ SHA512_CTX ctx; UINT8 i = 0; if (!INIT(SHA384)(&ctx)) { return OSAL_FAIL; } UPDATE(SHA384)(&ctx, in, len); FINAL(SHA384)(out, &ctx); memcpy(out, &ctx, SHA384_DIGEST_LENGTH); /* Change output endianness for SHA1 algorithm */ for (i = 0; i < (SHA384_DIGEST_LENGTH >> 3); i++) { ((UINT64 *)(out))[i] = OSAL_HOST_TO_NW_64(((UINT64 *)(out))[i]); } return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA512(UINT8 *in, UINT8 *out) { SHA512_CTX ctx; if (!INIT(SHA512)(&ctx)) { return OSAL_FAIL; } TRANSFORM(SHA512)(&ctx, in); memcpy(out, &ctx, SHA512_DIGEST_LENGTH); return OSAL_SUCCESS; } OSAL_STATUS osalHashSHA512Full(UINT8 *in, UINT8 *out, UINT32 len) { SHA512_CTX ctx; UINT16 i = 0; if (!INIT(SHA512)(&ctx)) { return OSAL_FAIL; } UPDATE(SHA512)(&ctx, in, len); FINAL(SHA512)(out, &ctx); memcpy(out, &ctx, SHA512_DIGEST_LENGTH); /* Change output endianness for SHA512 algorithm */ for (i = 0; i < (SHA512_DIGEST_LENGTH >> 3); i++) { ((UINT64 *)(out))[i] = OSAL_HOST_TO_NW_64(((UINT64 *)(out))[i]); } return OSAL_SUCCESS; } OSAL_STATUS osalAESEncrypt(UINT8 *key, UINT32 keyLenInBytes, UINT8 *in, UINT8 *out) { AES_KEY enc_key; INT32 status = OSAL_AES_SET_ENCRYPT( key, keyLenInBytes << BYTE_TO_BITS_SHIFT, &enc_key); if (status < 0) { return OSAL_FAIL; } OSAL_AES_ENCRYPT(in, out, &enc_key); return OSAL_SUCCESS; } #define EXPANDED_KEY_KAT 0xcb5befb4 static OSAL_STATUS osalAesSetEncryptByteSwap(INT32 *byte_swap) { UINT32 key_len_bits = AES_128_KEY_LEN_BYTES << BYTE_TO_BITS_SHIFT; UINT8 key[AES_128_KEY_LEN_BYTES] = { 0 }; static INT32 byte_swap_required = -1; UINT32 lw_per_round = 4; int status; AES_KEY rev_key; UINT32 key_val; *byte_swap = byte_swap_required; if (byte_swap_required >= 0) return OSAL_SUCCESS; status = OSAL_AES_SET_ENCRYPT(key, key_len_bits, &rev_key); if (status < 0) return OSAL_FAIL; /* First 4 bytes of the last round of expanded key */ key_val = rev_key.rd_key[lw_per_round * rev_key.rounds]; if (EXPANDED_KEY_KAT == key_val) byte_swap_required = 0; else if (key_val == __builtin_bswap32(EXPANDED_KEY_KAT)) byte_swap_required = 1; else return OSAL_FAIL; *byte_swap = byte_swap_required; return OSAL_SUCCESS; } OSAL_STATUS osalAESKeyExpansionForward(UINT8 *key, UINT32 key_len_in_bytes, UINT32 *out) { AES_KEY rev_key; UINT32 i = 0, j = 0; UINT32 lw_per_round = 4; INT32 lw_left_to_copy = key_len_in_bytes / lw_per_round; UINT32 *key_pointer = NULL; INT32 status = 0; INT32 swap; /* Error check for wrong input key len */ if (AES_128_KEY_LEN_BYTES != key_len_in_bytes && AES_192_KEY_LEN_BYTES != key_len_in_bytes && AES_256_KEY_LEN_BYTES != key_len_in_bytes) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalAESKeyExpansionForward:" "Incorrect key length\n"); return OSAL_FAIL; } status = osalAesSetEncryptByteSwap(&swap); if (OSAL_SUCCESS != status) return status; status = OSAL_AES_SET_ENCRYPT( key, key_len_in_bytes << BYTE_TO_BITS_SHIFT, &rev_key); if (status < 0) return OSAL_FAIL; /* Pointer to the last round of expanded key. */ key_pointer = &rev_key.rd_key[lw_per_round * rev_key.rounds]; while (lw_left_to_copy > 0) { for (i = 0; i < MIN(lw_left_to_copy, lw_per_round); i++, j++) { if (swap) out[j] = __builtin_bswap32(key_pointer[i]); else out[j] = key_pointer[i]; } lw_left_to_copy -= lw_per_round; key_pointer -= lw_left_to_copy; } return OSAL_SUCCESS; } qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/OsalMutex.c000066400000000000000000000140701503624047500266320ustar00rootroot00000000000000/** * @file OsalMutex.c (user space) * * @brief Implementation for Mutexes. * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include "Osal.h" OSAL_PUBLIC OSAL_STATUS osalMutexInit(OsalMutex *mutex) { #ifndef ICP_WITHOUT_THREAD pthread_mutex_t *pMutex; if (NULL == mutex) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexInit: NULL Mutex handle \n"); return OSAL_FAIL; } pMutex = (pthread_mutex_t *)osalMemAlloc(sizeof(pthread_mutex_t)); if (!(pMutex)) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexInit: fail to allocate for Mutex \n"); return OSAL_FAIL; } if (pthread_mutex_init(pMutex, NULL) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexInit: mutex init failed\n"); /* free the allocated pthread_mutex_t structure */ osalMemFree((void *)pMutex); return OSAL_FAIL; } *mutex = pMutex; #else *mutex = osalMemAlloc(sizeof(OsalMutex)); #endif return OSAL_SUCCESS; } /* * timeout expressed in milliseconds. */ OSAL_PUBLIC OSAL_STATUS osalMutexLock(OsalMutex *mutex, INT32 timeout) { #ifndef ICP_WITHOUT_THREAD OSAL_STATUS status; OsalTimeval timeoutVal; OsalTimeval currTime; struct timespec tspec; OSAL_PTR_ENSURE(mutex, "osalMutexLock(): Null mutex pointer", OSAL_FAIL); if ((timeout < 0) && (timeout != OSAL_WAIT_FOREVER)) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexLock(): illegal timeout value \n"); return OSAL_FAIL; } if (timeout == OSAL_WAIT_NONE) { status = pthread_mutex_trylock(*mutex); if (status) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexLock(): Failed to Lock Mutex \n"); return OSAL_FAIL; } } else if (timeout == OSAL_WAIT_FOREVER) { status = pthread_mutex_lock(*mutex); if (status) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexLock(): Failed to Lock Mutex \n"); return OSAL_FAIL; } } else /* Finite Timeout case */ { /* * Convert the inputted time into appropriate timespec struct. * Since timespec and OSAL timeval are of the the same type. * Reuse the timeval to timespec macros. */ OSAL_MS_TO_TIMEVAL(timeout, &timeoutVal); /* Get the current timestamp */ if (OSAL_SUCCESS != osalTimeGet(&currTime)) { return OSAL_FAIL; } /* Add this to the timeout so that it gives absolute * timeout value... */ OSAL_TIME_ADD(timeoutVal, currTime); /* ...and assign it to the timespec structure */ tspec.tv_sec = timeoutVal.secs; tspec.tv_nsec = timeoutVal.nsecs; status = pthread_mutex_timedlock(*mutex, &tspec); if (status) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexLock(): Failed to Lock Mutex \n"); return OSAL_FAIL; } } #endif return OSAL_SUCCESS; } OSAL_PUBLIC OSAL_STATUS osalMutexUnlock(OsalMutex *mutex) { #ifndef ICP_WITHOUT_THREAD OSAL_STATUS status; OSAL_PTR_ENSURE( mutex, "osalMutexUnlock(): Null mutex pointer", OSAL_FAIL); status = pthread_mutex_unlock(*mutex); if (status) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexUnlock(): Failed to Unlock Mutex \n"); return OSAL_FAIL; } #endif return OSAL_SUCCESS; } OSAL_PUBLIC OSAL_STATUS osalMutexDestroy(OsalMutex *mutex) { #ifndef ICP_WITHOUT_THREAD OSAL_STATUS status; OSAL_PTR_ENSURE( mutex, "osalMutexDestroy(): Null mutex pointer", OSAL_FAIL); status = pthread_mutex_destroy(*mutex); if (!status) { /* free the associated mutex structure */ osalMemFree((void *)*mutex); *mutex = NULL; } else { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "OsalMutexDestroy(): Failed to Destroy Mutex \n"); } return (status ? OSAL_FAIL : OSAL_SUCCESS); #else osalMemFree((void *)*mutex); return OSAL_SUCCESS; #endif } qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/OsalSemaphore.c000066400000000000000000000160431503624047500274550ustar00rootroot00000000000000/** * @file OsalSemaphore.c (linux user space) * * @brief Implementation for semaphore. * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include "Osal.h" /********************************************** * OSAL Semaphore Functions implemented using * POSIX interfaces. *********************************************/ /* * Initializes a semaphore object */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreInit(OsalSemaphore *sid, UINT32 start_value) { OSAL_LOCAL_ENSURE( sid, "osalSemaphoreInit(): Null semaphore pointer", OSAL_FAIL); /* * Allocate memory for the semaphore object. */ *sid = osalMemAlloc(sizeof(sem_t)); if (!(*sid)) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalSemaphoreInit: fail to allocate for semaphore \n"); return OSAL_FAIL; } /* * Initialize the semaphore object. */ if (sem_init(*sid, OSAL_POSIX_UNSHARED_SEMAPHORE, start_value) == -1) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalSemaphoreInit: Failed to \ initialize semaphore, exceeds the max counter value %d \n", SEM_VALUE_MAX); osalMemFree(*sid); *sid = NULL; return OSAL_FAIL; } return OSAL_SUCCESS; } /* * Decrements a semaphore, blocking if the * semaphore is unavailable (value is 0). */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreWait(OsalSemaphore *sid, INT32 timeout) { INT32 status; OsalTimeval timeoutVal, currTime; struct timespec ts; OSAL_LOCAL_ENSURE( sid, "osalSemaphoreWait(): Null semaphore pointer", OSAL_FAIL); /* * Guard against illegal timeout values * OSAL_WAIT_FORVER = -1 */ if (timeout < OSAL_WAIT_FOREVER) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalSemaphoreWait(): illegal timeout value \n"); return OSAL_FAIL; } /* * The return value can take OSAL_SUCCESS or OSAL_FAIL. * For this reason the caller can not distinguish * between recoverable/unrecoverable errors. * Semaphore wait can be interrupted, which is a * recoverable error; the retry is implemented * in OSAL with a loop. */ if (timeout == OSAL_WAIT_FOREVER) { do { status = sem_wait(*sid); } while (status < 0 && EINTR == errno); } else if (timeout == OSAL_WAIT_NONE) { do { status = sem_trywait(*sid); } while (status < 0 && EINTR == errno); } else { /* * Convert the inputted time into appropriate timespec struct. * Since timespec and OSAL timeval are of the the same type. * Reuse the timeval to timespec macros. */ OSAL_MS_TO_TIMEVAL(timeout, &timeoutVal); /* Get current time */ if (OSAL_SUCCESS != osalTimeGet(&currTime)) { return OSAL_FAIL; } /* Add this to the timeout so that it gives absolute timeout value */ OSAL_TIME_ADD(timeoutVal, currTime); do { ts.tv_sec = timeoutVal.secs; ts.tv_nsec = timeoutVal.nsecs; status = sem_timedwait(*sid, &ts); } while ((status == -1) && (errno == EINTR)); } if (status < 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalSemaphoreWait(): %s\n", strerror(errno)); return OSAL_FAIL; } else { return OSAL_SUCCESS; } } /* * Increments a semaphore object */ OSAL_PUBLIC OSAL_STATUS osalSemaphorePost(OsalSemaphore *sid) { INT32 status; OSAL_LOCAL_ENSURE( sid, "osalSemaphorePost(): Null semaphore pointer", OSAL_FAIL); /* * Increment the semaphore object. */ status = sem_post(*sid); if (status < 0) { return OSAL_FAIL; } else { return OSAL_SUCCESS; } } /* * Destroys the semaphore object */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreDestroy(OsalSemaphore *sid) { INT32 status; OSAL_LOCAL_ENSURE( sid, "osalSemaphoreDestroy(): Null semaphore pointer", OSAL_FAIL); /* * Destroy the semaphore object. */ status = sem_destroy(*sid); if (status != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalSemaphoreDestroy() : Semaphore Destroy failed\n"); return OSAL_FAIL; } /* * Free space allocated for the semaphore object. */ osalMemFree(*sid); *sid = NULL; return OSAL_SUCCESS; } /* * Decrements a semaphore, not blocking the calling thread * if the semaphore is unavailable */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreTryWait(OsalSemaphore *sid) { OSAL_LOCAL_ENSURE( sid, "osalSemaphoreTryWait(): Null semaphore pointer", OSAL_FAIL); if (sem_trywait(*sid)) { return OSAL_FAIL; } else { return OSAL_SUCCESS; } } /* * Retrieves the current value of a semaphore object */ OSAL_PUBLIC OSAL_STATUS osalSemaphoreGetValue(OsalSemaphore *sid, UINT32 *value) { OSAL_LOCAL_ENSURE( sid, "osalSemaphoreTryWait(): Null semaphore pointer", OSAL_FAIL); if (sem_getvalue(*sid, (int *)value)) { return OSAL_FAIL; } else { return OSAL_SUCCESS; } } qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/OsalServices.c000066400000000000000000000316321503624047500273160ustar00rootroot00000000000000/** * @file OsalServices.c (user space) * * @brief Implementation for Mem, Sleep and Log. * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #define __STDC_WANT_LIB_EXT1__ 1 #include #include #include #include #include #include #include #include #include "Osal.h" #define OSAL_IOFILE struct _IO_FILE #define OSAL_TIMEVAL_TOO_LARGE 0 /********************* * Log function *********************/ static char *traceHeaders[] = {"", "[fatal] ", "[error] ", "[warn] ", "[message] ", "[debug1] ", "[debug2] ", "[debug3] ", "[all] "}; static CHAR osalModuleName[OSAL_MAX_MODULE_NAME_LENGTH] = ""; OSAL_PRIVATE UINT32 max_UINT32 = 0xFFFFFFFF; /* by default trace all but debug message */ OSAL_PRIVATE int osalCurrLogLevel = OSAL_LOG_LVL_MESSAGE; #ifdef ICP_LOG_SYSLOG OSAL_PRIVATE int osalCurrOutput = OSAL_LOG_OUTPUT_SYSLOG; #else OSAL_PRIVATE int osalCurrOutput = OSAL_LOG_OUTPUT_STD; #endif /* Writing Log */ INT32 osalLog(OsalLogLevel level, OsalLogDevice device, char *format, ...) { OSAL_IOFILE *output_stream_s; int mask = 0; va_list args; INT32 headerByteCount = 0; INT32 byteCount = 0; /* * Return -1 for custom display devices */ switch (device) { case OSAL_LOG_DEV_STDOUT: output_stream_s = stdout; break; case OSAL_LOG_DEV_STDERR: output_stream_s = stderr; break; default: printf("osalLog: only OSAL_LOG_DEV_STDOUT" " and OSAL_LOG_DEV_STDERR are supported \n"); return (OSAL_LOG_ERROR); } if ((level <= osalCurrLogLevel) && (level != OSAL_LOG_LVL_NONE)) { if (OSAL_LOG_OUTPUT_SYSLOG == osalCurrOutput) { mask = setlogmask(0); setlogmask(mask | LOG_MASK(LOG_INFO)); if (level != OSAL_LOG_LVL_USER) { syslog(LOG_INFO, "%s", traceHeaders[level - 1]); } if (OSAL_OS_GET_STRING_LENGTH(osalModuleName, sizeof(osalModuleName)) != 0) { syslog(LOG_INFO, "%s :", osalModuleName); } va_start(args, format); vsyslog(LOG_INFO, format, args); va_end(args); return 0; } if (level != OSAL_LOG_LVL_USER) { byteCount = fprintf(output_stream_s, "%s", traceHeaders[level - 1]); if (byteCount < 0) { return (OSAL_LOG_ERROR); } headerByteCount += byteCount; } if (OSAL_OS_GET_STRING_LENGTH(osalModuleName, sizeof(osalModuleName)) != 0) { byteCount = fprintf(output_stream_s, "%s :", osalModuleName); if (byteCount < 0) { return (OSAL_LOG_ERROR); } headerByteCount += byteCount; } va_start(args, format); byteCount = vfprintf(output_stream_s, format, args); if (byteCount < 0) { return (OSAL_LOG_ERROR); } headerByteCount += byteCount; va_end(args); return headerByteCount; } else { return (OSAL_LOG_ERROR); } } OSAL_PUBLIC OSAL_STATUS osalStdLog(const char *arg_pFmtString, ...) { OSAL_STATUS err = OSAL_SUCCESS; va_list argList; va_start(argList, arg_pFmtString); if (OSAL_OS_GET_STRING_LENGTH(osalModuleName, sizeof(osalModuleName)) != 0) { printf("%s :", osalModuleName); } vprintf(arg_pFmtString, argList); va_end(argList); return err; } /* Returns the old level that got overwritten */ OSAL_PUBLIC UINT32 osalLogLevelSet(UINT32 level) { UINT32 oldLevel; /* * Check value first */ if (level > OSAL_LOG_LVL_ALL) { osalLog(OSAL_LOG_LVL_MESSAGE, OSAL_LOG_DEV_STDOUT, "osalLogLevelSet: Log Level is between %d and %d \n", OSAL_LOG_LVL_NONE, OSAL_LOG_LVL_ALL); return OSAL_LOG_LVL_NONE; } oldLevel = osalCurrLogLevel; osalCurrLogLevel = level; return oldLevel; } OSAL_PUBLIC void osalLogModuleSet(const char *name) { snprintf(osalModuleName, OSAL_MAX_MODULE_NAME_LENGTH, "%s", name); } OSAL_PUBLIC void osalLogOutputSet(UINT32 output) { osalCurrOutput = output; } /************************************** * Memory functions *************************************/ void *osalMemAlloc(UINT32 size) { return (malloc(size)); } void *osalMemAllocAtomic(UINT32 size) { return (malloc(size)); } /* * MemAlloc with Alignment API: * Make sure memory is aligned to alignment ( passed as last parameter) * This function is maintained for backward compatibility * IDS team has requested not to touch this code, as this is in working condition. * another implementation of this function can be found in API * "void * _OsalMemAllocAlligned(unsigned int size, unsigned int alignment)" * * return - Pointer to requested aligned memory. * in - space (unknown....why?) - size need to malloc * - alignment required ( 4, 8....256) * */ void *osalMemAllocAligned(UINT32 space, UINT32 size, UINT32 alignment) { void *pMem = NULL; if (alignment < 1 || alignment > OSAL_MAX_ALIGNMENT) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalMemAllocAligned(): invalid alignment value %d \n", alignment); return (void *)NULL; } if (alignment == 1) { pMem = osalMemAlloc(size); return pMem; } if (posix_memalign(&pMem, alignment, size) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalMemAllocAlligned(): not able to align memory\n"); return (void *)NULL; } return pMem; } void osalMemFree(void *ptr) { OSAL_MEM_ASSERT(ptr != NULL); free(ptr); } /* * Copy count bytes from src to dest , * returns pointer to the dest mem zone. */ void *osalMemCopy(void *dest, const void *src, UINT32 count) { OSAL_MEM_ASSERT(dest != NULL); OSAL_MEM_ASSERT(src != NULL); return (memcpy(dest, src, count)); } /* * Fills a memory zone with a given constant byte, * returns pointer to the memory zone. */ void *osalMemSet(void *ptr, UINT8 filler, UINT32 count) { OSAL_MEM_ASSERT(ptr != NULL); return (memset(ptr, filler, count)); } static void *osalMemZero(void *const ptr, const UINT32 count) { UINT32 lim = 0; volatile unsigned char *volatile dstPtr = ptr; while (lim < count) { dstPtr[lim++] = '\0'; } return (void *)dstPtr; } /* * Function for unoptimized calls. * Fills a memory zone with 0, * returns pointer to the memory zone. */ void *osalMemZeroExplicit(void *ptr, UINT32 count) { OSAL_MEM_ASSERT(ptr != NULL); #ifdef __STDC_LIB_EXT1__ errno_t result = memset_s(ptr, sizeof(ptr), 0, count); /* Supported on C11 standard */ OSAL_MEM_ASSERT(result == 0); return ptr; #else return osalMemZero(ptr, count); /* Platform-independent secure memset */ #endif } OSAL_PUBLIC void osalMemAlignedFree(void *ptr) { osalMemFree(ptr); } /********************************************** * Time module **********************************************/ /* * Retrieve current system time. */ OSAL_PUBLIC OSAL_STATUS osalTimeGet(OsalTimeval *ptime) { struct timeval tval; if (gettimeofday(&tval, NULL) == -1) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalTimeGet(): gettimeofday system call failed \n"); return OSAL_FAIL; } ptime->secs = tval.tv_sec; /* * gettimeofday returns in terms of sec and uSec. * Convert it into sec and nanoseconds into OSAL type */ ptime->nsecs = tval.tv_usec * OSAL_THOUSAND; return OSAL_SUCCESS; } OSAL_PUBLIC UINT64 osalTimestampGet(void) { OsalTimeval ptime = {0}; osalTimeGet(&ptime); return ((ptime.secs * OSAL_MILLION) + ptime.nsecs / OSAL_THOUSAND); } OSAL_PUBLIC UINT64 osalTimestampGetNs(void) { OsalTimeval ptime; #if __GLIBC_PREREQ(2, 17) struct timespec tspec; if (clock_gettime(CLOCK_REALTIME, &tspec) == 0) { return (UINT64)tspec.tv_sec * OSAL_BILLION + (UINT64)tspec.tv_nsec; } osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalTimestampGetNs(): clock_gettime(CLOCK_REALTIME) system call " "failed. Invoking osalTimeGet() as fallback\n"); #endif ptime.secs = 0; ptime.nsecs = 0; (void)osalTimeGet(&ptime); return ptime.secs * OSAL_BILLION + ptime.nsecs; } OSAL_PUBLIC UINT32 osalSysClockRateGet(void) { return (HZ); } OSAL_PUBLIC void osalTicksToTimeval(UINT64 ticks, OsalTimeval *pTv) { UINT32 tickPerSecs = 0; UINT32 nanoSecsPerTick = 0; /* * Reset the time value */ pTv->secs = 0; pTv->nsecs = 0; tickPerSecs = osalSysClockRateGet(); nanoSecsPerTick = OSAL_BILLION / tickPerSecs; /* * value less than 1 sec */ if (tickPerSecs > ticks) /* value less then 1 sec */ { pTv->nsecs = ticks * nanoSecsPerTick; } else { pTv->secs = ticks / tickPerSecs; pTv->nsecs = (ticks % tickPerSecs) * nanoSecsPerTick; } } OSAL_PUBLIC UINT32 osalTimevalToTicks(OsalTimeval tv) { UINT32 tickPerSecs = 0; UINT32 nanoSecsPerTick = 0; UINT32 maxSecs = 0; tickPerSecs = osalSysClockRateGet(); nanoSecsPerTick = OSAL_BILLION / tickPerSecs; /* * Make sure we do not overflow */ maxSecs = (max_UINT32 / tickPerSecs) - (tv.nsecs / OSAL_BILLION); if (maxSecs < tv.secs) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalTimevalToTicks(): Timeval too high. Max value allowed" " in seconds is %u < %llu\n", maxSecs, tv.secs); return OSAL_TIMEVAL_TOO_LARGE; } return ((tv.secs * tickPerSecs) + (tv.nsecs / nanoSecsPerTick)); } /************************************** * Task services module *************************************/ /* * Sleep for the specified number of milliseconds */ OSAL_PUBLIC OSAL_STATUS osalSleep(UINT32 milliseconds) { struct timespec resTime, remTime; INT32 status; UINT32 mil_rem; /* Divide by number of millisec per second */ resTime.tv_sec = milliseconds / OSAL_THOUSAND; /* Multiply remainder by number of nanosecs per millisecond */ mil_rem = milliseconds % OSAL_THOUSAND; resTime.tv_nsec = mil_rem * OSAL_MILLION; do { status = nanosleep(&resTime, &remTime); resTime.tv_sec = remTime.tv_sec; resTime.tv_nsec = remTime.tv_nsec; } while ((status != OSAL_SUCCESS) && (errno == EINTR)); if (status != OSAL_SUCCESS) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalSleep():nanosleep() failed; errno=%d\n", errno); return OSAL_FAIL; } else { return OSAL_SUCCESS; } } OSAL_PUBLIC void osalYield(void) { sched_yield(); } qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/OsalSpinLock.c000066400000000000000000000063321503624047500272540ustar00rootroot00000000000000/** * @file OsalSpinLock.c (linux user space) * * @brief Implementation for spinlocks * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "Osal.h" OSAL_PUBLIC OSAL_STATUS osalLockInit(OsalLock *slock, OsalLockType slockType) { #ifndef ICP_WITHOUT_THREAD OSAL_LOCAL_ENSURE( slock, "osalLockInit(): Null spinlock pointer", OSAL_FAIL); /* Spinlock type is ignored in case of Linux */ return pthread_spin_init(slock, PTHREAD_PROCESS_PRIVATE) ? OSAL_FAIL : OSAL_SUCCESS; #else return OSAL_SUCCESS; #endif } OSAL_PUBLIC OSAL_STATUS osalLock(OsalLock *slock) { #ifndef ICP_WITHOUT_THREAD OSAL_LOCAL_ENSURE( slock, "osalLockLock(): Null spinlock pointer", OSAL_FAIL); return pthread_spin_lock(slock) ? OSAL_FAIL : OSAL_SUCCESS; #else return OSAL_SUCCESS; #endif } OSAL_PUBLIC OSAL_STATUS osalUnlock(OsalLock *slock) { #ifndef ICP_WITHOUT_THREAD OSAL_LOCAL_ENSURE( slock, "osalLockUnlock(): Null spinlock pointer", OSAL_FAIL); return pthread_spin_unlock(slock) ? OSAL_FAIL : OSAL_SUCCESS; #else return OSAL_SUCCESS; #endif } OSAL_PUBLIC OSAL_STATUS osalLockDestroy(OsalLock *slock) { #ifndef ICP_WITHOUT_THREAD OSAL_LOCAL_ENSURE( slock, "osalLockDestroy(): Null spinlock pointer", OSAL_FAIL); return pthread_spin_destroy(slock) ? OSAL_FAIL : OSAL_SUCCESS; #else return OSAL_SUCCESS; #endif } OSAL_PUBLIC OSAL_STATUS osalLockBh(OsalLock *slock) { return osalLock(slock); } OSAL_PUBLIC OSAL_STATUS osalUnlockBh(OsalLock *slock) { return osalUnlock(slock); } qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/OsalThread.c000066400000000000000000000335701503624047500267450ustar00rootroot00000000000000/** * @file OsalThread.c (user space) * * @brief POSIX thread implementation. * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef ICP_WITHOUT_THREAD #define _GNU_SOURCE #include #endif #include "Osal.h" OSAL_PUBLIC OSAL_STATUS osalThreadCreate(OsalThread *thread, OsalThreadAttr *threadAttr, OsalVoidFnVoidPtr startRoutine, void *arg) { #ifndef ICP_WITHOUT_THREAD INT32 status; pthread_attr_t attr; struct sched_param param; OSAL_LOCAL_ENSURE(startRoutine, "OsalThreadCreate(): Null start routine pointer", OSAL_FAIL); if (pthread_attr_init(&attr) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to initialize Thread Attributes!\n"); return OSAL_FAIL; } /* Setting scheduling parameter will fail for non root user, * as the default value of inheritsched is PTHREAD_EXPLICIT_SCHED in * POSIX. It is not required to set it explicitly before setting the * scheduling policy */ if (threadAttr == NULL) { if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to set inherit sched for thread!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } if (pthread_attr_setschedpolicy( &attr, OSAL_OS_THREAD_DEFAULT_SCHED_POLICY) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to set scheduling policy for thread!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } /* Set priority based on value in threadAttr */ osalMemSet(¶m, 0, sizeof(param)); param.sched_priority = OSAL_OS_DEFAULT_THREAD_PRIORITY; if (pthread_attr_setschedparam(&attr, ¶m) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to set the sched parameters attribute!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } } else { /* Set scheduling policy based on value in threadAttr */ if ((threadAttr->policy != SCHED_RR) && (threadAttr->policy != SCHED_FIFO) && (threadAttr->policy != SCHED_OTHER)) { osalLog(OSAL_LOG_LVL_DEBUG3, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate: Invalid policy type! " "Changing to OSAL_THREAD_DEFAULT_SCHED_POLICY\n"); threadAttr->policy = OSAL_THREAD_DEFAULT_SCHED_POLICY; } if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to set inherit sched for thread!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } if (pthread_attr_setschedpolicy(&attr, threadAttr->policy) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to set scheduling policy for thread!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } /* Set priority based on value in threadAttr */ osalMemSet(¶m, 0, sizeof(param)); param.sched_priority = threadAttr->priority; if (threadAttr->policy != SCHED_OTHER) { if (pthread_attr_setschedparam(&attr, ¶m) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to set the sched parameters attribute!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } } } /* end of if(threadAttr == NULL) */ /* Always create detached thread as JOINABLE thread is not needed by * any of the OSAL users currently */ if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate:" "Failed to set the dettachState attribute!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate: Failed to set the attribute!\n"); pthread_attr_destroy(&attr); return OSAL_FAIL; } status = pthread_create(thread, &attr, (void *(*)(void *))startRoutine, arg); if (status) { switch (status) { case EAGAIN: osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate: Not enough resources to create " "the thread!\n"); break; case EINVAL: osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate: value specified in attr is " "invalid!\n"); break; case EPERM: osalLog( OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate: insufficient permissions!\n" "Running below options can resolve EPERM issue" "1. Check the value from" "/sys/fs/cgroup/cpu,cpuacct/cpu.rt_runtime_us, and add " "the same in " "/sys/fs/cgroup/cpu,cpuacct/user.slice/cpu.rt_runtime_us" "2. When running inside container(docker) environment, the " "sched_setscheduler() system call " "might return non-zero value (indicating error), so please " "make sure that:\n" "1) your image was run with '--cap-add=SYS_NICE' or " "'--cap-add=ALL' flag\n" "2) your image was run with '--cpu-rt-runtime=x' where 'x' " "is the CPU real-time runtime in μs (for example 900000)\n" "3) the value in " "/sys/fs/cgroups/cpu,cpuacct/machine.slice/" "cpu.rt_runtime_us corresponds to the value of 'x' from " "2)\n"); break; default: osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadCreate: Failed to create the thread!\n"); break; } pthread_attr_destroy(&attr); return OSAL_FAIL; } pthread_attr_destroy(&attr); #endif return OSAL_SUCCESS; } /* osalThreadCreate */ OSAL_PUBLIC void osalThreadBind(OsalThread *pTid, UINT32 cpu) { #ifndef ICP_WITHOUT_THREAD cpu_set_t cpuSet; /* Initialize the cpuSet to zero */ CPU_ZERO(&cpuSet); /* Set given cpu in cpuSet */ CPU_SET(cpu, &cpuSet); /* Bind given thread to requested CPU core */ if (pthread_setaffinity_np(*pTid, sizeof(cpuSet), &cpuSet) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadBind: Failed to bind the thread to requested " "core!\n"); return; } /* Obtain actual thread CPU affinity */ if (pthread_getaffinity_np(*pTid, sizeof(cpuSet), &cpuSet) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadBind: Failed to obtain bounded thread " "affinity!\n"); return; } /* Check if thread is bound as requested */ if (!CPU_ISSET(cpu, &cpuSet)) { osalLog(OSAL_LOG_LVL_WARNING, OSAL_LOG_DEV_STDOUT, "\nosalThreadBind: thread is not bound with requested core!\n"); return; } #endif } OSAL_PUBLIC OSAL_STATUS osalThreadStart(OsalThread *thread) { osalLog(OSAL_LOG_LVL_DEBUG3, OSAL_LOG_DEV_STDOUT, "\nosalThreadStart: Nothing to be done!\n"); return OSAL_SUCCESS; } OSAL_PUBLIC OSAL_STATUS osalThreadKill(OsalThread *thread) { #ifndef ICP_WITHOUT_THREAD INT32 status; OSAL_LOCAL_ENSURE( thread, "osalThreadKill(): Null thread pointer", OSAL_FAIL); status = pthread_cancel(*thread); if (status) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadKill: Failed to cancel the thread!\n"); return OSAL_FAIL; } #endif return OSAL_SUCCESS; } /* osalThreadKill */ OSAL_PUBLIC OSAL_STATUS osalThreadPrioritySet(OsalThread *thread, UINT32 priority) { #ifndef ICP_WITHOUT_THREAD INT32 status; struct sched_param param1; int policy1; int minPrio, maxPrio; OSAL_LOCAL_ENSURE( thread, "osalThreadPrioritySet(): Null thread pointer", OSAL_FAIL); if (pthread_getschedparam(*thread, &policy1, ¶m1) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalThreadPrioritySet(): could not get sched param!\n"); return OSAL_FAIL; } minPrio = sched_get_priority_min(policy1); maxPrio = sched_get_priority_max(policy1); if ((priority < minPrio) || (priority > maxPrio)) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalThreadPrioritySet(): Erroneous priority!\n"); return OSAL_FAIL; } status = pthread_setschedprio(*thread, priority); if (status) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "\nosalThreadPrioritySet(): set prio failed \n !"); return OSAL_FAIL; } #endif return OSAL_SUCCESS; } OSAL_PUBLIC void osalThreadExit(void) { #ifndef ICP_WITHOUT_THREAD pthread_exit(NULL); #endif } /* API to set scheduling policy and priority of an executing thread */ OSAL_PUBLIC OSAL_STATUS osalThreadSetPolicyAndPriority(OsalThread *thread, UINT32 policy, UINT32 priority) { #ifndef ICP_WITHOUT_THREAD int ret = 0; struct sched_param param; int minPrio, maxPrio, policy1; OSAL_LOCAL_ENSURE(thread, "osalThreadSetPolicyAndPriority(): Null thread pointer", OSAL_FAIL); /* check for a valid value for 'policy' */ if ((policy != SCHED_RR) && (policy != SCHED_FIFO) && (policy != SCHED_OTHER)) { osalLog( OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalThreadSetPolicyAndPriority(): invalid value for policy!\n"); return OSAL_FAIL; } osalMemSet(¶m, 0, sizeof(param)); if (pthread_getschedparam(*thread, &policy1, ¶m) != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalThreadSetPolicyAndPriority(): could not get sched param" "!\n"); return OSAL_FAIL; } minPrio = sched_get_priority_min(policy); maxPrio = sched_get_priority_max(policy); if ((priority < minPrio) || (priority > maxPrio)) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalThreadPrioritySet(): Erroneous priority!\n"); return OSAL_FAIL; } param.sched_priority = priority; ret = pthread_setschedparam(*thread, policy, ¶m); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "osalThreadSetPolicyAndPriority:" "Policy and Priority Set operation failed!\n"); return OSAL_FAIL; } #endif return OSAL_SUCCESS; } qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/OsalUsrKrnProxy.c000066400000000000000000001077461503624047500300330ustar00rootroot00000000000000/** * @file OsalUsrKrnProxy.c (linux user space) * * @brief Implementation for NUMA. * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "Osal.h" #include "OsalOsTypes.h" #include "OsalDevDrv.h" #include "OsalDevDrvCommon.h" #include #include #include #include #include #include #include #include #include #include #include #include /* The maximum number we allow to search for available size */ #define MAX_LOOKUP_NUM 10 /* the maximum retry to wait for memcpy ready */ #define MAX_MEMCPY_WAITNUM 100 #define BITMAP_LEN 8 #define QWORD_WIDTH (8 * sizeof(UINT64)) #define DWORD_WIDTH (8 * sizeof(UINT32)) #define WORD_WIDTH (8 * sizeof(UINT16)) #define QWORD_ALL_ONE 0xFFFFFFFFFFFFFFFFULL #define QWORD_MSB_SET 0x8000000000000000ULL #define LOWER_WORD_ALL_ONE 0xFFFFUL #define MMAP_FLAGS MAP_PRIVATE #ifndef __off_t typedef off_t __off_t; #endif static int fd = -1; static int fdp = -1; static int strict_node = 1; #ifndef ICP_WITHOUT_THREAD static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mutex_page = PTHREAD_MUTEX_INITIALIZER; #endif static dev_mem_info_t *pUserMemList = NULL; static dev_mem_info_t *pUserMemListHead = NULL; static dev_mem_info_t *pUserLargeMemList = NULL; static dev_mem_info_t *pUserLargeMemListHead = NULL; static dev_mem_info_t *pUserMemListPage = NULL; static dev_mem_info_t *pUserMemListHeadPage = NULL; static INT32 ctzll(UINT64 bitmap_window) { UINT64 mask = 1ULL; UINT32 retval = 0; while (!(mask & bitmap_window)) { ++retval; mask <<= 1; } return retval; } /* * reads a 64-bit window from a 8x64-bit bitmap * starting from window_pos (0 - 510 ) * map points to the 8x64 bit map area * returns the 64-bit window from the 8x64 bitmap. */ static UINT64 bitmap_read(UINT64 *map, size_t window_pos) { UINT64 quad_word_window = 0ULL; UINT64 next_quad_word = 0ULL; size_t quad_word_pos = BITMAP_LEN - window_pos / QWORD_WIDTH - 1; size_t bit_pos = window_pos % QWORD_WIDTH; quad_word_window = map[quad_word_pos]; if (0 == bit_pos) { return quad_word_window; } if (0 == quad_word_pos) { next_quad_word = QWORD_ALL_ONE; } else { next_quad_word = map[quad_word_pos - 1]; } quad_word_window >>= bit_pos; next_quad_word &= ((1ULL << bit_pos) - 1); next_quad_word <<= QWORD_WIDTH - bit_pos; quad_word_window |= next_quad_word; return quad_word_window; } /* * modify the 8x64-bit bitmap from pos * for len length * if set nonzero bits from pos for len length are set to 1 * otherwise they are cleared to zero */ static void modify_bitmap(UINT64 *map, size_t pos, size_t len, UINT32 set) { size_t window = 0; size_t bitfield_pos = 0; size_t bitfield_len = 0; UINT64 mask = 0ULL; while (len > 0) { window = BITMAP_LEN - pos / QWORD_WIDTH - 1; bitfield_pos = pos % QWORD_WIDTH; if (len + bitfield_pos >= QWORD_WIDTH) { bitfield_len = QWORD_WIDTH - bitfield_pos; mask = ((1ULL << bitfield_pos) - 1); } else { bitfield_len = len; mask = ((1ULL << bitfield_pos) - 1) | ~((1ULL << (bitfield_pos + bitfield_len)) - 1); } if (set) { map[window] |= ~mask; } else { map[window] &= mask; } len -= bitfield_len; pos += bitfield_len; } } /* * mem_alloc allocates memory with min. size = PAGE_SIZE * map points to a dev_mem_info_t structure with virtual address * size is the requested number of bytes * minimum allocation size is PAGE_SIZE * the first unsigned int of the allocated block has * the starting block number in the upper * and the size in PAGE_SIZE in the lower 16 bits. * returns a pointer to the newly allocated block that * points to the memory area after this unsigned integer */ static void *mem_alloc(void *map, size_t size) { UINT64 *bitmap = NULL; INT32 window_pos = 0; UINT32 *retval = NULL; INT32 blocks_found = 0; UINT64 bitmap_window = 0ULL; UINT32 blocks_required = 0ULL; UINT32 first_block = 1; if (NULL == map || 0 == size) { return retval; } bitmap = (UINT64 *)((UINT8 *)map + USER_MEM_128BYTE_OFFSET); /* increase size to make room for an integer to hold first block/length * info*/ size += sizeof(UINT32); blocks_required = size % PAGE_SIZE ? size / PAGE_SIZE + 1 : size / PAGE_SIZE; do { INT32 width = 0; /* read 64-bit bitmap window from window_pos (0-510) */ bitmap_window = bitmap_read(bitmap, window_pos); /* check if there is at least a 1 in bitmap window */ if (bitmap_window) { /* find number of contiguous 0s from right */ width = ctzll(bitmap_window); } else { /* bitmap window is 0 there are 64 contiguous 0s*/ width = QWORD_WIDTH; } /* increment number of blocks found with number of contig. 0s in bitmap * window */ blocks_found += width; /* check if a fit is found */ if (blocks_found >= blocks_required) { /* calculate return address from virtual address and first block * number */ retval = (UINT32 *)(((dev_mem_info_t *)map)->virt_addr) + (first_block)*PAGE_SIZE / sizeof(UINT32); /* save first block number and length in the first integer of the * block * and increment pointer */ *retval++ = (first_block << WORD_WIDTH) | (blocks_required & LOWER_WORD_ALL_ONE); /* set bit maps from bit position (0-510) = first_block(1-511) - 1 * with blocks_required length in bitmap */ modify_bitmap(bitmap, first_block - 1, blocks_required, 1); break; } else { /* did not find fit check if bitmap_window has at least a 1*/ if (bitmap_window) { /* bit field of 0s not contiguous, clear blocks_found adjust * first_block * and window_pos */ blocks_found = 0; window_pos += width + 1; first_block = window_pos + 1; } else { /* bit field of 0s is contiguous, but fit not found yet * move window_pos an search more 0s */ window_pos += width; } } } while (window_pos < BITMAP_LEN * QWORD_WIDTH - 1); return retval; } /* * deallocates previously allocated blocks * map is a pointer to dev_mem_info_t structure * block is returned by ia previous mem_alloc call */ static void mem_free(void *map, void *block) { UINT32 first_block = 0; UINT32 length = 0; UINT32 *start_of_block = block; UINT64 *bitmap = (UINT64 *)((UINT8 *)map + USER_MEM_128BYTE_OFFSET); if (NULL == block) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Block address is zero \n"); return; } /* find start of block that is one integer back from user area */ --start_of_block; /* retrieve first_block and length of block from integer at the start of * block */ first_block = *start_of_block >> WORD_WIDTH; length = *start_of_block & LOWER_WORD_ALL_ONE; if (!first_block || first_block > BITMAP_LEN * QWORD_WIDTH - 1 || length + first_block > BITMAP_LEN * QWORD_WIDTH) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Invalid block first block: %d length: %d\n", first_block, length); return; } /* clear bitmap from bitmap position (0-510) = first_block(1-511) - 1 for * length */ modify_bitmap(bitmap, first_block - 1, length, 0); } OSAL_STATUS userMemListAdd(dev_mem_info_t *pMemInfo) { #ifndef ICP_WITHOUT_THREAD int ret = 0; ret = pthread_mutex_lock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_lock(): Failed to lock mutex, ret = %d \n", ret); return OSAL_FAIL; } #endif ADD_ELEMENT_TO_HEAD_OF_LIST(pMemInfo, pUserMemList, pUserMemListHead); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = %d \n", ret); return OSAL_FAIL; } #endif return OSAL_SUCCESS; } static OSAL_STATUS userLargeMemListAdd(dev_mem_info_t *pMemInfo) { #ifndef ICP_WITHOUT_THREAD int ret = 0; ret = pthread_mutex_lock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_lock(): Failed to lock mutex, ret = %d \n", ret); return OSAL_FAIL; } #endif ADD_ELEMENT_TO_HEAD_OF_LIST( pMemInfo, pUserLargeMemList, pUserLargeMemListHead); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = %d \n", ret); return OSAL_FAIL; } #endif return OSAL_SUCCESS; } OSAL_STATUS userMemListAddPage(dev_mem_info_t *pMemInfo) { #ifndef ICP_WITHOUT_THREAD int ret = 0; ret = pthread_mutex_lock(&mutex_page); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_lock(): Failed to lock mutex, ret = %d \n", ret); return OSAL_FAIL; } #endif ADD_ELEMENT_TO_END_OF_LIST( pMemInfo, pUserMemListPage, pUserMemListHeadPage); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex_page); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = %d \n", ret); return OSAL_FAIL; } #endif return OSAL_SUCCESS; } void userMemListFree(dev_mem_info_t *pMemInfo) { dev_mem_info_t *pCurr = NULL; int done = 0; for (pCurr = pUserLargeMemListHead; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr == pMemInfo) { REMOVE_ELEMENT_FROM_LIST( pCurr, pUserLargeMemList, pUserLargeMemListHead); done = 1; break; } } for (pCurr = pUserMemListHead; (pCurr != NULL) && (done == 0); pCurr = pCurr->pNext) { if (pCurr == pMemInfo) { REMOVE_ELEMENT_FROM_LIST(pCurr, pUserMemList, pUserMemListHead); break; } } } void userMemListFreePage(dev_mem_info_t *pMemInfo) { dev_mem_info_t *pCurr = NULL; for (pCurr = pUserMemListHeadPage; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr == pMemInfo) { REMOVE_ELEMENT_FROM_LIST( pCurr, pUserMemListPage, pUserMemListHeadPage); break; } } } dev_mem_info_t *userMemLookupBySize(UINT32 size, UINT32 node, void **block) { dev_mem_info_t *pCurr = NULL; int link_num = 0; /* Search from new to old */ for (pCurr = pUserMemListHead; pCurr != NULL; pCurr = pCurr->pNext) { if (strict_node && (pCurr->nodeId != node)) { continue; } if (pCurr->available_size >= size + sizeof(UINT32)) { *block = mem_alloc(pCurr, size); if (*block != NULL) { return pCurr; } } /* Prevent from visiting whole chain, because after the first * several node, the chance to get one is very small. * Another consideration is to prevent new allocation from old * link, so that the old link could be released */ link_num++; if (link_num >= MAX_LOOKUP_NUM) { break; } } return NULL; } dev_mem_info_t *userMemLookupByVirtAddr(void *virt_addr) { dev_mem_info_t *pCurr = NULL; for (pCurr = pUserMemListHead; pCurr != NULL; pCurr = pCurr->pNext) { if ((UARCH_INT)pCurr->virt_addr <= (UARCH_INT)virt_addr && ((UARCH_INT)pCurr->virt_addr + pCurr->size) > (UARCH_INT)virt_addr) { return pCurr; } } return NULL; } static dev_mem_info_t *userLargeMemLookupByVirtAddr(void *virt_addr) { dev_mem_info_t *pCurr = NULL; for (pCurr = pUserLargeMemListHead; pCurr != NULL; pCurr = pCurr->pNext) { if ((UARCH_INT)pCurr->virt_addr <= (UARCH_INT)virt_addr && ((UARCH_INT)pCurr->virt_addr + pCurr->size) > (UARCH_INT)virt_addr) { return pCurr; } } return NULL; } dev_mem_info_t *userMemLookupByVirtAddrPage(void *virt_addr) { dev_mem_info_t *pCurr = NULL; for (pCurr = pUserMemListHeadPage; pCurr != NULL; pCurr = pCurr->pNext) { if ((UARCH_INT)pCurr->virt_addr == (UARCH_INT)virt_addr) { return pCurr; } } return NULL; } OSAL_PUBLIC OSAL_STATUS osalMemInitialize(char *path) { char mem_path[DEV_PATH_SIZE] = ""; char mempage_path[DEV_PATH_SIZE] = ""; if (fd > 0 && fdp > 0) { return OSAL_SUCCESS; } if (path != NULL) { size_t dev_mem_name_page_len = 0; size_t offs = 0; size_t os_dev_dir_len = 0; size_t path_len = 0; // Look only at the first DEV_PATH_SIZE characters for a null byte. path_len = OSAL_OS_GET_STRING_LENGTH(path, DEV_PATH_SIZE); os_dev_dir_len = sizeof(OS_DEV_DIRECTORY) - 1; dev_mem_name_page_len = sizeof(DEV_MEM_NAME_PAGE) - 1; if (path_len + os_dev_dir_len + dev_mem_name_page_len > DEV_PATH_SIZE) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "path to device is greater that max length %d\n", fd); return OSAL_FAIL; } offs = snprintf(mem_path, sizeof(mem_path), "%s", OS_DEV_DIRECTORY); offs = MIN(offs, sizeof(mem_path)); offs += snprintf(mem_path + offs, sizeof(mem_path) - offs, "%s", path); offs = MIN(offs, sizeof(mem_path)); snprintf(mem_path + offs, sizeof(mem_path) - offs, "%s", DEV_MEM_NAME); offs = snprintf( mempage_path, sizeof(mempage_path), "%s", OS_DEV_DIRECTORY); offs = MIN(offs, sizeof(mempage_path)); offs += snprintf( mempage_path + offs, sizeof(mempage_path) - offs, "%s", path); offs = MIN(offs, sizeof(mempage_path)); snprintf(mempage_path + offs, sizeof(mempage_path) - offs, "%s", DEV_MEM_NAME_PAGE); } fd = open((path) ? mem_path : DEV_MEM_PATH, O_RDWR); if (fd < 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "unable to open %s %d\n", (path) ? mem_path : DEV_MEM_PATH, fd); return OSAL_FAIL; } fdp = open((path) ? mempage_path : DEV_MEM_PAGE_PATH, O_RDWR); if (fdp < 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "unable to open %s %d\n", (path) ? mempage_path : DEV_MEM_PAGE_PATH, fdp); close(fd); fd = -1; return OSAL_FAIL; } return OSAL_SUCCESS; } OSAL_PUBLIC void osalMemDestroy() { if (fd > 0) { close(fd); fd = -1; } if (fdp > 0) { close(fdp); fdp = -1; } } OSAL_PUBLIC void *osalMemAllocContiguousNUMA(UINT32 size, UINT32 node, UINT32 alignment) { int ret = 0; dev_mem_info_t *pMemInfo = NULL; void *pVirtAddress = NULL; void *pOriginalAddress = NULL; UARCH_INT padding = 0; UARCH_INT aligned_address = 0; int requested_pages = 0; int full_size = 0; int allocate_pages = 0; UARCH_INT offset = 0; int mmap_size = 0; int alloc_size = 0; int large_memory = 0; UINT8 *bitmask = NULL; if (size == 0 || alignment == 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Invalid size or alignment parameter \n"); return NULL; } if (fd < 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Memory file handle %d is not ready\n", fd); return NULL; } if (alignment == sizeof(UINT32) || alignment == sizeof(UINT16)) { alignment = 0; } #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_lock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_lock(): Failed to lock mutex, ret = %d \n", ret); return NULL; } #endif if ((pMemInfo = userMemLookupBySize( size + alignment, node, &pOriginalAddress)) != NULL) { padding = alignment ? (UARCH_INT)pOriginalAddress % alignment : 0; aligned_address = ((UARCH_INT)pOriginalAddress) + (alignment - padding); pMemInfo->available_size -= (*((UINT32 *)pOriginalAddress - 1) & LOWER_WORD_ALL_ONE) * PAGE_SIZE; pMemInfo->allocations += 1; #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalMemFreeNUMA(pMemInfo); osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = " "%d \n", ret); return NULL; } #endif return (void *)aligned_address; } #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = %d \n", ret); return NULL; } #endif /* full size means header size plus requested size */ full_size = size + sizeof(UINT32) + alignment; /* calculate pages needed */ requested_pages = full_size % PAGE_SIZE ? ((full_size / PAGE_SIZE) + 1) : (full_size) / PAGE_SIZE; if (requested_pages > NUM_PAGES_PER_ALLOC - 1) { large_memory = 1; allocate_pages = size % PAGE_SIZE ? size / PAGE_SIZE + 1 : size / PAGE_SIZE; } else { allocate_pages = NUM_PAGES_PER_ALLOC; } /* calculate how many memory for allocation*/ if (alloc_size == 0) { alloc_size = allocate_pages * PAGE_SIZE; } /* Memory needed for pMemInfo: * The first part is for the struct dev_mem_info_t. * The second part is for the bitmap window which is located at an offset * of USER_MEM_128BYTE_OFFSET. See mem_alloc() function for usage. * Note sizeof(dev_mem_info_t) is less than USER_MEM_128BYTE_OFFSET * The explicit calculation below is just to let static analysers know that * the struct will fit in the resulting space. */ size_t pMemInfo_size = sizeof(dev_mem_info_t) > (USER_MEM_128BYTE_OFFSET) ? sizeof(dev_mem_info_t) : USER_MEM_128BYTE_OFFSET; pMemInfo_size += ((BITMAP_LEN) * sizeof(UINT64)); pMemInfo = calloc(1, pMemInfo_size); if (NULL == pMemInfo) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "unable to allocate pMemInfo buffer\n"); return NULL; } pMemInfo->allocations = 0; pMemInfo->nodeId = node; pMemInfo->size = alloc_size; /* Try to allocate memory as much as possible */ ret = ioctl(fd, DEV_MEM_IOC_MEMALLOC, pMemInfo); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "ioctl memory alloc failed, ret = %d\n", ret); free(pMemInfo); return NULL; } if (node != pMemInfo->nodeId) { strict_node = 0; } if (large_memory) { mmap_size = pMemInfo->size; /* When uses really wants to mmap 0x2*NUM_PAGES_PER_ALLOC * We have to do some fixup */ if ((mmap_size / PAGE_SIZE) == DOUBLE_NUM_PAGES_PER_ALLOC) mmap_size = PAGE_SIZE * ICP_MMAP_DOUBLE_NUM_PAGES; } else { /* Use double size to call mmap, so that we can get aligned * virtual address */ mmap_size = 0x2 * pMemInfo->size; } pMemInfo->mmap_size = mmap_size; pMemInfo->fvirt_addr = mmap((caddr_t)0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (pMemInfo->id * getpagesize())); if (pMemInfo->fvirt_addr == (caddr_t)MAP_FAILED) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "mmap failed\n"); ret = ioctl(fd, DEV_MEM_IOC_MEMFREE, pMemInfo); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "ioctl DEV_MEM_IOC_MEMFREE call failed, ret = %d\n", ret); } free(pMemInfo); return NULL; } /* available size needs to subtract current size and header */ /* As DMA remapping may add extra page, so we need to use alloc_size instead of the size in pMemInfo structure */ #ifdef ICP_SRIOV /* Save one page for IORemapping */ alloc_size -= PAGE_SIZE; #endif pMemInfo->allocations = 1; if (large_memory) { pMemInfo->available_size = alloc_size - size - USER_MEM_128BYTE_OFFSET; pMemInfo->virt_addr = pMemInfo->fvirt_addr; pMemInfo->fvirt_addr = 0; if (userLargeMemListAdd(pMemInfo)) { ioctl(fd, DEV_MEM_IOC_MEMFREE, pMemInfo); userMemListFree(pMemInfo); free(pMemInfo); return NULL; } pVirtAddress = (void *)((UARCH_INT)pMemInfo->virt_addr + USER_MEM_128BYTE_OFFSET); } else { /* Save some space for memory info block*/ offset = ((UARCH_INT)pMemInfo->fvirt_addr + pMemInfo->size) % (pMemInfo->size); pMemInfo->virt_addr = (void *)((UARCH_INT)pMemInfo->fvirt_addr + pMemInfo->size - offset); if ((UARCH_INT)pMemInfo->virt_addr % PAGE_SIZE) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Bad virtual address alignment %p %x %lu\n", pMemInfo->virt_addr, NUM_PAGES_PER_ALLOC, PAGE_SIZE); ioctl(fd, DEV_MEM_IOC_MEMFREE, pMemInfo); free(pMemInfo); return NULL; } memcpy(pMemInfo->virt_addr, pMemInfo, sizeof(dev_mem_info_t)); bitmask = (UINT8 *)pMemInfo; *(UINT64 *)(bitmask + USER_MEM_128BYTE_OFFSET) = QWORD_MSB_SET; pVirtAddress = mem_alloc(pMemInfo, size + alignment); if (NULL == pVirtAddress) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Memory allocation failed Virtual address: %p Size: %x \n", pMemInfo->virt_addr, size + alignment); ioctl(fd, DEV_MEM_IOC_MEMFREE, pMemInfo); free(pMemInfo); return NULL; } pMemInfo->available_size = alloc_size - ((*((UINT32 *)pVirtAddress - 1) & LOWER_WORD_ALL_ONE) + 1) * PAGE_SIZE; userMemListAdd(pMemInfo); padding = alignment ? (UARCH_INT)pVirtAddress % alignment : 0; aligned_address = ((UARCH_INT)pVirtAddress) - padding + alignment; pVirtAddress = (void *)aligned_address; } return pVirtAddress; } OSAL_PUBLIC void *osalMemAllocPage(UINT32 node, UINT64 *physAddr) { int ret = 0; dev_mem_info_t *pMemInfo = NULL; if (fd < 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Memory file handle %d is not ready\n", fd); return NULL; } pMemInfo = malloc(sizeof(dev_mem_info_t)); if (NULL == pMemInfo) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "unable to allocate pMemInfo buffer\n"); return NULL; } pMemInfo->nodeId = node; pMemInfo->size = getpagesize(); ret = ioctl(fdp, DEV_MEM_IOC_MEMALLOCPAGE, pMemInfo); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "ioctl call failed, ret = %d\n", ret); free(pMemInfo); return NULL; } pMemInfo->virt_addr = mmap(NULL, pMemInfo->size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fdp, (__off_t)pMemInfo->id * getpagesize()); if (pMemInfo->virt_addr == MAP_FAILED) { osalStdLog("Errno: %d\n", errno); osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "mmap failed\n"); ret = ioctl(fd, DEV_MEM_IOC_MEMFREEPAGE, pMemInfo); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "ioctl call failed, ret = %d\n", ret); } free(pMemInfo); return NULL; } if (userMemListAddPage(pMemInfo)) { ret = munmap(pMemInfo->virt_addr, getpagesize()); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "munmap failed, ret = %d\n", ret); } ret = ioctl(fdp, DEV_MEM_IOC_MEMFREEPAGE, pMemInfo); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "ioctl call failed, ret = %d\n", ret); } userMemListFreePage(pMemInfo); free(pMemInfo); return NULL; } *physAddr = pMemInfo->phy_addr; return pMemInfo->virt_addr; } OSAL_PUBLIC void osalMemFreeNUMA(void *pVirtAddress) { int ret = 0; dev_mem_info_t *pMemInfo = NULL; if (NULL == pVirtAddress) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Invalid virtual address\n"); return; } #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_lock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_lock(): Failed to lock mutex, ret = %d \n", ret); return; } #endif if ((pMemInfo = userMemLookupByVirtAddr(pVirtAddress)) != NULL) { pMemInfo->allocations -= 1; if (pMemInfo->allocations != 0) { UINT32 *blockAddress = (UINT32 *)((UARCH_INT)pVirtAddress & ~(PAGE_SIZE - 1)); pMemInfo->available_size += (*blockAddress & LOWER_WORD_ALL_ONE) * PAGE_SIZE; mem_free(pMemInfo, ++blockAddress); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalMemFreeNUMA(pMemInfo); osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, " "ret = %d \n", ret); } #endif return; } } else { if ((pMemInfo = userLargeMemLookupByVirtAddr(pVirtAddress)) == NULL) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "userMemLookupByVirtAddr failed\n"); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, " "ret = %d \n", ret); } #endif return; } } if (pMemInfo->fvirt_addr) { ret = munmap(pMemInfo->fvirt_addr, pMemInfo->mmap_size); } else { ret = munmap(pMemInfo->virt_addr, pMemInfo->mmap_size); } if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "munmap failed, ret = %d\n", ret); } ret = ioctl(fd, DEV_MEM_IOC_MEMFREE, pMemInfo); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "ioctl call failed, ret = %d\n", ret); } userMemListFree(pMemInfo); free(pMemInfo); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = %d \n", ret); } #endif return; } OSAL_PUBLIC void osalMemFreePage(void *pVirtAddress) { int ret = 0; dev_mem_info_t *pMemInfo = NULL; if (NULL == pVirtAddress) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Invalid virtual address\n"); return; } #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_lock(&mutex_page); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_lock(): Failed to lock mutex, ret = %d \n", ret); return; } #endif pMemInfo = userMemLookupByVirtAddrPage(pVirtAddress); if (pMemInfo == NULL) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "userMemLookupByVirtAddrPage failed \n"); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex_page); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = " "%d \n", ret); } #endif return; } ret = munmap(pMemInfo->virt_addr, getpagesize()); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "munmap failed, ret = %d\n", ret); } ret = ioctl(fdp, DEV_MEM_IOC_MEMFREEPAGE, pMemInfo); if (ret != 0) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "ioctl call failed, ret = %d\n", ret); } userMemListFreePage(pMemInfo); free(pMemInfo); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex_page); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = %d \n", ret); } #endif return; } UINT64 osalVirtToPhysNUMA(void *pVirtAddress) { dev_mem_info_t *pMemInfo = NULL; UARCH_INT offset = 0; UINT64 phy_address = 0; #ifndef ICP_WITHOUT_THREAD int ret = 0; #endif OSAL_LOCAL_ENSURE(pVirtAddress != NULL, "osalVirtToPhysNUMA(): Null virtual address pointer", 0); /* Firstly search the large memory tree */ #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_lock(&mutex); if (ret) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_lock(): Failed to lock mutex, ret = %d \n", ret); return (UINT64)0; } #endif if ((pMemInfo = userLargeMemLookupByVirtAddr(pVirtAddress)) != NULL) { #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { osalMemFreeNUMA(pMemInfo); osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = " "%d \n", ret); return (UINT64)0; } #endif return (UINT64)(pMemInfo->phy_addr + (UARCH_INT)pVirtAddress - (UARCH_INT)pMemInfo->virt_addr); } pMemInfo = userMemLookupByVirtAddr(pVirtAddress); #ifndef ICP_WITHOUT_THREAD ret = pthread_mutex_unlock(&mutex); if (ret) { if (NULL != pMemInfo) { osalMemFreeNUMA(pMemInfo); } osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "pthread_mutex_unlock(): Failed to unlock mutex, ret = %d \n", ret); return (UINT64)0; } #endif if (NULL == pMemInfo) { osalLog(OSAL_LOG_LVL_ERROR, OSAL_LOG_DEV_STDOUT, "Invalid block address %p !\n", pVirtAddress); return (UINT64)0; } offset = (UARCH_INT)pVirtAddress - (UARCH_INT)(pMemInfo->virt_addr); phy_address = pMemInfo->phy_addr; return (UINT64)(phy_address + offset); } #ifndef ICP_WITHOUT_IOMMU int osalIOMMUMap(UINT64 phaddr, UINT64 iova, size_t size) { dev_iommu_info_t info = {phaddr, iova, size}; return ioctl(fd, DEV_MEM_IOC_IOMMUMAP, &info); } int osalIOMMUUnmap(UINT64 iova, size_t size) { dev_iommu_info_t info = {0, iova, size}; return ioctl(fd, DEV_MEM_IOC_IOMMUUNMAP, &info); } UINT64 osalIOMMUVirtToPhys(UINT64 iova) { dev_iommu_info_t info = {0, iova, 0}; return (ioctl(fd, DEV_MEM_IOC_IOMMUVTOP, &info) == 0) ? info.phaddr : 0; } size_t osalIOMMUgetRemappingSize(size_t size) { int pages = (size >> PAGE_SHIFT) + 1; size_t new_size = (pages * PAGE_SIZE); return new_size; } #else int osalIOMMUMap(UINT64 phaddr, UINT64 iova, size_t size) { return 0; } int osalIOMMUUnmap(UINT64 iova, size_t size) { return 0; } UINT64 osalIOMMUVirtToPhys(UINT64 iova) { return iova; } size_t osalIOMMUgetRemappingSize(size_t size) { return size; } #endif qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/include/000077500000000000000000000000001503624047500261665ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/include/OsalDevDrv.h000066400000000000000000000041541503624047500303540ustar00rootroot00000000000000/** * @file OsalDevDrv.h * * @brief Device driver macros and data types * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef OSAL_DEV_DRV_H #define OSAL_DEV_DRV_H #ifdef __cplusplus extern "C" { #endif #ifdef PAGE_SIZE #undef PAGE_SIZE #endif #define PAGE_SHIFT 12 #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE - 1)) #define USER_MEM_64BYTE_OFFSET 64 #define USER_MEM_128BYTE_OFFSET 128 #define FREE(ptr) osalMemFree(ptr) #ifdef __cplusplus } #endif #endif qatlib-25.08.0/quickassist/utilities/osal/src/linux/user_space/include/OsalOsTypes.h000066400000000000000000000217161503624047500305730ustar00rootroot00000000000000/** * @file OsalOsTypes.h * * @brief 0S-specific data types and macros * * * @par * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef OSAL_OS_TYPES_H #define OSAL_OS_TYPES_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #ifndef ICP_WITHOUT_THREAD #include #endif #include #include #include #include #include #include #include #ifndef ICP_WITHOUT_THREAD typedef pthread_t OsalThread; typedef pthread_mutex_t *OsalMutex; typedef pthread_mutex_t *OsalFastMutex; typedef pthread_spinlock_t OsalLock; typedef pthread_attr_t OsalPosixThreadAttr; #else typedef int OsalThread; typedef void *OsalMutex; typedef void *OsalFastMutex; typedef int OsalLock; typedef int OsalPosixThreadAttr; #endif typedef sem_t *OsalSemaphore; typedef int64_t INT64; /**< 64-bit signed integer */ typedef uint64_t UINT64; /**< 64-bit unsigned integer */ typedef int32_t INT32; /**< 32-bit signed integer */ typedef uint32_t UINT32; /**< 32-bit unsigned integer */ typedef int16_t INT16; /**< 16-bit signed integer */ typedef uint16_t UINT16; /**< 16-bit unsigned integer */ typedef int8_t INT8; /**< 8-bit signed integer */ typedef char CHAR; typedef unsigned char UINT8; /**< 8-bit unsigned integer */ typedef UINT32 ULONG; /**< alias for UINT32 */ typedef UINT16 USHORT; /**< alias for UINT16 */ typedef UINT8 UCHAR; /**< alias for UINT8 */ typedef UINT32 BOOL; /**< alias for UINT32 */ typedef void VOID; /**< alias for void */ typedef volatile INT64 OsalAtomic; #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #define ATOMIC_INIT(i) \ { \ (i) \ } #define OSAL_POSIX_UNSHARED_SEMAPHORE 0 #define OSAL_POSIX_SHARED_SEMAPHORE 1 #define OSAL_OS_WAIT_FOREVER (-1) #define OSAL_OS_WAIT_NONE 0 #define OSAL_OS_PAGE_SIZE 4096 /* Default stack limit is 10 KB */ #define OSAL_OS_THREAD_DEFAULT_STACK_SIZE (10240) /* Maximum stack limit is 32 MB */ #define OSAL_OS_THREAD_MAX_STACK_SIZE (33554432) /* 32 MBytes */ /* Thread minimum priority : PTHREAD_MIN_PRIORITY */ #define OSAL_OS_MIN_THREAD_PRIORITY (1) /* Default thread priority */ #define OSAL_OS_DEFAULT_THREAD_PRIORITY (15) /* Thread maximum priority : PTHREAD_MAX_PRIORITY */ #define OSAL_OS_MAX_THREAD_PRIORITY (99) /* Thread default scheduling policy */ #define OSAL_OS_THREAD_DEFAULT_SCHED_POLICY SCHED_RR /* Thread scheduling policy - Round Robin */ #define OSAL_THREAD_SCHED_RR SCHED_RR /* Thread scheduling policy - FiFo */ #define OSAL_THREAD_SCHED_FIFO SCHED_FIFO /* Thread scheduling policy - Other */ #define OSAL_THREAD_SCHED_OTHER SCHED_OTHER /* error numbers */ /* #define EAGAIN EAGAIN #define EBADF EBADF #define EMSGSIZE EMSGSIZE #define EINTR EINTR #define EINVAL EINVAL #define ETIMEDOUT ETIMEDOUT #define EBADMSG EBADMSG #define EFAULT EFAULT */ /* Maximum alignment allowed */ #ifndef OSAL_MAX_ALIGNMENT #define OSAL_MAX_ALIGNMENT 256 #endif /* In case of SCHED_OTHER the supported priority value is only zero */ /* Thread minimum priority : PTHREAD_MIN_PRIORITY */ #define OSAL_POSIX_THREAD_MIN_PRIORITY (1) /* Default thread priority */ #define OSAL_POSIX_THREAD_DEFAULT_PRIORITY (31) /* Thread maximum priority : PTHREAD_MAX_PRIORITY */ #define OSAL_POSIX_THREAD_MAX_PRIORITY (99) /* Thread default scheduling policy - SCHED_RR, SCHED_FIFO or SCHED_OTHER */ #define OSAL_POSIX_THREAD_DEFAULT_SCHED_POLICY SCHED_RR /* String manipulation definitions */ #define OSAL_OS_GET_STRING_LENGTH(str, n) strnlen(str, n) #define OSAL_OS_MMU_VIRT_TO_PHYS(addr) ((UINT64)(addr)) #define OSAL_OS_MMU_PHYS_TO_VIRT(addr) (addr) #define OSAL_ASSERT(c) \ if (!(c)) \ { \ abort(); \ } #define OSAL_MEM_ASSERT(c) \ if (!(c)) \ { \ abort(); \ } typedef enum { TYPE_IGNORE = 0, /**< Spin Lock type Ignore */ NON_QUEUED = 1, /**< Non Queued Spin Lock type */ QUEUED = 2, /**< Queued Spin Lock type */ NON_QUEUED_AT_DPC_LEVEL = 3, /**< Non Queued Spin Lock type at DPC level */ QUEUED_AT_DPC_LEVEL /**< Queued Spin Lock type at DPC level */ } OsalLockType; #define OSAL_OS_HOST_TO_NW_16(uData) \ ((0xff & ((uData) >> 8)) | (((uData)&0xff) << 8)) #define OSAL_OS_HOST_TO_NW_32(uData) \ (((uData) >> 24) | (((uData)&0x00ff0000) >> 8) | \ (((uData)&0x0000ff00) << 8) | (((uData)&0x000000ff) << 24)) #define OSAL_OS_HOST_TO_NW_64(uData) \ ((((uData) >> 56) & 0xffull) | (((uData) >> 40) & 0x000000000000ff00ull) | \ (((uData) >> 24) & 0x0000000000ff0000ull) | \ (((uData) >> 8) & 0x00000000ff000000ull) | \ (((uData) << 56) & 0xff00000000000000ull) | \ (((uData) << 40) & 0x00ff000000000000ull) | \ (((uData) << 24) & 0x0000ff0000000000ull) | \ (((uData) << 8) & 0x000000ff00000000ull)) #define OSAL_OS_NW_TO_HOST_16(uData) \ ((0xff & ((uData) >> 8)) | (((uData)&0xff) << 8)) #define OSAL_OS_NW_TO_HOST_32(uData) \ (((uData) >> 24) | (((uData) >> 8) & 0x0000ff00) | \ (((uData) << 8) & 0x00ff0000) | ((uData) << 24)) #define OSAL_OS_NW_TO_HOST_64(uData) \ ((((uData) >> 56) & 0xffull) | (((uData) >> 40) & 0x000000000000ff00ull) | \ (((uData) >> 24) & 0x0000000000ff0000ull) | \ (((uData) >> 8) & 0x00000000ff000000ull) | \ (((uData) << 56) & 0xff00000000000000ull) | \ (((uData) << 40) & 0x00ff000000000000ull) | \ (((uData) << 24) & 0x0000ff0000000000ull) | \ (((uData) << 8) & 0x000000ff00000000ull)) #define OSAL_OS_UDIV64_32(dividend, divisor) (dividend / divisor); #define OSAL_OS_UMOD64_32(dividend, divisor) (dividend % divisor); #define OSAL_PID pid_t #ifndef osalGetPid #define osalGetPid getpid #endif #ifndef osalStrtoul #define osalStrtoul strtoull #endif #ifndef osalStrsep #define osalStrsep strsep #endif #ifdef __cplusplus } #endif #endif /* OsalTypes_H */ qatlib-25.08.0/quickassist/utilities/qat_mgr/000077500000000000000000000000001503624047500211605ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/qat_mgr/qat_mgr.c000066400000000000000000000417201503624047500227620ustar00rootroot00000000000000/***************************************************************************** * * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * * BSD LICENSE * * Copyright(c) 2007-2022 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "icp_platform.h" #include "qat_log.h" #include "qat_mgr.h" static char *sock_file = QATMGR_SOCKET; static int parent_pipe = 0; #define PIDFILE_ENV "PIDFILE" #define PIDFILE_DEFAULT "/run/qat/qatmgr.pid" #define QUEUE_LENGTH 5 #define MAX_CLIENTS 3 #define POLICY_MIN 0 #define POLICY_MAX MAX_DEVS #define DEBUG_LEVEL_MIN 0 #define DEBUG_LEVEL_MAX 2 #define CLIENT_TIMEOUT_DEFAULT_MS 1000 #define MAX_ERR_STRING_LEN 1024 #define MAX_ERR_SUBSTRING_LEN 32 struct ucred { pid_t pid; /* process ID of the sending process */ uid_t uid; /* user ID of the sending process */ gid_t gid; /* group ID of the sending process */ }; /* * This array does not need to be global, it is only used locally to main(). * However, it is global to avoid excessive use of stack memory and potential * stack-overflow in this function. */ static struct qatmgr_dev_data dev_list[MAX_DEVS] = { 0 }; void *handle_client(void *arg) { int bytes_r; int bytes_w = 0; int index = -1; pthread_t tid; int conn_fd; struct qatmgr_msg_req msgreq = { 0 }; struct qatmgr_msg_rsp msgrsp = { 0 }; char *section_name = NULL; struct pollfd fd; int ret = -1; int write_errno = 0; conn_fd = (intptr_t)arg; tid = pthread_self(); qat_log(LOG_LEVEL_DEBUG, "connect_fd %d, tid %lu, client_timeout %d ms\n", conn_fd, tid, CLIENT_TIMEOUT_DEFAULT_MS); memset(&fd, 0, sizeof(fd)); fd.fd = conn_fd; fd.events = POLLIN; ret = poll(&fd, 1, CLIENT_TIMEOUT_DEFAULT_MS); if (ret > 0) { while ((bytes_r = read(conn_fd, (void *)&msgreq, sizeof(msgreq))) > 0) { qat_log(LOG_LEVEL_DEBUG, "tid %lu, Received %u bytes: Message type %d, length %d\n", tid, bytes_r, msgreq.hdr.type, msgreq.hdr.len); handle_message(&msgreq, &msgrsp, §ion_name, tid, &index); /* Send response */ errno = 0; bytes_w = write(conn_fd, (const void *)&msgrsp, msgrsp.hdr.len); write_errno = errno; if (bytes_w < 0) break; if (bytes_w < msgrsp.hdr.len) qat_log(LOG_LEVEL_ERROR, "Socket write incomplete\n"); } /* If the socket is closed while a section is still held then release it */ if (index >= 0 && section_name) { qat_log( LOG_LEVEL_INFO, "Force release of section %s\n", section_name); release_section(index, tid, section_name, strnlen(section_name, QATMGR_MAX_STRLEN)); free(section_name); } if (bytes_r < 0 || bytes_w < 0) { qat_log( LOG_LEVEL_ERROR, "Socket read/write error %d\n", write_errno); } else if (bytes_r == 0) { qat_log(LOG_LEVEL_INFO, "EOF tid %lu\n", tid); } } else if (ret == 0) { qat_log(LOG_LEVEL_ERROR, "qatmgr timed out waiting on data from the client, connect_fd " "%d, tid %lu\n", conn_fd, tid); } else { qat_log(LOG_LEVEL_ERROR, "Failed to poll client fd\n"); } close(conn_fd); return NULL; } void usage(char *prog) { printf("Usage: %s [options]\n", prog); printf(" -h, -help\n"); printf(" -d, --debug=LEVEL (%d..%d)\n", DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX); printf(" -f, --foreground\n"); printf(" -p, --policy=POLICY\n"); printf(" 0 (default) - One VF from each PF per process\n"); printf(" 1 - One VF per process\n"); printf(" >1 - n VFs per process\n"); printf(" max value - %d\n", MAX_DEVS); printf(" -v, --version\n"); } static void version(char *prog) { char qatmgr_ver_str[VER_STR_LEN]; VER_STR(THIS_LIB_VERSION, qatmgr_ver_str); printf("%s %d.%02d.%d\n", prog, SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER); } static int check_pidfile(const char *filename, char **err_string) { FILE *pidfile; int pid; int num; if (!(pidfile = fopen(filename, "r"))) return 0; num = fscanf(pidfile, "%d", &pid); fclose(pidfile); if (num != 1) return 0; if (getsid(pid) < 0) return 0; *err_string = malloc(MAX_ERR_STRING_LEN); if (*err_string) snprintf(*err_string, MAX_ERR_STRING_LEN, "Another qatmgr may be running -- pid=%d", pid); return 1; } static int write_pidfile(const char *filename, char **err_string) { FILE *pidfile; char err_substr[MAX_ERR_SUBSTRING_LEN]; if (!(pidfile = fopen(filename, "w"))) { snprintf(err_substr, MAX_ERR_SUBSTRING_LEN, "Cannot open"); goto err_out; } if (0 > fprintf(pidfile, "%d\n", (int)getpid())) { snprintf(err_substr, MAX_ERR_SUBSTRING_LEN, "Cannot write pid"); goto err_out; } if (fclose(pidfile)) { snprintf(err_substr, MAX_ERR_SUBSTRING_LEN, "Cannot close"); goto err_out; } return 0; err_out: *err_string = malloc(MAX_ERR_STRING_LEN); if (*err_string) snprintf(*err_string, MAX_ERR_STRING_LEN, "%s, %s, %s\n", err_substr, filename, strerror(errno)); return 1; } static void daemonise(void) { int pid; int fd; int pipefd[2]; struct rlimit rl; /* Pipe used to indicate success/failure from child */ if (pipe(pipefd)) { qat_log( LOG_LEVEL_ERROR, "Failed to create pipe. %s\n", strerror(errno)); exit(1); } pid = fork(); if (pid < 0) { qat_log(LOG_LEVEL_ERROR, "Failed to fork. %s\n", strerror(errno)); } else if (pid > 0) { /* Parent */ char msg[64]; int len; close(pipefd[1]); memset(msg, 0, sizeof(msg)); len = read(pipefd[0], msg, sizeof(msg) - 1); if (len > 0) { /* Error from the child */ qat_log(LOG_LEVEL_ERROR, "%s\n", msg); exit(1); } else if (len < 0) { qat_log(LOG_LEVEL_ERROR, "Pipe error %s\n", strerror(errno)); exit(1); } else { exit(0); } } else { /* Child */ close(pipefd[0]); parent_pipe = pipefd[1]; setsid(); /* Fork a second time */ pid = fork(); if (pid < 0) { qat_log(LOG_LEVEL_ERROR, "Failed to fork. %s\n", strerror(errno)); } else if (pid > 0) { exit(0); } else { /* Final daemon process */ if (chdir("/") < 0) { qat_log( LOG_LEVEL_ERROR, "Failed to chdir. %s\n", strerror(errno)); } #define MAX_FILES 1024 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) rl.rlim_max = MAX_FILES; else if (rl.rlim_max == RLIM_INFINITY) rl.rlim_max = MAX_FILES; /* Close descriptors except for pipe */ for (fd = 3; fd < rl.rlim_max; fd++) { if (fd != pipefd[1]) close(fd); } umask(0117); } } } static int write_parent(int fd, char *buf) { int len; if (!buf) return -1; len = strnlen(buf, MAX_ERR_STRING_LEN); if (len < MAX_ERR_STRING_LEN) return write(fd, buf, len + 1); else return -1; } static int parse_and_validate_arg(char *arg, int *val, int min, int max) { if (!arg) return -EINVAL; char *end_ptr; errno = 0; long long temp = strtoll(arg, &end_ptr, 10); if (errno == ERANGE || *arg == 0 || *end_ptr != 0 || temp < min || temp > max) return -EINVAL; *val = (int)temp; return 0; } void signal_handler(int sig_num) { if (sig_num == SIGPIPE) { qat_log(LOG_LEVEL_DEBUG, "qatmgr received SIGPIPE signal\n"); } } int main(int argc, char **argv) { struct sockaddr_un sockaddr; int listen_fd; int connect_fd; int ret; pthread_t mgr_socket_tid; struct ucred ucred; unsigned len; unsigned num_devices; unsigned list_size = ARRAY_SIZE(dev_list); int i; const char *mgr_opts = "hvd:p:f"; const struct option mgr_optl[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'v' }, { "debug", 1, NULL, 'd' }, { "policy", 1, NULL, 'p' }, { "foreground", 0, NULL, 'f' }, { NULL, 0, NULL, 0 } }; int opt; int policy = 0; int foreground = 0; char *env; char pid_filename[256]; char *err_string; env = getenv(PIDFILE_ENV); if (env) strncpy(pid_filename, env, sizeof(pid_filename) - 1); else strncpy(pid_filename, PIDFILE_DEFAULT, sizeof(pid_filename) - 1); pid_filename[sizeof(pid_filename) - 1] = 0; opt = getopt_long(argc, argv, mgr_opts, mgr_optl, NULL); while (opt != -1) { switch (opt) { case '?': usage(argv[0]); exit(1); case 'h': usage(argv[0]); exit(0); case 'v': version(argv[0]); exit(0); case 'd': if (parse_and_validate_arg( optarg, &debug_level, DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX)) { printf("Invalid debug level %s\n", optarg); exit(1); } break; case 'f': foreground = 1; break; case 'p': if (parse_and_validate_arg( optarg, &policy, POLICY_MIN, POLICY_MAX)) { printf("Invalid policy %s\n", optarg); exit(1); } break; default: printf("Unknown argument\n"); } opt = getopt_long(argc, argv, mgr_opts, mgr_optl, NULL); } if (!foreground) { daemonise(); if (check_pidfile(pid_filename, &err_string) || write_pidfile(pid_filename, &err_string)) { if (err_string) { ret = write_parent(parent_pipe, err_string); free(err_string); } else { ret = write_parent(parent_pipe, "Unable to set pidfile"); } if (ret) perror("Failed to write error string"); exit(-1); } } signal(SIGPIPE, signal_handler); if (qat_mgr_get_vfio_dev_list(&num_devices, dev_list, list_size, 0)) { printf("get_dev_list failed\n"); } if (num_devices == 0) { if (foreground) qat_log(LOG_LEVEL_ERROR, "No QAT device found"); else write_parent(parent_pipe, "No QAT device found"); exit(-1); } for (i = 0; i < num_devices; i++) { qat_log(LOG_LEVEL_INFO, "Device %d, %X, %04x:%02x:%02x.%01x\n", i, dev_list[i].bdf, BDF_DOMAIN(dev_list[i].bdf), BDF_BUS(dev_list[i].bdf), BDF_DEV(dev_list[i].bdf), BDF_FUN(dev_list[i].bdf)); } if ((ret = qat_mgr_vfio_build_data(dev_list, num_devices, policy, 0))) { if (foreground) qat_log(LOG_LEVEL_ERROR, "Failed qat_mgr_vfio_build_data. ret %d\n", ret); else write_parent(parent_pipe, "Failed qat_mgr_vfio_build_data"); exit(ret); } listen_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (listen_fd < 0) { perror("socket error"); qat_mgr_cleanup_cfg(); exit(-1); } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sun_family = AF_UNIX; strncpy(sockaddr.sun_path, sock_file, sizeof(sockaddr.sun_path) - 1); sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = 0; /* Remove an existing file if it exists */ unlink(sock_file); ret = bind(listen_fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); if (ret < 0) { perror("bind error"); qat_mgr_cleanup_cfg(); exit(-1); } ret = listen(listen_fd, QUEUE_LENGTH); if (ret < 0) { perror("listen error"); qat_mgr_cleanup_cfg(); exit(-1); } if (init_section_data_mutex()) { perror("init section_data mutex error"); qat_mgr_cleanup_cfg(); exit(-1); } if (!foreground) close(parent_pipe); while (1) { connect_fd = accept(listen_fd, NULL, NULL); if (connect_fd < 0) { perror("accept error"); continue; } len = sizeof(struct ucred); ret = getsockopt(connect_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len); if (ret < 0) perror("getsockopt error"); else qat_log(LOG_LEVEL_DEBUG, "Client pid %ld\n", (long)ucred.pid); ret = pthread_create( &mgr_socket_tid, NULL, handle_client, (void *)(intptr_t)connect_fd); if (ret == 0) { pthread_detach(mgr_socket_tid); qat_log(LOG_LEVEL_DEBUG, "Child thread %lu\n", mgr_socket_tid); } else { perror("pthread_create error"); } } destroy_section_data_mutex(); qat_mgr_cleanup_cfg(); return 0; } qatlib-25.08.0/quickassist/utilities/service/000077500000000000000000000000001503624047500211665ustar00rootroot00000000000000qatlib-25.08.0/quickassist/utilities/service/qat000066400000000000000000000012441503624047500216770ustar00rootroot00000000000000# /etc/sysconfig/qat # # Optional file for qatlib configuration # # To change config from the default, update and uncomment the variables below, # install the file and restart the service, i.e. # # sudo cp /etc/sysconfig/qat /etc/sysconfig/qat.bak # sudo cp qat /etc/sysconfig/qat # sudo chmod 640 /etc/sysconfig/qat # sudo systemctl stop qat # sudo systemctl start qat # # See https://intel.github.io/quickassist/qatlib/configuration.html for more details # # 'POLICY' indicates how many VFs will be assigned to each process. #POLICY= # 'ServicesEnabled' tells the kernel driver which Services to enable on PFs. # All VFs on a PF have the same service. #ServicesEnabled= qatlib-25.08.0/quickassist/utilities/service/qat.service.in000066400000000000000000000042161503624047500237450ustar00rootroot00000000000000################################################################ # BSD LICENSE # # Copyright(c) 2007-2022 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################ [Unit] Description=QAT service After=local-fs.target [Service] Type=forking PIDFile=/run/qat/qatmgr.pid Group=qat RuntimeDirectory=qat RuntimeDirectoryMode=755 Environment="POLICY=0" EnvironmentFile=-/etc/sysconfig/qat ExecStartPre=/bin/sh -c "test $(getent group qat)" ExecStartPre=@prefix@/sbin/qat_init.sh ExecStart=@prefix@/sbin/qatmgr --policy=${POLICY} [Install] WantedBy=multi-user.target qatlib-25.08.0/quickassist/utilities/service/qat_init.sh.in000066400000000000000000000300001503624047500237300ustar00rootroot00000000000000#!/bin/sh ################################################################# # # BSD LICENSE # # Copyright(c) 2007-2022 Intel Corporation. All rights reserved. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of Intel Corporation nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # ################################################################# # # # qat_init.sh Setup drivers for Intel QAT. # VFIO_DRIVER=${VFIO_DRIVER-vfio-pci} QAT_USER_GROUP=${QAT_USER_GROUP-qat} INTEL_VENDORID="0x8086" DH895_DEVICE_PCI_ID="0x0435" DH895_DEVICE_PCI_ID_VM="0x0443" DH895_DEVICE_NAME="dh895xcc" DH895_DRIVER_NAME="qat_dh895xcc" C62X_DEVICE_PCI_ID="0x37c8" C62X_DEVICE_PCI_ID_VM="0x37c9" C62X_DEVICE_NAME="c6xx" C62X_DRIVER_NAME="qat_c62x" C3XX_DEVICE_PCI_ID="0x19e2" C3XX_DEVICE_PCI_ID_VM="0x19e3" C3XX_DEVICE_NAME="c3xxx" C3XX_DRIVER_NAME="qat_c3xxx" D15XX_DEVICE_PCI_ID="0x6f54" D15XX_DEVICE_PCI_ID_VM="0x6f55" D15XX_DEVICE_NAME="d15xx" D15XX_DRIVER_NAME="qat_d15xx" QAT_4XXX_DEVICE_PCI_ID="0x4940" QAT_4XXX_DEVICE_PCI_ID_VM="0x4941" QAT_401XX_DEVICE_PCI_ID="0x4942" QAT_401XX_DEVICE_PCI_ID_VM="0x4943" QAT_402XX_DEVICE_PCI_ID="0x4944" QAT_402XX_DEVICE_PCI_ID_VM="0x4945" QAT_4XXX_DEVICE_NAME="4xxx" QAT_4XXX_DRIVER_NAME="qat_4xxx" PF_NAMES="$QAT_4XXX_DEVICE_NAME" VF_DEVICE_IDS="$QAT_4XXX_DEVICE_PCI_ID_VM $QAT_401XX_DEVICE_PCI_ID_VM $QAT_402XX_DEVICE_PCI_ID_VM" QAT_420XX_DEVICE_PCI_ID="0x4946" QAT_420XX_DEVICE_PCI_ID_VM="0x4947" QAT_420XX_DEVICE_NAME="420xx" QAT_420XX_DRIVER_NAME="qat_420xx" PF_NAMES="$PF_NAMES $QAT_420XX_DEVICE_NAME" VF_DEVICE_IDS="$VF_DEVICE_IDS $QAT_420XX_DEVICE_PCI_ID_VM" SERVICES_LIST="sym asym sym;asym dc sym;dc asym;dc dcc" SERVICES_ENABLED="NONE" SERVICES_ENABLED_FOUND="FALSE" SYSTEMD_FILE="@systemdsystemunitdir@/qat.service" # space separated array for supporting new devices pci ids SUPPORTED_DEVICE_PCI_IDS="$QAT_4XXX_DEVICE_PCI_ID" SUPPORTED_DEVICE_PCI_IDS="$SUPPORTED_DEVICE_PCI_IDS $QAT_401XX_DEVICE_PCI_ID" SUPPORTED_DEVICE_PCI_IDS="$SUPPORTED_DEVICE_PCI_IDS $QAT_402XX_DEVICE_PCI_ID" SUPPORTED_DEVICE_PCI_IDS="$SUPPORTED_DEVICE_PCI_IDS $QAT_420XX_DEVICE_PCI_ID" # space separated array for supporting new devices pci names SUPPORTED_DRIVER_NAMES="$QAT_4XXX_DRIVER_NAME" SUPPORTED_DRIVER_NAMES="$SUPPORTED_DRIVER_NAMES $QAT_420XX_DRIVER_NAME" check_config() { CONFIG_FILE=$(awk -F'EnvironmentFile=-' '{print $2}' $SYSTEMD_FILE | grep '\S') if [ ! -f "$CONFIG_FILE" ]; then return fi SERVICES_ENABLED=$(awk -F'ServicesEnabled=' '{print $2}' $CONFIG_FILE | grep '\S') SERVICES_ENABLED_FOUND="FALSE" for SERVICE in $SERVICES_LIST do if [ "$SERVICE" = "$SERVICES_ENABLED" ]; then SERVICES_ENABLED_FOUND="TRUE" break fi done } get_module_state() { CMD="" for SUPPORTED_DRIVER_NAME in $SUPPORTED_DRIVER_NAMES; do CMD="$CMD -e ^$SUPPORTED_DRIVER_NAME" done echo "$(cat /proc/modules | grep $CMD | cut -d' ' -f5)" } check_driver() { # check if is running on VM (no PFs) PF_AVAILABLE=0 for SUPPORTED_PCI_ID in $SUPPORTED_DEVICE_PCI_IDS; do if [ ! -z "$(lspci -nD | grep ${SUPPORTED_PCI_ID#0x})" ]; then PF_AVAILABLE=1 break fi done if [ $PF_AVAILABLE -ne 1 ]; then echo "lspci: No PFs found, so assume qatlib is running on a VM" return fi # qat driver needs 0.2s per PF, so for 8S machine it needs ~ 6.4 s # TIMEOUT = TIMEOUT_CNT * ATTEMPT_INTERVAL so there is a 20s TIMEOUT_CNT=40 ATTEMPT_INTERVAL=0.5 ATTEMPT_CNT=0 CURRENT_STATE=$(get_module_state) while [ "$CURRENT_STATE" != "Live" ] do if [ $ATTEMPT_CNT -ge $TIMEOUT_CNT ]; then TIMEOUT=$(awk "BEGIN {print $ATTEMPT_CNT * $ATTEMPT_INTERVAL}") echo "QAT driver is still not present after ${TIMEOUT}s. Aborting qat_init" exit 1 fi ATTEMPT_CNT=`expr $ATTEMPT_CNT + 1` sleep $ATTEMPT_INTERVAL CURRENT_STATE=$(get_module_state) done } sysfs_config() { if [ "$SERVICES_ENABLED_FOUND" != "TRUE" ]; then return fi PCI_DEV_SUPPORTED=0 PCI_DEVS=`ls -d /sys/bus/pci/devices/* | awk 'BEGIN{FS="/"} {print $NF}'` for DEV_PCI_ADDR in $PCI_DEVS do DEV=/sys/bus/pci/devices/$DEV_PCI_ADDR PCI_DEV=`cat $DEV/device 2> /dev/null` for SUPPORTED_PCI_ID in $SUPPORTED_DEVICE_PCI_IDS; do if [ "$PCI_DEV" = "$SUPPORTED_PCI_ID" ]; then PCI_DEV_SUPPORTED=1 break fi done if [ $PCI_DEV_SUPPORTED -ne 1 ]; then continue fi PCI_DEV_SUPPORTED=0 if [ ! -e "$DEV/qat/cfg_services" ]; then echo "Cannot access $DEV/qat/cfg_services: No such file or directory." echo "You may need to update your kernel driver. See QAT kernel release notes." continue fi CURRENT_SERVICES=`cat $DEV/qat/cfg_services` if [ "$CURRENT_SERVICES" != "$SERVICES_ENABLED" ]; then CURRENT_STATE=`cat $DEV/qat/state` if [ "$CURRENT_STATE" = "up" ]; then echo down > $DEV/qat/state fi echo $SERVICES_ENABLED > $DEV/qat/cfg_services if [ $? != 0 ]; then echo "Can't write to cfg_services file: $SERVICES_ENABLED is not supported." echo "You may need to update your kernel driver. See QAT kernel release notes." continue fi CURRENT_SERVICES=`cat $DEV/qat/cfg_services` fi echo "$0, device $DEV_PCI_ADDR configured with services: $CURRENT_SERVICES" done } unbind() { BSF=$1 OLD_DRIVER=$2 LOOP=0 while [ $LOOP -lt 5 ] do echo -n 2> /dev/null $BSF > /sys/bus/pci/drivers/$OLD_DRIVER/unbind if [ $? -eq 0 ]; then break else LOOP=`expr $LOOP + 1` sleep 1 fi done } override() { BSF=$1 NEW_DRIVER=$2 LOOP=0 while [ $LOOP -lt 5 ] do echo -n 2> /dev/null $NEW_DRIVER > /sys/bus/pci/devices/$BSF/driver_override if [ $? -eq 0 ]; then break else LOOP=`expr $LOOP + 1` sleep 1 fi done } bind() { BSF=$1 DRIVER=$2 LOOP=0 while [ $LOOP -lt 5 ] do echo -n 2> /dev/null $BSF > /sys/bus/pci/drivers/$DRIVER/bind if [ $? -eq 0 ]; then break else LOOP=`expr $LOOP + 1` echo -n 2> /dev/null $BSF > /sys/bus/pci/devices/$BSF/driver/unbind sleep 1 fi done } bind_driver() { BSF=$1 DEVICE=$2 NEW_DRIVER=$VFIO_DRIVER MODULE=$VFIO_DRIVER # Check if this device should be bound to qat VF driver LKCF_DEV= for DEV in $LKCF_LIST do if echo $BSF | grep -q -E $DEV; then LKCF_DEV=$DEV break fi done if [ $LKCF_DEV ]; then # Find the qat vf driver case "$DEVICE" in $DH895_DEVICE_PCI_ID_VM ) NEW_DRIVER=${DH895_DEVICE_NAME}vf MODULE=${DH895_DRIVER_NAME}vf ;; $C62X_DEVICE_PCI_ID_VM ) NEW_DRIVER=${C62X_DEVICE_NAME}vf MODULE=${C62X_DRIVER_NAME}vf ;; $C3XX_DEVICE_PCI_ID_VM ) NEW_DRIVER=${C3XX_DEVICE_NAME}vf MODULE=${C3XX_DRIVER_NAME}vf ;; $D15XX_DEVICE_PCI_ID_VM ) NEW_DRIVER=${D15XX_DEVICE_NAME}vf MODULE=${D15XX_DRIVER_NAME}vf ;; $QAT_4XXX_DEVICE_PCI_ID_VM ) NEW_DRIVER=${QAT_4XXX_DEVICE_NAME}vf MODULE=${QAT_4XXX_DRIVER_NAME}vf ;; $QAT_401XX_DEVICE_PCI_ID_VM ) NEW_DRIVER=${QAT_4XXX_DEVICE_NAME}vf MODULE=${QAT_4XXX_DRIVER_NAME}vf ;; $QAT_402XX_DEVICE_PCI_ID_VM ) NEW_DRIVER=${QAT_4XXX_DEVICE_NAME}vf MODULE=${QAT_4XXX_DRIVER_NAME}vf ;; $QAT_420XX_DEVICE_PCI_ID_VM ) NEW_DRIVER=${QAT_420XX_DEVICE_NAME}vf MODULE=${QAT_420XX_DRIVER_NAME}vf ;; * ) echo Unsupported PCI device $DEVICE ;; esac fi VF_DEV=/sys/bus/pci/devices/$BSF if [ ! -d /sys/bus/pci/drivers/$NEW_DRIVER ]; then modprobe $MODULE fi # What driver is currently bound to the device? if [ -e $VF_DEV/driver ]; then VF_DRIVER=`readlink $VF_DEV/driver | awk 'BEGIN {FS="/"} {print $NF}'` else VF_DRIVER= fi if [ x$VF_DRIVER != x$NEW_DRIVER ]; then if [ $VF_DRIVER ]; then # Unbind from existing driver unbind $BSF $VF_DRIVER fi # Bind to $NEW_DRIVER override $BSF $NEW_DRIVER bind $BSF $NEW_DRIVER # Change permissions on the device, # a delay is needed to allow the init caused # by the bind to complete before the permissions # can be changed GROUP=`readlink $VF_DEV/iommu_group | awk 'BEGIN {FS="/"} {print $NF}'` if [ -e /dev/vfio/$GROUP ]; then sleep 0.1 chown :$QAT_USER_GROUP /dev/vfio/$GROUP chmod +060 /dev/vfio/$GROUP fi fi } enable_sriov() { PF_LIST= for NAME in $PF_NAMES do for PF in `ls -d /sys/bus/pci/drivers/$NAME/????:??:??.? 2> /dev/null` do PF_LIST="$PF_LIST $PF" done done if [ "$PF_LIST" ]; then for PF_DEV in $PF_LIST do # Enable sriov on the PF_DEV if [ -r $PF_DEV/sriov_totalvfs -a -w $PF_DEV/sriov_numvfs ]; then TOTALVFS=`cat $PF_DEV/sriov_totalvfs` NUMVFS=`cat $PF_DEV/sriov_numvfs` if [ $TOTALVFS -ne $NUMVFS ]; then echo $TOTALVFS > $PF_DEV/sriov_numvfs fi fi for VF_LINK in `ls -d $PF_DEV/virtfn* 2> /dev/null` do BSF=`readlink $VF_LINK | awk 'BEGIN {FS="/"} {print $NF}'` DEVICE=`cat /sys/bus/pci/devices/$BSF/device` bind_driver $BSF $DEVICE & done done else # No PFs. Find by pci device id. PCI_DEVICES=`ls -d /sys/bus/pci/devices/* | awk 'BEGIN{FS="/"} {print $NF}'` for BSF in $PCI_DEVICES do DEVICE=`cat /sys/bus/pci/devices/$BSF/device` if echo $VF_DEVICE_IDS | grep -q $DEVICE; then VENDOR=`cat /sys/bus/pci/devices/$BSF/vendor` if [ $VENDOR = $INTEL_VENDORID ]; then bind_driver $BSF $DEVICE & fi fi done fi } check_config check_driver sysfs_config enable_sriov wait exit 0 qatlib-25.08.0/versionfile000066400000000000000000000002561503624047500154230ustar00rootroot00000000000000PACKAGE_TYPE=QAT_UPSTREAM PACKAGE_OS=L PACKAGE_VERSION_MAJOR_NUMBER=25 PACKAGE_VERSION_MINOR_NUMBER=08 PACKAGE_VERSION_PATCH_NUMBER=0 PACKAGE_VERSION_BUILD_NUMBER=00028